From 599979b019be2cbe7069168133f639257d8790d6 Mon Sep 17 00:00:00 2001 From: Jaysyn904 <68194417+Jaysyn904@users.noreply.github.com> Date: Sat, 19 Jul 2025 14:20:47 -0400 Subject: [PATCH] 2025/07/19 Update Added PEPS AI Full compile. --- nasher.cfg | 12 +- pack_haks.cmd | 1 + src/hakpak/peps_prc8/2da/ai_messages.2da | 49 + src/hakpak/peps_prc8/2da/ai_spells.2da | 19400 +++++++ src/hakpak/peps_prc8/tga/armor_pallet.tga | Bin 0 -> 180268 bytes src/hakpak/peps_prc8/tga/gui_pal_tattoo.tga | Bin 0 -> 180268 bytes src/include/inc_epicspellfnc.nss | 2 +- src/include/nw_inc_nui.nss | 852 +- src/include/prc_inc_combat.nss | 1 + src/include/prc_inc_skills.nss | 12 +- src/include/prc_inc_wpnrest.nss | 180 +- src/module/dlg/nw_g_animal.dlg.json | 49670 ++++++++++++++++++ src/module/dlg/nw_g_fam.dlg.json | 23412 +++++++++ src/module/dlg/oc_ai_henchmen.dlg.json | 27180 ++++++++++ src/module/ifo/module.ifo.json | 9 +- src/module/nss/0c_assoc_actions.nss | 172 + src/module/nss/0c_cast_polymorp.nss | 18 + src/module/nss/0c_fire_henchmen.nss | 15 + src/module/nss/0c_get_convo.nss | 22 + src/module/nss/0c_get_henchman.nss | 25 + src/module/nss/0c_h_cast_spell.nss | 12 + src/module/nss/0c_henchmenspell.nss | 81 + src/module/nss/0c_if_a_magic_m.nss | 16 + src/module/nss/0c_if_ass_convo.nss | 132 + src/module/nss/0c_if_assoc_mode.nss | 22 + src/module/nss/0c_if_cntrspell.nss | 17 + src/module/nss/0c_if_com_script.nss | 16 + src/module/nss/0c_if_convo.nss | 21 + src/module/nss/0c_if_has_assoc.nss | 18 + src/module/nss/0c_if_has_class.nss | 28 + src/module/nss/0c_if_has_feat.nss | 22 + src/module/nss/0c_if_has_spell.nss | 26 + src/module/nss/0c_if_hen_leave.nss | 12 + src/module/nss/0c_if_identify.nss | 17 + src/module/nss/0c_if_not_master.nss | 11 + src/module/nss/0c_if_open_inven.nss | 13 + src/module/nss/0c_if_pickuploot.nss | 12 + src/module/nss/0c_if_polymorph.nss | 11 + src/module/nss/0c_if_scout.nss | 11 + src/module/nss/0c_if_skillrank.nss | 18 + src/module/nss/0c_if_taunt.nss | 15 + src/module/nss/0c_listhenchman.nss | 19 + src/module/nss/0c_no_com_script.nss | 27 + src/module/nss/0c_remove_effect.nss | 14 + src/module/nss/0c_summon_assoc.nss | 17 + src/module/nss/0c_use_feat.nss | 15 + src/module/nss/0e_c2_1_hb.nss | 16 + src/module/nss/0e_c2_7_ondeath.nss | 32 + src/module/nss/0e_ch_1_hb.nss | 14 + src/module/nss/0e_ch_7_ondeath.nss | 41 + src/module/nss/0e_do_combat_rnd.nss | 22 + src/module/nss/0e_gui_events.nss | 60 + src/module/nss/0e_m1_3_endround.nss | 46 + src/module/nss/0e_nui.nss | 1975 + src/module/nss/0e_nui_dm.nss | 700 + src/module/nss/0e_onclientload.nss | 23 + src/module/nss/0e_player_target.nss | 154 + src/module/nss/0e_prc_ch_events.nss | 78 + src/module/nss/0i_actions.nss | 2325 + src/module/nss/0i_associates.nss | 2192 + src/module/nss/0i_color.nss | 70 + src/module/nss/0i_combat.nss | 3498 ++ src/module/nss/0i_constants.nss | 667 + src/module/nss/0i_gui_events.nss | 1032 + src/module/nss/0i_items.nss | 1243 + src/module/nss/0i_main.nss | 1328 + src/module/nss/0i_menus.nss | 4823 ++ src/module/nss/0i_menus_dm.nss | 1386 + src/module/nss/0i_messages.nss | 88 + src/module/nss/0i_module.nss | 544 + src/module/nss/0i_nui.nss | 434 + src/module/nss/0i_player_target.nss | 793 + src/module/nss/0i_spells.nss | 2157 + src/module/nss/0i_states_cond.nss | 423 + src/module/nss/0i_talents.nss | 3098 ++ src/module/nss/0i_time.nss | 95 + src/module/nss/ai_a_ambusher.nss | 105 + src/module/nss/ai_a_atk_casters.nss | 159 + src/module/nss/ai_a_atk_nearest.nss | 80 + src/module/nss/ai_a_atk_warrior.nss | 159 + src/module/nss/ai_a_barbarian.nss | 87 + src/module/nss/ai_a_bard.nss | 83 + src/module/nss/ai_a_cleric.nss | 102 + src/module/nss/ai_a_cntrspell.nss | 69 + src/module/nss/ai_a_default.nss | 80 + src/module/nss/ai_a_defensive.nss | 77 + src/module/nss/ai_a_druid.nss | 86 + src/module/nss/ai_a_fighter.nss | 82 + src/module/nss/ai_a_flanker.nss | 117 + src/module/nss/ai_a_invisible.nss | 123 + src/module/nss/ai_a_monk.nss | 82 + src/module/nss/ai_a_no_cmb_mode.nss | 131 + src/module/nss/ai_a_paladin.nss | 110 + src/module/nss/ai_a_peaceful.nss | 81 + src/module/nss/ai_a_polymorphed.nss | 70 + src/module/nss/ai_a_ranged.nss | 129 + src/module/nss/ai_a_ranger.nss | 96 + src/module/nss/ai_a_rogue.nss | 83 + src/module/nss/ai_a_sorcerer.nss | 75 + src/module/nss/ai_a_taunter.nss | 53 + src/module/nss/ai_a_wizard.nss | 77 + src/module/nss/ai_ambusher.nss | 100 + src/module/nss/ai_barbarian.nss | 71 + src/module/nss/ai_bard.nss | 67 + src/module/nss/ai_cleric.nss | 68 + src/module/nss/ai_cntrspell.nss | 68 + src/module/nss/ai_coward.nss | 133 + src/module/nss/ai_default.nss | 49 + src/module/nss/ai_defensive.nss | 48 + src/module/nss/ai_dragon.nss | 51 + src/module/nss/ai_druid.nss | 70 + src/module/nss/ai_fighter.nss | 65 + src/module/nss/ai_flanker.nss | 102 + src/module/nss/ai_incorporeal.nss | 83 + src/module/nss/ai_invisible.nss | 93 + src/module/nss/ai_monk.nss | 65 + src/module/nss/ai_paladin.nss | 71 + src/module/nss/ai_polymorphed.nss | 55 + src/module/nss/ai_ranged.nss | 116 + src/module/nss/ai_ranger.nss | 79 + src/module/nss/ai_rogue.nss | 66 + src/module/nss/ai_shadow.nss | 77 + src/module/nss/ai_sorcerer.nss | 61 + src/module/nss/ai_taunter.nss | 78 + src/module/nss/ai_wizard.nss | 63 + src/module/nss/hc_on_cl_enter.nss | 7 + src/module/nss/inc_spell_track.nss | 13 +- src/module/nss/mm_prc_spells.nss | 161 + src/module/nss/nw_c2_default1.nss | 160 +- src/module/nss/nw_c2_default2.nss | 254 +- src/module/nss/nw_c2_default3.nss | 105 +- src/module/nss/nw_c2_default4.nss | 114 +- src/module/nss/nw_c2_default5.nss | 92 +- src/module/nss/nw_c2_default6.nss | 131 +- src/module/nss/nw_c2_default8.nss | 44 +- src/module/nss/nw_c2_defaultb.nss | 183 +- src/module/nss/nw_c2_defaulte.nss | 82 +- src/module/nss/nw_ch_ac1.nss | 354 +- src/module/nss/nw_ch_ac2.nss | 107 + src/module/nss/nw_ch_ac3.nss | 56 + src/module/nss/nw_ch_ac4.nss | 81 +- src/module/nss/nw_ch_ac5.nss | 51 + src/module/nss/nw_ch_ac6.nss | 32 + src/module/nss/nw_ch_ac8.nss | 25 + src/module/nss/nw_ch_aca.nss | 46 + src/module/nss/nw_ch_acb.nss | 42 + src/module/nss/nw_ch_ace.nss | 60 + src/module/nss/nw_ch_summon_9.nss | 74 +- src/module/nss/pc_savebuffs.nss | 182 + src/module/nss/pe_buffing.nss | 534 + src/module/nss/pe_crafting.nss | 2153 + src/module/nss/pe_debug.nss | 900 + src/module/nss/pe_henchmen.nss | 589 + src/module/nss/pe_mod_set.nss | 119 + src/module/nss/pe_test.nss | 227 + src/module/nss/pi_buffing.nss | 338 + src/module/nss/pi_crafting.nss | 717 + src/module/nss/pi_debug.nss | 200 + src/module/nss/pi_forcerest.nss | 70 + src/module/nss/pi_henchmen.nss | 209 + src/module/nss/pi_test.nss | 103 + src/module/nss/pinc_henchmen.nss | 1531 + src/module/nss/xx_pc_1_hb.nss | 79 + src/module/nss/xx_pc_2_percept.nss | 107 + src/module/nss/xx_pc_3_endround.nss | 60 + src/module/nss/xx_pc_4_convers.nss | 30 + src/module/nss/xx_pc_5_phyatked.nss | 29 + src/module/nss/xx_pc_6_damaged.nss | 27 + src/module/nss/xx_pc_8_disturb.nss | 21 + src/module/nss/xx_pc_b_castat.nss | 35 + src/module/nss/xx_pc_e_blocked.nss | 68 + unpack_haks.cmd | 1 + update_src_from_haks.cmd | 1 + 173 files changed, 164296 insertions(+), 1515 deletions(-) create mode 100644 pack_haks.cmd create mode 100644 src/hakpak/peps_prc8/2da/ai_messages.2da create mode 100644 src/hakpak/peps_prc8/2da/ai_spells.2da create mode 100644 src/hakpak/peps_prc8/tga/armor_pallet.tga create mode 100644 src/hakpak/peps_prc8/tga/gui_pal_tattoo.tga create mode 100644 src/module/dlg/nw_g_animal.dlg.json create mode 100644 src/module/dlg/nw_g_fam.dlg.json create mode 100644 src/module/dlg/oc_ai_henchmen.dlg.json create mode 100644 src/module/nss/0c_assoc_actions.nss create mode 100644 src/module/nss/0c_cast_polymorp.nss create mode 100644 src/module/nss/0c_fire_henchmen.nss create mode 100644 src/module/nss/0c_get_convo.nss create mode 100644 src/module/nss/0c_get_henchman.nss create mode 100644 src/module/nss/0c_h_cast_spell.nss create mode 100644 src/module/nss/0c_henchmenspell.nss create mode 100644 src/module/nss/0c_if_a_magic_m.nss create mode 100644 src/module/nss/0c_if_ass_convo.nss create mode 100644 src/module/nss/0c_if_assoc_mode.nss create mode 100644 src/module/nss/0c_if_cntrspell.nss create mode 100644 src/module/nss/0c_if_com_script.nss create mode 100644 src/module/nss/0c_if_convo.nss create mode 100644 src/module/nss/0c_if_has_assoc.nss create mode 100644 src/module/nss/0c_if_has_class.nss create mode 100644 src/module/nss/0c_if_has_feat.nss create mode 100644 src/module/nss/0c_if_has_spell.nss create mode 100644 src/module/nss/0c_if_hen_leave.nss create mode 100644 src/module/nss/0c_if_identify.nss create mode 100644 src/module/nss/0c_if_not_master.nss create mode 100644 src/module/nss/0c_if_open_inven.nss create mode 100644 src/module/nss/0c_if_pickuploot.nss create mode 100644 src/module/nss/0c_if_polymorph.nss create mode 100644 src/module/nss/0c_if_scout.nss create mode 100644 src/module/nss/0c_if_skillrank.nss create mode 100644 src/module/nss/0c_if_taunt.nss create mode 100644 src/module/nss/0c_listhenchman.nss create mode 100644 src/module/nss/0c_no_com_script.nss create mode 100644 src/module/nss/0c_remove_effect.nss create mode 100644 src/module/nss/0c_summon_assoc.nss create mode 100644 src/module/nss/0c_use_feat.nss create mode 100644 src/module/nss/0e_c2_1_hb.nss create mode 100644 src/module/nss/0e_c2_7_ondeath.nss create mode 100644 src/module/nss/0e_ch_1_hb.nss create mode 100644 src/module/nss/0e_ch_7_ondeath.nss create mode 100644 src/module/nss/0e_do_combat_rnd.nss create mode 100644 src/module/nss/0e_gui_events.nss create mode 100644 src/module/nss/0e_m1_3_endround.nss create mode 100644 src/module/nss/0e_nui.nss create mode 100644 src/module/nss/0e_nui_dm.nss create mode 100644 src/module/nss/0e_onclientload.nss create mode 100644 src/module/nss/0e_player_target.nss create mode 100644 src/module/nss/0e_prc_ch_events.nss create mode 100644 src/module/nss/0i_actions.nss create mode 100644 src/module/nss/0i_associates.nss create mode 100644 src/module/nss/0i_color.nss create mode 100644 src/module/nss/0i_combat.nss create mode 100644 src/module/nss/0i_constants.nss create mode 100644 src/module/nss/0i_gui_events.nss create mode 100644 src/module/nss/0i_items.nss create mode 100644 src/module/nss/0i_main.nss create mode 100644 src/module/nss/0i_menus.nss create mode 100644 src/module/nss/0i_menus_dm.nss create mode 100644 src/module/nss/0i_messages.nss create mode 100644 src/module/nss/0i_module.nss create mode 100644 src/module/nss/0i_nui.nss create mode 100644 src/module/nss/0i_player_target.nss create mode 100644 src/module/nss/0i_spells.nss create mode 100644 src/module/nss/0i_states_cond.nss create mode 100644 src/module/nss/0i_talents.nss create mode 100644 src/module/nss/0i_time.nss create mode 100644 src/module/nss/ai_a_ambusher.nss create mode 100644 src/module/nss/ai_a_atk_casters.nss create mode 100644 src/module/nss/ai_a_atk_nearest.nss create mode 100644 src/module/nss/ai_a_atk_warrior.nss create mode 100644 src/module/nss/ai_a_barbarian.nss create mode 100644 src/module/nss/ai_a_bard.nss create mode 100644 src/module/nss/ai_a_cleric.nss create mode 100644 src/module/nss/ai_a_cntrspell.nss create mode 100644 src/module/nss/ai_a_default.nss create mode 100644 src/module/nss/ai_a_defensive.nss create mode 100644 src/module/nss/ai_a_druid.nss create mode 100644 src/module/nss/ai_a_fighter.nss create mode 100644 src/module/nss/ai_a_flanker.nss create mode 100644 src/module/nss/ai_a_invisible.nss create mode 100644 src/module/nss/ai_a_monk.nss create mode 100644 src/module/nss/ai_a_no_cmb_mode.nss create mode 100644 src/module/nss/ai_a_paladin.nss create mode 100644 src/module/nss/ai_a_peaceful.nss create mode 100644 src/module/nss/ai_a_polymorphed.nss create mode 100644 src/module/nss/ai_a_ranged.nss create mode 100644 src/module/nss/ai_a_ranger.nss create mode 100644 src/module/nss/ai_a_rogue.nss create mode 100644 src/module/nss/ai_a_sorcerer.nss create mode 100644 src/module/nss/ai_a_taunter.nss create mode 100644 src/module/nss/ai_a_wizard.nss create mode 100644 src/module/nss/ai_ambusher.nss create mode 100644 src/module/nss/ai_barbarian.nss create mode 100644 src/module/nss/ai_bard.nss create mode 100644 src/module/nss/ai_cleric.nss create mode 100644 src/module/nss/ai_cntrspell.nss create mode 100644 src/module/nss/ai_coward.nss create mode 100644 src/module/nss/ai_default.nss create mode 100644 src/module/nss/ai_defensive.nss create mode 100644 src/module/nss/ai_dragon.nss create mode 100644 src/module/nss/ai_druid.nss create mode 100644 src/module/nss/ai_fighter.nss create mode 100644 src/module/nss/ai_flanker.nss create mode 100644 src/module/nss/ai_incorporeal.nss create mode 100644 src/module/nss/ai_invisible.nss create mode 100644 src/module/nss/ai_monk.nss create mode 100644 src/module/nss/ai_paladin.nss create mode 100644 src/module/nss/ai_polymorphed.nss create mode 100644 src/module/nss/ai_ranged.nss create mode 100644 src/module/nss/ai_ranger.nss create mode 100644 src/module/nss/ai_rogue.nss create mode 100644 src/module/nss/ai_shadow.nss create mode 100644 src/module/nss/ai_sorcerer.nss create mode 100644 src/module/nss/ai_taunter.nss create mode 100644 src/module/nss/ai_wizard.nss create mode 100644 src/module/nss/mm_prc_spells.nss create mode 100644 src/module/nss/nw_ch_ac2.nss create mode 100644 src/module/nss/nw_ch_ac3.nss create mode 100644 src/module/nss/nw_ch_ac5.nss create mode 100644 src/module/nss/nw_ch_ac6.nss create mode 100644 src/module/nss/nw_ch_ac8.nss create mode 100644 src/module/nss/nw_ch_aca.nss create mode 100644 src/module/nss/nw_ch_acb.nss create mode 100644 src/module/nss/nw_ch_ace.nss create mode 100644 src/module/nss/pc_savebuffs.nss create mode 100644 src/module/nss/pe_buffing.nss create mode 100644 src/module/nss/pe_crafting.nss create mode 100644 src/module/nss/pe_debug.nss create mode 100644 src/module/nss/pe_henchmen.nss create mode 100644 src/module/nss/pe_mod_set.nss create mode 100644 src/module/nss/pe_test.nss create mode 100644 src/module/nss/pi_buffing.nss create mode 100644 src/module/nss/pi_crafting.nss create mode 100644 src/module/nss/pi_debug.nss create mode 100644 src/module/nss/pi_forcerest.nss create mode 100644 src/module/nss/pi_henchmen.nss create mode 100644 src/module/nss/pi_test.nss create mode 100644 src/module/nss/pinc_henchmen.nss create mode 100644 src/module/nss/xx_pc_1_hb.nss create mode 100644 src/module/nss/xx_pc_2_percept.nss create mode 100644 src/module/nss/xx_pc_3_endround.nss create mode 100644 src/module/nss/xx_pc_4_convers.nss create mode 100644 src/module/nss/xx_pc_5_phyatked.nss create mode 100644 src/module/nss/xx_pc_6_damaged.nss create mode 100644 src/module/nss/xx_pc_8_disturb.nss create mode 100644 src/module/nss/xx_pc_b_castat.nss create mode 100644 src/module/nss/xx_pc_e_blocked.nss create mode 100644 unpack_haks.cmd create mode 100644 update_src_from_haks.cmd diff --git a/nasher.cfg b/nasher.cfg index 7bdd15d..602053b 100644 --- a/nasher.cfg +++ b/nasher.cfg @@ -235,4 +235,14 @@ description = "PRC8 version of D3 - Vault of the Drow." filter = "xchst_inc.nss" [target.rules] - "*" = "src/module/$ext" \ No newline at end of file + "*" = "src/module/$ext" + +[target] +name = "pepshak" +file = "peps_prc8.hak" +description = "PEPS hakpak for PRC8 version of D3 - Vault of the Drow." + [target.sources] + include = "src/hakpak/peps_prc8/**/*" + + [target.rules] + "*" = "src/hakpak/peps_prc8/$ext" \ No newline at end of file diff --git a/pack_haks.cmd b/pack_haks.cmd new file mode 100644 index 0000000..f07456c --- /dev/null +++ b/pack_haks.cmd @@ -0,0 +1 @@ +nasher pack pepshak --verbose \ No newline at end of file diff --git a/src/hakpak/peps_prc8/2da/ai_messages.2da b/src/hakpak/peps_prc8/2da/ai_messages.2da new file mode 100644 index 0000000..cc5d0c9 --- /dev/null +++ b/src/hakpak/peps_prc8/2da/ai_messages.2da @@ -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!" diff --git a/src/hakpak/peps_prc8/2da/ai_spells.2da b/src/hakpak/peps_prc8/2da/ai_spells.2da new file mode 100644 index 0000000..14db4b5 --- /dev/null +++ b/src/hakpak/peps_prc8/2da/ai_spells.2da @@ -0,0 +1,19400 @@ +2DA V2.0 + + Label ImmunityType SaveType SpellResist Category HostileSetting Buff_Duration Buff_Target Buff_Group +0 Acid_Fog Acid **** 1 I 1 **** **** **** +1 Aid **** **** **** E 0 2 9 **** +2 Animate_Dead **** **** **** S 0 **** **** **** +3 Barkskin **** **** **** P 0 3 7 **** +4 Bestow_Curse **** Will 1 T 1 **** **** **** +5 Blade_Barrier **** Reflex 1 I 1 **** **** **** +6 Bless **** **** **** E 0 2 0 **** +7 Bless_Weapon[NOT_USED] **** **** **** **** **** **** **** **** +8 Blindness_and_Deafness Blindness Fortitude 1 R 1 **** **** **** +9 Bulls_Strength **** **** **** E 0 3 1 **** +10 Burning_Hands Fire Reflex 1 I 1 **** **** **** +11 Call_Lightning Electricity Reflex 1 D 1 **** **** **** +12 Calm_Emotions[NOT_USED] **** **** **** **** **** **** **** **** +13 Cats_Grace **** **** **** E 0 3 2 **** +14 Chain_Lightning Electricity Reflex 1 D 1 **** **** **** +15 Charm_Monster Mind_Affecting Will 1 R 1 **** **** **** +16 Charm_Person Mind_Affecting Will 1 R 1 **** **** **** +17 Charm_Person_or_Animal Mind_Affecting Will 1 R 1 **** **** **** +18 Circle_of_Death Death Fortitude 1 D 1 **** **** **** +19 Circle_of_Doom Negative Fortitude 1 D 1 **** **** **** +20 Clairaudience_and_Clairvoyance **** **** **** C 0 2 5 **** +21 Clarity **** **** **** C 0 2 13 **** +22 Cloak_of_Chaos[NOT_USED] **** **** **** **** **** **** **** **** +23 Cloudkill Poison Fortitude 0 I 1 **** **** **** +24 Color_Spray Blindness Will 1 I 1 **** **** **** +25 Cone_of_Cold Cold Reflex 1 I 1 **** **** **** +26 Confusion Confusion Will 1 D 1 **** **** **** +27 Contagion Disease Fortitude 1 T 1 **** **** **** +28 Control_Undead NoImmunity Will 1 R 1 **** **** **** +29 Create_Greater_Undead **** **** **** S 0 3 0 -2 +30 Create_Undead **** **** **** S 0 3 0 -2 +31 Cure_Critical_Wounds **** **** **** H 0 **** **** **** +32 Cure_Light_Wounds **** **** **** H 0 **** **** **** +33 Cure_Minor_Wounds **** **** **** H 0 **** **** **** +34 Cure_Moderate_Wounds **** **** **** H 0 **** **** **** +35 Cure_Serious_Wounds **** **** **** H 0 **** **** **** +36 Darkness **** **** **** I 0 **** **** **** +37 Daze Dazed Will 1 R 1 **** **** **** +38 Death_Ward **** **** **** E 0 3 11 **** +39 Delayed_Blast_Fireball Fire Reflex 1 I 1 **** **** **** +40 Dismissal **** **** 1 I 1 **** **** **** +41 Dispel_Magic **** **** **** R 0 **** **** **** +42 Divine_Power **** **** **** E 0 2 0 **** +43 Dominate_Animal Domination Will 1 R 1 **** **** **** +44 Dominate_Monster Domination Will 1 R 1 **** **** **** +45 Dominate_Person Domination Will 1 R 1 **** **** **** +46 Doom Fear Will 1 R 1 **** **** **** +47 Elemental_Shield **** **** **** P 0 2 7 **** +48 Elemental_Swarm **** **** **** S 0 3 0 -2 +49 Endurance **** **** **** E 0 3 3 **** +50 Endure_Elements **** **** **** P 0 3 10 -1 +51 Energy_Drain Level_Drain **** 1 R 1 **** **** **** +52 Enervation Level_Drain **** 1 R 1 **** **** **** +53 Entangle **** Reflex 0 I 1 **** **** **** +54 Fear Fear Will 1 D 1 **** **** **** +55 Feeblemind Mind_Affecting Will 1 R 1 **** **** **** +56 Finger_of_Death Death Fortitude 1 R 1 **** **** **** +57 Fire_Storm Fire Reflex 1 D 1 **** **** **** +58 Fireball Fire Reflex 1 I 1 **** **** **** +59 Flame_Arrow Fire Reflex 1 R 1 **** **** **** +60 Flame_Lash Fire Reflex 1 R 1 **** **** **** +61 Flame_Strike Fire Reflex 1 I 1 **** **** **** +62 Freedom_of_Movement **** **** **** E 0 2 9 **** +63 Gate **** **** **** S 0 3 0 -2 +64 Ghoul_Touch Poison Fortitude 1 T 1 **** **** **** +65 Globe_of_Invulnerability **** **** **** P 0 2 0 -7 +66 Grease **** Reflex 0 I 1 **** **** **** +67 Greater_Dispelling **** **** **** R 0 **** **** **** +68 Greater_Magic_Weapon[NOT_USED] **** **** **** **** **** **** **** **** +69 Greater_Planar_Binding **** **** **** S 0 3 0 -2 +70 Greater_Restoration **** **** **** C 0 **** **** **** +71 Greater_Shadow_Conjuration **** **** **** **** 1 **** **** **** +72 Greater_Spell_Breach **** **** 0 R 1 **** **** **** +73 Greater_Spell_Mantle **** **** **** P 0 2 0 -9 +74 Greater_Stoneskin **** **** **** P 0 3 0 -8 +75 Gust_of_Wind **** Fortitude 0 I 1 **** **** **** +76 Hammer_of_the_Gods Divine Will 1 D 1 **** **** **** +77 Harm Negative Will 1 T 1 **** **** **** +78 Haste **** **** **** E 0 2 9 -16 +79 Heal **** **** **** H 0 **** **** **** +80 Healing_Circle **** **** **** H 0 **** **** **** +81 Hold_Animal Paralysis Will 1 R 1 **** **** **** +82 Hold_Monster Paralysis Will 1 R 1 **** **** **** +83 Hold_Person Paralysis Will 1 R 1 **** **** **** +84 Holy_Aura[NOT_USED] **** **** **** **** **** **** **** **** +85 Holy_Sword[NOT_USED] **** **** **** **** **** **** **** **** +86 Identify **** **** **** **** 0 **** **** **** +87 Implosion Death Fortitude 1 I 1 **** **** **** +88 Improved_Invisibility **** **** **** E 0 2 7 -5 +89 Incendiary_Cloud Fire Reflex 0 I 1 **** **** **** +90 Invisibility **** **** **** E 0 2 7 -5 +91 Invisibility_Purge **** **** **** E 0 2 0 **** +92 Invisibility_Sphere **** **** **** E 0 2 0 -5 +93 Knock **** **** **** **** 0 **** **** **** +94 Lesser_Dispel **** **** **** R 0 **** **** **** +95 Lesser_Mind_Blank **** **** **** E 0 2 13 **** +96 Lesser_Planar_Binding **** **** **** S 0 3 0 -2 +97 Lesser_Restoration **** **** **** C 0 **** **** **** +98 Lesser_Spell_Breach **** **** 0 R 1 **** **** **** +99 Lesser_Spell_Mantle **** **** **** P 0 2 0 -9 +100 Light **** **** **** **** 0 3 0 -15 +101 Lightning_Bolt Electricity Reflex 1 I 1 **** **** **** +102 Mage_Armor **** **** **** P 0 3 7 -102 +103 Magic_Circle_against_Chaos **** **** **** P 0 3 14 -10 +104 Magic_Circle_against_Evil **** **** **** P 0 3 14 -11 +105 Magic_Circle_against_Good **** **** **** P 0 3 14 -12 +106 Magic_Circle_against_Law **** **** **** P 0 3 14 -13 +107 Magic_Missile **** **** 1 R 1 **** **** **** +108 Magic_Vestment[NOT_USED] **** **** **** **** **** **** **** **** +109 Magic_Weapon[NOT_USED] **** **** **** **** **** **** **** **** +110 Mass_Blindness_and_Deafness Blindness Will 1 D 1 **** **** **** +111 Mass_Charm Charm Will 1 D 1 **** **** **** +112 Mass_Domination Domination Will 1 D 1 **** **** **** +113 Mass_Haste **** **** **** E 0 2 0 -16 +114 Mass_Heal **** **** **** H 0 **** **** **** +115 Melfs_Acid_Arrow Acid **** 0 R 1 **** **** **** +116 Meteor_Swarm Fire Reflex 1 D 1 **** **** **** +117 Mind_Blank **** **** **** E 0 2 0 **** +118 Mind_Fog Mind_Affecting Will 1 I 1 **** **** **** +119 Minor_Globe_of_Invulnerability **** **** **** P 0 2 0 -7 +120 Ghostly_Visage **** **** **** P 0 2 0 -8 +121 Ethereal_Visage **** **** **** E 0 2 0 -8 +122 Mordenkainens_Disjunction **** **** **** I 0 **** **** **** +123 Mordenkainens_Sword **** **** **** S 0 2 0 -2 +124 Natures_Balance Postive Will 0 D 0 **** **** **** +125 Negative_Energy_Protection **** **** **** P 0 2 10 **** +126 Neutralize_Poison **** **** **** C 0 **** **** **** +127 Phantasmal_Killer Fear Will 1 R 1 **** **** **** +128 Planar_Binding **** **** **** S 0 3 0 -2 +129 Poison Poison Fortitude 1 R 1 **** **** **** +130 Polymorph_Self **** **** **** **** 0 2 0 -17 +131 Power_Word_Kill **** **** 1 R 1 **** **** **** +132 Power_Word_Stun **** **** 1 I 1 **** **** **** +133 Prayer **** **** **** E 0 2 0 **** +134 Premonition **** **** **** P 0 3 0 -8 +135 Prismatic_Spray Mind_Affecing Will 1 I 1 **** **** **** +136 Protection__from_Chaos[NOT_USED] **** **** **** **** **** **** **** **** +137 Protection_from_Elements **** **** **** P 0 3 10 -1 +138 Protection_from_Evil **** **** **** **** **** **** **** **** +139 Protection_from_Good **** **** **** **** **** **** **** **** +140 Protection_from_Law **** **** **** **** **** **** **** **** +141 Protection_from_Spells **** **** **** P 0 3 0 **** +142 Raise_Dead **** **** **** **** 0 **** **** **** +143 Ray_of_Enfeeblement **** **** 1 R 1 **** **** **** +144 Ray_of_Frost Cold **** 1 R 1 **** **** **** +145 Remove_Blindness_and_Deafness **** **** **** C 0 **** **** **** +146 Remove_Curse **** **** **** C 0 **** **** **** +147 Remove_Disease **** **** **** C 0 **** **** **** +148 Remove_Fear **** **** **** C 0 3 13 **** +149 Remove_Paralysis **** **** **** C 0 **** **** **** +150 Resist_Elements **** **** **** P 0 2 10 -1 +151 Resistance **** **** **** P 0 2 14 **** +152 Restoration **** **** **** C 0 **** **** **** +153 Resurrection **** **** **** **** 0 **** **** **** +154 Sanctuary **** **** **** E 0 2 8 -5 +155 Scare Fear Will 1 R 1 **** **** **** +156 Searing_Light Divine **** 1 R 1 **** **** **** +157 See_Invisibility **** **** **** E 0 2 9 **** +158 Shades **** **** **** **** 1 **** **** **** +159 Shadow_Conjuration **** **** **** **** 1 **** **** **** +160 Shadow_Shield **** **** **** P 0 2 0 **** +161 Shapechange **** **** **** **** 0 2 0 -17 +162 Shield_of_Law[NOT_USED] **** **** **** **** **** **** **** **** +163 Silence **** **** **** I 1 **** **** **** +164 Slay_Living Negative Fortitude 1 R 1 **** **** **** +165 Sleep Sleep Will 1 I 1 **** **** **** +166 Slow **** **** **** D 1 **** **** **** +167 Sound_Burst Sonic Fortitude 1 I 1 **** **** **** +168 Spell_Resistance **** **** **** P 0 2 14 **** +169 Spell_Mantle **** **** **** P 0 2 0 -9 +170 Sphere_of_Chaos **** **** **** E 1 **** **** **** +171 Stinking_Cloud Poison Fortitude 1 I 1 **** **** **** +172 Stoneskin **** **** **** P 0 3 7 -8 +173 Storm_of_Vengeance Electricity Reflex 1 D 1 **** **** **** +174 Summon_Creature_I **** **** **** S 0 3 0 -2 +175 Summon_Creature_II **** **** **** S 0 3 0 -2 +176 Summon_Creature_III **** **** **** S 0 3 0 -2 +177 Summon_Creature_IV **** **** **** S 0 3 0 -2 +178 Summon_Creature_IX **** **** **** S 0 3 0 -2 +179 Summon_Creature_V **** **** **** S 0 3 0 -2 +180 Summon_Creature_VI **** **** **** S 0 3 0 -2 +181 Summon_Creature_VII **** **** **** S 0 3 0 -2 +182 Summon_Creature_VIII **** **** **** S 0 3 0 -2 +183 Sunbeam Divine Reflex 1 D 1 **** **** **** +184 Tensers_Transformation **** **** **** E 0 **** **** **** +185 Time_Stop **** **** **** D 0 **** **** **** +186 True_Seeing **** **** **** E 0 2 9 **** +187 Unholy_Aura[NOT_USED] **** **** **** **** **** **** **** **** +188 Vampiric_Touch Negative **** 1 T 1 **** **** **** +189 Virtue **** **** **** E 0 2 10 **** +190 Wail_of_the_Banshee Death Fortitude 1 D 1 **** **** **** +191 Wall_of_Fire Fire Reflex 1 I 1 **** **** **** +192 Web **** Reflex 1 I 1 **** **** **** +193 Weird Fear Will 1 D 1 **** **** **** +194 Word_of_Faith Divine **** 1 D 1 **** **** **** +195 AURA_BLINDING Mind_Affecting Will 0 A 1 **** **** **** +196 Aura_Cold **** **** **** A 1 **** **** **** +197 Aura_Electricity **** **** **** A 1 **** **** **** +198 Aura_Fear **** **** **** A 1 **** **** **** +199 Aura_Fire **** **** **** A 1 **** **** **** +200 Aura_Menace **** **** **** A 1 **** **** **** +201 Aura_Protection **** **** **** A 0 **** **** **** +202 Aura_Stun **** **** **** A 1 **** **** **** +203 Aura_Unearthly_Visage **** **** **** A 1 **** **** **** +204 Aura_Unnatural **** **** **** A 1 **** **** **** +205 Bolt_Ability_Drain_Charisma **** **** 0 R 1 **** **** **** +206 Bolt_Ability_Drain_Constitution **** **** 0 R 1 **** **** **** +207 Bolt_Ability_Drain_Dexterity **** **** 0 R 1 **** **** **** +208 Bolt_Ability_Drain_Intelligence **** **** 0 R 1 **** **** **** +209 Bolt_Ability_Drain_Strength **** **** 0 R 1 **** **** **** +210 Bolt_Ability_Drain_Wisdom **** **** 0 R 1 **** **** **** +211 Bolt_Acid Acid **** 0 R 1 **** **** **** +212 Bolt_Charm **** **** 0 R 1 **** **** **** +213 Bolt_Cold Cold **** 0 R 1 **** **** **** +214 Bolt_Confuse **** **** 0 R 1 **** **** **** +215 Bolt_Daze **** **** 0 R 1 **** **** **** +216 Bolt_Death **** **** 0 R 1 **** **** **** +217 Bolt_Disease **** **** 0 R 1 **** **** **** +218 Bolt_Dominate **** **** 0 R 1 **** **** **** +219 Bolt_Fire Fire **** 0 R 1 **** **** **** +220 Bolt_Knockdown **** **** 0 R 1 **** **** **** +221 Bolt_Level_Drain **** **** 0 R 1 **** **** **** +222 Bolt_Lightning Electricity **** 0 R 1 **** **** **** +223 Bolt_Paralyze **** **** 0 R 1 **** **** **** +224 Bolt_Poison **** **** 0 R 1 **** **** **** +225 Bolt_Shards **** **** 0 R 1 **** **** **** +226 Bolt_Slow **** **** 0 R 1 **** **** **** +227 Bolt_Stun **** **** 0 R 1 **** **** **** +228 Bolt_Web **** **** 0 R 1 **** **** **** +229 Cone_Acid Acid Reflex 0 I 1 **** **** **** +230 Cone_Cold Cold Reflex 0 I 1 **** **** **** +231 Cone_Disease Disease Fortitude 0 I 1 **** **** **** +232 Cone_Fire Fire Reflex 0 I 1 **** **** **** +233 Cone_Lightning Electricity Reflex 0 I 1 **** **** **** +234 Cone_Poison Poison Fortitude 0 I 1 **** **** **** +235 Cone_Sonic Sonic Reflex 0 I 1 **** **** **** +236 Dragon_Breath_Acid Acid Reflex 0 **** 1 **** **** **** +237 Dragon_Breath_Cold Cold Reflex 0 **** 1 **** **** **** +238 Dragon_Breath_Fear Fear Will 0 **** 1 **** **** **** +239 Dragon_Breath_Fire Fire Reflex 0 **** 1 **** **** **** +240 Dragon_Breath_Gas Acid Reflex 0 **** 1 **** **** **** +241 Dragon_Breath_Lightning Electricity Reflex 0 **** 1 **** **** **** +242 Dragon_Breath_Paralyze Paralyze Fortitude 0 **** 1 **** **** **** +243 Dragon_Breath_Sleep Sleep Will 0 **** 1 **** **** **** +244 Dragon_Breath_Slow **** Reflex 0 **** 1 **** **** **** +245 Dragon_Breath_Weaken Negative Reflex 0 **** 1 **** **** **** +246 Dragon_Wing_Buffet **** **** **** **** 1 **** **** **** +247 Ferocity_1 **** **** **** **** 0 **** **** **** +248 Ferocity_2 **** **** **** **** 0 **** **** **** +249 Ferocity_3 **** **** **** **** 0 **** **** **** +250 Gaze_Charm Charm Will 0 I 1 **** **** **** +251 Gaze_Confusion Confusion Will 0 I 1 **** **** **** +252 Gaze_Daze Daze Will 0 I 1 **** **** **** +253 Gaze_Death Death Will 0 I 1 **** **** **** +254 Gaze_Destroy_Chaos Death Will 0 I 1 **** **** **** +255 Gaze_Destroy_Evil Death Will 0 I 1 **** **** **** +256 Gaze_Destroy_Good Death Will 0 I 1 **** **** **** +257 Gaze_Destroy_Law Death Will 0 I 1 **** **** **** +258 Gaze_Dominate Domination Will 0 I 1 **** **** **** +259 Gaze_Doom **** Will 0 I 1 **** **** **** +260 Gaze_Fear Fear Will 0 I 1 **** **** **** +261 Gaze_Paralysis **** Will 0 I 1 **** **** **** +262 Gaze_Stunned Mind_Affecting Will 0 I 1 **** **** **** +263 Golem_Breath_Gas Poison Fortitude 0 I 1 **** **** **** +264 Hell_Hound_Firebreath Fire **** 0 I 1 **** **** **** +265 Howl_Confuse Confusion Will 0 I 1 **** **** **** +266 Howl_Daze Daze Will 0 I 1 **** **** **** +267 Howl_Death Death Will 0 I 1 **** **** **** +268 Howl_Doom **** Will 0 I 1 **** **** **** +269 Howl_Fear Fear Will 0 I 1 **** **** **** +270 Howl_Paralysis **** Will 0 I 1 **** **** **** +271 Howl_Sonic Sonic Fortitude 0 I 1 **** **** **** +272 Howl_Stun Mind_Affecting Will 0 I 1 **** **** **** +273 Intensity_1 **** **** **** **** 0 **** **** **** +274 Intensity_2 **** **** **** **** 0 **** **** **** +275 Intensity_3 **** **** **** **** 0 **** **** **** +276 Krenshar_Scare Fear Will 0 D 1 **** **** **** +277 Lesser_Body_Adjustment **** **** **** H 0 **** **** **** +278 Mephit_Salt_Breath Acid Reflex 0 I 1 **** **** **** +279 Mephit_Steam_Breath Fire Reflex 0 I 1 **** **** **** +280 Mummy_Bolster_Undead **** **** **** E 1 **** **** **** +281 Pulse_Drown **** Reflex 0 D 1 **** **** **** +282 Pulse_Spores Disease Fortitude 0 D 1 **** **** **** +283 Pulse_Whirlwind **** Reflex 0 D 1 **** **** **** +284 Pulse_Fire Fire Reflex 0 I 1 **** **** **** +285 Pulse_Lightning Electricity Reflex 0 I 1 **** **** **** +286 Pulse_Cold Cold Reflex 0 I 1 **** **** **** +287 Pulse_Negative Negative Reflex 0 I 1 **** **** **** +288 Pulse_Holy Divine Reflex 0 I 1 **** **** **** +289 Pulse_Death Death Fortitude 0 I 1 **** **** **** +290 Pulse_Level_Drain Level_Drain Fortitude 0 I 1 **** **** **** +291 Pulse_Ability_Drain_Intelligence Ability_Drain Fortitude 0 D 1 **** **** **** +292 Pulse_Ability_Drain_Charisma Ability_Drain Fortitude 0 D 1 **** **** **** +293 Pulse_Ability_Drain_Constitution Ability_Drain Fortitude 0 D 1 **** **** **** +294 Pulse_Ability_Drain_Dexterity Ability_Drain Fortitude 0 D 1 **** **** **** +295 Pulse_Ability_Drain_Strength Ability_Drain Fortitude 0 D 1 **** **** **** +296 Pulse_Ability_Drain_Wisdom Ability_Drain Fortitude 0 D 1 **** **** **** +297 Pulse_Poison Poison Fortitude 0 D 1 **** **** **** +298 Pulse_Disease Disease Fortitude 0 D 1 **** **** **** +299 Rage_3 **** **** **** *** 0 **** **** **** +300 Rage_4 **** **** **** *** 0 **** **** **** +301 Rage_5 **** **** **** **** 0 **** **** **** +302 Smoke_Claw **** Fortitude 0 T 1 **** **** **** +303 Summon_Slaad **** **** **** S 1 **** **** **** +304 Summon_Tanarri **** **** **** S 1 **** **** **** +305 Trumpet_Blast **** Will 0 D 1 **** **** **** +306 Tyrant_Fog_Mist **** **** **** A 1 **** **** **** +307 BARBARIAN_RAGE **** **** **** **** 0 **** **** **** +308 Turn_Undead Divine **** **** D 1 **** **** **** +309 Wholeness_of_Body **** **** **** H 0 **** **** **** +310 Quivering_Palm **** **** **** **** 1 **** **** **** +311 Empty_Body **** **** **** E 0 **** **** **** +312 Detect_Evil **** **** **** **** 0 **** **** **** +313 Lay_On_Hands **** **** **** H 0 **** **** **** +314 Aura_Of_Courage **** **** **** **** 0 **** **** **** +315 Smite_Evil **** **** **** T 1 **** **** **** +316 Remove_Disease **** **** **** C 0 **** **** **** +317 Summon_Animal_Companion **** **** **** **** 0 **** **** **** +318 Summon_Familiar **** **** **** **** 0 **** **** **** +319 Elemental_Shape **** **** **** **** 0 **** **** **** +320 Wild_Shape **** **** **** **** 0 **** **** **** +321 PROTECTION_FROM_ALIGNMENT **** **** **** **** 0 **** **** **** +322 Magic_Circle_against_Alignment **** **** **** **** 0 **** **** **** +323 Aura_versus_Alignment **** **** **** **** 0 **** **** **** +324 SHADES_Summon_Shadow **** **** **** D 0 **** **** **** +325 DELETED_PRO_Cold **** **** **** **** 0 **** **** **** +326 DELETED_PRO_Fire **** **** **** **** 0 **** **** **** +327 DELETED_PRO_Acid **** **** **** **** 0 **** **** **** +328 DELETED_PRO_Sonic **** **** **** **** 0 **** **** **** +329 DELETED_PRO_Elec **** **** **** **** 0 **** **** **** +330 DELETED_END_Cold **** **** **** **** 0 **** **** **** +331 DELETED_END_Fire **** **** **** **** 0 **** **** **** +332 DELETED_END_Acid **** **** **** **** 0 **** **** **** +333 DELETED_END_Sonic **** **** **** **** 0 **** **** **** +334 DELETED_END_Elec **** **** **** **** 0 **** **** **** +335 DELETED_RES_Cold **** **** **** **** 0 **** **** **** +336 DELETED_RES_Fire **** **** **** **** 0 **** **** **** +337 DELETED_RES_Acid **** **** **** **** 0 **** **** **** +338 DELETED_RES_Sonic **** **** **** **** 0 **** **** **** +339 DELETED_RES_Elec **** **** **** **** 0 **** **** **** +340 SHADES_Cone_of_Cold Cold Reflex 1 I 1 **** **** **** +341 SHADES_Fireball Fire Reflex 1 I 1 **** **** **** +342 SHADES_Stoneskin **** **** **** P 0 **** **** **** +343 SHADES_Wall_of_Fire Fire Reflex 1 I 1 **** **** **** +344 SHADOW_CON_Summon_Shadow **** **** **** D 0 **** **** **** +345 SHADOW_CON_Darkness **** **** **** I 0 **** **** **** +346 SHADOW_CON_Inivsibility **** **** **** E 0 **** **** **** +347 SHADOW_CON_Mage_Armor **** **** **** P 0 **** **** **** +348 SHADOW_CON_Magic_Missile **** **** 1 R 1 **** **** **** +349 GR_SHADOW_CON_Summon_Shadow **** **** **** D 0 **** **** **** +350 GR_SHADOW_CON_Acid_Arrow Acid **** 1 R 1 **** **** **** +351 GR_SHADOW_CON_Ghostly_Visage **** **** **** P 0 **** **** **** +352 GR_SHADOW_CON_Web **** Reflex 0 I 1 **** **** **** +353 GR_SHADOW_CON_Minor_Globe **** **** **** P 0 **** **** **** +354 Eagle_Splendor **** **** **** E 0 3 6 **** +355 Owls_Wisdom **** **** **** E 0 3 5 **** +356 Foxs_Cunning **** **** **** E 0 3 4 **** +357 Greater_Eagle_Splendor[NOT_USED] **** **** **** **** **** **** **** **** +358 Greater_Owls_Wisdom[NOT_USED] **** **** **** **** **** **** **** **** +359 Greater_Foxs_Cunning[NOT_USED] **** **** **** **** **** **** **** **** +360 Greater_Bulls_Strength[NOT_USED] **** **** **** **** **** **** **** **** +361 Greater_Cats_Grace[NOT_USED] **** **** **** **** *** **** **** **** +362 Greater_Endurance[NOT_USED] **** **** **** **** **** **** **** **** +363 Awaken **** **** **** E 0 **** **** **** +364 Creeping_Doom **** **** 0 D 1 **** **** **** +365 Ultravision **** **** **** E 0 3 9 **** +366 Destruction Death Fortitude 1 R 1 **** **** **** +367 Horrid_Wilting **** Fortitude 1 D 1 **** **** **** +368 Ice_Storm Cold **** 1 I 1 **** **** **** +369 Energy_Buffer **** **** **** P 0 2 0 -1 +370 Negative_Energy_Burst Negative Will 1 D 1 **** **** **** +371 Negative_Energy_Ray Negative Will 1 R 1 **** **** **** +372 Aura_of_Vitality **** **** **** E 0 2 0 **** +373 War_Cry **** **** **** D 0 **** **** **** +374 Regenerate **** **** **** E 0 2 10 -6 +375 Evards_Black_Tentacles **** Fortitude 0 D 1 **** **** **** +376 Legend_Lore **** **** **** **** 0 **** **** **** +377 Find_Traps **** **** **** **** 0 **** **** **** +378 Summon_Mephit **** **** **** S 0 **** **** **** +379 Summon_Celestial **** **** **** S 0 **** **** **** +380 Battle_Mastery_Spell **** **** **** E 0 **** **** **** +381 Divine_Strength **** **** **** E 0 **** **** **** +382 Divine_Protection **** **** **** E 0 **** **** **** +383 Negative_Plane_Avatar **** **** **** E 0 **** **** **** +384 Divine_Trickery **** **** **** E 0 **** **** **** +385 Rogues_Cunning **** **** **** E 0 **** **** **** +386 ACTIVATE_ITEM **** **** **** **** 0 **** **** **** +387 Polymorph_GIANT_SPIDER **** **** **** **** 0 **** **** **** +388 Polymorph_TROLL **** **** **** **** 0 **** **** **** +389 Polymorph_UMBER_HULK **** **** **** **** 0 **** **** **** +390 Polymorph_PIXIE **** **** **** **** 0 **** **** **** +391 Polymorph_ZOMBIE **** **** **** **** 0 **** **** **** +392 Shapechange_RED_DRAGON **** **** **** **** 0 **** **** **** +393 Shapechange_FIRE_GIANT **** **** **** **** 0 **** **** **** +394 Shapechange_BALOR **** **** **** **** 0 **** **** **** +395 Shapechange_DEATH_SLAAD **** **** **** **** 0 **** **** **** +396 Shapechange_IRON_GOLEM **** **** **** **** 0 **** **** **** +397 Elemental_Shape_FIRE **** **** **** **** 0 **** **** **** +398 Elemental_Shape_WATER **** **** **** **** 0 **** **** **** +399 Elemental_Shape_EARTH **** **** **** **** 0 **** **** **** +400 Elemental_Shape_AIR **** **** **** **** 0 **** **** **** +401 Wild_Shape_BROWN_BEAR **** **** **** **** 0 **** **** **** +402 Wild_Shape_PANTHER **** **** **** **** 0 **** **** **** +403 Wild_Shape_WOLF **** **** **** **** 0 **** **** **** +404 Wild_Shape_BOAR **** **** **** **** 0 **** **** **** +405 Wild_Shape_BADGER **** **** **** **** 0 **** **** **** +406 Special_Alcohol_Beer **** **** **** **** 0 **** **** **** +407 Special_Alcohol_Wine **** **** **** **** 0 **** **** **** +408 Special_Alcohol_Spirits **** **** **** **** 0 **** **** **** +409 Special_Herb_Belladonna **** **** **** **** 0 **** **** **** +410 Special_Herb_Garlic **** **** **** **** 0 **** **** **** +411 Bards_Song **** **** **** **** 0 **** **** **** +412 Aura_Fear_Dragon **** **** **** A 1 **** **** **** +413 ACTIVATE_ITEM_SELF **** **** **** **** 0 **** **** **** +414 Divine_Favor **** **** **** E 0 2 0 **** +415 True_Strike **** **** **** E 0 **** **** **** +416 Flare **** Fortitude 1 R 1 **** **** **** +417 Shield **** **** **** P 0 2 7 **** +418 Entropic_Shield **** **** **** P 0 2 0 **** +419 Continual_Flame **** **** **** **** 0 3 0 -15 +420 One_With_The_Land **** **** **** **** 0 3 0 **** +421 Camoflage **** **** **** **** 0 3 0 **** +422 Blood_Frenzy **** **** **** **** 0 2 0 **** +423 Bombardment **** Reflex 1 I 1 **** **** **** +424 Acid_Splash Acid **** 0 R 1 **** **** **** +425 Quillfire Poison Fortitude 0 R 1 **** **** **** +426 Earthquake **** Fortitude 0 I 1 **** **** **** +427 Sunburst Divine Reflex 1 D 1 **** **** **** +428 ACTIVATE_ITEM_SELF2 **** **** **** **** 0 **** **** **** +429 AuraOfGlory Mind_Affecting **** **** E 0 2 0 **** +430 Banishment **** Will 1 I 1 **** **** **** +431 Inflict_Minor_Wounds Negative Will 1 T 1 **** **** **** +432 Inflict_Light_Wounds Negative Will 1 T 1 **** **** **** +433 Inflict_Moderate_Wounds Negative Will 1 T 1 **** **** **** +434 Inflict_Serious_Wounds Negative Will 1 T 1 **** **** **** +435 Inflict_Critical_Wounds Negative Will 1 T 1 **** **** **** +436 BalagarnsIronHorn **** **** 1 D 1 **** **** **** +437 Drown **** Fortitude 1 R 1 **** **** **** +438 Owls_Insight **** **** **** E 0 3 5 **** +439 Electric_Jolt Electricity **** 0 R 1 **** **** **** +440 Firebrand Fire Reflex 1 R 1 **** **** **** +441 Wounding_Whispers Sonic **** 0 P 0 2 0 **** +442 Amplify **** **** **** E 0 2 5 **** +443 Etherealness **** **** **** E 0 2 0 -5 +444 Undeaths_Eternal_Foe **** **** **** E 0 2 10 **** +445 Dirge **** Fortitude 0 I 1 **** **** **** +446 Inferno Fire **** 1 R 1 **** **** **** +447 Isaacs_Lesser_Missile_Storm **** **** 1 R 1 **** **** **** +448 Isaacs_Greater_Missile_Storm **** **** 1 R 1 **** **** **** +449 Bane Fear Will 1 E 1 **** **** **** +450 Shield_of_Faith **** **** **** P 0 2 7 -3 +451 Planar_Ally **** **** **** S 0 3 0 -2 +452 Magic_Fang **** **** **** P 0 **** **** **** +453 Greater_Magic_Fang **** **** **** P 0 **** **** **** +454 Spike_Growth **** Reflex 1 I 1 **** **** **** +455 Mass_Camoflage **** **** **** E 0 2 0 **** +456 Expeditious_Retreat **** **** **** E 0 2 7 **** +457 Tashas_Hideous_Laughter Mind_Affecting Will 1 R 1 **** **** **** +458 Displacement **** **** **** E 0 2 7 -8 +459 Bigbys_Interposing_Hand **** **** **** R 0 **** **** **** +460 Bigbys_Forceful_Hand **** **** 1 R 1 **** **** **** +461 Bigbys_Grasping_Hand **** **** 1 R 1 **** **** **** +462 Bigbys_Clenched_Fist **** **** 1 R 1 **** **** **** +463 Bigbys_Crushing_Hand **** **** 1 R 1 **** **** **** +464 Grenade_Fire Fire **** 0 I 1 **** **** **** +465 Grenade_Tangle **** Reflex 0 I 1 **** **** **** +466 Grenade_Holy Divine **** 0 I 1 **** **** **** +467 Grenade_Choking **** **** 0 I 1 **** **** **** +468 Grenade_Thunderstone **** Fortitude 0 I 1 **** **** **** +469 Grenade_Acid Acid **** 0 I 1 **** **** **** +470 Grenade_Chicken **** **** 0 R 1 **** **** **** +471 Grenade_Caltrops **** **** 0 I 1 **** **** **** +472 ACTIVATE_ITEM_PORTAL **** **** **** **** 0 **** **** **** +473 Divine_Might **** **** **** **** 0 **** **** **** +474 Divine_Shield **** **** **** **** 0 **** **** **** +475 SHADOW_DAZE Daze Will 1 R 1 **** **** **** +476 SUMMON_SHADOW **** **** **** R 1 **** **** **** +477 SHADOW_EVADE **** **** **** E 0 **** **** **** +478 TYMORAS_SMILE **** **** **** E 0 **** **** **** +479 CRAFT_HARPER_ITEM **** **** **** **** 0 **** **** **** +480 Sleep Sleep Will 1 D 1 **** **** **** +481 Cats_Grace **** **** **** E 0 **** **** **** +482 Eagle_Splendor **** **** **** E 0 **** **** **** +483 Invisibility **** **** **** E 0 **** **** **** +484 **** **** **** **** **** **** **** **** **** +485 Flesh_to_stone **** Fortitude 1 R 1 **** **** **** +486 Stone_to_flesh **** **** **** E 0 **** **** **** +487 Trap_Arrow **** **** **** **** 1 **** **** **** +488 Trap_Bolt **** **** **** **** 1 **** **** **** +489 PADDING **** **** **** **** **** **** **** **** +490 PADDING **** **** **** **** **** **** **** **** +491 PADDING **** **** **** **** **** **** **** **** +492 PADDING **** **** **** **** **** **** **** **** +493 Trap_Dart **** **** **** **** 1 **** **** **** +494 Trap_Shuriken **** **** **** **** 1 **** **** **** +495 Breath_Petrify Petrification Fortitude 0 R 1 **** **** **** +496 Touch_Petrify Petrification Fortitude 0 R 1 **** **** **** +497 Gaze_Petrify Petrification Fortitude 0 R 1 **** **** **** +498 Manticore_Spikes **** **** **** R 1 **** **** **** +499 RodOfWonder **** **** **** **** 1 **** **** **** +500 DeckOfManyThings **** **** **** **** 0 **** **** **** +501 PADDING **** **** **** **** **** **** **** **** +502 ElementalSummoningItem **** **** **** **** 0 3 0 -2 +503 DeckAvatar **** **** **** **** 0 **** **** **** +504 Gem_Spray **** **** **** **** 1 **** **** **** +505 Butterfly_Spray **** **** **** **** 1 **** **** **** +506 HealingKit **** **** **** E **** **** **** **** +507 PowerStone **** **** **** **** 0 **** **** **** +508 Spellstaff **** **** **** **** 0 **** **** **** +509 Charger **** **** **** **** 0 **** **** **** +510 Decharger **** **** **** **** 0 **** **** **** +511 Kobold_Jump **** **** **** **** **** **** **** **** +512 Crumble Sonic **** 0 R 1 **** **** **** +513 Infestation_of_Maggots Disease Fortitude 1 T 1 **** **** **** +514 Healing_Sting Negative Fortitude 1 T 1 **** **** **** +515 Great_Thunderclap Sonic **** 0 I 1 **** **** **** +516 Ball_Lightning Electricity **** 1 I 1 **** **** **** +517 Battletide **** **** 1 D 1 **** **** **** +518 Combust Fire Reflex 1 T 1 **** **** **** +519 Death_Armor **** **** **** P 0 2 0 **** +520 Gedlees_Electric_Loop Electricity Reflex 1 D 1 **** **** **** +521 Horizikauls_Boom Sonic Will 1 R 1 **** **** **** +522 Ironguts **** **** **** E 0 3 11 **** +523 Mestils_Acid_Breath Acid Reflex 1 I 1 **** **** **** +524 Mestils_Acid_Sheath Acid **** **** P 0 2 9 **** +525 Monstrous_Regeneration **** **** **** H 0 2 10 -6 +526 Scintillating_Sphere Electricity Reflex 1 I 1 **** **** **** +527 Stone_Bones **** **** **** P 0 3 7 **** +528 Undeath_to_Death **** Will 1 D 1 **** **** **** +529 Vine_Mine **** **** 0 **** 1 **** **** **** +530 Vine_Mine_Entangle **** **** 0 I 1 **** **** **** +531 Vine_Mine_Hamper_Movement **** **** 0 I 1 **** **** **** +532 Vine_Mine_Camouflage **** **** **** P 0 **** **** **** +533 Black_Blade_of_Disaster **** **** **** S 0 **** **** **** +534 Shelgarns_Persistent_Blade **** **** **** S 0 2 0 -2 +535 Blade_Thirst **** **** **** E 0 2 15 -14 +536 Deafening_Clang **** **** **** E 0 2 15 -14 +537 Bless_Weapon **** **** **** E 0 2 15 **** +538 Holy_Sword **** **** **** E 0 2 15 **** +539 Keen_Edge **** **** **** E 0 3 15 **** +540 **** **** **** **** **** **** **** **** **** +541 Blackstaff **** **** **** E 0 2 15 **** +542 Flame_Weapon **** **** **** E 0 3 15 **** +543 Ice_Dagger Cold Reflex 1 R 1 **** **** **** +544 Magic_Weapon **** **** **** E 0 3 15 -14 +545 Greater_Magic_Weapon **** **** **** E 0 3 15 -14 +546 Magic_Vestment **** **** **** E 0 3 15 -4 +547 Stonehold Paralysis Will 1 I 1 **** **** **** +548 Darkfire **** **** **** E 0 3 15 **** +549 Glyph_of_Warding Sonic Reflex 1 I 1 **** **** **** +550 **** **** **** **** **** **** **** **** **** +551 MONSTER_MindBlast **** **** **** I 1 **** **** **** +552 MONSTER_CharmMonster **** **** **** R 1 **** **** **** +553 Goblin_Ballista_Fireball Fire **** **** **** 1 **** **** **** +554 Ioun_Stone_Dusty_Rose **** **** **** **** 0 **** **** **** +555 Ioun_Stone_Pale_Blue **** **** **** **** 0 **** **** **** +556 Ioun_Stone_Scarlet_Blue **** **** **** **** 0 **** **** **** +557 Ioun_Stone_Blue **** **** **** **** 0 **** **** **** +558 Ioun_Stone_Deep_Red **** **** **** **** 0 **** **** **** +559 Ioun_Stone_Pink **** **** **** **** 0 **** **** **** +560 Ioun_Stone_Pink_Green **** **** **** **** 0 **** **** **** +561 Whirlwind **** **** **** **** 0 **** **** **** +562 AuraOfGlory_X2 Mind_Affecting **** **** E 0 **** **** **** +563 Haste_Slow_X2 **** **** **** E 0 **** **** **** +564 Summon_Shadow_X2 **** **** **** S 0 **** **** **** +565 Tide_of_Battle **** **** **** D 0 **** **** **** +566 Evil_Blight **** **** **** T 0 **** **** **** +567 Cure_Critical_Wounds_Others **** **** **** H 0 **** **** **** +568 Restoration_Others **** **** **** C 0 **** **** **** +569 Cloud_of_Bewilderment Poison Fortitude 1 I 1 **** **** **** +570 PADDING **** **** **** **** **** **** **** **** +571 PADDING **** **** **** **** **** **** **** **** +572 PADDING **** **** **** **** **** **** **** **** +573 PADDING **** **** **** **** **** **** **** **** +574 PADDING **** **** **** **** **** **** **** **** +575 PADDING **** **** **** **** **** **** **** **** +576 PADDING **** **** **** **** **** **** **** **** +577 PADDING **** **** **** **** **** **** **** **** +578 PADDING **** **** **** **** **** **** **** **** +579 PADDING **** **** **** **** **** **** **** **** +580 PADDING **** **** **** **** **** **** **** **** +581 PADDING **** **** **** **** **** **** **** **** +582 PADDING **** **** **** **** **** **** **** **** +583 PADDING **** **** **** **** **** **** **** **** +584 PADDING **** **** **** **** **** **** **** **** +585 PADDING **** **** **** **** **** **** **** **** +586 PADDING **** **** **** **** **** **** **** **** +587 PADDING **** **** **** **** **** **** **** **** +588 PADDING **** **** **** **** **** **** **** **** +589 PADDING **** **** **** **** **** **** **** **** +590 PADDING **** **** **** **** **** **** **** **** +591 PADDING **** **** **** **** **** **** **** **** +592 PADDING **** **** **** **** **** **** **** **** +593 PADDING **** **** **** **** **** **** **** **** +594 PADDING **** **** **** **** **** **** **** **** +595 PADDING **** **** **** **** **** **** **** **** +596 PADDING **** **** **** **** **** **** **** **** +597 PADDING **** **** **** **** **** **** **** **** +598 PADDING **** **** **** **** **** **** **** **** +599 PADDING **** **** **** **** **** **** **** **** +600 ARImbueArrow **** **** **** **** 1 **** **** **** +601 ARSeekerArrow **** **** **** **** 1 **** **** **** +602 ARSeekerArrow2 **** **** **** **** 1 **** **** **** +603 ARHailOfArrows **** **** **** I 1 **** **** **** +604 ARArrowOfDeath **** **** **** **** 1 **** **** **** +605 ASGhostlyVisage **** **** **** P 0 **** **** **** +606 ASDarkness **** **** **** **** 0 **** **** **** +607 ASInvisibility **** **** **** E 0 **** **** **** +608 ASImprovedInvisibility **** **** **** E 0 **** **** **** +609 BGCreateDead **** **** **** S 1 **** **** **** +610 BGFiendish Negative **** **** T 1 **** **** **** +611 BGInflictSerious Negative **** **** T 1 **** **** **** +612 BGInflictCritical Negative **** **** T 1 **** **** **** +613 BK_Contagion Disease **** **** T 1 **** **** **** +614 BK_BullsStrength **** **** **** E 0 **** **** **** +615 Twinfists **** **** **** **** 0 **** **** **** +616 LichLyrics **** **** **** **** 0 **** **** **** +617 Iceberry **** **** **** **** 0 **** **** **** +618 Flameberry **** **** **** **** 0 **** **** **** +619 PrayerBox **** **** **** **** 0 **** **** **** +620 Flying_Debris **** **** **** **** **** **** **** **** +621 PADDING **** **** **** **** **** **** **** **** +622 DC_Divine_Wrath **** **** **** E 0 **** **** **** +623 PM_Animate_Dead **** **** **** S 0 **** **** **** +624 PM_Summon_Undead **** **** **** S 0 **** **** **** +625 PM_Undead_Graft1 Mind_Affecting **** **** T 1 **** **** **** +626 PM_Undead_Graft2 Mind_Affecting **** **** T 1 **** **** **** +627 PM_Summon_Greater_Undead **** **** **** S 0 **** **** **** +628 PM_Deathless_Master_Touch Death **** **** T 1 **** **** **** +629 PADDING **** **** **** **** **** **** **** **** +630 PADDING **** **** **** **** **** **** **** **** +631 PADDING **** **** **** **** **** **** **** **** +632 PADDING **** **** **** **** **** **** **** **** +633 PADDING **** **** **** **** **** **** **** **** +634 PADDING **** **** **** **** **** **** **** **** +635 PADDING **** **** **** **** **** **** **** **** +636 Hellball **** Reflex 0 I 1 **** **** **** +637 Mummy_Dust **** **** **** S 0 **** **** **** +638 Dragon_Knight **** **** **** S 0 **** **** **** +639 Epic_Mage_Armor **** **** **** P 0 **** **** **** +640 Ruin Positive Fortitude 0 R 1 **** **** **** +641 DWDEF_Defensive_Stance **** **** **** A 0 **** **** **** +642 Mighty_Rage **** **** **** A 0 **** **** **** +643 PlanarTurning **** **** **** D 1 **** **** **** +644 Curse_Song **** **** **** E 0 **** **** **** +645 Improved_Whirlwind **** **** **** **** 0 **** **** **** +646 Greater_Wild_Shape_1 **** **** **** **** 0 **** **** **** +647 Epic_Blinding_speed **** **** **** E 0 **** **** **** +648 Dye_Armor_cloth1 **** **** **** **** 0 **** **** **** +649 Dye_Armor_Cloth2 **** **** **** **** 0 **** **** **** +650 Dye_Armor_Leather1 **** **** **** **** 0 **** **** **** +651 Dye_Armor_Leather2 **** **** **** **** 0 **** **** **** +652 Dye_Armor_Metal1 **** **** **** **** 0 **** **** **** +653 Dye_Armor_Metal2 **** **** **** **** 0 **** **** **** +654 Add_Item_Property **** **** **** **** 0 **** **** **** +655 Poison_Weapon **** **** **** **** 0 **** **** **** +656 Craft_Weapon **** **** **** **** 0 **** **** **** +657 Craft_Armor **** **** **** **** 0 **** **** **** +658 Greater_Wild_Shape_Wyrmling_Red **** **** **** **** 0 **** **** **** +659 Greater_Wild_Shape_Wyrmling_Blue **** **** **** **** 0 **** **** **** +660 Greater_Wild_Shape_Wyrmling_Black **** **** **** **** 0 **** **** **** +661 Greater_Wild_Shape_Wyrmling_White **** **** **** **** 0 **** **** **** +662 Greater_Wild_Shape_Wyrmling_Green **** **** **** **** 0 **** **** **** +663 WyrmlingPCBreathCold Cold Reflex 0 I 1 **** **** **** +664 WyrmlingPCBreathAcid Acid Reflex 0 I 1 **** **** **** +665 WyrmlingPCBreathFire Fire Reflex 0 I 1 **** **** **** +666 WyrmlingPCBreathGas Acid Reflex 0 I 1 **** **** **** +667 WyrmlingPCBreathLightning Electricity Reflex 0 I 1 **** **** **** +668 ITEM_Teleport **** **** **** **** **** **** **** **** +669 ITEM_Chaos_Shield **** **** **** **** **** **** **** **** +670 Greater_Wild_Shape_Basilisk **** **** **** **** 0 **** **** **** +671 Greater_Wild_Shape_Beholder **** **** **** **** 0 **** **** **** +672 Greater_Wild_Shape_Harpy **** **** **** **** 0 **** **** **** +673 Greater_Wild_Shape_Drider **** **** **** **** 0 **** **** **** +674 Greater_Wild_Shape_Manticore **** **** **** **** 0 **** **** **** +675 Greater_Wild_Shape_2 **** **** **** **** 0 **** **** **** +676 Greater_Wild_Shape_3 **** **** **** **** 0 **** **** **** +677 Greater_Wild_Shape_4 **** **** **** **** 0 **** **** **** +678 Greater_Wild_Shape_Gargoyle **** **** **** **** 0 **** **** **** +679 Greater_Wild_Shape_Medusa **** **** **** **** 0 **** **** **** +680 Greater_Wild_Shape_Minotaur **** **** **** **** 0 **** **** **** +681 Humanoid_Shape **** **** **** **** 0 **** **** **** +682 Humanoid_Shape_Drow **** **** **** **** 0 **** **** **** +683 Humanoid_Shape_Lizardfolk **** **** **** **** 0 **** **** **** +684 Humanoid_Shape_KoboldAssa **** **** **** **** 0 **** **** **** +685 Undead_shape **** **** **** **** 0 **** **** **** +686 Harpysong Mind_Affecting Will 0 I 1 **** **** **** +687 GWildShape_Stonegaze Petrification Fortitude 0 R 1 **** **** **** +688 GWildShape_DriderDarkness **** **** **** **** 0 **** **** **** +689 SlayRakshasa **** **** **** **** **** **** **** **** +690 RedDragonDiscipleBreath Fire Relfex 0 I 1 **** **** **** +691 Greater_Wild_Shape_Mindflayer **** **** **** **** 0 **** **** **** +692 Greater_Wild_Shape_Spikes **** **** **** R 1 **** **** **** +693 GWildShape_Mindblast **** **** **** I 1 **** **** **** +694 Greater_Wild_Shape_DireTiger **** **** **** **** 0 **** **** **** +695 Epic_Warding **** **** **** P 1 **** **** **** +696 OnHitFireDamage Fire **** **** **** 1 **** **** **** +697 ACTIVATE_ITEM_L **** **** **** **** 0 **** **** **** +698 Dragon_Breath_Negative Negative Reflex 0 I 1 **** **** **** +699 **** **** **** **** P 0 **** **** **** +700 ACTIVATE_ITEM_ONHITSPELLCAST **** **** **** **** 0 **** **** **** +701 Summon_Baatezu **** **** **** S 1 **** **** **** +702 OnHitPlanarRift Cold **** **** R 1 **** **** **** +703 OnHitDarkfire Cold **** **** R 1 **** **** **** +704 Undead_Shape_risen_lord **** **** **** **** 0 **** **** **** +705 Undead_Shape_Vampire **** **** **** **** 0 **** **** **** +706 Undead_Shape_Spectre **** **** **** **** 0 **** **** **** +707 Greater_Wild_Shape_Red_dragon **** **** **** **** 0 **** **** **** +708 Greater_Wild_Shape_Blue_dragon **** **** **** **** 0 **** **** **** +709 Greater_Wild_Shape_Green_dragon **** **** **** **** 0 **** **** **** +710 EyeballRay0 Cold Fortitude 0 R 1 **** **** **** +711 EyeballRay1 Negative Fortitude 0 R 1 **** **** **** +712 EyeballRay2 Fire Fortitude 0 R 1 **** **** **** +713 Mindflayer_Mindblast_10 Mind_Affecting Will 0 I 1 **** **** **** +714 Mindflayer_Paragon_Mindblast **** **** **** P 1 **** **** **** +715 Golem_Ranged_Slam **** Reflex 0 R 1 **** **** **** +716 SuckBrain **** **** **** P 0 **** **** **** +717 ACTIVATE_ITEM_SEQUENCER_1 **** **** **** **** 0 **** **** **** +718 ACTIVATE_ITEM_SEQUENCER_2 **** **** **** **** 0 **** **** **** +719 ACTIVATE_ITEM_SEQUENCER_3 **** **** **** **** 0 **** **** **** +720 CLEAR_SEQUENCER **** **** **** **** 0 **** **** **** +721 OnHitFlamingSkin **** **** **** **** 0 **** **** **** +722 Mimic_Eat **** **** **** R **** **** **** **** +723 Mimic_Gem_Thrower **** **** **** R **** **** **** **** +724 Etherealness **** **** **** **** 0 **** **** **** +725 Dragon_Shape **** **** **** **** 0 **** **** **** +726 Mimic_Eat_Enemy **** **** **** R **** **** **** **** +727 Beholder_Anti_Magic_Cone **** **** **** I **** **** **** **** +728 **** **** **** **** **** 1 **** **** **** +729 Mimic_Steal_armor **** **** **** R **** **** **** **** +730 **** **** **** **** **** 0 **** **** **** +731 Bebelith_Web **** Reflex 0 R 1 **** **** **** +732 Outsider_Shape **** **** **** **** 0 **** **** **** +733 Outsider_Shape_Azer **** **** **** **** 0 **** **** **** +734 Outsider_Shape_Rakshasa **** **** **** **** 0 **** **** **** +735 Outsider_Shape_DeathSlaad **** **** **** **** 0 **** **** **** +736 Beholder_Special_Spell_AI **** **** **** I 1 **** **** **** +737 Construct_Shape **** **** **** **** 0 **** **** **** +738 Construct_Shape_StoneGolem **** **** **** **** 0 **** **** **** +739 Construct_Shape_DemonFleshGolem **** **** **** **** 0 **** **** **** +740 Construct_Shape_IronGolem **** **** **** **** 0 **** **** **** +741 Psionic_Inertial_Barrier **** **** **** P 0 **** **** **** +742 Craft_Weapon_Component **** **** **** **** 0 **** **** **** +743 Craft_Armor_Component **** **** **** **** 0 **** **** **** +744 Grenade_FireBomb Fire **** 0 R 1 **** **** **** +745 Grenade_AcidBomb Acid **** 0 R 1 **** **** **** +746 Hell_Catapult_Male **** **** **** R **** **** **** **** +747 Hell_Catapult_Female **** **** **** R **** **** **** **** +748 Hell_Br_Catapult_Male **** **** **** R **** **** **** **** +749 Hell_Brazier_Male **** **** **** R **** **** **** **** +750 Hell_Fence_Male **** **** **** R **** **** **** **** +751 Hell_Boulder_Male **** **** **** R **** **** **** **** +752 Hell_Tree_Male **** **** **** R **** **** **** **** +753 Hell_KNOWER_EFFECT1 **** **** **** R **** **** **** **** +754 Hell_KNOWER_EFFECT2 **** **** **** R **** **** **** **** +755 Hell_KNOWER_EFFECT3 **** **** **** R **** **** **** **** +756 OnHitBebilithAttack **** **** **** **** 1 **** **** **** +757 ShadowBlend **** **** **** **** 0 **** **** **** +758 OnHitDemilichTouch **** **** **** **** 1 **** **** **** +759 UndeadSelfHarm Positive **** **** H 0 **** **** **** +760 OnHitDracolichTouch **** **** **** **** 1 **** **** **** +761 Aura_of_Hellfire Fire **** **** D 1 **** **** **** +762 Hell_Inferno Fire **** **** R 1 **** **** **** +763 Psionic_Mass_Concussion **** **** **** D 1 **** **** **** +764 GlyphOfWardingDefault **** **** **** I 1 **** **** **** +765 Hell_KNOWER_EFFECT4 **** **** **** R **** **** **** **** +766 Hell_KNOWER_EFFECT5 **** **** **** R **** **** **** **** +767 Intelligent_Weapon_Talk **** **** **** **** 0 **** **** **** +768 Intelligent_Weapon_OnHit **** **** **** **** 1 **** **** **** +769 Shadow_Attack **** **** **** T 1 **** **** **** +770 Slaad_Chaos_Spittle Acid **** **** R 1 **** **** **** +771 Dragon_Breath_Prismatic Mind_Affecting Reflex 0 I 1 **** **** **** +772 Spiral_Fireball Fire **** **** I 1 **** **** **** +773 Battle_Boulder_Toss **** **** **** R **** **** **** **** +774 Deflecting_Force **** **** **** P 0 **** **** **** +775 Giant_hurl_rock **** **** 0 R 1 **** **** **** +776 Beholder_Node_1 Death Fortitude 0 I 1 **** **** **** +777 Beholder_Node_2 **** Will 0 I 1 **** **** **** +778 Beholder_Node_3 Petrification Fortitude 0 I 1 **** **** **** +779 Beholder_Node_4 Charm Will 0 I 1 **** **** **** +780 Beholder_Node_5 **** Will 0 I 1 **** **** **** +781 Bridge_VFX **** **** **** R **** **** **** **** +782 Sphere_Spell **** **** **** R **** **** **** **** +783 Beholder_Node_6 **** Fortitude 0 I 1 **** **** **** +784 Beholder_Node_7 Fear Will 0 I 1 **** **** **** +785 Beholder_Node_8 **** **** 0 I 1 **** **** **** +786 Beholder_Node_9 **** **** 0 I 1 **** **** **** +787 Beholder_Node_10 **** **** 0 I 1 **** **** **** +788 OnHitParalyze **** **** **** **** 1 **** **** **** +789 Illithid_Mindblast **** Will 0 I 1 **** **** **** +790 OnHitDeafenClang **** **** **** **** 1 **** **** **** +791 OnHitKnockDown **** **** **** **** 0 **** **** **** +792 OnHitFreeze **** **** **** **** 0 **** **** **** +793 Demonic_Grappling_Hand **** **** **** R **** **** **** **** +794 Ballista_Bolt **** **** **** I 1 **** **** **** +795 ACTIVATE_ITEM_T **** **** **** **** 0 **** **** **** +796 Dragon_Breath_Lightning Electricity Reflex 0 I 1 **** **** **** +797 Dragon_Breath_Fire Fire Reflex 0 I 1 **** **** **** +798 Dragon_Breath_Gas Acid Reflex 0 I 1 **** **** **** +799 Vampire_Invisibility **** **** **** E 0 **** **** **** +800 Vampire_DominationGaze Domination Will 0 I 1 **** **** **** +801 Azer_Fire_Blast Fire Reflex 0 R 1 **** **** **** +802 Shifter_Spectre_Attack Drain Fortitude 0 T 1 **** **** **** +803 SeaHag_EvilEye Drain Fortitude 0 I 1 **** **** **** +804 Aura_HorrificAppearance **** Fortitude 0 A 1 **** **** **** +805 Troglodyte_Stench **** **** **** A 1 **** **** **** +806 PDK_RallyingCry **** **** **** E 0 **** **** **** +807 PDK_Shield **** **** **** E 0 **** **** **** +808 PDK_Fear Fear Will 1 D 1 **** **** **** +809 PDK_OathOfWrath **** **** **** R 0 **** **** **** +810 PDK_FinalStand **** **** **** E 0 **** **** **** +811 PDK_InspireCourage **** **** **** E 0 **** **** **** +812 Horse_Menu **** **** **** **** 0 **** **** **** +813 Horse_Mount **** **** **** **** 0 **** **** **** +814 Horse_Dismount **** **** **** **** 0 **** **** **** +815 Horse_Party_Mount **** **** **** **** 0 **** **** **** +816 Horse_Party_Dismount **** **** **** **** 0 **** **** **** +817 Horse_Assign_Mount **** **** **** **** 0 **** **** **** +818 Paladin_Summon_Mount **** **** **** **** 0 **** **** **** +819 Nightmare_Smoke **** **** **** A 1 **** **** **** +820 DM_TOOL_01 **** **** **** **** 0 **** **** **** +821 DM_TOOL_02 **** **** **** **** 0 **** **** **** +822 DM_TOOL_03 **** **** **** **** 0 **** **** **** +823 DM_TOOL_04 **** **** **** **** 0 **** **** **** +824 DM_TOOL_05 **** **** **** **** 0 **** **** **** +825 DM_TOOL_06 **** **** **** **** 0 **** **** **** +826 DM_TOOL_07 **** **** **** **** 0 **** **** **** +827 DM_TOOL_08 **** **** **** **** 0 **** **** **** +828 DM_TOOL_09 **** **** **** **** 0 **** **** **** +829 DM_TOOL_10 **** **** **** **** 0 **** **** **** +830 PLAYER_TOOL_01 **** **** **** **** 0 **** **** **** +831 PLAYER_TOOL_02 **** **** **** **** 0 **** **** **** +832 PLAYER_TOOL_03 **** **** **** **** 0 **** **** **** +833 PLAYER_TOOL_04 **** **** **** **** 0 **** **** **** +834 PLAYER_TOOL_05 **** **** **** **** 0 **** **** **** +835 PLAYER_TOOL_06 **** **** **** **** 0 **** **** **** +836 PLAYER_TOOL_07 **** **** **** **** 0 **** **** **** +837 PLAYER_TOOL_08 **** **** **** **** 0 **** **** **** +838 PLAYER_TOOL_09 **** **** **** **** 0 **** **** **** +839 PLAYER_TOOL_10 **** **** **** **** 0 **** **** **** +840 **** **** **** **** **** **** **** **** **** +841 **** **** **** **** **** **** **** **** **** +842 **** **** **** **** **** **** **** **** **** +843 **** **** **** **** **** **** **** **** **** +844 **** **** **** **** **** **** **** **** **** +845 **** **** **** **** **** **** **** **** **** +846 **** **** **** **** **** **** **** **** **** +847 **** **** **** **** **** **** **** **** **** +848 **** **** **** **** **** **** **** **** **** +849 **** **** **** **** **** **** **** **** **** +850 **** **** **** **** **** **** **** **** **** +851 **** **** **** **** **** **** **** **** **** +852 **** **** **** **** **** **** **** **** **** +853 **** **** **** **** **** **** **** **** **** +854 **** **** **** **** **** **** **** **** **** +855 **** **** **** **** **** **** **** **** **** +856 **** **** **** **** **** **** **** **** **** +857 **** **** **** **** **** **** **** **** **** +858 **** **** **** **** **** **** **** **** **** +859 **** **** **** **** **** **** **** **** **** +860 **** **** **** **** **** **** **** **** **** +861 **** **** **** **** **** **** **** **** **** +862 **** **** **** **** **** **** **** **** **** +863 **** **** **** **** **** **** **** **** **** +864 **** **** **** **** **** **** **** **** **** +865 **** **** **** **** **** **** **** **** **** +866 **** **** **** **** **** **** **** **** **** +867 **** **** **** **** **** **** **** **** **** +868 **** **** **** **** **** **** **** **** **** +869 **** **** **** **** **** **** **** **** **** +870 **** **** **** **** **** **** **** **** **** +871 **** **** **** **** **** **** **** **** **** +872 **** **** **** **** **** **** **** **** **** +873 **** **** **** **** **** **** **** **** **** +874 **** **** **** **** **** **** **** **** **** +875 **** **** **** **** **** **** **** **** **** +876 **** **** **** **** **** **** **** **** **** +877 **** **** **** **** **** **** **** **** **** +878 **** **** **** **** **** **** **** **** **** +879 **** **** **** **** **** **** **** **** **** +880 **** **** **** **** **** **** **** **** **** +881 **** **** **** **** **** **** **** **** **** +882 **** **** **** **** **** **** **** **** **** +883 **** **** **** **** **** **** **** **** **** +884 **** **** **** **** **** **** **** **** **** +885 **** **** **** **** **** **** **** **** **** +886 **** **** **** **** **** **** **** **** **** +887 **** **** **** **** **** **** **** **** **** +888 **** **** **** **** **** **** **** **** **** +889 **** **** **** **** **** **** **** **** **** +890 **** **** **** **** **** **** **** **** **** +891 **** **** **** **** **** **** **** **** **** +892 **** **** **** **** **** **** **** **** **** +893 **** **** **** **** **** **** **** **** **** +894 **** **** **** **** **** **** **** **** **** +895 **** **** **** **** **** **** **** **** **** +896 **** **** **** **** **** **** **** **** **** +897 **** **** **** **** **** **** **** **** **** +898 **** **** **** **** **** **** **** **** **** +899 **** **** **** **** **** **** **** **** **** +900 **** **** **** **** **** **** **** **** **** +901 **** **** **** **** **** **** **** **** **** +902 **** **** **** **** **** **** **** **** **** +903 **** **** **** **** **** **** **** **** **** +904 **** **** **** **** **** **** **** **** **** +905 **** **** **** **** **** **** **** **** **** +906 **** **** **** **** **** **** **** **** **** +907 **** **** **** **** **** **** **** **** **** +908 **** **** **** **** **** **** **** **** **** +909 **** **** **** **** **** **** **** **** **** +910 **** **** **** **** **** **** **** **** **** +911 **** **** **** **** **** **** **** **** **** +912 **** **** **** **** **** **** **** **** **** +913 **** **** **** **** **** **** **** **** **** +914 **** **** **** **** **** **** **** **** **** +915 **** **** **** **** **** **** **** **** **** +916 **** **** **** **** **** **** **** **** **** +917 **** **** **** **** **** **** **** **** **** +918 **** **** **** **** **** **** **** **** **** +919 **** **** **** **** **** **** **** **** **** +920 **** **** **** **** **** **** **** **** **** +921 **** **** **** **** **** **** **** **** **** +922 **** **** **** **** **** **** **** **** **** +923 **** **** **** **** **** **** **** **** **** +924 **** **** **** **** **** **** **** **** **** +925 **** **** **** **** **** **** **** **** **** +926 **** **** **** **** **** **** **** **** **** +927 **** **** **** **** **** **** **** **** **** +928 **** **** **** **** **** **** **** **** **** +929 **** **** **** **** **** **** **** **** **** +930 **** **** **** **** **** **** **** **** **** +931 **** **** **** **** **** **** **** **** **** +932 **** **** **** **** **** **** **** **** **** +933 **** **** **** **** **** **** **** **** **** +934 **** **** **** **** **** **** **** **** **** +935 **** **** **** **** **** **** **** **** **** +936 **** **** **** **** **** **** **** **** **** +937 **** **** **** **** **** **** **** **** **** +938 **** **** **** **** **** **** **** **** **** +939 **** **** **** **** **** **** **** **** **** +940 **** **** **** **** **** **** **** **** **** +941 **** **** **** **** **** **** **** **** **** +942 **** **** **** **** **** **** **** **** **** +943 **** **** **** **** **** **** **** **** **** +944 **** **** **** **** **** **** **** **** **** +945 **** **** **** **** **** **** **** **** **** +946 **** **** **** **** **** **** **** **** **** +947 **** **** **** **** **** **** **** **** **** +948 **** **** **** **** **** **** **** **** **** +949 **** **** **** **** **** **** **** **** **** +950 **** **** **** **** **** **** **** **** **** +951 **** **** **** **** **** **** **** **** **** +952 **** **** **** **** **** **** **** **** **** +953 **** **** **** **** **** **** **** **** **** +954 **** **** **** **** **** **** **** **** **** +955 **** **** **** **** **** **** **** **** **** +956 **** **** **** **** **** **** **** **** **** +957 **** **** **** **** **** **** **** **** **** +958 **** **** **** **** **** **** **** **** **** +959 **** **** **** **** **** **** **** **** **** +960 **** **** **** **** **** **** **** **** **** +961 **** **** **** **** **** **** **** **** **** +962 **** **** **** **** **** **** **** **** **** +963 **** **** **** **** **** **** **** **** **** +964 **** **** **** **** **** **** **** **** **** +965 **** **** **** **** **** **** **** **** **** +966 **** **** **** **** **** **** **** **** **** +967 **** **** **** **** **** **** **** **** **** +968 **** **** **** **** **** **** **** **** **** +969 **** **** **** **** **** **** **** **** **** +970 **** **** **** **** **** **** **** **** **** +971 **** **** **** **** **** **** **** **** **** +972 **** **** **** **** **** **** **** **** **** +973 **** **** **** **** **** **** **** **** **** +974 **** **** **** **** **** **** **** **** **** +975 **** **** **** **** **** **** **** **** **** +976 **** **** **** **** **** **** **** **** **** +977 **** **** **** **** **** **** **** **** **** +978 **** **** **** **** **** **** **** **** **** +979 **** **** **** **** **** **** **** **** **** +980 **** **** **** **** **** **** **** **** **** +981 **** **** **** **** **** **** **** **** **** +982 **** **** **** **** **** **** **** **** **** +983 **** **** **** **** **** **** **** **** **** +984 **** **** **** **** **** **** **** **** **** +985 **** **** **** **** **** **** **** **** **** +986 **** **** **** **** **** **** **** **** **** +987 **** **** **** **** **** **** **** **** **** +988 **** **** **** **** **** **** **** **** **** +989 **** **** **** **** **** **** **** **** **** +990 **** **** **** **** **** **** **** **** **** +991 **** **** **** **** **** **** **** **** **** +992 **** **** **** **** **** **** **** **** **** +993 **** **** **** **** **** **** **** **** **** +994 **** **** **** **** **** **** **** **** **** +995 **** **** **** **** **** **** **** **** **** +996 **** **** **** **** **** **** **** **** **** +997 **** **** **** **** **** **** **** **** **** +998 **** **** **** **** **** **** **** **** **** +999 **** **** **** **** **** **** **** **** **** +1000 **** **** **** **** **** **** **** **** **** +1001 **** **** **** **** **** **** **** **** **** +1002 **** **** **** **** **** **** **** **** **** +1003 **** **** **** **** **** **** **** **** **** +1004 **** **** **** **** **** **** **** **** **** +1005 **** **** **** **** **** **** **** **** **** +1006 **** **** **** **** **** **** **** **** **** +1007 **** **** **** **** **** **** **** **** **** +1008 **** **** **** **** **** **** **** **** **** +1009 **** **** **** **** **** **** **** **** **** +1010 **** **** **** **** **** **** **** **** **** +1011 **** **** **** **** **** **** **** **** **** +1012 **** **** **** **** **** **** **** **** **** +1013 **** **** **** **** **** **** **** **** **** +1014 **** **** **** **** **** **** **** **** **** +1015 **** **** **** **** **** **** **** **** **** +1016 **** **** **** **** **** **** **** **** **** +1017 **** **** **** **** **** **** **** **** **** +1018 **** **** **** **** **** **** **** **** **** +1019 **** **** **** **** **** **** **** **** **** +1020 **** **** **** **** **** **** **** **** **** +1021 **** **** **** **** **** **** **** **** **** +1022 **** **** **** **** **** **** **** **** **** +1023 **** **** **** **** **** **** **** **** **** +1024 **** **** **** **** **** **** **** **** **** +1025 **** **** **** **** **** **** **** **** **** +1026 **** **** **** **** **** **** **** **** **** +1027 **** **** **** **** **** **** **** **** **** +1028 **** **** **** **** **** **** **** **** **** +1029 **** **** **** **** **** **** **** **** **** +1030 **** **** **** **** **** **** **** **** **** +1031 **** **** **** **** **** **** **** **** **** +1032 **** **** **** **** **** **** **** **** **** +1033 **** **** **** **** **** **** **** **** **** +1034 **** **** **** **** **** **** **** **** **** +1035 **** **** **** **** **** **** **** **** **** +1036 **** **** **** **** **** **** **** **** **** +1037 **** **** **** **** **** **** **** **** **** +1038 **** **** **** **** **** **** **** **** **** +1039 **** **** **** **** **** **** **** **** **** +1040 **** **** **** **** **** **** **** **** **** +1041 **** **** **** **** **** **** **** **** **** +1042 **** **** **** **** **** **** **** **** **** +1043 **** **** **** **** **** **** **** **** **** +1044 **** **** **** **** **** **** **** **** **** +1045 **** **** **** **** **** **** **** **** **** +1046 **** **** **** **** **** **** **** **** **** +1047 **** **** **** **** **** **** **** **** **** +1048 **** **** **** **** **** **** **** **** **** +1049 **** **** **** **** **** **** **** **** **** +1050 **** **** **** **** **** **** **** **** **** +1051 **** **** **** **** **** **** **** **** **** +1052 **** **** **** **** **** **** **** **** **** +1053 **** **** **** **** **** **** **** **** **** +1054 **** **** **** **** **** **** **** **** **** +1055 **** **** **** **** **** **** **** **** **** +1056 **** **** **** **** **** **** **** **** **** +1057 **** **** **** **** **** **** **** **** **** +1058 **** **** **** **** **** **** **** **** **** +1059 **** **** **** **** **** **** **** **** **** +1060 **** **** **** **** **** **** **** **** **** +1061 **** **** **** **** **** **** **** **** **** +1062 **** **** **** **** **** **** **** **** **** +1063 **** **** **** **** **** **** **** **** **** +1064 **** **** **** **** **** **** **** **** **** +1065 **** **** **** **** **** **** **** **** **** +1066 **** **** **** **** **** **** **** **** **** +1067 **** **** **** **** **** **** **** **** **** +1068 **** **** **** **** **** **** **** **** **** +1069 **** **** **** **** **** **** **** **** **** +1070 **** **** **** **** **** **** **** **** **** +1071 **** **** **** **** **** **** **** **** **** +1072 **** **** **** **** **** **** **** **** **** +1073 **** **** **** **** **** **** **** **** **** +1074 **** **** **** **** **** **** **** **** **** +1075 **** **** **** **** **** **** **** **** **** +1076 **** **** **** **** **** **** **** **** **** +1077 **** **** **** **** **** **** **** **** **** +1078 **** **** **** **** **** **** **** **** **** +1079 **** **** **** **** **** **** **** **** **** +1080 **** **** **** **** **** **** **** **** **** +1081 **** **** **** **** **** **** **** **** **** +1082 **** **** **** **** **** **** **** **** **** +1083 **** **** **** **** **** **** **** **** **** +1084 **** **** **** **** **** **** **** **** **** +1085 **** **** **** **** **** **** **** **** **** +1086 **** **** **** **** **** **** **** **** **** +1087 **** **** **** **** **** **** **** **** **** +1088 **** **** **** **** **** **** **** **** **** +1089 **** **** **** **** **** **** **** **** **** +1090 **** **** **** **** **** **** **** **** **** +1091 **** **** **** **** **** **** **** **** **** +1092 **** **** **** **** **** **** **** **** **** +1093 **** **** **** **** **** **** **** **** **** +1094 **** **** **** **** **** **** **** **** **** +1095 **** **** **** **** **** **** **** **** **** +1096 **** **** **** **** **** **** **** **** **** +1097 **** **** **** **** **** **** **** **** **** +1098 **** **** **** **** **** **** **** **** **** +1099 **** **** **** **** **** **** **** **** **** +1100 **** **** **** **** **** **** **** **** **** +1101 **** **** **** **** **** **** **** **** **** +1102 **** **** **** **** **** **** **** **** **** +1103 **** **** **** **** **** **** **** **** **** +1104 **** **** **** **** **** **** **** **** **** +1105 **** **** **** **** **** **** **** **** **** +1106 **** **** **** **** **** **** **** **** **** +1107 **** **** **** **** **** **** **** **** **** +1108 **** **** **** **** **** **** **** **** **** +1109 **** **** **** **** **** **** **** **** **** +1110 **** **** **** **** **** **** **** **** **** +1111 **** **** **** **** **** **** **** **** **** +1112 **** **** **** **** **** **** **** **** **** +1113 **** **** **** **** **** **** **** **** **** +1114 **** **** **** **** **** **** **** **** **** +1115 **** **** **** **** **** **** **** **** **** +1116 **** **** **** **** **** **** **** **** **** +1117 **** **** **** **** **** **** **** **** **** +1118 **** **** **** **** **** **** **** **** **** +1119 **** **** **** **** **** **** **** **** **** +1120 **** **** **** **** **** **** **** **** **** +1121 **** **** **** **** **** **** **** **** **** +1122 **** **** **** **** **** **** **** **** **** +1123 **** **** **** **** **** **** **** **** **** +1124 **** **** **** **** **** **** **** **** **** +1125 **** **** **** **** **** **** **** **** **** +1126 **** **** **** **** **** **** **** **** **** +1127 **** **** **** **** **** **** **** **** **** +1128 **** **** **** **** **** **** **** **** **** +1129 **** **** **** **** **** **** **** **** **** +1130 **** **** **** **** **** **** **** **** **** +1131 **** **** **** **** **** **** **** **** **** +1132 **** **** **** **** **** **** **** **** **** +1133 **** **** **** **** **** **** **** **** **** +1134 **** **** **** **** **** **** **** **** **** +1135 **** **** **** **** **** **** **** **** **** +1136 **** **** **** **** **** **** **** **** **** +1137 **** **** **** **** **** **** **** **** **** +1138 **** **** **** **** **** **** **** **** **** +1139 **** **** **** **** **** **** **** **** **** +1140 **** **** **** **** **** **** **** **** **** +1141 **** **** **** **** **** **** **** **** **** +1142 **** **** **** **** **** **** **** **** **** +1143 **** **** **** **** **** **** **** **** **** +1144 **** **** **** **** **** **** **** **** **** +1145 **** **** **** **** **** **** **** **** **** +1146 **** **** **** **** **** **** **** **** **** +1147 **** **** **** **** **** **** **** **** **** +1148 **** **** **** **** **** **** **** **** **** +1149 **** **** **** **** **** **** **** **** **** +1150 **** **** **** **** **** **** **** **** **** +1151 **** **** **** **** **** **** **** **** **** +1152 **** **** **** **** **** **** **** **** **** +1153 **** **** **** **** **** **** **** **** **** +1154 **** **** **** **** **** **** **** **** **** +1155 **** **** **** **** **** **** **** **** **** +1156 **** **** **** **** **** **** **** **** **** +1157 **** **** **** **** **** **** **** **** **** +1158 **** **** **** **** **** **** **** **** **** +1159 **** **** **** **** **** **** **** **** **** +1160 **** **** **** **** **** **** **** **** **** +1161 **** **** **** **** **** **** **** **** **** +1162 **** **** **** **** **** **** **** **** **** +1163 **** **** **** **** **** **** **** **** **** +1164 **** **** **** **** **** **** **** **** **** +1165 **** **** **** **** **** **** **** **** **** +1166 **** **** **** **** **** **** **** **** **** +1167 **** **** **** **** **** **** **** **** **** +1168 **** **** **** **** **** **** **** **** **** +1169 **** **** **** **** **** **** **** **** **** +1170 **** **** **** **** **** **** **** **** **** +1171 **** **** **** **** **** **** **** **** **** +1172 **** **** **** **** **** **** **** **** **** +1173 **** **** **** **** **** **** **** **** **** +1174 **** **** **** **** **** **** **** **** **** +1175 **** **** **** **** **** **** **** **** **** +1176 **** **** **** **** **** **** **** **** **** +1177 **** **** **** **** **** **** **** **** **** +1178 **** **** **** **** **** **** **** **** **** +1179 **** **** **** **** **** **** **** **** **** +1180 **** **** **** **** **** **** **** **** **** +1181 **** **** **** **** **** **** **** **** **** +1182 **** **** **** **** **** **** **** **** **** +1183 **** **** **** **** **** **** **** **** **** +1184 **** **** **** **** **** **** **** **** **** +1185 **** **** **** **** **** **** **** **** **** +1186 **** **** **** **** **** **** **** **** **** +1187 **** **** **** **** **** **** **** **** **** +1188 **** **** **** **** **** **** **** **** **** +1189 **** **** **** **** **** **** **** **** **** +1190 **** **** **** **** **** **** **** **** **** +1191 **** **** **** **** **** **** **** **** **** +1192 **** **** **** **** **** **** **** **** **** +1193 **** **** **** **** **** **** **** **** **** +1194 **** **** **** **** **** **** **** **** **** +1195 **** **** **** **** **** **** **** **** **** +1196 **** **** **** **** **** **** **** **** **** +1197 **** **** **** **** **** **** **** **** **** +1198 **** **** **** **** **** **** **** **** **** +1199 **** **** **** **** **** **** **** **** **** +1200 **** **** **** **** **** **** **** **** **** +1201 **** **** **** **** **** **** **** **** **** +1202 **** **** **** **** **** **** **** **** **** +1203 **** **** **** **** **** **** **** **** **** +1204 **** **** **** **** **** **** **** **** **** +1205 **** **** **** **** **** **** **** **** **** +1206 **** **** **** **** **** **** **** **** **** +1207 **** **** **** **** **** **** **** **** **** +1208 **** **** **** **** **** **** **** **** **** +1209 **** **** **** **** **** **** **** **** **** +1210 **** **** **** **** **** **** **** **** **** +1211 **** **** **** **** **** **** **** **** **** +1212 **** **** **** **** **** **** **** **** **** +1213 **** **** **** **** **** **** **** **** **** +1214 **** **** **** **** **** **** **** **** **** +1215 **** **** **** **** **** **** **** **** **** +1216 **** **** **** **** **** **** **** **** **** +1217 **** **** **** **** **** **** **** **** **** +1218 **** **** **** **** **** **** **** **** **** +1219 **** **** **** **** **** **** **** **** **** +1220 **** **** **** **** **** **** **** **** **** +1221 **** **** **** **** **** **** **** **** **** +1222 **** **** **** **** **** **** **** **** **** +1223 **** **** **** **** **** **** **** **** **** +1224 **** **** **** **** **** **** **** **** **** +1225 **** **** **** **** **** **** **** **** **** +1226 **** **** **** **** **** **** **** **** **** +1227 **** **** **** **** **** **** **** **** **** +1228 **** **** **** **** **** **** **** **** **** +1229 **** **** **** **** **** **** **** **** **** +1230 **** **** **** **** **** **** **** **** **** +1231 **** **** **** **** **** **** **** **** **** +1232 **** **** **** **** **** **** **** **** **** +1233 **** **** **** **** **** **** **** **** **** +1234 **** **** **** **** **** **** **** **** **** +1235 **** **** **** **** **** **** **** **** **** +1236 **** **** **** **** **** **** **** **** **** +1237 **** **** **** **** **** **** **** **** **** +1238 **** **** **** **** **** **** **** **** **** +1239 **** **** **** **** **** **** **** **** **** +1240 **** **** **** **** **** **** **** **** **** +1241 **** **** **** **** **** **** **** **** **** +1242 **** **** **** **** **** **** **** **** **** +1243 **** **** **** **** **** **** **** **** **** +1244 **** **** **** **** **** **** **** **** **** +1245 **** **** **** **** **** **** **** **** **** +1246 **** **** **** **** **** **** **** **** **** +1247 **** **** **** **** **** **** **** **** **** +1248 **** **** **** **** **** **** **** **** **** +1249 **** **** **** **** **** **** **** **** **** +1250 **** **** **** **** **** **** **** **** **** +1251 **** **** **** **** **** **** **** **** **** +1252 **** **** **** **** **** **** **** **** **** +1253 **** **** **** **** **** **** **** **** **** +1254 **** **** **** **** **** **** **** **** **** +1255 **** **** **** **** **** **** **** **** **** +1256 **** **** **** **** **** **** **** **** **** +1257 **** **** **** **** **** **** **** **** **** +1258 **** **** **** **** **** **** **** **** **** +1259 **** **** **** **** **** **** **** **** **** +1260 **** **** **** **** **** **** **** **** **** +1261 **** **** **** **** **** **** **** **** **** +1262 **** **** **** **** **** **** **** **** **** +1263 **** **** **** **** **** **** **** **** **** +1264 **** **** **** **** **** **** **** **** **** +1265 **** **** **** **** **** **** **** **** **** +1266 **** **** **** **** **** **** **** **** **** +1267 **** **** **** **** **** **** **** **** **** +1268 **** **** **** **** **** **** **** **** **** +1269 **** **** **** **** **** **** **** **** **** +1270 **** **** **** **** **** **** **** **** **** +1271 **** **** **** **** **** **** **** **** **** +1272 **** **** **** **** **** **** **** **** **** +1273 **** **** **** **** **** **** **** **** **** +1274 **** **** **** **** **** **** **** **** **** +1275 **** **** **** **** **** **** **** **** **** +1276 **** **** **** **** **** **** **** **** **** +1277 **** **** **** **** **** **** **** **** **** +1278 **** **** **** **** **** **** **** **** **** +1279 **** **** **** **** **** **** **** **** **** +1280 **** **** **** **** **** **** **** **** **** +1281 **** **** **** **** **** **** **** **** **** +1282 **** **** **** **** **** **** **** **** **** +1283 **** **** **** **** **** **** **** **** **** +1284 **** **** **** **** **** **** **** **** **** +1285 **** **** **** **** **** **** **** **** **** +1286 **** **** **** **** **** **** **** **** **** +1287 **** **** **** **** **** **** **** **** **** +1288 **** **** **** **** **** **** **** **** **** +1289 **** **** **** **** **** **** **** **** **** +1290 **** **** **** **** **** **** **** **** **** +1291 **** **** **** **** **** **** **** **** **** +1292 **** **** **** **** **** **** **** **** **** +1293 **** **** **** **** **** **** **** **** **** +1294 **** **** **** **** **** **** **** **** **** +1295 **** **** **** **** **** **** **** **** **** +1296 **** **** **** **** **** **** **** **** **** +1297 **** **** **** **** **** **** **** **** **** +1298 **** **** **** **** **** **** **** **** **** +1299 **** **** **** **** **** **** **** **** **** +1300 **** **** **** **** **** **** **** **** **** +1301 **** **** **** **** **** **** **** **** **** +1302 **** **** **** **** **** **** **** **** **** +1303 **** **** **** **** **** **** **** **** **** +1304 **** **** **** **** **** **** **** **** **** +1305 **** **** **** **** **** **** **** **** **** +1306 **** **** **** **** **** **** **** **** **** +1307 **** **** **** **** **** **** **** **** **** +1308 **** **** **** **** **** **** **** **** **** +1309 **** **** **** **** **** **** **** **** **** +1310 **** **** **** **** **** **** **** **** **** +1311 **** **** **** **** **** **** **** **** **** +1312 **** **** **** **** **** **** **** **** **** +1313 **** **** **** **** **** **** **** **** **** +1314 **** **** **** **** **** **** **** **** **** +1315 **** **** **** **** **** **** **** **** **** +1316 **** **** **** **** **** **** **** **** **** +1317 **** **** **** **** **** **** **** **** **** +1318 **** **** **** **** **** **** **** **** **** +1319 **** **** **** **** **** **** **** **** **** +1320 **** **** **** **** **** **** **** **** **** +1321 **** **** **** **** **** **** **** **** **** +1322 **** **** **** **** **** **** **** **** **** +1323 **** **** **** **** **** **** **** **** **** +1324 **** **** **** **** **** **** **** **** **** +1325 **** **** **** **** **** **** **** **** **** +1326 **** **** **** **** **** **** **** **** **** +1327 **** **** **** **** **** **** **** **** **** +1328 **** **** **** **** **** **** **** **** **** +1329 **** **** **** **** **** **** **** **** **** +1330 **** **** **** **** **** **** **** **** **** +1331 **** **** **** **** **** **** **** **** **** +1332 **** **** **** **** **** **** **** **** **** +1333 **** **** **** **** **** **** **** **** **** +1334 **** **** **** **** **** **** **** **** **** +1335 **** **** **** **** **** **** **** **** **** +1336 **** **** **** **** **** **** **** **** **** +1337 **** **** **** **** **** **** **** **** **** +1338 **** **** **** **** **** **** **** **** **** +1339 **** **** **** **** **** **** **** **** **** +1340 **** **** **** **** **** **** **** **** **** +1341 **** **** **** **** **** **** **** **** **** +1342 **** **** **** **** **** **** **** **** **** +1343 **** **** **** **** **** **** **** **** **** +1344 **** **** **** **** **** **** **** **** **** +1345 **** **** **** **** **** **** **** **** **** +1346 **** **** **** **** **** **** **** **** **** +1347 **** **** **** **** **** **** **** **** **** +1348 **** **** **** **** **** **** **** **** **** +1349 **** **** **** **** **** **** **** **** **** +1350 **** **** **** **** **** **** **** **** **** +1351 **** **** **** **** **** **** **** **** **** +1352 **** **** **** **** **** **** **** **** **** +1353 **** **** **** **** **** **** **** **** **** +1354 **** **** **** **** **** **** **** **** **** +1355 **** **** **** **** **** **** **** **** **** +1356 **** **** **** **** **** **** **** **** **** +1357 **** **** **** **** **** **** **** **** **** +1358 **** **** **** **** **** **** **** **** **** +1359 **** **** **** **** **** **** **** **** **** +1360 **** **** **** **** **** **** **** **** **** +1361 **** **** **** **** **** **** **** **** **** +1362 **** **** **** **** **** **** **** **** **** +1363 **** **** **** **** **** **** **** **** **** +1364 **** **** **** **** **** **** **** **** **** +1365 **** **** **** **** **** **** **** **** **** +1366 **** **** **** **** **** **** **** **** **** +1367 **** **** **** **** **** **** **** **** **** +1368 **** **** **** **** **** **** **** **** **** +1369 **** **** **** **** **** **** **** **** **** +1370 **** **** **** **** **** **** **** **** **** +1371 **** **** **** **** **** **** **** **** **** +1372 **** **** **** **** **** **** **** **** **** +1373 **** **** **** **** **** **** **** **** **** +1374 **** **** **** **** **** **** **** **** **** +1375 **** **** **** **** **** **** **** **** **** +1376 **** **** **** **** **** **** **** **** **** +1377 **** **** **** **** **** **** **** **** **** +1378 **** **** **** **** **** **** **** **** **** +1379 **** **** **** **** **** **** **** **** **** +1380 **** **** **** **** **** **** **** **** **** +1381 **** **** **** **** **** **** **** **** **** +1382 **** **** **** **** **** **** **** **** **** +1383 **** **** **** **** **** **** **** **** **** +1384 **** **** **** **** **** **** **** **** **** +1385 **** **** **** **** **** **** **** **** **** +1386 **** **** **** **** **** **** **** **** **** +1387 **** **** **** **** **** **** **** **** **** +1388 **** **** **** **** **** **** **** **** **** +1389 **** **** **** **** **** **** **** **** **** +1390 **** **** **** **** **** **** **** **** **** +1391 **** **** **** **** **** **** **** **** **** +1392 **** **** **** **** **** **** **** **** **** +1393 **** **** **** **** **** **** **** **** **** +1394 **** **** **** **** **** **** **** **** **** +1395 **** **** **** **** **** **** **** **** **** +1396 **** **** **** **** **** **** **** **** **** +1397 **** **** **** **** **** **** **** **** **** +1398 **** **** **** **** **** **** **** **** **** +1399 **** **** **** **** **** **** **** **** **** +1400 **** **** **** **** **** **** **** **** **** +1401 **** **** **** **** **** **** **** **** **** +1402 **** **** **** **** **** **** **** **** **** +1403 **** **** **** **** **** **** **** **** **** +1404 **** **** **** **** **** **** **** **** **** +1405 **** **** **** **** **** **** **** **** **** +1406 **** **** **** **** **** **** **** **** **** +1407 **** **** **** **** **** **** **** **** **** +1408 **** **** **** **** **** **** **** **** **** +1409 **** **** **** **** **** **** **** **** **** +1410 **** **** **** **** **** **** **** **** **** +1411 **** **** **** **** **** **** **** **** **** +1412 **** **** **** **** **** **** **** **** **** +1413 **** **** **** **** **** **** **** **** **** +1414 **** **** **** **** **** **** **** **** **** +1415 **** **** **** **** **** **** **** **** **** +1416 **** **** **** **** **** **** **** **** **** +1417 **** **** **** **** **** **** **** **** **** +1418 **** **** **** **** **** **** **** **** **** +1419 **** **** **** **** **** **** **** **** **** +1420 **** **** **** **** **** **** **** **** **** +1421 **** **** **** **** **** **** **** **** **** +1422 **** **** **** **** **** **** **** **** **** +1423 **** **** **** **** **** **** **** **** **** +1424 **** **** **** **** **** **** **** **** **** +1425 **** **** **** **** **** **** **** **** **** +1426 **** **** **** **** **** **** **** **** **** +1427 **** **** **** **** **** **** **** **** **** +1428 **** **** **** **** **** **** **** **** **** +1429 **** **** **** **** **** **** **** **** **** +1430 **** **** **** **** **** **** **** **** **** +1431 **** **** **** **** **** **** **** **** **** +1432 **** **** **** **** **** **** **** **** **** +1433 **** **** **** **** **** **** **** **** **** +1434 **** **** **** **** **** **** **** **** **** +1435 **** **** **** **** **** **** **** **** **** +1436 **** **** **** **** **** **** **** **** **** +1437 **** **** **** **** **** **** **** **** **** +1438 **** **** **** **** **** **** **** **** **** +1439 **** **** **** **** **** **** **** **** **** +1440 **** **** **** **** **** **** **** **** **** +1441 **** **** **** **** **** **** **** **** **** +1442 **** **** **** **** **** **** **** **** **** +1443 **** **** **** **** **** **** **** **** **** +1444 **** **** **** **** **** **** **** **** **** +1445 **** **** **** **** **** **** **** **** **** +1446 **** **** **** **** **** **** **** **** **** +1447 **** **** **** **** **** **** **** **** **** +1448 **** **** **** **** **** **** **** **** **** +1449 **** **** **** **** **** **** **** **** **** +1450 **** **** **** **** **** **** **** **** **** +1451 **** **** **** **** **** **** **** **** **** +1452 **** **** **** **** **** **** **** **** **** +1453 **** **** **** **** **** **** **** **** **** +1454 **** **** **** **** **** **** **** **** **** +1455 **** **** **** **** **** **** **** **** **** +1456 **** **** **** **** **** **** **** **** **** +1457 **** **** **** **** **** **** **** **** **** +1458 **** **** **** **** **** **** **** **** **** +1459 **** **** **** **** **** **** **** **** **** +1460 **** **** **** **** **** **** **** **** **** +1461 **** **** **** **** **** **** **** **** **** +1462 **** **** **** **** **** **** **** **** **** +1463 **** **** **** **** **** **** **** **** **** +1464 **** **** **** **** **** **** **** **** **** +1465 **** **** **** **** **** **** **** **** **** +1466 **** **** **** **** **** **** **** **** **** +1467 **** **** **** **** **** **** **** **** **** +1468 **** **** **** **** **** **** **** **** **** +1469 **** **** **** **** **** **** **** **** **** +1470 **** **** **** **** **** **** **** **** **** +1471 **** **** **** **** **** **** **** **** **** +1472 **** **** **** **** **** **** **** **** **** +1473 **** **** **** **** **** **** **** **** **** +1474 **** **** **** **** **** **** **** **** **** +1475 **** **** **** **** **** **** **** **** **** +1476 **** **** **** **** **** **** **** **** **** +1477 **** **** **** **** **** **** **** **** **** +1478 **** **** **** **** **** **** **** **** **** +1479 **** **** **** **** **** **** **** **** **** +1480 **** **** **** **** **** **** **** **** **** +1481 **** **** **** **** **** **** **** **** **** +1482 **** **** **** **** **** **** **** **** **** +1483 **** **** **** **** **** **** **** **** **** +1484 **** **** **** **** **** **** **** **** **** +1485 Warsoul_CultPower **** **** **** **** **** **** **** **** +1486 Warsoul_SoulTyrant **** **** **** **** **** **** **** **** +1487 SPIRETOP_FOG_CLOUD_BREATH **** **** **** **** **** **** **** **** +1488 MEPHLING_BREATH_WEAPON **** **** **** **** **** **** **** **** +1489 ARANEA_ALTFORM_RADIAL **** **** **** **** **** **** **** **** +1490 ARANEA_ALT_HUMANOID **** **** **** **** **** **** **** **** +1491 ARANEA_ALT_HYBRID **** **** **** **** **** **** **** **** +1492 ARANEA_ALT_SPIDER **** **** **** **** **** **** **** **** +1493 ARANEA_WEB **** **** **** **** **** **** **** **** +1494 MUCKDWELLER_SQUIRT **** **** **** **** **** **** **** **** +1495 TN_DES_20 **** **** **** **** **** **** **** **** +1496 TN_DES_100 **** **** **** **** **** **** **** **** +1497 TN_Unsummon **** **** **** **** **** **** **** **** +1498 VAMPIRIC_DRAIN **** **** **** **** **** **** **** **** +1499 Dancing_Lights **** **** **** **** **** **** **** **** +1500 Read_Magic **** **** **** **** **** **** **** **** +1501 Sobriety **** **** **** **** **** **** **** **** +1502 Crafters_Blessing **** **** **** **** **** **** **** **** +1503 Crafters_Curse **** **** **** **** **** **** **** **** +1504 Lesser_Planar_Ally **** **** **** S 0 3 0 -2 +1505 Greater_Planar_Ally **** **** **** S 0 3 0 -2 +1506 Eternal_Charm_Monster **** **** **** **** **** **** **** **** +1507 Eternal_Charm_Person **** **** **** **** **** **** **** **** +1508 Weapon_of_Impact **** **** **** E 0 3 15 **** +1509 Shillelagh **** **** **** E 0 2 15 -14 +1510 Daze_Monster Dazed Will 1 R 1 **** **** **** +1511 Curse_Water **** **** **** **** **** **** **** **** +1512 Mislead **** **** **** P 0 2 0 **** +1513 Power_Word_Blind **** **** 1 R 1 **** **** **** +1514 BFZ_FatefulStride **** **** **** **** **** **** **** **** +1515 PA_FLETCH_1 **** **** **** **** **** **** **** **** +1516 PA_FLETCH_2 **** **** **** **** **** **** **** **** +1517 PA_FLETCH_3 **** **** **** **** **** **** **** **** +1518 PA_FLETCH_4 **** **** **** **** **** **** **** **** +1519 PA_FLETCH_5 **** **** **** **** **** **** **** **** +1520 PA_POWERSHOT **** **** **** **** **** **** **** **** +1521 PA_IMP_POWERSHOT **** **** **** **** **** **** **** **** +1522 PA_SUP_POWERSHOT **** **** **** **** **** **** **** **** +1523 Hext_StrBoost **** **** **** **** **** **** **** **** +1524 AT_RL_LOCK **** **** **** **** **** **** **** **** +1525 AT_RL_TRAP **** **** **** **** **** **** **** **** +1526 AT_ISA **** **** **** **** **** **** **** **** +1527 TN_CGUNDEAD **** **** **** **** **** **** **** **** +1528 Thousand_Faces_MEDIUM **** **** **** **** **** **** **** **** +1529 Thousand_Faces_SMALL **** **** **** **** **** **** **** **** +1530 Thousand_Faces_DWARF **** **** **** **** **** **** **** **** +1531 Thousand_Faces_ELF **** **** **** **** **** **** **** **** +1532 Thousand_Faces_HALF_ELF **** **** **** **** **** **** **** **** +1533 Thousand_Faces_HALF_ORC **** **** **** **** **** **** **** **** +1534 Thousand_Faces_HUMAN **** **** **** **** **** **** **** **** +1535 Thousand_Faces_GNOME **** **** **** **** **** **** **** **** +1536 Thousand_Faces_HALFLING **** **** **** **** **** **** **** **** +1537 Thousand_Face_OFF **** **** **** **** **** **** **** **** +1538 OcRay_ChPer **** **** **** **** **** **** **** **** +1539 OcRay_Sleep **** **** **** **** **** **** **** **** +1540 OcRay_InfW **** **** **** **** **** **** **** **** +1541 OcRay_Slow **** **** **** **** **** **** **** **** +1542 OcRay_Fear **** **** **** **** **** **** **** **** +1543 OcRay_ChMon **** **** **** **** **** **** **** **** +1544 OcRay_Tele **** **** **** **** **** **** **** **** +1545 OcRay_FlSt **** **** **** **** **** **** **** **** +1546 OcRay_Dis **** **** **** **** **** **** **** **** +1547 OcRay_Death **** **** **** **** **** **** **** **** +1548 Samu_AncestralDaisho **** **** **** **** **** **** **** **** +1549 Warpr_Rally **** **** **** **** **** **** **** **** +1550 Warpr_Inflame **** **** **** **** **** **** **** **** +1551 Warpr_ImplicableFoe **** **** **** **** **** **** **** **** +1552 Warpr_Healing_Circle **** **** **** **** **** **** **** **** +1553 TN_CLUNDEAD **** **** **** **** **** **** **** **** +1554 TN_EnergyDrain **** **** **** **** **** **** **** **** +1555 Warpr_Mass_Haste **** **** **** **** **** **** **** **** +1556 TO_Fear **** **** **** **** **** **** **** **** +1557 TO_Pallor **** **** **** **** **** **** **** **** +1558 TO_Carrion **** **** **** **** **** **** **** **** +1559 TO_DeathTouch **** **** **** **** **** **** **** **** +1560 TO_MNRUndead **** **** **** **** **** **** **** **** +1561 TO_MJRUndead **** **** **** **** **** **** **** **** +1562 TO_Nightwing **** **** **** **** **** **** **** **** +1563 Warpr_Mass_Heal **** **** **** **** **** **** **** **** +1564 SB_ShockWeap **** **** **** **** **** **** **** **** +1565 SB_HolyWeap **** **** **** **** **** **** **** **** +1566 SB_BrillWeap **** **** **** **** **** **** **** **** +1567 Spell_Turning **** **** **** P 0 3 0 -9 +1568 Death_Knell **** **** **** **** **** **** **** **** +1569 SereneGuardian_PainfulRelease **** **** **** **** **** **** **** **** +1570 SereneGuardian_DamagingRelease **** **** **** **** **** **** **** **** +1571 SereneGuardian_StaggeringRelease **** **** **** **** **** **** **** **** +1572 SereneGuardian_ConfoundingRelease **** **** **** **** **** **** **** **** +1573 SereneGuardian_SoulRelease **** **** **** **** **** **** **** **** +1574 AnimalTrance Mind_Affecting Will 1 R 1 **** **** **** +1575 Blink **** **** **** E 0 2 0 **** +1576 DetectMagic **** **** **** **** **** **** **** **** +1577 Marrusault_Howl **** **** **** **** **** **** **** **** +1578 Hybsil_Mirror_Image **** **** **** **** **** **** **** **** +1579 HYBSIL_DANCLIGHTS **** **** **** **** **** **** **** **** +1580 HYBSIL_JUMP **** **** **** **** **** **** **** **** +1581 Bariaur_Charge **** **** **** **** **** **** **** **** +1582 Wildren_fury **** **** **** **** **** **** **** **** +1583 KotMC_CombatSense **** **** **** **** **** **** **** **** +1584 InvestArmour **** **** **** **** **** **** **** **** +1585 ThayK_FinalStand **** **** **** **** **** **** **** **** +1586 ArmouredMind **** **** **** **** **** **** **** **** +1587 Diabol_Diabolism **** **** **** **** **** **** **** **** +1588 Diabol_VDiabolism **** **** **** **** **** **** **** **** +1589 MindOverBody **** **** **** **** **** **** **** **** +1590 Maester_Identification **** **** **** **** **** **** **** **** +1591 LendResolve **** **** **** **** **** **** **** **** +1592 Ollam_InspireCompetence **** **** **** **** **** **** **** **** +1593 Ollam_InspireResilience **** **** **** **** **** **** **** **** +1594 Duskblade_Channeling **** **** **** **** **** **** **** **** +1595 DivineWholeness **** **** **** **** **** **** **** **** +1596 Hexblade_Companion **** **** **** **** **** **** **** **** +1597 TribalFrenzy **** **** **** **** **** **** **** **** +1598 HexbladeCurse **** **** **** **** **** **** **** **** +1599 HexbladeAura **** **** **** **** **** **** **** **** +1600 Changestaff **** **** **** S 0 3 0 -2 +1601 Rage **** **** **** E 0 2 9 **** +1602 Arach_SpidMount **** **** **** **** **** **** **** **** +1603 Arach_DominateMale **** **** **** **** **** **** **** **** +1604 Arach_ZinCarla **** **** **** **** **** **** **** **** +1605 Arach_YochlolMaster **** **** **** **** **** **** **** **** +1606 Arach_YochlolYoch **** **** **** **** **** **** **** **** +1607 Arach_YochlolSpid **** **** **** **** **** **** **** **** +1608 Arach_YochloloGas **** **** **** **** **** **** **** **** +1609 Arach_YochlolRevert **** **** **** **** **** **** **** **** +1610 Duskblade_Quickcast **** **** **** **** **** **** **** **** +1611 WarStrike **** **** **** **** **** **** **** **** +1612 SelvetarmsWrath **** **** **** **** **** **** **** **** +1613 SpidersGrace **** **** **** **** **** **** **** **** +1614 SpiderServantMonstrous **** **** **** **** **** **** **** **** +1615 SpiderServantSword **** **** **** **** **** **** **** **** +1616 SpiderServantMyrlochar **** **** **** **** **** **** **** **** +1617 SpiderServantPhase **** **** **** **** **** **** **** **** +1618 SpiderServantMasterFeat **** **** **** **** **** **** **** **** +1619 Judgment **** **** **** **** **** **** **** **** +1620 Healer_Clean_Para **** **** **** **** **** **** **** **** +1621 InscribeRune **** **** **** **** **** **** **** **** +1622 MaximizeRune **** **** **** **** **** **** **** **** +1623 RuneChant **** **** **** **** **** **** **** **** +1624 ImprovedRunecast **** **** **** **** **** **** **** **** +1625 RuneCharges **** **** **** **** **** **** **** **** +1626 RuneUsesPerDay **** **** **** **** **** **** **** **** +1627 RuneCountOne **** **** **** **** **** **** **** **** +1628 RuneCountTen **** **** **** **** **** **** **** **** +1629 RuneClear **** **** **** **** **** **** **** **** +1630 Healer_Clean_Dis **** **** **** **** **** **** **** **** +1631 PDK_RallyingCry **** **** **** **** **** **** **** **** +1632 PDK_Fear **** **** **** **** **** **** **** **** +1633 PDK_OathOfWrath **** **** **** **** **** **** **** **** +1634 PDK_FinalStand **** **** **** **** **** **** **** **** +1635 PDK_InspireCourage **** **** **** **** **** **** **** **** +1636 Healer_Clean_Fear **** **** **** **** **** **** **** **** +1637 WidenSpell **** **** **** **** **** **** **** **** +1638 Healer_Clean_Poison **** **** **** **** **** **** **** **** +1639 Dirge_Sorrow **** **** **** **** **** **** **** **** +1640 Dirge_Bolster **** **** **** **** **** **** **** **** +1641 Dirge_Grief **** **** **** **** **** **** **** **** +1642 Dirge_Horror **** **** **** **** **** **** **** **** +1643 Dirge_Awaken **** **** **** **** **** **** **** **** +1644 Healer_Clean_Blind **** **** **** **** **** **** **** **** +1645 Suel_DispellingStrike **** **** **** **** **** **** **** **** +1646 SancMind_CleanStrike **** **** **** **** **** **** **** **** +1647 SancMind_DisruptBlow **** **** **** **** **** **** **** **** +1648 SancMind_PartitionMind **** **** **** **** **** **** **** **** +1649 Healer_Clean_Spirit **** **** **** **** **** **** **** **** +1650 ClangeddinsStrike **** **** **** **** **** **** **** **** +1651 ClangeddinsMight **** **** **** **** **** **** **** **** +1652 Rockburst **** **** **** **** **** **** **** **** +1653 Healer_Clean_Petri **** **** **** **** **** **** **** **** +1654 CheckDomainSlots **** **** **** **** **** **** **** **** +1655 CastDomainLevel1 **** **** **** **** **** **** **** **** +1656 CastDomainLevel1Slot1 **** **** **** **** **** **** **** **** +1657 CastDomainLevel1Slot2 **** **** **** **** **** **** **** **** +1658 CastDomainLevel1Slot3 **** **** **** **** **** **** **** **** +1659 CastDomainLevel1Slot4 **** **** **** **** **** **** **** **** +1660 CastDomainLevel1Slot5 **** **** **** **** **** **** **** **** +1661 CastDomainLevel2 **** **** **** **** **** **** **** **** +1662 CastDomainLevel2Slot1 **** **** **** **** **** **** **** **** +1663 CastDomainLevel2Slot2 **** **** **** **** **** **** **** **** +1664 CastDomainLevel2Slot3 **** **** **** **** **** **** **** **** +1665 CastDomainLevel2Slot4 **** **** **** **** **** **** **** **** +1666 CastDomainLevel2Slot5 **** **** **** **** **** **** **** **** +1667 CastDomainLevel3 **** **** **** **** **** **** **** **** +1668 CastDomainLevel3Slot1 **** **** **** **** **** **** **** **** +1669 CastDomainLevel3Slot2 **** **** **** **** **** **** **** **** +1670 CastDomainLevel3Slot3 **** **** **** **** **** **** **** **** +1671 CastDomainLevel3Slot4 **** **** **** **** **** **** **** **** +1672 CastDomainLevel3Slot5 **** **** **** **** **** **** **** **** +1673 CastDomainLevel4 **** **** **** **** **** **** **** **** +1674 CastDomainLevel4Slot1 **** **** **** **** **** **** **** **** +1675 CastDomainLevel4Slot2 **** **** **** **** **** **** **** **** +1676 CastDomainLevel4Slot3 **** **** **** **** **** **** **** **** +1677 CastDomainLevel4Slot4 **** **** **** **** **** **** **** **** +1678 CastDomainLevel4Slot5 **** **** **** **** **** **** **** **** +1679 CastDomainLevel5 **** **** **** **** **** **** **** **** +1680 CastDomainLevel5Slot1 **** **** **** **** **** **** **** **** +1681 CastDomainLevel5Slot2 **** **** **** **** **** **** **** **** +1682 CastDomainLevel5Slot3 **** **** **** **** **** **** **** **** +1683 CastDomainLevel5Slot4 **** **** **** **** **** **** **** **** +1684 CastDomainLevel5Slot5 **** **** **** **** **** **** **** **** +1685 CastDomainLevel6 **** **** **** **** **** **** **** **** +1686 CastDomainLevel6Slot1 **** **** **** **** **** **** **** **** +1687 CastDomainLevel6Slot2 **** **** **** **** **** **** **** **** +1688 CastDomainLevel6Slot3 **** **** **** **** **** **** **** **** +1689 CastDomainLevel6Slot4 **** **** **** **** **** **** **** **** +1690 CastDomainLevel6Slot5 **** **** **** **** **** **** **** **** +1691 CastDomainLevel7 **** **** **** **** **** **** **** **** +1692 CastDomainLevel7Slot1 **** **** **** **** **** **** **** **** +1693 CastDomainLevel7Slot2 **** **** **** **** **** **** **** **** +1694 CastDomainLevel7Slot3 **** **** **** **** **** **** **** **** +1695 CastDomainLevel7Slot4 **** **** **** **** **** **** **** **** +1696 CastDomainLevel7Slot5 **** **** **** **** **** **** **** **** +1697 Healer_New_Limb **** **** **** **** **** **** **** **** +1698 Healer_New_Life **** **** **** **** **** **** **** **** +1699 SenseMagic **** **** **** **** **** **** **** **** +1700 CHANNEL_SPELL **** **** **** **** **** **** **** **** +1701 CastDomainLevel8 **** **** **** **** **** **** **** **** +1702 CastDomainLevel8Slot1 **** **** **** **** **** **** **** **** +1703 CastDomainLevel8Slot2 **** **** **** **** **** **** **** **** +1704 CastDomainLevel8Slot3 **** **** **** **** **** **** **** **** +1705 CastDomainLevel8Slot4 **** **** **** **** **** **** **** **** +1706 CastDomainLevel8Slot5 **** **** **** **** **** **** **** **** +1707 CastDomainLevel9 **** **** **** **** **** **** **** **** +1708 CastDomainLevel9Slot1 **** **** **** **** **** **** **** **** +1709 CastDomainLevel9Slot2 **** **** **** **** **** **** **** **** +1710 CastDomainLevel9Slot3 **** **** **** **** **** **** **** **** +1711 CastDomainLevel9Slot4 **** **** **** **** **** **** **** **** +1712 CastDomainLevel9Slot5 **** **** **** **** **** **** **** **** +1713 DualBoost **** **** **** **** **** **** **** **** +1714 Charm_Domain_Power **** **** **** **** **** **** **** **** +1715 Death_Domain_Power **** **** **** **** **** **** **** **** +1716 Destruction_Domain_Power **** **** **** **** **** **** **** **** +1717 Family_Domain_Power **** **** **** **** **** **** **** **** +1718 Halfling_Domain_Power **** **** **** **** **** **** **** **** +1719 Hate_Domain_Power **** **** **** **** **** **** **** **** +1720 Nobility_Domain_Power **** **** **** **** **** **** **** **** +1721 Orc_Domain_Power **** **** **** **** **** **** **** **** +1722 Protection_Domain_Power **** **** **** **** **** **** **** **** +1723 Renewal_Domain_Power **** **** **** **** **** **** **** **** +1724 Strength_Domain_Power **** **** **** **** **** **** **** **** +1725 Travel_Domain_Power **** **** **** **** **** **** **** **** +1726 Turn_Scaleykind **** **** **** **** **** **** **** **** +1727 Turn_Slime **** **** **** **** **** **** **** **** +1728 DrowJudicator_Command_Spiders **** **** **** **** **** **** **** **** +1729 Turn_Plant **** **** **** **** **** **** **** **** +1730 Turn_Air **** **** **** **** **** **** **** **** +1731 Turn_Earth **** **** **** **** **** **** **** **** +1732 Turn_Fire **** **** **** **** **** **** **** **** +1733 Turn_Water **** **** **** **** **** **** **** **** +1734 Turn_Blightspawned **** **** **** **** **** **** **** **** +1735 AppraiseMagicValue **** **** **** **** **** **** **** **** +1736 CraftSkullTalisman **** **** **** **** **** **** **** **** +1737 Grenade_Cursed_Water **** **** **** **** **** **** **** **** +1738 Frostrager_OneTwoPunch **** **** **** **** **** **** **** **** +1739 ZealousSurge **** **** **** **** **** **** **** **** +1740 CrusaderSmite **** **** **** **** **** **** **** **** +1741 Animalistic_Power **** **** **** E 0 2 1 **** +1742 Bigbys_Striking_Fist **** Reflex 1 R 1 **** **** **** +1743 Bigbys_Tripping_Hand **** Reflex 1 R 1 **** **** **** +1744 Blade_of_Blood **** **** **** **** **** **** **** **** +1745 Blade_of_Blood_1d6 **** **** **** E 0 2 15 **** +1746 Blade_of_Blood_3d6 **** **** **** **** **** **** **** **** +1747 FEAT_FRIGHTFUL_CLEAVE **** **** **** **** **** **** **** **** +1748 FEAT_FRIGHTFUL_ATTACK **** **** **** **** **** **** **** **** +1749 FEAT_GFKILL_GHOST_STEP **** **** **** **** **** **** **** **** +1750 Acrobatic_Charge **** **** **** **** **** **** **** **** +1751 Stunning_Shout **** **** **** **** **** **** **** **** +1752 Ki_Save **** **** **** **** **** **** **** **** +1753 Ki_Skill **** **** **** **** **** **** **** **** +1754 Ki_Heal **** **** **** **** **** **** **** **** +1755 Deadly_Shout **** **** **** **** **** **** **** **** +1756 Censure_Demons **** **** **** **** **** **** **** **** +1757 Courage_Of_Heaven **** **** **** **** **** **** **** **** +1758 Consecrated_Aura **** **** **** **** **** **** **** **** +1759 Holy_Aura_Versus_Demons **** **** **** **** **** **** **** **** +1760 ChosenWeapon **** **** **** **** **** **** **** **** +1761 DexterousAttack **** **** **** **** **** **** **** **** +1762 FlurryOfSwords **** **** **** **** **** **** **** **** +1763 FalseKeeness **** **** **** **** **** **** **** **** +1764 Blur **** **** **** **** **** **** **** **** +1765 MirrorImage **** **** **** **** **** **** **** **** +1766 SuddenEmpower **** **** **** **** **** **** **** **** +1767 SuddenExtend **** **** **** **** **** **** **** **** +1768 SuddenMaximize **** **** **** **** **** **** **** **** +1769 SuddenWiden **** **** **** **** **** **** **** **** +1770 FightingChallenge **** **** **** **** **** **** **** **** +1771 TestOfMettle **** **** **** **** **** **** **** **** +1772 CallToBattle **** **** **** **** **** **** **** **** +1773 DauntingChallenge **** **** **** **** **** **** **** **** +1774 BondOfLoyalty **** **** **** **** **** **** **** **** +1775 LoyalBeyondDeath **** **** **** **** **** **** **** **** +1776 ShieldBlock **** **** **** **** **** **** **** **** +1777 BulwarkOfDefense **** **** **** **** **** **** **** **** +1778 VigilantDefender **** **** **** **** **** **** **** **** +1779 ShieldAlly **** **** **** **** **** **** **** **** +1780 ImprovedShieldAlly **** **** **** **** **** **** **** **** +1781 AttuneGem **** **** **** **** **** **** **** **** +1782 AttuneGemCraft **** **** **** **** **** **** **** **** +1783 AttuneGemCheckGem **** **** **** **** **** **** **** **** +1784 SummonUndeadI **** **** **** S 0 2 0 **** +1785 SummonUndeadII **** **** **** S 0 2 0 **** +1786 SummonUndeadIII **** **** **** S 0 2 0 **** +1787 SummonUndeadIV **** **** **** S 0 2 0 **** +1788 SummonUndeadV **** **** **** S 0 2 0 **** +1789 Scare Fear Will 1 I 1 **** **** **** +1790 Animate_Object **** **** **** **** **** **** **** **** +1791 Chill_Touch Negative Fortitude 1 T 1 **** **** **** +1792 Spellbook **** **** **** **** **** **** **** **** +1793 PnPFamiliarHide **** **** **** **** **** **** **** **** +1794 ChangeCodeSwitches **** **** **** **** **** **** **** **** +1795 FEAT_ZONE_OF_ANIMATION **** **** **** **** **** **** **** **** +1796 AugmentFamiliar **** **** **** **** **** **** **** **** +1797 Deflect **** **** **** P 0 2 0 **** +1798 EndScrying **** **** **** **** **** **** **** **** +1799 FalseLife **** **** **** P 0 3 0 **** +1800 ProtectionArrows **** **** **** P 0 2 7 **** +1801 TouchIdiocy **** **** 1 T 1 **** **** **** +1802 DeepSlumber Mind_Affecting Will 1 I 1 **** **** **** +1803 HoundDoom **** **** **** **** **** **** **** **** +1804 RepelVermin **** **** **** P 0 3 0 **** +1805 BalefulPolymorph **** Fortitude 1 R 1 **** **** **** +1806 BreakEnchantment **** **** **** **** **** **** **** **** +1807 CursedBlade **** **** **** **** **** **** **** **** +1808 SolidFog **** **** **** I 1 **** **** **** +1809 DetectScrying **** **** **** **** **** **** **** **** +1810 Channeled_Pyroburst **** **** **** **** **** **** **** **** +1811 Channeled_Pyroburst_Swift **** **** **** **** **** **** **** **** +1812 Channeled_Pyroburst_Standard **** **** **** **** **** **** **** **** +1813 Channeled_Pyroburst_Full **** **** **** **** **** **** **** **** +1814 Channeled_Pyroburst_Two **** **** **** **** **** **** **** **** +1815 Crown_Might **** **** **** E 0 3 1 **** +1816 Crown_Protection **** **** **** P 0 3 14 **** +1817 Lesser_Deflect **** **** **** P 0 2 0 **** +1818 Dimension_Hop **** **** **** **** **** **** **** **** +1819 Dispelling_Touch **** **** **** **** **** **** **** **** +1820 Doom_Scarabs **** Will 0 I 1 **** **** **** +1821 Energy_Aegis **** **** **** **** **** **** **** **** +1822 Energy_Aegis_Acid **** **** **** **** **** **** **** **** +1823 Energy_Aegis_Cold **** **** **** **** **** **** **** **** +1824 Energy_Aegis_Elec **** **** **** **** **** **** **** **** +1825 Energy_Aegis_Fire **** **** **** **** **** **** **** **** +1826 Energy_Aegis_Sonic **** **** **** **** **** **** **** **** +1827 Energy_Surge **** **** **** **** **** **** **** **** +1828 Energy_Surge_Acid **** **** **** **** **** **** **** **** +1829 Energy_Surge_Cold **** **** **** **** **** **** **** **** +1830 Energy_Surge_Elec **** **** **** **** **** **** **** **** +1831 Energy_Surge_Fire **** **** **** **** **** **** **** **** +1832 Energy_Surge_Sonic **** **** **** **** **** **** **** **** +1833 Halt **** Will 1 R 1 **** **** **** +1834 Kelgores_Fire_Bolt Fire Reflex 0 R 1 **** **** **** +1835 Regroup **** **** **** **** **** **** **** **** +1836 Rouse **** **** **** **** **** **** **** **** +1837 Seeking_Ray Electricity **** 1 R 1 **** **** **** +1838 Slashing_Dispel **** **** **** R 1 **** **** **** +1839 Sonic_Shield **** **** **** P 0 2 0 **** +1840 Sure_Strike **** **** **** E 0 2 0 **** +1841 CoC_Bless **** **** **** **** **** **** **** **** +1842 CoC_Wrath **** **** **** **** **** **** **** **** +1843 OAAnimalCompanion **** **** **** **** **** **** **** **** +1844 Celestial_Companion **** **** **** **** **** **** **** **** +1845 Unicorn_Companion **** **** **** **** **** **** **** **** +1846 Lammasu_Companion **** **** **** **** **** **** **** **** +1847 Androsphinx_Companion **** **** **** **** **** **** **** **** +1848 SongArcanePower **** **** **** **** **** **** **** **** +1849 Close_Wounds **** **** **** H 0 **** **** **** +1850 Revivify **** **** **** **** **** **** **** **** +1851 Bless_Water **** **** **** **** **** **** **** **** +1852 Calm_Emotions **** **** **** **** **** **** **** **** +1853 Repulsion **** **** **** P 0 2 0 **** +1854 Holy_Aura **** **** **** P 0 2 0 **** +1855 True_Resurrection **** **** **** **** **** **** **** **** +1856 Foresight **** **** **** P 0 3 0 **** +1857 SongTimelessness **** **** **** **** **** **** **** **** +1858 Draconic_Arcane_Grace_Master_1_5 **** **** **** **** **** **** **** **** +1859 Draconic_Arcane_Grace_Master_6_9 **** **** **** **** **** **** **** **** +1860 Draconic_Breath_Master_1_5 **** **** **** **** **** **** **** **** +1861 Draconic_Breath_Master_6_9 **** **** **** **** **** **** **** **** +1862 Draconic_Arcane_Grace_1 **** **** **** **** **** **** **** **** +1863 Draconic_Arcane_Grace_2 **** **** **** **** **** **** **** **** +1864 Draconic_Arcane_Grace_3 **** **** **** **** **** **** **** **** +1865 Draconic_Arcane_Grace_4 **** **** **** **** **** **** **** **** +1866 Draconic_Arcane_Grace_5 **** **** **** **** **** **** **** **** +1867 Draconic_Arcane_Grace_6 **** **** **** **** **** **** **** **** +1868 Draconic_Arcane_Grace_7 **** **** **** **** **** **** **** **** +1869 Draconic_Arcane_Grace_8 **** **** **** **** **** **** **** **** +1870 Draconic_Arcane_Grace_9 **** **** **** **** **** **** **** **** +1871 Draconic_Breath_1 **** **** **** **** **** **** **** **** +1872 Draconic_Breath_2 **** **** **** **** **** **** **** **** +1873 Draconic_Breath_3 **** **** **** **** **** **** **** **** +1874 Draconic_Breath_4 **** **** **** **** **** **** **** **** +1875 Draconic_Breath_5 **** **** **** **** **** **** **** **** +1876 Draconic_Breath_6 **** **** **** **** **** **** **** **** +1877 Draconic_Breath_7 **** **** **** **** **** **** **** **** +1878 Draconic_Breath_8 **** **** **** **** **** **** **** **** +1879 Draconic_Breath_9 **** **** **** **** **** **** **** **** +1880 Breath_of_Life **** **** **** **** **** **** **** **** +1881 Swift_Wing_Wings **** **** **** **** **** **** **** **** +1882 ToT_Frightful_Presence **** **** **** **** **** **** **** **** +1883 ToT_Dominate_Dragon **** **** **** **** **** **** **** **** +1884 ToT_Breath_Weapon **** **** **** **** **** **** **** **** +1885 ToT_Cold_Cone **** **** **** **** **** **** **** **** +1886 ToT_Acid_Line **** **** **** **** **** **** **** **** +1887 ToT_Acid_Cone **** **** **** **** **** **** **** **** +1888 ToT_Elec_Line **** **** **** **** **** **** **** **** +1889 ToT_Fire_Cone **** **** **** **** **** **** **** **** +1890 Dragonfire_Strike_Toggle **** **** **** **** **** **** **** **** +1891 True_Stealth_Toggle **** **** **** **** **** **** **** **** +1892 Fire_Lash **** **** **** **** **** **** **** **** +1893 Bolt_of_Fire **** **** **** **** **** **** **** **** +1894 Nimbus **** **** **** **** **** **** **** **** +1895 Nimbus_Touch_Attack **** **** **** **** **** **** **** **** +1896 Firewalk **** **** **** **** **** **** **** **** +1897 Heat_Death **** **** **** **** **** **** **** **** +1898 Conflagration **** **** **** **** **** **** **** **** +1899 SongCosmicFire **** **** **** **** **** **** **** **** +1900 Shifter_GWShape **** **** **** **** **** **** **** **** +1901 Shifter_EGWShape **** **** **** **** **** **** **** **** +1902 Shifter_Options **** **** **** **** **** **** **** **** +1903 Shifter_TrueForm **** **** **** **** **** **** **** **** +1904 Lich_Touch **** **** **** **** **** **** **** **** +1905 Lich_Fear_Aura **** **** **** **** **** **** **** **** +1906 Lich_AlterSelf **** **** **** **** **** **** **** **** +1907 Lich_CraftWonderus **** **** **** **** **** **** **** **** +1908 Lich_Trap **** **** **** **** **** **** **** **** +1909 Assassin_DeathAttack **** **** **** **** **** **** **** **** +1910 SPELL_LASHER_THIRD_HAND **** **** **** **** **** **** **** **** +1911 SPELL_LASHER_CRACK **** **** **** **** **** **** **** **** +1912 SPELL_LASHER_STUN_SNAP **** **** **** **** **** **** **** **** +1913 SPELL_LASHER_DEATH_SPIRAL **** **** **** **** **** **** **** **** +1914 SPELL_LASHER_LASHW **** **** **** **** **** **** **** **** +1915 ForceOfPersonality **** **** **** **** **** **** **** **** +1916 InsightfulReflexes **** **** **** **** **** **** **** **** +1917 SPELL_LASHER_CRACK_DOOM **** **** **** **** **** **** **** **** +1918 Shifter_Effects_Application **** **** **** **** **** **** **** **** +1919 Shifter_QuickShiftSlots_1 **** **** **** **** **** **** **** **** +1920 Shifter_QuickShiftSlots_2 **** **** **** **** **** **** **** **** +1921 Shifter_QuickSlot_1 **** **** **** **** **** **** **** **** +1922 Shifter_QuickSlot_2 **** **** **** **** **** **** **** **** +1923 Shifter_QuickSlot_3 **** **** **** **** **** **** **** **** +1924 Shifter_QuickSlot_4 **** **** **** **** **** **** **** **** +1925 Shifter_QuickSlot_5 **** **** **** **** **** **** **** **** +1926 Shifter_QuickSlot_6 **** **** **** **** **** **** **** **** +1927 Shifter_QuickSlot_7 **** **** **** **** **** **** **** **** +1928 Shifter_QuickSlot_8 **** **** **** **** **** **** **** **** +1929 Shifter_QuickSlot_9 **** **** **** **** **** **** **** **** +1930 Shifter_QuickSlot_10 **** **** **** **** **** **** **** **** +1931 FEAT_RACE_GAZECONF **** **** **** **** **** **** **** **** +1932 FEAT_RACE_GAZEEVIL **** **** **** **** **** **** **** **** +1933 FEAT_RACE_GAZEPETRIFY **** **** **** **** **** **** **** **** +1934 SlayerOfDomielDetectEvil **** **** **** **** **** **** **** **** +1935 FEAT_RACE_VAMPTOUCH **** **** **** **** **** **** **** **** +1936 FEAT_IRDA_CHANGE_SHAPE **** **** **** **** **** **** **** **** +1937 Irda_Select_Form **** **** **** **** **** **** **** **** +1938 Irda_Options **** **** **** **** **** **** **** **** +1939 Irda_True_Form **** **** **** **** **** **** **** **** +1940 Irda_Quickslot_1 **** **** **** **** **** **** **** **** +1941 Irda_Quickslot_2 **** **** **** **** **** **** **** **** +1942 FEAT_CHANGELING_CHANGE_SHAPE **** **** **** **** **** **** **** **** +1943 Changeling_Select_Form **** **** **** **** **** **** **** **** +1944 Changeling_Options **** **** **** **** **** **** **** **** +1945 Changeling_True_Form **** **** **** **** **** **** **** **** +1946 Changeling_Quickslot_1 **** **** **** **** **** **** **** **** +1947 Changeling_Quickslot_2 **** **** **** **** **** **** **** **** +1948 Nymph_Stunning_Glance **** **** **** **** **** **** **** **** +1949 Nymph_Blinding_Beauty **** **** **** **** **** **** **** **** +1950 SlayerOfDomielDeathTouch1 **** **** **** **** **** **** **** **** +1951 Rakshasa_Disguise **** **** **** **** **** **** **** **** +1952 EndPRCPolymorph **** **** **** **** **** **** **** **** +1953 Shout Sonic Fortitude 1 I 1 **** **** **** +1954 Greater_Shout Sonic Fortitude 1 I 1 **** **** **** +1955 Feyri_Alter **** **** **** **** **** **** **** **** +1956 Nixie_Waterbreathing **** **** **** **** **** **** **** **** +1957 Urdinnir_StoneSkin **** **** **** **** **** **** **** **** +1958 Race_Darkness **** **** **** **** **** **** **** **** +1959 Race_Daze **** **** **** **** **** **** **** **** +1960 Race_Light **** **** **** **** **** **** **** **** +1961 Svirf_BlindDeaf **** **** **** **** **** **** **** **** +1962 Duegar_Invis **** **** **** **** **** **** **** **** +1963 Illithid_Charm_Monster **** **** **** **** **** **** **** **** +1964 Race_Charm_Person **** **** **** **** **** **** **** **** +1965 Faerie_Fire **** **** **** **** **** **** **** **** +1966 Avariel_Dive **** **** **** **** **** **** **** **** +1967 Minotaur_Charge **** **** **** **** **** **** **** **** +1968 Race_Blur **** **** **** **** **** **** **** **** +1969 Feyri_Enervation **** **** **** **** **** **** **** **** +1970 Race_Entangle **** **** **** **** **** **** **** **** +1971 Race_Fear **** **** **** **** **** **** **** **** +1972 Race_Clair **** **** **** **** **** **** **** **** +1973 Race_Neutralize_Poison **** **** **** **** **** **** **** **** +1974 Pixie_Confusion **** **** **** **** **** **** **** **** +1975 Pixie_Invis **** **** **** **** **** **** **** **** +1976 Pixie_Dispel **** **** **** **** **** **** **** **** +1977 Race_Chill_Touch **** **** **** **** **** **** **** **** +1978 Pixie_Polymorph **** **** **** **** **** **** **** **** +1979 Pixie_BROWN_BEAR **** **** **** **** **** **** **** **** +1980 Pixie_PANTHER **** **** **** **** **** **** **** **** +1981 Pixie_WOLF **** **** **** **** **** **** **** **** +1982 Pixie_BOAR **** **** **** **** **** **** **** **** +1983 Pixie_BADGER **** **** **** **** **** **** **** **** +1984 EnergyRay **** **** **** **** **** **** **** **** +1985 EnergyRay_Cold **** **** **** **** **** **** **** **** +1986 EnergyRay_Elec **** **** **** **** **** **** **** **** +1987 EnergyRay_Fire **** **** **** **** **** **** **** **** +1988 EnergyRay_Sonic **** **** **** **** **** **** **** **** +1989 Race_Silence **** **** **** **** **** **** **** **** +1990 Race_Mage_Hand **** **** **** **** **** **** **** **** +1991 Race_Elan_Resistance **** **** **** **** **** **** **** **** +1992 Race_Elan_Resiliance **** **** **** **** **** **** **** **** +1993 Race_Halfgiant_Stomp **** **** **** **** **** **** **** **** +1994 Race_Maenad_Outburst **** **** **** **** **** **** **** **** +1995 Race_Xeph_Burst **** **** **** **** **** **** **** **** +1996 Race_Vampiric_Touch **** **** **** **** **** **** **** **** +1997 SacredPurifier_SacredStrike **** **** **** **** **** **** **** **** +1998 FogCloud **** **** **** **** **** **** **** **** +1999 PsychicRenewal **** **** **** **** **** **** **** **** +2000 Mastery_Elements(Normal) **** **** **** **** **** **** **** **** +2001 Mastery_Elements(Fire) **** **** **** **** **** **** **** **** +2002 Mastery_Elements(Cold) **** **** **** **** **** **** **** **** +2003 Mastery_Elements(Acid) **** **** **** **** **** **** **** **** +2004 Mastery_Elements(Electricity) **** **** **** **** **** **** **** **** +2005 Mastery_Elements(Sonic) **** **** **** **** **** **** **** **** +2006 Mastery_Shaping **** **** **** **** **** **** **** **** +2007 Arcane_Fire **** **** **** **** **** **** **** **** +2008 Spell_Like **** **** **** **** **** **** **** **** +2009 Mastery_Elements(Master) **** **** **** **** **** **** **** **** +2010 MinOozyTouchBrown **** **** **** **** **** **** **** **** +2011 MinOozyTouchGray **** **** **** **** **** **** **** **** +2012 MinOozyTouchOchr **** **** **** **** **** **** **** **** +2013 MinOozyTouchFungus **** **** **** **** **** **** **** **** +2014 MajOozyTouchBlack **** **** **** **** **** **** **** **** +2015 MajOozyTouchCube **** **** **** **** **** **** **** **** +2016 MajOozyTouchSlime **** **** **** **** **** **** **** **** +2017 MajOozyTouchYellow **** **** **** **** **** **** **** **** +2018 OozyGlob **** **** **** **** **** **** **** **** +2019 OozyGlob(Brown) **** **** **** **** **** **** **** **** +2020 OozyGlob(Gray) **** **** **** **** **** **** **** **** +2021 OozyGlob(Ochre) **** **** **** **** **** **** **** **** +2022 OozyGlob(Fungus) **** **** **** **** **** **** **** **** +2023 SlimeWave **** **** **** **** **** **** **** **** +2024 Feat_End_Spell_Effects **** **** **** **** **** **** **** **** +2025 HavocMage_BattleCast **** **** **** **** **** **** **** **** +2026 EndPRCTreeshape **** **** **** **** **** **** **** **** +2027 BAELNORN_EYES **** **** **** **** **** **** **** **** +2028 Cohort **** **** **** **** **** **** **** **** +2029 Hath_GrCommand **** **** **** **** **** **** **** **** +2030 ShadowbaneSmite **** **** **** **** **** **** **** **** +2031 Shadowbane_SacredStealth **** **** **** **** **** **** **** **** +2032 NimbusOfLight **** **** **** **** **** **** **** **** +2033 ServanOfHeaven **** **** **** **** **** **** **** **** +2034 Ranged_Smite **** **** **** **** **** **** **** **** +2035 HathranFear **** **** **** **** **** **** **** **** +2036 SLA_I **** **** **** **** **** **** **** **** +2037 SLA_II **** **** **** **** **** **** **** **** +2038 SLA_III **** **** **** **** **** **** **** **** +2039 SLA_IV **** **** **** **** **** **** **** **** +2040 SLA_V **** **** **** **** **** **** **** **** +2041 MLGreaterTurn **** **** **** **** **** **** **** **** +2042 MLMaximizeTurn **** **** **** **** **** **** **** **** +2043 MLSearingRay **** **** **** **** **** **** **** **** +2044 MLRejuvenationOfMorn **** **** **** **** **** **** **** **** +2045 MLAuraOfRadiance **** **** **** **** **** **** **** **** +2046 MLDaylight **** **** **** **** **** **** **** **** +2047 EXTRA_SUMMONING **** **** **** **** **** **** **** **** +2048 SummonAir **** **** **** **** **** **** **** **** +2049 SummonEarth **** **** **** **** **** **** **** **** +2050 SummonFire **** **** **** **** **** **** **** **** +2051 SummonWater **** **** **** **** **** **** **** **** +2052 Anti-paladin_Summon_Mount **** **** **** **** **** **** **** **** +2053 Rune_DimensionDoor_RadialMaster **** **** **** **** **** **** **** **** +2054 Rune_DimensionDoor_DirDist_SelfOnly **** **** **** **** **** **** **** **** +2055 Rune_DimensionDoor_DirDist_Party **** **** **** **** **** **** **** **** +2056 ShadowInq_PierceShadows **** **** **** **** **** **** **** **** +2057 ShadowInq_BurningLight **** **** **** **** **** **** **** **** +2058 ShadowStk_SacredDefense **** **** **** **** **** **** **** **** +2059 ShadowStk_SacredStrike **** **** **** **** **** **** **** **** +2060 BurnSpell **** **** **** **** **** **** **** **** +2061 KnightWeave_Damage **** **** **** **** **** **** **** **** +2062 KnightWeave_Heal **** **** **** **** **** **** **** **** +2063 Enthrall **** **** **** **** **** **** **** **** +2064 Spelldance_Enthrall **** **** **** **** **** **** **** **** +2065 Spelldance_Sleep **** **** **** **** **** **** **** **** +2066 MountainFortressStance **** **** **** **** **** **** **** **** +2067 CrashingMountainJuggernaught **** **** **** **** **** **** **** **** +2068 DragonsTooth **** **** **** **** **** **** **** **** +2069 AwakenTheStoneDragon **** **** **** **** **** **** **** **** +2070 Spell_Jump **** **** **** **** **** **** **** **** +2071 IRON_BODY **** **** **** **** **** **** **** **** +2072 ENLARGE_PERSON **** **** **** E 0 2 9 -2072 +2073 MASS_ENLARGE_PERSON **** **** **** E 0 2 9 -2072 +2074 REDUCE_PERSON **** Fortitude 1 R 1 **** **** **** +2075 MASS_REDUCE_PERSON **** Fortitude 1 I 1 **** **** **** +2076 ANTIMAGIC_FIELD **** **** **** P 0 3 0 -7 +2077 NONDETECTION **** **** **** **** **** **** **** **** +2078 RAINBOW_PATTERN Mind_Affecting Will 1 I 1 **** **** **** +2079 MAGE_HAND **** **** **** **** **** **** **** **** +2080 DETECT_UNDEAD **** **** **** **** **** **** **** **** +2081 GLIBNESS **** **** **** **** **** **** **** **** +2082 Imbue_Item **** **** **** **** **** **** **** **** +2083 Eldritch_Blast **** **** **** **** **** **** **** **** +2084 FIENDISH_RESILIENCE **** **** **** **** **** **** **** **** +2085 PouncingStrike **** **** **** **** **** **** **** **** +2086 SPELL_AP_DEATHKNELL **** **** **** **** **** **** **** **** +2087 SPELL_AP_CONTAGION **** **** **** **** **** **** **** **** +2088 SPELL_AP_SMITEGOOD **** **** **** **** **** **** **** **** +2089 SPELL_AP_AURAFEAR **** **** **** **** **** **** **** **** +2090 SPELL_INTUTIVATK **** **** **** **** **** **** **** **** +2091 Blacklight **** Will 1 I 1 **** **** **** +2092 DarkBolt **** **** **** **** **** **** **** **** +2093 DarkBolt_all **** **** **** **** **** **** **** **** +2094 DarkBolt_1 **** **** **** **** **** **** **** **** +2095 Darkness_Armor **** **** **** **** **** **** **** **** +2096 Greater_Wall_of_Dispel_Magic **** **** **** **** **** **** **** **** +2097 Nature_Avatar **** **** **** **** **** **** **** **** +2098 Unyielding_Roots **** **** **** H 0 **** **** **** +2099 Blessing_of_bahamut **** **** **** P 0 2 0 **** +2100 BloodClawShifting **** **** **** **** **** **** **** **** +2101 Adept_Fire_Breath **** **** **** **** **** **** **** **** +2102 Adept_Fire_Cone **** **** **** **** **** **** **** **** +2103 Adept_Fire_Line **** **** **** **** **** **** **** **** +2104 Adept_Frost_Cone **** **** **** **** **** **** **** **** +2105 Adept_Electric_Line **** **** **** **** **** **** **** **** +2106 Adept_Sickness_Cone **** **** **** **** **** **** **** **** +2107 Adept_Acid_Breath **** **** **** **** **** **** **** **** +2108 Adept_Acid_Cone **** **** **** **** **** **** **** **** +2109 Adept_Acid_Line **** **** **** **** **** **** **** **** +2110 Adept_Shaped_Breath **** **** **** **** **** **** **** **** +2111 Adept_Slow_Cone **** **** **** **** **** **** **** **** +2112 Adept_Weakening_Cone **** **** **** **** **** **** **** **** +2113 Adept_Cloud_Breath **** **** **** **** **** **** **** **** +2114 Adept_Enduring_Breath **** **** **** **** **** **** **** **** +2115 Adept_Sleep_Cone **** **** **** **** **** **** **** **** +2116 Adept_Thunder_Cone **** **** **** **** **** **** **** **** +2117 Adept_Bahamut_Line **** **** **** **** **** **** **** **** +2118 Adept_Force_Line **** **** **** **** **** **** **** **** +2119 Adept_Paralyzation_Cone **** **** **** **** **** **** **** **** +2120 Adept_Tiamat_Breath **** **** **** **** **** **** **** **** +2121 RKVDivineRecovery **** **** **** **** **** **** **** **** +2122 Mass_Contagion Disease Fortitude 1 I 1 **** **** **** +2123 SPELL_SACREDSPEED **** **** **** **** **** **** **** **** +2124 SPELL_INNERARMOR **** **** **** **** **** **** **** **** +2125 SPELL_SACREDFLAME **** **** **** **** **** **** **** **** +2126 SPELL_SHADOWSHIELD **** **** **** **** **** **** **** **** +2127 SPELL_SHADOWWALK **** **** **** **** **** **** **** **** +2128 SPELL_SHADOWDOUBLE **** **** **** **** **** **** **** **** +2129 SPELL_NS_INVISIBILITY **** **** **** **** **** **** **** **** +2130 SPELL_NS_WEB **** **** **** **** **** **** **** **** +2131 SPELL_NS_POISON **** **** **** **** **** **** **** **** +2132 SPELL_NS_SHADOWWALK **** **** **** **** **** **** **** **** +2133 SPELL_NS_POISONSPELL **** **** **** **** **** **** **** **** +2134 SPELL_UR_FAVORITE_ENEMY **** **** **** **** **** **** **** **** +2135 SPELL_DSL_SONG_STRENGTH **** **** **** **** **** **** **** **** +2136 SPELL_DSL_SONG_COMPULSION **** **** **** **** **** **** **** **** +2137 SPELL_DSL_SONG_SPEED **** **** **** **** **** **** **** **** +2138 SPELL_DSL_SONG_FEAR **** **** **** **** **** **** **** **** +2139 SPELL_DSL_SONG_HEALING **** **** **** **** **** **** **** **** +2140 SPELL_UR_HAWK_TOTEM **** **** **** **** **** **** **** **** +2141 SPELL_NS_LINGDMG **** **** **** **** **** **** **** **** +2142 SPELL_UR_ANIMALCOMPANION **** **** **** **** **** **** **** **** +2143 SPELL_UR_HIPS **** **** **** **** **** **** **** **** +2144 LuckyShot **** **** **** **** **** **** **** **** +2145 MINSTREL_SONG_CHARM **** **** **** **** **** **** **** **** +2146 RKVDivineImpteus **** **** **** **** **** **** **** **** +2147 MINSTREL_SONG_IMM_FEAR **** **** **** **** **** **** **** **** +2148 MINSTREL_SONG_SHIELD_AC **** **** **** **** **** **** **** **** +2149 MINSTREL_SONG_SONIC_WEAP **** **** **** **** **** **** **** **** +2150 MINSTREL_SONG_STRENGTH **** **** **** **** **** **** **** **** +2151 MINSTREL_SONG_CONSTITUTION **** **** **** **** **** **** **** **** +2152 MINSTREL_SONG_DEXTERITY **** **** **** **** **** **** **** **** +2153 MINSTREL_SONG_INTELLIGENCE **** **** **** **** **** **** **** **** +2154 MINSTREL_SONG_WISDOM **** **** **** **** **** **** **** **** +2155 MINSTREL_SONG_CHARISMA **** **** **** **** **** **** **** **** +2156 MINSTREL_SONG_WOUND_WHISP **** **** **** **** **** **** **** **** +2157 MINSTREL_SONG_SLEEP **** **** **** **** **** **** **** **** +2158 MINSTREL_SONG_SILENCE **** **** **** **** **** **** **** **** +2159 MINSTREL_SONG_HASTE **** **** **** **** **** **** **** **** +2160 MINSTREL_SONG_SLOW **** **** **** **** **** **** **** **** +2161 SPELL_BRAWLER_EXTRA_ATT **** **** **** **** **** **** **** **** +2162 SPELL_EPIC_DIVINE_VIGOR **** **** **** **** **** **** **** **** +2163 SPELL_INVOKE_DIVINE_WRATH **** **** **** **** **** **** **** **** +2164 SPELL_DIVINE_VIGOR **** **** **** **** **** **** **** **** +2165 SPELL_DIVINE_CLEANSING **** **** **** **** **** **** **** **** +2166 SPELL_DIVINE_RESISTANCE **** **** **** **** **** **** **** **** +2167 Consecrate **** **** **** **** **** **** **** **** +2168 BOLT_XAGYA **** **** **** **** **** **** **** **** +2169 SPELL_DISCIPLE_OF_SUN **** **** **** **** **** **** **** **** +2170 PowerAtk_Single_Radial_Master **** **** **** **** **** **** **** **** +2171 PowerAttack_0 **** **** **** **** **** **** **** **** +2172 PowerAttack_1 **** **** **** **** **** **** **** **** +2173 PowerAttack_2 **** **** **** **** **** **** **** **** +2174 PowerAttack_3 **** **** **** **** **** **** **** **** +2175 PowerAttack_4 **** **** **** **** **** **** **** **** +2176 PowerAtk_Fives_Radial **** **** **** **** **** **** **** **** +2177 PowerAttack_0 **** **** **** **** **** **** **** **** +2178 PowerAttack_5 **** **** **** **** **** **** **** **** +2179 PowerAttack_10 **** **** **** **** **** **** **** **** +2180 PowerAttack_15 **** **** **** **** **** **** **** **** +2181 PowerAttack_20 **** **** **** **** **** **** **** **** +2182 SPELL_FURIOUS_ASSAULT **** **** **** **** **** **** **** **** +2183 Summon_Energon **** **** **** **** **** **** **** **** +2184 SPELL_SMITE_UNDEAD **** **** **** **** **** **** **** **** +2185 SPELL_DIVINE_VENGEANCE **** **** **** **** **** **** **** **** +2186 SPELL_POSITIVE_ENERGY_BURST **** **** **** **** **** **** **** **** +2187 SPELL_FIST_OF_IRON **** **** **** **** **** **** **** **** +2188 RKVDivineFury **** **** **** **** **** **** **** **** +2189 Summon_Familiar **** **** **** **** **** **** **** **** +2190 RavageGoldenIce **** **** **** **** **** **** **** **** +2191 SPELL_STIGMATA **** **** **** **** **** **** **** **** +2192 SPELL_STIGMATA5 **** **** **** **** **** **** **** **** +2193 SPELL_STIGMATA2 **** **** **** **** **** **** **** **** +2194 SPELL_STIGMATA3 **** **** **** **** **** **** **** **** +2195 SPELL_STIGMATA4 **** **** **** **** **** **** **** **** +2196 SPELL_HOLYRADIANCE **** **** **** **** **** **** **** **** +2197 FEAT_ANIMALMASTERY **** **** **** **** **** **** **** **** +2198 IncreaseUnarmedEpic **** **** **** **** **** **** **** **** +2199 FEAT_ARCH_RANGEDDISARM **** **** **** **** **** **** **** **** +2200 FEAT_SONG_OF_FURY **** **** **** **** **** **** **** **** +2201 FEAT_EXTRASHOT **** **** **** **** **** **** **** **** +2202 FEAT_RANGEDTRIP **** **** **** **** **** **** **** **** +2203 Pinpoint_Accuracy **** **** **** **** **** **** **** **** +2204 Pinpoint_Accuracy2 **** **** **** **** **** **** **** **** +2205 Pinpoint_Accuracy4 **** **** **** **** **** **** **** **** +2206 Pinpoint_Accuracy6 **** **** **** **** **** **** **** **** +2207 Imp_ManyShot **** **** **** **** **** **** **** **** +2208 Imp_ManyShot5 **** **** **** **** **** **** **** **** +2209 Imp_ManyShot6 **** **** **** **** **** **** **** **** +2210 LIPS_RAPTUR **** **** **** **** **** **** **** **** +2211 TEARS_EVERGOLD **** **** **** **** **** **** **** **** +2212 Elemental_Conflag **** **** **** **** **** **** **** **** +2213 Elemental_FIRE **** **** **** **** **** **** **** **** +2214 Elemental_WATER **** **** **** **** **** **** **** **** +2215 Elemental_EARTH **** **** **** **** **** **** **** **** +2216 Elemental_AIR **** **** **** **** **** **** **** **** +2217 Smite_Evil_Raziel **** **** **** **** **** **** **** **** +2218 FEAT_MAGIC_CIRCLE_EVIL **** **** **** **** **** **** **** **** +2219 Inspire_allies **** **** **** **** **** **** **** **** +2220 TEMPUS_ENCHANT_WEAPON **** **** **** **** **** **** **** **** +2221 TEMPUS_IDENTIFY_ARMS **** **** **** **** **** **** **** **** +2222 Shadowlord_Jump **** **** **** **** **** **** **** **** +2223 Shadowlord_Blur **** **** **** **** **** **** **** **** +2224 DivineSpirit **** **** **** **** **** **** **** **** +2225 InstantClarity **** **** **** **** **** **** **** **** +2226 TrapEngineer **** **** **** **** **** **** **** **** +2227 ContagiousTouch Disease Fortitude 1 T 1 **** **** **** +2228 Blighter_Blightfire **** **** **** **** **** **** **** **** +2229 Blighter_AnimateDeadAnimal **** **** **** **** **** **** **** **** +2230 Blighter_Unbond **** **** **** **** **** **** **** **** +2231 Blighter_Plague **** **** **** **** **** **** **** **** +2232 Battlesmith_TemperedInBlood **** **** **** **** **** **** **** **** +2233 Battlesmith_Boosts **** **** **** **** **** **** **** **** +2234 PsyRogue_ShadowJump **** **** **** **** **** **** **** **** +2235 POLYMORPH_ELEM **** **** **** **** **** **** **** **** +2236 ClawDragon **** **** **** **** **** **** **** **** +2237 FrightfulPresence **** **** **** **** **** **** **** **** +2238 ShapeDragon **** **** **** **** **** **** **** **** +2239 ShapeDragonGold **** **** **** **** **** **** **** **** +2240 ShapeDragonRed **** **** **** **** **** **** **** **** +2241 ShapeDragonPrysmatic **** **** **** **** **** **** **** **** +2242 Dragon_Breath_Fire **** **** **** **** **** **** **** **** +2243 Dragon_Breath_Gas **** **** **** **** **** **** **** **** +2244 Dragon_Breath_Prismatic **** **** **** **** **** **** **** **** +2245 ManyShot **** **** **** **** **** **** **** **** +2246 ManyShot2 **** **** **** **** **** **** **** **** +2247 Magic_Missile **** **** 1 R 1 **** **** **** +2248 ManyShot4 **** **** **** **** **** **** **** **** +2249 ManyShot6 **** **** **** **** **** **** **** **** +2250 Examine_Recipe **** **** **** **** **** **** **** **** +2251 Read **** **** **** **** **** **** **** **** +2252 Item_Creation **** **** **** **** **** **** **** **** +2253 Craft_Item **** **** **** **** **** **** **** **** +2254 Examine_Recipe **** **** **** **** **** **** **** **** +2255 NEW_CRAFTING **** **** **** **** **** **** **** **** +2256 Spelldance_Confuse **** **** **** **** **** **** **** **** +2257 Spelldance **** **** **** **** **** **** **** **** +2258 IncreaseUnarmedShape **** **** **** **** **** **** **** **** +2259 SPELL_AP_TURNOUTS **** **** **** **** **** **** **** **** +2260 Riddle_of_Awareness **** **** **** **** **** **** **** **** +2261 Happo_Zanshin **** **** **** **** **** **** **** **** +2262 Riddle_of_Interaction **** **** **** **** **** **** **** **** +2263 Blind_Sight **** **** **** **** **** **** **** **** +2264 Hitsu_Do **** **** **** **** **** **** **** **** +2265 Walk_Through_the_Mountains **** **** **** **** **** **** **** **** +2266 Riddle_of_Invulnerability **** **** **** **** **** **** **** **** +2267 Spelldance_Max **** **** **** **** **** **** **** **** +2268 Bottle_Proficiency **** **** **** **** **** **** **** **** +2269 Stagger **** **** **** **** **** **** **** **** +2270 Swaying_Waist **** **** **** **** **** **** **** **** +2271 Spelldance_Emp **** **** **** **** **** **** **** **** +2272 Lurch **** **** **** **** **** **** **** **** +2273 Drunken_Embrace **** **** **** **** **** **** **** **** +2274 For_Medicinal_Purposes **** **** **** **** **** **** **** **** +2275 Breath_of_Flame **** **** **** **** **** **** **** **** +2276 Spelldance_Ext **** **** **** **** **** **** **** **** +2277 ACP_Fighting_Stance_change **** **** **** **** **** **** **** **** +2278 ACP_Fighting_Stance_KENSAI **** **** **** **** **** **** **** **** +2279 ACP_Fighting_Stance_ASSASSIN **** **** **** **** **** **** **** **** +2280 ACP_Fighting_Stance_HEAVY **** **** **** **** **** **** **** **** +2281 ACP_Fighting_Stance_FENCING **** **** **** **** **** **** **** **** +2282 ACP_Fighting_Stance_NORMAL **** **** **** **** **** **** **** **** +2283 Undead_Wild_Shape_Master **** **** **** **** **** **** **** **** +2284 Undead_Wild_Shape_BROWN_BEAR **** **** **** **** **** **** **** **** +2285 Undead_Wild_Shape_PANTHER **** **** **** **** **** **** **** **** +2286 Undead_Wild_Shape_WOLF **** **** **** **** **** **** **** **** +2287 Undead_Wild_Shape_BOAR **** **** **** **** **** **** **** **** +2288 Undead_Wild_Shape_BADGER **** **** **** **** **** **** **** **** +2289 Ashrati_Bodylamp **** **** **** **** **** **** **** **** +2290 RAY_CHARM_PERSON **** **** **** **** **** **** **** **** +2291 RAY_CHARM_MONSTER **** **** **** **** **** **** **** **** +2292 RAY_SLEEP **** **** **** **** **** **** **** **** +2293 RAY_FLESH_TO_STONE **** **** **** **** **** **** **** **** +2294 RAY_DISINTIGRATE **** **** **** **** **** **** **** **** +2295 RAY_FEAR **** **** **** **** **** **** **** **** +2296 RAY_SLOW **** **** **** **** **** **** **** **** +2297 RAY_INFLICT_MODERATE_WOUNDS **** **** **** **** **** **** **** **** +2298 RAY_FINGER_OF_DEATH **** **** **** **** **** **** **** **** +2299 PsyRogue_BlindSpot **** **** **** **** **** **** **** **** +2300 SPELL_FOM_DIVINE_SONG_BLESS **** **** **** **** **** **** **** **** +2301 SPELL_FOM_DIVINE_SONG_CONVICTION **** **** **** **** **** **** **** **** +2302 SPELL_FOM_DIVINE_SONG_CURELIGHT **** **** **** **** **** **** **** **** +2303 SPELL_FOM_DIVINE_SONG_REMOVEFEAR **** **** **** **** **** **** **** **** +2304 SPELL_FOM_DIVINE_SONG_SANCTUARY **** **** **** **** **** **** **** **** +2305 SPELL_FOM_DIVINE_SONG_SHIELDFAITH **** **** **** **** **** **** **** **** +2306 SPELL_FOM_DIVINE_SONG_AID **** **** **** **** **** **** **** **** +2307 SPELL_FOM_DIVINE_SONG_BULLSTRENGTH **** **** **** **** **** **** **** **** +2308 SPELL_FOM_DIVINE_SONG_CUREMODERATE **** **** **** **** **** **** **** **** +2309 SPELL_FOM_DIVINE_SONG_EAGLESPLENDOR **** **** **** **** **** **** **** **** +2310 SPELL_FOM_DIVINE_SONG_ENDURANCE **** **** **** **** **** **** **** **** +2311 SPELL_FOM_DIVINE_SONG_FOXCUNNING **** **** **** **** **** **** **** **** +2312 SPELL_FOM_DIVINE_SONG_LESSRESTORE **** **** **** **** **** **** **** **** +2313 SPELL_FOM_DIVINE_SONG_OWLWISDOM **** **** **** **** **** **** **** **** +2314 SPELL_FOM_DIVINE_SONG_CLAIRVOYANCE **** **** **** **** **** **** **** **** +2315 SPELL_FOM_DIVINE_SONG_CLARITY **** **** **** **** **** **** **** **** +2316 SPELL_FOM_DIVINE_SONG_CURESERIOUS **** **** **** **** **** **** **** **** +2317 SPELL_FOM_DIVINE_SONG_NEGATIVEPROT **** **** **** **** **** **** **** **** +2318 SPELL_FOM_DIVINE_SONG_PRAYER **** **** **** **** **** **** **** **** +2319 SPELL_FOM_DIVINE_SONG_PROTELEMENTS **** **** **** **** **** **** **** **** +2320 SPELL_FOM_DIVINE_SONG_REMOVECURSE **** **** **** **** **** **** **** **** +2321 SPELL_FOM_DIVINE_SONG_CURECRITICAL **** **** **** **** **** **** **** **** +2322 SPELL_FOM_DIVINE_SONG_DEATHWARD **** **** **** **** **** **** **** **** +2323 SPELL_FOM_DIVINE_SONG_FREEDOMMOVEMENT **** **** **** **** **** **** **** **** +2324 SPELL_FOM_DIVINE_SONG_PANACEA **** **** **** **** **** **** **** **** +2325 SPELL_FOM_DIVINE_SONG_RESTORATION **** **** **** **** **** **** **** **** +2326 SPELL_FOM_DIVINE_SONG_STONESKIN **** **** **** **** **** **** **** **** +2327 SPELL_FOM_DIVINE_SONG_TRUESEEING **** **** **** **** **** **** **** **** +2328 SPELL_FOM_DIVINE_SONG_MONSTREGEN **** **** **** **** **** **** **** **** +2329 SPELL_FOM_DIVINE_SONG_RAISEDEAD **** **** **** **** **** **** **** **** +2330 SPELL_FOM_DIVINE_SONG_SPELLRESISTANCE **** **** **** **** **** **** **** **** +2331 SPELL_FOM_ENCOREPERFORMANCE **** **** **** **** **** **** **** **** +2332 Ashrati_BodylampDazzle **** **** **** **** **** **** **** **** +2333 Killoren_Aspect_A **** **** **** **** **** **** **** **** +2334 Killoren_Aspect_D **** **** **** **** **** **** **** **** +2335 Killoren_Aspect_H **** **** **** **** **** **** **** **** +2336 Killoren_Hunter **** **** **** **** **** **** **** **** +2337 Skarn_Spines **** **** **** **** **** **** **** **** +2338 ScorpionsGrasp **** **** **** **** **** **** **** **** +2339 CultistShatteredPeak_SmiteMage **** **** **** **** **** **** **** **** +2340 AwesomeBlow **** **** **** **** **** **** **** **** +2341 BloodedOne_War_Cry **** **** **** **** **** **** **** **** +2342 Desecrate **** **** **** **** **** **** **** **** +2343 BlastOfForce **** Fortitude 1 R 1 **** **** **** +2344 ShieldBash **** **** **** **** **** **** **** **** +2345 ShieldCharge **** **** **** **** **** **** **** **** +2346 ShieldSlam **** **** **** **** **** **** **** **** +2347 PhantomSteed **** **** **** **** **** **** **** **** +2348 GaseousForm **** **** **** **** **** **** **** **** +2349 begin_psionics **** **** **** **** **** **** **** **** +2350 Augment_QuickSelects **** **** **** **** **** **** **** **** +2351 Augment_Digits_0_4 **** **** **** **** **** **** **** **** +2352 Augment_Digits_5_9 **** **** **** **** **** **** **** **** +2353 Augment_Tens **** **** **** **** **** **** **** **** +2354 Augment_StartConvo **** **** **** **** **** **** **** **** +2355 Augment_Off **** **** **** **** **** **** **** **** +2356 Augment_ToggleMaxAugment **** **** **** **** **** **** **** **** +2357 Augment_Quickselect1 **** **** **** **** **** **** **** **** +2358 Augment_Quickselect2 **** **** **** **** **** **** **** **** +2359 Augment_0 **** **** **** **** **** **** **** **** +2360 Augment_1 **** **** **** **** **** **** **** **** +2361 Augment_2 **** **** **** **** **** **** **** **** +2362 Augment_3 **** **** **** **** **** **** **** **** +2363 Augment_4 **** **** **** **** **** **** **** **** +2364 Augment_5 **** **** **** **** **** **** **** **** +2365 Augment_6 **** **** **** **** **** **** **** **** +2366 Augment_7 **** **** **** **** **** **** **** **** +2367 Augment_8 **** **** **** **** **** **** **** **** +2368 Augment_9 **** **** **** **** **** **** **** **** +2369 Augment_00 **** **** **** **** **** **** **** **** +2370 Augment_10 **** **** **** **** **** **** **** **** +2371 Augment_20 **** **** **** **** **** **** **** **** +2372 Augment_30 **** **** **** **** **** **** **** **** +2373 Augment_40 **** **** **** **** **** **** **** **** +2374 Augment_QuickSelects_2 **** **** **** **** **** **** **** **** +2375 **** **** **** **** **** **** **** **** **** +2376 **** **** **** **** **** **** **** **** **** +2377 Wilder_WildSurge_Off **** **** **** **** **** **** **** **** +2378 Wilder_WildSurge_1-5_RadialMaster **** **** **** **** **** **** **** **** +2379 Wilder_WildSurge_6-10_RadialMaster **** **** **** **** **** **** **** **** +2380 Wilder_WildSurge_1 **** **** **** **** **** **** **** **** +2381 Wilder_WildSurge_2 **** **** **** **** **** **** **** **** +2382 Wilder_WildSurge_3 **** **** **** **** **** **** **** **** +2383 Wilder_WildSurge_4 **** **** **** **** **** **** **** **** +2384 Wilder_WildSurge_5 **** **** **** **** **** **** **** **** +2385 Wilder_WildSurge_6 **** **** **** **** **** **** **** **** +2386 Wilder_WildSurge_7 **** **** **** **** **** **** **** **** +2387 Wilder_WildSurge_8 **** **** **** **** **** **** **** **** +2388 Wilder_WildSurge_9 **** **** **** **** **** **** **** **** +2389 Wilder_WildSurge_10 **** **** **** **** **** **** **** **** +2390 Wilder_WildSurge_11 **** **** **** **** **** **** **** **** +2391 **** **** **** **** **** **** **** **** **** +2392 Augment_Quickselect3 **** **** **** **** **** **** **** **** +2393 Augment_Quickselect4 **** **** **** **** **** **** **** **** +2394 Augment_Quickselect5 **** **** **** **** **** **** **** **** +2395 Augment_Quickselect6 **** **** **** **** **** **** **** **** +2396 Augment_Quickselect7 **** **** **** **** **** **** **** **** +2397 **** **** **** **** **** **** **** **** **** +2398 Manifest_Shield_of_Thought **** **** **** **** **** **** **** **** +2399 Spiritual_Force **** **** **** **** **** **** **** **** +2400 Manifest_Mindblade **** **** **** **** **** **** **** **** +2401 Throw_Mindblade **** **** **** **** **** **** **** **** +2402 Psychic_Strike **** **** **** **** **** **** **** **** +2403 Free_Draw **** **** **** **** **** **** **** **** +2404 Shape_Mindblade_RadialMaster **** **** **** **** **** **** **** **** +2405 Shape_Mindblade_Shortsword **** **** **** **** **** **** **** **** +2406 Shape_Mindblade_2xShortsword **** **** **** **** **** **** **** **** +2407 Shape_Mindblade_Longsword **** **** **** **** **** **** **** **** +2408 Shape_Mindblade_Bastardsword **** **** **** **** **** **** **** **** +2409 Mindblade_Enhancement **** **** **** **** **** **** **** **** +2410 Bladewind **** **** **** **** **** **** **** **** +2411 KnifeToTheSoul_RadialMaster **** **** **** **** **** **** **** **** +2412 KnifeToTheSoul_Off **** **** **** **** **** **** **** **** +2413 KnifeToTheSoul_Intelligence **** **** **** **** **** **** **** **** +2414 KnifeToTheSoul_Wisdom **** **** **** **** **** **** **** **** +2415 KnifeToTheSoul_Charisma **** **** **** **** **** **** **** **** +2416 KnifeToTheSoul_DieRadial1_Radialmaster **** **** **** **** **** **** **** **** +2417 KnifeToTheSoul_1Die **** **** **** **** **** **** **** **** +2418 KnifeToTheSoul_2Die **** **** **** **** **** **** **** **** +2419 KnifeToTheSoul_3Die **** **** **** **** **** **** **** **** +2420 KnifeToTheSoul_4Die **** **** **** **** **** **** **** **** +2421 KnifeToTheSoul_5Die **** **** **** **** **** **** **** **** +2422 KnifeToTheSoul_DieRadial2_Radialmaster **** **** **** **** **** **** **** **** +2423 KnifeToTheSoul_6Die **** **** **** **** **** **** **** **** +2424 KnifeToTheSoul_7Die **** **** **** **** **** **** **** **** +2425 KnifeToTheSoul_8Die **** **** **** **** **** **** **** **** +2426 KnifeToTheSoul_9Die **** **** **** **** **** **** **** **** +2427 KnifeToTheSoul_10Die **** **** **** **** **** **** **** **** +2428 ChangeHandedness **** **** **** **** **** **** **** **** +2429 Mindblade_Lucky **** **** **** **** **** **** **** **** +2430 Healing_Kicker_1_Sanctuary **** **** **** **** **** **** **** **** +2431 Healing_Kicker_2_ReflexSaves **** **** **** **** **** **** **** **** +2432 Healing_Kicker_3_Aid **** **** **** **** **** **** **** **** +2433 Spontaneous_Heal **** **** **** **** **** **** **** **** +2434 StrengthOfTwo **** **** **** **** **** **** **** **** +2435 OotBI_RangedPrecision **** **** **** **** **** **** **** **** +2436 OotBI_GreaterWeaponFocus **** **** **** **** **** **** **** **** +2437 Thrallherd_Master **** **** **** **** **** **** **** **** +2438 Thrallherd_Fighter **** **** **** **** **** **** **** **** +2439 Thrallherd_Cleric **** **** **** **** **** **** **** **** +2440 Thrallherd_Rogue **** **** **** **** **** **** **** **** +2441 Thrallherd_Wizard **** **** **** **** **** **** **** **** +2442 PsionicCharm **** **** **** **** **** **** **** **** +2443 PsionicDominate **** **** **** **** **** **** **** **** +2444 Twofold_Master **** **** **** **** **** **** **** **** +2445 Twofold_Fighter **** **** **** **** **** **** **** **** +2446 Twofold_Cleric **** **** **** **** **** **** **** **** +2447 Twofold_Rogue **** **** **** **** **** **** **** **** +2448 Twofold_Wizard **** **** **** **** **** **** **** **** +2449 **** **** **** **** **** **** **** **** **** +2450 Warmind_PersSuperior **** **** **** **** **** **** **** **** +2451 Warmind_DefPosture **** **** **** **** **** **** **** **** +2452 Warmind_OverwhelmForce **** **** **** **** **** **** **** **** +2453 **** **** **** **** **** **** **** **** **** +2454 ShadowmindDistract **** **** **** **** **** **** **** **** +2455 ShadowmindCloudMind **** **** **** **** **** **** **** **** +2456 ShadowmindCloudMindMass **** **** **** **** **** **** **** **** +2457 ShadowmindMindStab **** **** **** **** **** **** **** **** +2458 **** **** **** **** **** **** **** **** **** +2459 DiamondDragon_Claws **** **** **** **** **** **** **** **** +2460 DiamondDragon_Breath **** **** **** **** **** **** **** **** +2461 DiamondDragon_Wings **** **** **** **** **** **** **** **** +2462 DiamondDragon_Tail **** **** **** **** **** **** **** **** +2463 DiamondDragon_Aura **** **** **** **** **** **** **** **** +2464 DiamondDragon_Breath_Cold **** **** **** **** **** **** **** **** +2465 DiamondDragon_Breath_Electric **** **** **** **** **** **** **** **** +2466 DiamondDragon_Breath_Fire **** **** **** **** **** **** **** **** +2467 DiamondDragon_Breath_Sonic **** **** **** **** **** **** **** **** +2468 Psionic_Paralysis_Sleep_Immunity **** **** **** **** **** **** **** **** +2469 **** **** **** **** **** **** **** **** **** +2470 FistOfDalQuor_StunningStrike **** **** **** **** **** **** **** **** +2471 **** **** **** **** **** **** **** **** **** +2472 ForestMaster_ForestDominion **** **** **** **** **** **** **** **** +2473 ForestMaster_GreatMalletRadialMaster **** **** **** **** **** **** **** **** +2474 ForestMaster_IcyMallet **** **** **** **** **** **** **** **** +2475 ForestMaster_ShockMallet **** **** **** **** **** **** **** **** +2476 ForestMaster_DeepRoots **** **** **** **** **** **** **** **** +2477 **** **** **** **** **** **** **** **** **** +2478 **** **** **** **** **** **** **** **** **** +2479 SPELL_CHASING_PERFECTION **** **** **** **** **** **** **** **** +2480 SPELL_FORCE_MISSILES **** **** 1 R 1 **** **** **** +2481 SYMBOL_OF_DEATH **** **** **** **** **** **** **** **** +2482 SYMBOL_OF_FEAR **** **** **** **** **** **** **** **** +2483 SYMBOL_OF_STUNING **** **** **** **** **** **** **** **** +2484 SYMBOL_OF_INSANITY **** **** **** **** **** **** **** **** +2485 SYMBOL_OF_PAIN **** **** **** **** **** **** **** **** +2486 SYMBOL_OF_PERSUASION **** **** **** **** **** **** **** **** +2487 SYMBOL_OF_SLEEP **** **** **** **** **** **** **** **** +2488 SYMBOL_OF_WEAKNESS **** **** **** **** **** **** **** **** +2489 ENERGIZE_POTION_ACID **** **** **** **** **** **** **** **** +2490 ENERGIZE_POTION_COLD **** **** **** **** **** **** **** **** +2491 ENERGIZE_POTION_ELECTRICITY **** **** **** **** **** **** **** **** +2492 ENERGIZE_POTION_FIRE **** **** **** **** **** **** **** **** +2493 ENERGIZE_POTION_SONIC **** **** **** **** **** **** **** **** +2494 SPELL_DIVINE_SACRIFICE_2 **** **** **** **** **** **** **** **** +2495 SPELL_DIVINE_SACRIFICE_4 **** **** **** **** **** **** **** **** +2496 SPELL_DIVINE_SACRIFICE_6 **** **** **** **** **** **** **** **** +2497 SPELL_DIVINE_SACRIFICE_8 **** **** **** **** **** **** **** **** +2498 SPELL_DIVINE_SACRIFICE_10 **** **** **** **** **** **** **** **** +2499 Command_Undead **** **** **** **** **** **** **** **** +2500 SPELL_PRC_EXTRA_STUNNING **** **** **** **** **** **** **** **** +2501 SPELL_EF_FIST_OF_ENERGY **** **** **** **** **** **** **** **** +2502 SPELL_EF_FIST_OF_ENERGY_FIRE **** **** **** **** **** **** **** **** +2503 SPELL_EF_FIST_OF_ENERGY_ELECTRICITY **** **** **** **** **** **** **** **** +2504 SPELL_EF_SPELL_SELECT **** **** **** **** **** **** **** **** +2505 SPELL_EF_SPELL_SELECT_CONVO **** **** **** **** **** **** **** **** +2506 SPELL_EF_SPELL_SELECT_QUICK1 **** **** **** **** **** **** **** **** +2507 SPELL_EF_SPELL_SELECT_QUICK2 **** **** **** **** **** **** **** **** +2508 SPELL_EF_SPELL_SELECT_QUICK3 **** **** **** **** **** **** **** **** +2509 SPELL_EF_SPELL_SELECT_QUICK4 **** **** **** **** **** **** **** **** +2510 SPELL_EF_ARCANE_FIST **** **** **** **** **** **** **** **** +2511 SPELL_EF_ARCANE_REJUVENATION **** **** **** **** **** **** **** **** +2512 ABERRATE **** **** **** **** **** **** **** **** +2513 ABSORB_STRENGTH **** **** **** **** **** **** **** **** +2514 ABYSSAL_MIGHT **** **** **** E 0 3 0 **** +2515 ANGRY_ACHE **** Fortitude 1 R 1 **** **** **** +2516 APOCALYPSE_FROM_THE_SKY **** **** **** **** **** **** **** **** +2517 APOCALYPSE_FROM_THE_SKY_FIRE **** **** **** **** **** **** **** **** +2518 APOCALYPSE_FROM_THE_SKY_ACID **** **** **** **** **** **** **** **** +2519 APOCALYPSE_FROM_THE_SKY_SONIC **** **** **** **** **** **** **** **** +2520 BESTOW_WOUND **** Fortitude 1 T 1 **** **** **** +2521 BODAK_BIRTH **** **** **** **** **** **** **** **** +2522 BONEBLADE **** **** **** **** **** **** **** **** +2523 BONEBLADE_GREATSWORD **** **** **** **** **** **** **** **** +2524 BONEBLADE_LONGSWORD **** **** **** **** **** **** **** **** +2525 BONEBLADE_SHORTSWORD **** **** **** **** **** **** **** **** +2526 BONEBLAST **** Fortitude 1 T 1 **** **** **** +2527 CALL_DRETCH_HORDE **** **** **** **** **** **** **** **** +2528 CALL_LEMURE_HORDE **** **** **** **** **** **** **** **** +2529 CLAWS_OF_THE_BEBILITH **** **** **** **** **** **** **** **** +2530 CLAWS_OF_THE_SAVAGE **** **** **** **** **** **** **** **** +2531 CLOUD_OF_THE_ACHAIERAI **** Fortitude 1 I 1 **** **** **** +2532 CLUTCH_OF_ORCUS **** **** **** **** **** **** **** **** +2533 CRUSHING_FIST_OF_SPITE **** Reflex 1 I 1 **** **** **** +2534 CURSE_OF_THE_PUTRID_HUSK Fear Will 1 R 1 **** **** **** +2535 DAMNING_DARKNESS **** **** **** I 1 **** **** **** +2536 DEATH_BY_THORNS **** **** **** **** **** **** **** **** +2537 DEMONCALL **** **** **** **** **** **** **** **** +2538 DEMONFLESH **** **** **** **** **** **** **** **** +2539 DESPOIL **** **** **** **** **** **** **** **** +2540 DEVILS_EGO **** **** **** **** **** **** **** **** +2541 DEVILS_EYE **** **** **** **** **** **** **** **** +2542 DEVILS_TAIL **** **** **** **** **** **** **** **** +2543 DREAD_WORD **** **** **** **** **** **** **** **** +2544 DRUG_RESISTANCE **** **** **** **** **** **** **** **** +2545 ECTOPLASMIC_ENCHANCEMENT **** **** **** **** **** **** **** **** +2546 ETERNITY_OF_TORTURE **** **** **** **** **** **** **** **** +2547 EVIL_EYE **** Will 1 R 1 **** **** **** +2548 EYE_OF_THE_BEHOLDER **** **** **** **** **** **** **** **** +2549 EVIL_WEATHER **** **** **** **** **** **** **** **** +2550 EVIL_WEATHER_RAIN_OF_BLOOD **** **** **** **** **** **** **** **** +2551 EVIL_WEATHER_VIOLET_RAIN **** **** **** **** **** **** **** **** +2552 EVIL_WEATHER_GREEN_FOG **** **** **** **** **** **** **** **** +2553 EVIL_WEATHER_RAIN_OF_FISH **** **** **** **** **** **** **** **** +2554 EXTRACT_DRUG **** **** **** **** **** **** **** **** +2555 EXTRACT_BACCARAN **** **** **** **** **** **** **** **** +2556 EXTRACT_VODARE **** **** **** **** **** **** **** **** +2557 EXTRACT_SANNISH **** **** **** **** **** **** **** **** +2558 EXTRACT_MUSHROOM_POWDER **** **** **** **** **** **** **** **** +2559 FANGS_OF_THE_VAMPIRE_KING **** **** **** **** **** **** **** **** +2560 FIENDISH_CLARITY **** **** **** E 0 3 0 **** +2561 FLESH_ARMOR **** **** **** **** **** **** **** **** +2562 FLESH_RIPPER **** **** 1 R 1 **** **** **** +2563 GRIM_REVENGE **** Fortitude 1 R 1 **** **** **** +2564 GUTWRENCH Death Fortitude 1 R 1 **** **** **** +2565 HEARTACHE Mind_Affecting Will 1 R 1 **** **** **** +2566 HEARTCLUTCH **** Fortitude 1 R 1 **** **** **** +2567 HELLFIRE **** **** **** **** **** **** **** **** +2568 HELLFIRE_STORM **** **** **** **** **** **** **** **** +2569 HELLS_POWER **** **** **** **** **** **** **** **** +2570 LAHMS_FINGER_DARTS **** **** **** **** **** **** **** **** +2571 LIQUID_PAIN **** **** **** **** **** **** **** **** +2572 MORALITY_UNDONE **** **** **** **** **** **** **** **** +2573 POWER_LEECH **** **** **** **** **** **** **** **** +2574 RAPTURE_OF_RUPTURE **** **** **** **** **** **** **** **** +2575 REALITY_BLIND Mind_Affecting Will 1 R 1 **** **** **** +2576 RED_FESTER **** **** **** **** **** **** **** **** +2577 RESONATING_RESISTANCE **** **** **** **** **** **** **** **** +2578 ROTTING_CURSE_OF_URFESTRA **** **** **** **** **** **** **** **** +2579 SEETHING_EYEBANE **** **** **** **** **** **** **** **** +2580 SHRIVELING Negative Reflex 1 R 1 **** **** **** +2581 SONG_OF_FESTERING_DEATH **** Fortitude 1 R 1 **** **** **** +2582 SORROW Mind_Affecting Will 1 R 1 **** **** **** +2583 EXALTED_RAIMENT **** **** **** **** **** **** **** **** +2584 SPORES_OF_THE_VROCK **** Fortitude 1 I 1 **** **** **** +2585 STUNNING_SCREECH **** Fortitude 1 I 1 **** **** **** +2586 STOP_HEART **** Fortitude 1 R 1 **** **** **** +2587 THOUSAND_NEEDLES **** Fortitude 1 R 1 **** **** **** +2588 TONGUE_OF_BAALZEBUL **** **** **** **** **** **** **** **** +2589 TOUCH_OF_JUIBLEX **** **** **** **** **** **** **** **** +2590 UNHEAVENED **** **** **** P 0 3 14 **** +2591 UNLIVING_WEAPON **** **** **** **** **** **** **** **** +2592 UTTERDARK **** **** **** I 1 **** **** **** +2593 WAVE_OF_GRIEF Mind_Affecting Will 1 I 1 **** **** **** +2594 WAVE_OF_PAIN **** Fortitude 1 I 1 **** **** **** +2595 WRACK **** Fortitude 1 I 1 **** **** **** +2596 WRETCHED_BLIGHT **** **** **** **** **** **** **** **** +2597 AGONY **** **** **** **** **** **** **** **** +2598 BACCARAN **** **** **** **** **** **** **** **** +2599 DEVILWEED **** **** **** **** **** **** **** **** +2600 LUHIX **** **** **** **** **** **** **** **** +2601 MUSHROOM_POWDER **** **** **** **** **** **** **** **** +2602 SANNISH **** **** **** **** **** **** **** **** +2603 TERRAN_BRANDY **** **** **** **** **** **** **** **** +2604 VODARE **** **** **** **** **** **** **** **** +2605 LESSER_SHIVERING_TOUCH **** **** 1 R 1 **** **** **** +2606 SHIVERING_TOUCH **** **** 1 R 1 **** **** **** +2607 AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +2608 BRILLIANT_EMANATION **** **** **** **** **** **** **** **** +2609 DIVINE_INSPIRATION **** **** **** **** **** **** **** **** +2610 DIAMOND_SPRAY **** **** **** **** **** **** **** **** +2611 DRAGON_CLOUD **** **** **** **** **** **** **** **** +2612 EXALTED_FURY **** **** **** **** **** **** **** **** +2613 HAMMER_OF_RIGHTEOUSNESS **** **** **** **** **** **** **** **** +2614 PHIERANS_RESOLVE **** **** **** **** **** **** **** **** +2615 PHOENIX_FIRE **** **** **** **** **** **** **** **** +2616 RAIN_OF_EMBERS **** **** **** **** **** **** **** **** +2617 SICKEN_EVIL **** **** **** **** **** **** **** **** +2618 STORM_OF_SHARDS **** **** **** **** **** **** **** **** +2619 SUNMANTLE **** **** **** **** **** **** **** **** +2620 TWILIGHT_LUCK **** **** **** **** **** **** **** **** +2621 AMBER_SARCOPHAGUS **** **** 1 R 1 **** **** **** +2622 BLINDING_GLORY **** **** **** I 1 **** **** **** +2623 BOLT_OF_GLORY **** **** **** **** **** **** **** **** +2624 CALL_FAITHFUL_SERVANTS **** **** **** S 0 2 0 **** +2625 CELESTIAL_BLOOD **** **** **** P 0 2 7 **** +2626 CHAAVS_LAUGH **** Will 1 D 1 **** **** **** +2627 CONVERT_WAND **** **** **** **** **** **** **** **** +2628 DANCING_WEB **** Reflex 1 I 1 **** **** **** +2629 DIVINE_SACRIFICE **** **** **** **** **** **** **** **** +2630 ELATION **** **** **** E 0 2 0 **** +2631 ENERGIZE_POTION **** **** **** **** **** **** **** **** +2632 EYES_OF_THE_AVORAL **** **** **** E 0 3 5 **** +2633 VisionOfGlory **** **** **** **** **** **** **** **** +2634 LANTERN_LIGHT **** **** 1 R 1 **** **** **** +2635 LAST_JUDGEMENT **** **** **** **** **** **** **** **** +2636 LUMINOUS_ARMOR **** **** **** P 0 3 8 -3 +2637 GREATER_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +2638 RAIN_OF_BLACK_TULIPS **** **** **** **** **** **** **** **** +2639 RAIN_OF_ROSES **** **** **** **** **** **** **** **** +2640 RAY_OF_HOPE **** **** **** E 0 2 9 **** +2641 RIGHTEOUS_SMITE **** Will 1 I 1 **** **** **** +2642 STARMANTLE **** **** **** P 0 2 7 **** +2643 TOMB_OF_LIGHT **** **** **** **** **** **** **** **** +2644 MASOCHISM **** **** **** E 0 2 0 **** +2645 ADDICTION **** **** **** **** **** **** **** **** +2646 ADDICTION_TERRAN_BRANDY **** **** **** **** **** **** **** **** +2647 ADDICTION_MUSHROOM_POWDER **** **** **** **** **** **** **** **** +2648 ADDICTION_VODARE **** **** **** **** **** **** **** **** +2649 ADDICTION_AGONY **** **** **** **** **** **** **** **** +2650 **StartDomainReserver** **** **** **** **** **** **** **** **** +2651 Sun_Domain_Power **** **** **** **** **** **** **** **** +2652 **** **** **** **** **** **** **** **** **** +2653 **** **** **** **** **** **** **** **** **** +2654 **** **** **** **** **** **** **** **** **** +2655 **** **** **** **** **** **** **** **** **** +2656 **** **** **** **** **** **** **** **** **** +2657 **** **** **** **** **** **** **** **** **** +2658 **** **** **** **** **** **** **** **** **** +2659 **** **** **** **** **** **** **** **** **** +2660 **** **** **** **** **** **** **** **** **** +2661 **** **** **** **** **** **** **** **** **** +2662 **** **** **** **** **** **** **** **** **** +2663 **** **** **** **** **** **** **** **** **** +2664 **** **** **** **** **** **** **** **** **** +2665 **** **** **** **** **** **** **** **** **** +2666 **** **** **** **** **** **** **** **** **** +2667 **** **** **** **** **** **** **** **** **** +2668 **** **** **** **** **** **** **** **** **** +2669 **** **** **** **** **** **** **** **** **** +2670 **** **** **** **** **** **** **** **** **** +2671 **** **** **** **** **** **** **** **** **** +2672 **** **** **** **** **** **** **** **** **** +2673 **** **** **** **** **** **** **** **** **** +2674 **** **** **** **** **** **** **** **** **** +2675 **** **** **** **** **** **** **** **** **** +2676 **** **** **** **** **** **** **** **** **** +2677 **** **** **** **** **** **** **** **** **** +2678 **** **** **** **** **** **** **** **** **** +2679 **** **** **** **** **** **** **** **** **** +2680 **** **** **** **** **** **** **** **** **** +2681 **** **** **** **** **** **** **** **** **** +2682 **** **** **** **** **** **** **** **** **** +2683 **** **** **** **** **** **** **** **** **** +2684 **** **** **** **** **** **** **** **** **** +2685 **** **** **** **** **** **** **** **** **** +2686 **** **** **** **** **** **** **** **** **** +2687 **** **** **** **** **** **** **** **** **** +2688 **** **** **** **** **** **** **** **** **** +2689 **** **** **** **** **** **** **** **** **** +2690 **EndDomainReserver** **** **** **** **** **** **** **** **** +2691 end_psionics **** **** **** **** **** **** **** **** +2692 BATTLE_RAGE **** **** **** **** **** **** **** **** +2693 Teleport_Management_Radial_Master **** **** **** **** **** **** **** **** +2694 Teleport_Mark_Location **** **** **** **** **** **** **** **** +2695 Teleport_Options_Dialog **** **** **** **** **** **** **** **** +2696 Teleport_End_Quickselect **** **** **** **** **** **** **** **** +2697 Teleport_Quickselect_1 **** **** **** **** **** **** **** **** +2698 Teleport_Quickselect_2 **** **** **** **** **** **** **** **** +2699 PnP_Scry_Familiar **** **** **** **** **** **** **** **** +2700 FRENZY **** **** **** **** **** **** **** **** +2701 INSPIRE_FRENZY **** **** **** **** **** **** **** **** +2702 (*Deprecated*)SUPREME_POWER_ATTACK **** **** **** **** **** **** **** **** +2703 REMOVE_FRENZY **** **** **** **** **** **** **** **** +2704 PnP_Familiar **** **** **** **** **** **** **** **** +2705 Frostrager_OneTwoPunch **** **** **** **** **** **** **** **** +2706 RANCOR **** **** **** **** **** **** **** **** +2707 FH_DEATH_ATTACK **** **** **** **** **** **** **** **** +2708 COMMAND_THE_HORDE **** **** **** **** **** **** **** **** +2709 BLINDING_SPITTLE **** **** **** **** **** **** **** **** +2710 BLINDSIGHT_5_FT **** **** **** **** **** **** **** **** +2711 BLINDSIGHT_10_FT **** **** **** **** **** **** **** **** +2712 OW_INSPIRE_COURAGE **** **** **** **** **** **** **** **** +2713 FINAL_RAGE **** **** **** **** **** **** **** **** +2714 RELEASE_HORDE **** **** **** **** **** **** **** **** +2715 GATHER_HORDE_I **** **** **** **** **** **** **** **** +2716 GATHER_HORDE_II **** **** **** **** **** **** **** **** +2717 Gather_Skull_Splitter **** **** **** **** **** **** **** **** +2718 Gather_Weapon_Master **** **** **** **** **** **** **** **** +2719 Gather_Axe_Thrower **** **** **** **** **** **** **** **** +2720 Gather_Shaman **** **** **** **** **** **** **** **** +2721 BLOOD_OF_THE_WARLORD **** **** **** **** **** **** **** **** +2722 Dirge_Sorrow **** **** **** **** **** **** **** **** +2723 InlindlSchool **** **** **** **** **** **** **** **** +2724 SpinningHalberd **** **** **** **** **** **** **** **** +2725 Shou_Flurry_Light **** **** **** **** **** **** **** **** +2726 Shou_Flurry_All **** **** **** **** **** **** **** **** +2727 FEAT_JUMP **** **** **** **** **** **** **** **** +2728 Battlerager_damage **** **** **** **** **** **** **** **** +2729 Hextor_damage **** **** **** **** **** **** **** **** +2730 Thayanknight_damage **** **** **** **** **** **** **** **** +2731 Man_at_arms_damage **** **** **** **** **** **** **** **** +2732 SetCompositeAttackBonus **** **** **** **** **** **** **** **** +2733 KnightChalice_damage **** **** **** **** **** **** **** **** +2734 UnarmedAttackPenetration **** **** **** **** **** **** **** **** +2735 SPELL_TOG_CHARM **** **** **** **** **** **** **** **** +2736 TOG_SUMMON_DEMON **** **** **** **** **** **** **** **** +2737 TOG_SUMMON_SUCCUBUS **** **** **** **** **** **** **** **** +2738 TOG_SUMMON_VROCK **** **** **** **** **** **** **** **** +2739 TOG_SUMMON_GLABREZU **** **** **** **** **** **** **** **** +2740 TOG_SUMMON_MARILITH **** **** **** **** **** **** **** **** +2741 TOG_SUMMON_BALOR **** **** **** **** **** **** **** **** +2742 Ninja_Ghost_Step **** **** **** **** **** **** **** **** +2743 Ninja_Ghost_Strike **** **** **** **** **** **** **** **** +2744 Ninja_Ghost_walk **** **** **** **** **** **** **** **** +2745 Ninja_Greater_Ki_Dodge **** **** **** **** **** **** **** **** +2746 Ninja_Ki_Dodge **** **** **** **** **** **** **** **** +2747 Ninja_Ghost_Step_2 **** **** **** **** **** **** **** **** +2748 SlayerOfDomielDivineGrace **** **** **** **** **** **** **** **** +2749 FEAT_CLIMB **** **** **** **** **** **** **** **** +2750 Unmovable **** **** **** **** **** **** **** **** +2751 Unstoppable **** **** **** **** **** **** **** **** +2752 Beguiling_Nature **** **** **** **** **** **** **** **** +2753 Suggestion **** **** **** **** **** **** **** **** +2754 Baal_Summon_1 **** **** **** **** **** **** **** **** +2755 Baal_Summon_2 **** **** **** **** **** **** **** **** +2756 Insect_Plague **** **** **** **** **** **** **** **** +2757 IAIJUTSU_FINESSE **** **** **** **** **** **** **** **** +2758 Iaijutsu_Attack **** **** **** **** **** **** **** **** +2759 Iaijutsu_Spirit_Stike **** **** **** **** **** **** **** **** +2760 Iaijutsu_Echo_Edge **** **** **** **** **** **** **** **** +2761 Iaijutsu_Two_Cuts **** **** **** **** **** **** **** **** +2762 Iron_Hews **** **** **** **** **** **** **** **** +2763 Rusting_Grasp **** **** **** **** **** **** **** **** +2764 Summon_Erinyes **** **** **** **** **** **** **** **** +2765 Greater_Hews **** **** **** **** **** **** **** **** +2766 Iron_Skin **** **** **** **** **** **** **** **** +2767 Iron_Body **** **** **** **** **** **** **** **** +2768 Pain_Touch **** **** **** **** **** **** **** **** +2769 Cruelest_Cut **** **** **** **** **** **** **** **** +2770 Rava_Aura **** **** **** **** **** **** **** **** +2771 Visage_Terror **** **** **** **** **** **** **** **** +2772 Kiai_Smite **** **** **** **** **** **** **** **** +2773 Staredown **** **** **** **** **** **** **** **** +2774 Mass_Staredown **** **** **** **** **** **** **** **** +2775 WeaponAndTorch **** **** **** **** **** **** **** **** +2776 Contact_Shadowlords **** **** **** **** **** **** **** **** +2777 Scribe_Runescar **** **** **** **** **** **** **** **** +2778 LH_Scribe **** **** **** **** **** **** **** **** +2779 RH_Scribe **** **** **** **** **** **** **** **** +2780 LA_Scribe **** **** **** **** **** **** **** **** +2781 RA_Scribe **** **** **** **** **** **** **** **** +2782 LC_Scribe **** **** **** **** **** **** **** **** +2783 RC_Scribe **** **** **** **** **** **** **** **** +2784 F_Scribe **** **** **** **** **** **** **** **** +2785 Rune_Bers **** **** **** **** **** **** **** **** +2786 Blight_Touch **** **** **** **** **** **** **** **** +2787 SE_Soul_Radiance **** **** **** **** **** **** **** **** +2788 SE_Energy_Drain **** **** **** **** **** **** **** **** +2789 SE_Soul_Blast **** **** **** **** **** **** **** **** +2790 BlightMind **** **** **** **** **** **** **** **** +2791 AnvilofThunder **** **** **** **** **** **** **** **** +2792 HammersEdge **** **** **** **** **** **** **** **** +2793 HighSwordLowAxe **** **** **** **** **** **** **** **** +2794 PowerAttack_Quick_Radial **** **** **** **** **** **** **** **** +2795 PowerAttack_ChangeQuickselect **** **** **** **** **** **** **** **** +2796 PowerAttack_Off **** **** **** **** **** **** **** **** +2797 PowerAttack_Quickslot_1 **** **** **** **** **** **** **** **** +2798 PowerAttack_Quickslot_2 **** **** **** **** **** **** **** **** +2799 PowerAttack_Quickslot_3 **** **** **** **** **** **** **** **** +2800 PsionicFocus_RadialMaster **** **** **** **** **** **** **** **** +2801 CloakDance **** **** **** **** **** **** **** **** +2802 RecklessOffense **** **** **** **** **** **** **** **** +2803 MentalLeap **** **** **** **** **** **** **** **** +2804 PowerPenetration **** **** **** **** **** **** **** **** +2805 GreaterPowerPenetration **** **** **** **** **** **** **** **** +2806 PowerSpecialization **** **** **** **** **** **** **** **** +2807 PsionicEndowment **** **** **** **** **** **** **** **** +2808 GreaterPsionicEndowment **** **** **** **** **** **** **** **** +2809 PsionicFist **** **** **** **** **** **** **** **** +2810 GreaterPsionicFist **** **** **** **** **** **** **** **** +2811 PsionicWeapon **** **** **** **** **** **** **** **** +2812 GreaterPsionicWeapon **** **** **** **** **** **** **** **** +2813 PsionicShot **** **** **** **** **** **** **** **** +2814 GreaterPsionicShot **** **** **** **** **** **** **** **** +2815 OverchannelRadialMaster **** **** **** **** **** **** **** **** +2816 OverchannelOff **** **** **** **** **** **** **** **** +2817 Overchannel_1 **** **** **** **** **** **** **** **** +2818 Overchannel_2 **** **** **** **** **** **** **** **** +2819 Overchannel_3 **** **** **** **** **** **** **** **** +2820 SpeedOfThought_Applying **** **** **** **** **** **** **** **** +2821 Talented **** **** **** **** **** **** **** **** +2822 Psionic_Meditation **** **** **** **** **** **** **** **** +2823 UnavoidableStrike **** **** **** **** **** **** **** **** +2824 WoundingAttackRadialMaster **** **** **** **** **** **** **** **** +2825 WoundingAttackMelee **** **** **** **** **** **** **** **** +2826 WoundingAttackRanged **** **** **** **** **** **** **** **** +2827 DeepImpact **** **** **** **** **** **** **** **** +2828 FellShot **** **** **** **** **** **** **** **** +2829 Metapsi_ChainPower **** **** **** **** **** **** **** **** +2830 Metapsi_EmpowerPower **** **** **** **** **** **** **** **** +2831 Metapsi_ExtendPower **** **** **** **** **** **** **** **** +2832 Metapsi_MaximizePower **** **** **** **** **** **** **** **** +2833 Metapsi_SplitPsionicRay **** **** **** **** **** **** **** **** +2834 Metapsi_TwinPower **** **** **** **** **** **** **** **** +2835 Metapsi_WidenPower **** **** **** **** **** **** **** **** +2836 PsionicFocus_Gain **** **** **** **** **** **** **** **** +2837 PsionicFocus_TurnOffAllFocusUsingAbilities **** **** **** **** **** **** **** **** +2838 Metapsi_QuickenPower **** **** **** **** **** **** **** **** +2839 Disguise_Self_Radial_Master **** **** **** **** **** **** **** **** +2840 Disguise_Self_Learn **** **** **** **** **** **** **** **** +2841 Disguise_Self_Options **** **** **** **** **** **** **** **** +2842 Disguise_Self_QS1 **** **** **** **** **** **** **** **** +2843 Disguise_Self_QS2 **** **** **** **** **** **** **** **** +2844 Disguise_Self_QS3 **** **** **** **** **** **** **** **** +2845 Alter_Self_Radial_Master **** **** **** **** **** **** **** **** +2846 Alter_Self_Learn **** **** **** **** **** **** **** **** +2847 Alter_Self_Options **** **** **** **** **** **** **** **** +2848 Alter_Self_QS1 **** **** **** **** **** **** **** **** +2849 Alter_Self_QS2 **** **** **** **** **** **** **** **** +2850 Alter_Self_QS3 **** **** **** **** **** **** **** **** +2851 Avasculate **** Fortitude 1 R 1 **** **** **** +2852 Avascular_Mass **** Fortitude 1 I 1 **** **** **** +2853 Mass_Aid **** **** **** E 0 2 0 **** +2854 Necrotic_Awareness **** **** **** **** **** **** **** **** +2855 Necrotic_Cyst **** **** **** **** **** **** **** **** +2856 Necrotic_Bloat **** **** **** **** **** **** **** **** +2857 Necrotic_Domination **** **** **** **** **** **** **** **** +2858 Necrotic_Burst **** **** **** **** **** **** **** **** +2859 Necrotic_Eruption **** **** **** **** **** **** **** **** +2860 Necrotic_Empowerment **** **** **** **** **** **** **** **** +2861 Necrotic_Termination **** **** **** **** **** **** **** **** +2862 Ghoul_Gauntlet Death Fortitude 1 T 1 **** **** **** +2863 Energy_Ebb Level_Drain Fortitude 1 R 1 **** **** **** +2864 Nights_Caress **** Fortitude 1 T 1 **** **** **** +2865 Agony **** **** **** **** **** **** **** **** +2866 Baccaran **** **** **** **** **** **** **** **** +2867 Devilweed **** **** **** **** **** **** **** **** +2868 Luhix **** **** **** **** **** **** **** **** +2869 Mushroom_Powder **** **** **** **** **** **** **** **** +2870 Sannish **** **** **** **** **** **** **** **** +2871 Terran_Brandy **** **** **** **** **** **** **** **** +2872 Vodare **** **** **** **** **** **** **** **** +2873 ThrowEnergizedPotion **** **** **** **** **** **** **** **** +2874 Teleport_RadialMaster **** **** **** **** **** **** **** **** +2875 Teleport_SelfOnly **** **** **** **** **** **** **** **** +2876 Teleport_Party **** **** **** **** **** **** **** **** +2877 TeleportationCircle_RadialMaster **** **** **** **** **** **** **** **** +2878 TeleportationCircle_Visible **** **** **** **** **** **** **** **** +2879 TeleportationCircle_Hidden **** **** **** **** **** **** **** **** +2880 PoisonedWeapon **** **** **** **** **** **** **** **** +2881 Grenade_Poisonvial **** **** **** **** **** **** **** **** +2882 Poison_Weapon **** **** **** **** **** **** **** **** +2883 Poison_Item **** **** **** **** **** **** **** **** +2884 Poison_Food **** **** **** **** **** **** **** **** +2885 Clean_Poison_Off **** **** **** **** **** **** **** **** +2886 Pox **** Fortitude 1 I 1 **** **** **** +2887 Pestilence Disease Fortitude 1 T 1 **** **** **** +2888 Maze **** **** 1 R 1 **** **** **** +2889 Dimensional_Anchor **** **** **** **** **** **** **** **** +2890 DimensionDoor_RadialMaster **** **** **** **** **** **** **** **** +2891 DimensionDoor_SelfOnly **** **** **** **** **** **** **** **** +2892 DimensionDoor_Party **** **** **** **** **** **** **** **** +2893 GreaterTeleport_RadialMaster **** **** **** **** **** **** **** **** +2894 GreaterTeleport_SelfOnly **** **** **** **** **** **** **** **** +2895 GreaterTeleport_Party **** **** **** **** **** **** **** **** +2896 DimensionDoor_DirDist_SelfOnly **** **** **** **** **** **** **** **** +2897 DimensionDoor_DirDist_Party **** **** **** **** **** **** **** **** +2898 Dimensional_Lock **** **** **** **** **** **** **** **** +2899 End_Projection **** **** **** **** **** **** **** **** +2900 Wolf_From **** **** **** **** **** **** **** **** +2901 Werewolf_Form **** **** **** **** **** **** **** **** +2902 PROJECTION **** **** **** **** **** **** **** **** +2903 BAELNORN_TOUCH **** **** **** **** **** **** **** **** +2904 Wolf_Empathy **** **** **** **** **** **** **** **** +2905 FEAT_HOUND_AURAMENACE **** **** **** **** **** **** **** **** +2906 FEAT_RACE_WEB **** **** **** **** **** **** **** **** +2907 FEAT_RACE_MINOR_SHAPE_CHANGE **** **** **** **** **** **** **** **** +2908 FEAT_CHANGELING_QUICK_CHANGE **** **** **** **** **** **** **** **** +2909 Quick_Change_Learn **** **** **** **** **** **** **** **** +2910 Quick_Change_Options **** **** **** **** **** **** **** **** +2911 Quick_Change_True **** **** **** **** **** **** **** **** +2912 Quick_Change_QS1 **** **** **** **** **** **** **** **** +2913 Quick_Change_QS2 **** **** **** **** **** **** **** **** +2914 Grig_Pyrotechnics **** **** **** **** **** **** **** **** +2915 Grig_Pyrotechnics_Fireworks **** **** **** **** **** **** **** **** +2916 Grig_Pyrotechnics_Smoke **** **** **** **** **** **** **** **** +2917 Bralani_Lightning_Bolt **** **** **** **** **** **** **** **** +2918 Bralani_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +2919 Bralani_Gust_of_Wind **** **** **** **** **** **** **** **** +2920 Bralani_Mirror_Image **** **** **** **** **** **** **** **** +2921 CrusaderReadyManeuver **** **** **** **** **** **** **** **** +2922 FEAT_RACE_FLARE **** **** **** **** **** **** **** **** +2923 SwordsageReadyManeuver **** **** **** **** **** **** **** **** +2924 Faerie_Fire **** **** **** **** **** **** **** **** +2925 FEAT_RACE_CONEOFCOLD **** **** **** **** **** **** **** **** +2926 WarbladeReadyManeuver **** **** **** **** **** **** **** **** +2927 FEAT_RACE_CHAINLIGHT **** **** **** **** **** **** **** **** +2928 FEAT_RACE_CALLLIGHT **** **** **** **** **** **** **** **** +2929 FEAT_RACE_BLESS **** **** **** **** **** **** **** **** +2930 FEAT_HOUND_AID **** **** **** **** **** **** **** **** +2931 WarbladeRecoverManeuver **** **** **** **** **** **** **** **** +2932 FEAT_HOUND_CONTFLAME **** **** **** **** **** **** **** **** +2933 FEAT_HOUND_DETECTEVIL **** **** **** **** **** **** **** **** +2934 FEAT_HOUND_MAGICCIRCLE **** **** **** **** **** **** **** **** +2935 FEAT_HOUND_TELEPORT **** **** **** **** **** **** **** **** +2936 FEAT_HOUND_DISGUISE **** **** **** **** **** **** **** **** +2937 FEAT_ZENYTH_TRUE_STRIKE **** **** **** **** **** **** **** **** +2938 Racial_Magic_Circle_vs_Good **** **** **** **** **** **** **** **** +2939 Racial_Magic_Circle_vs_Evil **** **** **** **** **** **** **** **** +2940 Racial_Magic_Circle_vs_Law **** **** **** **** **** **** **** **** +2941 Racial_Magic_Circle_vs_Chaos **** **** **** **** **** **** **** **** +2942 Racial_Magic_Circle_against_Alignment **** **** **** **** **** **** **** **** +2943 FEAT_NATHRI_EXP_RETREAT **** **** **** **** **** **** **** **** +2944 FEAT_BLADELING_RAZOR_STORM **** **** **** **** **** **** **** **** +2945 Racial_Detect_Good **** **** **** **** **** **** **** **** +2946 Racial_Detect_Law **** **** **** **** **** **** **** **** +2947 Kapak_Saliva_Application **** **** **** **** **** **** **** **** +2948 OnHit_Kapak_Saliva **** **** **** **** **** **** **** **** +2949 Shifter_Shifting **** **** **** **** **** **** **** **** +2950 FEAT_FEYRI_CHANGE_SHAPE **** **** **** **** **** **** **** **** +2951 Feyri_Select_Form **** **** **** **** **** **** **** **** +2952 Feyri_Options **** **** **** **** **** **** **** **** +2953 Feyri_True_Form **** **** **** **** **** **** **** **** +2954 Feyri_Quickslot_1 **** **** **** **** **** **** **** **** +2955 Feyri_Quickslot_2 **** **** **** **** **** **** **** **** +2956 Nymph_DimensionDoor_RadialMaster **** **** **** **** **** **** **** **** +2957 Nymph_DimensionDoor_SelfOnly **** **** **** **** **** **** **** **** +2958 Nymph_DimensionDoor_Party **** **** **** **** **** **** **** **** +2959 Nymph_DimensionDoor_DirDist_SelfOnly **** **** **** **** **** **** **** **** +2960 Nymph_DimensionDoor_DirDist_Party **** **** **** **** **** **** **** **** +2961 FEAT_RAK_CHANGE_SHAPE **** **** **** **** **** **** **** **** +2962 Raksahsa_Select_Form **** **** **** **** **** **** **** **** +2963 Raksahsa_Options **** **** **** **** **** **** **** **** +2964 Rakshasa_True_Form **** **** **** **** **** **** **** **** +2965 Rakshasa_Quickslot_1 **** **** **** **** **** **** **** **** +2966 Rakshasa_Quickslot_2 **** **** **** **** **** **** **** **** +2967 Forestlord_Treewalk_Selected **** **** **** **** **** **** **** **** +2968 Forestlord_Treewalk_Dirdist **** **** **** **** **** **** **** **** +2969 Glimmerskin_Touch_of_Luck **** **** **** **** **** **** **** **** +2970 Forestlord_Treewalk_Master_Radial **** **** **** **** **** **** **** **** +2971 Daylight **** **** **** **** 0 3 0 -15 +2972 Clinging_Breath **** **** **** **** **** **** **** **** +2973 Clinging_Conv **** **** **** **** **** **** **** **** +2974 Clinging_Off **** **** **** **** **** **** **** **** +2975 Clinging_QS1 **** **** **** **** **** **** **** **** +2976 Clinging_QS2 **** **** **** **** **** **** **** **** +2977 Clinging_QS3 **** **** **** **** **** **** **** **** +2978 Lingering_Breath **** **** **** **** **** **** **** **** +2979 Lingering_Conv **** **** **** **** **** **** **** **** +2980 Lingering_Off **** **** **** **** **** **** **** **** +2981 Lingering_QS1 **** **** **** **** **** **** **** **** +2982 Lingering_QS2 **** **** **** **** **** **** **** **** +2983 Lingering_QS3 **** **** **** **** **** **** **** **** +2984 Heighten_Breath **** **** **** **** **** **** **** **** +2985 Heighten_Conv **** **** **** **** **** **** **** **** +2986 Heighten_Off **** **** **** **** **** **** **** **** +2987 Heighten_QS1 **** **** **** **** **** **** **** **** +2988 Heighten_QS2 **** **** **** **** **** **** **** **** +2989 Heighten_Max **** **** **** **** **** **** **** **** +2990 Exhale_Barrier **** **** **** **** **** **** **** **** +2991 Spreading_Breath **** **** **** **** **** **** **** **** +2992 Tempest_Breath **** **** **** **** **** **** **** **** +2993 Exhale_Immunity **** **** **** **** **** **** **** **** +2994 Enlarge_Breath **** **** **** **** **** **** **** **** +2995 Maximize_Breath **** **** **** **** **** **** **** **** +2996 Exhale_Immunity **** **** **** **** **** **** **** **** +2997 Shape_Breath **** **** **** **** **** **** **** **** +2998 Poison_Weapon **** **** **** **** **** **** **** **** +2999 Avenging_Strike **** **** **** **** **** **** **** **** +3000 HellFire_Grasp **** **** **** **** **** **** **** **** +3001 Hellfire_Blast **** **** **** **** **** **** **** **** +3002 Hellfire_Flare **** **** **** **** **** **** **** **** +3003 Summon_Hamatula **** **** **** **** **** **** **** **** +3004 HellFire **** **** **** **** **** **** **** **** +3005 Fire_Shield **** **** **** **** **** **** **** **** +3006 HellFire_Storm **** **** **** **** **** **** **** **** +3007 Body_of_Fire **** **** **** **** **** **** **** **** +3008 Disciple_of_Darkness **** **** **** **** **** **** **** **** +3009 MOS_Summon **** **** **** **** **** **** **** **** +3010 MOS_Summon **** **** **** **** **** **** **** **** +3011 MOS_Summon **** **** **** **** **** **** **** **** +3012 MOS_Summon **** **** **** **** **** **** **** **** +3013 SPELL_SPELLFIRE_WIELDER **** **** **** **** **** **** **** **** +3014 SPELL_SPELLFIRE_INCREASE **** **** **** **** **** **** **** **** +3015 SPELL_SPELLFIRE_DECREASE **** **** **** **** **** **** **** **** +3016 SPELL_SPELLFIRE_QUICKSELECT **** **** **** **** **** **** **** **** +3017 SPELL_SPELLFIRE_ATTACK **** **** **** **** **** **** **** **** +3018 SPELL_SPELLFIRE_HEAL **** **** **** **** **** **** **** **** +3019 SPELL_SPELLFIRE_CHECK **** **** **** **** **** **** **** **** +3020 SPELL_SPELLFIRE_PLUS_ONE **** **** **** **** **** **** **** **** +3021 SPELL_SPELLFIRE_PLUS_FIVE **** **** **** **** **** **** **** **** +3022 SPELL_SPELLFIRE_PLUS_TEN **** **** **** **** **** **** **** **** +3023 SPELL_SPELLFIRE_PLUS_TWENTY **** **** **** **** **** **** **** **** +3024 SPELL_SPELLFIRE_MINUS_ONE **** **** **** **** **** **** **** **** +3025 SPELL_SPELLFIRE_MINUS_FIVE **** **** **** **** **** **** **** **** +3026 SPELL_SPELLFIRE_MINUS_TEN **** **** **** **** **** **** **** **** +3027 SPELL_SPELLFIRE_MINUS_TWENTY **** **** **** **** **** **** **** **** +3028 SPELL_SPELLFIRE_CHECK_EXP **** **** **** **** **** **** **** **** +3029 SPELL_SPELLFIRE_QUICKSELECT_CHANGE **** **** **** **** **** **** **** **** +3030 SPELL_SPELLFIRE_QUICKSELECT_1 **** **** **** **** **** **** **** **** +3031 SPELL_SPELLFIRE_QUICKSELECT_2 **** **** **** **** **** **** **** **** +3032 SPELL_SPELLFIRE_QUICKSELECT_3 **** **** **** **** **** **** **** **** +3033 SPELL_SPELLFIRE_DRAIN_CHARGED **** **** **** **** **** **** **** **** +3034 SPELL_SPELLFIRE_RAPID_BLAST **** **** **** **** **** **** **** **** +3035 SPELL_SPELLFIRE_RAPID_BLAST_TWO **** **** **** **** **** **** **** **** +3036 SPELL_SPELLFIRE_RAPID_BLAST_THREE **** **** **** **** **** **** **** **** +3037 SPELL_SPELLFIRE_DRAIN_PERMANENT **** **** **** **** **** **** **** **** +3038 SPELL_SPELLFIRE_CHARGE_ITEM **** **** **** **** **** **** **** **** +3039 SPELL_SPELLFIRE_CROWN **** **** **** **** **** **** **** **** +3040 SPELL_SPELLFIRE_MAELSTROM **** **** **** **** **** **** **** **** +3041 SPELL_SPELLFIRE_ABSORB **** **** **** **** **** **** **** **** +3042 SPELLS_SPELLS_TOUCH_ATTACK **** **** **** **** **** **** **** **** +3043 SPELLS_SPELLS_RANGED_ATTACK **** **** **** **** **** **** **** **** +3044 SPELLS_SPELLS_CONCENTRATION_TARGET **** **** **** **** **** **** **** **** +3045 SPELLS_SPELLS_HOLD_CHARGE_TOGGLE **** **** **** **** **** **** **** **** +3046 Virtuoso_Sustaining_Song **** **** **** **** **** **** **** **** +3047 Virtuoso_Calumny **** **** **** **** **** **** **** **** +3048 Virtuoso_Jarring_Song **** **** **** **** **** **** **** **** +3049 Virtuoso_Sharp_Note **** **** **** **** **** **** **** **** +3050 Virtuoso_Mindbending_Melody **** **** **** **** **** **** **** **** +3051 Virtuoso_Greater_Calumny **** **** **** **** **** **** **** **** +3052 Virtuoso_Magical_Melody **** **** **** **** **** **** **** **** +3053 Virtuoso_Song_of_Fury **** **** **** **** **** **** **** **** +3054 Virtuoso_Revealing_Melody **** **** **** **** **** **** **** **** +3055 ShockingGrasp Electricity **** 1 T 1 **** **** **** +3056 ScorchingRay Fire **** 1 R 1 **** **** **** +3057 RayofExhaustion **** Fortitude 1 R 1 **** **** **** +3058 WavesofFatigue **** **** 1 I 1 **** **** **** +3059 Asmodeus_DreadMight **** **** **** **** **** **** **** **** +3060 DOA_SUMMON_SUCCUBUS **** **** **** **** **** **** **** **** +3061 DOA_SUMMON_VROCK **** **** **** **** **** **** **** **** +3062 DOA_SUMMON_GLABREZU **** **** **** **** **** **** **** **** +3063 DOA_SUMMON_MARILITH **** **** **** **** **** **** **** **** +3064 DOA_SUMMON_BALOR **** **** **** **** **** **** **** **** +3065 SoheiKiFrenzy **** **** **** **** **** **** **** **** +3066 AsmodeusLearnSecrets1 **** **** **** **** **** **** **** **** +3067 AsmodeusCharm **** **** **** **** **** **** **** **** +3068 AsmodeusHellcat **** **** **** **** **** **** **** **** +3069 AsmodeusEvilAuthority **** **** **** **** **** **** **** **** +3070 AsmodeusSummonDevil **** **** **** **** **** **** **** **** +3071 DoA_GreaterCommand_RadialMaster **** **** **** **** **** **** **** **** +3072 DoA_GreaterCommand_Approach **** **** **** **** **** **** **** **** +3073 DoA_GreaterCommand_Drop **** **** **** **** **** **** **** **** +3074 DoA_GreaterCommand_Fall **** **** **** **** **** **** **** **** +3075 DoA_GreaterCommand_Flee **** **** **** **** **** **** **** **** +3076 DoA_GreaterCommand_Halt **** **** **** **** **** **** **** **** +3077 DoA_Command_RadialMaster **** **** **** **** **** **** **** **** +3078 DoA_Command_Approach **** **** **** **** **** **** **** **** +3079 DoA_Command_Drop **** **** **** **** **** **** **** **** +3080 DoA_Command_Fall **** **** **** **** **** **** **** **** +3081 DoA_Command_Flee **** **** **** **** **** **** **** **** +3082 DoA_Command_Halt **** **** **** **** **** **** **** **** +3083 VisionOfHeaven Daze Will 1 R 1 **** **** **** +3084 SwordOfConscience **** **** **** **** **** **** **** **** +3085 Obscuring_Mist **** **** **** P 0 2 0 -5 +3086 GreaterCommand_RadialMaster **** **** **** **** **** **** **** **** +3087 GreaterCommand_Approach **** **** **** **** **** **** **** **** +3088 GreaterCommand_Drop **** **** **** **** **** **** **** **** +3089 GreaterCommand_Fall **** **** **** **** **** **** **** **** +3090 GreaterCommand_Flee **** **** **** **** **** **** **** **** +3091 GreaterCommand_Halt **** **** **** **** **** **** **** **** +3092 Command_RadialMaster **** **** **** **** **** **** **** **** +3093 Command_Approach **** **** **** **** **** **** **** **** +3094 Command_Drop **** **** **** **** **** **** **** **** +3095 Command_Fall **** **** **** **** **** **** **** **** +3096 Command_Flee **** **** **** **** **** **** **** **** +3097 Command_Halt **** **** **** **** **** **** **** **** +3098 PolarRay Cold **** 1 R 1 **** **** **** +3099 BloodOfTheMartyr **** **** **** **** **** **** **** **** +3100 Acid_Orb Acid Fortitude 0 R 1 **** **** **** +3101 Cold_Orb Cold Fortitude 0 R 1 **** **** **** +3102 Electric_Orb Electricity Fortitude 0 R 1 **** **** **** +3103 Fire_Orb Fire Fortitude 0 R 1 **** **** **** +3104 Sonic_Orb Sonic Fortitude 0 R 1 **** **** **** +3105 Ice_Burst Cold Reflex 1 I 1 **** **** **** +3106 Acid_Storm Acid Reflex 1 I 1 **** **** **** +3107 Mass_Hold_Person Paralysis Will 1 D 1 **** **** **** +3108 Mass_Hold_Monster Paralysis Will 1 D 1 **** **** **** +3109 Burning_Bolt Fire **** 1 R 1 **** **** **** +3110 Blast_of_Flame Fire Reflex 1 I 1 **** **** **** +3111 Disintegrate **** Fortitude 1 R 1 **** **** **** +3112 Mantle_of_Eg_Might **** **** **** E 0 3 9 **** +3113 Energy_Immunity **** **** **** **** **** **** **** **** +3114 EI_Acid **** **** **** **** **** **** **** **** +3115 EI_Cold **** **** **** **** **** **** **** **** +3116 EI_Elec **** **** **** **** **** **** **** **** +3117 EI_Fire **** **** **** **** **** **** **** **** +3118 EI_Sonic **** **** **** **** **** **** **** **** +3119 Mass_Bulls_Strength **** **** **** E 0 3 0 **** +3120 Mass_Cats_Grace **** **** **** E 0 3 0 **** +3121 Mass_Eagle_Splendor **** **** **** E 0 3 0 **** +3122 Mass_Endurance **** **** **** E 0 3 0 **** +3123 Mass_Foxs_Cunning **** **** **** E 0 3 0 **** +3124 Mass_Owls_Wisdom **** **** **** E 0 3 0 **** +3125 Mass_Ultravision **** **** **** P 0 3 0 **** +3126 Lower_Spell_Resistance **** **** **** **** **** **** **** **** +3127 Serpents_Sigh **** **** **** **** **** **** **** **** +3128 SS_Bolt_of_Acid **** **** **** **** **** **** **** **** +3129 SS_Bolt_of_Lightning **** **** **** **** **** **** **** **** +3130 SS_Cone_of_Acid **** **** **** **** **** **** **** **** +3131 SS_Cone_of_Cold **** **** **** **** **** **** **** **** +3132 SS_Cone_of_Fire **** **** **** **** **** **** **** **** +3133 Heroism **** **** **** E 0 3 9 -3133 +3134 Greater_Heroism **** **** **** E 0 2 9 -3133 +3135 Mass_Cure_Light_Wounds **** **** **** **** **** **** **** **** +3136 Mass_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +3137 Mass_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +3138 Mass_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +3139 Righteous_Might **** **** **** E 0 2 0 **** +3140 Recitation **** **** **** E 0 2 0 **** +3141 Forceblast **** Reflex 1 R 1 **** **** **** +3142 Glitterdust **** Will **** I 1 **** **** **** +3143 Mords_Mansion **** **** **** **** **** **** **** **** +3144 Lesser_Acid_Orb Acid **** **** R 1 **** **** **** +3145 Lesser_Cold_Orb Cold **** **** R 1 **** **** **** +3146 Lesser_Electric_Orb Electricity **** **** R 1 **** **** **** +3147 Lesser_Fire_Orb Fire **** **** R 1 **** **** **** +3148 Lesser_Sonic_Orb Sonic **** **** R 1 **** **** **** +3149 Baleful_Transposition **** **** **** **** **** **** **** **** +3150 Benign_Transposition **** **** **** **** **** **** **** **** +3151 Conviction **** **** **** P 0 2 14 -3151 +3152 Legions_Conviction **** **** **** P 0 2 14 -3151 +3153 Curse_of_Impending_Blades **** **** 1 R 1 **** **** **** +3154 Legions_Curse_of_Impending_Blades **** **** 1 R 1 **** **** **** +3155 Curse_of_Petty_Failing **** **** 1 R 1 **** **** **** +3156 Legions_Curse_of_Petty_Failing **** **** 1 R 1 **** **** **** +3157 Divine_Protection **** **** **** P 0 2 0 **** +3158 Fireburst Fire Reflex 1 I 1 **** **** **** +3159 Greater_Fireburst Fire Reflex 1 I 1 **** **** **** +3160 Lionheart **** **** **** P 0 2 13 **** +3161 Living_Undeath **** **** **** P 0 2 12 **** +3162 Panacea **** **** **** **** **** **** **** **** +3163 Legions_Shield_of_Faith **** **** **** P 0 3 7 -3 +3164 Slashing_Darkness Positive **** 1 R 1 **** **** **** +3165 Agnazzars_Scorcher Fire Reflex 0 I 1 **** **** **** +3166 Create_Magic_Tattoo **** **** **** **** **** **** **** **** +3167 CT_Scribe **** **** **** **** **** **** **** **** +3168 Flashburst Blindness Will 1 I 1 **** **** **** +3169 Flensing **** Fortitude 1 R 1 **** **** **** +3170 Shadow_Spray **** Fortitude 1 I 1 **** **** **** +3171 Snillocs_Snowball_Swarm Cold Reflex 1 I 1 **** **** **** +3172 Beltyns_Burning_Blood Fire Fortitude 1 R 1 **** **** **** +3173 Ilyykurs_Mantle **** **** **** P 0 2 0 **** +3174 Improved_Mage_Armor **** **** **** P 0 2 7 -102 +3175 Nybors_Gentle_Reminder Mind_Affecting Fortitude 1 R 1 **** **** **** +3176 Nybors_Stern_Reproof Death Fortitude 1 R 1 **** **** **** +3177 Sinsaburs_Baleful_Bolt **** Reflex 1 I 1 **** **** **** +3178 Snillocs_Snowball Cold **** 1 R 1 **** **** **** +3179 Soulscour Mind_Affecting Will 1 T 1 **** **** **** +3180 Sphere_of_Ultimate_Destruction Death Fortitude 1 R 1 **** **** **** +3181 Clarity_of_Mind **** **** **** P 0 3 13 **** +3182 Mass_Drown **** Fortitude 1 I 1 **** **** **** +3183 Hail_of_Stone **** **** 1 I 1 **** **** **** +3184 Spiderskin **** **** **** P 0 3 7 **** +3185 Viscid_Glob **** Reflex 1 R 1 **** **** **** +3186 Word_of_Balance **** **** 1 I 1 **** **** **** +3187 Greenfire **** **** **** **** **** **** **** **** +3188 Blank **** **** **** **** **** **** **** **** +3189 Summon7Air **** **** **** **** **** **** **** **** +3190 Summon7Earth **** **** **** **** **** **** **** **** +3191 Summon7Fire **** **** **** **** **** **** **** **** +3192 Summon7Water **** **** **** **** **** **** **** **** +3193 Summon8Air **** **** **** **** **** **** **** **** +3194 Summon8Earth **** **** **** **** **** **** **** **** +3195 Summon8Fire **** **** **** **** **** **** **** **** +3196 Summon8Water **** **** **** **** **** **** **** **** +3197 Summon9Air **** **** **** **** **** **** **** **** +3198 Summon9Earth **** **** **** **** **** **** **** **** +3199 Summon9Fire **** **** **** **** **** **** **** **** +3200 Summon9Water **** **** **** **** **** **** **** **** +3201 Detect_Evil **** **** **** **** **** **** **** **** +3202 Detect_Good **** **** **** **** **** **** **** **** +3203 Detect_Law **** **** **** **** **** **** **** **** +3204 Detect_Chaos **** **** **** **** **** **** **** **** +3205 UndetectableAlignment **** **** **** **** **** **** **** **** +3206 Unholy_Sword **** **** **** **** **** **** **** **** +3207 DeeperDarkness **** **** **** I 1 **** **** **** +3208 Blur **** **** **** P 0 2 7 -5 +3209 MirrorImage **** **** **** P 0 2 0 **** +3210 Swashbuckler_damage **** **** **** **** **** **** **** **** +3211 CoC_damage **** **** **** **** **** **** **** **** +3212 Insanity Confusion Will 1 R 1 **** **** **** +3213 Mass_Inflict_Light_Wounds Negative Will 1 I 1 **** **** **** +3214 Mass_Inflict_Moderate_Wounds Negative Will 1 I 1 **** **** **** +3215 Mass_Inflict_Serious_Wounds Negative Will 1 I 1 **** **** **** +3216 Mass_Inflict_Critical_Wounds Negative Will 1 I 1 **** **** **** +3217 Greater_Harm Negative Will 1 T 1 **** **** **** +3218 Mass_Harm Negative Will 1 I 1 **** **** **** +3219 Scrying **** **** **** **** **** **** **** **** +3220 Holy_Word **** **** 1 D 1 **** **** **** +3221 Blasphemy **** **** 1 D 1 **** **** **** +3222 Dictum **** **** 1 D 1 **** **** **** +3223 Word_of_Chaos **** **** 1 D 1 **** **** **** +3224 **Truenaming** **** **** **** **** **** **** **** **** +3225 DefensiveEdge **** **** **** **** **** **** **** **** +3226 DefensiveEdge_Normal **** **** **** **** **** **** **** **** +3227 DefensiveEdge_Reverse **** **** **** **** **** **** **** **** +3228 InertialSurge **** **** **** **** **** **** **** **** +3229 InertialSurge_Normal **** **** **** **** **** **** **** **** +3230 InertialSurge_Reverse **** **** **** **** **** **** **** **** +3231 KnightsPuissance **** **** **** **** **** **** **** **** +3232 KnightsPuissance_Normal **** **** **** **** **** **** **** **** +3233 KnightsPuissance_Reverse **** **** **** **** **** **** **** **** +3234 UniversalAptitude **** **** **** **** **** **** **** **** +3235 UniversalAptitude_Normal **** **** **** **** **** **** **** **** +3236 UniversalAptitude_Reverse **** **** **** **** **** **** **** **** +3237 WordOfNurturingMinor **** **** **** **** **** **** **** **** +3238 WordOfNurturingMinor_Normal **** **** **** **** **** **** **** **** +3239 WordOfNurturingMinor_Reverse **** **** **** **** **** **** **** **** +3240 FortifyArmour **** **** **** **** **** **** **** **** +3241 FortifyArmour_SneakAttacks **** **** **** **** **** **** **** **** +3242 FortifyArmour_Criticals **** **** **** **** **** **** **** **** +3243 KeenWeapon **** **** **** **** **** **** **** **** +3244 FogOfTheVoid **** **** **** **** **** **** **** **** +3245 FogOfTheVoid_FogCloud **** **** **** **** **** **** **** **** +3246 FogOfTheVoid_SolidFog **** **** **** **** **** **** **** **** +3247 ShieldOfTheLandscape **** **** **** **** **** **** **** **** +3248 Shockwave **** **** **** **** **** **** **** **** +3249 ArchersEye **** **** **** **** **** **** **** **** +3250 ArchersEye_Normal **** **** **** **** **** **** **** **** +3251 ArchersEye_Reverse **** **** **** **** **** **** **** **** +3252 HiddenTruth **** **** **** **** **** **** **** **** +3253 HiddenTruth_Normal **** **** **** **** **** **** **** **** +3254 HiddenTruth_Reverse **** **** **** **** **** **** **** **** +3255 PercieveTheUnseen **** **** **** **** **** **** **** **** +3256 PercieveTheUnseen_Normal **** **** **** **** **** **** **** **** +3257 PercieveTheUnseen_Reverse **** **** **** **** **** **** **** **** +3258 SilentCaster **** **** **** **** **** **** **** **** +3259 SilentCaster_Normal **** **** **** **** **** **** **** **** +3260 SilentCaster_Reverse **** **** **** **** **** **** **** **** +3261 SpeedOfTheZephyr **** **** **** **** **** **** **** **** +3262 SpeedOfTheZephyr_Normal **** **** **** **** **** **** **** **** +3263 SpeedOfTheZephyr_Reverse **** **** **** **** **** **** **** **** +3264 StrikeOfMight **** **** **** **** **** **** **** **** +3265 StrikeOfMight_Normal **** **** **** **** **** **** **** **** +3266 StrikeOfMight_Reverse **** **** **** **** **** **** **** **** +3267 TemporalTwist **** **** **** **** **** **** **** **** +3268 TemporalTwist_Normal **** **** **** **** **** **** **** **** +3269 TemporalTwist_Reverse **** **** **** **** **** **** **** **** +3270 WordOfNurturingLesser **** **** **** **** **** **** **** **** +3271 WordOfNurturingLesser_Normal **** **** **** **** **** **** **** **** +3272 WordOfNurturingLesser_Reverse **** **** **** **** **** **** **** **** +3273 AgitateItem **** **** **** **** **** **** **** **** +3274 AgitateItem_Hot **** **** **** **** **** **** **** **** +3275 AgitateItem_Cold **** **** **** **** **** **** **** **** +3276 AnalyzeIten **** **** **** **** **** **** **** **** +3277 EnergyVortex **** **** **** **** **** **** **** **** +3278 EnergyVortex_Acid **** **** **** **** **** **** **** **** +3279 EnergyVortex_Cold **** **** **** **** **** **** **** **** +3280 EnergyVortex_Elec **** **** **** **** **** **** **** **** +3281 EnergyVortex_Fire **** **** **** **** **** **** **** **** +3282 SpeakRockToMud **** **** **** **** **** **** **** **** +3283 TransformTheLandscape **** **** **** **** **** **** **** **** +3284 AcceleratedAttack **** **** **** **** **** **** **** **** +3285 AcceleratedAttack_Normal **** **** **** **** **** **** **** **** +3286 AcceleratedAttack_Reverse **** **** **** **** **** **** **** **** +3287 EnergyNegation **** **** **** **** **** **** **** **** +3288 EnergyNegation_Normal **** **** **** **** **** **** **** **** +3289 EnergyNegation_Reverse **** **** **** **** **** **** **** **** +3290 EnergyNegation_Choice **** **** **** **** **** **** **** **** +3291 IncarnationOfAngels **** **** **** **** **** **** **** **** +3292 IncarnationOfAngels_Normal **** **** **** **** **** **** **** **** +3293 IncarnationOfAngels_Reverse **** **** **** **** **** **** **** **** +3294 SpeedOfTheZephyrGreater **** **** **** **** **** **** **** **** +3295 SpeedOfTheZephyrGreater_Normal **** **** **** **** **** **** **** **** +3296 SpeedOfTheZephyrGreater_Reverse **** **** **** **** **** **** **** **** +3297 TemporalSpiral **** **** **** **** **** **** **** **** +3298 TemporalSpiral_Normal **** **** **** **** **** **** **** **** +3299 TemporalSpiral_Reverse **** **** **** **** **** **** **** **** +3300 VisionSharpened **** **** **** **** **** **** **** **** +3301 VisionSharpened_Normal **** **** **** **** **** **** **** **** +3302 VisionSharpened_Reverse **** **** **** **** **** **** **** **** +3303 WordOfNurturingModerate **** **** **** **** **** **** **** **** +3304 WordOfNurturingModerate_Normal **** **** **** **** **** **** **** **** +3305 WordOfNurturingModerate_Reverse **** **** **** **** **** **** **** **** +3306 RemoveItem **** **** **** **** **** **** **** **** +3307 SuppressWeapon **** **** **** **** **** **** **** **** +3308 LoreOfTheWorld **** **** **** **** **** **** **** **** +3309 MasterTheFourWinds **** **** **** **** **** **** **** **** +3310 ThwartTheTraveller **** **** **** **** **** **** **** **** +3311 BreathOfCleansing **** **** **** **** **** **** **** **** +3312 BreathOfCleansing_Normal **** **** **** **** **** **** **** **** +3313 BreathOfCleansing_Reverse **** **** **** **** **** **** **** **** +3314 CasterLens **** **** **** **** **** **** **** **** +3315 CasterLens_Normal **** **** **** **** **** **** **** **** +3316 CasterLens_Reverse **** **** **** **** **** **** **** **** +3317 ConfoundingResistance **** **** **** **** **** **** **** **** +3318 ConfoundingResistance_Normal **** **** **** **** **** **** **** **** +3319 ConfoundingResistance_Reverse **** **** **** **** **** **** **** **** +3320 MoraleBoost **** **** **** **** **** **** **** **** +3321 MoraleBoost_Normal **** **** **** **** **** **** **** **** +3322 MoraleBoost_Reverse **** **** **** **** **** **** **** **** +3323 MagicalContraction **** **** **** **** **** **** **** **** +3324 MagicalContraction_Normal **** **** **** **** **** **** **** **** +3325 MagicalContraction_Reverse **** **** **** **** **** **** **** **** +3326 SpellRebirth **** **** **** **** **** **** **** **** +3327 SpellRebirth_Normal **** **** **** **** **** **** **** **** +3328 SpellRebirth_Reverse **** **** **** **** **** **** **** **** +3329 WordOfNurturingPotent **** **** **** **** **** **** **** **** +3330 WordOfNurturingPotent_Normal **** **** **** **** **** **** **** **** +3331 WordOfNurturingPotent_Reverse **** **** **** **** **** **** **** **** +3332 WordOfBolstering **** **** **** **** **** **** **** **** +3333 WordOfBolstering_Normal **** **** **** **** **** **** **** **** +3334 WordOfBolstering_Reverse **** **** **** **** **** **** **** **** +3335 WordOfBolstering_Choice **** **** **** **** **** **** **** **** +3336 SuppressItem **** **** **** **** **** **** **** **** +3337 TransmuteWeapon **** **** **** **** **** **** **** **** +3338 AngerTheSleepingEarth **** **** **** **** **** **** **** **** +3339 ConjunctiveGate **** **** **** **** **** **** **** **** +3340 DenyPassage **** **** **** **** **** **** **** **** +3341 EldritchAttraction **** **** **** **** **** **** **** **** +3342 EldritchAttraction_Normal **** **** **** **** **** **** **** **** +3343 EldritchAttraction_Reverse **** **** **** **** **** **** **** **** +3344 EnergyNegationGreater **** **** **** **** **** **** **** **** +3345 EnergyNegationGreater_Normal **** **** **** **** **** **** **** **** +3346 EnergyNegationGreater_Reverse **** **** **** **** **** **** **** **** +3347 EnergyNegationGreater_Choice **** **** **** **** **** **** **** **** +3348 EssenceOfLifespark **** **** **** **** **** **** **** **** +3349 EssenceOfLifespark_Normal **** **** **** **** **** **** **** **** +3350 EssenceOfLifespark_Reverse **** **** **** **** **** **** **** **** +3351 PreturnaturalClarity **** **** **** **** **** **** **** **** +3352 PreturnaturalClarity_Attack **** **** **** **** **** **** **** **** +3353 PreturnaturalClarity_Skill **** **** **** **** **** **** **** **** +3354 PreturnaturalClarity_Save **** **** **** **** **** **** **** **** +3355 PreturnaturalClarity_Reverse **** **** **** **** **** **** **** **** +3356 SensoryFocus **** **** **** **** **** **** **** **** +3357 SensoryFocus_Normal **** **** **** **** **** **** **** **** +3358 SensoryFocus_Reverse **** **** **** **** **** **** **** **** +3359 WardOfPeace **** **** **** **** **** **** **** **** +3360 WardOfPeace_Normal **** **** **** **** **** **** **** **** +3361 WardOfPeace_Reverse **** **** **** **** **** **** **** **** +3362 WordOfNurturingCritical **** **** **** **** **** **** **** **** +3363 WordOfNurturingCritical_Normal **** **** **** **** **** **** **** **** +3364 WordOfNurturingCritical_Reverse **** **** **** **** **** **** **** **** +3365 MetamagicCatalyst **** **** **** **** **** **** **** **** +3366 MetamagicCatalyst_Empower **** **** **** **** **** **** **** **** +3367 MetamagicCatalyst_Extend **** **** **** **** **** **** **** **** +3368 MetamagicCatalyst_Maximize **** **** **** **** **** **** **** **** +3369 SeizeItem **** **** **** **** **** **** **** **** +3370 BreathOfRecovery **** **** **** **** **** **** **** **** +3371 BreathOfRecovery_Normal **** **** **** **** **** **** **** **** +3372 BreathOfRecovery_Reverse **** **** **** **** **** **** **** **** +3373 EtherReforged **** **** **** **** **** **** **** **** +3374 EtherReforged_Normal **** **** **** **** **** **** **** **** +3375 EtherReforged_Reverse **** **** **** **** **** **** **** **** +3376 KnightsPuissanceGreater **** **** **** **** **** **** **** **** +3377 KnightsPuissanceGreater_Normal **** **** **** **** **** **** **** **** +3378 KnightsPuissanceGreater_Reverse **** **** **** **** **** **** **** **** +3379 MysticRampart **** **** **** **** **** **** **** **** +3380 MysticRampart_Normal **** **** **** **** **** **** **** **** +3381 MysticRampart_Reverse **** **** **** **** **** **** **** **** +3382 SingularMind **** **** **** **** **** **** **** **** +3383 SingularMind_Normal **** **** **** **** **** **** **** **** +3384 SingularMind_Reverse **** **** **** **** **** **** **** **** +3385 WordOfNurturingGreater **** **** **** **** **** **** **** **** +3386 WordOfNurturingGreater_Normal **** **** **** **** **** **** **** **** +3387 WordOfNurturingGreater_Reverse **** **** **** **** **** **** **** **** +3388 DRAGON_ALLY **** **** **** **** **** **** **** **** +3389 OnHit_Dragonfire_Inspiration **** **** **** **** **** **** **** **** +3390 Dragonfire_Inspiration_Toggle **** **** **** **** **** **** **** **** +3391 Dragonfire_Assault_Toggle **** **** **** **** **** **** **** **** +3392 Dragonfire_Channeling **** **** **** **** **** **** **** **** +3393 Marrutact_Howl **** **** **** **** **** **** **** **** +3394 BrilliantEnergyArrows **** **** **** R 1 **** **** **** +3395 HideFromAnimals **** **** **** **** **** **** **** **** +3396 Longstrider **** **** **** E 0 3 0 **** +3397 SerpentArrows **** **** **** R 1 **** **** **** +3398 Treeshape **** **** **** **** **** **** **** **** +3399 WaterBreathing **** **** **** **** **** **** **** **** +3400 RECITATION_FORTIFIED **** **** **** **** **** **** **** **** +3401 RECITATION_MEDITATIVE **** **** **** **** **** **** **** **** +3402 RECITATION_MINDFUL **** **** **** **** **** **** **** **** +3403 RECITATION_SANGUINE **** **** **** **** **** **** **** **** +3404 RECITATION_VITAL **** **** **** **** **** **** **** **** +3405 EmpowerUtterance **** **** **** **** **** **** **** **** +3406 ExtendUtterance **** **** **** **** **** **** **** **** +3407 QuickenUtterance **** **** **** **** **** **** **** **** +3408 Truenamer_Ignore_SR **** **** **** **** **** **** **** **** +3409 Truenamer_Crafted_Tool_Target **** **** **** **** **** **** **** **** +3410 Truenamer_Crafted_Tool_Target_Conversation **** **** **** **** **** **** **** **** +3411 Truenamer_Crafted_Tool_Target_Choice1 **** **** **** **** **** **** **** **** +3412 Truenamer_Crafted_Tool_Target_Choice2 **** **** **** **** **** **** **** **** +3413 Truenamer_Crafted_Tool_Target_Choice3 **** **** **** **** **** **** **** **** +3414 Truenamer_Crafted_Tool_Target_Choice4 **** **** **** **** **** **** **** **** +3415 SeeTheNamed **** **** **** **** **** **** **** **** +3416 SpeakUntoTheMasses **** **** **** **** **** **** **** **** +3417 SayMyNameAndIAmThere **** **** **** **** **** **** **** **** +3418 SyllableOfDetachment **** **** **** **** **** **** **** **** +3419 SyllableOfAffliction_Master **** **** **** **** **** **** **** **** +3420 SyllableOfAffliction_Sight **** **** **** **** **** **** **** **** +3421 SyllableOfAffliction_Hearing **** **** **** **** **** **** **** **** +3422 SyllableOfAffliction_Touch **** **** **** **** **** **** **** **** +3423 SyllableOfExile **** **** **** **** **** **** **** **** +3424 SyllableOfDissolution **** **** **** **** **** **** **** **** +3425 SyllableOfEnervation **** **** **** **** **** **** **** **** +3426 Brimstone_TongueOfFire3d6 **** **** **** **** **** **** **** **** +3427 Brimstone_TongueOfFire5d6 **** **** **** **** **** **** **** **** +3428 Brimstone_TongueOfFire8d6 **** **** **** **** **** **** **** **** +3429 Brimstone_LesserHeavenlyEntreaty **** **** **** **** **** **** **** **** +3430 Brimstone_NormalHeavenlyEntreaty **** **** **** **** **** **** **** **** +3431 Brimstone_GreaterHeavenlyEntreaty **** **** **** **** **** **** **** **** +3432 HideFromUndead **** **** **** **** **** **** **** **** +3433 CrushingDespair Mind_Affecting Will 1 I 1 **** **** **** +3434 HaltUndead **** **** **** **** **** **** **** **** +3435 Eyebite **** Fortitude 1 R 1 **** **** **** +3436 SongOfDiscord Mind_Affecting Will 1 I 1 **** **** **** +3437 FireInTheBlood **** **** **** E 0 2 0 **** +3438 VileDeath **** **** **** **** **** **** **** **** +3439 PlagueOfUndead **** **** **** S 0 3 0 -2 +3440 DNecroCharnelTouch **** **** **** **** **** **** **** **** +3441 DNecroScabTouch **** **** **** **** **** **** **** **** +3442 DNecroEnervTouch **** **** **** **** **** **** **** **** +3443 DNecroNegative_Energy_Burst **** **** **** **** **** **** **** **** +3444 DNecroFearAura **** **** **** **** **** **** **** **** +3445 NobleCoord **** **** **** **** **** **** **** **** +3446 NobleFavor **** **** **** **** **** **** **** **** +3447 NobleGreat **** **** **** **** **** **** **** **** +3448 NobleInspire **** **** **** **** **** **** **** **** +3449 Extend_Spell_Ability **** **** **** **** **** **** **** **** +3450 Silent_Spell_Ability **** **** **** **** **** **** **** **** +3451 Still_Spell_Ability **** **** **** **** **** **** **** **** +3452 Empower_Spell_Ability **** **** **** **** **** **** **** **** +3453 Maximize_Spell_Ability **** **** **** **** **** **** **** **** +3454 Quicken_Spell_Ability **** **** **** **** **** **** **** **** +3455 Weapon_Aptitude **** **** **** **** **** **** **** **** +3456 Weapon_Aptitude_Options **** **** **** **** **** **** **** **** +3457 Greater_Resistance **** **** **** P 0 3 14 **** +3458 Superior_Resistance **** **** **** P 0 3 14 **** +3459 Vigor **** **** **** E 0 2 10 -3459 +3460 Lesser_Vigor **** **** **** E 0 2 10 -3459 +3461 Mass_Lesser_Vigor **** **** **** E 0 2 10 -3459 +3462 Vigorous_Circle **** **** **** E 0 2 10 -3459 +3463 Mystic_Barrier **** **** **** **** **** **** **** **** +3464 Cadence_Bull **** **** **** **** **** **** **** **** +3465 Cadence_Iron **** **** **** **** **** **** **** **** +3466 Cadence_Heart **** **** **** **** **** **** **** **** +3467 Cadence_Swallow **** **** **** **** **** **** **** **** +3468 Cadence_Wound **** **** **** **** **** **** **** **** +3469 Cadence_Fool **** **** **** **** **** **** **** **** +3470 Cadence_Fort **** **** **** **** **** **** **** **** +3471 Cadence_Fright **** **** **** **** **** **** **** **** +3472 Cadence_Drake **** **** **** **** **** **** **** **** +3473 Cadence_Step **** **** **** **** **** **** **** **** +3474 ResonantVoice **** **** **** **** **** **** **** **** +3475 Grapple **** **** **** **** **** **** **** **** +3476 Bullrush **** **** **** **** **** **** **** **** +3477 Overrun **** **** **** **** **** **** **** **** +3478 Trip **** **** **** **** **** **** **** **** +3479 Charge **** **** **** **** **** **** **** **** +3480 ChargeBullrush **** **** **** **** **** **** **** **** +3481 GrappleEnd **** **** **** **** **** **** **** **** +3482 CombatMove_RadialMaster **** **** **** **** **** **** **** **** +3483 MasterWand **** **** **** **** **** **** **** **** +3484 RecklessWandWielder **** **** **** **** **** **** **** **** +3485 DoubleWandWielder **** **** **** **** **** **** **** **** +3486 Wandstrike **** **** **** **** **** **** **** **** +3487 WildMage_RandomDeflector **** **** **** **** **** **** **** **** +3488 WildMage_RodOfWonder **** **** **** **** **** **** **** **** +3489 WildMage_Wildstrike **** **** **** **** **** **** **** **** +3490 FMM_SwiftShield **** **** **** **** **** **** **** **** +3491 Disarm **** **** **** **** **** **** **** **** +3492 CombatMove_RadialMaster2 **** **** **** **** **** **** **** **** +3493 RangedDisarm **** **** **** **** **** **** **** **** +3494 Stonechild_Magic_Stone **** **** **** **** **** **** **** **** +3495 FightingDefensively **** **** **** **** **** **** **** **** +3496 CombatMove_RadialMaster3 **** **** **** **** **** **** **** **** +3497 Turn_Cold **** **** **** **** **** **** **** **** +3498 ChosenOfIborighu **** **** **** **** **** **** **** **** +3499 SnowflakeWardance **** **** **** **** **** **** **** **** +3500 Min_aura_1 **** **** **** **** **** **** **** **** +3501 Min_aura_2 **** **** **** **** **** **** **** **** +3502 Min_aura_3 **** **** **** **** **** **** **** **** +3503 Min_aura_4 **** **** **** **** **** **** **** **** +3504 Min_aura_5 **** **** **** **** **** **** **** **** +3505 Min_aura_6 **** **** **** **** **** **** **** **** +3506 Min_aura_7 **** **** **** **** **** **** **** **** +3507 Min_aura_8 **** **** **** **** **** **** **** **** +3508 Min_aura_9 **** **** **** **** **** **** **** **** +3509 Min_aura_10 **** **** **** **** **** **** **** **** +3510 Min_aura_11 **** **** **** **** **** **** **** **** +3511 Maj_aura_1 **** **** **** **** **** **** **** **** +3512 Maj_aura_2 **** **** **** **** **** **** **** **** +3513 Maj_aura_3 **** **** **** **** **** **** **** **** +3514 Maj_aura_4 **** **** **** **** **** **** **** **** +3515 Maj_aura_5 **** **** **** **** **** **** **** **** +3516 Maj_aura_6 **** **** **** **** **** **** **** **** +3517 Maj_aura_7 **** **** **** **** **** **** **** **** +3518 Grant_Move **** **** **** **** **** **** **** **** +3519 Maj_aura_8 **** **** **** **** **** **** **** **** +3520 Maj_aura_9 **** **** **** **** **** **** **** **** +3521 Maj_aura_10 **** **** **** **** **** **** **** **** +3522 Maj_aura_11 **** **** **** **** **** **** **** **** +3523 Maj_aura_12 **** **** **** **** **** **** **** **** +3524 Maj_aura_13 **** **** **** **** **** **** **** **** +3525 **Truenaming_RealUtters** **** **** **** **** **** **** **** **** +3526 Defensive_Edge_Normal **** **** **** **** **** **** **** **** +3527 Defensive_Edge_Reverse **** **** **** **** **** **** **** **** +3528 InertialSurge_Normal **** **** **** **** **** **** **** **** +3529 InertialSurge_Reverse **** **** **** **** **** **** **** **** +3530 KnightsPuissance_Normal **** **** **** **** **** **** **** **** +3531 KnightsPuissance_Reverse **** **** **** **** **** **** **** **** +3532 UniversalAptitude_Normal **** **** **** **** **** **** **** **** +3533 UniversalAptitude_Reverse **** **** **** **** **** **** **** **** +3534 WordOfNurturingMinor_Normal **** **** **** **** **** **** **** **** +3535 WordOfNurturingMinor_Reverse **** **** **** **** **** **** **** **** +3536 FortifyArmour_SneakAttacks **** **** **** **** **** **** **** **** +3537 FortifyArmour_Criticals **** **** **** **** **** **** **** **** +3538 KeenWeapon **** **** **** **** **** **** **** **** +3539 FogOfTheVoid_FogCloud **** **** **** **** **** **** **** **** +3540 FogOfTheVoid_SolidFog **** **** **** **** **** **** **** **** +3541 ShieldOfTheLandscape **** **** **** **** **** **** **** **** +3542 Shockwave **** **** **** **** **** **** **** **** +3543 ArchersEye_Normal **** **** **** **** **** **** **** **** +3544 ArchersEye_Reverse **** **** **** **** **** **** **** **** +3545 HiddenTruth_Normal **** **** **** **** **** **** **** **** +3546 HiddenTruth_Reverse **** **** **** **** **** **** **** **** +3547 PercieveTheUnseen_Normal **** **** **** **** **** **** **** **** +3548 PercieveTheUnseen_Reverse **** **** **** **** **** **** **** **** +3549 SilentCaster_Normal **** **** **** **** **** **** **** **** +3550 SilentCaster_Reverse **** **** **** **** **** **** **** **** +3551 SpeedOfTheZephyr_Normal **** **** **** **** **** **** **** **** +3552 SpeedOfTheZephyr_Reverse **** **** **** **** **** **** **** **** +3553 StrikeOfMight_Normal **** **** **** **** **** **** **** **** +3554 StrikeOfMight_Reverse **** **** **** **** **** **** **** **** +3555 TemporalTwist_Normal **** **** **** **** **** **** **** **** +3556 TemporalTwist_Reverse **** **** **** **** **** **** **** **** +3557 WordOfNurturingLesser_Normal **** **** **** **** **** **** **** **** +3558 WordOfNurturingLesser_Reverse **** **** **** **** **** **** **** **** +3559 AgitateItem_Hot **** **** **** **** **** **** **** **** +3560 AgitateItem_Cold **** **** **** **** **** **** **** **** +3561 AnalyzeIten **** **** **** **** **** **** **** **** +3562 EnergyVortex_Acid **** **** **** **** **** **** **** **** +3563 EnergyVortex_Cold **** **** **** **** **** **** **** **** +3564 EnergyVortex_Elec **** **** **** **** **** **** **** **** +3565 EnergyVortex_Fire **** **** **** **** **** **** **** **** +3566 SpeakRockToMud **** **** **** **** **** **** **** **** +3567 TransformTheLandscape **** **** **** **** **** **** **** **** +3568 AcceleratedAttack_Normal **** **** **** **** **** **** **** **** +3569 AcceleratedAttack_Reverse **** **** **** **** **** **** **** **** +3570 EnergyNegation_Normal **** **** **** **** **** **** **** **** +3571 EnergyNegation_Reverse **** **** **** **** **** **** **** **** +3572 IncarnationOfAngels_Normal **** **** **** **** **** **** **** **** +3573 IncarnationOfAngels_Reverse **** **** **** **** **** **** **** **** +3574 SpeedOfTheZephyrGreater_Normal **** **** **** **** **** **** **** **** +3575 SpeedOfTheZephyrGreater_Reverse **** **** **** **** **** **** **** **** +3576 TemporalSpiral_Normal **** **** **** **** **** **** **** **** +3577 TemporalSpiral_Reverse **** **** **** **** **** **** **** **** +3578 VisionSharpened_Normal **** **** **** **** **** **** **** **** +3579 VisionSharpened_Reverse **** **** **** **** **** **** **** **** +3580 WordOfNurturingModerate_Normal **** **** **** **** **** **** **** **** +3581 WordOfNurturingModerate_Reverse **** **** **** **** **** **** **** **** +3582 RemoveItem **** **** **** **** **** **** **** **** +3583 SuppressWeapon **** **** **** **** **** **** **** **** +3584 LoreOfTheWorld **** **** **** **** **** **** **** **** +3585 MasterTheFourWinds **** **** **** **** **** **** **** **** +3586 ThwartTheTraveller **** **** **** **** **** **** **** **** +3587 BreathOfCleansing_Normal **** **** **** **** **** **** **** **** +3588 BreathOfCleansing_Reverse **** **** **** **** **** **** **** **** +3589 CasterLens_Normal **** **** **** **** **** **** **** **** +3590 CasterLens_Reverse **** **** **** **** **** **** **** **** +3591 ConfoundingResistance_Normal **** **** **** **** **** **** **** **** +3592 ConfoundingResistance_Reverse **** **** **** **** **** **** **** **** +3593 MoraleBoost_Normal **** **** **** **** **** **** **** **** +3594 MoraleBoost_Reverse **** **** **** **** **** **** **** **** +3595 MagicalContraction_Normal **** **** **** **** **** **** **** **** +3596 MagicalContraction_Reverse **** **** **** **** **** **** **** **** +3597 SpellRebirth_Normal **** **** **** **** **** **** **** **** +3598 SpellRebirth_Reverse **** **** **** **** **** **** **** **** +3599 WordOfNurturingPotent_Normal **** **** **** **** **** **** **** **** +3600 WordOfNurturingPotent_Reverse **** **** **** **** **** **** **** **** +3601 WordOfBolstering_Normal **** **** **** **** **** **** **** **** +3602 WordOfBolstering_Reverse **** **** **** **** **** **** **** **** +3603 SuppressItem **** **** **** **** **** **** **** **** +3604 TransmuteWeapon **** **** **** **** **** **** **** **** +3605 AngerTheSleepingEarth **** **** **** **** **** **** **** **** +3606 ConjunctiveGate **** **** **** **** **** **** **** **** +3607 DenyPassage **** **** **** **** **** **** **** **** +3608 EldritchAttraction_Normal **** **** **** **** **** **** **** **** +3609 EldritchAttraction_Reverse **** **** **** **** **** **** **** **** +3610 EnergyNegationGreater_Normal **** **** **** **** **** **** **** **** +3611 EnergyNegationGreater_Reverse **** **** **** **** **** **** **** **** +3612 EssenceOfLifespark_Normal **** **** **** **** **** **** **** **** +3613 EssenceOfLifespark_Reverse **** **** **** **** **** **** **** **** +3614 PreturnaturalClarity_Attack **** **** **** **** **** **** **** **** +3615 PreturnaturalClarity_Skill **** **** **** **** **** **** **** **** +3616 PreturnaturalClarity_Save **** **** **** **** **** **** **** **** +3617 PreturnaturalClarity_Reverse **** **** **** **** **** **** **** **** +3618 SensoryFocus_Normal **** **** **** **** **** **** **** **** +3619 SensoryFocus_Reverse **** **** **** **** **** **** **** **** +3620 WardOfPeace_Normal **** **** **** **** **** **** **** **** +3621 WardOfPeace_Reverse **** **** **** **** **** **** **** **** +3622 WordOfNurturingCritical_Normal **** **** **** **** **** **** **** **** +3623 WordOfNurturingCritical_Reverse **** **** **** **** **** **** **** **** +3624 MetamagicCatalyst_Empower **** **** **** **** **** **** **** **** +3625 MetamagicCatalyst_Extend **** **** **** **** **** **** **** **** +3626 MetamagicCatalyst_Maximize **** **** **** **** **** **** **** **** +3627 SeizeItem **** **** **** **** **** **** **** **** +3628 BreathOfRecovery_Normal **** **** **** **** **** **** **** **** +3629 BreathOfRecovery_Reverse **** **** **** **** **** **** **** **** +3630 EtherReforged_Normal **** **** **** **** **** **** **** **** +3631 EtherReforged_Reverse **** **** **** **** **** **** **** **** +3632 KnightsPuissanceGreater_Normal **** **** **** **** **** **** **** **** +3633 KnightsPuissanceGreater_Reverse **** **** **** **** **** **** **** **** +3634 MysticRampart_Normal **** **** **** **** **** **** **** **** +3635 MysticRampart_Reverse **** **** **** **** **** **** **** **** +3636 SingularMind_Normal **** **** **** **** **** **** **** **** +3637 SingularMind_Reverse **** **** **** **** **** **** **** **** +3638 WordOfNurturingGreater_Normal **** **** **** **** **** **** **** **** +3639 WordOfNurturingGreater_Reverse **** **** **** **** **** **** **** **** +3640 **** **** **** **** **** **** **** **** **** +3641 Wild_Shape_Plant **** **** **** **** **** **** **** **** +3642 Wild_Shape_Plant_01 **** **** **** **** **** **** **** **** +3643 Wild_Shape_Plant_02 **** **** **** **** **** **** **** **** +3644 Wild_Shape_Plant_03 **** **** **** **** **** **** **** **** +3645 Wild_Shape_Plant_04 **** **** **** **** **** **** **** **** +3646 Wild_Shape_Plant_05 **** **** **** **** **** **** **** **** +3647 **** **** **** **** **** **** **** **** **** +3648 **** **** **** **** **** **** **** **** **** +3649 Unseen_Weapon_Activate **** **** **** **** **** **** **** **** +3650 Unseen_Weapon_Unerring_Strike **** **** **** **** **** **** **** **** +3651 Unseen_Weapon_Unexpected_Strike **** **** **** **** **** **** **** **** +3652 Unseen_Weapon_Ephemeral_Weapon **** **** **** **** **** **** **** **** +3653 Unseen_Weapon_Shadowy_Strike **** **** **** **** **** **** **** **** +3654 Unseen_Weapon_Far_Shadow **** **** **** **** **** **** **** **** +3655 GreaterScrying **** **** **** **** **** **** **** **** +3656 DiscernLocation **** **** **** **** **** **** **** **** +3657 LocateCreature **** **** **** **** **** **** **** **** +3658 LocateObject **** **** **** **** **** **** **** **** +3659 ArcaneEye **** **** **** **** **** **** **** **** +3660 ObscureObject **** **** **** **** **** **** **** **** +3661 Sequester **** **** **** **** **** **** **** **** +3662 SarcophagusOfStone **** Reflex **** R 1 **** **** **** +3663 ArrowOfBone **** **** **** **** **** **** **** **** +3664 DraconicMight **** **** **** E 0 2 9 **** +3665 ExtractWaterElemental **** Fortitude 1 R 1 **** **** **** +3666 HeartRipper **** **** **** **** **** **** **** **** +3667 LifeBolt **** **** **** **** **** **** **** **** +3668 RainbowBlast **** Reflex 1 I 1 **** **** **** +3669 ToweringOak **** **** **** E 0 2 0 **** +3670 LifeBolt1Bolt **** **** **** **** **** **** **** **** +3671 LifeBolt2Bolts **** **** **** **** **** **** **** **** +3672 LifeBolt3Bolts **** **** **** **** **** **** **** **** +3673 LifeBolt4Bolts **** **** **** **** **** **** **** **** +3674 LifeBolt5Bolts **** **** **** **** **** **** **** **** +3675 DisruptUndead **** **** **** **** **** **** **** **** +3676 Otilukes_Resilient_Sphere **** Reflex 1 R 1 **** **** **** +3677 FistOfStone **** **** **** E 0 2 0 **** +3678 BladesOfFire **** **** **** E 0 2 15 **** +3679 FireTrap **** **** **** **** **** **** **** **** +3680 Pyrotechnics **** **** **** **** **** **** **** **** +3681 IceKnife **** **** **** **** **** **** **** **** +3682 MassFireShieldRed **** **** **** **** **** **** **** **** +3683 WhirlingBlade **** **** **** I 1 **** **** **** +3684 PnP_FireShield **** **** **** **** **** **** **** **** +3685 RingOfBlades **** **** **** E 0 2 7 **** +3686 SleetStorm **** **** **** I 1 **** **** **** +3687 OrbOfForce **** **** **** R 1 **** **** **** +3688 MassFireShield **** **** **** **** **** **** **** **** +3689 PrismaticRay **** Reflex 1 R 1 **** **** **** +3690 SwordsageRecoverManeuver **** **** **** **** **** **** **** **** +3691 OtilukesFreezingSphere Cold Reflex 1 I 1 **** **** **** +3692 WavesOfExhaustion **** **** 1 I 1 **** **** **** +3693 PrismaticWall **** Reflex 1 I 1 **** **** **** +3694 ScintillatingPattern Mind_Affecting **** 1 I 1 **** **** **** +3695 PrismaticSphere **** **** **** P 0 2 0 **** +3696 Pyrotechnics_Fireworks **** **** **** **** **** **** **** **** +3697 Pyrotechnics_Smoke **** **** **** **** **** **** **** **** +3698 GreaterDisruptUndead **** **** **** **** **** **** **** **** +3699 PnP_FireShieldRed **** **** **** **** **** **** **** **** +3700 PnPFireShieldBlue **** **** **** **** **** **** **** **** +3701 MassFireShieldBlue **** **** **** **** **** **** **** **** +3702 ArrowStorm **** **** **** **** **** **** **** **** +3703 ArrowSplit **** **** **** R 1 **** **** **** +3704 BloodfreezeArrow Cold Fortitude 1 R 1 **** **** **** +3705 DischargeCrown **** **** **** **** **** **** **** **** +3706 DoublestrikeArrow **** **** **** D 1 **** **** **** +3707 DetectFavoredEnemies **** **** **** **** **** **** **** **** +3708 DarkflameArrow **** **** 1 R 1 **** **** **** +3709 HealAnimalCompanion **** **** **** **** **** **** **** **** +3710 ShadowArrow **** **** 1 R 1 **** **** **** +3711 Snare **** **** **** **** **** **** **** **** +3712 SpellslayerArrow **** **** 1 R 1 **** **** **** +3713 AcidicFire **** **** **** **** **** **** **** **** +3714 AlchemistsFrost **** **** **** **** **** **** **** **** +3715 AlchemicalSleepingGas **** **** **** **** **** **** **** **** +3716 AlchemistsSpark **** **** **** **** **** **** **** **** +3717 BlendCream **** **** **** **** **** **** **** **** +3718 Brittlebone **** **** **** **** **** **** **** **** +3719 Cracklepowder **** **** **** **** **** **** **** **** +3720 EmbalmingFire **** **** **** **** **** **** **** **** +3721 FareyeOil **** **** **** **** **** **** **** **** +3722 FesteringBomb **** **** **** **** **** **** **** **** +3723 FlashPellet **** **** **** **** **** **** **** **** +3724 HealersBalm **** **** **** **** **** **** **** **** +3725 KeenearPowder **** **** **** **** **** **** **** **** +3726 LockslipGrease **** **** **** **** **** **** **** **** +3727 NaturesDraught **** **** **** **** **** **** **** **** +3728 Nerv **** **** **** **** **** **** **** **** +3729 ScreamingFlask **** **** **** **** **** **** **** **** +3730 Softfoot **** **** **** **** **** **** **** **** +3731 WeepingStone **** **** **** **** **** **** **** **** +3732 BileDroppings **** **** **** **** **** **** **** **** +3733 Shedden **** **** **** **** **** **** **** **** +3734 Shedden2 **** **** **** **** **** **** **** **** +3735 Shedden3 **** **** **** **** **** **** **** **** +3736 Shedden4 **** **** **** **** **** **** **** **** +3737 Shedden5 **** **** **** **** **** **** **** **** +3738 Antitoxin **** **** **** **** **** **** **** **** +3739 SuddenRecover **** **** **** **** **** **** **** **** +3740 SongWhiteRaven **** **** **** **** **** **** **** **** +3741 StonePower **** **** **** **** **** **** **** **** +3742 MorphemeSavant_Master **** **** **** **** **** **** **** **** +3743 ShadowmasterConceal **** **** **** **** **** **** **** **** +3744 Shadowmaster_Shades_Master **** **** **** **** **** **** **** **** +3745 Shadowmaster_Summon_Shadow **** **** **** **** **** **** **** **** +3746 Shadowmaster_Cone_of_Cold **** **** **** **** **** **** **** **** +3747 Shadowmaster_Fireball **** **** **** **** **** **** **** **** +3748 Shadowmaster_Stoneskin **** **** **** **** **** **** **** **** +3749 Shadowmaster_Wall_of_Fire **** **** **** **** **** **** **** **** +3750 MorphemeSavantKill **** **** **** **** **** **** **** **** +3751 MorphemeSavantStun **** **** **** **** **** **** **** **** +3752 MasterOfElements_Master **** **** **** **** **** **** **** **** +3753 MasterOfElements_SummonAir **** **** **** **** **** **** **** **** +3754 MasterOfElements_SummonEarth **** **** **** **** **** **** **** **** +3755 MasterOfElements_SummonFire **** **** **** **** **** **** **** **** +3756 MasterOfElements_SummonWater **** **** **** **** **** **** **** **** +3757 MasterOfElements_Dominate **** **** **** **** **** **** **** **** +3758 LordOfAllEssences **** **** **** **** **** **** **** **** +3759 TouchVitality_Master **** **** **** **** **** **** **** **** +3760 PresenceAura **** **** **** **** **** **** **** **** +3761 VigorAura **** **** **** **** **** **** **** **** +3762 ToughnesAura **** **** **** **** **** **** **** **** +3763 EnergyShldAura **** **** **** **** **** **** **** **** +3764 ResistanceAura **** **** **** **** **** **** **** **** +3765 PowerAura **** **** **** **** **** **** **** **** +3766 SenseAura **** **** **** **** **** **** **** **** +3767 TouchVitality **** **** **** **** **** **** **** **** +3768 TouchVitalityMinor **** **** **** **** **** **** **** **** +3769 TouchVitalityRestore **** **** **** **** **** **** **** **** +3770 TouchVitalityMajor **** **** **** **** **** **** **** **** +3771 DragonShamanBreath **** **** **** **** **** **** **** **** +3772 InsightAura **** **** **** **** **** **** **** **** +3773 ResolveAura **** **** **** **** **** **** **** **** +3774 StaminaAura **** **** **** **** **** **** **** **** +3775 SwiftnessAura **** **** **** **** **** **** **** **** +3776 BonusResistAcidAura **** **** **** **** **** **** **** **** +3777 BonusResistColdAura **** **** **** **** **** **** **** **** +3778 BonusResistElecAura **** **** **** **** **** **** **** **** +3779 BonusResistFireAura **** **** **** **** **** **** **** **** +3780 MarshalInsightAura **** **** **** **** **** **** **** **** +3781 MarshalPresenceAura **** **** **** **** **** **** **** **** +3782 MarshalResistAcidAura **** **** **** **** **** **** **** **** +3783 MarshalResistColdAura **** **** **** **** **** **** **** **** +3784 MarshalResistElecAura **** **** **** **** **** **** **** **** +3785 MarshalResistFireAura **** **** **** **** **** **** **** **** +3786 MarshalResolveAura **** **** **** **** **** **** **** **** +3787 MarshalSensesAura **** **** **** **** **** **** **** **** +3788 MarshalStaminaAura **** **** **** **** **** **** **** **** +3789 MarshalSwiftnessAura **** **** **** **** **** **** **** **** +3790 MarshalToughnessAura **** **** **** **** **** **** **** **** +3791 DivineIntercession **** **** **** **** **** **** **** **** +3792 ProfaneAgony **** **** **** **** **** **** **** **** +3793 LolthsBoon **** **** **** **** **** **** **** **** +3794 Snap_Kick **** **** **** **** **** **** **** **** +3795 Verminlord_Master **** **** **** **** **** **** **** **** +3796 Verminlord_CreepingDoom **** **** **** **** **** **** **** **** +3797 Verminlord_Dominate_Vermin **** **** **** **** **** **** **** **** +3798 DespanaSchool **** **** **** **** **** **** **** **** +3799 Crinti_ShadowRide **** **** **** **** **** **** **** **** +3800 Crinti_ShadowWalk **** **** **** **** **** **** **** **** +3801 Earth_Strike **** **** **** **** **** **** **** **** +3802 FrostFolk_IceBlast **** **** **** **** **** **** **** **** +3803 TouchFatigue **** Fortitude 1 T 1 **** **** **** +3804 Uldra_Ray_of_Frost **** **** **** **** **** **** **** **** +3805 Uldra_TouchFatigue **** **** **** **** **** **** **** **** +3806 BonusInsightAura **** **** **** **** **** **** **** **** +3807 BonusPresenceAura **** **** **** **** **** **** **** **** +3808 BonusResolveAura **** **** **** **** **** **** **** **** +3809 BonusSensesAura **** **** **** **** **** **** **** **** +3810 BonusStaminaAura **** **** **** **** **** **** **** **** +3811 BonusSwiftnessAura **** **** **** **** **** **** **** **** +3812 BonusToughnessAura **** **** **** **** **** **** **** **** +3813 MagicPowerAura **** **** **** **** **** **** **** **** +3814 MarshalMagicPowerAura **** **** **** **** **** **** **** **** +3815 BonusMagicPowerAura **** **** **** **** **** **** **** **** +3816 Marrulurk_NauseatingBreath **** **** **** **** **** **** **** **** +3817 EnergyAura **** **** **** **** **** **** **** **** +3818 MarshalAcidEnergyAura **** **** **** **** **** **** **** **** +3819 MarshalColdEnergyAura **** **** **** **** **** **** **** **** +3820 MarshalElecEnergyAura **** **** **** **** **** **** **** **** +3821 MarshalFireEnergyAura **** **** **** **** **** **** **** **** +3822 BonusAcidEnergyAura **** **** **** **** **** **** **** **** +3823 BonusColdEnergyAura **** **** **** **** **** **** **** **** +3824 BonusElecEnergyAura **** **** **** **** **** **** **** **** +3825 BonusFireEnergyAura **** **** **** **** **** **** **** **** +3826 ExtaminaarCharmAnimal **** **** **** **** **** **** **** **** +3827 SuddenStalagmite **** Reflex **** R 1 **** **** **** +3828 BonesOfTheEarth **** **** **** **** **** **** **** **** +3829 BonesOfTheEarth_Feat **** **** **** **** **** **** **** **** +3830 Hallow **** **** **** **** **** **** **** **** +3831 DauntingPresence **** **** **** **** **** **** **** **** +3832 ProfaneLifeleech **** **** **** **** **** **** **** **** +3833 SacredVitality **** **** **** **** **** **** **** **** +3834 SacredVengeance **** **** **** **** **** **** **** **** +3835 Deformity(eyes) **** **** **** **** **** **** **** **** +3836 Deformity(parasite) **** **** **** **** **** **** **** **** +3837 DarkSpeech **** **** **** **** **** **** **** **** +3838 DarkSpeechDread **** **** **** **** **** **** **** **** +3839 DarkSpeechPower **** **** **** **** **** **** **** **** +3840 DarkWhispers **** **** **** **** **** **** **** **** +3841 Deformity(madness) **** **** **** **** **** **** **** **** +3842 ReflexivePsychosis **** **** **** **** **** **** **** **** +3843 ChosenOfEvil **** **** **** **** **** **** **** **** +3844 MastersWill **** **** **** **** **** **** **** **** +3845 ChosenOfEvilAttack **** **** **** **** **** **** **** **** +3846 ChosenOfEvilSkill **** **** **** **** **** **** **** **** +3847 ChosenOfEvilSave **** **** **** **** **** **** **** **** +3848 ShieldOther **** **** **** P 0 3 9 **** +3849 TensersFloatingDisk **** **** **** **** **** **** **** **** +3850 Wolfskin **** **** **** P 0 2 0 -17 +3851 True_Casting **** **** **** **** **** **** **** **** +3852 Mass_Spell_Resistance **** **** **** P 0 2 14 **** +3853 Magic_Stone **** **** **** **** **** **** **** **** +3854 Control_Weather **** **** **** **** **** **** **** **** +3855 CW_Rain **** **** **** **** **** **** **** **** +3856 CW_Snow **** **** **** **** **** **** **** **** +3857 CW_Clear **** **** **** **** **** **** **** **** +3858 Glyph_of_Warding_Acid **** **** **** **** **** **** **** **** +3859 Glyph_of_Warding_Cold **** **** **** **** **** **** **** **** +3860 Glyph_of_Warding_Electricity **** **** **** **** **** **** **** **** +3861 Glyph_of_Warding_Fire **** **** **** **** **** **** **** **** +3862 Glyph_of_Warding_Sonic **** **** **** **** **** **** **** **** +3863 Greater_Glyph_of_Warding_Master **** **** **** **** **** **** **** **** +3864 Greater_Glyph_of_Warding_Acid **** **** **** **** **** **** **** **** +3865 Greater_Glyph_of_Warding_Cold **** **** **** **** **** **** **** **** +3866 Greater_Glyph_of_Warding_Electricity **** **** **** **** **** **** **** **** +3867 Greater_Glyph_of_Warding_Fire **** **** **** **** **** **** **** **** +3868 Greater_Glyph_of_Warding_Sonic **** **** **** **** **** **** **** **** +3869 Elder_Glyph_of_Warding_Master **** **** **** **** **** **** **** **** +3870 Elder_Glyph_of_Warding_Acid **** **** **** **** **** **** **** **** +3871 Elder_Glyph_of_Warding_Cold **** **** **** **** **** **** **** **** +3872 Elder_Glyph_of_Warding_Electricity **** **** **** **** **** **** **** **** +3873 Elder_Glyph_of_Warding_Fire **** **** **** **** **** **** **** **** +3874 Elder_Glyph_of_Warding_Sonic **** **** **** **** **** **** **** **** +3875 Elemental_Strike **** **** **** **** **** **** **** **** +3876 Elemental_Strike_Acid **** **** **** **** **** **** **** **** +3877 Elemental_Strike_Cold **** **** **** **** **** **** **** **** +3878 Elemental_Strike_Electricity **** **** **** **** **** **** **** **** +3879 Elemental_Strike_Fire **** **** **** **** **** **** **** **** +3880 Elemental_Strike_Sonic **** **** **** **** **** **** **** **** +3881 WordOfRecall_RadialMaster **** **** **** **** **** **** **** **** +3882 WordOfRecall_SelfOnly **** **** **** **** **** **** **** **** +3883 WordOfRecall_Party **** **** **** **** **** **** **** **** +3884 TransportViaPlants_RadialMaster **** **** **** **** **** **** **** **** +3885 TransportViaPlants_SelfOnly **** **** **** **** **** **** **** **** +3886 TransportViaPlants_Party **** **** **** **** **** **** **** **** +3887 Factotum_ArcaneDilettante_1 **** **** **** **** **** **** **** **** +3888 Factotum_ArcaneDilettante_2 **** **** **** **** **** **** **** **** +3889 Factotum_ArcaneDilettante_3 **** **** **** **** **** **** **** **** +3890 Factotum_ArcaneDilettante_4 **** **** **** **** **** **** **** **** +3891 Factotum_ArcaneDilettante_5 **** **** **** **** **** **** **** **** +3892 Factotum_ArcaneDilettante_6 **** **** **** **** **** **** **** **** +3893 Factotum_ArcaneDilettante_7 **** **** **** **** **** **** **** **** +3894 Factotum_ArcaneDilettante_8 **** **** **** **** **** **** **** **** +3895 Factotum_Cunning_Insight_Attack **** **** **** **** **** **** **** **** +3896 Factotum_Cunning_Insight_Damage **** **** **** **** **** **** **** **** +3897 Factotum_Cunning_Insight_Saves **** **** **** **** **** **** **** **** +3898 Factotum_Cunning_Defense **** **** **** **** **** **** **** **** +3899 Factotum_Cunning_Strike **** **** **** **** **** **** **** **** +3900 Factotum_Cunning_Surge **** **** **** **** **** **** **** **** +3901 Factotum_Cunning_Breach **** **** **** **** **** **** **** **** +3902 Factotum_Cunning_Dodge **** **** **** **** **** **** **** **** +3903 Factotum_Cunning_Knowledge **** **** **** **** **** **** **** **** +3904 Factotum_Opportunistic_Piety_Heal **** **** **** **** **** **** **** **** +3905 Factotum_Opportunistic_Piety_Turn **** **** **** **** **** **** **** **** +3906 Factotum_ArcaneDilettante_SlotCheck **** **** **** **** **** **** **** **** +3907 Sharess_Fascinate **** **** **** **** **** **** **** **** +3908 Sharess_Confuse **** **** **** **** **** **** **** **** +3909 Sharess_Dominate **** **** **** **** **** **** **** **** +3910 Sharess_Sanctuary **** **** **** **** **** **** **** **** +3911 Sharess_Haste **** **** **** **** **** **** **** **** +3912 ForceOrb **** Reflex 1 R 1 **** **** **** +3913 Forsaker_FastHealing **** **** **** **** **** **** **** **** +3914 AugmentTrueFriend **** **** **** **** **** **** **** **** +3915 UrPriestSiphonSpellPower **** **** **** **** **** **** **** **** +3916 UrPriestSiphonSpellPower_Conv **** **** **** **** **** **** **** **** +3917 Factotum_CunningBrilliance_1 **** **** **** **** **** **** **** **** +3918 Factotum_CunningBrilliance_2 **** **** **** **** **** **** **** **** +3919 Factotum_CunningBrilliance_3 **** **** **** **** **** **** **** **** +3920 Factotum_CunningBrilliance_SlotCheck **** **** **** **** **** **** **** **** +3921 Arkamoi_ArcaneMastermind **** **** **** **** **** **** **** **** +3922 AlignedAura **** **** **** **** **** **** **** **** +3923 Angelskin **** **** **** **** **** **** **** **** +3924 AxiomaticStorm **** **** **** **** **** **** **** **** +3925 Bladebane **** **** **** **** **** **** **** **** +3926 BlessedAim **** **** **** **** **** **** **** **** +3927 BlessingOfTheRighteous **** **** **** **** **** **** **** **** +3928 ClearMind **** **** **** **** **** **** **** **** +3929 CloakOfBravery **** **** **** **** **** **** **** **** +3930 Diamondsteel **** **** **** **** **** **** **** **** +3931 LesserAspectOfTheDiety **** **** **** **** **** **** **** **** +3932 LawfulSword **** **** **** **** **** **** **** **** +3933 LesserAuraOfCold **** **** **** **** **** **** **** **** +3934 AuraOfTheSun **** **** **** **** **** **** **** **** +3935 RighteousFury **** **** **** **** **** **** **** **** +3936 SeekEternalRest **** **** **** **** **** **** **** **** +3937 StrengthOfStone **** **** **** **** **** **** **** **** +3938 UndeadBaneWeapon **** **** **** **** **** **** **** **** +3939 LesserViageOfTheDiety **** **** **** **** **** **** **** **** +3940 AlignedAuraChaos **** **** **** **** **** **** **** **** +3941 AlignedAuraEvil **** **** **** **** **** **** **** **** +3942 AlignedAuraGood **** **** **** **** **** **** **** **** +3943 AlignedAuraLaw **** **** **** **** **** **** **** **** +3944 AxiomaticWater **** **** **** **** **** **** **** **** +3945 BlazeOfLight **** **** **** **** **** **** **** **** +3946 CallMount **** **** **** **** **** **** **** **** +3947 Castigate **** **** **** **** **** **** **** **** +3948 CheckmatesLight **** **** **** **** **** **** **** **** +3949 ConduitOfLight **** **** **** **** **** **** **** **** +3950 CurseOfTheBrute **** **** **** **** **** **** **** **** +3951 Denounce **** **** **** **** **** **** **** **** +3952 DevastatingSmite **** **** **** **** **** **** **** **** +3953 DivinePresence **** **** **** **** **** **** **** **** +3954 EmbraceOfEndlessDay **** **** **** **** **** **** **** **** +3955 EnergizedShield **** **** **** **** **** **** **** **** +3956 LesserEnergizedShield **** **** **** **** **** **** **** **** +3957 EstanasStew **** **** **** **** **** **** **** **** +3958 FavorOfTheMartyr **** **** **** **** **** **** **** **** +3959 Forceward **** **** **** **** **** **** **** **** +3960 GloryOfTheMartyr **** **** **** **** **** **** **** **** +3961 HolyFire **** **** **** **** **** **** **** **** +3962 HolyStorm **** **** **** **** **** **** **** **** +3963 InvokeTheCeruleanSign **** **** **** **** **** **** **** **** +3964 IrresistibleForce **** **** **** **** **** **** **** **** +3965 LegionsMagicWeapon **** **** **** **** **** **** **** **** +3966 MajorResistance **** **** **** **** **** **** **** **** +3967 MeteoricStrike **** **** **** **** **** **** **** **** +3968 QuickMarch **** **** **** **** **** **** **** **** +3969 ResistEnergy **** **** **** **** **** **** **** **** +3970 Revenance **** **** **** **** **** **** **** **** +3971 RhinosRush **** **** **** **** **** **** **** **** +3972 RighteousAura **** **** **** **** **** **** **** **** +3973 SeedOfLife **** **** **** **** **** **** **** **** +3974 ShieldOfWarding **** **** **** **** **** **** **** **** +3975 SmiteHeretic **** **** **** **** **** **** **** **** +3976 SmiteOfSacredFire **** **** **** **** **** **** **** **** +3977 SoldiersOfSanctity **** **** **** **** **** **** **** **** +3978 SoulOfLight **** **** **** **** **** **** **** **** +3979 SoulOfOrder **** **** **** **** **** **** **** **** +3980 Stabilize **** **** **** **** **** **** **** **** +3981 StrategicCharge **** **** **** **** **** **** **** **** +3982 TouchOfRestoration **** **** **** **** **** **** **** **** +3983 TruePrayerOfTheChosen **** **** **** **** **** **** **** **** +3984 TruePrayerOfTheFaithful **** **** **** **** **** **** **** **** +3985 UnmovableIbject **** **** **** **** **** **** **** **** +3986 BFZ_FatefulStride **** **** **** **** **** **** **** **** +3987 TN_DES_100 **** **** **** **** **** **** **** **** +3988 TN_DES_20 **** **** **** **** **** **** **** **** +3989 Hext_Fright **** **** **** **** **** **** **** **** +3990 INSTRUMENT **** **** **** **** **** **** **** **** +3991 LLIIRAS_AURA **** **** **** **** **** **** **** **** +3992 MIELIKKI_TRUTH **** **** **** **** **** **** **** **** +3993 LYCANBANE **** **** **** **** **** **** **** **** +3994 CRAFT_MHARPER_ITEM **** **** **** **** **** **** **** **** +3995 Shou_Flurry **** **** **** **** **** **** **** **** +3996 TN_Unsummon **** **** **** **** **** **** **** **** +3997 Summon_fiend **** **** **** **** **** **** **** **** +3998 Pit_Glare **** **** **** **** **** **** **** **** +3999 Fiendish_Glare **** **** **** **** **** **** **** **** +4000 Epic_Spell_Achilles_Heel **** **** **** **** **** **** **** **** +4001 Epic_Spell_All_Hope_Lost **** **** **** **** **** **** **** **** +4002 Epic_Spell_Allied_Martyr **** **** **** **** **** **** **** **** +4003 Epic_Spell_Anarchys_Call **** **** **** **** **** **** **** **** +4004 Epic_Spell_Animus_Blast **** **** **** **** **** **** **** **** +4005 Epic_Spell_Animus_Blizzard **** **** **** **** **** **** **** **** +4006 Epic_Spell_Army_Unfallen **** **** **** **** **** **** **** **** +4007 Epic_Spell_Audience_of_Stone **** **** **** **** **** **** **** **** +4008 Epic_Spell_Battle_Bounding **** **** **** **** **** **** **** **** +4009 Epic_Spell_Celestial_Council **** **** **** **** **** **** **** **** +4010 Epic_Spell_Champions_Valor **** **** **** **** **** **** **** **** +4011 Epic_Spell_Contingent_Resurrection **** **** **** **** **** **** **** **** +4012 Epic_Spell_Contingent_Reunion **** **** **** **** **** **** **** **** +4013 Epic_Spell_Deadeye_Sense **** **** **** **** **** **** **** **** +4014 Epic_Spell_Deathmark **** **** **** **** **** **** **** **** +4015 Epic_Spell_Dire_Winter **** **** **** **** **** **** **** **** +4016 Epic_Spell_Dragon_Knight **** **** **** **** **** **** **** **** +4017 Epic_Spell_Dreamscape **** **** **** **** **** **** **** **** +4018 Epic_Spell_Dullblades **** **** **** **** **** **** **** **** +4019 Epic_Spell_Dweomer_Thief **** **** **** **** **** **** **** **** +4020 Epic_Spell_Enslave **** **** **** **** **** **** **** **** +4021 Epic_Spell_Epic_Mage_Armor **** **** **** **** **** **** **** **** +4022 Epic_Spell_Epic_Repulsion **** **** **** **** **** **** **** **** +4023 Epic_Spell_Epic_Spell_Reflection **** **** **** **** **** **** **** **** +4024 Epic_Spell_Epic_Warding **** **** **** **** **** **** **** **** +4025 Epic_Spell_Eternal_Freedom **** **** **** **** **** **** **** **** +4026 Epic_Spell_Fiendish_Words **** **** **** **** **** **** **** **** +4027 Epic_Spell_Fleetness_of_Foot **** **** **** **** **** **** **** **** +4028 Epic_Spell_Gem_Cage **** **** **** **** **** **** **** **** +4029 Epic_Spell_Godsmite **** **** **** **** **** **** **** **** +4030 Epic_Spell_Greater_Ruin **** **** **** **** **** **** **** **** +4031 Epic_Spell_Greater_Spell_Resistance **** **** **** **** **** **** **** **** +4032 Epic_Spell_Greater_Timestop **** **** **** **** **** **** **** **** +4033 Epic_Spell_Hell_Send **** **** **** **** **** **** **** **** +4034 Epic_Spell_Hellball **** **** **** **** **** **** **** **** +4035 Epic_Spell_Herculean_Alliance **** **** **** **** **** **** **** **** +4036 Epic_Spell_Herculean_Empowerment **** **** **** **** **** **** **** **** +4037 Epic_Spell_Impenetrability **** **** **** **** **** **** **** **** +4038 Epic_Spell_Leech_Field **** **** **** **** **** **** **** **** +4039 Epic_Spell_Legendary_Artisan **** **** **** **** **** **** **** **** +4040 Epic_Spell_Life_Force_Transfer **** **** **** **** **** **** **** **** +4041 Epic_Spell_Magma_Burst **** **** **** **** **** **** **** **** +4042 Epic_Spell_Mass_Penguin **** **** **** **** **** **** **** **** +4043 Epic_Spell_Momento_Mori **** **** **** **** **** **** **** **** +4044 Epic_Spell_Mummy_Dust **** **** **** **** **** **** **** **** +4045 Epic_Spell_Nailed_to_the_Sky **** **** **** **** **** **** **** **** +4046 Epic_Spell_Nights_Undoing **** **** **** **** **** **** **** **** +4047 Epic_Spell_Order_Restored **** **** **** **** **** **** **** **** +4048 Epic_Spell_Paths_Become_Known **** **** **** **** **** **** **** **** +4049 Epic_Spell_Peerless_Penitence **** **** **** **** **** **** **** **** +4050 Epic_Spell_Pestilence **** **** **** **** **** **** **** **** +4051 Epic_Spell_Pious_Parley **** **** **** **** **** **** **** **** +4052 Epic_Spell_Planar_Cell **** **** **** **** **** **** **** **** +4053 Epic_Spell_Psionic_Salvo **** **** **** **** **** **** **** **** +4054 Epic_Spell_Rain_of_Fire **** **** **** **** **** **** **** **** +4055 Epic_Spell_Risen_Reunited **** **** **** **** **** **** **** **** +4056 Epic_Spell_Ruin **** **** **** **** **** **** **** **** +4057 Epic_Spell_Singular_Sunder **** **** **** **** **** **** **** **** +4058 Epic_Spell_Spell_Worm **** **** **** **** **** **** **** **** +4059 Epic_Spell_Storm_Mantle **** **** **** **** **** **** **** **** +4060 Epic_Spell_Summon_Aberration **** **** **** **** **** **** **** **** +4061 Epic_Spell_Superb_Dispelling **** **** **** **** **** **** **** **** +4062 Epic_Spell_Symrustars_Spellbinding **** **** **** **** **** **** **** **** +4063 Epic_Spell_The_Withering **** **** **** **** **** **** **** **** +4064 Epic_Spell_Tolodines_Killing_Wind **** **** **** **** **** **** **** **** +4065 Epic_Spell_Transcendent_Vitality **** **** **** **** **** **** **** **** +4066 Epic_Spell_Twinfiend **** **** **** **** **** **** **** **** +4067 Epic_Spell_Unholy_Disciple **** **** **** **** **** **** **** **** +4068 Epic_Spell_Unimpinged **** **** **** **** **** **** **** **** +4069 Epic_Spell_Unseen_Wanderer **** **** **** **** **** **** **** **** +4070 Epic_Spell_Whip_of_Shar **** **** **** **** **** **** **** **** +4071 Wander_Unseen **** **** **** **** **** **** **** **** +4072 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4073 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4074 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4075 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4076 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4077 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4078 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4079 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4080 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4081 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4082 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4083 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4084 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4085 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4086 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4087 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4088 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4089 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4090 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4091 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4092 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4093 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4094 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4095 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4096 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4097 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4098 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4099 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4100 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4101 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4102 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4103 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4104 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4105 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4106 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4107 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4108 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4109 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4110 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4111 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4112 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4113 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4114 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4115 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4116 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4117 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4118 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4119 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4120 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4121 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4122 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4123 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4124 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4125 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4126 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4127 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4128 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4129 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4130 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4131 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4132 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4133 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4134 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4135 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4136 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4137 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4138 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4139 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4140 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4141 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4142 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4143 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4144 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4145 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4146 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4147 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4148 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4149 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4150 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4151 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4152 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4153 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4154 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4155 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4156 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4157 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4158 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4159 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4160 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4161 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4162 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4163 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4164 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4165 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4166 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4167 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4168 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4169 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4170 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4171 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4172 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4173 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4174 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4175 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4176 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4177 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4178 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4179 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4180 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4181 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4182 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4183 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4184 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4185 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4186 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4187 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4188 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4189 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4190 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4191 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4192 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4193 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4194 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4195 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4196 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4197 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4198 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4199 ReservedForISCAndESS **** **** **** **** **** **** **** **** +4200 ####START_OF_NEW_SPELLBOOK_RESERVE **** **** **** **** **** **** **** **** +4201 Bard_Cure_Minor_Wounds **** **** **** **** **** **** **** **** +4202 Bard_Dancing_Lights **** **** **** **** **** **** **** **** +4203 Bard_Daze **** **** **** **** **** **** **** **** +4204 Bard_Flare **** **** **** **** **** **** **** **** +4205 Bard_Light **** **** **** **** **** **** **** **** +4206 Bard_MAGE_HAND **** **** **** **** **** **** **** **** +4207 Bard_Read_Magic **** **** **** **** **** **** **** **** +4208 Bard_Resistance **** **** **** **** **** **** **** **** +4209 Bard_Amplify **** **** **** **** **** **** **** **** +4210 Bard_BalagarnsIronHorn **** **** **** **** **** **** **** **** +4211 Bard_Cause_Fear **** **** **** **** **** **** **** **** +4212 Bard_Charm_Person **** **** **** **** **** **** **** **** +4213 Bard_Cure_Light_Wounds **** **** **** **** **** **** **** **** +4214 Bard_Disguise_Self_Radial_Master **** **** **** **** **** **** **** **** +4215 Bard_Disguise_Self_Learn **** **** **** **** **** **** **** **** +4216 Bard_Disguise_Self_Options **** **** **** **** **** **** **** **** +4217 Bard_Disguise_Self_QS1 **** **** **** **** **** **** **** **** +4218 Bard_Disguise_Self_QS2 **** **** **** **** **** **** **** **** +4219 Bard_Disguise_Self_QS3 **** **** **** **** **** **** **** **** +4220 Bard_Expeditious_Retreat **** **** **** **** **** **** **** **** +4221 Bard_EXTRACT_DRUG **** **** **** **** **** **** **** **** +4222 Bard_EXTRACT_BACCARAN **** **** **** **** **** **** **** **** +4223 Bard_EXTRACT_VODARE **** **** **** **** **** **** **** **** +4224 Bard_EXTRACT_SANNISH **** **** **** **** **** **** **** **** +4225 Bard_EXTRACT_MUSHROOM_POWDER **** **** **** **** **** **** **** **** +4226 Bard_Grease **** **** **** **** **** **** **** **** +4227 Bard_Identify **** **** **** **** **** **** **** **** +4228 Bard_Lesser_Dispel **** **** **** **** **** **** **** **** +4229 Bard_Mage_Armor **** **** **** **** **** **** **** **** +4230 Bard_Magic_Weapon **** **** **** **** **** **** **** **** +4231 Bard_ObscureObject **** **** **** **** **** **** **** **** +4232 Bard_Protection_from_Chaos **** **** **** **** **** **** **** **** +4233 Bard_Protection_from_Evil **** **** **** **** **** **** **** **** +4234 Bard_Protection_from_Good **** **** **** **** **** **** **** **** +4235 Bard_Protection_from_Law **** **** **** **** **** **** **** **** +4236 Bard_RAY_OF_HOPE **** **** **** **** **** **** **** **** +4237 Bard_Sleep **** **** **** **** **** **** **** **** +4238 Bard_SORROW **** **** **** **** **** **** **** **** +4239 Bard_Summon_Creature_I **** **** **** **** **** **** **** **** +4240 Bard_ADDICTION **** **** **** **** **** **** **** **** +4241 Bard_ADDICTION_TERRAN_BRANDY **** **** **** **** **** **** **** **** +4242 Bard_ADDICTION_MUSHROOM_POWDER **** **** **** **** **** **** **** **** +4243 Bard_ADDICTION_VODARE **** **** **** **** **** **** **** **** +4244 Bard_ADDICTION_AGONY **** **** **** **** **** **** **** **** +4245 Bard_Alter_Self_Radial_Master **** **** **** **** **** **** **** **** +4246 Bard_Alter_Self_Learn **** **** **** **** **** **** **** **** +4247 Bard_Alter_Self_Options **** **** **** **** **** **** **** **** +4248 Bard_Alter_Self_QS1 **** **** **** **** **** **** **** **** +4249 Bard_Alter_Self_QS2 **** **** **** **** **** **** **** **** +4250 Bard_Alter_Self_QS3 **** **** **** **** **** **** **** **** +4251 Bard_Blindness_and_Deafness **** **** **** **** **** **** **** **** +4252 Bard_Blur **** **** **** **** **** **** **** **** +4253 Bard_Bulls_Strength **** **** **** **** **** **** **** **** +4254 Bard_Calm_Emotions **** **** **** **** **** **** **** **** +4255 Bard_Cats_Grace **** **** **** **** **** **** **** **** +4256 Bard_Clarity **** **** **** **** **** **** **** **** +4257 Bard_Cloud_of_Bewilderment **** **** **** **** **** **** **** **** +4258 Bard_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +4259 Bard_Curse_of_Impending_Blades **** **** **** **** **** **** **** **** +4260 Bard_Darkness **** **** **** **** **** **** **** **** +4261 Bard_Daze_Monster **** **** **** **** **** **** **** **** +4262 Bard_Eagle_Splendor **** **** **** **** **** **** **** **** +4263 Bard_ELATION **** **** **** **** **** **** **** **** +4264 Bard_Foxs_Cunning **** **** **** **** **** **** **** **** +4265 Bard_Ghostly_Visage **** **** **** **** **** **** **** **** +4266 Bard_Glitterdust **** **** **** **** **** **** **** **** +4267 Bard_Heroism **** **** **** **** **** **** **** **** +4268 Bard_Hold_Person **** **** **** **** **** **** **** **** +4269 Bard_Invisibility **** **** **** **** **** **** **** **** +4270 Bard_LocateObject **** **** **** **** **** **** **** **** +4271 Bard_MirrorImage **** **** **** **** **** **** **** **** +4272 Bard_Owls_Wisdom **** **** **** **** **** **** **** **** +4273 Bard_Pyrotechnics **** **** **** **** **** **** **** **** +4274 Bard_Pyrotechnics_Fireworks **** **** **** **** **** **** **** **** +4275 Bard_Pyrotechnics_Smoke **** **** **** **** **** **** **** **** +4276 Bard_Scare **** **** **** **** **** **** **** **** +4277 Bard_See_Invisibility **** **** **** **** **** **** **** **** +4278 Bard_Silence **** **** **** **** **** **** **** **** +4279 Bard_SONG_OF_FESTERING_DEATH **** **** **** **** **** **** **** **** +4280 Bard_Sound_Burst **** **** **** **** **** **** **** **** +4281 Bard_Summon_Creature_II **** **** **** **** **** **** **** **** +4282 Bard_Tashas_Hideous_Laughter **** **** **** **** **** **** **** **** +4283 Bard_Ultravision **** **** **** **** **** **** **** **** +4284 Bard_UndetectableAlignment **** **** **** **** **** **** **** **** +4285 Bard_WAVE_OF_GRIEF **** **** **** **** **** **** **** **** +4286 Bard_WhirlingBlade **** **** **** **** **** **** **** **** +4287 Bard_Bestow_Curse **** **** **** **** **** **** **** **** +4288 Bard_Charm_Monster **** **** **** **** **** **** **** **** +4289 Bard_Clairaudience_and_Clairvoyance **** **** **** **** **** **** **** **** +4290 Bard_Confusion **** **** **** **** **** **** **** **** +4291 Bard_CrushingDespair **** **** **** **** **** **** **** **** +4292 Bard_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +4293 Bard_CURSE_OF_THE_PUTRID_HUSK **** **** **** **** **** **** **** **** +4294 Bard_Daylight **** **** **** **** **** **** **** **** +4295 Bard_Dispel_Magic **** **** **** **** **** **** **** **** +4296 Bard_Displacement **** **** **** **** **** **** **** **** +4297 Bard_Fear **** **** **** **** **** **** **** **** +4298 Bard_Find_Traps **** **** **** **** **** **** **** **** +4299 Bard_GLIBNESS **** **** **** **** **** **** **** **** +4300 Bard_Greater_Magic_Weapon **** **** **** **** **** **** **** **** +4301 Bard_Gust_of_Wind **** **** **** **** **** **** **** **** +4302 Bard_Halt **** **** **** **** **** **** **** **** +4303 Bard_Haste **** **** **** **** **** **** **** **** +4304 Bard_Invisibility_Sphere **** **** **** **** **** **** **** **** +4305 Bard_Keen_Edge **** **** **** **** **** **** **** **** +4306 Bard_Legions_Curse_of_Impending_Blades **** **** **** **** **** **** **** **** +4307 Bard_Magic_Circle_against_Chaos **** **** **** **** **** **** **** **** +4308 Bard_Magic_Circle_against_Evil **** **** **** **** **** **** **** **** +4309 Bard_Magic_Circle_against_Good **** **** **** **** **** **** **** **** +4310 Bard_Magic_Circle_against_Law **** **** **** **** **** **** **** **** +4311 Bard_Remove_Curse **** **** **** **** **** **** **** **** +4312 Bard_Remove_Disease **** **** **** **** **** **** **** **** +4313 Bard_Scrying **** **** **** **** **** **** **** **** +4314 Bard_Slow **** **** **** **** **** **** **** **** +4315 Bard_Sonic_Shield **** **** **** **** **** **** **** **** +4316 Bard_STUNNING_SCREECH **** **** **** **** **** **** **** **** +4317 Bard_Summon_Creature_III **** **** **** **** **** **** **** **** +4318 Bard_Weapon_of_Impact **** **** **** **** **** **** **** **** +4319 Bard_Wounding_Whispers **** **** **** **** **** **** **** **** +4320 Bard_BreakEnchantment **** **** **** **** **** **** **** **** +4321 Bard_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +4322 Bard_DetectScrying **** **** **** **** **** **** **** **** +4323 Bard_DimensionDoor_RadialMaster **** **** **** **** **** **** **** **** +4324 Bard_DimensionDoor_SelfOnly **** **** **** **** **** **** **** **** +4325 Bard_DimensionDoor_Party **** **** **** **** **** **** **** **** +4326 Bard_DimensionDoor_DirDist_SelfOnly **** **** **** **** **** **** **** **** +4327 Bard_DimensionDoor_DirDist_Party **** **** **** **** **** **** **** **** +4328 Bard_Dismissal **** **** **** **** **** **** **** **** +4329 Bard_Dominate_Person **** **** **** **** **** **** **** **** +4330 Bard_Greater_Resistance **** **** **** **** **** **** **** **** +4331 Bard_Hold_Monster **** **** **** **** **** **** **** **** +4332 Bard_Improved_Invisibility **** **** **** **** **** **** **** **** +4333 Bard_Legend_Lore **** **** **** **** **** **** **** **** +4334 Bard_LocateCreature **** **** **** **** **** **** **** **** +4335 Bard_Mass_Ultravision **** **** **** **** **** **** **** **** +4336 Bard_Neutralize_Poison **** **** **** **** **** **** **** **** +4337 Bard_RAINBOW_PATTERN **** **** **** **** **** **** **** **** +4338 Bard_RepelVermin **** **** **** **** **** **** **** **** +4339 Bard_Shout **** **** **** **** **** **** **** **** +4340 Bard_Summon_Creature_IV **** **** **** **** **** **** **** **** +4341 Bard_War_Cry **** **** **** **** **** **** **** **** +4342 Bard_Ethereal_Visage **** **** **** **** **** **** **** **** +4343 Bard_Greater_Dispelling **** **** **** **** **** **** **** **** +4344 Bard_Greater_Heroism **** **** **** **** **** **** **** **** +4345 Bard_Greater_Wall_of_Dispel_Magic **** **** **** **** **** **** **** **** +4346 Bard_Healing_Circle **** **** **** **** **** **** **** **** +4347 Bard_Mass_Cure_Light_Wounds **** **** **** **** **** **** **** **** +4348 Bard_Mind_Fog **** **** **** **** **** **** **** **** +4349 Bard_Mislead **** **** **** **** **** **** **** **** +4350 Bard_MORALITY_UNDONE **** **** **** **** **** **** **** **** +4351 Bard_SongOfDiscord **** **** **** **** **** **** **** **** +4352 Bard_Summon_Creature_V **** **** **** **** **** **** **** **** +4353 Bard_Animate_Object **** **** **** **** **** **** **** **** +4354 Bard_Dirge **** **** **** **** **** **** **** **** +4355 Bard_Energy_Buffer **** **** **** **** **** **** **** **** +4356 Bard_Eyebite **** **** **** **** **** **** **** **** +4357 Bard_Greater_Shout **** **** **** **** **** **** **** **** +4358 Bard_GreaterScrying **** **** **** **** **** **** **** **** +4359 Bard_Ice_Storm **** **** **** **** **** **** **** **** +4360 Bard_Mass_Bulls_Strength **** **** **** **** **** **** **** **** +4361 Bard_Mass_Cats_Grace **** **** **** **** **** **** **** **** +4362 Bard_Mass_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +4363 Bard_Mass_Eagle_Splendor **** **** **** **** **** **** **** **** +4364 Bard_Mass_Foxs_Cunning **** **** **** **** **** **** **** **** +4365 Bard_Mass_Haste **** **** **** **** **** **** **** **** +4366 Bard_Mass_Owls_Wisdom **** **** **** **** **** **** **** **** +4367 Bard_Summon_Creature_VI **** **** **** **** **** **** **** **** +4368 Bard_Superior_Resistance **** **** **** **** **** **** **** **** +4369 Bard_WAVE_OF_PAIN **** **** **** **** **** **** **** **** +4370 Sorcerer_Acid_Splash **** **** **** **** **** **** **** **** +4371 Sorcerer_Dancing_Lights **** **** **** **** **** **** **** **** +4372 Sorcerer_Daze **** **** **** **** **** **** **** **** +4373 Sorcerer_DisruptUndead **** **** **** **** **** **** **** **** +4374 Sorcerer_Electric_Jolt **** **** **** **** **** **** **** **** +4375 Sorcerer_Flare **** **** **** **** **** **** **** **** +4376 Sorcerer_Light **** **** **** **** **** **** **** **** +4377 Sorcerer_MAGE_HAND **** **** **** **** **** **** **** **** +4378 Sorcerer_Ray_of_Frost **** **** **** **** **** **** **** **** +4379 Sorcerer_Read_Magic **** **** **** **** **** **** **** **** +4380 Sorcerer_Resistance **** **** **** **** **** **** **** **** +4381 Sorcerer_ABERRATE **** **** **** **** **** **** **** **** +4382 Sorcerer_Benign_Transposition **** **** **** **** **** **** **** **** +4383 Sorcerer_BESTOW_WOUND **** **** **** **** **** **** **** **** +4384 Sorcerer_Bigbys_Tripping_Hand **** **** **** **** **** **** **** **** +4385 Sorcerer_Blade_of_Blood **** **** **** **** **** **** **** **** +4386 Sorcerer_Blade_of_Blood_1d6 **** **** **** **** **** **** **** **** +4387 Sorcerer_Blade_of_Blood_3d6 **** **** **** **** **** **** **** **** +4388 Sorcerer_Burning_Bolt **** **** **** **** **** **** **** **** +4389 Sorcerer_Burning_Hands **** **** **** **** **** **** **** **** +4390 Sorcerer_Cause_Fear **** **** **** **** **** **** **** **** +4391 Sorcerer_Charm_Person **** **** **** **** **** **** **** **** +4392 Sorcerer_Chill_Touch **** **** **** **** **** **** **** **** +4393 Sorcerer_Color_Spray **** **** **** **** **** **** **** **** +4394 Sorcerer_DETECT_UNDEAD **** **** **** **** **** **** **** **** +4395 Sorcerer_Disguise_Self_Radial_Master **** **** **** **** **** **** **** **** +4396 Sorcerer_Disguise_Self_Learn **** **** **** **** **** **** **** **** +4397 Sorcerer_Disguise_Self_Options **** **** **** **** **** **** **** **** +4398 Sorcerer_Disguise_Self_QS1 **** **** **** **** **** **** **** **** +4399 Sorcerer_Disguise_Self_QS2 **** **** **** **** **** **** **** **** +4400 Sorcerer_Disguise_Self_QS3 **** **** **** **** **** **** **** **** +4401 Sorcerer_DRUG_RESISTANCE **** **** **** **** **** **** **** **** +4402 Sorcerer_Endure_Elements **** **** **** **** **** **** **** **** +4403 Sorcerer_ENLARGE_PERSON **** **** **** **** **** **** **** **** +4404 Sorcerer_Expeditious_Retreat **** **** **** **** **** **** **** **** +4405 Sorcerer_EXTRACT_DRUG **** **** **** **** **** **** **** **** +4406 Sorcerer_EXTRACT_BACCARAN **** **** **** **** **** **** **** **** +4407 Sorcerer_EXTRACT_VODARE **** **** **** **** **** **** **** **** +4408 Sorcerer_EXTRACT_SANNISH **** **** **** **** **** **** **** **** +4409 Sorcerer_EXTRACT_MUSHROOM_POWDER **** **** **** **** **** **** **** **** +4410 Sorcerer_EYES_OF_THE_AVORAL **** **** **** **** **** **** **** **** +4411 Sorcerer_FistOfStone **** **** **** **** **** **** **** **** +4412 Sorcerer_Grease **** **** **** **** **** **** **** **** +4413 Sorcerer_Hail_of_Stone **** **** **** **** **** **** **** **** +4414 Sorcerer_Horizikauls_Boom **** **** **** **** **** **** **** **** +4415 Sorcerer_Ice_Dagger **** **** **** **** **** **** **** **** +4416 Sorcerer_Identify **** **** **** **** **** **** **** **** +4417 Sorcerer_Ironguts **** **** **** **** **** **** **** **** +4418 Sorcerer_Kelgores_Fire_Bolt **** **** **** **** **** **** **** **** +4419 Sorcerer_LANTERN_LIGHT **** **** **** **** **** **** **** **** +4420 Sorcerer_Lesser_Acid_Orb **** **** **** **** **** **** **** **** +4421 Sorcerer_Lesser_Cold_Orb **** **** **** **** **** **** **** **** +4422 Sorcerer_Lesser_Deflect **** **** **** **** **** **** **** **** +4423 Sorcerer_Lesser_Electric_Orb **** **** **** **** **** **** **** **** +4424 Sorcerer_Lesser_Fire_Orb **** **** **** **** **** **** **** **** +4425 Sorcerer_LESSER_SHIVERING_TOUCH **** **** **** **** **** **** **** **** +4426 Sorcerer_Lesser_Sonic_Orb **** **** **** **** **** **** **** **** +4427 Sorcerer_Mage_Armor **** **** **** **** **** **** **** **** +4428 Sorcerer_Magic_Missile **** **** **** **** **** **** **** **** +4429 Sorcerer_Magic_Weapon **** **** **** **** **** **** **** **** +4430 Sorcerer_Necrotic_Awareness **** **** **** **** **** **** **** **** +4431 Sorcerer_Negative_Energy_Ray **** **** **** **** **** **** **** **** +4432 Sorcerer_Nybors_Gentle_Reminder **** **** **** **** **** **** **** **** +4433 Sorcerer_Obscuring_Mist **** **** **** **** **** **** **** **** +4434 Sorcerer_Protection_from_Chaos **** **** **** **** **** **** **** **** +4435 Sorcerer_Protection_from_Evil **** **** **** **** **** **** **** **** +4436 Sorcerer_Protection_from_Good **** **** **** **** **** **** **** **** +4437 Sorcerer_Protection_from_Law **** **** **** **** **** **** **** **** +4438 Sorcerer_Ray_of_Enfeeblement **** **** **** **** **** **** **** **** +4439 Sorcerer_REDUCE_PERSON **** **** **** **** **** **** **** **** +4440 Sorcerer_Rouse **** **** **** **** **** **** **** **** +4441 Sorcerer_Shelgarns_Persistent_Blade **** **** **** **** **** **** **** **** +4442 Sorcerer_Shield **** **** **** **** **** **** **** **** +4443 Sorcerer_ShockingGrasp **** **** **** **** **** **** **** **** +4444 Sorcerer_Sleep **** **** **** **** **** **** **** **** +4445 Sorcerer_Snillocs_Snowball **** **** **** **** **** **** **** **** +4446 Sorcerer_Spell_Jump **** **** **** **** **** **** **** **** +4447 Sorcerer_Summon_Creature_I **** **** **** **** **** **** **** **** +4448 Sorcerer_SummonUndeadI **** **** **** **** **** **** **** **** +4449 Sorcerer_TensersFloatingDisk **** **** **** **** **** **** **** **** +4450 Sorcerer_True_Casting **** **** **** **** **** **** **** **** +4451 Sorcerer_True_Strike **** **** **** **** **** **** **** **** +4452 Sorcerer_ADDICTION **** **** **** **** **** **** **** **** +4453 Sorcerer_ADDICTION_TERRAN_BRANDY **** **** **** **** **** **** **** **** +4454 Sorcerer_ADDICTION_MUSHROOM_POWDER **** **** **** **** **** **** **** **** +4455 Sorcerer_ADDICTION_VODARE **** **** **** **** **** **** **** **** +4456 Sorcerer_ADDICTION_AGONY **** **** **** **** **** **** **** **** +4457 Sorcerer_Agnazzars_Scorcher **** **** **** **** **** **** **** **** +4458 Sorcerer_Alter_Self_Radial_Master **** **** **** **** **** **** **** **** +4459 Sorcerer_Alter_Self_Learn **** **** **** **** **** **** **** **** +4460 Sorcerer_Alter_Self_Options **** **** **** **** **** **** **** **** +4461 Sorcerer_Alter_Self_QS1 **** **** **** **** **** **** **** **** +4462 Sorcerer_Alter_Self_QS2 **** **** **** **** **** **** **** **** +4463 Sorcerer_Alter_Self_QS3 **** **** **** **** **** **** **** **** +4464 Sorcerer_Animalistic_Power **** **** **** **** **** **** **** **** +4465 Sorcerer_AugmentFamiliar **** **** **** **** **** **** **** **** +4466 Sorcerer_BalagarnsIronHorn **** **** **** **** **** **** **** **** +4467 Sorcerer_Baleful_Transposition **** **** **** **** **** **** **** **** +4468 Sorcerer_Bigbys_Striking_Fist **** **** **** **** **** **** **** **** +4469 Sorcerer_BladesOfFire **** **** **** **** **** **** **** **** +4470 Sorcerer_Blindness_and_Deafness **** **** **** **** **** **** **** **** +4471 Sorcerer_Blur **** **** **** **** **** **** **** **** +4472 Sorcerer_Bulls_Strength **** **** **** **** **** **** **** **** +4473 Sorcerer_Cats_Grace **** **** **** **** **** **** **** **** +4474 Sorcerer_Cloud_of_Bewilderment **** **** **** **** **** **** **** **** +4475 Sorcerer_Combust **** **** **** **** **** **** **** **** +4476 Sorcerer_Command_Undead **** **** **** **** **** **** **** **** +4477 Sorcerer_Continual_Flame **** **** **** **** **** **** **** **** +4478 Sorcerer_Create_Magic_Tattoo **** **** **** **** **** **** **** **** +4479 Sorcerer_Curse_of_Impending_Blades **** **** **** **** **** **** **** **** +4480 Sorcerer_Darkness **** **** **** **** **** **** **** **** +4481 Sorcerer_Daze_Monster **** **** **** **** **** **** **** **** +4482 Sorcerer_Death_Armor **** **** **** **** **** **** **** **** +4483 Sorcerer_Deflect **** **** **** **** **** **** **** **** +4484 Sorcerer_Dimension_Hop **** **** **** **** **** **** **** **** +4485 Sorcerer_Dispelling_Touch **** **** **** **** **** **** **** **** +4486 Sorcerer_Eagle_Splendor **** **** **** **** **** **** **** **** +4487 Sorcerer_Endurance **** **** **** **** **** **** **** **** +4488 Sorcerer_ENERGIZE_POTION **** **** **** **** **** **** **** **** +4489 Sorcerer_ENERGIZE_POTION_ACID **** **** **** **** **** **** **** **** +4490 Sorcerer_ENERGIZE_POTION_COLD **** **** **** **** **** **** **** **** +4491 Sorcerer_ENERGIZE_POTION_ELECTRICITY **** **** **** **** **** **** **** **** +4492 Sorcerer_ENERGIZE_POTION_FIRE **** **** **** **** **** **** **** **** +4493 Sorcerer_ENERGIZE_POTION_SONIC **** **** **** **** **** **** **** **** +4494 Sorcerer_FalseLife **** **** **** **** **** **** **** **** +4495 Sorcerer_Fireburst **** **** **** **** **** **** **** **** +4496 Sorcerer_Flame_Weapon **** **** **** **** **** **** **** **** +4497 Sorcerer_FogCloud **** **** **** **** **** **** **** **** +4498 Sorcerer_Foxs_Cunning **** **** **** **** **** **** **** **** +4499 Sorcerer_Gedlees_Electric_Loop **** **** **** **** **** **** **** **** +4500 Sorcerer_Ghostly_Visage **** **** **** **** **** **** **** **** +4501 Sorcerer_Ghoul_Touch **** **** **** **** **** **** **** **** +4502 Sorcerer_Glitterdust **** **** **** **** **** **** **** **** +4503 Sorcerer_Invisibility **** **** **** **** **** **** **** **** +4504 Sorcerer_Knock **** **** **** **** **** **** **** **** +4505 Sorcerer_Lesser_Dispel **** **** **** **** **** **** **** **** +4506 Sorcerer_LifeBolt **** **** **** **** **** **** **** **** +4507 Sorcerer_LifeBolt1Bolt **** **** **** **** **** **** **** **** +4508 Sorcerer_LifeBolt2Bolts **** **** **** **** **** **** **** **** +4509 Sorcerer_LifeBolt3Bolts **** **** **** **** **** **** **** **** +4510 Sorcerer_LifeBolt4Bolts **** **** **** **** **** **** **** **** +4511 Sorcerer_LifeBolt5Bolts **** **** **** **** **** **** **** **** +4512 Sorcerer_LocateObject **** **** **** **** **** **** **** **** +4513 Sorcerer_MASOCHISM **** **** **** **** **** **** **** **** +4514 Sorcerer_Melfs_Acid_Arrow **** **** **** **** **** **** **** **** +4515 Sorcerer_MirrorImage **** **** **** **** **** **** **** **** +4516 Sorcerer_Necrotic_Cyst **** **** **** **** **** **** **** **** +4517 Sorcerer_ObscureObject **** **** **** **** **** **** **** **** +4518 Sorcerer_Owls_Wisdom **** **** **** **** **** **** **** **** +4519 Sorcerer_ProtectionArrows **** **** **** **** **** **** **** **** +4520 Sorcerer_Pyrotechnics **** **** **** **** **** **** **** **** +4521 Sorcerer_Pyrotechnics_Fireworks **** **** **** **** **** **** **** **** +4522 Sorcerer_Pyrotechnics_Smoke **** **** **** **** **** **** **** **** +4523 Sorcerer_Resist_Elements **** **** **** **** **** **** **** **** +4524 Sorcerer_Scare **** **** **** **** **** **** **** **** +4525 Sorcerer_ScorchingRay **** **** **** **** **** **** **** **** +4526 Sorcerer_See_Invisibility **** **** **** **** **** **** **** **** +4527 Sorcerer_Seeking_Ray **** **** **** **** **** **** **** **** +4528 Sorcerer_Shadow_Spray **** **** **** **** **** **** **** **** +4529 Sorcerer_SHRIVELING **** **** **** **** **** **** **** **** +4530 Sorcerer_Snillocs_Snowball_Swarm **** **** **** **** **** **** **** **** +4531 Sorcerer_Stone_Bones **** **** **** **** **** **** **** **** +4532 Sorcerer_Summon_Creature_II **** **** **** **** **** **** **** **** +4533 Sorcerer_SummonUndeadII **** **** **** **** **** **** **** **** +4534 Sorcerer_Sure_Strike **** **** **** **** **** **** **** **** +4535 Sorcerer_Tashas_Hideous_Laughter **** **** **** **** **** **** **** **** +4536 Sorcerer_TouchIdiocy **** **** **** **** **** **** **** **** +4537 Sorcerer_Ultravision **** **** **** **** **** **** **** **** +4538 Sorcerer_UNHEAVENED **** **** **** **** **** **** **** **** +4539 Sorcerer_Web **** **** **** **** **** **** **** **** +4540 Sorcerer_WhirlingBlade **** **** **** **** **** **** **** **** +4541 Sorcerer_Clairaudience_and_Clairvoyance **** **** **** **** **** **** **** **** +4542 Sorcerer_Clarity **** **** **** **** **** **** **** **** +4543 Sorcerer_Crown_Might **** **** **** **** **** **** **** **** +4544 Sorcerer_Crown_Protection **** **** **** **** **** **** **** **** +4545 Sorcerer_CURSE_OF_THE_PUTRID_HUSK **** **** **** **** **** **** **** **** +4546 Sorcerer_Daylight **** **** **** **** **** **** **** **** +4547 Sorcerer_DeepSlumber **** **** **** **** **** **** **** **** +4548 Sorcerer_DEVILS_EYE **** **** **** **** **** **** **** **** +4549 Sorcerer_Dispel_Magic **** **** **** **** **** **** **** **** +4550 Sorcerer_Displacement **** **** **** **** **** **** **** **** +4551 Sorcerer_DREAD_WORD **** **** **** **** **** **** **** **** +4552 Sorcerer_ELATION **** **** **** **** **** **** **** **** +4553 Sorcerer_Energy_Aegis **** **** **** **** **** **** **** **** +4554 Sorcerer_Energy_Aegis_Acid **** **** **** **** **** **** **** **** +4555 Sorcerer_Energy_Aegis_Cold **** **** **** **** **** **** **** **** +4556 Sorcerer_Energy_Aegis_Elec **** **** **** **** **** **** **** **** +4557 Sorcerer_Energy_Aegis_Fire **** **** **** **** **** **** **** **** +4558 Sorcerer_Energy_Aegis_Sonic **** **** **** **** **** **** **** **** +4559 Sorcerer_Energy_Surge **** **** **** **** **** **** **** **** +4560 Sorcerer_Energy_Surge_Acid **** **** **** **** **** **** **** **** +4561 Sorcerer_Energy_Surge_Cold **** **** **** **** **** **** **** **** +4562 Sorcerer_Energy_Surge_Elec **** **** **** **** **** **** **** **** +4563 Sorcerer_Energy_Surge_Fire **** **** **** **** **** **** **** **** +4564 Sorcerer_Energy_Surge_Sonic **** **** **** **** **** **** **** **** +4565 Sorcerer_EVIL_EYE **** **** **** **** **** **** **** **** +4566 Sorcerer_Find_Traps **** **** **** **** **** **** **** **** +4567 Sorcerer_Fireball **** **** **** **** **** **** **** **** +4568 Sorcerer_Flame_Arrow **** **** **** **** **** **** **** **** +4569 Sorcerer_Flashburst **** **** **** **** **** **** **** **** +4570 Sorcerer_Forceblast **** **** **** **** **** **** **** **** +4571 Sorcerer_Greater_Magic_Weapon **** **** **** **** **** **** **** **** +4572 Sorcerer_GreaterDisruptUndead **** **** **** **** **** **** **** **** +4573 Sorcerer_Gust_of_Wind **** **** **** **** **** **** **** **** +4574 Sorcerer_Halt **** **** **** **** **** **** **** **** +4575 Sorcerer_HaltUndead **** **** **** **** **** **** **** **** +4576 Sorcerer_Haste **** **** **** **** **** **** **** **** +4577 Sorcerer_Heroism **** **** **** **** **** **** **** **** +4578 Sorcerer_Hold_Person **** **** **** **** **** **** **** **** +4579 Sorcerer_Ice_Burst **** **** **** **** **** **** **** **** +4580 Sorcerer_Improved_Mage_Armor **** **** **** **** **** **** **** **** +4581 Sorcerer_Invisibility_Sphere **** **** **** **** **** **** **** **** +4582 Sorcerer_Keen_Edge **** **** **** **** **** **** **** **** +4583 Sorcerer_Legions_Curse_of_Impending_Blades **** **** **** **** **** **** **** **** +4584 Sorcerer_Lightning_Bolt **** **** **** **** **** **** **** **** +4585 Sorcerer_Magic_Circle_against_Chaos **** **** **** **** **** **** **** **** +4586 Sorcerer_Magic_Circle_against_Evil **** **** **** **** **** **** **** **** +4587 Sorcerer_Magic_Circle_against_Good **** **** **** **** **** **** **** **** +4588 Sorcerer_Magic_Circle_against_Law **** **** **** **** **** **** **** **** +4589 Sorcerer_Mestils_Acid_Breath **** **** **** **** **** **** **** **** +4590 Sorcerer_Necrotic_Bloat **** **** **** **** **** **** **** **** +4591 Sorcerer_Negative_Energy_Burst **** **** **** **** **** **** **** **** +4592 Sorcerer_NONDETECTION **** **** **** **** **** **** **** **** +4593 Sorcerer_Protection_from_Elements **** **** **** **** **** **** **** **** +4594 Sorcerer_RainbowBlast **** **** **** **** **** **** **** **** +4595 Sorcerer_RayofExhaustion **** **** **** **** **** **** **** **** +4596 Sorcerer_REALITY_BLIND **** **** **** **** **** **** **** **** +4597 Sorcerer_Regroup **** **** **** **** **** **** **** **** +4598 Sorcerer_Scintillating_Sphere **** **** **** **** **** **** **** **** +4599 Sorcerer_Serpents_Sigh **** **** **** **** **** **** **** **** +4600 Sorcerer_SS_Bolt_of_Acid **** **** **** **** **** **** **** **** +4601 Sorcerer_SS_Bolt_of_Lightning **** **** **** **** **** **** **** **** +4602 Sorcerer_SS_Cone_of_Acid **** **** **** **** **** **** **** **** +4603 Sorcerer_SS_Cone_of_Cold **** **** **** **** **** **** **** **** +4604 Sorcerer_SS_Cone_of_Fire **** **** **** **** **** **** **** **** +4605 Sorcerer_SHIVERING_TOUCH **** **** **** **** **** **** **** **** +4606 Sorcerer_SleetStorm **** **** **** **** **** **** **** **** +4607 Sorcerer_Slow **** **** **** **** **** **** **** **** +4608 Sorcerer_Spiderskin **** **** **** **** **** **** **** **** +4609 Sorcerer_Stinking_Cloud **** **** **** **** **** **** **** **** +4610 Sorcerer_Summon_Creature_III **** **** **** **** **** **** **** **** +4611 Sorcerer_SummonUndeadIII **** **** **** **** **** **** **** **** +4612 Sorcerer_Vampiric_Touch **** **** **** **** **** **** **** **** +4613 Sorcerer_WaterBreathing **** **** **** **** **** **** **** **** +4614 Sorcerer_Weapon_of_Impact **** **** **** **** **** **** **** **** +4615 Sorcerer_ABYSSAL_MIGHT **** **** **** **** **** **** **** **** +4616 Sorcerer_Acid_Orb **** **** **** **** **** **** **** **** +4617 Sorcerer_ArcaneEye **** **** **** **** **** **** **** **** +4618 Sorcerer_Bestow_Curse **** **** **** **** **** **** **** **** +4619 Sorcerer_Blast_of_Flame **** **** **** **** **** **** **** **** +4620 Sorcerer_Channeled_Pyroburst **** **** **** **** **** **** **** **** +4621 Sorcerer_Channeled_Pyroburst_Swift **** **** **** **** **** **** **** **** +4622 Sorcerer_Channeled_Pyroburst_Standard **** **** **** **** **** **** **** **** +4623 Sorcerer_Channeled_Pyroburst_Full **** **** **** **** **** **** **** **** +4624 Sorcerer_Channeled_Pyroburst_Two **** **** **** **** **** **** **** **** +4625 Sorcerer_Charm_Monster **** **** **** **** **** **** **** **** +4626 Sorcerer_Cold_Orb **** **** **** **** **** **** **** **** +4627 Sorcerer_Confusion **** **** **** **** **** **** **** **** +4628 Sorcerer_Contagion **** **** **** **** **** **** **** **** +4629 Sorcerer_CrushingDespair **** **** **** **** **** **** **** **** +4630 Sorcerer_DAMNING_DARKNESS **** **** **** **** **** **** **** **** +4631 Sorcerer_DANCING_WEB **** **** **** **** **** **** **** **** +4632 Sorcerer_DetectScrying **** **** **** **** **** **** **** **** +4633 Sorcerer_Dimensional_Anchor **** **** **** **** **** **** **** **** +4634 Sorcerer_DimensionDoor_RadialMaster **** **** **** **** **** **** **** **** +4635 Sorcerer_DimensionDoor_SelfOnly **** **** **** **** **** **** **** **** +4636 Sorcerer_DimensionDoor_Party **** **** **** **** **** **** **** **** +4637 Sorcerer_DimensionDoor_DirDist_SelfOnly **** **** **** **** **** **** **** **** +4638 Sorcerer_DimensionDoor_DirDist_Party **** **** **** **** **** **** **** **** +4639 Sorcerer_Doom_Scarabs **** **** **** **** **** **** **** **** +4640 Sorcerer_Electric_Orb **** **** **** **** **** **** **** **** +4641 Sorcerer_Elemental_Shield **** **** **** **** **** **** **** **** +4642 Sorcerer_Enervation **** **** **** **** **** **** **** **** +4643 Sorcerer_Evards_Black_Tentacles **** **** **** **** **** **** **** **** +4644 Sorcerer_Fear **** **** **** **** **** **** **** **** +4645 Sorcerer_Fire_Orb **** **** **** **** **** **** **** **** +4646 Sorcerer_FireTrap **** **** **** **** **** **** **** **** +4647 Sorcerer_Greater_Resistance **** **** **** **** **** **** **** **** +4648 Sorcerer_GRIM_REVENGE **** **** **** **** **** **** **** **** +4649 Sorcerer_Ice_Storm **** **** **** **** **** **** **** **** +4650 Sorcerer_Ilyykurs_Mantle **** **** **** **** **** **** **** **** +4651 Sorcerer_Improved_Invisibility **** **** **** **** **** **** **** **** +4652 Sorcerer_Isaacs_Lesser_Missile_Storm **** **** **** **** **** **** **** **** +4653 Sorcerer_Lesser_Spell_Breach **** **** **** **** **** **** **** **** +4654 Sorcerer_LIQUID_PAIN **** **** **** **** **** **** **** **** +4655 Sorcerer_LocateCreature **** **** **** **** **** **** **** **** +4656 Sorcerer_Lower_Spell_Resistance **** **** **** **** **** **** **** **** +4657 Sorcerer_MASS_ENLARGE_PERSON **** **** **** **** **** **** **** **** +4658 Sorcerer_MASS_REDUCE_PERSON **** **** **** **** **** **** **** **** +4659 Sorcerer_Mass_Ultravision **** **** **** **** **** **** **** **** +4660 Sorcerer_Minor_Globe_of_Invulnerability **** **** **** **** **** **** **** **** +4661 Sorcerer_Necrotic_Domination **** **** **** **** **** **** **** **** +4662 Sorcerer_OrbOfForce **** **** **** **** **** **** **** **** +4663 Sorcerer_Otilukes_Resilient_Sphere **** **** **** **** **** **** **** **** +4664 Sorcerer_Phantasmal_Killer **** **** **** **** **** **** **** **** +4665 Sorcerer_PnP_FireShield **** **** **** **** **** **** **** **** +4666 Sorcerer_PnP_FireShieldRed **** **** **** **** **** **** **** **** +4667 Sorcerer_PnPFireShieldBlue **** **** **** **** **** **** **** **** +4668 Sorcerer_Polymorph_Self **** **** **** **** **** **** **** **** +4669 Sorcerer_Polymorph_GIANT_SPIDER **** **** **** **** **** **** **** **** +4670 Sorcerer_Polymorph_TROLL **** **** **** **** **** **** **** **** +4671 Sorcerer_Polymorph_UMBER_HULK **** **** **** **** **** **** **** **** +4672 Sorcerer_Polymorph_PIXIE **** **** **** **** **** **** **** **** +4673 Sorcerer_Polymorph_ZOMBIE **** **** **** **** **** **** **** **** +4674 Sorcerer_RAINBOW_PATTERN **** **** **** **** **** **** **** **** +4675 Sorcerer_Remove_Blindness_and_Deafness **** **** **** **** **** **** **** **** +4676 Sorcerer_Remove_Curse **** **** **** **** **** **** **** **** +4677 Sorcerer_Scrying **** **** **** **** **** **** **** **** +4678 Sorcerer_SerpentArrows **** **** **** **** **** **** **** **** +4679 Sorcerer_Shadow_Conjuration **** **** **** **** **** **** **** **** +4680 Sorcerer_SHADOW_CON_Summon_Shadow **** **** **** **** **** **** **** **** +4681 Sorcerer_SHADOW_CON_Darkness **** **** **** **** **** **** **** **** +4682 Sorcerer_SHADOW_CON_Inivsibility **** **** **** **** **** **** **** **** +4683 Sorcerer_SHADOW_CON_Mage_Armor **** **** **** **** **** **** **** **** +4684 Sorcerer_SHADOW_CON_Magic_Missile **** **** **** **** **** **** **** **** +4685 Sorcerer_Shout **** **** **** **** **** **** **** **** +4686 Sorcerer_Sinsaburs_Baleful_Bolt **** **** **** **** **** **** **** **** +4687 Sorcerer_Slashing_Dispel **** **** **** **** **** **** **** **** +4688 Sorcerer_SolidFog **** **** **** **** **** **** **** **** +4689 Sorcerer_Sonic_Orb **** **** **** **** **** **** **** **** +4690 Sorcerer_Stoneskin **** **** **** **** **** **** **** **** +4691 Sorcerer_Summon_Creature_IV **** **** **** **** **** **** **** **** +4692 Sorcerer_SummonUndeadIV **** **** **** **** **** **** **** **** +4693 Sorcerer_Viscid_Glob **** **** **** **** **** **** **** **** +4694 Sorcerer_Wall_of_Fire **** **** **** **** **** **** **** **** +4695 Sorcerer_WRACK **** **** **** **** **** **** **** **** +4696 Sorcerer_Animate_Dead **** **** **** **** **** **** **** **** +4697 Sorcerer_BalefulPolymorph **** **** **** **** **** **** **** **** +4698 Sorcerer_Ball_Lightning **** **** **** **** **** **** **** **** +4699 Sorcerer_Beltyns_Burning_Blood **** **** **** **** **** **** **** **** +4700 Sorcerer_Bigbys_Interposing_Hand **** **** **** **** **** **** **** **** +4701 Sorcerer_BreakEnchantment **** **** **** **** **** **** **** **** +4702 Sorcerer_CALL_DRETCH_HORDE **** **** **** **** **** **** **** **** +4703 Sorcerer_CALL_LEMURE_HORDE **** **** **** **** **** **** **** **** +4704 Sorcerer_Cloudkill **** **** **** **** **** **** **** **** +4705 Sorcerer_Cone_of_Cold **** **** **** **** **** **** **** **** +4706 Sorcerer_Dismissal **** **** **** **** **** **** **** **** +4707 Sorcerer_Dominate_Person **** **** **** **** **** **** **** **** +4708 Sorcerer_DraconicMight **** **** **** **** **** **** **** **** +4709 Sorcerer_Energy_Buffer **** **** **** **** **** **** **** **** +4710 Sorcerer_Feeblemind **** **** **** **** **** **** **** **** +4711 Sorcerer_Firebrand **** **** **** **** **** **** **** **** +4712 Sorcerer_Greater_Fireburst **** **** **** **** **** **** **** **** +4713 Sorcerer_Greater_Shadow_Conjuration **** **** **** **** **** **** **** **** +4714 Sorcerer_GR_SHADOW_CON_Summon_Shadow **** **** **** **** **** **** **** **** +4715 Sorcerer_GR_SHADOW_CON_Acid_Arrow **** **** **** **** **** **** **** **** +4716 Sorcerer_GR_SHADOW_CON_Ghostly_Visage **** **** **** **** **** **** **** **** +4717 Sorcerer_GR_SHADOW_CON_Web **** **** **** **** **** **** **** **** +4718 Sorcerer_GR_SHADOW_CON_Minor_Globe **** **** **** **** **** **** **** **** +4719 Sorcerer_Hold_Monster **** **** **** **** **** **** **** **** +4720 Sorcerer_Lesser_Mind_Blank **** **** **** **** **** **** **** **** +4721 Sorcerer_Lesser_Planar_Binding **** **** **** **** **** **** **** **** +4722 Sorcerer_Lesser_Spell_Mantle **** **** **** **** **** **** **** **** +4723 Sorcerer_Magic_Missile **** **** **** **** **** **** **** **** +4724 Sorcerer_MassFireShield **** **** **** **** **** **** **** **** +4725 Sorcerer_MassFireShieldRed **** **** **** **** **** **** **** **** +4726 Sorcerer_MassFireShieldBlue **** **** **** **** **** **** **** **** +4727 Sorcerer_Mestils_Acid_Sheath **** **** **** **** **** **** **** **** +4728 Sorcerer_Mind_Fog **** **** **** **** **** **** **** **** +4729 Sorcerer_Necrotic_Burst **** **** **** **** **** **** **** **** +4730 Sorcerer_Nights_Caress **** **** **** **** **** **** **** **** +4731 Sorcerer_PrismaticRay **** **** **** **** **** **** **** **** +4732 Sorcerer_RESONATING_RESISTANCE **** **** **** **** **** **** **** **** +4733 Sorcerer_Sonic_Shield **** **** **** **** **** **** **** **** +4734 Sorcerer_STOP_HEART **** **** **** **** **** **** **** **** +4735 Sorcerer_Summon_Creature_V **** **** **** **** **** **** **** **** +4736 Sorcerer_SummonUndeadV **** **** **** **** **** **** **** **** +4737 Sorcerer_SYMBOL_OF_PAIN **** **** **** **** **** **** **** **** +4738 Sorcerer_SYMBOL_OF_SLEEP **** **** **** **** **** **** **** **** +4739 Sorcerer_Teleport_RadialMaster **** **** **** **** **** **** **** **** +4740 Sorcerer_Teleport_SelfOnly **** **** **** **** **** **** **** **** +4741 Sorcerer_Teleport_Party **** **** **** **** **** **** **** **** +4742 Sorcerer_WavesofFatigue **** **** **** **** **** **** **** **** +4743 Sorcerer_Acid_Fog **** **** **** **** **** **** **** **** +4744 Sorcerer_Acid_Storm **** **** **** **** **** **** **** **** +4745 Sorcerer_ANTIMAGIC_FIELD **** **** **** **** **** **** **** **** +4746 Sorcerer_Bigbys_Forceful_Hand **** **** **** **** **** **** **** **** +4747 Sorcerer_CALL_FAITHFUL_SERVANTS **** **** **** **** **** **** **** **** +4748 Sorcerer_Chain_Lightning **** **** **** **** **** **** **** **** +4749 Sorcerer_Circle_of_Death **** **** **** **** **** **** **** **** +4750 Sorcerer_Disintegrate **** **** **** **** **** **** **** **** +4751 Sorcerer_ECTOPLASMIC_ENCHANCEMENT **** **** **** **** **** **** **** **** +4752 Sorcerer_Ethereal_Visage **** **** **** **** **** **** **** **** +4753 Sorcerer_ExtractWaterElemental **** **** **** **** **** **** **** **** +4754 Sorcerer_Eyebite **** **** **** **** **** **** **** **** +4755 Sorcerer_Flesh_to_stone **** **** **** **** **** **** **** **** +4756 Sorcerer_Ghoul_Gauntlet **** **** **** **** **** **** **** **** +4757 Sorcerer_Globe_of_Invulnerability **** **** **** **** **** **** **** **** +4758 Sorcerer_Greater_Dispelling **** **** **** **** **** **** **** **** +4759 Sorcerer_Greater_Heroism **** **** **** **** **** **** **** **** +4760 Sorcerer_Greater_Spell_Breach **** **** **** **** **** **** **** **** +4761 Sorcerer_Greater_Stoneskin **** **** **** **** **** **** **** **** +4762 Sorcerer_Isaacs_Greater_Missile_Storm **** **** **** **** **** **** **** **** +4763 Sorcerer_Legend_Lore **** **** **** **** **** **** **** **** +4764 Sorcerer_Mass_Bulls_Strength **** **** **** **** **** **** **** **** +4765 Sorcerer_Mass_Cats_Grace **** **** **** **** **** **** **** **** +4766 Sorcerer_Mass_Contagion **** **** **** **** **** **** **** **** +4767 Sorcerer_Mass_Eagle_Splendor **** **** **** **** **** **** **** **** +4768 Sorcerer_Mass_Endurance **** **** **** **** **** **** **** **** +4769 Sorcerer_Mass_Foxs_Cunning **** **** **** **** **** **** **** **** +4770 Sorcerer_Mass_Haste **** **** **** **** **** **** **** **** +4771 Sorcerer_Mass_Owls_Wisdom **** **** **** **** **** **** **** **** +4772 Sorcerer_Mislead **** **** **** **** **** **** **** **** +4773 Sorcerer_Necrotic_Eruption **** **** **** **** **** **** **** **** +4774 Sorcerer_OtilukesFreezingSphere **** **** **** **** **** **** **** **** +4775 Sorcerer_Planar_Binding **** **** **** **** **** **** **** **** +4776 Sorcerer_Repulsion **** **** **** **** **** **** **** **** +4777 Sorcerer_Shades **** **** **** **** **** **** **** **** +4778 Sorcerer_SHADES_Summon_Shadow **** **** **** **** **** **** **** **** +4779 Sorcerer_SHADES_Cone_of_Cold **** **** **** **** **** **** **** **** +4780 Sorcerer_SHADES_Fireball **** **** **** **** **** **** **** **** +4781 Sorcerer_SHADES_Stoneskin **** **** **** **** **** **** **** **** +4782 Sorcerer_SHADES_Wall_of_Fire **** **** **** **** **** **** **** **** +4783 Sorcerer_STARMANTLE **** **** **** **** **** **** **** **** +4784 Sorcerer_Stone_to_flesh **** **** **** **** **** **** **** **** +4785 Sorcerer_Summon_Creature_VI **** **** **** **** **** **** **** **** +4786 Sorcerer_Superior_Resistance **** **** **** **** **** **** **** **** +4787 Sorcerer_SYMBOL_OF_FEAR **** **** **** **** **** **** **** **** +4788 Sorcerer_SYMBOL_OF_PERSUASION **** **** **** **** **** **** **** **** +4789 Sorcerer_Tensers_Transformation **** **** **** **** **** **** **** **** +4790 Sorcerer_True_Seeing **** **** **** **** **** **** **** **** +4791 Sorcerer_Undeath_to_Death **** **** **** **** **** **** **** **** +4792 Sorcerer_AMBER_SARCOPHAGUS **** **** **** **** **** **** **** **** +4793 Sorcerer_ArrowOfBone **** **** **** **** **** **** **** **** +4794 Sorcerer_Avasculate **** **** **** **** **** **** **** **** +4795 Sorcerer_Banishment **** **** **** **** **** **** **** **** +4796 Sorcerer_Bigbys_Grasping_Hand **** **** **** **** **** **** **** **** +4797 Sorcerer_Control_Undead **** **** **** **** **** **** **** **** +4798 Sorcerer_Control_Weather **** **** **** **** **** **** **** **** +4799 Sorcerer_CW_Rain **** **** **** **** **** **** **** **** +4800 Sorcerer_CW_Snow **** **** **** **** **** **** **** **** +4801 Sorcerer_CW_Clear **** **** **** **** **** **** **** **** +4802 Sorcerer_Delayed_Blast_Fireball **** **** **** **** **** **** **** **** +4803 Sorcerer_DRAGON_ALLY **** **** **** **** **** **** **** **** +4804 Sorcerer_Energy_Ebb **** **** **** **** **** **** **** **** +4805 Sorcerer_Energy_Immunity **** **** **** **** **** **** **** **** +4806 Sorcerer_EI_Acid **** **** **** **** **** **** **** **** +4807 Sorcerer_EI_Cold **** **** **** **** **** **** **** **** +4808 Sorcerer_EI_Elec **** **** **** **** **** **** **** **** +4809 Sorcerer_EI_Fire **** **** **** **** **** **** **** **** +4810 Sorcerer_EI_Sonic **** **** **** **** **** **** **** **** +4811 Sorcerer_EYE_OF_THE_BEHOLDER **** **** **** **** **** **** **** **** +4812 Sorcerer_FIENDISH_CLARITY **** **** **** **** **** **** **** **** +4813 Sorcerer_Finger_of_Death **** **** **** **** **** **** **** **** +4814 Sorcerer_Great_Thunderclap **** **** **** **** **** **** **** **** +4815 Sorcerer_GreaterScrying **** **** **** **** **** **** **** **** +4816 Sorcerer_GreaterTeleport_RadialMaster **** **** **** **** **** **** **** **** +4817 Sorcerer_GreaterTeleport_SelfOnly **** **** **** **** **** **** **** **** +4818 Sorcerer_GreaterTeleport_Party **** **** **** **** **** **** **** **** +4819 Sorcerer_Insanity **** **** **** **** **** **** **** **** +4820 Sorcerer_Mass_Hold_Person **** **** **** **** **** **** **** **** +4821 Sorcerer_Mordenkainens_Sword **** **** **** **** **** **** **** **** +4822 Sorcerer_Mords_Mansion **** **** **** **** **** **** **** **** +4823 Sorcerer_Nybors_Stern_Reproof **** **** **** **** **** **** **** **** +4824 Sorcerer_Power_Word_Blind **** **** **** **** **** **** **** **** +4825 Sorcerer_Power_Word_Stun **** **** **** **** **** **** **** **** +4826 Sorcerer_Prismatic_Spray **** **** **** **** **** **** **** **** +4827 Sorcerer_Protection_from_Spells **** **** **** **** **** **** **** **** +4828 Sorcerer_Sequester **** **** **** **** **** **** **** **** +4829 Sorcerer_Shadow_Shield **** **** **** **** **** **** **** **** +4830 Sorcerer_Spell_Mantle **** **** **** **** **** **** **** **** +4831 Sorcerer_Spell_Turning **** **** **** **** **** **** **** **** +4832 Sorcerer_Summon_Creature_VII **** **** **** **** **** **** **** **** +4833 Sorcerer_Summon7Air **** **** **** **** **** **** **** **** +4834 Sorcerer_Summon7Earth **** **** **** **** **** **** **** **** +4835 Sorcerer_Summon7Fire **** **** **** **** **** **** **** **** +4836 Sorcerer_Summon7Water **** **** **** **** **** **** **** **** +4837 Sorcerer_SYMBOL_OF_STUNING **** **** **** **** **** **** **** **** +4838 Sorcerer_SYMBOL_OF_WEAKNESS **** **** **** **** **** **** **** **** +4839 Sorcerer_TOMB_OF_LIGHT **** **** **** **** **** **** **** **** +4840 Sorcerer_WavesOfExhaustion **** **** **** **** **** **** **** **** +4841 Sorcerer_Avascular_Mass **** **** **** **** **** **** **** **** +4842 Sorcerer_Bigbys_Clenched_Fist **** **** **** **** **** **** **** **** +4843 Sorcerer_Blackstaff **** **** **** **** **** **** **** **** +4844 Sorcerer_Create_Undead **** **** **** **** **** **** **** **** +4845 Sorcerer_Dimensional_Lock **** **** **** **** **** **** **** **** +4846 Sorcerer_DiscernLocation **** **** **** **** **** **** **** **** +4847 Sorcerer_Etherealness **** **** **** **** **** **** **** **** +4848 Sorcerer_Flensing **** **** **** **** **** **** **** **** +4849 Sorcerer_Greater_Planar_Binding **** **** **** **** **** **** **** **** +4850 Sorcerer_Greater_Shout **** **** **** **** **** **** **** **** +4851 Sorcerer_Greater_Wall_of_Dispel_Magic **** **** **** **** **** **** **** **** +4852 Sorcerer_GUTWRENCH **** **** **** **** **** **** **** **** +4853 Sorcerer_Horrid_Wilting **** **** **** **** **** **** **** **** +4854 Sorcerer_Incendiary_Cloud **** **** **** **** **** **** **** **** +4855 Sorcerer_IRON_BODY **** **** **** **** **** **** **** **** +4856 Sorcerer_LAST_JUDGEMENT **** **** **** **** **** **** **** **** +4857 Sorcerer_Mantle_of_Eg_Might **** **** **** **** **** **** **** **** +4858 Sorcerer_Mass_Blindness_and_Deafness **** **** **** **** **** **** **** **** +4859 Sorcerer_Mass_Charm **** **** **** **** **** **** **** **** +4860 Sorcerer_Maze **** **** **** **** **** **** **** **** +4861 Sorcerer_Mind_Blank **** **** **** **** **** **** **** **** +4862 Sorcerer_Necrotic_Empowerment **** **** **** **** **** **** **** **** +4863 Sorcerer_PolarRay **** **** **** **** **** **** **** **** +4864 Sorcerer_Premonition **** **** **** **** **** **** **** **** +4865 Sorcerer_PrismaticWall **** **** **** **** **** **** **** **** +4866 Sorcerer_ScintillatingPattern **** **** **** **** **** **** **** **** +4867 Sorcerer_Summon_Creature_VIII **** **** **** **** **** **** **** **** +4868 Sorcerer_Summon8Air **** **** **** **** **** **** **** **** +4869 Sorcerer_Summon8Earth **** **** **** **** **** **** **** **** +4870 Sorcerer_Summon8Fire **** **** **** **** **** **** **** **** +4871 Sorcerer_Summon8Water **** **** **** **** **** **** **** **** +4872 Sorcerer_Sunburst **** **** **** **** **** **** **** **** +4873 Sorcerer_SYMBOL_OF_DEATH **** **** **** **** **** **** **** **** +4874 Sorcerer_SYMBOL_OF_INSANITY **** **** **** **** **** **** **** **** +4875 Sorcerer_Bigbys_Crushing_Hand **** **** **** **** **** **** **** **** +4876 Sorcerer_Black_Blade_of_Disaster **** **** **** **** **** **** **** **** +4877 Sorcerer_BLINDING_GLORY **** **** **** **** **** **** **** **** +4878 Sorcerer_CRUSHING_FIST_OF_SPITE **** **** **** **** **** **** **** **** +4879 Sorcerer_Dominate_Monster **** **** **** **** **** **** **** **** +4880 Sorcerer_Energy_Drain **** **** **** **** **** **** **** **** +4881 Sorcerer_Foresight **** **** **** **** **** **** **** **** +4882 Sorcerer_Gate **** **** **** **** **** **** **** **** +4883 Sorcerer_Greater_Spell_Mantle **** **** **** **** **** **** **** **** +4884 Sorcerer_Mass_Hold_Monster **** **** **** **** **** **** **** **** +4885 Sorcerer_Meteor_Swarm **** **** **** **** **** **** **** **** +4886 Sorcerer_Mordenkainens_Disjunction **** **** **** **** **** **** **** **** +4887 Sorcerer_Necrotic_Termination **** **** **** **** **** **** **** **** +4888 Sorcerer_PlagueOfUndead **** **** **** **** **** **** **** **** +4889 Sorcerer_Power_Word_Kill **** **** **** **** **** **** **** **** +4890 Sorcerer_PrismaticSphere **** **** **** **** **** **** **** **** +4891 Sorcerer_Shapechange **** **** **** **** **** **** **** **** +4892 Sorcerer_Shapechange_RED_DRAGON **** **** **** **** **** **** **** **** +4893 Sorcerer_Shapechange_FIRE_GIANT **** **** **** **** **** **** **** **** +4894 Sorcerer_Shapechange_BALOR **** **** **** **** **** **** **** **** +4895 Sorcerer_Shapechange_DEATH_SLAAD **** **** **** **** **** **** **** **** +4896 Sorcerer_Shapechange_IRON_GOLEM **** **** **** **** **** **** **** **** +4897 Sorcerer_Sphere_of_Ultimate_Destruction **** **** **** **** **** **** **** **** +4898 Sorcerer_Summon_Creature_IX **** **** **** **** **** **** **** **** +4899 Sorcerer_Summon9Air **** **** **** **** **** **** **** **** +4900 Sorcerer_Summon9Earth **** **** **** **** **** **** **** **** +4901 Sorcerer_Summon9Fire **** **** **** **** **** **** **** **** +4902 Sorcerer_Summon9Water **** **** **** **** **** **** **** **** +4903 Sorcerer_TeleportationCircle_RadialMaster **** **** **** **** **** **** **** **** +4904 Sorcerer_TeleportationCircle_Visible **** **** **** **** **** **** **** **** +4905 Sorcerer_TeleportationCircle_Hidden **** **** **** **** **** **** **** **** +4906 Sorcerer_Time_Stop **** **** **** **** **** **** **** **** +4907 Sorcerer_UTTERDARK **** **** **** **** **** **** **** **** +4908 Sorcerer_VileDeath **** **** **** **** **** **** **** **** +4909 Sorcerer_Wail_of_the_Banshee **** **** **** **** **** **** **** **** +4910 Sorcerer_Weird **** **** **** **** **** **** **** **** +4911 Harper_Camoflage **** **** **** **** **** **** **** **** +4912 Harper_Alter_Self_Radial_Master **** **** **** **** **** **** **** **** +4913 Harper_Alter_Self_Learn **** **** **** **** **** **** **** **** +4914 Harper_Alter_Self_Options **** **** **** **** **** **** **** **** +4915 Harper_Alter_Self_QS1 **** **** **** **** **** **** **** **** +4916 Harper_Alter_Self_QS2 **** **** **** **** **** **** **** **** +4917 Harper_Alter_Self_QS3 **** **** **** **** **** **** **** **** +4918 Harper_Charm_Person **** **** **** **** **** **** **** **** +4919 Harper_Spell_Jump **** **** **** **** **** **** **** **** +4920 Harper_Light **** **** **** **** **** **** **** **** +4921 Harper_Read_Magic **** **** **** **** **** **** **** **** +4922 Harper_Sleep **** **** **** **** **** **** **** **** +4923 Harper_Cats_Grace **** **** **** **** **** **** **** **** +4924 Harper_Eagle_Splendor **** **** **** **** **** **** **** **** +4925 Harper_Invisibility **** **** **** **** **** **** **** **** +4926 Harper_Knock **** **** **** **** **** **** **** **** +4927 Harper_LocateObject **** **** **** **** **** **** **** **** +4928 Harper_See_Invisibility **** **** **** **** **** **** **** **** +4929 Harper_Clairaudience_and_Clairvoyance **** **** **** **** **** **** **** **** +4930 Harper_NONDETECTION **** **** **** **** **** **** **** **** +4931 Harper_UndetectableAlignment **** **** **** **** **** **** **** **** +4932 Assassin_ADDICTION **** **** **** **** **** **** **** **** +4933 Assassin_ADDICTION_TERRAN_BRANDY **** **** **** **** **** **** **** **** +4934 Assassin_ADDICTION_MUSHROOM_POWDER **** **** **** **** **** **** **** **** +4935 Assassin_ADDICTION_VODARE **** **** **** **** **** **** **** **** +4936 Assassin_ADDICTION_AGONY **** **** **** **** **** **** **** **** +4937 Assassin_ANGRY_ACHE **** **** **** **** **** **** **** **** +4938 Assassin_Blade_of_Blood **** **** **** **** **** **** **** **** +4939 Assassin_Blade_of_Blood_1d6 **** **** **** **** **** **** **** **** +4940 Assassin_Blade_of_Blood_3d6 **** **** **** **** **** **** **** **** +4941 Assassin_Disguise_Self_Radial_Master **** **** **** **** **** **** **** **** +4942 Assassin_Disguise_Self_Learn **** **** **** **** **** **** **** **** +4943 Assassin_Disguise_Self_Options **** **** **** **** **** **** **** **** +4944 Assassin_Disguise_Self_QS1 **** **** **** **** **** **** **** **** +4945 Assassin_Disguise_Self_QS2 **** **** **** **** **** **** **** **** +4946 Assassin_Disguise_Self_QS3 **** **** **** **** **** **** **** **** +4947 Assassin_Spell_Jump **** **** **** **** **** **** **** **** +4948 Assassin_Obscuring_Mist **** **** **** **** **** **** **** **** +4949 Assassin_Sleep **** **** **** **** **** **** **** **** +4950 Assassin_True_Strike **** **** **** **** **** **** **** **** +4951 Assassin_Alter_Self_Radial_Master **** **** **** **** **** **** **** **** +4952 Assassin_Alter_Self_Learn **** **** **** **** **** **** **** **** +4953 Assassin_Alter_Self_Options **** **** **** **** **** **** **** **** +4954 Assassin_Alter_Self_QS1 **** **** **** **** **** **** **** **** +4955 Assassin_Alter_Self_QS2 **** **** **** **** **** **** **** **** +4956 Assassin_Alter_Self_QS3 **** **** **** **** **** **** **** **** +4957 Assassin_Cats_Grace **** **** **** **** **** **** **** **** +4958 Assassin_Darkness **** **** **** **** **** **** **** **** +4959 Assassin_Foxs_Cunning **** **** **** **** **** **** **** **** +4960 Assassin_IceKnife **** **** **** **** **** **** **** **** +4961 Assassin_Invisibility **** **** **** **** **** **** **** **** +4962 Assassin_UndetectableAlignment **** **** **** **** **** **** **** **** +4963 Assassin_DeeperDarkness **** **** **** **** **** **** **** **** +4964 Assassin_DeepSlumber **** **** **** **** **** **** **** **** +4965 Assassin_FalseLife **** **** **** **** **** **** **** **** +4966 Assassin_Magic_Circle_against_Good **** **** **** **** **** **** **** **** +4967 Assassin_MASOCHISM **** **** **** **** **** **** **** **** +4968 Assassin_NONDETECTION **** **** **** **** **** **** **** **** +4969 Assassin_Clairaudience_and_Clairvoyance **** **** **** **** **** **** **** **** +4970 Assassin_CursedBlade **** **** **** **** **** **** **** **** +4971 Assassin_DimensionDoor_RadialMaster **** **** **** **** **** **** **** **** +4972 Assassin_DimensionDoor_SelfOnly **** **** **** **** **** **** **** **** +4973 Assassin_DimensionDoor_Party **** **** **** **** **** **** **** **** +4974 Assassin_DimensionDoor_DirDist_SelfOnly **** **** **** **** **** **** **** **** +4975 Assassin_DimensionDoor_DirDist_Party **** **** **** **** **** **** **** **** +4976 Assassin_FLESH_ARMOR **** **** **** **** **** **** **** **** +4977 Assassin_Freedom_of_Movement **** **** **** **** **** **** **** **** +4978 Assassin_GLIBNESS **** **** **** **** **** **** **** **** +4979 Assassin_HeartRipper **** **** **** **** **** **** **** **** +4980 Assassin_Improved_Invisibility **** **** **** **** **** **** **** **** +4981 Assassin_LocateCreature **** **** **** **** **** **** **** **** +4982 Assassin_Poison **** **** **** **** **** **** **** **** +4983 Assassin_STOP_HEART **** **** **** **** **** **** **** **** +4984 Blackguard_Cure_Light_Wounds **** **** **** **** **** **** **** **** +4985 Blackguard_Empowered_Cure_Light_Wounds **** **** **** **** **** **** **** **** +4986 Blackguard_Maximized_Cure_Light_Wounds **** **** **** **** **** **** **** **** +4987 Blackguard_Silent_Cure_Light_Wounds **** **** **** **** **** **** **** **** +4988 Blackguard_Still_Cure_Light_Wounds **** **** **** **** **** **** **** **** +4989 Blackguard_Cause_Fear **** **** **** **** **** **** **** **** +4990 Blackguard_Exteneded_Cause_Fear **** **** **** **** **** **** **** **** +4991 Blackguard_Still_Cause_Fear **** **** **** **** **** **** **** **** +4992 Blackguard_Doom **** **** **** **** **** **** **** **** +4993 Blackguard_Exteneded_Doom **** **** **** **** **** **** **** **** +4994 Blackguard_Silent_Doom **** **** **** **** **** **** **** **** +4995 Blackguard_Still_Doom **** **** **** **** **** **** **** **** +4996 Blackguard_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +4997 Blackguard_Empowered_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +4998 Blackguard_Maximized_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +4999 Blackguard_Silent_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +5000 Blackguard_Still_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +5001 Blackguard_Magic_Weapon **** **** **** **** **** **** **** **** +5002 Blackguard_Exteneded_Magic_Weapon **** **** **** **** **** **** **** **** +5003 Blackguard_Silent_Magic_Weapon **** **** **** **** **** **** **** **** +5004 Blackguard_Still_Magic_Weapon **** **** **** **** **** **** **** **** +5005 Blackguard_Summon_Creature_I **** **** **** **** **** **** **** **** +5006 Blackguard_Exteneded_Summon_Creature_I **** **** **** **** **** **** **** **** +5007 Blackguard_Silent_Summon_Creature_I **** **** **** **** **** **** **** **** +5008 Blackguard_Still_Summon_Creature_I **** **** **** **** **** **** **** **** +5009 Blackguard_Blade_of_Blood **** **** **** **** **** **** **** **** +5010 Blackguard_Blade_of_Blood_1d6 **** **** **** **** **** **** **** **** +5011 Blackguard_Blade_of_Blood_3d6 **** **** **** **** **** **** **** **** +5012 Blackguard_Empowered_Blade_of_Blood **** **** **** **** **** **** **** **** +5013 Blackguard_Empowered_Blade_of_Blood_1d6 **** **** **** **** **** **** **** **** +5014 Blackguard_Empowered_Blade_of_Blood_3d6 **** **** **** **** **** **** **** **** +5015 Blackguard_Exteneded_Blade_of_Blood **** **** **** **** **** **** **** **** +5016 Blackguard_Exteneded_Blade_of_Blood_1d6 **** **** **** **** **** **** **** **** +5017 Blackguard_Exteneded_Blade_of_Blood_3d6 **** **** **** **** **** **** **** **** +5018 Blackguard_Maximized_Blade_of_Blood **** **** **** **** **** **** **** **** +5019 Blackguard_Maximized_Blade_of_Blood_1d6 **** **** **** **** **** **** **** **** +5020 Blackguard_Maximized_Blade_of_Blood_3d6 **** **** **** **** **** **** **** **** +5021 Blackguard_Silent_Blade_of_Blood **** **** **** **** **** **** **** **** +5022 Blackguard_Silent_Blade_of_Blood_1d6 **** **** **** **** **** **** **** **** +5023 Blackguard_Silent_Blade_of_Blood_3d6 **** **** **** **** **** **** **** **** +5024 Blackguard_Still_Blade_of_Blood **** **** **** **** **** **** **** **** +5025 Blackguard_Still_Blade_of_Blood_1d6 **** **** **** **** **** **** **** **** +5026 Blackguard_Still_Blade_of_Blood_3d6 **** **** **** **** **** **** **** **** +5027 Blackguard_BONEBLAST **** **** **** **** **** **** **** **** +5028 Blackguard_Silent_BONEBLAST **** **** **** **** **** **** **** **** +5029 Blackguard_Still_BONEBLAST **** **** **** **** **** **** **** **** +5030 Blackguard_DEMONFLESH **** **** **** **** **** **** **** **** +5031 Blackguard_Exteneded_DEMONFLESH **** **** **** **** **** **** **** **** +5032 Blackguard_Silent_DEMONFLESH **** **** **** **** **** **** **** **** +5033 Blackguard_Still_DEMONFLESH **** **** **** **** **** **** **** **** +5034 Blackguard_SEETHING_EYEBANE **** **** **** **** **** **** **** **** +5035 Blackguard_Silent_SEETHING_EYEBANE **** **** **** **** **** **** **** **** +5036 Blackguard_Still_SEETHING_EYEBANE **** **** **** **** **** **** **** **** +5037 Blackguard_SummonUndeadI **** **** **** **** **** **** **** **** +5038 Blackguard_Exteneded_SummonUndeadI **** **** **** **** **** **** **** **** +5039 Blackguard_Silent_SummonUndeadI **** **** **** **** **** **** **** **** +5040 Blackguard_Still_SummonUndeadI **** **** **** **** **** **** **** **** +5041 Blackguard_Bulls_Strength **** **** **** **** **** **** **** **** +5042 Blackguard_Empowered_Bulls_Strength **** **** **** **** **** **** **** **** +5043 Blackguard_Exteneded_Bulls_Strength **** **** **** **** **** **** **** **** +5044 Blackguard_Silent_Bulls_Strength **** **** **** **** **** **** **** **** +5045 Blackguard_Still_Bulls_Strength **** **** **** **** **** **** **** **** +5046 Blackguard_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +5047 Blackguard_Empowered_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +5048 Blackguard_Silent_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +5049 Blackguard_Still_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +5050 Blackguard_Darkness **** **** **** **** **** **** **** **** +5051 Blackguard_Exteneded_Darkness **** **** **** **** **** **** **** **** +5052 Blackguard_Silent_Darkness **** **** **** **** **** **** **** **** +5053 Blackguard_Eagle_Splendor **** **** **** **** **** **** **** **** +5054 Blackguard_Empowered_Eagle_Splendor **** **** **** **** **** **** **** **** +5055 Blackguard_Exteneded_Eagle_Splendor **** **** **** **** **** **** **** **** +5056 Blackguard_Silent_Eagle_Splendor **** **** **** **** **** **** **** **** +5057 Blackguard_Still_Eagle_Splendor **** **** **** **** **** **** **** **** +5058 Blackguard_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +5059 Blackguard_Empowered_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +5060 Blackguard_Silent_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +5061 Blackguard_Still_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +5062 Blackguard_Summon_Creature_II **** **** **** **** **** **** **** **** +5063 Blackguard_Exteneded_Summon_Creature_II **** **** **** **** **** **** **** **** +5064 Blackguard_Silent_Summon_Creature_II **** **** **** **** **** **** **** **** +5065 Blackguard_Still_Summon_Creature_II **** **** **** **** **** **** **** **** +5066 Blackguard_BONEBLADE **** **** **** **** **** **** **** **** +5067 Blackguard_BONEBLADE_GREATSWORD **** **** **** **** **** **** **** **** +5068 Blackguard_BONEBLADE_LONGSWORD **** **** **** **** **** **** **** **** +5069 Blackguard_BONEBLADE_SHORTSWORD **** **** **** **** **** **** **** **** +5070 Blackguard_Exteneded_BONEBLADE **** **** **** **** **** **** **** **** +5071 Blackguard_Exteneded_BONEBLADE_GREATSWORD **** **** **** **** **** **** **** **** +5072 Blackguard_Exteneded_BONEBLADE_LONGSWORD **** **** **** **** **** **** **** **** +5073 Blackguard_Exteneded_BONEBLADE_SHORTSWORD **** **** **** **** **** **** **** **** +5074 Blackguard_Silent_BONEBLADE **** **** **** **** **** **** **** **** +5075 Blackguard_Silent_BONEBLADE_GREATSWORD **** **** **** **** **** **** **** **** +5076 Blackguard_Silent_BONEBLADE_LONGSWORD **** **** **** **** **** **** **** **** +5077 Blackguard_Silent_BONEBLADE_SHORTSWORD **** **** **** **** **** **** **** **** +5078 Blackguard_Still_BONEBLADE **** **** **** **** **** **** **** **** +5079 Blackguard_Still_BONEBLADE_GREATSWORD **** **** **** **** **** **** **** **** +5080 Blackguard_Still_BONEBLADE_LONGSWORD **** **** **** **** **** **** **** **** +5081 Blackguard_Still_BONEBLADE_SHORTSWORD **** **** **** **** **** **** **** **** +5082 Blackguard_Death_Knell **** **** **** **** **** **** **** **** +5083 Blackguard_Empowered_Death_Knell **** **** **** **** **** **** **** **** +5084 Blackguard_Exteneded_Death_Knell **** **** **** **** **** **** **** **** +5085 Blackguard_Silent_Death_Knell **** **** **** **** **** **** **** **** +5086 Blackguard_Still_Death_Knell **** **** **** **** **** **** **** **** +5087 Blackguard_DEMONCALL **** **** **** **** **** **** **** **** +5088 Blackguard_Silent_DEMONCALL **** **** **** **** **** **** **** **** +5089 Blackguard_Still_DEMONCALL **** **** **** **** **** **** **** **** +5090 Blackguard_DEVILS_EYE **** **** **** **** **** **** **** **** +5091 Blackguard_Silent_DEVILS_EYE **** **** **** **** **** **** **** **** +5092 Blackguard_Still_DEVILS_EYE **** **** **** **** **** **** **** **** +5093 Blackguard_LAHMS_FINGER_DARTS **** **** **** **** **** **** **** **** +5094 Blackguard_Silent_LAHMS_FINGER_DARTS **** **** **** **** **** **** **** **** +5095 Blackguard_Still_LAHMS_FINGER_DARTS **** **** **** **** **** **** **** **** +5096 Blackguard_SummonUndeadII **** **** **** **** **** **** **** **** +5097 Blackguard_Exteneded_SummonUndeadII **** **** **** **** **** **** **** **** +5098 Blackguard_Silent_SummonUndeadII **** **** **** **** **** **** **** **** +5099 Blackguard_Still_SummonUndeadII **** **** **** **** **** **** **** **** +5100 Blackguard_Contagion **** **** **** **** **** **** **** **** +5101 Blackguard_Silent_Contagion **** **** **** **** **** **** **** **** +5102 Blackguard_Still_Contagion **** **** **** **** **** **** **** **** +5103 Blackguard_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +5104 Blackguard_Silent_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +5105 Blackguard_Still_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +5106 Blackguard_DeeperDarkness **** **** **** **** **** **** **** **** +5107 Blackguard_Exteneded_DeeperDarkness **** **** **** **** **** **** **** **** +5108 Blackguard_Silent_DeeperDarkness **** **** **** **** **** **** **** **** +5109 Blackguard_Inflict_Serious_Wounds **** **** **** **** **** **** **** **** +5110 Blackguard_Silent_Inflict_Serious_Wounds **** **** **** **** **** **** **** **** +5111 Blackguard_Still_Inflict_Serious_Wounds **** **** **** **** **** **** **** **** +5112 Blackguard_Protection_from_Elements **** **** **** **** **** **** **** **** +5113 Blackguard_Exteneded_Protection_from_Elements **** **** **** **** **** **** **** **** +5114 Blackguard_Silent_Protection_from_Elements **** **** **** **** **** **** **** **** +5115 Blackguard_Still_Protection_from_Elements **** **** **** **** **** **** **** **** +5116 Blackguard_Summon_Creature_III **** **** **** **** **** **** **** **** +5117 Blackguard_Exteneded_Summon_Creature_III **** **** **** **** **** **** **** **** +5118 Blackguard_Silent_Summon_Creature_III **** **** **** **** **** **** **** **** +5119 Blackguard_Still_Summon_Creature_III **** **** **** **** **** **** **** **** +5120 Blackguard_ABYSSAL_MIGHT **** **** **** **** **** **** **** **** +5121 Blackguard_Exteneded_ABYSSAL_MIGHT **** **** **** **** **** **** **** **** +5122 Blackguard_Silent_ABYSSAL_MIGHT **** **** **** **** **** **** **** **** +5123 Blackguard_Still_ABYSSAL_MIGHT **** **** **** **** **** **** **** **** +5124 Blackguard_RED_FESTER **** **** **** **** **** **** **** **** +5125 Blackguard_Silent_RED_FESTER **** **** **** **** **** **** **** **** +5126 Blackguard_Still_RED_FESTER **** **** **** **** **** **** **** **** +5127 Blackguard_ROTTING_CURSE_OF_URFESTRA **** **** **** **** **** **** **** **** +5128 Blackguard_Silent_ROTTING_CURSE_OF_URFESTRA **** **** **** **** **** **** **** **** +5129 Blackguard_Still_ROTTING_CURSE_OF_URFESTRA **** **** **** **** **** **** **** **** +5130 Blackguard_TOUCH_OF_JUIBLEX **** **** **** **** **** **** **** **** +5131 Blackguard_Silent_TOUCH_OF_JUIBLEX **** **** **** **** **** **** **** **** +5132 Blackguard_Still_TOUCH_OF_JUIBLEX **** **** **** **** **** **** **** **** +5133 Blackguard_MASOCHISM **** **** **** **** **** **** **** **** +5134 Blackguard_Exteneded_MASOCHISM **** **** **** **** **** **** **** **** +5135 Blackguard_SummonUndeadIII **** **** **** **** **** **** **** **** +5136 Blackguard_Exteneded_SummonUndeadIII **** **** **** **** **** **** **** **** +5137 Blackguard_Silent_SummonUndeadIII **** **** **** **** **** **** **** **** +5138 Blackguard_Still_SummonUndeadIII **** **** **** **** **** **** **** **** +5139 Blackguard_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +5140 Blackguard_Freedom_of_Movement **** **** **** **** **** **** **** **** +5141 Blackguard_Inflict_Critical_Wounds **** **** **** **** **** **** **** **** +5142 Blackguard_Poison **** **** **** **** **** **** **** **** +5143 Blackguard_Summon_Creature_IV **** **** **** **** **** **** **** **** +5144 Blackguard_ABSORB_STRENGTH **** **** **** **** **** **** **** **** +5145 Blackguard_CLAWS_OF_THE_SAVAGE **** **** **** **** **** **** **** **** +5146 Blackguard_SummonUndeadIV **** **** **** **** **** **** **** **** +5147 Ocular_Adept_Cure_Minor_Wounds **** **** **** **** **** **** **** **** +5148 Ocular_Adept_Quickened_Cure_Minor_Wounds **** **** **** **** **** **** **** **** +5149 Ocular_Adept_Silent_Cure_Minor_Wounds **** **** **** **** **** **** **** **** +5150 Ocular_Adept_Still_Cure_Minor_Wounds **** **** **** **** **** **** **** **** +5151 Ocular_Adept_Inflict_Minor_Wounds **** **** **** **** **** **** **** **** +5152 Ocular_Adept_Quickened_Inflict_Minor_Wounds **** **** **** **** **** **** **** **** +5153 Ocular_Adept_Silent_Inflict_Minor_Wounds **** **** **** **** **** **** **** **** +5154 Ocular_Adept_Still_Inflict_Minor_Wounds **** **** **** **** **** **** **** **** +5155 Ocular_Adept_Light **** **** **** **** **** **** **** **** +5156 Ocular_Adept_Exteneded_Light **** **** **** **** **** **** **** **** +5157 Ocular_Adept_Quickened_Light **** **** **** **** **** **** **** **** +5158 Ocular_Adept_Silent_Light **** **** **** **** **** **** **** **** +5159 Ocular_Adept_Read_Magic **** **** **** **** **** **** **** **** +5160 Ocular_Adept_Quickened_Read_Magic **** **** **** **** **** **** **** **** +5161 Ocular_Adept_Silent_Read_Magic **** **** **** **** **** **** **** **** +5162 Ocular_Adept_Still_Read_Magic **** **** **** **** **** **** **** **** +5163 Ocular_Adept_Resistance **** **** **** **** **** **** **** **** +5164 Ocular_Adept_Exteneded_Resistance **** **** **** **** **** **** **** **** +5165 Ocular_Adept_Quickened_Resistance **** **** **** **** **** **** **** **** +5166 Ocular_Adept_Silent_Resistance **** **** **** **** **** **** **** **** +5167 Ocular_Adept_Still_Resistance **** **** **** **** **** **** **** **** +5168 Ocular_Adept_Virtue **** **** **** **** **** **** **** **** +5169 Ocular_Adept_Exteneded_Virtue **** **** **** **** **** **** **** **** +5170 Ocular_Adept_Quickened_Virtue **** **** **** **** **** **** **** **** +5171 Ocular_Adept_Silent_Virtue **** **** **** **** **** **** **** **** +5172 Ocular_Adept_Still_Virtue **** **** **** **** **** **** **** **** +5173 Ocular_Adept_ANGRY_ACHE **** **** **** **** **** **** **** **** +5174 Ocular_Adept_Exteneded_ANGRY_ACHE **** **** **** **** **** **** **** **** +5175 Ocular_Adept_Quickened_ANGRY_ACHE **** **** **** **** **** **** **** **** +5176 Ocular_Adept_Silent_ANGRY_ACHE **** **** **** **** **** **** **** **** +5177 Ocular_Adept_Still_ANGRY_ACHE **** **** **** **** **** **** **** **** +5178 Ocular_Adept_Bane **** **** **** **** **** **** **** **** +5179 Ocular_Adept_Exteneded_Bane **** **** **** **** **** **** **** **** +5180 Ocular_Adept_Quickened_Bane **** **** **** **** **** **** **** **** +5181 Ocular_Adept_Silent_Bane **** **** **** **** **** **** **** **** +5182 Ocular_Adept_Still_Bane **** **** **** **** **** **** **** **** +5183 Ocular_Adept_Blade_of_Blood **** **** **** **** **** **** **** **** +5184 Ocular_Adept_Blade_of_Blood_1d6 **** **** **** **** **** **** **** **** +5185 Ocular_Adept_Blade_of_Blood_3d6 **** **** **** **** **** **** **** **** +5186 Ocular_Adept_Empowered_Blade_of_Blood **** **** **** **** **** **** **** **** +5187 Ocular_Adept_Empowered_Blade_of_Blood_1d6 **** **** **** **** **** **** **** **** +5188 Ocular_Adept_Empowered_Blade_of_Blood_3d6 **** **** **** **** **** **** **** **** +5189 Ocular_Adept_Exteneded_Blade_of_Blood **** **** **** **** **** **** **** **** +5190 Ocular_Adept_Exteneded_Blade_of_Blood_1d6 **** **** **** **** **** **** **** **** +5191 Ocular_Adept_Exteneded_Blade_of_Blood_3d6 **** **** **** **** **** **** **** **** +5192 Ocular_Adept_Maximized_Blade_of_Blood **** **** **** **** **** **** **** **** +5193 Ocular_Adept_Maximized_Blade_of_Blood_1d6 **** **** **** **** **** **** **** **** +5194 Ocular_Adept_Maximized_Blade_of_Blood_3d6 **** **** **** **** **** **** **** **** +5195 Ocular_Adept_Quickened_Blade_of_Blood **** **** **** **** **** **** **** **** +5196 Ocular_Adept_Quickened_Blade_of_Blood_1d6 **** **** **** **** **** **** **** **** +5197 Ocular_Adept_Quickened_Blade_of_Blood_3d6 **** **** **** **** **** **** **** **** +5198 Ocular_Adept_Silent_Blade_of_Blood **** **** **** **** **** **** **** **** +5199 Ocular_Adept_Silent_Blade_of_Blood_1d6 **** **** **** **** **** **** **** **** +5200 Ocular_Adept_Silent_Blade_of_Blood_3d6 **** **** **** **** **** **** **** **** +5201 Ocular_Adept_Still_Blade_of_Blood **** **** **** **** **** **** **** **** +5202 Ocular_Adept_Still_Blade_of_Blood_1d6 **** **** **** **** **** **** **** **** +5203 Ocular_Adept_Still_Blade_of_Blood_3d6 **** **** **** **** **** **** **** **** +5204 Ocular_Adept_Bless **** **** **** **** **** **** **** **** +5205 Ocular_Adept_Exteneded_Bless **** **** **** **** **** **** **** **** +5206 Ocular_Adept_Quickened_Bless **** **** **** **** **** **** **** **** +5207 Ocular_Adept_Silent_Bless **** **** **** **** **** **** **** **** +5208 Ocular_Adept_Still_Bless **** **** **** **** **** **** **** **** +5209 Ocular_Adept_Bless_Water **** **** **** **** **** **** **** **** +5210 Ocular_Adept_Quickened_Bless_Water **** **** **** **** **** **** **** **** +5211 Ocular_Adept_Silent_Bless_Water **** **** **** **** **** **** **** **** +5212 Ocular_Adept_Still_Bless_Water **** **** **** **** **** **** **** **** +5213 Ocular_Adept_Cause_Fear **** **** **** **** **** **** **** **** +5214 Ocular_Adept_Exteneded_Cause_Fear **** **** **** **** **** **** **** **** +5215 Ocular_Adept_Quickened_Cause_Fear **** **** **** **** **** **** **** **** +5216 Ocular_Adept_Still_Cause_Fear **** **** **** **** **** **** **** **** +5217 Ocular_Adept_Command_RadialMaster **** **** **** **** **** **** **** **** +5218 Ocular_Adept_Command_Approach **** **** **** **** **** **** **** **** +5219 Ocular_Adept_Command_Drop **** **** **** **** **** **** **** **** +5220 Ocular_Adept_Command_Fall **** **** **** **** **** **** **** **** +5221 Ocular_Adept_Command_Flee **** **** **** **** **** **** **** **** +5222 Ocular_Adept_Command_Halt **** **** **** **** **** **** **** **** +5223 Ocular_Adept_Exteneded_Command_RadialMaster **** **** **** **** **** **** **** **** +5224 Ocular_Adept_Exteneded_Command_Approach **** **** **** **** **** **** **** **** +5225 Ocular_Adept_Exteneded_Command_Drop **** **** **** **** **** **** **** **** +5226 Ocular_Adept_Exteneded_Command_Fall **** **** **** **** **** **** **** **** +5227 Ocular_Adept_Exteneded_Command_Flee **** **** **** **** **** **** **** **** +5228 Ocular_Adept_Exteneded_Command_Halt **** **** **** **** **** **** **** **** +5229 Ocular_Adept_Quickened_Command_RadialMaster **** **** **** **** **** **** **** **** +5230 Ocular_Adept_Quickened_Command_Approach **** **** **** **** **** **** **** **** +5231 Ocular_Adept_Quickened_Command_Drop **** **** **** **** **** **** **** **** +5232 Ocular_Adept_Quickened_Command_Fall **** **** **** **** **** **** **** **** +5233 Ocular_Adept_Quickened_Command_Flee **** **** **** **** **** **** **** **** +5234 Ocular_Adept_Quickened_Command_Halt **** **** **** **** **** **** **** **** +5235 Ocular_Adept_Silent_Command_RadialMaster **** **** **** **** **** **** **** **** +5236 Ocular_Adept_Silent_Command_Approach **** **** **** **** **** **** **** **** +5237 Ocular_Adept_Silent_Command_Drop **** **** **** **** **** **** **** **** +5238 Ocular_Adept_Silent_Command_Fall **** **** **** **** **** **** **** **** +5239 Ocular_Adept_Silent_Command_Flee **** **** **** **** **** **** **** **** +5240 Ocular_Adept_Silent_Command_Halt **** **** **** **** **** **** **** **** +5241 Ocular_Adept_Still_Command_RadialMaster **** **** **** **** **** **** **** **** +5242 Ocular_Adept_Still_Command_Approach **** **** **** **** **** **** **** **** +5243 Ocular_Adept_Still_Command_Drop **** **** **** **** **** **** **** **** +5244 Ocular_Adept_Still_Command_Fall **** **** **** **** **** **** **** **** +5245 Ocular_Adept_Still_Command_Flee **** **** **** **** **** **** **** **** +5246 Ocular_Adept_Still_Command_Halt **** **** **** **** **** **** **** **** +5247 Ocular_Adept_Conviction **** **** **** **** **** **** **** **** +5248 Ocular_Adept_Exteneded_Conviction **** **** **** **** **** **** **** **** +5249 Ocular_Adept_Quickened_Conviction **** **** **** **** **** **** **** **** +5250 Ocular_Adept_Silent_Conviction **** **** **** **** **** **** **** **** +5251 Ocular_Adept_Still_Conviction **** **** **** **** **** **** **** **** +5252 Ocular_Adept_Crafters_Blessing **** **** **** **** **** **** **** **** +5253 Ocular_Adept_Exteneded_Crafters_Blessing **** **** **** **** **** **** **** **** +5254 Ocular_Adept_Quickened_Crafters_Blessing **** **** **** **** **** **** **** **** +5255 Ocular_Adept_Silent_Crafters_Blessing **** **** **** **** **** **** **** **** +5256 Ocular_Adept_Still_Crafters_Blessing **** **** **** **** **** **** **** **** +5257 Ocular_Adept_Crafters_Curse **** **** **** **** **** **** **** **** +5258 Ocular_Adept_Exteneded_Crafters_Curse **** **** **** **** **** **** **** **** +5259 Ocular_Adept_Quickened_Crafters_Curse **** **** **** **** **** **** **** **** +5260 Ocular_Adept_Silent_Crafters_Curse **** **** **** **** **** **** **** **** +5261 Ocular_Adept_Still_Crafters_Curse **** **** **** **** **** **** **** **** +5262 Ocular_Adept_Cure_Light_Wounds **** **** **** **** **** **** **** **** +5263 Ocular_Adept_Empowered_Cure_Light_Wounds **** **** **** **** **** **** **** **** +5264 Ocular_Adept_Maximized_Cure_Light_Wounds **** **** **** **** **** **** **** **** +5265 Ocular_Adept_Quickened_Cure_Light_Wounds **** **** **** **** **** **** **** **** +5266 Ocular_Adept_Silent_Cure_Light_Wounds **** **** **** **** **** **** **** **** +5267 Ocular_Adept_Still_Cure_Light_Wounds **** **** **** **** **** **** **** **** +5268 Ocular_Adept_Curse_Water **** **** **** **** **** **** **** **** +5269 Ocular_Adept_Quickened_Curse_Water **** **** **** **** **** **** **** **** +5270 Ocular_Adept_Silent_Curse_Water **** **** **** **** **** **** **** **** +5271 Ocular_Adept_Still_Curse_Water **** **** **** **** **** **** **** **** +5272 Ocular_Adept_Detect_Chaos **** **** **** **** **** **** **** **** +5273 Ocular_Adept_Exteneded_Detect_Chaos **** **** **** **** **** **** **** **** +5274 Ocular_Adept_Quickened_Detect_Chaos **** **** **** **** **** **** **** **** +5275 Ocular_Adept_Silent_Detect_Chaos **** **** **** **** **** **** **** **** +5276 Ocular_Adept_Still_Detect_Chaos **** **** **** **** **** **** **** **** +5277 Ocular_Adept_Detect_Evil **** **** **** **** **** **** **** **** +5278 Ocular_Adept_Exteneded_Detect_Evil **** **** **** **** **** **** **** **** +5279 Ocular_Adept_Quickened_Detect_Evil **** **** **** **** **** **** **** **** +5280 Ocular_Adept_Silent_Detect_Evil **** **** **** **** **** **** **** **** +5281 Ocular_Adept_Still_Detect_Evil **** **** **** **** **** **** **** **** +5282 Ocular_Adept_Detect_Good **** **** **** **** **** **** **** **** +5283 Ocular_Adept_Exteneded_Detect_Good **** **** **** **** **** **** **** **** +5284 Ocular_Adept_Quickened_Detect_Good **** **** **** **** **** **** **** **** +5285 Ocular_Adept_Silent_Detect_Good **** **** **** **** **** **** **** **** +5286 Ocular_Adept_Still_Detect_Good **** **** **** **** **** **** **** **** +5287 Ocular_Adept_Detect_Law **** **** **** **** **** **** **** **** +5288 Ocular_Adept_Exteneded_Detect_Law **** **** **** **** **** **** **** **** +5289 Ocular_Adept_Quickened_Detect_Law **** **** **** **** **** **** **** **** +5290 Ocular_Adept_Silent_Detect_Law **** **** **** **** **** **** **** **** +5291 Ocular_Adept_Still_Detect_Law **** **** **** **** **** **** **** **** +5292 Ocular_Adept_DETECT_UNDEAD **** **** **** **** **** **** **** **** +5293 Ocular_Adept_Exteneded_DETECT_UNDEAD **** **** **** **** **** **** **** **** +5294 Ocular_Adept_Quickened_DETECT_UNDEAD **** **** **** **** **** **** **** **** +5295 Ocular_Adept_Silent_DETECT_UNDEAD **** **** **** **** **** **** **** **** +5296 Ocular_Adept_Still_DETECT_UNDEAD **** **** **** **** **** **** **** **** +5297 Ocular_Adept_Divine_Favor **** **** **** **** **** **** **** **** +5298 Ocular_Adept_Exteneded_Divine_Favor **** **** **** **** **** **** **** **** +5299 Ocular_Adept_Quickened_Divine_Favor **** **** **** **** **** **** **** **** +5300 Ocular_Adept_Silent_Divine_Favor **** **** **** **** **** **** **** **** +5301 Ocular_Adept_Still_Divine_Favor **** **** **** **** **** **** **** **** +5302 Ocular_Adept_Doom **** **** **** **** **** **** **** **** +5303 Ocular_Adept_Exteneded_Doom **** **** **** **** **** **** **** **** +5304 Ocular_Adept_Quickened_Doom **** **** **** **** **** **** **** **** +5305 Ocular_Adept_Silent_Doom **** **** **** **** **** **** **** **** +5306 Ocular_Adept_Still_Doom **** **** **** **** **** **** **** **** +5307 Ocular_Adept_DRUG_RESISTANCE **** **** **** **** **** **** **** **** +5308 Ocular_Adept_Quickened_DRUG_RESISTANCE **** **** **** **** **** **** **** **** +5309 Ocular_Adept_Silent_DRUG_RESISTANCE **** **** **** **** **** **** **** **** +5310 Ocular_Adept_Endure_Elements **** **** **** **** **** **** **** **** +5311 Ocular_Adept_Exteneded_Endure_Elements **** **** **** **** **** **** **** **** +5312 Ocular_Adept_Quickened_Endure_Elements **** **** **** **** **** **** **** **** +5313 Ocular_Adept_Silent_Endure_Elements **** **** **** **** **** **** **** **** +5314 Ocular_Adept_Still_Endure_Elements **** **** **** **** **** **** **** **** +5315 Ocular_Adept_Entropic_Shield **** **** **** **** **** **** **** **** +5316 Ocular_Adept_Exteneded_Entropic_Shield **** **** **** **** **** **** **** **** +5317 Ocular_Adept_Quickened_Entropic_Shield **** **** **** **** **** **** **** **** +5318 Ocular_Adept_Silent_Entropic_Shield **** **** **** **** **** **** **** **** +5319 Ocular_Adept_Still_Entropic_Shield **** **** **** **** **** **** **** **** +5320 Ocular_Adept_EXTRACT_DRUG **** **** **** **** **** **** **** **** +5321 Ocular_Adept_EXTRACT_BACCARAN **** **** **** **** **** **** **** **** +5322 Ocular_Adept_EXTRACT_VODARE **** **** **** **** **** **** **** **** +5323 Ocular_Adept_EXTRACT_SANNISH **** **** **** **** **** **** **** **** +5324 Ocular_Adept_EXTRACT_MUSHROOM_POWDER **** **** **** **** **** **** **** **** +5325 Ocular_Adept_Quickened_EXTRACT_DRUG **** **** **** **** **** **** **** **** +5326 Ocular_Adept_Quickened_EXTRACT_BACCARAN **** **** **** **** **** **** **** **** +5327 Ocular_Adept_Quickened_EXTRACT_VODARE **** **** **** **** **** **** **** **** +5328 Ocular_Adept_Quickened_EXTRACT_SANNISH **** **** **** **** **** **** **** **** +5329 Ocular_Adept_Quickened_EXTRACT_MUSHROOM_POWDER **** **** **** **** **** **** **** **** +5330 Ocular_Adept_Silent_EXTRACT_DRUG **** **** **** **** **** **** **** **** +5331 Ocular_Adept_Silent_EXTRACT_BACCARAN **** **** **** **** **** **** **** **** +5332 Ocular_Adept_Silent_EXTRACT_VODARE **** **** **** **** **** **** **** **** +5333 Ocular_Adept_Silent_EXTRACT_SANNISH **** **** **** **** **** **** **** **** +5334 Ocular_Adept_Silent_EXTRACT_MUSHROOM_POWDER **** **** **** **** **** **** **** **** +5335 Ocular_Adept_Still_EXTRACT_DRUG **** **** **** **** **** **** **** **** +5336 Ocular_Adept_Still_EXTRACT_BACCARAN **** **** **** **** **** **** **** **** +5337 Ocular_Adept_Still_EXTRACT_VODARE **** **** **** **** **** **** **** **** +5338 Ocular_Adept_Still_EXTRACT_SANNISH **** **** **** **** **** **** **** **** +5339 Ocular_Adept_Still_EXTRACT_MUSHROOM_POWDER **** **** **** **** **** **** **** **** +5340 Ocular_Adept_EYES_OF_THE_AVORAL **** **** **** **** **** **** **** **** +5341 Ocular_Adept_Exteneded_EYES_OF_THE_AVORAL **** **** **** **** **** **** **** **** +5342 Ocular_Adept_Quickened_EYES_OF_THE_AVORAL **** **** **** **** **** **** **** **** +5343 Ocular_Adept_Still_EYES_OF_THE_AVORAL **** **** **** **** **** **** **** **** +5344 Ocular_Adept_HEARTACHE **** **** **** **** **** **** **** **** +5345 Ocular_Adept_Exteneded_HEARTACHE **** **** **** **** **** **** **** **** +5346 Ocular_Adept_Quickened_HEARTACHE **** **** **** **** **** **** **** **** +5347 Ocular_Adept_Silent_HEARTACHE **** **** **** **** **** **** **** **** +5348 Ocular_Adept_Still_HEARTACHE **** **** **** **** **** **** **** **** +5349 Ocular_Adept_HideFromUndead **** **** **** **** **** **** **** **** +5350 Ocular_Adept_Exteneded_HideFromUndead **** **** **** **** **** **** **** **** +5351 Ocular_Adept_Quickened_HideFromUndead **** **** **** **** **** **** **** **** +5352 Ocular_Adept_Still_HideFromUndead **** **** **** **** **** **** **** **** +5353 Ocular_Adept_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +5354 Ocular_Adept_Empowered_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +5355 Ocular_Adept_Maximized_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +5356 Ocular_Adept_Quickened_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +5357 Ocular_Adept_Silent_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +5358 Ocular_Adept_Still_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +5359 Ocular_Adept_LANTERN_LIGHT **** **** **** **** **** **** **** **** +5360 Ocular_Adept_Empowered_LANTERN_LIGHT **** **** **** **** **** **** **** **** +5361 Ocular_Adept_Maximized_LANTERN_LIGHT **** **** **** **** **** **** **** **** +5362 Ocular_Adept_Quickened_LANTERN_LIGHT **** **** **** **** **** **** **** **** +5363 Ocular_Adept_Still_LANTERN_LIGHT **** **** **** **** **** **** **** **** +5364 Ocular_Adept_LESSER_SHIVERING_TOUCH **** **** **** **** **** **** **** **** +5365 Ocular_Adept_Empowered_LESSER_SHIVERING_TOUCH **** **** **** **** **** **** **** **** +5366 Ocular_Adept_Exteneded_LESSER_SHIVERING_TOUCH **** **** **** **** **** **** **** **** +5367 Ocular_Adept_Maximized_LESSER_SHIVERING_TOUCH **** **** **** **** **** **** **** **** +5368 Ocular_Adept_Quickened_LESSER_SHIVERING_TOUCH **** **** **** **** **** **** **** **** +5369 Ocular_Adept_Silent_LESSER_SHIVERING_TOUCH **** **** **** **** **** **** **** **** +5370 Ocular_Adept_Still_LESSER_SHIVERING_TOUCH **** **** **** **** **** **** **** **** +5371 Ocular_Adept_Lesser_Vigor **** **** **** **** **** **** **** **** +5372 Ocular_Adept_Exteneded_Lesser_Vigor **** **** **** **** **** **** **** **** +5373 Ocular_Adept_Quickened_Lesser_Vigor **** **** **** **** **** **** **** **** +5374 Ocular_Adept_Silent_Lesser_Vigor **** **** **** **** **** **** **** **** +5375 Ocular_Adept_Still_Lesser_Vigor **** **** **** **** **** **** **** **** +5376 Ocular_Adept_Magic_Stone **** **** **** **** **** **** **** **** +5377 Ocular_Adept_Exteneded_Magic_Stone **** **** **** **** **** **** **** **** +5378 Ocular_Adept_Quickened_Magic_Stone **** **** **** **** **** **** **** **** +5379 Ocular_Adept_Silent_Magic_Stone **** **** **** **** **** **** **** **** +5380 Ocular_Adept_Still_Magic_Stone **** **** **** **** **** **** **** **** +5381 Ocular_Adept_Magic_Weapon **** **** **** **** **** **** **** **** +5382 Ocular_Adept_Exteneded_Magic_Weapon **** **** **** **** **** **** **** **** +5383 Ocular_Adept_Quickened_Magic_Weapon **** **** **** **** **** **** **** **** +5384 Ocular_Adept_Silent_Magic_Weapon **** **** **** **** **** **** **** **** +5385 Ocular_Adept_Still_Magic_Weapon **** **** **** **** **** **** **** **** +5386 Ocular_Adept_Necrotic_Awareness **** **** **** **** **** **** **** **** +5387 Ocular_Adept_Quickened_Necrotic_Awareness **** **** **** **** **** **** **** **** +5388 Ocular_Adept_Silent_Necrotic_Awareness **** **** **** **** **** **** **** **** +5389 Ocular_Adept_Still_Necrotic_Awareness **** **** **** **** **** **** **** **** +5390 Ocular_Adept_Obscuring_Mist **** **** **** **** **** **** **** **** +5391 Ocular_Adept_Exteneded_Obscuring_Mist **** **** **** **** **** **** **** **** +5392 Ocular_Adept_Quickened_Obscuring_Mist **** **** **** **** **** **** **** **** +5393 Ocular_Adept_Silent_Obscuring_Mist **** **** **** **** **** **** **** **** +5394 Ocular_Adept_Still_Obscuring_Mist **** **** **** **** **** **** **** **** +5395 Ocular_Adept_Protection_from_Chaos **** **** **** **** **** **** **** **** +5396 Ocular_Adept_Exteneded_Protection_from_Chaos **** **** **** **** **** **** **** **** +5397 Ocular_Adept_Quickened_Protection_from_Chaos **** **** **** **** **** **** **** **** +5398 Ocular_Adept_Silent_Protection_from_Chaos **** **** **** **** **** **** **** **** +5399 Ocular_Adept_Still_Protection_from_Chaos **** **** **** **** **** **** **** **** +5400 Ocular_Adept_Protection_from_Evil **** **** **** **** **** **** **** **** +5401 Ocular_Adept_Exteneded_Protection_from_Evil **** **** **** **** **** **** **** **** +5402 Ocular_Adept_Quickened_Protection_from_Evil **** **** **** **** **** **** **** **** +5403 Ocular_Adept_Silent_Protection_from_Evil **** **** **** **** **** **** **** **** +5404 Ocular_Adept_Still_Protection_from_Evil **** **** **** **** **** **** **** **** +5405 Ocular_Adept_Protection_from_Good **** **** **** **** **** **** **** **** +5406 Ocular_Adept_Exteneded_Protection_from_Good **** **** **** **** **** **** **** **** +5407 Ocular_Adept_Quickened_Protection_from_Good **** **** **** **** **** **** **** **** +5408 Ocular_Adept_Silent_Protection_from_Good **** **** **** **** **** **** **** **** +5409 Ocular_Adept_Still_Protection_from_Good **** **** **** **** **** **** **** **** +5410 Ocular_Adept_Protection_from_Law **** **** **** **** **** **** **** **** +5411 Ocular_Adept_Exteneded_Protection_from_Law **** **** **** **** **** **** **** **** +5412 Ocular_Adept_Quickened_Protection_from_Law **** **** **** **** **** **** **** **** +5413 Ocular_Adept_Silent_Protection_from_Law **** **** **** **** **** **** **** **** +5414 Ocular_Adept_Still_Protection_from_Law **** **** **** **** **** **** **** **** +5415 Ocular_Adept_RAY_OF_HOPE **** **** **** **** **** **** **** **** +5416 Ocular_Adept_Exteneded_RAY_OF_HOPE **** **** **** **** **** **** **** **** +5417 Ocular_Adept_Quickened_RAY_OF_HOPE **** **** **** **** **** **** **** **** +5418 Ocular_Adept_Silent_RAY_OF_HOPE **** **** **** **** **** **** **** **** +5419 Ocular_Adept_Still_RAY_OF_HOPE **** **** **** **** **** **** **** **** +5420 Ocular_Adept_Remove_Fear **** **** **** **** **** **** **** **** +5421 Ocular_Adept_Exteneded_Remove_Fear **** **** **** **** **** **** **** **** +5422 Ocular_Adept_Quickened_Remove_Fear **** **** **** **** **** **** **** **** +5423 Ocular_Adept_Silent_Remove_Fear **** **** **** **** **** **** **** **** +5424 Ocular_Adept_Still_Remove_Fear **** **** **** **** **** **** **** **** +5425 Ocular_Adept_Sanctuary **** **** **** **** **** **** **** **** +5426 Ocular_Adept_Exteneded_Sanctuary **** **** **** **** **** **** **** **** +5427 Ocular_Adept_Quickened_Sanctuary **** **** **** **** **** **** **** **** +5428 Ocular_Adept_Silent_Sanctuary **** **** **** **** **** **** **** **** +5429 Ocular_Adept_Still_Sanctuary **** **** **** **** **** **** **** **** +5430 Ocular_Adept_SEETHING_EYEBANE **** **** **** **** **** **** **** **** +5431 Ocular_Adept_Quickened_SEETHING_EYEBANE **** **** **** **** **** **** **** **** +5432 Ocular_Adept_Silent_SEETHING_EYEBANE **** **** **** **** **** **** **** **** +5433 Ocular_Adept_Still_SEETHING_EYEBANE **** **** **** **** **** **** **** **** +5434 Ocular_Adept_Shield_of_Faith **** **** **** **** **** **** **** **** +5435 Ocular_Adept_Exteneded_Shield_of_Faith **** **** **** **** **** **** **** **** +5436 Ocular_Adept_Quickened_Shield_of_Faith **** **** **** **** **** **** **** **** +5437 Ocular_Adept_Silent_Shield_of_Faith **** **** **** **** **** **** **** **** +5438 Ocular_Adept_Still_Shield_of_Faith **** **** **** **** **** **** **** **** +5439 Ocular_Adept_SORROW **** **** **** **** **** **** **** **** +5440 Ocular_Adept_Quickened_SORROW **** **** **** **** **** **** **** **** +5441 Ocular_Adept_Silent_SORROW **** **** **** **** **** **** **** **** +5442 Ocular_Adept_Still_SORROW **** **** **** **** **** **** **** **** +5443 Ocular_Adept_Summon_Creature_I **** **** **** **** **** **** **** **** +5444 Ocular_Adept_Exteneded_Summon_Creature_I **** **** **** **** **** **** **** **** +5445 Ocular_Adept_Quickened_Summon_Creature_I **** **** **** **** **** **** **** **** +5446 Ocular_Adept_Silent_Summon_Creature_I **** **** **** **** **** **** **** **** +5447 Ocular_Adept_Still_Summon_Creature_I **** **** **** **** **** **** **** **** +5448 Ocular_Adept_SummonUndeadI **** **** **** **** **** **** **** **** +5449 Ocular_Adept_Exteneded_SummonUndeadI **** **** **** **** **** **** **** **** +5450 Ocular_Adept_Quickened_SummonUndeadI **** **** **** **** **** **** **** **** +5451 Ocular_Adept_Silent_SummonUndeadI **** **** **** **** **** **** **** **** +5452 Ocular_Adept_Still_SummonUndeadI **** **** **** **** **** **** **** **** +5453 Ocular_Adept_TONGUE_OF_BAALZEBUL **** **** **** **** **** **** **** **** +5454 Ocular_Adept_Exteneded_TONGUE_OF_BAALZEBUL **** **** **** **** **** **** **** **** +5455 Ocular_Adept_Quickened_TONGUE_OF_BAALZEBUL **** **** **** **** **** **** **** **** +5456 Ocular_Adept_Silent_TONGUE_OF_BAALZEBUL **** **** **** **** **** **** **** **** +5457 Ocular_Adept_Still_TONGUE_OF_BAALZEBUL **** **** **** **** **** **** **** **** +5458 Ocular_Adept_VisionOfHeaven **** **** **** **** **** **** **** **** +5459 Ocular_Adept_Exteneded_VisionOfHeaven **** **** **** **** **** **** **** **** +5460 Ocular_Adept_Quickened_VisionOfHeaven **** **** **** **** **** **** **** **** +5461 Ocular_Adept_Silent_VisionOfHeaven **** **** **** **** **** **** **** **** +5462 Ocular_Adept_ADDICTION **** **** **** **** **** **** **** **** +5463 Ocular_Adept_ADDICTION_TERRAN_BRANDY **** **** **** **** **** **** **** **** +5464 Ocular_Adept_ADDICTION_MUSHROOM_POWDER **** **** **** **** **** **** **** **** +5465 Ocular_Adept_ADDICTION_VODARE **** **** **** **** **** **** **** **** +5466 Ocular_Adept_ADDICTION_AGONY **** **** **** **** **** **** **** **** +5467 Ocular_Adept_Silent_ADDICTION **** **** **** **** **** **** **** **** +5468 Ocular_Adept_Silent_ADDICTION_TERRAN_BRANDY **** **** **** **** **** **** **** **** +5469 Ocular_Adept_Silent_ADDICTION_MUSHROOM_POWDER **** **** **** **** **** **** **** **** +5470 Ocular_Adept_Silent_ADDICTION_VODARE **** **** **** **** **** **** **** **** +5471 Ocular_Adept_Silent_ADDICTION_AGONY **** **** **** **** **** **** **** **** +5472 Ocular_Adept_Still_ADDICTION **** **** **** **** **** **** **** **** +5473 Ocular_Adept_Still_ADDICTION_TERRAN_BRANDY **** **** **** **** **** **** **** **** +5474 Ocular_Adept_Still_ADDICTION_MUSHROOM_POWDER **** **** **** **** **** **** **** **** +5475 Ocular_Adept_Still_ADDICTION_VODARE **** **** **** **** **** **** **** **** +5476 Ocular_Adept_Still_ADDICTION_AGONY **** **** **** **** **** **** **** **** +5477 Ocular_Adept_Aid **** **** **** **** **** **** **** **** +5478 Ocular_Adept_Empowered_Aid **** **** **** **** **** **** **** **** +5479 Ocular_Adept_Exteneded_Aid **** **** **** **** **** **** **** **** +5480 Ocular_Adept_Maximized_Aid **** **** **** **** **** **** **** **** +5481 Ocular_Adept_Silent_Aid **** **** **** **** **** **** **** **** +5482 Ocular_Adept_Still_Aid **** **** **** **** **** **** **** **** +5483 Ocular_Adept_Animalistic_Power **** **** **** **** **** **** **** **** +5484 Ocular_Adept_Exteneded_Animalistic_Power **** **** **** **** **** **** **** **** +5485 Ocular_Adept_BONEBLAST **** **** **** **** **** **** **** **** +5486 Ocular_Adept_Silent_BONEBLAST **** **** **** **** **** **** **** **** +5487 Ocular_Adept_Still_BONEBLAST **** **** **** **** **** **** **** **** +5488 Ocular_Adept_Bulls_Strength **** **** **** **** **** **** **** **** +5489 Ocular_Adept_Empowered_Bulls_Strength **** **** **** **** **** **** **** **** +5490 Ocular_Adept_Exteneded_Bulls_Strength **** **** **** **** **** **** **** **** +5491 Ocular_Adept_Maximized_Bulls_Strength **** **** **** **** **** **** **** **** +5492 Ocular_Adept_Silent_Bulls_Strength **** **** **** **** **** **** **** **** +5493 Ocular_Adept_Still_Bulls_Strength **** **** **** **** **** **** **** **** +5494 Ocular_Adept_Calm_Emotions **** **** **** **** **** **** **** **** +5495 Ocular_Adept_Exteneded_Calm_Emotions **** **** **** **** **** **** **** **** +5496 Ocular_Adept_Silent_Calm_Emotions **** **** **** **** **** **** **** **** +5497 Ocular_Adept_Still_Calm_Emotions **** **** **** **** **** **** **** **** +5498 Ocular_Adept_Consecrated_Aura **** **** **** **** **** **** **** **** +5499 Ocular_Adept_Exteneded_Consecrated_Aura **** **** **** **** **** **** **** **** +5500 Ocular_Adept_Silent_Consecrated_Aura **** **** **** **** **** **** **** **** +5501 Ocular_Adept_Still_Consecrated_Aura **** **** **** **** **** **** **** **** +5502 Ocular_Adept_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +5503 Ocular_Adept_Empowered_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +5504 Ocular_Adept_Maximized_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +5505 Ocular_Adept_Silent_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +5506 Ocular_Adept_Still_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +5507 Ocular_Adept_Darkness **** **** **** **** **** **** **** **** +5508 Ocular_Adept_Exteneded_Darkness **** **** **** **** **** **** **** **** +5509 Ocular_Adept_Silent_Darkness **** **** **** **** **** **** **** **** +5510 Ocular_Adept_Death_Knell **** **** **** **** **** **** **** **** +5511 Ocular_Adept_Empowered_Death_Knell **** **** **** **** **** **** **** **** +5512 Ocular_Adept_Exteneded_Death_Knell **** **** **** **** **** **** **** **** +5513 Ocular_Adept_Maximized_Death_Knell **** **** **** **** **** **** **** **** +5514 Ocular_Adept_Silent_Death_Knell **** **** **** **** **** **** **** **** +5515 Ocular_Adept_Still_Death_Knell **** **** **** **** **** **** **** **** +5516 Ocular_Adept_Divine_Protection **** **** **** **** **** **** **** **** +5517 Ocular_Adept_Exteneded_Divine_Protection **** **** **** **** **** **** **** **** +5518 Ocular_Adept_Silent_Divine_Protection **** **** **** **** **** **** **** **** +5519 Ocular_Adept_Still_Divine_Protection **** **** **** **** **** **** **** **** +5520 Ocular_Adept_Eagle_Splendor **** **** **** **** **** **** **** **** +5521 Ocular_Adept_Empowered_Eagle_Splendor **** **** **** **** **** **** **** **** +5522 Ocular_Adept_Exteneded_Eagle_Splendor **** **** **** **** **** **** **** **** +5523 Ocular_Adept_Maximized_Eagle_Splendor **** **** **** **** **** **** **** **** +5524 Ocular_Adept_Silent_Eagle_Splendor **** **** **** **** **** **** **** **** +5525 Ocular_Adept_Still_Eagle_Splendor **** **** **** **** **** **** **** **** +5526 Ocular_Adept_ELATION **** **** **** **** **** **** **** **** +5527 Ocular_Adept_Exteneded_ELATION **** **** **** **** **** **** **** **** +5528 Ocular_Adept_Silent_ELATION **** **** **** **** **** **** **** **** +5529 Ocular_Adept_Still_ELATION **** **** **** **** **** **** **** **** +5530 Ocular_Adept_Endurance **** **** **** **** **** **** **** **** +5531 Ocular_Adept_Empowered_Endurance **** **** **** **** **** **** **** **** +5532 Ocular_Adept_Exteneded_Endurance **** **** **** **** **** **** **** **** +5533 Ocular_Adept_Maximized_Endurance **** **** **** **** **** **** **** **** +5534 Ocular_Adept_Silent_Endurance **** **** **** **** **** **** **** **** +5535 Ocular_Adept_Still_Endurance **** **** **** **** **** **** **** **** +5536 Ocular_Adept_Find_Traps **** **** **** **** **** **** **** **** +5537 Ocular_Adept_Exteneded_Find_Traps **** **** **** **** **** **** **** **** +5538 Ocular_Adept_Silent_Find_Traps **** **** **** **** **** **** **** **** +5539 Ocular_Adept_Still_Find_Traps **** **** **** **** **** **** **** **** +5540 Ocular_Adept_Foxs_Cunning **** **** **** **** **** **** **** **** +5541 Ocular_Adept_Empowered_Foxs_Cunning **** **** **** **** **** **** **** **** +5542 Ocular_Adept_Exteneded_Foxs_Cunning **** **** **** **** **** **** **** **** +5543 Ocular_Adept_Maximized_Foxs_Cunning **** **** **** **** **** **** **** **** +5544 Ocular_Adept_Silent_Foxs_Cunning **** **** **** **** **** **** **** **** +5545 Ocular_Adept_Still_Foxs_Cunning **** **** **** **** **** **** **** **** +5546 Ocular_Adept_Hold_Person **** **** **** **** **** **** **** **** +5547 Ocular_Adept_Exteneded_Hold_Person **** **** **** **** **** **** **** **** +5548 Ocular_Adept_Silent_Hold_Person **** **** **** **** **** **** **** **** +5549 Ocular_Adept_Still_Hold_Person **** **** **** **** **** **** **** **** +5550 Ocular_Adept_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +5551 Ocular_Adept_Empowered_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +5552 Ocular_Adept_Maximized_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +5553 Ocular_Adept_Silent_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +5554 Ocular_Adept_Still_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +5555 Ocular_Adept_LAHMS_FINGER_DARTS **** **** **** **** **** **** **** **** +5556 Ocular_Adept_Silent_LAHMS_FINGER_DARTS **** **** **** **** **** **** **** **** +5557 Ocular_Adept_Still_LAHMS_FINGER_DARTS **** **** **** **** **** **** **** **** +5558 Ocular_Adept_Lesser_Dispel **** **** **** **** **** **** **** **** +5559 Ocular_Adept_Silent_Lesser_Dispel **** **** **** **** **** **** **** **** +5560 Ocular_Adept_Still_Lesser_Dispel **** **** **** **** **** **** **** **** +5561 Ocular_Adept_Lesser_Restoration **** **** **** **** **** **** **** **** +5562 Ocular_Adept_Silent_Lesser_Restoration **** **** **** **** **** **** **** **** +5563 Ocular_Adept_Still_Lesser_Restoration **** **** **** **** **** **** **** **** +5564 Ocular_Adept_Living_Undeath **** **** **** **** **** **** **** **** +5565 Ocular_Adept_Exteneded_Living_Undeath **** **** **** **** **** **** **** **** +5566 Ocular_Adept_Silent_Living_Undeath **** **** **** **** **** **** **** **** +5567 Ocular_Adept_Still_Living_Undeath **** **** **** **** **** **** **** **** +5568 Ocular_Adept_Necrotic_Cyst **** **** **** **** **** **** **** **** +5569 Ocular_Adept_Silent_Necrotic_Cyst **** **** **** **** **** **** **** **** +5570 Ocular_Adept_Still_Necrotic_Cyst **** **** **** **** **** **** **** **** +5571 Ocular_Adept_Negative_Energy_Ray **** **** **** **** **** **** **** **** +5572 Ocular_Adept_Empowered_Negative_Energy_Ray **** **** **** **** **** **** **** **** +5573 Ocular_Adept_Maximized_Negative_Energy_Ray **** **** **** **** **** **** **** **** +5574 Ocular_Adept_Silent_Negative_Energy_Ray **** **** **** **** **** **** **** **** +5575 Ocular_Adept_Still_Negative_Energy_Ray **** **** **** **** **** **** **** **** +5576 Ocular_Adept_Owls_Wisdom **** **** **** **** **** **** **** **** +5577 Ocular_Adept_Empowered_Owls_Wisdom **** **** **** **** **** **** **** **** +5578 Ocular_Adept_Exteneded_Owls_Wisdom **** **** **** **** **** **** **** **** +5579 Ocular_Adept_Maximized_Owls_Wisdom **** **** **** **** **** **** **** **** +5580 Ocular_Adept_Silent_Owls_Wisdom **** **** **** **** **** **** **** **** +5581 Ocular_Adept_Still_Owls_Wisdom **** **** **** **** **** **** **** **** +5582 Ocular_Adept_Remove_Paralysis **** **** **** **** **** **** **** **** +5583 Ocular_Adept_Silent_Remove_Paralysis **** **** **** **** **** **** **** **** +5584 Ocular_Adept_Still_Remove_Paralysis **** **** **** **** **** **** **** **** +5585 Ocular_Adept_Resist_Elements **** **** **** **** **** **** **** **** +5586 Ocular_Adept_Exteneded_Resist_Elements **** **** **** **** **** **** **** **** +5587 Ocular_Adept_Silent_Resist_Elements **** **** **** **** **** **** **** **** +5588 Ocular_Adept_Still_Resist_Elements **** **** **** **** **** **** **** **** +5589 Ocular_Adept_ShieldOther **** **** **** **** **** **** **** **** +5590 Ocular_Adept_Exteneded_ShieldOther **** **** **** **** **** **** **** **** +5591 Ocular_Adept_Silent_ShieldOther **** **** **** **** **** **** **** **** +5592 Ocular_Adept_Still_ShieldOther **** **** **** **** **** **** **** **** +5593 Ocular_Adept_Silence **** **** **** **** **** **** **** **** +5594 Ocular_Adept_Exteneded_Silence **** **** **** **** **** **** **** **** +5595 Ocular_Adept_Silent_Silence **** **** **** **** **** **** **** **** +5596 Ocular_Adept_Still_Silence **** **** **** **** **** **** **** **** +5597 Ocular_Adept_Sound_Burst **** **** **** **** **** **** **** **** +5598 Ocular_Adept_Maximized_Sound_Burst **** **** **** **** **** **** **** **** +5599 Ocular_Adept_Silent_Sound_Burst **** **** **** **** **** **** **** **** +5600 Ocular_Adept_Still_Sound_Burst **** **** **** **** **** **** **** **** +5601 Ocular_Adept_SPORES_OF_THE_VROCK **** **** **** **** **** **** **** **** +5602 Ocular_Adept_Empowered_SPORES_OF_THE_VROCK **** **** **** **** **** **** **** **** +5603 Ocular_Adept_Maximized_SPORES_OF_THE_VROCK **** **** **** **** **** **** **** **** +5604 Ocular_Adept_Silent_SPORES_OF_THE_VROCK **** **** **** **** **** **** **** **** +5605 Ocular_Adept_Still_SPORES_OF_THE_VROCK **** **** **** **** **** **** **** **** +5606 Ocular_Adept_Stone_Bones **** **** **** **** **** **** **** **** +5607 Ocular_Adept_Exteneded_Stone_Bones **** **** **** **** **** **** **** **** +5608 Ocular_Adept_Silent_Stone_Bones **** **** **** **** **** **** **** **** +5609 Ocular_Adept_Still_Stone_Bones **** **** **** **** **** **** **** **** +5610 Ocular_Adept_Summon_Creature_II **** **** **** **** **** **** **** **** +5611 Ocular_Adept_Exteneded_Summon_Creature_II **** **** **** **** **** **** **** **** +5612 Ocular_Adept_Silent_Summon_Creature_II **** **** **** **** **** **** **** **** +5613 Ocular_Adept_Still_Summon_Creature_II **** **** **** **** **** **** **** **** +5614 Ocular_Adept_SummonUndeadII **** **** **** **** **** **** **** **** +5615 Ocular_Adept_Exteneded_SummonUndeadII **** **** **** **** **** **** **** **** +5616 Ocular_Adept_Silent_SummonUndeadII **** **** **** **** **** **** **** **** +5617 Ocular_Adept_Still_SummonUndeadII **** **** **** **** **** **** **** **** +5618 Ocular_Adept_Ultravision **** **** **** **** **** **** **** **** +5619 Ocular_Adept_Exteneded_Ultravision **** **** **** **** **** **** **** **** +5620 Ocular_Adept_Silent_Ultravision **** **** **** **** **** **** **** **** +5621 Ocular_Adept_Still_Ultravision **** **** **** **** **** **** **** **** +5622 Ocular_Adept_UndetectableAlignment **** **** **** **** **** **** **** **** +5623 Ocular_Adept_Exteneded_UndetectableAlignment **** **** **** **** **** **** **** **** +5624 Ocular_Adept_Silent_UndetectableAlignment **** **** **** **** **** **** **** **** +5625 Ocular_Adept_Still_UndetectableAlignment **** **** **** **** **** **** **** **** +5626 Ocular_Adept_WAVE_OF_GRIEF **** **** **** **** **** **** **** **** +5627 Ocular_Adept_Exteneded_WAVE_OF_GRIEF **** **** **** **** **** **** **** **** +5628 Ocular_Adept_Still_WAVE_OF_GRIEF **** **** **** **** **** **** **** **** +5629 Ocular_Adept_Animate_Dead **** **** **** **** **** **** **** **** +5630 Ocular_Adept_Exteneded_Animate_Dead **** **** **** **** **** **** **** **** +5631 Ocular_Adept_Silent_Animate_Dead **** **** **** **** **** **** **** **** +5632 Ocular_Adept_Still_Animate_Dead **** **** **** **** **** **** **** **** +5633 Ocular_Adept_Bestow_Curse **** **** **** **** **** **** **** **** +5634 Ocular_Adept_Silent_Bestow_Curse **** **** **** **** **** **** **** **** +5635 Ocular_Adept_Still_Bestow_Curse **** **** **** **** **** **** **** **** +5636 Ocular_Adept_Blindness_and_Deafness **** **** **** **** **** **** **** **** +5637 Ocular_Adept_Exteneded_Blindness_and_Deafness **** **** **** **** **** **** **** **** +5638 Ocular_Adept_Silent_Blindness_and_Deafness **** **** **** **** **** **** **** **** +5639 Ocular_Adept_BONEBLADE **** **** **** **** **** **** **** **** +5640 Ocular_Adept_BONEBLADE_GREATSWORD **** **** **** **** **** **** **** **** +5641 Ocular_Adept_BONEBLADE_LONGSWORD **** **** **** **** **** **** **** **** +5642 Ocular_Adept_BONEBLADE_SHORTSWORD **** **** **** **** **** **** **** **** +5643 Ocular_Adept_Exteneded_BONEBLADE **** **** **** **** **** **** **** **** +5644 Ocular_Adept_Exteneded_BONEBLADE_GREATSWORD **** **** **** **** **** **** **** **** +5645 Ocular_Adept_Exteneded_BONEBLADE_LONGSWORD **** **** **** **** **** **** **** **** +5646 Ocular_Adept_Exteneded_BONEBLADE_SHORTSWORD **** **** **** **** **** **** **** **** +5647 Ocular_Adept_Silent_BONEBLADE **** **** **** **** **** **** **** **** +5648 Ocular_Adept_Silent_BONEBLADE_GREATSWORD **** **** **** **** **** **** **** **** +5649 Ocular_Adept_Silent_BONEBLADE_LONGSWORD **** **** **** **** **** **** **** **** +5650 Ocular_Adept_Silent_BONEBLADE_SHORTSWORD **** **** **** **** **** **** **** **** +5651 Ocular_Adept_Still_BONEBLADE **** **** **** **** **** **** **** **** +5652 Ocular_Adept_Still_BONEBLADE_GREATSWORD **** **** **** **** **** **** **** **** +5653 Ocular_Adept_Still_BONEBLADE_LONGSWORD **** **** **** **** **** **** **** **** +5654 Ocular_Adept_Still_BONEBLADE_SHORTSWORD **** **** **** **** **** **** **** **** +5655 Ocular_Adept_Clarity **** **** **** **** **** **** **** **** +5656 Ocular_Adept_Exteneded_Clarity **** **** **** **** **** **** **** **** +5657 Ocular_Adept_Still_Clarity **** **** **** **** **** **** **** **** +5658 Ocular_Adept_Close_Wounds **** **** **** **** **** **** **** **** +5659 Ocular_Adept_Empowered_Close_Wounds **** **** **** **** **** **** **** **** +5660 Ocular_Adept_Silent_Close_Wounds **** **** **** **** **** **** **** **** +5661 Ocular_Adept_CLUTCH_OF_ORCUS **** **** **** **** **** **** **** **** +5662 Ocular_Adept_Silent_CLUTCH_OF_ORCUS **** **** **** **** **** **** **** **** +5663 Ocular_Adept_Still_CLUTCH_OF_ORCUS **** **** **** **** **** **** **** **** +5664 Ocular_Adept_Contagion **** **** **** **** **** **** **** **** +5665 Ocular_Adept_Silent_Contagion **** **** **** **** **** **** **** **** +5666 Ocular_Adept_Still_Contagion **** **** **** **** **** **** **** **** +5667 Ocular_Adept_Continual_Flame **** **** **** **** **** **** **** **** +5668 Ocular_Adept_Silent_Continual_Flame **** **** **** **** **** **** **** **** +5669 Ocular_Adept_Still_Continual_Flame **** **** **** **** **** **** **** **** +5670 Ocular_Adept_Crown_Might **** **** **** **** **** **** **** **** +5671 Ocular_Adept_Exteneded_Crown_Might **** **** **** **** **** **** **** **** +5672 Ocular_Adept_Silent_Crown_Might **** **** **** **** **** **** **** **** +5673 Ocular_Adept_Still_Crown_Might **** **** **** **** **** **** **** **** +5674 Ocular_Adept_Crown_Protection **** **** **** **** **** **** **** **** +5675 Ocular_Adept_Exteneded_Crown_Protection **** **** **** **** **** **** **** **** +5676 Ocular_Adept_Silent_Crown_Protection **** **** **** **** **** **** **** **** +5677 Ocular_Adept_Still_Crown_Protection **** **** **** **** **** **** **** **** +5678 Ocular_Adept_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +5679 Ocular_Adept_Empowered_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +5680 Ocular_Adept_Silent_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +5681 Ocular_Adept_Still_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +5682 Ocular_Adept_Curse_of_Petty_Failing **** **** **** **** **** **** **** **** +5683 Ocular_Adept_Exteneded_Curse_of_Petty_Failing **** **** **** **** **** **** **** **** +5684 Ocular_Adept_Silent_Curse_of_Petty_Failing **** **** **** **** **** **** **** **** +5685 Ocular_Adept_Still_Curse_of_Petty_Failing **** **** **** **** **** **** **** **** +5686 Ocular_Adept_Darkfire **** **** **** **** **** **** **** **** +5687 Ocular_Adept_Exteneded_Darkfire **** **** **** **** **** **** **** **** +5688 Ocular_Adept_Silent_Darkfire **** **** **** **** **** **** **** **** +5689 Ocular_Adept_Still_Darkfire **** **** **** **** **** **** **** **** +5690 Ocular_Adept_Daylight **** **** **** **** **** **** **** **** +5691 Ocular_Adept_Exteneded_Daylight **** **** **** **** **** **** **** **** +5692 Ocular_Adept_Silent_Daylight **** **** **** **** **** **** **** **** +5693 Ocular_Adept_Still_Daylight **** **** **** **** **** **** **** **** +5694 Ocular_Adept_DeeperDarkness **** **** **** **** **** **** **** **** +5695 Ocular_Adept_Exteneded_DeeperDarkness **** **** **** **** **** **** **** **** +5696 Ocular_Adept_Silent_DeeperDarkness **** **** **** **** **** **** **** **** +5697 Ocular_Adept_DEVILS_EYE **** **** **** **** **** **** **** **** +5698 Ocular_Adept_Silent_DEVILS_EYE **** **** **** **** **** **** **** **** +5699 Ocular_Adept_Still_DEVILS_EYE **** **** **** **** **** **** **** **** +5700 Ocular_Adept_Dispel_Magic **** **** **** **** **** **** **** **** +5701 Ocular_Adept_Silent_Dispel_Magic **** **** **** **** **** **** **** **** +5702 Ocular_Adept_Still_Dispel_Magic **** **** **** **** **** **** **** **** +5703 Ocular_Adept_ENERGIZE_POTION **** **** **** **** **** **** **** **** +5704 Ocular_Adept_ENERGIZE_POTION_ACID **** **** **** **** **** **** **** **** +5705 Ocular_Adept_ENERGIZE_POTION_COLD **** **** **** **** **** **** **** **** +5706 Ocular_Adept_ENERGIZE_POTION_ELECTRICITY **** **** **** **** **** **** **** **** +5707 Ocular_Adept_ENERGIZE_POTION_FIRE **** **** **** **** **** **** **** **** +5708 Ocular_Adept_ENERGIZE_POTION_SONIC **** **** **** **** **** **** **** **** +5709 Ocular_Adept_Silent_ENERGIZE_POTION **** **** **** **** **** **** **** **** +5710 Ocular_Adept_Silent_ENERGIZE_POTION_ACID **** **** **** **** **** **** **** **** +5711 Ocular_Adept_Silent_ENERGIZE_POTION_COLD **** **** **** **** **** **** **** **** +5712 Ocular_Adept_Silent_ENERGIZE_POTION_ELECTRICITY **** **** **** **** **** **** **** **** +5713 Ocular_Adept_Silent_ENERGIZE_POTION_FIRE **** **** **** **** **** **** **** **** +5714 Ocular_Adept_Silent_ENERGIZE_POTION_SONIC **** **** **** **** **** **** **** **** +5715 Ocular_Adept_Still_ENERGIZE_POTION **** **** **** **** **** **** **** **** +5716 Ocular_Adept_Still_ENERGIZE_POTION_ACID **** **** **** **** **** **** **** **** +5717 Ocular_Adept_Still_ENERGIZE_POTION_COLD **** **** **** **** **** **** **** **** +5718 Ocular_Adept_Still_ENERGIZE_POTION_ELECTRICITY **** **** **** **** **** **** **** **** +5719 Ocular_Adept_Still_ENERGIZE_POTION_FIRE **** **** **** **** **** **** **** **** +5720 Ocular_Adept_Still_ENERGIZE_POTION_SONIC **** **** **** **** **** **** **** **** +5721 Ocular_Adept_Energy_Aegis **** **** **** **** **** **** **** **** +5722 Ocular_Adept_Energy_Aegis_Acid **** **** **** **** **** **** **** **** +5723 Ocular_Adept_Energy_Aegis_Cold **** **** **** **** **** **** **** **** +5724 Ocular_Adept_Energy_Aegis_Elec **** **** **** **** **** **** **** **** +5725 Ocular_Adept_Energy_Aegis_Fire **** **** **** **** **** **** **** **** +5726 Ocular_Adept_Energy_Aegis_Sonic **** **** **** **** **** **** **** **** +5727 Ocular_Adept_Exteneded_Energy_Aegis **** **** **** **** **** **** **** **** +5728 Ocular_Adept_Exteneded_Energy_Aegis_Acid **** **** **** **** **** **** **** **** +5729 Ocular_Adept_Exteneded_Energy_Aegis_Cold **** **** **** **** **** **** **** **** +5730 Ocular_Adept_Exteneded_Energy_Aegis_Elec **** **** **** **** **** **** **** **** +5731 Ocular_Adept_Exteneded_Energy_Aegis_Fire **** **** **** **** **** **** **** **** +5732 Ocular_Adept_Exteneded_Energy_Aegis_Sonic **** **** **** **** **** **** **** **** +5733 Ocular_Adept_Silent_Energy_Aegis **** **** **** **** **** **** **** **** +5734 Ocular_Adept_Silent_Energy_Aegis_Acid **** **** **** **** **** **** **** **** +5735 Ocular_Adept_Silent_Energy_Aegis_Cold **** **** **** **** **** **** **** **** +5736 Ocular_Adept_Silent_Energy_Aegis_Elec **** **** **** **** **** **** **** **** +5737 Ocular_Adept_Silent_Energy_Aegis_Fire **** **** **** **** **** **** **** **** +5738 Ocular_Adept_Silent_Energy_Aegis_Sonic **** **** **** **** **** **** **** **** +5739 Ocular_Adept_Still_Energy_Aegis **** **** **** **** **** **** **** **** +5740 Ocular_Adept_Still_Energy_Aegis_Acid **** **** **** **** **** **** **** **** +5741 Ocular_Adept_Still_Energy_Aegis_Cold **** **** **** **** **** **** **** **** +5742 Ocular_Adept_Still_Energy_Aegis_Elec **** **** **** **** **** **** **** **** +5743 Ocular_Adept_Still_Energy_Aegis_Fire **** **** **** **** **** **** **** **** +5744 Ocular_Adept_Still_Energy_Aegis_Sonic **** **** **** **** **** **** **** **** +5745 Ocular_Adept_FLESH_RIPPER **** **** **** **** **** **** **** **** +5746 Ocular_Adept_Empowered_FLESH_RIPPER **** **** **** **** **** **** **** **** +5747 Ocular_Adept_Silent_FLESH_RIPPER **** **** **** **** **** **** **** **** +5748 Ocular_Adept_Still_FLESH_RIPPER **** **** **** **** **** **** **** **** +5749 Ocular_Adept_Glyph_of_Warding_Master **** **** **** **** **** **** **** **** +5750 Ocular_Adept_Glyph_of_Warding_Acid **** **** **** **** **** **** **** **** +5751 Ocular_Adept_Glyph_of_Warding_Cold **** **** **** **** **** **** **** **** +5752 Ocular_Adept_Glyph_of_Warding_Electricity **** **** **** **** **** **** **** **** +5753 Ocular_Adept_Glyph_of_Warding_Fire **** **** **** **** **** **** **** **** +5754 Ocular_Adept_Glyph_of_Warding_Sonic **** **** **** **** **** **** **** **** +5755 Ocular_Adept_Empowered_Glyph_of_Warding_Master **** **** **** **** **** **** **** **** +5756 Ocular_Adept_Empowered_Glyph_of_Warding_Acid **** **** **** **** **** **** **** **** +5757 Ocular_Adept_Empowered_Glyph_of_Warding_Cold **** **** **** **** **** **** **** **** +5758 Ocular_Adept_Empowered_Glyph_of_Warding_Electricity **** **** **** **** **** **** **** **** +5759 Ocular_Adept_Empowered_Glyph_of_Warding_Fire **** **** **** **** **** **** **** **** +5760 Ocular_Adept_Empowered_Glyph_of_Warding_Sonic **** **** **** **** **** **** **** **** +5761 Ocular_Adept_Exteneded_Glyph_of_Warding_Master **** **** **** **** **** **** **** **** +5762 Ocular_Adept_Exteneded_Glyph_of_Warding_Acid **** **** **** **** **** **** **** **** +5763 Ocular_Adept_Exteneded_Glyph_of_Warding_Cold **** **** **** **** **** **** **** **** +5764 Ocular_Adept_Exteneded_Glyph_of_Warding_Electricity **** **** **** **** **** **** **** **** +5765 Ocular_Adept_Exteneded_Glyph_of_Warding_Fire **** **** **** **** **** **** **** **** +5766 Ocular_Adept_Exteneded_Glyph_of_Warding_Sonic **** **** **** **** **** **** **** **** +5767 Ocular_Adept_Silent_Glyph_of_Warding_Master **** **** **** **** **** **** **** **** +5768 Ocular_Adept_Silent_Glyph_of_Warding_Acid **** **** **** **** **** **** **** **** +5769 Ocular_Adept_Silent_Glyph_of_Warding_Cold **** **** **** **** **** **** **** **** +5770 Ocular_Adept_Silent_Glyph_of_Warding_Electricity **** **** **** **** **** **** **** **** +5771 Ocular_Adept_Silent_Glyph_of_Warding_Fire **** **** **** **** **** **** **** **** +5772 Ocular_Adept_Silent_Glyph_of_Warding_Sonic **** **** **** **** **** **** **** **** +5773 Ocular_Adept_Still_Glyph_of_Warding_Master **** **** **** **** **** **** **** **** +5774 Ocular_Adept_Still_Glyph_of_Warding_Acid **** **** **** **** **** **** **** **** +5775 Ocular_Adept_Still_Glyph_of_Warding_Cold **** **** **** **** **** **** **** **** +5776 Ocular_Adept_Still_Glyph_of_Warding_Electricity **** **** **** **** **** **** **** **** +5777 Ocular_Adept_Still_Glyph_of_Warding_Fire **** **** **** **** **** **** **** **** +5778 Ocular_Adept_Still_Glyph_of_Warding_Sonic **** **** **** **** **** **** **** **** +5779 Ocular_Adept_Inflict_Serious_Wounds **** **** **** **** **** **** **** **** +5780 Ocular_Adept_Empowered_Inflict_Serious_Wounds **** **** **** **** **** **** **** **** +5781 Ocular_Adept_Silent_Inflict_Serious_Wounds **** **** **** **** **** **** **** **** +5782 Ocular_Adept_Still_Inflict_Serious_Wounds **** **** **** **** **** **** **** **** +5783 Ocular_Adept_Invisibility_Purge **** **** **** **** **** **** **** **** +5784 Ocular_Adept_Exteneded_Invisibility_Purge **** **** **** **** **** **** **** **** +5785 Ocular_Adept_Silent_Invisibility_Purge **** **** **** **** **** **** **** **** +5786 Ocular_Adept_Still_Invisibility_Purge **** **** **** **** **** **** **** **** +5787 Ocular_Adept_Legions_Conviction **** **** **** **** **** **** **** **** +5788 Ocular_Adept_Exteneded_Legions_Conviction **** **** **** **** **** **** **** **** +5789 Ocular_Adept_Silent_Legions_Conviction **** **** **** **** **** **** **** **** +5790 Ocular_Adept_Still_Legions_Conviction **** **** **** **** **** **** **** **** +5791 Ocular_Adept_LocateObject **** **** **** **** **** **** **** **** +5792 Ocular_Adept_Exteneded_LocateObject **** **** **** **** **** **** **** **** +5793 Ocular_Adept_Silent_LocateObject **** **** **** **** **** **** **** **** +5794 Ocular_Adept_Still_LocateObject **** **** **** **** **** **** **** **** +5795 Ocular_Adept_Magic_Circle_against_Chaos **** **** **** **** **** **** **** **** +5796 Ocular_Adept_Exteneded_Magic_Circle_against_Chaos **** **** **** **** **** **** **** **** +5797 Ocular_Adept_Silent_Magic_Circle_against_Chaos **** **** **** **** **** **** **** **** +5798 Ocular_Adept_Still_Magic_Circle_against_Chaos **** **** **** **** **** **** **** **** +5799 Ocular_Adept_Magic_Circle_against_Evil **** **** **** **** **** **** **** **** +5800 Ocular_Adept_Exteneded_Magic_Circle_against_Evil **** **** **** **** **** **** **** **** +5801 Ocular_Adept_Silent_Magic_Circle_against_Evil **** **** **** **** **** **** **** **** +5802 Ocular_Adept_Still_Magic_Circle_against_Evil **** **** **** **** **** **** **** **** +5803 Ocular_Adept_Magic_Circle_against_Good **** **** **** **** **** **** **** **** +5804 Ocular_Adept_Exteneded_Magic_Circle_against_Good **** **** **** **** **** **** **** **** +5805 Ocular_Adept_Silent_Magic_Circle_against_Good **** **** **** **** **** **** **** **** +5806 Ocular_Adept_Still_Magic_Circle_against_Good **** **** **** **** **** **** **** **** +5807 Ocular_Adept_Magic_Circle_against_Law **** **** **** **** **** **** **** **** +5808 Ocular_Adept_Exteneded_Magic_Circle_against_Law **** **** **** **** **** **** **** **** +5809 Ocular_Adept_Silent_Magic_Circle_against_Law **** **** **** **** **** **** **** **** +5810 Ocular_Adept_Still_Magic_Circle_against_Law **** **** **** **** **** **** **** **** +5811 Ocular_Adept_Magic_Vestment **** **** **** **** **** **** **** **** +5812 Ocular_Adept_Exteneded_Magic_Vestment **** **** **** **** **** **** **** **** +5813 Ocular_Adept_Silent_Magic_Vestment **** **** **** **** **** **** **** **** +5814 Ocular_Adept_Still_Magic_Vestment **** **** **** **** **** **** **** **** +5815 Ocular_Adept_MASOCHISM **** **** **** **** **** **** **** **** +5816 Ocular_Adept_Exteneded_MASOCHISM **** **** **** **** **** **** **** **** +5817 Ocular_Adept_Mass_Aid **** **** **** **** **** **** **** **** +5818 Ocular_Adept_Empowered_Mass_Aid **** **** **** **** **** **** **** **** +5819 Ocular_Adept_Exteneded_Mass_Aid **** **** **** **** **** **** **** **** +5820 Ocular_Adept_Silent_Mass_Aid **** **** **** **** **** **** **** **** +5821 Ocular_Adept_Still_Mass_Aid **** **** **** **** **** **** **** **** +5822 Ocular_Adept_Mass_Lesser_Vigor **** **** **** **** **** **** **** **** +5823 Ocular_Adept_Exteneded_Mass_Lesser_Vigor **** **** **** **** **** **** **** **** +5824 Ocular_Adept_Silent_Mass_Lesser_Vigor **** **** **** **** **** **** **** **** +5825 Ocular_Adept_Still_Mass_Lesser_Vigor **** **** **** **** **** **** **** **** +5826 Ocular_Adept_Necrotic_Bloat **** **** **** **** **** **** **** **** +5827 Ocular_Adept_Empowered_Necrotic_Bloat **** **** **** **** **** **** **** **** +5828 Ocular_Adept_Negative_Energy_Protection **** **** **** **** **** **** **** **** +5829 Ocular_Adept_Exteneded_Negative_Energy_Protection **** **** **** **** **** **** **** **** +5830 Ocular_Adept_Silent_Negative_Energy_Protection **** **** **** **** **** **** **** **** +5831 Ocular_Adept_Still_Negative_Energy_Protection **** **** **** **** **** **** **** **** +5832 Ocular_Adept_ObscureObject **** **** **** **** **** **** **** **** +5833 Ocular_Adept_Exteneded_ObscureObject **** **** **** **** **** **** **** **** +5834 Ocular_Adept_Silent_ObscureObject **** **** **** **** **** **** **** **** +5835 Ocular_Adept_Still_ObscureObject **** **** **** **** **** **** **** **** +5836 Ocular_Adept_Prayer **** **** **** **** **** **** **** **** +5837 Ocular_Adept_Exteneded_Prayer **** **** **** **** **** **** **** **** +5838 Ocular_Adept_Silent_Prayer **** **** **** **** **** **** **** **** +5839 Ocular_Adept_Still_Prayer **** **** **** **** **** **** **** **** +5840 Ocular_Adept_Protection_from_Elements **** **** **** **** **** **** **** **** +5841 Ocular_Adept_Exteneded_Protection_from_Elements **** **** **** **** **** **** **** **** +5842 Ocular_Adept_Silent_Protection_from_Elements **** **** **** **** **** **** **** **** +5843 Ocular_Adept_Still_Protection_from_Elements **** **** **** **** **** **** **** **** +5844 Ocular_Adept_RED_FESTER **** **** **** **** **** **** **** **** +5845 Ocular_Adept_Silent_RED_FESTER **** **** **** **** **** **** **** **** +5846 Ocular_Adept_Still_RED_FESTER **** **** **** **** **** **** **** **** +5847 Ocular_Adept_Remove_Blindness_and_Deafness **** **** **** **** **** **** **** **** +5848 Ocular_Adept_Silent_Remove_Blindness_and_Deafness **** **** **** **** **** **** **** **** +5849 Ocular_Adept_Still_Remove_Blindness_and_Deafness **** **** **** **** **** **** **** **** +5850 Ocular_Adept_Remove_Curse **** **** **** **** **** **** **** **** +5851 Ocular_Adept_Silent_Remove_Curse **** **** **** **** **** **** **** **** +5852 Ocular_Adept_Still_Remove_Curse **** **** **** **** **** **** **** **** +5853 Ocular_Adept_Remove_Disease **** **** **** **** **** **** **** **** +5854 Ocular_Adept_Silent_Remove_Disease **** **** **** **** **** **** **** **** +5855 Ocular_Adept_Still_Remove_Disease **** **** **** **** **** **** **** **** +5856 Ocular_Adept_RingOfBlades **** **** **** **** **** **** **** **** +5857 Ocular_Adept_Exteneded_RingOfBlades **** **** **** **** **** **** **** **** +5858 Ocular_Adept_Silent_RingOfBlades **** **** **** **** **** **** **** **** +5859 Ocular_Adept_Still_RingOfBlades **** **** **** **** **** **** **** **** +5860 Ocular_Adept_ROTTING_CURSE_OF_URFESTRA **** **** **** **** **** **** **** **** +5861 Ocular_Adept_Empowered_ROTTING_CURSE_OF_URFESTRA **** **** **** **** **** **** **** **** +5862 Ocular_Adept_Silent_ROTTING_CURSE_OF_URFESTRA **** **** **** **** **** **** **** **** +5863 Ocular_Adept_Still_ROTTING_CURSE_OF_URFESTRA **** **** **** **** **** **** **** **** +5864 Ocular_Adept_Searing_Light **** **** **** **** **** **** **** **** +5865 Ocular_Adept_Empowered_Searing_Light **** **** **** **** **** **** **** **** +5866 Ocular_Adept_Silent_Searing_Light **** **** **** **** **** **** **** **** +5867 Ocular_Adept_Still_Searing_Light **** **** **** **** **** **** **** **** +5868 Ocular_Adept_SHIVERING_TOUCH **** **** **** **** **** **** **** **** +5869 Ocular_Adept_Empowered_SHIVERING_TOUCH **** **** **** **** **** **** **** **** +5870 Ocular_Adept_Exteneded_SHIVERING_TOUCH **** **** **** **** **** **** **** **** +5871 Ocular_Adept_Silent_SHIVERING_TOUCH **** **** **** **** **** **** **** **** +5872 Ocular_Adept_Still_SHIVERING_TOUCH **** **** **** **** **** **** **** **** +5873 Ocular_Adept_SHRIVELING **** **** **** **** **** **** **** **** +5874 Ocular_Adept_Empowered_SHRIVELING **** **** **** **** **** **** **** **** +5875 Ocular_Adept_Silent_SHRIVELING **** **** **** **** **** **** **** **** +5876 Ocular_Adept_Still_SHRIVELING **** **** **** **** **** **** **** **** +5877 Ocular_Adept_Slashing_Darkness **** **** **** **** **** **** **** **** +5878 Ocular_Adept_Empowered_Slashing_Darkness **** **** **** **** **** **** **** **** +5879 Ocular_Adept_Silent_Slashing_Darkness **** **** **** **** **** **** **** **** +5880 Ocular_Adept_Still_Slashing_Darkness **** **** **** **** **** **** **** **** +5881 Ocular_Adept_Summon_Creature_III **** **** **** **** **** **** **** **** +5882 Ocular_Adept_Exteneded_Summon_Creature_III **** **** **** **** **** **** **** **** +5883 Ocular_Adept_Silent_Summon_Creature_III **** **** **** **** **** **** **** **** +5884 Ocular_Adept_Still_Summon_Creature_III **** **** **** **** **** **** **** **** +5885 Ocular_Adept_SummonUndeadIII **** **** **** **** **** **** **** **** +5886 Ocular_Adept_Exteneded_SummonUndeadIII **** **** **** **** **** **** **** **** +5887 Ocular_Adept_Silent_SummonUndeadIII **** **** **** **** **** **** **** **** +5888 Ocular_Adept_Still_SummonUndeadIII **** **** **** **** **** **** **** **** +5889 Ocular_Adept_TOUCH_OF_JUIBLEX **** **** **** **** **** **** **** **** +5890 Ocular_Adept_Silent_TOUCH_OF_JUIBLEX **** **** **** **** **** **** **** **** +5891 Ocular_Adept_Still_TOUCH_OF_JUIBLEX **** **** **** **** **** **** **** **** +5892 Ocular_Adept_UNLIVING_WEAPON **** **** **** **** **** **** **** **** +5893 Ocular_Adept_Empowered_UNLIVING_WEAPON **** **** **** **** **** **** **** **** +5894 Ocular_Adept_Silent_UNLIVING_WEAPON **** **** **** **** **** **** **** **** +5895 Ocular_Adept_Still_UNLIVING_WEAPON **** **** **** **** **** **** **** **** +5896 Ocular_Adept_Vigor **** **** **** **** **** **** **** **** +5897 Ocular_Adept_Exteneded_Vigor **** **** **** **** **** **** **** **** +5898 Ocular_Adept_Silent_Vigor **** **** **** **** **** **** **** **** +5899 Ocular_Adept_Still_Vigor **** **** **** **** **** **** **** **** +5900 Ocular_Adept_WaterBreathing **** **** **** **** **** **** **** **** +5901 Ocular_Adept_Exteneded_WaterBreathing **** **** **** **** **** **** **** **** +5902 Ocular_Adept_Silent_WaterBreathing **** **** **** **** **** **** **** **** +5903 Ocular_Adept_Still_WaterBreathing **** **** **** **** **** **** **** **** +5904 Ocular_Adept_WRACK **** **** **** **** **** **** **** **** +5905 Ocular_Adept_Exteneded_WRACK **** **** **** **** **** **** **** **** +5906 Ocular_Adept_Silent_WRACK **** **** **** **** **** **** **** **** +5907 Ocular_Adept_Still_WRACK **** **** **** **** **** **** **** **** +5908 Ocular_Adept_ABSORB_STRENGTH **** **** **** **** **** **** **** **** +5909 Ocular_Adept_Exteneded_ABSORB_STRENGTH **** **** **** **** **** **** **** **** +5910 Ocular_Adept_Silent_ABSORB_STRENGTH **** **** **** **** **** **** **** **** +5911 Ocular_Adept_Still_ABSORB_STRENGTH **** **** **** **** **** **** **** **** +5912 Ocular_Adept_ABYSSAL_MIGHT **** **** **** **** **** **** **** **** +5913 Ocular_Adept_Exteneded_ABYSSAL_MIGHT **** **** **** **** **** **** **** **** +5914 Ocular_Adept_Silent_ABYSSAL_MIGHT **** **** **** **** **** **** **** **** +5915 Ocular_Adept_Still_ABYSSAL_MIGHT **** **** **** **** **** **** **** **** +5916 Ocular_Adept_BloodOfTheMartyr **** **** **** **** **** **** **** **** +5917 Ocular_Adept_Silent_BloodOfTheMartyr **** **** **** **** **** **** **** **** +5918 Ocular_Adept_Still_BloodOfTheMartyr **** **** **** **** **** **** **** **** +5919 Ocular_Adept_CLAWS_OF_THE_SAVAGE **** **** **** **** **** **** **** **** +5920 Ocular_Adept_Exteneded_CLAWS_OF_THE_SAVAGE **** **** **** **** **** **** **** **** +5921 Ocular_Adept_Silent_CLAWS_OF_THE_SAVAGE **** **** **** **** **** **** **** **** +5922 Ocular_Adept_Still_CLAWS_OF_THE_SAVAGE **** **** **** **** **** **** **** **** +5923 Ocular_Adept_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +5924 Ocular_Adept_Silent_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +5925 Ocular_Adept_Still_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +5926 Ocular_Adept_DAMNING_DARKNESS **** **** **** **** **** **** **** **** +5927 Ocular_Adept_Exteneded_DAMNING_DARKNESS **** **** **** **** **** **** **** **** +5928 Ocular_Adept_Silent_DAMNING_DARKNESS **** **** **** **** **** **** **** **** +5929 Ocular_Adept_Death_Ward **** **** **** **** **** **** **** **** +5930 Ocular_Adept_Exteneded_Death_Ward **** **** **** **** **** **** **** **** +5931 Ocular_Adept_Silent_Death_Ward **** **** **** **** **** **** **** **** +5932 Ocular_Adept_Still_Death_Ward **** **** **** **** **** **** **** **** +5933 Ocular_Adept_Dimensional_Anchor **** **** **** **** **** **** **** **** +5934 Ocular_Adept_Exteneded_Dimensional_Anchor **** **** **** **** **** **** **** **** +5935 Ocular_Adept_Silent_Dimensional_Anchor **** **** **** **** **** **** **** **** +5936 Ocular_Adept_Still_Dimensional_Anchor **** **** **** **** **** **** **** **** +5937 Ocular_Adept_Dismissal **** **** **** **** **** **** **** **** +5938 Ocular_Adept_Silent_Dismissal **** **** **** **** **** **** **** **** +5939 Ocular_Adept_Still_Dismissal **** **** **** **** **** **** **** **** +5940 Ocular_Adept_Divine_Power **** **** **** **** **** **** **** **** +5941 Ocular_Adept_Exteneded_Divine_Power **** **** **** **** **** **** **** **** +5942 Ocular_Adept_Silent_Divine_Power **** **** **** **** **** **** **** **** +5943 Ocular_Adept_Still_Divine_Power **** **** **** **** **** **** **** **** +5944 Ocular_Adept_Freedom_of_Movement **** **** **** **** **** **** **** **** +5945 Ocular_Adept_Exteneded_Freedom_of_Movement **** **** **** **** **** **** **** **** +5946 Ocular_Adept_Silent_Freedom_of_Movement **** **** **** **** **** **** **** **** +5947 Ocular_Adept_Still_Freedom_of_Movement **** **** **** **** **** **** **** **** +5948 Ocular_Adept_Greater_Magic_Weapon **** **** **** **** **** **** **** **** +5949 Ocular_Adept_Exteneded_Greater_Magic_Weapon **** **** **** **** **** **** **** **** +5950 Ocular_Adept_Silent_Greater_Magic_Weapon **** **** **** **** **** **** **** **** +5951 Ocular_Adept_Still_Greater_Magic_Weapon **** **** **** **** **** **** **** **** +5952 Ocular_Adept_Greater_Resistance **** **** **** **** **** **** **** **** +5953 Ocular_Adept_Exteneded_Greater_Resistance **** **** **** **** **** **** **** **** +5954 Ocular_Adept_Silent_Greater_Resistance **** **** **** **** **** **** **** **** +5955 Ocular_Adept_Still_Greater_Resistance **** **** **** **** **** **** **** **** +5956 Ocular_Adept_Hammer_of_the_Gods **** **** **** **** **** **** **** **** +5957 Ocular_Adept_Silent_Hammer_of_the_Gods **** **** **** **** **** **** **** **** +5958 Ocular_Adept_Still_Hammer_of_the_Gods **** **** **** **** **** **** **** **** +5959 Ocular_Adept_Inflict_Critical_Wounds **** **** **** **** **** **** **** **** +5960 Ocular_Adept_Silent_Inflict_Critical_Wounds **** **** **** **** **** **** **** **** +5961 Ocular_Adept_Still_Inflict_Critical_Wounds **** **** **** **** **** **** **** **** +5962 Ocular_Adept_Legions_Shield_of_Faith **** **** **** **** **** **** **** **** +5963 Ocular_Adept_Exteneded_Legions_Shield_of_Faith **** **** **** **** **** **** **** **** +5964 Ocular_Adept_Silent_Legions_Shield_of_Faith **** **** **** **** **** **** **** **** +5965 Ocular_Adept_Still_Legions_Shield_of_Faith **** **** **** **** **** **** **** **** +5966 Ocular_Adept_Lesser_Planar_Ally **** **** **** **** **** **** **** **** +5967 Ocular_Adept_Exteneded_Lesser_Planar_Ally **** **** **** **** **** **** **** **** +5968 Ocular_Adept_Silent_Lesser_Planar_Ally **** **** **** **** **** **** **** **** +5969 Ocular_Adept_Still_Lesser_Planar_Ally **** **** **** **** **** **** **** **** +5970 Ocular_Adept_Lower_Spell_Resistance **** **** **** **** **** **** **** **** +5971 Ocular_Adept_Exteneded_Lower_Spell_Resistance **** **** **** **** **** **** **** **** +5972 Ocular_Adept_Silent_Lower_Spell_Resistance **** **** **** **** **** **** **** **** +5973 Ocular_Adept_Still_Lower_Spell_Resistance **** **** **** **** **** **** **** **** +5974 Ocular_Adept_Mass_Ultravision **** **** **** **** **** **** **** **** +5975 Ocular_Adept_Exteneded_Mass_Ultravision **** **** **** **** **** **** **** **** +5976 Ocular_Adept_Silent_Mass_Ultravision **** **** **** **** **** **** **** **** +5977 Ocular_Adept_Still_Mass_Ultravision **** **** **** **** **** **** **** **** +5978 Ocular_Adept_Necrotic_Domination **** **** **** **** **** **** **** **** +5979 Ocular_Adept_Exteneded_Necrotic_Domination **** **** **** **** **** **** **** **** +5980 Ocular_Adept_Silent_Necrotic_Domination **** **** **** **** **** **** **** **** +5981 Ocular_Adept_Still_Necrotic_Domination **** **** **** **** **** **** **** **** +5982 Ocular_Adept_Neutralize_Poison **** **** **** **** **** **** **** **** +5983 Ocular_Adept_Silent_Neutralize_Poison **** **** **** **** **** **** **** **** +5984 Ocular_Adept_Still_Neutralize_Poison **** **** **** **** **** **** **** **** +5985 Ocular_Adept_Panacea **** **** **** **** **** **** **** **** +5986 Ocular_Adept_Silent_Panacea **** **** **** **** **** **** **** **** +5987 Ocular_Adept_Still_Panacea **** **** **** **** **** **** **** **** +5988 Ocular_Adept_Poison **** **** **** **** **** **** **** **** +5989 Ocular_Adept_Silent_Poison **** **** **** **** **** **** **** **** +5990 Ocular_Adept_Still_Poison **** **** **** **** **** **** **** **** +5991 Ocular_Adept_Recitation **** **** **** **** **** **** **** **** +5992 Ocular_Adept_Exteneded_Recitation **** **** **** **** **** **** **** **** +5993 Ocular_Adept_Silent_Recitation **** **** **** **** **** **** **** **** +5994 Ocular_Adept_Still_Recitation **** **** **** **** **** **** **** **** +5995 Ocular_Adept_RepelVermin **** **** **** **** **** **** **** **** +5996 Ocular_Adept_Exteneded_RepelVermin **** **** **** **** **** **** **** **** +5997 Ocular_Adept_Silent_RepelVermin **** **** **** **** **** **** **** **** +5998 Ocular_Adept_Still_RepelVermin **** **** **** **** **** **** **** **** +5999 Ocular_Adept_Restoration **** **** **** **** **** **** **** **** +6000 Ocular_Adept_Silent_Restoration **** **** **** **** **** **** **** **** +6001 Ocular_Adept_Still_Restoration **** **** **** **** **** **** **** **** +6002 Ocular_Adept_STOP_HEART **** **** **** **** **** **** **** **** +6003 Ocular_Adept_Still_STOP_HEART **** **** **** **** **** **** **** **** +6004 Ocular_Adept_Summon_Creature_IV **** **** **** **** **** **** **** **** +6005 Ocular_Adept_Exteneded_Summon_Creature_IV **** **** **** **** **** **** **** **** +6006 Ocular_Adept_Silent_Summon_Creature_IV **** **** **** **** **** **** **** **** +6007 Ocular_Adept_Still_Summon_Creature_IV **** **** **** **** **** **** **** **** +6008 Ocular_Adept_SummonUndeadIV **** **** **** **** **** **** **** **** +6009 Ocular_Adept_Exteneded_SummonUndeadIV **** **** **** **** **** **** **** **** +6010 Ocular_Adept_Silent_SummonUndeadIV **** **** **** **** **** **** **** **** +6011 Ocular_Adept_Still_SummonUndeadIV **** **** **** **** **** **** **** **** +6012 Ocular_Adept_SwordOfConscience **** **** **** **** **** **** **** **** +6013 Ocular_Adept_Silent_SwordOfConscience **** **** **** **** **** **** **** **** +6014 Ocular_Adept_Battletide **** **** **** **** **** **** **** **** +6015 Ocular_Adept_BreakEnchantment **** **** **** **** **** **** **** **** +6016 Ocular_Adept_CHAAVS_LAUGH **** **** **** **** **** **** **** **** +6017 Ocular_Adept_Circle_of_Doom **** **** **** **** **** **** **** **** +6018 Ocular_Adept_CLAWS_OF_THE_BEBILITH **** **** **** **** **** **** **** **** +6019 Ocular_Adept_CONVERT_WAND **** **** **** **** **** **** **** **** +6020 Ocular_Adept_DANCING_WEB **** **** **** **** **** **** **** **** +6021 Ocular_Adept_FireInTheBlood **** **** **** **** **** **** **** **** +6022 Ocular_Adept_Flame_Strike **** **** **** **** **** **** **** **** +6023 Ocular_Adept_Greater_Vigor(Monstrous_Regeneration) **** **** **** **** **** **** **** **** +6024 Ocular_Adept_GreaterCommand_RadialMaster **** **** **** **** **** **** **** **** +6025 Ocular_Adept_GreaterCommand_Approach **** **** **** **** **** **** **** **** +6026 Ocular_Adept_GreaterCommand_Drop **** **** **** **** **** **** **** **** +6027 Ocular_Adept_GreaterCommand_Fall **** **** **** **** **** **** **** **** +6028 Ocular_Adept_GreaterCommand_Flee **** **** **** **** **** **** **** **** +6029 Ocular_Adept_GreaterCommand_Halt **** **** **** **** **** **** **** **** +6030 Ocular_Adept_Healing_Circle **** **** **** **** **** **** **** **** +6031 Ocular_Adept_HEARTCLUTCH **** **** **** **** **** **** **** **** +6032 Ocular_Adept_Legions_Curse_of_Petty_Failing **** **** **** **** **** **** **** **** +6033 Ocular_Adept_Mass_Contagion **** **** **** **** **** **** **** **** +6034 Ocular_Adept_Mass_Cure_Light_Wounds **** **** **** **** **** **** **** **** +6035 Ocular_Adept_Mass_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +6036 Ocular_Adept_MORALITY_UNDONE **** **** **** **** **** **** **** **** +6037 Ocular_Adept_Necrotic_Burst **** **** **** **** **** **** **** **** +6038 Ocular_Adept_POWER_LEECH **** **** **** **** **** **** **** **** +6039 Ocular_Adept_Raise_Dead **** **** **** **** **** **** **** **** +6040 Ocular_Adept_RESONATING_RESISTANCE **** **** **** **** **** **** **** **** +6041 Ocular_Adept_Revivify **** **** **** **** **** **** **** **** +6042 Ocular_Adept_Righteous_Might **** **** **** **** **** **** **** **** +6043 Ocular_Adept_Scrying **** **** **** **** **** **** **** **** +6044 Ocular_Adept_Slay_Living **** **** **** **** **** **** **** **** +6045 Ocular_Adept_Soulscour **** **** **** **** **** **** **** **** +6046 Ocular_Adept_Spell_Resistance **** **** **** **** **** **** **** **** +6047 Ocular_Adept_Summon_Creature_V **** **** **** **** **** **** **** **** +6048 Ocular_Adept_SummonUndeadV **** **** **** **** **** **** **** **** +6049 Ocular_Adept_SYMBOL_OF_PAIN **** **** **** **** **** **** **** **** +6050 Ocular_Adept_SYMBOL_OF_SLEEP **** **** **** **** **** **** **** **** +6051 Ocular_Adept_True_Seeing **** **** **** **** **** **** **** **** +6052 Hexblade_AugmentFamiliar **** **** **** **** **** **** **** **** +6053 Hexblade_Light **** **** **** **** **** **** **** **** +6054 Hexblade_Cause_Fear **** **** **** **** **** **** **** **** +6055 Hexblade_Charm_Person **** **** **** **** **** **** **** **** +6056 Hexblade_Disguise_Self_Radial_Master **** **** **** **** **** **** **** **** +6057 Hexblade_Disguise_Self_Learn **** **** **** **** **** **** **** **** +6058 Hexblade_Disguise_Self_Options **** **** **** **** **** **** **** **** +6059 Hexblade_Disguise_Self_QS1 **** **** **** **** **** **** **** **** +6060 Hexblade_Disguise_Self_QS2 **** **** **** **** **** **** **** **** +6061 Hexblade_Disguise_Self_QS3 **** **** **** **** **** **** **** **** +6062 Hexblade_Entropic_Shield **** **** **** **** **** **** **** **** +6063 Hexblade_Expeditious_Retreat **** **** **** **** **** **** **** **** +6064 Hexblade_Identify **** **** **** **** **** **** **** **** +6065 Hexblade_Magic_Weapon **** **** **** **** **** **** **** **** +6066 Hexblade_Protection_from_Chaos **** **** **** **** **** **** **** **** +6067 Hexblade_Protection_from_Evil **** **** **** **** **** **** **** **** +6068 Hexblade_Protection_from_Good **** **** **** **** **** **** **** **** +6069 Hexblade_Protection_from_Law **** **** **** **** **** **** **** **** +6070 Hexblade_Read_Magic **** **** **** **** **** **** **** **** +6071 Hexblade_Sleep **** **** **** **** **** **** **** **** +6072 Hexblade_Tashas_Hideous_Laughter **** **** **** **** **** **** **** **** +6073 Hexblade_UndetectableAlignment **** **** **** **** **** **** **** **** +6074 Hexblade_Alter_Self_Radial_Master **** **** **** **** **** **** **** **** +6075 Hexblade_Alter_Self_Learn **** **** **** **** **** **** **** **** +6076 Hexblade_Alter_Self_Options **** **** **** **** **** **** **** **** +6077 Hexblade_Alter_Self_QS1 **** **** **** **** **** **** **** **** +6078 Hexblade_Alter_Self_QS2 **** **** **** **** **** **** **** **** +6079 Hexblade_Alter_Self_QS3 **** **** **** **** **** **** **** **** +6080 Hexblade_Blindness_and_Deafness **** **** **** **** **** **** **** **** +6081 Hexblade_Blood_Frenzy **** **** **** **** **** **** **** **** +6082 Hexblade_Bulls_Strength **** **** **** **** **** **** **** **** +6083 Hexblade_Darkness **** **** **** **** **** **** **** **** +6084 Hexblade_Eagle_Splendor **** **** **** **** **** **** **** **** +6085 Hexblade_FalseLife **** **** **** **** **** **** **** **** +6086 Hexblade_Glitterdust **** **** **** **** **** **** **** **** +6087 Hexblade_Invisibility **** **** **** **** **** **** **** **** +6088 Hexblade_MirrorImage **** **** **** **** **** **** **** **** +6089 Hexblade_ProtectionArrows **** **** **** **** **** **** **** **** +6090 Hexblade_Pyrotechnics **** **** **** **** **** **** **** **** +6091 Hexblade_Pyrotechnics_Fireworks **** **** **** **** **** **** **** **** +6092 Hexblade_Pyrotechnics_Smoke **** **** **** **** **** **** **** **** +6093 Hexblade_Resist_Elements **** **** **** **** **** **** **** **** +6094 Hexblade_See_Invisibility **** **** **** **** **** **** **** **** +6095 Hexblade_TouchIdiocy **** **** **** **** **** **** **** **** +6096 Hexblade_Charm_Monster **** **** **** **** **** **** **** **** +6097 Hexblade_Confusion **** **** **** **** **** **** **** **** +6098 Hexblade_DeepSlumber **** **** **** **** **** **** **** **** +6099 Hexblade_Dispel_Magic **** **** **** **** **** **** **** **** +6100 Hexblade_Greater_Magic_Weapon **** **** **** **** **** **** **** **** +6101 Hexblade_HoundDoom **** **** **** **** **** **** **** **** +6102 Hexblade_Invisibility_Sphere **** **** **** **** **** **** **** **** +6103 Hexblade_NONDETECTION **** **** **** **** **** **** **** **** +6104 Hexblade_Poison **** **** **** **** **** **** **** **** +6105 Hexblade_Protection_from_Elements **** **** **** **** **** **** **** **** +6106 Hexblade_RepelVermin **** **** **** **** **** **** **** **** +6107 Hexblade_Slow **** **** **** **** **** **** **** **** +6108 Hexblade_Stinking_Cloud **** **** **** **** **** **** **** **** +6109 Hexblade_Vampiric_Touch **** **** **** **** **** **** **** **** +6110 Hexblade_BalefulPolymorph **** **** **** **** **** **** **** **** +6111 Hexblade_BreakEnchantment **** **** **** **** **** **** **** **** +6112 Hexblade_CursedBlade **** **** **** **** **** **** **** **** +6113 Hexblade_DimensionDoor_RadialMaster **** **** **** **** **** **** **** **** +6114 Hexblade_DimensionDoor_SelfOnly **** **** **** **** **** **** **** **** +6115 Hexblade_DimensionDoor_Party **** **** **** **** **** **** **** **** +6116 Hexblade_DimensionDoor_DirDist_SelfOnly **** **** **** **** **** **** **** **** +6117 Hexblade_DimensionDoor_DirDist_Party **** **** **** **** **** **** **** **** +6118 Hexblade_Dominate_Person **** **** **** **** **** **** **** **** +6119 Hexblade_Enervation **** **** **** **** **** **** **** **** +6120 Hexblade_Improved_Invisibility **** **** **** **** **** **** **** **** +6121 Hexblade_Phantasmal_Killer **** **** **** **** **** **** **** **** +6122 Hexblade_Polymorph_Self **** **** **** **** **** **** **** **** +6123 Hexblade_Polymorph_GIANT_SPIDER **** **** **** **** **** **** **** **** +6124 Hexblade_Polymorph_TROLL **** **** **** **** **** **** **** **** +6125 Hexblade_Polymorph_UMBER_HULK **** **** **** **** **** **** **** **** +6126 Hexblade_Polymorph_PIXIE **** **** **** **** **** **** **** **** +6127 Hexblade_Polymorph_ZOMBIE **** **** **** **** **** **** **** **** +6128 Hexblade_Fear **** **** **** **** **** **** **** **** +6129 Hexblade_Scrying **** **** **** **** **** **** **** **** +6130 Hexblade_SolidFog **** **** **** **** **** **** **** **** +6131 Duskblade_Acid_Splash **** **** **** **** **** **** **** **** +6132 Duskblade_DisruptUndead **** **** **** **** **** **** **** **** +6133 Duskblade_Ray_of_Frost **** **** **** **** **** **** **** **** +6134 Duskblade_Blade_of_Blood **** **** **** **** **** **** **** **** +6135 Duskblade_Blade_of_Blood_1d6 **** **** **** **** **** **** **** **** +6136 Duskblade_Blade_of_Blood_3d6 **** **** **** **** **** **** **** **** +6137 Duskblade_Kelgores_Fire_Bolt **** **** **** **** **** **** **** **** +6138 Duskblade_Lesser_Deflect **** **** **** **** **** **** **** **** +6139 Duskblade_Rouse **** **** **** **** **** **** **** **** +6140 Duskblade_Bigbys_Tripping_Hand **** **** **** **** **** **** **** **** +6141 Duskblade_Burning_Hands **** **** **** **** **** **** **** **** +6142 Duskblade_Chill_Touch **** **** **** **** **** **** **** **** +6143 Duskblade_Color_Spray **** **** **** **** **** **** **** **** +6144 Duskblade_Expeditious_Retreat **** **** **** **** **** **** **** **** +6145 Duskblade_Spell_Jump **** **** **** **** **** **** **** **** +6146 Duskblade_Magic_Weapon **** **** **** **** **** **** **** **** +6147 Duskblade_Obscuring_Mist **** **** **** **** **** **** **** **** +6148 Duskblade_Ray_of_Enfeeblement **** **** **** **** **** **** **** **** +6149 Duskblade_Cause_Fear **** **** **** **** **** **** **** **** +6150 Duskblade_True_Strike **** **** **** **** **** **** **** **** +6151 Duskblade_Resist_Elements **** **** **** **** **** **** **** **** +6152 Duskblade_ShockingGrasp **** **** **** **** **** **** **** **** +6153 Duskblade_Animalistic_Power **** **** **** **** **** **** **** **** +6154 Duskblade_Deflect **** **** **** **** **** **** **** **** +6155 Duskblade_Dimension_Hop **** **** **** **** **** **** **** **** +6156 Duskblade_Seeking_Ray **** **** **** **** **** **** **** **** +6157 Duskblade_Sure_Strike **** **** **** **** **** **** **** **** +6158 Duskblade_Bigbys_Striking_Fist **** **** **** **** **** **** **** **** +6159 Duskblade_Bulls_Strength **** **** **** **** **** **** **** **** +6160 Duskblade_Cats_Grace **** **** **** **** **** **** **** **** +6161 Duskblade_Endurance **** **** **** **** **** **** **** **** +6162 Duskblade_Ghoul_Touch **** **** **** **** **** **** **** **** +6163 Duskblade_Invisibility **** **** **** **** **** **** **** **** +6164 Duskblade_Melfs_Acid_Arrow **** **** **** **** **** **** **** **** +6165 Duskblade_TouchIdiocy **** **** **** **** **** **** **** **** +6166 Duskblade_See_Invisibility **** **** **** **** **** **** **** **** +6167 Duskblade_ScorchingRay **** **** **** **** **** **** **** **** +6168 Duskblade_Crown_Might **** **** **** **** **** **** **** **** +6169 Duskblade_Crown_Protection **** **** **** **** **** **** **** **** +6170 Duskblade_Dispelling_Touch **** **** **** **** **** **** **** **** +6171 Duskblade_Doom_Scarabs **** **** **** **** **** **** **** **** +6172 Duskblade_Energy_Aegis **** **** **** **** **** **** **** **** +6173 Duskblade_Energy_Aegis_Acid **** **** **** **** **** **** **** **** +6174 Duskblade_Energy_Aegis_Cold **** **** **** **** **** **** **** **** +6175 Duskblade_Energy_Aegis_Elec **** **** **** **** **** **** **** **** +6176 Duskblade_Energy_Aegis_Fire **** **** **** **** **** **** **** **** +6177 Duskblade_Energy_Aegis_Sonic **** **** **** **** **** **** **** **** +6178 Duskblade_Energy_Surge **** **** **** **** **** **** **** **** +6179 Duskblade_Energy_Surge_Acid **** **** **** **** **** **** **** **** +6180 Duskblade_Energy_Surge_Cold **** **** **** **** **** **** **** **** +6181 Duskblade_Energy_Surge_Elec **** **** **** **** **** **** **** **** +6182 Duskblade_Energy_Surge_Fire **** **** **** **** **** **** **** **** +6183 Duskblade_Energy_Surge_Sonic **** **** **** **** **** **** **** **** +6184 Duskblade_Halt **** **** **** **** **** **** **** **** +6185 Duskblade_Regroup **** **** **** **** **** **** **** **** +6186 Duskblade_Greater_Magic_Weapon **** **** **** **** **** **** **** **** +6187 Duskblade_Keen_Edge **** **** **** **** **** **** **** **** +6188 Duskblade_Protection_from_Elements **** **** **** **** **** **** **** **** +6189 Duskblade_Vampiric_Touch **** **** **** **** **** **** **** **** +6190 Duskblade_RayofExhaustion **** **** **** **** **** **** **** **** +6191 Duskblade_Channeled_Pyroburst **** **** **** **** **** **** **** **** +6192 Duskblade_Channeled_Pyroburst_Swift **** **** **** **** **** **** **** **** +6193 Duskblade_Channeled_Pyroburst_Standard **** **** **** **** **** **** **** **** +6194 Duskblade_Channeled_Pyroburst_Full **** **** **** **** **** **** **** **** +6195 Duskblade_Channeled_Pyroburst_Two **** **** **** **** **** **** **** **** +6196 Duskblade_DimensionDoor_RadialMaster **** **** **** **** **** **** **** **** +6197 Duskblade_DimensionDoor_SelfOnly **** **** **** **** **** **** **** **** +6198 Duskblade_DimensionDoor_Party **** **** **** **** **** **** **** **** +6199 Duskblade_DimensionDoor_DirDist_SelfOnly **** **** **** **** **** **** **** **** +6200 Duskblade_DimensionDoor_DirDist_Party **** **** **** **** **** **** **** **** +6201 Duskblade_Elemental_Shield **** **** **** **** **** **** **** **** +6202 Duskblade_Enervation **** **** **** **** **** **** **** **** +6203 Duskblade_Phantasmal_Killer **** **** **** **** **** **** **** **** +6204 Duskblade_Shout **** **** **** **** **** **** **** **** +6205 Duskblade_Bigbys_Interposing_Hand **** **** **** **** **** **** **** **** +6206 Duskblade_Dispel_Magic **** **** **** **** **** **** **** **** +6207 Duskblade_Slashing_Dispel **** **** **** **** **** **** **** **** +6208 Duskblade_Sonic_Shield **** **** **** **** **** **** **** **** +6209 Duskblade_Hold_Monster **** **** **** **** **** **** **** **** +6210 Duskblade_Chain_Lightning **** **** **** **** **** **** **** **** +6211 Duskblade_Disintegrate **** **** **** **** **** **** **** **** +6212 Duskblade_Bigbys_Clenched_Fist **** **** **** **** **** **** **** **** +6213 Duskblade_PolarRay **** **** **** **** **** **** **** **** +6214 Duskblade_WavesofFatigue **** **** **** **** **** **** **** **** +6215 Healer_Cure_Minor_Wounds **** **** **** **** **** **** **** **** +6216 Healer_Quickened_Cure_Minor_Wounds **** **** **** **** **** **** **** **** +6217 Healer_Silent_Cure_Minor_Wounds **** **** **** **** **** **** **** **** +6218 Healer_Still_Cure_Minor_Wounds **** **** **** **** **** **** **** **** +6219 Healer_Light **** **** **** **** **** **** **** **** +6220 Healer_Exteneded_Light **** **** **** **** **** **** **** **** +6221 Healer_Quickened_Light **** **** **** **** **** **** **** **** +6222 Healer_Silent_Light **** **** **** **** **** **** **** **** +6223 Healer_Read_Magic **** **** **** **** **** **** **** **** +6224 Healer_Quickened_Read_Magic **** **** **** **** **** **** **** **** +6225 Healer_Silent_Read_Magic **** **** **** **** **** **** **** **** +6226 Healer_Still_Read_Magic **** **** **** **** **** **** **** **** +6227 Healer_Bless_Water **** **** **** **** **** **** **** **** +6228 Healer_Quickened_Bless_Water **** **** **** **** **** **** **** **** +6229 Healer_Silent_Bless_Water **** **** **** **** **** **** **** **** +6230 Healer_Still_Bless_Water **** **** **** **** **** **** **** **** +6231 Healer_Cure_Light_Wounds **** **** **** **** **** **** **** **** +6232 Healer_Empowered_Cure_Light_Wounds **** **** **** **** **** **** **** **** +6233 Healer_Maximized_Cure_Light_Wounds **** **** **** **** **** **** **** **** +6234 Healer_Quickened_Cure_Light_Wounds **** **** **** **** **** **** **** **** +6235 Healer_Silent_Cure_Light_Wounds **** **** **** **** **** **** **** **** +6236 Healer_Still_Cure_Light_Wounds **** **** **** **** **** **** **** **** +6237 Healer_Lesser_Vigor **** **** **** **** **** **** **** **** +6238 Healer_Exteneded_Lesser_Vigor **** **** **** **** **** **** **** **** +6239 Healer_Quickened_Lesser_Vigor **** **** **** **** **** **** **** **** +6240 Healer_Silent_Lesser_Vigor **** **** **** **** **** **** **** **** +6241 Healer_Still_Lesser_Vigor **** **** **** **** **** **** **** **** +6242 Healer_Protection_from_Evil **** **** **** **** **** **** **** **** +6243 Healer_Exteneded_Protection_from_Evil **** **** **** **** **** **** **** **** +6244 Healer_Quickened_Protection_from_Evil **** **** **** **** **** **** **** **** +6245 Healer_Silent_Protection_from_Evil **** **** **** **** **** **** **** **** +6246 Healer_Still_Protection_from_Evil **** **** **** **** **** **** **** **** +6247 Healer_Remove_Fear **** **** **** **** **** **** **** **** +6248 Healer_Exteneded_Remove_Fear **** **** **** **** **** **** **** **** +6249 Healer_Quickened_Remove_Fear **** **** **** **** **** **** **** **** +6250 Healer_Silent_Remove_Fear **** **** **** **** **** **** **** **** +6251 Healer_Still_Remove_Fear **** **** **** **** **** **** **** **** +6252 Healer_Remove_Paralysis **** **** **** **** **** **** **** **** +6253 Healer_Quickened_Remove_Paralysis **** **** **** **** **** **** **** **** +6254 Healer_Silent_Remove_Paralysis **** **** **** **** **** **** **** **** +6255 Healer_Still_Remove_Paralysis **** **** **** **** **** **** **** **** +6256 Healer_Sanctuary **** **** **** **** **** **** **** **** +6257 Healer_Exteneded_Sanctuary **** **** **** **** **** **** **** **** +6258 Healer_Quickened_Sanctuary **** **** **** **** **** **** **** **** +6259 Healer_Silent_Sanctuary **** **** **** **** **** **** **** **** +6260 Healer_Still_Sanctuary **** **** **** **** **** **** **** **** +6261 Healer_TWILIGHT_LUCK **** **** **** **** **** **** **** **** +6262 Healer_Exteneded_TWILIGHT_LUCK **** **** **** **** **** **** **** **** +6263 Healer_Silent_TWILIGHT_LUCK **** **** **** **** **** **** **** **** +6264 Healer_DIVINE_INSPIRATION **** **** **** **** **** **** **** **** +6265 Healer_Exteneded_DIVINE_INSPIRATION **** **** **** **** **** **** **** **** +6266 Healer_Quickened_DIVINE_INSPIRATION **** **** **** **** **** **** **** **** +6267 Healer_Calm_Emotions **** **** **** **** **** **** **** **** +6268 Healer_Exteneded_Calm_Emotions **** **** **** **** **** **** **** **** +6269 Healer_Quickened_Calm_Emotions **** **** **** **** **** **** **** **** +6270 Healer_Silent_Calm_Emotions **** **** **** **** **** **** **** **** +6271 Healer_Still_Calm_Emotions **** **** **** **** **** **** **** **** +6272 Healer_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +6273 Healer_Empowered_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +6274 Healer_Maximized_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +6275 Healer_Quickened_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +6276 Healer_Silent_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +6277 Healer_Still_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +6278 Healer_Remove_Blindness_and_Deafness **** **** **** **** **** **** **** **** +6279 Healer_Quickened_Remove_Blindness_and_Deafness **** **** **** **** **** **** **** **** +6280 Healer_Silent_Remove_Blindness_and_Deafness **** **** **** **** **** **** **** **** +6281 Healer_Still_Remove_Blindness_and_Deafness **** **** **** **** **** **** **** **** +6282 Healer_Remove_Disease **** **** **** **** **** **** **** **** +6283 Healer_Quickened_Remove_Disease **** **** **** **** **** **** **** **** +6284 Healer_Silent_Remove_Disease **** **** **** **** **** **** **** **** +6285 Healer_Still_Remove_Disease **** **** **** **** **** **** **** **** +6286 Healer_Lesser_Restoration **** **** **** **** **** **** **** **** +6287 Healer_Quickened_Lesser_Restoration **** **** **** **** **** **** **** **** +6288 Healer_Silent_Lesser_Restoration **** **** **** **** **** **** **** **** +6289 Healer_Still_Lesser_Restoration **** **** **** **** **** **** **** **** +6290 Healer_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +6291 Healer_Exteneded_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +6292 Healer_Quickened_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +6293 Healer_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +6294 Healer_Empowered_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +6295 Healer_Maximized_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +6296 Healer_Quickened_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +6297 Healer_Silent_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +6298 Healer_Still_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +6299 Healer_Close_Wounds **** **** **** **** **** **** **** **** +6300 Healer_Empowered_Close_Wounds **** **** **** **** **** **** **** **** +6301 Healer_Maximized_Close_Wounds **** **** **** **** **** **** **** **** +6302 Healer_Quickened_Close_Wounds **** **** **** **** **** **** **** **** +6303 Healer_Silent_Close_Wounds **** **** **** **** **** **** **** **** +6304 Healer_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +6305 Healer_Empowered_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +6306 Healer_Maximized_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +6307 Healer_Quickened_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +6308 Healer_Silent_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +6309 Healer_Still_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +6310 Healer_Mass_Lesser_Vigor **** **** **** **** **** **** **** **** +6311 Healer_Exteneded_Mass_Lesser_Vigor **** **** **** **** **** **** **** **** +6312 Healer_Quickened_Mass_Lesser_Vigor **** **** **** **** **** **** **** **** +6313 Healer_Silent_Mass_Lesser_Vigor **** **** **** **** **** **** **** **** +6314 Healer_Still_Mass_Lesser_Vigor **** **** **** **** **** **** **** **** +6315 Healer_Neutralize_Poison **** **** **** **** **** **** **** **** +6316 Healer_Quickened_Neutralize_Poison **** **** **** **** **** **** **** **** +6317 Healer_Silent_Neutralize_Poison **** **** **** **** **** **** **** **** +6318 Healer_Still_Neutralize_Poison **** **** **** **** **** **** **** **** +6319 Healer_Remove_Curse **** **** **** **** **** **** **** **** +6320 Healer_Quickened_Remove_Curse **** **** **** **** **** **** **** **** +6321 Healer_Silent_Remove_Curse **** **** **** **** **** **** **** **** +6322 Healer_Still_Remove_Curse **** **** **** **** **** **** **** **** +6323 Healer_Restoration **** **** **** **** **** **** **** **** +6324 Healer_Quickened_Restoration **** **** **** **** **** **** **** **** +6325 Healer_Silent_Restoration **** **** **** **** **** **** **** **** +6326 Healer_Still_Restoration **** **** **** **** **** **** **** **** +6327 Healer_BRILLIANT_EMANATION **** **** **** **** **** **** **** **** +6328 Healer_Exteneded_BRILLIANT_EMANATION **** **** **** **** **** **** **** **** +6329 Healer_Quickened_BRILLIANT_EMANATION **** **** **** **** **** **** **** **** +6330 Healer_HAMMER_OF_RIGHTEOUSNESS **** **** **** **** **** **** **** **** +6331 Healer_Empowered_HAMMER_OF_RIGHTEOUSNESS **** **** **** **** **** **** **** **** +6332 Healer_Maximized_HAMMER_OF_RIGHTEOUSNESS **** **** **** **** **** **** **** **** +6333 Healer_Quickened_HAMMER_OF_RIGHTEOUSNESS **** **** **** **** **** **** **** **** +6334 Healer_Silent_HAMMER_OF_RIGHTEOUSNESS **** **** **** **** **** **** **** **** +6335 Healer_Still_HAMMER_OF_RIGHTEOUSNESS **** **** **** **** **** **** **** **** +6336 Healer_Vigor **** **** **** **** **** **** **** **** +6337 Healer_Exteneded_Vigor **** **** **** **** **** **** **** **** +6338 Healer_Quickened_Vigor **** **** **** **** **** **** **** **** +6339 Healer_Silent_Vigor **** **** **** **** **** **** **** **** +6340 Healer_Still_Vigor **** **** **** **** **** **** **** **** +6341 Healer_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +6342 Healer_Empowered_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +6343 Healer_Maximized_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +6344 Healer_Quickened_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +6345 Healer_Silent_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +6346 Healer_Still_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +6347 Healer_Death_Ward **** **** **** **** **** **** **** **** +6348 Healer_Exteneded_Death_Ward **** **** **** **** **** **** **** **** +6349 Healer_Quickened_Death_Ward **** **** **** **** **** **** **** **** +6350 Healer_Silent_Death_Ward **** **** **** **** **** **** **** **** +6351 Healer_Still_Death_Ward **** **** **** **** **** **** **** **** +6352 Healer_Freedom_of_Movement **** **** **** **** **** **** **** **** +6353 Healer_Exteneded_Freedom_of_Movement **** **** **** **** **** **** **** **** +6354 Healer_Quickened_Freedom_of_Movement **** **** **** **** **** **** **** **** +6355 Healer_Silent_Freedom_of_Movement **** **** **** **** **** **** **** **** +6356 Healer_Still_Freedom_of_Movement **** **** **** **** **** **** **** **** +6357 Healer_Mass_Cure_Light_Wounds **** **** **** **** **** **** **** **** +6358 Healer_Empowered_Mass_Cure_Light_Wounds **** **** **** **** **** **** **** **** +6359 Healer_Maximized_Mass_Cure_Light_Wounds **** **** **** **** **** **** **** **** +6360 Healer_Quickened_Mass_Cure_Light_Wounds **** **** **** **** **** **** **** **** +6361 Healer_Silent_Mass_Cure_Light_Wounds **** **** **** **** **** **** **** **** +6362 Healer_Still_Mass_Cure_Light_Wounds **** **** **** **** **** **** **** **** +6363 Healer_Panacea **** **** **** **** **** **** **** **** +6364 Healer_Empowered_Panacea **** **** **** **** **** **** **** **** +6365 Healer_Maximized_Panacea **** **** **** **** **** **** **** **** +6366 Healer_Quickened_Panacea **** **** **** **** **** **** **** **** +6367 Healer_Silent_Panacea **** **** **** **** **** **** **** **** +6368 Healer_Still_Panacea **** **** **** **** **** **** **** **** +6369 Healer_GREATER_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +6370 Healer_Exteneded_GREATER_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +6371 Healer_Quickened_GREATER_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +6372 Healer_SUNMANTLE **** **** **** **** **** **** **** **** +6373 Healer_Exteneded_SUNMANTLE **** **** **** **** **** **** **** **** +6374 Healer_Quickened_SUNMANTLE **** **** **** **** **** **** **** **** +6375 Healer_Still_SUNMANTLE **** **** **** **** **** **** **** **** +6376 Healer_DIAMOND_SPRAY **** **** **** **** **** **** **** **** +6377 Healer_Empowered_DIAMOND_SPRAY **** **** **** **** **** **** **** **** +6378 Healer_Exteneded_DIAMOND_SPRAY **** **** **** **** **** **** **** **** +6379 Healer_Maximized_DIAMOND_SPRAY **** **** **** **** **** **** **** **** +6380 Healer_Quickened_DIAMOND_SPRAY **** **** **** **** **** **** **** **** +6381 Healer_Silent_DIAMOND_SPRAY **** **** **** **** **** **** **** **** +6382 Healer_Still_DIAMOND_SPRAY **** **** **** **** **** **** **** **** +6383 Healer_BreakEnchantment **** **** **** **** **** **** **** **** +6384 Healer_Quickened_BreakEnchantment **** **** **** **** **** **** **** **** +6385 Healer_Silent_BreakEnchantment **** **** **** **** **** **** **** **** +6386 Healer_Still_BreakEnchantment **** **** **** **** **** **** **** **** +6387 Healer_Greater_Vigor(Monstrous_Regeneration) **** **** **** **** **** **** **** **** +6388 Healer_Exteneded_Greater_Vigor(Monstrous_Regeneration) **** **** **** **** **** **** **** **** +6389 Healer_Quickened_Greater_Vigor(Monstrous_Regeneration) **** **** **** **** **** **** **** **** +6390 Healer_Silent_Greater_Vigor(Monstrous_Regeneration) **** **** **** **** **** **** **** **** +6391 Healer_Still_Greater_Vigor(Monstrous_Regeneration) **** **** **** **** **** **** **** **** +6392 Healer_Mass_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +6393 Healer_Empowered_Mass_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +6394 Healer_Maximized_Mass_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +6395 Healer_Quickened_Mass_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +6396 Healer_Silent_Mass_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +6397 Healer_Still_Mass_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +6398 Healer_Raise_Dead **** **** **** **** **** **** **** **** +6399 Healer_Quickened_Raise_Dead **** **** **** **** **** **** **** **** +6400 Healer_Silent_Raise_Dead **** **** **** **** **** **** **** **** +6401 Healer_Still_Raise_Dead **** **** **** **** **** **** **** **** +6402 Healer_Revivify **** **** **** **** **** **** **** **** +6403 Healer_Quickened_Revivify **** **** **** **** **** **** **** **** +6404 Healer_Silent_Revivify **** **** **** **** **** **** **** **** +6405 Healer_Still_Revivify **** **** **** **** **** **** **** **** +6406 Healer_Stone_to_flesh **** **** **** **** **** **** **** **** +6407 Healer_Exteneded_Stone_to_flesh **** **** **** **** **** **** **** **** +6408 Healer_Quickened_Stone_to_flesh **** **** **** **** **** **** **** **** +6409 Healer_Silent_Stone_to_flesh **** **** **** **** **** **** **** **** +6410 Healer_Still_Stone_to_flesh **** **** **** **** **** **** **** **** +6411 Healer_True_Seeing **** **** **** **** **** **** **** **** +6412 Healer_Exteneded_True_Seeing **** **** **** **** **** **** **** **** +6413 Healer_Quickened_True_Seeing **** **** **** **** **** **** **** **** +6414 Healer_Silent_True_Seeing **** **** **** **** **** **** **** **** +6415 Healer_Still_True_Seeing **** **** **** **** **** **** **** **** +6416 Healer_SICKEN_EVIL **** **** **** **** **** **** **** **** +6417 Healer_Exteneded_SICKEN_EVIL **** **** **** **** **** **** **** **** +6418 Healer_Quickened_SICKEN_EVIL **** **** **** **** **** **** **** **** +6419 Healer_Silent_SICKEN_EVIL **** **** **** **** **** **** **** **** +6420 Healer_Still_SICKEN_EVIL **** **** **** **** **** **** **** **** +6421 Healer_Greater_Restoration **** **** **** **** **** **** **** **** +6422 Healer_Silent_Greater_Restoration **** **** **** **** **** **** **** **** +6423 Healer_Still_Greater_Restoration **** **** **** **** **** **** **** **** +6424 Healer_Heal **** **** **** **** **** **** **** **** +6425 Healer_Silent_Heal **** **** **** **** **** **** **** **** +6426 Healer_Still_Heal **** **** **** **** **** **** **** **** +6427 Healer_Mass_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +6428 Healer_Empowered_Mass_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +6429 Healer_Maximized_Mass_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +6430 Healer_Silent_Mass_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +6431 Healer_Still_Mass_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +6432 Healer_Regenerate **** **** **** **** **** **** **** **** +6433 Healer_Exteneded_Regenerate **** **** **** **** **** **** **** **** +6434 Healer_Silent_Regenerate **** **** **** **** **** **** **** **** +6435 Healer_Still_Regenerate **** **** **** **** **** **** **** **** +6436 Healer_EXALTED_RAIMENT **** **** **** **** **** **** **** **** +6437 Healer_Exteneded_EXALTED_RAIMENT **** **** **** **** **** **** **** **** +6438 Healer_Silent_EXALTED_RAIMENT **** **** **** **** **** **** **** **** +6439 Healer_STORM_OF_SHARDS **** **** **** **** **** **** **** **** +6440 Healer_Empowered_STORM_OF_SHARDS **** **** **** **** **** **** **** **** +6441 Healer_Maximized_STORM_OF_SHARDS **** **** **** **** **** **** **** **** +6442 Healer_Silent_STORM_OF_SHARDS **** **** **** **** **** **** **** **** +6443 Healer_Still_STORM_OF_SHARDS **** **** **** **** **** **** **** **** +6444 Healer_Vigorous_Circle **** **** **** **** **** **** **** **** +6445 Healer_Exteneded_Vigorous_Circle **** **** **** **** **** **** **** **** +6446 Healer_Silent_Vigorous_Circle **** **** **** **** **** **** **** **** +6447 Healer_Still_Vigorous_Circle **** **** **** **** **** **** **** **** +6448 Healer_Mass_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +6449 Healer_Empowered_Mass_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +6450 Healer_Silent_Mass_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +6451 Healer_Still_Mass_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +6452 Healer_Resurrection **** **** **** **** **** **** **** **** +6453 Healer_Silent_Resurrection **** **** **** **** **** **** **** **** +6454 Healer_Still_Resurrection **** **** **** **** **** **** **** **** +6455 Healer_Repulsion **** **** **** **** **** **** **** **** +6456 Healer_Exteneded_Repulsion **** **** **** **** **** **** **** **** +6457 Healer_Silent_Repulsion **** **** **** **** **** **** **** **** +6458 Healer_Still_Repulsion **** **** **** **** **** **** **** **** +6459 Healer_RAIN_OF_EMBERS **** **** **** **** **** **** **** **** +6460 Healer_Empowered_RAIN_OF_EMBERS **** **** **** **** **** **** **** **** +6461 Healer_Exteneded_RAIN_OF_EMBERS **** **** **** **** **** **** **** **** +6462 Healer_Silent_RAIN_OF_EMBERS **** **** **** **** **** **** **** **** +6463 Healer_Still_RAIN_OF_EMBERS **** **** **** **** **** **** **** **** +6464 Healer_PHOENIX_FIRE **** **** **** **** **** **** **** **** +6465 Healer_Empowered_PHOENIX_FIRE **** **** **** **** **** **** **** **** +6466 Healer_Silent_PHOENIX_FIRE **** **** **** **** **** **** **** **** +6467 Healer_Still_PHOENIX_FIRE **** **** **** **** **** **** **** **** +6468 Healer_DiscernLocation **** **** **** **** **** **** **** **** +6469 Healer_Exteneded_DiscernLocation **** **** **** **** **** **** **** **** +6470 Healer_Silent_DiscernLocation **** **** **** **** **** **** **** **** +6471 Healer_Still_DiscernLocation **** **** **** **** **** **** **** **** +6472 Healer_Holy_Aura **** **** **** **** **** **** **** **** +6473 Healer_Exteneded_Holy_Aura **** **** **** **** **** **** **** **** +6474 Healer_Silent_Holy_Aura **** **** **** **** **** **** **** **** +6475 Healer_Still_Holy_Aura **** **** **** **** **** **** **** **** +6476 Healer_Mass_Heal **** **** **** **** **** **** **** **** +6477 Healer_Silent_Mass_Heal **** **** **** **** **** **** **** **** +6478 Healer_Still_Mass_Heal **** **** **** **** **** **** **** **** +6479 Healer_DRAGON_CLOUD **** **** **** **** **** **** **** **** +6480 Healer_Silent_DRAGON_CLOUD **** **** **** **** **** **** **** **** +6481 Healer_Still_DRAGON_CLOUD **** **** **** **** **** **** **** **** +6482 Healer_Foresight **** **** **** **** **** **** **** **** +6483 Healer_Gate **** **** **** **** **** **** **** **** +6484 Healer_True_Resurrection **** **** **** **** **** **** **** **** +6485 Healer_EXALTED_FURY **** **** **** **** **** **** **** **** +6486 CelebrantSharess_Cause_Fear **** **** **** **** **** **** **** **** +6487 CelebrantSharess_Charm_Person **** **** **** **** **** **** **** **** +6488 CelebrantSharess_Daze **** **** **** **** **** **** **** **** +6489 CelebrantSharess_Disguise_Self_Radial_Master **** **** **** **** **** **** **** **** +6490 CelebrantSharess_Disguise_Self_Learn **** **** **** **** **** **** **** **** +6491 CelebrantSharess_Disguise_Self_Options **** **** **** **** **** **** **** **** +6492 CelebrantSharess_Disguise_Self_QS1 **** **** **** **** **** **** **** **** +6493 CelebrantSharess_Disguise_Self_QS2 **** **** **** **** **** **** **** **** +6494 CelebrantSharess_Disguise_Self_QS3 **** **** **** **** **** **** **** **** +6495 CelebrantSharess_RAY_OF_HOPE **** **** **** **** **** **** **** **** +6496 CelebrantSharess_Read_Magic **** **** **** **** **** **** **** **** +6497 CelebrantSharess_Remove_Fear **** **** **** **** **** **** **** **** +6498 CelebrantSharess_Sleep **** **** **** **** **** **** **** **** +6499 CelebrantSharess_Tashas_Hideous_Laughter **** **** **** **** **** **** **** **** +6500 CelebrantSharess_Alter_Self_Radial_Master **** **** **** **** **** **** **** **** +6501 CelebrantSharess_Alter_Self_Learn **** **** **** **** **** **** **** **** +6502 CelebrantSharess_Alter_Self_Options **** **** **** **** **** **** **** **** +6503 CelebrantSharess_Alter_Self_QS1 **** **** **** **** **** **** **** **** +6504 CelebrantSharess_Alter_Self_QS2 **** **** **** **** **** **** **** **** +6505 CelebrantSharess_Alter_Self_QS3 **** **** **** **** **** **** **** **** +6506 CelebrantSharess_Calm_Emotions **** **** **** **** **** **** **** **** +6507 CelebrantSharess_Cats_Grace **** **** **** **** **** **** **** **** +6508 CelebrantSharess_Daze_Monster **** **** **** **** **** **** **** **** +6509 CelebrantSharess_Eagle_Splendor **** **** **** **** **** **** **** **** +6510 CelebrantSharess_ELATION **** **** **** **** **** **** **** **** +6511 CelebrantSharess_Enthrall **** **** **** **** **** **** **** **** +6512 CelebrantSharess_Heroism **** **** **** **** **** **** **** **** +6513 CelebrantSharess_Hold_Person **** **** **** **** **** **** **** **** +6514 CelebrantSharess_Rage **** **** **** **** **** **** **** **** +6515 CelebrantSharess_Scare **** **** **** **** **** **** **** **** +6516 CelebrantSharess_Charm_Monster **** **** **** **** **** **** **** **** +6517 CelebrantSharess_Confusion **** **** **** **** **** **** **** **** +6518 CelebrantSharess_CrushingDespair **** **** **** **** **** **** **** **** +6519 CelebrantSharess_DeepSlumber **** **** **** **** **** **** **** **** +6520 CelebrantSharess_Fear **** **** **** **** **** **** **** **** +6521 CelebrantSharess_GLIBNESS **** **** **** **** **** **** **** **** +6522 CelebrantSharess_Slow **** **** **** **** **** **** **** **** +6523 CelebrantSharess_War_Cry **** **** **** **** **** **** **** **** +6524 CelebrantSharess_BreakEnchantment **** **** **** **** **** **** **** **** +6525 CelebrantSharess_Dominate_Person **** **** **** **** **** **** **** **** +6526 CelebrantSharess_Hold_Monster **** **** **** **** **** **** **** **** +6527 CelebrantSharess_RAINBOW_PATTERN **** **** **** **** **** **** **** **** +6528 CultistShatteredP_Endure_Elements **** **** **** **** **** **** **** **** +6529 CultistShatteredP_Exteneded_Endure_Elements **** **** **** **** **** **** **** **** +6530 CultistShatteredP_Silent_Endure_Elements **** **** **** **** **** **** **** **** +6531 CultistShatteredP_Still_Endure_Elements **** **** **** **** **** **** **** **** +6532 CultistShatteredP_Protection_from_Chaos **** **** **** **** **** **** **** **** +6533 CultistShatteredP_Exteneded_Protection_from_Chaos **** **** **** **** **** **** **** **** +6534 CultistShatteredP_Silent_Protection_from_Chaos **** **** **** **** **** **** **** **** +6535 CultistShatteredP_Still_Protection_from_Chaos **** **** **** **** **** **** **** **** +6536 CultistShatteredP_Protection_from_Evil **** **** **** **** **** **** **** **** +6537 CultistShatteredP_Exteneded_Protection_from_Evil **** **** **** **** **** **** **** **** +6538 CultistShatteredP_Silent_Protection_from_Evil **** **** **** **** **** **** **** **** +6539 CultistShatteredP_Still_Protection_from_Evil **** **** **** **** **** **** **** **** +6540 CultistShatteredP_Protection_from_Good **** **** **** **** **** **** **** **** +6541 CultistShatteredP_Exteneded_Protection_from_Good **** **** **** **** **** **** **** **** +6542 CultistShatteredP_Silent_Protection_from_Good **** **** **** **** **** **** **** **** +6543 CultistShatteredP_Still_Protection_from_Good **** **** **** **** **** **** **** **** +6544 CultistShatteredP_Protection_from_Law **** **** **** **** **** **** **** **** +6545 CultistShatteredP_Exteneded_Protection_from_Law **** **** **** **** **** **** **** **** +6546 CultistShatteredP_Silent_Protection_from_Law **** **** **** **** **** **** **** **** +6547 CultistShatteredP_Still_Protection_from_Law **** **** **** **** **** **** **** **** +6548 CultistShatteredP_Shield **** **** **** **** **** **** **** **** +6549 CultistShatteredP_Exteneded_Shield **** **** **** **** **** **** **** **** +6550 CultistShatteredP_Silent_Shield **** **** **** **** **** **** **** **** +6551 CultistShatteredP_Still_Shield **** **** **** **** **** **** **** **** +6552 CultistShatteredP_Ironguts **** **** **** **** **** **** **** **** +6553 CultistShatteredP_Exteneded_Ironguts **** **** **** **** **** **** **** **** +6554 CultistShatteredP_Silent_Ironguts **** **** **** **** **** **** **** **** +6555 CultistShatteredP_Still_Ironguts **** **** **** **** **** **** **** **** +6556 CultistShatteredP_Lesser_Deflect **** **** **** **** **** **** **** **** +6557 CultistShatteredP_Exteneded_Lesser_Deflect **** **** **** **** **** **** **** **** +6558 CultistShatteredP_Silent_Lesser_Deflect **** **** **** **** **** **** **** **** +6559 CultistShatteredP_TWILIGHT_LUCK **** **** **** **** **** **** **** **** +6560 CultistShatteredP_Exteneded_TWILIGHT_LUCK **** **** **** **** **** **** **** **** +6561 CultistShatteredP_Silent_TWILIGHT_LUCK **** **** **** **** **** **** **** **** +6562 CultistShatteredP_Charm_Person **** **** **** **** **** **** **** **** +6563 CultistShatteredP_Exteneded_Charm_Person **** **** **** **** **** **** **** **** +6564 CultistShatteredP_Silent_Charm_Person **** **** **** **** **** **** **** **** +6565 CultistShatteredP_Still_Charm_Person **** **** **** **** **** **** **** **** +6566 CultistShatteredP_Sleep **** **** **** **** **** **** **** **** +6567 CultistShatteredP_Empowered_Sleep **** **** **** **** **** **** **** **** +6568 CultistShatteredP_Exteneded_Sleep **** **** **** **** **** **** **** **** +6569 CultistShatteredP_Silent_Sleep **** **** **** **** **** **** **** **** +6570 CultistShatteredP_Still_Sleep **** **** **** **** **** **** **** **** +6571 CultistShatteredP_Rouse **** **** **** **** **** **** **** **** +6572 CultistShatteredP_Silent_Rouse **** **** **** **** **** **** **** **** +6573 CultistShatteredP_Still_Rouse **** **** **** **** **** **** **** **** +6574 CultistShatteredP_DRUG_RESISTANCE **** **** **** **** **** **** **** **** +6575 CultistShatteredP_Silent_DRUG_RESISTANCE **** **** **** **** **** **** **** **** +6576 CultistShatteredP_Nybors_Gentle_Reminder **** **** **** **** **** **** **** **** +6577 CultistShatteredP_Exteneded_Nybors_Gentle_Reminder **** **** **** **** **** **** **** **** +6578 CultistShatteredP_Silent_Nybors_Gentle_Reminder **** **** **** **** **** **** **** **** +6579 CultistShatteredP_Still_Nybors_Gentle_Reminder **** **** **** **** **** **** **** **** +6580 CultistShatteredP_Lesser_Dispel **** **** **** **** **** **** **** **** +6581 CultistShatteredP_Silent_Lesser_Dispel **** **** **** **** **** **** **** **** +6582 CultistShatteredP_Still_Lesser_Dispel **** **** **** **** **** **** **** **** +6583 CultistShatteredP_Resist_Elements **** **** **** **** **** **** **** **** +6584 CultistShatteredP_Exteneded_Resist_Elements **** **** **** **** **** **** **** **** +6585 CultistShatteredP_Silent_Resist_Elements **** **** **** **** **** **** **** **** +6586 CultistShatteredP_Still_Resist_Elements **** **** **** **** **** **** **** **** +6587 CultistShatteredP_Deflect **** **** **** **** **** **** **** **** +6588 CultistShatteredP_Exteneded_Deflect **** **** **** **** **** **** **** **** +6589 CultistShatteredP_Silent_Deflect **** **** **** **** **** **** **** **** +6590 CultistShatteredP_ProtectionArrows **** **** **** **** **** **** **** **** +6591 CultistShatteredP_Exteneded_ProtectionArrows **** **** **** **** **** **** **** **** +6592 CultistShatteredP_Silent_ProtectionArrows **** **** **** **** **** **** **** **** +6593 CultistShatteredP_Still_ProtectionArrows **** **** **** **** **** **** **** **** +6594 CultistShatteredP_Dispelling_Touch **** **** **** **** **** **** **** **** +6595 CultistShatteredP_Silent_Dispelling_Touch **** **** **** **** **** **** **** **** +6596 CultistShatteredP_Still_Dispelling_Touch **** **** **** **** **** **** **** **** +6597 CultistShatteredP_UNHEAVENED **** **** **** **** **** **** **** **** +6598 CultistShatteredP_Silent_UNHEAVENED **** **** **** **** **** **** **** **** +6599 CultistShatteredP_Still_UNHEAVENED **** **** **** **** **** **** **** **** +6600 CultistShatteredP_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +6601 CultistShatteredP_Exteneded_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +6602 CultistShatteredP_ObscureObject **** **** **** **** **** **** **** **** +6603 CultistShatteredP_Exteneded_ObscureObject **** **** **** **** **** **** **** **** +6604 CultistShatteredP_Silent_ObscureObject **** **** **** **** **** **** **** **** +6605 CultistShatteredP_Still_ObscureObject **** **** **** **** **** **** **** **** +6606 CultistShatteredP_Tashas_Hideous_Laughter **** **** **** **** **** **** **** **** +6607 CultistShatteredP_Exteneded_Tashas_Hideous_Laughter **** **** **** **** **** **** **** **** +6608 CultistShatteredP_Silent_Tashas_Hideous_Laughter **** **** **** **** **** **** **** **** +6609 CultistShatteredP_Still_Tashas_Hideous_Laughter **** **** **** **** **** **** **** **** +6610 CultistShatteredP_Daze_Monster **** **** **** **** **** **** **** **** +6611 CultistShatteredP_Exteneded_Daze_Monster **** **** **** **** **** **** **** **** +6612 CultistShatteredP_Silent_Daze_Monster **** **** **** **** **** **** **** **** +6613 CultistShatteredP_Still_Daze_Monster **** **** **** **** **** **** **** **** +6614 CultistShatteredP_TouchIdiocy **** **** **** **** **** **** **** **** +6615 CultistShatteredP_Exteneded_TouchIdiocy **** **** **** **** **** **** **** **** +6616 CultistShatteredP_Silent_TouchIdiocy **** **** **** **** **** **** **** **** +6617 CultistShatteredP_Still_TouchIdiocy **** **** **** **** **** **** **** **** +6618 CultistShatteredP_MASOCHISM **** **** **** **** **** **** **** **** +6619 CultistShatteredP_Exteneded_MASOCHISM **** **** **** **** **** **** **** **** +6620 CultistShatteredP_ADDICTION **** **** **** **** **** **** **** **** +6621 CultistShatteredP_ADDICTION_TERRAN_BRANDY **** **** **** **** **** **** **** **** +6622 CultistShatteredP_ADDICTION_MUSHROOM_POWDER **** **** **** **** **** **** **** **** +6623 CultistShatteredP_ADDICTION_VODARE **** **** **** **** **** **** **** **** +6624 CultistShatteredP_ADDICTION_AGONY **** **** **** **** **** **** **** **** +6625 CultistShatteredP_Silent_ADDICTION **** **** **** **** **** **** **** **** +6626 CultistShatteredP_Silent_ADDICTION_TERRAN_BRANDY **** **** **** **** **** **** **** **** +6627 CultistShatteredP_Silent_ADDICTION_MUSHROOM_POWDER **** **** **** **** **** **** **** **** +6628 CultistShatteredP_Silent_ADDICTION_VODARE **** **** **** **** **** **** **** **** +6629 CultistShatteredP_Silent_ADDICTION_AGONY **** **** **** **** **** **** **** **** +6630 CultistShatteredP_Still_ADDICTION **** **** **** **** **** **** **** **** +6631 CultistShatteredP_Still_ADDICTION_TERRAN_BRANDY **** **** **** **** **** **** **** **** +6632 CultistShatteredP_Still_ADDICTION_MUSHROOM_POWDER **** **** **** **** **** **** **** **** +6633 CultistShatteredP_Still_ADDICTION_VODARE **** **** **** **** **** **** **** **** +6634 CultistShatteredP_Still_ADDICTION_AGONY **** **** **** **** **** **** **** **** +6635 CultistShatteredP_Clarity **** **** **** **** **** **** **** **** +6636 CultistShatteredP_Dispel_Magic **** **** **** **** **** **** **** **** +6637 CultistShatteredP_Magic_Circle_against_Chaos **** **** **** **** **** **** **** **** +6638 CultistShatteredP_Magic_Circle_against_Evil **** **** **** **** **** **** **** **** +6639 CultistShatteredP_Magic_Circle_against_Good **** **** **** **** **** **** **** **** +6640 CultistShatteredP_Magic_Circle_against_Law **** **** **** **** **** **** **** **** +6641 CultistShatteredP_Protection_from_Elements **** **** **** **** **** **** **** **** +6642 CultistShatteredP_Energy_Aegis **** **** **** **** **** **** **** **** +6643 CultistShatteredP_Energy_Aegis_Acid **** **** **** **** **** **** **** **** +6644 CultistShatteredP_Energy_Aegis_Cold **** **** **** **** **** **** **** **** +6645 CultistShatteredP_Energy_Aegis_Elec **** **** **** **** **** **** **** **** +6646 CultistShatteredP_Energy_Aegis_Fire **** **** **** **** **** **** **** **** +6647 CultistShatteredP_Energy_Aegis_Sonic **** **** **** **** **** **** **** **** +6648 CultistShatteredP_NONDETECTION **** **** **** **** **** **** **** **** +6649 CultistShatteredP_Hold_Person **** **** **** **** **** **** **** **** +6650 CultistShatteredP_Rage **** **** **** **** **** **** **** **** +6651 CultistShatteredP_DeepSlumber **** **** **** **** **** **** **** **** +6652 CultistShatteredP_EVIL_EYE **** **** **** **** **** **** **** **** +6653 CultistShatteredP_ELATION **** **** **** **** **** **** **** **** +6654 CultistShatteredP_Heroism **** **** **** **** **** **** **** **** +6655 Beguiler_Dancing_Lights **** **** **** **** **** **** **** **** +6656 Beguiler_Daze **** **** **** **** **** **** **** **** +6657 Beguiler_Read_Magic **** **** **** **** **** **** **** **** +6658 Beguiler_Charm_Person **** **** **** **** **** **** **** **** +6659 Beguiler_Color_Spray **** **** **** **** **** **** **** **** +6660 Beguiler_Disguise_Self_Radial_Master **** **** **** **** **** **** **** **** +6661 Beguiler_Disguise_Self_Learn **** **** **** **** **** **** **** **** +6662 Beguiler_Disguise_Self_Options **** **** **** **** **** **** **** **** +6663 Beguiler_Disguise_Self_QS1 **** **** **** **** **** **** **** **** +6664 Beguiler_Disguise_Self_QS2 **** **** **** **** **** **** **** **** +6665 Beguiler_Disguise_Self_QS3 **** **** **** **** **** **** **** **** +6666 Beguiler_DRUG_RESISTANCE **** **** **** **** **** **** **** **** +6667 Beguiler_Expeditious_Retreat **** **** **** **** **** **** **** **** +6668 Beguiler_Mage_Armor **** **** **** **** **** **** **** **** +6669 Beguiler_Nybors_Gentle_Reminder **** **** **** **** **** **** **** **** +6670 Beguiler_Obscuring_Mist **** **** **** **** **** **** **** **** +6671 Beguiler_Rouse **** **** **** **** **** **** **** **** +6672 Beguiler_Sleep **** **** **** **** **** **** **** **** +6673 Beguiler_UndetectableAlignment **** **** **** **** **** **** **** **** +6674 Beguiler_ADDICTION **** **** **** **** **** **** **** **** +6675 Beguiler_ADDICTION_TERRAN_BRANDY **** **** **** **** **** **** **** **** +6676 Beguiler_ADDICTION_MUSHROOM_POWDER **** **** **** **** **** **** **** **** +6677 Beguiler_ADDICTION_VODARE **** **** **** **** **** **** **** **** +6678 Beguiler_ADDICTION_AGONY **** **** **** **** **** **** **** **** +6679 Beguiler_Blindness_and_Deafness **** **** **** **** **** **** **** **** +6680 Beguiler_Blur **** **** **** **** **** **** **** **** +6681 Beguiler_Continual_Flame **** **** **** **** **** **** **** **** +6682 Beguiler_Daze_Monster **** **** **** **** **** **** **** **** +6683 Beguiler_FogCloud **** **** **** **** **** **** **** **** +6684 Beguiler_Ghostly_Visage **** **** **** **** **** **** **** **** +6685 Beguiler_Glitterdust **** **** **** **** **** **** **** **** +6686 Beguiler_Invisibility **** **** **** **** **** **** **** **** +6687 Beguiler_Knock **** **** **** **** **** **** **** **** +6688 Beguiler_MASOCHISM **** **** **** **** **** **** **** **** +6689 Beguiler_MirrorImage **** **** **** **** **** **** **** **** +6690 Beguiler_See_Invisibility **** **** **** **** **** **** **** **** +6691 Beguiler_Shadow_Spray **** **** **** **** **** **** **** **** +6692 Beguiler_Silence **** **** **** **** **** **** **** **** +6693 Beguiler_Tashas_Hideous_Laughter **** **** **** **** **** **** **** **** +6694 Beguiler_TouchIdiocy **** **** **** **** **** **** **** **** +6695 Beguiler_Clairaudience_and_Clairvoyance **** **** **** **** **** **** **** **** +6696 Beguiler_CURSE_OF_THE_PUTRID_HUSK **** **** **** **** **** **** **** **** +6697 Beguiler_DeepSlumber **** **** **** **** **** **** **** **** +6698 Beguiler_Dispel_Magic **** **** **** **** **** **** **** **** +6699 Beguiler_Displacement **** **** **** **** **** **** **** **** +6700 Beguiler_ELATION **** **** **** **** **** **** **** **** +6701 Beguiler_EVIL_EYE **** **** **** **** **** **** **** **** +6702 Beguiler_GLIBNESS **** **** **** **** **** **** **** **** +6703 Beguiler_Halt **** **** **** **** **** **** **** **** +6704 Beguiler_Haste **** **** **** **** **** **** **** **** +6705 Beguiler_Heroism **** **** **** **** **** **** **** **** +6706 Beguiler_Hold_Person **** **** **** **** **** **** **** **** +6707 Beguiler_Invisibility_Sphere **** **** **** **** **** **** **** **** +6708 Beguiler_NONDETECTION **** **** **** **** **** **** **** **** +6709 Beguiler_REALITY_BLIND **** **** **** **** **** **** **** **** +6710 Beguiler_Slow **** **** **** **** **** **** **** **** +6711 Beguiler_Charm_Monster **** **** **** **** **** **** **** **** +6712 Beguiler_Confusion **** **** **** **** **** **** **** **** +6713 Beguiler_CrushingDespair **** **** **** **** **** **** **** **** +6714 Beguiler_Freedom_of_Movement **** **** **** **** **** **** **** **** +6715 Beguiler_Improved_Invisibility **** **** **** **** **** **** **** **** +6716 Beguiler_LocateCreature **** **** **** **** **** **** **** **** +6717 Beguiler_Phantasmal_Killer **** **** **** **** **** **** **** **** +6718 Beguiler_RAINBOW_PATTERN **** **** **** **** **** **** **** **** +6719 Beguiler_Shadow_Conjuration **** **** **** **** **** **** **** **** +6720 Beguiler_SHADOW_CON_Summon_Shadow **** **** **** **** **** **** **** **** +6721 Beguiler_SHADOW_CON_Darkness **** **** **** **** **** **** **** **** +6722 Beguiler_SHADOW_CON_Inivsibility **** **** **** **** **** **** **** **** +6723 Beguiler_SHADOW_CON_Mage_Armor **** **** **** **** **** **** **** **** +6724 Beguiler_SHADOW_CON_Magic_Missile **** **** **** **** **** **** **** **** +6725 Beguiler_SolidFog **** **** **** **** **** **** **** **** +6726 Beguiler_BreakEnchantment **** **** **** **** **** **** **** **** +6727 Beguiler_Dominate_Person **** **** **** **** **** **** **** **** +6728 Beguiler_Feeblemind **** **** **** **** **** **** **** **** +6729 Beguiler_Greater_Shadow_Conjuration **** **** **** **** **** **** **** **** +6730 Beguiler_GR_SHADOW_CON_Summon_Shadow **** **** **** **** **** **** **** **** +6731 Beguiler_GR_SHADOW_CON_Acid_Arrow **** **** **** **** **** **** **** **** +6732 Beguiler_GR_SHADOW_CON_Ghostly_Visage **** **** **** **** **** **** **** **** +6733 Beguiler_GR_SHADOW_CON_Web **** **** **** **** **** **** **** **** +6734 Beguiler_GR_SHADOW_CON_Minor_Globe **** **** **** **** **** **** **** **** +6735 Beguiler_Hold_Monster **** **** **** **** **** **** **** **** +6736 Beguiler_Mind_Fog **** **** **** **** **** **** **** **** +6737 Beguiler_SYMBOL_OF_SLEEP **** **** **** **** **** **** **** **** +6738 Beguiler_Ethereal_Visage **** **** **** **** **** **** **** **** +6739 Beguiler_Greater_Dispelling **** **** **** **** **** **** **** **** +6740 Beguiler_Greater_Heroism **** **** **** **** **** **** **** **** +6741 Beguiler_Mass_Haste **** **** **** **** **** **** **** **** +6742 Beguiler_Mislead **** **** **** **** **** **** **** **** +6743 Beguiler_Repulsion **** **** **** **** **** **** **** **** +6744 Beguiler_Shades **** **** **** **** **** **** **** **** +6745 Beguiler_SHADES_Summon_Shadow **** **** **** **** **** **** **** **** +6746 Beguiler_SHADES_Cone_of_Cold **** **** **** **** **** **** **** **** +6747 Beguiler_SHADES_Fireball **** **** **** **** **** **** **** **** +6748 Beguiler_SHADES_Stoneskin **** **** **** **** **** **** **** **** +6749 Beguiler_SHADES_Wall_of_Fire **** **** **** **** **** **** **** **** +6750 Beguiler_SYMBOL_OF_PERSUASION **** **** **** **** **** **** **** **** +6751 Beguiler_True_Seeing **** **** **** **** **** **** **** **** +6752 Beguiler_Etherealness **** **** **** **** **** **** **** **** +6753 Beguiler_Insanity **** **** **** **** **** **** **** **** +6754 Beguiler_Mass_Hold_Person **** **** **** **** **** **** **** **** +6755 Beguiler_Nybors_Stern_Reproof **** **** **** **** **** **** **** **** +6756 Beguiler_Power_Word_Blind **** **** **** **** **** **** **** **** +6757 Beguiler_Protection_from_Spells **** **** **** **** **** **** **** **** +6758 Beguiler_Shadow_Shield **** **** **** **** **** **** **** **** +6759 Beguiler_Spell_Turning **** **** **** **** **** **** **** **** +6760 Beguiler_SYMBOL_OF_STUNING **** **** **** **** **** **** **** **** +6761 Beguiler_DiscernLocation **** **** **** **** **** **** **** **** +6762 Beguiler_Mass_Blindness_and_Deafness **** **** **** **** **** **** **** **** +6763 Beguiler_Mass_Charm **** **** **** **** **** **** **** **** +6764 Beguiler_Mind_Blank **** **** **** **** **** **** **** **** +6765 Beguiler_Power_Word_Stun **** **** **** **** **** **** **** **** +6766 Beguiler_ScintillatingPattern **** **** **** **** **** **** **** **** +6767 Beguiler_SYMBOL_OF_INSANITY **** **** **** **** **** **** **** **** +6768 Beguiler_Dominate_Monster **** **** **** **** **** **** **** **** +6769 Beguiler_Foresight **** **** **** **** **** **** **** **** +6770 Beguiler_Mass_Hold_Monster **** **** **** **** **** **** **** **** +6771 Beguiler_Power_Word_Kill **** **** **** **** **** **** **** **** +6772 Beguiler_Time_Stop **** **** **** **** **** **** **** **** +6773 Beguiler_Weird **** **** **** **** **** **** **** **** +6774 KnightOfTheChalic_Bless_Water **** **** **** **** **** **** **** **** +6775 KnightOfTheChalic_Silent_Bless_Water **** **** **** **** **** **** **** **** +6776 KnightOfTheChalic_Still_Bless_Water **** **** **** **** **** **** **** **** +6777 KnightOfTheChalic_Bless_Weapon **** **** **** **** **** **** **** **** +6778 KnightOfTheChalic_Exteneded_Bless_Weapon **** **** **** **** **** **** **** **** +6779 KnightOfTheChalic_Silent_Bless_Weapon **** **** **** **** **** **** **** **** +6780 KnightOfTheChalic_Still_Bless_Weapon **** **** **** **** **** **** **** **** +6781 KnightOfTheChalic_Divine_Favor **** **** **** **** **** **** **** **** +6782 KnightOfTheChalic_Exteneded_Divine_Favor **** **** **** **** **** **** **** **** +6783 KnightOfTheChalic_Silent_Divine_Favor **** **** **** **** **** **** **** **** +6784 KnightOfTheChalic_Still_Divine_Favor **** **** **** **** **** **** **** **** +6785 KnightOfTheChalic_Detect_Chaos **** **** **** **** **** **** **** **** +6786 KnightOfTheChalic_Exteneded_Detect_Chaos **** **** **** **** **** **** **** **** +6787 KnightOfTheChalic_Silent_Detect_Chaos **** **** **** **** **** **** **** **** +6788 KnightOfTheChalic_Still_Detect_Chaos **** **** **** **** **** **** **** **** +6789 KnightOfTheChalic_Detect_Evil **** **** **** **** **** **** **** **** +6790 KnightOfTheChalic_Exteneded_Detect_Evil **** **** **** **** **** **** **** **** +6791 KnightOfTheChalic_Silent_Detect_Evil **** **** **** **** **** **** **** **** +6792 KnightOfTheChalic_Still_Detect_Evil **** **** **** **** **** **** **** **** +6793 KnightOfTheChalic_Doom **** **** **** **** **** **** **** **** +6794 KnightOfTheChalic_Exteneded_Doom **** **** **** **** **** **** **** **** +6795 KnightOfTheChalic_Silent_Doom **** **** **** **** **** **** **** **** +6796 KnightOfTheChalic_Still_Doom **** **** **** **** **** **** **** **** +6797 KnightOfTheChalic_Endure_Elements **** **** **** **** **** **** **** **** +6798 KnightOfTheChalic_Exteneded_Endure_Elements **** **** **** **** **** **** **** **** +6799 KnightOfTheChalic_Silent_Endure_Elements **** **** **** **** **** **** **** **** +6800 KnightOfTheChalic_Still_Endure_Elements **** **** **** **** **** **** **** **** +6801 KnightOfTheChalic_Magic_Weapon **** **** **** **** **** **** **** **** +6802 KnightOfTheChalic_Exteneded_Magic_Weapon **** **** **** **** **** **** **** **** +6803 KnightOfTheChalic_Silent_Magic_Weapon **** **** **** **** **** **** **** **** +6804 KnightOfTheChalic_Still_Magic_Weapon **** **** **** **** **** **** **** **** +6805 KnightOfTheChalic_Protection_from_Evil **** **** **** **** **** **** **** **** +6806 KnightOfTheChalic_Exteneded_Protection_from_Evil **** **** **** **** **** **** **** **** +6807 KnightOfTheChalic_Silent_Protection_from_Evil **** **** **** **** **** **** **** **** +6808 KnightOfTheChalic_Still_Protection_from_Evil **** **** **** **** **** **** **** **** +6809 KnightOfTheChalic_Remove_Fear **** **** **** **** **** **** **** **** +6810 KnightOfTheChalic_Exteneded_Remove_Fear **** **** **** **** **** **** **** **** +6811 KnightOfTheChalic_Silent_Remove_Fear **** **** **** **** **** **** **** **** +6812 KnightOfTheChalic_Still_Remove_Fear **** **** **** **** **** **** **** **** +6813 KnightOfTheChalic_Summon_Creature_I **** **** **** **** **** **** **** **** +6814 KnightOfTheChalic_Exteneded_Summon_Creature_I **** **** **** **** **** **** **** **** +6815 KnightOfTheChalic_Silent_Summon_Creature_I **** **** **** **** **** **** **** **** +6816 KnightOfTheChalic_Still_Summon_Creature_I **** **** **** **** **** **** **** **** +6817 KnightOfTheChalic_DIVINE_INSPIRATION **** **** **** **** **** **** **** **** +6818 KnightOfTheChalic_Exteneded_DIVINE_INSPIRATION **** **** **** **** **** **** **** **** +6819 KnightOfTheChalic_TWILIGHT_LUCK **** **** **** **** **** **** **** **** +6820 KnightOfTheChalic_Exteneded_TWILIGHT_LUCK **** **** **** **** **** **** **** **** +6821 KnightOfTheChalic_Silent_TWILIGHT_LUCK **** **** **** **** **** **** **** **** +6822 KnightOfTheChalic_LANTERN_LIGHT **** **** **** **** **** **** **** **** +6823 KnightOfTheChalic_Empowered_LANTERN_LIGHT **** **** **** **** **** **** **** **** +6824 KnightOfTheChalic_Maximized_LANTERN_LIGHT **** **** **** **** **** **** **** **** +6825 KnightOfTheChalic_Still_LANTERN_LIGHT **** **** **** **** **** **** **** **** +6826 KnightOfTheChalic_Aid **** **** **** **** **** **** **** **** +6827 KnightOfTheChalic_Empowered_Aid **** **** **** **** **** **** **** **** +6828 KnightOfTheChalic_Exteneded_Aid **** **** **** **** **** **** **** **** +6829 KnightOfTheChalic_Silent_Aid **** **** **** **** **** **** **** **** +6830 KnightOfTheChalic_Still_Aid **** **** **** **** **** **** **** **** +6831 KnightOfTheChalic_Bulls_Strength **** **** **** **** **** **** **** **** +6832 KnightOfTheChalic_Empowered_Bulls_Strength **** **** **** **** **** **** **** **** +6833 KnightOfTheChalic_Exteneded_Bulls_Strength **** **** **** **** **** **** **** **** +6834 KnightOfTheChalic_Silent_Bulls_Strength **** **** **** **** **** **** **** **** +6835 KnightOfTheChalic_Still_Bulls_Strength **** **** **** **** **** **** **** **** +6836 KnightOfTheChalic_Consecrated_Aura **** **** **** **** **** **** **** **** +6837 KnightOfTheChalic_Exteneded_Consecrated_Aura **** **** **** **** **** **** **** **** +6838 KnightOfTheChalic_Silent_Consecrated_Aura **** **** **** **** **** **** **** **** +6839 KnightOfTheChalic_Still_Consecrated_Aura **** **** **** **** **** **** **** **** +6840 KnightOfTheChalic_Endurance **** **** **** **** **** **** **** **** +6841 KnightOfTheChalic_Empowered_Endurance **** **** **** **** **** **** **** **** +6842 KnightOfTheChalic_Exteneded_Endurance **** **** **** **** **** **** **** **** +6843 KnightOfTheChalic_Silent_Endurance **** **** **** **** **** **** **** **** +6844 KnightOfTheChalic_Still_Endurance **** **** **** **** **** **** **** **** +6845 KnightOfTheChalic_Resist_Elements **** **** **** **** **** **** **** **** +6846 KnightOfTheChalic_Exteneded_Resist_Elements **** **** **** **** **** **** **** **** +6847 KnightOfTheChalic_Silent_Resist_Elements **** **** **** **** **** **** **** **** +6848 KnightOfTheChalic_Still_Resist_Elements **** **** **** **** **** **** **** **** +6849 KnightOfTheChalic_Sound_Burst **** **** **** **** **** **** **** **** +6850 KnightOfTheChalic_Silent_Sound_Burst **** **** **** **** **** **** **** **** +6851 KnightOfTheChalic_Still_Sound_Burst **** **** **** **** **** **** **** **** +6852 KnightOfTheChalic_Summon_Creature_II **** **** **** **** **** **** **** **** +6853 KnightOfTheChalic_Exteneded_Summon_Creature_II **** **** **** **** **** **** **** **** +6854 KnightOfTheChalic_Silent_Summon_Creature_II **** **** **** **** **** **** **** **** +6855 KnightOfTheChalic_Still_Summon_Creature_II **** **** **** **** **** **** **** **** +6856 KnightOfTheChalic_UndetectableAlignment **** **** **** **** **** **** **** **** +6857 KnightOfTheChalic_Exteneded_UndetectableAlignment **** **** **** **** **** **** **** **** +6858 KnightOfTheChalic_Silent_UndetectableAlignment **** **** **** **** **** **** **** **** +6859 KnightOfTheChalic_Still_UndetectableAlignment **** **** **** **** **** **** **** **** +6860 KnightOfTheChalic_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +6861 KnightOfTheChalic_Empowered_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +6862 KnightOfTheChalic_Silent_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +6863 KnightOfTheChalic_Still_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +6864 KnightOfTheChalic_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +6865 KnightOfTheChalic_Exteneded_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +6866 KnightOfTheChalic_Dispel_Magic **** **** **** **** **** **** **** **** +6867 KnightOfTheChalic_Silent_Dispel_Magic **** **** **** **** **** **** **** **** +6868 KnightOfTheChalic_Still_Dispel_Magic **** **** **** **** **** **** **** **** +6869 KnightOfTheChalic_Summon_Creature_III **** **** **** **** **** **** **** **** +6870 KnightOfTheChalic_Exteneded_Summon_Creature_III **** **** **** **** **** **** **** **** +6871 KnightOfTheChalic_Silent_Summon_Creature_III **** **** **** **** **** **** **** **** +6872 KnightOfTheChalic_Still_Summon_Creature_III **** **** **** **** **** **** **** **** +6873 KnightOfTheChalic_Invisibility_Purge **** **** **** **** **** **** **** **** +6874 KnightOfTheChalic_Exteneded_Invisibility_Purge **** **** **** **** **** **** **** **** +6875 KnightOfTheChalic_Silent_Invisibility_Purge **** **** **** **** **** **** **** **** +6876 KnightOfTheChalic_Still_Invisibility_Purge **** **** **** **** **** **** **** **** +6877 KnightOfTheChalic_Magic_Circle_against_Evil **** **** **** **** **** **** **** **** +6878 KnightOfTheChalic_Exteneded_Magic_Circle_against_Evil **** **** **** **** **** **** **** **** +6879 KnightOfTheChalic_Silent_Magic_Circle_against_Evil **** **** **** **** **** **** **** **** +6880 KnightOfTheChalic_Still_Magic_Circle_against_Evil **** **** **** **** **** **** **** **** +6881 KnightOfTheChalic_Magic_Vestment **** **** **** **** **** **** **** **** +6882 KnightOfTheChalic_Exteneded_Magic_Vestment **** **** **** **** **** **** **** **** +6883 KnightOfTheChalic_Silent_Magic_Vestment **** **** **** **** **** **** **** **** +6884 KnightOfTheChalic_Still_Magic_Vestment **** **** **** **** **** **** **** **** +6885 KnightOfTheChalic_Prayer **** **** **** **** **** **** **** **** +6886 KnightOfTheChalic_Exteneded_Prayer **** **** **** **** **** **** **** **** +6887 KnightOfTheChalic_Silent_Prayer **** **** **** **** **** **** **** **** +6888 KnightOfTheChalic_Still_Prayer **** **** **** **** **** **** **** **** +6889 KnightOfTheChalic_Protection_from_Elements **** **** **** **** **** **** **** **** +6890 KnightOfTheChalic_Exteneded_Protection_from_Elements **** **** **** **** **** **** **** **** +6891 KnightOfTheChalic_Silent_Protection_from_Elements **** **** **** **** **** **** **** **** +6892 KnightOfTheChalic_Still_Protection_from_Elements **** **** **** **** **** **** **** **** +6893 KnightOfTheChalic_Searing_Light **** **** **** **** **** **** **** **** +6894 KnightOfTheChalic_Silent_Searing_Light **** **** **** **** **** **** **** **** +6895 KnightOfTheChalic_Still_Searing_Light **** **** **** **** **** **** **** **** +6896 KnightOfTheChalic_Shout **** **** **** **** **** **** **** **** +6897 KnightOfTheChalic_Silent_Shout **** **** **** **** **** **** **** **** +6898 KnightOfTheChalic_BRILLIANT_EMANATION **** **** **** **** **** **** **** **** +6899 KnightOfTheChalic_Exteneded_BRILLIANT_EMANATION **** **** **** **** **** **** **** **** +6900 KnightOfTheChalic_HAMMER_OF_RIGHTEOUSNESS **** **** **** **** **** **** **** **** +6901 KnightOfTheChalic_Silent_HAMMER_OF_RIGHTEOUSNESS **** **** **** **** **** **** **** **** +6902 KnightOfTheChalic_Still_HAMMER_OF_RIGHTEOUSNESS **** **** **** **** **** **** **** **** +6903 KnightOfTheChalic_Dimensional_Anchor **** **** **** **** **** **** **** **** +6904 KnightOfTheChalic_Dismissal **** **** **** **** **** **** **** **** +6905 KnightOfTheChalic_Hammer_of_the_Gods **** **** **** **** **** **** **** **** +6906 KnightOfTheChalic_Greater_Magic_Weapon **** **** **** **** **** **** **** **** +6907 KnightOfTheChalic_Lesser_Planar_Ally **** **** **** **** **** **** **** **** +6908 KnightOfTheChalic_DIAMOND_SPRAY **** **** **** **** **** **** **** **** +6909 KnightOfTheChalic_SUNMANTLE **** **** **** **** **** **** **** **** +6910 KnightOfTheChalic_GREATER_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +6911 Vigilant_Blur **** **** **** **** **** **** **** **** +6912 Vigilant_Exteneded_Blur **** **** **** **** **** **** **** **** +6913 Vigilant_Silent_Blur **** **** **** **** **** **** **** **** +6914 Vigilant_Expeditious_Retreat **** **** **** **** **** **** **** **** +6915 Vigilant_Exteneded_Expeditious_Retreat **** **** **** **** **** **** **** **** +6916 Vigilant_Silent_Expeditious_Retreat **** **** **** **** **** **** **** **** +6917 Vigilant_Still_Expeditious_Retreat **** **** **** **** **** **** **** **** +6918 Vigilant_LANTERN_LIGHT **** **** **** **** **** **** **** **** +6919 Vigilant_Empowered_LANTERN_LIGHT **** **** **** **** **** **** **** **** +6920 Vigilant_Maximized_LANTERN_LIGHT **** **** **** **** **** **** **** **** +6921 Vigilant_Still_LANTERN_LIGHT **** **** **** **** **** **** **** **** +6922 Vigilant_Resist_Elements **** **** **** **** **** **** **** **** +6923 Vigilant_Exteneded_Resist_Elements **** **** **** **** **** **** **** **** +6924 Vigilant_Silent_Resist_Elements **** **** **** **** **** **** **** **** +6925 Vigilant_Still_Resist_Elements **** **** **** **** **** **** **** **** +6926 Vigilant_TWILIGHT_LUCK **** **** **** **** **** **** **** **** +6927 Vigilant_Exteneded_TWILIGHT_LUCK **** **** **** **** **** **** **** **** +6928 Vigilant_Silent_TWILIGHT_LUCK **** **** **** **** **** **** **** **** +6929 Vigilant_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +6930 Vigilant_Empowered_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +6931 Vigilant_Silent_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +6932 Vigilant_Still_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +6933 Vigilant_Detect_Chaos **** **** **** **** **** **** **** **** +6934 Vigilant_Exteneded_Detect_Chaos **** **** **** **** **** **** **** **** +6935 Vigilant_Silent_Detect_Chaos **** **** **** **** **** **** **** **** +6936 Vigilant_Still_Detect_Chaos **** **** **** **** **** **** **** **** +6937 Vigilant_Detect_Evil **** **** **** **** **** **** **** **** +6938 Vigilant_Exteneded_Detect_Evil **** **** **** **** **** **** **** **** +6939 Vigilant_Silent_Detect_Evil **** **** **** **** **** **** **** **** +6940 Vigilant_Still_Detect_Evil **** **** **** **** **** **** **** **** +6941 Vigilant_Detect_Good **** **** **** **** **** **** **** **** +6942 Vigilant_Exteneded_Detect_Good **** **** **** **** **** **** **** **** +6943 Vigilant_Silent_Detect_Good **** **** **** **** **** **** **** **** +6944 Vigilant_Still_Detect_Good **** **** **** **** **** **** **** **** +6945 Vigilant_Detect_Law **** **** **** **** **** **** **** **** +6946 Vigilant_Exteneded_Detect_Law **** **** **** **** **** **** **** **** +6947 Vigilant_Silent_Detect_Law **** **** **** **** **** **** **** **** +6948 Vigilant_Still_Detect_Law **** **** **** **** **** **** **** **** +6949 Vigilant_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +6950 Vigilant_Exteneded_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +6951 Vigilant_Protection_from_Elements **** **** **** **** **** **** **** **** +6952 Vigilant_Exteneded_Protection_from_Elements **** **** **** **** **** **** **** **** +6953 Vigilant_Silent_Protection_from_Elements **** **** **** **** **** **** **** **** +6954 Vigilant_Still_Protection_from_Elements **** **** **** **** **** **** **** **** +6955 Vigilant_Snare **** **** **** **** **** **** **** **** +6956 Vigilant_Silent_Snare **** **** **** **** **** **** **** **** +6957 Vigilant_Still_Snare **** **** **** **** **** **** **** **** +6958 Vigilant_Silence **** **** **** **** **** **** **** **** +6959 Vigilant_Exteneded_Silence **** **** **** **** **** **** **** **** +6960 Vigilant_Silent_Silence **** **** **** **** **** **** **** **** +6961 Vigilant_Still_Silence **** **** **** **** **** **** **** **** +6962 Vigilant_BRILLIANT_EMANATION **** **** **** **** **** **** **** **** +6963 Vigilant_Exteneded_BRILLIANT_EMANATION **** **** **** **** **** **** **** **** +6964 Vigilant_Endurance **** **** **** **** **** **** **** **** +6965 Vigilant_Exteneded_Endurance **** **** **** **** **** **** **** **** +6966 Vigilant_Silent_Endurance **** **** **** **** **** **** **** **** +6967 Vigilant_Still_Endurance **** **** **** **** **** **** **** **** +6968 Vigilant_HAMMER_OF_RIGHTEOUSNESS **** **** **** **** **** **** **** **** +6969 Vigilant_Silent_HAMMER_OF_RIGHTEOUSNESS **** **** **** **** **** **** **** **** +6970 Vigilant_Still_HAMMER_OF_RIGHTEOUSNESS **** **** **** **** **** **** **** **** +6971 Vigilant_Neutralize_Poison **** **** **** **** **** **** **** **** +6972 Vigilant_Silent_Neutralize_Poison **** **** **** **** **** **** **** **** +6973 Vigilant_Still_Neutralize_Poison **** **** **** **** **** **** **** **** +6974 Vigilant_Remove_Disease **** **** **** **** **** **** **** **** +6975 Vigilant_Silent_Remove_Disease **** **** **** **** **** **** **** **** +6976 Vigilant_Still_Remove_Disease **** **** **** **** **** **** **** **** +6977 Vigilant_Spike_Growth **** **** **** **** **** **** **** **** +6978 Vigilant_Exteneded_Spike_Growth **** **** **** **** **** **** **** **** +6979 Vigilant_Silent_Spike_Growth **** **** **** **** **** **** **** **** +6980 Vigilant_Still_Spike_Growth **** **** **** **** **** **** **** **** +6981 Vigilant_DIAMOND_SPRAY **** **** **** **** **** **** **** **** +6982 Vigilant_Freedom_of_Movement **** **** **** **** **** **** **** **** +6983 Vigilant_GREATER_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +6984 Vigilant_RepelVermin **** **** **** **** **** **** **** **** +6985 Vigilant_SUNMANTLE **** **** **** **** **** **** **** **** +6986 Vassal_Shield_of_Faith **** **** **** **** **** **** **** **** +6987 Vassal_Exteneded_Shield_of_Faith **** **** **** **** **** **** **** **** +6988 Vassal_Silent_Shield_of_Faith **** **** **** **** **** **** **** **** +6989 Vassal_Still_Shield_of_Faith **** **** **** **** **** **** **** **** +6990 Vassal_Protection_from_Evil **** **** **** **** **** **** **** **** +6991 Vassal_Exteneded_Protection_from_Evil **** **** **** **** **** **** **** **** +6992 Vassal_Silent_Protection_from_Evil **** **** **** **** **** **** **** **** +6993 Vassal_Still_Protection_from_Evil **** **** **** **** **** **** **** **** +6994 Vassal_Endure_Elements **** **** **** **** **** **** **** **** +6995 Vassal_Exteneded_Endure_Elements **** **** **** **** **** **** **** **** +6996 Vassal_Silent_Endure_Elements **** **** **** **** **** **** **** **** +6997 Vassal_Still_Endure_Elements **** **** **** **** **** **** **** **** +6998 Vassal_Divine_Favor **** **** **** **** **** **** **** **** +6999 Vassal_Exteneded_Divine_Favor **** **** **** **** **** **** **** **** +7000 Vassal_Silent_Divine_Favor **** **** **** **** **** **** **** **** +7001 Vassal_Still_Divine_Favor **** **** **** **** **** **** **** **** +7002 Vassal_Bless_Weapon **** **** **** **** **** **** **** **** +7003 Vassal_Exteneded_Bless_Weapon **** **** **** **** **** **** **** **** +7004 Vassal_Silent_Bless_Weapon **** **** **** **** **** **** **** **** +7005 Vassal_Still_Bless_Weapon **** **** **** **** **** **** **** **** +7006 Vassal_Bless **** **** **** **** **** **** **** **** +7007 Vassal_Exteneded_Bless **** **** **** **** **** **** **** **** +7008 Vassal_Silent_Bless **** **** **** **** **** **** **** **** +7009 Vassal_Still_Bless **** **** **** **** **** **** **** **** +7010 Vassal_TWILIGHT_LUCK **** **** **** **** **** **** **** **** +7011 Vassal_Exteneded_TWILIGHT_LUCK **** **** **** **** **** **** **** **** +7012 Vassal_Silent_TWILIGHT_LUCK **** **** **** **** **** **** **** **** +7013 Vassal_LANTERN_LIGHT **** **** **** **** **** **** **** **** +7014 Vassal_Empowered_LANTERN_LIGHT **** **** **** **** **** **** **** **** +7015 Vassal_Maximized_LANTERN_LIGHT **** **** **** **** **** **** **** **** +7016 Vassal_Still_LANTERN_LIGHT **** **** **** **** **** **** **** **** +7017 Vassal_Protection_from_Elements **** **** **** **** **** **** **** **** +7018 Vassal_Exteneded_Protection_from_Elements **** **** **** **** **** **** **** **** +7019 Vassal_Silent_Protection_from_Elements **** **** **** **** **** **** **** **** +7020 Vassal_Still_Protection_from_Elements **** **** **** **** **** **** **** **** +7021 Vassal_Bulls_Strength **** **** **** **** **** **** **** **** +7022 Vassal_Empowered_Bulls_Strength **** **** **** **** **** **** **** **** +7023 Vassal_Exteneded_Bulls_Strength **** **** **** **** **** **** **** **** +7024 Vassal_Silent_Bulls_Strength **** **** **** **** **** **** **** **** +7025 Vassal_Still_Bulls_Strength **** **** **** **** **** **** **** **** +7026 Vassal_Alter_Self_Radial_Master **** **** **** **** **** **** **** **** +7027 Vassal_Alter_Self_Learn **** **** **** **** **** **** **** **** +7028 Vassal_Alter_Self_Options **** **** **** **** **** **** **** **** +7029 Vassal_Alter_Self_QS1 **** **** **** **** **** **** **** **** +7030 Vassal_Alter_Self_QS2 **** **** **** **** **** **** **** **** +7031 Vassal_Alter_Self_QS3 **** **** **** **** **** **** **** **** +7032 Vassal_Exteneded_Alter_Self_Radial_Master **** **** **** **** **** **** **** **** +7033 Vassal_Exteneded_Alter_Self_Learn **** **** **** **** **** **** **** **** +7034 Vassal_Exteneded_Alter_Self_Options **** **** **** **** **** **** **** **** +7035 Vassal_Exteneded_Alter_Self_QS1 **** **** **** **** **** **** **** **** +7036 Vassal_Exteneded_Alter_Self_QS2 **** **** **** **** **** **** **** **** +7037 Vassal_Exteneded_Alter_Self_QS3 **** **** **** **** **** **** **** **** +7038 Vassal_Silent_Alter_Self_Radial_Master **** **** **** **** **** **** **** **** +7039 Vassal_Silent_Alter_Self_Learn **** **** **** **** **** **** **** **** +7040 Vassal_Silent_Alter_Self_Options **** **** **** **** **** **** **** **** +7041 Vassal_Silent_Alter_Self_QS1 **** **** **** **** **** **** **** **** +7042 Vassal_Silent_Alter_Self_QS2 **** **** **** **** **** **** **** **** +7043 Vassal_Silent_Alter_Self_QS3 **** **** **** **** **** **** **** **** +7044 Vassal_Still_Alter_Self_Radial_Master **** **** **** **** **** **** **** **** +7045 Vassal_Still_Alter_Self_Learn **** **** **** **** **** **** **** **** +7046 Vassal_Still_Alter_Self_Options **** **** **** **** **** **** **** **** +7047 Vassal_Still_Alter_Self_QS1 **** **** **** **** **** **** **** **** +7048 Vassal_Still_Alter_Self_QS2 **** **** **** **** **** **** **** **** +7049 Vassal_Still_Alter_Self_QS3 **** **** **** **** **** **** **** **** +7050 Vassal_Endurance **** **** **** **** **** **** **** **** +7051 Vassal_Empowered_Endurance **** **** **** **** **** **** **** **** +7052 Vassal_Exteneded_Endurance **** **** **** **** **** **** **** **** +7053 Vassal_Silent_Endurance **** **** **** **** **** **** **** **** +7054 Vassal_Still_Endurance **** **** **** **** **** **** **** **** +7055 Vassal_ShieldOther **** **** **** **** **** **** **** **** +7056 Vassal_Exteneded_ShieldOther **** **** **** **** **** **** **** **** +7057 Vassal_Silent_ShieldOther **** **** **** **** **** **** **** **** +7058 Vassal_Still_ShieldOther **** **** **** **** **** **** **** **** +7059 Vassal_UndetectableAlignment **** **** **** **** **** **** **** **** +7060 Vassal_Exteneded_UndetectableAlignment **** **** **** **** **** **** **** **** +7061 Vassal_Silent_UndetectableAlignment **** **** **** **** **** **** **** **** +7062 Vassal_Still_UndetectableAlignment **** **** **** **** **** **** **** **** +7063 Vassal_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +7064 Vassal_Empowered_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +7065 Vassal_Silent_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +7066 Vassal_Still_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +7067 Vassal_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +7068 Vassal_Exteneded_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +7069 Vassal_Searing_Light **** **** **** **** **** **** **** **** +7070 Vassal_Silent_Searing_Light **** **** **** **** **** **** **** **** +7071 Vassal_Still_Searing_Light **** **** **** **** **** **** **** **** +7072 Vassal_Resist_Elements **** **** **** **** **** **** **** **** +7073 Vassal_Exteneded_Resist_Elements **** **** **** **** **** **** **** **** +7074 Vassal_Silent_Resist_Elements **** **** **** **** **** **** **** **** +7075 Vassal_Still_Resist_Elements **** **** **** **** **** **** **** **** +7076 Vassal_Magic_Circle_against_Evil **** **** **** **** **** **** **** **** +7077 Vassal_Exteneded_Magic_Circle_against_Evil **** **** **** **** **** **** **** **** +7078 Vassal_Silent_Magic_Circle_against_Evil **** **** **** **** **** **** **** **** +7079 Vassal_Still_Magic_Circle_against_Evil **** **** **** **** **** **** **** **** +7080 Vassal_BRILLIANT_EMANATION **** **** **** **** **** **** **** **** +7081 Vassal_Exteneded_BRILLIANT_EMANATION **** **** **** **** **** **** **** **** +7082 Vassal_HAMMER_OF_RIGHTEOUSNESS **** **** **** **** **** **** **** **** +7083 Vassal_Silent_HAMMER_OF_RIGHTEOUSNESS **** **** **** **** **** **** **** **** +7084 Vassal_Still_HAMMER_OF_RIGHTEOUSNESS **** **** **** **** **** **** **** **** +7085 Vassal_Holy_Sword **** **** **** **** **** **** **** **** +7086 Vassal_Divine_Power **** **** **** **** **** **** **** **** +7087 Vassal_DIAMOND_SPRAY **** **** **** **** **** **** **** **** +7088 Vassal_SUNMANTLE **** **** **** **** **** **** **** **** +7089 Vassal_GREATER_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +7090 SublimeChord_ABYSSAL_MIGHT **** **** **** **** **** **** **** **** +7091 SublimeChord_Acid_Orb **** **** **** **** **** **** **** **** +7092 SublimeChord_ArcaneEye **** **** **** **** **** **** **** **** +7093 SublimeChord_Bestow_Curse **** **** **** **** **** **** **** **** +7094 SublimeChord_Blast_of_Flame **** **** **** **** **** **** **** **** +7095 SublimeChord_BreakEnchantment **** **** **** **** **** **** **** **** +7096 SublimeChord_Channeled_Pyroburst **** **** **** **** **** **** **** **** +7097 SublimeChord_Channeled_Pyroburst_Swift **** **** **** **** **** **** **** **** +7098 SublimeChord_Channeled_Pyroburst_Standard **** **** **** **** **** **** **** **** +7099 SublimeChord_Channeled_Pyroburst_Full **** **** **** **** **** **** **** **** +7100 SublimeChord_Channeled_Pyroburst_Two **** **** **** **** **** **** **** **** +7101 SublimeChord_Charm_Monster **** **** **** **** **** **** **** **** +7102 SublimeChord_Cold_Orb **** **** **** **** **** **** **** **** +7103 SublimeChord_Confusion **** **** **** **** **** **** **** **** +7104 SublimeChord_Contagion **** **** **** **** **** **** **** **** +7105 SublimeChord_CrushingDespair **** **** **** **** **** **** **** **** +7106 SublimeChord_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +7107 SublimeChord_DAMNING_DARKNESS **** **** **** **** **** **** **** **** +7108 SublimeChord_DANCING_WEB **** **** **** **** **** **** **** **** +7109 SublimeChord_DetectScrying **** **** **** **** **** **** **** **** +7110 SublimeChord_Dimensional_Anchor **** **** **** **** **** **** **** **** +7111 SublimeChord_DimensionDoor_RadialMaster **** **** **** **** **** **** **** **** +7112 SublimeChord_DimensionDoor_SelfOnly **** **** **** **** **** **** **** **** +7113 SublimeChord_DimensionDoor_Party **** **** **** **** **** **** **** **** +7114 SublimeChord_DimensionDoor_DirDist_SelfOnly **** **** **** **** **** **** **** **** +7115 SublimeChord_DimensionDoor_DirDist_Party **** **** **** **** **** **** **** **** +7116 SublimeChord_Dismissal **** **** **** **** **** **** **** **** +7117 SublimeChord_Dominate_Person **** **** **** **** **** **** **** **** +7118 SublimeChord_Doom_Scarabs **** **** **** **** **** **** **** **** +7119 SublimeChord_Electric_Orb **** **** **** **** **** **** **** **** +7120 SublimeChord_Elemental_Shield **** **** **** **** **** **** **** **** +7121 SublimeChord_Enervation **** **** **** **** **** **** **** **** +7122 SublimeChord_Evards_Black_Tentacles **** **** **** **** **** **** **** **** +7123 SublimeChord_Fear **** **** **** **** **** **** **** **** +7124 SublimeChord_Fire_Orb **** **** **** **** **** **** **** **** +7125 SublimeChord_FireTrap **** **** **** **** **** **** **** **** +7126 SublimeChord_Greater_Resistance **** **** **** **** **** **** **** **** +7127 SublimeChord_GRIM_REVENGE **** **** **** **** **** **** **** **** +7128 SublimeChord_Hold_Monster **** **** **** **** **** **** **** **** +7129 SublimeChord_Ilyykurs_Mantle **** **** **** **** **** **** **** **** +7130 SublimeChord_Improved_Invisibility **** **** **** **** **** **** **** **** +7131 SublimeChord_Isaacs_Lesser_Missile_Storm **** **** **** **** **** **** **** **** +7132 SublimeChord_Legend_Lore **** **** **** **** **** **** **** **** +7133 SublimeChord_Lesser_Spell_Breach **** **** **** **** **** **** **** **** +7134 SublimeChord_LIQUID_PAIN **** **** **** **** **** **** **** **** +7135 SublimeChord_LocateCreature **** **** **** **** **** **** **** **** +7136 SublimeChord_Lower_Spell_Resistance **** **** **** **** **** **** **** **** +7137 SublimeChord_MASS_ENLARGE_PERSON **** **** **** **** **** **** **** **** +7138 SublimeChord_MASS_REDUCE_PERSON **** **** **** **** **** **** **** **** +7139 SublimeChord_Mass_Ultravision **** **** **** **** **** **** **** **** +7140 SublimeChord_Minor_Globe_of_Invulnerability **** **** **** **** **** **** **** **** +7141 SublimeChord_Necrotic_Domination **** **** **** **** **** **** **** **** +7142 SublimeChord_Neutralize_Poison **** **** **** **** **** **** **** **** +7143 SublimeChord_OrbOfForce **** **** **** **** **** **** **** **** +7144 SublimeChord_Otilukes_Resilient_Sphere **** **** **** **** **** **** **** **** +7145 SublimeChord_Phantasmal_Killer **** **** **** **** **** **** **** **** +7146 SublimeChord_PnP_FireShield **** **** **** **** **** **** **** **** +7147 SublimeChord_PnP_FireShieldRed **** **** **** **** **** **** **** **** +7148 SublimeChord_PnPFireShieldBlue **** **** **** **** **** **** **** **** +7149 SublimeChord_Polymorph_Self **** **** **** **** **** **** **** **** +7150 SublimeChord_Polymorph_GIANT_SPIDER **** **** **** **** **** **** **** **** +7151 SublimeChord_Polymorph_TROLL **** **** **** **** **** **** **** **** +7152 SublimeChord_Polymorph_UMBER_HULK **** **** **** **** **** **** **** **** +7153 SublimeChord_Polymorph_PIXIE **** **** **** **** **** **** **** **** +7154 SublimeChord_Polymorph_ZOMBIE **** **** **** **** **** **** **** **** +7155 SublimeChord_RAINBOW_PATTERN **** **** **** **** **** **** **** **** +7156 SublimeChord_Remove_Blindness_and_Deafness **** **** **** **** **** **** **** **** +7157 SublimeChord_Remove_Curse **** **** **** **** **** **** **** **** +7158 SublimeChord_RepelVermin **** **** **** **** **** **** **** **** +7159 SublimeChord_Scrying **** **** **** **** **** **** **** **** +7160 SublimeChord_SerpentArrows **** **** **** **** **** **** **** **** +7161 SublimeChord_Shadow_Conjuration **** **** **** **** **** **** **** **** +7162 SublimeChord_SHADOW_CON_Summon_Shadow **** **** **** **** **** **** **** **** +7163 SublimeChord_SHADOW_CON_Darkness **** **** **** **** **** **** **** **** +7164 SublimeChord_SHADOW_CON_Inivsibility **** **** **** **** **** **** **** **** +7165 SublimeChord_SHADOW_CON_Mage_Armor **** **** **** **** **** **** **** **** +7166 SublimeChord_SHADOW_CON_Magic_Missile **** **** **** **** **** **** **** **** +7167 SublimeChord_Shout **** **** **** **** **** **** **** **** +7168 SublimeChord_Sinsaburs_Baleful_Bolt **** **** **** **** **** **** **** **** +7169 SublimeChord_Slashing_Dispel **** **** **** **** **** **** **** **** +7170 SublimeChord_SolidFog **** **** **** **** **** **** **** **** +7171 SublimeChord_Sonic_Orb **** **** **** **** **** **** **** **** +7172 SublimeChord_Stoneskin **** **** **** **** **** **** **** **** +7173 SublimeChord_Summon_Creature_IV **** **** **** **** **** **** **** **** +7174 SublimeChord_SummonUndeadIV **** **** **** **** **** **** **** **** +7175 SublimeChord_Viscid_Glob **** **** **** **** **** **** **** **** +7176 SublimeChord_Wall_of_Fire **** **** **** **** **** **** **** **** +7177 SublimeChord_War_Cry **** **** **** **** **** **** **** **** +7178 SublimeChord_WRACK **** **** **** **** **** **** **** **** +7179 SublimeChord_Animate_Dead **** **** **** **** **** **** **** **** +7180 SublimeChord_BalefulPolymorph **** **** **** **** **** **** **** **** +7181 SublimeChord_Ball_Lightning **** **** **** **** **** **** **** **** +7182 SublimeChord_Beltyns_Burning_Blood **** **** **** **** **** **** **** **** +7183 SublimeChord_Bigbys_Interposing_Hand **** **** **** **** **** **** **** **** +7184 SublimeChord_CALL_DRETCH_HORDE **** **** **** **** **** **** **** **** +7185 SublimeChord_CALL_LEMURE_HORDE **** **** **** **** **** **** **** **** +7186 SublimeChord_Cloudkill **** **** **** **** **** **** **** **** +7187 SublimeChord_Cone_of_Cold **** **** **** **** **** **** **** **** +7188 SublimeChord_DraconicMight **** **** **** **** **** **** **** **** +7189 SublimeChord_Ethereal_Visage **** **** **** **** **** **** **** **** +7190 SublimeChord_Feeblemind **** **** **** **** **** **** **** **** +7191 SublimeChord_Firebrand **** **** **** **** **** **** **** **** +7192 SublimeChord_Greater_Dispelling **** **** **** **** **** **** **** **** +7193 SublimeChord_Greater_Fireburst **** **** **** **** **** **** **** **** +7194 SublimeChord_Greater_Heroism **** **** **** **** **** **** **** **** +7195 SublimeChord_Greater_Shadow_Conjuration **** **** **** **** **** **** **** **** +7196 SublimeChord_GR_SHADOW_CON_Summon_Shadow **** **** **** **** **** **** **** **** +7197 SublimeChord_GR_SHADOW_CON_Acid_Arrow **** **** **** **** **** **** **** **** +7198 SublimeChord_GR_SHADOW_CON_Ghostly_Visage **** **** **** **** **** **** **** **** +7199 SublimeChord_GR_SHADOW_CON_Web **** **** **** **** **** **** **** **** +7200 SublimeChord_GR_SHADOW_CON_Minor_Globe **** **** **** **** **** **** **** **** +7201 SublimeChord_Greater_Wall_of_Dispel_Magic **** **** **** **** **** **** **** **** +7202 SublimeChord_Healing_Circle **** **** **** **** **** **** **** **** +7203 SublimeChord_Lesser_Mind_Blank **** **** **** **** **** **** **** **** +7204 SublimeChord_Lesser_Planar_Binding **** **** **** **** **** **** **** **** +7205 SublimeChord_Lesser_Spell_Mantle **** **** **** **** **** **** **** **** +7206 SublimeChord_Magic_Missile **** **** **** **** **** **** **** **** +7207 SublimeChord_Mass_Cure_Light_Wounds **** **** **** **** **** **** **** **** +7208 SublimeChord_MassFireShield **** **** **** **** **** **** **** **** +7209 SublimeChord_MassFireShieldRed **** **** **** **** **** **** **** **** +7210 SublimeChord_MassFireShieldBlue **** **** **** **** **** **** **** **** +7211 SublimeChord_Mestils_Acid_Sheath **** **** **** **** **** **** **** **** +7212 SublimeChord_Mind_Fog **** **** **** **** **** **** **** **** +7213 SublimeChord_Mislead **** **** **** **** **** **** **** **** +7214 SublimeChord_MORALITY_UNDONE **** **** **** **** **** **** **** **** +7215 SublimeChord_Necrotic_Burst **** **** **** **** **** **** **** **** +7216 SublimeChord_Nights_Caress **** **** **** **** **** **** **** **** +7217 SublimeChord_PrismaticRay **** **** **** **** **** **** **** **** +7218 SublimeChord_RESONATING_RESISTANCE **** **** **** **** **** **** **** **** +7219 SublimeChord_SongOfDiscord **** **** **** **** **** **** **** **** +7220 SublimeChord_Sonic_Shield **** **** **** **** **** **** **** **** +7221 SublimeChord_STOP_HEART **** **** **** **** **** **** **** **** +7222 SublimeChord_Summon_Creature_V **** **** **** **** **** **** **** **** +7223 SublimeChord_SummonUndeadV **** **** **** **** **** **** **** **** +7224 SublimeChord_SYMBOL_OF_PAIN **** **** **** **** **** **** **** **** +7225 SublimeChord_SYMBOL_OF_SLEEP **** **** **** **** **** **** **** **** +7226 SublimeChord_Teleport_RadialMaster **** **** **** **** **** **** **** **** +7227 SublimeChord_Teleport_SelfOnly **** **** **** **** **** **** **** **** +7228 SublimeChord_Teleport_Party **** **** **** **** **** **** **** **** +7229 SublimeChord_WavesofFatigue **** **** **** **** **** **** **** **** +7230 SublimeChord_Acid_Fog **** **** **** **** **** **** **** **** +7231 SublimeChord_Acid_Storm **** **** **** **** **** **** **** **** +7232 SublimeChord_Animate_Object **** **** **** **** **** **** **** **** +7233 SublimeChord_ANTIMAGIC_FIELD **** **** **** **** **** **** **** **** +7234 SublimeChord_Bigbys_Forceful_Hand **** **** **** **** **** **** **** **** +7235 SublimeChord_CALL_FAITHFUL_SERVANTS **** **** **** **** **** **** **** **** +7236 SublimeChord_Chain_Lightning **** **** **** **** **** **** **** **** +7237 SublimeChord_Circle_of_Death **** **** **** **** **** **** **** **** +7238 SublimeChord_Dirge **** **** **** **** **** **** **** **** +7239 SublimeChord_Disintegrate **** **** **** **** **** **** **** **** +7240 SublimeChord_ECTOPLASMIC_ENCHANCEMENT **** **** **** **** **** **** **** **** +7241 SublimeChord_Energy_Buffer **** **** **** **** **** **** **** **** +7242 SublimeChord_ExtractWaterElemental **** **** **** **** **** **** **** **** +7243 SublimeChord_Eyebite **** **** **** **** **** **** **** **** +7244 SublimeChord_Flesh_to_stone **** **** **** **** **** **** **** **** +7245 SublimeChord_Ghoul_Gauntlet **** **** **** **** **** **** **** **** +7246 SublimeChord_Globe_of_Invulnerability **** **** **** **** **** **** **** **** +7247 SublimeChord_Greater_Shout **** **** **** **** **** **** **** **** +7248 SublimeChord_Greater_Spell_Breach **** **** **** **** **** **** **** **** +7249 SublimeChord_Greater_Stoneskin **** **** **** **** **** **** **** **** +7250 SublimeChord_GreaterScrying **** **** **** **** **** **** **** **** +7251 SublimeChord_Ice_Storm **** **** **** **** **** **** **** **** +7252 SublimeChord_Isaacs_Greater_Missile_Storm **** **** **** **** **** **** **** **** +7253 SublimeChord_Mass_Bulls_Strength **** **** **** **** **** **** **** **** +7254 SublimeChord_Mass_Cats_Grace **** **** **** **** **** **** **** **** +7255 SublimeChord_Mass_Contagion **** **** **** **** **** **** **** **** +7256 SublimeChord_Mass_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +7257 SublimeChord_Mass_Eagle_Splendor **** **** **** **** **** **** **** **** +7258 SublimeChord_Mass_Endurance **** **** **** **** **** **** **** **** +7259 SublimeChord_Mass_Foxs_Cunning **** **** **** **** **** **** **** **** +7260 SublimeChord_Mass_Haste **** **** **** **** **** **** **** **** +7261 SublimeChord_Mass_Owls_Wisdom **** **** **** **** **** **** **** **** +7262 SublimeChord_Necrotic_Eruption **** **** **** **** **** **** **** **** +7263 SublimeChord_OtilukesFreezingSphere **** **** **** **** **** **** **** **** +7264 SublimeChord_Planar_Binding **** **** **** **** **** **** **** **** +7265 SublimeChord_Repulsion **** **** **** **** **** **** **** **** +7266 SublimeChord_Shades **** **** **** **** **** **** **** **** +7267 SublimeChord_SHADES_Summon_Shadow **** **** **** **** **** **** **** **** +7268 SublimeChord_SHADES_Cone_of_Cold **** **** **** **** **** **** **** **** +7269 SublimeChord_SHADES_Fireball **** **** **** **** **** **** **** **** +7270 SublimeChord_SHADES_Stoneskin **** **** **** **** **** **** **** **** +7271 SublimeChord_SHADES_Wall_of_Fire **** **** **** **** **** **** **** **** +7272 SublimeChord_STARMANTLE **** **** **** **** **** **** **** **** +7273 SublimeChord_Stone_to_flesh **** **** **** **** **** **** **** **** +7274 SublimeChord_Summon_Creature_VI **** **** **** **** **** **** **** **** +7275 SublimeChord_Superior_Resistance **** **** **** **** **** **** **** **** +7276 SublimeChord_SYMBOL_OF_FEAR **** **** **** **** **** **** **** **** +7277 SublimeChord_SYMBOL_OF_PERSUASION **** **** **** **** **** **** **** **** +7278 SublimeChord_Tensers_Transformation **** **** **** **** **** **** **** **** +7279 SublimeChord_True_Seeing **** **** **** **** **** **** **** **** +7280 SublimeChord_Undeath_to_Death **** **** **** **** **** **** **** **** +7281 SublimeChord_WAVE_OF_PAIN **** **** **** **** **** **** **** **** +7282 SublimeChord_AMBER_SARCOPHAGUS **** **** **** **** **** **** **** **** +7283 SublimeChord_ArrowOfBone **** **** **** **** **** **** **** **** +7284 SublimeChord_Avasculate **** **** **** **** **** **** **** **** +7285 SublimeChord_Banishment **** **** **** **** **** **** **** **** +7286 SublimeChord_Bigbys_Grasping_Hand **** **** **** **** **** **** **** **** +7287 SublimeChord_Control_Undead **** **** **** **** **** **** **** **** +7288 SublimeChord_Control_Weather **** **** **** **** **** **** **** **** +7289 SublimeChord_CW_Rain **** **** **** **** **** **** **** **** +7290 SublimeChord_CW_Snow **** **** **** **** **** **** **** **** +7291 SublimeChord_CW_Clear **** **** **** **** **** **** **** **** +7292 SublimeChord_Delayed_Blast_Fireball **** **** **** **** **** **** **** **** +7293 SublimeChord_DRAGON_ALLY **** **** **** **** **** **** **** **** +7294 SublimeChord_Energy_Ebb **** **** **** **** **** **** **** **** +7295 SublimeChord_Energy_Immunity **** **** **** **** **** **** **** **** +7296 SublimeChord_EI_Acid **** **** **** **** **** **** **** **** +7297 SublimeChord_EI_Cold **** **** **** **** **** **** **** **** +7298 SublimeChord_EI_Elec **** **** **** **** **** **** **** **** +7299 SublimeChord_EI_Fire **** **** **** **** **** **** **** **** +7300 SublimeChord_EI_Sonic **** **** **** **** **** **** **** **** +7301 SublimeChord_EYE_OF_THE_BEHOLDER **** **** **** **** **** **** **** **** +7302 SublimeChord_FIENDISH_CLARITY **** **** **** **** **** **** **** **** +7303 SublimeChord_Finger_of_Death **** **** **** **** **** **** **** **** +7304 SublimeChord_Great_Thunderclap **** **** **** **** **** **** **** **** +7305 SublimeChord_GreaterTeleport_RadialMaster **** **** **** **** **** **** **** **** +7306 SublimeChord_GreaterTeleport_SelfOnly **** **** **** **** **** **** **** **** +7307 SublimeChord_GreaterTeleport_Party **** **** **** **** **** **** **** **** +7308 SublimeChord_Insanity **** **** **** **** **** **** **** **** +7309 SublimeChord_Mass_Hold_Person **** **** **** **** **** **** **** **** +7310 SublimeChord_Mordenkainens_Sword **** **** **** **** **** **** **** **** +7311 SublimeChord_Mords_Mansion **** **** **** **** **** **** **** **** +7312 SublimeChord_Nybors_Stern_Reproof **** **** **** **** **** **** **** **** +7313 SublimeChord_Power_Word_Blind **** **** **** **** **** **** **** **** +7314 SublimeChord_Power_Word_Stun **** **** **** **** **** **** **** **** +7315 SublimeChord_Prismatic_Spray **** **** **** **** **** **** **** **** +7316 SublimeChord_Protection_from_Spells **** **** **** **** **** **** **** **** +7317 SublimeChord_Sequester **** **** **** **** **** **** **** **** +7318 SublimeChord_Shadow_Shield **** **** **** **** **** **** **** **** +7319 SublimeChord_Spell_Mantle **** **** **** **** **** **** **** **** +7320 SublimeChord_Spell_Turning **** **** **** **** **** **** **** **** +7321 SublimeChord_Summon_Creature_VII **** **** **** **** **** **** **** **** +7322 SublimeChord_Summon7Air **** **** **** **** **** **** **** **** +7323 SublimeChord_Summon7Earth **** **** **** **** **** **** **** **** +7324 SublimeChord_Summon7Fire **** **** **** **** **** **** **** **** +7325 SublimeChord_Summon7Water **** **** **** **** **** **** **** **** +7326 SublimeChord_SYMBOL_OF_STUNING **** **** **** **** **** **** **** **** +7327 SublimeChord_SYMBOL_OF_WEAKNESS **** **** **** **** **** **** **** **** +7328 SublimeChord_TOMB_OF_LIGHT **** **** **** **** **** **** **** **** +7329 SublimeChord_WavesOfExhaustion **** **** **** **** **** **** **** **** +7330 SublimeChord_Avascular_Mass **** **** **** **** **** **** **** **** +7331 SublimeChord_Bigbys_Clenched_Fist **** **** **** **** **** **** **** **** +7332 SublimeChord_Blackstaff **** **** **** **** **** **** **** **** +7333 SublimeChord_Create_Undead **** **** **** **** **** **** **** **** +7334 SublimeChord_Dimensional_Lock **** **** **** **** **** **** **** **** +7335 SublimeChord_DiscernLocation **** **** **** **** **** **** **** **** +7336 SublimeChord_Etherealness **** **** **** **** **** **** **** **** +7337 SublimeChord_Flensing **** **** **** **** **** **** **** **** +7338 SublimeChord_Greater_Planar_Binding **** **** **** **** **** **** **** **** +7339 SublimeChord_GUTWRENCH **** **** **** **** **** **** **** **** +7340 SublimeChord_Horrid_Wilting **** **** **** **** **** **** **** **** +7341 SublimeChord_Incendiary_Cloud **** **** **** **** **** **** **** **** +7342 SublimeChord_IRON_BODY **** **** **** **** **** **** **** **** +7343 SublimeChord_LAST_JUDGEMENT **** **** **** **** **** **** **** **** +7344 SublimeChord_Mantle_of_Eg_Might **** **** **** **** **** **** **** **** +7345 SublimeChord_Mass_Blindness_and_Deafness **** **** **** **** **** **** **** **** +7346 SublimeChord_Mass_Charm **** **** **** **** **** **** **** **** +7347 SublimeChord_Maze **** **** **** **** **** **** **** **** +7348 SublimeChord_Mind_Blank **** **** **** **** **** **** **** **** +7349 SublimeChord_Necrotic_Empowerment **** **** **** **** **** **** **** **** +7350 SublimeChord_PolarRay **** **** **** **** **** **** **** **** +7351 SublimeChord_Premonition **** **** **** **** **** **** **** **** +7352 SublimeChord_PrismaticWall **** **** **** **** **** **** **** **** +7353 SublimeChord_ScintillatingPattern **** **** **** **** **** **** **** **** +7354 SublimeChord_Summon_Creature_VIII **** **** **** **** **** **** **** **** +7355 SublimeChord_Summon8Air **** **** **** **** **** **** **** **** +7356 SublimeChord_Summon8Earth **** **** **** **** **** **** **** **** +7357 SublimeChord_Summon8Fire **** **** **** **** **** **** **** **** +7358 SublimeChord_Summon8Water **** **** **** **** **** **** **** **** +7359 SublimeChord_Sunburst **** **** **** **** **** **** **** **** +7360 SublimeChord_SYMBOL_OF_DEATH **** **** **** **** **** **** **** **** +7361 SublimeChord_SYMBOL_OF_INSANITY **** **** **** **** **** **** **** **** +7362 SublimeChord_Bigbys_Crushing_Hand **** **** **** **** **** **** **** **** +7363 SublimeChord_Black_Blade_of_Disaster **** **** **** **** **** **** **** **** +7364 SublimeChord_BLINDING_GLORY **** **** **** **** **** **** **** **** +7365 SublimeChord_CRUSHING_FIST_OF_SPITE **** **** **** **** **** **** **** **** +7366 SublimeChord_Dominate_Monster **** **** **** **** **** **** **** **** +7367 SublimeChord_Energy_Drain **** **** **** **** **** **** **** **** +7368 SublimeChord_Foresight **** **** **** **** **** **** **** **** +7369 SublimeChord_Gate **** **** **** **** **** **** **** **** +7370 SublimeChord_Greater_Spell_Mantle **** **** **** **** **** **** **** **** +7371 SublimeChord_Mass_Hold_Monster **** **** **** **** **** **** **** **** +7372 SublimeChord_Meteor_Swarm **** **** **** **** **** **** **** **** +7373 SublimeChord_Mordenkainens_Disjunction **** **** **** **** **** **** **** **** +7374 SublimeChord_Necrotic_Termination **** **** **** **** **** **** **** **** +7375 SublimeChord_PlagueOfUndead **** **** **** **** **** **** **** **** +7376 SublimeChord_Power_Word_Kill **** **** **** **** **** **** **** **** +7377 SublimeChord_PrismaticSphere **** **** **** **** **** **** **** **** +7378 SublimeChord_Shapechange **** **** **** **** **** **** **** **** +7379 SublimeChord_Shapechange_RED_DRAGON **** **** **** **** **** **** **** **** +7380 SublimeChord_Shapechange_FIRE_GIANT **** **** **** **** **** **** **** **** +7381 SublimeChord_Shapechange_BALOR **** **** **** **** **** **** **** **** +7382 SublimeChord_Shapechange_DEATH_SLAAD **** **** **** **** **** **** **** **** +7383 SublimeChord_Shapechange_IRON_GOLEM **** **** **** **** **** **** **** **** +7384 SublimeChord_Sphere_of_Ultimate_Destruction **** **** **** **** **** **** **** **** +7385 SublimeChord_Summon_Creature_IX **** **** **** **** **** **** **** **** +7386 SublimeChord_Summon9Air **** **** **** **** **** **** **** **** +7387 SublimeChord_Summon9Earth **** **** **** **** **** **** **** **** +7388 SublimeChord_Summon9Fire **** **** **** **** **** **** **** **** +7389 SublimeChord_Summon9Water **** **** **** **** **** **** **** **** +7390 SublimeChord_TeleportationCircle_RadialMaster **** **** **** **** **** **** **** **** +7391 SublimeChord_TeleportationCircle_Visible **** **** **** **** **** **** **** **** +7392 SublimeChord_TeleportationCircle_Hidden **** **** **** **** **** **** **** **** +7393 SublimeChord_Time_Stop **** **** **** **** **** **** **** **** +7394 SublimeChord_UTTERDARK **** **** **** **** **** **** **** **** +7395 SublimeChord_VileDeath **** **** **** **** **** **** **** **** +7396 SublimeChord_Wail_of_the_Banshee **** **** **** **** **** **** **** **** +7397 SublimeChord_Weird **** **** **** **** **** **** **** **** +7398 KnightoftheWeave_Bless **** **** **** **** **** **** **** **** +7399 KnightoftheWeave_Bless_Weapon **** **** **** **** **** **** **** **** +7400 KnightoftheWeave_Charm_Person **** **** **** **** **** **** **** **** +7401 KnightoftheWeave_Command_RadialMaster **** **** **** **** **** **** **** **** +7402 KnightoftheWeave_Command_Approach **** **** **** **** **** **** **** **** +7403 KnightoftheWeave_Command_Drop **** **** **** **** **** **** **** **** +7404 KnightoftheWeave_Command_Fall **** **** **** **** **** **** **** **** +7405 KnightoftheWeave_Command_Flee **** **** **** **** **** **** **** **** +7406 KnightoftheWeave_Command_Halt **** **** **** **** **** **** **** **** +7407 KnightoftheWeave_Cure_Light_Wounds **** **** **** **** **** **** **** **** +7408 KnightoftheWeave_Divine_Favor **** **** **** **** **** **** **** **** +7409 KnightoftheWeave_Lesser_Restoration **** **** **** **** **** **** **** **** +7410 KnightoftheWeave_Mage_Armor **** **** **** **** **** **** **** **** +7411 KnightoftheWeave_Magic_Missile **** **** **** **** **** **** **** **** +7412 KnightoftheWeave_Magic_Weapon **** **** **** **** **** **** **** **** +7413 KnightoftheWeave_Read_Magic **** **** **** **** **** **** **** **** +7414 KnightoftheWeave_Shield **** **** **** **** **** **** **** **** +7415 KnightoftheWeave_Bulls_Strength **** **** **** **** **** **** **** **** +7416 KnightoftheWeave_Cats_Grace **** **** **** **** **** **** **** **** +7417 KnightoftheWeave_Endurance **** **** **** **** **** **** **** **** +7418 KnightoftheWeave_Ultravision **** **** **** **** **** **** **** **** +7419 KnightoftheWeave_Eagle_Splendor **** **** **** **** **** **** **** **** +7420 KnightoftheWeave_Resist_Elements **** **** **** **** **** **** **** **** +7421 KnightoftheWeave_See_Invisibility **** **** **** **** **** **** **** **** +7422 KnightoftheWeave_ShieldOther **** **** **** **** **** **** **** **** +7423 KnightoftheWeave_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +7424 KnightoftheWeave_Daylight **** **** **** **** **** **** **** **** +7425 KnightoftheWeave_Dispel_Magic **** **** **** **** **** **** **** **** +7426 KnightoftheWeave_Greater_Magic_Weapon **** **** **** **** **** **** **** **** +7427 KnightoftheWeave_Remove_Curse **** **** **** **** **** **** **** **** +7428 KnightoftheWeave_BreakEnchantment **** **** **** **** **** **** **** **** +7429 KnightoftheWeave_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +7430 KnightoftheWeave_Death_Ward **** **** **** **** **** **** **** **** +7431 KnightoftheWeave_Minor_Globe_of_Invulnerability **** **** **** **** **** **** **** **** +7432 KnightoftheWeave_Neutralize_Poison **** **** **** **** **** **** **** **** +7433 KnightoftheWeave_Restoration **** **** **** **** **** **** **** **** +7434 KnightoftheWeave_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +7435 KnightoftheWeave_DimensionDoor_RadialMaster **** **** **** **** **** **** **** **** +7436 KnightoftheWeave_DimensionDoor_SelfOnly **** **** **** **** **** **** **** **** +7437 KnightoftheWeave_DimensionDoor_Party **** **** **** **** **** **** **** **** +7438 KnightoftheWeave_DimensionDoor_DirDist_SelfOnly **** **** **** **** **** **** **** **** +7439 KnightoftheWeave_DimensionDoor_DirDist_Party **** **** **** **** **** **** **** **** +7440 KnightoftheWeave_Spell_Resistance **** **** **** **** **** **** **** **** +7441 KnightoftheWeave_True_Seeing **** **** **** **** **** **** **** **** +7442 KnightoftheWeave_Banishment **** **** **** **** **** **** **** **** +7443 KnightoftheWeave_Greater_Dispelling **** **** **** **** **** **** **** **** +7444 KnightoftheWeave_Teleport_RadialMaster **** **** **** **** **** **** **** **** +7445 KnightoftheWeave_Teleport_SelfOnly **** **** **** **** **** **** **** **** +7446 KnightoftheWeave_Teleport_Party **** **** **** **** **** **** **** **** +7447 Anti_Paladin_Bane **** **** **** **** **** **** **** **** +7448 Anti_Paladin_Exteneded_Bane **** **** **** **** **** **** **** **** +7449 Anti_Paladin_Silent_Bane **** **** **** **** **** **** **** **** +7450 Anti_Paladin_Still_Bane **** **** **** **** **** **** **** **** +7451 Anti_Paladin_Cause_Fear **** **** **** **** **** **** **** **** +7452 Anti_Paladin_Exteneded_Cause_Fear **** **** **** **** **** **** **** **** +7453 Anti_Paladin_Still_Cause_Fear **** **** **** **** **** **** **** **** +7454 Anti_Paladin_Curse_Water **** **** **** **** **** **** **** **** +7455 Anti_Paladin_Silent_Curse_Water **** **** **** **** **** **** **** **** +7456 Anti_Paladin_Still_Curse_Water **** **** **** **** **** **** **** **** +7457 Anti_Paladin_Doom **** **** **** **** **** **** **** **** +7458 Anti_Paladin_Exteneded_Doom **** **** **** **** **** **** **** **** +7459 Anti_Paladin_Silent_Doom **** **** **** **** **** **** **** **** +7460 Anti_Paladin_Still_Doom **** **** **** **** **** **** **** **** +7461 Anti_Paladin_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +7462 Anti_Paladin_Empowered_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +7463 Anti_Paladin_Maximized_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +7464 Anti_Paladin_Silent_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +7465 Anti_Paladin_Still_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +7466 Anti_Paladin_Magic_Weapon **** **** **** **** **** **** **** **** +7467 Anti_Paladin_Exteneded_Magic_Weapon **** **** **** **** **** **** **** **** +7468 Anti_Paladin_Silent_Magic_Weapon **** **** **** **** **** **** **** **** +7469 Anti_Paladin_Still_Magic_Weapon **** **** **** **** **** **** **** **** +7470 Anti_Paladin_Protection_from_Good **** **** **** **** **** **** **** **** +7471 Anti_Paladin_Exteneded_Protection_from_Good **** **** **** **** **** **** **** **** +7472 Anti_Paladin_Silent_Protection_from_Good **** **** **** **** **** **** **** **** +7473 Anti_Paladin_Still_Protection_from_Good **** **** **** **** **** **** **** **** +7474 Anti_Paladin_Protection_from_Law **** **** **** **** **** **** **** **** +7475 Anti_Paladin_Exteneded_Protection_from_Law **** **** **** **** **** **** **** **** +7476 Anti_Paladin_Silent_Protection_from_Law **** **** **** **** **** **** **** **** +7477 Anti_Paladin_Still_Protection_from_Law **** **** **** **** **** **** **** **** +7478 Anti_Paladin_Ray_of_Enfeeblement **** **** **** **** **** **** **** **** +7479 Anti_Paladin_Empowered_Ray_of_Enfeeblement **** **** **** **** **** **** **** **** +7480 Anti_Paladin_Exteneded_Ray_of_Enfeeblement **** **** **** **** **** **** **** **** +7481 Anti_Paladin_Maximized_Ray_of_Enfeeblement **** **** **** **** **** **** **** **** +7482 Anti_Paladin_Silent_Ray_of_Enfeeblement **** **** **** **** **** **** **** **** +7483 Anti_Paladin_Still_Ray_of_Enfeeblement **** **** **** **** **** **** **** **** +7484 Anti_Paladin_Read_Magic **** **** **** **** **** **** **** **** +7485 Anti_Paladin_Silent_Read_Magic **** **** **** **** **** **** **** **** +7486 Anti_Paladin_Still_Read_Magic **** **** **** **** **** **** **** **** +7487 Anti_Paladin_Summon_Creature_I **** **** **** **** **** **** **** **** +7488 Anti_Paladin_Exteneded_Summon_Creature_I **** **** **** **** **** **** **** **** +7489 Anti_Paladin_Silent_Summon_Creature_I **** **** **** **** **** **** **** **** +7490 Anti_Paladin_Still_Summon_Creature_I **** **** **** **** **** **** **** **** +7491 Anti_Paladin_ANGRY_ACHE **** **** **** **** **** **** **** **** +7492 Anti_Paladin_Exteneded_ANGRY_ACHE **** **** **** **** **** **** **** **** +7493 Anti_Paladin_Silent_ANGRY_ACHE **** **** **** **** **** **** **** **** +7494 Anti_Paladin_Still_ANGRY_ACHE **** **** **** **** **** **** **** **** +7495 Anti_Paladin_SEETHING_EYEBANE **** **** **** **** **** **** **** **** +7496 Anti_Paladin_Silent_SEETHING_EYEBANE **** **** **** **** **** **** **** **** +7497 Anti_Paladin_Still_SEETHING_EYEBANE **** **** **** **** **** **** **** **** +7498 Anti_Paladin_Bulls_Strength **** **** **** **** **** **** **** **** +7499 Anti_Paladin_Empowered_Bulls_Strength **** **** **** **** **** **** **** **** +7500 Anti_Paladin_Exteneded_Bulls_Strength **** **** **** **** **** **** **** **** +7501 Anti_Paladin_Silent_Bulls_Strength **** **** **** **** **** **** **** **** +7502 Anti_Paladin_Still_Bulls_Strength **** **** **** **** **** **** **** **** +7503 Anti_Paladin_Darkness **** **** **** **** **** **** **** **** +7504 Anti_Paladin_Exteneded_Darkness **** **** **** **** **** **** **** **** +7505 Anti_Paladin_Silent_Darkness **** **** **** **** **** **** **** **** +7506 Anti_Paladin_Summon_Creature_II **** **** **** **** **** **** **** **** +7507 Anti_Paladin_Exteneded_Summon_Creature_II **** **** **** **** **** **** **** **** +7508 Anti_Paladin_Silent_Summon_Creature_II **** **** **** **** **** **** **** **** +7509 Anti_Paladin_Still_Summon_Creature_II **** **** **** **** **** **** **** **** +7510 Anti_Paladin_UndetectableAlignment **** **** **** **** **** **** **** **** +7511 Anti_Paladin_Exteneded_UndetectableAlignment **** **** **** **** **** **** **** **** +7512 Anti_Paladin_Silent_UndetectableAlignment **** **** **** **** **** **** **** **** +7513 Anti_Paladin_Still_UndetectableAlignment **** **** **** **** **** **** **** **** +7514 Anti_Paladin_LAHMS_FINGER_DARTS **** **** **** **** **** **** **** **** +7515 Anti_Paladin_Silent_LAHMS_FINGER_DARTS **** **** **** **** **** **** **** **** +7516 Anti_Paladin_Still_LAHMS_FINGER_DARTS **** **** **** **** **** **** **** **** +7517 Anti_Paladin_Greater_Magic_Weapon **** **** **** **** **** **** **** **** +7518 Anti_Paladin_Exteneded_Greater_Magic_Weapon **** **** **** **** **** **** **** **** +7519 Anti_Paladin_Silent_Greater_Magic_Weapon **** **** **** **** **** **** **** **** +7520 Anti_Paladin_Still_Greater_Magic_Weapon **** **** **** **** **** **** **** **** +7521 Anti_Paladin_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +7522 Anti_Paladin_Silent_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +7523 Anti_Paladin_Still_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +7524 Anti_Paladin_Magic_Circle_against_Good **** **** **** **** **** **** **** **** +7525 Anti_Paladin_Exteneded_Magic_Circle_against_Good **** **** **** **** **** **** **** **** +7526 Anti_Paladin_Silent_Magic_Circle_against_Good **** **** **** **** **** **** **** **** +7527 Anti_Paladin_Still_Magic_Circle_against_Good **** **** **** **** **** **** **** **** +7528 Anti_Paladin_Magic_Circle_against_Law **** **** **** **** **** **** **** **** +7529 Anti_Paladin_Exteneded_Magic_Circle_against_Law **** **** **** **** **** **** **** **** +7530 Anti_Paladin_Silent_Magic_Circle_against_Law **** **** **** **** **** **** **** **** +7531 Anti_Paladin_Still_Magic_Circle_against_Law **** **** **** **** **** **** **** **** +7532 Anti_Paladin_Summon_Creature_III **** **** **** **** **** **** **** **** +7533 Anti_Paladin_Exteneded_Summon_Creature_III **** **** **** **** **** **** **** **** +7534 Anti_Paladin_Silent_Summon_Creature_III **** **** **** **** **** **** **** **** +7535 Anti_Paladin_Still_Summon_Creature_III **** **** **** **** **** **** **** **** +7536 Anti_Paladin_Bestow_Curse **** **** **** **** **** **** **** **** +7537 Anti_Paladin_Silent_Bestow_Curse **** **** **** **** **** **** **** **** +7538 Anti_Paladin_Still_Bestow_Curse **** **** **** **** **** **** **** **** +7539 Anti_Paladin_Blindness_and_Deafness **** **** **** **** **** **** **** **** +7540 Anti_Paladin_Exteneded_Blindness_and_Deafness **** **** **** **** **** **** **** **** +7541 Anti_Paladin_Silent_Blindness_and_Deafness **** **** **** **** **** **** **** **** +7542 Anti_Paladin_DeeperDarkness **** **** **** **** **** **** **** **** +7543 Anti_Paladin_Exteneded_DeeperDarkness **** **** **** **** **** **** **** **** +7544 Anti_Paladin_Silent_DeeperDarkness **** **** **** **** **** **** **** **** +7545 Anti_Paladin_RED_FESTER **** **** **** **** **** **** **** **** +7546 Anti_Paladin_Silent_RED_FESTER **** **** **** **** **** **** **** **** +7547 Anti_Paladin_Still_RED_FESTER **** **** **** **** **** **** **** **** +7548 Anti_Paladin_ROTTING_CURSE_OF_URFESTRA **** **** **** **** **** **** **** **** +7549 Anti_Paladin_Silent_ROTTING_CURSE_OF_URFESTRA **** **** **** **** **** **** **** **** +7550 Anti_Paladin_Still_ROTTING_CURSE_OF_URFESTRA **** **** **** **** **** **** **** **** +7551 Anti_Paladin_TOUCH_OF_JUIBLEX **** **** **** **** **** **** **** **** +7552 Anti_Paladin_Silent_TOUCH_OF_JUIBLEX **** **** **** **** **** **** **** **** +7553 Anti_Paladin_Still_TOUCH_OF_JUIBLEX **** **** **** **** **** **** **** **** +7554 Anti_Paladin_MASOCHISM **** **** **** **** **** **** **** **** +7555 Anti_Paladin_Exteneded_MASOCHISM **** **** **** **** **** **** **** **** +7556 Anti_Paladin_Death_Ward **** **** **** **** **** **** **** **** +7557 Anti_Paladin_Inflict_Serious_Wounds **** **** **** **** **** **** **** **** +7558 Anti_Paladin_Fear **** **** **** **** **** **** **** **** +7559 Anti_Paladin_Poison **** **** **** **** **** **** **** **** +7560 Anti_Paladin_Unholy_Sword **** **** **** **** **** **** **** **** +7561 Anti_Paladin_ABSORB_STRENGTH **** **** **** **** **** **** **** **** +7562 Soldier_of_Light_Cure_Light_Wounds **** **** **** **** **** **** **** **** +7563 Soldier_of_Light_Empowered_Cure_Light_Wounds **** **** **** **** **** **** **** **** +7564 Soldier_of_Light_Maximized_Cure_Light_Wounds **** **** **** **** **** **** **** **** +7565 Soldier_of_Light_Silent_Cure_Light_Wounds **** **** **** **** **** **** **** **** +7566 Soldier_of_Light_Still_Cure_Light_Wounds **** **** **** **** **** **** **** **** +7567 Soldier_of_Light_Bless_Water **** **** **** **** **** **** **** **** +7568 Soldier_of_Light_Silent_Bless_Water **** **** **** **** **** **** **** **** +7569 Soldier_of_Light_Still_Bless_Water **** **** **** **** **** **** **** **** +7570 Soldier_of_Light_Bless_Weapon **** **** **** **** **** **** **** **** +7571 Soldier_of_Light_Exteneded_Bless_Weapon **** **** **** **** **** **** **** **** +7572 Soldier_of_Light_Silent_Bless_Weapon **** **** **** **** **** **** **** **** +7573 Soldier_of_Light_Still_Bless_Weapon **** **** **** **** **** **** **** **** +7574 Soldier_of_Light_Bless **** **** **** **** **** **** **** **** +7575 Soldier_of_Light_Exteneded_Bless **** **** **** **** **** **** **** **** +7576 Soldier_of_Light_Silent_Bless **** **** **** **** **** **** **** **** +7577 Soldier_of_Light_Still_Bless **** **** **** **** **** **** **** **** +7578 Soldier_of_Light_Detect_Evil **** **** **** **** **** **** **** **** +7579 Soldier_of_Light_Exteneded_Detect_Evil **** **** **** **** **** **** **** **** +7580 Soldier_of_Light_Silent_Detect_Evil **** **** **** **** **** **** **** **** +7581 Soldier_of_Light_Still_Detect_Evil **** **** **** **** **** **** **** **** +7582 Soldier_of_Light_HideFromUndead **** **** **** **** **** **** **** **** +7583 Soldier_of_Light_Exteneded_HideFromUndead **** **** **** **** **** **** **** **** +7584 Soldier_of_Light_Still_HideFromUndead **** **** **** **** **** **** **** **** +7585 Soldier_of_Light_Magic_Weapon **** **** **** **** **** **** **** **** +7586 Soldier_of_Light_Exteneded_Magic_Weapon **** **** **** **** **** **** **** **** +7587 Soldier_of_Light_Silent_Magic_Weapon **** **** **** **** **** **** **** **** +7588 Soldier_of_Light_Still_Magic_Weapon **** **** **** **** **** **** **** **** +7589 Soldier_of_Light_Shield_of_Faith **** **** **** **** **** **** **** **** +7590 Soldier_of_Light_Exteneded_Shield_of_Faith **** **** **** **** **** **** **** **** +7591 Soldier_of_Light_Silent_Shield_of_Faith **** **** **** **** **** **** **** **** +7592 Soldier_of_Light_Still_Shield_of_Faith **** **** **** **** **** **** **** **** +7593 Soldier_of_Light_Protection_from_Evil **** **** **** **** **** **** **** **** +7594 Soldier_of_Light_Exteneded_Protection_from_Evil **** **** **** **** **** **** **** **** +7595 Soldier_of_Light_Silent_Protection_from_Evil **** **** **** **** **** **** **** **** +7596 Soldier_of_Light_Still_Protection_from_Evil **** **** **** **** **** **** **** **** +7597 Soldier_of_Light_Light **** **** **** **** **** **** **** **** +7598 Soldier_of_Light_Exteneded_Light **** **** **** **** **** **** **** **** +7599 Soldier_of_Light_Silent_Light **** **** **** **** **** **** **** **** +7600 Soldier_of_Light_TWILIGHT_LUCK **** **** **** **** **** **** **** **** +7601 Soldier_of_Light_Exteneded_TWILIGHT_LUCK **** **** **** **** **** **** **** **** +7602 Soldier_of_Light_Silent_TWILIGHT_LUCK **** **** **** **** **** **** **** **** +7603 Soldier_of_Light_LANTERN_LIGHT **** **** **** **** **** **** **** **** +7604 Soldier_of_Light_Empowered_LANTERN_LIGHT **** **** **** **** **** **** **** **** +7605 Soldier_of_Light_Maximized_LANTERN_LIGHT **** **** **** **** **** **** **** **** +7606 Soldier_of_Light_Still_LANTERN_LIGHT **** **** **** **** **** **** **** **** +7607 Soldier_of_Light_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +7608 Soldier_of_Light_Empowered_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +7609 Soldier_of_Light_Silent_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +7610 Soldier_of_Light_Still_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +7611 Soldier_of_Light_Aid **** **** **** **** **** **** **** **** +7612 Soldier_of_Light_Empowered_Aid **** **** **** **** **** **** **** **** +7613 Soldier_of_Light_Exteneded_Aid **** **** **** **** **** **** **** **** +7614 Soldier_of_Light_Silent_Aid **** **** **** **** **** **** **** **** +7615 Soldier_of_Light_Still_Aid **** **** **** **** **** **** **** **** +7616 Soldier_of_Light_Consecrated_Aura **** **** **** **** **** **** **** **** +7617 Soldier_of_Light_Exteneded_Consecrated_Aura **** **** **** **** **** **** **** **** +7618 Soldier_of_Light_Silent_Consecrated_Aura **** **** **** **** **** **** **** **** +7619 Soldier_of_Light_Still_Consecrated_Aura **** **** **** **** **** **** **** **** +7620 Soldier_of_Light_Daylight **** **** **** **** **** **** **** **** +7621 Soldier_of_Light_Exteneded_Daylight **** **** **** **** **** **** **** **** +7622 Soldier_of_Light_Silent_Daylight **** **** **** **** **** **** **** **** +7623 Soldier_of_Light_Still_Daylight **** **** **** **** **** **** **** **** +7624 Soldier_of_Light_Lesser_Restoration **** **** **** **** **** **** **** **** +7625 Soldier_of_Light_Silent_Lesser_Restoration **** **** **** **** **** **** **** **** +7626 Soldier_of_Light_Still_Lesser_Restoration **** **** **** **** **** **** **** **** +7627 Soldier_of_Light_ShieldOther **** **** **** **** **** **** **** **** +7628 Soldier_of_Light_Exteneded_ShieldOther **** **** **** **** **** **** **** **** +7629 Soldier_of_Light_Silent_ShieldOther **** **** **** **** **** **** **** **** +7630 Soldier_of_Light_Still_ShieldOther **** **** **** **** **** **** **** **** +7631 Soldier_of_Light_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +7632 Soldier_of_Light_Empowered_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +7633 Soldier_of_Light_Silent_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +7634 Soldier_of_Light_Still_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +7635 Soldier_of_Light_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +7636 Soldier_of_Light_Exteneded_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +7637 Soldier_of_Light_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +7638 Soldier_of_Light_Silent_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +7639 Soldier_of_Light_Still_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +7640 Soldier_of_Light_Greater_Magic_Weapon **** **** **** **** **** **** **** **** +7641 Soldier_of_Light_Exteneded_Greater_Magic_Weapon **** **** **** **** **** **** **** **** +7642 Soldier_of_Light_Silent_Greater_Magic_Weapon **** **** **** **** **** **** **** **** +7643 Soldier_of_Light_Still_Greater_Magic_Weapon **** **** **** **** **** **** **** **** +7644 Soldier_of_Light_Magic_Circle_against_Evil **** **** **** **** **** **** **** **** +7645 Soldier_of_Light_Exteneded_Magic_Circle_against_Evil **** **** **** **** **** **** **** **** +7646 Soldier_of_Light_Silent_Magic_Circle_against_Evil **** **** **** **** **** **** **** **** +7647 Soldier_of_Light_Still_Magic_Circle_against_Evil **** **** **** **** **** **** **** **** +7648 Soldier_of_Light_Searing_Light **** **** **** **** **** **** **** **** +7649 Soldier_of_Light_Silent_Searing_Light **** **** **** **** **** **** **** **** +7650 Soldier_of_Light_Still_Searing_Light **** **** **** **** **** **** **** **** +7651 Soldier_of_Light_Negative_Energy_Protection **** **** **** **** **** **** **** **** +7652 Soldier_of_Light_Exteneded_Negative_Energy_Protection **** **** **** **** **** **** **** **** +7653 Soldier_of_Light_Silent_Negative_Energy_Protection **** **** **** **** **** **** **** **** +7654 Soldier_of_Light_Still_Negative_Energy_Protection **** **** **** **** **** **** **** **** +7655 Soldier_of_Light_Prayer **** **** **** **** **** **** **** **** +7656 Soldier_of_Light_Exteneded_Prayer **** **** **** **** **** **** **** **** +7657 Soldier_of_Light_Silent_Prayer **** **** **** **** **** **** **** **** +7658 Soldier_of_Light_Still_Prayer **** **** **** **** **** **** **** **** +7659 Soldier_of_Light_Remove_Disease **** **** **** **** **** **** **** **** +7660 Soldier_of_Light_Silent_Remove_Disease **** **** **** **** **** **** **** **** +7661 Soldier_of_Light_Still_Remove_Disease **** **** **** **** **** **** **** **** +7662 Soldier_of_Light_BRILLIANT_EMANATION **** **** **** **** **** **** **** **** +7663 Soldier_of_Light_Exteneded_BRILLIANT_EMANATION **** **** **** **** **** **** **** **** +7664 Soldier_of_Light_HAMMER_OF_RIGHTEOUSNESS **** **** **** **** **** **** **** **** +7665 Soldier_of_Light_Silent_HAMMER_OF_RIGHTEOUSNESS **** **** **** **** **** **** **** **** +7666 Soldier_of_Light_Still_HAMMER_OF_RIGHTEOUSNESS **** **** **** **** **** **** **** **** +7667 Soldier_of_Light_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +7668 Soldier_of_Light_Death_Ward **** **** **** **** **** **** **** **** +7669 Soldier_of_Light_Hammer_of_the_Gods **** **** **** **** **** **** **** **** +7670 Soldier_of_Light_Holy_Sword **** **** **** **** **** **** **** **** +7671 Soldier_of_Light_Lesser_Planar_Ally **** **** **** **** **** **** **** **** +7672 Soldier_of_Light_Restoration **** **** **** **** **** **** **** **** +7673 Soldier_of_Light_DIAMOND_SPRAY **** **** **** **** **** **** **** **** +7674 Soldier_of_Light_SUNMANTLE **** **** **** **** **** **** **** **** +7675 Soldier_of_Light_GREATER_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +7676 Telflammar_Shadow_Blindness_and_Deafness **** **** **** **** **** **** **** **** +7677 Telflammar_Shadow_Exteneded_Blindness_and_Deafness **** **** **** **** **** **** **** **** +7678 Telflammar_Shadow_Silent_Blindness_and_Deafness **** **** **** **** **** **** **** **** +7679 Telflammar_Shadow_Ultravision **** **** **** **** **** **** **** **** +7680 Telflammar_Shadow_Exteneded_Ultravision **** **** **** **** **** **** **** **** +7681 Telflammar_Shadow_Silent_Ultravision **** **** **** **** **** **** **** **** +7682 Telflammar_Shadow_Still_Ultravision **** **** **** **** **** **** **** **** +7683 Telflammar_Shadow_Chill_Touch **** **** **** **** **** **** **** **** +7684 Telflammar_Shadow_Empowered_Chill_Touch **** **** **** **** **** **** **** **** +7685 Telflammar_Shadow_Exteneded_Chill_Touch **** **** **** **** **** **** **** **** +7686 Telflammar_Shadow_Silent_Chill_Touch **** **** **** **** **** **** **** **** +7687 Telflammar_Shadow_Still_Chill_Touch **** **** **** **** **** **** **** **** +7688 Telflammar_Shadow_Darkness **** **** **** **** **** **** **** **** +7689 Telflammar_Shadow_Exteneded_Darkness **** **** **** **** **** **** **** **** +7690 Telflammar_Shadow_Silent_Darkness **** **** **** **** **** **** **** **** +7691 Telflammar_Shadow_Shadow_Spray **** **** **** **** **** **** **** **** +7692 Telflammar_Shadow_Empowered_Shadow_Spray **** **** **** **** **** **** **** **** +7693 Telflammar_Shadow_Exteneded_Shadow_Spray **** **** **** **** **** **** **** **** +7694 Telflammar_Shadow_Silent_Shadow_Spray **** **** **** **** **** **** **** **** +7695 Telflammar_Shadow_Still_Shadow_Spray **** **** **** **** **** **** **** **** +7696 Telflammar_Shadow_Invisibility **** **** **** **** **** **** **** **** +7697 Telflammar_Shadow_Exteneded_Invisibility **** **** **** **** **** **** **** **** +7698 Telflammar_Shadow_Silent_Invisibility **** **** **** **** **** **** **** **** +7699 Telflammar_Shadow_Still_Invisibility **** **** **** **** **** **** **** **** +7700 Telflammar_Shadow_Knock **** **** **** **** **** **** **** **** +7701 Telflammar_Shadow_Still_Knock **** **** **** **** **** **** **** **** +7702 Telflammar_Shadow_SEETHING_EYEBANE **** **** **** **** **** **** **** **** +7703 Telflammar_Shadow_Silent_SEETHING_EYEBANE **** **** **** **** **** **** **** **** +7704 Telflammar_Shadow_Still_SEETHING_EYEBANE **** **** **** **** **** **** **** **** +7705 Telflammar_Shadow_Blacklight **** **** **** **** **** **** **** **** +7706 Telflammar_Shadow_Exteneded_Blacklight **** **** **** **** **** **** **** **** +7707 Telflammar_Shadow_Silent_Blacklight **** **** **** **** **** **** **** **** +7708 Telflammar_Shadow_Still_Blacklight **** **** **** **** **** **** **** **** +7709 Telflammar_Shadow_Displacement **** **** **** **** **** **** **** **** +7710 Telflammar_Shadow_Exteneded_Displacement **** **** **** **** **** **** **** **** +7711 Telflammar_Shadow_Silent_Displacement **** **** **** **** **** **** **** **** +7712 Telflammar_Shadow_Haste **** **** **** **** **** **** **** **** +7713 Telflammar_Shadow_Exteneded_Haste **** **** **** **** **** **** **** **** +7714 Telflammar_Shadow_Silent_Haste **** **** **** **** **** **** **** **** +7715 Telflammar_Shadow_Still_Haste **** **** **** **** **** **** **** **** +7716 Telflammar_Shadow_Improved_Invisibility **** **** **** **** **** **** **** **** +7717 Telflammar_Shadow_Exteneded_Improved_Invisibility **** **** **** **** **** **** **** **** +7718 Telflammar_Shadow_Silent_Improved_Invisibility **** **** **** **** **** **** **** **** +7719 Telflammar_Shadow_Still_Improved_Invisibility **** **** **** **** **** **** **** **** +7720 Telflammar_Shadow_Vampiric_Touch **** **** **** **** **** **** **** **** +7721 Telflammar_Shadow_Silent_Vampiric_Touch **** **** **** **** **** **** **** **** +7722 Telflammar_Shadow_Still_Vampiric_Touch **** **** **** **** **** **** **** **** +7723 Telflammar_Shadow_NONDETECTION **** **** **** **** **** **** **** **** +7724 Telflammar_Shadow_Exteneded_NONDETECTION **** **** **** **** **** **** **** **** +7725 Telflammar_Shadow_Silent_NONDETECTION **** **** **** **** **** **** **** **** +7726 Telflammar_Shadow_Still_NONDETECTION **** **** **** **** **** **** **** **** +7727 Telflammar_Shadow_LAHMS_FINGER_DARTS **** **** **** **** **** **** **** **** +7728 Telflammar_Shadow_Silent_LAHMS_FINGER_DARTS **** **** **** **** **** **** **** **** +7729 Telflammar_Shadow_Still_LAHMS_FINGER_DARTS **** **** **** **** **** **** **** **** +7730 Telflammar_Shadow_DimensionDoor_RadialMaster **** **** **** **** **** **** **** **** +7731 Telflammar_Shadow_DimensionDoor_SelfOnly **** **** **** **** **** **** **** **** +7732 Telflammar_Shadow_DimensionDoor_Party **** **** **** **** **** **** **** **** +7733 Telflammar_Shadow_DimensionDoor_DirDist_SelfOnly **** **** **** **** **** **** **** **** +7734 Telflammar_Shadow_DimensionDoor_DirDist_Party **** **** **** **** **** **** **** **** +7735 Telflammar_Shadow_Confusion **** **** **** **** **** **** **** **** +7736 Telflammar_Shadow_DarkBolt **** **** **** **** **** **** **** **** +7737 Telflammar_Shadow_DarkBolt_all **** **** **** **** **** **** **** **** +7738 Telflammar_Shadow_DarkBolt_1 **** **** **** **** **** **** **** **** +7739 Telflammar_Shadow_Invisibility_Sphere **** **** **** **** **** **** **** **** +7740 Telflammar_Shadow_Mislead **** **** **** **** **** **** **** **** +7741 Telflammar_Shadow_DetectScrying **** **** **** **** **** **** **** **** +7742 Telflammar_Shadow_RED_FESTER **** **** **** **** **** **** **** **** +7743 Telflammar_Shadow_ROTTING_CURSE_OF_URFESTRA **** **** **** **** **** **** **** **** +7744 Telflammar_Shadow_TOUCH_OF_JUIBLEX **** **** **** **** **** **** **** **** +7745 Telflammar_Shadow_MASOCHISM **** **** **** **** **** **** **** **** +7746 JusticeOfWealdAnd_Camoflage **** **** **** **** **** **** **** **** +7747 JusticeOfWealdAnd_Endure_Elements **** **** **** **** **** **** **** **** +7748 JusticeOfWealdAnd_Faerie_Fire **** **** **** **** **** **** **** **** +7749 JusticeOfWealdAnd_HideFromAnimals **** **** **** **** **** **** **** **** +7750 JusticeOfWealdAnd_Spell_Jump **** **** **** **** **** **** **** **** +7751 JusticeOfWealdAnd_Longstrider **** **** **** **** **** **** **** **** +7752 JusticeOfWealdAnd_Obscuring_Mist **** **** **** **** **** **** **** **** +7753 JusticeOfWealdAnd_Barkskin **** **** **** **** **** **** **** **** +7754 JusticeOfWealdAnd_BrilliantEnergyArrows **** **** **** **** **** **** **** **** +7755 JusticeOfWealdAnd_Cats_Grace **** **** **** **** **** **** **** **** +7756 JusticeOfWealdAnd_FogCloud **** **** **** **** **** **** **** **** +7757 JusticeOfWealdAnd_Snare **** **** **** **** **** **** **** **** +7758 JusticeOfWealdAnd_SpellslayerArrow **** **** **** **** **** **** **** **** +7759 JusticeOfWealdAnd_Treeshape **** **** **** **** **** **** **** **** +7760 JusticeOfWealdAnd_ArrowSplit **** **** **** **** **** **** **** **** +7761 JusticeOfWealdAnd_DarkflameArrow **** **** **** **** **** **** **** **** +7762 JusticeOfWealdAnd_Ultravision **** **** **** **** **** **** **** **** +7763 JusticeOfWealdAnd_SerpentArrows **** **** **** **** **** **** **** **** +7764 JusticeOfWealdAnd_Spike_Growth **** **** **** **** **** **** **** **** +7765 JusticeOfWealdAnd_WaterBreathing **** **** **** **** **** **** **** **** +7766 JusticeOfWealdAnd_BloodfreezeArrow **** **** **** **** **** **** **** **** +7767 JusticeOfWealdAnd_DoublestrikeArrow **** **** **** **** **** **** **** **** +7768 JusticeOfWealdAnd_Freedom_of_Movement **** **** **** **** **** **** **** **** +7769 JusticeOfWealdAnd_Poison **** **** **** **** **** **** **** **** +7770 JusticeOfWealdAnd_Scrying **** **** **** **** **** **** **** **** +7771 JusticeOfWealdAnd_ShadowArrow **** **** **** **** **** **** **** **** +7772 KnightMiddleCircl_Bless **** **** **** **** **** **** **** **** +7773 KnightMiddleCircl_Exteneded_Bless **** **** **** **** **** **** **** **** +7774 KnightMiddleCircl_Silent_Bless **** **** **** **** **** **** **** **** +7775 KnightMiddleCircl_Still_Bless **** **** **** **** **** **** **** **** +7776 KnightMiddleCircl_Bless_Weapon **** **** **** **** **** **** **** **** +7777 KnightMiddleCircl_Exteneded_Bless_Weapon **** **** **** **** **** **** **** **** +7778 KnightMiddleCircl_Silent_Bless_Weapon **** **** **** **** **** **** **** **** +7779 KnightMiddleCircl_Still_Bless_Weapon **** **** **** **** **** **** **** **** +7780 KnightMiddleCircl_Cure_Light_Wounds **** **** **** **** **** **** **** **** +7781 KnightMiddleCircl_Empowered_Cure_Light_Wounds **** **** **** **** **** **** **** **** +7782 KnightMiddleCircl_Silent_Cure_Light_Wounds **** **** **** **** **** **** **** **** +7783 KnightMiddleCircl_Still_Cure_Light_Wounds **** **** **** **** **** **** **** **** +7784 KnightMiddleCircl_DETECT_UNDEAD **** **** **** **** **** **** **** **** +7785 KnightMiddleCircl_Exteneded_DETECT_UNDEAD **** **** **** **** **** **** **** **** +7786 KnightMiddleCircl_Silent_DETECT_UNDEAD **** **** **** **** **** **** **** **** +7787 KnightMiddleCircl_Still_DETECT_UNDEAD **** **** **** **** **** **** **** **** +7788 KnightMiddleCircl_Divine_Favor **** **** **** **** **** **** **** **** +7789 KnightMiddleCircl_Exteneded_Divine_Favor **** **** **** **** **** **** **** **** +7790 KnightMiddleCircl_Silent_Divine_Favor **** **** **** **** **** **** **** **** +7791 KnightMiddleCircl_Still_Divine_Favor **** **** **** **** **** **** **** **** +7792 KnightMiddleCircl_Magic_Weapon **** **** **** **** **** **** **** **** +7793 KnightMiddleCircl_Exteneded_Magic_Weapon **** **** **** **** **** **** **** **** +7794 KnightMiddleCircl_Silent_Magic_Weapon **** **** **** **** **** **** **** **** +7795 KnightMiddleCircl_Still_Magic_Weapon **** **** **** **** **** **** **** **** +7796 KnightMiddleCircl_Protection_from_Evil **** **** **** **** **** **** **** **** +7797 KnightMiddleCircl_Exteneded_Protection_from_Evil **** **** **** **** **** **** **** **** +7798 KnightMiddleCircl_Silent_Protection_from_Evil **** **** **** **** **** **** **** **** +7799 KnightMiddleCircl_Still_Protection_from_Evil **** **** **** **** **** **** **** **** +7800 KnightMiddleCircl_Read_Magic **** **** **** **** **** **** **** **** +7801 KnightMiddleCircl_Silent_Read_Magic **** **** **** **** **** **** **** **** +7802 KnightMiddleCircl_Still_Read_Magic **** **** **** **** **** **** **** **** +7803 KnightMiddleCircl_DIVINE_INSPIRATION **** **** **** **** **** **** **** **** +7804 KnightMiddleCircl_Exteneded_DIVINE_INSPIRATION **** **** **** **** **** **** **** **** +7805 KnightMiddleCircl_TWILIGHT_LUCK **** **** **** **** **** **** **** **** +7806 KnightMiddleCircl_Exteneded_TWILIGHT_LUCK **** **** **** **** **** **** **** **** +7807 KnightMiddleCircl_Silent_TWILIGHT_LUCK **** **** **** **** **** **** **** **** +7808 KnightMiddleCircl_LANTERN_LIGHT **** **** **** **** **** **** **** **** +7809 KnightMiddleCircl_Empowered_LANTERN_LIGHT **** **** **** **** **** **** **** **** +7810 KnightMiddleCircl_Still_LANTERN_LIGHT **** **** **** **** **** **** **** **** +7811 KnightMiddleCircl_Aid **** **** **** **** **** **** **** **** +7812 KnightMiddleCircl_Exteneded_Aid **** **** **** **** **** **** **** **** +7813 KnightMiddleCircl_Silent_Aid **** **** **** **** **** **** **** **** +7814 KnightMiddleCircl_Still_Aid **** **** **** **** **** **** **** **** +7815 KnightMiddleCircl_Divine_Protection **** **** **** **** **** **** **** **** +7816 KnightMiddleCircl_Exteneded_Divine_Protection **** **** **** **** **** **** **** **** +7817 KnightMiddleCircl_Silent_Divine_Protection **** **** **** **** **** **** **** **** +7818 KnightMiddleCircl_Still_Divine_Protection **** **** **** **** **** **** **** **** +7819 KnightMiddleCircl_Conviction **** **** **** **** **** **** **** **** +7820 KnightMiddleCircl_Exteneded_Conviction **** **** **** **** **** **** **** **** +7821 KnightMiddleCircl_Silent_Conviction **** **** **** **** **** **** **** **** +7822 KnightMiddleCircl_Still_Conviction **** **** **** **** **** **** **** **** +7823 KnightMiddleCircl_ShieldOther **** **** **** **** **** **** **** **** +7824 KnightMiddleCircl_Exteneded_ShieldOther **** **** **** **** **** **** **** **** +7825 KnightMiddleCircl_Silent_ShieldOther **** **** **** **** **** **** **** **** +7826 KnightMiddleCircl_Still_ShieldOther **** **** **** **** **** **** **** **** +7827 KnightMiddleCircl_UndetectableAlignment **** **** **** **** **** **** **** **** +7828 KnightMiddleCircl_Exteneded_UndetectableAlignment **** **** **** **** **** **** **** **** +7829 KnightMiddleCircl_Silent_UndetectableAlignment **** **** **** **** **** **** **** **** +7830 KnightMiddleCircl_Still_UndetectableAlignment **** **** **** **** **** **** **** **** +7831 KnightMiddleCircl_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +7832 KnightMiddleCircl_Silent_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +7833 KnightMiddleCircl_Still_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +7834 KnightMiddleCircl_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +7835 KnightMiddleCircl_Exteneded_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +7836 KnightMiddleCircl_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +7837 KnightMiddleCircl_Dispel_Magic **** **** **** **** **** **** **** **** +7838 KnightMiddleCircl_Greater_Magic_Weapon **** **** **** **** **** **** **** **** +7839 KnightMiddleCircl_Prayer **** **** **** **** **** **** **** **** +7840 KnightMiddleCircl_BRILLIANT_EMANATION **** **** **** **** **** **** **** **** +7841 KnightMiddleCircl_HAMMER_OF_RIGHTEOUSNESS **** **** **** **** **** **** **** **** +7842 DreadNecromancer_ANGRY_ACHE **** **** **** **** **** **** **** **** +7843 DreadNecromancer_Bane **** **** **** **** **** **** **** **** +7844 DreadNecromancer_BESTOW_WOUND **** **** **** **** **** **** **** **** +7845 DreadNecromancer_Blade_of_Blood **** **** **** **** **** **** **** **** +7846 DreadNecromancer_Blade_of_Blood_1d6 **** **** **** **** **** **** **** **** +7847 DreadNecromancer_Blade_of_Blood_3d6 **** **** **** **** **** **** **** **** +7848 DreadNecromancer_Cause_Fear **** **** **** **** **** **** **** **** +7849 DreadNecromancer_Chill_Touch **** **** **** **** **** **** **** **** +7850 DreadNecromancer_DETECT_UNDEAD **** **** **** **** **** **** **** **** +7851 DreadNecromancer_Doom **** **** **** **** **** **** **** **** +7852 DreadNecromancer_HideFromUndead **** **** **** **** **** **** **** **** +7853 DreadNecromancer_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +7854 DreadNecromancer_Necrotic_Awareness **** **** **** **** **** **** **** **** +7855 DreadNecromancer_Negative_Energy_Ray **** **** **** **** **** **** **** **** +7856 DreadNecromancer_Ray_of_Enfeeblement **** **** **** **** **** **** **** **** +7857 DreadNecromancer_SummonUndeadI **** **** **** **** **** **** **** **** +7858 DreadNecromancer_UndetectableAlignment **** **** **** **** **** **** **** **** +7859 DreadNecromancer_Blindness_and_Deafness **** **** **** **** **** **** **** **** +7860 DreadNecromancer_BONEBLAST **** **** **** **** **** **** **** **** +7861 DreadNecromancer_Command_Undead **** **** **** **** **** **** **** **** +7862 DreadNecromancer_Curse_of_Impending_Blades **** **** **** **** **** **** **** **** +7863 DreadNecromancer_Darkness **** **** **** **** **** **** **** **** +7864 DreadNecromancer_Death_Armor **** **** **** **** **** **** **** **** +7865 DreadNecromancer_Death_Knell **** **** **** **** **** **** **** **** +7866 DreadNecromancer_FalseLife **** **** **** **** **** **** **** **** +7867 DreadNecromancer_Ghoul_Touch **** **** **** **** **** **** **** **** +7868 DreadNecromancer_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +7869 DreadNecromancer_LifeBolt **** **** **** **** **** **** **** **** +7870 DreadNecromancer_LifeBolt1Bolt **** **** **** **** **** **** **** **** +7871 DreadNecromancer_LifeBolt2Bolts **** **** **** **** **** **** **** **** +7872 DreadNecromancer_LifeBolt3Bolts **** **** **** **** **** **** **** **** +7873 DreadNecromancer_LifeBolt4Bolts **** **** **** **** **** **** **** **** +7874 DreadNecromancer_LifeBolt5Bolts **** **** **** **** **** **** **** **** +7875 DreadNecromancer_Living_Undeath **** **** **** **** **** **** **** **** +7876 DreadNecromancer_Necrotic_Cyst **** **** **** **** **** **** **** **** +7877 DreadNecromancer_Scare **** **** **** **** **** **** **** **** +7878 DreadNecromancer_SHRIVELING **** **** **** **** **** **** **** **** +7879 DreadNecromancer_SummonUndeadII **** **** **** **** **** **** **** **** +7880 DreadNecromancer_Animate_Dead **** **** **** **** **** **** **** **** +7881 DreadNecromancer_BONEBLADE **** **** **** **** **** **** **** **** +7882 DreadNecromancer_BONEBLADE_GREATSWORD **** **** **** **** **** **** **** **** +7883 DreadNecromancer_BONEBLADE_LONGSWORD **** **** **** **** **** **** **** **** +7884 DreadNecromancer_BONEBLADE_SHORTSWORD **** **** **** **** **** **** **** **** +7885 DreadNecromancer_CLUTCH_OF_ORCUS **** **** **** **** **** **** **** **** +7886 DreadNecromancer_CrushingDespair **** **** **** **** **** **** **** **** +7887 DreadNecromancer_Curse_of_Petty_Failing **** **** **** **** **** **** **** **** +7888 DreadNecromancer_GreaterDisruptUndead **** **** **** **** **** **** **** **** +7889 DreadNecromancer_HaltUndead **** **** **** **** **** **** **** **** +7890 DreadNecromancer_Inflict_Serious_Wounds **** **** **** **** **** **** **** **** +7891 DreadNecromancer_Legions_Curse_of_Impending_Blades **** **** **** **** **** **** **** **** +7892 DreadNecromancer_Magic_Circle_against_Chaos **** **** **** **** **** **** **** **** +7893 DreadNecromancer_Magic_Circle_against_Evil **** **** **** **** **** **** **** **** +7894 DreadNecromancer_Magic_Circle_against_Good **** **** **** **** **** **** **** **** +7895 DreadNecromancer_Magic_Circle_against_Law **** **** **** **** **** **** **** **** +7896 DreadNecromancer_Necrotic_Bloat **** **** **** **** **** **** **** **** +7897 DreadNecromancer_Negative_Energy_Burst **** **** **** **** **** **** **** **** +7898 DreadNecromancer_RayofExhaustion **** **** **** **** **** **** **** **** +7899 DreadNecromancer_Slashing_Darkness **** **** **** **** **** **** **** **** +7900 DreadNecromancer_SummonUndeadIII **** **** **** **** **** **** **** **** +7901 DreadNecromancer_UNLIVING_WEAPON **** **** **** **** **** **** **** **** +7902 DreadNecromancer_Vampiric_Touch **** **** **** **** **** **** **** **** +7903 DreadNecromancer_WRACK **** **** **** **** **** **** **** **** +7904 DreadNecromancer_Bestow_Curse **** **** **** **** **** **** **** **** +7905 DreadNecromancer_BloodOfTheMartyr **** **** **** **** **** **** **** **** +7906 DreadNecromancer_Contagion **** **** **** **** **** **** **** **** +7907 DreadNecromancer_Death_Ward **** **** **** **** **** **** **** **** +7908 DreadNecromancer_Dispel_Magic **** **** **** **** **** **** **** **** +7909 DreadNecromancer_Doom_Scarabs **** **** **** **** **** **** **** **** +7910 DreadNecromancer_Enervation **** **** **** **** **** **** **** **** +7911 DreadNecromancer_Evards_Black_Tentacles **** **** **** **** **** **** **** **** +7912 DreadNecromancer_Fear **** **** **** **** **** **** **** **** +7913 DreadNecromancer_GRIM_REVENGE **** **** **** **** **** **** **** **** +7914 DreadNecromancer_Inflict_Critical_Wounds **** **** **** **** **** **** **** **** +7915 DreadNecromancer_LIQUID_PAIN **** **** **** **** **** **** **** **** +7916 DreadNecromancer_Necrotic_Domination **** **** **** **** **** **** **** **** +7917 DreadNecromancer_Phantasmal_Killer **** **** **** **** **** **** **** **** +7918 DreadNecromancer_Poison **** **** **** **** **** **** **** **** +7919 DreadNecromancer_Sinsaburs_Baleful_Bolt **** **** **** **** **** **** **** **** +7920 DreadNecromancer_STOP_HEART **** **** **** **** **** **** **** **** +7921 DreadNecromancer_SummonUndeadIV **** **** **** **** **** **** **** **** +7922 DreadNecromancer_Beltyns_Burning_Blood **** **** **** **** **** **** **** **** +7923 DreadNecromancer_Circle_of_Doom **** **** **** **** **** **** **** **** +7924 DreadNecromancer_Cloudkill **** **** **** **** **** **** **** **** +7925 DreadNecromancer_FireInTheBlood **** **** **** **** **** **** **** **** +7926 DreadNecromancer_Greater_Dispelling **** **** **** **** **** **** **** **** +7927 DreadNecromancer_Legions_Curse_of_Petty_Failing **** **** **** **** **** **** **** **** +7928 DreadNecromancer_Lesser_Planar_Binding **** **** **** **** **** **** **** **** +7929 DreadNecromancer_Mass_Contagion **** **** **** **** **** **** **** **** +7930 DreadNecromancer_Mass_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +7931 DreadNecromancer_Necrotic_Burst **** **** **** **** **** **** **** **** +7932 DreadNecromancer_Nights_Caress **** **** **** **** **** **** **** **** +7933 DreadNecromancer_Slay_Living **** **** **** **** **** **** **** **** +7934 DreadNecromancer_Soulscour **** **** **** **** **** **** **** **** +7935 DreadNecromancer_SummonUndeadV **** **** **** **** **** **** **** **** +7936 DreadNecromancer_SYMBOL_OF_PAIN **** **** **** **** **** **** **** **** +7937 DreadNecromancer_Undeath_to_Death **** **** **** **** **** **** **** **** +7938 DreadNecromancer_WavesofFatigue **** **** **** **** **** **** **** **** +7939 DreadNecromancer_Acid_Fog **** **** **** **** **** **** **** **** +7940 DreadNecromancer_Circle_of_Death **** **** **** **** **** **** **** **** +7941 DreadNecromancer_Create_Undead **** **** **** **** **** **** **** **** +7942 DreadNecromancer_ECTOPLASMIC_ENCHANCEMENT **** **** **** **** **** **** **** **** +7943 DreadNecromancer_Eyebite **** **** **** **** **** **** **** **** +7944 DreadNecromancer_Ghoul_Gauntlet **** **** **** **** **** **** **** **** +7945 DreadNecromancer_Harm **** **** **** **** **** **** **** **** +7946 DreadNecromancer_Mass_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +7947 DreadNecromancer_Necrotic_Eruption **** **** **** **** **** **** **** **** +7948 DreadNecromancer_Planar_Binding **** **** **** **** **** **** **** **** +7949 DreadNecromancer_SYMBOL_OF_FEAR **** **** **** **** **** **** **** **** +7950 DreadNecromancer_WavesOfExhaustion **** **** **** **** **** **** **** **** +7951 DreadNecromancer_ArrowOfBone **** **** **** **** **** **** **** **** +7952 DreadNecromancer_Avasculate **** **** **** **** **** **** **** **** +7953 DreadNecromancer_Control_Undead **** **** **** **** **** **** **** **** +7954 DreadNecromancer_Destruction **** **** **** **** **** **** **** **** +7955 DreadNecromancer_Energy_Ebb **** **** **** **** **** **** **** **** +7956 DreadNecromancer_Finger_of_Death **** **** **** **** **** **** **** **** +7957 DreadNecromancer_Greater_Harm **** **** **** **** **** **** **** **** +7958 DreadNecromancer_Mass_Inflict_Serious_Wounds **** **** **** **** **** **** **** **** +7959 DreadNecromancer_SongOfDiscord **** **** **** **** **** **** **** **** +7960 DreadNecromancer_SYMBOL_OF_WEAKNESS **** **** **** **** **** **** **** **** +7961 DreadNecromancer_VileDeath **** **** **** **** **** **** **** **** +7962 DreadNecromancer_Avascular_Mass **** **** **** **** **** **** **** **** +7963 DreadNecromancer_Create_Greater_Undead **** **** **** **** **** **** **** **** +7964 DreadNecromancer_GUTWRENCH **** **** **** **** **** **** **** **** +7965 DreadNecromancer_Horrid_Wilting **** **** **** **** **** **** **** **** +7966 DreadNecromancer_LAST_JUDGEMENT **** **** **** **** **** **** **** **** +7967 DreadNecromancer_Mass_Inflict_Critical_Wounds **** **** **** **** **** **** **** **** +7968 DreadNecromancer_Necrotic_Empowerment **** **** **** **** **** **** **** **** +7969 DreadNecromancer_Pestilence **** **** **** **** **** **** **** **** +7970 DreadNecromancer_SYMBOL_OF_DEATH **** **** **** **** **** **** **** **** +7971 DreadNecromancer_Energy_Drain **** **** **** **** **** **** **** **** +7972 DreadNecromancer_Mass_Harm **** **** **** **** **** **** **** **** +7973 DreadNecromancer_Necrotic_Termination **** **** **** **** **** **** **** **** +7974 DreadNecromancer_PlagueOfUndead **** **** **** **** **** **** **** **** +7975 DreadNecromancer_Wail_of_the_Banshee **** **** **** **** **** **** **** **** +7976 ****_Cure_Minor_Wounds **** **** **** **** **** **** **** **** +7977 ****_Inflict_Minor_Wounds **** **** **** **** **** **** **** **** +7978 ****_Light **** **** **** **** **** **** **** **** +7979 ****_Read_Magic **** **** **** **** **** **** **** **** +7980 ****_Resistance **** **** **** **** **** **** **** **** +7981 ****_Virtue **** **** **** **** **** **** **** **** +7982 ****_ANGRY_ACHE **** **** **** **** **** **** **** **** +7983 ****_Bane **** **** **** **** **** **** **** **** +7984 ****_Blade_of_Blood **** **** **** **** **** **** **** **** +7985 ****_Blade_of_Blood_1d6 **** **** **** **** **** **** **** **** +7986 ****_Blade_of_Blood_3d6 **** **** **** **** **** **** **** **** +7987 ****_Bless **** **** **** **** **** **** **** **** +7988 ****_Bless_Water **** **** **** **** **** **** **** **** +7989 ****_Cause_Fear **** **** **** **** **** **** **** **** +7990 ****_Command_RadialMaster **** **** **** **** **** **** **** **** +7991 ****_Command_Approach **** **** **** **** **** **** **** **** +7992 ****_Command_Drop **** **** **** **** **** **** **** **** +7993 ****_Command_Fall **** **** **** **** **** **** **** **** +7994 ****_Command_Flee **** **** **** **** **** **** **** **** +7995 ****_Command_Halt **** **** **** **** **** **** **** **** +7996 ****_Conviction **** **** **** **** **** **** **** **** +7997 ****_Crafters_Blessing **** **** **** **** **** **** **** **** +7998 ****_Crafters_Curse **** **** **** **** **** **** **** **** +7999 ****_Cure_Light_Wounds **** **** **** **** **** **** **** **** +8000 ****_Curse_Water **** **** **** **** **** **** **** **** +8001 ****_Detect_Chaos **** **** **** **** **** **** **** **** +8002 ****_Detect_Evil **** **** **** **** **** **** **** **** +8003 ****_Detect_Good **** **** **** **** **** **** **** **** +8004 ****_Detect_Law **** **** **** **** **** **** **** **** +8005 ****_DETECT_UNDEAD **** **** **** **** **** **** **** **** +8006 ****_Divine_Favor **** **** **** **** **** **** **** **** +8007 ****_Doom **** **** **** **** **** **** **** **** +8008 ****_DRUG_RESISTANCE **** **** **** **** **** **** **** **** +8009 ****_Endure_Elements **** **** **** **** **** **** **** **** +8010 ****_Entropic_Shield **** **** **** **** **** **** **** **** +8011 ****_EXTRACT_DRUG **** **** **** **** **** **** **** **** +8012 ****_EXTRACT_BACCARAN **** **** **** **** **** **** **** **** +8013 ****_EXTRACT_VODARE **** **** **** **** **** **** **** **** +8014 ****_EXTRACT_SANNISH **** **** **** **** **** **** **** **** +8015 ****_EXTRACT_MUSHROOM_POWDER **** **** **** **** **** **** **** **** +8016 ****_EYES_OF_THE_AVORAL **** **** **** **** **** **** **** **** +8017 ****_HEARTACHE **** **** **** **** **** **** **** **** +8018 ****_HideFromUndead **** **** **** **** **** **** **** **** +8019 ****_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +8020 ****_LANTERN_LIGHT **** **** **** **** **** **** **** **** +8021 ****_LESSER_SHIVERING_TOUCH **** **** **** **** **** **** **** **** +8022 ****_Lesser_Vigor **** **** **** **** **** **** **** **** +8023 ****_Magic_Stone **** **** **** **** **** **** **** **** +8024 ****_Magic_Weapon **** **** **** **** **** **** **** **** +8025 ****_Necrotic_Awareness **** **** **** **** **** **** **** **** +8026 ****_Obscuring_Mist **** **** **** **** **** **** **** **** +8027 ****_Protection_from_Chaos **** **** **** **** **** **** **** **** +8028 ****_Protection_from_Evil **** **** **** **** **** **** **** **** +8029 ****_Protection_from_Good **** **** **** **** **** **** **** **** +8030 ****_Protection_from_Law **** **** **** **** **** **** **** **** +8031 ****_RAY_OF_HOPE **** **** **** **** **** **** **** **** +8032 ****_Remove_Fear **** **** **** **** **** **** **** **** +8033 ****_Sanctuary **** **** **** **** **** **** **** **** +8034 ****_Shield_of_Faith **** **** **** **** **** **** **** **** +8035 ****_SORROW **** **** **** **** **** **** **** **** +8036 ****_Summon_Creature_I **** **** **** **** **** **** **** **** +8037 ****_SummonUndeadI **** **** **** **** **** **** **** **** +8038 ****_TONGUE_OF_BAALZEBUL **** **** **** **** **** **** **** **** +8039 ****_VisionOfHeaven **** **** **** **** **** **** **** **** +8040 ****_ADDICTION **** **** **** **** **** **** **** **** +8041 ****_ADDICTION_TERRAN_BRANDY **** **** **** **** **** **** **** **** +8042 ****_ADDICTION_MUSHROOM_POWDER **** **** **** **** **** **** **** **** +8043 ****_ADDICTION_VODARE **** **** **** **** **** **** **** **** +8044 ****_ADDICTION_AGONY **** **** **** **** **** **** **** **** +8045 ****_Aid **** **** **** **** **** **** **** **** +8046 ****_Animalistic_Power **** **** **** **** **** **** **** **** +8047 ****_BONEBLAST **** **** **** **** **** **** **** **** +8048 ****_Bulls_Strength **** **** **** **** **** **** **** **** +8049 ****_Calm_Emotions **** **** **** **** **** **** **** **** +8050 ****_Consecrated_Aura **** **** **** **** **** **** **** **** +8051 ****_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +8052 ****_Darkness **** **** **** **** **** **** **** **** +8053 ****_Death_Knell **** **** **** **** **** **** **** **** +8054 ****_Divine_Protection **** **** **** **** **** **** **** **** +8055 ****_Eagle_Splendor **** **** **** **** **** **** **** **** +8056 ****_ELATION **** **** **** **** **** **** **** **** +8057 ****_Endurance **** **** **** **** **** **** **** **** +8058 ****_Find_Traps **** **** **** **** **** **** **** **** +8059 ****_Foxs_Cunning **** **** **** **** **** **** **** **** +8060 ****_Hold_Person **** **** **** **** **** **** **** **** +8061 ****_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +8062 ****_Lesser_Dispel **** **** **** **** **** **** **** **** +8063 ****_Lesser_Restoration **** **** **** **** **** **** **** **** +8064 ****_Living_Undeath **** **** **** **** **** **** **** **** +8065 ****_Necrotic_Cyst **** **** **** **** **** **** **** **** +8066 ****_Negative_Energy_Ray **** **** **** **** **** **** **** **** +8067 ****_Owls_Wisdom **** **** **** **** **** **** **** **** +8068 ****_Remove_Paralysis **** **** **** **** **** **** **** **** +8069 ****_Resist_Elements **** **** **** **** **** **** **** **** +8070 ****_ShieldOther **** **** **** **** **** **** **** **** +8071 ****_Silence **** **** **** **** **** **** **** **** +8072 ****_Sound_Burst **** **** **** **** **** **** **** **** +8073 ****_SPORES_OF_THE_VROCK **** **** **** **** **** **** **** **** +8074 ****_Stone_Bones **** **** **** **** **** **** **** **** +8075 ****_Summon_Creature_II **** **** **** **** **** **** **** **** +8076 ****_SummonUndeadII **** **** **** **** **** **** **** **** +8077 ****_Ultravision **** **** **** **** **** **** **** **** +8078 ****_UndetectableAlignment **** **** **** **** **** **** **** **** +8079 ****_WAVE_OF_GRIEF **** **** **** **** **** **** **** **** +8080 ****_Animate_Dead **** **** **** **** **** **** **** **** +8081 ****_Bestow_Curse **** **** **** **** **** **** **** **** +8082 ****_Blindness_and_Deafness **** **** **** **** **** **** **** **** +8083 ****_BONEBLADE **** **** **** **** **** **** **** **** +8084 ****_BONEBLADE_GREATSWORD **** **** **** **** **** **** **** **** +8085 ****_BONEBLADE_LONGSWORD **** **** **** **** **** **** **** **** +8086 ****_BONEBLADE_SHORTSWORD **** **** **** **** **** **** **** **** +8087 ****_Clarity **** **** **** **** **** **** **** **** +8088 ****_Close_Wounds **** **** **** **** **** **** **** **** +8089 ****_CLUTCH_OF_ORCUS **** **** **** **** **** **** **** **** +8090 ****_Contagion **** **** **** **** **** **** **** **** +8091 ****_Continual_Flame **** **** **** **** **** **** **** **** +8092 ****_Crown_Might **** **** **** **** **** **** **** **** +8093 ****_Crown_Protection **** **** **** **** **** **** **** **** +8094 ****_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +8095 ****_Curse_of_Petty_Failing **** **** **** **** **** **** **** **** +8096 ****_Darkfire **** **** **** **** **** **** **** **** +8097 ****_Daylight **** **** **** **** **** **** **** **** +8098 ****_DeeperDarkness **** **** **** **** **** **** **** **** +8099 ****_DEVILS_EYE **** **** **** **** **** **** **** **** +8100 ****_Dispel_Magic **** **** **** **** **** **** **** **** +8101 ****_ENERGIZE_POTION **** **** **** **** **** **** **** **** +8102 ****_ENERGIZE_POTION_ACID **** **** **** **** **** **** **** **** +8103 ****_ENERGIZE_POTION_COLD **** **** **** **** **** **** **** **** +8104 ****_ENERGIZE_POTION_ELECTRICITY **** **** **** **** **** **** **** **** +8105 ****_ENERGIZE_POTION_FIRE **** **** **** **** **** **** **** **** +8106 ****_ENERGIZE_POTION_SONIC **** **** **** **** **** **** **** **** +8107 ****_Energy_Aegis **** **** **** **** **** **** **** **** +8108 ****_Energy_Aegis_Acid **** **** **** **** **** **** **** **** +8109 ****_Energy_Aegis_Cold **** **** **** **** **** **** **** **** +8110 ****_Energy_Aegis_Elec **** **** **** **** **** **** **** **** +8111 ****_Energy_Aegis_Fire **** **** **** **** **** **** **** **** +8112 ****_Energy_Aegis_Sonic **** **** **** **** **** **** **** **** +8113 ****_FLESH_RIPPER **** **** **** **** **** **** **** **** +8114 ****_Glyph_of_Warding_Master **** **** **** **** **** **** **** **** +8115 ****_Glyph_of_Warding_Acid **** **** **** **** **** **** **** **** +8116 ****_Glyph_of_Warding_Cold **** **** **** **** **** **** **** **** +8117 ****_Glyph_of_Warding_Electricity **** **** **** **** **** **** **** **** +8118 ****_Glyph_of_Warding_Fire **** **** **** **** **** **** **** **** +8119 ****_Glyph_of_Warding_Sonic **** **** **** **** **** **** **** **** +8120 ****_Inflict_Serious_Wounds **** **** **** **** **** **** **** **** +8121 ****_Invisibility_Purge **** **** **** **** **** **** **** **** +8122 ****_Legions_Conviction **** **** **** **** **** **** **** **** +8123 ****_LocateObject **** **** **** **** **** **** **** **** +8124 ****_Magic_Circle_against_Chaos **** **** **** **** **** **** **** **** +8125 ****_Magic_Circle_against_Evil **** **** **** **** **** **** **** **** +8126 ****_Magic_Circle_against_Good **** **** **** **** **** **** **** **** +8127 ****_Magic_Circle_against_Law **** **** **** **** **** **** **** **** +8128 ****_Magic_Vestment **** **** **** **** **** **** **** **** +8129 ****_MASOCHISM **** **** **** **** **** **** **** **** +8130 ****_Mass_Aid **** **** **** **** **** **** **** **** +8131 ****_Mass_Lesser_Vigor **** **** **** **** **** **** **** **** +8132 ****_Necrotic_Bloat **** **** **** **** **** **** **** **** +8133 ****_Negative_Energy_Protection **** **** **** **** **** **** **** **** +8134 ****_ObscureObject **** **** **** **** **** **** **** **** +8135 ****_Prayer **** **** **** **** **** **** **** **** +8136 ****_Protection_from_Elements **** **** **** **** **** **** **** **** +8137 ****_Remove_Blindness_and_Deafness **** **** **** **** **** **** **** **** +8138 ****_Remove_Curse **** **** **** **** **** **** **** **** +8139 ****_Remove_Disease **** **** **** **** **** **** **** **** +8140 ****_RingOfBlades **** **** **** **** **** **** **** **** +8141 ****_Searing_Light **** **** **** **** **** **** **** **** +8142 ****_SHIVERING_TOUCH **** **** **** **** **** **** **** **** +8143 ****_SHRIVELING **** **** **** **** **** **** **** **** +8144 ****_Slashing_Darkness **** **** **** **** **** **** **** **** +8145 ****_Summon_Creature_III **** **** **** **** **** **** **** **** +8146 ****_SummonUndeadIII **** **** **** **** **** **** **** **** +8147 ****_UNLIVING_WEAPON **** **** **** **** **** **** **** **** +8148 ****_Vigor **** **** **** **** **** **** **** **** +8149 ****_WaterBreathing **** **** **** **** **** **** **** **** +8150 ****_WRACK **** **** **** **** **** **** **** **** +8151 ****_ABYSSAL_MIGHT **** **** **** **** **** **** **** **** +8152 ****_BloodOfTheMartyr **** **** **** **** **** **** **** **** +8153 ****_CLAWS_OF_THE_SAVAGE **** **** **** **** **** **** **** **** +8154 ****_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +8155 ****_DAMNING_DARKNESS **** **** **** **** **** **** **** **** +8156 ****_Death_Ward **** **** **** **** **** **** **** **** +8157 ****_Dimensional_Anchor **** **** **** **** **** **** **** **** +8158 ****_Dismissal **** **** **** **** **** **** **** **** +8159 ****_Divine_Power **** **** **** **** **** **** **** **** +8160 ****_Freedom_of_Movement **** **** **** **** **** **** **** **** +8161 ****_Greater_Magic_Weapon **** **** **** **** **** **** **** **** +8162 ****_Greater_Resistance **** **** **** **** **** **** **** **** +8163 ****_Hammer_of_the_Gods **** **** **** **** **** **** **** **** +8164 ****_Inflict_Critical_Wounds **** **** **** **** **** **** **** **** +8165 ****_Legions_Shield_of_Faith **** **** **** **** **** **** **** **** +8166 ****_Lesser_Planar_Ally **** **** **** **** **** **** **** **** +8167 ****_Lower_Spell_Resistance **** **** **** **** **** **** **** **** +8168 ****_Mass_Ultravision **** **** **** **** **** **** **** **** +8169 ****_Necrotic_Domination **** **** **** **** **** **** **** **** +8170 ****_Neutralize_Poison **** **** **** **** **** **** **** **** +8171 ****_Panacea **** **** **** **** **** **** **** **** +8172 ****_Poison **** **** **** **** **** **** **** **** +8173 ****_Recitation **** **** **** **** **** **** **** **** +8174 ****_RepelVermin **** **** **** **** **** **** **** **** +8175 ****_Restoration **** **** **** **** **** **** **** **** +8176 ****_STOP_HEART **** **** **** **** **** **** **** **** +8177 ****_Summon_Creature_IV **** **** **** **** **** **** **** **** +8178 ****_SummonUndeadIV **** **** **** **** **** **** **** **** +8179 ****_SwordOfConscience **** **** **** **** **** **** **** **** +8180 ****_Battletide **** **** **** **** **** **** **** **** +8181 ****_BreakEnchantment **** **** **** **** **** **** **** **** +8182 ****_CHAAVS_LAUGH **** **** **** **** **** **** **** **** +8183 ****_Circle_of_Doom **** **** **** **** **** **** **** **** +8184 ****_CONVERT_WAND **** **** **** **** **** **** **** **** +8185 ****_DANCING_WEB **** **** **** **** **** **** **** **** +8186 ****_FireInTheBlood **** **** **** **** **** **** **** **** +8187 ****_Flame_Strike **** **** **** **** **** **** **** **** +8188 ****_Greater_Vigor(Monstrous_Regeneration) **** **** **** **** **** **** **** **** +8189 ****_GreaterCommand_RadialMaster **** **** **** **** **** **** **** **** +8190 ****_GreaterCommand_Approach **** **** **** **** **** **** **** **** +8191 ****_GreaterCommand_Drop **** **** **** **** **** **** **** **** +8192 ****_GreaterCommand_Fall **** **** **** **** **** **** **** **** +8193 ****_GreaterCommand_Flee **** **** **** **** **** **** **** **** +8194 ****_GreaterCommand_Halt **** **** **** **** **** **** **** **** +8195 ****_Healing_Circle **** **** **** **** **** **** **** **** +8196 ****_HEARTCLUTCH **** **** **** **** **** **** **** **** +8197 ****_Legions_Curse_of_Petty_Failing **** **** **** **** **** **** **** **** +8198 ****_Mass_Contagion **** **** **** **** **** **** **** **** +8199 ****_Mass_Cure_Light_Wounds **** **** **** **** **** **** **** **** +8200 ****_Mass_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +8201 ****_MORALITY_UNDONE **** **** **** **** **** **** **** **** +8202 ****_Necrotic_Burst **** **** **** **** **** **** **** **** +8203 ****_Raise_Dead **** **** **** **** **** **** **** **** +8204 ****_RESONATING_RESISTANCE **** **** **** **** **** **** **** **** +8205 ****_Revivify **** **** **** **** **** **** **** **** +8206 ****_Righteous_Might **** **** **** **** **** **** **** **** +8207 ****_Scrying **** **** **** **** **** **** **** **** +8208 ****_Slay_Living **** **** **** **** **** **** **** **** +8209 ****_Soulscour **** **** **** **** **** **** **** **** +8210 ****_Spell_Resistance **** **** **** **** **** **** **** **** +8211 ****_Summon_Creature_V **** **** **** **** **** **** **** **** +8212 ****_SummonUndeadV **** **** **** **** **** **** **** **** +8213 ****_SYMBOL_OF_PAIN **** **** **** **** **** **** **** **** +8214 ****_SYMBOL_OF_SLEEP **** **** **** **** **** **** **** **** +8215 ****_True_Seeing **** **** **** **** **** **** **** **** +8216 ****_Animate_Object **** **** **** **** **** **** **** **** +8217 ****_Banishment **** **** **** **** **** **** **** **** +8218 ****_Blade_Barrier **** **** **** **** **** **** **** **** +8219 ****_CALL_FAITHFUL_SERVANTS **** **** **** **** **** **** **** **** +8220 ****_CELESTIAL_BLOOD **** **** **** **** **** **** **** **** +8221 ****_CLOUD_OF_THE_ACHAIERAI **** **** **** **** **** **** **** **** +8222 ****_Control_Undead **** **** **** **** **** **** **** **** +8223 ****_Create_Undead **** **** **** **** **** **** **** **** +8224 ****_Energy_Immunity **** **** **** **** **** **** **** **** +8225 ****_EI_Acid **** **** **** **** **** **** **** **** +8226 ****_EI_Cold **** **** **** **** **** **** **** **** +8227 ****_EI_Elec **** **** **** **** **** **** **** **** +8228 ****_EI_Fire **** **** **** **** **** **** **** **** +8229 ****_EI_Sonic **** **** **** **** **** **** **** **** +8230 ****_Etherealness **** **** **** **** **** **** **** **** +8231 ****_Greater_Dispelling **** **** **** **** **** **** **** **** +8232 ****_Greater_Glyph_of_Warding_Master **** **** **** **** **** **** **** **** +8233 ****_Greater_Glyph_of_Warding_Acid **** **** **** **** **** **** **** **** +8234 ****_Greater_Glyph_of_Warding_Cold **** **** **** **** **** **** **** **** +8235 ****_Greater_Glyph_of_Warding_Electricity **** **** **** **** **** **** **** **** +8236 ****_Greater_Glyph_of_Warding_Fire **** **** **** **** **** **** **** **** +8237 ****_Greater_Glyph_of_Warding_Sonic **** **** **** **** **** **** **** **** +8238 ****_Harm **** **** **** **** **** **** **** **** +8239 ****_Heal **** **** **** **** **** **** **** **** +8240 ****_Mass_Bulls_Strength **** **** **** **** **** **** **** **** +8241 ****_Mass_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +8242 ****_Mass_Eagle_Splendor **** **** **** **** **** **** **** **** +8243 ****_Mass_Endurance **** **** **** **** **** **** **** **** +8244 ****_Mass_Foxs_Cunning **** **** **** **** **** **** **** **** +8245 ****_Mass_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +8246 ****_Mass_Owls_Wisdom **** **** **** **** **** **** **** **** +8247 ****_Necrotic_Eruption **** **** **** **** **** **** **** **** +8248 ****_Planar_Ally **** **** **** **** **** **** **** **** +8249 ****_SarcophagusOfStone **** **** **** **** **** **** **** **** +8250 ****_Summon_Creature_VI **** **** **** **** **** **** **** **** +8251 ****_Superior_Resistance **** **** **** **** **** **** **** **** +8252 ****_SYMBOL_OF_FEAR **** **** **** **** **** **** **** **** +8253 ****_SYMBOL_OF_PERSUASION **** **** **** **** **** **** **** **** +8254 ****_THOUSAND_NEEDLES **** **** **** **** **** **** **** **** +8255 ****_Undeath_to_Death **** **** **** **** **** **** **** **** +8256 ****_Vigorous_Circle **** **** **** **** **** **** **** **** +8257 ****_WordOfRecall_RadialMaster **** **** **** **** **** **** **** **** +8258 ****_WordOfRecall_SelfOnly **** **** **** **** **** **** **** **** +8259 ****_WordOfRecall_Party **** **** **** **** **** **** **** **** +8260 ****_Blasphemy **** **** **** **** **** **** **** **** +8261 ****_Control_Weather **** **** **** **** **** **** **** **** +8262 ****_CW_Rain **** **** **** **** **** **** **** **** +8263 ****_CW_Snow **** **** **** **** **** **** **** **** +8264 ****_CW_Clear **** **** **** **** **** **** **** **** +8265 ****_Destruction **** **** **** **** **** **** **** **** +8266 ****_Dictum **** **** **** **** **** **** **** **** +8267 ****_Energy_Ebb **** **** **** **** **** **** **** **** +8268 ****_FIENDISH_CLARITY **** **** **** **** **** **** **** **** +8269 ****_Greater_Harm **** **** **** **** **** **** **** **** +8270 ****_Greater_Restoration **** **** **** **** **** **** **** **** +8271 ****_GreaterScrying **** **** **** **** **** **** **** **** +8272 ****_Holy_Word **** **** **** **** **** **** **** **** +8273 ****_Mass_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +8274 ****_Mass_Inflict_Serious_Wounds **** **** **** **** **** **** **** **** +8275 ****_Mass_Spell_Resistance **** **** **** **** **** **** **** **** +8276 ****_Regenerate **** **** **** **** **** **** **** **** +8277 ****_Repulsion **** **** **** **** **** **** **** **** +8278 ****_Resurrection **** **** **** **** **** **** **** **** +8279 ****_RIGHTEOUS_SMITE **** **** **** **** **** **** **** **** +8280 ****_Summon_Creature_VII **** **** **** **** **** **** **** **** +8281 ****_Summon7Air **** **** **** **** **** **** **** **** +8282 ****_Summon7Earth **** **** **** **** **** **** **** **** +8283 ****_Summon7Fire **** **** **** **** **** **** **** **** +8284 ****_Summon7Water **** **** **** **** **** **** **** **** +8285 ****_SYMBOL_OF_STUNING **** **** **** **** **** **** **** **** +8286 ****_SYMBOL_OF_WEAKNESS **** **** **** **** **** **** **** **** +8287 ****_TOMB_OF_LIGHT **** **** **** **** **** **** **** **** +8288 ****_Word_of_Chaos **** **** **** **** **** **** **** **** +8289 ****_WRETCHED_BLIGHT **** **** **** **** **** **** **** **** +8290 ****_ANTIMAGIC_FIELD **** **** **** **** **** **** **** **** +8291 ****_Aura_versus_Alignment **** **** **** **** **** **** **** **** +8292 ****_Unholy_Aura **** **** **** **** **** **** **** **** +8293 ****_Holy_Aura **** **** **** **** **** **** **** **** +8294 ****_BODAK_BIRTH **** **** **** **** **** **** **** **** +8295 ****_Create_Greater_Undead **** **** **** **** **** **** **** **** +8296 ****_Dimensional_Lock **** **** **** **** **** **** **** **** +8297 ****_DiscernLocation **** **** **** **** **** **** **** **** +8298 ****_Earthquake **** **** **** **** **** **** **** **** +8299 ****_Fire_Storm **** **** **** **** **** **** **** **** +8300 ****_Greater_Planar_Ally **** **** **** **** **** **** **** **** +8301 ****_Greater_Wall_of_Dispel_Magic **** **** **** **** **** **** **** **** +8302 ****_Holy_Aura **** **** **** **** **** **** **** **** +8303 ****_LAST_JUDGEMENT **** **** **** **** **** **** **** **** +8304 ****_Mass_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +8305 ****_Mass_Heal **** **** **** **** **** **** **** **** +8306 ****_Mass_Inflict_Critical_Wounds **** **** **** **** **** **** **** **** +8307 ****_Necrotic_Empowerment **** **** **** **** **** **** **** **** +8308 ****_Pestilence **** **** **** **** **** **** **** **** +8309 ****_Summon_Creature_VIII **** **** **** **** **** **** **** **** +8310 ****_Summon8Air **** **** **** **** **** **** **** **** +8311 ****_Summon8Earth **** **** **** **** **** **** **** **** +8312 ****_Summon8Fire **** **** **** **** **** **** **** **** +8313 ****_Summon8Water **** **** **** **** **** **** **** **** +8314 ****_Sunbeam **** **** **** **** **** **** **** **** +8315 ****_SYMBOL_OF_DEATH **** **** **** **** **** **** **** **** +8316 ****_SYMBOL_OF_INSANITY **** **** **** **** **** **** **** **** +8317 ****_DESPOIL **** **** **** **** **** **** **** **** +8318 ****_Elder_Glyph_of_Warding_Master **** **** **** **** **** **** **** **** +8319 ****_Elder_Glyph_of_Warding_Acid **** **** **** **** **** **** **** **** +8320 ****_Elder_Glyph_of_Warding_Cold **** **** **** **** **** **** **** **** +8321 ****_Elder_Glyph_of_Warding_Electricity **** **** **** **** **** **** **** **** +8322 ****_Elder_Glyph_of_Warding_Fire **** **** **** **** **** **** **** **** +8323 ****_Elder_Glyph_of_Warding_Sonic **** **** **** **** **** **** **** **** +8324 ****_Energy_Drain **** **** **** **** **** **** **** **** +8325 ****_Gate **** **** **** **** **** **** **** **** +8326 ****_Implosion **** **** **** **** **** **** **** **** +8327 ****_Mass_Harm **** **** **** **** **** **** **** **** +8328 ****_Necrotic_Termination **** **** **** **** **** **** **** **** +8329 ****_PlagueOfUndead **** **** **** **** **** **** **** **** +8330 ****_Storm_of_Vengeance **** **** **** **** **** **** **** **** +8331 ****_Summon_Creature_IX **** **** **** **** **** **** **** **** +8332 ****_Summon9Air **** **** **** **** **** **** **** **** +8333 ****_Summon9Earth **** **** **** **** **** **** **** **** +8334 ****_Summon9Fire **** **** **** **** **** **** **** **** +8335 ****_Summon9Water **** **** **** **** **** **** **** **** +8336 ****_True_Resurrection **** **** **** **** **** **** **** **** +8337 ****_Undeaths_Eternal_Foe **** **** **** **** **** **** **** **** +8338 ****_VileDeath **** **** **** **** **** **** **** **** +8339 Archivist_Cure_Minor_Wounds **** **** **** **** **** **** **** **** +8340 Archivist_Quickened_Cure_Minor_Wounds **** **** **** **** **** **** **** **** +8341 Archivist_Silent_Cure_Minor_Wounds **** **** **** **** **** **** **** **** +8342 Archivist_Still_Cure_Minor_Wounds **** **** **** **** **** **** **** **** +8343 Archivist_Flare **** **** **** **** **** **** **** **** +8344 Archivist_Exteneded_Flare **** **** **** **** **** **** **** **** +8345 Archivist_Quickened_Flare **** **** **** **** **** **** **** **** +8346 Archivist_Silent_Flare **** **** **** **** **** **** **** **** +8347 Archivist_Inflict_Minor_Wounds **** **** **** **** **** **** **** **** +8348 Archivist_Quickened_Inflict_Minor_Wounds **** **** **** **** **** **** **** **** +8349 Archivist_Silent_Inflict_Minor_Wounds **** **** **** **** **** **** **** **** +8350 Archivist_Still_Inflict_Minor_Wounds **** **** **** **** **** **** **** **** +8351 Archivist_Light **** **** **** **** **** **** **** **** +8352 Archivist_Exteneded_Light **** **** **** **** **** **** **** **** +8353 Archivist_Quickened_Light **** **** **** **** **** **** **** **** +8354 Archivist_Silent_Light **** **** **** **** **** **** **** **** +8355 Archivist_Read_Magic **** **** **** **** **** **** **** **** +8356 Archivist_Quickened_Read_Magic **** **** **** **** **** **** **** **** +8357 Archivist_Silent_Read_Magic **** **** **** **** **** **** **** **** +8358 Archivist_Still_Read_Magic **** **** **** **** **** **** **** **** +8359 Archivist_Resistance **** **** **** **** **** **** **** **** +8360 Archivist_Exteneded_Resistance **** **** **** **** **** **** **** **** +8361 Archivist_Quickened_Resistance **** **** **** **** **** **** **** **** +8362 Archivist_Silent_Resistance **** **** **** **** **** **** **** **** +8363 Archivist_Still_Resistance **** **** **** **** **** **** **** **** +8364 Archivist_Virtue **** **** **** **** **** **** **** **** +8365 Archivist_Exteneded_Virtue **** **** **** **** **** **** **** **** +8366 Archivist_Quickened_Virtue **** **** **** **** **** **** **** **** +8367 Archivist_Silent_Virtue **** **** **** **** **** **** **** **** +8368 Archivist_Still_Virtue **** **** **** **** **** **** **** **** +8369 Archivist_ANGRY_ACHE **** **** **** **** **** **** **** **** +8370 Archivist_Exteneded_ANGRY_ACHE **** **** **** **** **** **** **** **** +8371 Archivist_Quickened_ANGRY_ACHE **** **** **** **** **** **** **** **** +8372 Archivist_Silent_ANGRY_ACHE **** **** **** **** **** **** **** **** +8373 Archivist_Still_ANGRY_ACHE **** **** **** **** **** **** **** **** +8374 Archivist_Bane **** **** **** **** **** **** **** **** +8375 Archivist_Exteneded_Bane **** **** **** **** **** **** **** **** +8376 Archivist_Quickened_Bane **** **** **** **** **** **** **** **** +8377 Archivist_Silent_Bane **** **** **** **** **** **** **** **** +8378 Archivist_Still_Bane **** **** **** **** **** **** **** **** +8379 Archivist_Blade_of_Blood **** **** **** **** **** **** **** **** +8380 Archivist_Blade_of_Blood_1d6 **** **** **** **** **** **** **** **** +8381 Archivist_Blade_of_Blood_3d6 **** **** **** **** **** **** **** **** +8382 Archivist_Empowered_Blade_of_Blood **** **** **** **** **** **** **** **** +8383 Archivist_Empowered_Blade_of_Blood_1d6 **** **** **** **** **** **** **** **** +8384 Archivist_Empowered_Blade_of_Blood_3d6 **** **** **** **** **** **** **** **** +8385 Archivist_Exteneded_Blade_of_Blood **** **** **** **** **** **** **** **** +8386 Archivist_Exteneded_Blade_of_Blood_1d6 **** **** **** **** **** **** **** **** +8387 Archivist_Exteneded_Blade_of_Blood_3d6 **** **** **** **** **** **** **** **** +8388 Archivist_Maximized_Blade_of_Blood **** **** **** **** **** **** **** **** +8389 Archivist_Maximized_Blade_of_Blood_1d6 **** **** **** **** **** **** **** **** +8390 Archivist_Maximized_Blade_of_Blood_3d6 **** **** **** **** **** **** **** **** +8391 Archivist_Quickened_Blade_of_Blood **** **** **** **** **** **** **** **** +8392 Archivist_Quickened_Blade_of_Blood_1d6 **** **** **** **** **** **** **** **** +8393 Archivist_Quickened_Blade_of_Blood_3d6 **** **** **** **** **** **** **** **** +8394 Archivist_Silent_Blade_of_Blood **** **** **** **** **** **** **** **** +8395 Archivist_Silent_Blade_of_Blood_1d6 **** **** **** **** **** **** **** **** +8396 Archivist_Silent_Blade_of_Blood_3d6 **** **** **** **** **** **** **** **** +8397 Archivist_Still_Blade_of_Blood **** **** **** **** **** **** **** **** +8398 Archivist_Still_Blade_of_Blood_1d6 **** **** **** **** **** **** **** **** +8399 Archivist_Still_Blade_of_Blood_3d6 **** **** **** **** **** **** **** **** +8400 Archivist_Bless **** **** **** **** **** **** **** **** +8401 Archivist_Exteneded_Bless **** **** **** **** **** **** **** **** +8402 Archivist_Quickened_Bless **** **** **** **** **** **** **** **** +8403 Archivist_Silent_Bless **** **** **** **** **** **** **** **** +8404 Archivist_Still_Bless **** **** **** **** **** **** **** **** +8405 Archivist_Bless_Water **** **** **** **** **** **** **** **** +8406 Archivist_Quickened_Bless_Water **** **** **** **** **** **** **** **** +8407 Archivist_Silent_Bless_Water **** **** **** **** **** **** **** **** +8408 Archivist_Still_Bless_Water **** **** **** **** **** **** **** **** +8409 Archivist_Bless_Weapon **** **** **** **** **** **** **** **** +8410 Archivist_Exteneded_Bless_Weapon **** **** **** **** **** **** **** **** +8411 Archivist_Quickened_Bless_Weapon **** **** **** **** **** **** **** **** +8412 Archivist_Silent_Bless_Weapon **** **** **** **** **** **** **** **** +8413 Archivist_Still_Bless_Weapon **** **** **** **** **** **** **** **** +8414 Archivist_Camoflage **** **** **** **** **** **** **** **** +8415 Archivist_Exteneded_Camoflage **** **** **** **** **** **** **** **** +8416 Archivist_Quickened_Camoflage **** **** **** **** **** **** **** **** +8417 Archivist_Silent_Camoflage **** **** **** **** **** **** **** **** +8418 Archivist_Still_Camoflage **** **** **** **** **** **** **** **** +8419 Archivist_Cause_Fear **** **** **** **** **** **** **** **** +8420 Archivist_Exteneded_Cause_Fear **** **** **** **** **** **** **** **** +8421 Archivist_Quickened_Cause_Fear **** **** **** **** **** **** **** **** +8422 Archivist_Still_Cause_Fear **** **** **** **** **** **** **** **** +8423 Archivist_Charm_Person **** **** **** **** **** **** **** **** +8424 Archivist_Exteneded_Charm_Person **** **** **** **** **** **** **** **** +8425 Archivist_Quickened_Charm_Person **** **** **** **** **** **** **** **** +8426 Archivist_Silent_Charm_Person **** **** **** **** **** **** **** **** +8427 Archivist_Still_Charm_Person **** **** **** **** **** **** **** **** +8428 Archivist_Color_Spray **** **** **** **** **** **** **** **** +8429 Archivist_Empowered_Color_Spray **** **** **** **** **** **** **** **** +8430 Archivist_Maximized_Color_Spray **** **** **** **** **** **** **** **** +8431 Archivist_Quickened_Color_Spray **** **** **** **** **** **** **** **** +8432 Archivist_Silent_Color_Spray **** **** **** **** **** **** **** **** +8433 Archivist_Still_Color_Spray **** **** **** **** **** **** **** **** +8434 Archivist_Command_RadialMaster **** **** **** **** **** **** **** **** +8435 Archivist_Command_Approach **** **** **** **** **** **** **** **** +8436 Archivist_Command_Drop **** **** **** **** **** **** **** **** +8437 Archivist_Command_Fall **** **** **** **** **** **** **** **** +8438 Archivist_Command_Flee **** **** **** **** **** **** **** **** +8439 Archivist_Command_Halt **** **** **** **** **** **** **** **** +8440 Archivist_Exteneded_Command_RadialMaster **** **** **** **** **** **** **** **** +8441 Archivist_Exteneded_Command_Approach **** **** **** **** **** **** **** **** +8442 Archivist_Exteneded_Command_Drop **** **** **** **** **** **** **** **** +8443 Archivist_Exteneded_Command_Fall **** **** **** **** **** **** **** **** +8444 Archivist_Exteneded_Command_Flee **** **** **** **** **** **** **** **** +8445 Archivist_Exteneded_Command_Halt **** **** **** **** **** **** **** **** +8446 Archivist_Quickened_Command_RadialMaster **** **** **** **** **** **** **** **** +8447 Archivist_Quickened_Command_Approach **** **** **** **** **** **** **** **** +8448 Archivist_Quickened_Command_Drop **** **** **** **** **** **** **** **** +8449 Archivist_Quickened_Command_Fall **** **** **** **** **** **** **** **** +8450 Archivist_Quickened_Command_Flee **** **** **** **** **** **** **** **** +8451 Archivist_Quickened_Command_Halt **** **** **** **** **** **** **** **** +8452 Archivist_Silent_Command_RadialMaster **** **** **** **** **** **** **** **** +8453 Archivist_Silent_Command_Approach **** **** **** **** **** **** **** **** +8454 Archivist_Silent_Command_Drop **** **** **** **** **** **** **** **** +8455 Archivist_Silent_Command_Fall **** **** **** **** **** **** **** **** +8456 Archivist_Silent_Command_Flee **** **** **** **** **** **** **** **** +8457 Archivist_Silent_Command_Halt **** **** **** **** **** **** **** **** +8458 Archivist_Still_Command_RadialMaster **** **** **** **** **** **** **** **** +8459 Archivist_Still_Command_Approach **** **** **** **** **** **** **** **** +8460 Archivist_Still_Command_Drop **** **** **** **** **** **** **** **** +8461 Archivist_Still_Command_Fall **** **** **** **** **** **** **** **** +8462 Archivist_Still_Command_Flee **** **** **** **** **** **** **** **** +8463 Archivist_Still_Command_Halt **** **** **** **** **** **** **** **** +8464 Archivist_Conviction **** **** **** **** **** **** **** **** +8465 Archivist_Exteneded_Conviction **** **** **** **** **** **** **** **** +8466 Archivist_Quickened_Conviction **** **** **** **** **** **** **** **** +8467 Archivist_Silent_Conviction **** **** **** **** **** **** **** **** +8468 Archivist_Still_Conviction **** **** **** **** **** **** **** **** +8469 Archivist_Crafters_Blessing **** **** **** **** **** **** **** **** +8470 Archivist_Exteneded_Crafters_Blessing **** **** **** **** **** **** **** **** +8471 Archivist_Quickened_Crafters_Blessing **** **** **** **** **** **** **** **** +8472 Archivist_Silent_Crafters_Blessing **** **** **** **** **** **** **** **** +8473 Archivist_Still_Crafters_Blessing **** **** **** **** **** **** **** **** +8474 Archivist_Crafters_Curse **** **** **** **** **** **** **** **** +8475 Archivist_Exteneded_Crafters_Curse **** **** **** **** **** **** **** **** +8476 Archivist_Quickened_Crafters_Curse **** **** **** **** **** **** **** **** +8477 Archivist_Silent_Crafters_Curse **** **** **** **** **** **** **** **** +8478 Archivist_Still_Crafters_Curse **** **** **** **** **** **** **** **** +8479 Archivist_Cure_Light_Wounds **** **** **** **** **** **** **** **** +8480 Archivist_Empowered_Cure_Light_Wounds **** **** **** **** **** **** **** **** +8481 Archivist_Maximized_Cure_Light_Wounds **** **** **** **** **** **** **** **** +8482 Archivist_Quickened_Cure_Light_Wounds **** **** **** **** **** **** **** **** +8483 Archivist_Silent_Cure_Light_Wounds **** **** **** **** **** **** **** **** +8484 Archivist_Still_Cure_Light_Wounds **** **** **** **** **** **** **** **** +8485 Archivist_Curse_Water **** **** **** **** **** **** **** **** +8486 Archivist_Quickened_Curse_Water **** **** **** **** **** **** **** **** +8487 Archivist_Silent_Curse_Water **** **** **** **** **** **** **** **** +8488 Archivist_Still_Curse_Water **** **** **** **** **** **** **** **** +8489 Archivist_Deafening_Clang **** **** **** **** **** **** **** **** +8490 Archivist_Exteneded_Deafening_Clang **** **** **** **** **** **** **** **** +8491 Archivist_Quickened_Deafening_Clang **** **** **** **** **** **** **** **** +8492 Archivist_Silent_Deafening_Clang **** **** **** **** **** **** **** **** +8493 Archivist_Still_Deafening_Clang **** **** **** **** **** **** **** **** +8494 Archivist_DEMONFLESH **** **** **** **** **** **** **** **** +8495 Archivist_Exteneded_DEMONFLESH **** **** **** **** **** **** **** **** +8496 Archivist_Quickened_DEMONFLESH **** **** **** **** **** **** **** **** +8497 Archivist_Silent_DEMONFLESH **** **** **** **** **** **** **** **** +8498 Archivist_Still_DEMONFLESH **** **** **** **** **** **** **** **** +8499 Archivist_Detect_Chaos **** **** **** **** **** **** **** **** +8500 Archivist_Exteneded_Detect_Chaos **** **** **** **** **** **** **** **** +8501 Archivist_Quickened_Detect_Chaos **** **** **** **** **** **** **** **** +8502 Archivist_Silent_Detect_Chaos **** **** **** **** **** **** **** **** +8503 Archivist_Still_Detect_Chaos **** **** **** **** **** **** **** **** +8504 Archivist_Detect_Evil **** **** **** **** **** **** **** **** +8505 Archivist_Exteneded_Detect_Evil **** **** **** **** **** **** **** **** +8506 Archivist_Quickened_Detect_Evil **** **** **** **** **** **** **** **** +8507 Archivist_Silent_Detect_Evil **** **** **** **** **** **** **** **** +8508 Archivist_Still_Detect_Evil **** **** **** **** **** **** **** **** +8509 Archivist_Detect_Good **** **** **** **** **** **** **** **** +8510 Archivist_Exteneded_Detect_Good **** **** **** **** **** **** **** **** +8511 Archivist_Quickened_Detect_Good **** **** **** **** **** **** **** **** +8512 Archivist_Silent_Detect_Good **** **** **** **** **** **** **** **** +8513 Archivist_Still_Detect_Good **** **** **** **** **** **** **** **** +8514 Archivist_Detect_Law **** **** **** **** **** **** **** **** +8515 Archivist_Exteneded_Detect_Law **** **** **** **** **** **** **** **** +8516 Archivist_Quickened_Detect_Law **** **** **** **** **** **** **** **** +8517 Archivist_Silent_Detect_Law **** **** **** **** **** **** **** **** +8518 Archivist_Still_Detect_Law **** **** **** **** **** **** **** **** +8519 Archivist_DETECT_UNDEAD **** **** **** **** **** **** **** **** +8520 Archivist_Exteneded_DETECT_UNDEAD **** **** **** **** **** **** **** **** +8521 Archivist_Quickened_DETECT_UNDEAD **** **** **** **** **** **** **** **** +8522 Archivist_Silent_DETECT_UNDEAD **** **** **** **** **** **** **** **** +8523 Archivist_Still_DETECT_UNDEAD **** **** **** **** **** **** **** **** +8524 Archivist_DetectFavoredEnemies **** **** **** **** **** **** **** **** +8525 Archivist_Quickened_DetectFavoredEnemies **** **** **** **** **** **** **** **** +8526 Archivist_Silent_DetectFavoredEnemies **** **** **** **** **** **** **** **** +8527 Archivist_Still_DetectFavoredEnemies **** **** **** **** **** **** **** **** +8528 Archivist_Divine_Favor **** **** **** **** **** **** **** **** +8529 Archivist_Exteneded_Divine_Favor **** **** **** **** **** **** **** **** +8530 Archivist_Quickened_Divine_Favor **** **** **** **** **** **** **** **** +8531 Archivist_Silent_Divine_Favor **** **** **** **** **** **** **** **** +8532 Archivist_Still_Divine_Favor **** **** **** **** **** **** **** **** +8533 Archivist_DIVINE_INSPIRATION **** **** **** **** **** **** **** **** +8534 Archivist_Exteneded_DIVINE_INSPIRATION **** **** **** **** **** **** **** **** +8535 Archivist_Quickened_DIVINE_INSPIRATION **** **** **** **** **** **** **** **** +8536 Archivist_DIVINE_SACRIFICE **** **** **** **** **** **** **** **** +8537 Archivist_SPELL_DIVINE_SACRIFICE_2 **** **** **** **** **** **** **** **** +8538 Archivist_SPELL_DIVINE_SACRIFICE_4 **** **** **** **** **** **** **** **** +8539 Archivist_SPELL_DIVINE_SACRIFICE_6 **** **** **** **** **** **** **** **** +8540 Archivist_SPELL_DIVINE_SACRIFICE_8 **** **** **** **** **** **** **** **** +8541 Archivist_SPELL_DIVINE_SACRIFICE_10 **** **** **** **** **** **** **** **** +8542 Archivist_Doom **** **** **** **** **** **** **** **** +8543 Archivist_Exteneded_Doom **** **** **** **** **** **** **** **** +8544 Archivist_Quickened_Doom **** **** **** **** **** **** **** **** +8545 Archivist_Silent_Doom **** **** **** **** **** **** **** **** +8546 Archivist_Still_Doom **** **** **** **** **** **** **** **** +8547 Archivist_DRUG_RESISTANCE **** **** **** **** **** **** **** **** +8548 Archivist_Quickened_DRUG_RESISTANCE **** **** **** **** **** **** **** **** +8549 Archivist_Silent_DRUG_RESISTANCE **** **** **** **** **** **** **** **** +8550 Archivist_Endure_Elements **** **** **** **** **** **** **** **** +8551 Archivist_Exteneded_Endure_Elements **** **** **** **** **** **** **** **** +8552 Archivist_Quickened_Endure_Elements **** **** **** **** **** **** **** **** +8553 Archivist_Silent_Endure_Elements **** **** **** **** **** **** **** **** +8554 Archivist_Still_Endure_Elements **** **** **** **** **** **** **** **** +8555 Archivist_Entangle **** **** **** **** **** **** **** **** +8556 Archivist_Exteneded_Entangle **** **** **** **** **** **** **** **** +8557 Archivist_Quickened_Entangle **** **** **** **** **** **** **** **** +8558 Archivist_Silent_Entangle **** **** **** **** **** **** **** **** +8559 Archivist_Still_Entangle **** **** **** **** **** **** **** **** +8560 Archivist_Entropic_Shield **** **** **** **** **** **** **** **** +8561 Archivist_Exteneded_Entropic_Shield **** **** **** **** **** **** **** **** +8562 Archivist_Quickened_Entropic_Shield **** **** **** **** **** **** **** **** +8563 Archivist_Silent_Entropic_Shield **** **** **** **** **** **** **** **** +8564 Archivist_Still_Entropic_Shield **** **** **** **** **** **** **** **** +8565 Archivist_Expeditious_Retreat **** **** **** **** **** **** **** **** +8566 Archivist_Exteneded_Expeditious_Retreat **** **** **** **** **** **** **** **** +8567 Archivist_Quickened_Expeditious_Retreat **** **** **** **** **** **** **** **** +8568 Archivist_Silent_Expeditious_Retreat **** **** **** **** **** **** **** **** +8569 Archivist_Still_Expeditious_Retreat **** **** **** **** **** **** **** **** +8570 Archivist_EXTRACT_DRUG **** **** **** **** **** **** **** **** +8571 Archivist_EXTRACT_BACCARAN **** **** **** **** **** **** **** **** +8572 Archivist_EXTRACT_VODARE **** **** **** **** **** **** **** **** +8573 Archivist_EXTRACT_SANNISH **** **** **** **** **** **** **** **** +8574 Archivist_EXTRACT_MUSHROOM_POWDER **** **** **** **** **** **** **** **** +8575 Archivist_Quickened_EXTRACT_DRUG **** **** **** **** **** **** **** **** +8576 Archivist_Quickened_EXTRACT_BACCARAN **** **** **** **** **** **** **** **** +8577 Archivist_Quickened_EXTRACT_VODARE **** **** **** **** **** **** **** **** +8578 Archivist_Quickened_EXTRACT_SANNISH **** **** **** **** **** **** **** **** +8579 Archivist_Quickened_EXTRACT_MUSHROOM_POWDER **** **** **** **** **** **** **** **** +8580 Archivist_Silent_EXTRACT_DRUG **** **** **** **** **** **** **** **** +8581 Archivist_Silent_EXTRACT_BACCARAN **** **** **** **** **** **** **** **** +8582 Archivist_Silent_EXTRACT_VODARE **** **** **** **** **** **** **** **** +8583 Archivist_Silent_EXTRACT_SANNISH **** **** **** **** **** **** **** **** +8584 Archivist_Silent_EXTRACT_MUSHROOM_POWDER **** **** **** **** **** **** **** **** +8585 Archivist_Still_EXTRACT_DRUG **** **** **** **** **** **** **** **** +8586 Archivist_Still_EXTRACT_BACCARAN **** **** **** **** **** **** **** **** +8587 Archivist_Still_EXTRACT_VODARE **** **** **** **** **** **** **** **** +8588 Archivist_Still_EXTRACT_SANNISH **** **** **** **** **** **** **** **** +8589 Archivist_Still_EXTRACT_MUSHROOM_POWDER **** **** **** **** **** **** **** **** +8590 Archivist_EYES_OF_THE_AVORAL **** **** **** **** **** **** **** **** +8591 Archivist_Exteneded_EYES_OF_THE_AVORAL **** **** **** **** **** **** **** **** +8592 Archivist_Quickened_EYES_OF_THE_AVORAL **** **** **** **** **** **** **** **** +8593 Archivist_Still_EYES_OF_THE_AVORAL **** **** **** **** **** **** **** **** +8594 Archivist_Faerie_Fire **** **** **** **** **** **** **** **** +8595 Archivist_Exteneded_Faerie_Fire **** **** **** **** **** **** **** **** +8596 Archivist_Quickened_Faerie_Fire **** **** **** **** **** **** **** **** +8597 Archivist_Silent_Faerie_Fire **** **** **** **** **** **** **** **** +8598 Archivist_Still_Faerie_Fire **** **** **** **** **** **** **** **** +8599 Archivist_Grease **** **** **** **** **** **** **** **** +8600 Archivist_Exteneded_Grease **** **** **** **** **** **** **** **** +8601 Archivist_Quickened_Grease **** **** **** **** **** **** **** **** +8602 Archivist_Silent_Grease **** **** **** **** **** **** **** **** +8603 Archivist_Still_Grease **** **** **** **** **** **** **** **** +8604 Archivist_HEARTACHE **** **** **** **** **** **** **** **** +8605 Archivist_Exteneded_HEARTACHE **** **** **** **** **** **** **** **** +8606 Archivist_Quickened_HEARTACHE **** **** **** **** **** **** **** **** +8607 Archivist_Silent_HEARTACHE **** **** **** **** **** **** **** **** +8608 Archivist_Still_HEARTACHE **** **** **** **** **** **** **** **** +8609 Archivist_HideFromAnimals **** **** **** **** **** **** **** **** +8610 Archivist_Exteneded_HideFromAnimals **** **** **** **** **** **** **** **** +8611 Archivist_Quickened_HideFromAnimals **** **** **** **** **** **** **** **** +8612 Archivist_Still_HideFromAnimals **** **** **** **** **** **** **** **** +8613 Archivist_HideFromUndead **** **** **** **** **** **** **** **** +8614 Archivist_Exteneded_HideFromUndead **** **** **** **** **** **** **** **** +8615 Archivist_Quickened_HideFromUndead **** **** **** **** **** **** **** **** +8616 Archivist_Still_HideFromUndead **** **** **** **** **** **** **** **** +8617 Archivist_Identify **** **** **** **** **** **** **** **** +8618 Archivist_Exteneded_Identify **** **** **** **** **** **** **** **** +8619 Archivist_Quickened_Identify **** **** **** **** **** **** **** **** +8620 Archivist_Silent_Identify **** **** **** **** **** **** **** **** +8621 Archivist_Still_Identify **** **** **** **** **** **** **** **** +8622 Archivist_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +8623 Archivist_Empowered_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +8624 Archivist_Maximized_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +8625 Archivist_Quickened_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +8626 Archivist_Silent_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +8627 Archivist_Still_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +8628 Archivist_Spell_Jump **** **** **** **** **** **** **** **** +8629 Archivist_Exteneded_Spell_Jump **** **** **** **** **** **** **** **** +8630 Archivist_Quickened_Spell_Jump **** **** **** **** **** **** **** **** +8631 Archivist_Silent_Spell_Jump **** **** **** **** **** **** **** **** +8632 Archivist_Still_Spell_Jump **** **** **** **** **** **** **** **** +8633 Archivist_LANTERN_LIGHT **** **** **** **** **** **** **** **** +8634 Archivist_Empowered_LANTERN_LIGHT **** **** **** **** **** **** **** **** +8635 Archivist_Maximized_LANTERN_LIGHT **** **** **** **** **** **** **** **** +8636 Archivist_Quickened_LANTERN_LIGHT **** **** **** **** **** **** **** **** +8637 Archivist_Still_LANTERN_LIGHT **** **** **** **** **** **** **** **** +8638 Archivist_LESSER_SHIVERING_TOUCH **** **** **** **** **** **** **** **** +8639 Archivist_Empowered_LESSER_SHIVERING_TOUCH **** **** **** **** **** **** **** **** +8640 Archivist_Exteneded_LESSER_SHIVERING_TOUCH **** **** **** **** **** **** **** **** +8641 Archivist_Maximized_LESSER_SHIVERING_TOUCH **** **** **** **** **** **** **** **** +8642 Archivist_Quickened_LESSER_SHIVERING_TOUCH **** **** **** **** **** **** **** **** +8643 Archivist_Silent_LESSER_SHIVERING_TOUCH **** **** **** **** **** **** **** **** +8644 Archivist_Still_LESSER_SHIVERING_TOUCH **** **** **** **** **** **** **** **** +8645 Archivist_Lesser_Vigor **** **** **** **** **** **** **** **** +8646 Archivist_Exteneded_Lesser_Vigor **** **** **** **** **** **** **** **** +8647 Archivist_Quickened_Lesser_Vigor **** **** **** **** **** **** **** **** +8648 Archivist_Silent_Lesser_Vigor **** **** **** **** **** **** **** **** +8649 Archivist_Still_Lesser_Vigor **** **** **** **** **** **** **** **** +8650 Archivist_Lionheart **** **** **** **** **** **** **** **** +8651 Archivist_Exteneded_Lionheart **** **** **** **** **** **** **** **** +8652 Archivist_Quickened_Lionheart **** **** **** **** **** **** **** **** +8653 Archivist_Silent_Lionheart **** **** **** **** **** **** **** **** +8654 Archivist_Still_Lionheart **** **** **** **** **** **** **** **** +8655 Archivist_Longstrider **** **** **** **** **** **** **** **** +8656 Archivist_Exteneded_Longstrider **** **** **** **** **** **** **** **** +8657 Archivist_Quickened_Longstrider **** **** **** **** **** **** **** **** +8658 Archivist_Silent_Longstrider **** **** **** **** **** **** **** **** +8659 Archivist_Still_Longstrider **** **** **** **** **** **** **** **** +8660 Archivist_Mage_Armor **** **** **** **** **** **** **** **** +8661 Archivist_Exteneded_Mage_Armor **** **** **** **** **** **** **** **** +8662 Archivist_Quickened_Mage_Armor **** **** **** **** **** **** **** **** +8663 Archivist_Silent_Mage_Armor **** **** **** **** **** **** **** **** +8664 Archivist_Still_Mage_Armor **** **** **** **** **** **** **** **** +8665 Archivist_Magic_Fang **** **** **** **** **** **** **** **** +8666 Archivist_Exteneded_Magic_Fang **** **** **** **** **** **** **** **** +8667 Archivist_Quickened_Magic_Fang **** **** **** **** **** **** **** **** +8668 Archivist_Silent_Magic_Fang **** **** **** **** **** **** **** **** +8669 Archivist_Still_Magic_Fang **** **** **** **** **** **** **** **** +8670 Archivist_Magic_Stone **** **** **** **** **** **** **** **** +8671 Archivist_Exteneded_Magic_Stone **** **** **** **** **** **** **** **** +8672 Archivist_Quickened_Magic_Stone **** **** **** **** **** **** **** **** +8673 Archivist_Silent_Magic_Stone **** **** **** **** **** **** **** **** +8674 Archivist_Still_Magic_Stone **** **** **** **** **** **** **** **** +8675 Archivist_Magic_Weapon **** **** **** **** **** **** **** **** +8676 Archivist_Exteneded_Magic_Weapon **** **** **** **** **** **** **** **** +8677 Archivist_Quickened_Magic_Weapon **** **** **** **** **** **** **** **** +8678 Archivist_Silent_Magic_Weapon **** **** **** **** **** **** **** **** +8679 Archivist_Still_Magic_Weapon **** **** **** **** **** **** **** **** +8680 Archivist_Necrotic_Awareness **** **** **** **** **** **** **** **** +8681 Archivist_Quickened_Necrotic_Awareness **** **** **** **** **** **** **** **** +8682 Archivist_Silent_Necrotic_Awareness **** **** **** **** **** **** **** **** +8683 Archivist_Still_Necrotic_Awareness **** **** **** **** **** **** **** **** +8684 Archivist_Obscuring_Mist **** **** **** **** **** **** **** **** +8685 Archivist_Exteneded_Obscuring_Mist **** **** **** **** **** **** **** **** +8686 Archivist_Quickened_Obscuring_Mist **** **** **** **** **** **** **** **** +8687 Archivist_Silent_Obscuring_Mist **** **** **** **** **** **** **** **** +8688 Archivist_Still_Obscuring_Mist **** **** **** **** **** **** **** **** +8689 Archivist_Protection_from_Chaos **** **** **** **** **** **** **** **** +8690 Archivist_Exteneded_Protection_from_Chaos **** **** **** **** **** **** **** **** +8691 Archivist_Quickened_Protection_from_Chaos **** **** **** **** **** **** **** **** +8692 Archivist_Silent_Protection_from_Chaos **** **** **** **** **** **** **** **** +8693 Archivist_Still_Protection_from_Chaos **** **** **** **** **** **** **** **** +8694 Archivist_Protection_from_Evil **** **** **** **** **** **** **** **** +8695 Archivist_Exteneded_Protection_from_Evil **** **** **** **** **** **** **** **** +8696 Archivist_Quickened_Protection_from_Evil **** **** **** **** **** **** **** **** +8697 Archivist_Silent_Protection_from_Evil **** **** **** **** **** **** **** **** +8698 Archivist_Still_Protection_from_Evil **** **** **** **** **** **** **** **** +8699 Archivist_Protection_from_Good **** **** **** **** **** **** **** **** +8700 Archivist_Exteneded_Protection_from_Good **** **** **** **** **** **** **** **** +8701 Archivist_Quickened_Protection_from_Good **** **** **** **** **** **** **** **** +8702 Archivist_Silent_Protection_from_Good **** **** **** **** **** **** **** **** +8703 Archivist_Still_Protection_from_Good **** **** **** **** **** **** **** **** +8704 Archivist_Protection_from_Law **** **** **** **** **** **** **** **** +8705 Archivist_Exteneded_Protection_from_Law **** **** **** **** **** **** **** **** +8706 Archivist_Quickened_Protection_from_Law **** **** **** **** **** **** **** **** +8707 Archivist_Silent_Protection_from_Law **** **** **** **** **** **** **** **** +8708 Archivist_Still_Protection_from_Law **** **** **** **** **** **** **** **** +8709 Archivist_RAY_OF_HOPE **** **** **** **** **** **** **** **** +8710 Archivist_Exteneded_RAY_OF_HOPE **** **** **** **** **** **** **** **** +8711 Archivist_Quickened_RAY_OF_HOPE **** **** **** **** **** **** **** **** +8712 Archivist_Silent_RAY_OF_HOPE **** **** **** **** **** **** **** **** +8713 Archivist_Still_RAY_OF_HOPE **** **** **** **** **** **** **** **** +8714 Archivist_Ray_of_Enfeeblement **** **** **** **** **** **** **** **** +8715 Archivist_Empowered_Ray_of_Enfeeblement **** **** **** **** **** **** **** **** +8716 Archivist_Exteneded_Ray_of_Enfeeblement **** **** **** **** **** **** **** **** +8717 Archivist_Maximized_Ray_of_Enfeeblement **** **** **** **** **** **** **** **** +8718 Archivist_Quickened_Ray_of_Enfeeblement **** **** **** **** **** **** **** **** +8719 Archivist_Silent_Ray_of_Enfeeblement **** **** **** **** **** **** **** **** +8720 Archivist_Still_Ray_of_Enfeeblement **** **** **** **** **** **** **** **** +8721 Archivist_Remove_Fear **** **** **** **** **** **** **** **** +8722 Archivist_Exteneded_Remove_Fear **** **** **** **** **** **** **** **** +8723 Archivist_Quickened_Remove_Fear **** **** **** **** **** **** **** **** +8724 Archivist_Silent_Remove_Fear **** **** **** **** **** **** **** **** +8725 Archivist_Still_Remove_Fear **** **** **** **** **** **** **** **** +8726 Archivist_Sanctuary **** **** **** **** **** **** **** **** +8727 Archivist_Exteneded_Sanctuary **** **** **** **** **** **** **** **** +8728 Archivist_Quickened_Sanctuary **** **** **** **** **** **** **** **** +8729 Archivist_Silent_Sanctuary **** **** **** **** **** **** **** **** +8730 Archivist_Still_Sanctuary **** **** **** **** **** **** **** **** +8731 Archivist_SEETHING_EYEBANE **** **** **** **** **** **** **** **** +8732 Archivist_Quickened_SEETHING_EYEBANE **** **** **** **** **** **** **** **** +8733 Archivist_Silent_SEETHING_EYEBANE **** **** **** **** **** **** **** **** +8734 Archivist_Still_SEETHING_EYEBANE **** **** **** **** **** **** **** **** +8735 Archivist_Shield **** **** **** **** **** **** **** **** +8736 Archivist_Exteneded_Shield **** **** **** **** **** **** **** **** +8737 Archivist_Quickened_Shield **** **** **** **** **** **** **** **** +8738 Archivist_Silent_Shield **** **** **** **** **** **** **** **** +8739 Archivist_Still_Shield **** **** **** **** **** **** **** **** +8740 Archivist_Shield_of_Faith **** **** **** **** **** **** **** **** +8741 Archivist_Exteneded_Shield_of_Faith **** **** **** **** **** **** **** **** +8742 Archivist_Quickened_Shield_of_Faith **** **** **** **** **** **** **** **** +8743 Archivist_Silent_Shield_of_Faith **** **** **** **** **** **** **** **** +8744 Archivist_Still_Shield_of_Faith **** **** **** **** **** **** **** **** +8745 Archivist_Shillelagh **** **** **** **** **** **** **** **** +8746 Archivist_Exteneded_Shillelagh **** **** **** **** **** **** **** **** +8747 Archivist_Quickened_Shillelagh **** **** **** **** **** **** **** **** +8748 Archivist_Silent_Shillelagh **** **** **** **** **** **** **** **** +8749 Archivist_Still_Shillelagh **** **** **** **** **** **** **** **** +8750 Archivist_Sleep **** **** **** **** **** **** **** **** +8751 Archivist_Empowered_Sleep **** **** **** **** **** **** **** **** +8752 Archivist_Exteneded_Sleep **** **** **** **** **** **** **** **** +8753 Archivist_Maximized_Sleep **** **** **** **** **** **** **** **** +8754 Archivist_Quickened_Sleep **** **** **** **** **** **** **** **** +8755 Archivist_Silent_Sleep **** **** **** **** **** **** **** **** +8756 Archivist_Still_Sleep **** **** **** **** **** **** **** **** +8757 Archivist_Snillocs_Snowball **** **** **** **** **** **** **** **** +8758 Archivist_Empowered_Snillocs_Snowball **** **** **** **** **** **** **** **** +8759 Archivist_Maximized_Snillocs_Snowball **** **** **** **** **** **** **** **** +8760 Archivist_Quickened_Snillocs_Snowball **** **** **** **** **** **** **** **** +8761 Archivist_Silent_Snillocs_Snowball **** **** **** **** **** **** **** **** +8762 Archivist_Still_Snillocs_Snowball **** **** **** **** **** **** **** **** +8763 Archivist_SORROW **** **** **** **** **** **** **** **** +8764 Archivist_Quickened_SORROW **** **** **** **** **** **** **** **** +8765 Archivist_Silent_SORROW **** **** **** **** **** **** **** **** +8766 Archivist_Still_SORROW **** **** **** **** **** **** **** **** +8767 Archivist_Summon_Creature_I **** **** **** **** **** **** **** **** +8768 Archivist_Exteneded_Summon_Creature_I **** **** **** **** **** **** **** **** +8769 Archivist_Quickened_Summon_Creature_I **** **** **** **** **** **** **** **** +8770 Archivist_Silent_Summon_Creature_I **** **** **** **** **** **** **** **** +8771 Archivist_Still_Summon_Creature_I **** **** **** **** **** **** **** **** +8772 Archivist_SummonUndeadI **** **** **** **** **** **** **** **** +8773 Archivist_Exteneded_SummonUndeadI **** **** **** **** **** **** **** **** +8774 Archivist_Quickened_SummonUndeadI **** **** **** **** **** **** **** **** +8775 Archivist_Silent_SummonUndeadI **** **** **** **** **** **** **** **** +8776 Archivist_Still_SummonUndeadI **** **** **** **** **** **** **** **** +8777 Archivist_TONGUE_OF_BAALZEBUL **** **** **** **** **** **** **** **** +8778 Archivist_Exteneded_TONGUE_OF_BAALZEBUL **** **** **** **** **** **** **** **** +8779 Archivist_Quickened_TONGUE_OF_BAALZEBUL **** **** **** **** **** **** **** **** +8780 Archivist_Silent_TONGUE_OF_BAALZEBUL **** **** **** **** **** **** **** **** +8781 Archivist_Still_TONGUE_OF_BAALZEBUL **** **** **** **** **** **** **** **** +8782 Archivist_ToweringOak **** **** **** **** **** **** **** **** +8783 Archivist_Exteneded_ToweringOak **** **** **** **** **** **** **** **** +8784 Archivist_Quickened_ToweringOak **** **** **** **** **** **** **** **** +8785 Archivist_Silent_ToweringOak **** **** **** **** **** **** **** **** +8786 Archivist_Still_ToweringOak **** **** **** **** **** **** **** **** +8787 Archivist_True_Strike **** **** **** **** **** **** **** **** +8788 Archivist_Quickened_True_Strike **** **** **** **** **** **** **** **** +8789 Archivist_Silent_True_Strike **** **** **** **** **** **** **** **** +8790 Archivist_TWILIGHT_LUCK **** **** **** **** **** **** **** **** +8791 Archivist_Exteneded_TWILIGHT_LUCK **** **** **** **** **** **** **** **** +8792 Archivist_Silent_TWILIGHT_LUCK **** **** **** **** **** **** **** **** +8793 Archivist_VisionOfHeaven **** **** **** **** **** **** **** **** +8794 Archivist_Exteneded_VisionOfHeaven **** **** **** **** **** **** **** **** +8795 Archivist_Quickened_VisionOfHeaven **** **** **** **** **** **** **** **** +8796 Archivist_Silent_VisionOfHeaven **** **** **** **** **** **** **** **** +8797 Archivist_ADDICTION **** **** **** **** **** **** **** **** +8798 Archivist_ADDICTION_TERRAN_BRANDY **** **** **** **** **** **** **** **** +8799 Archivist_ADDICTION_MUSHROOM_POWDER **** **** **** **** **** **** **** **** +8800 Archivist_ADDICTION_VODARE **** **** **** **** **** **** **** **** +8801 Archivist_ADDICTION_AGONY **** **** **** **** **** **** **** **** +8802 Archivist_Quickened_ADDICTION **** **** **** **** **** **** **** **** +8803 Archivist_Quickened_ADDICTION_TERRAN_BRANDY **** **** **** **** **** **** **** **** +8804 Archivist_Quickened_ADDICTION_MUSHROOM_POWDER **** **** **** **** **** **** **** **** +8805 Archivist_Quickened_ADDICTION_VODARE **** **** **** **** **** **** **** **** +8806 Archivist_Quickened_ADDICTION_AGONY **** **** **** **** **** **** **** **** +8807 Archivist_Silent_ADDICTION **** **** **** **** **** **** **** **** +8808 Archivist_Silent_ADDICTION_TERRAN_BRANDY **** **** **** **** **** **** **** **** +8809 Archivist_Silent_ADDICTION_MUSHROOM_POWDER **** **** **** **** **** **** **** **** +8810 Archivist_Silent_ADDICTION_VODARE **** **** **** **** **** **** **** **** +8811 Archivist_Silent_ADDICTION_AGONY **** **** **** **** **** **** **** **** +8812 Archivist_Still_ADDICTION **** **** **** **** **** **** **** **** +8813 Archivist_Still_ADDICTION_TERRAN_BRANDY **** **** **** **** **** **** **** **** +8814 Archivist_Still_ADDICTION_MUSHROOM_POWDER **** **** **** **** **** **** **** **** +8815 Archivist_Still_ADDICTION_VODARE **** **** **** **** **** **** **** **** +8816 Archivist_Still_ADDICTION_AGONY **** **** **** **** **** **** **** **** +8817 Archivist_Aid **** **** **** **** **** **** **** **** +8818 Archivist_Empowered_Aid **** **** **** **** **** **** **** **** +8819 Archivist_Exteneded_Aid **** **** **** **** **** **** **** **** +8820 Archivist_Maximized_Aid **** **** **** **** **** **** **** **** +8821 Archivist_Quickened_Aid **** **** **** **** **** **** **** **** +8822 Archivist_Silent_Aid **** **** **** **** **** **** **** **** +8823 Archivist_Still_Aid **** **** **** **** **** **** **** **** +8824 Archivist_Alter_Self_Radial_Master **** **** **** **** **** **** **** **** +8825 Archivist_Alter_Self_Learn **** **** **** **** **** **** **** **** +8826 Archivist_Alter_Self_Options **** **** **** **** **** **** **** **** +8827 Archivist_Alter_Self_QS1 **** **** **** **** **** **** **** **** +8828 Archivist_Alter_Self_QS2 **** **** **** **** **** **** **** **** +8829 Archivist_Alter_Self_QS3 **** **** **** **** **** **** **** **** +8830 Archivist_Exteneded_Alter_Self_Radial_Master **** **** **** **** **** **** **** **** +8831 Archivist_Exteneded_Alter_Self_Learn **** **** **** **** **** **** **** **** +8832 Archivist_Exteneded_Alter_Self_Options **** **** **** **** **** **** **** **** +8833 Archivist_Exteneded_Alter_Self_QS1 **** **** **** **** **** **** **** **** +8834 Archivist_Exteneded_Alter_Self_QS2 **** **** **** **** **** **** **** **** +8835 Archivist_Exteneded_Alter_Self_QS3 **** **** **** **** **** **** **** **** +8836 Archivist_Quickened_Alter_Self_Radial_Master **** **** **** **** **** **** **** **** +8837 Archivist_Quickened_Alter_Self_Learn **** **** **** **** **** **** **** **** +8838 Archivist_Quickened_Alter_Self_Options **** **** **** **** **** **** **** **** +8839 Archivist_Quickened_Alter_Self_QS1 **** **** **** **** **** **** **** **** +8840 Archivist_Quickened_Alter_Self_QS2 **** **** **** **** **** **** **** **** +8841 Archivist_Quickened_Alter_Self_QS3 **** **** **** **** **** **** **** **** +8842 Archivist_Silent_Alter_Self_Radial_Master **** **** **** **** **** **** **** **** +8843 Archivist_Silent_Alter_Self_Learn **** **** **** **** **** **** **** **** +8844 Archivist_Silent_Alter_Self_Options **** **** **** **** **** **** **** **** +8845 Archivist_Silent_Alter_Self_QS1 **** **** **** **** **** **** **** **** +8846 Archivist_Silent_Alter_Self_QS2 **** **** **** **** **** **** **** **** +8847 Archivist_Silent_Alter_Self_QS3 **** **** **** **** **** **** **** **** +8848 Archivist_Still_Alter_Self_Radial_Master **** **** **** **** **** **** **** **** +8849 Archivist_Still_Alter_Self_Learn **** **** **** **** **** **** **** **** +8850 Archivist_Still_Alter_Self_Options **** **** **** **** **** **** **** **** +8851 Archivist_Still_Alter_Self_QS1 **** **** **** **** **** **** **** **** +8852 Archivist_Still_Alter_Self_QS2 **** **** **** **** **** **** **** **** +8853 Archivist_Still_Alter_Self_QS3 **** **** **** **** **** **** **** **** +8854 Archivist_Animalistic_Power **** **** **** **** **** **** **** **** +8855 Archivist_Exteneded_Animalistic_Power **** **** **** **** **** **** **** **** +8856 Archivist_AuraOfGlory **** **** **** **** **** **** **** **** +8857 Archivist_Exteneded_AuraOfGlory **** **** **** **** **** **** **** **** +8858 Archivist_Quickened_AuraOfGlory **** **** **** **** **** **** **** **** +8859 Archivist_Silent_AuraOfGlory **** **** **** **** **** **** **** **** +8860 Archivist_Still_AuraOfGlory **** **** **** **** **** **** **** **** +8861 Archivist_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +8862 Archivist_Empowered_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +8863 Archivist_Maximized_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +8864 Archivist_Quickened_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +8865 Archivist_Silent_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +8866 Archivist_Still_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +8867 Archivist_Barkskin **** **** **** **** **** **** **** **** +8868 Archivist_Exteneded_Barkskin **** **** **** **** **** **** **** **** +8869 Archivist_Quickened_Barkskin **** **** **** **** **** **** **** **** +8870 Archivist_Silent_Barkskin **** **** **** **** **** **** **** **** +8871 Archivist_Still_Barkskin **** **** **** **** **** **** **** **** +8872 Archivist_Benign_Transposition **** **** **** **** **** **** **** **** +8873 Archivist_Quickened_Benign_Transposition **** **** **** **** **** **** **** **** +8874 Archivist_Silent_Benign_Transposition **** **** **** **** **** **** **** **** +8875 Archivist_BladesOfFire **** **** **** **** **** **** **** **** +8876 Archivist_Exteneded_BladesOfFire **** **** **** **** **** **** **** **** +8877 Archivist_Quickened_BladesOfFire **** **** **** **** **** **** **** **** +8878 Archivist_Silent_BladesOfFire **** **** **** **** **** **** **** **** +8879 Archivist_Blood_Frenzy **** **** **** **** **** **** **** **** +8880 Archivist_Exteneded_Blood_Frenzy **** **** **** **** **** **** **** **** +8881 Archivist_Quickened_Blood_Frenzy **** **** **** **** **** **** **** **** +8882 Archivist_Silent_Blood_Frenzy **** **** **** **** **** **** **** **** +8883 Archivist_Still_Blood_Frenzy **** **** **** **** **** **** **** **** +8884 Archivist_Blur **** **** **** **** **** **** **** **** +8885 Archivist_Exteneded_Blur **** **** **** **** **** **** **** **** +8886 Archivist_Quickened_Blur **** **** **** **** **** **** **** **** +8887 Archivist_Silent_Blur **** **** **** **** **** **** **** **** +8888 Archivist_BONEBLAST **** **** **** **** **** **** **** **** +8889 Archivist_Quickened_BONEBLAST **** **** **** **** **** **** **** **** +8890 Archivist_Silent_BONEBLAST **** **** **** **** **** **** **** **** +8891 Archivist_Still_BONEBLAST **** **** **** **** **** **** **** **** +8892 Archivist_BrilliantEnergyArrows **** **** **** **** **** **** **** **** +8893 Archivist_Quickened_BrilliantEnergyArrows **** **** **** **** **** **** **** **** +8894 Archivist_Silent_BrilliantEnergyArrows **** **** **** **** **** **** **** **** +8895 Archivist_Bulls_Strength **** **** **** **** **** **** **** **** +8896 Archivist_Empowered_Bulls_Strength **** **** **** **** **** **** **** **** +8897 Archivist_Exteneded_Bulls_Strength **** **** **** **** **** **** **** **** +8898 Archivist_Maximized_Bulls_Strength **** **** **** **** **** **** **** **** +8899 Archivist_Quickened_Bulls_Strength **** **** **** **** **** **** **** **** +8900 Archivist_Silent_Bulls_Strength **** **** **** **** **** **** **** **** +8901 Archivist_Still_Bulls_Strength **** **** **** **** **** **** **** **** +8902 Archivist_Burning_Bolt **** **** **** **** **** **** **** **** +8903 Archivist_Empowered_Burning_Bolt **** **** **** **** **** **** **** **** +8904 Archivist_Maximized_Burning_Bolt **** **** **** **** **** **** **** **** +8905 Archivist_Quickened_Burning_Bolt **** **** **** **** **** **** **** **** +8906 Archivist_Silent_Burning_Bolt **** **** **** **** **** **** **** **** +8907 Archivist_Still_Burning_Bolt **** **** **** **** **** **** **** **** +8908 Archivist_Calm_Emotions **** **** **** **** **** **** **** **** +8909 Archivist_Exteneded_Calm_Emotions **** **** **** **** **** **** **** **** +8910 Archivist_Quickened_Calm_Emotions **** **** **** **** **** **** **** **** +8911 Archivist_Silent_Calm_Emotions **** **** **** **** **** **** **** **** +8912 Archivist_Still_Calm_Emotions **** **** **** **** **** **** **** **** +8913 Archivist_Cats_Grace **** **** **** **** **** **** **** **** +8914 Archivist_Empowered_Cats_Grace **** **** **** **** **** **** **** **** +8915 Archivist_Exteneded_Cats_Grace **** **** **** **** **** **** **** **** +8916 Archivist_Maximized_Cats_Grace **** **** **** **** **** **** **** **** +8917 Archivist_Quickened_Cats_Grace **** **** **** **** **** **** **** **** +8918 Archivist_Silent_Cats_Grace **** **** **** **** **** **** **** **** +8919 Archivist_Still_Cats_Grace **** **** **** **** **** **** **** **** +8920 Archivist_Charm_Person_or_Animal **** **** **** **** **** **** **** **** +8921 Archivist_Exteneded_Charm_Person_or_Animal **** **** **** **** **** **** **** **** +8922 Archivist_Quickened_Charm_Person_or_Animal **** **** **** **** **** **** **** **** +8923 Archivist_Silent_Charm_Person_or_Animal **** **** **** **** **** **** **** **** +8924 Archivist_Still_Charm_Person_or_Animal **** **** **** **** **** **** **** **** +8925 Archivist_Clarity_of_Mind **** **** **** **** **** **** **** **** +8926 Archivist_Exteneded_Clarity_of_Mind **** **** **** **** **** **** **** **** +8927 Archivist_Quickened_Clarity_of_Mind **** **** **** **** **** **** **** **** +8928 Archivist_Silent_Clarity_of_Mind **** **** **** **** **** **** **** **** +8929 Archivist_Still_Clarity_of_Mind **** **** **** **** **** **** **** **** +8930 Archivist_Consecrated_Aura **** **** **** **** **** **** **** **** +8931 Archivist_Exteneded_Consecrated_Aura **** **** **** **** **** **** **** **** +8932 Archivist_Quickened_Consecrated_Aura **** **** **** **** **** **** **** **** +8933 Archivist_Silent_Consecrated_Aura **** **** **** **** **** **** **** **** +8934 Archivist_Still_Consecrated_Aura **** **** **** **** **** **** **** **** +8935 Archivist_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +8936 Archivist_Empowered_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +8937 Archivist_Maximized_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +8938 Archivist_Quickened_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +8939 Archivist_Silent_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +8940 Archivist_Still_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +8941 Archivist_Curse_of_Impending_Blades **** **** **** **** **** **** **** **** +8942 Archivist_Exteneded_Curse_of_Impending_Blades **** **** **** **** **** **** **** **** +8943 Archivist_Quickened_Curse_of_Impending_Blades **** **** **** **** **** **** **** **** +8944 Archivist_Silent_Curse_of_Impending_Blades **** **** **** **** **** **** **** **** +8945 Archivist_Still_Curse_of_Impending_Blades **** **** **** **** **** **** **** **** +8946 Archivist_Darkness **** **** **** **** **** **** **** **** +8947 Archivist_Exteneded_Darkness **** **** **** **** **** **** **** **** +8948 Archivist_Quickened_Darkness **** **** **** **** **** **** **** **** +8949 Archivist_Silent_Darkness **** **** **** **** **** **** **** **** +8950 Archivist_Death_Armor **** **** **** **** **** **** **** **** +8951 Archivist_Exteneded_Death_Armor **** **** **** **** **** **** **** **** +8952 Archivist_Quickened_Death_Armor **** **** **** **** **** **** **** **** +8953 Archivist_Silent_Death_Armor **** **** **** **** **** **** **** **** +8954 Archivist_Still_Death_Armor **** **** **** **** **** **** **** **** +8955 Archivist_Death_Knell **** **** **** **** **** **** **** **** +8956 Archivist_Empowered_Death_Knell **** **** **** **** **** **** **** **** +8957 Archivist_Exteneded_Death_Knell **** **** **** **** **** **** **** **** +8958 Archivist_Maximized_Death_Knell **** **** **** **** **** **** **** **** +8959 Archivist_Quickened_Death_Knell **** **** **** **** **** **** **** **** +8960 Archivist_Silent_Death_Knell **** **** **** **** **** **** **** **** +8961 Archivist_Still_Death_Knell **** **** **** **** **** **** **** **** +8962 Archivist_DEMONCALL **** **** **** **** **** **** **** **** +8963 Archivist_Quickened_DEMONCALL **** **** **** **** **** **** **** **** +8964 Archivist_Silent_DEMONCALL **** **** **** **** **** **** **** **** +8965 Archivist_Still_DEMONCALL **** **** **** **** **** **** **** **** +8966 Archivist_Divine_Protection **** **** **** **** **** **** **** **** +8967 Archivist_Exteneded_Divine_Protection **** **** **** **** **** **** **** **** +8968 Archivist_Quickened_Divine_Protection **** **** **** **** **** **** **** **** +8969 Archivist_Silent_Divine_Protection **** **** **** **** **** **** **** **** +8970 Archivist_Still_Divine_Protection **** **** **** **** **** **** **** **** +8971 Archivist_Eagle_Splendor **** **** **** **** **** **** **** **** +8972 Archivist_Empowered_Eagle_Splendor **** **** **** **** **** **** **** **** +8973 Archivist_Exteneded_Eagle_Splendor **** **** **** **** **** **** **** **** +8974 Archivist_Maximized_Eagle_Splendor **** **** **** **** **** **** **** **** +8975 Archivist_Quickened_Eagle_Splendor **** **** **** **** **** **** **** **** +8976 Archivist_Silent_Eagle_Splendor **** **** **** **** **** **** **** **** +8977 Archivist_Still_Eagle_Splendor **** **** **** **** **** **** **** **** +8978 Archivist_ELATION **** **** **** **** **** **** **** **** +8979 Archivist_Exteneded_ELATION **** **** **** **** **** **** **** **** +8980 Archivist_Quickened_ELATION **** **** **** **** **** **** **** **** +8981 Archivist_Silent_ELATION **** **** **** **** **** **** **** **** +8982 Archivist_Still_ELATION **** **** **** **** **** **** **** **** +8983 Archivist_Endurance **** **** **** **** **** **** **** **** +8984 Archivist_Empowered_Endurance **** **** **** **** **** **** **** **** +8985 Archivist_Exteneded_Endurance **** **** **** **** **** **** **** **** +8986 Archivist_Maximized_Endurance **** **** **** **** **** **** **** **** +8987 Archivist_Quickened_Endurance **** **** **** **** **** **** **** **** +8988 Archivist_Silent_Endurance **** **** **** **** **** **** **** **** +8989 Archivist_Still_Endurance **** **** **** **** **** **** **** **** +8990 Archivist_Find_Traps **** **** **** **** **** **** **** **** +8991 Archivist_Exteneded_Find_Traps **** **** **** **** **** **** **** **** +8992 Archivist_Quickened_Find_Traps **** **** **** **** **** **** **** **** +8993 Archivist_Silent_Find_Traps **** **** **** **** **** **** **** **** +8994 Archivist_Still_Find_Traps **** **** **** **** **** **** **** **** +8995 Archivist_FireTrap **** **** **** **** **** **** **** **** +8996 Archivist_Empowered_FireTrap **** **** **** **** **** **** **** **** +8997 Archivist_Maximized_FireTrap **** **** **** **** **** **** **** **** +8998 Archivist_Quickened_FireTrap **** **** **** **** **** **** **** **** +8999 Archivist_Silent_FireTrap **** **** **** **** **** **** **** **** +9000 Archivist_Still_FireTrap **** **** **** **** **** **** **** **** +9001 Archivist_Flame_Lash **** **** **** **** **** **** **** **** +9002 Archivist_Empowered_Flame_Lash **** **** **** **** **** **** **** **** +9003 Archivist_Maximized_Flame_Lash **** **** **** **** **** **** **** **** +9004 Archivist_Quickened_Flame_Lash **** **** **** **** **** **** **** **** +9005 Archivist_Silent_Flame_Lash **** **** **** **** **** **** **** **** +9006 Archivist_Still_Flame_Lash **** **** **** **** **** **** **** **** +9007 Archivist_FogCloud **** **** **** **** **** **** **** **** +9008 Archivist_Exteneded_FogCloud **** **** **** **** **** **** **** **** +9009 Archivist_Quickened_FogCloud **** **** **** **** **** **** **** **** +9010 Archivist_Silent_FogCloud **** **** **** **** **** **** **** **** +9011 Archivist_Foxs_Cunning **** **** **** **** **** **** **** **** +9012 Archivist_Empowered_Foxs_Cunning **** **** **** **** **** **** **** **** +9013 Archivist_Exteneded_Foxs_Cunning **** **** **** **** **** **** **** **** +9014 Archivist_Maximized_Foxs_Cunning **** **** **** **** **** **** **** **** +9015 Archivist_Quickened_Foxs_Cunning **** **** **** **** **** **** **** **** +9016 Archivist_Silent_Foxs_Cunning **** **** **** **** **** **** **** **** +9017 Archivist_Still_Foxs_Cunning **** **** **** **** **** **** **** **** +9018 Archivist_Ghoul_Touch **** **** **** **** **** **** **** **** +9019 Archivist_Exteneded_Ghoul_Touch **** **** **** **** **** **** **** **** +9020 Archivist_Quickened_Ghoul_Touch **** **** **** **** **** **** **** **** +9021 Archivist_Silent_Ghoul_Touch **** **** **** **** **** **** **** **** +9022 Archivist_Still_Ghoul_Touch **** **** **** **** **** **** **** **** +9023 Archivist_Hold_Animal **** **** **** **** **** **** **** **** +9024 Archivist_Exteneded_Hold_Animal **** **** **** **** **** **** **** **** +9025 Archivist_Quickened_Hold_Animal **** **** **** **** **** **** **** **** +9026 Archivist_Silent_Hold_Animal **** **** **** **** **** **** **** **** +9027 Archivist_Still_Hold_Animal **** **** **** **** **** **** **** **** +9028 Archivist_Hold_Person **** **** **** **** **** **** **** **** +9029 Archivist_Exteneded_Hold_Person **** **** **** **** **** **** **** **** +9030 Archivist_Quickened_Hold_Person **** **** **** **** **** **** **** **** +9031 Archivist_Silent_Hold_Person **** **** **** **** **** **** **** **** +9032 Archivist_Still_Hold_Person **** **** **** **** **** **** **** **** +9033 Archivist_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +9034 Archivist_Empowered_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +9035 Archivist_Maximized_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +9036 Archivist_Quickened_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +9037 Archivist_Silent_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +9038 Archivist_Still_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +9039 Archivist_Knock **** **** **** **** **** **** **** **** +9040 Archivist_Quickened_Knock **** **** **** **** **** **** **** **** +9041 Archivist_Still_Knock **** **** **** **** **** **** **** **** +9042 Archivist_LAHMS_FINGER_DARTS **** **** **** **** **** **** **** **** +9043 Archivist_Quickened_LAHMS_FINGER_DARTS **** **** **** **** **** **** **** **** +9044 Archivist_Silent_LAHMS_FINGER_DARTS **** **** **** **** **** **** **** **** +9045 Archivist_Still_LAHMS_FINGER_DARTS **** **** **** **** **** **** **** **** +9046 Archivist_Lesser_Dispel **** **** **** **** **** **** **** **** +9047 Archivist_Silent_Lesser_Dispel **** **** **** **** **** **** **** **** +9048 Archivist_Still_Lesser_Dispel **** **** **** **** **** **** **** **** +9049 Archivist_Lesser_Restoration **** **** **** **** **** **** **** **** +9050 Archivist_Quickened_Lesser_Restoration **** **** **** **** **** **** **** **** +9051 Archivist_Silent_Lesser_Restoration **** **** **** **** **** **** **** **** +9052 Archivist_Still_Lesser_Restoration **** **** **** **** **** **** **** **** +9053 Archivist_Living_Undeath **** **** **** **** **** **** **** **** +9054 Archivist_Exteneded_Living_Undeath **** **** **** **** **** **** **** **** +9055 Archivist_Quickened_Living_Undeath **** **** **** **** **** **** **** **** +9056 Archivist_Silent_Living_Undeath **** **** **** **** **** **** **** **** +9057 Archivist_Still_Living_Undeath **** **** **** **** **** **** **** **** +9058 Archivist_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +9059 Archivist_Exteneded_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +9060 Archivist_Quickened_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +9061 Archivist_Magic_Missile **** **** **** **** **** **** **** **** +9062 Archivist_Empowered_Magic_Missile **** **** **** **** **** **** **** **** +9063 Archivist_Maximized_Magic_Missile **** **** **** **** **** **** **** **** +9064 Archivist_Quickened_Magic_Missile **** **** **** **** **** **** **** **** +9065 Archivist_Silent_Magic_Missile **** **** **** **** **** **** **** **** +9066 Archivist_Still_Magic_Missile **** **** **** **** **** **** **** **** +9067 Archivist_Melfs_Acid_Arrow **** **** **** **** **** **** **** **** +9068 Archivist_Empowered_Melfs_Acid_Arrow **** **** **** **** **** **** **** **** +9069 Archivist_Maximized_Melfs_Acid_Arrow **** **** **** **** **** **** **** **** +9070 Archivist_Quickened_Melfs_Acid_Arrow **** **** **** **** **** **** **** **** +9071 Archivist_Silent_Melfs_Acid_Arrow **** **** **** **** **** **** **** **** +9072 Archivist_Still_Melfs_Acid_Arrow **** **** **** **** **** **** **** **** +9073 Archivist_Necrotic_Cyst **** **** **** **** **** **** **** **** +9074 Archivist_Quickened_Necrotic_Cyst **** **** **** **** **** **** **** **** +9075 Archivist_Silent_Necrotic_Cyst **** **** **** **** **** **** **** **** +9076 Archivist_Still_Necrotic_Cyst **** **** **** **** **** **** **** **** +9077 Archivist_Negative_Energy_Ray **** **** **** **** **** **** **** **** +9078 Archivist_Empowered_Negative_Energy_Ray **** **** **** **** **** **** **** **** +9079 Archivist_Maximized_Negative_Energy_Ray **** **** **** **** **** **** **** **** +9080 Archivist_Quickened_Negative_Energy_Ray **** **** **** **** **** **** **** **** +9081 Archivist_Silent_Negative_Energy_Ray **** **** **** **** **** **** **** **** +9082 Archivist_Still_Negative_Energy_Ray **** **** **** **** **** **** **** **** +9083 Archivist_One_With_The_Land **** **** **** **** **** **** **** **** +9084 Archivist_Exteneded_One_With_The_Land **** **** **** **** **** **** **** **** +9085 Archivist_Quickened_One_With_The_Land **** **** **** **** **** **** **** **** +9086 Archivist_Silent_One_With_The_Land **** **** **** **** **** **** **** **** +9087 Archivist_Still_One_With_The_Land **** **** **** **** **** **** **** **** +9088 Archivist_Owls_Wisdom **** **** **** **** **** **** **** **** +9089 Archivist_Empowered_Owls_Wisdom **** **** **** **** **** **** **** **** +9090 Archivist_Exteneded_Owls_Wisdom **** **** **** **** **** **** **** **** +9091 Archivist_Maximized_Owls_Wisdom **** **** **** **** **** **** **** **** +9092 Archivist_Quickened_Owls_Wisdom **** **** **** **** **** **** **** **** +9093 Archivist_Silent_Owls_Wisdom **** **** **** **** **** **** **** **** +9094 Archivist_Still_Owls_Wisdom **** **** **** **** **** **** **** **** +9095 Archivist_Remove_Paralysis **** **** **** **** **** **** **** **** +9096 Archivist_Quickened_Remove_Paralysis **** **** **** **** **** **** **** **** +9097 Archivist_Silent_Remove_Paralysis **** **** **** **** **** **** **** **** +9098 Archivist_Still_Remove_Paralysis **** **** **** **** **** **** **** **** +9099 Archivist_Resist_Elements **** **** **** **** **** **** **** **** +9100 Archivist_Exteneded_Resist_Elements **** **** **** **** **** **** **** **** +9101 Archivist_Quickened_Resist_Elements **** **** **** **** **** **** **** **** +9102 Archivist_Silent_Resist_Elements **** **** **** **** **** **** **** **** +9103 Archivist_Still_Resist_Elements **** **** **** **** **** **** **** **** +9104 Archivist_ShieldOther **** **** **** **** **** **** **** **** +9105 Archivist_Exteneded_ShieldOther **** **** **** **** **** **** **** **** +9106 Archivist_Quickened_ShieldOther **** **** **** **** **** **** **** **** +9107 Archivist_Silent_ShieldOther **** **** **** **** **** **** **** **** +9108 Archivist_Still_ShieldOther **** **** **** **** **** **** **** **** +9109 Archivist_Silence **** **** **** **** **** **** **** **** +9110 Archivist_Exteneded_Silence **** **** **** **** **** **** **** **** +9111 Archivist_Quickened_Silence **** **** **** **** **** **** **** **** +9112 Archivist_Silent_Silence **** **** **** **** **** **** **** **** +9113 Archivist_Still_Silence **** **** **** **** **** **** **** **** +9114 Archivist_Snillocs_Snowball_Swarm **** **** **** **** **** **** **** **** +9115 Archivist_Empowered_Snillocs_Snowball_Swarm **** **** **** **** **** **** **** **** +9116 Archivist_Maximized_Snillocs_Snowball_Swarm **** **** **** **** **** **** **** **** +9117 Archivist_Quickened_Snillocs_Snowball_Swarm **** **** **** **** **** **** **** **** +9118 Archivist_Silent_Snillocs_Snowball_Swarm **** **** **** **** **** **** **** **** +9119 Archivist_Still_Snillocs_Snowball_Swarm **** **** **** **** **** **** **** **** +9120 Archivist_Sound_Burst **** **** **** **** **** **** **** **** +9121 Archivist_Maximized_Sound_Burst **** **** **** **** **** **** **** **** +9122 Archivist_Quickened_Sound_Burst **** **** **** **** **** **** **** **** +9123 Archivist_Silent_Sound_Burst **** **** **** **** **** **** **** **** +9124 Archivist_Still_Sound_Burst **** **** **** **** **** **** **** **** +9125 Archivist_SpellslayerArrow **** **** **** **** **** **** **** **** +9126 Archivist_Silent_SpellslayerArrow **** **** **** **** **** **** **** **** +9127 Archivist_Still_SpellslayerArrow **** **** **** **** **** **** **** **** +9128 Archivist_SPORES_OF_THE_VROCK **** **** **** **** **** **** **** **** +9129 Archivist_Empowered_SPORES_OF_THE_VROCK **** **** **** **** **** **** **** **** +9130 Archivist_Maximized_SPORES_OF_THE_VROCK **** **** **** **** **** **** **** **** +9131 Archivist_Quickened_SPORES_OF_THE_VROCK **** **** **** **** **** **** **** **** +9132 Archivist_Silent_SPORES_OF_THE_VROCK **** **** **** **** **** **** **** **** +9133 Archivist_Still_SPORES_OF_THE_VROCK **** **** **** **** **** **** **** **** +9134 Archivist_Stone_Bones **** **** **** **** **** **** **** **** +9135 Archivist_Exteneded_Stone_Bones **** **** **** **** **** **** **** **** +9136 Archivist_Quickened_Stone_Bones **** **** **** **** **** **** **** **** +9137 Archivist_Silent_Stone_Bones **** **** **** **** **** **** **** **** +9138 Archivist_Still_Stone_Bones **** **** **** **** **** **** **** **** +9139 Archivist_Summon_Creature_II **** **** **** **** **** **** **** **** +9140 Archivist_Exteneded_Summon_Creature_II **** **** **** **** **** **** **** **** +9141 Archivist_Quickened_Summon_Creature_II **** **** **** **** **** **** **** **** +9142 Archivist_Silent_Summon_Creature_II **** **** **** **** **** **** **** **** +9143 Archivist_Still_Summon_Creature_II **** **** **** **** **** **** **** **** +9144 Archivist_SummonUndeadII **** **** **** **** **** **** **** **** +9145 Archivist_Exteneded_SummonUndeadII **** **** **** **** **** **** **** **** +9146 Archivist_Quickened_SummonUndeadII **** **** **** **** **** **** **** **** +9147 Archivist_Silent_SummonUndeadII **** **** **** **** **** **** **** **** +9148 Archivist_Still_SummonUndeadII **** **** **** **** **** **** **** **** +9149 Archivist_Treeshape **** **** **** **** **** **** **** **** +9150 Archivist_Exteneded_Treeshape **** **** **** **** **** **** **** **** +9151 Archivist_Quickened_Treeshape **** **** **** **** **** **** **** **** +9152 Archivist_Silent_Treeshape **** **** **** **** **** **** **** **** +9153 Archivist_Still_Treeshape **** **** **** **** **** **** **** **** +9154 Archivist_Ultravision **** **** **** **** **** **** **** **** +9155 Archivist_Exteneded_Ultravision **** **** **** **** **** **** **** **** +9156 Archivist_Silent_Ultravision **** **** **** **** **** **** **** **** +9157 Archivist_Still_Ultravision **** **** **** **** **** **** **** **** +9158 Archivist_UndetectableAlignment **** **** **** **** **** **** **** **** +9159 Archivist_Exteneded_UndetectableAlignment **** **** **** **** **** **** **** **** +9160 Archivist_Quickened_UndetectableAlignment **** **** **** **** **** **** **** **** +9161 Archivist_Silent_UndetectableAlignment **** **** **** **** **** **** **** **** +9162 Archivist_Still_UndetectableAlignment **** **** **** **** **** **** **** **** +9163 Archivist_WAVE_OF_GRIEF **** **** **** **** **** **** **** **** +9164 Archivist_Exteneded_WAVE_OF_GRIEF **** **** **** **** **** **** **** **** +9165 Archivist_Quickened_WAVE_OF_GRIEF **** **** **** **** **** **** **** **** +9166 Archivist_Still_WAVE_OF_GRIEF **** **** **** **** **** **** **** **** +9167 Archivist_Web **** **** **** **** **** **** **** **** +9168 Archivist_Exteneded_Web **** **** **** **** **** **** **** **** +9169 Archivist_Quickened_Web **** **** **** **** **** **** **** **** +9170 Archivist_Silent_Web **** **** **** **** **** **** **** **** +9171 Archivist_Still_Web **** **** **** **** **** **** **** **** +9172 Archivist_Wolfskin **** **** **** **** **** **** **** **** +9173 Archivist_Exteneded_Wolfskin **** **** **** **** **** **** **** **** +9174 Archivist_Quickened_Wolfskin **** **** **** **** **** **** **** **** +9175 Archivist_Silent_Wolfskin **** **** **** **** **** **** **** **** +9176 Archivist_Still_Wolfskin **** **** **** **** **** **** **** **** +9177 Archivist_Animate_Dead **** **** **** **** **** **** **** **** +9178 Archivist_Exteneded_Animate_Dead **** **** **** **** **** **** **** **** +9179 Archivist_Quickened_Animate_Dead **** **** **** **** **** **** **** **** +9180 Archivist_Silent_Animate_Dead **** **** **** **** **** **** **** **** +9181 Archivist_Still_Animate_Dead **** **** **** **** **** **** **** **** +9182 Archivist_ArrowSplit **** **** **** **** **** **** **** **** +9183 Archivist_Silent_ArrowSplit **** **** **** **** **** **** **** **** +9184 Archivist_ArrowStorm **** **** **** **** **** **** **** **** +9185 Archivist_Silent_ArrowStorm **** **** **** **** **** **** **** **** +9186 Archivist_Bestow_Curse **** **** **** **** **** **** **** **** +9187 Archivist_Quickened_Bestow_Curse **** **** **** **** **** **** **** **** +9188 Archivist_Silent_Bestow_Curse **** **** **** **** **** **** **** **** +9189 Archivist_Still_Bestow_Curse **** **** **** **** **** **** **** **** +9190 Archivist_Blacklight **** **** **** **** **** **** **** **** +9191 Archivist_Exteneded_Blacklight **** **** **** **** **** **** **** **** +9192 Archivist_Quickened_Blacklight **** **** **** **** **** **** **** **** +9193 Archivist_Silent_Blacklight **** **** **** **** **** **** **** **** +9194 Archivist_Still_Blacklight **** **** **** **** **** **** **** **** +9195 Archivist_Blade_Thirst **** **** **** **** **** **** **** **** +9196 Archivist_Exteneded_Blade_Thirst **** **** **** **** **** **** **** **** +9197 Archivist_Quickened_Blade_Thirst **** **** **** **** **** **** **** **** +9198 Archivist_Silent_Blade_Thirst **** **** **** **** **** **** **** **** +9199 Archivist_Still_Blade_Thirst **** **** **** **** **** **** **** **** +9200 Archivist_Blessing_of_bahamut **** **** **** **** **** **** **** **** +9201 Archivist_Exteneded_Blessing_of_bahamut **** **** **** **** **** **** **** **** +9202 Archivist_Quickened_Blessing_of_bahamut **** **** **** **** **** **** **** **** +9203 Archivist_Silent_Blessing_of_bahamut **** **** **** **** **** **** **** **** +9204 Archivist_Still_Blessing_of_bahamut **** **** **** **** **** **** **** **** +9205 Archivist_Blindness_and_Deafness **** **** **** **** **** **** **** **** +9206 Archivist_Exteneded_Blindness_and_Deafness **** **** **** **** **** **** **** **** +9207 Archivist_Quickened_Blindness_and_Deafness **** **** **** **** **** **** **** **** +9208 Archivist_Silent_Blindness_and_Deafness **** **** **** **** **** **** **** **** +9209 Archivist_BONEBLADE **** **** **** **** **** **** **** **** +9210 Archivist_BONEBLADE_GREATSWORD **** **** **** **** **** **** **** **** +9211 Archivist_BONEBLADE_LONGSWORD **** **** **** **** **** **** **** **** +9212 Archivist_BONEBLADE_SHORTSWORD **** **** **** **** **** **** **** **** +9213 Archivist_Exteneded_BONEBLADE **** **** **** **** **** **** **** **** +9214 Archivist_Exteneded_BONEBLADE_GREATSWORD **** **** **** **** **** **** **** **** +9215 Archivist_Exteneded_BONEBLADE_LONGSWORD **** **** **** **** **** **** **** **** +9216 Archivist_Exteneded_BONEBLADE_SHORTSWORD **** **** **** **** **** **** **** **** +9217 Archivist_Quickened_BONEBLADE **** **** **** **** **** **** **** **** +9218 Archivist_Quickened_BONEBLADE_GREATSWORD **** **** **** **** **** **** **** **** +9219 Archivist_Quickened_BONEBLADE_LONGSWORD **** **** **** **** **** **** **** **** +9220 Archivist_Quickened_BONEBLADE_SHORTSWORD **** **** **** **** **** **** **** **** +9221 Archivist_Silent_BONEBLADE **** **** **** **** **** **** **** **** +9222 Archivist_Silent_BONEBLADE_GREATSWORD **** **** **** **** **** **** **** **** +9223 Archivist_Silent_BONEBLADE_LONGSWORD **** **** **** **** **** **** **** **** +9224 Archivist_Silent_BONEBLADE_SHORTSWORD **** **** **** **** **** **** **** **** +9225 Archivist_Still_BONEBLADE **** **** **** **** **** **** **** **** +9226 Archivist_Still_BONEBLADE_GREATSWORD **** **** **** **** **** **** **** **** +9227 Archivist_Still_BONEBLADE_LONGSWORD **** **** **** **** **** **** **** **** +9228 Archivist_Still_BONEBLADE_SHORTSWORD **** **** **** **** **** **** **** **** +9229 Archivist_BRILLIANT_EMANATION **** **** **** **** **** **** **** **** +9230 Archivist_Exteneded_BRILLIANT_EMANATION **** **** **** **** **** **** **** **** +9231 Archivist_Quickened_BRILLIANT_EMANATION **** **** **** **** **** **** **** **** +9232 Archivist_Call_Lightning **** **** **** **** **** **** **** **** +9233 Archivist_Empowered_Call_Lightning **** **** **** **** **** **** **** **** +9234 Archivist_Maximized_Call_Lightning **** **** **** **** **** **** **** **** +9235 Archivist_Quickened_Call_Lightning **** **** **** **** **** **** **** **** +9236 Archivist_Silent_Call_Lightning **** **** **** **** **** **** **** **** +9237 Archivist_Still_Call_Lightning **** **** **** **** **** **** **** **** +9238 Archivist_Charm_Monster **** **** **** **** **** **** **** **** +9239 Archivist_Exteneded_Charm_Monster **** **** **** **** **** **** **** **** +9240 Archivist_Quickened_Charm_Monster **** **** **** **** **** **** **** **** +9241 Archivist_Silent_Charm_Monster **** **** **** **** **** **** **** **** +9242 Archivist_Still_Charm_Monster **** **** **** **** **** **** **** **** +9243 Archivist_Clairaudience_and_Clairvoyance **** **** **** **** **** **** **** **** +9244 Archivist_Exteneded_Clairaudience_and_Clairvoyance **** **** **** **** **** **** **** **** +9245 Archivist_Quickened_Clairaudience_and_Clairvoyance **** **** **** **** **** **** **** **** +9246 Archivist_Silent_Clairaudience_and_Clairvoyance **** **** **** **** **** **** **** **** +9247 Archivist_Still_Clairaudience_and_Clairvoyance **** **** **** **** **** **** **** **** +9248 Archivist_Clarity **** **** **** **** **** **** **** **** +9249 Archivist_Exteneded_Clarity **** **** **** **** **** **** **** **** +9250 Archivist_Quickened_Clarity **** **** **** **** **** **** **** **** +9251 Archivist_Still_Clarity **** **** **** **** **** **** **** **** +9252 Archivist_Close_Wounds **** **** **** **** **** **** **** **** +9253 Archivist_Empowered_Close_Wounds **** **** **** **** **** **** **** **** +9254 Archivist_Maximized_Close_Wounds **** **** **** **** **** **** **** **** +9255 Archivist_Quickened_Close_Wounds **** **** **** **** **** **** **** **** +9256 Archivist_Silent_Close_Wounds **** **** **** **** **** **** **** **** +9257 Archivist_CLUTCH_OF_ORCUS **** **** **** **** **** **** **** **** +9258 Archivist_Quickened_CLUTCH_OF_ORCUS **** **** **** **** **** **** **** **** +9259 Archivist_Silent_CLUTCH_OF_ORCUS **** **** **** **** **** **** **** **** +9260 Archivist_Still_CLUTCH_OF_ORCUS **** **** **** **** **** **** **** **** +9261 Archivist_Contagion **** **** **** **** **** **** **** **** +9262 Archivist_Quickened_Contagion **** **** **** **** **** **** **** **** +9263 Archivist_Silent_Contagion **** **** **** **** **** **** **** **** +9264 Archivist_Still_Contagion **** **** **** **** **** **** **** **** +9265 Archivist_Continual_Flame **** **** **** **** **** **** **** **** +9266 Archivist_Quickened_Continual_Flame **** **** **** **** **** **** **** **** +9267 Archivist_Silent_Continual_Flame **** **** **** **** **** **** **** **** +9268 Archivist_Still_Continual_Flame **** **** **** **** **** **** **** **** +9269 Archivist_Crown_Might **** **** **** **** **** **** **** **** +9270 Archivist_Exteneded_Crown_Might **** **** **** **** **** **** **** **** +9271 Archivist_Quickened_Crown_Might **** **** **** **** **** **** **** **** +9272 Archivist_Silent_Crown_Might **** **** **** **** **** **** **** **** +9273 Archivist_Still_Crown_Might **** **** **** **** **** **** **** **** +9274 Archivist_Crown_Protection **** **** **** **** **** **** **** **** +9275 Archivist_Exteneded_Crown_Protection **** **** **** **** **** **** **** **** +9276 Archivist_Quickened_Crown_Protection **** **** **** **** **** **** **** **** +9277 Archivist_Silent_Crown_Protection **** **** **** **** **** **** **** **** +9278 Archivist_Still_Crown_Protection **** **** **** **** **** **** **** **** +9279 Archivist_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +9280 Archivist_Empowered_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +9281 Archivist_Maximized_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +9282 Archivist_Quickened_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +9283 Archivist_Silent_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +9284 Archivist_Still_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +9285 Archivist_Curse_of_Petty_Failing **** **** **** **** **** **** **** **** +9286 Archivist_Exteneded_Curse_of_Petty_Failing **** **** **** **** **** **** **** **** +9287 Archivist_Quickened_Curse_of_Petty_Failing **** **** **** **** **** **** **** **** +9288 Archivist_Silent_Curse_of_Petty_Failing **** **** **** **** **** **** **** **** +9289 Archivist_Still_Curse_of_Petty_Failing **** **** **** **** **** **** **** **** +9290 Archivist_Darkfire **** **** **** **** **** **** **** **** +9291 Archivist_Exteneded_Darkfire **** **** **** **** **** **** **** **** +9292 Archivist_Quickened_Darkfire **** **** **** **** **** **** **** **** +9293 Archivist_Silent_Darkfire **** **** **** **** **** **** **** **** +9294 Archivist_Still_Darkfire **** **** **** **** **** **** **** **** +9295 Archivist_DarkflameArrow **** **** **** **** **** **** **** **** +9296 Archivist_Silent_DarkflameArrow **** **** **** **** **** **** **** **** +9297 Archivist_Daylight **** **** **** **** **** **** **** **** +9298 Archivist_Exteneded_Daylight **** **** **** **** **** **** **** **** +9299 Archivist_Quickened_Daylight **** **** **** **** **** **** **** **** +9300 Archivist_Silent_Daylight **** **** **** **** **** **** **** **** +9301 Archivist_Still_Daylight **** **** **** **** **** **** **** **** +9302 Archivist_DeeperDarkness **** **** **** **** **** **** **** **** +9303 Archivist_Exteneded_DeeperDarkness **** **** **** **** **** **** **** **** +9304 Archivist_Quickened_DeeperDarkness **** **** **** **** **** **** **** **** +9305 Archivist_Silent_DeeperDarkness **** **** **** **** **** **** **** **** +9306 Archivist_DEVILS_EYE **** **** **** **** **** **** **** **** +9307 Archivist_Quickened_DEVILS_EYE **** **** **** **** **** **** **** **** +9308 Archivist_Silent_DEVILS_EYE **** **** **** **** **** **** **** **** +9309 Archivist_Still_DEVILS_EYE **** **** **** **** **** **** **** **** +9310 Archivist_Dispel_Magic **** **** **** **** **** **** **** **** +9311 Archivist_Quickened_Dispel_Magic **** **** **** **** **** **** **** **** +9312 Archivist_Silent_Dispel_Magic **** **** **** **** **** **** **** **** +9313 Archivist_Still_Dispel_Magic **** **** **** **** **** **** **** **** +9314 Archivist_Dominate_Animal **** **** **** **** **** **** **** **** +9315 Archivist_Exteneded_Dominate_Animal **** **** **** **** **** **** **** **** +9316 Archivist_Quickened_Dominate_Animal **** **** **** **** **** **** **** **** +9317 Archivist_Silent_Dominate_Animal **** **** **** **** **** **** **** **** +9318 Archivist_Still_Dominate_Animal **** **** **** **** **** **** **** **** +9319 Archivist_ENERGIZE_POTION **** **** **** **** **** **** **** **** +9320 Archivist_ENERGIZE_POTION_ACID **** **** **** **** **** **** **** **** +9321 Archivist_ENERGIZE_POTION_COLD **** **** **** **** **** **** **** **** +9322 Archivist_ENERGIZE_POTION_ELECTRICITY **** **** **** **** **** **** **** **** +9323 Archivist_ENERGIZE_POTION_FIRE **** **** **** **** **** **** **** **** +9324 Archivist_ENERGIZE_POTION_SONIC **** **** **** **** **** **** **** **** +9325 Archivist_Quickened_ENERGIZE_POTION **** **** **** **** **** **** **** **** +9326 Archivist_Quickened_ENERGIZE_POTION_ACID **** **** **** **** **** **** **** **** +9327 Archivist_Quickened_ENERGIZE_POTION_COLD **** **** **** **** **** **** **** **** +9328 Archivist_Quickened_ENERGIZE_POTION_ELECTRICITY **** **** **** **** **** **** **** **** +9329 Archivist_Quickened_ENERGIZE_POTION_FIRE **** **** **** **** **** **** **** **** +9330 Archivist_Quickened_ENERGIZE_POTION_SONIC **** **** **** **** **** **** **** **** +9331 Archivist_Silent_ENERGIZE_POTION **** **** **** **** **** **** **** **** +9332 Archivist_Silent_ENERGIZE_POTION_ACID **** **** **** **** **** **** **** **** +9333 Archivist_Silent_ENERGIZE_POTION_COLD **** **** **** **** **** **** **** **** +9334 Archivist_Silent_ENERGIZE_POTION_ELECTRICITY **** **** **** **** **** **** **** **** +9335 Archivist_Silent_ENERGIZE_POTION_FIRE **** **** **** **** **** **** **** **** +9336 Archivist_Silent_ENERGIZE_POTION_SONIC **** **** **** **** **** **** **** **** +9337 Archivist_Still_ENERGIZE_POTION **** **** **** **** **** **** **** **** +9338 Archivist_Still_ENERGIZE_POTION_ACID **** **** **** **** **** **** **** **** +9339 Archivist_Still_ENERGIZE_POTION_COLD **** **** **** **** **** **** **** **** +9340 Archivist_Still_ENERGIZE_POTION_ELECTRICITY **** **** **** **** **** **** **** **** +9341 Archivist_Still_ENERGIZE_POTION_FIRE **** **** **** **** **** **** **** **** +9342 Archivist_Still_ENERGIZE_POTION_SONIC **** **** **** **** **** **** **** **** +9343 Archivist_Energy_Aegis **** **** **** **** **** **** **** **** +9344 Archivist_Energy_Aegis_Acid **** **** **** **** **** **** **** **** +9345 Archivist_Energy_Aegis_Cold **** **** **** **** **** **** **** **** +9346 Archivist_Energy_Aegis_Elec **** **** **** **** **** **** **** **** +9347 Archivist_Energy_Aegis_Fire **** **** **** **** **** **** **** **** +9348 Archivist_Energy_Aegis_Sonic **** **** **** **** **** **** **** **** +9349 Archivist_Exteneded_Energy_Aegis **** **** **** **** **** **** **** **** +9350 Archivist_Exteneded_Energy_Aegis_Acid **** **** **** **** **** **** **** **** +9351 Archivist_Exteneded_Energy_Aegis_Cold **** **** **** **** **** **** **** **** +9352 Archivist_Exteneded_Energy_Aegis_Elec **** **** **** **** **** **** **** **** +9353 Archivist_Exteneded_Energy_Aegis_Fire **** **** **** **** **** **** **** **** +9354 Archivist_Exteneded_Energy_Aegis_Sonic **** **** **** **** **** **** **** **** +9355 Archivist_Quickened_Energy_Aegis **** **** **** **** **** **** **** **** +9356 Archivist_Quickened_Energy_Aegis_Acid **** **** **** **** **** **** **** **** +9357 Archivist_Quickened_Energy_Aegis_Cold **** **** **** **** **** **** **** **** +9358 Archivist_Quickened_Energy_Aegis_Elec **** **** **** **** **** **** **** **** +9359 Archivist_Quickened_Energy_Aegis_Fire **** **** **** **** **** **** **** **** +9360 Archivist_Quickened_Energy_Aegis_Sonic **** **** **** **** **** **** **** **** +9361 Archivist_Silent_Energy_Aegis **** **** **** **** **** **** **** **** +9362 Archivist_Silent_Energy_Aegis_Acid **** **** **** **** **** **** **** **** +9363 Archivist_Silent_Energy_Aegis_Cold **** **** **** **** **** **** **** **** +9364 Archivist_Silent_Energy_Aegis_Elec **** **** **** **** **** **** **** **** +9365 Archivist_Silent_Energy_Aegis_Fire **** **** **** **** **** **** **** **** +9366 Archivist_Silent_Energy_Aegis_Sonic **** **** **** **** **** **** **** **** +9367 Archivist_Still_Energy_Aegis **** **** **** **** **** **** **** **** +9368 Archivist_Still_Energy_Aegis_Acid **** **** **** **** **** **** **** **** +9369 Archivist_Still_Energy_Aegis_Cold **** **** **** **** **** **** **** **** +9370 Archivist_Still_Energy_Aegis_Elec **** **** **** **** **** **** **** **** +9371 Archivist_Still_Energy_Aegis_Fire **** **** **** **** **** **** **** **** +9372 Archivist_Still_Energy_Aegis_Sonic **** **** **** **** **** **** **** **** +9373 Archivist_FLESH_RIPPER **** **** **** **** **** **** **** **** +9374 Archivist_Empowered_FLESH_RIPPER **** **** **** **** **** **** **** **** +9375 Archivist_Maximized_FLESH_RIPPER **** **** **** **** **** **** **** **** +9376 Archivist_Quickened_FLESH_RIPPER **** **** **** **** **** **** **** **** +9377 Archivist_Silent_FLESH_RIPPER **** **** **** **** **** **** **** **** +9378 Archivist_Still_FLESH_RIPPER **** **** **** **** **** **** **** **** +9379 Archivist_Forceblast **** **** **** **** **** **** **** **** +9380 Archivist_Empowered_Forceblast **** **** **** **** **** **** **** **** +9381 Archivist_Maximized_Forceblast **** **** **** **** **** **** **** **** +9382 Archivist_Quickened_Forceblast **** **** **** **** **** **** **** **** +9383 Archivist_Silent_Forceblast **** **** **** **** **** **** **** **** +9384 Archivist_Still_Forceblast **** **** **** **** **** **** **** **** +9385 Archivist_Glyph_of_Warding_Master **** **** **** **** **** **** **** **** +9386 Archivist_Glyph_of_Warding_Acid **** **** **** **** **** **** **** **** +9387 Archivist_Glyph_of_Warding_Cold **** **** **** **** **** **** **** **** +9388 Archivist_Glyph_of_Warding_Electricity **** **** **** **** **** **** **** **** +9389 Archivist_Glyph_of_Warding_Fire **** **** **** **** **** **** **** **** +9390 Archivist_Glyph_of_Warding_Sonic **** **** **** **** **** **** **** **** +9391 Archivist_Empowered_Glyph_of_Warding_Master **** **** **** **** **** **** **** **** +9392 Archivist_Empowered_Glyph_of_Warding_Acid **** **** **** **** **** **** **** **** +9393 Archivist_Empowered_Glyph_of_Warding_Cold **** **** **** **** **** **** **** **** +9394 Archivist_Empowered_Glyph_of_Warding_Electricity **** **** **** **** **** **** **** **** +9395 Archivist_Empowered_Glyph_of_Warding_Fire **** **** **** **** **** **** **** **** +9396 Archivist_Empowered_Glyph_of_Warding_Sonic **** **** **** **** **** **** **** **** +9397 Archivist_Exteneded_Glyph_of_Warding_Master **** **** **** **** **** **** **** **** +9398 Archivist_Exteneded_Glyph_of_Warding_Acid **** **** **** **** **** **** **** **** +9399 Archivist_Exteneded_Glyph_of_Warding_Cold **** **** **** **** **** **** **** **** +9400 Archivist_Exteneded_Glyph_of_Warding_Electricity **** **** **** **** **** **** **** **** +9401 Archivist_Exteneded_Glyph_of_Warding_Fire **** **** **** **** **** **** **** **** +9402 Archivist_Exteneded_Glyph_of_Warding_Sonic **** **** **** **** **** **** **** **** +9403 Archivist_Maximized_Glyph_of_Warding_Master **** **** **** **** **** **** **** **** +9404 Archivist_Maximized_Glyph_of_Warding_Acid **** **** **** **** **** **** **** **** +9405 Archivist_Maximized_Glyph_of_Warding_Cold **** **** **** **** **** **** **** **** +9406 Archivist_Maximized_Glyph_of_Warding_Electricity **** **** **** **** **** **** **** **** +9407 Archivist_Maximized_Glyph_of_Warding_Fire **** **** **** **** **** **** **** **** +9408 Archivist_Maximized_Glyph_of_Warding_Sonic **** **** **** **** **** **** **** **** +9409 Archivist_Quickened_Glyph_of_Warding_Master **** **** **** **** **** **** **** **** +9410 Archivist_Quickened_Glyph_of_Warding_Acid **** **** **** **** **** **** **** **** +9411 Archivist_Quickened_Glyph_of_Warding_Cold **** **** **** **** **** **** **** **** +9412 Archivist_Quickened_Glyph_of_Warding_Electricity **** **** **** **** **** **** **** **** +9413 Archivist_Quickened_Glyph_of_Warding_Fire **** **** **** **** **** **** **** **** +9414 Archivist_Quickened_Glyph_of_Warding_Sonic **** **** **** **** **** **** **** **** +9415 Archivist_Silent_Glyph_of_Warding_Master **** **** **** **** **** **** **** **** +9416 Archivist_Silent_Glyph_of_Warding_Acid **** **** **** **** **** **** **** **** +9417 Archivist_Silent_Glyph_of_Warding_Cold **** **** **** **** **** **** **** **** +9418 Archivist_Silent_Glyph_of_Warding_Electricity **** **** **** **** **** **** **** **** +9419 Archivist_Silent_Glyph_of_Warding_Fire **** **** **** **** **** **** **** **** +9420 Archivist_Silent_Glyph_of_Warding_Sonic **** **** **** **** **** **** **** **** +9421 Archivist_Still_Glyph_of_Warding_Master **** **** **** **** **** **** **** **** +9422 Archivist_Still_Glyph_of_Warding_Acid **** **** **** **** **** **** **** **** +9423 Archivist_Still_Glyph_of_Warding_Cold **** **** **** **** **** **** **** **** +9424 Archivist_Still_Glyph_of_Warding_Electricity **** **** **** **** **** **** **** **** +9425 Archivist_Still_Glyph_of_Warding_Fire **** **** **** **** **** **** **** **** +9426 Archivist_Still_Glyph_of_Warding_Sonic **** **** **** **** **** **** **** **** +9427 Archivist_Greater_Magic_Fang **** **** **** **** **** **** **** **** +9428 Archivist_Exteneded_Greater_Magic_Fang **** **** **** **** **** **** **** **** +9429 Archivist_Quickened_Greater_Magic_Fang **** **** **** **** **** **** **** **** +9430 Archivist_Silent_Greater_Magic_Fang **** **** **** **** **** **** **** **** +9431 Archivist_Still_Greater_Magic_Fang **** **** **** **** **** **** **** **** +9432 Archivist_Greenfire **** **** **** **** **** **** **** **** +9433 Archivist_Empowered_Greenfire **** **** **** **** **** **** **** **** +9434 Archivist_Exteneded_Greenfire **** **** **** **** **** **** **** **** +9435 Archivist_Maximized_Greenfire **** **** **** **** **** **** **** **** +9436 Archivist_Quickened_Greenfire **** **** **** **** **** **** **** **** +9437 Archivist_Silent_Greenfire **** **** **** **** **** **** **** **** +9438 Archivist_Still_Greenfire **** **** **** **** **** **** **** **** +9439 Archivist_HAMMER_OF_RIGHTEOUSNESS **** **** **** **** **** **** **** **** +9440 Archivist_Empowered_HAMMER_OF_RIGHTEOUSNESS **** **** **** **** **** **** **** **** +9441 Archivist_Maximized_HAMMER_OF_RIGHTEOUSNESS **** **** **** **** **** **** **** **** +9442 Archivist_Quickened_HAMMER_OF_RIGHTEOUSNESS **** **** **** **** **** **** **** **** +9443 Archivist_Silent_HAMMER_OF_RIGHTEOUSNESS **** **** **** **** **** **** **** **** +9444 Archivist_Still_HAMMER_OF_RIGHTEOUSNESS **** **** **** **** **** **** **** **** +9445 Archivist_Healing_Sting **** **** **** **** **** **** **** **** +9446 Archivist_Empowered_Healing_Sting **** **** **** **** **** **** **** **** +9447 Archivist_Maximized_Healing_Sting **** **** **** **** **** **** **** **** +9448 Archivist_Quickened_Healing_Sting **** **** **** **** **** **** **** **** +9449 Archivist_Silent_Healing_Sting **** **** **** **** **** **** **** **** +9450 Archivist_Still_Healing_Sting **** **** **** **** **** **** **** **** +9451 Archivist_Heroism **** **** **** **** **** **** **** **** +9452 Archivist_Exteneded_Heroism **** **** **** **** **** **** **** **** +9453 Archivist_Quickened_Heroism **** **** **** **** **** **** **** **** +9454 Archivist_Silent_Heroism **** **** **** **** **** **** **** **** +9455 Archivist_Still_Heroism **** **** **** **** **** **** **** **** +9456 Archivist_Infestation_of_Maggots **** **** **** **** **** **** **** **** +9457 Archivist_Empowered_Infestation_of_Maggots **** **** **** **** **** **** **** **** +9458 Archivist_Exteneded_Infestation_of_Maggots **** **** **** **** **** **** **** **** +9459 Archivist_Maximized_Infestation_of_Maggots **** **** **** **** **** **** **** **** +9460 Archivist_Quickened_Infestation_of_Maggots **** **** **** **** **** **** **** **** +9461 Archivist_Silent_Infestation_of_Maggots **** **** **** **** **** **** **** **** +9462 Archivist_Still_Infestation_of_Maggots **** **** **** **** **** **** **** **** +9463 Archivist_Inflict_Serious_Wounds **** **** **** **** **** **** **** **** +9464 Archivist_Empowered_Inflict_Serious_Wounds **** **** **** **** **** **** **** **** +9465 Archivist_Maximized_Inflict_Serious_Wounds **** **** **** **** **** **** **** **** +9466 Archivist_Quickened_Inflict_Serious_Wounds **** **** **** **** **** **** **** **** +9467 Archivist_Silent_Inflict_Serious_Wounds **** **** **** **** **** **** **** **** +9468 Archivist_Still_Inflict_Serious_Wounds **** **** **** **** **** **** **** **** +9469 Archivist_Invisibility **** **** **** **** **** **** **** **** +9470 Archivist_Exteneded_Invisibility **** **** **** **** **** **** **** **** +9471 Archivist_Quickened_Invisibility **** **** **** **** **** **** **** **** +9472 Archivist_Silent_Invisibility **** **** **** **** **** **** **** **** +9473 Archivist_Still_Invisibility **** **** **** **** **** **** **** **** +9474 Archivist_Invisibility_Purge **** **** **** **** **** **** **** **** +9475 Archivist_Exteneded_Invisibility_Purge **** **** **** **** **** **** **** **** +9476 Archivist_Quickened_Invisibility_Purge **** **** **** **** **** **** **** **** +9477 Archivist_Silent_Invisibility_Purge **** **** **** **** **** **** **** **** +9478 Archivist_Still_Invisibility_Purge **** **** **** **** **** **** **** **** +9479 Archivist_Invisibility_Sphere **** **** **** **** **** **** **** **** +9480 Archivist_Exteneded_Invisibility_Sphere **** **** **** **** **** **** **** **** +9481 Archivist_Quickened_Invisibility_Sphere **** **** **** **** **** **** **** **** +9482 Archivist_Silent_Invisibility_Sphere **** **** **** **** **** **** **** **** +9483 Archivist_Still_Invisibility_Sphere **** **** **** **** **** **** **** **** +9484 Archivist_Keen_Edge **** **** **** **** **** **** **** **** +9485 Archivist_Exteneded_Keen_Edge **** **** **** **** **** **** **** **** +9486 Archivist_Quickened_Keen_Edge **** **** **** **** **** **** **** **** +9487 Archivist_Silent_Keen_Edge **** **** **** **** **** **** **** **** +9488 Archivist_Still_Keen_Edge **** **** **** **** **** **** **** **** +9489 Archivist_Legions_Conviction **** **** **** **** **** **** **** **** +9490 Archivist_Exteneded_Legions_Conviction **** **** **** **** **** **** **** **** +9491 Archivist_Quickened_Legions_Conviction **** **** **** **** **** **** **** **** +9492 Archivist_Silent_Legions_Conviction **** **** **** **** **** **** **** **** +9493 Archivist_Still_Legions_Conviction **** **** **** **** **** **** **** **** +9494 Archivist_Legions_Curse_of_Impending_Blades **** **** **** **** **** **** **** **** +9495 Archivist_Exteneded_Legions_Curse_of_Impending_Blades **** **** **** **** **** **** **** **** +9496 Archivist_Quickened_Legions_Curse_of_Impending_Blades **** **** **** **** **** **** **** **** +9497 Archivist_Silent_Legions_Curse_of_Impending_Blades **** **** **** **** **** **** **** **** +9498 Archivist_Still_Legions_Curse_of_Impending_Blades **** **** **** **** **** **** **** **** +9499 Archivist_Lightning_Bolt **** **** **** **** **** **** **** **** +9500 Archivist_Empowered_Lightning_Bolt **** **** **** **** **** **** **** **** +9501 Archivist_Maximized_Lightning_Bolt **** **** **** **** **** **** **** **** +9502 Archivist_Quickened_Lightning_Bolt **** **** **** **** **** **** **** **** +9503 Archivist_Silent_Lightning_Bolt **** **** **** **** **** **** **** **** +9504 Archivist_Still_Lightning_Bolt **** **** **** **** **** **** **** **** +9505 Archivist_LocateObject **** **** **** **** **** **** **** **** +9506 Archivist_Exteneded_LocateObject **** **** **** **** **** **** **** **** +9507 Archivist_Quickened_LocateObject **** **** **** **** **** **** **** **** +9508 Archivist_Silent_LocateObject **** **** **** **** **** **** **** **** +9509 Archivist_Still_LocateObject **** **** **** **** **** **** **** **** +9510 Archivist_Magic_Circle_against_Chaos **** **** **** **** **** **** **** **** +9511 Archivist_Exteneded_Magic_Circle_against_Chaos **** **** **** **** **** **** **** **** +9512 Archivist_Quickened_Magic_Circle_against_Chaos **** **** **** **** **** **** **** **** +9513 Archivist_Silent_Magic_Circle_against_Chaos **** **** **** **** **** **** **** **** +9514 Archivist_Still_Magic_Circle_against_Chaos **** **** **** **** **** **** **** **** +9515 Archivist_Magic_Circle_against_Evil **** **** **** **** **** **** **** **** +9516 Archivist_Exteneded_Magic_Circle_against_Evil **** **** **** **** **** **** **** **** +9517 Archivist_Quickened_Magic_Circle_against_Evil **** **** **** **** **** **** **** **** +9518 Archivist_Silent_Magic_Circle_against_Evil **** **** **** **** **** **** **** **** +9519 Archivist_Still_Magic_Circle_against_Evil **** **** **** **** **** **** **** **** +9520 Archivist_Magic_Circle_against_Good **** **** **** **** **** **** **** **** +9521 Archivist_Exteneded_Magic_Circle_against_Good **** **** **** **** **** **** **** **** +9522 Archivist_Quickened_Magic_Circle_against_Good **** **** **** **** **** **** **** **** +9523 Archivist_Silent_Magic_Circle_against_Good **** **** **** **** **** **** **** **** +9524 Archivist_Still_Magic_Circle_against_Good **** **** **** **** **** **** **** **** +9525 Archivist_Magic_Circle_against_Law **** **** **** **** **** **** **** **** +9526 Archivist_Exteneded_Magic_Circle_against_Law **** **** **** **** **** **** **** **** +9527 Archivist_Quickened_Magic_Circle_against_Law **** **** **** **** **** **** **** **** +9528 Archivist_Silent_Magic_Circle_against_Law **** **** **** **** **** **** **** **** +9529 Archivist_Still_Magic_Circle_against_Law **** **** **** **** **** **** **** **** +9530 Archivist_Magic_Vestment **** **** **** **** **** **** **** **** +9531 Archivist_Exteneded_Magic_Vestment **** **** **** **** **** **** **** **** +9532 Archivist_Quickened_Magic_Vestment **** **** **** **** **** **** **** **** +9533 Archivist_Silent_Magic_Vestment **** **** **** **** **** **** **** **** +9534 Archivist_Still_Magic_Vestment **** **** **** **** **** **** **** **** +9535 Archivist_MASOCHISM **** **** **** **** **** **** **** **** +9536 Archivist_Exteneded_MASOCHISM **** **** **** **** **** **** **** **** +9537 Archivist_Mass_Aid **** **** **** **** **** **** **** **** +9538 Archivist_Empowered_Mass_Aid **** **** **** **** **** **** **** **** +9539 Archivist_Exteneded_Mass_Aid **** **** **** **** **** **** **** **** +9540 Archivist_Maximized_Mass_Aid **** **** **** **** **** **** **** **** +9541 Archivist_Quickened_Mass_Aid **** **** **** **** **** **** **** **** +9542 Archivist_Silent_Mass_Aid **** **** **** **** **** **** **** **** +9543 Archivist_Still_Mass_Aid **** **** **** **** **** **** **** **** +9544 Archivist_Mass_Lesser_Vigor **** **** **** **** **** **** **** **** +9545 Archivist_Exteneded_Mass_Lesser_Vigor **** **** **** **** **** **** **** **** +9546 Archivist_Quickened_Mass_Lesser_Vigor **** **** **** **** **** **** **** **** +9547 Archivist_Silent_Mass_Lesser_Vigor **** **** **** **** **** **** **** **** +9548 Archivist_Still_Mass_Lesser_Vigor **** **** **** **** **** **** **** **** +9549 Archivist_MirrorImage **** **** **** **** **** **** **** **** +9550 Archivist_Exteneded_MirrorImage **** **** **** **** **** **** **** **** +9551 Archivist_Quickened_MirrorImage **** **** **** **** **** **** **** **** +9552 Archivist_Silent_MirrorImage **** **** **** **** **** **** **** **** +9553 Archivist_Still_MirrorImage **** **** **** **** **** **** **** **** +9554 Archivist_Necrotic_Bloat **** **** **** **** **** **** **** **** +9555 Archivist_Empowered_Necrotic_Bloat **** **** **** **** **** **** **** **** +9556 Archivist_Maximized_Necrotic_Bloat **** **** **** **** **** **** **** **** +9557 Archivist_Negative_Energy_Burst **** **** **** **** **** **** **** **** +9558 Archivist_Empowered_Negative_Energy_Burst **** **** **** **** **** **** **** **** +9559 Archivist_Maximized_Negative_Energy_Burst **** **** **** **** **** **** **** **** +9560 Archivist_Quickened_Negative_Energy_Burst **** **** **** **** **** **** **** **** +9561 Archivist_Silent_Negative_Energy_Burst **** **** **** **** **** **** **** **** +9562 Archivist_Still_Negative_Energy_Burst **** **** **** **** **** **** **** **** +9563 Archivist_Negative_Energy_Protection **** **** **** **** **** **** **** **** +9564 Archivist_Exteneded_Negative_Energy_Protection **** **** **** **** **** **** **** **** +9565 Archivist_Quickened_Negative_Energy_Protection **** **** **** **** **** **** **** **** +9566 Archivist_Silent_Negative_Energy_Protection **** **** **** **** **** **** **** **** +9567 Archivist_Still_Negative_Energy_Protection **** **** **** **** **** **** **** **** +9568 Archivist_ObscureObject **** **** **** **** **** **** **** **** +9569 Archivist_Exteneded_ObscureObject **** **** **** **** **** **** **** **** +9570 Archivist_Quickened_ObscureObject **** **** **** **** **** **** **** **** +9571 Archivist_Silent_ObscureObject **** **** **** **** **** **** **** **** +9572 Archivist_Still_ObscureObject **** **** **** **** **** **** **** **** +9573 Archivist_Prayer **** **** **** **** **** **** **** **** +9574 Archivist_Exteneded_Prayer **** **** **** **** **** **** **** **** +9575 Archivist_Quickened_Prayer **** **** **** **** **** **** **** **** +9576 Archivist_Silent_Prayer **** **** **** **** **** **** **** **** +9577 Archivist_Still_Prayer **** **** **** **** **** **** **** **** +9578 Archivist_Protection_from_Elements **** **** **** **** **** **** **** **** +9579 Archivist_Exteneded_Protection_from_Elements **** **** **** **** **** **** **** **** +9580 Archivist_Quickened_Protection_from_Elements **** **** **** **** **** **** **** **** +9581 Archivist_Silent_Protection_from_Elements **** **** **** **** **** **** **** **** +9582 Archivist_Still_Protection_from_Elements **** **** **** **** **** **** **** **** +9583 Archivist_Quillfire **** **** **** **** **** **** **** **** +9584 Archivist_Empowered_Quillfire **** **** **** **** **** **** **** **** +9585 Archivist_Maximized_Quillfire **** **** **** **** **** **** **** **** +9586 Archivist_Quickened_Quillfire **** **** **** **** **** **** **** **** +9587 Archivist_Silent_Quillfire **** **** **** **** **** **** **** **** +9588 Archivist_Still_Quillfire **** **** **** **** **** **** **** **** +9589 Archivist_RED_FESTER **** **** **** **** **** **** **** **** +9590 Archivist_Quickened_RED_FESTER **** **** **** **** **** **** **** **** +9591 Archivist_Silent_RED_FESTER **** **** **** **** **** **** **** **** +9592 Archivist_Still_RED_FESTER **** **** **** **** **** **** **** **** +9593 Archivist_Remove_Blindness_and_Deafness **** **** **** **** **** **** **** **** +9594 Archivist_Quickened_Remove_Blindness_and_Deafness **** **** **** **** **** **** **** **** +9595 Archivist_Silent_Remove_Blindness_and_Deafness **** **** **** **** **** **** **** **** +9596 Archivist_Still_Remove_Blindness_and_Deafness **** **** **** **** **** **** **** **** +9597 Archivist_Remove_Curse **** **** **** **** **** **** **** **** +9598 Archivist_Quickened_Remove_Curse **** **** **** **** **** **** **** **** +9599 Archivist_Silent_Remove_Curse **** **** **** **** **** **** **** **** +9600 Archivist_Still_Remove_Curse **** **** **** **** **** **** **** **** +9601 Archivist_Remove_Disease **** **** **** **** **** **** **** **** +9602 Archivist_Quickened_Remove_Disease **** **** **** **** **** **** **** **** +9603 Archivist_Silent_Remove_Disease **** **** **** **** **** **** **** **** +9604 Archivist_Still_Remove_Disease **** **** **** **** **** **** **** **** +9605 Archivist_RingOfBlades **** **** **** **** **** **** **** **** +9606 Archivist_Exteneded_RingOfBlades **** **** **** **** **** **** **** **** +9607 Archivist_Quickened_RingOfBlades **** **** **** **** **** **** **** **** +9608 Archivist_Silent_RingOfBlades **** **** **** **** **** **** **** **** +9609 Archivist_Still_RingOfBlades **** **** **** **** **** **** **** **** +9610 Archivist_ROTTING_CURSE_OF_URFESTRA **** **** **** **** **** **** **** **** +9611 Archivist_Empowered_ROTTING_CURSE_OF_URFESTRA **** **** **** **** **** **** **** **** +9612 Archivist_Maximized_ROTTING_CURSE_OF_URFESTRA **** **** **** **** **** **** **** **** +9613 Archivist_Quickened_ROTTING_CURSE_OF_URFESTRA **** **** **** **** **** **** **** **** +9614 Archivist_Silent_ROTTING_CURSE_OF_URFESTRA **** **** **** **** **** **** **** **** +9615 Archivist_Still_ROTTING_CURSE_OF_URFESTRA **** **** **** **** **** **** **** **** +9616 Archivist_Searing_Light **** **** **** **** **** **** **** **** +9617 Archivist_Empowered_Searing_Light **** **** **** **** **** **** **** **** +9618 Archivist_Maximized_Searing_Light **** **** **** **** **** **** **** **** +9619 Archivist_Quickened_Searing_Light **** **** **** **** **** **** **** **** +9620 Archivist_Silent_Searing_Light **** **** **** **** **** **** **** **** +9621 Archivist_Still_Searing_Light **** **** **** **** **** **** **** **** +9622 Archivist_SerpentArrows **** **** **** **** **** **** **** **** +9623 Archivist_Quickened_SerpentArrows **** **** **** **** **** **** **** **** +9624 Archivist_Silent_SerpentArrows **** **** **** **** **** **** **** **** +9625 Archivist_Still_SerpentArrows **** **** **** **** **** **** **** **** +9626 Archivist_Serpents_Sigh **** **** **** **** **** **** **** **** +9627 Archivist_SS_Bolt_of_Acid **** **** **** **** **** **** **** **** +9628 Archivist_SS_Bolt_of_Lightning **** **** **** **** **** **** **** **** +9629 Archivist_SS_Cone_of_Acid **** **** **** **** **** **** **** **** +9630 Archivist_SS_Cone_of_Cold **** **** **** **** **** **** **** **** +9631 Archivist_SS_Cone_of_Fire **** **** **** **** **** **** **** **** +9632 Archivist_Empowered_Serpents_Sigh **** **** **** **** **** **** **** **** +9633 Archivist_Empowered_SS_Bolt_of_Acid **** **** **** **** **** **** **** **** +9634 Archivist_Empowered_SS_Bolt_of_Lightning **** **** **** **** **** **** **** **** +9635 Archivist_Empowered_SS_Cone_of_Acid **** **** **** **** **** **** **** **** +9636 Archivist_Empowered_SS_Cone_of_Cold **** **** **** **** **** **** **** **** +9637 Archivist_Empowered_SS_Cone_of_Fire **** **** **** **** **** **** **** **** +9638 Archivist_Maximized_Serpents_Sigh **** **** **** **** **** **** **** **** +9639 Archivist_Maximized_SS_Bolt_of_Acid **** **** **** **** **** **** **** **** +9640 Archivist_Maximized_SS_Bolt_of_Lightning **** **** **** **** **** **** **** **** +9641 Archivist_Maximized_SS_Cone_of_Acid **** **** **** **** **** **** **** **** +9642 Archivist_Maximized_SS_Cone_of_Cold **** **** **** **** **** **** **** **** +9643 Archivist_Maximized_SS_Cone_of_Fire **** **** **** **** **** **** **** **** +9644 Archivist_Quickened_Serpents_Sigh **** **** **** **** **** **** **** **** +9645 Archivist_Quickened_SS_Bolt_of_Acid **** **** **** **** **** **** **** **** +9646 Archivist_Quickened_SS_Bolt_of_Lightning **** **** **** **** **** **** **** **** +9647 Archivist_Quickened_SS_Cone_of_Acid **** **** **** **** **** **** **** **** +9648 Archivist_Quickened_SS_Cone_of_Cold **** **** **** **** **** **** **** **** +9649 Archivist_Quickened_SS_Cone_of_Fire **** **** **** **** **** **** **** **** +9650 Archivist_Silent_Serpents_Sigh **** **** **** **** **** **** **** **** +9651 Archivist_Silent_SS_Bolt_of_Acid **** **** **** **** **** **** **** **** +9652 Archivist_Silent_SS_Bolt_of_Lightning **** **** **** **** **** **** **** **** +9653 Archivist_Silent_SS_Cone_of_Acid **** **** **** **** **** **** **** **** +9654 Archivist_Silent_SS_Cone_of_Cold **** **** **** **** **** **** **** **** +9655 Archivist_Silent_SS_Cone_of_Fire **** **** **** **** **** **** **** **** +9656 Archivist_Still_Serpents_Sigh **** **** **** **** **** **** **** **** +9657 Archivist_Still_SS_Bolt_of_Acid **** **** **** **** **** **** **** **** +9658 Archivist_Still_SS_Bolt_of_Lightning **** **** **** **** **** **** **** **** +9659 Archivist_Still_SS_Cone_of_Acid **** **** **** **** **** **** **** **** +9660 Archivist_Still_SS_Cone_of_Cold **** **** **** **** **** **** **** **** +9661 Archivist_Still_SS_Cone_of_Fire **** **** **** **** **** **** **** **** +9662 Archivist_SHIVERING_TOUCH **** **** **** **** **** **** **** **** +9663 Archivist_Empowered_SHIVERING_TOUCH **** **** **** **** **** **** **** **** +9664 Archivist_Exteneded_SHIVERING_TOUCH **** **** **** **** **** **** **** **** +9665 Archivist_Maximized_SHIVERING_TOUCH **** **** **** **** **** **** **** **** +9666 Archivist_Quickened_SHIVERING_TOUCH **** **** **** **** **** **** **** **** +9667 Archivist_Silent_SHIVERING_TOUCH **** **** **** **** **** **** **** **** +9668 Archivist_Still_SHIVERING_TOUCH **** **** **** **** **** **** **** **** +9669 Archivist_Shout **** **** **** **** **** **** **** **** +9670 Archivist_Empowered_Shout **** **** **** **** **** **** **** **** +9671 Archivist_Maximized_Shout **** **** **** **** **** **** **** **** +9672 Archivist_Quickened_Shout **** **** **** **** **** **** **** **** +9673 Archivist_Silent_Shout **** **** **** **** **** **** **** **** +9674 Archivist_SHRIVELING **** **** **** **** **** **** **** **** +9675 Archivist_Empowered_SHRIVELING **** **** **** **** **** **** **** **** +9676 Archivist_Maximized_SHRIVELING **** **** **** **** **** **** **** **** +9677 Archivist_Quickened_SHRIVELING **** **** **** **** **** **** **** **** +9678 Archivist_Silent_SHRIVELING **** **** **** **** **** **** **** **** +9679 Archivist_Still_SHRIVELING **** **** **** **** **** **** **** **** +9680 Archivist_Slashing_Darkness **** **** **** **** **** **** **** **** +9681 Archivist_Empowered_Slashing_Darkness **** **** **** **** **** **** **** **** +9682 Archivist_Maximized_Slashing_Darkness **** **** **** **** **** **** **** **** +9683 Archivist_Quickened_Slashing_Darkness **** **** **** **** **** **** **** **** +9684 Archivist_Silent_Slashing_Darkness **** **** **** **** **** **** **** **** +9685 Archivist_Still_Slashing_Darkness **** **** **** **** **** **** **** **** +9686 Archivist_SleetStorm **** **** **** **** **** **** **** **** +9687 Archivist_Exteneded_SleetStorm **** **** **** **** **** **** **** **** +9688 Archivist_Quickened_SleetStorm **** **** **** **** **** **** **** **** +9689 Archivist_Silent_SleetStorm **** **** **** **** **** **** **** **** +9690 Archivist_Still_SleetStorm **** **** **** **** **** **** **** **** +9691 Archivist_Snare **** **** **** **** **** **** **** **** +9692 Archivist_Quickened_Snare **** **** **** **** **** **** **** **** +9693 Archivist_Silent_Snare **** **** **** **** **** **** **** **** +9694 Archivist_Still_Snare **** **** **** **** **** **** **** **** +9695 Archivist_Spiderskin **** **** **** **** **** **** **** **** +9696 Archivist_Exteneded_Spiderskin **** **** **** **** **** **** **** **** +9697 Archivist_Quickened_Spiderskin **** **** **** **** **** **** **** **** +9698 Archivist_Silent_Spiderskin **** **** **** **** **** **** **** **** +9699 Archivist_Still_Spiderskin **** **** **** **** **** **** **** **** +9700 Archivist_Spike_Growth **** **** **** **** **** **** **** **** +9701 Archivist_Exteneded_Spike_Growth **** **** **** **** **** **** **** **** +9702 Archivist_Quickened_Spike_Growth **** **** **** **** **** **** **** **** +9703 Archivist_Silent_Spike_Growth **** **** **** **** **** **** **** **** +9704 Archivist_Still_Spike_Growth **** **** **** **** **** **** **** **** +9705 Archivist_Summon_Creature_III **** **** **** **** **** **** **** **** +9706 Archivist_Exteneded_Summon_Creature_III **** **** **** **** **** **** **** **** +9707 Archivist_Quickened_Summon_Creature_III **** **** **** **** **** **** **** **** +9708 Archivist_Silent_Summon_Creature_III **** **** **** **** **** **** **** **** +9709 Archivist_Still_Summon_Creature_III **** **** **** **** **** **** **** **** +9710 Archivist_SummonUndeadIII **** **** **** **** **** **** **** **** +9711 Archivist_Exteneded_SummonUndeadIII **** **** **** **** **** **** **** **** +9712 Archivist_Quickened_SummonUndeadIII **** **** **** **** **** **** **** **** +9713 Archivist_Silent_SummonUndeadIII **** **** **** **** **** **** **** **** +9714 Archivist_Still_SummonUndeadIII **** **** **** **** **** **** **** **** +9715 Archivist_TOUCH_OF_JUIBLEX **** **** **** **** **** **** **** **** +9716 Archivist_Quickened_TOUCH_OF_JUIBLEX **** **** **** **** **** **** **** **** +9717 Archivist_Silent_TOUCH_OF_JUIBLEX **** **** **** **** **** **** **** **** +9718 Archivist_Still_TOUCH_OF_JUIBLEX **** **** **** **** **** **** **** **** +9719 Archivist_UNLIVING_WEAPON **** **** **** **** **** **** **** **** +9720 Archivist_Empowered_UNLIVING_WEAPON **** **** **** **** **** **** **** **** +9721 Archivist_Maximized_UNLIVING_WEAPON **** **** **** **** **** **** **** **** +9722 Archivist_Quickened_UNLIVING_WEAPON **** **** **** **** **** **** **** **** +9723 Archivist_Silent_UNLIVING_WEAPON **** **** **** **** **** **** **** **** +9724 Archivist_Still_UNLIVING_WEAPON **** **** **** **** **** **** **** **** +9725 Archivist_Vigor **** **** **** **** **** **** **** **** +9726 Archivist_Exteneded_Vigor **** **** **** **** **** **** **** **** +9727 Archivist_Quickened_Vigor **** **** **** **** **** **** **** **** +9728 Archivist_Silent_Vigor **** **** **** **** **** **** **** **** +9729 Archivist_Still_Vigor **** **** **** **** **** **** **** **** +9730 Archivist_WaterBreathing **** **** **** **** **** **** **** **** +9731 Archivist_Exteneded_WaterBreathing **** **** **** **** **** **** **** **** +9732 Archivist_Quickened_WaterBreathing **** **** **** **** **** **** **** **** +9733 Archivist_Silent_WaterBreathing **** **** **** **** **** **** **** **** +9734 Archivist_Still_WaterBreathing **** **** **** **** **** **** **** **** +9735 Archivist_WRACK **** **** **** **** **** **** **** **** +9736 Archivist_Exteneded_WRACK **** **** **** **** **** **** **** **** +9737 Archivist_Quickened_WRACK **** **** **** **** **** **** **** **** +9738 Archivist_Silent_WRACK **** **** **** **** **** **** **** **** +9739 Archivist_Still_WRACK **** **** **** **** **** **** **** **** +9740 Archivist_ABSORB_STRENGTH **** **** **** **** **** **** **** **** +9741 Archivist_Exteneded_ABSORB_STRENGTH **** **** **** **** **** **** **** **** +9742 Archivist_Quickened_ABSORB_STRENGTH **** **** **** **** **** **** **** **** +9743 Archivist_Silent_ABSORB_STRENGTH **** **** **** **** **** **** **** **** +9744 Archivist_Still_ABSORB_STRENGTH **** **** **** **** **** **** **** **** +9745 Archivist_ABYSSAL_MIGHT **** **** **** **** **** **** **** **** +9746 Archivist_Empowered_ABYSSAL_MIGHT **** **** **** **** **** **** **** **** +9747 Archivist_Exteneded_ABYSSAL_MIGHT **** **** **** **** **** **** **** **** +9748 Archivist_Quickened_ABYSSAL_MIGHT **** **** **** **** **** **** **** **** +9749 Archivist_Silent_ABYSSAL_MIGHT **** **** **** **** **** **** **** **** +9750 Archivist_Still_ABYSSAL_MIGHT **** **** **** **** **** **** **** **** +9751 Archivist_BloodfreezeArrow **** **** **** **** **** **** **** **** +9752 Archivist_Silent_BloodfreezeArrow **** **** **** **** **** **** **** **** +9753 Archivist_BloodOfTheMartyr **** **** **** **** **** **** **** **** +9754 Archivist_Quickened_BloodOfTheMartyr **** **** **** **** **** **** **** **** +9755 Archivist_Silent_BloodOfTheMartyr **** **** **** **** **** **** **** **** +9756 Archivist_Still_BloodOfTheMartyr **** **** **** **** **** **** **** **** +9757 Archivist_CLAWS_OF_THE_SAVAGE **** **** **** **** **** **** **** **** +9758 Archivist_Empowered_CLAWS_OF_THE_SAVAGE **** **** **** **** **** **** **** **** +9759 Archivist_Exteneded_CLAWS_OF_THE_SAVAGE **** **** **** **** **** **** **** **** +9760 Archivist_Quickened_CLAWS_OF_THE_SAVAGE **** **** **** **** **** **** **** **** +9761 Archivist_Silent_CLAWS_OF_THE_SAVAGE **** **** **** **** **** **** **** **** +9762 Archivist_Still_CLAWS_OF_THE_SAVAGE **** **** **** **** **** **** **** **** +9763 Archivist_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +9764 Archivist_Empowered_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +9765 Archivist_Maximized_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +9766 Archivist_Quickened_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +9767 Archivist_Silent_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +9768 Archivist_Still_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +9769 Archivist_DAMNING_DARKNESS **** **** **** **** **** **** **** **** +9770 Archivist_Exteneded_DAMNING_DARKNESS **** **** **** **** **** **** **** **** +9771 Archivist_Quickened_DAMNING_DARKNESS **** **** **** **** **** **** **** **** +9772 Archivist_Silent_DAMNING_DARKNESS **** **** **** **** **** **** **** **** +9773 Archivist_Darkness_Armor **** **** **** **** **** **** **** **** +9774 Archivist_Exteneded_Darkness_Armor **** **** **** **** **** **** **** **** +9775 Archivist_Quickened_Darkness_Armor **** **** **** **** **** **** **** **** +9776 Archivist_Silent_Darkness_Armor **** **** **** **** **** **** **** **** +9777 Archivist_Still_Darkness_Armor **** **** **** **** **** **** **** **** +9778 Archivist_Death_Ward **** **** **** **** **** **** **** **** +9779 Archivist_Exteneded_Death_Ward **** **** **** **** **** **** **** **** +9780 Archivist_Quickened_Death_Ward **** **** **** **** **** **** **** **** +9781 Archivist_Silent_Death_Ward **** **** **** **** **** **** **** **** +9782 Archivist_Still_Death_Ward **** **** **** **** **** **** **** **** +9783 Archivist_DIAMOND_SPRAY **** **** **** **** **** **** **** **** +9784 Archivist_Empowered_DIAMOND_SPRAY **** **** **** **** **** **** **** **** +9785 Archivist_Exteneded_DIAMOND_SPRAY **** **** **** **** **** **** **** **** +9786 Archivist_Maximized_DIAMOND_SPRAY **** **** **** **** **** **** **** **** +9787 Archivist_Quickened_DIAMOND_SPRAY **** **** **** **** **** **** **** **** +9788 Archivist_Silent_DIAMOND_SPRAY **** **** **** **** **** **** **** **** +9789 Archivist_Still_DIAMOND_SPRAY **** **** **** **** **** **** **** **** +9790 Archivist_Dimensional_Anchor **** **** **** **** **** **** **** **** +9791 Archivist_Exteneded_Dimensional_Anchor **** **** **** **** **** **** **** **** +9792 Archivist_Quickened_Dimensional_Anchor **** **** **** **** **** **** **** **** +9793 Archivist_Silent_Dimensional_Anchor **** **** **** **** **** **** **** **** +9794 Archivist_Still_Dimensional_Anchor **** **** **** **** **** **** **** **** +9795 Archivist_DimensionDoor_RadialMaster **** **** **** **** **** **** **** **** +9796 Archivist_DimensionDoor_SelfOnly **** **** **** **** **** **** **** **** +9797 Archivist_DimensionDoor_Party **** **** **** **** **** **** **** **** +9798 Archivist_DimensionDoor_DirDist_SelfOnly **** **** **** **** **** **** **** **** +9799 Archivist_DimensionDoor_DirDist_Party **** **** **** **** **** **** **** **** +9800 Archivist_Quickened_DimensionDoor_RadialMaster **** **** **** **** **** **** **** **** +9801 Archivist_Quickened_DimensionDoor_SelfOnly **** **** **** **** **** **** **** **** +9802 Archivist_Quickened_DimensionDoor_Party **** **** **** **** **** **** **** **** +9803 Archivist_Quickened_DimensionDoor_DirDist_SelfOnly **** **** **** **** **** **** **** **** +9804 Archivist_Quickened_DimensionDoor_DirDist_Party **** **** **** **** **** **** **** **** +9805 Archivist_Silent_DimensionDoor_RadialMaster **** **** **** **** **** **** **** **** +9806 Archivist_Silent_DimensionDoor_SelfOnly **** **** **** **** **** **** **** **** +9807 Archivist_Silent_DimensionDoor_Party **** **** **** **** **** **** **** **** +9808 Archivist_Silent_DimensionDoor_DirDist_SelfOnly **** **** **** **** **** **** **** **** +9809 Archivist_Silent_DimensionDoor_DirDist_Party **** **** **** **** **** **** **** **** +9810 Archivist_Dismissal **** **** **** **** **** **** **** **** +9811 Archivist_Quickened_Dismissal **** **** **** **** **** **** **** **** +9812 Archivist_Silent_Dismissal **** **** **** **** **** **** **** **** +9813 Archivist_Still_Dismissal **** **** **** **** **** **** **** **** +9814 Archivist_Divine_Power **** **** **** **** **** **** **** **** +9815 Archivist_Exteneded_Divine_Power **** **** **** **** **** **** **** **** +9816 Archivist_Quickened_Divine_Power **** **** **** **** **** **** **** **** +9817 Archivist_Silent_Divine_Power **** **** **** **** **** **** **** **** +9818 Archivist_Still_Divine_Power **** **** **** **** **** **** **** **** +9819 Archivist_Dominate_Person **** **** **** **** **** **** **** **** +9820 Archivist_Exteneded_Dominate_Person **** **** **** **** **** **** **** **** +9821 Archivist_Quickened_Dominate_Person **** **** **** **** **** **** **** **** +9822 Archivist_Silent_Dominate_Person **** **** **** **** **** **** **** **** +9823 Archivist_Still_Dominate_Person **** **** **** **** **** **** **** **** +9824 Archivist_DoublestrikeArrow **** **** **** **** **** **** **** **** +9825 Archivist_Quickened_DoublestrikeArrow **** **** **** **** **** **** **** **** +9826 Archivist_Silent_DoublestrikeArrow **** **** **** **** **** **** **** **** +9827 Archivist_Still_DoublestrikeArrow **** **** **** **** **** **** **** **** +9828 Archivist_DraconicMight **** **** **** **** **** **** **** **** +9829 Archivist_Exteneded_DraconicMight **** **** **** **** **** **** **** **** +9830 Archivist_Quickened_DraconicMight **** **** **** **** **** **** **** **** +9831 Archivist_Silent_DraconicMight **** **** **** **** **** **** **** **** +9832 Archivist_Still_DraconicMight **** **** **** **** **** **** **** **** +9833 Archivist_Elemental_Shield **** **** **** **** **** **** **** **** +9834 Archivist_Exteneded_Elemental_Shield **** **** **** **** **** **** **** **** +9835 Archivist_Quickened_Elemental_Shield **** **** **** **** **** **** **** **** +9836 Archivist_Silent_Elemental_Shield **** **** **** **** **** **** **** **** +9837 Archivist_Still_Elemental_Shield **** **** **** **** **** **** **** **** +9838 Archivist_Enervation **** **** **** **** **** **** **** **** +9839 Archivist_Empowered_Enervation **** **** **** **** **** **** **** **** +9840 Archivist_Maximized_Enervation **** **** **** **** **** **** **** **** +9841 Archivist_Quickened_Enervation **** **** **** **** **** **** **** **** +9842 Archivist_Silent_Enervation **** **** **** **** **** **** **** **** +9843 Archivist_Still_Enervation **** **** **** **** **** **** **** **** +9844 Archivist_Fear **** **** **** **** **** **** **** **** +9845 Archivist_Exteneded_Fear **** **** **** **** **** **** **** **** +9846 Archivist_Quickened_Fear **** **** **** **** **** **** **** **** +9847 Archivist_Silent_Fear **** **** **** **** **** **** **** **** +9848 Archivist_Still_Fear **** **** **** **** **** **** **** **** +9849 Archivist_Fireball **** **** **** **** **** **** **** **** +9850 Archivist_Empowered_Fireball **** **** **** **** **** **** **** **** +9851 Archivist_Maximized_Fireball **** **** **** **** **** **** **** **** +9852 Archivist_Quickened_Fireball **** **** **** **** **** **** **** **** +9853 Archivist_Silent_Fireball **** **** **** **** **** **** **** **** +9854 Archivist_Still_Fireball **** **** **** **** **** **** **** **** +9855 Archivist_Freedom_of_Movement **** **** **** **** **** **** **** **** +9856 Archivist_Exteneded_Freedom_of_Movement **** **** **** **** **** **** **** **** +9857 Archivist_Quickened_Freedom_of_Movement **** **** **** **** **** **** **** **** +9858 Archivist_Silent_Freedom_of_Movement **** **** **** **** **** **** **** **** +9859 Archivist_Still_Freedom_of_Movement **** **** **** **** **** **** **** **** +9860 Archivist_GREATER_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +9861 Archivist_Exteneded_GREATER_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +9862 Archivist_Quickened_GREATER_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +9863 Archivist_Greater_Magic_Weapon **** **** **** **** **** **** **** **** +9864 Archivist_Exteneded_Greater_Magic_Weapon **** **** **** **** **** **** **** **** +9865 Archivist_Quickened_Greater_Magic_Weapon **** **** **** **** **** **** **** **** +9866 Archivist_Silent_Greater_Magic_Weapon **** **** **** **** **** **** **** **** +9867 Archivist_Still_Greater_Magic_Weapon **** **** **** **** **** **** **** **** +9868 Archivist_Greater_Resistance **** **** **** **** **** **** **** **** +9869 Archivist_Exteneded_Greater_Resistance **** **** **** **** **** **** **** **** +9870 Archivist_Quickened_Greater_Resistance **** **** **** **** **** **** **** **** +9871 Archivist_Silent_Greater_Resistance **** **** **** **** **** **** **** **** +9872 Archivist_Still_Greater_Resistance **** **** **** **** **** **** **** **** +9873 Archivist_Gust_of_Wind **** **** **** **** **** **** **** **** +9874 Archivist_Quickened_Gust_of_Wind **** **** **** **** **** **** **** **** +9875 Archivist_Silent_Gust_of_Wind **** **** **** **** **** **** **** **** +9876 Archivist_Still_Gust_of_Wind **** **** **** **** **** **** **** **** +9877 Archivist_Hammer_of_the_Gods **** **** **** **** **** **** **** **** +9878 Archivist_Empowered_Hammer_of_the_Gods **** **** **** **** **** **** **** **** +9879 Archivist_Maximized_Hammer_of_the_Gods **** **** **** **** **** **** **** **** +9880 Archivist_Quickened_Hammer_of_the_Gods **** **** **** **** **** **** **** **** +9881 Archivist_Silent_Hammer_of_the_Gods **** **** **** **** **** **** **** **** +9882 Archivist_Still_Hammer_of_the_Gods **** **** **** **** **** **** **** **** +9883 Archivist_Haste **** **** **** **** **** **** **** **** +9884 Archivist_Exteneded_Haste **** **** **** **** **** **** **** **** +9885 Archivist_Quickened_Haste **** **** **** **** **** **** **** **** +9886 Archivist_Silent_Haste **** **** **** **** **** **** **** **** +9887 Archivist_Still_Haste **** **** **** **** **** **** **** **** +9888 Archivist_Hold_Monster **** **** **** **** **** **** **** **** +9889 Archivist_Exteneded_Hold_Monster **** **** **** **** **** **** **** **** +9890 Archivist_Quickened_Hold_Monster **** **** **** **** **** **** **** **** +9891 Archivist_Silent_Hold_Monster **** **** **** **** **** **** **** **** +9892 Archivist_Still_Hold_Monster **** **** **** **** **** **** **** **** +9893 Archivist_Holy_Sword **** **** **** **** **** **** **** **** +9894 Archivist_Exteneded_Holy_Sword **** **** **** **** **** **** **** **** +9895 Archivist_Quickened_Holy_Sword **** **** **** **** **** **** **** **** +9896 Archivist_Silent_Holy_Sword **** **** **** **** **** **** **** **** +9897 Archivist_Still_Holy_Sword **** **** **** **** **** **** **** **** +9898 Archivist_Improved_Invisibility **** **** **** **** **** **** **** **** +9899 Archivist_Exteneded_Improved_Invisibility **** **** **** **** **** **** **** **** +9900 Archivist_Quickened_Improved_Invisibility **** **** **** **** **** **** **** **** +9901 Archivist_Silent_Improved_Invisibility **** **** **** **** **** **** **** **** +9902 Archivist_Still_Improved_Invisibility **** **** **** **** **** **** **** **** +9903 Archivist_Improved_Mage_Armor **** **** **** **** **** **** **** **** +9904 Archivist_Exteneded_Improved_Mage_Armor **** **** **** **** **** **** **** **** +9905 Archivist_Quickened_Improved_Mage_Armor **** **** **** **** **** **** **** **** +9906 Archivist_Silent_Improved_Mage_Armor **** **** **** **** **** **** **** **** +9907 Archivist_Still_Improved_Mage_Armor **** **** **** **** **** **** **** **** +9908 Archivist_Inflict_Critical_Wounds **** **** **** **** **** **** **** **** +9909 Archivist_Empowered_Inflict_Critical_Wounds **** **** **** **** **** **** **** **** +9910 Archivist_Maximized_Inflict_Critical_Wounds **** **** **** **** **** **** **** **** +9911 Archivist_Quickened_Inflict_Critical_Wounds **** **** **** **** **** **** **** **** +9912 Archivist_Silent_Inflict_Critical_Wounds **** **** **** **** **** **** **** **** +9913 Archivist_Still_Inflict_Critical_Wounds **** **** **** **** **** **** **** **** +9914 Archivist_Legions_Shield_of_Faith **** **** **** **** **** **** **** **** +9915 Archivist_Exteneded_Legions_Shield_of_Faith **** **** **** **** **** **** **** **** +9916 Archivist_Quickened_Legions_Shield_of_Faith **** **** **** **** **** **** **** **** +9917 Archivist_Silent_Legions_Shield_of_Faith **** **** **** **** **** **** **** **** +9918 Archivist_Still_Legions_Shield_of_Faith **** **** **** **** **** **** **** **** +9919 Archivist_Lesser_Planar_Ally **** **** **** **** **** **** **** **** +9920 Archivist_Exteneded_Lesser_Planar_Ally **** **** **** **** **** **** **** **** +9921 Archivist_Quickened_Lesser_Planar_Ally **** **** **** **** **** **** **** **** +9922 Archivist_Silent_Lesser_Planar_Ally **** **** **** **** **** **** **** **** +9923 Archivist_Still_Lesser_Planar_Ally **** **** **** **** **** **** **** **** +9924 Archivist_Lesser_Planar_Binding **** **** **** **** **** **** **** **** +9925 Archivist_Exteneded_Lesser_Planar_Binding **** **** **** **** **** **** **** **** +9926 Archivist_Quickened_Lesser_Planar_Binding **** **** **** **** **** **** **** **** +9927 Archivist_Silent_Lesser_Planar_Binding **** **** **** **** **** **** **** **** +9928 Archivist_Still_Lesser_Planar_Binding **** **** **** **** **** **** **** **** +9929 Archivist_Lesser_Spell_Breach **** **** **** **** **** **** **** **** +9930 Archivist_Quickened_Lesser_Spell_Breach **** **** **** **** **** **** **** **** +9931 Archivist_Silent_Lesser_Spell_Breach **** **** **** **** **** **** **** **** +9932 Archivist_Still_Lesser_Spell_Breach **** **** **** **** **** **** **** **** +9933 Archivist_Lower_Spell_Resistance **** **** **** **** **** **** **** **** +9934 Archivist_Exteneded_Lower_Spell_Resistance **** **** **** **** **** **** **** **** +9935 Archivist_Silent_Lower_Spell_Resistance **** **** **** **** **** **** **** **** +9936 Archivist_Still_Lower_Spell_Resistance **** **** **** **** **** **** **** **** +9937 Archivist_Mass_Camoflage **** **** **** **** **** **** **** **** +9938 Archivist_Exteneded_Mass_Camoflage **** **** **** **** **** **** **** **** +9939 Archivist_Quickened_Mass_Camoflage **** **** **** **** **** **** **** **** +9940 Archivist_Silent_Mass_Camoflage **** **** **** **** **** **** **** **** +9941 Archivist_Still_Mass_Camoflage **** **** **** **** **** **** **** **** +9942 Archivist_Mass_Ultravision **** **** **** **** **** **** **** **** +9943 Archivist_Exteneded_Mass_Ultravision **** **** **** **** **** **** **** **** +9944 Archivist_Silent_Mass_Ultravision **** **** **** **** **** **** **** **** +9945 Archivist_Still_Mass_Ultravision **** **** **** **** **** **** **** **** +9946 Archivist_Necrotic_Domination **** **** **** **** **** **** **** **** +9947 Archivist_Exteneded_Necrotic_Domination **** **** **** **** **** **** **** **** +9948 Archivist_Quickened_Necrotic_Domination **** **** **** **** **** **** **** **** +9949 Archivist_Silent_Necrotic_Domination **** **** **** **** **** **** **** **** +9950 Archivist_Still_Necrotic_Domination **** **** **** **** **** **** **** **** +9951 Archivist_Neutralize_Poison **** **** **** **** **** **** **** **** +9952 Archivist_Quickened_Neutralize_Poison **** **** **** **** **** **** **** **** +9953 Archivist_Silent_Neutralize_Poison **** **** **** **** **** **** **** **** +9954 Archivist_Still_Neutralize_Poison **** **** **** **** **** **** **** **** +9955 Archivist_NONDETECTION **** **** **** **** **** **** **** **** +9956 Archivist_Exteneded_NONDETECTION **** **** **** **** **** **** **** **** +9957 Archivist_Quickened_NONDETECTION **** **** **** **** **** **** **** **** +9958 Archivist_Silent_NONDETECTION **** **** **** **** **** **** **** **** +9959 Archivist_Still_NONDETECTION **** **** **** **** **** **** **** **** +9960 Archivist_Panacea **** **** **** **** **** **** **** **** +9961 Archivist_Empowered_Panacea **** **** **** **** **** **** **** **** +9962 Archivist_Maximized_Panacea **** **** **** **** **** **** **** **** +9963 Archivist_Quickened_Panacea **** **** **** **** **** **** **** **** +9964 Archivist_Silent_Panacea **** **** **** **** **** **** **** **** +9965 Archivist_Still_Panacea **** **** **** **** **** **** **** **** +9966 Archivist_Phantasmal_Killer **** **** **** **** **** **** **** **** +9967 Archivist_Empowered_Phantasmal_Killer **** **** **** **** **** **** **** **** +9968 Archivist_Maximized_Phantasmal_Killer **** **** **** **** **** **** **** **** +9969 Archivist_Quickened_Phantasmal_Killer **** **** **** **** **** **** **** **** +9970 Archivist_Silent_Phantasmal_Killer **** **** **** **** **** **** **** **** +9971 Archivist_Still_Phantasmal_Killer **** **** **** **** **** **** **** **** +9972 Archivist_Poison **** **** **** **** **** **** **** **** +9973 Archivist_Empowered_Poison **** **** **** **** **** **** **** **** +9974 Archivist_Maximized_Poison **** **** **** **** **** **** **** **** +9975 Archivist_Quickened_Poison **** **** **** **** **** **** **** **** +9976 Archivist_Silent_Poison **** **** **** **** **** **** **** **** +9977 Archivist_Still_Poison **** **** **** **** **** **** **** **** +9978 Archivist_Polymorph_Self **** **** **** **** **** **** **** **** +9979 Archivist_Polymorph_GIANT_SPIDER **** **** **** **** **** **** **** **** +9980 Archivist_Polymorph_TROLL **** **** **** **** **** **** **** **** +9981 Archivist_Polymorph_UMBER_HULK **** **** **** **** **** **** **** **** +9982 Archivist_Polymorph_PIXIE **** **** **** **** **** **** **** **** +9983 Archivist_Polymorph_ZOMBIE **** **** **** **** **** **** **** **** +9984 Archivist_Exteneded_Polymorph_Self **** **** **** **** **** **** **** **** +9985 Archivist_Exteneded_Polymorph_GIANT_SPIDER **** **** **** **** **** **** **** **** +9986 Archivist_Exteneded_Polymorph_TROLL **** **** **** **** **** **** **** **** +9987 Archivist_Exteneded_Polymorph_UMBER_HULK **** **** **** **** **** **** **** **** +9988 Archivist_Exteneded_Polymorph_PIXIE **** **** **** **** **** **** **** **** +9989 Archivist_Exteneded_Polymorph_ZOMBIE **** **** **** **** **** **** **** **** +9990 Archivist_Quickened_Polymorph_Self **** **** **** **** **** **** **** **** +9991 Archivist_Quickened_Polymorph_GIANT_SPIDER **** **** **** **** **** **** **** **** +9992 Archivist_Quickened_Polymorph_TROLL **** **** **** **** **** **** **** **** +9993 Archivist_Quickened_Polymorph_UMBER_HULK **** **** **** **** **** **** **** **** +9994 Archivist_Quickened_Polymorph_PIXIE **** **** **** **** **** **** **** **** +9995 Archivist_Quickened_Polymorph_ZOMBIE **** **** **** **** **** **** **** **** +9996 Archivist_Silent_Polymorph_Self **** **** **** **** **** **** **** **** +9997 Archivist_Silent_Polymorph_GIANT_SPIDER **** **** **** **** **** **** **** **** +9998 Archivist_Silent_Polymorph_TROLL **** **** **** **** **** **** **** **** +9999 Archivist_Silent_Polymorph_UMBER_HULK **** **** **** **** **** **** **** **** +10000 Archivist_Silent_Polymorph_PIXIE **** **** **** **** **** **** **** **** +10001 Archivist_Silent_Polymorph_ZOMBIE **** **** **** **** **** **** **** **** +10002 Archivist_Recitation **** **** **** **** **** **** **** **** +10003 Archivist_Exteneded_Recitation **** **** **** **** **** **** **** **** +10004 Archivist_Quickened_Recitation **** **** **** **** **** **** **** **** +10005 Archivist_Silent_Recitation **** **** **** **** **** **** **** **** +10006 Archivist_Still_Recitation **** **** **** **** **** **** **** **** +10007 Archivist_RepelVermin **** **** **** **** **** **** **** **** +10008 Archivist_Exteneded_RepelVermin **** **** **** **** **** **** **** **** +10009 Archivist_Quickened_RepelVermin **** **** **** **** **** **** **** **** +10010 Archivist_Silent_RepelVermin **** **** **** **** **** **** **** **** +10011 Archivist_Still_RepelVermin **** **** **** **** **** **** **** **** +10012 Archivist_Restoration **** **** **** **** **** **** **** **** +10013 Archivist_Quickened_Restoration **** **** **** **** **** **** **** **** +10014 Archivist_Silent_Restoration **** **** **** **** **** **** **** **** +10015 Archivist_Still_Restoration **** **** **** **** **** **** **** **** +10016 Archivist_ShadowArrow **** **** **** **** **** **** **** **** +10017 Archivist_Silent_ShadowArrow **** **** **** **** **** **** **** **** +10018 Archivist_Stoneskin **** **** **** **** **** **** **** **** +10019 Archivist_Exteneded_Stoneskin **** **** **** **** **** **** **** **** +10020 Archivist_Quickened_Stoneskin **** **** **** **** **** **** **** **** +10021 Archivist_Silent_Stoneskin **** **** **** **** **** **** **** **** +10022 Archivist_Still_Stoneskin **** **** **** **** **** **** **** **** +10023 Archivist_STOP_HEART **** **** **** **** **** **** **** **** +10024 Archivist_Quickened_STOP_HEART **** **** **** **** **** **** **** **** +10025 Archivist_Still_STOP_HEART **** **** **** **** **** **** **** **** +10026 Archivist_Summon_Creature_IV **** **** **** **** **** **** **** **** +10027 Archivist_Exteneded_Summon_Creature_IV **** **** **** **** **** **** **** **** +10028 Archivist_Quickened_Summon_Creature_IV **** **** **** **** **** **** **** **** +10029 Archivist_Silent_Summon_Creature_IV **** **** **** **** **** **** **** **** +10030 Archivist_Still_Summon_Creature_IV **** **** **** **** **** **** **** **** +10031 Archivist_SummonUndeadIV **** **** **** **** **** **** **** **** +10032 Archivist_Exteneded_SummonUndeadIV **** **** **** **** **** **** **** **** +10033 Archivist_Quickened_SummonUndeadIV **** **** **** **** **** **** **** **** +10034 Archivist_Silent_SummonUndeadIV **** **** **** **** **** **** **** **** +10035 Archivist_Still_SummonUndeadIV **** **** **** **** **** **** **** **** +10036 Archivist_SUNMANTLE **** **** **** **** **** **** **** **** +10037 Archivist_Exteneded_SUNMANTLE **** **** **** **** **** **** **** **** +10038 Archivist_Quickened_SUNMANTLE **** **** **** **** **** **** **** **** +10039 Archivist_Still_SUNMANTLE **** **** **** **** **** **** **** **** +10040 Archivist_SwordOfConscience **** **** **** **** **** **** **** **** +10041 Archivist_Quickened_SwordOfConscience **** **** **** **** **** **** **** **** +10042 Archivist_Silent_SwordOfConscience **** **** **** **** **** **** **** **** +10043 Archivist_Unholy_Sword **** **** **** **** **** **** **** **** +10044 Archivist_Exteneded_Unholy_Sword **** **** **** **** **** **** **** **** +10045 Archivist_Quickened_Unholy_Sword **** **** **** **** **** **** **** **** +10046 Archivist_Silent_Unholy_Sword **** **** **** **** **** **** **** **** +10047 Archivist_Still_Unholy_Sword **** **** **** **** **** **** **** **** +10048 Archivist_Awaken **** **** **** **** **** **** **** **** +10049 Archivist_Empowered_Awaken **** **** **** **** **** **** **** **** +10050 Archivist_Maximized_Awaken **** **** **** **** **** **** **** **** +10051 Archivist_Quickened_Awaken **** **** **** **** **** **** **** **** +10052 Archivist_Silent_Awaken **** **** **** **** **** **** **** **** +10053 Archivist_Still_Awaken **** **** **** **** **** **** **** **** +10054 Archivist_BalefulPolymorph **** **** **** **** **** **** **** **** +10055 Archivist_Quickened_BalefulPolymorph **** **** **** **** **** **** **** **** +10056 Archivist_Silent_BalefulPolymorph **** **** **** **** **** **** **** **** +10057 Archivist_Still_BalefulPolymorph **** **** **** **** **** **** **** **** +10058 Archivist_Battletide **** **** **** **** **** **** **** **** +10059 Archivist_Exteneded_Battletide **** **** **** **** **** **** **** **** +10060 Archivist_Quickened_Battletide **** **** **** **** **** **** **** **** +10061 Archivist_Silent_Battletide **** **** **** **** **** **** **** **** +10062 Archivist_Still_Battletide **** **** **** **** **** **** **** **** +10063 Archivist_BreakEnchantment **** **** **** **** **** **** **** **** +10064 Archivist_Quickened_BreakEnchantment **** **** **** **** **** **** **** **** +10065 Archivist_Silent_BreakEnchantment **** **** **** **** **** **** **** **** +10066 Archivist_Still_BreakEnchantment **** **** **** **** **** **** **** **** +10067 Archivist_CHAAVS_LAUGH **** **** **** **** **** **** **** **** +10068 Archivist_Exteneded_CHAAVS_LAUGH **** **** **** **** **** **** **** **** +10069 Archivist_Quickened_CHAAVS_LAUGH **** **** **** **** **** **** **** **** +10070 Archivist_Silent_CHAAVS_LAUGH **** **** **** **** **** **** **** **** +10071 Archivist_Circle_of_Doom **** **** **** **** **** **** **** **** +10072 Archivist_Empowered_Circle_of_Doom **** **** **** **** **** **** **** **** +10073 Archivist_Maximized_Circle_of_Doom **** **** **** **** **** **** **** **** +10074 Archivist_Quickened_Circle_of_Doom **** **** **** **** **** **** **** **** +10075 Archivist_Silent_Circle_of_Doom **** **** **** **** **** **** **** **** +10076 Archivist_Still_Circle_of_Doom **** **** **** **** **** **** **** **** +10077 Archivist_CLAWS_OF_THE_BEBILITH **** **** **** **** **** **** **** **** +10078 Archivist_Exteneded_CLAWS_OF_THE_BEBILITH **** **** **** **** **** **** **** **** +10079 Archivist_Quickened_CLAWS_OF_THE_BEBILITH **** **** **** **** **** **** **** **** +10080 Archivist_Silent_CLAWS_OF_THE_BEBILITH **** **** **** **** **** **** **** **** +10081 Archivist_Still_CLAWS_OF_THE_BEBILITH **** **** **** **** **** **** **** **** +10082 Archivist_Cone_of_Cold **** **** **** **** **** **** **** **** +10083 Archivist_Empowered_Cone_of_Cold **** **** **** **** **** **** **** **** +10084 Archivist_Maximized_Cone_of_Cold **** **** **** **** **** **** **** **** +10085 Archivist_Quickened_Cone_of_Cold **** **** **** **** **** **** **** **** +10086 Archivist_Silent_Cone_of_Cold **** **** **** **** **** **** **** **** +10087 Archivist_Still_Cone_of_Cold **** **** **** **** **** **** **** **** +10088 Archivist_CONVERT_WAND **** **** **** **** **** **** **** **** +10089 Archivist_Exteneded_CONVERT_WAND **** **** **** **** **** **** **** **** +10090 Archivist_Quickened_CONVERT_WAND **** **** **** **** **** **** **** **** +10091 Archivist_Silent_CONVERT_WAND **** **** **** **** **** **** **** **** +10092 Archivist_Still_CONVERT_WAND **** **** **** **** **** **** **** **** +10093 Archivist_DANCING_WEB **** **** **** **** **** **** **** **** +10094 Archivist_Empowered_DANCING_WEB **** **** **** **** **** **** **** **** +10095 Archivist_Exteneded_DANCING_WEB **** **** **** **** **** **** **** **** +10096 Archivist_Maximized_DANCING_WEB **** **** **** **** **** **** **** **** +10097 Archivist_Quickened_DANCING_WEB **** **** **** **** **** **** **** **** +10098 Archivist_Silent_DANCING_WEB **** **** **** **** **** **** **** **** +10099 Archivist_Still_DANCING_WEB **** **** **** **** **** **** **** **** +10100 Archivist_DarkBolt **** **** **** **** **** **** **** **** +10101 Archivist_DarkBolt_all **** **** **** **** **** **** **** **** +10102 Archivist_DarkBolt_1 **** **** **** **** **** **** **** **** +10103 Archivist_Empowered_DarkBolt **** **** **** **** **** **** **** **** +10104 Archivist_Empowered_DarkBolt_all **** **** **** **** **** **** **** **** +10105 Archivist_Empowered_DarkBolt_1 **** **** **** **** **** **** **** **** +10106 Archivist_Maximized_DarkBolt **** **** **** **** **** **** **** **** +10107 Archivist_Maximized_DarkBolt_all **** **** **** **** **** **** **** **** +10108 Archivist_Maximized_DarkBolt_1 **** **** **** **** **** **** **** **** +10109 Archivist_Quickened_DarkBolt **** **** **** **** **** **** **** **** +10110 Archivist_Quickened_DarkBolt_all **** **** **** **** **** **** **** **** +10111 Archivist_Quickened_DarkBolt_1 **** **** **** **** **** **** **** **** +10112 Archivist_Silent_DarkBolt **** **** **** **** **** **** **** **** +10113 Archivist_Silent_DarkBolt_all **** **** **** **** **** **** **** **** +10114 Archivist_Silent_DarkBolt_1 **** **** **** **** **** **** **** **** +10115 Archivist_Still_DarkBolt **** **** **** **** **** **** **** **** +10116 Archivist_Still_DarkBolt_all **** **** **** **** **** **** **** **** +10117 Archivist_Still_DarkBolt_1 **** **** **** **** **** **** **** **** +10118 Archivist_Elemental_Strike **** **** **** **** **** **** **** **** +10119 Archivist_Elemental_Strike_Acid **** **** **** **** **** **** **** **** +10120 Archivist_Elemental_Strike_Cold **** **** **** **** **** **** **** **** +10121 Archivist_Elemental_Strike_Electricity **** **** **** **** **** **** **** **** +10122 Archivist_Elemental_Strike_Fire **** **** **** **** **** **** **** **** +10123 Archivist_Elemental_Strike_Sonic **** **** **** **** **** **** **** **** +10124 Archivist_Empowered_Elemental_Strike **** **** **** **** **** **** **** **** +10125 Archivist_Empowered_Elemental_Strike_Acid **** **** **** **** **** **** **** **** +10126 Archivist_Empowered_Elemental_Strike_Cold **** **** **** **** **** **** **** **** +10127 Archivist_Empowered_Elemental_Strike_Electricity **** **** **** **** **** **** **** **** +10128 Archivist_Empowered_Elemental_Strike_Fire **** **** **** **** **** **** **** **** +10129 Archivist_Empowered_Elemental_Strike_Sonic **** **** **** **** **** **** **** **** +10130 Archivist_Maximized_Elemental_Strike **** **** **** **** **** **** **** **** +10131 Archivist_Maximized_Elemental_Strike_Acid **** **** **** **** **** **** **** **** +10132 Archivist_Maximized_Elemental_Strike_Cold **** **** **** **** **** **** **** **** +10133 Archivist_Maximized_Elemental_Strike_Electricity **** **** **** **** **** **** **** **** +10134 Archivist_Maximized_Elemental_Strike_Fire **** **** **** **** **** **** **** **** +10135 Archivist_Maximized_Elemental_Strike_Sonic **** **** **** **** **** **** **** **** +10136 Archivist_Quickened_Elemental_Strike **** **** **** **** **** **** **** **** +10137 Archivist_Quickened_Elemental_Strike_Acid **** **** **** **** **** **** **** **** +10138 Archivist_Quickened_Elemental_Strike_Cold **** **** **** **** **** **** **** **** +10139 Archivist_Quickened_Elemental_Strike_Electricity **** **** **** **** **** **** **** **** +10140 Archivist_Quickened_Elemental_Strike_Fire **** **** **** **** **** **** **** **** +10141 Archivist_Quickened_Elemental_Strike_Sonic **** **** **** **** **** **** **** **** +10142 Archivist_Silent_Elemental_Strike **** **** **** **** **** **** **** **** +10143 Archivist_Silent_Elemental_Strike_Acid **** **** **** **** **** **** **** **** +10144 Archivist_Silent_Elemental_Strike_Cold **** **** **** **** **** **** **** **** +10145 Archivist_Silent_Elemental_Strike_Electricity **** **** **** **** **** **** **** **** +10146 Archivist_Silent_Elemental_Strike_Fire **** **** **** **** **** **** **** **** +10147 Archivist_Silent_Elemental_Strike_Sonic **** **** **** **** **** **** **** **** +10148 Archivist_Still_Elemental_Strike **** **** **** **** **** **** **** **** +10149 Archivist_Still_Elemental_Strike_Acid **** **** **** **** **** **** **** **** +10150 Archivist_Still_Elemental_Strike_Cold **** **** **** **** **** **** **** **** +10151 Archivist_Still_Elemental_Strike_Electricity **** **** **** **** **** **** **** **** +10152 Archivist_Still_Elemental_Strike_Fire **** **** **** **** **** **** **** **** +10153 Archivist_Still_Elemental_Strike_Sonic **** **** **** **** **** **** **** **** +10154 Archivist_Evards_Black_Tentacles **** **** **** **** **** **** **** **** +10155 Archivist_Empowered_Evards_Black_Tentacles **** **** **** **** **** **** **** **** +10156 Archivist_Exteneded_Evards_Black_Tentacles **** **** **** **** **** **** **** **** +10157 Archivist_Maximized_Evards_Black_Tentacles **** **** **** **** **** **** **** **** +10158 Archivist_Quickened_Evards_Black_Tentacles **** **** **** **** **** **** **** **** +10159 Archivist_Silent_Evards_Black_Tentacles **** **** **** **** **** **** **** **** +10160 Archivist_Still_Evards_Black_Tentacles **** **** **** **** **** **** **** **** +10161 Archivist_FireInTheBlood **** **** **** **** **** **** **** **** +10162 Archivist_Exteneded_FireInTheBlood **** **** **** **** **** **** **** **** +10163 Archivist_Quickened_FireInTheBlood **** **** **** **** **** **** **** **** +10164 Archivist_Silent_FireInTheBlood **** **** **** **** **** **** **** **** +10165 Archivist_Still_FireInTheBlood **** **** **** **** **** **** **** **** +10166 Archivist_Flame_Strike **** **** **** **** **** **** **** **** +10167 Archivist_Empowered_Flame_Strike **** **** **** **** **** **** **** **** +10168 Archivist_Maximized_Flame_Strike **** **** **** **** **** **** **** **** +10169 Archivist_Quickened_Flame_Strike **** **** **** **** **** **** **** **** +10170 Archivist_Silent_Flame_Strike **** **** **** **** **** **** **** **** +10171 Archivist_Still_Flame_Strike **** **** **** **** **** **** **** **** +10172 Archivist_Greater_Heroism **** **** **** **** **** **** **** **** +10173 Archivist_Exteneded_Greater_Heroism **** **** **** **** **** **** **** **** +10174 Archivist_Silent_Greater_Heroism **** **** **** **** **** **** **** **** +10175 Archivist_Still_Greater_Heroism **** **** **** **** **** **** **** **** +10176 Archivist_Greater_Vigor(Monstrous_Regeneration) **** **** **** **** **** **** **** **** +10177 Archivist_Exteneded_Greater_Vigor(Monstrous_Regeneration) **** **** **** **** **** **** **** **** +10178 Archivist_Quickened_Greater_Vigor(Monstrous_Regeneration) **** **** **** **** **** **** **** **** +10179 Archivist_Silent_Greater_Vigor(Monstrous_Regeneration) **** **** **** **** **** **** **** **** +10180 Archivist_Still_Greater_Vigor(Monstrous_Regeneration) **** **** **** **** **** **** **** **** +10181 Archivist_GreaterCommand_RadialMaster **** **** **** **** **** **** **** **** +10182 Archivist_GreaterCommand_Approach **** **** **** **** **** **** **** **** +10183 Archivist_GreaterCommand_Drop **** **** **** **** **** **** **** **** +10184 Archivist_GreaterCommand_Fall **** **** **** **** **** **** **** **** +10185 Archivist_GreaterCommand_Flee **** **** **** **** **** **** **** **** +10186 Archivist_GreaterCommand_Halt **** **** **** **** **** **** **** **** +10187 Archivist_Exteneded_GreaterCommand_RadialMaster **** **** **** **** **** **** **** **** +10188 Archivist_Exteneded_GreaterCommand_Approach **** **** **** **** **** **** **** **** +10189 Archivist_Exteneded_GreaterCommand_Drop **** **** **** **** **** **** **** **** +10190 Archivist_Exteneded_GreaterCommand_Fall **** **** **** **** **** **** **** **** +10191 Archivist_Exteneded_GreaterCommand_Flee **** **** **** **** **** **** **** **** +10192 Archivist_Exteneded_GreaterCommand_Halt **** **** **** **** **** **** **** **** +10193 Archivist_Quickened_GreaterCommand_RadialMaster **** **** **** **** **** **** **** **** +10194 Archivist_Quickened_GreaterCommand_Approach **** **** **** **** **** **** **** **** +10195 Archivist_Quickened_GreaterCommand_Drop **** **** **** **** **** **** **** **** +10196 Archivist_Quickened_GreaterCommand_Fall **** **** **** **** **** **** **** **** +10197 Archivist_Quickened_GreaterCommand_Flee **** **** **** **** **** **** **** **** +10198 Archivist_Quickened_GreaterCommand_Halt **** **** **** **** **** **** **** **** +10199 Archivist_Silent_GreaterCommand_RadialMaster **** **** **** **** **** **** **** **** +10200 Archivist_Silent_GreaterCommand_Approach **** **** **** **** **** **** **** **** +10201 Archivist_Silent_GreaterCommand_Drop **** **** **** **** **** **** **** **** +10202 Archivist_Silent_GreaterCommand_Fall **** **** **** **** **** **** **** **** +10203 Archivist_Silent_GreaterCommand_Flee **** **** **** **** **** **** **** **** +10204 Archivist_Silent_GreaterCommand_Halt **** **** **** **** **** **** **** **** +10205 Archivist_Still_GreaterCommand_RadialMaster **** **** **** **** **** **** **** **** +10206 Archivist_Still_GreaterCommand_Approach **** **** **** **** **** **** **** **** +10207 Archivist_Still_GreaterCommand_Drop **** **** **** **** **** **** **** **** +10208 Archivist_Still_GreaterCommand_Fall **** **** **** **** **** **** **** **** +10209 Archivist_Still_GreaterCommand_Flee **** **** **** **** **** **** **** **** +10210 Archivist_Still_GreaterCommand_Halt **** **** **** **** **** **** **** **** +10211 Archivist_HealAnimalCompanion **** **** **** **** **** **** **** **** +10212 Archivist_Quickened_HealAnimalCompanion **** **** **** **** **** **** **** **** +10213 Archivist_Silent_HealAnimalCompanion **** **** **** **** **** **** **** **** +10214 Archivist_Still_HealAnimalCompanion **** **** **** **** **** **** **** **** +10215 Archivist_Healing_Circle **** **** **** **** **** **** **** **** +10216 Archivist_Empowered_Healing_Circle **** **** **** **** **** **** **** **** +10217 Archivist_Maximized_Healing_Circle **** **** **** **** **** **** **** **** +10218 Archivist_Quickened_Healing_Circle **** **** **** **** **** **** **** **** +10219 Archivist_Silent_Healing_Circle **** **** **** **** **** **** **** **** +10220 Archivist_Still_Healing_Circle **** **** **** **** **** **** **** **** +10221 Archivist_HEARTCLUTCH **** **** **** **** **** **** **** **** +10222 Archivist_Quickened_HEARTCLUTCH **** **** **** **** **** **** **** **** +10223 Archivist_Silent_HEARTCLUTCH **** **** **** **** **** **** **** **** +10224 Archivist_Still_HEARTCLUTCH **** **** **** **** **** **** **** **** +10225 Archivist_Ice_Storm **** **** **** **** **** **** **** **** +10226 Archivist_Empowered_Ice_Storm **** **** **** **** **** **** **** **** +10227 Archivist_Maximized_Ice_Storm **** **** **** **** **** **** **** **** +10228 Archivist_Quickened_Ice_Storm **** **** **** **** **** **** **** **** +10229 Archivist_Silent_Ice_Storm **** **** **** **** **** **** **** **** +10230 Archivist_Still_Ice_Storm **** **** **** **** **** **** **** **** +10231 Archivist_Inferno **** **** **** **** **** **** **** **** +10232 Archivist_Empowered_Inferno **** **** **** **** **** **** **** **** +10233 Archivist_Exteneded_Inferno **** **** **** **** **** **** **** **** +10234 Archivist_Maximized_Inferno **** **** **** **** **** **** **** **** +10235 Archivist_Quickened_Inferno **** **** **** **** **** **** **** **** +10236 Archivist_Silent_Inferno **** **** **** **** **** **** **** **** +10237 Archivist_Still_Inferno **** **** **** **** **** **** **** **** +10238 Archivist_Legions_Curse_of_Petty_Failing **** **** **** **** **** **** **** **** +10239 Archivist_Exteneded_Legions_Curse_of_Petty_Failing **** **** **** **** **** **** **** **** +10240 Archivist_Quickened_Legions_Curse_of_Petty_Failing **** **** **** **** **** **** **** **** +10241 Archivist_Silent_Legions_Curse_of_Petty_Failing **** **** **** **** **** **** **** **** +10242 Archivist_Still_Legions_Curse_of_Petty_Failing **** **** **** **** **** **** **** **** +10243 Archivist_Mass_Cats_Grace **** **** **** **** **** **** **** **** +10244 Archivist_Empowered_Mass_Cats_Grace **** **** **** **** **** **** **** **** +10245 Archivist_Exteneded_Mass_Cats_Grace **** **** **** **** **** **** **** **** +10246 Archivist_Maximized_Mass_Cats_Grace **** **** **** **** **** **** **** **** +10247 Archivist_Quickened_Mass_Cats_Grace **** **** **** **** **** **** **** **** +10248 Archivist_Silent_Mass_Cats_Grace **** **** **** **** **** **** **** **** +10249 Archivist_Still_Mass_Cats_Grace **** **** **** **** **** **** **** **** +10250 Archivist_Mass_Contagion **** **** **** **** **** **** **** **** +10251 Archivist_Quickened_Mass_Contagion **** **** **** **** **** **** **** **** +10252 Archivist_Silent_Mass_Contagion **** **** **** **** **** **** **** **** +10253 Archivist_Still_Mass_Contagion **** **** **** **** **** **** **** **** +10254 Archivist_Mass_Cure_Light_Wounds **** **** **** **** **** **** **** **** +10255 Archivist_Empowered_Mass_Cure_Light_Wounds **** **** **** **** **** **** **** **** +10256 Archivist_Maximized_Mass_Cure_Light_Wounds **** **** **** **** **** **** **** **** +10257 Archivist_Quickened_Mass_Cure_Light_Wounds **** **** **** **** **** **** **** **** +10258 Archivist_Silent_Mass_Cure_Light_Wounds **** **** **** **** **** **** **** **** +10259 Archivist_Still_Mass_Cure_Light_Wounds **** **** **** **** **** **** **** **** +10260 Archivist_Mass_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +10261 Archivist_Empowered_Mass_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +10262 Archivist_Maximized_Mass_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +10263 Archivist_Quickened_Mass_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +10264 Archivist_Silent_Mass_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +10265 Archivist_Still_Mass_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +10266 Archivist_MORALITY_UNDONE **** **** **** **** **** **** **** **** +10267 Archivist_Quickened_MORALITY_UNDONE **** **** **** **** **** **** **** **** +10268 Archivist_Silent_MORALITY_UNDONE **** **** **** **** **** **** **** **** +10269 Archivist_Still_MORALITY_UNDONE **** **** **** **** **** **** **** **** +10270 Archivist_Necrotic_Burst **** **** **** **** **** **** **** **** +10271 Archivist_Empowered_Necrotic_Burst **** **** **** **** **** **** **** **** +10272 Archivist_Maximized_Necrotic_Burst **** **** **** **** **** **** **** **** +10273 Archivist_Quickened_Necrotic_Burst **** **** **** **** **** **** **** **** +10274 Archivist_Silent_Necrotic_Burst **** **** **** **** **** **** **** **** +10275 Archivist_Still_Necrotic_Burst **** **** **** **** **** **** **** **** +10276 Archivist_Owls_Insight **** **** **** **** **** **** **** **** +10277 Archivist_Exteneded_Owls_Insight **** **** **** **** **** **** **** **** +10278 Archivist_Quickened_Owls_Insight **** **** **** **** **** **** **** **** +10279 Archivist_Silent_Owls_Insight **** **** **** **** **** **** **** **** +10280 Archivist_Still_Owls_Insight **** **** **** **** **** **** **** **** +10281 Archivist_POWER_LEECH **** **** **** **** **** **** **** **** +10282 Archivist_Exteneded_POWER_LEECH **** **** **** **** **** **** **** **** +10283 Archivist_Quickened_POWER_LEECH **** **** **** **** **** **** **** **** +10284 Archivist_Silent_POWER_LEECH **** **** **** **** **** **** **** **** +10285 Archivist_Still_POWER_LEECH **** **** **** **** **** **** **** **** +10286 Archivist_Raise_Dead **** **** **** **** **** **** **** **** +10287 Archivist_Quickened_Raise_Dead **** **** **** **** **** **** **** **** +10288 Archivist_Silent_Raise_Dead **** **** **** **** **** **** **** **** +10289 Archivist_Still_Raise_Dead **** **** **** **** **** **** **** **** +10290 Archivist_RESONATING_RESISTANCE **** **** **** **** **** **** **** **** +10291 Archivist_Exteneded_RESONATING_RESISTANCE **** **** **** **** **** **** **** **** +10292 Archivist_Quickened_RESONATING_RESISTANCE **** **** **** **** **** **** **** **** +10293 Archivist_Silent_RESONATING_RESISTANCE **** **** **** **** **** **** **** **** +10294 Archivist_Revivify **** **** **** **** **** **** **** **** +10295 Archivist_Quickened_Revivify **** **** **** **** **** **** **** **** +10296 Archivist_Silent_Revivify **** **** **** **** **** **** **** **** +10297 Archivist_Still_Revivify **** **** **** **** **** **** **** **** +10298 Archivist_Righteous_Might **** **** **** **** **** **** **** **** +10299 Archivist_Exteneded_Righteous_Might **** **** **** **** **** **** **** **** +10300 Archivist_Quickened_Righteous_Might **** **** **** **** **** **** **** **** +10301 Archivist_Silent_Righteous_Might **** **** **** **** **** **** **** **** +10302 Archivist_Still_Righteous_Might **** **** **** **** **** **** **** **** +10303 Archivist_Scrying **** **** **** **** **** **** **** **** +10304 Archivist_Exteneded_Scrying **** **** **** **** **** **** **** **** +10305 Archivist_Quickened_Scrying **** **** **** **** **** **** **** **** +10306 Archivist_Silent_Scrying **** **** **** **** **** **** **** **** +10307 Archivist_Still_Scrying **** **** **** **** **** **** **** **** +10308 Archivist_SICKEN_EVIL **** **** **** **** **** **** **** **** +10309 Archivist_Exteneded_SICKEN_EVIL **** **** **** **** **** **** **** **** +10310 Archivist_Quickened_SICKEN_EVIL **** **** **** **** **** **** **** **** +10311 Archivist_Silent_SICKEN_EVIL **** **** **** **** **** **** **** **** +10312 Archivist_Still_SICKEN_EVIL **** **** **** **** **** **** **** **** +10313 Archivist_Slay_Living **** **** **** **** **** **** **** **** +10314 Archivist_Empowered_Slay_Living **** **** **** **** **** **** **** **** +10315 Archivist_Maximized_Slay_Living **** **** **** **** **** **** **** **** +10316 Archivist_Quickened_Slay_Living **** **** **** **** **** **** **** **** +10317 Archivist_Silent_Slay_Living **** **** **** **** **** **** **** **** +10318 Archivist_Still_Slay_Living **** **** **** **** **** **** **** **** +10319 Archivist_Soulscour **** **** **** **** **** **** **** **** +10320 Archivist_Empowered_Soulscour **** **** **** **** **** **** **** **** +10321 Archivist_Maximized_Soulscour **** **** **** **** **** **** **** **** +10322 Archivist_Quickened_Soulscour **** **** **** **** **** **** **** **** +10323 Archivist_Silent_Soulscour **** **** **** **** **** **** **** **** +10324 Archivist_Still_Soulscour **** **** **** **** **** **** **** **** +10325 Archivist_Spell_Mantle **** **** **** **** **** **** **** **** +10326 Archivist_Empowered_Spell_Mantle **** **** **** **** **** **** **** **** +10327 Archivist_Exteneded_Spell_Mantle **** **** **** **** **** **** **** **** +10328 Archivist_Maximized_Spell_Mantle **** **** **** **** **** **** **** **** +10329 Archivist_Quickened_Spell_Mantle **** **** **** **** **** **** **** **** +10330 Archivist_Silent_Spell_Mantle **** **** **** **** **** **** **** **** +10331 Archivist_Still_Spell_Mantle **** **** **** **** **** **** **** **** +10332 Archivist_Spell_Resistance **** **** **** **** **** **** **** **** +10333 Archivist_Exteneded_Spell_Resistance **** **** **** **** **** **** **** **** +10334 Archivist_Quickened_Spell_Resistance **** **** **** **** **** **** **** **** +10335 Archivist_Silent_Spell_Resistance **** **** **** **** **** **** **** **** +10336 Archivist_Still_Spell_Resistance **** **** **** **** **** **** **** **** +10337 Archivist_Stone_to_flesh **** **** **** **** **** **** **** **** +10338 Archivist_Exteneded_Stone_to_flesh **** **** **** **** **** **** **** **** +10339 Archivist_Quickened_Stone_to_flesh **** **** **** **** **** **** **** **** +10340 Archivist_Silent_Stone_to_flesh **** **** **** **** **** **** **** **** +10341 Archivist_Still_Stone_to_flesh **** **** **** **** **** **** **** **** +10342 Archivist_Summon_Creature_V **** **** **** **** **** **** **** **** +10343 Archivist_Exteneded_Summon_Creature_V **** **** **** **** **** **** **** **** +10344 Archivist_Quickened_Summon_Creature_V **** **** **** **** **** **** **** **** +10345 Archivist_Silent_Summon_Creature_V **** **** **** **** **** **** **** **** +10346 Archivist_Still_Summon_Creature_V **** **** **** **** **** **** **** **** +10347 Archivist_SummonUndeadV **** **** **** **** **** **** **** **** +10348 Archivist_Exteneded_SummonUndeadV **** **** **** **** **** **** **** **** +10349 Archivist_Quickened_SummonUndeadV **** **** **** **** **** **** **** **** +10350 Archivist_Silent_SummonUndeadV **** **** **** **** **** **** **** **** +10351 Archivist_Still_SummonUndeadV **** **** **** **** **** **** **** **** +10352 Archivist_SYMBOL_OF_PAIN **** **** **** **** **** **** **** **** +10353 Archivist_Empowered_SYMBOL_OF_PAIN **** **** **** **** **** **** **** **** +10354 Archivist_Exteneded_SYMBOL_OF_PAIN **** **** **** **** **** **** **** **** +10355 Archivist_Maximized_SYMBOL_OF_PAIN **** **** **** **** **** **** **** **** +10356 Archivist_Quickened_SYMBOL_OF_PAIN **** **** **** **** **** **** **** **** +10357 Archivist_Silent_SYMBOL_OF_PAIN **** **** **** **** **** **** **** **** +10358 Archivist_Still_SYMBOL_OF_PAIN **** **** **** **** **** **** **** **** +10359 Archivist_SYMBOL_OF_SLEEP **** **** **** **** **** **** **** **** +10360 Archivist_Empowered_SYMBOL_OF_SLEEP **** **** **** **** **** **** **** **** +10361 Archivist_Exteneded_SYMBOL_OF_SLEEP **** **** **** **** **** **** **** **** +10362 Archivist_Maximized_SYMBOL_OF_SLEEP **** **** **** **** **** **** **** **** +10363 Archivist_Quickened_SYMBOL_OF_SLEEP **** **** **** **** **** **** **** **** +10364 Archivist_Silent_SYMBOL_OF_SLEEP **** **** **** **** **** **** **** **** +10365 Archivist_Still_SYMBOL_OF_SLEEP **** **** **** **** **** **** **** **** +10366 Archivist_Teleport_RadialMaster **** **** **** **** **** **** **** **** +10367 Archivist_Teleport_SelfOnly **** **** **** **** **** **** **** **** +10368 Archivist_Teleport_Party **** **** **** **** **** **** **** **** +10369 Archivist_Quickened_Teleport_RadialMaster **** **** **** **** **** **** **** **** +10370 Archivist_Quickened_Teleport_SelfOnly **** **** **** **** **** **** **** **** +10371 Archivist_Quickened_Teleport_Party **** **** **** **** **** **** **** **** +10372 Archivist_Silent_Teleport_RadialMaster **** **** **** **** **** **** **** **** +10373 Archivist_Silent_Teleport_SelfOnly **** **** **** **** **** **** **** **** +10374 Archivist_Silent_Teleport_Party **** **** **** **** **** **** **** **** +10375 Archivist_True_Seeing **** **** **** **** **** **** **** **** +10376 Archivist_Exteneded_True_Seeing **** **** **** **** **** **** **** **** +10377 Archivist_Quickened_True_Seeing **** **** **** **** **** **** **** **** +10378 Archivist_Silent_True_Seeing **** **** **** **** **** **** **** **** +10379 Archivist_Still_True_Seeing **** **** **** **** **** **** **** **** +10380 Archivist_Vine_Mine **** **** **** **** **** **** **** **** +10381 Archivist_Vine_Mine_Entangle **** **** **** **** **** **** **** **** +10382 Archivist_Vine_Mine_Hamper_Movement **** **** **** **** **** **** **** **** +10383 Archivist_Vine_Mine_Camouflage **** **** **** **** **** **** **** **** +10384 Archivist_Exteneded_Vine_Mine **** **** **** **** **** **** **** **** +10385 Archivist_Exteneded_Vine_Mine_Entangle **** **** **** **** **** **** **** **** +10386 Archivist_Exteneded_Vine_Mine_Hamper_Movement **** **** **** **** **** **** **** **** +10387 Archivist_Exteneded_Vine_Mine_Camouflage **** **** **** **** **** **** **** **** +10388 Archivist_Quickened_Vine_Mine **** **** **** **** **** **** **** **** +10389 Archivist_Quickened_Vine_Mine_Entangle **** **** **** **** **** **** **** **** +10390 Archivist_Quickened_Vine_Mine_Hamper_Movement **** **** **** **** **** **** **** **** +10391 Archivist_Quickened_Vine_Mine_Camouflage **** **** **** **** **** **** **** **** +10392 Archivist_Silent_Vine_Mine **** **** **** **** **** **** **** **** +10393 Archivist_Silent_Vine_Mine_Entangle **** **** **** **** **** **** **** **** +10394 Archivist_Silent_Vine_Mine_Hamper_Movement **** **** **** **** **** **** **** **** +10395 Archivist_Silent_Vine_Mine_Camouflage **** **** **** **** **** **** **** **** +10396 Archivist_Still_Vine_Mine **** **** **** **** **** **** **** **** +10397 Archivist_Still_Vine_Mine_Entangle **** **** **** **** **** **** **** **** +10398 Archivist_Still_Vine_Mine_Hamper_Movement **** **** **** **** **** **** **** **** +10399 Archivist_Still_Vine_Mine_Camouflage **** **** **** **** **** **** **** **** +10400 Archivist_Viscid_Glob **** **** **** **** **** **** **** **** +10401 Archivist_Exteneded_Viscid_Glob **** **** **** **** **** **** **** **** +10402 Archivist_Quickened_Viscid_Glob **** **** **** **** **** **** **** **** +10403 Archivist_Silent_Viscid_Glob **** **** **** **** **** **** **** **** +10404 Archivist_Still_Viscid_Glob **** **** **** **** **** **** **** **** +10405 Archivist_Wall_of_Fire **** **** **** **** **** **** **** **** +10406 Archivist_Empowered_Wall_of_Fire **** **** **** **** **** **** **** **** +10407 Archivist_Exteneded_Wall_of_Fire **** **** **** **** **** **** **** **** +10408 Archivist_Maximized_Wall_of_Fire **** **** **** **** **** **** **** **** +10409 Archivist_Quickened_Wall_of_Fire **** **** **** **** **** **** **** **** +10410 Archivist_Silent_Wall_of_Fire **** **** **** **** **** **** **** **** +10411 Archivist_Still_Wall_of_Fire **** **** **** **** **** **** **** **** +10412 Archivist_Acid_Storm **** **** **** **** **** **** **** **** +10413 Archivist_Empowered_Acid_Storm **** **** **** **** **** **** **** **** +10414 Archivist_Maximized_Acid_Storm **** **** **** **** **** **** **** **** +10415 Archivist_Silent_Acid_Storm **** **** **** **** **** **** **** **** +10416 Archivist_Still_Acid_Storm **** **** **** **** **** **** **** **** +10417 Archivist_Animate_Object **** **** **** **** **** **** **** **** +10418 Archivist_Exteneded_Animate_Object **** **** **** **** **** **** **** **** +10419 Archivist_Banishment **** **** **** **** **** **** **** **** +10420 Archivist_Silent_Banishment **** **** **** **** **** **** **** **** +10421 Archivist_Still_Banishment **** **** **** **** **** **** **** **** +10422 Archivist_Blade_Barrier **** **** **** **** **** **** **** **** +10423 Archivist_Empowered_Blade_Barrier **** **** **** **** **** **** **** **** +10424 Archivist_Exteneded_Blade_Barrier **** **** **** **** **** **** **** **** +10425 Archivist_Maximized_Blade_Barrier **** **** **** **** **** **** **** **** +10426 Archivist_Silent_Blade_Barrier **** **** **** **** **** **** **** **** +10427 Archivist_Still_Blade_Barrier **** **** **** **** **** **** **** **** +10428 Archivist_CALL_FAITHFUL_SERVANTS **** **** **** **** **** **** **** **** +10429 Archivist_Empowered_CALL_FAITHFUL_SERVANTS **** **** **** **** **** **** **** **** +10430 Archivist_Maximized_CALL_FAITHFUL_SERVANTS **** **** **** **** **** **** **** **** +10431 Archivist_Silent_CALL_FAITHFUL_SERVANTS **** **** **** **** **** **** **** **** +10432 Archivist_Still_CALL_FAITHFUL_SERVANTS **** **** **** **** **** **** **** **** +10433 Archivist_CELESTIAL_BLOOD **** **** **** **** **** **** **** **** +10434 Archivist_Silent_CELESTIAL_BLOOD **** **** **** **** **** **** **** **** +10435 Archivist_Still_CELESTIAL_BLOOD **** **** **** **** **** **** **** **** +10436 Archivist_Chain_Lightning **** **** **** **** **** **** **** **** +10437 Archivist_Empowered_Chain_Lightning **** **** **** **** **** **** **** **** +10438 Archivist_Maximized_Chain_Lightning **** **** **** **** **** **** **** **** +10439 Archivist_Silent_Chain_Lightning **** **** **** **** **** **** **** **** +10440 Archivist_Still_Chain_Lightning **** **** **** **** **** **** **** **** +10441 Archivist_CLOUD_OF_THE_ACHAIERAI **** **** **** **** **** **** **** **** +10442 Archivist_Exteneded_CLOUD_OF_THE_ACHAIERAI **** **** **** **** **** **** **** **** +10443 Archivist_Silent_CLOUD_OF_THE_ACHAIERAI **** **** **** **** **** **** **** **** +10444 Archivist_Still_CLOUD_OF_THE_ACHAIERAI **** **** **** **** **** **** **** **** +10445 Archivist_Control_Undead **** **** **** **** **** **** **** **** +10446 Archivist_Exteneded_Control_Undead **** **** **** **** **** **** **** **** +10447 Archivist_Silent_Control_Undead **** **** **** **** **** **** **** **** +10448 Archivist_Still_Control_Undead **** **** **** **** **** **** **** **** +10449 Archivist_Create_Undead **** **** **** **** **** **** **** **** +10450 Archivist_Exteneded_Create_Undead **** **** **** **** **** **** **** **** +10451 Archivist_Silent_Create_Undead **** **** **** **** **** **** **** **** +10452 Archivist_Still_Create_Undead **** **** **** **** **** **** **** **** +10453 Archivist_Crumble **** **** **** **** **** **** **** **** +10454 Archivist_Empowered_Crumble **** **** **** **** **** **** **** **** +10455 Archivist_Maximized_Crumble **** **** **** **** **** **** **** **** +10456 Archivist_Silent_Crumble **** **** **** **** **** **** **** **** +10457 Archivist_Still_Crumble **** **** **** **** **** **** **** **** +10458 Archivist_Drown **** **** **** **** **** **** **** **** +10459 Archivist_Silent_Drown **** **** **** **** **** **** **** **** +10460 Archivist_Still_Drown **** **** **** **** **** **** **** **** +10461 Archivist_Energy_Buffer **** **** **** **** **** **** **** **** +10462 Archivist_Exteneded_Energy_Buffer **** **** **** **** **** **** **** **** +10463 Archivist_Silent_Energy_Buffer **** **** **** **** **** **** **** **** +10464 Archivist_Still_Energy_Buffer **** **** **** **** **** **** **** **** +10465 Archivist_Energy_Immunity **** **** **** **** **** **** **** **** +10466 Archivist_EI_Acid **** **** **** **** **** **** **** **** +10467 Archivist_EI_Cold **** **** **** **** **** **** **** **** +10468 Archivist_EI_Elec **** **** **** **** **** **** **** **** +10469 Archivist_EI_Fire **** **** **** **** **** **** **** **** +10470 Archivist_EI_Sonic **** **** **** **** **** **** **** **** +10471 Archivist_Exteneded_Energy_Immunity **** **** **** **** **** **** **** **** +10472 Archivist_Exteneded_EI_Acid **** **** **** **** **** **** **** **** +10473 Archivist_Exteneded_EI_Cold **** **** **** **** **** **** **** **** +10474 Archivist_Exteneded_EI_Elec **** **** **** **** **** **** **** **** +10475 Archivist_Exteneded_EI_Fire **** **** **** **** **** **** **** **** +10476 Archivist_Exteneded_EI_Sonic **** **** **** **** **** **** **** **** +10477 Archivist_Silent_Energy_Immunity **** **** **** **** **** **** **** **** +10478 Archivist_Silent_EI_Acid **** **** **** **** **** **** **** **** +10479 Archivist_Silent_EI_Cold **** **** **** **** **** **** **** **** +10480 Archivist_Silent_EI_Elec **** **** **** **** **** **** **** **** +10481 Archivist_Silent_EI_Fire **** **** **** **** **** **** **** **** +10482 Archivist_Silent_EI_Sonic **** **** **** **** **** **** **** **** +10483 Archivist_Still_Energy_Immunity **** **** **** **** **** **** **** **** +10484 Archivist_Still_EI_Acid **** **** **** **** **** **** **** **** +10485 Archivist_Still_EI_Cold **** **** **** **** **** **** **** **** +10486 Archivist_Still_EI_Elec **** **** **** **** **** **** **** **** +10487 Archivist_Still_EI_Fire **** **** **** **** **** **** **** **** +10488 Archivist_Still_EI_Sonic **** **** **** **** **** **** **** **** +10489 Archivist_EXALTED_RAIMENT **** **** **** **** **** **** **** **** +10490 Archivist_Exteneded_EXALTED_RAIMENT **** **** **** **** **** **** **** **** +10491 Archivist_Silent_EXALTED_RAIMENT **** **** **** **** **** **** **** **** +10492 Archivist_ExtractWaterElemental **** **** **** **** **** **** **** **** +10493 Archivist_Empowered_ExtractWaterElemental **** **** **** **** **** **** **** **** +10494 Archivist_Maximized_ExtractWaterElemental **** **** **** **** **** **** **** **** +10495 Archivist_Silent_ExtractWaterElemental **** **** **** **** **** **** **** **** +10496 Archivist_Still_ExtractWaterElemental **** **** **** **** **** **** **** **** +10497 Archivist_Greater_Dispelling **** **** **** **** **** **** **** **** +10498 Archivist_Silent_Greater_Dispelling **** **** **** **** **** **** **** **** +10499 Archivist_Still_Greater_Dispelling **** **** **** **** **** **** **** **** +10500 Archivist_Greater_Glyph_of_Warding_Master **** **** **** **** **** **** **** **** +10501 Archivist_Greater_Glyph_of_Warding_Acid **** **** **** **** **** **** **** **** +10502 Archivist_Greater_Glyph_of_Warding_Cold **** **** **** **** **** **** **** **** +10503 Archivist_Greater_Glyph_of_Warding_Electricity **** **** **** **** **** **** **** **** +10504 Archivist_Greater_Glyph_of_Warding_Fire **** **** **** **** **** **** **** **** +10505 Archivist_Greater_Glyph_of_Warding_Sonic **** **** **** **** **** **** **** **** +10506 Archivist_Empowered_Greater_Glyph_of_Warding_Master **** **** **** **** **** **** **** **** +10507 Archivist_Empowered_Greater_Glyph_of_Warding_Acid **** **** **** **** **** **** **** **** +10508 Archivist_Empowered_Greater_Glyph_of_Warding_Cold **** **** **** **** **** **** **** **** +10509 Archivist_Empowered_Greater_Glyph_of_Warding_Electricity **** **** **** **** **** **** **** **** +10510 Archivist_Empowered_Greater_Glyph_of_Warding_Fire **** **** **** **** **** **** **** **** +10511 Archivist_Empowered_Greater_Glyph_of_Warding_Sonic **** **** **** **** **** **** **** **** +10512 Archivist_Exteneded_Greater_Glyph_of_Warding_Master **** **** **** **** **** **** **** **** +10513 Archivist_Exteneded_Greater_Glyph_of_Warding_Acid **** **** **** **** **** **** **** **** +10514 Archivist_Exteneded_Greater_Glyph_of_Warding_Cold **** **** **** **** **** **** **** **** +10515 Archivist_Exteneded_Greater_Glyph_of_Warding_Electricity **** **** **** **** **** **** **** **** +10516 Archivist_Exteneded_Greater_Glyph_of_Warding_Fire **** **** **** **** **** **** **** **** +10517 Archivist_Exteneded_Greater_Glyph_of_Warding_Sonic **** **** **** **** **** **** **** **** +10518 Archivist_Maximized_Greater_Glyph_of_Warding_Master **** **** **** **** **** **** **** **** +10519 Archivist_Maximized_Greater_Glyph_of_Warding_Acid **** **** **** **** **** **** **** **** +10520 Archivist_Maximized_Greater_Glyph_of_Warding_Cold **** **** **** **** **** **** **** **** +10521 Archivist_Maximized_Greater_Glyph_of_Warding_Electricity **** **** **** **** **** **** **** **** +10522 Archivist_Maximized_Greater_Glyph_of_Warding_Fire **** **** **** **** **** **** **** **** +10523 Archivist_Maximized_Greater_Glyph_of_Warding_Sonic **** **** **** **** **** **** **** **** +10524 Archivist_Silent_Greater_Glyph_of_Warding_Master **** **** **** **** **** **** **** **** +10525 Archivist_Silent_Greater_Glyph_of_Warding_Acid **** **** **** **** **** **** **** **** +10526 Archivist_Silent_Greater_Glyph_of_Warding_Cold **** **** **** **** **** **** **** **** +10527 Archivist_Silent_Greater_Glyph_of_Warding_Electricity **** **** **** **** **** **** **** **** +10528 Archivist_Silent_Greater_Glyph_of_Warding_Fire **** **** **** **** **** **** **** **** +10529 Archivist_Silent_Greater_Glyph_of_Warding_Sonic **** **** **** **** **** **** **** **** +10530 Archivist_Still_Greater_Glyph_of_Warding_Master **** **** **** **** **** **** **** **** +10531 Archivist_Still_Greater_Glyph_of_Warding_Acid **** **** **** **** **** **** **** **** +10532 Archivist_Still_Greater_Glyph_of_Warding_Cold **** **** **** **** **** **** **** **** +10533 Archivist_Still_Greater_Glyph_of_Warding_Electricity **** **** **** **** **** **** **** **** +10534 Archivist_Still_Greater_Glyph_of_Warding_Fire **** **** **** **** **** **** **** **** +10535 Archivist_Still_Greater_Glyph_of_Warding_Sonic **** **** **** **** **** **** **** **** +10536 Archivist_Etherealness **** **** **** **** **** **** **** **** +10537 Archivist_Exteneded_Etherealness **** **** **** **** **** **** **** **** +10538 Archivist_Silent_Etherealness **** **** **** **** **** **** **** **** +10539 Archivist_Still_Etherealness **** **** **** **** **** **** **** **** +10540 Archivist_Greater_Stoneskin **** **** **** **** **** **** **** **** +10541 Archivist_Exteneded_Greater_Stoneskin **** **** **** **** **** **** **** **** +10542 Archivist_Silent_Greater_Stoneskin **** **** **** **** **** **** **** **** +10543 Archivist_Still_Greater_Stoneskin **** **** **** **** **** **** **** **** +10544 Archivist_Harm **** **** **** **** **** **** **** **** +10545 Archivist_Silent_Harm **** **** **** **** **** **** **** **** +10546 Archivist_Still_Harm **** **** **** **** **** **** **** **** +10547 Archivist_Heal **** **** **** **** **** **** **** **** +10548 Archivist_Silent_Heal **** **** **** **** **** **** **** **** +10549 Archivist_Still_Heal **** **** **** **** **** **** **** **** +10550 Archivist_Legend_Lore **** **** **** **** **** **** **** **** +10551 Archivist_Exteneded_Legend_Lore **** **** **** **** **** **** **** **** +10552 Archivist_Silent_Legend_Lore **** **** **** **** **** **** **** **** +10553 Archivist_Still_Legend_Lore **** **** **** **** **** **** **** **** +10554 Archivist_Mass_Bulls_Strength **** **** **** **** **** **** **** **** +10555 Archivist_Empowered_Mass_Bulls_Strength **** **** **** **** **** **** **** **** +10556 Archivist_Exteneded_Mass_Bulls_Strength **** **** **** **** **** **** **** **** +10557 Archivist_Maximized_Mass_Bulls_Strength **** **** **** **** **** **** **** **** +10558 Archivist_Silent_Mass_Bulls_Strength **** **** **** **** **** **** **** **** +10559 Archivist_Still_Mass_Bulls_Strength **** **** **** **** **** **** **** **** +10560 Archivist_Mass_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +10561 Archivist_Empowered_Mass_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +10562 Archivist_Maximized_Mass_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +10563 Archivist_Silent_Mass_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +10564 Archivist_Still_Mass_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +10565 Archivist_Mass_Eagle_Splendor **** **** **** **** **** **** **** **** +10566 Archivist_Empowered_Mass_Eagle_Splendor **** **** **** **** **** **** **** **** +10567 Archivist_Exteneded_Mass_Eagle_Splendor **** **** **** **** **** **** **** **** +10568 Archivist_Maximized_Mass_Eagle_Splendor **** **** **** **** **** **** **** **** +10569 Archivist_Silent_Mass_Eagle_Splendor **** **** **** **** **** **** **** **** +10570 Archivist_Still_Mass_Eagle_Splendor **** **** **** **** **** **** **** **** +10571 Archivist_Mass_Endurance **** **** **** **** **** **** **** **** +10572 Archivist_Empowered_Mass_Endurance **** **** **** **** **** **** **** **** +10573 Archivist_Exteneded_Mass_Endurance **** **** **** **** **** **** **** **** +10574 Archivist_Maximized_Mass_Endurance **** **** **** **** **** **** **** **** +10575 Archivist_Silent_Mass_Endurance **** **** **** **** **** **** **** **** +10576 Archivist_Still_Mass_Endurance **** **** **** **** **** **** **** **** +10577 Archivist_Mass_Foxs_Cunning **** **** **** **** **** **** **** **** +10578 Archivist_Empowered_Mass_Foxs_Cunning **** **** **** **** **** **** **** **** +10579 Archivist_Exteneded_Mass_Foxs_Cunning **** **** **** **** **** **** **** **** +10580 Archivist_Maximized_Mass_Foxs_Cunning **** **** **** **** **** **** **** **** +10581 Archivist_Silent_Mass_Foxs_Cunning **** **** **** **** **** **** **** **** +10582 Archivist_Still_Mass_Foxs_Cunning **** **** **** **** **** **** **** **** +10583 Archivist_Mass_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +10584 Archivist_Empowered_Mass_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +10585 Archivist_Maximized_Mass_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +10586 Archivist_Silent_Mass_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +10587 Archivist_Still_Mass_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +10588 Archivist_Mass_Owls_Wisdom **** **** **** **** **** **** **** **** +10589 Archivist_Empowered_Mass_Owls_Wisdom **** **** **** **** **** **** **** **** +10590 Archivist_Exteneded_Mass_Owls_Wisdom **** **** **** **** **** **** **** **** +10591 Archivist_Maximized_Mass_Owls_Wisdom **** **** **** **** **** **** **** **** +10592 Archivist_Silent_Mass_Owls_Wisdom **** **** **** **** **** **** **** **** +10593 Archivist_Still_Mass_Owls_Wisdom **** **** **** **** **** **** **** **** +10594 Archivist_Necrotic_Eruption **** **** **** **** **** **** **** **** +10595 Archivist_Empowered_Necrotic_Eruption **** **** **** **** **** **** **** **** +10596 Archivist_Maximized_Necrotic_Eruption **** **** **** **** **** **** **** **** +10597 Archivist_Silent_Necrotic_Eruption **** **** **** **** **** **** **** **** +10598 Archivist_Still_Necrotic_Eruption **** **** **** **** **** **** **** **** +10599 Archivist_Planar_Ally **** **** **** **** **** **** **** **** +10600 Archivist_Exteneded_Planar_Ally **** **** **** **** **** **** **** **** +10601 Archivist_Silent_Planar_Ally **** **** **** **** **** **** **** **** +10602 Archivist_Still_Planar_Ally **** **** **** **** **** **** **** **** +10603 Archivist_Planar_Binding **** **** **** **** **** **** **** **** +10604 Archivist_Exteneded_Planar_Binding **** **** **** **** **** **** **** **** +10605 Archivist_Silent_Planar_Binding **** **** **** **** **** **** **** **** +10606 Archivist_Still_Planar_Binding **** **** **** **** **** **** **** **** +10607 Archivist_Pox **** **** **** **** **** **** **** **** +10608 Archivist_Empowered_Pox **** **** **** **** **** **** **** **** +10609 Archivist_Maximized_Pox **** **** **** **** **** **** **** **** +10610 Archivist_Silent_Pox **** **** **** **** **** **** **** **** +10611 Archivist_Still_Pox **** **** **** **** **** **** **** **** +10612 Archivist_SarcophagusOfStone **** **** **** **** **** **** **** **** +10613 Archivist_Silent_SarcophagusOfStone **** **** **** **** **** **** **** **** +10614 Archivist_Still_SarcophagusOfStone **** **** **** **** **** **** **** **** +10615 Archivist_Stonehold **** **** **** **** **** **** **** **** +10616 Archivist_Empowered_Stonehold **** **** **** **** **** **** **** **** +10617 Archivist_Exteneded_Stonehold **** **** **** **** **** **** **** **** +10618 Archivist_Maximized_Stonehold **** **** **** **** **** **** **** **** +10619 Archivist_Silent_Stonehold **** **** **** **** **** **** **** **** +10620 Archivist_Still_Stonehold **** **** **** **** **** **** **** **** +10621 Archivist_STORM_OF_SHARDS **** **** **** **** **** **** **** **** +10622 Archivist_Empowered_STORM_OF_SHARDS **** **** **** **** **** **** **** **** +10623 Archivist_Maximized_STORM_OF_SHARDS **** **** **** **** **** **** **** **** +10624 Archivist_Silent_STORM_OF_SHARDS **** **** **** **** **** **** **** **** +10625 Archivist_Still_STORM_OF_SHARDS **** **** **** **** **** **** **** **** +10626 Archivist_Summon_Creature_VI **** **** **** **** **** **** **** **** +10627 Archivist_Exteneded_Summon_Creature_VI **** **** **** **** **** **** **** **** +10628 Archivist_Silent_Summon_Creature_VI **** **** **** **** **** **** **** **** +10629 Archivist_Still_Summon_Creature_VI **** **** **** **** **** **** **** **** +10630 Archivist_Superior_Resistance **** **** **** **** **** **** **** **** +10631 Archivist_Exteneded_Superior_Resistance **** **** **** **** **** **** **** **** +10632 Archivist_Silent_Superior_Resistance **** **** **** **** **** **** **** **** +10633 Archivist_Still_Superior_Resistance **** **** **** **** **** **** **** **** +10634 Archivist_SYMBOL_OF_FEAR **** **** **** **** **** **** **** **** +10635 Archivist_Empowered_SYMBOL_OF_FEAR **** **** **** **** **** **** **** **** +10636 Archivist_Exteneded_SYMBOL_OF_FEAR **** **** **** **** **** **** **** **** +10637 Archivist_Maximized_SYMBOL_OF_FEAR **** **** **** **** **** **** **** **** +10638 Archivist_Silent_SYMBOL_OF_FEAR **** **** **** **** **** **** **** **** +10639 Archivist_Still_SYMBOL_OF_FEAR **** **** **** **** **** **** **** **** +10640 Archivist_SYMBOL_OF_PERSUASION **** **** **** **** **** **** **** **** +10641 Archivist_Empowered_SYMBOL_OF_PERSUASION **** **** **** **** **** **** **** **** +10642 Archivist_Exteneded_SYMBOL_OF_PERSUASION **** **** **** **** **** **** **** **** +10643 Archivist_Maximized_SYMBOL_OF_PERSUASION **** **** **** **** **** **** **** **** +10644 Archivist_Silent_SYMBOL_OF_PERSUASION **** **** **** **** **** **** **** **** +10645 Archivist_Still_SYMBOL_OF_PERSUASION **** **** **** **** **** **** **** **** +10646 Archivist_THOUSAND_NEEDLES **** **** **** **** **** **** **** **** +10647 Archivist_Empowered_THOUSAND_NEEDLES **** **** **** **** **** **** **** **** +10648 Archivist_Exteneded_THOUSAND_NEEDLES **** **** **** **** **** **** **** **** +10649 Archivist_Maximized_THOUSAND_NEEDLES **** **** **** **** **** **** **** **** +10650 Archivist_Silent_THOUSAND_NEEDLES **** **** **** **** **** **** **** **** +10651 Archivist_Still_THOUSAND_NEEDLES **** **** **** **** **** **** **** **** +10652 Archivist_TransportViaPlants_RadialMaster **** **** **** **** **** **** **** **** +10653 Archivist_TransportViaPlants_SelfOnly **** **** **** **** **** **** **** **** +10654 Archivist_TransportViaPlants_Party **** **** **** **** **** **** **** **** +10655 Archivist_Silent_TransportViaPlants_RadialMaster **** **** **** **** **** **** **** **** +10656 Archivist_Silent_TransportViaPlants_SelfOnly **** **** **** **** **** **** **** **** +10657 Archivist_Silent_TransportViaPlants_Party **** **** **** **** **** **** **** **** +10658 Archivist_Undeath_to_Death **** **** **** **** **** **** **** **** +10659 Archivist_Empowered_Undeath_to_Death **** **** **** **** **** **** **** **** +10660 Archivist_Maximized_Undeath_to_Death **** **** **** **** **** **** **** **** +10661 Archivist_Silent_Undeath_to_Death **** **** **** **** **** **** **** **** +10662 Archivist_Still_Undeath_to_Death **** **** **** **** **** **** **** **** +10663 Archivist_Vigorous_Circle **** **** **** **** **** **** **** **** +10664 Archivist_Exteneded_Vigorous_Circle **** **** **** **** **** **** **** **** +10665 Archivist_Silent_Vigorous_Circle **** **** **** **** **** **** **** **** +10666 Archivist_Still_Vigorous_Circle **** **** **** **** **** **** **** **** +10667 Archivist_WordOfRecall_RadialMaster **** **** **** **** **** **** **** **** +10668 Archivist_WordOfRecall_SelfOnly **** **** **** **** **** **** **** **** +10669 Archivist_WordOfRecall_Party **** **** **** **** **** **** **** **** +10670 Archivist_Silent_WordOfRecall_RadialMaster **** **** **** **** **** **** **** **** +10671 Archivist_Silent_WordOfRecall_SelfOnly **** **** **** **** **** **** **** **** +10672 Archivist_Silent_WordOfRecall_Party **** **** **** **** **** **** **** **** +10673 Archivist_Aura_of_Vitality **** **** **** **** **** **** **** **** +10674 Archivist_Exteneded_Aura_of_Vitality **** **** **** **** **** **** **** **** +10675 Archivist_Silent_Aura_of_Vitality **** **** **** **** **** **** **** **** +10676 Archivist_Still_Aura_of_Vitality **** **** **** **** **** **** **** **** +10677 Archivist_Bigbys_Grasping_Hand **** **** **** **** **** **** **** **** +10678 Archivist_Exteneded_Bigbys_Grasping_Hand **** **** **** **** **** **** **** **** +10679 Archivist_Silent_Bigbys_Grasping_Hand **** **** **** **** **** **** **** **** +10680 Archivist_Still_Bigbys_Grasping_Hand **** **** **** **** **** **** **** **** +10681 Archivist_Blasphemy **** **** **** **** **** **** **** **** +10682 Archivist_Silent_Blasphemy **** **** **** **** **** **** **** **** +10683 Archivist_Still_Blasphemy **** **** **** **** **** **** **** **** +10684 Archivist_Control_Weather **** **** **** **** **** **** **** **** +10685 Archivist_CW_Rain **** **** **** **** **** **** **** **** +10686 Archivist_CW_Snow **** **** **** **** **** **** **** **** +10687 Archivist_CW_Clear **** **** **** **** **** **** **** **** +10688 Archivist_Exteneded_Control_Weather **** **** **** **** **** **** **** **** +10689 Archivist_Exteneded_CW_Rain **** **** **** **** **** **** **** **** +10690 Archivist_Exteneded_CW_Snow **** **** **** **** **** **** **** **** +10691 Archivist_Exteneded_CW_Clear **** **** **** **** **** **** **** **** +10692 Archivist_Silent_Control_Weather **** **** **** **** **** **** **** **** +10693 Archivist_Silent_CW_Rain **** **** **** **** **** **** **** **** +10694 Archivist_Silent_CW_Snow **** **** **** **** **** **** **** **** +10695 Archivist_Silent_CW_Clear **** **** **** **** **** **** **** **** +10696 Archivist_Still_Control_Weather **** **** **** **** **** **** **** **** +10697 Archivist_Still_CW_Rain **** **** **** **** **** **** **** **** +10698 Archivist_Still_CW_Snow **** **** **** **** **** **** **** **** +10699 Archivist_Still_CW_Clear **** **** **** **** **** **** **** **** +10700 Archivist_Creeping_Doom **** **** **** **** **** **** **** **** +10701 Archivist_Exteneded_Creeping_Doom **** **** **** **** **** **** **** **** +10702 Archivist_Silent_Creeping_Doom **** **** **** **** **** **** **** **** +10703 Archivist_Still_Creeping_Doom **** **** **** **** **** **** **** **** +10704 Archivist_DEATH_BY_THORNS **** **** **** **** **** **** **** **** +10705 Archivist_Silent_DEATH_BY_THORNS **** **** **** **** **** **** **** **** +10706 Archivist_Still_DEATH_BY_THORNS **** **** **** **** **** **** **** **** +10707 Archivist_Destruction **** **** **** **** **** **** **** **** +10708 Archivist_Silent_Destruction **** **** **** **** **** **** **** **** +10709 Archivist_Still_Destruction **** **** **** **** **** **** **** **** +10710 Archivist_Dictum **** **** **** **** **** **** **** **** +10711 Archivist_Silent_Dictum **** **** **** **** **** **** **** **** +10712 Archivist_Still_Dictum **** **** **** **** **** **** **** **** +10713 Archivist_Disintegrate **** **** **** **** **** **** **** **** +10714 Archivist_Empowered_Disintegrate **** **** **** **** **** **** **** **** +10715 Archivist_Silent_Disintegrate **** **** **** **** **** **** **** **** +10716 Archivist_Still_Disintegrate **** **** **** **** **** **** **** **** +10717 Archivist_DRAGON_ALLY **** **** **** **** **** **** **** **** +10718 Archivist_Exteneded_DRAGON_ALLY **** **** **** **** **** **** **** **** +10719 Archivist_Silent_DRAGON_ALLY **** **** **** **** **** **** **** **** +10720 Archivist_Energy_Ebb **** **** **** **** **** **** **** **** +10721 Archivist_Exteneded_Energy_Ebb **** **** **** **** **** **** **** **** +10722 Archivist_Silent_Energy_Ebb **** **** **** **** **** **** **** **** +10723 Archivist_Still_Energy_Ebb **** **** **** **** **** **** **** **** +10724 Archivist_FIENDISH_CLARITY **** **** **** **** **** **** **** **** +10725 Archivist_Silent_FIENDISH_CLARITY **** **** **** **** **** **** **** **** +10726 Archivist_Still_FIENDISH_CLARITY **** **** **** **** **** **** **** **** +10727 Archivist_Great_Thunderclap **** **** **** **** **** **** **** **** +10728 Archivist_Silent_Great_Thunderclap **** **** **** **** **** **** **** **** +10729 Archivist_Still_Great_Thunderclap **** **** **** **** **** **** **** **** +10730 Archivist_Greater_Harm **** **** **** **** **** **** **** **** +10731 Archivist_Silent_Greater_Harm **** **** **** **** **** **** **** **** +10732 Archivist_Still_Greater_Harm **** **** **** **** **** **** **** **** +10733 Archivist_Greater_Restoration **** **** **** **** **** **** **** **** +10734 Archivist_Silent_Greater_Restoration **** **** **** **** **** **** **** **** +10735 Archivist_Still_Greater_Restoration **** **** **** **** **** **** **** **** +10736 Archivist_GreaterScrying **** **** **** **** **** **** **** **** +10737 Archivist_Exteneded_GreaterScrying **** **** **** **** **** **** **** **** +10738 Archivist_Silent_GreaterScrying **** **** **** **** **** **** **** **** +10739 Archivist_Still_GreaterScrying **** **** **** **** **** **** **** **** +10740 Archivist_GreaterTeleport_RadialMaster **** **** **** **** **** **** **** **** +10741 Archivist_GreaterTeleport_SelfOnly **** **** **** **** **** **** **** **** +10742 Archivist_GreaterTeleport_Party **** **** **** **** **** **** **** **** +10743 Archivist_Silent_GreaterTeleport_RadialMaster **** **** **** **** **** **** **** **** +10744 Archivist_Silent_GreaterTeleport_SelfOnly **** **** **** **** **** **** **** **** +10745 Archivist_Silent_GreaterTeleport_Party **** **** **** **** **** **** **** **** +10746 Archivist_Holy_Word **** **** **** **** **** **** **** **** +10747 Archivist_Silent_Holy_Word **** **** **** **** **** **** **** **** +10748 Archivist_Still_Holy_Word **** **** **** **** **** **** **** **** +10749 Archivist_Mass_Charm **** **** **** **** **** **** **** **** +10750 Archivist_Exteneded_Mass_Charm **** **** **** **** **** **** **** **** +10751 Archivist_Silent_Mass_Charm **** **** **** **** **** **** **** **** +10752 Archivist_Mass_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +10753 Archivist_Empowered_Mass_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +10754 Archivist_Silent_Mass_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +10755 Archivist_Still_Mass_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +10756 Archivist_Mass_Haste **** **** **** **** **** **** **** **** +10757 Archivist_Exteneded_Mass_Haste **** **** **** **** **** **** **** **** +10758 Archivist_Silent_Mass_Haste **** **** **** **** **** **** **** **** +10759 Archivist_Still_Mass_Haste **** **** **** **** **** **** **** **** +10760 Archivist_Mass_Hold_Person **** **** **** **** **** **** **** **** +10761 Archivist_Exteneded_Mass_Hold_Person **** **** **** **** **** **** **** **** +10762 Archivist_Silent_Mass_Hold_Person **** **** **** **** **** **** **** **** +10763 Archivist_Still_Mass_Hold_Person **** **** **** **** **** **** **** **** +10764 Archivist_Mass_Inflict_Serious_Wounds **** **** **** **** **** **** **** **** +10765 Archivist_Empowered_Mass_Inflict_Serious_Wounds **** **** **** **** **** **** **** **** +10766 Archivist_Silent_Mass_Inflict_Serious_Wounds **** **** **** **** **** **** **** **** +10767 Archivist_Still_Mass_Inflict_Serious_Wounds **** **** **** **** **** **** **** **** +10768 Archivist_Mass_Spell_Resistance **** **** **** **** **** **** **** **** +10769 Archivist_Exteneded_Mass_Spell_Resistance **** **** **** **** **** **** **** **** +10770 Archivist_Silent_Mass_Spell_Resistance **** **** **** **** **** **** **** **** +10771 Archivist_Still_Mass_Spell_Resistance **** **** **** **** **** **** **** **** +10772 Archivist_PHOENIX_FIRE **** **** **** **** **** **** **** **** +10773 Archivist_Empowered_PHOENIX_FIRE **** **** **** **** **** **** **** **** +10774 Archivist_Silent_PHOENIX_FIRE **** **** **** **** **** **** **** **** +10775 Archivist_Still_PHOENIX_FIRE **** **** **** **** **** **** **** **** +10776 Archivist_Prismatic_Spray **** **** **** **** **** **** **** **** +10777 Archivist_Silent_Prismatic_Spray **** **** **** **** **** **** **** **** +10778 Archivist_Still_Prismatic_Spray **** **** **** **** **** **** **** **** +10779 Archivist_Protection_from_Spells **** **** **** **** **** **** **** **** +10780 Archivist_Exteneded_Protection_from_Spells **** **** **** **** **** **** **** **** +10781 Archivist_Silent_Protection_from_Spells **** **** **** **** **** **** **** **** +10782 Archivist_Still_Protection_from_Spells **** **** **** **** **** **** **** **** +10783 Archivist_RAIN_OF_EMBERS **** **** **** **** **** **** **** **** +10784 Archivist_Empowered_RAIN_OF_EMBERS **** **** **** **** **** **** **** **** +10785 Archivist_Exteneded_RAIN_OF_EMBERS **** **** **** **** **** **** **** **** +10786 Archivist_Silent_RAIN_OF_EMBERS **** **** **** **** **** **** **** **** +10787 Archivist_Still_RAIN_OF_EMBERS **** **** **** **** **** **** **** **** +10788 Archivist_RAIN_OF_ROSES **** **** **** **** **** **** **** **** +10789 Archivist_Exteneded_RAIN_OF_ROSES **** **** **** **** **** **** **** **** +10790 Archivist_Silent_RAIN_OF_ROSES **** **** **** **** **** **** **** **** +10791 Archivist_Still_RAIN_OF_ROSES **** **** **** **** **** **** **** **** +10792 Archivist_RAPTURE_OF_RUPTURE **** **** **** **** **** **** **** **** +10793 Archivist_Empowered_RAPTURE_OF_RUPTURE **** **** **** **** **** **** **** **** +10794 Archivist_Regenerate **** **** **** **** **** **** **** **** +10795 Archivist_Exteneded_Regenerate **** **** **** **** **** **** **** **** +10796 Archivist_Silent_Regenerate **** **** **** **** **** **** **** **** +10797 Archivist_Still_Regenerate **** **** **** **** **** **** **** **** +10798 Archivist_Repulsion **** **** **** **** **** **** **** **** +10799 Archivist_Exteneded_Repulsion **** **** **** **** **** **** **** **** +10800 Archivist_Silent_Repulsion **** **** **** **** **** **** **** **** +10801 Archivist_Still_Repulsion **** **** **** **** **** **** **** **** +10802 Archivist_Resurrection **** **** **** **** **** **** **** **** +10803 Archivist_Silent_Resurrection **** **** **** **** **** **** **** **** +10804 Archivist_Still_Resurrection **** **** **** **** **** **** **** **** +10805 Archivist_RIGHTEOUS_SMITE **** **** **** **** **** **** **** **** +10806 Archivist_Empowered_RIGHTEOUS_SMITE **** **** **** **** **** **** **** **** +10807 Archivist_Silent_RIGHTEOUS_SMITE **** **** **** **** **** **** **** **** +10808 Archivist_Still_RIGHTEOUS_SMITE **** **** **** **** **** **** **** **** +10809 Archivist_Spell_Turning **** **** **** **** **** **** **** **** +10810 Archivist_Empowered_Spell_Turning **** **** **** **** **** **** **** **** +10811 Archivist_Exteneded_Spell_Turning **** **** **** **** **** **** **** **** +10812 Archivist_Silent_Spell_Turning **** **** **** **** **** **** **** **** +10813 Archivist_Still_Spell_Turning **** **** **** **** **** **** **** **** +10814 Archivist_Summon_Creature_VII **** **** **** **** **** **** **** **** +10815 Archivist_Summon7Air **** **** **** **** **** **** **** **** +10816 Archivist_Summon7Earth **** **** **** **** **** **** **** **** +10817 Archivist_Summon7Fire **** **** **** **** **** **** **** **** +10818 Archivist_Summon7Water **** **** **** **** **** **** **** **** +10819 Archivist_Exteneded_Summon_Creature_VII **** **** **** **** **** **** **** **** +10820 Archivist_Exteneded_Summon7Air **** **** **** **** **** **** **** **** +10821 Archivist_Exteneded_Summon7Earth **** **** **** **** **** **** **** **** +10822 Archivist_Exteneded_Summon7Fire **** **** **** **** **** **** **** **** +10823 Archivist_Exteneded_Summon7Water **** **** **** **** **** **** **** **** +10824 Archivist_Silent_Summon_Creature_VII **** **** **** **** **** **** **** **** +10825 Archivist_Silent_Summon7Air **** **** **** **** **** **** **** **** +10826 Archivist_Silent_Summon7Earth **** **** **** **** **** **** **** **** +10827 Archivist_Silent_Summon7Fire **** **** **** **** **** **** **** **** +10828 Archivist_Silent_Summon7Water **** **** **** **** **** **** **** **** +10829 Archivist_Still_Summon_Creature_VII **** **** **** **** **** **** **** **** +10830 Archivist_Still_Summon7Air **** **** **** **** **** **** **** **** +10831 Archivist_Still_Summon7Earth **** **** **** **** **** **** **** **** +10832 Archivist_Still_Summon7Fire **** **** **** **** **** **** **** **** +10833 Archivist_Still_Summon7Water **** **** **** **** **** **** **** **** +10834 Archivist_SYMBOL_OF_STUNING **** **** **** **** **** **** **** **** +10835 Archivist_Empowered_SYMBOL_OF_STUNING **** **** **** **** **** **** **** **** +10836 Archivist_Exteneded_SYMBOL_OF_STUNING **** **** **** **** **** **** **** **** +10837 Archivist_Silent_SYMBOL_OF_STUNING **** **** **** **** **** **** **** **** +10838 Archivist_Still_SYMBOL_OF_STUNING **** **** **** **** **** **** **** **** +10839 Archivist_SYMBOL_OF_WEAKNESS **** **** **** **** **** **** **** **** +10840 Archivist_Empowered_SYMBOL_OF_WEAKNESS **** **** **** **** **** **** **** **** +10841 Archivist_Exteneded_SYMBOL_OF_WEAKNESS **** **** **** **** **** **** **** **** +10842 Archivist_Silent_SYMBOL_OF_WEAKNESS **** **** **** **** **** **** **** **** +10843 Archivist_Still_SYMBOL_OF_WEAKNESS **** **** **** **** **** **** **** **** +10844 Archivist_TOMB_OF_LIGHT **** **** **** **** **** **** **** **** +10845 Archivist_Silent_TOMB_OF_LIGHT **** **** **** **** **** **** **** **** +10846 Archivist_Still_TOMB_OF_LIGHT **** **** **** **** **** **** **** **** +10847 Archivist_Word_of_Balance **** **** **** **** **** **** **** **** +10848 Archivist_Empowered_Word_of_Balance **** **** **** **** **** **** **** **** +10849 Archivist_Silent_Word_of_Balance **** **** **** **** **** **** **** **** +10850 Archivist_Word_of_Chaos **** **** **** **** **** **** **** **** +10851 Archivist_Silent_Word_of_Chaos **** **** **** **** **** **** **** **** +10852 Archivist_Still_Word_of_Chaos **** **** **** **** **** **** **** **** +10853 Archivist_WRETCHED_BLIGHT **** **** **** **** **** **** **** **** +10854 Archivist_Empowered_WRETCHED_BLIGHT **** **** **** **** **** **** **** **** +10855 Archivist_Silent_WRETCHED_BLIGHT **** **** **** **** **** **** **** **** +10856 Archivist_Still_WRETCHED_BLIGHT **** **** **** **** **** **** **** **** +10857 Archivist_ANTIMAGIC_FIELD **** **** **** **** **** **** **** **** +10858 Archivist_Exteneded_ANTIMAGIC_FIELD **** **** **** **** **** **** **** **** +10859 Archivist_Silent_ANTIMAGIC_FIELD **** **** **** **** **** **** **** **** +10860 Archivist_Still_ANTIMAGIC_FIELD **** **** **** **** **** **** **** **** +10861 Archivist_Aura_versus_Alignment **** **** **** **** **** **** **** **** +10862 Archivist_Unholy_Aura **** **** **** **** **** **** **** **** +10863 Archivist_Holy_Aura **** **** **** **** **** **** **** **** +10864 Archivist_Exteneded_Aura_versus_Alignment **** **** **** **** **** **** **** **** +10865 Archivist_Exteneded_Unholy_Aura **** **** **** **** **** **** **** **** +10866 Archivist_Exteneded_Holy_Aura **** **** **** **** **** **** **** **** +10867 Archivist_Silent_Aura_versus_Alignment **** **** **** **** **** **** **** **** +10868 Archivist_Silent_Unholy_Aura **** **** **** **** **** **** **** **** +10869 Archivist_Silent_Holy_Aura **** **** **** **** **** **** **** **** +10870 Archivist_Still_Aura_versus_Alignment **** **** **** **** **** **** **** **** +10871 Archivist_Still_Unholy_Aura **** **** **** **** **** **** **** **** +10872 Archivist_Still_Holy_Aura **** **** **** **** **** **** **** **** +10873 Archivist_Blackstaff **** **** **** **** **** **** **** **** +10874 Archivist_Exteneded_Blackstaff **** **** **** **** **** **** **** **** +10875 Archivist_Silent_Blackstaff **** **** **** **** **** **** **** **** +10876 Archivist_Still_Blackstaff **** **** **** **** **** **** **** **** +10877 Archivist_BODAK_BIRTH **** **** **** **** **** **** **** **** +10878 Archivist_Silent_BODAK_BIRTH **** **** **** **** **** **** **** **** +10879 Archivist_Still_BODAK_BIRTH **** **** **** **** **** **** **** **** +10880 Archivist_Bombardment **** **** **** **** **** **** **** **** +10881 Archivist_Silent_Bombardment **** **** **** **** **** **** **** **** +10882 Archivist_Still_Bombardment **** **** **** **** **** **** **** **** +10883 Archivist_Create_Greater_Undead **** **** **** **** **** **** **** **** +10884 Archivist_Exteneded_Create_Greater_Undead **** **** **** **** **** **** **** **** +10885 Archivist_Silent_Create_Greater_Undead **** **** **** **** **** **** **** **** +10886 Archivist_Still_Create_Greater_Undead **** **** **** **** **** **** **** **** +10887 Archivist_Delayed_Blast_Fireball **** **** **** **** **** **** **** **** +10888 Archivist_Exteneded_Delayed_Blast_Fireball **** **** **** **** **** **** **** **** +10889 Archivist_Silent_Delayed_Blast_Fireball **** **** **** **** **** **** **** **** +10890 Archivist_Still_Delayed_Blast_Fireball **** **** **** **** **** **** **** **** +10891 Archivist_Dimensional_Lock **** **** **** **** **** **** **** **** +10892 Archivist_Exteneded_Dimensional_Lock **** **** **** **** **** **** **** **** +10893 Archivist_Silent_Dimensional_Lock **** **** **** **** **** **** **** **** +10894 Archivist_Still_Dimensional_Lock **** **** **** **** **** **** **** **** +10895 Archivist_DiscernLocation **** **** **** **** **** **** **** **** +10896 Archivist_Exteneded_DiscernLocation **** **** **** **** **** **** **** **** +10897 Archivist_Silent_DiscernLocation **** **** **** **** **** **** **** **** +10898 Archivist_Still_DiscernLocation **** **** **** **** **** **** **** **** +10899 Archivist_Dominate_Monster **** **** **** **** **** **** **** **** +10900 Archivist_Exteneded_Dominate_Monster **** **** **** **** **** **** **** **** +10901 Archivist_Silent_Dominate_Monster **** **** **** **** **** **** **** **** +10902 Archivist_Still_Dominate_Monster **** **** **** **** **** **** **** **** +10903 Archivist_DRAGON_CLOUD **** **** **** **** **** **** **** **** +10904 Archivist_Silent_DRAGON_CLOUD **** **** **** **** **** **** **** **** +10905 Archivist_Still_DRAGON_CLOUD **** **** **** **** **** **** **** **** +10906 Archivist_Earthquake **** **** **** **** **** **** **** **** +10907 Archivist_Exteneded_Earthquake **** **** **** **** **** **** **** **** +10908 Archivist_Silent_Earthquake **** **** **** **** **** **** **** **** +10909 Archivist_Still_Earthquake **** **** **** **** **** **** **** **** +10910 Archivist_EVIL_WEATHER **** **** **** **** **** **** **** **** +10911 Archivist_EVIL_WEATHER_RAIN_OF_BLOOD **** **** **** **** **** **** **** **** +10912 Archivist_EVIL_WEATHER_VIOLET_RAIN **** **** **** **** **** **** **** **** +10913 Archivist_EVIL_WEATHER_GREEN_FOG **** **** **** **** **** **** **** **** +10914 Archivist_EVIL_WEATHER_RAIN_OF_FISH **** **** **** **** **** **** **** **** +10915 Archivist_Silent_EVIL_WEATHER **** **** **** **** **** **** **** **** +10916 Archivist_Silent_EVIL_WEATHER_RAIN_OF_BLOOD **** **** **** **** **** **** **** **** +10917 Archivist_Silent_EVIL_WEATHER_VIOLET_RAIN **** **** **** **** **** **** **** **** +10918 Archivist_Silent_EVIL_WEATHER_GREEN_FOG **** **** **** **** **** **** **** **** +10919 Archivist_Silent_EVIL_WEATHER_RAIN_OF_FISH **** **** **** **** **** **** **** **** +10920 Archivist_Still_EVIL_WEATHER **** **** **** **** **** **** **** **** +10921 Archivist_Still_EVIL_WEATHER_RAIN_OF_BLOOD **** **** **** **** **** **** **** **** +10922 Archivist_Still_EVIL_WEATHER_VIOLET_RAIN **** **** **** **** **** **** **** **** +10923 Archivist_Still_EVIL_WEATHER_GREEN_FOG **** **** **** **** **** **** **** **** +10924 Archivist_Still_EVIL_WEATHER_RAIN_OF_FISH **** **** **** **** **** **** **** **** +10925 Archivist_Finger_of_Death **** **** **** **** **** **** **** **** +10926 Archivist_Silent_Finger_of_Death **** **** **** **** **** **** **** **** +10927 Archivist_Still_Finger_of_Death **** **** **** **** **** **** **** **** +10928 Archivist_Fire_Storm **** **** **** **** **** **** **** **** +10929 Archivist_Silent_Fire_Storm **** **** **** **** **** **** **** **** +10930 Archivist_Still_Fire_Storm **** **** **** **** **** **** **** **** +10931 Archivist_Greater_Planar_Ally **** **** **** **** **** **** **** **** +10932 Archivist_Exteneded_Greater_Planar_Ally **** **** **** **** **** **** **** **** +10933 Archivist_Silent_Greater_Planar_Ally **** **** **** **** **** **** **** **** +10934 Archivist_Still_Greater_Planar_Ally **** **** **** **** **** **** **** **** +10935 Archivist_Greater_Wall_of_Dispel_Magic **** **** **** **** **** **** **** **** +10936 Archivist_Exteneded_Greater_Wall_of_Dispel_Magic **** **** **** **** **** **** **** **** +10937 Archivist_Silent_Greater_Wall_of_Dispel_Magic **** **** **** **** **** **** **** **** +10938 Archivist_Still_Greater_Wall_of_Dispel_Magic **** **** **** **** **** **** **** **** +10939 Archivist_Holy_Aura **** **** **** **** **** **** **** **** +10940 Archivist_Exteneded_Holy_Aura **** **** **** **** **** **** **** **** +10941 Archivist_Silent_Holy_Aura **** **** **** **** **** **** **** **** +10942 Archivist_Still_Holy_Aura **** **** **** **** **** **** **** **** +10943 Archivist_Horrid_Wilting **** **** **** **** **** **** **** **** +10944 Archivist_Silent_Horrid_Wilting **** **** **** **** **** **** **** **** +10945 Archivist_Still_Horrid_Wilting **** **** **** **** **** **** **** **** +10946 Archivist_LAST_JUDGEMENT **** **** **** **** **** **** **** **** +10947 Archivist_Silent_LAST_JUDGEMENT **** **** **** **** **** **** **** **** +10948 Archivist_Mass_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +10949 Archivist_Silent_Mass_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +10950 Archivist_Still_Mass_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +10951 Archivist_Mass_Heal **** **** **** **** **** **** **** **** +10952 Archivist_Silent_Mass_Heal **** **** **** **** **** **** **** **** +10953 Archivist_Still_Mass_Heal **** **** **** **** **** **** **** **** +10954 Archivist_Mass_Inflict_Critical_Wounds **** **** **** **** **** **** **** **** +10955 Archivist_Silent_Mass_Inflict_Critical_Wounds **** **** **** **** **** **** **** **** +10956 Archivist_Still_Mass_Inflict_Critical_Wounds **** **** **** **** **** **** **** **** +10957 Archivist_Natures_Balance **** **** **** **** **** **** **** **** +10958 Archivist_Silent_Natures_Balance **** **** **** **** **** **** **** **** +10959 Archivist_Still_Natures_Balance **** **** **** **** **** **** **** **** +10960 Archivist_Necrotic_Empowerment **** **** **** **** **** **** **** **** +10961 Archivist_Exteneded_Necrotic_Empowerment **** **** **** **** **** **** **** **** +10962 Archivist_Silent_Necrotic_Empowerment **** **** **** **** **** **** **** **** +10963 Archivist_Still_Necrotic_Empowerment **** **** **** **** **** **** **** **** +10964 Archivist_Pestilence **** **** **** **** **** **** **** **** +10965 Archivist_Silent_Pestilence **** **** **** **** **** **** **** **** +10966 Archivist_Still_Pestilence **** **** **** **** **** **** **** **** +10967 Archivist_Power_Word_Stun **** **** **** **** **** **** **** **** +10968 Archivist_Silent_Power_Word_Stun **** **** **** **** **** **** **** **** +10969 Archivist_Premonition **** **** **** **** **** **** **** **** +10970 Archivist_Exteneded_Premonition **** **** **** **** **** **** **** **** +10971 Archivist_Silent_Premonition **** **** **** **** **** **** **** **** +10972 Archivist_Still_Premonition **** **** **** **** **** **** **** **** +10973 Archivist_Shadow_Shield **** **** **** **** **** **** **** **** +10974 Archivist_Exteneded_Shadow_Shield **** **** **** **** **** **** **** **** +10975 Archivist_Silent_Shadow_Shield **** **** **** **** **** **** **** **** +10976 Archivist_Still_Shadow_Shield **** **** **** **** **** **** **** **** +10977 Archivist_Summon_Creature_VIII **** **** **** **** **** **** **** **** +10978 Archivist_Summon8Air **** **** **** **** **** **** **** **** +10979 Archivist_Summon8Earth **** **** **** **** **** **** **** **** +10980 Archivist_Summon8Fire **** **** **** **** **** **** **** **** +10981 Archivist_Summon8Water **** **** **** **** **** **** **** **** +10982 Archivist_Exteneded_Summon_Creature_VIII **** **** **** **** **** **** **** **** +10983 Archivist_Exteneded_Summon8Air **** **** **** **** **** **** **** **** +10984 Archivist_Exteneded_Summon8Earth **** **** **** **** **** **** **** **** +10985 Archivist_Exteneded_Summon8Fire **** **** **** **** **** **** **** **** +10986 Archivist_Exteneded_Summon8Water **** **** **** **** **** **** **** **** +10987 Archivist_Silent_Summon_Creature_VIII **** **** **** **** **** **** **** **** +10988 Archivist_Silent_Summon8Air **** **** **** **** **** **** **** **** +10989 Archivist_Silent_Summon8Earth **** **** **** **** **** **** **** **** +10990 Archivist_Silent_Summon8Fire **** **** **** **** **** **** **** **** +10991 Archivist_Silent_Summon8Water **** **** **** **** **** **** **** **** +10992 Archivist_Still_Summon_Creature_VIII **** **** **** **** **** **** **** **** +10993 Archivist_Still_Summon8Air **** **** **** **** **** **** **** **** +10994 Archivist_Still_Summon8Earth **** **** **** **** **** **** **** **** +10995 Archivist_Still_Summon8Fire **** **** **** **** **** **** **** **** +10996 Archivist_Still_Summon8Water **** **** **** **** **** **** **** **** +10997 Archivist_Sunbeam **** **** **** **** **** **** **** **** +10998 Archivist_Silent_Sunbeam **** **** **** **** **** **** **** **** +10999 Archivist_Still_Sunbeam **** **** **** **** **** **** **** **** +11000 Archivist_Sunburst **** **** **** **** **** **** **** **** +11001 Archivist_Silent_Sunburst **** **** **** **** **** **** **** **** +11002 Archivist_Still_Sunburst **** **** **** **** **** **** **** **** +11003 Archivist_SYMBOL_OF_DEATH **** **** **** **** **** **** **** **** +11004 Archivist_Exteneded_SYMBOL_OF_DEATH **** **** **** **** **** **** **** **** +11005 Archivist_Silent_SYMBOL_OF_DEATH **** **** **** **** **** **** **** **** +11006 Archivist_Still_SYMBOL_OF_DEATH **** **** **** **** **** **** **** **** +11007 Archivist_SYMBOL_OF_INSANITY **** **** **** **** **** **** **** **** +11008 Archivist_Exteneded_SYMBOL_OF_INSANITY **** **** **** **** **** **** **** **** +11009 Archivist_Silent_SYMBOL_OF_INSANITY **** **** **** **** **** **** **** **** +11010 Archivist_Still_SYMBOL_OF_INSANITY **** **** **** **** **** **** **** **** +11011 Archivist_APOCALYPSE_FROM_THE_SKY **** **** **** **** **** **** **** **** +11012 Archivist_APOCALYPSE_FROM_THE_SKY_FIRE **** **** **** **** **** **** **** **** +11013 Archivist_APOCALYPSE_FROM_THE_SKY_ACID **** **** **** **** **** **** **** **** +11014 Archivist_APOCALYPSE_FROM_THE_SKY_SONIC **** **** **** **** **** **** **** **** +11015 Archivist_DESPOIL **** **** **** **** **** **** **** **** +11016 Archivist_Elder_Glyph_of_Warding_Master **** **** **** **** **** **** **** **** +11017 Archivist_Elder_Glyph_of_Warding_Acid **** **** **** **** **** **** **** **** +11018 Archivist_Elder_Glyph_of_Warding_Cold **** **** **** **** **** **** **** **** +11019 Archivist_Elder_Glyph_of_Warding_Electricity **** **** **** **** **** **** **** **** +11020 Archivist_Elder_Glyph_of_Warding_Fire **** **** **** **** **** **** **** **** +11021 Archivist_Elder_Glyph_of_Warding_Sonic **** **** **** **** **** **** **** **** +11022 Archivist_Elemental_Swarm **** **** **** **** **** **** **** **** +11023 Archivist_Energy_Drain **** **** **** **** **** **** **** **** +11024 Archivist_EXALTED_FURY **** **** **** **** **** **** **** **** +11025 Archivist_Foresight **** **** **** **** **** **** **** **** +11026 Archivist_Gate **** **** **** **** **** **** **** **** +11027 Archivist_Greater_Planar_Binding **** **** **** **** **** **** **** **** +11028 Archivist_Greater_Spell_Mantle **** **** **** **** **** **** **** **** +11029 Archivist_Implosion **** **** **** **** **** **** **** **** +11030 Archivist_Mantle_of_Eg_Might **** **** **** **** **** **** **** **** +11031 Archivist_Mass_Drown **** **** **** **** **** **** **** **** +11032 Archivist_Mass_Harm **** **** **** **** **** **** **** **** +11033 Archivist_Mass_Hold_Monster **** **** **** **** **** **** **** **** +11034 Archivist_Nature_Avatar **** **** **** **** **** **** **** **** +11035 Archivist_Necrotic_Termination **** **** **** **** **** **** **** **** +11036 Archivist_PlagueOfUndead **** **** **** **** **** **** **** **** +11037 Archivist_Power_Word_Kill **** **** **** **** **** **** **** **** +11038 Archivist_Power_Word_Blind **** **** **** **** **** **** **** **** +11039 Archivist_RAIN_OF_BLACK_TULIPS **** **** **** **** **** **** **** **** +11040 Archivist_Shapechange **** **** **** **** **** **** **** **** +11041 Archivist_Shapechange_RED_DRAGON **** **** **** **** **** **** **** **** +11042 Archivist_Shapechange_FIRE_GIANT **** **** **** **** **** **** **** **** +11043 Archivist_Shapechange_BALOR **** **** **** **** **** **** **** **** +11044 Archivist_Shapechange_DEATH_SLAAD **** **** **** **** **** **** **** **** +11045 Archivist_Shapechange_IRON_GOLEM **** **** **** **** **** **** **** **** +11046 Archivist_Sphere_of_Ultimate_Destruction **** **** **** **** **** **** **** **** +11047 Archivist_Storm_of_Vengeance **** **** **** **** **** **** **** **** +11048 Archivist_Summon_Creature_IX **** **** **** **** **** **** **** **** +11049 Archivist_Summon9Air **** **** **** **** **** **** **** **** +11050 Archivist_Summon9Earth **** **** **** **** **** **** **** **** +11051 Archivist_Summon9Fire **** **** **** **** **** **** **** **** +11052 Archivist_Summon9Water **** **** **** **** **** **** **** **** +11053 Archivist_True_Resurrection **** **** **** **** **** **** **** **** +11054 Archivist_Undeaths_Eternal_Foe **** **** **** **** **** **** **** **** +11055 Archivist_Unyielding_Roots **** **** **** **** **** **** **** **** +11056 Archivist_VileDeath **** **** **** **** **** **** **** **** +11057 Archivist_Wail_of_the_Banshee **** **** **** **** **** **** **** **** +11058 Archivist_Weird **** **** **** **** **** **** **** **** +11059 ****_Cure_Minor_Wounds **** **** **** **** **** **** **** **** +11060 ****_Inflict_Minor_Wounds **** **** **** **** **** **** **** **** +11061 ****_Light **** **** **** **** **** **** **** **** +11062 ****_Read_Magic **** **** **** **** **** **** **** **** +11063 ****_Resistance **** **** **** **** **** **** **** **** +11064 ****_Virtue **** **** **** **** **** **** **** **** +11065 ****_Command_RadialMaster **** **** **** **** **** **** **** **** +11066 ****_Command_Approach **** **** **** **** **** **** **** **** +11067 ****_Command_Drop **** **** **** **** **** **** **** **** +11068 ****_Command_Fall **** **** **** **** **** **** **** **** +11069 ****_Command_Flee **** **** **** **** **** **** **** **** +11070 ****_Command_Halt **** **** **** **** **** **** **** **** +11071 ****_Cure_Light_Wounds **** **** **** **** **** **** **** **** +11072 ****_DETECT_UNDEAD **** **** **** **** **** **** **** **** +11073 ****_Divine_Favor **** **** **** **** **** **** **** **** +11074 ****_Doom **** **** **** **** **** **** **** **** +11075 ****_Endure_Elements **** **** **** **** **** **** **** **** +11076 ****_HideFromUndead **** **** **** **** **** **** **** **** +11077 ****_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +11078 ****_Remove_Fear **** **** **** **** **** **** **** **** +11079 ****_Protection_from_Evil **** **** **** **** **** **** **** **** +11080 ****_Protection_from_Good **** **** **** **** **** **** **** **** +11081 ****_Shield_of_Faith **** **** **** **** **** **** **** **** +11082 ****_Endurance **** **** **** **** **** **** **** **** +11083 ****_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +11084 ****_Hold_Person **** **** **** **** **** **** **** **** +11085 ****_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +11086 ****_Remove_Paralysis **** **** **** **** **** **** **** **** +11087 ****_Resist_Elements **** **** **** **** **** **** **** **** +11088 ****_Lesser_Restoration **** **** **** **** **** **** **** **** +11089 ****_Silence **** **** **** **** **** **** **** **** +11090 ****_UndetectableAlignment **** **** **** **** **** **** **** **** +11091 ****_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +11092 ****_Dispel_Magic **** **** **** **** **** **** **** **** +11093 ****_Glyph_of_Warding_Master **** **** **** **** **** **** **** **** +11094 ****_Glyph_of_Warding_Acid **** **** **** **** **** **** **** **** +11095 ****_Glyph_of_Warding_Cold **** **** **** **** **** **** **** **** +11096 ****_Glyph_of_Warding_Electricity **** **** **** **** **** **** **** **** +11097 ****_Glyph_of_Warding_Fire **** **** **** **** **** **** **** **** +11098 ****_Glyph_of_Warding_Sonic **** **** **** **** **** **** **** **** +11099 ****_Inflict_Serious_Wounds **** **** **** **** **** **** **** **** +11100 ****_Lightning_Bolt **** **** **** **** **** **** **** **** +11101 ****_LocateObject **** **** **** **** **** **** **** **** +11102 ****_Magic_Circle_against_Evil **** **** **** **** **** **** **** **** +11103 ****_Magic_Circle_against_Good **** **** **** **** **** **** **** **** +11104 ****_Magic_Vestment **** **** **** **** **** **** **** **** +11105 ****_Protection_from_Elements **** **** **** **** **** **** **** **** +11106 ****_Remove_Disease **** **** **** **** **** **** **** **** +11107 ****_GreaterCommand_RadialMaster **** **** **** **** **** **** **** **** +11108 ****_GreaterCommand_Approach **** **** **** **** **** **** **** **** +11109 ****_GreaterCommand_Drop **** **** **** **** **** **** **** **** +11110 ****_GreaterCommand_Fall **** **** **** **** **** **** **** **** +11111 ****_GreaterCommand_Flee **** **** **** **** **** **** **** **** +11112 ****_GreaterCommand_Halt **** **** **** **** **** **** **** **** +11113 ****_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +11114 ****_Dimensional_Anchor **** **** **** **** **** **** **** **** +11115 ****_Freedom_of_Movement **** **** **** **** **** **** **** **** +11116 ****_Inflict_Critical_Wounds **** **** **** **** **** **** **** **** +11117 ****_Greater_Magic_Weapon **** **** **** **** **** **** **** **** +11118 ****_Neutralize_Poison **** **** **** **** **** **** **** **** +11119 ****_BreakEnchantment **** **** **** **** **** **** **** **** +11120 ****_Elemental_Strike **** **** **** **** **** **** **** **** +11121 ****_Elemental_Strike_Acid **** **** **** **** **** **** **** **** +11122 ****_Elemental_Strike_Cold **** **** **** **** **** **** **** **** +11123 ****_Elemental_Strike_Electricity **** **** **** **** **** **** **** **** +11124 ****_Elemental_Strike_Fire **** **** **** **** **** **** **** **** +11125 ****_Elemental_Strike_Sonic **** **** **** **** **** **** **** **** +11126 ****_Scrying **** **** **** **** **** **** **** **** +11127 ****_SYMBOL_OF_PAIN **** **** **** **** **** **** **** **** +11128 ****_SYMBOL_OF_SLEEP **** **** **** **** **** **** **** **** +11129 ****_True_Seeing **** **** **** **** **** **** **** **** +11130 ****_Create_Undead **** **** **** **** **** **** **** **** +11131 ****_Greater_Dispelling **** **** **** **** **** **** **** **** +11132 ****_Greater_Glyph_of_Warding_Master **** **** **** **** **** **** **** **** +11133 ****_Greater_Glyph_of_Warding_Acid **** **** **** **** **** **** **** **** +11134 ****_Greater_Glyph_of_Warding_Cold **** **** **** **** **** **** **** **** +11135 ****_Greater_Glyph_of_Warding_Electricity **** **** **** **** **** **** **** **** +11136 ****_Greater_Glyph_of_Warding_Fire **** **** **** **** **** **** **** **** +11137 ****_Greater_Glyph_of_Warding_Sonic **** **** **** **** **** **** **** **** +11138 ****_Raise_Dead **** **** **** **** **** **** **** **** +11139 ****_SYMBOL_OF_FEAR **** **** **** **** **** **** **** **** +11140 ****_SYMBOL_OF_PERSUASION **** **** **** **** **** **** **** **** +11141 ****_WordOfRecall_RadialMaster **** **** **** **** **** **** **** **** +11142 ****_WordOfRecall_SelfOnly **** **** **** **** **** **** **** **** +11143 ****_WordOfRecall_Party **** **** **** **** **** **** **** **** +11144 ****_GreaterScrying **** **** **** **** **** **** **** **** +11145 ****_SYMBOL_OF_STUNING **** **** **** **** **** **** **** **** +11146 ****_SYMBOL_OF_WEAKNESS **** **** **** **** **** **** **** **** +11147 ****_Create_Greater_Undead **** **** **** **** **** **** **** **** +11148 ****_DiscernLocation **** **** **** **** **** **** **** **** +11149 ****_Finger_of_Death **** **** **** **** **** **** **** **** +11150 ****_Regenerate **** **** **** **** **** **** **** **** +11151 ****_SYMBOL_OF_DEATH **** **** **** **** **** **** **** **** +11152 ****_Energy_Drain **** **** **** **** **** **** **** **** +11153 ****_Power_Word_Blind **** **** **** **** **** **** **** **** +11154 ****_Cure_Minor_Wounds **** **** **** **** **** **** **** **** +11155 ****_Dancing_Lights **** **** **** **** **** **** **** **** +11156 ****_Daze **** **** **** **** **** **** **** **** +11157 ****_Flare **** **** **** **** **** **** **** **** +11158 ****_Light **** **** **** **** **** **** **** **** +11159 ****_MAGE_HAND **** **** **** **** **** **** **** **** +11160 ****_Read_Magic **** **** **** **** **** **** **** **** +11161 ****_Resistance **** **** **** **** **** **** **** **** +11162 ****_Sobriety **** **** **** **** **** **** **** **** +11163 ****_Virtue **** **** **** **** **** **** **** **** +11164 ****_Cause_Fear **** **** **** **** **** **** **** **** +11165 ****_Charm_Person **** **** **** **** **** **** **** **** +11166 ****_Command_RadialMaster **** **** **** **** **** **** **** **** +11167 ****_Command_Approach **** **** **** **** **** **** **** **** +11168 ****_Command_Drop **** **** **** **** **** **** **** **** +11169 ****_Command_Fall **** **** **** **** **** **** **** **** +11170 ****_Command_Flee **** **** **** **** **** **** **** **** +11171 ****_Command_Halt **** **** **** **** **** **** **** **** +11172 ****_Crafters_Blessing **** **** **** **** **** **** **** **** +11173 ****_Crafters_Curse **** **** **** **** **** **** **** **** +11174 ****_Cure_Light_Wounds **** **** **** **** **** **** **** **** +11175 ****_Disguise_Self_Radial_Master **** **** **** **** **** **** **** **** +11176 ****_Disguise_Self_Learn **** **** **** **** **** **** **** **** +11177 ****_Disguise_Self_Options **** **** **** **** **** **** **** **** +11178 ****_Disguise_Self_QS1 **** **** **** **** **** **** **** **** +11179 ****_Disguise_Self_QS2 **** **** **** **** **** **** **** **** +11180 ****_Disguise_Self_QS3 **** **** **** **** **** **** **** **** +11181 ****_Doom **** **** **** **** **** **** **** **** +11182 ****_Endure_Elements **** **** **** **** **** **** **** **** +11183 ****_Grease **** **** **** **** **** **** **** **** +11184 ****_Expeditious_Retreat **** **** **** **** **** **** **** **** +11185 ****_Faerie_Fire **** **** **** **** **** **** **** **** +11186 ****_Tashas_Hideous_Laughter **** **** **** **** **** **** **** **** +11187 ****_Identify **** **** **** **** **** **** **** **** +11188 ****_Spell_Jump **** **** **** **** **** **** **** **** +11189 ****_ObscureObject **** **** **** **** **** **** **** **** +11190 ****_Obscuring_Mist **** **** **** **** **** **** **** **** +11191 ****_Protection_from_Chaos **** **** **** **** **** **** **** **** +11192 ****_Protection_from_Evil **** **** **** **** **** **** **** **** +11193 ****_Protection_from_Good **** **** **** **** **** **** **** **** +11194 ****_Protection_from_Law **** **** **** **** **** **** **** **** +11195 ****_Remove_Fear **** **** **** **** **** **** **** **** +11196 ****_Sleep **** **** **** **** **** **** **** **** +11197 ****_Summon_Creature_I **** **** **** **** **** **** **** **** +11198 ****_UndetectableAlignment **** **** **** **** **** **** **** **** +11199 ****_Alter_Self_Radial_Master **** **** **** **** **** **** **** **** +11200 ****_Alter_Self_Learn **** **** **** **** **** **** **** **** +11201 ****_Alter_Self_Options **** **** **** **** **** **** **** **** +11202 ****_Alter_Self_QS1 **** **** **** **** **** **** **** **** +11203 ****_Alter_Self_QS2 **** **** **** **** **** **** **** **** +11204 ****_Alter_Self_QS3 **** **** **** **** **** **** **** **** +11205 ****_Endurance **** **** **** **** **** **** **** **** +11206 ****_Bulls_Strength **** **** **** **** **** **** **** **** +11207 ****_Blindness_and_Deafness **** **** **** **** **** **** **** **** +11208 ****_Blur **** **** **** **** **** **** **** **** +11209 ****_Calm_Emotions **** **** **** **** **** **** **** **** +11210 ****_Cats_Grace **** **** **** **** **** **** **** **** +11211 ****_Continual_Flame **** **** **** **** **** **** **** **** +11212 ****_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +11213 ****_Darkness **** **** **** **** **** **** **** **** +11214 ****_Daze_Monster **** **** **** **** **** **** **** **** +11215 ****_Eagle_Splendor **** **** **** **** **** **** **** **** +11216 ****_FogCloud **** **** **** **** **** **** **** **** +11217 ****_Foxs_Cunning **** **** **** **** **** **** **** **** +11218 ****_Heroism **** **** **** **** **** **** **** **** +11219 ****_Hold_Person **** **** **** **** **** **** **** **** +11220 ****_Invisibility **** **** **** **** **** **** **** **** +11221 ****_Lesser_Dispel **** **** **** **** **** **** **** **** +11222 ****_LocateObject **** **** **** **** **** **** **** **** +11223 ****_MirrorImage **** **** **** **** **** **** **** **** +11224 ****_Owls_Wisdom **** **** **** **** **** **** **** **** +11225 ****_ProtectionArrows **** **** **** **** **** **** **** **** +11226 ****_Pyrotechnics **** **** **** **** **** **** **** **** +11227 ****_Pyrotechnics_Fireworks **** **** **** **** **** **** **** **** +11228 ****_Pyrotechnics_Smoke **** **** **** **** **** **** **** **** +11229 ****_Resist_Elements **** **** **** **** **** **** **** **** +11230 ****_Scare **** **** **** **** **** **** **** **** +11231 ****_Silence **** **** **** **** **** **** **** **** +11232 ****_Summon_Creature_II **** **** **** **** **** **** **** **** +11233 ****_TouchIdiocy **** **** **** **** **** **** **** **** +11234 ****_Ultravision **** **** **** **** **** **** **** **** +11235 ****_Bestow_Curse **** **** **** **** **** **** **** **** +11236 ****_Charm_Monster **** **** **** **** **** **** **** **** +11237 ****_Clairaudience_and_Clairvoyance **** **** **** **** **** **** **** **** +11238 ****_Confusion **** **** **** **** **** **** **** **** +11239 ****_CrushingDespair **** **** **** **** **** **** **** **** +11240 ****_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +11241 ****_Daylight **** **** **** **** **** **** **** **** +11242 ****_DeepSlumber **** **** **** **** **** **** **** **** +11243 ****_Dispel_Magic **** **** **** **** **** **** **** **** +11244 ****_Displacement **** **** **** **** **** **** **** **** +11245 ****_Fear **** **** **** **** **** **** **** **** +11246 ****_GLIBNESS **** **** **** **** **** **** **** **** +11247 ****_Haste **** **** **** **** **** **** **** **** +11248 ****_Invisibility_Sphere **** **** **** **** **** **** **** **** +11249 ****_Magic_Circle_against_Chaos **** **** **** **** **** **** **** **** +11250 ****_Magic_Circle_against_Evil **** **** **** **** **** **** **** **** +11251 ****_Magic_Circle_against_Good **** **** **** **** **** **** **** **** +11252 ****_Magic_Circle_against_Law **** **** **** **** **** **** **** **** +11253 ****_Protection_from_Elements **** **** **** **** **** **** **** **** +11254 ****_RayofExhaustion **** **** **** **** **** **** **** **** +11255 ****_Remove_Blindness_and_Deafness **** **** **** **** **** **** **** **** +11256 ****_Remove_Curse **** **** **** **** **** **** **** **** +11257 ****_Remove_Disease **** **** **** **** **** **** **** **** +11258 ****_Scrying **** **** **** **** **** **** **** **** +11259 ****_See_Invisibility **** **** **** **** **** **** **** **** +11260 ****_Slow **** **** **** **** **** **** **** **** +11261 ****_Spiderskin **** **** **** **** **** **** **** **** +11262 ****_Summon_Creature_III **** **** **** **** **** **** **** **** +11263 ****_WaterBreathing **** **** **** **** **** **** **** **** +11264 ****_Animate_Dead **** **** **** **** **** **** **** **** +11265 ****_ArcaneEye **** **** **** **** **** **** **** **** +11266 ****_BreakEnchantment **** **** **** **** **** **** **** **** +11267 ****_Contagion **** **** **** **** **** **** **** **** +11268 ****_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +11269 ****_DetectScrying **** **** **** **** **** **** **** **** +11270 ****_DimensionDoor_RadialMaster **** **** **** **** **** **** **** **** +11271 ****_DimensionDoor_SelfOnly **** **** **** **** **** **** **** **** +11272 ****_DimensionDoor_Party **** **** **** **** **** **** **** **** +11273 ****_DimensionDoor_DirDist_SelfOnly **** **** **** **** **** **** **** **** +11274 ****_DimensionDoor_DirDist_Party **** **** **** **** **** **** **** **** +11275 ****_Dominate_Person **** **** **** **** **** **** **** **** +11276 ****_Freedom_of_Movement **** **** **** **** **** **** **** **** +11277 ****_Hold_Monster **** **** **** **** **** **** **** **** +11278 ****_Improved_Invisibility **** **** **** **** **** **** **** **** +11279 ****_Greater_Resistance **** **** **** **** **** **** **** **** +11280 ****_LocateCreature **** **** **** **** **** **** **** **** +11281 ****_Mass_Ultravision **** **** **** **** **** **** **** **** +11282 ****_Neutralize_Poison **** **** **** **** **** **** **** **** +11283 ****_Polymorph_Self **** **** **** **** **** **** **** **** +11284 ****_Polymorph_GIANT_SPIDER **** **** **** **** **** **** **** **** +11285 ****_Polymorph_TROLL **** **** **** **** **** **** **** **** +11286 ****_Polymorph_UMBER_HULK **** **** **** **** **** **** **** **** +11287 ****_Polymorph_PIXIE **** **** **** **** **** **** **** **** +11288 ****_Polymorph_ZOMBIE **** **** **** **** **** **** **** **** +11289 ****_RAINBOW_PATTERN **** **** **** **** **** **** **** **** +11290 ****_RepelVermin **** **** **** **** **** **** **** **** +11291 ****_Shadow_Conjuration **** **** **** **** **** **** **** **** +11292 ****_SHADOW_CON_Summon_Shadow **** **** **** **** **** **** **** **** +11293 ****_SHADOW_CON_Darkness **** **** **** **** **** **** **** **** +11294 ****_SHADOW_CON_Inivsibility **** **** **** **** **** **** **** **** +11295 ****_SHADOW_CON_Mage_Armor **** **** **** **** **** **** **** **** +11296 ****_SHADOW_CON_Magic_Missile **** **** **** **** **** **** **** **** +11297 ****_Stoneskin **** **** **** **** **** **** **** **** +11298 ****_Summon_Creature_IV **** **** **** **** **** **** **** **** +11299 ****_BalefulPolymorph **** **** **** **** **** **** **** **** +11300 ****_GreaterCommand_RadialMaster **** **** **** **** **** **** **** **** +11301 ****_GreaterCommand_Approach **** **** **** **** **** **** **** **** +11302 ****_GreaterCommand_Drop **** **** **** **** **** **** **** **** +11303 ****_GreaterCommand_Fall **** **** **** **** **** **** **** **** +11304 ****_GreaterCommand_Flee **** **** **** **** **** **** **** **** +11305 ****_GreaterCommand_Halt **** **** **** **** **** **** **** **** +11306 ****_Mass_Cure_Light_Wounds **** **** **** **** **** **** **** **** +11307 ****_Greater_Dispelling **** **** **** **** **** **** **** **** +11308 ****_Energy_Buffer **** **** **** **** **** **** **** **** +11309 ****_Eternal_Charm_Person **** **** **** **** **** **** **** **** +11310 ****_Feeblemind **** **** **** **** **** **** **** **** +11311 ****_Greater_Heroism **** **** **** **** **** **** **** **** +11312 ****_Lesser_Planar_Binding **** **** **** **** **** **** **** **** +11313 ****_Mind_Fog **** **** **** **** **** **** **** **** +11314 ****_Mislead **** **** **** **** **** **** **** **** +11315 ****_Panacea **** **** **** **** **** **** **** **** +11316 ****_GreaterScrying **** **** **** **** **** **** **** **** +11317 ****_Summon_Creature_V **** **** **** **** **** **** **** **** +11318 ****_WavesofFatigue **** **** **** **** **** **** **** **** +11319 ****_Animate_Object **** **** **** **** **** **** **** **** +11320 ****_Mass_Endurance **** **** **** **** **** **** **** **** +11321 ****_Mass_Bulls_Strength **** **** **** **** **** **** **** **** +11322 ****_Mass_Cats_Grace **** **** **** **** **** **** **** **** +11323 ****_Mass_Charm **** **** **** **** **** **** **** **** +11324 ****_Control_Weather **** **** **** **** **** **** **** **** +11325 ****_CW_Rain **** **** **** **** **** **** **** **** +11326 ****_CW_Snow **** **** **** **** **** **** **** **** +11327 ****_CW_Clear **** **** **** **** **** **** **** **** +11328 ****_Mass_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +11329 ****_Mass_Contagion **** **** **** **** **** **** **** **** +11330 ****_Mass_Eagle_Splendor **** **** **** **** **** **** **** **** +11331 ****_Energy_Immunity **** **** **** **** **** **** **** **** +11332 ****_EI_Acid **** **** **** **** **** **** **** **** +11333 ****_EI_Cold **** **** **** **** **** **** **** **** +11334 ****_EI_Elec **** **** **** **** **** **** **** **** +11335 ****_EI_Fire **** **** **** **** **** **** **** **** +11336 ****_EI_Sonic **** **** **** **** **** **** **** **** +11337 ****_Eyebite **** **** **** **** **** **** **** **** +11338 ****_Flesh_to_stone **** **** **** **** **** **** **** **** +11339 ****_Mass_Foxs_Cunning **** **** **** **** **** **** **** **** +11340 ****_Greater_Stoneskin **** **** **** **** **** **** **** **** +11341 ****_Legend_Lore **** **** **** **** **** **** **** **** +11342 ****_Mass_Owls_Wisdom **** **** **** **** **** **** **** **** +11343 ****_Planar_Binding **** **** **** **** **** **** **** **** +11344 ****_Summon_Creature_VI **** **** **** **** **** **** **** **** +11345 ****_True_Seeing **** **** **** **** **** **** **** **** +11346 ****_Repulsion **** **** **** **** **** **** **** **** +11347 ****_Superior_Resistance **** **** **** **** **** **** **** **** +11348 ****_Tensers_Transformation **** **** **** **** **** **** **** **** +11349 ****_Creeping_Doom **** **** **** **** **** **** **** **** +11350 ****_Eternal_Charm_Monster **** **** **** **** **** **** **** **** +11351 ****_Finger_of_Death **** **** **** **** **** **** **** **** +11352 ****_Insanity **** **** **** **** **** **** **** **** +11353 ****_Sequester **** **** **** **** **** **** **** **** +11354 ****_Summon_Creature_VII **** **** **** **** **** **** **** **** +11355 ****_Summon7Air **** **** **** **** **** **** **** **** +11356 ****_Summon7Earth **** **** **** **** **** **** **** **** +11357 ****_Summon7Fire **** **** **** **** **** **** **** **** +11358 ****_Summon7Water **** **** **** **** **** **** **** **** +11359 ****_TransportViaPlants_RadialMaster **** **** **** **** **** **** **** **** +11360 ****_TransportViaPlants_SelfOnly **** **** **** **** **** **** **** **** +11361 ****_TransportViaPlants_Party **** **** **** **** **** **** **** **** +11362 ****_DiscernLocation **** **** **** **** **** **** **** **** +11363 ****_Horrid_Wilting **** **** **** **** **** **** **** **** +11364 ****_Protection_from_Spells **** **** **** **** **** **** **** **** +11365 ****_Greater_Planar_Binding **** **** **** **** **** **** **** **** +11366 ****_Greater_Wall_of_Dispel_Magic **** **** **** **** **** **** **** **** +11367 ****_Shadow_Shield **** **** **** **** **** **** **** **** +11368 ****_Summon_Creature_VIII **** **** **** **** **** **** **** **** +11369 ****_Summon8Air **** **** **** **** **** **** **** **** +11370 ****_Summon8Earth **** **** **** **** **** **** **** **** +11371 ****_Summon8Fire **** **** **** **** **** **** **** **** +11372 ****_Summon8Water **** **** **** **** **** **** **** **** +11373 ****_Earthquake **** **** **** **** **** **** **** **** +11374 ****_Foresight **** **** **** **** **** **** **** **** +11375 ****_Gate **** **** **** **** **** **** **** **** +11376 ****_Mystic_Barrier **** **** **** **** **** **** **** **** +11377 ****_Shapechange **** **** **** **** **** **** **** **** +11378 ****_Shapechange_RED_DRAGON **** **** **** **** **** **** **** **** +11379 ****_Shapechange_FIRE_GIANT **** **** **** **** **** **** **** **** +11380 ****_Shapechange_BALOR **** **** **** **** **** **** **** **** +11381 ****_Shapechange_DEATH_SLAAD **** **** **** **** **** **** **** **** +11382 ****_Shapechange_IRON_GOLEM **** **** **** **** **** **** **** **** +11383 ****_Summon_Creature_IX **** **** **** **** **** **** **** **** +11384 ****_Summon9Air **** **** **** **** **** **** **** **** +11385 ****_Summon9Earth **** **** **** **** **** **** **** **** +11386 ****_Summon9Fire **** **** **** **** **** **** **** **** +11387 ****_Summon9Water **** **** **** **** **** **** **** **** +11388 ****_Wail_of_the_Banshee **** **** **** **** **** **** **** **** +11389 ****_Weird **** **** **** **** **** **** **** **** +11390 OAShaman_Cure_Minor_Wounds **** **** **** **** **** **** **** **** +11391 OAShaman_Quickened_Cure_Minor_Wounds **** **** **** **** **** **** **** **** +11392 OAShaman_Silent_Cure_Minor_Wounds **** **** **** **** **** **** **** **** +11393 OAShaman_Still_Cure_Minor_Wounds **** **** **** **** **** **** **** **** +11394 OAShaman_Inflict_Minor_Wounds **** **** **** **** **** **** **** **** +11395 OAShaman_Quickened_Inflict_Minor_Wounds **** **** **** **** **** **** **** **** +11396 OAShaman_Silent_Inflict_Minor_Wounds **** **** **** **** **** **** **** **** +11397 OAShaman_Still_Inflict_Minor_Wounds **** **** **** **** **** **** **** **** +11398 OAShaman_Light **** **** **** **** **** **** **** **** +11399 OAShaman_Exteneded_Light **** **** **** **** **** **** **** **** +11400 OAShaman_Quickened_Light **** **** **** **** **** **** **** **** +11401 OAShaman_Silent_Light **** **** **** **** **** **** **** **** +11402 OAShaman_Read_Magic **** **** **** **** **** **** **** **** +11403 OAShaman_Quickened_Read_Magic **** **** **** **** **** **** **** **** +11404 OAShaman_Silent_Read_Magic **** **** **** **** **** **** **** **** +11405 OAShaman_Still_Read_Magic **** **** **** **** **** **** **** **** +11406 OAShaman_Resistance **** **** **** **** **** **** **** **** +11407 OAShaman_Exteneded_Resistance **** **** **** **** **** **** **** **** +11408 OAShaman_Quickened_Resistance **** **** **** **** **** **** **** **** +11409 OAShaman_Silent_Resistance **** **** **** **** **** **** **** **** +11410 OAShaman_Still_Resistance **** **** **** **** **** **** **** **** +11411 OAShaman_Virtue **** **** **** **** **** **** **** **** +11412 OAShaman_Exteneded_Virtue **** **** **** **** **** **** **** **** +11413 OAShaman_Quickened_Virtue **** **** **** **** **** **** **** **** +11414 OAShaman_Silent_Virtue **** **** **** **** **** **** **** **** +11415 OAShaman_Still_Virtue **** **** **** **** **** **** **** **** +11416 OAShaman_Bane **** **** **** **** **** **** **** **** +11417 OAShaman_Exteneded_Bane **** **** **** **** **** **** **** **** +11418 OAShaman_Quickened_Bane **** **** **** **** **** **** **** **** +11419 OAShaman_Silent_Bane **** **** **** **** **** **** **** **** +11420 OAShaman_Still_Bane **** **** **** **** **** **** **** **** +11421 OAShaman_Bless **** **** **** **** **** **** **** **** +11422 OAShaman_Exteneded_Bless **** **** **** **** **** **** **** **** +11423 OAShaman_Quickened_Bless **** **** **** **** **** **** **** **** +11424 OAShaman_Silent_Bless **** **** **** **** **** **** **** **** +11425 OAShaman_Still_Bless **** **** **** **** **** **** **** **** +11426 OAShaman_Bless_Water **** **** **** **** **** **** **** **** +11427 OAShaman_Quickened_Bless_Water **** **** **** **** **** **** **** **** +11428 OAShaman_Silent_Bless_Water **** **** **** **** **** **** **** **** +11429 OAShaman_Still_Bless_Water **** **** **** **** **** **** **** **** +11430 OAShaman_Cure_Light_Wounds **** **** **** **** **** **** **** **** +11431 OAShaman_Empowered_Cure_Light_Wounds **** **** **** **** **** **** **** **** +11432 OAShaman_Maximized_Cure_Light_Wounds **** **** **** **** **** **** **** **** +11433 OAShaman_Quickened_Cure_Light_Wounds **** **** **** **** **** **** **** **** +11434 OAShaman_Silent_Cure_Light_Wounds **** **** **** **** **** **** **** **** +11435 OAShaman_Still_Cure_Light_Wounds **** **** **** **** **** **** **** **** +11436 OAShaman_Curse_Water **** **** **** **** **** **** **** **** +11437 OAShaman_Quickened_Curse_Water **** **** **** **** **** **** **** **** +11438 OAShaman_Silent_Curse_Water **** **** **** **** **** **** **** **** +11439 OAShaman_Still_Curse_Water **** **** **** **** **** **** **** **** +11440 OAShaman_Detect_Chaos **** **** **** **** **** **** **** **** +11441 OAShaman_Exteneded_Detect_Chaos **** **** **** **** **** **** **** **** +11442 OAShaman_Quickened_Detect_Chaos **** **** **** **** **** **** **** **** +11443 OAShaman_Silent_Detect_Chaos **** **** **** **** **** **** **** **** +11444 OAShaman_Still_Detect_Chaos **** **** **** **** **** **** **** **** +11445 OAShaman_Detect_Evil **** **** **** **** **** **** **** **** +11446 OAShaman_Exteneded_Detect_Evil **** **** **** **** **** **** **** **** +11447 OAShaman_Quickened_Detect_Evil **** **** **** **** **** **** **** **** +11448 OAShaman_Silent_Detect_Evil **** **** **** **** **** **** **** **** +11449 OAShaman_Still_Detect_Evil **** **** **** **** **** **** **** **** +11450 OAShaman_Detect_Good **** **** **** **** **** **** **** **** +11451 OAShaman_Exteneded_Detect_Good **** **** **** **** **** **** **** **** +11452 OAShaman_Quickened_Detect_Good **** **** **** **** **** **** **** **** +11453 OAShaman_Silent_Detect_Good **** **** **** **** **** **** **** **** +11454 OAShaman_Still_Detect_Good **** **** **** **** **** **** **** **** +11455 OAShaman_Detect_Law **** **** **** **** **** **** **** **** +11456 OAShaman_Exteneded_Detect_Law **** **** **** **** **** **** **** **** +11457 OAShaman_Quickened_Detect_Law **** **** **** **** **** **** **** **** +11458 OAShaman_Silent_Detect_Law **** **** **** **** **** **** **** **** +11459 OAShaman_Still_Detect_Law **** **** **** **** **** **** **** **** +11460 OAShaman_DETECT_UNDEAD **** **** **** **** **** **** **** **** +11461 OAShaman_Exteneded_DETECT_UNDEAD **** **** **** **** **** **** **** **** +11462 OAShaman_Quickened_DETECT_UNDEAD **** **** **** **** **** **** **** **** +11463 OAShaman_Silent_DETECT_UNDEAD **** **** **** **** **** **** **** **** +11464 OAShaman_Still_DETECT_UNDEAD **** **** **** **** **** **** **** **** +11465 OAShaman_DIVINE_INSPIRATION **** **** **** **** **** **** **** **** +11466 OAShaman_Exteneded_DIVINE_INSPIRATION **** **** **** **** **** **** **** **** +11467 OAShaman_Quickened_DIVINE_INSPIRATION **** **** **** **** **** **** **** **** +11468 OAShaman_Doom **** **** **** **** **** **** **** **** +11469 OAShaman_Exteneded_Doom **** **** **** **** **** **** **** **** +11470 OAShaman_Quickened_Doom **** **** **** **** **** **** **** **** +11471 OAShaman_Silent_Doom **** **** **** **** **** **** **** **** +11472 OAShaman_Still_Doom **** **** **** **** **** **** **** **** +11473 OAShaman_Endure_Elements **** **** **** **** **** **** **** **** +11474 OAShaman_Exteneded_Endure_Elements **** **** **** **** **** **** **** **** +11475 OAShaman_Quickened_Endure_Elements **** **** **** **** **** **** **** **** +11476 OAShaman_Silent_Endure_Elements **** **** **** **** **** **** **** **** +11477 OAShaman_Still_Endure_Elements **** **** **** **** **** **** **** **** +11478 OAShaman_Entropic_Shield **** **** **** **** **** **** **** **** +11479 OAShaman_Exteneded_Entropic_Shield **** **** **** **** **** **** **** **** +11480 OAShaman_Quickened_Entropic_Shield **** **** **** **** **** **** **** **** +11481 OAShaman_Silent_Entropic_Shield **** **** **** **** **** **** **** **** +11482 OAShaman_Still_Entropic_Shield **** **** **** **** **** **** **** **** +11483 OAShaman_HideFromUndead **** **** **** **** **** **** **** **** +11484 OAShaman_Exteneded_HideFromUndead **** **** **** **** **** **** **** **** +11485 OAShaman_Quickened_HideFromUndead **** **** **** **** **** **** **** **** +11486 OAShaman_Still_HideFromUndead **** **** **** **** **** **** **** **** +11487 OAShaman_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +11488 OAShaman_Empowered_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +11489 OAShaman_Maximized_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +11490 OAShaman_Quickened_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +11491 OAShaman_Silent_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +11492 OAShaman_Still_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +11493 OAShaman_Obscuring_Mist **** **** **** **** **** **** **** **** +11494 OAShaman_Exteneded_Obscuring_Mist **** **** **** **** **** **** **** **** +11495 OAShaman_Quickened_Obscuring_Mist **** **** **** **** **** **** **** **** +11496 OAShaman_Silent_Obscuring_Mist **** **** **** **** **** **** **** **** +11497 OAShaman_Still_Obscuring_Mist **** **** **** **** **** **** **** **** +11498 OAShaman_Protection_from_Chaos **** **** **** **** **** **** **** **** +11499 OAShaman_Exteneded_Protection_from_Chaos **** **** **** **** **** **** **** **** +11500 OAShaman_Quickened_Protection_from_Chaos **** **** **** **** **** **** **** **** +11501 OAShaman_Silent_Protection_from_Chaos **** **** **** **** **** **** **** **** +11502 OAShaman_Still_Protection_from_Chaos **** **** **** **** **** **** **** **** +11503 OAShaman_Protection_from_Evil **** **** **** **** **** **** **** **** +11504 OAShaman_Exteneded_Protection_from_Evil **** **** **** **** **** **** **** **** +11505 OAShaman_Quickened_Protection_from_Evil **** **** **** **** **** **** **** **** +11506 OAShaman_Silent_Protection_from_Evil **** **** **** **** **** **** **** **** +11507 OAShaman_Still_Protection_from_Evil **** **** **** **** **** **** **** **** +11508 OAShaman_Protection_from_Good **** **** **** **** **** **** **** **** +11509 OAShaman_Exteneded_Protection_from_Good **** **** **** **** **** **** **** **** +11510 OAShaman_Quickened_Protection_from_Good **** **** **** **** **** **** **** **** +11511 OAShaman_Silent_Protection_from_Good **** **** **** **** **** **** **** **** +11512 OAShaman_Still_Protection_from_Good **** **** **** **** **** **** **** **** +11513 OAShaman_Protection_from_Law **** **** **** **** **** **** **** **** +11514 OAShaman_Exteneded_Protection_from_Law **** **** **** **** **** **** **** **** +11515 OAShaman_Quickened_Protection_from_Law **** **** **** **** **** **** **** **** +11516 OAShaman_Silent_Protection_from_Law **** **** **** **** **** **** **** **** +11517 OAShaman_Still_Protection_from_Law **** **** **** **** **** **** **** **** +11518 OAShaman_SEETHING_EYEBANE **** **** **** **** **** **** **** **** +11519 OAShaman_Quickened_SEETHING_EYEBANE **** **** **** **** **** **** **** **** +11520 OAShaman_Silent_SEETHING_EYEBANE **** **** **** **** **** **** **** **** +11521 OAShaman_Still_SEETHING_EYEBANE **** **** **** **** **** **** **** **** +11522 OAShaman_Shield_of_Faith **** **** **** **** **** **** **** **** +11523 OAShaman_Exteneded_Shield_of_Faith **** **** **** **** **** **** **** **** +11524 OAShaman_Quickened_Shield_of_Faith **** **** **** **** **** **** **** **** +11525 OAShaman_Silent_Shield_of_Faith **** **** **** **** **** **** **** **** +11526 OAShaman_Still_Shield_of_Faith **** **** **** **** **** **** **** **** +11527 OAShaman_Summon_Creature_I **** **** **** **** **** **** **** **** +11528 OAShaman_Exteneded_Summon_Creature_I **** **** **** **** **** **** **** **** +11529 OAShaman_Quickened_Summon_Creature_I **** **** **** **** **** **** **** **** +11530 OAShaman_Silent_Summon_Creature_I **** **** **** **** **** **** **** **** +11531 OAShaman_Still_Summon_Creature_I **** **** **** **** **** **** **** **** +11532 OAShaman_TWILIGHT_LUCK **** **** **** **** **** **** **** **** +11533 OAShaman_Exteneded_TWILIGHT_LUCK **** **** **** **** **** **** **** **** +11534 OAShaman_Silent_TWILIGHT_LUCK **** **** **** **** **** **** **** **** +11535 OAShaman_Aid **** **** **** **** **** **** **** **** +11536 OAShaman_Empowered_Aid **** **** **** **** **** **** **** **** +11537 OAShaman_Exteneded_Aid **** **** **** **** **** **** **** **** +11538 OAShaman_Maximized_Aid **** **** **** **** **** **** **** **** +11539 OAShaman_Quickened_Aid **** **** **** **** **** **** **** **** +11540 OAShaman_Silent_Aid **** **** **** **** **** **** **** **** +11541 OAShaman_Still_Aid **** **** **** **** **** **** **** **** +11542 OAShaman_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +11543 OAShaman_Empowered_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +11544 OAShaman_Maximized_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +11545 OAShaman_Quickened_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +11546 OAShaman_Silent_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +11547 OAShaman_Still_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +11548 OAShaman_Bulls_Strength **** **** **** **** **** **** **** **** +11549 OAShaman_Empowered_Bulls_Strength **** **** **** **** **** **** **** **** +11550 OAShaman_Exteneded_Bulls_Strength **** **** **** **** **** **** **** **** +11551 OAShaman_Maximized_Bulls_Strength **** **** **** **** **** **** **** **** +11552 OAShaman_Quickened_Bulls_Strength **** **** **** **** **** **** **** **** +11553 OAShaman_Silent_Bulls_Strength **** **** **** **** **** **** **** **** +11554 OAShaman_Still_Bulls_Strength **** **** **** **** **** **** **** **** +11555 OAShaman_Calm_Emotions **** **** **** **** **** **** **** **** +11556 OAShaman_Exteneded_Calm_Emotions **** **** **** **** **** **** **** **** +11557 OAShaman_Quickened_Calm_Emotions **** **** **** **** **** **** **** **** +11558 OAShaman_Silent_Calm_Emotions **** **** **** **** **** **** **** **** +11559 OAShaman_Still_Calm_Emotions **** **** **** **** **** **** **** **** +11560 OAShaman_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +11561 OAShaman_Empowered_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +11562 OAShaman_Maximized_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +11563 OAShaman_Quickened_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +11564 OAShaman_Silent_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +11565 OAShaman_Still_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +11566 OAShaman_Ghoul_Touch **** **** **** **** **** **** **** **** +11567 OAShaman_Exteneded_Ghoul_Touch **** **** **** **** **** **** **** **** +11568 OAShaman_Quickened_Ghoul_Touch **** **** **** **** **** **** **** **** +11569 OAShaman_Silent_Ghoul_Touch **** **** **** **** **** **** **** **** +11570 OAShaman_Still_Ghoul_Touch **** **** **** **** **** **** **** **** +11571 OAShaman_Hold_Person **** **** **** **** **** **** **** **** +11572 OAShaman_Exteneded_Hold_Person **** **** **** **** **** **** **** **** +11573 OAShaman_Quickened_Hold_Person **** **** **** **** **** **** **** **** +11574 OAShaman_Silent_Hold_Person **** **** **** **** **** **** **** **** +11575 OAShaman_Still_Hold_Person **** **** **** **** **** **** **** **** +11576 OAShaman_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +11577 OAShaman_Empowered_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +11578 OAShaman_Maximized_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +11579 OAShaman_Quickened_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +11580 OAShaman_Silent_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +11581 OAShaman_Still_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +11582 OAShaman_LAHMS_FINGER_DARTS **** **** **** **** **** **** **** **** +11583 OAShaman_Quickened_LAHMS_FINGER_DARTS **** **** **** **** **** **** **** **** +11584 OAShaman_Silent_LAHMS_FINGER_DARTS **** **** **** **** **** **** **** **** +11585 OAShaman_Still_LAHMS_FINGER_DARTS **** **** **** **** **** **** **** **** +11586 OAShaman_Lesser_Restoration **** **** **** **** **** **** **** **** +11587 OAShaman_Quickened_Lesser_Restoration **** **** **** **** **** **** **** **** +11588 OAShaman_Silent_Lesser_Restoration **** **** **** **** **** **** **** **** +11589 OAShaman_Still_Lesser_Restoration **** **** **** **** **** **** **** **** +11590 OAShaman_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +11591 OAShaman_Exteneded_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +11592 OAShaman_Quickened_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +11593 OAShaman_Remove_Paralysis **** **** **** **** **** **** **** **** +11594 OAShaman_Quickened_Remove_Paralysis **** **** **** **** **** **** **** **** +11595 OAShaman_Silent_Remove_Paralysis **** **** **** **** **** **** **** **** +11596 OAShaman_Still_Remove_Paralysis **** **** **** **** **** **** **** **** +11597 OAShaman_Summon_Creature_II **** **** **** **** **** **** **** **** +11598 OAShaman_Exteneded_Summon_Creature_II **** **** **** **** **** **** **** **** +11599 OAShaman_Quickened_Summon_Creature_II **** **** **** **** **** **** **** **** +11600 OAShaman_Silent_Summon_Creature_II **** **** **** **** **** **** **** **** +11601 OAShaman_Still_Summon_Creature_II **** **** **** **** **** **** **** **** +11602 OAShaman_Bestow_Curse **** **** **** **** **** **** **** **** +11603 OAShaman_Quickened_Bestow_Curse **** **** **** **** **** **** **** **** +11604 OAShaman_Silent_Bestow_Curse **** **** **** **** **** **** **** **** +11605 OAShaman_Still_Bestow_Curse **** **** **** **** **** **** **** **** +11606 OAShaman_Blindness_and_Deafness **** **** **** **** **** **** **** **** +11607 OAShaman_Exteneded_Blindness_and_Deafness **** **** **** **** **** **** **** **** +11608 OAShaman_Quickened_Blindness_and_Deafness **** **** **** **** **** **** **** **** +11609 OAShaman_Silent_Blindness_and_Deafness **** **** **** **** **** **** **** **** +11610 OAShaman_BRILLIANT_EMANATION **** **** **** **** **** **** **** **** +11611 OAShaman_Exteneded_BRILLIANT_EMANATION **** **** **** **** **** **** **** **** +11612 OAShaman_Quickened_BRILLIANT_EMANATION **** **** **** **** **** **** **** **** +11613 OAShaman_Contagion **** **** **** **** **** **** **** **** +11614 OAShaman_Quickened_Contagion **** **** **** **** **** **** **** **** +11615 OAShaman_Silent_Contagion **** **** **** **** **** **** **** **** +11616 OAShaman_Still_Contagion **** **** **** **** **** **** **** **** +11617 OAShaman_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +11618 OAShaman_Empowered_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +11619 OAShaman_Maximized_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +11620 OAShaman_Quickened_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +11621 OAShaman_Silent_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +11622 OAShaman_Still_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +11623 OAShaman_Dispel_Magic **** **** **** **** **** **** **** **** +11624 OAShaman_Quickened_Dispel_Magic **** **** **** **** **** **** **** **** +11625 OAShaman_Silent_Dispel_Magic **** **** **** **** **** **** **** **** +11626 OAShaman_Still_Dispel_Magic **** **** **** **** **** **** **** **** +11627 OAShaman_HAMMER_OF_RIGHTEOUSNESS **** **** **** **** **** **** **** **** +11628 OAShaman_Empowered_HAMMER_OF_RIGHTEOUSNESS **** **** **** **** **** **** **** **** +11629 OAShaman_Maximized_HAMMER_OF_RIGHTEOUSNESS **** **** **** **** **** **** **** **** +11630 OAShaman_Quickened_HAMMER_OF_RIGHTEOUSNESS **** **** **** **** **** **** **** **** +11631 OAShaman_Silent_HAMMER_OF_RIGHTEOUSNESS **** **** **** **** **** **** **** **** +11632 OAShaman_Still_HAMMER_OF_RIGHTEOUSNESS **** **** **** **** **** **** **** **** +11633 OAShaman_Inflict_Serious_Wounds **** **** **** **** **** **** **** **** +11634 OAShaman_Empowered_Inflict_Serious_Wounds **** **** **** **** **** **** **** **** +11635 OAShaman_Maximized_Inflict_Serious_Wounds **** **** **** **** **** **** **** **** +11636 OAShaman_Quickened_Inflict_Serious_Wounds **** **** **** **** **** **** **** **** +11637 OAShaman_Silent_Inflict_Serious_Wounds **** **** **** **** **** **** **** **** +11638 OAShaman_Still_Inflict_Serious_Wounds **** **** **** **** **** **** **** **** +11639 OAShaman_LocateObject **** **** **** **** **** **** **** **** +11640 OAShaman_Exteneded_LocateObject **** **** **** **** **** **** **** **** +11641 OAShaman_Quickened_LocateObject **** **** **** **** **** **** **** **** +11642 OAShaman_Silent_LocateObject **** **** **** **** **** **** **** **** +11643 OAShaman_Still_LocateObject **** **** **** **** **** **** **** **** +11644 OAShaman_Magic_Circle_against_Chaos **** **** **** **** **** **** **** **** +11645 OAShaman_Exteneded_Magic_Circle_against_Chaos **** **** **** **** **** **** **** **** +11646 OAShaman_Quickened_Magic_Circle_against_Chaos **** **** **** **** **** **** **** **** +11647 OAShaman_Silent_Magic_Circle_against_Chaos **** **** **** **** **** **** **** **** +11648 OAShaman_Still_Magic_Circle_against_Chaos **** **** **** **** **** **** **** **** +11649 OAShaman_Magic_Circle_against_Evil **** **** **** **** **** **** **** **** +11650 OAShaman_Exteneded_Magic_Circle_against_Evil **** **** **** **** **** **** **** **** +11651 OAShaman_Quickened_Magic_Circle_against_Evil **** **** **** **** **** **** **** **** +11652 OAShaman_Silent_Magic_Circle_against_Evil **** **** **** **** **** **** **** **** +11653 OAShaman_Still_Magic_Circle_against_Evil **** **** **** **** **** **** **** **** +11654 OAShaman_Magic_Circle_against_Good **** **** **** **** **** **** **** **** +11655 OAShaman_Exteneded_Magic_Circle_against_Good **** **** **** **** **** **** **** **** +11656 OAShaman_Quickened_Magic_Circle_against_Good **** **** **** **** **** **** **** **** +11657 OAShaman_Silent_Magic_Circle_against_Good **** **** **** **** **** **** **** **** +11658 OAShaman_Still_Magic_Circle_against_Good **** **** **** **** **** **** **** **** +11659 OAShaman_Magic_Circle_against_Law **** **** **** **** **** **** **** **** +11660 OAShaman_Exteneded_Magic_Circle_against_Law **** **** **** **** **** **** **** **** +11661 OAShaman_Quickened_Magic_Circle_against_Law **** **** **** **** **** **** **** **** +11662 OAShaman_Silent_Magic_Circle_against_Law **** **** **** **** **** **** **** **** +11663 OAShaman_Still_Magic_Circle_against_Law **** **** **** **** **** **** **** **** +11664 OAShaman_Magic_Vestment **** **** **** **** **** **** **** **** +11665 OAShaman_Exteneded_Magic_Vestment **** **** **** **** **** **** **** **** +11666 OAShaman_Quickened_Magic_Vestment **** **** **** **** **** **** **** **** +11667 OAShaman_Silent_Magic_Vestment **** **** **** **** **** **** **** **** +11668 OAShaman_Still_Magic_Vestment **** **** **** **** **** **** **** **** +11669 OAShaman_Prayer **** **** **** **** **** **** **** **** +11670 OAShaman_Exteneded_Prayer **** **** **** **** **** **** **** **** +11671 OAShaman_Quickened_Prayer **** **** **** **** **** **** **** **** +11672 OAShaman_Silent_Prayer **** **** **** **** **** **** **** **** +11673 OAShaman_Still_Prayer **** **** **** **** **** **** **** **** +11674 OAShaman_Protection_from_Elements **** **** **** **** **** **** **** **** +11675 OAShaman_Exteneded_Protection_from_Elements **** **** **** **** **** **** **** **** +11676 OAShaman_Quickened_Protection_from_Elements **** **** **** **** **** **** **** **** +11677 OAShaman_Silent_Protection_from_Elements **** **** **** **** **** **** **** **** +11678 OAShaman_Still_Protection_from_Elements **** **** **** **** **** **** **** **** +11679 OAShaman_RED_FESTER **** **** **** **** **** **** **** **** +11680 OAShaman_Quickened_RED_FESTER **** **** **** **** **** **** **** **** +11681 OAShaman_Silent_RED_FESTER **** **** **** **** **** **** **** **** +11682 OAShaman_Still_RED_FESTER **** **** **** **** **** **** **** **** +11683 OAShaman_Remove_Blindness_and_Deafness **** **** **** **** **** **** **** **** +11684 OAShaman_Quickened_Remove_Blindness_and_Deafness **** **** **** **** **** **** **** **** +11685 OAShaman_Silent_Remove_Blindness_and_Deafness **** **** **** **** **** **** **** **** +11686 OAShaman_Still_Remove_Blindness_and_Deafness **** **** **** **** **** **** **** **** +11687 OAShaman_Remove_Curse **** **** **** **** **** **** **** **** +11688 OAShaman_Quickened_Remove_Curse **** **** **** **** **** **** **** **** +11689 OAShaman_Silent_Remove_Curse **** **** **** **** **** **** **** **** +11690 OAShaman_Still_Remove_Curse **** **** **** **** **** **** **** **** +11691 OAShaman_Remove_Disease **** **** **** **** **** **** **** **** +11692 OAShaman_Quickened_Remove_Disease **** **** **** **** **** **** **** **** +11693 OAShaman_Silent_Remove_Disease **** **** **** **** **** **** **** **** +11694 OAShaman_Still_Remove_Disease **** **** **** **** **** **** **** **** +11695 OAShaman_ROTTING_CURSE_OF_URFESTRA **** **** **** **** **** **** **** **** +11696 OAShaman_Empowered_ROTTING_CURSE_OF_URFESTRA **** **** **** **** **** **** **** **** +11697 OAShaman_Maximized_ROTTING_CURSE_OF_URFESTRA **** **** **** **** **** **** **** **** +11698 OAShaman_Quickened_ROTTING_CURSE_OF_URFESTRA **** **** **** **** **** **** **** **** +11699 OAShaman_Silent_ROTTING_CURSE_OF_URFESTRA **** **** **** **** **** **** **** **** +11700 OAShaman_Still_ROTTING_CURSE_OF_URFESTRA **** **** **** **** **** **** **** **** +11701 OAShaman_Summon_Creature_III **** **** **** **** **** **** **** **** +11702 OAShaman_Exteneded_Summon_Creature_III **** **** **** **** **** **** **** **** +11703 OAShaman_Quickened_Summon_Creature_III **** **** **** **** **** **** **** **** +11704 OAShaman_Silent_Summon_Creature_III **** **** **** **** **** **** **** **** +11705 OAShaman_Still_Summon_Creature_III **** **** **** **** **** **** **** **** +11706 OAShaman_TOUCH_OF_JUIBLEX **** **** **** **** **** **** **** **** +11707 OAShaman_Quickened_TOUCH_OF_JUIBLEX **** **** **** **** **** **** **** **** +11708 OAShaman_Silent_TOUCH_OF_JUIBLEX **** **** **** **** **** **** **** **** +11709 OAShaman_Still_TOUCH_OF_JUIBLEX **** **** **** **** **** **** **** **** +11710 OAShaman_ABSORB_STRENGTH **** **** **** **** **** **** **** **** +11711 OAShaman_Exteneded_ABSORB_STRENGTH **** **** **** **** **** **** **** **** +11712 OAShaman_Quickened_ABSORB_STRENGTH **** **** **** **** **** **** **** **** +11713 OAShaman_Silent_ABSORB_STRENGTH **** **** **** **** **** **** **** **** +11714 OAShaman_Still_ABSORB_STRENGTH **** **** **** **** **** **** **** **** +11715 OAShaman_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +11716 OAShaman_Empowered_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +11717 OAShaman_Maximized_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +11718 OAShaman_Quickened_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +11719 OAShaman_Silent_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +11720 OAShaman_Still_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +11721 OAShaman_Hammer_of_the_Gods **** **** **** **** **** **** **** **** +11722 OAShaman_Empowered_Hammer_of_the_Gods **** **** **** **** **** **** **** **** +11723 OAShaman_Maximized_Hammer_of_the_Gods **** **** **** **** **** **** **** **** +11724 OAShaman_Quickened_Hammer_of_the_Gods **** **** **** **** **** **** **** **** +11725 OAShaman_Silent_Hammer_of_the_Gods **** **** **** **** **** **** **** **** +11726 OAShaman_Still_Hammer_of_the_Gods **** **** **** **** **** **** **** **** +11727 OAShaman_DIAMOND_SPRAY **** **** **** **** **** **** **** **** +11728 OAShaman_Empowered_DIAMOND_SPRAY **** **** **** **** **** **** **** **** +11729 OAShaman_Exteneded_DIAMOND_SPRAY **** **** **** **** **** **** **** **** +11730 OAShaman_Maximized_DIAMOND_SPRAY **** **** **** **** **** **** **** **** +11731 OAShaman_Quickened_DIAMOND_SPRAY **** **** **** **** **** **** **** **** +11732 OAShaman_Silent_DIAMOND_SPRAY **** **** **** **** **** **** **** **** +11733 OAShaman_Still_DIAMOND_SPRAY **** **** **** **** **** **** **** **** +11734 OAShaman_Dismissal **** **** **** **** **** **** **** **** +11735 OAShaman_Quickened_Dismissal **** **** **** **** **** **** **** **** +11736 OAShaman_Silent_Dismissal **** **** **** **** **** **** **** **** +11737 OAShaman_Still_Dismissal **** **** **** **** **** **** **** **** +11738 OAShaman_GREATER_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +11739 OAShaman_Exteneded_GREATER_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +11740 OAShaman_Quickened_GREATER_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +11741 OAShaman_Inflict_Critical_Wounds **** **** **** **** **** **** **** **** +11742 OAShaman_Empowered_Inflict_Critical_Wounds **** **** **** **** **** **** **** **** +11743 OAShaman_Maximized_Inflict_Critical_Wounds **** **** **** **** **** **** **** **** +11744 OAShaman_Quickened_Inflict_Critical_Wounds **** **** **** **** **** **** **** **** +11745 OAShaman_Silent_Inflict_Critical_Wounds **** **** **** **** **** **** **** **** +11746 OAShaman_Still_Inflict_Critical_Wounds **** **** **** **** **** **** **** **** +11747 OAShaman_Lesser_Planar_Ally **** **** **** **** **** **** **** **** +11748 OAShaman_Exteneded_Lesser_Planar_Ally **** **** **** **** **** **** **** **** +11749 OAShaman_Quickened_Lesser_Planar_Ally **** **** **** **** **** **** **** **** +11750 OAShaman_Silent_Lesser_Planar_Ally **** **** **** **** **** **** **** **** +11751 OAShaman_Still_Lesser_Planar_Ally **** **** **** **** **** **** **** **** +11752 OAShaman_Neutralize_Poison **** **** **** **** **** **** **** **** +11753 OAShaman_Quickened_Neutralize_Poison **** **** **** **** **** **** **** **** +11754 OAShaman_Silent_Neutralize_Poison **** **** **** **** **** **** **** **** +11755 OAShaman_Still_Neutralize_Poison **** **** **** **** **** **** **** **** +11756 OAShaman_Polymorph_Self **** **** **** **** **** **** **** **** +11757 OAShaman_Polymorph_GIANT_SPIDER **** **** **** **** **** **** **** **** +11758 OAShaman_Polymorph_TROLL **** **** **** **** **** **** **** **** +11759 OAShaman_Polymorph_UMBER_HULK **** **** **** **** **** **** **** **** +11760 OAShaman_Polymorph_PIXIE **** **** **** **** **** **** **** **** +11761 OAShaman_Polymorph_ZOMBIE **** **** **** **** **** **** **** **** +11762 OAShaman_Exteneded_Polymorph_Self **** **** **** **** **** **** **** **** +11763 OAShaman_Exteneded_Polymorph_GIANT_SPIDER **** **** **** **** **** **** **** **** +11764 OAShaman_Exteneded_Polymorph_TROLL **** **** **** **** **** **** **** **** +11765 OAShaman_Exteneded_Polymorph_UMBER_HULK **** **** **** **** **** **** **** **** +11766 OAShaman_Exteneded_Polymorph_PIXIE **** **** **** **** **** **** **** **** +11767 OAShaman_Exteneded_Polymorph_ZOMBIE **** **** **** **** **** **** **** **** +11768 OAShaman_Quickened_Polymorph_Self **** **** **** **** **** **** **** **** +11769 OAShaman_Quickened_Polymorph_GIANT_SPIDER **** **** **** **** **** **** **** **** +11770 OAShaman_Quickened_Polymorph_TROLL **** **** **** **** **** **** **** **** +11771 OAShaman_Quickened_Polymorph_UMBER_HULK **** **** **** **** **** **** **** **** +11772 OAShaman_Quickened_Polymorph_PIXIE **** **** **** **** **** **** **** **** +11773 OAShaman_Quickened_Polymorph_ZOMBIE **** **** **** **** **** **** **** **** +11774 OAShaman_Silent_Polymorph_Self **** **** **** **** **** **** **** **** +11775 OAShaman_Silent_Polymorph_GIANT_SPIDER **** **** **** **** **** **** **** **** +11776 OAShaman_Silent_Polymorph_TROLL **** **** **** **** **** **** **** **** +11777 OAShaman_Silent_Polymorph_UMBER_HULK **** **** **** **** **** **** **** **** +11778 OAShaman_Silent_Polymorph_PIXIE **** **** **** **** **** **** **** **** +11779 OAShaman_Silent_Polymorph_ZOMBIE **** **** **** **** **** **** **** **** +11780 OAShaman_Restoration **** **** **** **** **** **** **** **** +11781 OAShaman_Quickened_Restoration **** **** **** **** **** **** **** **** +11782 OAShaman_Silent_Restoration **** **** **** **** **** **** **** **** +11783 OAShaman_Still_Restoration **** **** **** **** **** **** **** **** +11784 OAShaman_Summon_Creature_IV **** **** **** **** **** **** **** **** +11785 OAShaman_Exteneded_Summon_Creature_IV **** **** **** **** **** **** **** **** +11786 OAShaman_Quickened_Summon_Creature_IV **** **** **** **** **** **** **** **** +11787 OAShaman_Silent_Summon_Creature_IV **** **** **** **** **** **** **** **** +11788 OAShaman_Still_Summon_Creature_IV **** **** **** **** **** **** **** **** +11789 OAShaman_SUNMANTLE **** **** **** **** **** **** **** **** +11790 OAShaman_Exteneded_SUNMANTLE **** **** **** **** **** **** **** **** +11791 OAShaman_Quickened_SUNMANTLE **** **** **** **** **** **** **** **** +11792 OAShaman_Still_SUNMANTLE **** **** **** **** **** **** **** **** +11793 OAShaman_BreakEnchantment **** **** **** **** **** **** **** **** +11794 OAShaman_Quickened_BreakEnchantment **** **** **** **** **** **** **** **** +11795 OAShaman_Silent_BreakEnchantment **** **** **** **** **** **** **** **** +11796 OAShaman_Still_BreakEnchantment **** **** **** **** **** **** **** **** +11797 OAShaman_Circle_of_Doom **** **** **** **** **** **** **** **** +11798 OAShaman_Empowered_Circle_of_Doom **** **** **** **** **** **** **** **** +11799 OAShaman_Maximized_Circle_of_Doom **** **** **** **** **** **** **** **** +11800 OAShaman_Quickened_Circle_of_Doom **** **** **** **** **** **** **** **** +11801 OAShaman_Silent_Circle_of_Doom **** **** **** **** **** **** **** **** +11802 OAShaman_Still_Circle_of_Doom **** **** **** **** **** **** **** **** +11803 OAShaman_CLAWS_OF_THE_BEBILITH **** **** **** **** **** **** **** **** +11804 OAShaman_Exteneded_CLAWS_OF_THE_BEBILITH **** **** **** **** **** **** **** **** +11805 OAShaman_Quickened_CLAWS_OF_THE_BEBILITH **** **** **** **** **** **** **** **** +11806 OAShaman_Silent_CLAWS_OF_THE_BEBILITH **** **** **** **** **** **** **** **** +11807 OAShaman_Still_CLAWS_OF_THE_BEBILITH **** **** **** **** **** **** **** **** +11808 OAShaman_Etherealness **** **** **** **** **** **** **** **** +11809 OAShaman_Exteneded_Etherealness **** **** **** **** **** **** **** **** +11810 OAShaman_Quickened_Etherealness **** **** **** **** **** **** **** **** +11811 OAShaman_Silent_Etherealness **** **** **** **** **** **** **** **** +11812 OAShaman_Still_Etherealness **** **** **** **** **** **** **** **** +11813 OAShaman_Healing_Circle **** **** **** **** **** **** **** **** +11814 OAShaman_Empowered_Healing_Circle **** **** **** **** **** **** **** **** +11815 OAShaman_Maximized_Healing_Circle **** **** **** **** **** **** **** **** +11816 OAShaman_Quickened_Healing_Circle **** **** **** **** **** **** **** **** +11817 OAShaman_Silent_Healing_Circle **** **** **** **** **** **** **** **** +11818 OAShaman_Still_Healing_Circle **** **** **** **** **** **** **** **** +11819 OAShaman_POWER_LEECH **** **** **** **** **** **** **** **** +11820 OAShaman_Exteneded_POWER_LEECH **** **** **** **** **** **** **** **** +11821 OAShaman_Quickened_POWER_LEECH **** **** **** **** **** **** **** **** +11822 OAShaman_Silent_POWER_LEECH **** **** **** **** **** **** **** **** +11823 OAShaman_Still_POWER_LEECH **** **** **** **** **** **** **** **** +11824 OAShaman_Raise_Dead **** **** **** **** **** **** **** **** +11825 OAShaman_Quickened_Raise_Dead **** **** **** **** **** **** **** **** +11826 OAShaman_Silent_Raise_Dead **** **** **** **** **** **** **** **** +11827 OAShaman_Still_Raise_Dead **** **** **** **** **** **** **** **** +11828 OAShaman_Scrying **** **** **** **** **** **** **** **** +11829 OAShaman_Exteneded_Scrying **** **** **** **** **** **** **** **** +11830 OAShaman_Quickened_Scrying **** **** **** **** **** **** **** **** +11831 OAShaman_Silent_Scrying **** **** **** **** **** **** **** **** +11832 OAShaman_Still_Scrying **** **** **** **** **** **** **** **** +11833 OAShaman_SICKEN_EVIL **** **** **** **** **** **** **** **** +11834 OAShaman_Exteneded_SICKEN_EVIL **** **** **** **** **** **** **** **** +11835 OAShaman_Quickened_SICKEN_EVIL **** **** **** **** **** **** **** **** +11836 OAShaman_Silent_SICKEN_EVIL **** **** **** **** **** **** **** **** +11837 OAShaman_Still_SICKEN_EVIL **** **** **** **** **** **** **** **** +11838 OAShaman_Slay_Living **** **** **** **** **** **** **** **** +11839 OAShaman_Empowered_Slay_Living **** **** **** **** **** **** **** **** +11840 OAShaman_Maximized_Slay_Living **** **** **** **** **** **** **** **** +11841 OAShaman_Quickened_Slay_Living **** **** **** **** **** **** **** **** +11842 OAShaman_Silent_Slay_Living **** **** **** **** **** **** **** **** +11843 OAShaman_Still_Slay_Living **** **** **** **** **** **** **** **** +11844 OAShaman_Summon_Creature_V **** **** **** **** **** **** **** **** +11845 OAShaman_Exteneded_Summon_Creature_V **** **** **** **** **** **** **** **** +11846 OAShaman_Quickened_Summon_Creature_V **** **** **** **** **** **** **** **** +11847 OAShaman_Silent_Summon_Creature_V **** **** **** **** **** **** **** **** +11848 OAShaman_Still_Summon_Creature_V **** **** **** **** **** **** **** **** +11849 OAShaman_True_Seeing **** **** **** **** **** **** **** **** +11850 OAShaman_Exteneded_True_Seeing **** **** **** **** **** **** **** **** +11851 OAShaman_Quickened_True_Seeing **** **** **** **** **** **** **** **** +11852 OAShaman_Silent_True_Seeing **** **** **** **** **** **** **** **** +11853 OAShaman_Still_True_Seeing **** **** **** **** **** **** **** **** +11854 OAShaman_Animate_Object **** **** **** **** **** **** **** **** +11855 OAShaman_Exteneded_Animate_Object **** **** **** **** **** **** **** **** +11856 OAShaman_Planar_Ally **** **** **** **** **** **** **** **** +11857 OAShaman_Exteneded_Planar_Ally **** **** **** **** **** **** **** **** +11858 OAShaman_Silent_Planar_Ally **** **** **** **** **** **** **** **** +11859 OAShaman_Still_Planar_Ally **** **** **** **** **** **** **** **** +11860 OAShaman_EXALTED_RAIMENT **** **** **** **** **** **** **** **** +11861 OAShaman_Exteneded_EXALTED_RAIMENT **** **** **** **** **** **** **** **** +11862 OAShaman_Silent_EXALTED_RAIMENT **** **** **** **** **** **** **** **** +11863 OAShaman_Greater_Dispelling **** **** **** **** **** **** **** **** +11864 OAShaman_Silent_Greater_Dispelling **** **** **** **** **** **** **** **** +11865 OAShaman_Still_Greater_Dispelling **** **** **** **** **** **** **** **** +11866 OAShaman_Harm **** **** **** **** **** **** **** **** +11867 OAShaman_Silent_Harm **** **** **** **** **** **** **** **** +11868 OAShaman_Still_Harm **** **** **** **** **** **** **** **** +11869 OAShaman_Heal **** **** **** **** **** **** **** **** +11870 OAShaman_Silent_Heal **** **** **** **** **** **** **** **** +11871 OAShaman_Still_Heal **** **** **** **** **** **** **** **** +11872 OAShaman_Planar_Ally **** **** **** **** **** **** **** **** +11873 OAShaman_Exteneded_Planar_Ally **** **** **** **** **** **** **** **** +11874 OAShaman_Silent_Planar_Ally **** **** **** **** **** **** **** **** +11875 OAShaman_Still_Planar_Ally **** **** **** **** **** **** **** **** +11876 OAShaman_Stoneskin **** **** **** **** **** **** **** **** +11877 OAShaman_Exteneded_Stoneskin **** **** **** **** **** **** **** **** +11878 OAShaman_Silent_Stoneskin **** **** **** **** **** **** **** **** +11879 OAShaman_Still_Stoneskin **** **** **** **** **** **** **** **** +11880 OAShaman_STORM_OF_SHARDS **** **** **** **** **** **** **** **** +11881 OAShaman_Empowered_STORM_OF_SHARDS **** **** **** **** **** **** **** **** +11882 OAShaman_Maximized_STORM_OF_SHARDS **** **** **** **** **** **** **** **** +11883 OAShaman_Silent_STORM_OF_SHARDS **** **** **** **** **** **** **** **** +11884 OAShaman_Still_STORM_OF_SHARDS **** **** **** **** **** **** **** **** +11885 OAShaman_Summon_Creature_VI **** **** **** **** **** **** **** **** +11886 OAShaman_Exteneded_Summon_Creature_VI **** **** **** **** **** **** **** **** +11887 OAShaman_Silent_Summon_Creature_VI **** **** **** **** **** **** **** **** +11888 OAShaman_Still_Summon_Creature_VI **** **** **** **** **** **** **** **** +11889 OAShaman_Blasphemy **** **** **** **** **** **** **** **** +11890 OAShaman_Silent_Blasphemy **** **** **** **** **** **** **** **** +11891 OAShaman_Still_Blasphemy **** **** **** **** **** **** **** **** +11892 OAShaman_Control_Weather **** **** **** **** **** **** **** **** +11893 OAShaman_CW_Rain **** **** **** **** **** **** **** **** +11894 OAShaman_CW_Snow **** **** **** **** **** **** **** **** +11895 OAShaman_CW_Clear **** **** **** **** **** **** **** **** +11896 OAShaman_Exteneded_Control_Weather **** **** **** **** **** **** **** **** +11897 OAShaman_Exteneded_CW_Rain **** **** **** **** **** **** **** **** +11898 OAShaman_Exteneded_CW_Snow **** **** **** **** **** **** **** **** +11899 OAShaman_Exteneded_CW_Clear **** **** **** **** **** **** **** **** +11900 OAShaman_Silent_Control_Weather **** **** **** **** **** **** **** **** +11901 OAShaman_Silent_CW_Rain **** **** **** **** **** **** **** **** +11902 OAShaman_Silent_CW_Snow **** **** **** **** **** **** **** **** +11903 OAShaman_Silent_CW_Clear **** **** **** **** **** **** **** **** +11904 OAShaman_Still_Control_Weather **** **** **** **** **** **** **** **** +11905 OAShaman_Still_CW_Rain **** **** **** **** **** **** **** **** +11906 OAShaman_Still_CW_Snow **** **** **** **** **** **** **** **** +11907 OAShaman_Still_CW_Clear **** **** **** **** **** **** **** **** +11908 OAShaman_DEATH_BY_THORNS **** **** **** **** **** **** **** **** +11909 OAShaman_Silent_DEATH_BY_THORNS **** **** **** **** **** **** **** **** +11910 OAShaman_Still_DEATH_BY_THORNS **** **** **** **** **** **** **** **** +11911 OAShaman_Dictum **** **** **** **** **** **** **** **** +11912 OAShaman_Silent_Dictum **** **** **** **** **** **** **** **** +11913 OAShaman_Still_Dictum **** **** **** **** **** **** **** **** +11914 OAShaman_Greater_Restoration **** **** **** **** **** **** **** **** +11915 OAShaman_Silent_Greater_Restoration **** **** **** **** **** **** **** **** +11916 OAShaman_Still_Greater_Restoration **** **** **** **** **** **** **** **** +11917 OAShaman_GreaterScrying **** **** **** **** **** **** **** **** +11918 OAShaman_Exteneded_GreaterScrying **** **** **** **** **** **** **** **** +11919 OAShaman_Silent_GreaterScrying **** **** **** **** **** **** **** **** +11920 OAShaman_Still_GreaterScrying **** **** **** **** **** **** **** **** +11921 OAShaman_Holy_Word **** **** **** **** **** **** **** **** +11922 OAShaman_Silent_Holy_Word **** **** **** **** **** **** **** **** +11923 OAShaman_Still_Holy_Word **** **** **** **** **** **** **** **** +11924 OAShaman_PHOENIX_FIRE **** **** **** **** **** **** **** **** +11925 OAShaman_Empowered_PHOENIX_FIRE **** **** **** **** **** **** **** **** +11926 OAShaman_Silent_PHOENIX_FIRE **** **** **** **** **** **** **** **** +11927 OAShaman_Still_PHOENIX_FIRE **** **** **** **** **** **** **** **** +11928 OAShaman_RAIN_OF_EMBERS **** **** **** **** **** **** **** **** +11929 OAShaman_Empowered_RAIN_OF_EMBERS **** **** **** **** **** **** **** **** +11930 OAShaman_Exteneded_RAIN_OF_EMBERS **** **** **** **** **** **** **** **** +11931 OAShaman_Silent_RAIN_OF_EMBERS **** **** **** **** **** **** **** **** +11932 OAShaman_Still_RAIN_OF_EMBERS **** **** **** **** **** **** **** **** +11933 OAShaman_RAPTURE_OF_RUPTURE **** **** **** **** **** **** **** **** +11934 OAShaman_Empowered_RAPTURE_OF_RUPTURE **** **** **** **** **** **** **** **** +11935 OAShaman_Regenerate **** **** **** **** **** **** **** **** +11936 OAShaman_Exteneded_Regenerate **** **** **** **** **** **** **** **** +11937 OAShaman_Silent_Regenerate **** **** **** **** **** **** **** **** +11938 OAShaman_Still_Regenerate **** **** **** **** **** **** **** **** +11939 OAShaman_Repulsion **** **** **** **** **** **** **** **** +11940 OAShaman_Exteneded_Repulsion **** **** **** **** **** **** **** **** +11941 OAShaman_Silent_Repulsion **** **** **** **** **** **** **** **** +11942 OAShaman_Still_Repulsion **** **** **** **** **** **** **** **** +11943 OAShaman_Resurrection **** **** **** **** **** **** **** **** +11944 OAShaman_Silent_Resurrection **** **** **** **** **** **** **** **** +11945 OAShaman_Still_Resurrection **** **** **** **** **** **** **** **** +11946 OAShaman_Summon_Creature_VII **** **** **** **** **** **** **** **** +11947 OAShaman_Summon7Air **** **** **** **** **** **** **** **** +11948 OAShaman_Summon7Earth **** **** **** **** **** **** **** **** +11949 OAShaman_Summon7Fire **** **** **** **** **** **** **** **** +11950 OAShaman_Summon7Water **** **** **** **** **** **** **** **** +11951 OAShaman_Exteneded_Summon_Creature_VII **** **** **** **** **** **** **** **** +11952 OAShaman_Exteneded_Summon7Air **** **** **** **** **** **** **** **** +11953 OAShaman_Exteneded_Summon7Earth **** **** **** **** **** **** **** **** +11954 OAShaman_Exteneded_Summon7Fire **** **** **** **** **** **** **** **** +11955 OAShaman_Exteneded_Summon7Water **** **** **** **** **** **** **** **** +11956 OAShaman_Silent_Summon_Creature_VII **** **** **** **** **** **** **** **** +11957 OAShaman_Silent_Summon7Air **** **** **** **** **** **** **** **** +11958 OAShaman_Silent_Summon7Earth **** **** **** **** **** **** **** **** +11959 OAShaman_Silent_Summon7Fire **** **** **** **** **** **** **** **** +11960 OAShaman_Silent_Summon7Water **** **** **** **** **** **** **** **** +11961 OAShaman_Still_Summon_Creature_VII **** **** **** **** **** **** **** **** +11962 OAShaman_Still_Summon7Air **** **** **** **** **** **** **** **** +11963 OAShaman_Still_Summon7Earth **** **** **** **** **** **** **** **** +11964 OAShaman_Still_Summon7Fire **** **** **** **** **** **** **** **** +11965 OAShaman_Still_Summon7Water **** **** **** **** **** **** **** **** +11966 OAShaman_Sunbeam **** **** **** **** **** **** **** **** +11967 OAShaman_Silent_Sunbeam **** **** **** **** **** **** **** **** +11968 OAShaman_Still_Sunbeam **** **** **** **** **** **** **** **** +11969 OAShaman_Word_of_Chaos **** **** **** **** **** **** **** **** +11970 OAShaman_Silent_Word_of_Chaos **** **** **** **** **** **** **** **** +11971 OAShaman_Still_Word_of_Chaos **** **** **** **** **** **** **** **** +11972 OAShaman_ANTIMAGIC_FIELD **** **** **** **** **** **** **** **** +11973 OAShaman_Exteneded_ANTIMAGIC_FIELD **** **** **** **** **** **** **** **** +11974 OAShaman_Silent_ANTIMAGIC_FIELD **** **** **** **** **** **** **** **** +11975 OAShaman_Still_ANTIMAGIC_FIELD **** **** **** **** **** **** **** **** +11976 OAShaman_Aura_versus_Alignment **** **** **** **** **** **** **** **** +11977 OAShaman_Unholy_Aura **** **** **** **** **** **** **** **** +11978 OAShaman_Holy_Aura **** **** **** **** **** **** **** **** +11979 OAShaman_Exteneded_Aura_versus_Alignment **** **** **** **** **** **** **** **** +11980 OAShaman_Exteneded_Unholy_Aura **** **** **** **** **** **** **** **** +11981 OAShaman_Exteneded_Holy_Aura **** **** **** **** **** **** **** **** +11982 OAShaman_Silent_Aura_versus_Alignment **** **** **** **** **** **** **** **** +11983 OAShaman_Silent_Unholy_Aura **** **** **** **** **** **** **** **** +11984 OAShaman_Silent_Holy_Aura **** **** **** **** **** **** **** **** +11985 OAShaman_Still_Aura_versus_Alignment **** **** **** **** **** **** **** **** +11986 OAShaman_Still_Unholy_Aura **** **** **** **** **** **** **** **** +11987 OAShaman_Still_Holy_Aura **** **** **** **** **** **** **** **** +11988 OAShaman_DiscernLocation **** **** **** **** **** **** **** **** +11989 OAShaman_Exteneded_DiscernLocation **** **** **** **** **** **** **** **** +11990 OAShaman_Silent_DiscernLocation **** **** **** **** **** **** **** **** +11991 OAShaman_Still_DiscernLocation **** **** **** **** **** **** **** **** +11992 OAShaman_DRAGON_CLOUD **** **** **** **** **** **** **** **** +11993 OAShaman_Silent_DRAGON_CLOUD **** **** **** **** **** **** **** **** +11994 OAShaman_Still_DRAGON_CLOUD **** **** **** **** **** **** **** **** +11995 OAShaman_Earthquake **** **** **** **** **** **** **** **** +11996 OAShaman_Exteneded_Earthquake **** **** **** **** **** **** **** **** +11997 OAShaman_Silent_Earthquake **** **** **** **** **** **** **** **** +11998 OAShaman_Still_Earthquake **** **** **** **** **** **** **** **** +11999 OAShaman_EVIL_WEATHER **** **** **** **** **** **** **** **** +12000 OAShaman_EVIL_WEATHER_RAIN_OF_BLOOD **** **** **** **** **** **** **** **** +12001 OAShaman_EVIL_WEATHER_VIOLET_RAIN **** **** **** **** **** **** **** **** +12002 OAShaman_EVIL_WEATHER_GREEN_FOG **** **** **** **** **** **** **** **** +12003 OAShaman_EVIL_WEATHER_RAIN_OF_FISH **** **** **** **** **** **** **** **** +12004 OAShaman_Silent_EVIL_WEATHER **** **** **** **** **** **** **** **** +12005 OAShaman_Silent_EVIL_WEATHER_RAIN_OF_BLOOD **** **** **** **** **** **** **** **** +12006 OAShaman_Silent_EVIL_WEATHER_VIOLET_RAIN **** **** **** **** **** **** **** **** +12007 OAShaman_Silent_EVIL_WEATHER_GREEN_FOG **** **** **** **** **** **** **** **** +12008 OAShaman_Silent_EVIL_WEATHER_RAIN_OF_FISH **** **** **** **** **** **** **** **** +12009 OAShaman_Still_EVIL_WEATHER **** **** **** **** **** **** **** **** +12010 OAShaman_Still_EVIL_WEATHER_RAIN_OF_BLOOD **** **** **** **** **** **** **** **** +12011 OAShaman_Still_EVIL_WEATHER_VIOLET_RAIN **** **** **** **** **** **** **** **** +12012 OAShaman_Still_EVIL_WEATHER_GREEN_FOG **** **** **** **** **** **** **** **** +12013 OAShaman_Still_EVIL_WEATHER_RAIN_OF_FISH **** **** **** **** **** **** **** **** +12014 OAShaman_Greater_Planar_Ally **** **** **** **** **** **** **** **** +12015 OAShaman_Exteneded_Greater_Planar_Ally **** **** **** **** **** **** **** **** +12016 OAShaman_Silent_Greater_Planar_Ally **** **** **** **** **** **** **** **** +12017 OAShaman_Still_Greater_Planar_Ally **** **** **** **** **** **** **** **** +12018 OAShaman_Holy_Aura **** **** **** **** **** **** **** **** +12019 OAShaman_Exteneded_Holy_Aura **** **** **** **** **** **** **** **** +12020 OAShaman_Silent_Holy_Aura **** **** **** **** **** **** **** **** +12021 OAShaman_Still_Holy_Aura **** **** **** **** **** **** **** **** +12022 OAShaman_Mass_Heal **** **** **** **** **** **** **** **** +12023 OAShaman_Silent_Mass_Heal **** **** **** **** **** **** **** **** +12024 OAShaman_Still_Mass_Heal **** **** **** **** **** **** **** **** +12025 OAShaman_Summon_Creature_VIII **** **** **** **** **** **** **** **** +12026 OAShaman_Summon8Air **** **** **** **** **** **** **** **** +12027 OAShaman_Summon8Earth **** **** **** **** **** **** **** **** +12028 OAShaman_Summon8Fire **** **** **** **** **** **** **** **** +12029 OAShaman_Summon8Water **** **** **** **** **** **** **** **** +12030 OAShaman_Exteneded_Summon_Creature_VIII **** **** **** **** **** **** **** **** +12031 OAShaman_Exteneded_Summon8Air **** **** **** **** **** **** **** **** +12032 OAShaman_Exteneded_Summon8Earth **** **** **** **** **** **** **** **** +12033 OAShaman_Exteneded_Summon8Fire **** **** **** **** **** **** **** **** +12034 OAShaman_Exteneded_Summon8Water **** **** **** **** **** **** **** **** +12035 OAShaman_Silent_Summon_Creature_VIII **** **** **** **** **** **** **** **** +12036 OAShaman_Silent_Summon8Air **** **** **** **** **** **** **** **** +12037 OAShaman_Silent_Summon8Earth **** **** **** **** **** **** **** **** +12038 OAShaman_Silent_Summon8Fire **** **** **** **** **** **** **** **** +12039 OAShaman_Silent_Summon8Water **** **** **** **** **** **** **** **** +12040 OAShaman_Still_Summon_Creature_VIII **** **** **** **** **** **** **** **** +12041 OAShaman_Still_Summon8Air **** **** **** **** **** **** **** **** +12042 OAShaman_Still_Summon8Earth **** **** **** **** **** **** **** **** +12043 OAShaman_Still_Summon8Fire **** **** **** **** **** **** **** **** +12044 OAShaman_Still_Summon8Water **** **** **** **** **** **** **** **** +12045 OAShaman_APOCALYPSE_FROM_THE_SKY **** **** **** **** **** **** **** **** +12046 OAShaman_APOCALYPSE_FROM_THE_SKY_FIRE **** **** **** **** **** **** **** **** +12047 OAShaman_APOCALYPSE_FROM_THE_SKY_ACID **** **** **** **** **** **** **** **** +12048 OAShaman_APOCALYPSE_FROM_THE_SKY_SONIC **** **** **** **** **** **** **** **** +12049 OAShaman_EXALTED_FURY **** **** **** **** **** **** **** **** +12050 OAShaman_Gate **** **** **** **** **** **** **** **** +12051 OAShaman_Summon_Creature_IX **** **** **** **** **** **** **** **** +12052 OAShaman_Summon9Air **** **** **** **** **** **** **** **** +12053 OAShaman_Summon9Earth **** **** **** **** **** **** **** **** +12054 OAShaman_Summon9Fire **** **** **** **** **** **** **** **** +12055 OAShaman_Summon9Water **** **** **** **** **** **** **** **** +12056 OAShaman_True_Resurrection **** **** **** **** **** **** **** **** +12057 SlayerOfDomiel_Bless_Weapon **** **** **** **** **** **** **** **** +12058 SlayerOfDomiel_Exteneded_Bless_Weapon **** **** **** **** **** **** **** **** +12059 SlayerOfDomiel_Silent_Bless_Weapon **** **** **** **** **** **** **** **** +12060 SlayerOfDomiel_Still_Bless_Weapon **** **** **** **** **** **** **** **** +12061 SlayerOfDomiel_Alter_Self_Radial_Master **** **** **** **** **** **** **** **** +12062 SlayerOfDomiel_Alter_Self_Learn **** **** **** **** **** **** **** **** +12063 SlayerOfDomiel_Alter_Self_Options **** **** **** **** **** **** **** **** +12064 SlayerOfDomiel_Alter_Self_QS1 **** **** **** **** **** **** **** **** +12065 SlayerOfDomiel_Alter_Self_QS2 **** **** **** **** **** **** **** **** +12066 SlayerOfDomiel_Alter_Self_QS3 **** **** **** **** **** **** **** **** +12067 SlayerOfDomiel_Exteneded_Alter_Self_Radial_Master **** **** **** **** **** **** **** **** +12068 SlayerOfDomiel_Exteneded_Alter_Self_Learn **** **** **** **** **** **** **** **** +12069 SlayerOfDomiel_Exteneded_Alter_Self_Options **** **** **** **** **** **** **** **** +12070 SlayerOfDomiel_Exteneded_Alter_Self_QS1 **** **** **** **** **** **** **** **** +12071 SlayerOfDomiel_Exteneded_Alter_Self_QS2 **** **** **** **** **** **** **** **** +12072 SlayerOfDomiel_Exteneded_Alter_Self_QS3 **** **** **** **** **** **** **** **** +12073 SlayerOfDomiel_Silent_Alter_Self_Radial_Master **** **** **** **** **** **** **** **** +12074 SlayerOfDomiel_Silent_Alter_Self_Learn **** **** **** **** **** **** **** **** +12075 SlayerOfDomiel_Silent_Alter_Self_Options **** **** **** **** **** **** **** **** +12076 SlayerOfDomiel_Silent_Alter_Self_QS1 **** **** **** **** **** **** **** **** +12077 SlayerOfDomiel_Silent_Alter_Self_QS2 **** **** **** **** **** **** **** **** +12078 SlayerOfDomiel_Silent_Alter_Self_QS3 **** **** **** **** **** **** **** **** +12079 SlayerOfDomiel_Still_Alter_Self_Radial_Master **** **** **** **** **** **** **** **** +12080 SlayerOfDomiel_Still_Alter_Self_Learn **** **** **** **** **** **** **** **** +12081 SlayerOfDomiel_Still_Alter_Self_Options **** **** **** **** **** **** **** **** +12082 SlayerOfDomiel_Still_Alter_Self_QS1 **** **** **** **** **** **** **** **** +12083 SlayerOfDomiel_Still_Alter_Self_QS2 **** **** **** **** **** **** **** **** +12084 SlayerOfDomiel_Still_Alter_Self_QS3 **** **** **** **** **** **** **** **** +12085 SlayerOfDomiel_Divine_Favor **** **** **** **** **** **** **** **** +12086 SlayerOfDomiel_Exteneded_Divine_Favor **** **** **** **** **** **** **** **** +12087 SlayerOfDomiel_Silent_Divine_Favor **** **** **** **** **** **** **** **** +12088 SlayerOfDomiel_Still_Divine_Favor **** **** **** **** **** **** **** **** +12089 SlayerOfDomiel_Obscuring_Mist **** **** **** **** **** **** **** **** +12090 SlayerOfDomiel_Exteneded_Obscuring_Mist **** **** **** **** **** **** **** **** +12091 SlayerOfDomiel_Silent_Obscuring_Mist **** **** **** **** **** **** **** **** +12092 SlayerOfDomiel_Still_Obscuring_Mist **** **** **** **** **** **** **** **** +12093 SlayerOfDomiel_VisionOfHeaven **** **** **** **** **** **** **** **** +12094 SlayerOfDomiel_Exteneded_VisionOfHeaven **** **** **** **** **** **** **** **** +12095 SlayerOfDomiel_Silent_VisionOfHeaven **** **** **** **** **** **** **** **** +12096 SlayerOfDomiel_DIVINE_INSPIRATION **** **** **** **** **** **** **** **** +12097 SlayerOfDomiel_Exteneded_DIVINE_INSPIRATION **** **** **** **** **** **** **** **** +12098 SlayerOfDomiel_TWILIGHT_LUCK **** **** **** **** **** **** **** **** +12099 SlayerOfDomiel_Exteneded_TWILIGHT_LUCK **** **** **** **** **** **** **** **** +12100 SlayerOfDomiel_Silent_TWILIGHT_LUCK **** **** **** **** **** **** **** **** +12101 SlayerOfDomiel_LANTERN_LIGHT **** **** **** **** **** **** **** **** +12102 SlayerOfDomiel_Empowered_LANTERN_LIGHT **** **** **** **** **** **** **** **** +12103 SlayerOfDomiel_Maximized_LANTERN_LIGHT **** **** **** **** **** **** **** **** +12104 SlayerOfDomiel_Still_LANTERN_LIGHT **** **** **** **** **** **** **** **** +12105 SlayerOfDomiel_Alter_Self_Radial_Master **** **** **** **** **** **** **** **** +12106 SlayerOfDomiel_Alter_Self_Learn **** **** **** **** **** **** **** **** +12107 SlayerOfDomiel_Alter_Self_Options **** **** **** **** **** **** **** **** +12108 SlayerOfDomiel_Alter_Self_QS1 **** **** **** **** **** **** **** **** +12109 SlayerOfDomiel_Alter_Self_QS2 **** **** **** **** **** **** **** **** +12110 SlayerOfDomiel_Alter_Self_QS3 **** **** **** **** **** **** **** **** +12111 SlayerOfDomiel_Exteneded_Alter_Self_Radial_Master **** **** **** **** **** **** **** **** +12112 SlayerOfDomiel_Exteneded_Alter_Self_Learn **** **** **** **** **** **** **** **** +12113 SlayerOfDomiel_Exteneded_Alter_Self_Options **** **** **** **** **** **** **** **** +12114 SlayerOfDomiel_Exteneded_Alter_Self_QS1 **** **** **** **** **** **** **** **** +12115 SlayerOfDomiel_Exteneded_Alter_Self_QS2 **** **** **** **** **** **** **** **** +12116 SlayerOfDomiel_Exteneded_Alter_Self_QS3 **** **** **** **** **** **** **** **** +12117 SlayerOfDomiel_Silent_Alter_Self_Radial_Master **** **** **** **** **** **** **** **** +12118 SlayerOfDomiel_Silent_Alter_Self_Learn **** **** **** **** **** **** **** **** +12119 SlayerOfDomiel_Silent_Alter_Self_Options **** **** **** **** **** **** **** **** +12120 SlayerOfDomiel_Silent_Alter_Self_QS1 **** **** **** **** **** **** **** **** +12121 SlayerOfDomiel_Silent_Alter_Self_QS2 **** **** **** **** **** **** **** **** +12122 SlayerOfDomiel_Silent_Alter_Self_QS3 **** **** **** **** **** **** **** **** +12123 SlayerOfDomiel_Still_Alter_Self_Radial_Master **** **** **** **** **** **** **** **** +12124 SlayerOfDomiel_Still_Alter_Self_Learn **** **** **** **** **** **** **** **** +12125 SlayerOfDomiel_Still_Alter_Self_Options **** **** **** **** **** **** **** **** +12126 SlayerOfDomiel_Still_Alter_Self_QS1 **** **** **** **** **** **** **** **** +12127 SlayerOfDomiel_Still_Alter_Self_QS2 **** **** **** **** **** **** **** **** +12128 SlayerOfDomiel_Still_Alter_Self_QS3 **** **** **** **** **** **** **** **** +12129 SlayerOfDomiel_Darkness **** **** **** **** **** **** **** **** +12130 SlayerOfDomiel_Exteneded_Darkness **** **** **** **** **** **** **** **** +12131 SlayerOfDomiel_Silent_Darkness **** **** **** **** **** **** **** **** +12132 SlayerOfDomiel_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +12133 SlayerOfDomiel_Empowered_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +12134 SlayerOfDomiel_Silent_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +12135 SlayerOfDomiel_Still_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +12136 SlayerOfDomiel_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +12137 SlayerOfDomiel_Exteneded_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +12138 SlayerOfDomiel_DeeperDarkness **** **** **** **** **** **** **** **** +12139 SlayerOfDomiel_Exteneded_DeeperDarkness **** **** **** **** **** **** **** **** +12140 SlayerOfDomiel_Silent_DeeperDarkness **** **** **** **** **** **** **** **** +12141 SlayerOfDomiel_Invisibility **** **** **** **** **** **** **** **** +12142 SlayerOfDomiel_Exteneded_Invisibility **** **** **** **** **** **** **** **** +12143 SlayerOfDomiel_Silent_Invisibility **** **** **** **** **** **** **** **** +12144 SlayerOfDomiel_Still_Invisibility **** **** **** **** **** **** **** **** +12145 SlayerOfDomiel_NONDETECTION **** **** **** **** **** **** **** **** +12146 SlayerOfDomiel_Exteneded_NONDETECTION **** **** **** **** **** **** **** **** +12147 SlayerOfDomiel_Silent_NONDETECTION **** **** **** **** **** **** **** **** +12148 SlayerOfDomiel_Still_NONDETECTION **** **** **** **** **** **** **** **** +12149 SlayerOfDomiel_BRILLIANT_EMANATION **** **** **** **** **** **** **** **** +12150 SlayerOfDomiel_Exteneded_BRILLIANT_EMANATION **** **** **** **** **** **** **** **** +12151 SlayerOfDomiel_HAMMER_OF_RIGHTEOUSNESS **** **** **** **** **** **** **** **** +12152 SlayerOfDomiel_Silent_HAMMER_OF_RIGHTEOUSNESS **** **** **** **** **** **** **** **** +12153 SlayerOfDomiel_Still_HAMMER_OF_RIGHTEOUSNESS **** **** **** **** **** **** **** **** +12154 SlayerOfDomiel_Death_Ward **** **** **** **** **** **** **** **** +12155 SlayerOfDomiel_DimensionDoor_RadialMaster **** **** **** **** **** **** **** **** +12156 SlayerOfDomiel_DimensionDoor_SelfOnly **** **** **** **** **** **** **** **** +12157 SlayerOfDomiel_DimensionDoor_Party **** **** **** **** **** **** **** **** +12158 SlayerOfDomiel_DimensionDoor_DirDist_SelfOnly **** **** **** **** **** **** **** **** +12159 SlayerOfDomiel_DimensionDoor_DirDist_Party **** **** **** **** **** **** **** **** +12160 SlayerOfDomiel_Freedom_of_Movement **** **** **** **** **** **** **** **** +12161 SlayerOfDomiel_Holy_Sword **** **** **** **** **** **** **** **** +12162 SlayerOfDomiel_Improved_Invisibility **** **** **** **** **** **** **** **** +12163 SlayerOfDomiel_SwordOfConscience **** **** **** **** **** **** **** **** +12164 SlayerOfDomiel_DIAMOND_SPRAY **** **** **** **** **** **** **** **** +12165 SlayerOfDomiel_SUNMANTLE **** **** **** **** **** **** **** **** +12166 SlayerOfDomiel_GREATER_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +12167 Suel_Archanamach_ABERRATE **** **** **** **** **** **** **** **** +12168 Suel_Archanamach_BESTOW_WOUND **** **** **** **** **** **** **** **** +12169 Suel_Archanamach_Burning_Hands **** **** **** **** **** **** **** **** +12170 Suel_Archanamach_Color_Spray **** **** **** **** **** **** **** **** +12171 Suel_Archanamach_DETECT_UNDEAD **** **** **** **** **** **** **** **** +12172 Suel_Archanamach_Disguise_Self_Radial_Master **** **** **** **** **** **** **** **** +12173 Suel_Archanamach_Disguise_Self_Learn **** **** **** **** **** **** **** **** +12174 Suel_Archanamach_Disguise_Self_Options **** **** **** **** **** **** **** **** +12175 Suel_Archanamach_Disguise_Self_QS1 **** **** **** **** **** **** **** **** +12176 Suel_Archanamach_Disguise_Self_QS2 **** **** **** **** **** **** **** **** +12177 Suel_Archanamach_Disguise_Self_QS3 **** **** **** **** **** **** **** **** +12178 Suel_Archanamach_Endure_Elements **** **** **** **** **** **** **** **** +12179 Suel_Archanamach_ENLARGE_PERSON **** **** **** **** **** **** **** **** +12180 Suel_Archanamach_Expeditious_Retreat **** **** **** **** **** **** **** **** +12181 Suel_Archanamach_EYES_OF_THE_AVORAL **** **** **** **** **** **** **** **** +12182 Suel_Archanamach_FistOfStone **** **** **** **** **** **** **** **** +12183 Suel_Archanamach_Identify **** **** **** **** **** **** **** **** +12184 Suel_Archanamach_Ironguts **** **** **** **** **** **** **** **** +12185 Suel_Archanamach_Lesser_Deflect **** **** **** **** **** **** **** **** +12186 Suel_Archanamach_Magic_Weapon **** **** **** **** **** **** **** **** +12187 Suel_Archanamach_Protection_from_Chaos **** **** **** **** **** **** **** **** +12188 Suel_Archanamach_Protection_from_Evil **** **** **** **** **** **** **** **** +12189 Suel_Archanamach_Protection_from_Good **** **** **** **** **** **** **** **** +12190 Suel_Archanamach_Protection_from_Law **** **** **** **** **** **** **** **** +12191 Suel_Archanamach_REDUCE_PERSON **** **** **** **** **** **** **** **** +12192 Suel_Archanamach_Shield **** **** **** **** **** **** **** **** +12193 Suel_Archanamach_Spell_Jump **** **** **** **** **** **** **** **** +12194 Suel_Archanamach_True_Casting **** **** **** **** **** **** **** **** +12195 Suel_Archanamach_True_Strike **** **** **** **** **** **** **** **** +12196 Suel_Archanamach_Alter_Self_Radial_Master **** **** **** **** **** **** **** **** +12197 Suel_Archanamach_Alter_Self_Learn **** **** **** **** **** **** **** **** +12198 Suel_Archanamach_Alter_Self_Options **** **** **** **** **** **** **** **** +12199 Suel_Archanamach_Alter_Self_QS1 **** **** **** **** **** **** **** **** +12200 Suel_Archanamach_Alter_Self_QS2 **** **** **** **** **** **** **** **** +12201 Suel_Archanamach_Alter_Self_QS3 **** **** **** **** **** **** **** **** +12202 Suel_Archanamach_Animalistic_Power **** **** **** **** **** **** **** **** +12203 Suel_Archanamach_AugmentFamiliar **** **** **** **** **** **** **** **** +12204 Suel_Archanamach_BalagarnsIronHorn **** **** **** **** **** **** **** **** +12205 Suel_Archanamach_Blur **** **** **** **** **** **** **** **** +12206 Suel_Archanamach_Bulls_Strength **** **** **** **** **** **** **** **** +12207 Suel_Archanamach_Cats_Grace **** **** **** **** **** **** **** **** +12208 Suel_Archanamach_Continual_Flame **** **** **** **** **** **** **** **** +12209 Suel_Archanamach_Deflect **** **** **** **** **** **** **** **** +12210 Suel_Archanamach_Dispelling_Touch **** **** **** **** **** **** **** **** +12211 Suel_Archanamach_Eagle_Splendor **** **** **** **** **** **** **** **** +12212 Suel_Archanamach_Endurance **** **** **** **** **** **** **** **** +12213 Suel_Archanamach_ENERGIZE_POTION **** **** **** **** **** **** **** **** +12214 Suel_Archanamach_ENERGIZE_POTION_ACID **** **** **** **** **** **** **** **** +12215 Suel_Archanamach_ENERGIZE_POTION_COLD **** **** **** **** **** **** **** **** +12216 Suel_Archanamach_ENERGIZE_POTION_ELECTRICITY **** **** **** **** **** **** **** **** +12217 Suel_Archanamach_ENERGIZE_POTION_FIRE **** **** **** **** **** **** **** **** +12218 Suel_Archanamach_ENERGIZE_POTION_SONIC **** **** **** **** **** **** **** **** +12219 Suel_Archanamach_Foxs_Cunning **** **** **** **** **** **** **** **** +12220 Suel_Archanamach_Ghostly_Visage **** **** **** **** **** **** **** **** +12221 Suel_Archanamach_Invisibility **** **** **** **** **** **** **** **** +12222 Suel_Archanamach_Knock **** **** **** **** **** **** **** **** +12223 Suel_Archanamach_Lesser_Dispel **** **** **** **** **** **** **** **** +12224 Suel_Archanamach_LocateObject **** **** **** **** **** **** **** **** +12225 Suel_Archanamach_MirrorImage **** **** **** **** **** **** **** **** +12226 Suel_Archanamach_ObscureObject **** **** **** **** **** **** **** **** +12227 Suel_Archanamach_Owls_Wisdom **** **** **** **** **** **** **** **** +12228 Suel_Archanamach_ProtectionArrows **** **** **** **** **** **** **** **** +12229 Suel_Archanamach_Pyrotechnics **** **** **** **** **** **** **** **** +12230 Suel_Archanamach_Pyrotechnics_Fireworks **** **** **** **** **** **** **** **** +12231 Suel_Archanamach_Pyrotechnics_Smoke **** **** **** **** **** **** **** **** +12232 Suel_Archanamach_Resist_Elements **** **** **** **** **** **** **** **** +12233 Suel_Archanamach_See_Invisibility **** **** **** **** **** **** **** **** +12234 Suel_Archanamach_Shadow_Spray **** **** **** **** **** **** **** **** +12235 Suel_Archanamach_Stone_Bones **** **** **** **** **** **** **** **** +12236 Suel_Archanamach_Sure_Strike **** **** **** **** **** **** **** **** +12237 Suel_Archanamach_Ultravision **** **** **** **** **** **** **** **** +12238 Suel_Archanamach_UNHEAVENED **** **** **** **** **** **** **** **** +12239 Suel_Archanamach_WhirlingBlade **** **** **** **** **** **** **** **** +12240 Suel_Archanamach_Clairaudience_and_Clairvoyance **** **** **** **** **** **** **** **** +12241 Suel_Archanamach_Clarity **** **** **** **** **** **** **** **** +12242 Suel_Archanamach_Crown_Might **** **** **** **** **** **** **** **** +12243 Suel_Archanamach_Crown_Protection **** **** **** **** **** **** **** **** +12244 Suel_Archanamach_CURSE_OF_THE_PUTRID_HUSK **** **** **** **** **** **** **** **** +12245 Suel_Archanamach_DEVILS_EYE **** **** **** **** **** **** **** **** +12246 Suel_Archanamach_Dispel_Magic **** **** **** **** **** **** **** **** +12247 Suel_Archanamach_Displacement **** **** **** **** **** **** **** **** +12248 Suel_Archanamach_Energy_Aegis **** **** **** **** **** **** **** **** +12249 Suel_Archanamach_Energy_Aegis_Acid **** **** **** **** **** **** **** **** +12250 Suel_Archanamach_Energy_Aegis_Cold **** **** **** **** **** **** **** **** +12251 Suel_Archanamach_Energy_Aegis_Elec **** **** **** **** **** **** **** **** +12252 Suel_Archanamach_Energy_Aegis_Fire **** **** **** **** **** **** **** **** +12253 Suel_Archanamach_Energy_Aegis_Sonic **** **** **** **** **** **** **** **** +12254 Suel_Archanamach_Energy_Surge **** **** **** **** **** **** **** **** +12255 Suel_Archanamach_Energy_Surge_Acid **** **** **** **** **** **** **** **** +12256 Suel_Archanamach_Energy_Surge_Cold **** **** **** **** **** **** **** **** +12257 Suel_Archanamach_Energy_Surge_Elec **** **** **** **** **** **** **** **** +12258 Suel_Archanamach_Energy_Surge_Fire **** **** **** **** **** **** **** **** +12259 Suel_Archanamach_Energy_Surge_Sonic **** **** **** **** **** **** **** **** +12260 Suel_Archanamach_Find_Traps **** **** **** **** **** **** **** **** +12261 Suel_Archanamach_Greater_Magic_Weapon **** **** **** **** **** **** **** **** +12262 Suel_Archanamach_Halt **** **** **** **** **** **** **** **** +12263 Suel_Archanamach_Haste **** **** **** **** **** **** **** **** +12264 Suel_Archanamach_Invisibility_Sphere **** **** **** **** **** **** **** **** +12265 Suel_Archanamach_Keen_Edge **** **** **** **** **** **** **** **** +12266 Suel_Archanamach_Magic_Circle_against_Chaos **** **** **** **** **** **** **** **** +12267 Suel_Archanamach_Magic_Circle_against_Evil **** **** **** **** **** **** **** **** +12268 Suel_Archanamach_Magic_Circle_against_Good **** **** **** **** **** **** **** **** +12269 Suel_Archanamach_Magic_Circle_against_Law **** **** **** **** **** **** **** **** +12270 Suel_Archanamach_NONDETECTION **** **** **** **** **** **** **** **** +12271 Suel_Archanamach_Protection_from_Elements **** **** **** **** **** **** **** **** +12272 Suel_Archanamach_REALITY_BLIND **** **** **** **** **** **** **** **** +12273 Suel_Archanamach_Slow **** **** **** **** **** **** **** **** +12274 Suel_Archanamach_Spiderskin **** **** **** **** **** **** **** **** +12275 Suel_Archanamach_WaterBreathing **** **** **** **** **** **** **** **** +12276 Suel_Archanamach_Weapon_of_Impact **** **** **** **** **** **** **** **** +12277 Suel_Archanamach_ArcaneEye **** **** **** **** **** **** **** **** +12278 Suel_Archanamach_Bestow_Curse **** **** **** **** **** **** **** **** +12279 Suel_Archanamach_DetectScrying **** **** **** **** **** **** **** **** +12280 Suel_Archanamach_Dimensional_Anchor **** **** **** **** **** **** **** **** +12281 Suel_Archanamach_FireTrap **** **** **** **** **** **** **** **** +12282 Suel_Archanamach_Greater_Resistance **** **** **** **** **** **** **** **** +12283 Suel_Archanamach_Ilyykurs_Mantle **** **** **** **** **** **** **** **** +12284 Suel_Archanamach_Improved_Invisibility **** **** **** **** **** **** **** **** +12285 Suel_Archanamach_Lesser_Spell_Breach **** **** **** **** **** **** **** **** +12286 Suel_Archanamach_LocateCreature **** **** **** **** **** **** **** **** +12287 Suel_Archanamach_Lower_Spell_Resistance **** **** **** **** **** **** **** **** +12288 Suel_Archanamach_MASS_ENLARGE_PERSON **** **** **** **** **** **** **** **** +12289 Suel_Archanamach_MASS_REDUCE_PERSON **** **** **** **** **** **** **** **** +12290 Suel_Archanamach_Mass_Ultravision **** **** **** **** **** **** **** **** +12291 Suel_Archanamach_Minor_Globe_of_Invulnerability **** **** **** **** **** **** **** **** +12292 Suel_Archanamach_Phantasmal_Killer **** **** **** **** **** **** **** **** +12293 Suel_Archanamach_Polymorph_Self **** **** **** **** **** **** **** **** +12294 Suel_Archanamach_Polymorph_GIANT_SPIDER **** **** **** **** **** **** **** **** +12295 Suel_Archanamach_Polymorph_TROLL **** **** **** **** **** **** **** **** +12296 Suel_Archanamach_Polymorph_UMBER_HULK **** **** **** **** **** **** **** **** +12297 Suel_Archanamach_Polymorph_PIXIE **** **** **** **** **** **** **** **** +12298 Suel_Archanamach_Polymorph_ZOMBIE **** **** **** **** **** **** **** **** +12299 Suel_Archanamach_RAINBOW_PATTERN **** **** **** **** **** **** **** **** +12300 Suel_Archanamach_Remove_Blindness_and_Deafness **** **** **** **** **** **** **** **** +12301 Suel_Archanamach_Remove_Curse **** **** **** **** **** **** **** **** +12302 Suel_Archanamach_Scrying **** **** **** **** **** **** **** **** +12303 Suel_Archanamach_SerpentArrows **** **** **** **** **** **** **** **** +12304 Suel_Archanamach_Shadow_Conjuration **** **** **** **** **** **** **** **** +12305 Suel_Archanamach_SHADOW_CON_Summon_Shadow **** **** **** **** **** **** **** **** +12306 Suel_Archanamach_SHADOW_CON_Darkness **** **** **** **** **** **** **** **** +12307 Suel_Archanamach_SHADOW_CON_Inivsibility **** **** **** **** **** **** **** **** +12308 Suel_Archanamach_SHADOW_CON_Mage_Armor **** **** **** **** **** **** **** **** +12309 Suel_Archanamach_SHADOW_CON_Magic_Missile **** **** **** **** **** **** **** **** +12310 Suel_Archanamach_Slashing_Dispel **** **** **** **** **** **** **** **** +12311 Suel_Archanamach_Stoneskin **** **** **** **** **** **** **** **** +12312 Suel_Archanamach_BalefulPolymorph **** **** **** **** **** **** **** **** +12313 Suel_Archanamach_BreakEnchantment **** **** **** **** **** **** **** **** +12314 Suel_Archanamach_Dismissal **** **** **** **** **** **** **** **** +12315 Suel_Archanamach_DraconicMight **** **** **** **** **** **** **** **** +12316 Suel_Archanamach_Energy_Buffer **** **** **** **** **** **** **** **** +12317 Suel_Archanamach_Feeblemind **** **** **** **** **** **** **** **** +12318 Suel_Archanamach_Greater_Shadow_Conjuration **** **** **** **** **** **** **** **** +12319 Suel_Archanamach_GR_SHADOW_CON_Summon_Shadow **** **** **** **** **** **** **** **** +12320 Suel_Archanamach_GR_SHADOW_CON_Acid_Arrow **** **** **** **** **** **** **** **** +12321 Suel_Archanamach_GR_SHADOW_CON_Ghostly_Visage **** **** **** **** **** **** **** **** +12322 Suel_Archanamach_GR_SHADOW_CON_Web **** **** **** **** **** **** **** **** +12323 Suel_Archanamach_GR_SHADOW_CON_Minor_Globe **** **** **** **** **** **** **** **** +12324 Suel_Archanamach_Lesser_Mind_Blank **** **** **** **** **** **** **** **** +12325 Suel_Archanamach_Lesser_Spell_Mantle **** **** **** **** **** **** **** **** +12326 Suel_Archanamach_RESONATING_RESISTANCE **** **** **** **** **** **** **** **** +12327 Favoured_Soul_Cure_Minor_Wounds **** **** **** **** **** **** **** **** +12328 Favoured_Soul_Inflict_Minor_Wounds **** **** **** **** **** **** **** **** +12329 Favoured_Soul_Light **** **** **** **** **** **** **** **** +12330 Favoured_Soul_Read_Magic **** **** **** **** **** **** **** **** +12331 Favoured_Soul_Resistance **** **** **** **** **** **** **** **** +12332 Favoured_Soul_Virtue **** **** **** **** **** **** **** **** +12333 Favoured_Soul_ANGRY_ACHE **** **** **** **** **** **** **** **** +12334 Favoured_Soul_Bane **** **** **** **** **** **** **** **** +12335 Favoured_Soul_Blade_of_Blood **** **** **** **** **** **** **** **** +12336 Favoured_Soul_Blade_of_Blood_1d6 **** **** **** **** **** **** **** **** +12337 Favoured_Soul_Blade_of_Blood_3d6 **** **** **** **** **** **** **** **** +12338 Favoured_Soul_Bless **** **** **** **** **** **** **** **** +12339 Favoured_Soul_Bless_Water **** **** **** **** **** **** **** **** +12340 Favoured_Soul_Cause_Fear **** **** **** **** **** **** **** **** +12341 Favoured_Soul_Command_RadialMaster **** **** **** **** **** **** **** **** +12342 Favoured_Soul_Command_Approach **** **** **** **** **** **** **** **** +12343 Favoured_Soul_Command_Drop **** **** **** **** **** **** **** **** +12344 Favoured_Soul_Command_Fall **** **** **** **** **** **** **** **** +12345 Favoured_Soul_Command_Flee **** **** **** **** **** **** **** **** +12346 Favoured_Soul_Command_Halt **** **** **** **** **** **** **** **** +12347 Favoured_Soul_Conviction **** **** **** **** **** **** **** **** +12348 Favoured_Soul_Crafters_Blessing **** **** **** **** **** **** **** **** +12349 Favoured_Soul_Crafters_Curse **** **** **** **** **** **** **** **** +12350 Favoured_Soul_Cure_Light_Wounds **** **** **** **** **** **** **** **** +12351 Favoured_Soul_Curse_Water **** **** **** **** **** **** **** **** +12352 Favoured_Soul_Detect_Chaos **** **** **** **** **** **** **** **** +12353 Favoured_Soul_Detect_Evil **** **** **** **** **** **** **** **** +12354 Favoured_Soul_Detect_Good **** **** **** **** **** **** **** **** +12355 Favoured_Soul_Detect_Law **** **** **** **** **** **** **** **** +12356 Favoured_Soul_DETECT_UNDEAD **** **** **** **** **** **** **** **** +12357 Favoured_Soul_Divine_Favor **** **** **** **** **** **** **** **** +12358 Favoured_Soul_Doom **** **** **** **** **** **** **** **** +12359 Favoured_Soul_DRUG_RESISTANCE **** **** **** **** **** **** **** **** +12360 Favoured_Soul_Endure_Elements **** **** **** **** **** **** **** **** +12361 Favoured_Soul_Entropic_Shield **** **** **** **** **** **** **** **** +12362 Favoured_Soul_EXTRACT_DRUG **** **** **** **** **** **** **** **** +12363 Favoured_Soul_EXTRACT_BACCARAN **** **** **** **** **** **** **** **** +12364 Favoured_Soul_EXTRACT_VODARE **** **** **** **** **** **** **** **** +12365 Favoured_Soul_EXTRACT_SANNISH **** **** **** **** **** **** **** **** +12366 Favoured_Soul_EXTRACT_MUSHROOM_POWDER **** **** **** **** **** **** **** **** +12367 Favoured_Soul_EYES_OF_THE_AVORAL **** **** **** **** **** **** **** **** +12368 Favoured_Soul_HEARTACHE **** **** **** **** **** **** **** **** +12369 Favoured_Soul_HideFromUndead **** **** **** **** **** **** **** **** +12370 Favoured_Soul_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +12371 Favoured_Soul_LANTERN_LIGHT **** **** **** **** **** **** **** **** +12372 Favoured_Soul_LESSER_SHIVERING_TOUCH **** **** **** **** **** **** **** **** +12373 Favoured_Soul_Lesser_Vigor **** **** **** **** **** **** **** **** +12374 Favoured_Soul_Magic_Stone **** **** **** **** **** **** **** **** +12375 Favoured_Soul_Magic_Weapon **** **** **** **** **** **** **** **** +12376 Favoured_Soul_Necrotic_Awareness **** **** **** **** **** **** **** **** +12377 Favoured_Soul_Obscuring_Mist **** **** **** **** **** **** **** **** +12378 Favoured_Soul_Protection_from_Chaos **** **** **** **** **** **** **** **** +12379 Favoured_Soul_Protection_from_Evil **** **** **** **** **** **** **** **** +12380 Favoured_Soul_Protection_from_Good **** **** **** **** **** **** **** **** +12381 Favoured_Soul_Protection_from_Law **** **** **** **** **** **** **** **** +12382 Favoured_Soul_RAY_OF_HOPE **** **** **** **** **** **** **** **** +12383 Favoured_Soul_Remove_Fear **** **** **** **** **** **** **** **** +12384 Favoured_Soul_Sanctuary **** **** **** **** **** **** **** **** +12385 Favoured_Soul_Shield_of_Faith **** **** **** **** **** **** **** **** +12386 Favoured_Soul_SORROW **** **** **** **** **** **** **** **** +12387 Favoured_Soul_Summon_Creature_I **** **** **** **** **** **** **** **** +12388 Favoured_Soul_SummonUndeadI **** **** **** **** **** **** **** **** +12389 Favoured_Soul_TONGUE_OF_BAALZEBUL **** **** **** **** **** **** **** **** +12390 Favoured_Soul_VisionOfHeaven **** **** **** **** **** **** **** **** +12391 Favoured_Soul_ADDICTION **** **** **** **** **** **** **** **** +12392 Favoured_Soul_ADDICTION_TERRAN_BRANDY **** **** **** **** **** **** **** **** +12393 Favoured_Soul_ADDICTION_MUSHROOM_POWDER **** **** **** **** **** **** **** **** +12394 Favoured_Soul_ADDICTION_VODARE **** **** **** **** **** **** **** **** +12395 Favoured_Soul_ADDICTION_AGONY **** **** **** **** **** **** **** **** +12396 Favoured_Soul_Aid **** **** **** **** **** **** **** **** +12397 Favoured_Soul_Animalistic_Power **** **** **** **** **** **** **** **** +12398 Favoured_Soul_BONEBLAST **** **** **** **** **** **** **** **** +12399 Favoured_Soul_Bulls_Strength **** **** **** **** **** **** **** **** +12400 Favoured_Soul_Calm_Emotions **** **** **** **** **** **** **** **** +12401 Favoured_Soul_Consecrated_Aura **** **** **** **** **** **** **** **** +12402 Favoured_Soul_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +12403 Favoured_Soul_Darkness **** **** **** **** **** **** **** **** +12404 Favoured_Soul_Death_Knell **** **** **** **** **** **** **** **** +12405 Favoured_Soul_Divine_Protection **** **** **** **** **** **** **** **** +12406 Favoured_Soul_Eagle_Splendor **** **** **** **** **** **** **** **** +12407 Favoured_Soul_ELATION **** **** **** **** **** **** **** **** +12408 Favoured_Soul_Endurance **** **** **** **** **** **** **** **** +12409 Favoured_Soul_Find_Traps **** **** **** **** **** **** **** **** +12410 Favoured_Soul_Foxs_Cunning **** **** **** **** **** **** **** **** +12411 Favoured_Soul_Hold_Person **** **** **** **** **** **** **** **** +12412 Favoured_Soul_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +12413 Favoured_Soul_Lesser_Dispel **** **** **** **** **** **** **** **** +12414 Favoured_Soul_Lesser_Restoration **** **** **** **** **** **** **** **** +12415 Favoured_Soul_Living_Undeath **** **** **** **** **** **** **** **** +12416 Favoured_Soul_Necrotic_Cyst **** **** **** **** **** **** **** **** +12417 Favoured_Soul_Negative_Energy_Ray **** **** **** **** **** **** **** **** +12418 Favoured_Soul_Owls_Wisdom **** **** **** **** **** **** **** **** +12419 Favoured_Soul_Remove_Paralysis **** **** **** **** **** **** **** **** +12420 Favoured_Soul_Resist_Elements **** **** **** **** **** **** **** **** +12421 Favoured_Soul_ShieldOther **** **** **** **** **** **** **** **** +12422 Favoured_Soul_Silence **** **** **** **** **** **** **** **** +12423 Favoured_Soul_Sound_Burst **** **** **** **** **** **** **** **** +12424 Favoured_Soul_SPORES_OF_THE_VROCK **** **** **** **** **** **** **** **** +12425 Favoured_Soul_Stone_Bones **** **** **** **** **** **** **** **** +12426 Favoured_Soul_Summon_Creature_II **** **** **** **** **** **** **** **** +12427 Favoured_Soul_SummonUndeadII **** **** **** **** **** **** **** **** +12428 Favoured_Soul_Ultravision **** **** **** **** **** **** **** **** +12429 Favoured_Soul_UndetectableAlignment **** **** **** **** **** **** **** **** +12430 Favoured_Soul_WAVE_OF_GRIEF **** **** **** **** **** **** **** **** +12431 Favoured_Soul_Animate_Dead **** **** **** **** **** **** **** **** +12432 Favoured_Soul_Bestow_Curse **** **** **** **** **** **** **** **** +12433 Favoured_Soul_Blindness_and_Deafness **** **** **** **** **** **** **** **** +12434 Favoured_Soul_BONEBLADE **** **** **** **** **** **** **** **** +12435 Favoured_Soul_BONEBLADE_GREATSWORD **** **** **** **** **** **** **** **** +12436 Favoured_Soul_BONEBLADE_LONGSWORD **** **** **** **** **** **** **** **** +12437 Favoured_Soul_BONEBLADE_SHORTSWORD **** **** **** **** **** **** **** **** +12438 Favoured_Soul_Clarity **** **** **** **** **** **** **** **** +12439 Favoured_Soul_Close_Wounds **** **** **** **** **** **** **** **** +12440 Favoured_Soul_CLUTCH_OF_ORCUS **** **** **** **** **** **** **** **** +12441 Favoured_Soul_Contagion **** **** **** **** **** **** **** **** +12442 Favoured_Soul_Continual_Flame **** **** **** **** **** **** **** **** +12443 Favoured_Soul_Crown_Might **** **** **** **** **** **** **** **** +12444 Favoured_Soul_Crown_Protection **** **** **** **** **** **** **** **** +12445 Favoured_Soul_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +12446 Favoured_Soul_Curse_of_Petty_Failing **** **** **** **** **** **** **** **** +12447 Favoured_Soul_Darkfire **** **** **** **** **** **** **** **** +12448 Favoured_Soul_Daylight **** **** **** **** **** **** **** **** +12449 Favoured_Soul_DeeperDarkness **** **** **** **** **** **** **** **** +12450 Favoured_Soul_DEVILS_EYE **** **** **** **** **** **** **** **** +12451 Favoured_Soul_Dispel_Magic **** **** **** **** **** **** **** **** +12452 Favoured_Soul_ENERGIZE_POTION **** **** **** **** **** **** **** **** +12453 Favoured_Soul_ENERGIZE_POTION_ACID **** **** **** **** **** **** **** **** +12454 Favoured_Soul_ENERGIZE_POTION_COLD **** **** **** **** **** **** **** **** +12455 Favoured_Soul_ENERGIZE_POTION_ELECTRICITY **** **** **** **** **** **** **** **** +12456 Favoured_Soul_ENERGIZE_POTION_FIRE **** **** **** **** **** **** **** **** +12457 Favoured_Soul_ENERGIZE_POTION_SONIC **** **** **** **** **** **** **** **** +12458 Favoured_Soul_Energy_Aegis **** **** **** **** **** **** **** **** +12459 Favoured_Soul_Energy_Aegis_Acid **** **** **** **** **** **** **** **** +12460 Favoured_Soul_Energy_Aegis_Cold **** **** **** **** **** **** **** **** +12461 Favoured_Soul_Energy_Aegis_Elec **** **** **** **** **** **** **** **** +12462 Favoured_Soul_Energy_Aegis_Fire **** **** **** **** **** **** **** **** +12463 Favoured_Soul_Energy_Aegis_Sonic **** **** **** **** **** **** **** **** +12464 Favoured_Soul_FLESH_RIPPER **** **** **** **** **** **** **** **** +12465 Favoured_Soul_Glyph_of_Warding_Master **** **** **** **** **** **** **** **** +12466 Favoured_Soul_Glyph_of_Warding_Acid **** **** **** **** **** **** **** **** +12467 Favoured_Soul_Glyph_of_Warding_Cold **** **** **** **** **** **** **** **** +12468 Favoured_Soul_Glyph_of_Warding_Electricity **** **** **** **** **** **** **** **** +12469 Favoured_Soul_Glyph_of_Warding_Fire **** **** **** **** **** **** **** **** +12470 Favoured_Soul_Glyph_of_Warding_Sonic **** **** **** **** **** **** **** **** +12471 Favoured_Soul_Inflict_Serious_Wounds **** **** **** **** **** **** **** **** +12472 Favoured_Soul_Invisibility_Purge **** **** **** **** **** **** **** **** +12473 Favoured_Soul_Legions_Conviction **** **** **** **** **** **** **** **** +12474 Favoured_Soul_LocateObject **** **** **** **** **** **** **** **** +12475 Favoured_Soul_Magic_Circle_against_Chaos **** **** **** **** **** **** **** **** +12476 Favoured_Soul_Magic_Circle_against_Evil **** **** **** **** **** **** **** **** +12477 Favoured_Soul_Magic_Circle_against_Good **** **** **** **** **** **** **** **** +12478 Favoured_Soul_Magic_Circle_against_Law **** **** **** **** **** **** **** **** +12479 Favoured_Soul_Magic_Vestment **** **** **** **** **** **** **** **** +12480 Favoured_Soul_MASOCHISM **** **** **** **** **** **** **** **** +12481 Favoured_Soul_Mass_Aid **** **** **** **** **** **** **** **** +12482 Favoured_Soul_Mass_Lesser_Vigor **** **** **** **** **** **** **** **** +12483 Favoured_Soul_Necrotic_Bloat **** **** **** **** **** **** **** **** +12484 Favoured_Soul_Negative_Energy_Protection **** **** **** **** **** **** **** **** +12485 Favoured_Soul_ObscureObject **** **** **** **** **** **** **** **** +12486 Favoured_Soul_Prayer **** **** **** **** **** **** **** **** +12487 Favoured_Soul_Protection_from_Elements **** **** **** **** **** **** **** **** +12488 Favoured_Soul_Remove_Blindness_and_Deafness **** **** **** **** **** **** **** **** +12489 Favoured_Soul_Remove_Curse **** **** **** **** **** **** **** **** +12490 Favoured_Soul_Remove_Disease **** **** **** **** **** **** **** **** +12491 Favoured_Soul_RingOfBlades **** **** **** **** **** **** **** **** +12492 Favoured_Soul_Searing_Light **** **** **** **** **** **** **** **** +12493 Favoured_Soul_SHIVERING_TOUCH **** **** **** **** **** **** **** **** +12494 Favoured_Soul_SHRIVELING **** **** **** **** **** **** **** **** +12495 Favoured_Soul_Slashing_Darkness **** **** **** **** **** **** **** **** +12496 Favoured_Soul_Summon_Creature_III **** **** **** **** **** **** **** **** +12497 Favoured_Soul_SummonUndeadIII **** **** **** **** **** **** **** **** +12498 Favoured_Soul_UNLIVING_WEAPON **** **** **** **** **** **** **** **** +12499 Favoured_Soul_Vigor **** **** **** **** **** **** **** **** +12500 Favoured_Soul_WaterBreathing **** **** **** **** **** **** **** **** +12501 Favoured_Soul_WRACK **** **** **** **** **** **** **** **** +12502 Favoured_Soul_ABYSSAL_MIGHT **** **** **** **** **** **** **** **** +12503 Favoured_Soul_BloodOfTheMartyr **** **** **** **** **** **** **** **** +12504 Favoured_Soul_CLAWS_OF_THE_SAVAGE **** **** **** **** **** **** **** **** +12505 Favoured_Soul_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +12506 Favoured_Soul_DAMNING_DARKNESS **** **** **** **** **** **** **** **** +12507 Favoured_Soul_Death_Ward **** **** **** **** **** **** **** **** +12508 Favoured_Soul_Dimensional_Anchor **** **** **** **** **** **** **** **** +12509 Favoured_Soul_Dismissal **** **** **** **** **** **** **** **** +12510 Favoured_Soul_Divine_Power **** **** **** **** **** **** **** **** +12511 Favoured_Soul_Freedom_of_Movement **** **** **** **** **** **** **** **** +12512 Favoured_Soul_Greater_Magic_Weapon **** **** **** **** **** **** **** **** +12513 Favoured_Soul_Greater_Resistance **** **** **** **** **** **** **** **** +12514 Favoured_Soul_Hammer_of_the_Gods **** **** **** **** **** **** **** **** +12515 Favoured_Soul_Inflict_Critical_Wounds **** **** **** **** **** **** **** **** +12516 Favoured_Soul_Legions_Shield_of_Faith **** **** **** **** **** **** **** **** +12517 Favoured_Soul_Lesser_Planar_Ally **** **** **** **** **** **** **** **** +12518 Favoured_Soul_Lower_Spell_Resistance **** **** **** **** **** **** **** **** +12519 Favoured_Soul_Mass_Ultravision **** **** **** **** **** **** **** **** +12520 Favoured_Soul_Necrotic_Domination **** **** **** **** **** **** **** **** +12521 Favoured_Soul_Neutralize_Poison **** **** **** **** **** **** **** **** +12522 Favoured_Soul_Panacea **** **** **** **** **** **** **** **** +12523 Favoured_Soul_Poison **** **** **** **** **** **** **** **** +12524 Favoured_Soul_Recitation **** **** **** **** **** **** **** **** +12525 Favoured_Soul_RepelVermin **** **** **** **** **** **** **** **** +12526 Favoured_Soul_Restoration **** **** **** **** **** **** **** **** +12527 Favoured_Soul_STOP_HEART **** **** **** **** **** **** **** **** +12528 Favoured_Soul_Summon_Creature_IV **** **** **** **** **** **** **** **** +12529 Favoured_Soul_SummonUndeadIV **** **** **** **** **** **** **** **** +12530 Favoured_Soul_SwordOfConscience **** **** **** **** **** **** **** **** +12531 Favoured_Soul_Battletide **** **** **** **** **** **** **** **** +12532 Favoured_Soul_BreakEnchantment **** **** **** **** **** **** **** **** +12533 Favoured_Soul_CHAAVS_LAUGH **** **** **** **** **** **** **** **** +12534 Favoured_Soul_Circle_of_Doom **** **** **** **** **** **** **** **** +12535 Favoured_Soul_CONVERT_WAND **** **** **** **** **** **** **** **** +12536 Favoured_Soul_DANCING_WEB **** **** **** **** **** **** **** **** +12537 Favoured_Soul_FireInTheBlood **** **** **** **** **** **** **** **** +12538 Favoured_Soul_Flame_Strike **** **** **** **** **** **** **** **** +12539 Favoured_Soul_Greater_Vigor(Monstrous_Regeneration) **** **** **** **** **** **** **** **** +12540 Favoured_Soul_GreaterCommand_RadialMaster **** **** **** **** **** **** **** **** +12541 Favoured_Soul_GreaterCommand_Approach **** **** **** **** **** **** **** **** +12542 Favoured_Soul_GreaterCommand_Drop **** **** **** **** **** **** **** **** +12543 Favoured_Soul_GreaterCommand_Fall **** **** **** **** **** **** **** **** +12544 Favoured_Soul_GreaterCommand_Flee **** **** **** **** **** **** **** **** +12545 Favoured_Soul_GreaterCommand_Halt **** **** **** **** **** **** **** **** +12546 Favoured_Soul_Healing_Circle **** **** **** **** **** **** **** **** +12547 Favoured_Soul_HEARTCLUTCH **** **** **** **** **** **** **** **** +12548 Favoured_Soul_Legions_Curse_of_Petty_Failing **** **** **** **** **** **** **** **** +12549 Favoured_Soul_Mass_Contagion **** **** **** **** **** **** **** **** +12550 Favoured_Soul_Mass_Cure_Light_Wounds **** **** **** **** **** **** **** **** +12551 Favoured_Soul_Mass_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +12552 Favoured_Soul_MORALITY_UNDONE **** **** **** **** **** **** **** **** +12553 Favoured_Soul_Necrotic_Burst **** **** **** **** **** **** **** **** +12554 Favoured_Soul_Raise_Dead **** **** **** **** **** **** **** **** +12555 Favoured_Soul_RESONATING_RESISTANCE **** **** **** **** **** **** **** **** +12556 Favoured_Soul_Revivify **** **** **** **** **** **** **** **** +12557 Favoured_Soul_Righteous_Might **** **** **** **** **** **** **** **** +12558 Favoured_Soul_Scrying **** **** **** **** **** **** **** **** +12559 Favoured_Soul_Slay_Living **** **** **** **** **** **** **** **** +12560 Favoured_Soul_Soulscour **** **** **** **** **** **** **** **** +12561 Favoured_Soul_Spell_Resistance **** **** **** **** **** **** **** **** +12562 Favoured_Soul_Summon_Creature_V **** **** **** **** **** **** **** **** +12563 Favoured_Soul_SummonUndeadV **** **** **** **** **** **** **** **** +12564 Favoured_Soul_SYMBOL_OF_PAIN **** **** **** **** **** **** **** **** +12565 Favoured_Soul_SYMBOL_OF_SLEEP **** **** **** **** **** **** **** **** +12566 Favoured_Soul_True_Seeing **** **** **** **** **** **** **** **** +12567 Favoured_Soul_Animate_Object **** **** **** **** **** **** **** **** +12568 Favoured_Soul_Banishment **** **** **** **** **** **** **** **** +12569 Favoured_Soul_Blade_Barrier **** **** **** **** **** **** **** **** +12570 Favoured_Soul_CALL_FAITHFUL_SERVANTS **** **** **** **** **** **** **** **** +12571 Favoured_Soul_CELESTIAL_BLOOD **** **** **** **** **** **** **** **** +12572 Favoured_Soul_CLOUD_OF_THE_ACHAIERAI **** **** **** **** **** **** **** **** +12573 Favoured_Soul_Control_Undead **** **** **** **** **** **** **** **** +12574 Favoured_Soul_Create_Undead **** **** **** **** **** **** **** **** +12575 Favoured_Soul_Energy_Immunity **** **** **** **** **** **** **** **** +12576 Favoured_Soul_EI_Acid **** **** **** **** **** **** **** **** +12577 Favoured_Soul_EI_Cold **** **** **** **** **** **** **** **** +12578 Favoured_Soul_EI_Elec **** **** **** **** **** **** **** **** +12579 Favoured_Soul_EI_Fire **** **** **** **** **** **** **** **** +12580 Favoured_Soul_EI_Sonic **** **** **** **** **** **** **** **** +12581 Favoured_Soul_Etherealness **** **** **** **** **** **** **** **** +12582 Favoured_Soul_Greater_Dispelling **** **** **** **** **** **** **** **** +12583 Favoured_Soul_Greater_Glyph_of_Warding_Master **** **** **** **** **** **** **** **** +12584 Favoured_Soul_Greater_Glyph_of_Warding_Acid **** **** **** **** **** **** **** **** +12585 Favoured_Soul_Greater_Glyph_of_Warding_Cold **** **** **** **** **** **** **** **** +12586 Favoured_Soul_Greater_Glyph_of_Warding_Electricity **** **** **** **** **** **** **** **** +12587 Favoured_Soul_Greater_Glyph_of_Warding_Fire **** **** **** **** **** **** **** **** +12588 Favoured_Soul_Greater_Glyph_of_Warding_Sonic **** **** **** **** **** **** **** **** +12589 Favoured_Soul_Harm **** **** **** **** **** **** **** **** +12590 Favoured_Soul_Heal **** **** **** **** **** **** **** **** +12591 Favoured_Soul_Mass_Bulls_Strength **** **** **** **** **** **** **** **** +12592 Favoured_Soul_Mass_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +12593 Favoured_Soul_Mass_Eagle_Splendor **** **** **** **** **** **** **** **** +12594 Favoured_Soul_Mass_Endurance **** **** **** **** **** **** **** **** +12595 Favoured_Soul_Mass_Foxs_Cunning **** **** **** **** **** **** **** **** +12596 Favoured_Soul_Mass_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +12597 Favoured_Soul_Mass_Owls_Wisdom **** **** **** **** **** **** **** **** +12598 Favoured_Soul_Necrotic_Eruption **** **** **** **** **** **** **** **** +12599 Favoured_Soul_Planar_Ally **** **** **** **** **** **** **** **** +12600 Favoured_Soul_SarcophagusOfStone **** **** **** **** **** **** **** **** +12601 Favoured_Soul_Summon_Creature_VI **** **** **** **** **** **** **** **** +12602 Favoured_Soul_Superior_Resistance **** **** **** **** **** **** **** **** +12603 Favoured_Soul_SYMBOL_OF_FEAR **** **** **** **** **** **** **** **** +12604 Favoured_Soul_SYMBOL_OF_PERSUASION **** **** **** **** **** **** **** **** +12605 Favoured_Soul_THOUSAND_NEEDLES **** **** **** **** **** **** **** **** +12606 Favoured_Soul_Undeath_to_Death **** **** **** **** **** **** **** **** +12607 Favoured_Soul_Vigorous_Circle **** **** **** **** **** **** **** **** +12608 Favoured_Soul_WordOfRecall_RadialMaster **** **** **** **** **** **** **** **** +12609 Favoured_Soul_WordOfRecall_SelfOnly **** **** **** **** **** **** **** **** +12610 Favoured_Soul_WordOfRecall_Party **** **** **** **** **** **** **** **** +12611 Favoured_Soul_Blasphemy **** **** **** **** **** **** **** **** +12612 Favoured_Soul_Control_Weather **** **** **** **** **** **** **** **** +12613 Favoured_Soul_CW_Rain **** **** **** **** **** **** **** **** +12614 Favoured_Soul_CW_Snow **** **** **** **** **** **** **** **** +12615 Favoured_Soul_CW_Clear **** **** **** **** **** **** **** **** +12616 Favoured_Soul_Destruction **** **** **** **** **** **** **** **** +12617 Favoured_Soul_Dictum **** **** **** **** **** **** **** **** +12618 Favoured_Soul_Energy_Ebb **** **** **** **** **** **** **** **** +12619 Favoured_Soul_FIENDISH_CLARITY **** **** **** **** **** **** **** **** +12620 Favoured_Soul_Greater_Harm **** **** **** **** **** **** **** **** +12621 Favoured_Soul_Greater_Restoration **** **** **** **** **** **** **** **** +12622 Favoured_Soul_GreaterScrying **** **** **** **** **** **** **** **** +12623 Favoured_Soul_Holy_Word **** **** **** **** **** **** **** **** +12624 Favoured_Soul_Mass_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +12625 Favoured_Soul_Mass_Inflict_Serious_Wounds **** **** **** **** **** **** **** **** +12626 Favoured_Soul_Mass_Spell_Resistance **** **** **** **** **** **** **** **** +12627 Favoured_Soul_Regenerate **** **** **** **** **** **** **** **** +12628 Favoured_Soul_Repulsion **** **** **** **** **** **** **** **** +12629 Favoured_Soul_Resurrection **** **** **** **** **** **** **** **** +12630 Favoured_Soul_RIGHTEOUS_SMITE **** **** **** **** **** **** **** **** +12631 Favoured_Soul_Summon_Creature_VII **** **** **** **** **** **** **** **** +12632 Favoured_Soul_Summon7Air **** **** **** **** **** **** **** **** +12633 Favoured_Soul_Summon7Earth **** **** **** **** **** **** **** **** +12634 Favoured_Soul_Summon7Fire **** **** **** **** **** **** **** **** +12635 Favoured_Soul_Summon7Water **** **** **** **** **** **** **** **** +12636 Favoured_Soul_SYMBOL_OF_STUNING **** **** **** **** **** **** **** **** +12637 Favoured_Soul_SYMBOL_OF_WEAKNESS **** **** **** **** **** **** **** **** +12638 Favoured_Soul_TOMB_OF_LIGHT **** **** **** **** **** **** **** **** +12639 Favoured_Soul_Word_of_Chaos **** **** **** **** **** **** **** **** +12640 Favoured_Soul_WRETCHED_BLIGHT **** **** **** **** **** **** **** **** +12641 Favoured_Soul_ANTIMAGIC_FIELD **** **** **** **** **** **** **** **** +12642 Favoured_Soul_Aura_versus_Alignment **** **** **** **** **** **** **** **** +12643 Favoured_Soul_Unholy_Aura **** **** **** **** **** **** **** **** +12644 Favoured_Soul_Holy_Aura **** **** **** **** **** **** **** **** +12645 Favoured_Soul_BODAK_BIRTH **** **** **** **** **** **** **** **** +12646 Favoured_Soul_Create_Greater_Undead **** **** **** **** **** **** **** **** +12647 Favoured_Soul_Dimensional_Lock **** **** **** **** **** **** **** **** +12648 Favoured_Soul_DiscernLocation **** **** **** **** **** **** **** **** +12649 Favoured_Soul_Earthquake **** **** **** **** **** **** **** **** +12650 Favoured_Soul_Fire_Storm **** **** **** **** **** **** **** **** +12651 Favoured_Soul_Greater_Planar_Ally **** **** **** **** **** **** **** **** +12652 Favoured_Soul_Greater_Wall_of_Dispel_Magic **** **** **** **** **** **** **** **** +12653 Favoured_Soul_Holy_Aura **** **** **** **** **** **** **** **** +12654 Favoured_Soul_LAST_JUDGEMENT **** **** **** **** **** **** **** **** +12655 Favoured_Soul_Mass_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +12656 Favoured_Soul_Mass_Heal **** **** **** **** **** **** **** **** +12657 Favoured_Soul_Mass_Inflict_Critical_Wounds **** **** **** **** **** **** **** **** +12658 Favoured_Soul_Necrotic_Empowerment **** **** **** **** **** **** **** **** +12659 Favoured_Soul_Pestilence **** **** **** **** **** **** **** **** +12660 Favoured_Soul_Summon_Creature_VIII **** **** **** **** **** **** **** **** +12661 Favoured_Soul_Summon8Air **** **** **** **** **** **** **** **** +12662 Favoured_Soul_Summon8Earth **** **** **** **** **** **** **** **** +12663 Favoured_Soul_Summon8Fire **** **** **** **** **** **** **** **** +12664 Favoured_Soul_Summon8Water **** **** **** **** **** **** **** **** +12665 Favoured_Soul_Sunbeam **** **** **** **** **** **** **** **** +12666 Favoured_Soul_SYMBOL_OF_DEATH **** **** **** **** **** **** **** **** +12667 Favoured_Soul_SYMBOL_OF_INSANITY **** **** **** **** **** **** **** **** +12668 Favoured_Soul_DESPOIL **** **** **** **** **** **** **** **** +12669 Favoured_Soul_Elder_Glyph_of_Warding_Master **** **** **** **** **** **** **** **** +12670 Favoured_Soul_Elder_Glyph_of_Warding_Acid **** **** **** **** **** **** **** **** +12671 Favoured_Soul_Elder_Glyph_of_Warding_Cold **** **** **** **** **** **** **** **** +12672 Favoured_Soul_Elder_Glyph_of_Warding_Electricity **** **** **** **** **** **** **** **** +12673 Favoured_Soul_Elder_Glyph_of_Warding_Fire **** **** **** **** **** **** **** **** +12674 Favoured_Soul_Elder_Glyph_of_Warding_Sonic **** **** **** **** **** **** **** **** +12675 Favoured_Soul_Energy_Drain **** **** **** **** **** **** **** **** +12676 Favoured_Soul_Gate **** **** **** **** **** **** **** **** +12677 Favoured_Soul_Implosion **** **** **** **** **** **** **** **** +12678 Favoured_Soul_Mass_Harm **** **** **** **** **** **** **** **** +12679 Favoured_Soul_Necrotic_Termination **** **** **** **** **** **** **** **** +12680 Favoured_Soul_PlagueOfUndead **** **** **** **** **** **** **** **** +12681 Favoured_Soul_Storm_of_Vengeance **** **** **** **** **** **** **** **** +12682 Favoured_Soul_Summon_Creature_IX **** **** **** **** **** **** **** **** +12683 Favoured_Soul_Summon9Air **** **** **** **** **** **** **** **** +12684 Favoured_Soul_Summon9Earth **** **** **** **** **** **** **** **** +12685 Favoured_Soul_Summon9Fire **** **** **** **** **** **** **** **** +12686 Favoured_Soul_Summon9Water **** **** **** **** **** **** **** **** +12687 Favoured_Soul_True_Resurrection **** **** **** **** **** **** **** **** +12688 Favoured_Soul_Undeaths_Eternal_Foe **** **** **** **** **** **** **** **** +12689 Favoured_Soul_VileDeath **** **** **** **** **** **** **** **** +12690 Sohei_Bane **** **** **** **** **** **** **** **** +12691 Sohei_Exteneded_Bane **** **** **** **** **** **** **** **** +12692 Sohei_Silent_Bane **** **** **** **** **** **** **** **** +12693 Sohei_Still_Bane **** **** **** **** **** **** **** **** +12694 Sohei_Bless **** **** **** **** **** **** **** **** +12695 Sohei_Exteneded_Bless **** **** **** **** **** **** **** **** +12696 Sohei_Silent_Bless **** **** **** **** **** **** **** **** +12697 Sohei_Still_Bless **** **** **** **** **** **** **** **** +12698 Sohei_Bless_Weapon **** **** **** **** **** **** **** **** +12699 Sohei_Exteneded_Bless_Weapon **** **** **** **** **** **** **** **** +12700 Sohei_Silent_Bless_Weapon **** **** **** **** **** **** **** **** +12701 Sohei_Still_Bless_Weapon **** **** **** **** **** **** **** **** +12702 Sohei_Detect_Chaos **** **** **** **** **** **** **** **** +12703 Sohei_Exteneded_Detect_Chaos **** **** **** **** **** **** **** **** +12704 Sohei_Silent_Detect_Chaos **** **** **** **** **** **** **** **** +12705 Sohei_Still_Detect_Chaos **** **** **** **** **** **** **** **** +12706 Sohei_Detect_Law **** **** **** **** **** **** **** **** +12707 Sohei_Exteneded_Detect_Law **** **** **** **** **** **** **** **** +12708 Sohei_Silent_Detect_Law **** **** **** **** **** **** **** **** +12709 Sohei_Still_Detect_Law **** **** **** **** **** **** **** **** +12710 Sohei_Divine_Favor **** **** **** **** **** **** **** **** +12711 Sohei_Exteneded_Divine_Favor **** **** **** **** **** **** **** **** +12712 Sohei_Silent_Divine_Favor **** **** **** **** **** **** **** **** +12713 Sohei_Still_Divine_Favor **** **** **** **** **** **** **** **** +12714 Sohei_DIVINE_INSPIRATION **** **** **** **** **** **** **** **** +12715 Sohei_Exteneded_DIVINE_INSPIRATION **** **** **** **** **** **** **** **** +12716 Sohei_Doom **** **** **** **** **** **** **** **** +12717 Sohei_Exteneded_Doom **** **** **** **** **** **** **** **** +12718 Sohei_Silent_Doom **** **** **** **** **** **** **** **** +12719 Sohei_Still_Doom **** **** **** **** **** **** **** **** +12720 Sohei_Endure_Elements **** **** **** **** **** **** **** **** +12721 Sohei_Exteneded_Endure_Elements **** **** **** **** **** **** **** **** +12722 Sohei_Silent_Endure_Elements **** **** **** **** **** **** **** **** +12723 Sohei_Still_Endure_Elements **** **** **** **** **** **** **** **** +12724 Sohei_Magic_Weapon **** **** **** **** **** **** **** **** +12725 Sohei_Exteneded_Magic_Weapon **** **** **** **** **** **** **** **** +12726 Sohei_Silent_Magic_Weapon **** **** **** **** **** **** **** **** +12727 Sohei_Still_Magic_Weapon **** **** **** **** **** **** **** **** +12728 Sohei_Protection_from_Chaos **** **** **** **** **** **** **** **** +12729 Sohei_Exteneded_Protection_from_Chaos **** **** **** **** **** **** **** **** +12730 Sohei_Silent_Protection_from_Chaos **** **** **** **** **** **** **** **** +12731 Sohei_Still_Protection_from_Chaos **** **** **** **** **** **** **** **** +12732 Sohei_Resistance **** **** **** **** **** **** **** **** +12733 Sohei_Exteneded_Resistance **** **** **** **** **** **** **** **** +12734 Sohei_Silent_Resistance **** **** **** **** **** **** **** **** +12735 Sohei_Still_Resistance **** **** **** **** **** **** **** **** +12736 Sohei_SEETHING_EYEBANE **** **** **** **** **** **** **** **** +12737 Sohei_Silent_SEETHING_EYEBANE **** **** **** **** **** **** **** **** +12738 Sohei_Still_SEETHING_EYEBANE **** **** **** **** **** **** **** **** +12739 Sohei_Shield_of_Faith **** **** **** **** **** **** **** **** +12740 Sohei_Exteneded_Shield_of_Faith **** **** **** **** **** **** **** **** +12741 Sohei_Silent_Shield_of_Faith **** **** **** **** **** **** **** **** +12742 Sohei_Still_Shield_of_Faith **** **** **** **** **** **** **** **** +12743 Sohei_TWILIGHT_LUCK **** **** **** **** **** **** **** **** +12744 Sohei_Exteneded_TWILIGHT_LUCK **** **** **** **** **** **** **** **** +12745 Sohei_Silent_TWILIGHT_LUCK **** **** **** **** **** **** **** **** +12746 Sohei_Virtue **** **** **** **** **** **** **** **** +12747 Sohei_Exteneded_Virtue **** **** **** **** **** **** **** **** +12748 Sohei_Silent_Virtue **** **** **** **** **** **** **** **** +12749 Sohei_Still_Virtue **** **** **** **** **** **** **** **** +12750 Sohei_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +12751 Sohei_Empowered_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +12752 Sohei_Silent_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +12753 Sohei_Still_AYAILLAS_RADIANT_BURST **** **** **** **** **** **** **** **** +12754 Sohei_Bulls_Strength **** **** **** **** **** **** **** **** +12755 Sohei_Empowered_Bulls_Strength **** **** **** **** **** **** **** **** +12756 Sohei_Exteneded_Bulls_Strength **** **** **** **** **** **** **** **** +12757 Sohei_Silent_Bulls_Strength **** **** **** **** **** **** **** **** +12758 Sohei_Still_Bulls_Strength **** **** **** **** **** **** **** **** +12759 Sohei_LAHMS_FINGER_DARTS **** **** **** **** **** **** **** **** +12760 Sohei_Silent_LAHMS_FINGER_DARTS **** **** **** **** **** **** **** **** +12761 Sohei_Still_LAHMS_FINGER_DARTS **** **** **** **** **** **** **** **** +12762 Sohei_Lesser_Restoration **** **** **** **** **** **** **** **** +12763 Sohei_Silent_Lesser_Restoration **** **** **** **** **** **** **** **** +12764 Sohei_Still_Lesser_Restoration **** **** **** **** **** **** **** **** +12765 Sohei_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +12766 Sohei_Exteneded_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +12767 Sohei_Remove_Paralysis **** **** **** **** **** **** **** **** +12768 Sohei_Silent_Remove_Paralysis **** **** **** **** **** **** **** **** +12769 Sohei_Still_Remove_Paralysis **** **** **** **** **** **** **** **** +12770 Sohei_Resist_Elements **** **** **** **** **** **** **** **** +12771 Sohei_Exteneded_Resist_Elements **** **** **** **** **** **** **** **** +12772 Sohei_Silent_Resist_Elements **** **** **** **** **** **** **** **** +12773 Sohei_Still_Resist_Elements **** **** **** **** **** **** **** **** +12774 Sohei_ShieldOther **** **** **** **** **** **** **** **** +12775 Sohei_Exteneded_ShieldOther **** **** **** **** **** **** **** **** +12776 Sohei_Silent_ShieldOther **** **** **** **** **** **** **** **** +12777 Sohei_Still_ShieldOther **** **** **** **** **** **** **** **** +12778 Sohei_BRILLIANT_EMANATION **** **** **** **** **** **** **** **** +12779 Sohei_Exteneded_BRILLIANT_EMANATION **** **** **** **** **** **** **** **** +12780 Sohei_Dispel_Magic **** **** **** **** **** **** **** **** +12781 Sohei_Silent_Dispel_Magic **** **** **** **** **** **** **** **** +12782 Sohei_Still_Dispel_Magic **** **** **** **** **** **** **** **** +12783 Sohei_Greater_Magic_Weapon **** **** **** **** **** **** **** **** +12784 Sohei_Exteneded_Greater_Magic_Weapon **** **** **** **** **** **** **** **** +12785 Sohei_Silent_Greater_Magic_Weapon **** **** **** **** **** **** **** **** +12786 Sohei_Still_Greater_Magic_Weapon **** **** **** **** **** **** **** **** +12787 Sohei_HAMMER_OF_RIGHTEOUSNESS **** **** **** **** **** **** **** **** +12788 Sohei_Silent_HAMMER_OF_RIGHTEOUSNESS **** **** **** **** **** **** **** **** +12789 Sohei_Still_HAMMER_OF_RIGHTEOUSNESS **** **** **** **** **** **** **** **** +12790 Sohei_Magic_Circle_against_Chaos **** **** **** **** **** **** **** **** +12791 Sohei_Exteneded_Magic_Circle_against_Chaos **** **** **** **** **** **** **** **** +12792 Sohei_Silent_Magic_Circle_against_Chaos **** **** **** **** **** **** **** **** +12793 Sohei_Still_Magic_Circle_against_Chaos **** **** **** **** **** **** **** **** +12794 Sohei_Prayer **** **** **** **** **** **** **** **** +12795 Sohei_Exteneded_Prayer **** **** **** **** **** **** **** **** +12796 Sohei_Silent_Prayer **** **** **** **** **** **** **** **** +12797 Sohei_Still_Prayer **** **** **** **** **** **** **** **** +12798 Sohei_Protection_from_Elements **** **** **** **** **** **** **** **** +12799 Sohei_Exteneded_Protection_from_Elements **** **** **** **** **** **** **** **** +12800 Sohei_Silent_Protection_from_Elements **** **** **** **** **** **** **** **** +12801 Sohei_Still_Protection_from_Elements **** **** **** **** **** **** **** **** +12802 Sohei_RED_FESTER **** **** **** **** **** **** **** **** +12803 Sohei_Silent_RED_FESTER **** **** **** **** **** **** **** **** +12804 Sohei_Still_RED_FESTER **** **** **** **** **** **** **** **** +12805 Sohei_ROTTING_CURSE_OF_URFESTRA **** **** **** **** **** **** **** **** +12806 Sohei_Silent_ROTTING_CURSE_OF_URFESTRA **** **** **** **** **** **** **** **** +12807 Sohei_Still_ROTTING_CURSE_OF_URFESTRA **** **** **** **** **** **** **** **** +12808 Sohei_TOUCH_OF_JUIBLEX **** **** **** **** **** **** **** **** +12809 Sohei_Silent_TOUCH_OF_JUIBLEX **** **** **** **** **** **** **** **** +12810 Sohei_Still_TOUCH_OF_JUIBLEX **** **** **** **** **** **** **** **** +12811 Sohei_ABSORB_STRENGTH **** **** **** **** **** **** **** **** +12812 Sohei_Death_Ward **** **** **** **** **** **** **** **** +12813 Sohei_DIAMOND_SPRAY **** **** **** **** **** **** **** **** +12814 Sohei_Divine_Power **** **** **** **** **** **** **** **** +12815 Sohei_Freedom_of_Movement **** **** **** **** **** **** **** **** +12816 Sohei_GREATER_LUMINOUS_ARMOR **** **** **** **** **** **** **** **** +12817 Sohei_Hammer_of_the_Gods **** **** **** **** **** **** **** **** +12818 Sohei_Neutralize_Poison **** **** **** **** **** **** **** **** +12819 Sohei_Restoration **** **** **** **** **** **** **** **** +12820 Sohei_SUNMANTLE **** **** **** **** **** **** **** **** +12821 Warmage_Acid_Splash **** **** **** **** **** **** **** **** +12822 Warmage_Dancing_Lights **** **** **** **** **** **** **** **** +12823 Warmage_DisruptUndead **** **** **** **** **** **** **** **** +12824 Warmage_Electric_Jolt **** **** **** **** **** **** **** **** +12825 Warmage_Flare **** **** **** **** **** **** **** **** +12826 Warmage_Light **** **** **** **** **** **** **** **** +12827 Warmage_Ray_of_Frost **** **** **** **** **** **** **** **** +12828 Warmage_Bigbys_Tripping_Hand **** **** **** **** **** **** **** **** +12829 Warmage_Burning_Bolt **** **** **** **** **** **** **** **** +12830 Warmage_Burning_Hands **** **** **** **** **** **** **** **** +12831 Warmage_Chill_Touch **** **** **** **** **** **** **** **** +12832 Warmage_FistOfStone **** **** **** **** **** **** **** **** +12833 Warmage_Hail_of_Stone **** **** **** **** **** **** **** **** +12834 Warmage_Horizikauls_Boom **** **** **** **** **** **** **** **** +12835 Warmage_Ice_Dagger **** **** **** **** **** **** **** **** +12836 Warmage_Kelgores_Fire_Bolt **** **** **** **** **** **** **** **** +12837 Warmage_LANTERN_LIGHT **** **** **** **** **** **** **** **** +12838 Warmage_Lesser_Acid_Orb **** **** **** **** **** **** **** **** +12839 Warmage_Lesser_Cold_Orb **** **** **** **** **** **** **** **** +12840 Warmage_Lesser_Electric_Orb **** **** **** **** **** **** **** **** +12841 Warmage_Lesser_Fire_Orb **** **** **** **** **** **** **** **** +12842 Warmage_LESSER_SHIVERING_TOUCH **** **** **** **** **** **** **** **** +12843 Warmage_Lesser_Sonic_Orb **** **** **** **** **** **** **** **** +12844 Warmage_Magic_Missile **** **** **** **** **** **** **** **** +12845 Warmage_Shelgarns_Persistent_Blade **** **** **** **** **** **** **** **** +12846 Warmage_ShockingGrasp **** **** **** **** **** **** **** **** +12847 Warmage_Snillocs_Snowball **** **** **** **** **** **** **** **** +12848 Warmage_TensersFloatingDisk **** **** **** **** **** **** **** **** +12849 Warmage_True_Strike **** **** **** **** **** **** **** **** +12850 Warmage_Agnazzars_Scorcher **** **** **** **** **** **** **** **** +12851 Warmage_Bigbys_Striking_Fist **** **** **** **** **** **** **** **** +12852 Warmage_BladesOfFire **** **** **** **** **** **** **** **** +12853 Warmage_Cloud_of_Bewilderment **** **** **** **** **** **** **** **** +12854 Warmage_Combust **** **** **** **** **** **** **** **** +12855 Warmage_Continual_Flame **** **** **** **** **** **** **** **** +12856 Warmage_Darkness **** **** **** **** **** **** **** **** +12857 Warmage_Fireburst **** **** **** **** **** **** **** **** +12858 Warmage_FireTrap **** **** **** **** **** **** **** **** +12859 Warmage_Flame_Weapon **** **** **** **** **** **** **** **** +12860 Warmage_Gedlees_Electric_Loop **** **** **** **** **** **** **** **** +12861 Warmage_IceKnife **** **** **** **** **** **** **** **** +12862 Warmage_Melfs_Acid_Arrow **** **** **** **** **** **** **** **** +12863 Warmage_Pyrotechnics **** **** **** **** **** **** **** **** +12864 Warmage_Pyrotechnics_Fireworks **** **** **** **** **** **** **** **** +12865 Warmage_Pyrotechnics_Smoke **** **** **** **** **** **** **** **** +12866 Warmage_ScorchingRay **** **** **** **** **** **** **** **** +12867 Warmage_Seeking_Ray **** **** **** **** **** **** **** **** +12868 Warmage_Snillocs_Snowball_Swarm **** **** **** **** **** **** **** **** +12869 Warmage_WhirlingBlade **** **** **** **** **** **** **** **** +12870 Warmage_Daylight **** **** **** **** **** **** **** **** +12871 Warmage_DREAD_WORD **** **** **** **** **** **** **** **** +12872 Warmage_Elemental_Shield **** **** **** **** **** **** **** **** +12873 Warmage_Fireball **** **** **** **** **** **** **** **** +12874 Warmage_Flame_Arrow **** **** **** **** **** **** **** **** +12875 Warmage_Flashburst **** **** **** **** **** **** **** **** +12876 Warmage_Forceblast **** **** **** **** **** **** **** **** +12877 Warmage_Gust_of_Wind **** **** **** **** **** **** **** **** +12878 Warmage_Ice_Burst **** **** **** **** **** **** **** **** +12879 Warmage_Ice_Storm **** **** **** **** **** **** **** **** +12880 Warmage_Lightning_Bolt **** **** **** **** **** **** **** **** +12881 Warmage_PnP_FireShield **** **** **** **** **** **** **** **** +12882 Warmage_PnP_FireShieldRed **** **** **** **** **** **** **** **** +12883 Warmage_PnPFireShieldBlue **** **** **** **** **** **** **** **** +12884 Warmage_Poison **** **** **** **** **** **** **** **** +12885 Warmage_RainbowBlast **** **** **** **** **** **** **** **** +12886 Warmage_RingOfBlades **** **** **** **** **** **** **** **** +12887 Warmage_Scintillating_Sphere **** **** **** **** **** **** **** **** +12888 Warmage_Serpents_Sigh **** **** **** **** **** **** **** **** +12889 Warmage_SS_Bolt_of_Acid **** **** **** **** **** **** **** **** +12890 Warmage_SS_Bolt_of_Lightning **** **** **** **** **** **** **** **** +12891 Warmage_SS_Cone_of_Acid **** **** **** **** **** **** **** **** +12892 Warmage_SS_Cone_of_Cold **** **** **** **** **** **** **** **** +12893 Warmage_SS_Cone_of_Fire **** **** **** **** **** **** **** **** +12894 Warmage_SHIVERING_TOUCH **** **** **** **** **** **** **** **** +12895 Warmage_SleetStorm **** **** **** **** **** **** **** **** +12896 Warmage_Stinking_Cloud **** **** **** **** **** **** **** **** +12897 Warmage_Acid_Orb **** **** **** **** **** **** **** **** +12898 Warmage_Blast_of_Flame **** **** **** **** **** **** **** **** +12899 Warmage_Channeled_Pyroburst **** **** **** **** **** **** **** **** +12900 Warmage_Channeled_Pyroburst_Swift **** **** **** **** **** **** **** **** +12901 Warmage_Channeled_Pyroburst_Standard **** **** **** **** **** **** **** **** +12902 Warmage_Channeled_Pyroburst_Full **** **** **** **** **** **** **** **** +12903 Warmage_Channeled_Pyroburst_Two **** **** **** **** **** **** **** **** +12904 Warmage_Cold_Orb **** **** **** **** **** **** **** **** +12905 Warmage_Contagion **** **** **** **** **** **** **** **** +12906 Warmage_DAMNING_DARKNESS **** **** **** **** **** **** **** **** +12907 Warmage_DANCING_WEB **** **** **** **** **** **** **** **** +12908 Warmage_Electric_Orb **** **** **** **** **** **** **** **** +12909 Warmage_Evards_Black_Tentacles **** **** **** **** **** **** **** **** +12910 Warmage_Fire_Orb **** **** **** **** **** **** **** **** +12911 Warmage_Isaacs_Lesser_Missile_Storm **** **** **** **** **** **** **** **** +12912 Warmage_OrbOfForce **** **** **** **** **** **** **** **** +12913 Warmage_Otilukes_Resilient_Sphere **** **** **** **** **** **** **** **** +12914 Warmage_Phantasmal_Killer **** **** **** **** **** **** **** **** +12915 Warmage_Shout **** **** **** **** **** **** **** **** +12916 Warmage_Sonic_Orb **** **** **** **** **** **** **** **** +12917 Warmage_Wall_of_Fire **** **** **** **** **** **** **** **** +12918 Warmage_Ball_Lightning **** **** **** **** **** **** **** **** +12919 Warmage_Bigbys_Interposing_Hand **** **** **** **** **** **** **** **** +12920 Warmage_Cloudkill **** **** **** **** **** **** **** **** +12921 Warmage_Cone_of_Cold **** **** **** **** **** **** **** **** +12922 Warmage_Firebrand **** **** **** **** **** **** **** **** +12923 Warmage_Flame_Strike **** **** **** **** **** **** **** **** +12924 Warmage_Greater_Fireburst **** **** **** **** **** **** **** **** +12925 Warmage_Magic_Missile **** **** **** **** **** **** **** **** +12926 Warmage_MassFireShield **** **** **** **** **** **** **** **** +12927 Warmage_MassFireShieldRed **** **** **** **** **** **** **** **** +12928 Warmage_MassFireShieldBlue **** **** **** **** **** **** **** **** +12929 Warmage_PrismaticRay **** **** **** **** **** **** **** **** +12930 Warmage_Sonic_Shield **** **** **** **** **** **** **** **** +12931 Warmage_Acid_Fog **** **** **** **** **** **** **** **** +12932 Warmage_Acid_Storm **** **** **** **** **** **** **** **** +12933 Warmage_Bigbys_Forceful_Hand **** **** **** **** **** **** **** **** +12934 Warmage_Blade_Barrier **** **** **** **** **** **** **** **** +12935 Warmage_Chain_Lightning **** **** **** **** **** **** **** **** +12936 Warmage_Circle_of_Death **** **** **** **** **** **** **** **** +12937 Warmage_Disintegrate **** **** **** **** **** **** **** **** +12938 Warmage_Isaacs_Greater_Missile_Storm **** **** **** **** **** **** **** **** +12939 Warmage_OtilukesFreezingSphere **** **** **** **** **** **** **** **** +12940 Warmage_Tensers_Transformation **** **** **** **** **** **** **** **** +12941 Warmage_AMBER_SARCOPHAGUS **** **** **** **** **** **** **** **** +12942 Warmage_Bigbys_Grasping_Hand **** **** **** **** **** **** **** **** +12943 Warmage_Delayed_Blast_Fireball **** **** **** **** **** **** **** **** +12944 Warmage_Earthquake **** **** **** **** **** **** **** **** +12945 Warmage_Finger_of_Death **** **** **** **** **** **** **** **** +12946 Warmage_Fire_Storm **** **** **** **** **** **** **** **** +12947 Warmage_Great_Thunderclap **** **** **** **** **** **** **** **** +12948 Warmage_Prismatic_Spray **** **** **** **** **** **** **** **** +12949 Warmage_Sunbeam **** **** **** **** **** **** **** **** +12950 Warmage_WavesOfExhaustion **** **** **** **** **** **** **** **** +12951 Warmage_Bigbys_Clenched_Fist **** **** **** **** **** **** **** **** +12952 Warmage_Flensing **** **** **** **** **** **** **** **** +12953 Warmage_Greater_Shout **** **** **** **** **** **** **** **** +12954 Warmage_Horrid_Wilting **** **** **** **** **** **** **** **** +12955 Warmage_Incendiary_Cloud **** **** **** **** **** **** **** **** +12956 Warmage_PolarRay **** **** **** **** **** **** **** **** +12957 Warmage_PrismaticWall **** **** **** **** **** **** **** **** +12958 Warmage_ScintillatingPattern **** **** **** **** **** **** **** **** +12959 Warmage_Sunburst **** **** **** **** **** **** **** **** +12960 Warmage_Bigbys_Crushing_Hand **** **** **** **** **** **** **** **** +12961 Warmage_CRUSHING_FIST_OF_SPITE **** **** **** **** **** **** **** **** +12962 Warmage_Elemental_Swarm **** **** **** **** **** **** **** **** +12963 Warmage_Implosion **** **** **** **** **** **** **** **** +12964 Warmage_Meteor_Swarm **** **** **** **** **** **** **** **** +12965 Warmage_PrismaticSphere **** **** **** **** **** **** **** **** +12966 Warmage_Wail_of_the_Banshee **** **** **** **** **** **** **** **** +12967 Warmage_Weird **** **** **** **** **** **** **** **** +12968 NentyarHunter_Barkskin **** **** **** **** **** **** **** **** +12969 NentyarHunter_Exteneded_Barkskin **** **** **** **** **** **** **** **** +12970 NentyarHunter_Quickened_Barkskin **** **** **** **** **** **** **** **** +12971 NentyarHunter_Silent_Barkskin **** **** **** **** **** **** **** **** +12972 NentyarHunter_Still_Barkskin **** **** **** **** **** **** **** **** +12973 NentyarHunter_Cure_Light_Wounds **** **** **** **** **** **** **** **** +12974 NentyarHunter_Empowered_Cure_Light_Wounds **** **** **** **** **** **** **** **** +12975 NentyarHunter_Maximized_Cure_Light_Wounds **** **** **** **** **** **** **** **** +12976 NentyarHunter_Quickened_Cure_Light_Wounds **** **** **** **** **** **** **** **** +12977 NentyarHunter_Silent_Cure_Light_Wounds **** **** **** **** **** **** **** **** +12978 NentyarHunter_Still_Cure_Light_Wounds **** **** **** **** **** **** **** **** +12979 NentyarHunter_Entangle **** **** **** **** **** **** **** **** +12980 NentyarHunter_Exteneded_Entangle **** **** **** **** **** **** **** **** +12981 NentyarHunter_Quickened_Entangle **** **** **** **** **** **** **** **** +12982 NentyarHunter_Silent_Entangle **** **** **** **** **** **** **** **** +12983 NentyarHunter_Still_Entangle **** **** **** **** **** **** **** **** +12984 NentyarHunter_Spell_Jump **** **** **** **** **** **** **** **** +12985 NentyarHunter_Exteneded_Spell_Jump **** **** **** **** **** **** **** **** +12986 NentyarHunter_Quickened_Spell_Jump **** **** **** **** **** **** **** **** +12987 NentyarHunter_Silent_Spell_Jump **** **** **** **** **** **** **** **** +12988 NentyarHunter_Still_Spell_Jump **** **** **** **** **** **** **** **** +12989 NentyarHunter_Light **** **** **** **** **** **** **** **** +12990 NentyarHunter_Exteneded_Light **** **** **** **** **** **** **** **** +12991 NentyarHunter_Quickened_Light **** **** **** **** **** **** **** **** +12992 NentyarHunter_Silent_Light **** **** **** **** **** **** **** **** +12993 NentyarHunter_Magic_Missile **** **** **** **** **** **** **** **** +12994 NentyarHunter_Empowered_Magic_Missile **** **** **** **** **** **** **** **** +12995 NentyarHunter_Maximized_Magic_Missile **** **** **** **** **** **** **** **** +12996 NentyarHunter_Quickened_Magic_Missile **** **** **** **** **** **** **** **** +12997 NentyarHunter_Silent_Magic_Missile **** **** **** **** **** **** **** **** +12998 NentyarHunter_Still_Magic_Missile **** **** **** **** **** **** **** **** +12999 NentyarHunter_Snare **** **** **** **** **** **** **** **** +13000 NentyarHunter_Quickened_Snare **** **** **** **** **** **** **** **** +13001 NentyarHunter_Silent_Snare **** **** **** **** **** **** **** **** +13002 NentyarHunter_Still_Snare **** **** **** **** **** **** **** **** +13003 NentyarHunter_True_Strike **** **** **** **** **** **** **** **** +13004 NentyarHunter_Quickened_True_Strike **** **** **** **** **** **** **** **** +13005 NentyarHunter_Silent_True_Strike **** **** **** **** **** **** **** **** +13006 NentyarHunter_Agnazzars_Scorcher **** **** **** **** **** **** **** **** +13007 NentyarHunter_Empowered_Agnazzars_Scorcher **** **** **** **** **** **** **** **** +13008 NentyarHunter_Maximized_Agnazzars_Scorcher **** **** **** **** **** **** **** **** +13009 NentyarHunter_Silent_Agnazzars_Scorcher **** **** **** **** **** **** **** **** +13010 NentyarHunter_Still_Agnazzars_Scorcher **** **** **** **** **** **** **** **** +13011 NentyarHunter_Blur **** **** **** **** **** **** **** **** +13012 NentyarHunter_Exteneded_Blur **** **** **** **** **** **** **** **** +13013 NentyarHunter_Silent_Blur **** **** **** **** **** **** **** **** +13014 NentyarHunter_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +13015 NentyarHunter_Empowered_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +13016 NentyarHunter_Maximized_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +13017 NentyarHunter_Silent_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +13018 NentyarHunter_Still_Cure_Moderate_Wounds **** **** **** **** **** **** **** **** +13019 NentyarHunter_Gust_of_Wind **** **** **** **** **** **** **** **** +13020 NentyarHunter_Silent_Gust_of_Wind **** **** **** **** **** **** **** **** +13021 NentyarHunter_Still_Gust_of_Wind **** **** **** **** **** **** **** **** +13022 NentyarHunter_Neutralize_Poison **** **** **** **** **** **** **** **** +13023 NentyarHunter_Silent_Neutralize_Poison **** **** **** **** **** **** **** **** +13024 NentyarHunter_Still_Neutralize_Poison **** **** **** **** **** **** **** **** +13025 NentyarHunter_Remove_Disease **** **** **** **** **** **** **** **** +13026 NentyarHunter_Silent_Remove_Disease **** **** **** **** **** **** **** **** +13027 NentyarHunter_Still_Remove_Disease **** **** **** **** **** **** **** **** +13028 NentyarHunter_Resist_Elements **** **** **** **** **** **** **** **** +13029 NentyarHunter_Exteneded_Resist_Elements **** **** **** **** **** **** **** **** +13030 NentyarHunter_Silent_Resist_Elements **** **** **** **** **** **** **** **** +13031 NentyarHunter_Still_Resist_Elements **** **** **** **** **** **** **** **** +13032 NentyarHunter_Treeshape **** **** **** **** **** **** **** **** +13033 NentyarHunter_Exteneded_Treeshape **** **** **** **** **** **** **** **** +13034 NentyarHunter_Silent_Treeshape **** **** **** **** **** **** **** **** +13035 NentyarHunter_Still_Treeshape **** **** **** **** **** **** **** **** +13036 NentyarHunter_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +13037 NentyarHunter_Empowered_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +13038 NentyarHunter_Silent_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +13039 NentyarHunter_Still_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +13040 NentyarHunter_Freedom_of_Movement **** **** **** **** **** **** **** **** +13041 NentyarHunter_Exteneded_Freedom_of_Movement **** **** **** **** **** **** **** **** +13042 NentyarHunter_Silent_Freedom_of_Movement **** **** **** **** **** **** **** **** +13043 NentyarHunter_Still_Freedom_of_Movement **** **** **** **** **** **** **** **** +13044 NentyarHunter_Greenfire **** **** **** **** **** **** **** **** +13045 NentyarHunter_Empowered_Greenfire **** **** **** **** **** **** **** **** +13046 NentyarHunter_Exteneded_Greenfire **** **** **** **** **** **** **** **** +13047 NentyarHunter_Silent_Greenfire **** **** **** **** **** **** **** **** +13048 NentyarHunter_Still_Greenfire **** **** **** **** **** **** **** **** +13049 NentyarHunter_Invisibility **** **** **** **** **** **** **** **** +13050 NentyarHunter_Exteneded_Invisibility **** **** **** **** **** **** **** **** +13051 NentyarHunter_Silent_Invisibility **** **** **** **** **** **** **** **** +13052 NentyarHunter_Still_Invisibility **** **** **** **** **** **** **** **** +13053 NentyarHunter_Keen_Edge **** **** **** **** **** **** **** **** +13054 NentyarHunter_Exteneded_Keen_Edge **** **** **** **** **** **** **** **** +13055 NentyarHunter_Silent_Keen_Edge **** **** **** **** **** **** **** **** +13056 NentyarHunter_Still_Keen_Edge **** **** **** **** **** **** **** **** +13057 NentyarHunter_See_Invisibility **** **** **** **** **** **** **** **** +13058 NentyarHunter_Exteneded_See_Invisibility **** **** **** **** **** **** **** **** +13059 NentyarHunter_Silent_See_Invisibility **** **** **** **** **** **** **** **** +13060 NentyarHunter_Still_See_Invisibility **** **** **** **** **** **** **** **** +13061 NentyarHunter_BreakEnchantment **** **** **** **** **** **** **** **** +13062 NentyarHunter_Silent_BreakEnchantment **** **** **** **** **** **** **** **** +13063 NentyarHunter_Still_BreakEnchantment **** **** **** **** **** **** **** **** +13064 NentyarHunter_OrbOfForce **** **** **** **** **** **** **** **** +13065 NentyarHunter_Silent_OrbOfForce **** **** **** **** **** **** **** **** +13066 NentyarHunter_Still_OrbOfForce **** **** **** **** **** **** **** **** +13067 NentyarHunter_Greater_Magic_Weapon **** **** **** **** **** **** **** **** +13068 NentyarHunter_Exteneded_Greater_Magic_Weapon **** **** **** **** **** **** **** **** +13069 NentyarHunter_Silent_Greater_Magic_Weapon **** **** **** **** **** **** **** **** +13070 NentyarHunter_Still_Greater_Magic_Weapon **** **** **** **** **** **** **** **** +13071 NentyarHunter_Flame_Strike **** **** **** **** **** **** **** **** +13072 NentyarHunter_Healing_Circle **** **** **** **** **** **** **** **** +13073 NentyarHunter_Righteous_Might **** **** **** **** **** **** **** **** +13074 Blighter_Flare **** **** **** **** **** **** **** **** +13075 Blighter_Exteneded_Flare **** **** **** **** **** **** **** **** +13076 Blighter_Quickened_Flare **** **** **** **** **** **** **** **** +13077 Blighter_Silent_Flare **** **** **** **** **** **** **** **** +13078 Blighter_Inflict_Minor_Wounds **** **** **** **** **** **** **** **** +13079 Blighter_Quickened_Inflict_Minor_Wounds **** **** **** **** **** **** **** **** +13080 Blighter_Silent_Inflict_Minor_Wounds **** **** **** **** **** **** **** **** +13081 Blighter_Still_Inflict_Minor_Wounds **** **** **** **** **** **** **** **** +13082 Blighter_Read_Magic **** **** **** **** **** **** **** **** +13083 Blighter_Quickened_Read_Magic **** **** **** **** **** **** **** **** +13084 Blighter_Silent_Read_Magic **** **** **** **** **** **** **** **** +13085 Blighter_Still_Read_Magic **** **** **** **** **** **** **** **** +13086 Blighter_Bane **** **** **** **** **** **** **** **** +13087 Blighter_Exteneded_Bane **** **** **** **** **** **** **** **** +13088 Blighter_Quickened_Bane **** **** **** **** **** **** **** **** +13089 Blighter_Silent_Bane **** **** **** **** **** **** **** **** +13090 Blighter_Still_Bane **** **** **** **** **** **** **** **** +13091 Blighter_Burning_Hands **** **** **** **** **** **** **** **** +13092 Blighter_Empowered_Burning_Hands **** **** **** **** **** **** **** **** +13093 Blighter_Maximized_Burning_Hands **** **** **** **** **** **** **** **** +13094 Blighter_Quickened_Burning_Hands **** **** **** **** **** **** **** **** +13095 Blighter_Silent_Burning_Hands **** **** **** **** **** **** **** **** +13096 Blighter_Still_Burning_Hands **** **** **** **** **** **** **** **** +13097 Blighter_DETECT_UNDEAD **** **** **** **** **** **** **** **** +13098 Blighter_Exteneded_DETECT_UNDEAD **** **** **** **** **** **** **** **** +13099 Blighter_Quickened_DETECT_UNDEAD **** **** **** **** **** **** **** **** +13100 Blighter_Silent_DETECT_UNDEAD **** **** **** **** **** **** **** **** +13101 Blighter_Still_DETECT_UNDEAD **** **** **** **** **** **** **** **** +13102 Blighter_Doom **** **** **** **** **** **** **** **** +13103 Blighter_Exteneded_Doom **** **** **** **** **** **** **** **** +13104 Blighter_Quickened_Doom **** **** **** **** **** **** **** **** +13105 Blighter_Silent_Doom **** **** **** **** **** **** **** **** +13106 Blighter_Still_Doom **** **** **** **** **** **** **** **** +13107 Blighter_Endure_Elements **** **** **** **** **** **** **** **** +13108 Blighter_Exteneded_Endure_Elements **** **** **** **** **** **** **** **** +13109 Blighter_Quickened_Endure_Elements **** **** **** **** **** **** **** **** +13110 Blighter_Silent_Endure_Elements **** **** **** **** **** **** **** **** +13111 Blighter_Still_Endure_Elements **** **** **** **** **** **** **** **** +13112 Blighter_Ray_of_Enfeeblement **** **** **** **** **** **** **** **** +13113 Blighter_Empowered_Ray_of_Enfeeblement **** **** **** **** **** **** **** **** +13114 Blighter_Exteneded_Ray_of_Enfeeblement **** **** **** **** **** **** **** **** +13115 Blighter_Maximized_Ray_of_Enfeeblement **** **** **** **** **** **** **** **** +13116 Blighter_Quickened_Ray_of_Enfeeblement **** **** **** **** **** **** **** **** +13117 Blighter_Silent_Ray_of_Enfeeblement **** **** **** **** **** **** **** **** +13118 Blighter_Still_Ray_of_Enfeeblement **** **** **** **** **** **** **** **** +13119 Blighter_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +13120 Blighter_Empowered_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +13121 Blighter_Maximized_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +13122 Blighter_Quickened_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +13123 Blighter_Silent_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +13124 Blighter_Still_Inflict_Light_Wounds **** **** **** **** **** **** **** **** +13125 Blighter_Chill_Touch **** **** **** **** **** **** **** **** +13126 Blighter_Empowered_Chill_Touch **** **** **** **** **** **** **** **** +13127 Blighter_Exteneded_Chill_Touch **** **** **** **** **** **** **** **** +13128 Blighter_Maximized_Chill_Touch **** **** **** **** **** **** **** **** +13129 Blighter_Quickened_Chill_Touch **** **** **** **** **** **** **** **** +13130 Blighter_Silent_Chill_Touch **** **** **** **** **** **** **** **** +13131 Blighter_Still_Chill_Touch **** **** **** **** **** **** **** **** +13132 Blighter_Darkness **** **** **** **** **** **** **** **** +13133 Blighter_Exteneded_Darkness **** **** **** **** **** **** **** **** +13134 Blighter_Quickened_Darkness **** **** **** **** **** **** **** **** +13135 Blighter_Silent_Darkness **** **** **** **** **** **** **** **** +13136 Blighter_Death_Knell **** **** **** **** **** **** **** **** +13137 Blighter_Empowered_Death_Knell **** **** **** **** **** **** **** **** +13138 Blighter_Exteneded_Death_Knell **** **** **** **** **** **** **** **** +13139 Blighter_Maximized_Death_Knell **** **** **** **** **** **** **** **** +13140 Blighter_Quickened_Death_Knell **** **** **** **** **** **** **** **** +13141 Blighter_Silent_Death_Knell **** **** **** **** **** **** **** **** +13142 Blighter_Still_Death_Knell **** **** **** **** **** **** **** **** +13143 Blighter_FireTrap **** **** **** **** **** **** **** **** +13144 Blighter_Empowered_FireTrap **** **** **** **** **** **** **** **** +13145 Blighter_Maximized_FireTrap **** **** **** **** **** **** **** **** +13146 Blighter_Quickened_FireTrap **** **** **** **** **** **** **** **** +13147 Blighter_Silent_FireTrap **** **** **** **** **** **** **** **** +13148 Blighter_Still_FireTrap **** **** **** **** **** **** **** **** +13149 Blighter_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +13150 Blighter_Empowered_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +13151 Blighter_Maximized_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +13152 Blighter_Quickened_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +13153 Blighter_Silent_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +13154 Blighter_Still_Inflict_Moderate_Wounds **** **** **** **** **** **** **** **** +13155 Blighter_Resist_Elements **** **** **** **** **** **** **** **** +13156 Blighter_Exteneded_Resist_Elements **** **** **** **** **** **** **** **** +13157 Blighter_Quickened_Resist_Elements **** **** **** **** **** **** **** **** +13158 Blighter_Silent_Resist_Elements **** **** **** **** **** **** **** **** +13159 Blighter_Still_Resist_Elements **** **** **** **** **** **** **** **** +13160 Blighter_Contagion **** **** **** **** **** **** **** **** +13161 Blighter_Quickened_Contagion **** **** **** **** **** **** **** **** +13162 Blighter_Silent_Contagion **** **** **** **** **** **** **** **** +13163 Blighter_Still_Contagion **** **** **** **** **** **** **** **** +13164 Blighter_DeeperDarkness **** **** **** **** **** **** **** **** +13165 Blighter_Exteneded_DeeperDarkness **** **** **** **** **** **** **** **** +13166 Blighter_Quickened_DeeperDarkness **** **** **** **** **** **** **** **** +13167 Blighter_Silent_DeeperDarkness **** **** **** **** **** **** **** **** +13168 Blighter_Dispel_Magic **** **** **** **** **** **** **** **** +13169 Blighter_Quickened_Dispel_Magic **** **** **** **** **** **** **** **** +13170 Blighter_Silent_Dispel_Magic **** **** **** **** **** **** **** **** +13171 Blighter_Still_Dispel_Magic **** **** **** **** **** **** **** **** +13172 Blighter_Inflict_Serious_Wounds **** **** **** **** **** **** **** **** +13173 Blighter_Empowered_Inflict_Serious_Wounds **** **** **** **** **** **** **** **** +13174 Blighter_Maximized_Inflict_Serious_Wounds **** **** **** **** **** **** **** **** +13175 Blighter_Quickened_Inflict_Serious_Wounds **** **** **** **** **** **** **** **** +13176 Blighter_Silent_Inflict_Serious_Wounds **** **** **** **** **** **** **** **** +13177 Blighter_Still_Inflict_Serious_Wounds **** **** **** **** **** **** **** **** +13178 Blighter_Poison **** **** **** **** **** **** **** **** +13179 Blighter_Empowered_Poison **** **** **** **** **** **** **** **** +13180 Blighter_Maximized_Poison **** **** **** **** **** **** **** **** +13181 Blighter_Quickened_Poison **** **** **** **** **** **** **** **** +13182 Blighter_Silent_Poison **** **** **** **** **** **** **** **** +13183 Blighter_Still_Poison **** **** **** **** **** **** **** **** +13184 Blighter_Protection_from_Elements **** **** **** **** **** **** **** **** +13185 Blighter_Exteneded_Protection_from_Elements **** **** **** **** **** **** **** **** +13186 Blighter_Quickened_Protection_from_Elements **** **** **** **** **** **** **** **** +13187 Blighter_Silent_Protection_from_Elements **** **** **** **** **** **** **** **** +13188 Blighter_Still_Protection_from_Elements **** **** **** **** **** **** **** **** +13189 Blighter_Stinking_Cloud **** **** **** **** **** **** **** **** +13190 Blighter_Exteneded_Stinking_Cloud **** **** **** **** **** **** **** **** +13191 Blighter_Quickened_Stinking_Cloud **** **** **** **** **** **** **** **** +13192 Blighter_Silent_Stinking_Cloud **** **** **** **** **** **** **** **** +13193 Blighter_Still_Stinking_Cloud **** **** **** **** **** **** **** **** +13194 Blighter_Vampiric_Touch **** **** **** **** **** **** **** **** +13195 Blighter_Empowered_Vampiric_Touch **** **** **** **** **** **** **** **** +13196 Blighter_Maximized_Vampiric_Touch **** **** **** **** **** **** **** **** +13197 Blighter_Quickened_Vampiric_Touch **** **** **** **** **** **** **** **** +13198 Blighter_Silent_Vampiric_Touch **** **** **** **** **** **** **** **** +13199 Blighter_Still_Vampiric_Touch **** **** **** **** **** **** **** **** +13200 Blighter_Animate_Dead **** **** **** **** **** **** **** **** +13201 Blighter_Exteneded_Animate_Dead **** **** **** **** **** **** **** **** +13202 Blighter_Quickened_Animate_Dead **** **** **** **** **** **** **** **** +13203 Blighter_Silent_Animate_Dead **** **** **** **** **** **** **** **** +13204 Blighter_Still_Animate_Dead **** **** **** **** **** **** **** **** +13205 Blighter_ContagiousTouch **** **** **** **** **** **** **** **** +13206 Blighter_Quickened_ContagiousTouch **** **** **** **** **** **** **** **** +13207 Blighter_Silent_ContagiousTouch **** **** **** **** **** **** **** **** +13208 Blighter_Still_ContagiousTouch **** **** **** **** **** **** **** **** +13209 Blighter_Death_Ward **** **** **** **** **** **** **** **** +13210 Blighter_Exteneded_Death_Ward **** **** **** **** **** **** **** **** +13211 Blighter_Quickened_Death_Ward **** **** **** **** **** **** **** **** +13212 Blighter_Silent_Death_Ward **** **** **** **** **** **** **** **** +13213 Blighter_Still_Death_Ward **** **** **** **** **** **** **** **** +13214 Blighter_Flame_Strike **** **** **** **** **** **** **** **** +13215 Blighter_Empowered_Flame_Strike **** **** **** **** **** **** **** **** +13216 Blighter_Maximized_Flame_Strike **** **** **** **** **** **** **** **** +13217 Blighter_Quickened_Flame_Strike **** **** **** **** **** **** **** **** +13218 Blighter_Silent_Flame_Strike **** **** **** **** **** **** **** **** +13219 Blighter_Still_Flame_Strike **** **** **** **** **** **** **** **** +13220 Blighter_Inflict_Critical_Wounds **** **** **** **** **** **** **** **** +13221 Blighter_Empowered_Inflict_Critical_Wounds **** **** **** **** **** **** **** **** +13222 Blighter_Maximized_Inflict_Critical_Wounds **** **** **** **** **** **** **** **** +13223 Blighter_Quickened_Inflict_Critical_Wounds **** **** **** **** **** **** **** **** +13224 Blighter_Silent_Inflict_Critical_Wounds **** **** **** **** **** **** **** **** +13225 Blighter_Still_Inflict_Critical_Wounds **** **** **** **** **** **** **** **** +13226 Blighter_RepelVermin **** **** **** **** **** **** **** **** +13227 Blighter_Exteneded_RepelVermin **** **** **** **** **** **** **** **** +13228 Blighter_Quickened_RepelVermin **** **** **** **** **** **** **** **** +13229 Blighter_Silent_RepelVermin **** **** **** **** **** **** **** **** +13230 Blighter_Still_RepelVermin **** **** **** **** **** **** **** **** +13231 Blighter_Wall_of_Fire **** **** **** **** **** **** **** **** +13232 Blighter_Empowered_Wall_of_Fire **** **** **** **** **** **** **** **** +13233 Blighter_Exteneded_Wall_of_Fire **** **** **** **** **** **** **** **** +13234 Blighter_Maximized_Wall_of_Fire **** **** **** **** **** **** **** **** +13235 Blighter_Quickened_Wall_of_Fire **** **** **** **** **** **** **** **** +13236 Blighter_Silent_Wall_of_Fire **** **** **** **** **** **** **** **** +13237 Blighter_Still_Wall_of_Fire **** **** **** **** **** **** **** **** +13238 Blighter_Create_Undead **** **** **** **** **** **** **** **** +13239 Blighter_Exteneded_Create_Undead **** **** **** **** **** **** **** **** +13240 Blighter_Quickened_Create_Undead **** **** **** **** **** **** **** **** +13241 Blighter_Silent_Create_Undead **** **** **** **** **** **** **** **** +13242 Blighter_Still_Create_Undead **** **** **** **** **** **** **** **** +13243 Blighter_WavesofFatigue **** **** **** **** **** **** **** **** +13244 Blighter_Quickened_WavesofFatigue **** **** **** **** **** **** **** **** +13245 Blighter_Silent_WavesofFatigue **** **** **** **** **** **** **** **** +13246 Blighter_Still_WavesofFatigue **** **** **** **** **** **** **** **** +13247 Blighter_Acid_Fog **** **** **** **** **** **** **** **** +13248 Blighter_Empowered_Acid_Fog **** **** **** **** **** **** **** **** +13249 Blighter_Exteneded_Acid_Fog **** **** **** **** **** **** **** **** +13250 Blighter_Maximized_Acid_Fog **** **** **** **** **** **** **** **** +13251 Blighter_Silent_Acid_Fog **** **** **** **** **** **** **** **** +13252 Blighter_Still_Acid_Fog **** **** **** **** **** **** **** **** +13253 Blighter_Circle_of_Death **** **** **** **** **** **** **** **** +13254 Blighter_Empowered_Circle_of_Death **** **** **** **** **** **** **** **** +13255 Blighter_Maximized_Circle_of_Death **** **** **** **** **** **** **** **** +13256 Blighter_Silent_Circle_of_Death **** **** **** **** **** **** **** **** +13257 Blighter_Still_Circle_of_Death **** **** **** **** **** **** **** **** +13258 Blighter_Finger_of_Death **** **** **** **** **** **** **** **** +13259 Blighter_Empowered_Finger_of_Death **** **** **** **** **** **** **** **** +13260 Blighter_Maximized_Finger_of_Death **** **** **** **** **** **** **** **** +13261 Blighter_Silent_Finger_of_Death **** **** **** **** **** **** **** **** +13262 Blighter_Still_Finger_of_Death **** **** **** **** **** **** **** **** +13263 Blighter_Greater_Dispelling **** **** **** **** **** **** **** **** +13264 Blighter_Silent_Greater_Dispelling **** **** **** **** **** **** **** **** +13265 Blighter_Still_Greater_Dispelling **** **** **** **** **** **** **** **** +13266 Blighter_Harm **** **** **** **** **** **** **** **** +13267 Blighter_Silent_Harm **** **** **** **** **** **** **** **** +13268 Blighter_Still_Harm **** **** **** **** **** **** **** **** +13269 Blighter_Control_Undead **** **** **** **** **** **** **** **** +13270 Blighter_Exteneded_Control_Undead **** **** **** **** **** **** **** **** +13271 Blighter_Silent_Control_Undead **** **** **** **** **** **** **** **** +13272 Blighter_Still_Control_Undead **** **** **** **** **** **** **** **** +13273 Blighter_Control_Weather **** **** **** **** **** **** **** **** +13274 Blighter_CW_Rain **** **** **** **** **** **** **** **** +13275 Blighter_CW_Snow **** **** **** **** **** **** **** **** +13276 Blighter_CW_Clear **** **** **** **** **** **** **** **** +13277 Blighter_Exteneded_Control_Weather **** **** **** **** **** **** **** **** +13278 Blighter_Exteneded_CW_Rain **** **** **** **** **** **** **** **** +13279 Blighter_Exteneded_CW_Snow **** **** **** **** **** **** **** **** +13280 Blighter_Exteneded_CW_Clear **** **** **** **** **** **** **** **** +13281 Blighter_Silent_Control_Weather **** **** **** **** **** **** **** **** +13282 Blighter_Silent_CW_Rain **** **** **** **** **** **** **** **** +13283 Blighter_Silent_CW_Snow **** **** **** **** **** **** **** **** +13284 Blighter_Silent_CW_Clear **** **** **** **** **** **** **** **** +13285 Blighter_Still_Control_Weather **** **** **** **** **** **** **** **** +13286 Blighter_Still_CW_Rain **** **** **** **** **** **** **** **** +13287 Blighter_Still_CW_Snow **** **** **** **** **** **** **** **** +13288 Blighter_Still_CW_Clear **** **** **** **** **** **** **** **** +13289 Blighter_Earthquake **** **** **** **** **** **** **** **** +13290 Blighter_Exteneded_Earthquake **** **** **** **** **** **** **** **** +13291 Blighter_Silent_Earthquake **** **** **** **** **** **** **** **** +13292 Blighter_Still_Earthquake **** **** **** **** **** **** **** **** +13293 Blighter_Fire_Storm **** **** **** **** **** **** **** **** +13294 Blighter_Empowered_Fire_Storm **** **** **** **** **** **** **** **** +13295 Blighter_Silent_Fire_Storm **** **** **** **** **** **** **** **** +13296 Blighter_Still_Fire_Storm **** **** **** **** **** **** **** **** +13297 Blighter_Repulsion **** **** **** **** **** **** **** **** +13298 Blighter_Exteneded_Repulsion **** **** **** **** **** **** **** **** +13299 Blighter_Silent_Repulsion **** **** **** **** **** **** **** **** +13300 Blighter_Still_Repulsion **** **** **** **** **** **** **** **** +13301 Blighter_Horrid_Wilting **** **** **** **** **** **** **** **** +13302 Blighter_Silent_Horrid_Wilting **** **** **** **** **** **** **** **** +13303 Blighter_Still_Horrid_Wilting **** **** **** **** **** **** **** **** +13304 Blighter_Mind_Blank **** **** **** **** **** **** **** **** +13305 Blighter_Exteneded_Mind_Blank **** **** **** **** **** **** **** **** +13306 Blighter_Silent_Mind_Blank **** **** **** **** **** **** **** **** +13307 Blighter_Still_Mind_Blank **** **** **** **** **** **** **** **** +13308 Blighter_WavesOfExhaustion **** **** **** **** **** **** **** **** +13309 Blighter_Silent_WavesOfExhaustion **** **** **** **** **** **** **** **** +13310 Blighter_Still_WavesOfExhaustion **** **** **** **** **** **** **** **** +13311 Blighter_Foresight **** **** **** **** **** **** **** **** +13312 Blighter_Implosion **** **** **** **** **** **** **** **** +13313 Blighter_Incendiary_Cloud **** **** **** **** **** **** **** **** +13314 Blighter_Storm_of_Vengeance **** **** **** **** **** **** **** **** +13315 **** **** **** **** **** **** **** **** **** +13316 **** **** **** **** **** **** **** **** **** +13317 **** **** **** **** **** **** **** **** **** +13318 **** **** **** **** **** **** **** **** **** +13319 **** **** **** **** **** **** **** **** **** +13320 **** **** **** **** **** **** **** **** **** +13321 **** **** **** **** **** **** **** **** **** +13322 **** **** **** **** **** **** **** **** **** +13323 **** **** **** **** **** **** **** **** **** +13324 **** **** **** **** **** **** **** **** **** +13325 **** **** **** **** **** **** **** **** **** +13326 **** **** **** **** **** **** **** **** **** +13327 **** **** **** **** **** **** **** **** **** +13328 **** **** **** **** **** **** **** **** **** +13329 **** **** **** **** **** **** **** **** **** +13330 **** **** **** **** **** **** **** **** **** +13331 **** **** **** **** **** **** **** **** **** +13332 **** **** **** **** **** **** **** **** **** +13333 **** **** **** **** **** **** **** **** **** +13334 **** **** **** **** **** **** **** **** **** +13335 **** **** **** **** **** **** **** **** **** +13336 **** **** **** **** **** **** **** **** **** +13337 **** **** **** **** **** **** **** **** **** +13338 **** **** **** **** **** **** **** **** **** +13339 **** **** **** **** **** **** **** **** **** +13340 **** **** **** **** **** **** **** **** **** +13341 **** **** **** **** **** **** **** **** **** +13342 **** **** **** **** **** **** **** **** **** +13343 **** **** **** **** **** **** **** **** **** +13344 **** **** **** **** **** **** **** **** **** +13345 **** **** **** **** **** **** **** **** **** +13346 **** **** **** **** **** **** **** **** **** +13347 **** **** **** **** **** **** **** **** **** +13348 **** **** **** **** **** **** **** **** **** +13349 **** **** **** **** **** **** **** **** **** +13350 **** **** **** **** **** **** **** **** **** +13351 **** **** **** **** **** **** **** **** **** +13352 **** **** **** **** **** **** **** **** **** +13353 **** **** **** **** **** **** **** **** **** +13354 **** **** **** **** **** **** **** **** **** +13355 **** **** **** **** **** **** **** **** **** +13356 **** **** **** **** **** **** **** **** **** +13357 **** **** **** **** **** **** **** **** **** +13358 **** **** **** **** **** **** **** **** **** +13359 **** **** **** **** **** **** **** **** **** +13360 **** **** **** **** **** **** **** **** **** +13361 **** **** **** **** **** **** **** **** **** +13362 **** **** **** **** **** **** **** **** **** +13363 **** **** **** **** **** **** **** **** **** +13364 **** **** **** **** **** **** **** **** **** +13365 **** **** **** **** **** **** **** **** **** +13366 **** **** **** **** **** **** **** **** **** +13367 **** **** **** **** **** **** **** **** **** +13368 **** **** **** **** **** **** **** **** **** +13369 **** **** **** **** **** **** **** **** **** +13370 **** **** **** **** **** **** **** **** **** +13371 **** **** **** **** **** **** **** **** **** +13372 **** **** **** **** **** **** **** **** **** +13373 **** **** **** **** **** **** **** **** **** +13374 **** **** **** **** **** **** **** **** **** +13375 **** **** **** **** **** **** **** **** **** +13376 **** **** **** **** **** **** **** **** **** +13377 **** **** **** **** **** **** **** **** **** +13378 **** **** **** **** **** **** **** **** **** +13379 **** **** **** **** **** **** **** **** **** +13380 **** **** **** **** **** **** **** **** **** +13381 **** **** **** **** **** **** **** **** **** +13382 **** **** **** **** **** **** **** **** **** +13383 **** **** **** **** **** **** **** **** **** +13384 **** **** **** **** **** **** **** **** **** +13385 **** **** **** **** **** **** **** **** **** +13386 **** **** **** **** **** **** **** **** **** +13387 **** **** **** **** **** **** **** **** **** +13388 **** **** **** **** **** **** **** **** **** +13389 **** **** **** **** **** **** **** **** **** +13390 **** **** **** **** **** **** **** **** **** +13391 **** **** **** **** **** **** **** **** **** +13392 **** **** **** **** **** **** **** **** **** +13393 **** **** **** **** **** **** **** **** **** +13394 **** **** **** **** **** **** **** **** **** +13395 **** **** **** **** **** **** **** **** **** +13396 **** **** **** **** **** **** **** **** **** +13397 **** **** **** **** **** **** **** **** **** +13398 **** **** **** **** **** **** **** **** **** +13399 **** **** **** **** **** **** **** **** **** +13400 **** **** **** **** **** **** **** **** **** +13401 **** **** **** **** **** **** **** **** **** +13402 **** **** **** **** **** **** **** **** **** +13403 **** **** **** **** **** **** **** **** **** +13404 **** **** **** **** **** **** **** **** **** +13405 **** **** **** **** **** **** **** **** **** +13406 **** **** **** **** **** **** **** **** **** +13407 **** **** **** **** **** **** **** **** **** +13408 **** **** **** **** **** **** **** **** **** +13409 **** **** **** **** **** **** **** **** **** +13410 **** **** **** **** **** **** **** **** **** +13411 **** **** **** **** **** **** **** **** **** +13412 **** **** **** **** **** **** **** **** **** +13413 **** **** **** **** **** **** **** **** **** +13414 **** **** **** **** **** **** **** **** **** +13415 **** **** **** **** **** **** **** **** **** +13416 **** **** **** **** **** **** **** **** **** +13417 **** **** **** **** **** **** **** **** **** +13418 **** **** **** **** **** **** **** **** **** +13419 **** **** **** **** **** **** **** **** **** +13420 **** **** **** **** **** **** **** **** **** +13421 **** **** **** **** **** **** **** **** **** +13422 **** **** **** **** **** **** **** **** **** +13423 **** **** **** **** **** **** **** **** **** +13424 **** **** **** **** **** **** **** **** **** +13425 **** **** **** **** **** **** **** **** **** +13426 **** **** **** **** **** **** **** **** **** +13427 **** **** **** **** **** **** **** **** **** +13428 **** **** **** **** **** **** **** **** **** +13429 **** **** **** **** **** **** **** **** **** +13430 **** **** **** **** **** **** **** **** **** +13431 **** **** **** **** **** **** **** **** **** +13432 **** **** **** **** **** **** **** **** **** +13433 **** **** **** **** **** **** **** **** **** +13434 **** **** **** **** **** **** **** **** **** +13435 **** **** **** **** **** **** **** **** **** +13436 **** **** **** **** **** **** **** **** **** +13437 **** **** **** **** **** **** **** **** **** +13438 **** **** **** **** **** **** **** **** **** +13439 **** **** **** **** **** **** **** **** **** +13440 **** **** **** **** **** **** **** **** **** +13441 **** **** **** **** **** **** **** **** **** +13442 **** **** **** **** **** **** **** **** **** +13443 **** **** **** **** **** **** **** **** **** +13444 **** **** **** **** **** **** **** **** **** +13445 **** **** **** **** **** **** **** **** **** +13446 **** **** **** **** **** **** **** **** **** +13447 **** **** **** **** **** **** **** **** **** +13448 **** **** **** **** **** **** **** **** **** +13449 **** **** **** **** **** **** **** **** **** +13450 **** **** **** **** **** **** **** **** **** +13451 **** **** **** **** **** **** **** **** **** +13452 **** **** **** **** **** **** **** **** **** +13453 **** **** **** **** **** **** **** **** **** +13454 **** **** **** **** **** **** **** **** **** +13455 **** **** **** **** **** **** **** **** **** +13456 **** **** **** **** **** **** **** **** **** +13457 **** **** **** **** **** **** **** **** **** +13458 **** **** **** **** **** **** **** **** **** +13459 **** **** **** **** **** **** **** **** **** +13460 **** **** **** **** **** **** **** **** **** +13461 **** **** **** **** **** **** **** **** **** +13462 **** **** **** **** **** **** **** **** **** +13463 **** **** **** **** **** **** **** **** **** +13464 **** **** **** **** **** **** **** **** **** +13465 **** **** **** **** **** **** **** **** **** +13466 **** **** **** **** **** **** **** **** **** +13467 **** **** **** **** **** **** **** **** **** +13468 **** **** **** **** **** **** **** **** **** +13469 **** **** **** **** **** **** **** **** **** +13470 **** **** **** **** **** **** **** **** **** +13471 **** **** **** **** **** **** **** **** **** +13472 **** **** **** **** **** **** **** **** **** +13473 **** **** **** **** **** **** **** **** **** +13474 **** **** **** **** **** **** **** **** **** +13475 **** **** **** **** **** **** **** **** **** +13476 **** **** **** **** **** **** **** **** **** +13477 **** **** **** **** **** **** **** **** **** +13478 **** **** **** **** **** **** **** **** **** +13479 **** **** **** **** **** **** **** **** **** +13480 **** **** **** **** **** **** **** **** **** +13481 **** **** **** **** **** **** **** **** **** +13482 **** **** **** **** **** **** **** **** **** +13483 **** **** **** **** **** **** **** **** **** +13484 **** **** **** **** **** **** **** **** **** +13485 **** **** **** **** **** **** **** **** **** +13486 **** **** **** **** **** **** **** **** **** +13487 **** **** **** **** **** **** **** **** **** +13488 **** **** **** **** **** **** **** **** **** +13489 **** **** **** **** **** **** **** **** **** +13490 **** **** **** **** **** **** **** **** **** +13491 **** **** **** **** **** **** **** **** **** +13492 **** **** **** **** **** **** **** **** **** +13493 **** **** **** **** **** **** **** **** **** +13494 **** **** **** **** **** **** **** **** **** +13495 **** **** **** **** **** **** **** **** **** +13496 **** **** **** **** **** **** **** **** **** +13497 **** **** **** **** **** **** **** **** **** +13498 **** **** **** **** **** **** **** **** **** +13499 **** **** **** **** **** **** **** **** **** +13500 ####END_OF_NEW_SPELLBOOK_RESERVE **** **** **** **** **** **** **** **** +13501 ###START_ACP_4_RESERVE **** **** **** **** **** **** **** **** +13502 ACP_Fighting_Stance_QUICK **** **** **** **** **** **** **** **** +13503 ACP_Fighting_Stance_KENSAI **** **** **** **** **** **** **** **** +13504 ACP_Fighting_Stance_ASSASSIN **** **** **** **** **** **** **** **** +13505 ACP_Fighting_Stance_ARCANE **** **** **** **** **** **** **** **** +13506 ACP_Fighting_Stance_FENCING **** **** **** **** **** **** **** **** +13507 ACP_Fighting_Stance_NORMAL **** **** **** **** **** **** **** **** +13508 ACP_Fighting_Stance_HEAVY **** **** **** **** **** **** **** **** +13509 ACP_Fighting_Stance_BARBARIAN **** **** **** **** **** **** **** **** +13510 ACP_Fighting_Stance_DEMONBLADE **** **** **** **** **** **** **** **** +13511 ACP_Fighting_Stance_WARRIOR **** **** **** **** **** **** **** **** +13512 ACP_Fighting_Stance_NORMAL **** **** **** **** **** **** **** **** +13513 ACP_Fighting_Stance_UNARMED **** **** **** **** **** **** **** **** +13514 ACP_Fighting_Stance_TIGERFANG **** **** **** **** **** **** **** **** +13515 ACP_Fighting_Stance_SUNFIST **** **** **** **** **** **** **** **** +13516 ACP_Fighting_Stance_DRAGONPALM **** **** **** **** **** **** **** **** +13517 ACP_Fighting_Stance_BEARCLAW **** **** **** **** **** **** **** **** +13518 ACP_Fighting_Stance_NORMAL **** **** **** **** **** **** **** **** +13519 **** **** **** **** **** **** **** **** **** +13520 **** **** **** **** **** **** **** **** **** +13521 **** **** **** **** **** **** **** **** **** +13522 **** **** **** **** **** **** **** **** **** +13523 **** **** **** **** **** **** **** **** **** +13524 **** **** **** **** **** **** **** **** **** +13525 **** **** **** **** **** **** **** **** **** +13526 **** **** **** **** **** **** **** **** **** +13527 **** **** **** **** **** **** **** **** **** +13528 **** **** **** **** **** **** **** **** **** +13529 **** **** **** **** **** **** **** **** **** +13530 **** **** **** **** **** **** **** **** **** +13531 **** **** **** **** **** **** **** **** **** +13532 **** **** **** **** **** **** **** **** **** +13533 **** **** **** **** **** **** **** **** **** +13534 **** **** **** **** **** **** **** **** **** +13535 **** **** **** **** **** **** **** **** **** +13536 **** **** **** **** **** **** **** **** **** +13537 **** **** **** **** **** **** **** **** **** +13538 **** **** **** **** **** **** **** **** **** +13539 **** **** **** **** **** **** **** **** **** +13540 **** **** **** **** **** **** **** **** **** +13541 **** **** **** **** **** **** **** **** **** +13542 **** **** **** **** **** **** **** **** **** +13543 **** **** **** **** **** **** **** **** **** +13544 **** **** **** **** **** **** **** **** **** +13545 **** **** **** **** **** **** **** **** **** +13546 **** **** **** **** **** **** **** **** **** +13547 **** **** **** **** **** **** **** **** **** +13548 **** **** **** **** **** **** **** **** **** +13549 **** **** **** **** **** **** **** **** **** +13550 **** **** **** **** **** **** **** **** **** +13551 **** **** **** **** **** **** **** **** **** +13552 **** **** **** **** **** **** **** **** **** +13553 **** **** **** **** **** **** **** **** **** +13554 **** **** **** **** **** **** **** **** **** +13555 **** **** **** **** **** **** **** **** **** +13556 **** **** **** **** **** **** **** **** **** +13557 **** **** **** **** **** **** **** **** **** +13558 **** **** **** **** **** **** **** **** **** +13559 **** **** **** **** **** **** **** **** **** +13560 **** **** **** **** **** **** **** **** **** +13561 **** **** **** **** **** **** **** **** **** +13562 **** **** **** **** **** **** **** **** **** +13563 **** **** **** **** **** **** **** **** **** +13564 **** **** **** **** **** **** **** **** **** +13565 **** **** **** **** **** **** **** **** **** +13566 **** **** **** **** **** **** **** **** **** +13567 **** **** **** **** **** **** **** **** **** +13568 **** **** **** **** **** **** **** **** **** +13569 **** **** **** **** **** **** **** **** **** +13570 **** **** **** **** **** **** **** **** **** +13571 **** **** **** **** **** **** **** **** **** +13572 **** **** **** **** **** **** **** **** **** +13573 **** **** **** **** **** **** **** **** **** +13574 **** **** **** **** **** **** **** **** **** +13575 **** **** **** **** **** **** **** **** **** +13576 **** **** **** **** **** **** **** **** **** +13577 **** **** **** **** **** **** **** **** **** +13578 **** **** **** **** **** **** **** **** **** +13579 **** **** **** **** **** **** **** **** **** +13580 **** **** **** **** **** **** **** **** **** +13581 **** **** **** **** **** **** **** **** **** +13582 **** **** **** **** **** **** **** **** **** +13583 **** **** **** **** **** **** **** **** **** +13584 **** **** **** **** **** **** **** **** **** +13585 **** **** **** **** **** **** **** **** **** +13586 **** **** **** **** **** **** **** **** **** +13587 **** **** **** **** **** **** **** **** **** +13588 **** **** **** **** **** **** **** **** **** +13589 **** **** **** **** **** **** **** **** **** +13590 **** **** **** **** **** **** **** **** **** +13591 **** **** **** **** **** **** **** **** **** +13592 **** **** **** **** **** **** **** **** **** +13593 **** **** **** **** **** **** **** **** **** +13594 **** **** **** **** **** **** **** **** **** +13595 **** **** **** **** **** **** **** **** **** +13596 **** **** **** **** **** **** **** **** **** +13597 **** **** **** **** **** **** **** **** **** +13598 **** **** **** **** **** **** **** **** **** +13599 **** **** **** **** **** **** **** **** **** +13600 **** **** **** **** **** **** **** **** **** +13601 **** **** **** **** **** **** **** **** **** +13602 **** **** **** **** **** **** **** **** **** +13603 **** **** **** **** **** **** **** **** **** +13604 **** **** **** **** **** **** **** **** **** +13605 **** **** **** **** **** **** **** **** **** +13606 **** **** **** **** **** **** **** **** **** +13607 **** **** **** **** **** **** **** **** **** +13608 **** **** **** **** **** **** **** **** **** +13609 **** **** **** **** **** **** **** **** **** +13610 **** **** **** **** **** **** **** **** **** +13611 **** **** **** **** **** **** **** **** **** +13612 **** **** **** **** **** **** **** **** **** +13613 **** **** **** **** **** **** **** **** **** +13614 **** **** **** **** **** **** **** **** **** +13615 **** **** **** **** **** **** **** **** **** +13616 **** **** **** **** **** **** **** **** **** +13617 **** **** **** **** **** **** **** **** **** +13618 **** **** **** **** **** **** **** **** **** +13619 **** **** **** **** **** **** **** **** **** +13620 **** **** **** **** **** **** **** **** **** +13621 **** **** **** **** **** **** **** **** **** +13622 **** **** **** **** **** **** **** **** **** +13623 **** **** **** **** **** **** **** **** **** +13624 **** **** **** **** **** **** **** **** **** +13625 **** **** **** **** **** **** **** **** **** +13626 **** **** **** **** **** **** **** **** **** +13627 **** **** **** **** **** **** **** **** **** +13628 **** **** **** **** **** **** **** **** **** +13629 **** **** **** **** **** **** **** **** **** +13630 **** **** **** **** **** **** **** **** **** +13631 **** **** **** **** **** **** **** **** **** +13632 **** **** **** **** **** **** **** **** **** +13633 **** **** **** **** **** **** **** **** **** +13634 **** **** **** **** **** **** **** **** **** +13635 **** **** **** **** **** **** **** **** **** +13636 **** **** **** **** **** **** **** **** **** +13637 **** **** **** **** **** **** **** **** **** +13638 **** **** **** **** **** **** **** **** **** +13639 **** **** **** **** **** **** **** **** **** +13640 **** **** **** **** **** **** **** **** **** +13641 **** **** **** **** **** **** **** **** **** +13642 **** **** **** **** **** **** **** **** **** +13643 **** **** **** **** **** **** **** **** **** +13644 **** **** **** **** **** **** **** **** **** +13645 **** **** **** **** **** **** **** **** **** +13646 **** **** **** **** **** **** **** **** **** +13647 **** **** **** **** **** **** **** **** **** +13648 **** **** **** **** **** **** **** **** **** +13649 **** **** **** **** **** **** **** **** **** +13650 **** **** **** **** **** **** **** **** **** +13651 **** **** **** **** **** **** **** **** **** +13652 **** **** **** **** **** **** **** **** **** +13653 **** **** **** **** **** **** **** **** **** +13654 **** **** **** **** **** **** **** **** **** +13655 **** **** **** **** **** **** **** **** **** +13656 **** **** **** **** **** **** **** **** **** +13657 **** **** **** **** **** **** **** **** **** +13658 **** **** **** **** **** **** **** **** **** +13659 **** **** **** **** **** **** **** **** **** +13660 **** **** **** **** **** **** **** **** **** +13661 **** **** **** **** **** **** **** **** **** +13662 **** **** **** **** **** **** **** **** **** +13663 **** **** **** **** **** **** **** **** **** +13664 **** **** **** **** **** **** **** **** **** +13665 **** **** **** **** **** **** **** **** **** +13666 **** **** **** **** **** **** **** **** **** +13667 **** **** **** **** **** **** **** **** **** +13668 **** **** **** **** **** **** **** **** **** +13669 **** **** **** **** **** **** **** **** **** +13670 **** **** **** **** **** **** **** **** **** +13671 **** **** **** **** **** **** **** **** **** +13672 **** **** **** **** **** **** **** **** **** +13673 **** **** **** **** **** **** **** **** **** +13674 **** **** **** **** **** **** **** **** **** +13675 **** **** **** **** **** **** **** **** **** +13676 **** **** **** **** **** **** **** **** **** +13677 **** **** **** **** **** **** **** **** **** +13678 **** **** **** **** **** **** **** **** **** +13679 **** **** **** **** **** **** **** **** **** +13680 **** **** **** **** **** **** **** **** **** +13681 **** **** **** **** **** **** **** **** **** +13682 **** **** **** **** **** **** **** **** **** +13683 **** **** **** **** **** **** **** **** **** +13684 **** **** **** **** **** **** **** **** **** +13685 **** **** **** **** **** **** **** **** **** +13686 **** **** **** **** **** **** **** **** **** +13687 **** **** **** **** **** **** **** **** **** +13688 **** **** **** **** **** **** **** **** **** +13689 **** **** **** **** **** **** **** **** **** +13690 **** **** **** **** **** **** **** **** **** +13691 **** **** **** **** **** **** **** **** **** +13692 **** **** **** **** **** **** **** **** **** +13693 **** **** **** **** **** **** **** **** **** +13694 **** **** **** **** **** **** **** **** **** +13695 **** **** **** **** **** **** **** **** **** +13696 **** **** **** **** **** **** **** **** **** +13697 **** **** **** **** **** **** **** **** **** +13698 **** **** **** **** **** **** **** **** **** +13699 **** **** **** **** **** **** **** **** **** +13700 **** **** **** **** **** **** **** **** **** +13701 **** **** **** **** **** **** **** **** **** +13702 **** **** **** **** **** **** **** **** **** +13703 **** **** **** **** **** **** **** **** **** +13704 **** **** **** **** **** **** **** **** **** +13705 **** **** **** **** **** **** **** **** **** +13706 **** **** **** **** **** **** **** **** **** +13707 **** **** **** **** **** **** **** **** **** +13708 **** **** **** **** **** **** **** **** **** +13709 **** **** **** **** **** **** **** **** **** +13710 **** **** **** **** **** **** **** **** **** +13711 **** **** **** **** **** **** **** **** **** +13712 **** **** **** **** **** **** **** **** **** +13713 **** **** **** **** **** **** **** **** **** +13714 **** **** **** **** **** **** **** **** **** +13715 **** **** **** **** **** **** **** **** **** +13716 **** **** **** **** **** **** **** **** **** +13717 **** **** **** **** **** **** **** **** **** +13718 **** **** **** **** **** **** **** **** **** +13719 **** **** **** **** **** **** **** **** **** +13720 **** **** **** **** **** **** **** **** **** +13721 **** **** **** **** **** **** **** **** **** +13722 **** **** **** **** **** **** **** **** **** +13723 **** **** **** **** **** **** **** **** **** +13724 **** **** **** **** **** **** **** **** **** +13725 **** **** **** **** **** **** **** **** **** +13726 **** **** **** **** **** **** **** **** **** +13727 **** **** **** **** **** **** **** **** **** +13728 **** **** **** **** **** **** **** **** **** +13729 **** **** **** **** **** **** **** **** **** +13730 **** **** **** **** **** **** **** **** **** +13731 **** **** **** **** **** **** **** **** **** +13732 **** **** **** **** **** **** **** **** **** +13733 **** **** **** **** **** **** **** **** **** +13734 **** **** **** **** **** **** **** **** **** +13735 **** **** **** **** **** **** **** **** **** +13736 **** **** **** **** **** **** **** **** **** +13737 **** **** **** **** **** **** **** **** **** +13738 **** **** **** **** **** **** **** **** **** +13739 **** **** **** **** **** **** **** **** **** +13740 **** **** **** **** **** **** **** **** **** +13741 **** **** **** **** **** **** **** **** **** +13742 **** **** **** **** **** **** **** **** **** +13743 **** **** **** **** **** **** **** **** **** +13744 **** **** **** **** **** **** **** **** **** +13745 **** **** **** **** **** **** **** **** **** +13746 **** **** **** **** **** **** **** **** **** +13747 **** **** **** **** **** **** **** **** **** +13748 **** **** **** **** **** **** **** **** **** +13749 **** **** **** **** **** **** **** **** **** +13750 **** **** **** **** **** **** **** **** **** +13751 **** **** **** **** **** **** **** **** **** +13752 **** **** **** **** **** **** **** **** **** +13753 **** **** **** **** **** **** **** **** **** +13754 **** **** **** **** **** **** **** **** **** +13755 **** **** **** **** **** **** **** **** **** +13756 **** **** **** **** **** **** **** **** **** +13757 **** **** **** **** **** **** **** **** **** +13758 **** **** **** **** **** **** **** **** **** +13759 **** **** **** **** **** **** **** **** **** +13760 **** **** **** **** **** **** **** **** **** +13761 **** **** **** **** **** **** **** **** **** +13762 **** **** **** **** **** **** **** **** **** +13763 **** **** **** **** **** **** **** **** **** +13764 **** **** **** **** **** **** **** **** **** +13765 **** **** **** **** **** **** **** **** **** +13766 **** **** **** **** **** **** **** **** **** +13767 **** **** **** **** **** **** **** **** **** +13768 **** **** **** **** **** **** **** **** **** +13769 **** **** **** **** **** **** **** **** **** +13770 **** **** **** **** **** **** **** **** **** +13771 **** **** **** **** **** **** **** **** **** +13772 **** **** **** **** **** **** **** **** **** +13773 **** **** **** **** **** **** **** **** **** +13774 **** **** **** **** **** **** **** **** **** +13775 **** **** **** **** **** **** **** **** **** +13776 **** **** **** **** **** **** **** **** **** +13777 **** **** **** **** **** **** **** **** **** +13778 **** **** **** **** **** **** **** **** **** +13779 **** **** **** **** **** **** **** **** **** +13780 **** **** **** **** **** **** **** **** **** +13781 **** **** **** **** **** **** **** **** **** +13782 **** **** **** **** **** **** **** **** **** +13783 **** **** **** **** **** **** **** **** **** +13784 **** **** **** **** **** **** **** **** **** +13785 **** **** **** **** **** **** **** **** **** +13786 **** **** **** **** **** **** **** **** **** +13787 **** **** **** **** **** **** **** **** **** +13788 **** **** **** **** **** **** **** **** **** +13789 **** **** **** **** **** **** **** **** **** +13790 **** **** **** **** **** **** **** **** **** +13791 **** **** **** **** **** **** **** **** **** +13792 **** **** **** **** **** **** **** **** **** +13793 **** **** **** **** **** **** **** **** **** +13794 **** **** **** **** **** **** **** **** **** +13795 **** **** **** **** **** **** **** **** **** +13796 **** **** **** **** **** **** **** **** **** +13797 **** **** **** **** **** **** **** **** **** +13798 **** **** **** **** **** **** **** **** **** +13799 **** **** **** **** **** **** **** **** **** +13800 **** **** **** **** **** **** **** **** **** +13801 **** **** **** **** **** **** **** **** **** +13802 **** **** **** **** **** **** **** **** **** +13803 **** **** **** **** **** **** **** **** **** +13804 **** **** **** **** **** **** **** **** **** +13805 **** **** **** **** **** **** **** **** **** +13806 **** **** **** **** **** **** **** **** **** +13807 **** **** **** **** **** **** **** **** **** +13808 **** **** **** **** **** **** **** **** **** +13809 **** **** **** **** **** **** **** **** **** +13810 **** **** **** **** **** **** **** **** **** +13811 **** **** **** **** **** **** **** **** **** +13812 **** **** **** **** **** **** **** **** **** +13813 **** **** **** **** **** **** **** **** **** +13814 **** **** **** **** **** **** **** **** **** +13815 **** **** **** **** **** **** **** **** **** +13816 **** **** **** **** **** **** **** **** **** +13817 **** **** **** **** **** **** **** **** **** +13818 **** **** **** **** **** **** **** **** **** +13819 **** **** **** **** **** **** **** **** **** +13820 **** **** **** **** **** **** **** **** **** +13821 **** **** **** **** **** **** **** **** **** +13822 **** **** **** **** **** **** **** **** **** +13823 **** **** **** **** **** **** **** **** **** +13824 **** **** **** **** **** **** **** **** **** +13825 **** **** **** **** **** **** **** **** **** +13826 **** **** **** **** **** **** **** **** **** +13827 **** **** **** **** **** **** **** **** **** +13828 **** **** **** **** **** **** **** **** **** +13829 **** **** **** **** **** **** **** **** **** +13830 **** **** **** **** **** **** **** **** **** +13831 **** **** **** **** **** **** **** **** **** +13832 **** **** **** **** **** **** **** **** **** +13833 **** **** **** **** **** **** **** **** **** +13834 **** **** **** **** **** **** **** **** **** +13835 **** **** **** **** **** **** **** **** **** +13836 **** **** **** **** **** **** **** **** **** +13837 **** **** **** **** **** **** **** **** **** +13838 **** **** **** **** **** **** **** **** **** +13839 **** **** **** **** **** **** **** **** **** +13840 **** **** **** **** **** **** **** **** **** +13841 **** **** **** **** **** **** **** **** **** +13842 **** **** **** **** **** **** **** **** **** +13843 **** **** **** **** **** **** **** **** **** +13844 **** **** **** **** **** **** **** **** **** +13845 **** **** **** **** **** **** **** **** **** +13846 **** **** **** **** **** **** **** **** **** +13847 **** **** **** **** **** **** **** **** **** +13848 **** **** **** **** **** **** **** **** **** +13849 **** **** **** **** **** **** **** **** **** +13850 **** **** **** **** **** **** **** **** **** +13851 **** **** **** **** **** **** **** **** **** +13852 **** **** **** **** **** **** **** **** **** +13853 **** **** **** **** **** **** **** **** **** +13854 **** **** **** **** **** **** **** **** **** +13855 **** **** **** **** **** **** **** **** **** +13856 **** **** **** **** **** **** **** **** **** +13857 **** **** **** **** **** **** **** **** **** +13858 **** **** **** **** **** **** **** **** **** +13859 **** **** **** **** **** **** **** **** **** +13860 **** **** **** **** **** **** **** **** **** +13861 **** **** **** **** **** **** **** **** **** +13862 **** **** **** **** **** **** **** **** **** +13863 **** **** **** **** **** **** **** **** **** +13864 **** **** **** **** **** **** **** **** **** +13865 **** **** **** **** **** **** **** **** **** +13866 **** **** **** **** **** **** **** **** **** +13867 **** **** **** **** **** **** **** **** **** +13868 **** **** **** **** **** **** **** **** **** +13869 **** **** **** **** **** **** **** **** **** +13870 **** **** **** **** **** **** **** **** **** +13871 **** **** **** **** **** **** **** **** **** +13872 **** **** **** **** **** **** **** **** **** +13873 **** **** **** **** **** **** **** **** **** +13874 **** **** **** **** **** **** **** **** **** +13875 **** **** **** **** **** **** **** **** **** +13876 **** **** **** **** **** **** **** **** **** +13877 **** **** **** **** **** **** **** **** **** +13878 **** **** **** **** **** **** **** **** **** +13879 **** **** **** **** **** **** **** **** **** +13880 **** **** **** **** **** **** **** **** **** +13881 **** **** **** **** **** **** **** **** **** +13882 **** **** **** **** **** **** **** **** **** +13883 **** **** **** **** **** **** **** **** **** +13884 **** **** **** **** **** **** **** **** **** +13885 **** **** **** **** **** **** **** **** **** +13886 **** **** **** **** **** **** **** **** **** +13887 **** **** **** **** **** **** **** **** **** +13888 **** **** **** **** **** **** **** **** **** +13889 **** **** **** **** **** **** **** **** **** +13890 **** **** **** **** **** **** **** **** **** +13891 **** **** **** **** **** **** **** **** **** +13892 **** **** **** **** **** **** **** **** **** +13893 **** **** **** **** **** **** **** **** **** +13894 **** **** **** **** **** **** **** **** **** +13895 **** **** **** **** **** **** **** **** **** +13896 **** **** **** **** **** **** **** **** **** +13897 **** **** **** **** **** **** **** **** **** +13898 **** **** **** **** **** **** **** **** **** +13899 **** **** **** **** **** **** **** **** **** +13900 **** **** **** **** **** **** **** **** **** +13901 **** **** **** **** **** **** **** **** **** +13902 **** **** **** **** **** **** **** **** **** +13903 **** **** **** **** **** **** **** **** **** +13904 **** **** **** **** **** **** **** **** **** +13905 **** **** **** **** **** **** **** **** **** +13906 **** **** **** **** **** **** **** **** **** +13907 **** **** **** **** **** **** **** **** **** +13908 **** **** **** **** **** **** **** **** **** +13909 **** **** **** **** **** **** **** **** **** +13910 **** **** **** **** **** **** **** **** **** +13911 **** **** **** **** **** **** **** **** **** +13912 **** **** **** **** **** **** **** **** **** +13913 **** **** **** **** **** **** **** **** **** +13914 **** **** **** **** **** **** **** **** **** +13915 **** **** **** **** **** **** **** **** **** +13916 **** **** **** **** **** **** **** **** **** +13917 **** **** **** **** **** **** **** **** **** +13918 **** **** **** **** **** **** **** **** **** +13919 **** **** **** **** **** **** **** **** **** +13920 **** **** **** **** **** **** **** **** **** +13921 **** **** **** **** **** **** **** **** **** +13922 **** **** **** **** **** **** **** **** **** +13923 **** **** **** **** **** **** **** **** **** +13924 **** **** **** **** **** **** **** **** **** +13925 **** **** **** **** **** **** **** **** **** +13926 **** **** **** **** **** **** **** **** **** +13927 **** **** **** **** **** **** **** **** **** +13928 **** **** **** **** **** **** **** **** **** +13929 **** **** **** **** **** **** **** **** **** +13930 **** **** **** **** **** **** **** **** **** +13931 **** **** **** **** **** **** **** **** **** +13932 **** **** **** **** **** **** **** **** **** +13933 **** **** **** **** **** **** **** **** **** +13934 **** **** **** **** **** **** **** **** **** +13935 **** **** **** **** **** **** **** **** **** +13936 **** **** **** **** **** **** **** **** **** +13937 **** **** **** **** **** **** **** **** **** +13938 **** **** **** **** **** **** **** **** **** +13939 **** **** **** **** **** **** **** **** **** +13940 **** **** **** **** **** **** **** **** **** +13941 **** **** **** **** **** **** **** **** **** +13942 **** **** **** **** **** **** **** **** **** +13943 **** **** **** **** **** **** **** **** **** +13944 **** **** **** **** **** **** **** **** **** +13945 **** **** **** **** **** **** **** **** **** +13946 **** **** **** **** **** **** **** **** **** +13947 **** **** **** **** **** **** **** **** **** +13948 **** **** **** **** **** **** **** **** **** +13949 **** **** **** **** **** **** **** **** **** +13950 **** **** **** **** **** **** **** **** **** +13951 **** **** **** **** **** **** **** **** **** +13952 **** **** **** **** **** **** **** **** **** +13953 **** **** **** **** **** **** **** **** **** +13954 **** **** **** **** **** **** **** **** **** +13955 **** **** **** **** **** **** **** **** **** +13956 **** **** **** **** **** **** **** **** **** +13957 **** **** **** **** **** **** **** **** **** +13958 **** **** **** **** **** **** **** **** **** +13959 **** **** **** **** **** **** **** **** **** +13960 **** **** **** **** **** **** **** **** **** +13961 **** **** **** **** **** **** **** **** **** +13962 **** **** **** **** **** **** **** **** **** +13963 **** **** **** **** **** **** **** **** **** +13964 **** **** **** **** **** **** **** **** **** +13965 **** **** **** **** **** **** **** **** **** +13966 **** **** **** **** **** **** **** **** **** +13967 **** **** **** **** **** **** **** **** **** +13968 **** **** **** **** **** **** **** **** **** +13969 **** **** **** **** **** **** **** **** **** +13970 **** **** **** **** **** **** **** **** **** +13971 **** **** **** **** **** **** **** **** **** +13972 **** **** **** **** **** **** **** **** **** +13973 **** **** **** **** **** **** **** **** **** +13974 **** **** **** **** **** **** **** **** **** +13975 **** **** **** **** **** **** **** **** **** +13976 **** **** **** **** **** **** **** **** **** +13977 **** **** **** **** **** **** **** **** **** +13978 **** **** **** **** **** **** **** **** **** +13979 **** **** **** **** **** **** **** **** **** +13980 **** **** **** **** **** **** **** **** **** +13981 **** **** **** **** **** **** **** **** **** +13982 **** **** **** **** **** **** **** **** **** +13983 **** **** **** **** **** **** **** **** **** +13984 **** **** **** **** **** **** **** **** **** +13985 **** **** **** **** **** **** **** **** **** +13986 **** **** **** **** **** **** **** **** **** +13987 **** **** **** **** **** **** **** **** **** +13988 **** **** **** **** **** **** **** **** **** +13989 **** **** **** **** **** **** **** **** **** +13990 **** **** **** **** **** **** **** **** **** +13991 **** **** **** **** **** **** **** **** **** +13992 **** **** **** **** **** **** **** **** **** +13993 **** **** **** **** **** **** **** **** **** +13994 **** **** **** **** **** **** **** **** **** +13995 **** **** **** **** **** **** **** **** **** +13996 **** **** **** **** **** **** **** **** **** +13997 **** **** **** **** **** **** **** **** **** +13998 **** **** **** **** **** **** **** **** **** +13999 ####END_OF_NEW_SPELLBOOK_RESERVE **** **** **** **** **** **** **** **** +14000 **Psionic_Powers** **** **** **** **** **** **** **** **** +14001 Bolt **** **** **** **** **** **** **** **** +14002 CallToMind **** **** **** **** **** **** **** **** +14003 CharmPerson **** **** **** **** **** **** **** **** +14004 CrystalShard **** **** **** **** **** **** **** **** +14005 Daze **** **** **** **** **** **** **** **** +14006 Deceleration **** **** **** **** **** **** **** **** +14007 DefPrecog **** **** **** **** **** **** **** **** +14008 Demoralize **** **** **** **** **** **** **** **** +14009 Disable **** **** **** **** **** **** **** **** +14010 DissipatingTouch **** **** **** **** **** **** **** **** +14011 Distract **** **** **** **** **** **** **** **** +14012 EmptyMind **** **** **** **** **** **** **** **** +14013 Conceal_Thoughts **** **** **** **** **** **** **** **** +14014 EnergyRay_Cold **** **** **** **** **** **** **** **** +14015 EnergyRay_Elec **** **** **** **** **** **** **** **** +14016 EnergyRay_Fire **** **** **** **** **** **** **** **** +14017 EnergyRay_Sonic **** **** **** **** **** **** **** **** +14018 EntanglingEctoplasm **** **** **** **** **** **** **** **** +14019 ForceScreen **** **** **** **** **** **** **** **** +14020 Grease **** **** **** **** **** **** **** **** +14021 Hammer **** **** **** **** **** **** **** **** +14022 InertialArmour **** **** **** **** **** **** **** **** +14023 MindThrust **** **** **** **** **** **** **** **** +14024 MyLight **** **** **** **** **** **** **** **** +14025 OffPrecog **** **** **** **** **** **** **** **** +14026 OffPresc **** **** **** **** **** **** **** **** +14027 Stomp **** **** **** **** **** **** **** **** +14028 Synesthete **** **** **** **** **** **** **** **** +14029 ThickSkin **** **** **** **** **** **** **** **** +14030 Vigor **** **** **** **** **** **** **** **** +14031 Empathy **** **** **** **** **** **** **** **** +14032 Far_Hand **** **** **** **** **** **** **** **** +14033 Matter_Agitation **** **** **** **** **** **** **** **** +14034 Skate **** **** **** **** **** **** **** **** +14035 Telempathic_Projection **** **** **** **** **** **** **** **** +14036 AstralConstruct_Slot1 **** **** **** **** **** **** **** **** +14037 AstralConstruct_Slot2 **** **** **** **** **** **** **** **** +14038 AstralConstruct_Slot3 **** **** **** **** **** **** **** **** +14039 AstralConstruct_Slot4 **** **** **** **** **** **** **** **** +14040 AstralConstruct_Conversation **** **** **** **** **** **** **** **** +14041 Burst **** **** **** **** **** **** **** **** +14042 DestinyDissonance **** **** **** **** **** **** **** **** +14043 PrecognitionMain **** **** **** **** **** **** **** **** +14044 PrecognitionAttack **** **** **** **** **** **** **** **** +14045 PrecognitionDamage **** **** **** **** **** **** **** **** +14046 PrecognitionSaves **** **** **** **** **** **** **** **** +14047 PrecognitionSkills **** **** **** **** **** **** **** **** +14048 BiteOfTheWolf **** **** **** **** **** **** **** **** +14049 ClawsOfTheBeast **** **** **** **** **** **** **** **** +14050 CreateSound **** **** **** **** **** **** **** **** +14051 BestowPower **** **** **** **** **** **** **** **** +14052 Biofeedback **** **** **** **** **** **** **** **** +14053 BrainLock **** **** **** **** **** **** **** **** +14054 ConcBlast **** **** **** **** **** **** **** **** +14055 ConcealAmorpha **** **** **** **** **** **** **** **** +14056 SwarmOfCrystals **** **** **** **** **** **** **** **** +14057 DissolvingTouch **** **** **** **** **** **** **** **** +14058 EgoWhip **** **** **** **** **** **** **** **** +14059 ElfSight **** **** **** **** **** **** **** **** +14060 EnergyAdaptAcid **** **** **** **** **** **** **** **** +14061 EnergyAdaptCold **** **** **** **** **** **** **** **** +14062 EnergyAdaptElec **** **** **** **** **** **** **** **** +14063 EnergyAdaptFire **** **** **** **** **** **** **** **** +14064 EnergyAdaptSonic **** **** **** **** **** **** **** **** +14065 Body_Equilibrium **** **** **** **** **** **** **** **** +14066 PainfulStrike **** **** **** **** **** **** **** **** +14067 EnergyPush_Cold **** **** **** **** **** **** **** **** +14068 EnergyPush_Elec **** **** **** **** **** **** **** **** +14069 EnergyPush_Fire **** **** **** **** **** **** **** **** +14070 EnergyPush_Sonic **** **** **** **** **** **** **** **** +14071 Lock **** **** **** **** **** **** **** **** +14072 EnergyStun_Cold **** **** **** **** **** **** **** **** +14073 EnergyStun_Elec **** **** **** **** **** **** **** **** +14074 EnergyStun_Fire **** **** **** **** **** **** **** **** +14075 EnergyStun_Sonic **** **** **** **** **** **** **** **** +14076 Identify **** **** **** **** **** **** **** **** +14077 IdInsinuation **** **** **** **** **** **** **** **** +14078 InflictPain **** **** **** **** **** **** **** **** +14079 Knock **** **** **** **** **** **** **** **** +14080 MindDisrupt **** **** **** **** **** **** **** **** +14081 RecallAgony **** **** **** **** **** **** **** **** +14082 ThoughtShield **** **** **** **** **** **** **** **** +14083 Dissolving_Weapon **** **** **** **** **** **** **** **** +14084 SharePain **** **** **** **** **** **** **** **** +14085 ControlAir **** **** **** **** **** **** **** **** +14086 ControlSound **** **** **** **** **** **** **** **** +14087 RepairDamage **** **** **** **** **** **** **** **** +14088 Aversion **** **** **** **** **** **** **** **** +14089 DimensionSwap **** **** **** **** **** **** **** **** +14090 EmpathicTransfer **** **** **** **** **** **** **** **** +14091 Energy_Missile_Cold **** **** **** **** **** **** **** **** +14092 Energy_Missile_Elec **** **** **** **** **** **** **** **** +14093 Energy_Missile_Fire **** **** **** **** **** **** **** **** +14094 Energy_Missile_Sonic **** **** **** **** **** **** **** **** +14095 AnimalAffinity **** **** **** **** **** **** **** **** +14096 StrengthOfMyEnemy **** **** **** **** **** **** **** **** +14097 Chameleon **** **** **** **** **** **** **** **** +14098 ClairvoyantSense **** **** **** **** **** **** **** **** +14099 Cloud_Mind **** **** **** **** **** **** **** **** +14100 BodyAdjustment **** **** **** **** **** **** **** **** +14101 Greater_Amorpha **** **** **** **** **** **** **** **** +14102 Darkvision **** **** **** **** **** **** **** **** +14103 Psiblast **** **** **** **** **** **** **** **** +14104 Danger_Sense **** **** **** **** **** **** **** **** +14105 Energy_Bolt_Cold **** **** **** **** **** **** **** **** +14106 Energy_Bolt_Elec **** **** **** **** **** **** **** **** +14107 Energy_Bolt_Fire **** **** **** **** **** **** **** **** +14108 Energy_Bolt_Sonic **** **** **** **** **** **** **** **** +14109 Energy_Burst_Cold **** **** **** **** **** **** **** **** +14110 Energy_Burst_Elec **** **** **** **** **** **** **** **** +14111 Energy_Burst_Fire **** **** **** **** **** **** **** **** +14112 Energy_Burst_Sonic **** **** **** **** **** **** **** **** +14113 Energy_Retort_Cold **** **** **** **** **** **** **** **** +14114 Energy_Retort_Elec **** **** **** **** **** **** **** **** +14115 Energy_Retort_Fire **** **** **** **** **** **** **** **** +14116 Energy_Retort_Sonic **** **** **** **** **** **** **** **** +14117 Exhale_BlackDrag **** **** **** **** **** **** **** **** +14118 Eradicate_Invisibility **** **** **** **** **** **** **** **** +14119 SharePainForced **** **** **** **** **** **** **** **** +14120 Keen_Edge **** **** **** **** **** **** **** **** +14121 MentalBarrier **** **** **** **** **** **** **** **** +14122 Mindtrap **** **** **** **** **** **** **** **** +14123 Touchsight **** **** **** **** **** **** **** **** +14124 BodyPurification **** **** **** **** **** **** **** **** +14125 Dispel_Psionics **** **** **** **** **** **** **** **** +14126 Energy_Wall_Cold **** **** **** **** **** **** **** **** +14127 Energy_Wall_Elec **** **** **** **** **** **** **** **** +14128 Energy_Wall_Fire **** **** **** **** **** **** **** **** +14129 Energy_Wall_Sonic **** **** **** **** **** **** **** **** +14130 Hustle **** **** **** **** **** **** **** **** +14131 TimeHop **** **** **** **** **** **** **** **** +14132 UbiqVision **** **** **** **** **** **** **** **** +14133 EctoCocoon **** **** **** **** **** **** **** **** +14134 CrisisBreath **** **** **** **** **** **** **** **** +14135 EmpathicTransferHostile **** **** **** **** **** **** **** **** +14136 FateLink **** **** **** **** **** **** **** **** +14137 DimensionSlide **** **** **** **** **** **** **** **** +14138 EctoplasmicForm **** **** **** **** **** **** **** **** +14139 EnergyCone_Cold **** **** **** **** **** **** **** **** +14140 EnergyCone_Elec **** **** **** **** **** **** **** **** +14141 EnergyCone_Fire **** **** **** **** **** **** **** **** +14142 EnergyCone_Sonic **** **** **** **** **** **** **** **** +14143 ClawOfTheVampire **** **** **** **** **** **** **** **** +14144 DuodimensionalClaw **** **** **** **** **** **** **** **** +14145 VampiricWeapon **** **** **** **** **** **** **** **** +14146 EscapeDetection **** **** **** **** **** **** **** **** +14147 InertialBar **** **** **** **** **** **** **** **** +14148 SteadfastPercep **** **** **** **** **** **** **** **** +14149 DetectRemoteViewing **** **** **** **** **** **** **** **** +14150 EmpathicFeedback **** **** **** **** **** **** **** **** +14151 EnergyAdaption **** **** **** **** **** **** **** **** +14152 Freedom_of_Movement **** **** **** **** **** **** **** **** +14153 Mindwipe **** **** **** **** **** **** **** **** +14154 PowerLeech **** **** **** **** **** **** **** **** +14155 PsychicReformation **** **** **** **** **** **** **** **** +14156 TelekineticManeuver **** **** **** **** **** **** **** **** +14157 DimensionalAnchor **** **** **** **** **** **** **** **** +14158 Dismissal **** **** **** **** **** **** **** **** +14159 DimensionDoor_SelfOnly **** **** **** **** **** **** **** **** +14160 DimensionDoor_Party **** **** **** **** **** **** **** **** +14161 Dominate_Psionic **** **** **** **** **** **** **** **** +14162 DimensionDoor_Master **** **** **** **** **** **** **** **** +14163 DimensionDoor_DirDist_SelfOnly **** **** **** **** **** **** **** **** +14164 DimensionDoor_DirDist_Party **** **** **** **** **** **** **** **** +14165 EnergyBall_Cold **** **** **** **** **** **** **** **** +14166 EnergyBall_Elec **** **** **** **** **** **** **** **** +14167 EnergyBall_Fire **** **** **** **** **** **** **** **** +14168 EnergyBall_Sonic **** **** **** **** **** **** **** **** +14169 PsychicVampire **** **** **** **** **** **** **** **** +14170 ClawofEnergyCold **** **** **** **** **** **** **** **** +14171 ClawofEnergyElec **** **** **** **** **** **** **** **** +14172 ClawofEnergyFire **** **** **** **** **** **** **** **** +14173 Immovability **** **** **** **** **** **** **** **** +14174 Truevenom **** **** **** **** **** **** **** **** +14175 TruevenomWeapon **** **** **** **** **** **** **** **** +14176 WeaponofEnergyCold **** **** **** **** **** **** **** **** +14177 WeaponofEnergyElec **** **** **** **** **** **** **** **** +14178 WeaponofEnergyFire **** **** **** **** **** **** **** **** +14179 IntellectFortress **** **** **** **** **** **** **** **** +14180 RemoteViewing **** **** **** **** **** **** **** **** +14181 BaleTeleport **** **** **** **** **** **** **** **** +14182 EctoplasmicShambler **** **** **** **** **** **** **** **** +14183 Power_Resistance **** **** **** **** **** **** **** **** +14184 PsychicCrush **** **** **** **** **** **** **** **** +14185 TowerIronWill **** **** **** **** **** **** **** **** +14186 True_Seeing **** **** **** **** **** **** **** **** +14187 Catapsi **** **** **** **** **** **** **** **** +14188 ShatterMindBlank **** **** **** **** **** **** **** **** +14189 HailCrystals **** **** **** **** **** **** **** **** +14190 SecondChance **** **** **** **** **** **** **** **** +14191 Teleport_SelfOnly **** **** **** **** **** **** **** **** +14192 Teleport_Party **** **** **** **** **** **** **** **** +14193 EnergyCurrent_Cold **** **** **** **** **** **** **** **** +14194 EnergyCurrent_Elec **** **** **** **** **** **** **** **** +14195 EnergyCurrent_Fire **** **** **** **** **** **** **** **** +14196 EnergyCurrent_Sonic **** **** **** **** **** **** **** **** +14197 PsionicRevivify **** **** **** **** **** **** **** **** +14198 Psychofeedback **** **** **** **** **** **** **** **** +14199 ClairtangentHand **** **** **** **** **** **** **** **** +14200 BreathBlackDragon **** **** **** **** **** **** **** **** +14201 Disintegrate **** **** **** **** **** **** **** **** +14202 Crystallize **** **** **** **** **** **** **** **** +14203 FuseFlesh **** **** **** **** **** **** **** **** +14204 Retrieve **** **** **** **** **** **** **** **** +14205 TemporalAcceleration **** **** **** **** **** **** **** **** +14206 Banishment **** **** **** **** **** **** **** **** +14207 GreatPrecognitionMain **** **** **** **** **** **** **** **** +14208 GreatPrecognitionAttack **** **** **** **** **** **** **** **** +14209 GreatPrecognitionDamage **** **** **** **** **** **** **** **** +14210 GreatPrecognitionSaves **** **** **** **** **** **** **** **** +14211 GreatPrecognitionSkills **** **** **** **** **** **** **** **** +14212 RestorationPsionic **** **** **** **** **** **** **** **** +14213 DispellingBuffer **** **** **** **** **** **** **** **** +14214 FormOfDoom **** **** **** **** **** **** **** **** +14215 NullPsionicsField **** **** **** **** **** **** **** **** +14216 RemoteViewTrap **** **** **** **** **** **** **** **** +14217 Cloud_Mind_Mass **** **** **** **** **** **** **** **** +14218 CrisisLife **** **** **** **** **** **** **** **** +14219 Decerebrate **** **** **** **** **** **** **** **** +14220 EnergyWaveCold **** **** **** **** **** **** **** **** +14221 EnergyWaveElec **** **** **** **** **** **** **** **** +14222 EnergyWaveFire **** **** **** **** **** **** **** **** +14223 EnergyWaveSonic **** **** **** **** **** **** **** **** +14224 Insanity **** **** **** **** **** **** **** **** +14225 Mind_BlankPersonal **** **** **** **** **** **** **** **** +14226 OakBody **** **** **** **** **** **** **** **** +14227 Ultrablast **** **** **** **** **** **** **** **** +14228 EvadeBurst **** **** **** **** **** **** **** **** +14229 MomentOfPrescienceAttack **** **** **** **** **** **** **** **** +14230 MomentOfPrescienceArmour **** **** **** **** **** **** **** **** +14231 MomentOfPrescienceSaves **** **** **** **** **** **** **** **** +14232 MomentOfPrescienceSkills **** **** **** **** **** **** **** **** +14233 EctoCocoonMass **** **** **** **** **** **** **** **** +14234 EtherealJaunt **** **** **** **** **** **** **** **** +14235 Reddopsi **** **** **** **** **** **** **** **** +14236 Sequester **** **** **** **** **** **** **** **** +14237 RecallDeath **** **** **** **** **** **** **** **** +14238 IronBody **** **** **** **** **** **** **** **** +14239 PsionicMind_Blank **** **** **** **** **** **** **** **** +14240 TrueMetabolism **** **** **** **** **** **** **** **** +14241 Shadow_Body **** **** **** **** **** **** **** **** +14242 AstralSeed **** **** **** **** **** **** **** **** +14243 TimeHopMass **** **** **** **** **** **** **** **** +14244 Hypercognition **** **** **** **** **** **** **** **** +14245 GreaterTeleport_SelfOnly **** **** **** **** **** **** **** **** +14246 GreaterTeleport_Party **** **** **** **** **** **** **** **** +14247 Assimilate **** **** **** **** **** **** **** **** +14248 Etherealness **** **** **** **** **** **** **** **** +14249 Microcosm **** **** **** **** **** **** **** **** +14250 TimelessBody **** **** **** **** **** **** **** **** +14251 Genesis **** **** **** **** **** **** **** **** +14252 PsychicChirurgery_Repair **** **** **** **** **** **** **** **** +14253 TeleportationCircle_Visible **** **** **** **** **** **** **** **** +14254 TeleportationCircle_Hidden **** **** **** **** **** **** **** **** +14255 PsychicChirurgery_Transfer_TODO **** **** **** **** **** **** **** **** +14256 TornadoBlast **** **** **** **** **** **** **** **** +14257 CallWeaponry **** **** **** **** **** **** **** **** +14258 Compression **** **** **** **** **** **** **** **** +14259 Expansion **** **** **** **** **** **** **** **** +14260 ControlObject **** **** **** **** **** **** **** **** +14261 MetaphysicalClaw **** **** **** **** **** **** **** **** +14262 MetaphysicalWeapon **** **** **** **** **** **** **** **** +14263 Prevenom **** **** **** **** **** **** **** **** +14264 PrevenomWeapon **** **** **** **** **** **** **** **** +14265 GripOfIron **** **** **** **** **** **** **** **** +14266 PsionicLionsCharge **** **** **** **** **** **** **** **** +14267 **** **** **** **** **** **** **** **** **** +14268 **** **** **** **** **** **** **** **** **** +14269 **** **** **** **** **** **** **** **** **** +14270 **** **** **** **** **** **** **** **** **** +14271 **** **** **** **** **** **** **** **** **** +14272 **** **** **** **** **** **** **** **** **** +14273 **** **** **** **** **** **** **** **** **** +14274 **** **** **** **** **** **** **** **** **** +14275 **** **** **** **** **** **** **** **** **** +14276 **** **** **** **** **** **** **** **** **** +14277 **** **** **** **** **** **** **** **** **** +14278 **** **** **** **** **** **** **** **** **** +14279 **** **** **** **** **** **** **** **** **** +14280 **** **** **** **** **** **** **** **** **** +14281 **** **** **** **** **** **** **** **** **** +14282 **** **** **** **** **** **** **** **** **** +14283 **** **** **** **** **** **** **** **** **** +14284 **** **** **** **** **** **** **** **** **** +14285 **** **** **** **** **** **** **** **** **** +14286 **** **** **** **** **** **** **** **** **** +14287 **** **** **** **** **** **** **** **** **** +14288 **** **** **** **** **** **** **** **** **** +14289 **** **** **** **** **** **** **** **** **** +14290 **** **** **** **** **** **** **** **** **** +14291 **** **** **** **** **** **** **** **** **** +14292 **** **** **** **** **** **** **** **** **** +14293 **** **** **** **** **** **** **** **** **** +14294 **** **** **** **** **** **** **** **** **** +14295 **** **** **** **** **** **** **** **** **** +14296 **** **** **** **** **** **** **** **** **** +14297 **** **** **** **** **** **** **** **** **** +14298 **** **** **** **** **** **** **** **** **** +14299 **** **** **** **** **** **** **** **** **** +14300 **** **** **** **** **** **** **** **** **** +14301 **** **** **** **** **** **** **** **** **** +14302 **** **** **** **** **** **** **** **** **** +14303 **** **** **** **** **** **** **** **** **** +14304 **** **** **** **** **** **** **** **** **** +14305 **** **** **** **** **** **** **** **** **** +14306 **** **** **** **** **** **** **** **** **** +14307 **** **** **** **** **** **** **** **** **** +14308 **** **** **** **** **** **** **** **** **** +14309 **** **** **** **** **** **** **** **** **** +14310 **** **** **** **** **** **** **** **** **** +14311 **** **** **** **** **** **** **** **** **** +14312 **** **** **** **** **** **** **** **** **** +14313 **** **** **** **** **** **** **** **** **** +14314 **** **** **** **** **** **** **** **** **** +14315 **** **** **** **** **** **** **** **** **** +14316 **** **** **** **** **** **** **** **** **** +14317 **** **** **** **** **** **** **** **** **** +14318 **** **** **** **** **** **** **** **** **** +14319 **** **** **** **** **** **** **** **** **** +14320 **** **** **** **** **** **** **** **** **** +14321 **** **** **** **** **** **** **** **** **** +14322 **** **** **** **** **** **** **** **** **** +14323 **** **** **** **** **** **** **** **** **** +14324 **** **** **** **** **** **** **** **** **** +14325 **** **** **** **** **** **** **** **** **** +14326 **** **** **** **** **** **** **** **** **** +14327 **** **** **** **** **** **** **** **** **** +14328 **** **** **** **** **** **** **** **** **** +14329 **** **** **** **** **** **** **** **** **** +14330 AstralConstruct_RadialMaster **** **** **** **** **** **** **** **** +14331 EnergyRay_RadialMaster **** **** **** **** **** **** **** **** +14332 Precognition_RadialMaster **** **** **** **** **** **** **** **** +14333 EnergyAdaptSpec_RadialMaster **** **** **** **** **** **** **** **** +14334 EnergyPush_RadialMaster **** **** **** **** **** **** **** **** +14335 EnergyStun_RadialMaster **** **** **** **** **** **** **** **** +14336 Energy_Missile_RadialMaster **** **** **** **** **** **** **** **** +14337 EnergyBolt_RadialMaster **** **** **** **** **** **** **** **** +14338 EnergyBurst_RadialMaster **** **** **** **** **** **** **** **** +14339 EnergyRetort_RadialMaster **** **** **** **** **** **** **** **** +14340 EnergyWall_RadialMaster **** **** **** **** **** **** **** **** +14341 Energy_Cone_RadialMaster **** **** **** **** **** **** **** **** +14342 EnergyBall_RadialMaster **** **** **** **** **** **** **** **** +14343 Teleport_RadialMaster **** **** **** **** **** **** **** **** +14344 EnergyCurrent_RadialMaster **** **** **** **** **** **** **** **** +14345 GreatPrecognition_RadialMaster **** **** **** **** **** **** **** **** +14346 EnergyWave_RadialMaster **** **** **** **** **** **** **** **** +14347 MomentOfPrescience_RadialMaster **** **** **** **** **** **** **** **** +14348 GreaterTeleport_RadialMaster **** **** **** **** **** **** **** **** +14349 TeleportationCircle_RadialMaster **** **** **** **** **** **** **** **** +14350 ClawOfEnergy_RadialMaster **** **** **** **** **** **** **** **** +14351 WeaponOfEnergy_RadialMaster **** **** **** **** **** **** **** **** +14352 **** **** **** **** **** **** **** **** **** +14353 **** **** **** **** **** **** **** **** **** +14354 **** **** **** **** **** **** **** **** **** +14355 **** **** **** **** **** **** **** **** **** +14356 **** **** **** **** **** **** **** **** **** +14357 **** **** **** **** **** **** **** **** **** +14358 **** **** **** **** **** **** **** **** **** +14359 **** **** **** **** **** **** **** **** **** +14360 ####START_OF_PSI_SPELLBOOK_RESERVE **** **** **** **** **** **** **** **** +14361 Psychic_Rogue_Bolt **** **** **** **** **** **** **** **** +14362 Psychic_Rogue_Burst **** **** **** **** **** **** **** **** +14363 Psychic_Rogue_Compression **** **** **** **** **** **** **** **** +14364 Psychic_Rogue_Conceal_Thoughts **** **** **** **** **** **** **** **** +14365 Psychic_Rogue_ControlObject **** **** **** **** **** **** **** **** +14366 Psychic_Rogue_CreateSound **** **** **** **** **** **** **** **** +14367 Psychic_Rogue_DefPrecog **** **** **** **** **** **** **** **** +14368 Psychic_Rogue_Disable **** **** **** **** **** **** **** **** +14369 Psychic_Rogue_Distract **** **** **** **** **** **** **** **** +14370 Psychic_Rogue_ElfSight **** **** **** **** **** **** **** **** +14371 Psychic_Rogue_Empathy **** **** **** **** **** **** **** **** +14372 Psychic_Rogue_EmptyMind **** **** **** **** **** **** **** **** +14373 Psychic_Rogue_EntanglingEctoplasm **** **** **** **** **** **** **** **** +14374 Psychic_Rogue_Far_Hand **** **** **** **** **** **** **** **** +14375 Psychic_Rogue_ForceScreen **** **** **** **** **** **** **** **** +14376 Psychic_Rogue_MyLight **** **** **** **** **** **** **** **** +14377 Psychic_Rogue_OffPrecog **** **** **** **** **** **** **** **** +14378 Psychic_Rogue_OffPresc **** **** **** **** **** **** **** **** +14379 Psychic_Rogue_Skate **** **** **** **** **** **** **** **** +14380 Psychic_Rogue_Vigor **** **** **** **** **** **** **** **** +14381 Psychic_Rogue_AnimalAffinity **** **** **** **** **** **** **** **** +14382 Psychic_Rogue_Aversion **** **** **** **** **** **** **** **** +14383 Psychic_Rogue_Body_Equilibrium **** **** **** **** **** **** **** **** +14384 Psychic_Rogue_Chameleon **** **** **** **** **** **** **** **** +14385 Psychic_Rogue_Cloud_Mind **** **** **** **** **** **** **** **** +14386 Psychic_Rogue_ConcealAmorpha **** **** **** **** **** **** **** **** +14387 Psychic_Rogue_ControlObject **** **** **** **** **** **** **** **** +14388 Psychic_Rogue_ControlSound **** **** **** **** **** **** **** **** +14389 Psychic_Rogue_Darkvision **** **** **** **** **** **** **** **** +14390 Psychic_Rogue_Knock **** **** **** **** **** **** **** **** +14391 Psychic_Rogue_ThoughtShield **** **** **** **** **** **** **** **** +14392 Psychic_Rogue_BodyAdjustment **** **** **** **** **** **** **** **** +14393 Psychic_Rogue_BodyPurification **** **** **** **** **** **** **** **** +14394 Psychic_Rogue_ControlAir **** **** **** **** **** **** **** **** +14395 Psychic_Rogue_DimensionSlide **** **** **** **** **** **** **** **** +14396 Psychic_Rogue_EscapeDetection **** **** **** **** **** **** **** **** +14397 Psychic_Rogue_Greater_Amorpha **** **** **** **** **** **** **** **** +14398 Psychic_Rogue_Hustle **** **** **** **** **** **** **** **** +14399 Psychic_Rogue_Keen_Edge **** **** **** **** **** **** **** **** +14400 Psychic_Rogue_MentalBarrier **** **** **** **** **** **** **** **** +14401 Psychic_Rogue_UbiqVision **** **** **** **** **** **** **** **** +14402 Psychic_Rogue_DimensionDoor_Master **** **** **** **** **** **** **** **** +14403 Psychic_Rogue_DimensionDoor_SelfOnly **** **** **** **** **** **** **** **** +14404 Psychic_Rogue_DimensionDoor_Party **** **** **** **** **** **** **** **** +14405 Psychic_Rogue_DimensionDoor_DirDist_SelfOnly **** **** **** **** **** **** **** **** +14406 Psychic_Rogue_DimensionDoor_DirDist_Party **** **** **** **** **** **** **** **** +14407 Psychic_Rogue_Freedom_of_Movement **** **** **** **** **** **** **** **** +14408 Psychic_Rogue_SteadfastPercep **** **** **** **** **** **** **** **** +14409 Psychic_Rogue_TelekineticManeuver **** **** **** **** **** **** **** **** +14410 Psychic_Rogue_Power_Resistance **** **** **** **** **** **** **** **** +14411 Psychic_Rogue_RemoteViewing **** **** **** **** **** **** **** **** +14412 Psychic_Rogue_Retrieve **** **** **** **** **** **** **** **** +14413 Psychic_Rogue_PsionicRevivify **** **** **** **** **** **** **** **** +14414 Psychic_Rogue_True_Seeing **** **** **** **** **** **** **** **** +14415 Psion_AstralConstruct_RadialMaster **** **** **** **** **** **** **** **** +14416 Psion_AstralConstruct_Conversation **** **** **** **** **** **** **** **** +14417 Psion_AstralConstruct_Slot1 **** **** **** **** **** **** **** **** +14418 Psion_AstralConstruct_Slot2 **** **** **** **** **** **** **** **** +14419 Psion_AstralConstruct_Slot3 **** **** **** **** **** **** **** **** +14420 Psion_AstralConstruct_Slot4 **** **** **** **** **** **** **** **** +14421 Psion_BiteOfTheWolf **** **** **** **** **** **** **** **** +14422 Psion_Bolt **** **** **** **** **** **** **** **** +14423 Psion_Burst **** **** **** **** **** **** **** **** +14424 Psion_CallToMind **** **** **** **** **** **** **** **** +14425 Psion_CallWeaponry **** **** **** **** **** **** **** **** +14426 Psion_CharmPerson **** **** **** **** **** **** **** **** +14427 Psion_ClawsOfTheBeast **** **** **** **** **** **** **** **** +14428 Psion_Compression **** **** **** **** **** **** **** **** +14429 Psion_Conceal_Thoughts **** **** **** **** **** **** **** **** +14430 Psion_ControlObject **** **** **** **** **** **** **** **** +14431 Psion_CreateSound **** **** **** **** **** **** **** **** +14432 Psion_CrystalShard **** **** **** **** **** **** **** **** +14433 Psion_Daze **** **** **** **** **** **** **** **** +14434 Psion_Deceleration **** **** **** **** **** **** **** **** +14435 Psion_DefPrecog **** **** **** **** **** **** **** **** +14436 Psion_Demoralize **** **** **** **** **** **** **** **** +14437 Psion_DestinyDissonance **** **** **** **** **** **** **** **** +14438 Psion_Disable **** **** **** **** **** **** **** **** +14439 Psion_DissipatingTouch **** **** **** **** **** **** **** **** +14440 Psion_Distract **** **** **** **** **** **** **** **** +14441 Psion_Empathy **** **** **** **** **** **** **** **** +14442 Psion_EmptyMind **** **** **** **** **** **** **** **** +14443 Psion_EnergyRay_RadialMaster **** **** **** **** **** **** **** **** +14444 Psion_EnergyRay_Cold **** **** **** **** **** **** **** **** +14445 Psion_EnergyRay_Elec **** **** **** **** **** **** **** **** +14446 Psion_EnergyRay_Fire **** **** **** **** **** **** **** **** +14447 Psion_EnergyRay_Sonic **** **** **** **** **** **** **** **** +14448 Psion_EntanglingEctoplasm **** **** **** **** **** **** **** **** +14449 Psion_Expansion **** **** **** **** **** **** **** **** +14450 Psion_Far_Hand **** **** **** **** **** **** **** **** +14451 Psion_ForceScreen **** **** **** **** **** **** **** **** +14452 Psion_Grease **** **** **** **** **** **** **** **** +14453 Psion_Hammer **** **** **** **** **** **** **** **** +14454 Psion_InertialArmour **** **** **** **** **** **** **** **** +14455 Psion_Matter_Agitation **** **** **** **** **** **** **** **** +14456 Psion_MetaphysicalClaw **** **** **** **** **** **** **** **** +14457 Psion_MetaphysicalWeapon **** **** **** **** **** **** **** **** +14458 Psion_MindThrust **** **** **** **** **** **** **** **** +14459 Psion_MyLight **** **** **** **** **** **** **** **** +14460 Psion_OffPrecog **** **** **** **** **** **** **** **** +14461 Psion_OffPresc **** **** **** **** **** **** **** **** +14462 Psion_Precognition_RadialMaster **** **** **** **** **** **** **** **** +14463 Psion_PrecognitionMain **** **** **** **** **** **** **** **** +14464 Psion_PrecognitionAttack **** **** **** **** **** **** **** **** +14465 Psion_PrecognitionDamage **** **** **** **** **** **** **** **** +14466 Psion_PrecognitionSaves **** **** **** **** **** **** **** **** +14467 Psion_PrecognitionSkills **** **** **** **** **** **** **** **** +14468 Psion_Prevenom **** **** **** **** **** **** **** **** +14469 Psion_PrevenomWeapon **** **** **** **** **** **** **** **** +14470 Psion_Skate **** **** **** **** **** **** **** **** +14471 Psion_Stomp **** **** **** **** **** **** **** **** +14472 Psion_Synesthete **** **** **** **** **** **** **** **** +14473 Psion_Telempathic_Projection **** **** **** **** **** **** **** **** +14474 Psion_ThickSkin **** **** **** **** **** **** **** **** +14475 Psion_Vigor **** **** **** **** **** **** **** **** +14476 Psion_AnimalAffinity **** **** **** **** **** **** **** **** +14477 Psion_Aversion **** **** **** **** **** **** **** **** +14478 Psion_BestowPower **** **** **** **** **** **** **** **** +14479 Psion_Biofeedback **** **** **** **** **** **** **** **** +14480 Psion_Body_Equilibrium **** **** **** **** **** **** **** **** +14481 Psion_BrainLock **** **** **** **** **** **** **** **** +14482 Psion_Chameleon **** **** **** **** **** **** **** **** +14483 Psion_ClairvoyantSense **** **** **** **** **** **** **** **** +14484 Psion_Cloud_Mind **** **** **** **** **** **** **** **** +14485 Psion_ConcBlast **** **** **** **** **** **** **** **** +14486 Psion_ConcealAmorpha **** **** **** **** **** **** **** **** +14487 Psion_ControlAir **** **** **** **** **** **** **** **** +14488 Psion_ControlSound **** **** **** **** **** **** **** **** +14489 Psion_SwarmOfCrystals **** **** **** **** **** **** **** **** +14490 Psion_DimensionSwap **** **** **** **** **** **** **** **** +14491 Psion_DissolvingTouch **** **** **** **** **** **** **** **** +14492 Psion_Dissolving_Weapon **** **** **** **** **** **** **** **** +14493 Psion_EgoWhip **** **** **** **** **** **** **** **** +14494 Psion_ElfSight **** **** **** **** **** **** **** **** +14495 Psion_EmpathicTransfer **** **** **** **** **** **** **** **** +14496 Psion_EnergyAdaptSpec_RadialMaster **** **** **** **** **** **** **** **** +14497 Psion_EnergyAdaptAcid **** **** **** **** **** **** **** **** +14498 Psion_EnergyAdaptCold **** **** **** **** **** **** **** **** +14499 Psion_EnergyAdaptElec **** **** **** **** **** **** **** **** +14500 Psion_EnergyAdaptFire **** **** **** **** **** **** **** **** +14501 Psion_EnergyAdaptSonic **** **** **** **** **** **** **** **** +14502 Psion_Energy_Missile_RadialMaster **** **** **** **** **** **** **** **** +14503 Psion_Energy_Missile_Cold **** **** **** **** **** **** **** **** +14504 Psion_Energy_Missile_Elec **** **** **** **** **** **** **** **** +14505 Psion_Energy_Missile_Fire **** **** **** **** **** **** **** **** +14506 Psion_Energy_Missile_Sonic **** **** **** **** **** **** **** **** +14507 Psion_EnergyPush_RadialMaster **** **** **** **** **** **** **** **** +14508 Psion_EnergyPush_Cold **** **** **** **** **** **** **** **** +14509 Psion_EnergyPush_Elec **** **** **** **** **** **** **** **** +14510 Psion_EnergyPush_Fire **** **** **** **** **** **** **** **** +14511 Psion_EnergyPush_Sonic **** **** **** **** **** **** **** **** +14512 Psion_EnergyStun_RadialMaster **** **** **** **** **** **** **** **** +14513 Psion_EnergyStun_Cold **** **** **** **** **** **** **** **** +14514 Psion_EnergyStun_Elec **** **** **** **** **** **** **** **** +14515 Psion_EnergyStun_Fire **** **** **** **** **** **** **** **** +14516 Psion_EnergyStun_Sonic **** **** **** **** **** **** **** **** +14517 Psion_Identify **** **** **** **** **** **** **** **** +14518 Psion_IdInsinuation **** **** **** **** **** **** **** **** +14519 Psion_InflictPain **** **** **** **** **** **** **** **** +14520 Psion_Knock **** **** **** **** **** **** **** **** +14521 Psion_Lock **** **** **** **** **** **** **** **** +14522 Psion_MindDisrupt **** **** **** **** **** **** **** **** +14523 Psion_PainfulStrike **** **** **** **** **** **** **** **** +14524 Psion_RecallAgony **** **** **** **** **** **** **** **** +14525 Psion_RepairDamage **** **** **** **** **** **** **** **** +14526 Psion_SharePain **** **** **** **** **** **** **** **** +14527 Psion_StrengthOfMyEnemy **** **** **** **** **** **** **** **** +14528 Psion_ThoughtShield **** **** **** **** **** **** **** **** +14529 Psion_BodyAdjustment **** **** **** **** **** **** **** **** +14530 Psion_BodyPurification **** **** **** **** **** **** **** **** +14531 Psion_ClawOfTheVampire **** **** **** **** **** **** **** **** +14532 Psion_CrisisBreath **** **** **** **** **** **** **** **** +14533 Psion_Danger_Sense **** **** **** **** **** **** **** **** +14534 Psion_Darkvision **** **** **** **** **** **** **** **** +14535 Psion_DimensionSlide **** **** **** **** **** **** **** **** +14536 Psion_Dispel_Psionics **** **** **** **** **** **** **** **** +14537 Psion_DuodimensionalClaw **** **** **** **** **** **** **** **** +14538 Psion_EctoCocoon **** **** **** **** **** **** **** **** +14539 Psion_EctoplasmicForm **** **** **** **** **** **** **** **** +14540 Psion_EmpathicTransferHostile **** **** **** **** **** **** **** **** +14541 Psion_EnergyBolt_RadialMaster **** **** **** **** **** **** **** **** +14542 Psion_Energy_Bolt_Cold **** **** **** **** **** **** **** **** +14543 Psion_Energy_Bolt_Elec **** **** **** **** **** **** **** **** +14544 Psion_Energy_Bolt_Fire **** **** **** **** **** **** **** **** +14545 Psion_Energy_Bolt_Sonic **** **** **** **** **** **** **** **** +14546 Psion_EnergyBurst_RadialMaster **** **** **** **** **** **** **** **** +14547 Psion_Energy_Burst_Cold **** **** **** **** **** **** **** **** +14548 Psion_Energy_Burst_Elec **** **** **** **** **** **** **** **** +14549 Psion_Energy_Burst_Fire **** **** **** **** **** **** **** **** +14550 Psion_Energy_Burst_Sonic **** **** **** **** **** **** **** **** +14551 Psion_Energy_Cone_RadialMaster **** **** **** **** **** **** **** **** +14552 Psion_EnergyCone_Cold **** **** **** **** **** **** **** **** +14553 Psion_EnergyCone_Elec **** **** **** **** **** **** **** **** +14554 Psion_EnergyCone_Fire **** **** **** **** **** **** **** **** +14555 Psion_EnergyCone_Sonic **** **** **** **** **** **** **** **** +14556 Psion_EnergyRetort_RadialMaster **** **** **** **** **** **** **** **** +14557 Psion_Energy_Retort_Cold **** **** **** **** **** **** **** **** +14558 Psion_Energy_Retort_Elec **** **** **** **** **** **** **** **** +14559 Psion_Energy_Retort_Fire **** **** **** **** **** **** **** **** +14560 Psion_Energy_Retort_Sonic **** **** **** **** **** **** **** **** +14561 Psion_EnergyWall_RadialMaster **** **** **** **** **** **** **** **** +14562 Psion_Energy_Wall_Cold **** **** **** **** **** **** **** **** +14563 Psion_Energy_Wall_Elec **** **** **** **** **** **** **** **** +14564 Psion_Energy_Wall_Fire **** **** **** **** **** **** **** **** +14565 Psion_Energy_Wall_Sonic **** **** **** **** **** **** **** **** +14566 Psion_Eradicate_Invisibility **** **** **** **** **** **** **** **** +14567 Psion_EscapeDetection **** **** **** **** **** **** **** **** +14568 Psion_Exhale_BlackDrag **** **** **** **** **** **** **** **** +14569 Psion_FateLink **** **** **** **** **** **** **** **** +14570 Psion_Greater_Amorpha **** **** **** **** **** **** **** **** +14571 Psion_Hustle **** **** **** **** **** **** **** **** +14572 Psion_Keen_Edge **** **** **** **** **** **** **** **** +14573 Psion_MentalBarrier **** **** **** **** **** **** **** **** +14574 Psion_Mindtrap **** **** **** **** **** **** **** **** +14575 Psion_Psiblast **** **** **** **** **** **** **** **** +14576 Psion_SharePainForced **** **** **** **** **** **** **** **** +14577 Psion_TimeHop **** **** **** **** **** **** **** **** +14578 Psion_Touchsight **** **** **** **** **** **** **** **** +14579 Psion_UbiqVision **** **** **** **** **** **** **** **** +14580 Psion_VampiricWeapon **** **** **** **** **** **** **** **** +14581 Psion_ClawOfEnergy_RadialMaster **** **** **** **** **** **** **** **** +14582 Psion_ClawofEnergyCold **** **** **** **** **** **** **** **** +14583 Psion_ClawofEnergyElec **** **** **** **** **** **** **** **** +14584 Psion_ClawofEnergyFire **** **** **** **** **** **** **** **** +14585 Psion_DetectRemoteViewing **** **** **** **** **** **** **** **** +14586 Psion_DimensionalAnchor **** **** **** **** **** **** **** **** +14587 Psion_DimensionDoor_Master **** **** **** **** **** **** **** **** +14588 Psion_DimensionDoor_SelfOnly **** **** **** **** **** **** **** **** +14589 Psion_DimensionDoor_Party **** **** **** **** **** **** **** **** +14590 Psion_DimensionDoor_DirDist_SelfOnly **** **** **** **** **** **** **** **** +14591 Psion_DimensionDoor_DirDist_Party **** **** **** **** **** **** **** **** +14592 Psion_Dismissal **** **** **** **** **** **** **** **** +14593 Psion_EmpathicFeedback **** **** **** **** **** **** **** **** +14594 Psion_EnergyAdaption **** **** **** **** **** **** **** **** +14595 Psion_EnergyBall_RadialMaster **** **** **** **** **** **** **** **** +14596 Psion_EnergyBall_Cold **** **** **** **** **** **** **** **** +14597 Psion_EnergyBall_Elec **** **** **** **** **** **** **** **** +14598 Psion_EnergyBall_Fire **** **** **** **** **** **** **** **** +14599 Psion_EnergyBall_Sonic **** **** **** **** **** **** **** **** +14600 Psion_Freedom_of_Movement **** **** **** **** **** **** **** **** +14601 Psion_Immovability **** **** **** **** **** **** **** **** +14602 Psion_InertialBar **** **** **** **** **** **** **** **** +14603 Psion_IntellectFortress **** **** **** **** **** **** **** **** +14604 Psion_Mindwipe **** **** **** **** **** **** **** **** +14605 Psion_PowerLeech **** **** **** **** **** **** **** **** +14606 Psion_Dominate_Psionic **** **** **** **** **** **** **** **** +14607 Psion_PsychicReformation **** **** **** **** **** **** **** **** +14608 Psion_PsychicVampire **** **** **** **** **** **** **** **** +14609 Psion_RemoteViewing **** **** **** **** **** **** **** **** +14610 Psion_SteadfastPercep **** **** **** **** **** **** **** **** +14611 Psion_TelekineticManeuver **** **** **** **** **** **** **** **** +14612 Psion_Truevenom **** **** **** **** **** **** **** **** +14613 Psion_TruevenomWeapon **** **** **** **** **** **** **** **** +14614 Psion_WeaponOfEnergy_RadialMaster **** **** **** **** **** **** **** **** +14615 Psion_WeaponofEnergyCold **** **** **** **** **** **** **** **** +14616 Psion_WeaponofEnergyElec **** **** **** **** **** **** **** **** +14617 Psion_WeaponofEnergyFire **** **** **** **** **** **** **** **** +14618 Psion_BaleTeleport **** **** **** **** **** **** **** **** +14619 Psion_Catapsi **** **** **** **** **** **** **** **** +14620 Psion_ClairtangentHand **** **** **** **** **** **** **** **** +14621 Psion_EctoplasmicShambler **** **** **** **** **** **** **** **** +14622 Psion_EnergyCurrent_RadialMaster **** **** **** **** **** **** **** **** +14623 Psion_EnergyCurrent_Cold **** **** **** **** **** **** **** **** +14624 Psion_EnergyCurrent_Elec **** **** **** **** **** **** **** **** +14625 Psion_EnergyCurrent_Fire **** **** **** **** **** **** **** **** +14626 Psion_EnergyCurrent_Sonic **** **** **** **** **** **** **** **** +14627 Psion_HailCrystals **** **** **** **** **** **** **** **** +14628 Psion_Power_Resistance **** **** **** **** **** **** **** **** +14629 Psion_PsionicRevivify **** **** **** **** **** **** **** **** +14630 Psion_PsychicCrush **** **** **** **** **** **** **** **** +14631 Psion_Psychofeedback **** **** **** **** **** **** **** **** +14632 Psion_SecondChance **** **** **** **** **** **** **** **** +14633 Psion_ShatterMindBlank **** **** **** **** **** **** **** **** +14634 Psion_Teleport_RadialMaster **** **** **** **** **** **** **** **** +14635 Psion_Teleport_SelfOnly **** **** **** **** **** **** **** **** +14636 Psion_Teleport_Party **** **** **** **** **** **** **** **** +14637 Psion_TowerIronWill **** **** **** **** **** **** **** **** +14638 Psion_True_Seeing **** **** **** **** **** **** **** **** +14639 Psion_Banishment **** **** **** **** **** **** **** **** +14640 Psion_BreathBlackDragon **** **** **** **** **** **** **** **** +14641 Psion_Cloud_Mind_Mass **** **** **** **** **** **** **** **** +14642 Psion_Crystallize **** **** **** **** **** **** **** **** +14643 Psion_Disintegrate **** **** **** **** **** **** **** **** +14644 Psion_DispellingBuffer **** **** **** **** **** **** **** **** +14645 Psion_FormOfDoom **** **** **** **** **** **** **** **** +14646 Psion_FuseFlesh **** **** **** **** **** **** **** **** +14647 Psion_GreatPrecognition_RadialMaster **** **** **** **** **** **** **** **** +14648 Psion_GreatPrecognitionMain **** **** **** **** **** **** **** **** +14649 Psion_GreatPrecognitionAttack **** **** **** **** **** **** **** **** +14650 Psion_GreatPrecognitionDamage **** **** **** **** **** **** **** **** +14651 Psion_GreatPrecognitionSaves **** **** **** **** **** **** **** **** +14652 Psion_GreatPrecognitionSkills **** **** **** **** **** **** **** **** +14653 Psion_NullPsionicsField **** **** **** **** **** **** **** **** +14654 Psion_RemoteViewTrap **** **** **** **** **** **** **** **** +14655 Psion_RestorationPsionic **** **** **** **** **** **** **** **** +14656 Psion_Retrieve **** **** **** **** **** **** **** **** +14657 Psion_TemporalAcceleration **** **** **** **** **** **** **** **** +14658 Psion_CrisisLife **** **** **** **** **** **** **** **** +14659 Psion_Decerebrate **** **** **** **** **** **** **** **** +14660 Psion_EctoCocoonMass **** **** **** **** **** **** **** **** +14661 Psion_EnergyWave_RadialMaster **** **** **** **** **** **** **** **** +14662 Psion_EnergyWaveCold **** **** **** **** **** **** **** **** +14663 Psion_EnergyWaveElec **** **** **** **** **** **** **** **** +14664 Psion_EnergyWaveFire **** **** **** **** **** **** **** **** +14665 Psion_EnergyWaveSonic **** **** **** **** **** **** **** **** +14666 Psion_EtherealJaunt **** **** **** **** **** **** **** **** +14667 Psion_EvadeBurst **** **** **** **** **** **** **** **** +14668 Psion_Insanity **** **** **** **** **** **** **** **** +14669 Psion_Mind_BlankPersonal **** **** **** **** **** **** **** **** +14670 Psion_MomentOfPrescience_RadialMaster **** **** **** **** **** **** **** **** +14671 Psion_MomentOfPrescienceAttack **** **** **** **** **** **** **** **** +14672 Psion_MomentOfPrescienceArmour **** **** **** **** **** **** **** **** +14673 Psion_MomentOfPrescienceSaves **** **** **** **** **** **** **** **** +14674 Psion_MomentOfPrescienceSkills **** **** **** **** **** **** **** **** +14675 Psion_OakBody **** **** **** **** **** **** **** **** +14676 Psion_Reddopsi **** **** **** **** **** **** **** **** +14677 Psion_Sequester **** **** **** **** **** **** **** **** +14678 Psion_Ultrablast **** **** **** **** **** **** **** **** +14679 Psion_AstralSeed **** **** **** **** **** **** **** **** +14680 Psion_GreaterTeleport_RadialMaster **** **** **** **** **** **** **** **** +14681 Psion_GreaterTeleport_SelfOnly **** **** **** **** **** **** **** **** +14682 Psion_GreaterTeleport_Party **** **** **** **** **** **** **** **** +14683 Psion_Hypercognition **** **** **** **** **** **** **** **** +14684 Psion_IronBody **** **** **** **** **** **** **** **** +14685 Psion_PsionicMind_Blank **** **** **** **** **** **** **** **** +14686 Psion_RecallDeath **** **** **** **** **** **** **** **** +14687 Psion_Shadow_Body **** **** **** **** **** **** **** **** +14688 Psion_TimeHopMass **** **** **** **** **** **** **** **** +14689 Psion_TrueMetabolism **** **** **** **** **** **** **** **** +14690 Psion_Assimilate **** **** **** **** **** **** **** **** +14691 Psion_Etherealness **** **** **** **** **** **** **** **** +14692 Psion_Genesis **** **** **** **** **** **** **** **** +14693 Psion_Microcosm **** **** **** **** **** **** **** **** +14694 Psion_PsychicChirurgery_Repair **** **** **** **** **** **** **** **** +14695 Psion_TeleportationCircle_RadialMaster **** **** **** **** **** **** **** **** +14696 Psion_TeleportationCircle_Visible **** **** **** **** **** **** **** **** +14697 Psion_TeleportationCircle_Hidden **** **** **** **** **** **** **** **** +14698 Psion_TimelessBody **** **** **** **** **** **** **** **** +14699 Psion_TornadoBlast **** **** **** **** **** **** **** **** +14700 Psychic_Warrior_AstralConstruct_RadialMaster **** **** **** **** **** **** **** **** +14701 Psychic_Warrior_AstralConstruct_Conversation **** **** **** **** **** **** **** **** +14702 Psychic_Warrior_AstralConstruct_Slot1 **** **** **** **** **** **** **** **** +14703 Psychic_Warrior_AstralConstruct_Slot2 **** **** **** **** **** **** **** **** +14704 Psychic_Warrior_AstralConstruct_Slot3 **** **** **** **** **** **** **** **** +14705 Psychic_Warrior_AstralConstruct_Slot4 **** **** **** **** **** **** **** **** +14706 Psychic_Warrior_Biofeedback **** **** **** **** **** **** **** **** +14707 Psychic_Warrior_BiteOfTheWolf **** **** **** **** **** **** **** **** +14708 Psychic_Warrior_Bolt **** **** **** **** **** **** **** **** +14709 Psychic_Warrior_Burst **** **** **** **** **** **** **** **** +14710 Psychic_Warrior_CallToMind **** **** **** **** **** **** **** **** +14711 Psychic_Warrior_CallWeaponry **** **** **** **** **** **** **** **** +14712 Psychic_Warrior_Chameleon **** **** **** **** **** **** **** **** +14713 Psychic_Warrior_CharmPerson **** **** **** **** **** **** **** **** +14714 Psychic_Warrior_ClawsOfTheBeast **** **** **** **** **** **** **** **** +14715 Psychic_Warrior_Compression **** **** **** **** **** **** **** **** +14716 Psychic_Warrior_Conceal_Thoughts **** **** **** **** **** **** **** **** +14717 Psychic_Warrior_ControlObject **** **** **** **** **** **** **** **** +14718 Psychic_Warrior_CreateSound **** **** **** **** **** **** **** **** +14719 Psychic_Warrior_CrystalShard **** **** **** **** **** **** **** **** +14720 Psychic_Warrior_Daze **** **** **** **** **** **** **** **** +14721 Psychic_Warrior_Deceleration **** **** **** **** **** **** **** **** +14722 Psychic_Warrior_DefPrecog **** **** **** **** **** **** **** **** +14723 Psychic_Warrior_Demoralize **** **** **** **** **** **** **** **** +14724 Psychic_Warrior_DestinyDissonance **** **** **** **** **** **** **** **** +14725 Psychic_Warrior_Disable **** **** **** **** **** **** **** **** +14726 Psychic_Warrior_DissipatingTouch **** **** **** **** **** **** **** **** +14727 Psychic_Warrior_Distract **** **** **** **** **** **** **** **** +14728 Psychic_Warrior_ElfSight **** **** **** **** **** **** **** **** +14729 Psychic_Warrior_Empathy **** **** **** **** **** **** **** **** +14730 Psychic_Warrior_EmptyMind **** **** **** **** **** **** **** **** +14731 Psychic_Warrior_EnergyRay_RadialMaster **** **** **** **** **** **** **** **** +14732 Psychic_Warrior_EnergyRay_Cold **** **** **** **** **** **** **** **** +14733 Psychic_Warrior_EnergyRay_Elec **** **** **** **** **** **** **** **** +14734 Psychic_Warrior_EnergyRay_Fire **** **** **** **** **** **** **** **** +14735 Psychic_Warrior_EnergyRay_Sonic **** **** **** **** **** **** **** **** +14736 Psychic_Warrior_EntanglingEctoplasm **** **** **** **** **** **** **** **** +14737 Psychic_Warrior_Expansion **** **** **** **** **** **** **** **** +14738 Psychic_Warrior_Far_Hand **** **** **** **** **** **** **** **** +14739 Psychic_Warrior_ForceScreen **** **** **** **** **** **** **** **** +14740 Psychic_Warrior_Grease **** **** **** **** **** **** **** **** +14741 Psychic_Warrior_Hammer **** **** **** **** **** **** **** **** +14742 Psychic_Warrior_InertialArmour **** **** **** **** **** **** **** **** +14743 Psychic_Warrior_Matter_Agitation **** **** **** **** **** **** **** **** +14744 Psychic_Warrior_MetaphysicalClaw **** **** **** **** **** **** **** **** +14745 Psychic_Warrior_MetaphysicalWeapon **** **** **** **** **** **** **** **** +14746 Psychic_Warrior_MindThrust **** **** **** **** **** **** **** **** +14747 Psychic_Warrior_MyLight **** **** **** **** **** **** **** **** +14748 Psychic_Warrior_OffPrecog **** **** **** **** **** **** **** **** +14749 Psychic_Warrior_OffPresc **** **** **** **** **** **** **** **** +14750 Psychic_Warrior_Precognition_RadialMaster **** **** **** **** **** **** **** **** +14751 Psychic_Warrior_PrecognitionMain **** **** **** **** **** **** **** **** +14752 Psychic_Warrior_PrecognitionAttack **** **** **** **** **** **** **** **** +14753 Psychic_Warrior_PrecognitionDamage **** **** **** **** **** **** **** **** +14754 Psychic_Warrior_PrecognitionSaves **** **** **** **** **** **** **** **** +14755 Psychic_Warrior_PrecognitionSkills **** **** **** **** **** **** **** **** +14756 Psychic_Warrior_Prevenom **** **** **** **** **** **** **** **** +14757 Psychic_Warrior_PrevenomWeapon **** **** **** **** **** **** **** **** +14758 Psychic_Warrior_Skate **** **** **** **** **** **** **** **** +14759 Psychic_Warrior_Stomp **** **** **** **** **** **** **** **** +14760 Psychic_Warrior_Synesthete **** **** **** **** **** **** **** **** +14761 Psychic_Warrior_Telempathic_Projection **** **** **** **** **** **** **** **** +14762 Psychic_Warrior_ThickSkin **** **** **** **** **** **** **** **** +14763 Psychic_Warrior_Vigor **** **** **** **** **** **** **** **** +14764 Psychic_Warrior_AnimalAffinity **** **** **** **** **** **** **** **** +14765 Psychic_Warrior_Aversion **** **** **** **** **** **** **** **** +14766 Psychic_Warrior_BestowPower **** **** **** **** **** **** **** **** +14767 Psychic_Warrior_BodyAdjustment **** **** **** **** **** **** **** **** +14768 Psychic_Warrior_Body_Equilibrium **** **** **** **** **** **** **** **** +14769 Psychic_Warrior_BodyPurification **** **** **** **** **** **** **** **** +14770 Psychic_Warrior_BrainLock **** **** **** **** **** **** **** **** +14771 Psychic_Warrior_ClairvoyantSense **** **** **** **** **** **** **** **** +14772 Psychic_Warrior_Cloud_Mind **** **** **** **** **** **** **** **** +14773 Psychic_Warrior_ConcBlast **** **** **** **** **** **** **** **** +14774 Psychic_Warrior_ConcealAmorpha **** **** **** **** **** **** **** **** +14775 Psychic_Warrior_ControlAir **** **** **** **** **** **** **** **** +14776 Psychic_Warrior_ControlSound **** **** **** **** **** **** **** **** +14777 Psychic_Warrior_SwarmOfCrystals **** **** **** **** **** **** **** **** +14778 Psychic_Warrior_Darkvision **** **** **** **** **** **** **** **** +14779 Psychic_Warrior_DimensionSwap **** **** **** **** **** **** **** **** +14780 Psychic_Warrior_DissolvingTouch **** **** **** **** **** **** **** **** +14781 Psychic_Warrior_Dissolving_Weapon **** **** **** **** **** **** **** **** +14782 Psychic_Warrior_EgoWhip **** **** **** **** **** **** **** **** +14783 Psychic_Warrior_EmpathicTransfer **** **** **** **** **** **** **** **** +14784 Psychic_Warrior_EnergyAdaptSpec_RadialMaster **** **** **** **** **** **** **** **** +14785 Psychic_Warrior_EnergyAdaptAcid **** **** **** **** **** **** **** **** +14786 Psychic_Warrior_EnergyAdaptCold **** **** **** **** **** **** **** **** +14787 Psychic_Warrior_EnergyAdaptElec **** **** **** **** **** **** **** **** +14788 Psychic_Warrior_EnergyAdaptFire **** **** **** **** **** **** **** **** +14789 Psychic_Warrior_EnergyAdaptSonic **** **** **** **** **** **** **** **** +14790 Psychic_Warrior_Energy_Missile_RadialMaster **** **** **** **** **** **** **** **** +14791 Psychic_Warrior_Energy_Missile_Cold **** **** **** **** **** **** **** **** +14792 Psychic_Warrior_Energy_Missile_Elec **** **** **** **** **** **** **** **** +14793 Psychic_Warrior_Energy_Missile_Fire **** **** **** **** **** **** **** **** +14794 Psychic_Warrior_Energy_Missile_Sonic **** **** **** **** **** **** **** **** +14795 Psychic_Warrior_EnergyPush_RadialMaster **** **** **** **** **** **** **** **** +14796 Psychic_Warrior_EnergyPush_Cold **** **** **** **** **** **** **** **** +14797 Psychic_Warrior_EnergyPush_Elec **** **** **** **** **** **** **** **** +14798 Psychic_Warrior_EnergyPush_Fire **** **** **** **** **** **** **** **** +14799 Psychic_Warrior_EnergyPush_Sonic **** **** **** **** **** **** **** **** +14800 Psychic_Warrior_EnergyStun_RadialMaster **** **** **** **** **** **** **** **** +14801 Psychic_Warrior_EnergyStun_Cold **** **** **** **** **** **** **** **** +14802 Psychic_Warrior_EnergyStun_Elec **** **** **** **** **** **** **** **** +14803 Psychic_Warrior_EnergyStun_Fire **** **** **** **** **** **** **** **** +14804 Psychic_Warrior_EnergyStun_Sonic **** **** **** **** **** **** **** **** +14805 Psychic_Warrior_Hustle **** **** **** **** **** **** **** **** +14806 Psychic_Warrior_Identify **** **** **** **** **** **** **** **** +14807 Psychic_Warrior_IdInsinuation **** **** **** **** **** **** **** **** +14808 Psychic_Warrior_InflictPain **** **** **** **** **** **** **** **** +14809 Psychic_Warrior_Knock **** **** **** **** **** **** **** **** +14810 Psychic_Warrior_Lock **** **** **** **** **** **** **** **** +14811 Psychic_Warrior_MindDisrupt **** **** **** **** **** **** **** **** +14812 Psychic_Warrior_PainfulStrike **** **** **** **** **** **** **** **** +14813 Psychic_Warrior_RecallAgony **** **** **** **** **** **** **** **** +14814 Psychic_Warrior_RepairDamage **** **** **** **** **** **** **** **** +14815 Psychic_Warrior_SharePain **** **** **** **** **** **** **** **** +14816 Psychic_Warrior_StrengthOfMyEnemy **** **** **** **** **** **** **** **** +14817 Psychic_Warrior_ThoughtShield **** **** **** **** **** **** **** **** +14818 Psychic_Warrior_ClawOfTheVampire **** **** **** **** **** **** **** **** +14819 Psychic_Warrior_CrisisBreath **** **** **** **** **** **** **** **** +14820 Psychic_Warrior_Danger_Sense **** **** **** **** **** **** **** **** +14821 Psychic_Warrior_DimensionSlide **** **** **** **** **** **** **** **** +14822 Psychic_Warrior_Dispel_Psionics **** **** **** **** **** **** **** **** +14823 Psychic_Warrior_DuodimensionalClaw **** **** **** **** **** **** **** **** +14824 Psychic_Warrior_EctoCocoon **** **** **** **** **** **** **** **** +14825 Psychic_Warrior_EctoplasmicForm **** **** **** **** **** **** **** **** +14826 Psychic_Warrior_EmpathicFeedback **** **** **** **** **** **** **** **** +14827 Psychic_Warrior_EmpathicTransferHostile **** **** **** **** **** **** **** **** +14828 Psychic_Warrior_EnergyBolt_RadialMaster **** **** **** **** **** **** **** **** +14829 Psychic_Warrior_Energy_Bolt_Cold **** **** **** **** **** **** **** **** +14830 Psychic_Warrior_Energy_Bolt_Elec **** **** **** **** **** **** **** **** +14831 Psychic_Warrior_Energy_Bolt_Fire **** **** **** **** **** **** **** **** +14832 Psychic_Warrior_Energy_Bolt_Sonic **** **** **** **** **** **** **** **** +14833 Psychic_Warrior_EnergyBurst_RadialMaster **** **** **** **** **** **** **** **** +14834 Psychic_Warrior_Energy_Burst_Cold **** **** **** **** **** **** **** **** +14835 Psychic_Warrior_Energy_Burst_Elec **** **** **** **** **** **** **** **** +14836 Psychic_Warrior_Energy_Burst_Fire **** **** **** **** **** **** **** **** +14837 Psychic_Warrior_Energy_Burst_Sonic **** **** **** **** **** **** **** **** +14838 Psychic_Warrior_Energy_Cone_RadialMaster **** **** **** **** **** **** **** **** +14839 Psychic_Warrior_EnergyCone_Cold **** **** **** **** **** **** **** **** +14840 Psychic_Warrior_EnergyCone_Elec **** **** **** **** **** **** **** **** +14841 Psychic_Warrior_EnergyCone_Fire **** **** **** **** **** **** **** **** +14842 Psychic_Warrior_EnergyCone_Sonic **** **** **** **** **** **** **** **** +14843 Psychic_Warrior_EnergyRetort_RadialMaster **** **** **** **** **** **** **** **** +14844 Psychic_Warrior_Energy_Retort_Cold **** **** **** **** **** **** **** **** +14845 Psychic_Warrior_Energy_Retort_Elec **** **** **** **** **** **** **** **** +14846 Psychic_Warrior_Energy_Retort_Fire **** **** **** **** **** **** **** **** +14847 Psychic_Warrior_Energy_Retort_Sonic **** **** **** **** **** **** **** **** +14848 Psychic_Warrior_EnergyWall_RadialMaster **** **** **** **** **** **** **** **** +14849 Psychic_Warrior_Energy_Wall_Cold **** **** **** **** **** **** **** **** +14850 Psychic_Warrior_Energy_Wall_Elec **** **** **** **** **** **** **** **** +14851 Psychic_Warrior_Energy_Wall_Fire **** **** **** **** **** **** **** **** +14852 Psychic_Warrior_Energy_Wall_Sonic **** **** **** **** **** **** **** **** +14853 Psychic_Warrior_Eradicate_Invisibility **** **** **** **** **** **** **** **** +14854 Psychic_Warrior_EscapeDetection **** **** **** **** **** **** **** **** +14855 Psychic_Warrior_EvadeBurst **** **** **** **** **** **** **** **** +14856 Psychic_Warrior_Exhale_BlackDrag **** **** **** **** **** **** **** **** +14857 Psychic_Warrior_FateLink **** **** **** **** **** **** **** **** +14858 Psychic_Warrior_Greater_Amorpha **** **** **** **** **** **** **** **** +14859 Psychic_Warrior_Keen_Edge **** **** **** **** **** **** **** **** +14860 Psychic_Warrior_MentalBarrier **** **** **** **** **** **** **** **** +14861 Psychic_Warrior_Mindtrap **** **** **** **** **** **** **** **** +14862 Psychic_Warrior_Psiblast **** **** **** **** **** **** **** **** +14863 Psychic_Warrior_SharePainForced **** **** **** **** **** **** **** **** +14864 Psychic_Warrior_TimeHop **** **** **** **** **** **** **** **** +14865 Psychic_Warrior_Touchsight **** **** **** **** **** **** **** **** +14866 Psychic_Warrior_UbiqVision **** **** **** **** **** **** **** **** +14867 Psychic_Warrior_VampiricWeapon **** **** **** **** **** **** **** **** +14868 Psychic_Warrior_ClawOfEnergy_RadialMaster **** **** **** **** **** **** **** **** +14869 Psychic_Warrior_ClawofEnergyCold **** **** **** **** **** **** **** **** +14870 Psychic_Warrior_ClawofEnergyElec **** **** **** **** **** **** **** **** +14871 Psychic_Warrior_ClawofEnergyFire **** **** **** **** **** **** **** **** +14872 Psychic_Warrior_DetectRemoteViewing **** **** **** **** **** **** **** **** +14873 Psychic_Warrior_DimensionalAnchor **** **** **** **** **** **** **** **** +14874 Psychic_Warrior_DimensionDoor_Master **** **** **** **** **** **** **** **** +14875 Psychic_Warrior_DimensionDoor_SelfOnly **** **** **** **** **** **** **** **** +14876 Psychic_Warrior_DimensionDoor_Party **** **** **** **** **** **** **** **** +14877 Psychic_Warrior_DimensionDoor_DirDist_SelfOnly **** **** **** **** **** **** **** **** +14878 Psychic_Warrior_DimensionDoor_DirDist_Party **** **** **** **** **** **** **** **** +14879 Psychic_Warrior_Dismissal **** **** **** **** **** **** **** **** +14880 Psychic_Warrior_EnergyAdaption **** **** **** **** **** **** **** **** +14881 Psychic_Warrior_EnergyBall_RadialMaster **** **** **** **** **** **** **** **** +14882 Psychic_Warrior_EnergyBall_Cold **** **** **** **** **** **** **** **** +14883 Psychic_Warrior_EnergyBall_Elec **** **** **** **** **** **** **** **** +14884 Psychic_Warrior_EnergyBall_Fire **** **** **** **** **** **** **** **** +14885 Psychic_Warrior_EnergyBall_Sonic **** **** **** **** **** **** **** **** +14886 Psychic_Warrior_Freedom_of_Movement **** **** **** **** **** **** **** **** +14887 Psychic_Warrior_Immovability **** **** **** **** **** **** **** **** +14888 Psychic_Warrior_InertialBar **** **** **** **** **** **** **** **** +14889 Psychic_Warrior_IntellectFortress **** **** **** **** **** **** **** **** +14890 Psychic_Warrior_Mindwipe **** **** **** **** **** **** **** **** +14891 Psychic_Warrior_PowerLeech **** **** **** **** **** **** **** **** +14892 Psychic_Warrior_Dominate_Psionic **** **** **** **** **** **** **** **** +14893 Psychic_Warrior_PsychicReformation **** **** **** **** **** **** **** **** +14894 Psychic_Warrior_PsychicVampire **** **** **** **** **** **** **** **** +14895 Psychic_Warrior_RemoteViewing **** **** **** **** **** **** **** **** +14896 Psychic_Warrior_SteadfastPercep **** **** **** **** **** **** **** **** +14897 Psychic_Warrior_TelekineticManeuver **** **** **** **** **** **** **** **** +14898 Psychic_Warrior_Truevenom **** **** **** **** **** **** **** **** +14899 Psychic_Warrior_TruevenomWeapon **** **** **** **** **** **** **** **** +14900 Psychic_Warrior_WeaponOfEnergy_RadialMaster **** **** **** **** **** **** **** **** +14901 Psychic_Warrior_WeaponofEnergyCold **** **** **** **** **** **** **** **** +14902 Psychic_Warrior_WeaponofEnergyElec **** **** **** **** **** **** **** **** +14903 Psychic_Warrior_WeaponofEnergyFire **** **** **** **** **** **** **** **** +14904 Psychic_Warrior_BaleTeleport **** **** **** **** **** **** **** **** +14905 Psychic_Warrior_Catapsi **** **** **** **** **** **** **** **** +14906 Psychic_Warrior_ClairtangentHand **** **** **** **** **** **** **** **** +14907 Psychic_Warrior_EctoplasmicShambler **** **** **** **** **** **** **** **** +14908 Psychic_Warrior_EnergyCurrent_RadialMaster **** **** **** **** **** **** **** **** +14909 Psychic_Warrior_EnergyCurrent_Cold **** **** **** **** **** **** **** **** +14910 Psychic_Warrior_EnergyCurrent_Elec **** **** **** **** **** **** **** **** +14911 Psychic_Warrior_EnergyCurrent_Fire **** **** **** **** **** **** **** **** +14912 Psychic_Warrior_EnergyCurrent_Sonic **** **** **** **** **** **** **** **** +14913 Psychic_Warrior_HailCrystals **** **** **** **** **** **** **** **** +14914 Psychic_Warrior_OakBody **** **** **** **** **** **** **** **** +14915 Psychic_Warrior_Power_Resistance **** **** **** **** **** **** **** **** +14916 Psychic_Warrior_PsionicRevivify **** **** **** **** **** **** **** **** +14917 Psychic_Warrior_PsychicCrush **** **** **** **** **** **** **** **** +14918 Psychic_Warrior_Psychofeedback **** **** **** **** **** **** **** **** +14919 Psychic_Warrior_SecondChance **** **** **** **** **** **** **** **** +14920 Psychic_Warrior_ShatterMindBlank **** **** **** **** **** **** **** **** +14921 Psychic_Warrior_Teleport_RadialMaster **** **** **** **** **** **** **** **** +14922 Psychic_Warrior_Teleport_SelfOnly **** **** **** **** **** **** **** **** +14923 Psychic_Warrior_Teleport_Party **** **** **** **** **** **** **** **** +14924 Psychic_Warrior_TowerIronWill **** **** **** **** **** **** **** **** +14925 Psychic_Warrior_True_Seeing **** **** **** **** **** **** **** **** +14926 Psychic_Warrior_Banishment **** **** **** **** **** **** **** **** +14927 Psychic_Warrior_BreathBlackDragon **** **** **** **** **** **** **** **** +14928 Psychic_Warrior_Cloud_Mind_Mass **** **** **** **** **** **** **** **** +14929 Psychic_Warrior_Crystallize **** **** **** **** **** **** **** **** +14930 Psychic_Warrior_Disintegrate **** **** **** **** **** **** **** **** +14931 Psychic_Warrior_DispellingBuffer **** **** **** **** **** **** **** **** +14932 Psychic_Warrior_FormOfDoom **** **** **** **** **** **** **** **** +14933 Psychic_Warrior_FuseFlesh **** **** **** **** **** **** **** **** +14934 Psychic_Warrior_GreatPrecognition_RadialMaster **** **** **** **** **** **** **** **** +14935 Psychic_Warrior_GreatPrecognitionMain **** **** **** **** **** **** **** **** +14936 Psychic_Warrior_GreatPrecognitionAttack **** **** **** **** **** **** **** **** +14937 Psychic_Warrior_GreatPrecognitionDamage **** **** **** **** **** **** **** **** +14938 Psychic_Warrior_GreatPrecognitionSaves **** **** **** **** **** **** **** **** +14939 Psychic_Warrior_GreatPrecognitionSkills **** **** **** **** **** **** **** **** +14940 Psychic_Warrior_Mind_BlankPersonal **** **** **** **** **** **** **** **** +14941 Psychic_Warrior_NullPsionicsField **** **** **** **** **** **** **** **** +14942 Psychic_Warrior_RemoteViewTrap **** **** **** **** **** **** **** **** +14943 Psychic_Warrior_RestorationPsionic **** **** **** **** **** **** **** **** +14944 Psychic_Warrior_Retrieve **** **** **** **** **** **** **** **** +14945 Psychic_Warrior_TemporalAcceleration **** **** **** **** **** **** **** **** +14946 Wilder_AstralConstruct_RadialMaster **** **** **** **** **** **** **** **** +14947 Wilder_AstralConstruct_Conversation **** **** **** **** **** **** **** **** +14948 Wilder_AstralConstruct_Slot1 **** **** **** **** **** **** **** **** +14949 Wilder_AstralConstruct_Slot2 **** **** **** **** **** **** **** **** +14950 Wilder_AstralConstruct_Slot3 **** **** **** **** **** **** **** **** +14951 Wilder_AstralConstruct_Slot4 **** **** **** **** **** **** **** **** +14952 Wilder_BiteOfTheWolf **** **** **** **** **** **** **** **** +14953 Wilder_Bolt **** **** **** **** **** **** **** **** +14954 Wilder_Burst **** **** **** **** **** **** **** **** +14955 Wilder_CallToMind **** **** **** **** **** **** **** **** +14956 Wilder_CallWeaponry **** **** **** **** **** **** **** **** +14957 Wilder_CharmPerson **** **** **** **** **** **** **** **** +14958 Wilder_ClawsOfTheBeast **** **** **** **** **** **** **** **** +14959 Wilder_Compression **** **** **** **** **** **** **** **** +14960 Wilder_Conceal_Thoughts **** **** **** **** **** **** **** **** +14961 Wilder_ControlObject **** **** **** **** **** **** **** **** +14962 Wilder_CreateSound **** **** **** **** **** **** **** **** +14963 Wilder_CrystalShard **** **** **** **** **** **** **** **** +14964 Wilder_Daze **** **** **** **** **** **** **** **** +14965 Wilder_Deceleration **** **** **** **** **** **** **** **** +14966 Wilder_DefPrecog **** **** **** **** **** **** **** **** +14967 Wilder_Demoralize **** **** **** **** **** **** **** **** +14968 Wilder_DestinyDissonance **** **** **** **** **** **** **** **** +14969 Wilder_Disable **** **** **** **** **** **** **** **** +14970 Wilder_DissipatingTouch **** **** **** **** **** **** **** **** +14971 Wilder_Distract **** **** **** **** **** **** **** **** +14972 Wilder_Empathy **** **** **** **** **** **** **** **** +14973 Wilder_EmptyMind **** **** **** **** **** **** **** **** +14974 Wilder_EnergyRay_RadialMaster **** **** **** **** **** **** **** **** +14975 Wilder_EnergyRay_Cold **** **** **** **** **** **** **** **** +14976 Wilder_EnergyRay_Elec **** **** **** **** **** **** **** **** +14977 Wilder_EnergyRay_Fire **** **** **** **** **** **** **** **** +14978 Wilder_EnergyRay_Sonic **** **** **** **** **** **** **** **** +14979 Wilder_EntanglingEctoplasm **** **** **** **** **** **** **** **** +14980 Wilder_Expansion **** **** **** **** **** **** **** **** +14981 Wilder_Far_Hand **** **** **** **** **** **** **** **** +14982 Wilder_ForceScreen **** **** **** **** **** **** **** **** +14983 Wilder_Grease **** **** **** **** **** **** **** **** +14984 Wilder_Hammer **** **** **** **** **** **** **** **** +14985 Wilder_InertialArmour **** **** **** **** **** **** **** **** +14986 Wilder_Matter_Agitation **** **** **** **** **** **** **** **** +14987 Wilder_MetaphysicalClaw **** **** **** **** **** **** **** **** +14988 Wilder_MetaphysicalWeapon **** **** **** **** **** **** **** **** +14989 Wilder_MindThrust **** **** **** **** **** **** **** **** +14990 Wilder_MyLight **** **** **** **** **** **** **** **** +14991 Wilder_OffPrecog **** **** **** **** **** **** **** **** +14992 Wilder_OffPresc **** **** **** **** **** **** **** **** +14993 Wilder_Precognition_RadialMaster **** **** **** **** **** **** **** **** +14994 Wilder_PrecognitionMain **** **** **** **** **** **** **** **** +14995 Wilder_PrecognitionAttack **** **** **** **** **** **** **** **** +14996 Wilder_PrecognitionDamage **** **** **** **** **** **** **** **** +14997 Wilder_PrecognitionSaves **** **** **** **** **** **** **** **** +14998 Wilder_PrecognitionSkills **** **** **** **** **** **** **** **** +14999 Wilder_Prevenom **** **** **** **** **** **** **** **** +15000 Wilder_PrevenomWeapon **** **** **** **** **** **** **** **** +15001 Wilder_Skate **** **** **** **** **** **** **** **** +15002 Wilder_Stomp **** **** **** **** **** **** **** **** +15003 Wilder_Synesthete **** **** **** **** **** **** **** **** +15004 Wilder_Telempathic_Projection **** **** **** **** **** **** **** **** +15005 Wilder_ThickSkin **** **** **** **** **** **** **** **** +15006 Wilder_Vigor **** **** **** **** **** **** **** **** +15007 Wilder_AnimalAffinity **** **** **** **** **** **** **** **** +15008 Wilder_Aversion **** **** **** **** **** **** **** **** +15009 Wilder_BestowPower **** **** **** **** **** **** **** **** +15010 Wilder_Biofeedback **** **** **** **** **** **** **** **** +15011 Wilder_Body_Equilibrium **** **** **** **** **** **** **** **** +15012 Wilder_BrainLock **** **** **** **** **** **** **** **** +15013 Wilder_Chameleon **** **** **** **** **** **** **** **** +15014 Wilder_ClairvoyantSense **** **** **** **** **** **** **** **** +15015 Wilder_Cloud_Mind **** **** **** **** **** **** **** **** +15016 Wilder_ConcBlast **** **** **** **** **** **** **** **** +15017 Wilder_ConcealAmorpha **** **** **** **** **** **** **** **** +15018 Wilder_ControlAir **** **** **** **** **** **** **** **** +15019 Wilder_ControlSound **** **** **** **** **** **** **** **** +15020 Wilder_SwarmOfCrystals **** **** **** **** **** **** **** **** +15021 Wilder_DimensionSwap **** **** **** **** **** **** **** **** +15022 Wilder_DissolvingTouch **** **** **** **** **** **** **** **** +15023 Wilder_Dissolving_Weapon **** **** **** **** **** **** **** **** +15024 Wilder_EgoWhip **** **** **** **** **** **** **** **** +15025 Wilder_ElfSight **** **** **** **** **** **** **** **** +15026 Wilder_EmpathicTransfer **** **** **** **** **** **** **** **** +15027 Wilder_EnergyAdaptSpec_RadialMaster **** **** **** **** **** **** **** **** +15028 Wilder_EnergyAdaptAcid **** **** **** **** **** **** **** **** +15029 Wilder_EnergyAdaptCold **** **** **** **** **** **** **** **** +15030 Wilder_EnergyAdaptElec **** **** **** **** **** **** **** **** +15031 Wilder_EnergyAdaptFire **** **** **** **** **** **** **** **** +15032 Wilder_EnergyAdaptSonic **** **** **** **** **** **** **** **** +15033 Wilder_Energy_Missile_RadialMaster **** **** **** **** **** **** **** **** +15034 Wilder_Energy_Missile_Cold **** **** **** **** **** **** **** **** +15035 Wilder_Energy_Missile_Elec **** **** **** **** **** **** **** **** +15036 Wilder_Energy_Missile_Fire **** **** **** **** **** **** **** **** +15037 Wilder_Energy_Missile_Sonic **** **** **** **** **** **** **** **** +15038 Wilder_EnergyPush_RadialMaster **** **** **** **** **** **** **** **** +15039 Wilder_EnergyPush_Cold **** **** **** **** **** **** **** **** +15040 Wilder_EnergyPush_Elec **** **** **** **** **** **** **** **** +15041 Wilder_EnergyPush_Fire **** **** **** **** **** **** **** **** +15042 Wilder_EnergyPush_Sonic **** **** **** **** **** **** **** **** +15043 Wilder_EnergyStun_RadialMaster **** **** **** **** **** **** **** **** +15044 Wilder_EnergyStun_Cold **** **** **** **** **** **** **** **** +15045 Wilder_EnergyStun_Elec **** **** **** **** **** **** **** **** +15046 Wilder_EnergyStun_Fire **** **** **** **** **** **** **** **** +15047 Wilder_EnergyStun_Sonic **** **** **** **** **** **** **** **** +15048 Wilder_Identify **** **** **** **** **** **** **** **** +15049 Wilder_IdInsinuation **** **** **** **** **** **** **** **** +15050 Wilder_InflictPain **** **** **** **** **** **** **** **** +15051 Wilder_Knock **** **** **** **** **** **** **** **** +15052 Wilder_Lock **** **** **** **** **** **** **** **** +15053 Wilder_MindDisrupt **** **** **** **** **** **** **** **** +15054 Wilder_PainfulStrike **** **** **** **** **** **** **** **** +15055 Wilder_RecallAgony **** **** **** **** **** **** **** **** +15056 Wilder_RepairDamage **** **** **** **** **** **** **** **** +15057 Wilder_SharePain **** **** **** **** **** **** **** **** +15058 Wilder_StrengthOfMyEnemy **** **** **** **** **** **** **** **** +15059 Wilder_ThoughtShield **** **** **** **** **** **** **** **** +15060 Wilder_BodyAdjustment **** **** **** **** **** **** **** **** +15061 Wilder_BodyPurification **** **** **** **** **** **** **** **** +15062 Wilder_ClawOfTheVampire **** **** **** **** **** **** **** **** +15063 Wilder_CrisisBreath **** **** **** **** **** **** **** **** +15064 Wilder_Danger_Sense **** **** **** **** **** **** **** **** +15065 Wilder_Darkvision **** **** **** **** **** **** **** **** +15066 Wilder_DimensionSlide **** **** **** **** **** **** **** **** +15067 Wilder_Dispel_Psionics **** **** **** **** **** **** **** **** +15068 Wilder_DuodimensionalClaw **** **** **** **** **** **** **** **** +15069 Wilder_EctoCocoon **** **** **** **** **** **** **** **** +15070 Wilder_EctoplasmicForm **** **** **** **** **** **** **** **** +15071 Wilder_EmpathicTransferHostile **** **** **** **** **** **** **** **** +15072 Wilder_EnergyBolt_RadialMaster **** **** **** **** **** **** **** **** +15073 Wilder_Energy_Bolt_Cold **** **** **** **** **** **** **** **** +15074 Wilder_Energy_Bolt_Elec **** **** **** **** **** **** **** **** +15075 Wilder_Energy_Bolt_Fire **** **** **** **** **** **** **** **** +15076 Wilder_Energy_Bolt_Sonic **** **** **** **** **** **** **** **** +15077 Wilder_EnergyBurst_RadialMaster **** **** **** **** **** **** **** **** +15078 Wilder_Energy_Burst_Cold **** **** **** **** **** **** **** **** +15079 Wilder_Energy_Burst_Elec **** **** **** **** **** **** **** **** +15080 Wilder_Energy_Burst_Fire **** **** **** **** **** **** **** **** +15081 Wilder_Energy_Burst_Sonic **** **** **** **** **** **** **** **** +15082 Wilder_Energy_Cone_RadialMaster **** **** **** **** **** **** **** **** +15083 Wilder_EnergyCone_Cold **** **** **** **** **** **** **** **** +15084 Wilder_EnergyCone_Elec **** **** **** **** **** **** **** **** +15085 Wilder_EnergyCone_Fire **** **** **** **** **** **** **** **** +15086 Wilder_EnergyCone_Sonic **** **** **** **** **** **** **** **** +15087 Wilder_EnergyRetort_RadialMaster **** **** **** **** **** **** **** **** +15088 Wilder_Energy_Retort_Cold **** **** **** **** **** **** **** **** +15089 Wilder_Energy_Retort_Elec **** **** **** **** **** **** **** **** +15090 Wilder_Energy_Retort_Fire **** **** **** **** **** **** **** **** +15091 Wilder_Energy_Retort_Sonic **** **** **** **** **** **** **** **** +15092 Wilder_EnergyWall_RadialMaster **** **** **** **** **** **** **** **** +15093 Wilder_Energy_Wall_Cold **** **** **** **** **** **** **** **** +15094 Wilder_Energy_Wall_Elec **** **** **** **** **** **** **** **** +15095 Wilder_Energy_Wall_Fire **** **** **** **** **** **** **** **** +15096 Wilder_Energy_Wall_Sonic **** **** **** **** **** **** **** **** +15097 Wilder_Eradicate_Invisibility **** **** **** **** **** **** **** **** +15098 Wilder_EscapeDetection **** **** **** **** **** **** **** **** +15099 Wilder_Exhale_BlackDrag **** **** **** **** **** **** **** **** +15100 Wilder_FateLink **** **** **** **** **** **** **** **** +15101 Wilder_Greater_Amorpha **** **** **** **** **** **** **** **** +15102 Wilder_Hustle **** **** **** **** **** **** **** **** +15103 Wilder_Keen_Edge **** **** **** **** **** **** **** **** +15104 Wilder_MentalBarrier **** **** **** **** **** **** **** **** +15105 Wilder_Mindtrap **** **** **** **** **** **** **** **** +15106 Wilder_Psiblast **** **** **** **** **** **** **** **** +15107 Wilder_SharePainForced **** **** **** **** **** **** **** **** +15108 Wilder_TimeHop **** **** **** **** **** **** **** **** +15109 Wilder_Touchsight **** **** **** **** **** **** **** **** +15110 Wilder_UbiqVision **** **** **** **** **** **** **** **** +15111 Wilder_VampiricWeapon **** **** **** **** **** **** **** **** +15112 Wilder_ClawOfEnergy_RadialMaster **** **** **** **** **** **** **** **** +15113 Wilder_ClawofEnergyCold **** **** **** **** **** **** **** **** +15114 Wilder_ClawofEnergyElec **** **** **** **** **** **** **** **** +15115 Wilder_ClawofEnergyFire **** **** **** **** **** **** **** **** +15116 Wilder_DetectRemoteViewing **** **** **** **** **** **** **** **** +15117 Wilder_DimensionalAnchor **** **** **** **** **** **** **** **** +15118 Wilder_DimensionDoor_Master **** **** **** **** **** **** **** **** +15119 Wilder_DimensionDoor_SelfOnly **** **** **** **** **** **** **** **** +15120 Wilder_DimensionDoor_Party **** **** **** **** **** **** **** **** +15121 Wilder_DimensionDoor_DirDist_SelfOnly **** **** **** **** **** **** **** **** +15122 Wilder_DimensionDoor_DirDist_Party **** **** **** **** **** **** **** **** +15123 Wilder_Dismissal **** **** **** **** **** **** **** **** +15124 Wilder_EmpathicFeedback **** **** **** **** **** **** **** **** +15125 Wilder_EnergyAdaption **** **** **** **** **** **** **** **** +15126 Wilder_EnergyBall_RadialMaster **** **** **** **** **** **** **** **** +15127 Wilder_EnergyBall_Cold **** **** **** **** **** **** **** **** +15128 Wilder_EnergyBall_Elec **** **** **** **** **** **** **** **** +15129 Wilder_EnergyBall_Fire **** **** **** **** **** **** **** **** +15130 Wilder_EnergyBall_Sonic **** **** **** **** **** **** **** **** +15131 Wilder_Freedom_of_Movement **** **** **** **** **** **** **** **** +15132 Wilder_Immovability **** **** **** **** **** **** **** **** +15133 Wilder_InertialBar **** **** **** **** **** **** **** **** +15134 Wilder_IntellectFortress **** **** **** **** **** **** **** **** +15135 Wilder_Mindwipe **** **** **** **** **** **** **** **** +15136 Wilder_PowerLeech **** **** **** **** **** **** **** **** +15137 Wilder_Dominate_Psionic **** **** **** **** **** **** **** **** +15138 Wilder_PsychicReformation **** **** **** **** **** **** **** **** +15139 Wilder_PsychicVampire **** **** **** **** **** **** **** **** +15140 Wilder_RemoteViewing **** **** **** **** **** **** **** **** +15141 Wilder_SteadfastPercep **** **** **** **** **** **** **** **** +15142 Wilder_TelekineticManeuver **** **** **** **** **** **** **** **** +15143 Wilder_Truevenom **** **** **** **** **** **** **** **** +15144 Wilder_TruevenomWeapon **** **** **** **** **** **** **** **** +15145 Wilder_WeaponOfEnergy_RadialMaster **** **** **** **** **** **** **** **** +15146 Wilder_WeaponofEnergyCold **** **** **** **** **** **** **** **** +15147 Wilder_WeaponofEnergyElec **** **** **** **** **** **** **** **** +15148 Wilder_WeaponofEnergyFire **** **** **** **** **** **** **** **** +15149 Wilder_BaleTeleport **** **** **** **** **** **** **** **** +15150 Wilder_Catapsi **** **** **** **** **** **** **** **** +15151 Wilder_ClairtangentHand **** **** **** **** **** **** **** **** +15152 Wilder_EctoplasmicShambler **** **** **** **** **** **** **** **** +15153 Wilder_EnergyCurrent_RadialMaster **** **** **** **** **** **** **** **** +15154 Wilder_EnergyCurrent_Cold **** **** **** **** **** **** **** **** +15155 Wilder_EnergyCurrent_Elec **** **** **** **** **** **** **** **** +15156 Wilder_EnergyCurrent_Fire **** **** **** **** **** **** **** **** +15157 Wilder_EnergyCurrent_Sonic **** **** **** **** **** **** **** **** +15158 Wilder_HailCrystals **** **** **** **** **** **** **** **** +15159 Wilder_Power_Resistance **** **** **** **** **** **** **** **** +15160 Wilder_PsionicRevivify **** **** **** **** **** **** **** **** +15161 Wilder_PsychicCrush **** **** **** **** **** **** **** **** +15162 Wilder_Psychofeedback **** **** **** **** **** **** **** **** +15163 Wilder_SecondChance **** **** **** **** **** **** **** **** +15164 Wilder_ShatterMindBlank **** **** **** **** **** **** **** **** +15165 Wilder_Teleport_RadialMaster **** **** **** **** **** **** **** **** +15166 Wilder_Teleport_SelfOnly **** **** **** **** **** **** **** **** +15167 Wilder_Teleport_Party **** **** **** **** **** **** **** **** +15168 Wilder_TowerIronWill **** **** **** **** **** **** **** **** +15169 Wilder_True_Seeing **** **** **** **** **** **** **** **** +15170 Wilder_Banishment **** **** **** **** **** **** **** **** +15171 Wilder_BreathBlackDragon **** **** **** **** **** **** **** **** +15172 Wilder_Cloud_Mind_Mass **** **** **** **** **** **** **** **** +15173 Wilder_Crystallize **** **** **** **** **** **** **** **** +15174 Wilder_Disintegrate **** **** **** **** **** **** **** **** +15175 Wilder_DispellingBuffer **** **** **** **** **** **** **** **** +15176 Wilder_FormOfDoom **** **** **** **** **** **** **** **** +15177 Wilder_FuseFlesh **** **** **** **** **** **** **** **** +15178 Wilder_GreatPrecognition_RadialMaster **** **** **** **** **** **** **** **** +15179 Wilder_GreatPrecognitionMain **** **** **** **** **** **** **** **** +15180 Wilder_GreatPrecognitionAttack **** **** **** **** **** **** **** **** +15181 Wilder_GreatPrecognitionDamage **** **** **** **** **** **** **** **** +15182 Wilder_GreatPrecognitionSaves **** **** **** **** **** **** **** **** +15183 Wilder_GreatPrecognitionSkills **** **** **** **** **** **** **** **** +15184 Wilder_NullPsionicsField **** **** **** **** **** **** **** **** +15185 Wilder_RemoteViewTrap **** **** **** **** **** **** **** **** +15186 Wilder_RestorationPsionic **** **** **** **** **** **** **** **** +15187 Wilder_Retrieve **** **** **** **** **** **** **** **** +15188 Wilder_TemporalAcceleration **** **** **** **** **** **** **** **** +15189 Wilder_CrisisLife **** **** **** **** **** **** **** **** +15190 Wilder_Decerebrate **** **** **** **** **** **** **** **** +15191 Wilder_EctoCocoonMass **** **** **** **** **** **** **** **** +15192 Wilder_EnergyWave_RadialMaster **** **** **** **** **** **** **** **** +15193 Wilder_EnergyWaveCold **** **** **** **** **** **** **** **** +15194 Wilder_EnergyWaveElec **** **** **** **** **** **** **** **** +15195 Wilder_EnergyWaveFire **** **** **** **** **** **** **** **** +15196 Wilder_EnergyWaveSonic **** **** **** **** **** **** **** **** +15197 Wilder_EtherealJaunt **** **** **** **** **** **** **** **** +15198 Wilder_EvadeBurst **** **** **** **** **** **** **** **** +15199 Wilder_Insanity **** **** **** **** **** **** **** **** +15200 Wilder_Mind_BlankPersonal **** **** **** **** **** **** **** **** +15201 Wilder_MomentOfPrescience_RadialMaster **** **** **** **** **** **** **** **** +15202 Wilder_MomentOfPrescienceAttack **** **** **** **** **** **** **** **** +15203 Wilder_MomentOfPrescienceArmour **** **** **** **** **** **** **** **** +15204 Wilder_MomentOfPrescienceSaves **** **** **** **** **** **** **** **** +15205 Wilder_MomentOfPrescienceSkills **** **** **** **** **** **** **** **** +15206 Wilder_OakBody **** **** **** **** **** **** **** **** +15207 Wilder_Reddopsi **** **** **** **** **** **** **** **** +15208 Wilder_Sequester **** **** **** **** **** **** **** **** +15209 Wilder_Ultrablast **** **** **** **** **** **** **** **** +15210 Wilder_AstralSeed **** **** **** **** **** **** **** **** +15211 Wilder_GreaterTeleport_RadialMaster **** **** **** **** **** **** **** **** +15212 Wilder_GreaterTeleport_SelfOnly **** **** **** **** **** **** **** **** +15213 Wilder_GreaterTeleport_Party **** **** **** **** **** **** **** **** +15214 Wilder_Hypercognition **** **** **** **** **** **** **** **** +15215 Wilder_IronBody **** **** **** **** **** **** **** **** +15216 Wilder_PsionicMind_Blank **** **** **** **** **** **** **** **** +15217 Wilder_RecallDeath **** **** **** **** **** **** **** **** +15218 Wilder_Shadow_Body **** **** **** **** **** **** **** **** +15219 Wilder_TimeHopMass **** **** **** **** **** **** **** **** +15220 Wilder_TrueMetabolism **** **** **** **** **** **** **** **** +15221 Wilder_Assimilate **** **** **** **** **** **** **** **** +15222 Wilder_Etherealness **** **** **** **** **** **** **** **** +15223 Wilder_Genesis **** **** **** **** **** **** **** **** +15224 Wilder_Microcosm **** **** **** **** **** **** **** **** +15225 Wilder_PsychicChirurgery_Repair **** **** **** **** **** **** **** **** +15226 Wilder_TeleportationCircle_RadialMaster **** **** **** **** **** **** **** **** +15227 Wilder_TeleportationCircle_Visible **** **** **** **** **** **** **** **** +15228 Wilder_TeleportationCircle_Hidden **** **** **** **** **** **** **** **** +15229 Wilder_TimelessBody **** **** **** **** **** **** **** **** +15230 Wilder_TornadoBlast **** **** **** **** **** **** **** **** +15231 FistOfZouken_AstralConstruct_RadialMaster **** **** **** **** **** **** **** **** +15232 FistOfZouken_AstralConstruct_Conversation **** **** **** **** **** **** **** **** +15233 FistOfZouken_AstralConstruct_Slot1 **** **** **** **** **** **** **** **** +15234 FistOfZouken_AstralConstruct_Slot2 **** **** **** **** **** **** **** **** +15235 FistOfZouken_AstralConstruct_Slot3 **** **** **** **** **** **** **** **** +15236 FistOfZouken_AstralConstruct_Slot4 **** **** **** **** **** **** **** **** +15237 FistOfZouken_Biofeedback **** **** **** **** **** **** **** **** +15238 FistOfZouken_BiteOfTheWolf **** **** **** **** **** **** **** **** +15239 FistOfZouken_Bolt **** **** **** **** **** **** **** **** +15240 FistOfZouken_Burst **** **** **** **** **** **** **** **** +15241 FistOfZouken_CallToMind **** **** **** **** **** **** **** **** +15242 FistOfZouken_CallWeaponry **** **** **** **** **** **** **** **** +15243 FistOfZouken_Chameleon **** **** **** **** **** **** **** **** +15244 FistOfZouken_CharmPerson **** **** **** **** **** **** **** **** +15245 FistOfZouken_ClawsOfTheBeast **** **** **** **** **** **** **** **** +15246 FistOfZouken_Compression **** **** **** **** **** **** **** **** +15247 FistOfZouken_Conceal_Thoughts **** **** **** **** **** **** **** **** +15248 FistOfZouken_ControlObject **** **** **** **** **** **** **** **** +15249 FistOfZouken_CreateSound **** **** **** **** **** **** **** **** +15250 FistOfZouken_CrystalShard **** **** **** **** **** **** **** **** +15251 FistOfZouken_Daze **** **** **** **** **** **** **** **** +15252 FistOfZouken_Deceleration **** **** **** **** **** **** **** **** +15253 FistOfZouken_DefPrecog **** **** **** **** **** **** **** **** +15254 FistOfZouken_Demoralize **** **** **** **** **** **** **** **** +15255 FistOfZouken_DestinyDissonance **** **** **** **** **** **** **** **** +15256 FistOfZouken_Disable **** **** **** **** **** **** **** **** +15257 FistOfZouken_DissipatingTouch **** **** **** **** **** **** **** **** +15258 FistOfZouken_Distract **** **** **** **** **** **** **** **** +15259 FistOfZouken_ElfSight **** **** **** **** **** **** **** **** +15260 FistOfZouken_Empathy **** **** **** **** **** **** **** **** +15261 FistOfZouken_EmptyMind **** **** **** **** **** **** **** **** +15262 FistOfZouken_EnergyRay_RadialMaster **** **** **** **** **** **** **** **** +15263 FistOfZouken_EnergyRay_Cold **** **** **** **** **** **** **** **** +15264 FistOfZouken_EnergyRay_Elec **** **** **** **** **** **** **** **** +15265 FistOfZouken_EnergyRay_Fire **** **** **** **** **** **** **** **** +15266 FistOfZouken_EnergyRay_Sonic **** **** **** **** **** **** **** **** +15267 FistOfZouken_EntanglingEctoplasm **** **** **** **** **** **** **** **** +15268 FistOfZouken_Expansion **** **** **** **** **** **** **** **** +15269 FistOfZouken_Far_Hand **** **** **** **** **** **** **** **** +15270 FistOfZouken_ForceScreen **** **** **** **** **** **** **** **** +15271 FistOfZouken_Grease **** **** **** **** **** **** **** **** +15272 FistOfZouken_Hammer **** **** **** **** **** **** **** **** +15273 FistOfZouken_InertialArmour **** **** **** **** **** **** **** **** +15274 FistOfZouken_Matter_Agitation **** **** **** **** **** **** **** **** +15275 FistOfZouken_MetaphysicalClaw **** **** **** **** **** **** **** **** +15276 FistOfZouken_MetaphysicalWeapon **** **** **** **** **** **** **** **** +15277 FistOfZouken_MindThrust **** **** **** **** **** **** **** **** +15278 FistOfZouken_MyLight **** **** **** **** **** **** **** **** +15279 FistOfZouken_OffPrecog **** **** **** **** **** **** **** **** +15280 FistOfZouken_OffPresc **** **** **** **** **** **** **** **** +15281 FistOfZouken_Precognition_RadialMaster **** **** **** **** **** **** **** **** +15282 FistOfZouken_PrecognitionMain **** **** **** **** **** **** **** **** +15283 FistOfZouken_PrecognitionAttack **** **** **** **** **** **** **** **** +15284 FistOfZouken_PrecognitionDamage **** **** **** **** **** **** **** **** +15285 FistOfZouken_PrecognitionSaves **** **** **** **** **** **** **** **** +15286 FistOfZouken_PrecognitionSkills **** **** **** **** **** **** **** **** +15287 FistOfZouken_Prevenom **** **** **** **** **** **** **** **** +15288 FistOfZouken_PrevenomWeapon **** **** **** **** **** **** **** **** +15289 FistOfZouken_Skate **** **** **** **** **** **** **** **** +15290 FistOfZouken_Stomp **** **** **** **** **** **** **** **** +15291 FistOfZouken_Synesthete **** **** **** **** **** **** **** **** +15292 FistOfZouken_Telempathic_Projection **** **** **** **** **** **** **** **** +15293 FistOfZouken_ThickSkin **** **** **** **** **** **** **** **** +15294 FistOfZouken_Vigor **** **** **** **** **** **** **** **** +15295 FistOfZouken_AnimalAffinity **** **** **** **** **** **** **** **** +15296 FistOfZouken_Aversion **** **** **** **** **** **** **** **** +15297 FistOfZouken_BestowPower **** **** **** **** **** **** **** **** +15298 FistOfZouken_BodyAdjustment **** **** **** **** **** **** **** **** +15299 FistOfZouken_Body_Equilibrium **** **** **** **** **** **** **** **** +15300 FistOfZouken_BodyPurification **** **** **** **** **** **** **** **** +15301 FistOfZouken_BrainLock **** **** **** **** **** **** **** **** +15302 FistOfZouken_ClairvoyantSense **** **** **** **** **** **** **** **** +15303 FistOfZouken_Cloud_Mind **** **** **** **** **** **** **** **** +15304 FistOfZouken_ConcBlast **** **** **** **** **** **** **** **** +15305 FistOfZouken_ConcealAmorpha **** **** **** **** **** **** **** **** +15306 FistOfZouken_ControlAir **** **** **** **** **** **** **** **** +15307 FistOfZouken_ControlSound **** **** **** **** **** **** **** **** +15308 FistOfZouken_SwarmOfCrystals **** **** **** **** **** **** **** **** +15309 FistOfZouken_Darkvision **** **** **** **** **** **** **** **** +15310 FistOfZouken_DimensionSwap **** **** **** **** **** **** **** **** +15311 FistOfZouken_DissolvingTouch **** **** **** **** **** **** **** **** +15312 FistOfZouken_Dissolving_Weapon **** **** **** **** **** **** **** **** +15313 FistOfZouken_EgoWhip **** **** **** **** **** **** **** **** +15314 FistOfZouken_EmpathicTransfer **** **** **** **** **** **** **** **** +15315 FistOfZouken_EnergyAdaptSpec_RadialMaster **** **** **** **** **** **** **** **** +15316 FistOfZouken_EnergyAdaptAcid **** **** **** **** **** **** **** **** +15317 FistOfZouken_EnergyAdaptCold **** **** **** **** **** **** **** **** +15318 FistOfZouken_EnergyAdaptElec **** **** **** **** **** **** **** **** +15319 FistOfZouken_EnergyAdaptFire **** **** **** **** **** **** **** **** +15320 FistOfZouken_EnergyAdaptSonic **** **** **** **** **** **** **** **** +15321 FistOfZouken_Energy_Missile_RadialMaster **** **** **** **** **** **** **** **** +15322 FistOfZouken_Energy_Missile_Cold **** **** **** **** **** **** **** **** +15323 FistOfZouken_Energy_Missile_Elec **** **** **** **** **** **** **** **** +15324 FistOfZouken_Energy_Missile_Fire **** **** **** **** **** **** **** **** +15325 FistOfZouken_Energy_Missile_Sonic **** **** **** **** **** **** **** **** +15326 FistOfZouken_EnergyPush_RadialMaster **** **** **** **** **** **** **** **** +15327 FistOfZouken_EnergyPush_Cold **** **** **** **** **** **** **** **** +15328 FistOfZouken_EnergyPush_Elec **** **** **** **** **** **** **** **** +15329 FistOfZouken_EnergyPush_Fire **** **** **** **** **** **** **** **** +15330 FistOfZouken_EnergyPush_Sonic **** **** **** **** **** **** **** **** +15331 FistOfZouken_EnergyStun_RadialMaster **** **** **** **** **** **** **** **** +15332 FistOfZouken_EnergyStun_Cold **** **** **** **** **** **** **** **** +15333 FistOfZouken_EnergyStun_Elec **** **** **** **** **** **** **** **** +15334 FistOfZouken_EnergyStun_Fire **** **** **** **** **** **** **** **** +15335 FistOfZouken_EnergyStun_Sonic **** **** **** **** **** **** **** **** +15336 FistOfZouken_Hustle **** **** **** **** **** **** **** **** +15337 FistOfZouken_Identify **** **** **** **** **** **** **** **** +15338 FistOfZouken_IdInsinuation **** **** **** **** **** **** **** **** +15339 FistOfZouken_InflictPain **** **** **** **** **** **** **** **** +15340 FistOfZouken_Knock **** **** **** **** **** **** **** **** +15341 FistOfZouken_Lock **** **** **** **** **** **** **** **** +15342 FistOfZouken_MindDisrupt **** **** **** **** **** **** **** **** +15343 FistOfZouken_PainfulStrike **** **** **** **** **** **** **** **** +15344 FistOfZouken_RecallAgony **** **** **** **** **** **** **** **** +15345 FistOfZouken_RepairDamage **** **** **** **** **** **** **** **** +15346 FistOfZouken_SharePain **** **** **** **** **** **** **** **** +15347 FistOfZouken_StrengthOfMyEnemy **** **** **** **** **** **** **** **** +15348 FistOfZouken_ThoughtShield **** **** **** **** **** **** **** **** +15349 FistOfZouken_ClawOfTheVampire **** **** **** **** **** **** **** **** +15350 FistOfZouken_CrisisBreath **** **** **** **** **** **** **** **** +15351 FistOfZouken_Danger_Sense **** **** **** **** **** **** **** **** +15352 FistOfZouken_DimensionSlide **** **** **** **** **** **** **** **** +15353 FistOfZouken_Dispel_Psionics **** **** **** **** **** **** **** **** +15354 FistOfZouken_DuodimensionalClaw **** **** **** **** **** **** **** **** +15355 FistOfZouken_EctoCocoon **** **** **** **** **** **** **** **** +15356 FistOfZouken_EctoplasmicForm **** **** **** **** **** **** **** **** +15357 FistOfZouken_EmpathicFeedback **** **** **** **** **** **** **** **** +15358 FistOfZouken_EmpathicTransferHostile **** **** **** **** **** **** **** **** +15359 FistOfZouken_EnergyBolt_RadialMaster **** **** **** **** **** **** **** **** +15360 FistOfZouken_Energy_Bolt_Cold **** **** **** **** **** **** **** **** +15361 FistOfZouken_Energy_Bolt_Elec **** **** **** **** **** **** **** **** +15362 FistOfZouken_Energy_Bolt_Fire **** **** **** **** **** **** **** **** +15363 FistOfZouken_Energy_Bolt_Sonic **** **** **** **** **** **** **** **** +15364 FistOfZouken_EnergyBurst_RadialMaster **** **** **** **** **** **** **** **** +15365 FistOfZouken_Energy_Burst_Cold **** **** **** **** **** **** **** **** +15366 FistOfZouken_Energy_Burst_Elec **** **** **** **** **** **** **** **** +15367 FistOfZouken_Energy_Burst_Fire **** **** **** **** **** **** **** **** +15368 FistOfZouken_Energy_Burst_Sonic **** **** **** **** **** **** **** **** +15369 FistOfZouken_Energy_Cone_RadialMaster **** **** **** **** **** **** **** **** +15370 FistOfZouken_EnergyCone_Cold **** **** **** **** **** **** **** **** +15371 FistOfZouken_EnergyCone_Elec **** **** **** **** **** **** **** **** +15372 FistOfZouken_EnergyCone_Fire **** **** **** **** **** **** **** **** +15373 FistOfZouken_EnergyCone_Sonic **** **** **** **** **** **** **** **** +15374 FistOfZouken_EnergyRetort_RadialMaster **** **** **** **** **** **** **** **** +15375 FistOfZouken_Energy_Retort_Cold **** **** **** **** **** **** **** **** +15376 FistOfZouken_Energy_Retort_Elec **** **** **** **** **** **** **** **** +15377 FistOfZouken_Energy_Retort_Fire **** **** **** **** **** **** **** **** +15378 FistOfZouken_Energy_Retort_Sonic **** **** **** **** **** **** **** **** +15379 FistOfZouken_EnergyWall_RadialMaster **** **** **** **** **** **** **** **** +15380 FistOfZouken_Energy_Wall_Cold **** **** **** **** **** **** **** **** +15381 FistOfZouken_Energy_Wall_Elec **** **** **** **** **** **** **** **** +15382 FistOfZouken_Energy_Wall_Fire **** **** **** **** **** **** **** **** +15383 FistOfZouken_Energy_Wall_Sonic **** **** **** **** **** **** **** **** +15384 FistOfZouken_Eradicate_Invisibility **** **** **** **** **** **** **** **** +15385 FistOfZouken_EscapeDetection **** **** **** **** **** **** **** **** +15386 FistOfZouken_EvadeBurst **** **** **** **** **** **** **** **** +15387 FistOfZouken_Exhale_BlackDrag **** **** **** **** **** **** **** **** +15388 FistOfZouken_FateLink **** **** **** **** **** **** **** **** +15389 FistOfZouken_Greater_Amorpha **** **** **** **** **** **** **** **** +15390 FistOfZouken_Keen_Edge **** **** **** **** **** **** **** **** +15391 FistOfZouken_MentalBarrier **** **** **** **** **** **** **** **** +15392 FistOfZouken_Mindtrap **** **** **** **** **** **** **** **** +15393 FistOfZouken_Psiblast **** **** **** **** **** **** **** **** +15394 FistOfZouken_SharePainForced **** **** **** **** **** **** **** **** +15395 FistOfZouken_TimeHop **** **** **** **** **** **** **** **** +15396 FistOfZouken_Touchsight **** **** **** **** **** **** **** **** +15397 FistOfZouken_UbiqVision **** **** **** **** **** **** **** **** +15398 FistOfZouken_VampiricWeapon **** **** **** **** **** **** **** **** +15399 FistOfZouken_ClawOfEnergy_RadialMaster **** **** **** **** **** **** **** **** +15400 FistOfZouken_ClawofEnergyCold **** **** **** **** **** **** **** **** +15401 FistOfZouken_ClawofEnergyElec **** **** **** **** **** **** **** **** +15402 FistOfZouken_ClawofEnergyFire **** **** **** **** **** **** **** **** +15403 FistOfZouken_DetectRemoteViewing **** **** **** **** **** **** **** **** +15404 FistOfZouken_DimensionalAnchor **** **** **** **** **** **** **** **** +15405 FistOfZouken_DimensionDoor_Master **** **** **** **** **** **** **** **** +15406 FistOfZouken_DimensionDoor_SelfOnly **** **** **** **** **** **** **** **** +15407 FistOfZouken_DimensionDoor_Party **** **** **** **** **** **** **** **** +15408 FistOfZouken_DimensionDoor_DirDist_SelfOnly **** **** **** **** **** **** **** **** +15409 FistOfZouken_DimensionDoor_DirDist_Party **** **** **** **** **** **** **** **** +15410 FistOfZouken_Dismissal **** **** **** **** **** **** **** **** +15411 FistOfZouken_EnergyAdaption **** **** **** **** **** **** **** **** +15412 FistOfZouken_EnergyBall_RadialMaster **** **** **** **** **** **** **** **** +15413 FistOfZouken_EnergyBall_Cold **** **** **** **** **** **** **** **** +15414 FistOfZouken_EnergyBall_Elec **** **** **** **** **** **** **** **** +15415 FistOfZouken_EnergyBall_Fire **** **** **** **** **** **** **** **** +15416 FistOfZouken_EnergyBall_Sonic **** **** **** **** **** **** **** **** +15417 FistOfZouken_Freedom_of_Movement **** **** **** **** **** **** **** **** +15418 FistOfZouken_Immovability **** **** **** **** **** **** **** **** +15419 FistOfZouken_InertialBar **** **** **** **** **** **** **** **** +15420 FistOfZouken_IntellectFortress **** **** **** **** **** **** **** **** +15421 FistOfZouken_Mindwipe **** **** **** **** **** **** **** **** +15422 FistOfZouken_PowerLeech **** **** **** **** **** **** **** **** +15423 FistOfZouken_Dominate_Psionic **** **** **** **** **** **** **** **** +15424 FistOfZouken_PsychicReformation **** **** **** **** **** **** **** **** +15425 FistOfZouken_PsychicVampire **** **** **** **** **** **** **** **** +15426 FistOfZouken_RemoteViewing **** **** **** **** **** **** **** **** +15427 FistOfZouken_SteadfastPercep **** **** **** **** **** **** **** **** +15428 FistOfZouken_TelekineticManeuver **** **** **** **** **** **** **** **** +15429 FistOfZouken_Truevenom **** **** **** **** **** **** **** **** +15430 FistOfZouken_TruevenomWeapon **** **** **** **** **** **** **** **** +15431 FistOfZouken_WeaponOfEnergy_RadialMaster **** **** **** **** **** **** **** **** +15432 FistOfZouken_WeaponofEnergyCold **** **** **** **** **** **** **** **** +15433 FistOfZouken_WeaponofEnergyElec **** **** **** **** **** **** **** **** +15434 FistOfZouken_WeaponofEnergyFire **** **** **** **** **** **** **** **** +15435 FistOfZouken_BaleTeleport **** **** **** **** **** **** **** **** +15436 FistOfZouken_Catapsi **** **** **** **** **** **** **** **** +15437 FistOfZouken_ClairtangentHand **** **** **** **** **** **** **** **** +15438 FistOfZouken_EctoplasmicShambler **** **** **** **** **** **** **** **** +15439 FistOfZouken_EnergyCurrent_RadialMaster **** **** **** **** **** **** **** **** +15440 FistOfZouken_EnergyCurrent_Cold **** **** **** **** **** **** **** **** +15441 FistOfZouken_EnergyCurrent_Elec **** **** **** **** **** **** **** **** +15442 FistOfZouken_EnergyCurrent_Fire **** **** **** **** **** **** **** **** +15443 FistOfZouken_EnergyCurrent_Sonic **** **** **** **** **** **** **** **** +15444 FistOfZouken_HailCrystals **** **** **** **** **** **** **** **** +15445 FistOfZouken_OakBody **** **** **** **** **** **** **** **** +15446 FistOfZouken_Power_Resistance **** **** **** **** **** **** **** **** +15447 FistOfZouken_PsionicRevivify **** **** **** **** **** **** **** **** +15448 FistOfZouken_PsychicCrush **** **** **** **** **** **** **** **** +15449 FistOfZouken_Psychofeedback **** **** **** **** **** **** **** **** +15450 FistOfZouken_SecondChance **** **** **** **** **** **** **** **** +15451 FistOfZouken_ShatterMindBlank **** **** **** **** **** **** **** **** +15452 FistOfZouken_Teleport_RadialMaster **** **** **** **** **** **** **** **** +15453 FistOfZouken_Teleport_SelfOnly **** **** **** **** **** **** **** **** +15454 FistOfZouken_Teleport_Party **** **** **** **** **** **** **** **** +15455 FistOfZouken_TowerIronWill **** **** **** **** **** **** **** **** +15456 FistOfZouken_True_Seeing **** **** **** **** **** **** **** **** +15457 Warmind_AstralConstruct_RadialMaster **** **** **** **** **** **** **** **** +15458 Warmind_AstralConstruct_Conversation **** **** **** **** **** **** **** **** +15459 Warmind_AstralConstruct_Slot1 **** **** **** **** **** **** **** **** +15460 Warmind_AstralConstruct_Slot2 **** **** **** **** **** **** **** **** +15461 Warmind_AstralConstruct_Slot3 **** **** **** **** **** **** **** **** +15462 Warmind_AstralConstruct_Slot4 **** **** **** **** **** **** **** **** +15463 Warmind_Biofeedback **** **** **** **** **** **** **** **** +15464 Warmind_BiteOfTheWolf **** **** **** **** **** **** **** **** +15465 Warmind_Bolt **** **** **** **** **** **** **** **** +15466 Warmind_Burst **** **** **** **** **** **** **** **** +15467 Warmind_CallToMind **** **** **** **** **** **** **** **** +15468 Warmind_CallWeaponry **** **** **** **** **** **** **** **** +15469 Warmind_Chameleon **** **** **** **** **** **** **** **** +15470 Warmind_CharmPerson **** **** **** **** **** **** **** **** +15471 Warmind_ClawsOfTheBeast **** **** **** **** **** **** **** **** +15472 Warmind_Compression **** **** **** **** **** **** **** **** +15473 Warmind_Conceal_Thoughts **** **** **** **** **** **** **** **** +15474 Warmind_ControlObject **** **** **** **** **** **** **** **** +15475 Warmind_CreateSound **** **** **** **** **** **** **** **** +15476 Warmind_CrystalShard **** **** **** **** **** **** **** **** +15477 Warmind_Daze **** **** **** **** **** **** **** **** +15478 Warmind_Deceleration **** **** **** **** **** **** **** **** +15479 Warmind_DefPrecog **** **** **** **** **** **** **** **** +15480 Warmind_Demoralize **** **** **** **** **** **** **** **** +15481 Warmind_DestinyDissonance **** **** **** **** **** **** **** **** +15482 Warmind_Disable **** **** **** **** **** **** **** **** +15483 Warmind_DissipatingTouch **** **** **** **** **** **** **** **** +15484 Warmind_Distract **** **** **** **** **** **** **** **** +15485 Warmind_ElfSight **** **** **** **** **** **** **** **** +15486 Warmind_Empathy **** **** **** **** **** **** **** **** +15487 Warmind_EmptyMind **** **** **** **** **** **** **** **** +15488 Warmind_EnergyRay_RadialMaster **** **** **** **** **** **** **** **** +15489 Warmind_EnergyRay_Cold **** **** **** **** **** **** **** **** +15490 Warmind_EnergyRay_Elec **** **** **** **** **** **** **** **** +15491 Warmind_EnergyRay_Fire **** **** **** **** **** **** **** **** +15492 Warmind_EnergyRay_Sonic **** **** **** **** **** **** **** **** +15493 Warmind_EntanglingEctoplasm **** **** **** **** **** **** **** **** +15494 Warmind_Expansion **** **** **** **** **** **** **** **** +15495 Warmind_Far_Hand **** **** **** **** **** **** **** **** +15496 Warmind_ForceScreen **** **** **** **** **** **** **** **** +15497 Warmind_Grease **** **** **** **** **** **** **** **** +15498 Warmind_Hammer **** **** **** **** **** **** **** **** +15499 Warmind_InertialArmour **** **** **** **** **** **** **** **** +15500 Warmind_Matter_Agitation **** **** **** **** **** **** **** **** +15501 Warmind_MetaphysicalClaw **** **** **** **** **** **** **** **** +15502 Warmind_MetaphysicalWeapon **** **** **** **** **** **** **** **** +15503 Warmind_MindThrust **** **** **** **** **** **** **** **** +15504 Warmind_MyLight **** **** **** **** **** **** **** **** +15505 Warmind_OffPrecog **** **** **** **** **** **** **** **** +15506 Warmind_OffPresc **** **** **** **** **** **** **** **** +15507 Warmind_Precognition_RadialMaster **** **** **** **** **** **** **** **** +15508 Warmind_PrecognitionMain **** **** **** **** **** **** **** **** +15509 Warmind_PrecognitionAttack **** **** **** **** **** **** **** **** +15510 Warmind_PrecognitionDamage **** **** **** **** **** **** **** **** +15511 Warmind_PrecognitionSaves **** **** **** **** **** **** **** **** +15512 Warmind_PrecognitionSkills **** **** **** **** **** **** **** **** +15513 Warmind_Prevenom **** **** **** **** **** **** **** **** +15514 Warmind_PrevenomWeapon **** **** **** **** **** **** **** **** +15515 Warmind_Skate **** **** **** **** **** **** **** **** +15516 Warmind_Stomp **** **** **** **** **** **** **** **** +15517 Warmind_Synesthete **** **** **** **** **** **** **** **** +15518 Warmind_Telempathic_Projection **** **** **** **** **** **** **** **** +15519 Warmind_ThickSkin **** **** **** **** **** **** **** **** +15520 Warmind_Vigor **** **** **** **** **** **** **** **** +15521 Warmind_AnimalAffinity **** **** **** **** **** **** **** **** +15522 Warmind_Aversion **** **** **** **** **** **** **** **** +15523 Warmind_BestowPower **** **** **** **** **** **** **** **** +15524 Warmind_BodyAdjustment **** **** **** **** **** **** **** **** +15525 Warmind_Body_Equilibrium **** **** **** **** **** **** **** **** +15526 Warmind_BodyPurification **** **** **** **** **** **** **** **** +15527 Warmind_BrainLock **** **** **** **** **** **** **** **** +15528 Warmind_ClairvoyantSense **** **** **** **** **** **** **** **** +15529 Warmind_Cloud_Mind **** **** **** **** **** **** **** **** +15530 Warmind_ConcBlast **** **** **** **** **** **** **** **** +15531 Warmind_ConcealAmorpha **** **** **** **** **** **** **** **** +15532 Warmind_ControlAir **** **** **** **** **** **** **** **** +15533 Warmind_ControlSound **** **** **** **** **** **** **** **** +15534 Warmind_SwarmOfCrystals **** **** **** **** **** **** **** **** +15535 Warmind_Darkvision **** **** **** **** **** **** **** **** +15536 Warmind_DimensionSwap **** **** **** **** **** **** **** **** +15537 Warmind_DissolvingTouch **** **** **** **** **** **** **** **** +15538 Warmind_Dissolving_Weapon **** **** **** **** **** **** **** **** +15539 Warmind_EgoWhip **** **** **** **** **** **** **** **** +15540 Warmind_EmpathicTransfer **** **** **** **** **** **** **** **** +15541 Warmind_EnergyAdaptSpec_RadialMaster **** **** **** **** **** **** **** **** +15542 Warmind_EnergyAdaptAcid **** **** **** **** **** **** **** **** +15543 Warmind_EnergyAdaptCold **** **** **** **** **** **** **** **** +15544 Warmind_EnergyAdaptElec **** **** **** **** **** **** **** **** +15545 Warmind_EnergyAdaptFire **** **** **** **** **** **** **** **** +15546 Warmind_EnergyAdaptSonic **** **** **** **** **** **** **** **** +15547 Warmind_Energy_Missile_RadialMaster **** **** **** **** **** **** **** **** +15548 Warmind_Energy_Missile_Cold **** **** **** **** **** **** **** **** +15549 Warmind_Energy_Missile_Elec **** **** **** **** **** **** **** **** +15550 Warmind_Energy_Missile_Fire **** **** **** **** **** **** **** **** +15551 Warmind_Energy_Missile_Sonic **** **** **** **** **** **** **** **** +15552 Warmind_EnergyPush_RadialMaster **** **** **** **** **** **** **** **** +15553 Warmind_EnergyPush_Cold **** **** **** **** **** **** **** **** +15554 Warmind_EnergyPush_Elec **** **** **** **** **** **** **** **** +15555 Warmind_EnergyPush_Fire **** **** **** **** **** **** **** **** +15556 Warmind_EnergyPush_Sonic **** **** **** **** **** **** **** **** +15557 Warmind_EnergyStun_RadialMaster **** **** **** **** **** **** **** **** +15558 Warmind_EnergyStun_Cold **** **** **** **** **** **** **** **** +15559 Warmind_EnergyStun_Elec **** **** **** **** **** **** **** **** +15560 Warmind_EnergyStun_Fire **** **** **** **** **** **** **** **** +15561 Warmind_EnergyStun_Sonic **** **** **** **** **** **** **** **** +15562 Warmind_Hustle **** **** **** **** **** **** **** **** +15563 Warmind_Identify **** **** **** **** **** **** **** **** +15564 Warmind_IdInsinuation **** **** **** **** **** **** **** **** +15565 Warmind_InflictPain **** **** **** **** **** **** **** **** +15566 Warmind_Knock **** **** **** **** **** **** **** **** +15567 Warmind_Lock **** **** **** **** **** **** **** **** +15568 Warmind_MindDisrupt **** **** **** **** **** **** **** **** +15569 Warmind_PainfulStrike **** **** **** **** **** **** **** **** +15570 Warmind_RecallAgony **** **** **** **** **** **** **** **** +15571 Warmind_RepairDamage **** **** **** **** **** **** **** **** +15572 Warmind_SharePain **** **** **** **** **** **** **** **** +15573 Warmind_StrengthOfMyEnemy **** **** **** **** **** **** **** **** +15574 Warmind_ThoughtShield **** **** **** **** **** **** **** **** +15575 Warmind_ClawOfTheVampire **** **** **** **** **** **** **** **** +15576 Warmind_CrisisBreath **** **** **** **** **** **** **** **** +15577 Warmind_Danger_Sense **** **** **** **** **** **** **** **** +15578 Warmind_DimensionSlide **** **** **** **** **** **** **** **** +15579 Warmind_Dispel_Psionics **** **** **** **** **** **** **** **** +15580 Warmind_DuodimensionalClaw **** **** **** **** **** **** **** **** +15581 Warmind_EctoCocoon **** **** **** **** **** **** **** **** +15582 Warmind_EctoplasmicForm **** **** **** **** **** **** **** **** +15583 Warmind_EmpathicFeedback **** **** **** **** **** **** **** **** +15584 Warmind_EmpathicTransferHostile **** **** **** **** **** **** **** **** +15585 Warmind_EnergyBolt_RadialMaster **** **** **** **** **** **** **** **** +15586 Warmind_Energy_Bolt_Cold **** **** **** **** **** **** **** **** +15587 Warmind_Energy_Bolt_Elec **** **** **** **** **** **** **** **** +15588 Warmind_Energy_Bolt_Fire **** **** **** **** **** **** **** **** +15589 Warmind_Energy_Bolt_Sonic **** **** **** **** **** **** **** **** +15590 Warmind_EnergyBurst_RadialMaster **** **** **** **** **** **** **** **** +15591 Warmind_Energy_Burst_Cold **** **** **** **** **** **** **** **** +15592 Warmind_Energy_Burst_Elec **** **** **** **** **** **** **** **** +15593 Warmind_Energy_Burst_Fire **** **** **** **** **** **** **** **** +15594 Warmind_Energy_Burst_Sonic **** **** **** **** **** **** **** **** +15595 Warmind_Energy_Cone_RadialMaster **** **** **** **** **** **** **** **** +15596 Warmind_EnergyCone_Cold **** **** **** **** **** **** **** **** +15597 Warmind_EnergyCone_Elec **** **** **** **** **** **** **** **** +15598 Warmind_EnergyCone_Fire **** **** **** **** **** **** **** **** +15599 Warmind_EnergyCone_Sonic **** **** **** **** **** **** **** **** +15600 Warmind_EnergyRetort_RadialMaster **** **** **** **** **** **** **** **** +15601 Warmind_Energy_Retort_Cold **** **** **** **** **** **** **** **** +15602 Warmind_Energy_Retort_Elec **** **** **** **** **** **** **** **** +15603 Warmind_Energy_Retort_Fire **** **** **** **** **** **** **** **** +15604 Warmind_Energy_Retort_Sonic **** **** **** **** **** **** **** **** +15605 Warmind_EnergyWall_RadialMaster **** **** **** **** **** **** **** **** +15606 Warmind_Energy_Wall_Cold **** **** **** **** **** **** **** **** +15607 Warmind_Energy_Wall_Elec **** **** **** **** **** **** **** **** +15608 Warmind_Energy_Wall_Fire **** **** **** **** **** **** **** **** +15609 Warmind_Energy_Wall_Sonic **** **** **** **** **** **** **** **** +15610 Warmind_Eradicate_Invisibility **** **** **** **** **** **** **** **** +15611 Warmind_EscapeDetection **** **** **** **** **** **** **** **** +15612 Warmind_EvadeBurst **** **** **** **** **** **** **** **** +15613 Warmind_Exhale_BlackDrag **** **** **** **** **** **** **** **** +15614 Warmind_FateLink **** **** **** **** **** **** **** **** +15615 Warmind_Greater_Amorpha **** **** **** **** **** **** **** **** +15616 Warmind_Keen_Edge **** **** **** **** **** **** **** **** +15617 Warmind_MentalBarrier **** **** **** **** **** **** **** **** +15618 Warmind_Mindtrap **** **** **** **** **** **** **** **** +15619 Warmind_Psiblast **** **** **** **** **** **** **** **** +15620 Warmind_SharePainForced **** **** **** **** **** **** **** **** +15621 Warmind_TimeHop **** **** **** **** **** **** **** **** +15622 Warmind_Touchsight **** **** **** **** **** **** **** **** +15623 Warmind_UbiqVision **** **** **** **** **** **** **** **** +15624 Warmind_VampiricWeapon **** **** **** **** **** **** **** **** +15625 Warmind_ClawOfEnergy_RadialMaster **** **** **** **** **** **** **** **** +15626 Warmind_ClawofEnergyCold **** **** **** **** **** **** **** **** +15627 Warmind_ClawofEnergyElec **** **** **** **** **** **** **** **** +15628 Warmind_ClawofEnergyFire **** **** **** **** **** **** **** **** +15629 Warmind_DetectRemoteViewing **** **** **** **** **** **** **** **** +15630 Warmind_DimensionalAnchor **** **** **** **** **** **** **** **** +15631 Warmind_DimensionDoor_Master **** **** **** **** **** **** **** **** +15632 Warmind_DimensionDoor_SelfOnly **** **** **** **** **** **** **** **** +15633 Warmind_DimensionDoor_Party **** **** **** **** **** **** **** **** +15634 Warmind_DimensionDoor_DirDist_SelfOnly **** **** **** **** **** **** **** **** +15635 Warmind_DimensionDoor_DirDist_Party **** **** **** **** **** **** **** **** +15636 Warmind_Dismissal **** **** **** **** **** **** **** **** +15637 Warmind_EnergyAdaption **** **** **** **** **** **** **** **** +15638 Warmind_EnergyBall_RadialMaster **** **** **** **** **** **** **** **** +15639 Warmind_EnergyBall_Cold **** **** **** **** **** **** **** **** +15640 Warmind_EnergyBall_Elec **** **** **** **** **** **** **** **** +15641 Warmind_EnergyBall_Fire **** **** **** **** **** **** **** **** +15642 Warmind_EnergyBall_Sonic **** **** **** **** **** **** **** **** +15643 Warmind_Freedom_of_Movement **** **** **** **** **** **** **** **** +15644 Warmind_Immovability **** **** **** **** **** **** **** **** +15645 Warmind_InertialBar **** **** **** **** **** **** **** **** +15646 Warmind_IntellectFortress **** **** **** **** **** **** **** **** +15647 Warmind_Mindwipe **** **** **** **** **** **** **** **** +15648 Warmind_PowerLeech **** **** **** **** **** **** **** **** +15649 Warmind_Dominate_Psionic **** **** **** **** **** **** **** **** +15650 Warmind_PsychicReformation **** **** **** **** **** **** **** **** +15651 Warmind_PsychicVampire **** **** **** **** **** **** **** **** +15652 Warmind_RemoteViewing **** **** **** **** **** **** **** **** +15653 Warmind_SteadfastPercep **** **** **** **** **** **** **** **** +15654 Warmind_TelekineticManeuver **** **** **** **** **** **** **** **** +15655 Warmind_Truevenom **** **** **** **** **** **** **** **** +15656 Warmind_TruevenomWeapon **** **** **** **** **** **** **** **** +15657 Warmind_WeaponOfEnergy_RadialMaster **** **** **** **** **** **** **** **** +15658 Warmind_WeaponofEnergyCold **** **** **** **** **** **** **** **** +15659 Warmind_WeaponofEnergyElec **** **** **** **** **** **** **** **** +15660 Warmind_WeaponofEnergyFire **** **** **** **** **** **** **** **** +15661 Warmind_BaleTeleport **** **** **** **** **** **** **** **** +15662 Warmind_Catapsi **** **** **** **** **** **** **** **** +15663 Warmind_ClairtangentHand **** **** **** **** **** **** **** **** +15664 Warmind_EctoplasmicShambler **** **** **** **** **** **** **** **** +15665 Warmind_EnergyCurrent_RadialMaster **** **** **** **** **** **** **** **** +15666 Warmind_EnergyCurrent_Cold **** **** **** **** **** **** **** **** +15667 Warmind_EnergyCurrent_Elec **** **** **** **** **** **** **** **** +15668 Warmind_EnergyCurrent_Fire **** **** **** **** **** **** **** **** +15669 Warmind_EnergyCurrent_Sonic **** **** **** **** **** **** **** **** +15670 Warmind_HailCrystals **** **** **** **** **** **** **** **** +15671 Warmind_OakBody **** **** **** **** **** **** **** **** +15672 Warmind_Power_Resistance **** **** **** **** **** **** **** **** +15673 Warmind_PsionicRevivify **** **** **** **** **** **** **** **** +15674 Warmind_PsychicCrush **** **** **** **** **** **** **** **** +15675 Warmind_Psychofeedback **** **** **** **** **** **** **** **** +15676 Warmind_SecondChance **** **** **** **** **** **** **** **** +15677 Warmind_ShatterMindBlank **** **** **** **** **** **** **** **** +15678 Warmind_Teleport_RadialMaster **** **** **** **** **** **** **** **** +15679 Warmind_Teleport_SelfOnly **** **** **** **** **** **** **** **** +15680 Warmind_Teleport_Party **** **** **** **** **** **** **** **** +15681 Warmind_TowerIronWill **** **** **** **** **** **** **** **** +15682 Warmind_True_Seeing **** **** **** **** **** **** **** **** +15683 PsychicWarrior_GripOfIron **** **** **** **** **** **** **** **** +15684 FistOfZuoken_GripOfIron **** **** **** **** **** **** **** **** +15685 Warmind_GripOfIron **** **** **** **** **** **** **** **** +15686 Psion_GripOfIron **** **** **** **** **** **** **** **** +15687 Wilder_GripOfIron **** **** **** **** **** **** **** **** +15688 PsychicRogue_GripOfIron **** **** **** **** **** **** **** **** +15689 **** **** **** **** **** **** **** **** **** +15690 **** **** **** **** **** **** **** **** **** +15691 **** **** **** **** **** **** **** **** **** +15692 **** **** **** **** **** **** **** **** **** +15693 **** **** **** **** **** **** **** **** **** +15694 **** **** **** **** **** **** **** **** **** +15695 **** **** **** **** **** **** **** **** **** +15696 **** **** **** **** **** **** **** **** **** +15697 **** **** **** **** **** **** **** **** **** +15698 **** **** **** **** **** **** **** **** **** +15699 **** **** **** **** **** **** **** **** **** +15700 **** **** **** **** **** **** **** **** **** +15701 **** **** **** **** **** **** **** **** **** +15702 **** **** **** **** **** **** **** **** **** +15703 **** **** **** **** **** **** **** **** **** +15704 **** **** **** **** **** **** **** **** **** +15705 **** **** **** **** **** **** **** **** **** +15706 **** **** **** **** **** **** **** **** **** +15707 **** **** **** **** **** **** **** **** **** +15708 **** **** **** **** **** **** **** **** **** +15709 **** **** **** **** **** **** **** **** **** +15710 **** **** **** **** **** **** **** **** **** +15711 **** **** **** **** **** **** **** **** **** +15712 **** **** **** **** **** **** **** **** **** +15713 **** **** **** **** **** **** **** **** **** +15714 **** **** **** **** **** **** **** **** **** +15715 **** **** **** **** **** **** **** **** **** +15716 **** **** **** **** **** **** **** **** **** +15717 **** **** **** **** **** **** **** **** **** +15718 **** **** **** **** **** **** **** **** **** +15719 **** **** **** **** **** **** **** **** **** +15720 **** **** **** **** **** **** **** **** **** +15721 **** **** **** **** **** **** **** **** **** +15722 **** **** **** **** **** **** **** **** **** +15723 **** **** **** **** **** **** **** **** **** +15724 **** **** **** **** **** **** **** **** **** +15725 **** **** **** **** **** **** **** **** **** +15726 **** **** **** **** **** **** **** **** **** +15727 **** **** **** **** **** **** **** **** **** +15728 **** **** **** **** **** **** **** **** **** +15729 **** **** **** **** **** **** **** **** **** +15730 **** **** **** **** **** **** **** **** **** +15731 **** **** **** **** **** **** **** **** **** +15732 **** **** **** **** **** **** **** **** **** +15733 **** **** **** **** **** **** **** **** **** +15734 **** **** **** **** **** **** **** **** **** +15735 **** **** **** **** **** **** **** **** **** +15736 **** **** **** **** **** **** **** **** **** +15737 **** **** **** **** **** **** **** **** **** +15738 **** **** **** **** **** **** **** **** **** +15739 **** **** **** **** **** **** **** **** **** +15740 **** **** **** **** **** **** **** **** **** +15741 **** **** **** **** **** **** **** **** **** +15742 **** **** **** **** **** **** **** **** **** +15743 **** **** **** **** **** **** **** **** **** +15744 **** **** **** **** **** **** **** **** **** +15745 **** **** **** **** **** **** **** **** **** +15746 **** **** **** **** **** **** **** **** **** +15747 **** **** **** **** **** **** **** **** **** +15748 **** **** **** **** **** **** **** **** **** +15749 **** **** **** **** **** **** **** **** **** +15750 **** **** **** **** **** **** **** **** **** +15751 **** **** **** **** **** **** **** **** **** +15752 **** **** **** **** **** **** **** **** **** +15753 **** **** **** **** **** **** **** **** **** +15754 **** **** **** **** **** **** **** **** **** +15755 **** **** **** **** **** **** **** **** **** +15756 **** **** **** **** **** **** **** **** **** +15757 **** **** **** **** **** **** **** **** **** +15758 **** **** **** **** **** **** **** **** **** +15759 **** **** **** **** **** **** **** **** **** +15760 **** **** **** **** **** **** **** **** **** +15761 **** **** **** **** **** **** **** **** **** +15762 **** **** **** **** **** **** **** **** **** +15763 **** **** **** **** **** **** **** **** **** +15764 **** **** **** **** **** **** **** **** **** +15765 **** **** **** **** **** **** **** **** **** +15766 **** **** **** **** **** **** **** **** **** +15767 **** **** **** **** **** **** **** **** **** +15768 **** **** **** **** **** **** **** **** **** +15769 **** **** **** **** **** **** **** **** **** +15770 **** **** **** **** **** **** **** **** **** +15771 **** **** **** **** **** **** **** **** **** +15772 **** **** **** **** **** **** **** **** **** +15773 **** **** **** **** **** **** **** **** **** +15774 **** **** **** **** **** **** **** **** **** +15775 **** **** **** **** **** **** **** **** **** +15776 **** **** **** **** **** **** **** **** **** +15777 **** **** **** **** **** **** **** **** **** +15778 **** **** **** **** **** **** **** **** **** +15779 **** **** **** **** **** **** **** **** **** +15780 **** **** **** **** **** **** **** **** **** +15781 **** **** **** **** **** **** **** **** **** +15782 **** **** **** **** **** **** **** **** **** +15783 **** **** **** **** **** **** **** **** **** +15784 **** **** **** **** **** **** **** **** **** +15785 **** **** **** **** **** **** **** **** **** +15786 **** **** **** **** **** **** **** **** **** +15787 **** **** **** **** **** **** **** **** **** +15788 **** **** **** **** **** **** **** **** **** +15789 **** **** **** **** **** **** **** **** **** +15790 **** **** **** **** **** **** **** **** **** +15791 **** **** **** **** **** **** **** **** **** +15792 **** **** **** **** **** **** **** **** **** +15793 **** **** **** **** **** **** **** **** **** +15794 **** **** **** **** **** **** **** **** **** +15795 **** **** **** **** **** **** **** **** **** +15796 **** **** **** **** **** **** **** **** **** +15797 **** **** **** **** **** **** **** **** **** +15798 **** **** **** **** **** **** **** **** **** +15799 ####END_OF_PSI_SPELLBOOK_RESERVE **** **** **** **** **** **** **** **** +15800 ####START_OF_TOB_SPELLBOOK_RESERVE **** **** **** **** **** **** **** **** +15801 Crusader_BlisteringFlourish **** **** **** **** **** **** **** **** +15802 Crusader_BurningBlade **** **** **** **** **** **** **** **** +15803 Crusader_BurningBrand **** **** **** **** **** **** **** **** +15804 Crusader_DeathMark **** **** **** **** **** **** **** **** +15805 Crusader_DesertTempest **** **** **** **** **** **** **** **** +15806 Crusader_DistractingEmber **** **** **** **** **** **** **** **** +15807 Crusader_DragonsFlame **** **** **** **** **** **** **** **** +15808 Crusader_FanTheFlames **** **** **** **** **** **** **** **** +15809 Crusader_FieryAssault **** **** **** **** **** **** **** **** +15810 Crusader_FireRiposte **** **** **** **** **** **** **** **** +15811 Crusader_Firesnake **** **** **** **** **** **** **** **** +15812 Crusader_FlamesBlessing **** **** **** **** **** **** **** **** +15813 Crusader_FlashingSun **** **** **** **** **** **** **** **** +15814 Crusader_HatchlingsFlame **** **** **** **** **** **** **** **** +15815 Crusader_HolocaustCloak **** **** **** **** **** **** **** **** +15816 Crusader_InfernoBlade **** **** **** **** **** **** **** **** +15817 Crusader_InfernoBlast **** **** **** **** **** **** **** **** +15818 Crusader_LeapingFlame **** **** **** **** **** **** **** **** +15819 Crusader_LingeringInferno **** **** **** **** **** **** **** **** +15820 Crusader_RingOfFire **** **** **** **** **** **** **** **** +15821 Crusader_RisingPhoenix **** **** **** **** **** **** **** **** +15822 Crusader_SalamanderCharge **** **** **** **** **** **** **** **** +15823 Crusader_SearingBlade **** **** **** **** **** **** **** **** +15824 Crusader_SearingCharge **** **** **** **** **** **** **** **** +15825 Crusader_WindStride **** **** **** **** **** **** **** **** +15826 Crusader_WyrmsFlame **** **** **** **** **** **** **** **** +15827 Crusader_ZephyrDance **** **** **** **** **** **** **** **** +15828 Crusader_AuraOfChaos **** **** **** **** **** **** **** **** +15829 Crusader_AuraOfPerfectOrder **** **** **** **** **** **** **** **** +15830 Crusader_AuraOfTriumph **** **** **** **** **** **** **** **** +15831 Crusader_AuraOfTyranny **** **** **** **** **** **** **** **** +15832 Crusader_CastigatingStrike **** **** **** **** **** **** **** **** +15833 Crusader_CrusadersStrike **** **** **** **** **** **** **** **** +15834 Crusader_DauntingStrike **** **** **** **** **** **** **** **** +15835 Crusader_DefensiveRebuke **** **** **** **** **** **** **** **** +15836 Crusader_DivineSurge **** **** **** **** **** **** **** **** +15837 Crusader_DivineSurgeGreater **** **** **** **** **** **** **** **** +15838 Crusader_DivineSurgeGreaterSub1 **** **** **** **** **** **** **** **** +15839 Crusader_DivineSurgeGreaterSub2 **** **** **** **** **** **** **** **** +15840 Crusader_DivineSurgeGreaterSub3 **** **** **** **** **** **** **** **** +15841 Crusader_DoomCharge **** **** **** **** **** **** **** **** +15842 Crusader_EntanglingBlade **** **** **** **** **** **** **** **** +15843 Crusader_Foehammer **** **** **** **** **** **** **** **** +15844 Crusader_ImmortalFortitude **** **** **** **** **** **** **** **** +15845 Crusader_IronGuardsGlare **** **** **** **** **** **** **** **** +15846 Crusader_LawBearer **** **** **** **** **** **** **** **** +15847 Crusader_MartialSpirit **** **** **** **** **** **** **** **** +15848 Crusader_RadiantCharge **** **** **** **** **** **** **** **** +15849 Crusader_RallyingStrike **** **** **** **** **** **** **** **** +15850 Crusader_RevitalizingStrike **** **** **** **** **** **** **** **** +15851 Crusader_ShieldBlock **** **** **** **** **** **** **** **** +15852 Crusader_ShieldCounter **** **** **** **** **** **** **** **** +15853 Crusader_StrikeOfRighteousVitality **** **** **** **** **** **** **** **** +15854 Crusader_ThicketOfBlades **** **** **** **** **** **** **** **** +15855 Crusader_TideOfChaos **** **** **** **** **** **** **** **** +15856 Crusader_VanguardStrike **** **** **** **** **** **** **** **** +15857 Crusader_ActionBeforeThought **** **** **** **** **** **** **** **** +15858 Crusader_AvalancheOfBlades **** **** **** **** **** **** **** **** +15859 Crusader_BoundingAssault **** **** **** **** **** **** **** **** +15860 Crusader_DiamondDefense **** **** **** **** **** **** **** **** +15861 Crusader_DiamondNightmareBlade **** **** **** **** **** **** **** **** +15862 Crusader_DisruptingBlow **** **** **** **** **** **** **** **** +15863 Crusader_EmeraldRazor **** **** **** **** **** **** **** **** +15864 Crusader_HearingTheAir **** **** **** **** **** **** **** **** +15865 Crusader_InsightfulStrike **** **** **** **** **** **** **** **** +15866 Crusader_InsightfulStrikeGreater **** **** **** **** **** **** **** **** +15867 Crusader_MindOverBody **** **** **** **** **** **** **** **** +15868 Crusader_MindStrike **** **** **** **** **** **** **** **** +15869 Crusader_MomentOfAlacrity **** **** **** **** **** **** **** **** +15870 Crusader_MomentOfPerfectMind **** **** **** **** **** **** **** **** +15871 Crusader_PearlOfBlackDoubt **** **** **** **** **** **** **** **** +15872 Crusader_QuicksilverMotion **** **** **** **** **** **** **** **** +15873 Crusader_RapidCounter **** **** **** **** **** **** **** **** +15874 Crusader_RubyNightmareBlade **** **** **** **** **** **** **** **** +15875 Crusader_SapphireNightmareBlade **** **** **** **** **** **** **** **** +15876 Crusader_StanceOfAlacrity **** **** **** **** **** **** **** **** +15877 Crusader_StanceOfClarity **** **** **** **** **** **** **** **** +15878 Crusader_TimeStandsStill **** **** **** **** **** **** **** **** +15879 Crusader_AbsoluteSteel **** **** **** **** **** **** **** **** +15880 Crusader_AdamantineHurricane **** **** **** **** **** **** **** **** +15881 Crusader_DancingBladeForm **** **** **** **** **** **** **** **** +15882 Crusader_DazingStrike **** **** **** **** **** **** **** **** +15883 Crusader_DisarmingStrike **** **** **** **** **** **** **** **** +15884 Crusader_ExorcismOfSteel **** **** **** **** **** **** **** **** +15885 Crusader_FinishingMove **** **** **** **** **** **** **** **** +15886 Crusader_IronHeartEndurance **** **** **** **** **** **** **** **** +15887 Crusader_IronHeartFocus **** **** **** **** **** **** **** **** +15888 Crusader_IronHeartSurge **** **** **** **** **** **** **** **** +15889 Crusader_LightningRecovery **** **** **** **** **** **** **** **** +15890 Crusader_LightningThrow **** **** **** **** **** **** **** **** +15891 Crusader_ManticoreParry **** **** **** **** **** **** **** **** +15892 Crusader_MithralTornado **** **** **** **** **** **** **** **** +15893 Crusader_PunishingStance **** **** **** **** **** **** **** **** +15894 Crusader_ScythingBlade **** **** **** **** **** **** **** **** +15895 Crusader_SteelWind **** **** **** **** **** **** **** **** +15896 Crusader_SteelyStrike **** **** **** **** **** **** **** **** +15897 Crusader_StrikeOfPerfectClarity **** **** **** **** **** **** **** **** +15898 Crusader_SupremeBladeParry **** **** **** **** **** **** **** **** +15899 Crusader_WallOfBlades **** **** **** **** **** **** **** **** +15900 Crusader_BafflingDefense **** **** **** **** **** **** **** **** +15901 Crusader_BallistaThrow **** **** **** **** **** **** **** **** +15902 Crusader_CleverPositioning **** **** **** **** **** **** **** **** +15903 Crusader_CometThrow **** **** **** **** **** **** **** **** +15904 Crusader_CounterCharge **** **** **** **** **** **** **** **** +15905 Crusader_DevastatingThrow **** **** **** **** **** **** **** **** +15906 Crusader_FeignedOpening **** **** **** **** **** **** **** **** +15907 Crusader_FoolsStrike **** **** **** **** **** **** **** **** +15908 Crusader_GhostlyDefense **** **** **** **** **** **** **** **** +15909 Crusader_GiantKillingStyle **** **** **** **** **** **** **** **** +15910 Crusader_HydraSlayingStrike **** **** **** **** **** **** **** **** +15911 Crusader_MightyThrow **** **** **** **** **** **** **** **** +15912 Crusader_MirroredPursuit **** **** **** **** **** **** **** **** +15913 Crusader_ScorpionParry **** **** **** **** **** **** **** **** +15914 Crusader_ShiftingDefense **** **** **** **** **** **** **** **** +15915 Crusader_SoaringThrow **** **** **** **** **** **** **** **** +15916 Crusader_StalkingShadow **** **** **** **** **** **** **** **** +15917 Crusader_StepOfTheWind **** **** **** **** **** **** **** **** +15918 Crusader_StrikeOfTheBrokenShield **** **** **** **** **** **** **** **** +15919 Crusader_TornadoThrow **** **** **** **** **** **** **** **** +15920 Crusader_AssassinsStance **** **** **** **** **** **** **** **** +15921 Crusader_BalanceOnTheSky **** **** **** **** **** **** **** **** +15922 Crusader_BloodlettingStrike **** **** **** **** **** **** **** **** +15923 Crusader_ChildOfShadow **** **** **** **** **** **** **** **** +15924 Crusader_ClingingShadowStrike **** **** **** **** **** **** **** **** +15925 Crusader_CloakOfDeception **** **** **** **** **** **** **** **** +15926 Crusader_DanceOfTheSpider **** **** **** **** **** **** **** **** +15927 Crusader_DeathInTheDark **** **** **** **** **** **** **** **** +15928 Crusader_DrainVitality **** **** **** **** **** **** **** **** +15929 Crusader_EnervatingShadowStrike **** **** **** **** **** **** **** **** +15930 Crusader_FiveShadowCreepingIceEnervationStrike **** **** **** **** **** **** **** **** +15931 Crusader_GhostBlade **** **** **** **** **** **** **** **** +15932 Crusader_HandOfDeath **** **** **** **** **** **** **** **** +15933 Crusader_IslandOfBlades **** **** **** **** **** **** **** **** +15934 Crusader_ObscuringShadowVeil **** **** **** **** **** **** **** **** +15935 Crusader_OneWithShadow **** **** **** **** **** **** **** **** +15936 Crusader_ShadowBladeTechnique **** **** **** **** **** **** **** **** +15937 Crusader_ShadowBlink **** **** **** **** **** **** **** **** +15938 Crusader_ShadowGarrote **** **** **** **** **** **** **** **** +15939 Crusader_ShadowJaunt **** **** **** **** **** **** **** **** +15940 Crusader_ShadowNoose **** **** **** **** **** **** **** **** +15941 Crusader_ShadowStride **** **** **** **** **** **** **** **** +15942 Crusader_StalkerInTheNight **** **** **** **** **** **** **** **** +15943 Crusader_StepOfTheDancingMoth **** **** **** **** **** **** **** **** +15944 Crusader_StrengthDrainingStrike **** **** **** **** **** **** **** **** +15945 Crusader_AdamantineBones **** **** **** **** **** **** **** **** +15946 Crusader_AncientMountainHammer **** **** **** **** **** **** **** **** +15947 Crusader_BonesplittingStrike **** **** **** **** **** **** **** **** +15948 Crusader_Bonecrusher **** **** **** **** **** **** **** **** +15949 Crusader_BoulderRoll **** **** **** **** **** **** **** **** +15950 Crusader_ChargingMinotaur **** **** **** **** **** **** **** **** +15951 Crusader_ColossusStrike **** **** **** **** **** **** **** **** +15952 Crusader_CrushingVise **** **** **** **** **** **** **** **** +15953 Crusader_CrushingWeightOfTheMountain **** **** **** **** **** **** **** **** +15954 Crusader_EarthstrikeQuake **** **** **** **** **** **** **** **** +15955 Crusader_ElderMountainHammer **** **** **** **** **** **** **** **** +15956 Crusader_GiantsStance **** **** **** **** **** **** **** **** +15957 Crusader_IronBones **** **** **** **** **** **** **** **** +15958 Crusader_IrresistibleMountainStrike **** **** **** **** **** **** **** **** +15959 Crusader_MountainAvalanche **** **** **** **** **** **** **** **** +15960 Crusader_MountainHammer **** **** **** **** **** **** **** **** +15961 Crusader_MountainTombstoneStrike **** **** **** **** **** **** **** **** +15962 Crusader_OverwhelmingMountainStrike **** **** **** **** **** **** **** **** +15963 Crusader_RootsOfTheMountain **** **** **** **** **** **** **** **** +15964 Crusader_StoneBones **** **** **** **** **** **** **** **** +15965 Crusader_StoneDragonsFury **** **** **** **** **** **** **** **** +15966 Crusader_StoneVise **** **** **** **** **** **** **** **** +15967 Crusader_StonefootStance **** **** **** **** **** **** **** **** +15968 Crusader_StrengthOfStone **** **** **** **** **** **** **** **** +15969 Crusader_BloodInTheWater **** **** **** **** **** **** **** **** +15970 Crusader_ClawAtTheMoon **** **** **** **** **** **** **** **** +15971 Crusader_DancingMongoose **** **** **** **** **** **** **** **** +15972 Crusader_DeathFromAbove **** **** **** **** **** **** **** **** +15973 Crusader_FeralDeathBlow **** **** **** **** **** **** **** **** +15974 Crusader_FleshRipper **** **** **** **** **** **** **** **** +15975 Crusader_FountainOfBlood **** **** **** **** **** **** **** **** +15976 Crusader_GirallonWindmillFleshRip **** **** **** **** **** **** **** **** +15977 Crusader_HamstringAttack **** **** **** **** **** **** **** **** +15978 Crusader_HuntersSense **** **** **** **** **** **** **** **** +15979 Crusader_LeapingDragonStance **** **** **** **** **** **** **** **** +15980 Crusader_PouncingCharge **** **** **** **** **** **** **** **** +15981 Crusader_PreyOnTheWeak **** **** **** **** **** **** **** **** +15982 Crusader_RabidBearStrike **** **** **** **** **** **** **** **** +15983 Crusader_RabidWolfStrike **** **** **** **** **** **** **** **** +15984 Crusader_RagingMongoose **** **** **** **** **** **** **** **** +15985 Crusader_SoaringRaptorStrike **** **** **** **** **** **** **** **** +15986 Crusader_SuddenLeap **** **** **** **** **** **** **** **** +15987 Crusader_SwoopingDragonStrike **** **** **** **** **** **** **** **** +15988 Crusader_WolfClimbsTheMountain **** **** **** **** **** **** **** **** +15989 Crusader_WolfFangStrike **** **** **** **** **** **** **** **** +15990 Crusader_WolfPackTactics **** **** **** **** **** **** **** **** +15991 Crusader_WolverineStance **** **** **** **** **** **** **** **** +15992 Crusader_BattleLeadersCharge **** **** **** **** **** **** **** **** +15993 Crusader_BolsteringVoice **** **** **** **** **** **** **** **** +15994 Crusader_ClarionCall **** **** **** **** **** **** **** **** +15995 Crusader_CoveringStrike **** **** **** **** **** **** **** **** +15996 Crusader_DouseTheFlames **** **** **** **** **** **** **** **** +15997 Crusader_FlankingManeuver **** **** **** **** **** **** **** **** +15998 Crusader_LeadingTheAttack **** **** **** **** **** **** **** **** +15999 Crusader_LeadingTheCharge **** **** **** **** **** **** **** **** +16000 Crusader_LionsRoar **** **** **** **** **** **** **** **** +16001 Crusader_OrderForgedFromChaos **** **** **** **** **** **** **** **** +16002 Crusader_PressTheAdvantage **** **** **** **** **** **** **** **** +16003 Crusader_SwarmTactics **** **** **** **** **** **** **** **** +16004 Crusader_SwarmingAssault **** **** **** **** **** **** **** **** +16005 Crusader_TacticalStrike **** **** **** **** **** **** **** **** +16006 Crusader_TacticsOfTheWolf **** **** **** **** **** **** **** **** +16007 Crusader_WarLeadersCharge **** **** **** **** **** **** **** **** +16008 Crusader_WarMastersCharge **** **** **** **** **** **** **** **** +16009 Crusader_WhiteRavenHammer **** **** **** **** **** **** **** **** +16010 Crusader_WhiteRavenStrike **** **** **** **** **** **** **** **** +16011 Crusader_WhiteRavenTactics **** **** **** **** **** **** **** **** +16012 Swordsage_BlisteringFlourish **** **** **** **** **** **** **** **** +16013 Swordsage_BurningBlade **** **** **** **** **** **** **** **** +16014 Swordsage_BurningBrand **** **** **** **** **** **** **** **** +16015 Swordsage_DeathMark **** **** **** **** **** **** **** **** +16016 Swordsage_DesertTempest **** **** **** **** **** **** **** **** +16017 Swordsage_DistractingEmber **** **** **** **** **** **** **** **** +16018 Swordsage_DragonsFlame **** **** **** **** **** **** **** **** +16019 Swordsage_FanTheFlames **** **** **** **** **** **** **** **** +16020 Swordsage_FieryAssault **** **** **** **** **** **** **** **** +16021 Swordsage_FireRiposte **** **** **** **** **** **** **** **** +16022 Swordsage_Firesnake **** **** **** **** **** **** **** **** +16023 Swordsage_FlamesBlessing **** **** **** **** **** **** **** **** +16024 Swordsage_FlashingSun **** **** **** **** **** **** **** **** +16025 Swordsage_HatchlingsFlame **** **** **** **** **** **** **** **** +16026 Swordsage_HolocaustCloak **** **** **** **** **** **** **** **** +16027 Swordsage_InfernoBlade **** **** **** **** **** **** **** **** +16028 Swordsage_InfernoBlast **** **** **** **** **** **** **** **** +16029 Swordsage_LeapingFlame **** **** **** **** **** **** **** **** +16030 Swordsage_LingeringInferno **** **** **** **** **** **** **** **** +16031 Swordsage_RingOfFire **** **** **** **** **** **** **** **** +16032 Swordsage_RisingPhoenix **** **** **** **** **** **** **** **** +16033 Swordsage_SalamanderCharge **** **** **** **** **** **** **** **** +16034 Swordsage_SearingBlade **** **** **** **** **** **** **** **** +16035 Swordsage_SearingCharge **** **** **** **** **** **** **** **** +16036 Swordsage_WindStride **** **** **** **** **** **** **** **** +16037 Swordsage_WyrmsFlame **** **** **** **** **** **** **** **** +16038 Swordsage_ZephyrDance **** **** **** **** **** **** **** **** +16039 Swordsage_AuraOfChaos **** **** **** **** **** **** **** **** +16040 Swordsage_AuraOfPerfectOrder **** **** **** **** **** **** **** **** +16041 Swordsage_AuraOfTriumph **** **** **** **** **** **** **** **** +16042 Swordsage_AuraOfTyranny **** **** **** **** **** **** **** **** +16043 Swordsage_CastigatingStrike **** **** **** **** **** **** **** **** +16044 Swordsage_CrusadersStrike **** **** **** **** **** **** **** **** +16045 Swordsage_DauntingStrike **** **** **** **** **** **** **** **** +16046 Swordsage_DefensiveRebuke **** **** **** **** **** **** **** **** +16047 Swordsage_DivineSurge **** **** **** **** **** **** **** **** +16048 Swordsage_DivineSurgeGreater **** **** **** **** **** **** **** **** +16049 Swordsage_DivineSurgeGreaterSub1 **** **** **** **** **** **** **** **** +16050 Swordsage_DivineSurgeGreaterSub2 **** **** **** **** **** **** **** **** +16051 Swordsage_DivineSurgeGreaterSub3 **** **** **** **** **** **** **** **** +16052 Swordsage_DoomCharge **** **** **** **** **** **** **** **** +16053 Swordsage_EntanglingBlade **** **** **** **** **** **** **** **** +16054 Swordsage_Foehammer **** **** **** **** **** **** **** **** +16055 Swordsage_ImmortalFortitude **** **** **** **** **** **** **** **** +16056 Swordsage_IronGuardsGlare **** **** **** **** **** **** **** **** +16057 Swordsage_LawBearer **** **** **** **** **** **** **** **** +16058 Swordsage_MartialSpirit **** **** **** **** **** **** **** **** +16059 Swordsage_RadiantCharge **** **** **** **** **** **** **** **** +16060 Swordsage_RallyingStrike **** **** **** **** **** **** **** **** +16061 Swordsage_RevitalizingStrike **** **** **** **** **** **** **** **** +16062 Swordsage_ShieldBlock **** **** **** **** **** **** **** **** +16063 Swordsage_ShieldCounter **** **** **** **** **** **** **** **** +16064 Swordsage_StrikeOfRighteousVitality **** **** **** **** **** **** **** **** +16065 Swordsage_ThicketOfBlades **** **** **** **** **** **** **** **** +16066 Swordsage_TideOfChaos **** **** **** **** **** **** **** **** +16067 Swordsage_VanguardStrike **** **** **** **** **** **** **** **** +16068 Swordsage_ActionBeforeThought **** **** **** **** **** **** **** **** +16069 Swordsage_AvalancheOfBlades **** **** **** **** **** **** **** **** +16070 Swordsage_BoundingAssault **** **** **** **** **** **** **** **** +16071 Swordsage_DiamondDefense **** **** **** **** **** **** **** **** +16072 Swordsage_DiamondNightmareBlade **** **** **** **** **** **** **** **** +16073 Swordsage_DisruptingBlow **** **** **** **** **** **** **** **** +16074 Swordsage_EmeraldRazor **** **** **** **** **** **** **** **** +16075 Swordsage_HearingTheAir **** **** **** **** **** **** **** **** +16076 Swordsage_InsightfulStrike **** **** **** **** **** **** **** **** +16077 Swordsage_InsightfulStrikeGreater **** **** **** **** **** **** **** **** +16078 Swordsage_MindOverBody **** **** **** **** **** **** **** **** +16079 Swordsage_MindStrike **** **** **** **** **** **** **** **** +16080 Swordsage_MomentOfAlacrity **** **** **** **** **** **** **** **** +16081 Swordsage_MomentOfPerfectMind **** **** **** **** **** **** **** **** +16082 Swordsage_PearlOfBlackDoubt **** **** **** **** **** **** **** **** +16083 Swordsage_QuicksilverMotion **** **** **** **** **** **** **** **** +16084 Swordsage_RapidCounter **** **** **** **** **** **** **** **** +16085 Swordsage_RubyNightmareBlade **** **** **** **** **** **** **** **** +16086 Swordsage_SapphireNightmareBlade **** **** **** **** **** **** **** **** +16087 Swordsage_StanceOfAlacrity **** **** **** **** **** **** **** **** +16088 Swordsage_StanceOfClarity **** **** **** **** **** **** **** **** +16089 Swordsage_TimeStandsStill **** **** **** **** **** **** **** **** +16090 Swordsage_AbsoluteSteel **** **** **** **** **** **** **** **** +16091 Swordsage_AdamantineHurricane **** **** **** **** **** **** **** **** +16092 Swordsage_DancingBladeForm **** **** **** **** **** **** **** **** +16093 Swordsage_DazingStrike **** **** **** **** **** **** **** **** +16094 Swordsage_DisarmingStrike **** **** **** **** **** **** **** **** +16095 Swordsage_ExorcismOfSteel **** **** **** **** **** **** **** **** +16096 Swordsage_FinishingMove **** **** **** **** **** **** **** **** +16097 Swordsage_IronHeartEndurance **** **** **** **** **** **** **** **** +16098 Swordsage_IronHeartFocus **** **** **** **** **** **** **** **** +16099 Swordsage_IronHeartSurge **** **** **** **** **** **** **** **** +16100 Swordsage_LightningRecovery **** **** **** **** **** **** **** **** +16101 Swordsage_LightningThrow **** **** **** **** **** **** **** **** +16102 Swordsage_ManticoreParry **** **** **** **** **** **** **** **** +16103 Swordsage_MithralTornado **** **** **** **** **** **** **** **** +16104 Swordsage_PunishingStance **** **** **** **** **** **** **** **** +16105 Swordsage_ScythingBlade **** **** **** **** **** **** **** **** +16106 Swordsage_SteelWind **** **** **** **** **** **** **** **** +16107 Swordsage_SteelyStrike **** **** **** **** **** **** **** **** +16108 Swordsage_StrikeOfPerfectClarity **** **** **** **** **** **** **** **** +16109 Swordsage_SupremeBladeParry **** **** **** **** **** **** **** **** +16110 Swordsage_WallOfBlades **** **** **** **** **** **** **** **** +16111 Swordsage_BafflingDefense **** **** **** **** **** **** **** **** +16112 Swordsage_BallistaThrow **** **** **** **** **** **** **** **** +16113 Swordsage_CleverPositioning **** **** **** **** **** **** **** **** +16114 Swordsage_CometThrow **** **** **** **** **** **** **** **** +16115 Swordsage_CounterCharge **** **** **** **** **** **** **** **** +16116 Swordsage_DevastatingThrow **** **** **** **** **** **** **** **** +16117 Swordsage_FeignedOpening **** **** **** **** **** **** **** **** +16118 Swordsage_FoolsStrike **** **** **** **** **** **** **** **** +16119 Swordsage_GhostlyDefense **** **** **** **** **** **** **** **** +16120 Swordsage_GiantKillingStyle **** **** **** **** **** **** **** **** +16121 Swordsage_HydraSlayingStrike **** **** **** **** **** **** **** **** +16122 Swordsage_MightyThrow **** **** **** **** **** **** **** **** +16123 Swordsage_MirroredPursuit **** **** **** **** **** **** **** **** +16124 Swordsage_ScorpionParry **** **** **** **** **** **** **** **** +16125 Swordsage_ShiftingDefense **** **** **** **** **** **** **** **** +16126 Swordsage_SoaringThrow **** **** **** **** **** **** **** **** +16127 Swordsage_StalkingShadow **** **** **** **** **** **** **** **** +16128 Swordsage_StepOfTheWind **** **** **** **** **** **** **** **** +16129 Swordsage_StrikeOfTheBrokenShield **** **** **** **** **** **** **** **** +16130 Swordsage_TornadoThrow **** **** **** **** **** **** **** **** +16131 Swordsage_AssassinsStance **** **** **** **** **** **** **** **** +16132 Swordsage_BalanceOnTheSky **** **** **** **** **** **** **** **** +16133 Swordsage_BloodlettingStrike **** **** **** **** **** **** **** **** +16134 Swordsage_ChildOfShadow **** **** **** **** **** **** **** **** +16135 Swordsage_ClingingShadowStrike **** **** **** **** **** **** **** **** +16136 Swordsage_CloakOfDeception **** **** **** **** **** **** **** **** +16137 Swordsage_DanceOfTheSpider **** **** **** **** **** **** **** **** +16138 Swordsage_DeathInTheDark **** **** **** **** **** **** **** **** +16139 Swordsage_DrainVitality **** **** **** **** **** **** **** **** +16140 Swordsage_EnervatingShadowStrike **** **** **** **** **** **** **** **** +16141 Swordsage_FiveShadowCreepingIceEnervationStrike **** **** **** **** **** **** **** **** +16142 Swordsage_GhostBlade **** **** **** **** **** **** **** **** +16143 Swordsage_HandOfDeath **** **** **** **** **** **** **** **** +16144 Swordsage_IslandOfBlades **** **** **** **** **** **** **** **** +16145 Swordsage_ObscuringShadowVeil **** **** **** **** **** **** **** **** +16146 Swordsage_OneWithShadow **** **** **** **** **** **** **** **** +16147 Swordsage_ShadowBladeTechnique **** **** **** **** **** **** **** **** +16148 Swordsage_ShadowBlink **** **** **** **** **** **** **** **** +16149 Swordsage_ShadowGarrote **** **** **** **** **** **** **** **** +16150 Swordsage_ShadowJaunt **** **** **** **** **** **** **** **** +16151 Swordsage_ShadowNoose **** **** **** **** **** **** **** **** +16152 Swordsage_ShadowStride **** **** **** **** **** **** **** **** +16153 Swordsage_StalkerInTheNight **** **** **** **** **** **** **** **** +16154 Swordsage_StepOfTheDancingMoth **** **** **** **** **** **** **** **** +16155 Swordsage_StrengthDrainingStrike **** **** **** **** **** **** **** **** +16156 Swordsage_AdamantineBones **** **** **** **** **** **** **** **** +16157 Swordsage_AncientMountainHammer **** **** **** **** **** **** **** **** +16158 Swordsage_BonesplittingStrike **** **** **** **** **** **** **** **** +16159 Swordsage_Bonecrusher **** **** **** **** **** **** **** **** +16160 Swordsage_BoulderRoll **** **** **** **** **** **** **** **** +16161 Swordsage_ChargingMinotaur **** **** **** **** **** **** **** **** +16162 Swordsage_ColossusStrike **** **** **** **** **** **** **** **** +16163 Swordsage_CrushingVise **** **** **** **** **** **** **** **** +16164 Swordsage_CrushingWeightOfTheMountain **** **** **** **** **** **** **** **** +16165 Swordsage_EarthstrikeQuake **** **** **** **** **** **** **** **** +16166 Swordsage_ElderMountainHammer **** **** **** **** **** **** **** **** +16167 Swordsage_GiantsStance **** **** **** **** **** **** **** **** +16168 Swordsage_IronBones **** **** **** **** **** **** **** **** +16169 Swordsage_IrresistibleMountainStrike **** **** **** **** **** **** **** **** +16170 Swordsage_MountainAvalanche **** **** **** **** **** **** **** **** +16171 Swordsage_MountainHammer **** **** **** **** **** **** **** **** +16172 Swordsage_MountainTombstoneStrike **** **** **** **** **** **** **** **** +16173 Swordsage_OverwhelmingMountainStrike **** **** **** **** **** **** **** **** +16174 Swordsage_RootsOfTheMountain **** **** **** **** **** **** **** **** +16175 Swordsage_StoneBones **** **** **** **** **** **** **** **** +16176 Swordsage_StoneDragonsFury **** **** **** **** **** **** **** **** +16177 Swordsage_StoneVise **** **** **** **** **** **** **** **** +16178 Swordsage_StonefootStance **** **** **** **** **** **** **** **** +16179 Swordsage_StrengthOfStone **** **** **** **** **** **** **** **** +16180 Swordsage_BloodInTheWater **** **** **** **** **** **** **** **** +16181 Swordsage_ClawAtTheMoon **** **** **** **** **** **** **** **** +16182 Swordsage_DancingMongoose **** **** **** **** **** **** **** **** +16183 Swordsage_DeathFromAbove **** **** **** **** **** **** **** **** +16184 Swordsage_FeralDeathBlow **** **** **** **** **** **** **** **** +16185 Swordsage_FleshRipper **** **** **** **** **** **** **** **** +16186 Swordsage_FountainOfBlood **** **** **** **** **** **** **** **** +16187 Swordsage_GirallonWindmillFleshRip **** **** **** **** **** **** **** **** +16188 Swordsage_HamstringAttack **** **** **** **** **** **** **** **** +16189 Swordsage_HuntersSense **** **** **** **** **** **** **** **** +16190 Swordsage_LeapingDragonStance **** **** **** **** **** **** **** **** +16191 Swordsage_PouncingCharge **** **** **** **** **** **** **** **** +16192 Swordsage_PreyOnTheWeak **** **** **** **** **** **** **** **** +16193 Swordsage_RabidBearStrike **** **** **** **** **** **** **** **** +16194 Swordsage_RabidWolfStrike **** **** **** **** **** **** **** **** +16195 Swordsage_RagingMongoose **** **** **** **** **** **** **** **** +16196 Swordsage_SoaringRaptorStrike **** **** **** **** **** **** **** **** +16197 Swordsage_SuddenLeap **** **** **** **** **** **** **** **** +16198 Swordsage_SwoopingDragonStrike **** **** **** **** **** **** **** **** +16199 Swordsage_WolfClimbsTheMountain **** **** **** **** **** **** **** **** +16200 Swordsage_WolfFangStrike **** **** **** **** **** **** **** **** +16201 Swordsage_WolfPackTactics **** **** **** **** **** **** **** **** +16202 Swordsage_WolverineStance **** **** **** **** **** **** **** **** +16203 Swordsage_BattleLeadersCharge **** **** **** **** **** **** **** **** +16204 Swordsage_BolsteringVoice **** **** **** **** **** **** **** **** +16205 Swordsage_ClarionCall **** **** **** **** **** **** **** **** +16206 Swordsage_CoveringStrike **** **** **** **** **** **** **** **** +16207 Swordsage_DouseTheFlames **** **** **** **** **** **** **** **** +16208 Swordsage_FlankingManeuver **** **** **** **** **** **** **** **** +16209 Swordsage_LeadingTheAttack **** **** **** **** **** **** **** **** +16210 Swordsage_LeadingTheCharge **** **** **** **** **** **** **** **** +16211 Swordsage_LionsRoar **** **** **** **** **** **** **** **** +16212 Swordsage_OrderForgedFromChaos **** **** **** **** **** **** **** **** +16213 Swordsage_PressTheAdvantage **** **** **** **** **** **** **** **** +16214 Swordsage_SwarmTactics **** **** **** **** **** **** **** **** +16215 Swordsage_SwarmingAssault **** **** **** **** **** **** **** **** +16216 Swordsage_TacticalStrike **** **** **** **** **** **** **** **** +16217 Swordsage_TacticsOfTheWolf **** **** **** **** **** **** **** **** +16218 Swordsage_WarLeadersCharge **** **** **** **** **** **** **** **** +16219 Swordsage_WarMastersCharge **** **** **** **** **** **** **** **** +16220 Swordsage_WhiteRavenHammer **** **** **** **** **** **** **** **** +16221 Swordsage_WhiteRavenStrike **** **** **** **** **** **** **** **** +16222 Swordsage_WhiteRavenTactics **** **** **** **** **** **** **** **** +16223 Warblade_BlisteringFlourish **** **** **** **** **** **** **** **** +16224 Warblade_BurningBlade **** **** **** **** **** **** **** **** +16225 Warblade_BurningBrand **** **** **** **** **** **** **** **** +16226 Warblade_DeathMark **** **** **** **** **** **** **** **** +16227 Warblade_DesertTempest **** **** **** **** **** **** **** **** +16228 Warblade_DistractingEmber **** **** **** **** **** **** **** **** +16229 Warblade_DragonsFlame **** **** **** **** **** **** **** **** +16230 Warblade_FanTheFlames **** **** **** **** **** **** **** **** +16231 Warblade_FieryAssault **** **** **** **** **** **** **** **** +16232 Warblade_FireRiposte **** **** **** **** **** **** **** **** +16233 Warblade_Firesnake **** **** **** **** **** **** **** **** +16234 Warblade_FlamesBlessing **** **** **** **** **** **** **** **** +16235 Warblade_FlashingSun **** **** **** **** **** **** **** **** +16236 Warblade_HatchlingsFlame **** **** **** **** **** **** **** **** +16237 Warblade_HolocaustCloak **** **** **** **** **** **** **** **** +16238 Warblade_InfernoBlade **** **** **** **** **** **** **** **** +16239 Warblade_InfernoBlast **** **** **** **** **** **** **** **** +16240 Warblade_LeapingFlame **** **** **** **** **** **** **** **** +16241 Warblade_LingeringInferno **** **** **** **** **** **** **** **** +16242 Warblade_RingOfFire **** **** **** **** **** **** **** **** +16243 Warblade_RisingPhoenix **** **** **** **** **** **** **** **** +16244 Warblade_SalamanderCharge **** **** **** **** **** **** **** **** +16245 Warblade_SearingBlade **** **** **** **** **** **** **** **** +16246 Warblade_SearingCharge **** **** **** **** **** **** **** **** +16247 Warblade_WindStride **** **** **** **** **** **** **** **** +16248 Warblade_WyrmsFlame **** **** **** **** **** **** **** **** +16249 Warblade_ZephyrDance **** **** **** **** **** **** **** **** +16250 Warblade_AuraOfChaos **** **** **** **** **** **** **** **** +16251 Warblade_AuraOfPerfectOrder **** **** **** **** **** **** **** **** +16252 Warblade_AuraOfTriumph **** **** **** **** **** **** **** **** +16253 Warblade_AuraOfTyranny **** **** **** **** **** **** **** **** +16254 Warblade_CastigatingStrike **** **** **** **** **** **** **** **** +16255 Warblade_CrusadersStrike **** **** **** **** **** **** **** **** +16256 Warblade_DauntingStrike **** **** **** **** **** **** **** **** +16257 Warblade_DefensiveRebuke **** **** **** **** **** **** **** **** +16258 Warblade_DivineSurge **** **** **** **** **** **** **** **** +16259 Warblade_DivineSurgeGreater **** **** **** **** **** **** **** **** +16260 Warblade_DivineSurgeGreaterSub1 **** **** **** **** **** **** **** **** +16261 Warblade_DivineSurgeGreaterSub2 **** **** **** **** **** **** **** **** +16262 Warblade_DivineSurgeGreaterSub3 **** **** **** **** **** **** **** **** +16263 Warblade_DoomCharge **** **** **** **** **** **** **** **** +16264 Warblade_EntanglingBlade **** **** **** **** **** **** **** **** +16265 Warblade_Foehammer **** **** **** **** **** **** **** **** +16266 Warblade_ImmortalFortitude **** **** **** **** **** **** **** **** +16267 Warblade_IronGuardsGlare **** **** **** **** **** **** **** **** +16268 Warblade_LawBearer **** **** **** **** **** **** **** **** +16269 Warblade_MartialSpirit **** **** **** **** **** **** **** **** +16270 Warblade_RadiantCharge **** **** **** **** **** **** **** **** +16271 Warblade_RallyingStrike **** **** **** **** **** **** **** **** +16272 Warblade_RevitalizingStrike **** **** **** **** **** **** **** **** +16273 Warblade_ShieldBlock **** **** **** **** **** **** **** **** +16274 Warblade_ShieldCounter **** **** **** **** **** **** **** **** +16275 Warblade_StrikeOfRighteousVitality **** **** **** **** **** **** **** **** +16276 Warblade_ThicketOfBlades **** **** **** **** **** **** **** **** +16277 Warblade_TideOfChaos **** **** **** **** **** **** **** **** +16278 Warblade_VanguardStrike **** **** **** **** **** **** **** **** +16279 Warblade_ActionBeforeThought **** **** **** **** **** **** **** **** +16280 Warblade_AvalancheOfBlades **** **** **** **** **** **** **** **** +16281 Warblade_BoundingAssault **** **** **** **** **** **** **** **** +16282 Warblade_DiamondDefense **** **** **** **** **** **** **** **** +16283 Warblade_DiamondNightmareBlade **** **** **** **** **** **** **** **** +16284 Warblade_DisruptingBlow **** **** **** **** **** **** **** **** +16285 Warblade_EmeraldRazor **** **** **** **** **** **** **** **** +16286 Warblade_HearingTheAir **** **** **** **** **** **** **** **** +16287 Warblade_InsightfulStrike **** **** **** **** **** **** **** **** +16288 Warblade_InsightfulStrikeGreater **** **** **** **** **** **** **** **** +16289 Warblade_MindOverBody **** **** **** **** **** **** **** **** +16290 Warblade_MindStrike **** **** **** **** **** **** **** **** +16291 Warblade_MomentOfAlacrity **** **** **** **** **** **** **** **** +16292 Warblade_MomentOfPerfectMind **** **** **** **** **** **** **** **** +16293 Warblade_PearlOfBlackDoubt **** **** **** **** **** **** **** **** +16294 Warblade_QuicksilverMotion **** **** **** **** **** **** **** **** +16295 Warblade_RapidCounter **** **** **** **** **** **** **** **** +16296 Warblade_RubyNightmareBlade **** **** **** **** **** **** **** **** +16297 Warblade_SapphireNightmareBlade **** **** **** **** **** **** **** **** +16298 Warblade_StanceOfAlacrity **** **** **** **** **** **** **** **** +16299 ####END_OF_TOB_SPELLBOOK_RESERVE **** **** **** **** **** **** **** **** +16300 Templates_16300-16999 **** **** **** **** **** **** **** **** +16301 Celestial_Smite_Evil **** **** **** **** **** **** **** **** +16302 Fiendish_Smite_Good **** **** **** **** **** **** **** **** +16303 Half_Celestial_Smite_Evil **** **** **** **** **** **** **** **** +16304 Half_Celestial_Protection_from_Evil **** **** **** **** **** **** **** **** +16305 Half_Celestial_Bless **** **** **** **** **** **** **** **** +16306 Half_Celestial_Aid **** **** **** **** **** **** **** **** +16307 Half_Celestial_Detect_Evil **** **** **** **** **** **** **** **** +16308 Half_Celestial_Cure_Serious_Wounds **** **** **** **** **** **** **** **** +16309 Half_Celestial_Neutralize_Poison **** **** **** **** **** **** **** **** +16310 Half_Celestial_HolySmite **** **** **** **** **** **** **** **** +16311 Half_Celestial_Remove_Disease **** **** **** **** **** **** **** **** +16312 Half_Celestial_DispelEvil **** **** **** **** **** **** **** **** +16313 Half_Celestial_Holy_Word **** **** **** **** **** **** **** **** +16314 Half_Celestial_HolyAura **** **** **** **** **** **** **** **** +16315 Half_Celestial_Hallow **** **** **** **** **** **** **** **** +16316 Half_Celestial_Mass_Charm **** **** **** **** **** **** **** **** +16317 Half_Celestial_Summon_Creature_IX **** **** **** **** **** **** **** **** +16318 Half_Celestial_Summon_Creature_IX_Air **** **** **** **** **** **** **** **** +16319 Half_Celestial_Summon_Creature_IX_Earth **** **** **** **** **** **** **** **** +16320 Half_Celestial_Summon_Creature_IX_Fire **** **** **** **** **** **** **** **** +16321 Half_Celestial_Summon_Creature_IX_Water **** **** **** **** **** **** **** **** +16322 Half_Celestial_Resurrection **** **** **** **** **** **** **** **** +16323 Half_Celestial_Daylight **** **** **** **** **** **** **** **** +16324 Half_Fiendish_Smite_Good **** **** **** **** **** **** **** **** +16325 Half_Fiendish_Darkness **** **** **** **** **** **** **** **** +16326 Half_Fiendish_Desecrate **** **** **** **** **** **** **** **** +16327 Half_Fiendish_Unholy_Blight **** **** **** **** **** **** **** **** +16328 Half_Fiendish_Poison **** **** **** **** **** **** **** **** +16329 Half_Fiendish_Contagion **** **** **** **** **** **** **** **** +16330 Half_Fiendish_Blasphemy **** **** **** **** **** **** **** **** +16331 Half_Fiendish_Unholy_Aura **** **** **** **** **** **** **** **** +16332 Half_Fiendish_Unhallow **** **** **** **** **** **** **** **** +16333 Half_Fiendish_Horrid_Wilting **** **** **** **** **** **** **** **** +16334 Half_Fiendish_Summon_Creature_IX **** **** **** **** **** **** **** **** +16335 Half_Fiendish_Summon_Creature_IX_Air **** **** **** **** **** **** **** **** +16336 Half_Fiendish_Summon_Creature_IX_Earth **** **** **** **** **** **** **** **** +16337 Half_Fiendish_Summon_Creature_IX_Fire **** **** **** **** **** **** **** **** +16338 Half_Fiendish_Summon_Creature_IX_Water **** **** **** **** **** **** **** **** +16339 Half_Fiendish_Destruction **** **** **** **** **** **** **** **** +16340 Lich_Fear_Aura **** **** **** **** **** **** **** **** +16341 Lich_Paralyzing_Touch **** **** **** **** **** **** **** **** +16342 Lich_Appearance **** **** **** **** **** **** **** **** +16343 Demilich_Alter_Self **** **** **** **** **** **** **** **** +16344 Demilich_Alter_Self_Learn **** **** **** **** **** **** **** **** +16345 Demilich_Alter_Self_Options **** **** **** **** **** **** **** **** +16346 Demilich_Alter_Self_QS1 **** **** **** **** **** **** **** **** +16347 Demilich_Alter_Self_QS2 **** **** **** **** **** **** **** **** +16348 Demilich_Alter_Self_QS3 **** **** **** **** **** **** **** **** +16349 Demilich_Astral_Projection **** **** **** **** **** **** **** **** +16350 Demilich_Create_Greater_Undead **** **** **** **** **** **** **** **** +16351 Demilich_Create_Undead **** **** **** **** **** **** **** **** +16352 Demilich_Death_Knell **** **** **** **** **** **** **** **** +16353 Demilich_Enervation **** **** **** **** **** **** **** **** +16354 Demilich_Greater_Dispel_Magic **** **** **** **** **** **** **** **** +16355 Demilich_Harm **** **** **** **** **** **** **** **** +16356 Demilich_Summon_Creature_I **** **** **** **** **** **** **** **** +16357 Demilich_Summon_Creature_II **** **** **** **** **** **** **** **** +16358 Demilich_Summon_Creature_III **** **** **** **** **** **** **** **** +16359 Demilich_Summon_Creature_IV **** **** **** **** **** **** **** **** +16360 Demilich_Summon_Creature_V **** **** **** **** **** **** **** **** +16361 Demilich_Summon_Creature_VI **** **** **** **** **** **** **** **** +16362 Demilich_Summon_Creature_VII **** **** **** **** **** **** **** **** +16363 Demilich_Summon_Creature_VII_Air **** **** **** **** **** **** **** **** +16364 Demilich_Summon_Creature_VII_Earth **** **** **** **** **** **** **** **** +16365 Demilich_Summon_Creature_VII_Fire **** **** **** **** **** **** **** **** +16366 Demilich_Summon_Creature_VII_Water **** **** **** **** **** **** **** **** +16367 Demilich_Summon_Creature_VIII **** **** **** **** **** **** **** **** +16368 Demilich_Summon_Creature_VIII_Air **** **** **** **** **** **** **** **** +16369 Demilich_Summon_Creature_VIII_Earth **** **** **** **** **** **** **** **** +16370 Demilich_Summon_Creature_VIII_Fire **** **** **** **** **** **** **** **** +16371 Demilich_Summon_Creature_VIII_Water **** **** **** **** **** **** **** **** +16372 Demilich_Summon_Creature_IX **** **** **** **** **** **** **** **** +16373 Demilich_Summon_Creature_IX_Air **** **** **** **** **** **** **** **** +16374 Demilich_Summon_Creature_IX_Earth **** **** **** **** **** **** **** **** +16375 Demilich_Summon_Creature_IX_Fire **** **** **** **** **** **** **** **** +16376 Demilich_Summon_Creature_IX_Water **** **** **** **** **** **** **** **** +16377 Demilich_Telekinesis **** **** **** **** **** **** **** **** +16378 Demilich_Weird **** **** **** **** **** **** **** **** +16379 Demilich_Greater_Planar_Ally **** **** **** **** **** **** **** **** +16380 HalfDragon_Breath_Weapon **** **** **** **** **** **** **** **** +16381 Archlich_Turn_Undead **** **** **** **** **** **** **** **** +16382 Saint_Bless **** **** **** **** **** **** **** **** +16383 Saint_Guidance_Placeholder **** **** **** **** **** **** **** **** +16384 Saint_Resistance **** **** **** **** **** **** **** **** +16385 Saint_Virtue **** **** **** **** **** **** **** **** +16386 Saint_Protective_Aura **** **** **** **** **** **** **** **** +16387 **** **** **** **** **** **** **** **** **** +16388 **** **** **** **** **** **** **** **** **** +16389 **WeaponsOfLegacy** **** **** **** **** **** **** **** **** +16390 BBB_Darkvision **** **** **** **** **** **** **** **** +16391 BBB_Longstrider **** **** **** **** **** **** **** **** +16392 BBB_Lesser_Restoration **** **** **** **** **** **** **** **** +16393 BBB_Teleport_SelfOnly **** **** **** **** **** **** **** **** +16394 BBB_Protection_from_Evil **** **** **** **** **** **** **** **** +16395 BBB_Drowseeker **** **** **** **** **** **** **** **** +16396 BBB_ShockingShot **** **** **** **** **** **** **** **** +16397 BBB_PierceTheBlackHeart **** **** **** **** **** **** **** **** +16398 Steadfast_vigor **** **** **** **** **** **** **** **** +16399 Steadfast_slow **** **** **** **** **** **** **** **** +16400 Flay_SnakeSting **** **** **** **** **** **** **** **** +16401 Flay_WhipWrap **** **** **** **** **** **** **** **** +16402 CrimsonRuination_FrozenFate **** **** **** **** **** **** **** **** +16403 Devious_DetectThoughts **** **** **** **** **** **** **** **** +16404 SimpleBow_TrueSeeing **** **** **** **** **** **** **** **** +16405 SimpleBow_Prescience **** **** **** **** **** **** **** **** +16406 SimpleBow_Focus **** **** **** **** **** **** **** **** +16407 Aradros_Extend **** **** **** **** **** **** **** **** +16408 Aradros_Survive_Master **** **** **** **** **** **** **** **** +16409 Aradros_Survive_Acid **** **** **** **** **** **** **** **** +16410 Aradros_Survive_Cold **** **** **** **** **** **** **** **** +16411 Aradros_Survive_Elec **** **** **** **** **** **** **** **** +16412 Aradros_Survive_Fire **** **** **** **** **** **** **** **** +16413 Aradros_Survive_Sonic **** **** **** **** **** **** **** **** +16414 Guurgal_Force **** **** **** **** **** **** **** **** +16415 Guurgal_Rage **** **** **** **** **** **** **** **** +16416 DivSpark_Fear **** **** **** **** **** **** **** **** +16417 DivSpark_Light **** **** **** **** **** **** **** **** +16418 Wargirds_Haste **** **** **** **** **** **** **** **** +16419 Wargirds_Stoneskin **** **** **** **** **** **** **** **** +16420 DesertWind_FierySlash **** **** **** **** **** **** **** **** +16421 DesertWind_HowlingWind **** **** **** **** **** **** **** **** +16422 DesertWind_FanFlames **** **** **** **** **** **** **** **** +16423 DesertWind_DustDesert **** **** **** **** **** **** **** **** +16424 Mindsplinter_VirtueDenied **** **** **** **** **** **** **** **** +16425 Mindsplinter_KissOfDeath **** **** **** **** **** **** **** **** +16426 Mindsplinter_BattleShriek **** **** **** **** **** **** **** **** +16427 Mindsplinter_RuinousHowl **** **** **** **** **** **** **** **** +16428 NotchedSpear_ParliamentOfFishes **** **** **** **** **** **** **** **** +16429 NotchedSpear_ConcealmentKraken **** **** **** **** **** **** **** **** +16430 NotchedSpear_ScionSea **** **** **** **** **** **** **** **** +16431 NotchedSpear_CommandSeaChildren **** **** **** **** **** **** **** **** +16432 Ur_SwiftStride **** **** **** **** **** **** **** **** +16433 Ur_HealingTotem **** **** **** **** **** **** **** **** +16434 Ur_SavageTransformation **** **** **** **** **** **** **** **** +16435 FlamecastersBolt_MarkTarget **** **** **** **** **** **** **** **** +16436 FlamecastersBolt_Morale **** **** **** **** **** **** **** **** +16437 FlamecastersBolt_Fireball **** **** **** **** **** **** **** **** +16438 StalkersBow_StalkersInsight **** **** **** **** **** **** **** **** +16439 StalkersBow_Ethereal **** **** **** **** **** **** **** **** +16440 Exordius_Guidance **** **** **** **** **** **** **** **** +16441 Exordius_Cure **** **** **** **** **** **** **** **** +16442 Exordius_Dismissal **** **** **** **** **** **** **** **** +16443 Caladbolg_Imprison **** **** **** **** **** **** **** **** +16444 HammerWitches_Detect **** **** **** **** **** **** **** **** +16445 HammerWitches_Spellbreaker **** **** **** **** **** **** **** **** +16446 HammerWitches_AMF **** **** **** **** **** **** **** **** +16447 HammerWitches_Dispel **** **** **** **** **** **** **** **** +16448 HammerWitches_Mantle **** **** **** **** **** **** **** **** +16449 SlingOfTheDireWind_StunningStone **** **** **** **** **** **** **** **** +16450 SlingOfTheDireWind_GustOfWind **** **** **** **** **** **** **** **** +16451 SlingOfTheDireWind_WindWall **** **** **** **** **** **** **** **** +16452 Treebrother_Shillelagh **** **** **** **** **** **** **** **** +16453 Treebrother_Charm_Plant **** **** **** **** **** **** **** **** +16454 Treebrother_Entangle **** **** **** **** **** **** **** **** +16455 Treebrother_Owls_Insight **** **** **** **** **** **** **** **** +16456 Treebrother_Changestaff **** **** **** **** **** **** **** **** +16457 FullMoonsTrick_Rage **** **** **** **** **** **** **** **** +16458 FullMoonsTrick_Invis **** **** **** **** **** **** **** **** +16459 FiendkillersFlail_Darkvis **** **** **** **** **** **** **** **** +16460 FiendkillersFlail_Detect **** **** **** **** **** **** **** **** +16461 ScalesBalance_Detect **** **** **** **** **** **** **** **** +16462 ScalesBalance_Cure **** **** **** **** **** **** **** **** +16463 ScalesBalance_Knell **** **** **** **** **** **** **** **** +16464 ScalesBalance_Enerv **** **** **** **** **** **** **** **** +16465 ScalesBalance_Heal **** **** **** **** **** **** **** **** +16466 ScalesBalance_Finger **** **** **** **** **** **** **** **** +16467 ShishiO_Charm **** **** **** **** **** **** **** **** +16468 ShishiO_Summon **** **** **** **** **** **** **** **** +16469 ShishiO_Poly **** **** **** **** **** **** **** **** +16470 ShishiO_Shout **** **** **** **** **** **** **** **** +16471 Dymondheart_ShedBolts **** **** **** **** **** **** **** **** +16472 Dymondheart_Deflect **** **** **** **** **** **** **** **** +16473 Dymondheart_Daylight **** **** **** **** **** **** **** **** +16474 Dymondheart_Cure **** **** **** **** **** **** **** **** +16475 Dymondheart_Banish **** **** **** **** **** **** **** **** +16476 Sunsword_Daylight **** **** **** **** **** **** **** **** +16477 Sunsword_Death_Ward **** **** **** **** **** **** **** **** +16478 Sunsword_Banish **** **** **** **** **** **** **** **** +16479 Sunsword_Undeath_to_Death **** **** **** **** **** **** **** **** +16480 Blackrazor_Detect **** **** **** **** **** **** **** **** +16481 Blackrazor_Knell **** **** **** **** **** **** **** **** +16482 Blackrazor_Haste **** **** **** **** **** **** **** **** +16483 Ramethene_Detect **** **** **** **** **** **** **** **** +16484 Ramethene_Smite **** **** **** **** **** **** **** **** +16485 Ramethene_Resist_Elements **** **** **** **** **** **** **** **** +16486 Ramethene_Cloudkill **** **** **** **** **** **** **** **** +16487 Ramethene_SuddenMaximize **** **** **** **** **** **** **** **** +16488 Ramethene_Horrid_Wilting **** **** **** **** **** **** **** **** +16489 Wyrmbane_Cause_Fear **** **** **** **** **** **** **** **** +16490 Wyrmbane_Lightning_Bolt **** **** **** **** **** **** **** **** +16491 Wyrmbane_Sudden_Emp **** **** **** **** **** **** **** **** +16492 Wyrmbane_Breath_Lightning **** **** **** **** **** **** **** **** +16493 Whelm_Detect_Giant **** **** **** **** **** **** **** **** +16494 Whelm_Locate_Object **** **** **** **** **** **** **** **** +16495 Whelm_Detect_Goblin **** **** **** **** **** **** **** **** +16496 Ravenkind_Dancing_Lights **** **** **** **** **** **** **** **** +16497 Ravenkind_Light **** **** **** **** **** **** **** **** +16498 Ravenkind_Flare **** **** **** **** **** **** **** **** +16499 Ravenkind_Detect_Undead **** **** **** **** **** **** **** **** +16500 Ravenkind_Halt_Undead **** **** **** **** **** **** **** **** +16501 Ravenkind_Cure_Light_Wounds **** **** **** **** **** **** **** **** +16502 Ravenkind_Daylight **** **** **** **** **** **** **** **** +16503 Ravenkind_Death_Ward **** **** **** **** **** **** **** **** +16504 Ravenkind_Break_Enchantment **** **** **** **** **** **** **** **** +16505 Ravenkind_Mass_Heal **** **** **** **** **** **** **** **** +16506 LastCitadel_LeadingTheAttack **** **** **** **** **** **** **** **** +16507 LastCitadel_Prayer **** **** **** **** **** **** **** **** +16508 LastCitadel_Remove_Fear **** **** **** **** **** **** **** **** +16509 LastCitadel_Cure_Critical_Wounds **** **** **** **** **** **** **** **** +16510 LastCitadel_Blade_Barrier **** **** **** **** **** **** **** **** +16511 LastCitadel_Heal **** **** **** **** **** **** **** **** +16512 Unfettered_ChargingMinotaur **** **** **** **** **** **** **** **** +16513 Unfettered_ENLARGE_PERSON **** **** **** **** **** **** **** **** +16514 Unfettered_Etherealness **** **** **** **** **** **** **** **** +16515 Unfettered_Stoneskin **** **** **** **** **** **** **** **** +16516 Unfettered_Mordenkainens_Sword **** **** **** **** **** **** **** **** +16517 Hillcrusher_Earthen_Might **** **** **** **** **** **** **** **** +16518 Hillcrusher_Soften_Earth **** **** **** **** **** **** **** **** +16519 Hillcrusher_Fangs_of_Stone **** **** **** **** **** **** **** **** +16520 Hillcrusher_Raise_the_Earth **** **** **** **** **** **** **** **** +16521 Hillcrusher_Shake_the_Earth **** **** **** **** **** **** **** **** +16522 DesertWindToB_BurningBlade **** **** **** **** **** **** **** **** +16523 DesertWindToB_FanTheFlames **** **** **** **** **** **** **** **** +16524 DesertWindToB_WyrmsFlame **** **** **** **** **** **** **** **** +16525 Faithful_FaithfulStrike **** **** **** **** **** **** **** **** +16526 Faithful_Detect_Evil **** **** **** **** **** **** **** **** +16527 Faithful_Lesser_Restoration **** **** **** **** **** **** **** **** +16528 Faithful_Restoration **** **** **** **** **** **** **** **** +16529 Faithful_Resiliency **** **** **** **** **** **** **** **** +16530 Faithful_ImmortalFortitude **** **** **** **** **** **** **** **** +16531 SupernalClarity_SapphireNightmareBlade **** **** **** **** **** **** **** **** +16532 SupernalClarity_PsychicPoise **** **** **** **** **** **** **** **** +16533 SupernalClarity_Haste **** **** **** **** **** **** **** **** +16534 SupernalClarity_Freeeeeedom **** **** **** **** **** **** **** **** +16535 SupernalClarity_Time_Stop **** **** **** **** **** **** **** **** +16536 Kamate_SteelWind **** **** **** **** **** **** **** **** +16537 Kamate_ShockingGrasp **** **** **** **** **** **** **** **** +16538 Kamate_Lightning_Bolt **** **** **** **** **** **** **** **** +16539 Kamate_Chain_Lightning **** **** **** **** **** **** **** **** +16540 Kamate_True_Strike **** **** **** **** **** **** **** **** +16541 Eventide_CometThrow **** **** **** **** **** **** **** **** +16542 Eventide_BafflingDefense **** **** **** **** **** **** **** **** +16543 Eventide_Improved_Invisibility **** **** **** **** **** **** **** **** +16544 Umbral_Invisibility **** **** **** **** **** **** **** **** +16545 Umbral_Shadowstep **** **** **** **** **** **** **** **** +16546 Umbral_SpeedWeapon **** **** **** **** **** **** **** **** +16547 TigerFang_FrenziedCharge **** **** **** **** **** **** **** **** +16548 TigerFang_BattleFever **** **** **** **** **** **** **** **** +16549 TigerFang_Haste **** **** **** **** **** **** **** **** +16550 Bullybasher_KnockSilly **** **** **** **** **** **** **** **** +16551 Bullybasher_StoneGathering **** **** **** **** **** **** **** **** +16552 Bullybasher_LightningPunch **** **** **** **** **** **** **** **** +16553 Bullybasher_GiantBearing **** **** **** **** **** **** **** **** +16554 Lorestealer_Read_Magic **** **** **** **** **** **** **** **** +16555 Lorestealer_DetectMagic **** **** **** **** **** **** **** **** +16556 Lorestealer_Axecasting **** **** **** **** **** **** **** **** +16557 Durindana_Daylight **** **** **** **** **** **** **** **** +16558 Durindana_Death_Ward **** **** **** **** **** **** **** **** +16559 Durindana_Hallow **** **** **** **** **** **** **** **** +16560 Durindana_Dazzle **** **** **** **** **** **** **** **** +16561 Thaas_Detect_Demon **** **** **** **** **** **** **** **** +16562 Thaas_ObstructSummoning **** **** **** **** **** **** **** **** +16563 Thaas_Banishment **** **** **** **** **** **** **** **** +16564 Thaas_Teleport **** **** **** **** **** **** **** **** +16565 Quickspur_Entropic_Shield **** **** **** **** **** **** **** **** +16566 Quickspur_Resist_Elements **** **** **** **** **** **** **** **** +16567 Quickspur_PhantomSteed **** **** **** **** **** **** **** **** +16568 Quickspur_Blur **** **** **** **** **** **** **** **** +16569 Quickspur_Stoneskin **** **** **** **** **** **** **** **** +16570 BES_FIRE_OF_THE_HEART **** **** **** **** **** **** **** **** +16571 BES_ENTHRALLING_LIGHT **** **** **** **** **** **** **** **** +16572 BES_COLOR_SPRAY **** **** **** **** **** **** **** **** +16573 BES_BLINDING_FLASH **** **** **** **** **** **** **** **** +16574 BES_SHOOTING_STARS **** **** **** **** **** **** **** **** +16575 BES_GLITTERING_MOTES **** **** **** **** **** **** **** **** +16576 BES_TWINKLE **** **** **** **** **** **** **** **** +16577 BES_SILVER_STARLIGHT **** **** **** **** **** **** **** **** +16578 BES_STARLIGHT_DISPELLING **** **** **** **** **** **** **** **** +16579 BES_TALES_IN_THE_SKY **** **** **** **** **** **** **** **** +16580 BES_CALL_DOWN_A_STAR **** **** **** **** **** **** **** **** +16581 **** **** **** **** **** **** **** **** **** +16582 **** **** **** **** **** **** **** **** **** +16583 **** **** **** **** **** **** **** **** **** +16584 **** **** **** **** **** **** **** **** **** +16585 **** **** **** **** **** **** **** **** **** +16586 **** **** **** **** **** **** **** **** **** +16587 **** **** **** **** **** **** **** **** **** +16588 **** **** **** **** **** **** **** **** **** +16589 **** **** **** **** **** **** **** **** **** +16590 Templates_16300-16999 **** **** **** **** **** **** **** **** +16591 **** **** **** **** **** **** **** **** **** +16592 **** **** **** **** **** **** **** **** **** +16593 **** **** **** **** **** **** **** **** **** +16594 **** **** **** **** **** **** **** **** **** +16595 **** **** **** **** **** **** **** **** **** +16596 **** **** **** **** **** **** **** **** **** +16597 **** **** **** **** **** **** **** **** **** +16598 **** **** **** **** **** **** **** **** **** +16599 **** **** **** **** **** **** **** **** **** +16600 Templates_16300-16999 **** **** **** **** **** **** **** **** +16601 **** **** **** **** **** **** **** **** **** +16602 **** **** **** **** **** **** **** **** **** +16603 **** **** **** **** **** **** **** **** **** +16604 **** **** **** **** **** **** **** **** **** +16605 **** **** **** **** **** **** **** **** **** +16606 **** **** **** **** **** **** **** **** **** +16607 **** **** **** **** **** **** **** **** **** +16608 **** **** **** **** **** **** **** **** **** +16609 **** **** **** **** **** **** **** **** **** +16610 Templates_16300-16999 **** **** **** **** **** **** **** **** +16611 **** **** **** **** **** **** **** **** **** +16612 **** **** **** **** **** **** **** **** **** +16613 **** **** **** **** **** **** **** **** **** +16614 **** **** **** **** **** **** **** **** **** +16615 **** **** **** **** **** **** **** **** **** +16616 **** **** **** **** **** **** **** **** **** +16617 **** **** **** **** **** **** **** **** **** +16618 **** **** **** **** **** **** **** **** **** +16619 **** **** **** **** **** **** **** **** **** +16620 Templates_16300-16999 **** **** **** **** **** **** **** **** +16621 **** **** **** **** **** **** **** **** **** +16622 **** **** **** **** **** **** **** **** **** +16623 **** **** **** **** **** **** **** **** **** +16624 **** **** **** **** **** **** **** **** **** +16625 **** **** **** **** **** **** **** **** **** +16626 **** **** **** **** **** **** **** **** **** +16627 **** **** **** **** **** **** **** **** **** +16628 **** **** **** **** **** **** **** **** **** +16629 **** **** **** **** **** **** **** **** **** +16630 Templates_16300-16999 **** **** **** **** **** **** **** **** +16631 **** **** **** **** **** **** **** **** **** +16632 **** **** **** **** **** **** **** **** **** +16633 **** **** **** **** **** **** **** **** **** +16634 **** **** **** **** **** **** **** **** **** +16635 **** **** **** **** **** **** **** **** **** +16636 **** **** **** **** **** **** **** **** **** +16637 **** **** **** **** **** **** **** **** **** +16638 **** **** **** **** **** **** **** **** **** +16639 **** **** **** **** **** **** **** **** **** +16640 Templates_16300-16999 **** **** **** **** **** **** **** **** +16641 **** **** **** **** **** **** **** **** **** +16642 **** **** **** **** **** **** **** **** **** +16643 **** **** **** **** **** **** **** **** **** +16644 **** **** **** **** **** **** **** **** **** +16645 **** **** **** **** **** **** **** **** **** +16646 **** **** **** **** **** **** **** **** **** +16647 **** **** **** **** **** **** **** **** **** +16648 **** **** **** **** **** **** **** **** **** +16649 **** **** **** **** **** **** **** **** **** +16650 Templates_16300-16999 **** **** **** **** **** **** **** **** +16651 **** **** **** **** **** **** **** **** **** +16652 **** **** **** **** **** **** **** **** **** +16653 **** **** **** **** **** **** **** **** **** +16654 **** **** **** **** **** **** **** **** **** +16655 **** **** **** **** **** **** **** **** **** +16656 **** **** **** **** **** **** **** **** **** +16657 **** **** **** **** **** **** **** **** **** +16658 **** **** **** **** **** **** **** **** **** +16659 **** **** **** **** **** **** **** **** **** +16660 Templates_16300-16999 **** **** **** **** **** **** **** **** +16661 **** **** **** **** **** **** **** **** **** +16662 **** **** **** **** **** **** **** **** **** +16663 **** **** **** **** **** **** **** **** **** +16664 **** **** **** **** **** **** **** **** **** +16665 **** **** **** **** **** **** **** **** **** +16666 **** **** **** **** **** **** **** **** **** +16667 **** **** **** **** **** **** **** **** **** +16668 **** **** **** **** **** **** **** **** **** +16669 **** **** **** **** **** **** **** **** **** +16670 Templates_16300-16999 **** **** **** **** **** **** **** **** +16671 **** **** **** **** **** **** **** **** **** +16672 **** **** **** **** **** **** **** **** **** +16673 **** **** **** **** **** **** **** **** **** +16674 **** **** **** **** **** **** **** **** **** +16675 **** **** **** **** **** **** **** **** **** +16676 **** **** **** **** **** **** **** **** **** +16677 **** **** **** **** **** **** **** **** **** +16678 **** **** **** **** **** **** **** **** **** +16679 **** **** **** **** **** **** **** **** **** +16680 Templates_16300-16999 **** **** **** **** **** **** **** **** +16681 **** **** **** **** **** **** **** **** **** +16682 **** **** **** **** **** **** **** **** **** +16683 **** **** **** **** **** **** **** **** **** +16684 **** **** **** **** **** **** **** **** **** +16685 **** **** **** **** **** **** **** **** **** +16686 **** **** **** **** **** **** **** **** **** +16687 **** **** **** **** **** **** **** **** **** +16688 **** **** **** **** **** **** **** **** **** +16689 **** **** **** **** **** **** **** **** **** +16690 Templates_16300-16999 **** **** **** **** **** **** **** **** +16691 **** **** **** **** **** **** **** **** **** +16692 **** **** **** **** **** **** **** **** **** +16693 **** **** **** **** **** **** **** **** **** +16694 **** **** **** **** **** **** **** **** **** +16695 **** **** **** **** **** **** **** **** **** +16696 **** **** **** **** **** **** **** **** **** +16697 **** **** **** **** **** **** **** **** **** +16698 **** **** **** **** **** **** **** **** **** +16699 **** **** **** **** **** **** **** **** **** +16700 Templates_16300-16999 **** **** **** **** **** **** **** **** +16701 **** **** **** **** **** **** **** **** **** +16702 **** **** **** **** **** **** **** **** **** +16703 **** **** **** **** **** **** **** **** **** +16704 **** **** **** **** **** **** **** **** **** +16705 **** **** **** **** **** **** **** **** **** +16706 **** **** **** **** **** **** **** **** **** +16707 **** **** **** **** **** **** **** **** **** +16708 **** **** **** **** **** **** **** **** **** +16709 **** **** **** **** **** **** **** **** **** +16710 Templates_16300-16999 **** **** **** **** **** **** **** **** +16711 **** **** **** **** **** **** **** **** **** +16712 **** **** **** **** **** **** **** **** **** +16713 **** **** **** **** **** **** **** **** **** +16714 **** **** **** **** **** **** **** **** **** +16715 **** **** **** **** **** **** **** **** **** +16716 **** **** **** **** **** **** **** **** **** +16717 **** **** **** **** **** **** **** **** **** +16718 **** **** **** **** **** **** **** **** **** +16719 **** **** **** **** **** **** **** **** **** +16720 Templates_16300-16999 **** **** **** **** **** **** **** **** +16721 **** **** **** **** **** **** **** **** **** +16722 **** **** **** **** **** **** **** **** **** +16723 **** **** **** **** **** **** **** **** **** +16724 **** **** **** **** **** **** **** **** **** +16725 **** **** **** **** **** **** **** **** **** +16726 **** **** **** **** **** **** **** **** **** +16727 **** **** **** **** **** **** **** **** **** +16728 **** **** **** **** **** **** **** **** **** +16729 **** **** **** **** **** **** **** **** **** +16730 Templates_16300-16999 **** **** **** **** **** **** **** **** +16731 **** **** **** **** **** **** **** **** **** +16732 **** **** **** **** **** **** **** **** **** +16733 **** **** **** **** **** **** **** **** **** +16734 **** **** **** **** **** **** **** **** **** +16735 **** **** **** **** **** **** **** **** **** +16736 **** **** **** **** **** **** **** **** **** +16737 **** **** **** **** **** **** **** **** **** +16738 **** **** **** **** **** **** **** **** **** +16739 **** **** **** **** **** **** **** **** **** +16740 Templates_16300-16999 **** **** **** **** **** **** **** **** +16741 **** **** **** **** **** **** **** **** **** +16742 **** **** **** **** **** **** **** **** **** +16743 **** **** **** **** **** **** **** **** **** +16744 **** **** **** **** **** **** **** **** **** +16745 **** **** **** **** **** **** **** **** **** +16746 **** **** **** **** **** **** **** **** **** +16747 **** **** **** **** **** **** **** **** **** +16748 **** **** **** **** **** **** **** **** **** +16749 **** **** **** **** **** **** **** **** **** +16750 Templates_16300-16999 **** **** **** **** **** **** **** **** +16751 **** **** **** **** **** **** **** **** **** +16752 **** **** **** **** **** **** **** **** **** +16753 **** **** **** **** **** **** **** **** **** +16754 **** **** **** **** **** **** **** **** **** +16755 **** **** **** **** **** **** **** **** **** +16756 **** **** **** **** **** **** **** **** **** +16757 **** **** **** **** **** **** **** **** **** +16758 **** **** **** **** **** **** **** **** **** +16759 **** **** **** **** **** **** **** **** **** +16760 Templates_16300-16999 **** **** **** **** **** **** **** **** +16761 **** **** **** **** **** **** **** **** **** +16762 **** **** **** **** **** **** **** **** **** +16763 **** **** **** **** **** **** **** **** **** +16764 **** **** **** **** **** **** **** **** **** +16765 **** **** **** **** **** **** **** **** **** +16766 **** **** **** **** **** **** **** **** **** +16767 **** **** **** **** **** **** **** **** **** +16768 **** **** **** **** **** **** **** **** **** +16769 **** **** **** **** **** **** **** **** **** +16770 Templates_16300-16999 **** **** **** **** **** **** **** **** +16771 **** **** **** **** **** **** **** **** **** +16772 **** **** **** **** **** **** **** **** **** +16773 **** **** **** **** **** **** **** **** **** +16774 **** **** **** **** **** **** **** **** **** +16775 **** **** **** **** **** **** **** **** **** +16776 **** **** **** **** **** **** **** **** **** +16777 **** **** **** **** **** **** **** **** **** +16778 **** **** **** **** **** **** **** **** **** +16779 **** **** **** **** **** **** **** **** **** +16780 Templates_16300-16999 **** **** **** **** **** **** **** **** +16781 **** **** **** **** **** **** **** **** **** +16782 **** **** **** **** **** **** **** **** **** +16783 **** **** **** **** **** **** **** **** **** +16784 **** **** **** **** **** **** **** **** **** +16785 **** **** **** **** **** **** **** **** **** +16786 **** **** **** **** **** **** **** **** **** +16787 **** **** **** **** **** **** **** **** **** +16788 **** **** **** **** **** **** **** **** **** +16789 **** **** **** **** **** **** **** **** **** +16790 Templates_16300-16999 **** **** **** **** **** **** **** **** +16791 **** **** **** **** **** **** **** **** **** +16792 **** **** **** **** **** **** **** **** **** +16793 **** **** **** **** **** **** **** **** **** +16794 **** **** **** **** **** **** **** **** **** +16795 **** **** **** **** **** **** **** **** **** +16796 **** **** **** **** **** **** **** **** **** +16797 **** **** **** **** **** **** **** **** **** +16798 **** **** **** **** **** **** **** **** **** +16799 **** **** **** **** **** **** **** **** **** +16800 Templates_16300-16999 **** **** **** **** **** **** **** **** +16801 **** **** **** **** **** **** **** **** **** +16802 **** **** **** **** **** **** **** **** **** +16803 **** **** **** **** **** **** **** **** **** +16804 **** **** **** **** **** **** **** **** **** +16805 **** **** **** **** **** **** **** **** **** +16806 **** **** **** **** **** **** **** **** **** +16807 **** **** **** **** **** **** **** **** **** +16808 **** **** **** **** **** **** **** **** **** +16809 **** **** **** **** **** **** **** **** **** +16810 Templates_16300-16999 **** **** **** **** **** **** **** **** +16811 **** **** **** **** **** **** **** **** **** +16812 **** **** **** **** **** **** **** **** **** +16813 **** **** **** **** **** **** **** **** **** +16814 **** **** **** **** **** **** **** **** **** +16815 **** **** **** **** **** **** **** **** **** +16816 **** **** **** **** **** **** **** **** **** +16817 **** **** **** **** **** **** **** **** **** +16818 **** **** **** **** **** **** **** **** **** +16819 **** **** **** **** **** **** **** **** **** +16820 Templates_16300-16999 **** **** **** **** **** **** **** **** +16821 **** **** **** **** **** **** **** **** **** +16822 **** **** **** **** **** **** **** **** **** +16823 **** **** **** **** **** **** **** **** **** +16824 **** **** **** **** **** **** **** **** **** +16825 **** **** **** **** **** **** **** **** **** +16826 **** **** **** **** **** **** **** **** **** +16827 **** **** **** **** **** **** **** **** **** +16828 **** **** **** **** **** **** **** **** **** +16829 **** **** **** **** **** **** **** **** **** +16830 Templates_16300-16999 **** **** **** **** **** **** **** **** +16831 **** **** **** **** **** **** **** **** **** +16832 **** **** **** **** **** **** **** **** **** +16833 **** **** **** **** **** **** **** **** **** +16834 **** **** **** **** **** **** **** **** **** +16835 **** **** **** **** **** **** **** **** **** +16836 **** **** **** **** **** **** **** **** **** +16837 **** **** **** **** **** **** **** **** **** +16838 **** **** **** **** **** **** **** **** **** +16839 **** **** **** **** **** **** **** **** **** +16840 Templates_16300-16999 **** **** **** **** **** **** **** **** +16841 **** **** **** **** **** **** **** **** **** +16842 **** **** **** **** **** **** **** **** **** +16843 **** **** **** **** **** **** **** **** **** +16844 **** **** **** **** **** **** **** **** **** +16845 **** **** **** **** **** **** **** **** **** +16846 **** **** **** **** **** **** **** **** **** +16847 **** **** **** **** **** **** **** **** **** +16848 **** **** **** **** **** **** **** **** **** +16849 **** **** **** **** **** **** **** **** **** +16850 Templates_16300-16999 **** **** **** **** **** **** **** **** +16851 **** **** **** **** **** **** **** **** **** +16852 **** **** **** **** **** **** **** **** **** +16853 **** **** **** **** **** **** **** **** **** +16854 **** **** **** **** **** **** **** **** **** +16855 **** **** **** **** **** **** **** **** **** +16856 **** **** **** **** **** **** **** **** **** +16857 **** **** **** **** **** **** **** **** **** +16858 **** **** **** **** **** **** **** **** **** +16859 **** **** **** **** **** **** **** **** **** +16860 Templates_16300-16999 **** **** **** **** **** **** **** **** +16861 **** **** **** **** **** **** **** **** **** +16862 **** **** **** **** **** **** **** **** **** +16863 **** **** **** **** **** **** **** **** **** +16864 **** **** **** **** **** **** **** **** **** +16865 **** **** **** **** **** **** **** **** **** +16866 **** **** **** **** **** **** **** **** **** +16867 **** **** **** **** **** **** **** **** **** +16868 **** **** **** **** **** **** **** **** **** +16869 **** **** **** **** **** **** **** **** **** +16870 Templates_16300-16999 **** **** **** **** **** **** **** **** +16871 **** **** **** **** **** **** **** **** **** +16872 **** **** **** **** **** **** **** **** **** +16873 **** **** **** **** **** **** **** **** **** +16874 **** **** **** **** **** **** **** **** **** +16875 **** **** **** **** **** **** **** **** **** +16876 **** **** **** **** **** **** **** **** **** +16877 **** **** **** **** **** **** **** **** **** +16878 **** **** **** **** **** **** **** **** **** +16879 **** **** **** **** **** **** **** **** **** +16880 Templates_16300-16999 **** **** **** **** **** **** **** **** +16881 **** **** **** **** **** **** **** **** **** +16882 **** **** **** **** **** **** **** **** **** +16883 **** **** **** **** **** **** **** **** **** +16884 **** **** **** **** **** **** **** **** **** +16885 **** **** **** **** **** **** **** **** **** +16886 **** **** **** **** **** **** **** **** **** +16887 **** **** **** **** **** **** **** **** **** +16888 **** **** **** **** **** **** **** **** **** +16889 **** **** **** **** **** **** **** **** **** +16890 Templates_16300-16999 **** **** **** **** **** **** **** **** +16891 **** **** **** **** **** **** **** **** **** +16892 **** **** **** **** **** **** **** **** **** +16893 **** **** **** **** **** **** **** **** **** +16894 **** **** **** **** **** **** **** **** **** +16895 **** **** **** **** **** **** **** **** **** +16896 **** **** **** **** **** **** **** **** **** +16897 **** **** **** **** **** **** **** **** **** +16898 **** **** **** **** **** **** **** **** **** +16899 **** **** **** **** **** **** **** **** **** +16900 Templates_16300-16999 **** **** **** **** **** **** **** **** +16901 **** **** **** **** **** **** **** **** **** +16902 **** **** **** **** **** **** **** **** **** +16903 **** **** **** **** **** **** **** **** **** +16904 **** **** **** **** **** **** **** **** **** +16905 **** **** **** **** **** **** **** **** **** +16906 **** **** **** **** **** **** **** **** **** +16907 **** **** **** **** **** **** **** **** **** +16908 **** **** **** **** **** **** **** **** **** +16909 **** **** **** **** **** **** **** **** **** +16910 Templates_16300-16999 **** **** **** **** **** **** **** **** +16911 **** **** **** **** **** **** **** **** **** +16912 **** **** **** **** **** **** **** **** **** +16913 **** **** **** **** **** **** **** **** **** +16914 **** **** **** **** **** **** **** **** **** +16915 **** **** **** **** **** **** **** **** **** +16916 **** **** **** **** **** **** **** **** **** +16917 **** **** **** **** **** **** **** **** **** +16918 **** **** **** **** **** **** **** **** **** +16919 **** **** **** **** **** **** **** **** **** +16920 Templates_16300-16999 **** **** **** **** **** **** **** **** +16921 **** **** **** **** **** **** **** **** **** +16922 **** **** **** **** **** **** **** **** **** +16923 **** **** **** **** **** **** **** **** **** +16924 **** **** **** **** **** **** **** **** **** +16925 **** **** **** **** **** **** **** **** **** +16926 **** **** **** **** **** **** **** **** **** +16927 **** **** **** **** **** **** **** **** **** +16928 **** **** **** **** **** **** **** **** **** +16929 **** **** **** **** **** **** **** **** **** +16930 Templates_16300-16999 **** **** **** **** **** **** **** **** +16931 **** **** **** **** **** **** **** **** **** +16932 **** **** **** **** **** **** **** **** **** +16933 **** **** **** **** **** **** **** **** **** +16934 **** **** **** **** **** **** **** **** **** +16935 **** **** **** **** **** **** **** **** **** +16936 **** **** **** **** **** **** **** **** **** +16937 **** **** **** **** **** **** **** **** **** +16938 **** **** **** **** **** **** **** **** **** +16939 **** **** **** **** **** **** **** **** **** +16940 Templates_16300-16999 **** **** **** **** **** **** **** **** +16941 **** **** **** **** **** **** **** **** **** +16942 **** **** **** **** **** **** **** **** **** +16943 **** **** **** **** **** **** **** **** **** +16944 **** **** **** **** **** **** **** **** **** +16945 **** **** **** **** **** **** **** **** **** +16946 **** **** **** **** **** **** **** **** **** +16947 **** **** **** **** **** **** **** **** **** +16948 **** **** **** **** **** **** **** **** **** +16949 **** **** **** **** **** **** **** **** **** +16950 Templates_16300-16999 **** **** **** **** **** **** **** **** +16951 **** **** **** **** **** **** **** **** **** +16952 **** **** **** **** **** **** **** **** **** +16953 **** **** **** **** **** **** **** **** **** +16954 **** **** **** **** **** **** **** **** **** +16955 **** **** **** **** **** **** **** **** **** +16956 **** **** **** **** **** **** **** **** **** +16957 **** **** **** **** **** **** **** **** **** +16958 **** **** **** **** **** **** **** **** **** +16959 **** **** **** **** **** **** **** **** **** +16960 Templates_16300-16999 **** **** **** **** **** **** **** **** +16961 **** **** **** **** **** **** **** **** **** +16962 **** **** **** **** **** **** **** **** **** +16963 **** **** **** **** **** **** **** **** **** +16964 **** **** **** **** **** **** **** **** **** +16965 **** **** **** **** **** **** **** **** **** +16966 **** **** **** **** **** **** **** **** **** +16967 **** **** **** **** **** **** **** **** **** +16968 **** **** **** **** **** **** **** **** **** +16969 **** **** **** **** **** **** **** **** **** +16970 Templates_16300-16999 **** **** **** **** **** **** **** **** +16971 **** **** **** **** **** **** **** **** **** +16972 **** **** **** **** **** **** **** **** **** +16973 **** **** **** **** **** **** **** **** **** +16974 **** **** **** **** **** **** **** **** **** +16975 **** **** **** **** **** **** **** **** **** +16976 **** **** **** **** **** **** **** **** **** +16977 **** **** **** **** **** **** **** **** **** +16978 **** **** **** **** **** **** **** **** **** +16979 **** **** **** **** **** **** **** **** **** +16980 Templates_16300-16999 **** **** **** **** **** **** **** **** +16981 **** **** **** **** **** **** **** **** **** +16982 **** **** **** **** **** **** **** **** **** +16983 **** **** **** **** **** **** **** **** **** +16984 **** **** **** **** **** **** **** **** **** +16985 **** **** **** **** **** **** **** **** **** +16986 **** **** **** **** **** **** **** **** **** +16987 **** **** **** **** **** **** **** **** **** +16988 **** **** **** **** **** **** **** **** **** +16989 **** **** **** **** **** **** **** **** **** +16990 Templates_16300-16999 **** **** **** **** **** **** **** **** +16991 **** **** **** **** **** **** **** **** **** +16992 **** **** **** **** **** **** **** **** **** +16993 **** **** **** **** **** **** **** **** **** +16994 **** **** **** **** **** **** **** **** **** +16995 **** **** **** **** **** **** **** **** **** +16996 **** **** **** **** **** **** **** **** **** +16997 **** **** **** **** **** **** **** **** **** +16998 **** **** **** **** **** **** **** **** **** +16999 Templates_16300-16999 **** **** **** **** **** **** **** **** +17000 **** **** **** **** **** **** **** **** **** +17001 **** **** **** **** **** **** **** **** **** +17002 **** **** **** **** **** **** **** **** **** +17003 **** **** **** **** **** **** **** **** **** +17004 **** **** **** **** **** **** **** **** **** +17005 **** **** **** **** **** **** **** **** **** +17006 **** **** **** **** **** **** **** **** **** +17007 **** **** **** **** **** **** **** **** **** +17008 **** **** **** **** **** **** **** **** **** +17009 **** **** **** **** **** **** **** **** **** +17010 **** **** **** **** **** **** **** **** **** +17011 **** **** **** **** **** **** **** **** **** +17012 **** **** **** **** **** **** **** **** **** +17013 **** **** **** **** **** **** **** **** **** +17014 **** **** **** **** **** **** **** **** **** +17015 **** **** **** **** **** **** **** **** **** +17016 **** **** **** **** **** **** **** **** **** +17017 **** **** **** **** **** **** **** **** **** +17018 **** **** **** **** **** **** **** **** **** +17019 **** **** **** **** **** **** **** **** **** +17020 **** **** **** **** **** **** **** **** **** +17021 **** **** **** **** **** **** **** **** **** +17022 **** **** **** **** **** **** **** **** **** +17023 **** **** **** **** **** **** **** **** **** +17024 **** **** **** **** **** **** **** **** **** +17025 **** **** **** **** **** **** **** **** **** +17026 **** **** **** **** **** **** **** **** **** +17027 **** **** **** **** **** **** **** **** **** +17028 **** **** **** **** **** **** **** **** **** +17029 **** **** **** **** **** **** **** **** **** +17030 **** **** **** **** **** **** **** **** **** +17031 **** **** **** **** **** **** **** **** **** +17032 **** **** **** **** **** **** **** **** **** +17033 **** **** **** **** **** **** **** **** **** +17034 **** **** **** **** **** **** **** **** **** +17035 **** **** **** **** **** **** **** **** **** +17036 **** **** **** **** **** **** **** **** **** +17037 **** **** **** **** **** **** **** **** **** +17038 **** **** **** **** **** **** **** **** **** +17039 **** **** **** **** **** **** **** **** **** +17040 **** **** **** **** **** **** **** **** **** +17041 **** **** **** **** **** **** **** **** **** +17042 **** **** **** **** **** **** **** **** **** +17043 **** **** **** **** **** **** **** **** **** +17044 **** **** **** **** **** **** **** **** **** +17045 **** **** **** **** **** **** **** **** **** +17046 **** **** **** **** **** **** **** **** **** +17047 **** **** **** **** **** **** **** **** **** +17048 **** **** **** **** **** **** **** **** **** +17049 **** **** **** **** **** **** **** **** **** +17050 **** **** **** **** **** **** **** **** **** +17051 **** **** **** **** **** **** **** **** **** +17052 **** **** **** **** **** **** **** **** **** +17053 **** **** **** **** **** **** **** **** **** +17054 **** **** **** **** **** **** **** **** **** +17055 **** **** **** **** **** **** **** **** **** +17056 **** **** **** **** **** **** **** **** **** +17057 **** **** **** **** **** **** **** **** **** +17058 **** **** **** **** **** **** **** **** **** +17059 **** **** **** **** **** **** **** **** **** +17060 **** **** **** **** **** **** **** **** **** +17061 **** **** **** **** **** **** **** **** **** +17062 **** **** **** **** **** **** **** **** **** +17063 **** **** **** **** **** **** **** **** **** +17064 **** **** **** **** **** **** **** **** **** +17065 **** **** **** **** **** **** **** **** **** +17066 **** **** **** **** **** **** **** **** **** +17067 **** **** **** **** **** **** **** **** **** +17068 **** **** **** **** **** **** **** **** **** +17069 **** **** **** **** **** **** **** **** **** +17070 **** **** **** **** **** **** **** **** **** +17071 **** **** **** **** **** **** **** **** **** +17072 **** **** **** **** **** **** **** **** **** +17073 **** **** **** **** **** **** **** **** **** +17074 **** **** **** **** **** **** **** **** **** +17075 **** **** **** **** **** **** **** **** **** +17076 **** **** **** **** **** **** **** **** **** +17077 **** **** **** **** **** **** **** **** **** +17078 **** **** **** **** **** **** **** **** **** +17079 **** **** **** **** **** **** **** **** **** +17080 **** **** **** **** **** **** **** **** **** +17081 **** **** **** **** **** **** **** **** **** +17082 **** **** **** **** **** **** **** **** **** +17083 **** **** **** **** **** **** **** **** **** +17084 **** **** **** **** **** **** **** **** **** +17085 **** **** **** **** **** **** **** **** **** +17086 **** **** **** **** **** **** **** **** **** +17087 **** **** **** **** **** **** **** **** **** +17088 **** **** **** **** **** **** **** **** **** +17089 **** **** **** **** **** **** **** **** **** +17090 **** **** **** **** **** **** **** **** **** +17091 **** **** **** **** **** **** **** **** **** +17092 **** **** **** **** **** **** **** **** **** +17093 **** **** **** **** **** **** **** **** **** +17094 **** **** **** **** **** **** **** **** **** +17095 **** **** **** **** **** **** **** **** **** +17096 **** **** **** **** **** **** **** **** **** +17097 **** **** **** **** **** **** **** **** **** +17098 **** **** **** **** **** **** **** **** **** +17099 **** **** **** **** **** **** **** **** **** +17100 **** **** **** **** **** **** **** **** **** +17101 **** **** **** **** **** **** **** **** **** +17102 **** **** **** **** **** **** **** **** **** +17103 **** **** **** **** **** **** **** **** **** +17104 **** **** **** **** **** **** **** **** **** +17105 **** **** **** **** **** **** **** **** **** +17106 **** **** **** **** **** **** **** **** **** +17107 **** **** **** **** **** **** **** **** **** +17108 **** **** **** **** **** **** **** **** **** +17109 **** **** **** **** **** **** **** **** **** +17110 **** **** **** **** **** **** **** **** **** +17111 **** **** **** **** **** **** **** **** **** +17112 **** **** **** **** **** **** **** **** **** +17113 **** **** **** **** **** **** **** **** **** +17114 **** **** **** **** **** **** **** **** **** +17115 **** **** **** **** **** **** **** **** **** +17116 **** **** **** **** **** **** **** **** **** +17117 **** **** **** **** **** **** **** **** **** +17118 **** **** **** **** **** **** **** **** **** +17119 **** **** **** **** **** **** **** **** **** +17120 **** **** **** **** **** **** **** **** **** +17121 **** **** **** **** **** **** **** **** **** +17122 **** **** **** **** **** **** **** **** **** +17123 **** **** **** **** **** **** **** **** **** +17124 **** **** **** **** **** **** **** **** **** +17125 **** **** **** **** **** **** **** **** **** +17126 **** **** **** **** **** **** **** **** **** +17127 **** **** **** **** **** **** **** **** **** +17128 **** **** **** **** **** **** **** **** **** +17129 **** **** **** **** **** **** **** **** **** +17130 **** **** **** **** **** **** **** **** **** +17131 **** **** **** **** **** **** **** **** **** +17132 **** **** **** **** **** **** **** **** **** +17133 **** **** **** **** **** **** **** **** **** +17134 **** **** **** **** **** **** **** **** **** +17135 **** **** **** **** **** **** **** **** **** +17136 **** **** **** **** **** **** **** **** **** +17137 **** **** **** **** **** **** **** **** **** +17138 **** **** **** **** **** **** **** **** **** +17139 **** **** **** **** **** **** **** **** **** +17140 **** **** **** **** **** **** **** **** **** +17141 **** **** **** **** **** **** **** **** **** +17142 **** **** **** **** **** **** **** **** **** +17143 **** **** **** **** **** **** **** **** **** +17144 **** **** **** **** **** **** **** **** **** +17145 **** **** **** **** **** **** **** **** **** +17146 **** **** **** **** **** **** **** **** **** +17147 **** **** **** **** **** **** **** **** **** +17148 **** **** **** **** **** **** **** **** **** +17149 **** **** **** **** **** **** **** **** **** +17150 **** **** **** **** **** **** **** **** **** +17151 **** **** **** **** **** **** **** **** **** +17152 **** **** **** **** **** **** **** **** **** +17153 **** **** **** **** **** **** **** **** **** +17154 **** **** **** **** **** **** **** **** **** +17155 **** **** **** **** **** **** **** **** **** +17156 **** **** **** **** **** **** **** **** **** +17157 **** **** **** **** **** **** **** **** **** +17158 **** **** **** **** **** **** **** **** **** +17159 **** **** **** **** **** **** **** **** **** +17160 **** **** **** **** **** **** **** **** **** +17161 **** **** **** **** **** **** **** **** **** +17162 **** **** **** **** **** **** **** **** **** +17163 **** **** **** **** **** **** **** **** **** +17164 **** **** **** **** **** **** **** **** **** +17165 **** **** **** **** **** **** **** **** **** +17166 **** **** **** **** **** **** **** **** **** +17167 **** **** **** **** **** **** **** **** **** +17168 **** **** **** **** **** **** **** **** **** +17169 **** **** **** **** **** **** **** **** **** +17170 **** **** **** **** **** **** **** **** **** +17171 **** **** **** **** **** **** **** **** **** +17172 **** **** **** **** **** **** **** **** **** +17173 **** **** **** **** **** **** **** **** **** +17174 **** **** **** **** **** **** **** **** **** +17175 **** **** **** **** **** **** **** **** **** +17176 **** **** **** **** **** **** **** **** **** +17177 **** **** **** **** **** **** **** **** **** +17178 **** **** **** **** **** **** **** **** **** +17179 **** **** **** **** **** **** **** **** **** +17180 **** **** **** **** **** **** **** **** **** +17181 **** **** **** **** **** **** **** **** **** +17182 **** **** **** **** **** **** **** **** **** +17183 **** **** **** **** **** **** **** **** **** +17184 **** **** **** **** **** **** **** **** **** +17185 **** **** **** **** **** **** **** **** **** +17186 **** **** **** **** **** **** **** **** **** +17187 **** **** **** **** **** **** **** **** **** +17188 **** **** **** **** **** **** **** **** **** +17189 **** **** **** **** **** **** **** **** **** +17190 **** **** **** **** **** **** **** **** **** +17191 **** **** **** **** **** **** **** **** **** +17192 **** **** **** **** **** **** **** **** **** +17193 **** **** **** **** **** **** **** **** **** +17194 **** **** **** **** **** **** **** **** **** +17195 **** **** **** **** **** **** **** **** **** +17196 **** **** **** **** **** **** **** **** **** +17197 **** **** **** **** **** **** **** **** **** +17198 **** **** **** **** **** **** **** **** **** +17199 **** **** **** **** **** **** **** **** **** +17200 **** **** **** **** **** **** **** **** **** +17201 **** **** **** **** **** **** **** **** **** +17202 **** **** **** **** **** **** **** **** **** +17203 **** **** **** **** **** **** **** **** **** +17204 **** **** **** **** **** **** **** **** **** +17205 **** **** **** **** **** **** **** **** **** +17206 **** **** **** **** **** **** **** **** **** +17207 **** **** **** **** **** **** **** **** **** +17208 **** **** **** **** **** **** **** **** **** +17209 **** **** **** **** **** **** **** **** **** +17210 **** **** **** **** **** **** **** **** **** +17211 **** **** **** **** **** **** **** **** **** +17212 **** **** **** **** **** **** **** **** **** +17213 **** **** **** **** **** **** **** **** **** +17214 **** **** **** **** **** **** **** **** **** +17215 **** **** **** **** **** **** **** **** **** +17216 **** **** **** **** **** **** **** **** **** +17217 **** **** **** **** **** **** **** **** **** +17218 **** **** **** **** **** **** **** **** **** +17219 **** **** **** **** **** **** **** **** **** +17220 **** **** **** **** **** **** **** **** **** +17221 **** **** **** **** **** **** **** **** **** +17222 **** **** **** **** **** **** **** **** **** +17223 **** **** **** **** **** **** **** **** **** +17224 **** **** **** **** **** **** **** **** **** +17225 **** **** **** **** **** **** **** **** **** +17226 **** **** **** **** **** **** **** **** **** +17227 **** **** **** **** **** **** **** **** **** +17228 **** **** **** **** **** **** **** **** **** +17229 **** **** **** **** **** **** **** **** **** +17230 **** **** **** **** **** **** **** **** **** +17231 **** **** **** **** **** **** **** **** **** +17232 **** **** **** **** **** **** **** **** **** +17233 **** **** **** **** **** **** **** **** **** +17234 **** **** **** **** **** **** **** **** **** +17235 **** **** **** **** **** **** **** **** **** +17236 **** **** **** **** **** **** **** **** **** +17237 **** **** **** **** **** **** **** **** **** +17238 **** **** **** **** **** **** **** **** **** +17239 **** **** **** **** **** **** **** **** **** +17240 **** **** **** **** **** **** **** **** **** +17241 **** **** **** **** **** **** **** **** **** +17242 **** **** **** **** **** **** **** **** **** +17243 SPELL_REGEN_LIGHT_WOUNDS **** **** **** **** **** **** **** **** +17244 SPELL_REGEN_MODERATE_WOUNDS **** **** **** **** **** **** **** **** +17245 SPELL_REGEN_SERIOUS_WOUNDS **** **** **** **** **** **** **** **** +17246 SPELL_REGEN_CRITICAL_WOUNDS **** **** **** **** **** **** **** **** +17247 SPELL_SPEED_WIND **** **** **** **** **** **** **** **** +17248 SPELL_SPIRIT_WORM **** **** **** **** **** **** **** **** +17249 SPELL_SPIRITUAL_WEAPON **** **** **** **** **** **** **** **** +17250 SPELL_TORTISE_SHELL **** **** **** **** **** **** **** **** +17251 BattleBlessing **** **** **** **** **** **** **** **** +17252 TN_Wail_of_the_Banshee **** **** **** **** **** **** **** **** +17253 TN_Horrid_Wilting **** **** **** **** **** **** **** **** +17254 Spontaneous_Summoning **** **** **** **** **** **** **** **** +17255 Troglodyte_Stench **** **** **** **** **** **** **** **** +17256 FEAT_PRC_HIPS **** **** **** **** **** **** **** **** +17257 Hexblade_SwiftCast **** **** **** **** **** **** **** **** +17258 ET_GTEATREACH_BLAST **** **** **** **** **** **** **** **** +17259 ET_GTEATREACH_BLAST_CONVO **** **** **** **** **** **** **** **** +17260 ET_GTEATREACH_BLAST_QUICK1 **** **** **** **** **** **** **** **** +17261 ET_GTEATREACH_BLAST_QUICK2 **** **** **** **** **** **** **** **** +17262 ET_GTEATREACH_BLAST_QUICK3 **** **** **** **** **** **** **** **** +17263 ET_GTEATREACH_BLAST_QUICK4 **** **** **** **** **** **** **** **** +17264 ET_SPELLBLAST **** **** **** **** **** **** **** **** +17265 ET_SPELLBLAST_CONVO **** **** **** **** **** **** **** **** +17266 ET_SPELLBLAST_QUICK1 **** **** **** **** **** **** **** **** +17267 ET_SPELLBLAST_QUICK2 **** **** **** **** **** **** **** **** +17268 ET_SPELLBLAST_QUICK3 **** **** **** **** **** **** **** **** +17269 ET_SPELLBLAST_QUICK4 **** **** **** **** **** **** **** **** +17270 ED_CORRUPTING_BLAST **** **** **** **** **** **** **** **** +17271 ED_DAMAGE_REDUCTION **** **** **** **** **** **** **** **** +17272 ED_FEARFUL_GLARE **** **** **** **** **** **** **** **** +17273 ED_FIENDISH_RESISTANCE **** **** **** **** **** **** **** **** +17274 ED_HEALING_BLAST **** **** **** **** **** **** **** **** +17275 ED_PROTECTIVE_AURA **** **** **** **** **** **** **** **** +17276 ED_STRENGTH_OF_WILL **** **** **** **** **** **** **** **** +17277 ED_WILD_FRENZY **** **** **** **** **** **** **** **** +17278 Eldritch_Spellweave **** **** **** **** **** **** **** **** +17279 DivineMetamagic_Empower **** **** **** **** **** **** **** **** +17280 DivineMetamagic_Extend **** **** **** **** **** **** **** **** +17281 DivineMetamagic_Maximize **** **** **** **** **** **** **** **** +17282 Hellfire_Blast **** **** **** **** **** **** **** **** +17283 Hellfire_Spear **** **** **** **** **** **** **** **** +17284 Hellfire_Glaive **** **** **** **** **** **** **** **** +17285 Hellfire_Blow **** **** **** **** **** **** **** **** +17286 Hellfire_Chain **** **** **** **** **** **** **** **** +17287 Hellfire_Cone **** **** **** **** **** **** **** **** +17288 Hellfire_Line **** **** **** **** **** **** **** **** +17289 Hellfire_Doom **** **** **** **** **** **** **** **** +17290 Hellfire_Infusion **** **** **** **** **** **** **** **** +17291 Hellfire_Infusion_Extend **** **** **** **** **** **** **** **** +17292 Hellfire_Infusion_Empower **** **** **** **** **** **** **** **** +17293 Hellfire_Infusion_Widen **** **** **** **** **** **** **** **** +17294 Hellfire_Infusion_Maximize **** **** **** **** **** **** **** **** +17295 Hellfire_Shield **** **** **** **** **** **** **** **** +17296 Secular_Authority **** **** **** **** **** **** **** **** +17297 KotMC_TrueStrike **** **** **** **** **** **** **** **** +17298 Shifter_LearnShape **** **** **** **** **** **** **** **** +17299 FEAT_HEXTOR_BSTRIKE_MODE **** **** **** **** **** **** **** **** +17300 **** **** **** **** **** **** **** **** **** +17301 BlisteringFlourish **** **** **** **** **** **** **** **** +17302 BurningBlade **** **** **** **** **** **** **** **** +17303 BurningBrand **** **** **** **** **** **** **** **** +17304 DeathMark **** **** **** **** **** **** **** **** +17305 DesertTempest **** **** **** **** **** **** **** **** +17306 DistractingEmber **** **** **** **** **** **** **** **** +17307 DragonsFlame **** **** **** **** **** **** **** **** +17308 FanTheFlames **** **** **** **** **** **** **** **** +17309 FieryAssault **** **** **** **** **** **** **** **** +17310 FireRiposte **** **** **** **** **** **** **** **** +17311 Firesnake **** **** **** **** **** **** **** **** +17312 FlamesBlessing **** **** **** **** **** **** **** **** +17313 FlashingSun **** **** **** **** **** **** **** **** +17314 HatchlingsFlame **** **** **** **** **** **** **** **** +17315 HolocaustCloak **** **** **** **** **** **** **** **** +17316 InfernoBlade **** **** **** **** **** **** **** **** +17317 InfernoBlast **** **** **** **** **** **** **** **** +17318 LeapingFlame **** **** **** **** **** **** **** **** +17319 LingeringInferno **** **** **** **** **** **** **** **** +17320 RingOfFire **** **** **** **** **** **** **** **** +17321 RisingPhoenix **** **** **** **** **** **** **** **** +17322 SalamanderCharge **** **** **** **** **** **** **** **** +17323 SearingBlade **** **** **** **** **** **** **** **** +17324 SearingCharge **** **** **** **** **** **** **** **** +17325 WindStride **** **** **** **** **** **** **** **** +17326 WyrmsFlame **** **** **** **** **** **** **** **** +17327 ZephyrDance **** **** **** **** **** **** **** **** +17328 AuraOfChaos **** **** **** **** **** **** **** **** +17329 AuraOfPerfectOrder **** **** **** **** **** **** **** **** +17330 AuraOfTriumph **** **** **** **** **** **** **** **** +17331 AuraOfTyranny **** **** **** **** **** **** **** **** +17332 CastigatingStrike **** **** **** **** **** **** **** **** +17333 CrusadersStrike **** **** **** **** **** **** **** **** +17334 DauntingStrike **** **** **** **** **** **** **** **** +17335 DefensiveRebuke **** **** **** **** **** **** **** **** +17336 DivineSurge **** **** **** **** **** **** **** **** +17337 DivineSurgeGreater **** **** **** **** **** **** **** **** +17338 DoomCharge **** **** **** **** **** **** **** **** +17339 EntanglingBlade **** **** **** **** **** **** **** **** +17340 Foehammer **** **** **** **** **** **** **** **** +17341 ImmortalFortitude **** **** **** **** **** **** **** **** +17342 IronGuardsGlare **** **** **** **** **** **** **** **** +17343 LawBearer **** **** **** **** **** **** **** **** +17344 MartialSpirit **** **** **** **** **** **** **** **** +17345 RadiantCharge **** **** **** **** **** **** **** **** +17346 RallyingStrike **** **** **** **** **** **** **** **** +17347 RevitalizingStrike **** **** **** **** **** **** **** **** +17348 ShieldBlock **** **** **** **** **** **** **** **** +17349 ShieldCounter **** **** **** **** **** **** **** **** +17350 StrikeOfRighteousVitality **** **** **** **** **** **** **** **** +17351 ThicketOfBlades **** **** **** **** **** **** **** **** +17352 TideOfChaos **** **** **** **** **** **** **** **** +17353 VanguardStrike **** **** **** **** **** **** **** **** +17354 ActionBeforeThought **** **** **** **** **** **** **** **** +17355 AvalancheOfBlades **** **** **** **** **** **** **** **** +17356 BoundingAssault **** **** **** **** **** **** **** **** +17357 DiamondDefense **** **** **** **** **** **** **** **** +17358 DiamondNightmareBlade **** **** **** **** **** **** **** **** +17359 DisruptingBlow **** **** **** **** **** **** **** **** +17360 EmeraldRazor **** **** **** **** **** **** **** **** +17361 HearingTheAir **** **** **** **** **** **** **** **** +17362 InsightfulStrike **** **** **** **** **** **** **** **** +17363 InsightfulStrikeGreater **** **** **** **** **** **** **** **** +17364 MindOverBody **** **** **** **** **** **** **** **** +17365 MindStrike **** **** **** **** **** **** **** **** +17366 MomentOfAlacrity **** **** **** **** **** **** **** **** +17367 MomentOfPerfectMind **** **** **** **** **** **** **** **** +17368 PearlOfBlackDoubt **** **** **** **** **** **** **** **** +17369 QuicksilverMotion **** **** **** **** **** **** **** **** +17370 RapidCounter **** **** **** **** **** **** **** **** +17371 RubyNightmareBlade **** **** **** **** **** **** **** **** +17372 SapphireNightmareBlade **** **** **** **** **** **** **** **** +17373 StanceOfAlacrity **** **** **** **** **** **** **** **** +17374 StanceOfClarity **** **** **** **** **** **** **** **** +17375 TimeStandsStill **** **** **** **** **** **** **** **** +17376 AbsoluteSteel **** **** **** **** **** **** **** **** +17377 AdamantineHurricane **** **** **** **** **** **** **** **** +17378 DancingBladeForm **** **** **** **** **** **** **** **** +17379 DazingStrike **** **** **** **** **** **** **** **** +17380 DisarmingStrike **** **** **** **** **** **** **** **** +17381 ExorcismOfSteel **** **** **** **** **** **** **** **** +17382 FinishingMove **** **** **** **** **** **** **** **** +17383 IronHeartEndurance **** **** **** **** **** **** **** **** +17384 IronHeartFocus **** **** **** **** **** **** **** **** +17385 IronHeartSurge **** **** **** **** **** **** **** **** +17386 LightningRecovery **** **** **** **** **** **** **** **** +17387 LightningThrow **** **** **** **** **** **** **** **** +17388 ManticoreParry **** **** **** **** **** **** **** **** +17389 MithralTornado **** **** **** **** **** **** **** **** +17390 PunishingStance **** **** **** **** **** **** **** **** +17391 ScythingBlade **** **** **** **** **** **** **** **** +17392 SteelWind **** **** **** **** **** **** **** **** +17393 SteelyStrike **** **** **** **** **** **** **** **** +17394 StrikeOfPerfectClarity **** **** **** **** **** **** **** **** +17395 SupremeBladeParry **** **** **** **** **** **** **** **** +17396 WallOfBlades **** **** **** **** **** **** **** **** +17397 BafflingDefense **** **** **** **** **** **** **** **** +17398 BallistaThrow **** **** **** **** **** **** **** **** +17399 CleverPositioning **** **** **** **** **** **** **** **** +17400 CometThrow **** **** **** **** **** **** **** **** +17401 CounterCharge **** **** **** **** **** **** **** **** +17402 DevastatingThrow **** **** **** **** **** **** **** **** +17403 FeignedOpening **** **** **** **** **** **** **** **** +17404 FoolsStrike **** **** **** **** **** **** **** **** +17405 GhostlyDefense **** **** **** **** **** **** **** **** +17406 GiantKillingStyle **** **** **** **** **** **** **** **** +17407 HydraSlayingStrike **** **** **** **** **** **** **** **** +17408 MightyThrow **** **** **** **** **** **** **** **** +17409 MirroredPursuit **** **** **** **** **** **** **** **** +17410 ScorpionParry **** **** **** **** **** **** **** **** +17411 ShiftingDefense **** **** **** **** **** **** **** **** +17412 SoaringThrow **** **** **** **** **** **** **** **** +17413 StalkingShadow **** **** **** **** **** **** **** **** +17414 StepOfTheWind **** **** **** **** **** **** **** **** +17415 StrikeOfTheBrokenShield **** **** **** **** **** **** **** **** +17416 TornadoThrow **** **** **** **** **** **** **** **** +17417 AssassinsStance **** **** **** **** **** **** **** **** +17418 BalanceOnTheSky **** **** **** **** **** **** **** **** +17419 BloodlettingStrike **** **** **** **** **** **** **** **** +17420 ChildOfShadow **** **** **** **** **** **** **** **** +17421 ClingingShadowStrike **** **** **** **** **** **** **** **** +17422 CloakOfDeception **** **** **** **** **** **** **** **** +17423 DanceOfTheSpider **** **** **** **** **** **** **** **** +17424 DeathInTheDark **** **** **** **** **** **** **** **** +17425 DrainVitality **** **** **** **** **** **** **** **** +17426 EnervatingShadowStrike **** **** **** **** **** **** **** **** +17427 FiveShadowCreepingIceEnervationStrike **** **** **** **** **** **** **** **** +17428 GhostBlade **** **** **** **** **** **** **** **** +17429 HandOfDeath **** **** **** **** **** **** **** **** +17430 IslandOfBlades **** **** **** **** **** **** **** **** +17431 ObscuringShadowVeil **** **** **** **** **** **** **** **** +17432 OneWithShadow **** **** **** **** **** **** **** **** +17433 ShadowBladeTechnique **** **** **** **** **** **** **** **** +17434 ShadowBlink **** **** **** **** **** **** **** **** +17435 ShadowGarrote **** **** **** **** **** **** **** **** +17436 ShadowJaunt **** **** **** **** **** **** **** **** +17437 ShadowNoose **** **** **** **** **** **** **** **** +17438 ShadowStride **** **** **** **** **** **** **** **** +17439 StalkerInTheNight **** **** **** **** **** **** **** **** +17440 StepOfTheDancingMoth **** **** **** **** **** **** **** **** +17441 StrengthDrainingStrike **** **** **** **** **** **** **** **** +17442 AdamantineBones **** **** **** **** **** **** **** **** +17443 AncientMountainHammer **** **** **** **** **** **** **** **** +17444 BonesplittingStrike **** **** **** **** **** **** **** **** +17445 Bonecrusher **** **** **** **** **** **** **** **** +17446 BoulderRoll **** **** **** **** **** **** **** **** +17447 ChargingMinotaur **** **** **** **** **** **** **** **** +17448 ColossusStrike **** **** **** **** **** **** **** **** +17449 CrushingVise **** **** **** **** **** **** **** **** +17450 CrushingWeightOfTheMountain **** **** **** **** **** **** **** **** +17451 EarthstrikeQuake **** **** **** **** **** **** **** **** +17452 ElderMountainHammer **** **** **** **** **** **** **** **** +17453 GiantsStance **** **** **** **** **** **** **** **** +17454 IronBones **** **** **** **** **** **** **** **** +17455 IrresistibleMountainStrike **** **** **** **** **** **** **** **** +17456 MountainAvalanche **** **** **** **** **** **** **** **** +17457 MountainHammer **** **** **** **** **** **** **** **** +17458 MountainTombstoneStrike **** **** **** **** **** **** **** **** +17459 OverwhelmingMountainStrike **** **** **** **** **** **** **** **** +17460 RootsOfTheMountain **** **** **** **** **** **** **** **** +17461 StoneBones **** **** **** **** **** **** **** **** +17462 StoneDragonsFury **** **** **** **** **** **** **** **** +17463 StoneVise **** **** **** **** **** **** **** **** +17464 StonefootStance **** **** **** **** **** **** **** **** +17465 RisingPhoenix_FullAttack **** **** **** **** **** **** **** **** +17466 **** **** **** **** **** **** **** **** **** +17467 **** **** **** **** **** **** **** **** **** +17468 StrengthOfStone **** **** **** **** **** **** **** **** +17469 BloodInTheWater **** **** **** **** **** **** **** **** +17470 ClawAtTheMoon **** **** **** **** **** **** **** **** +17471 DancingMongoose **** **** **** **** **** **** **** **** +17472 DeathFromAbove **** **** **** **** **** **** **** **** +17473 FeralDeathBlow **** **** **** **** **** **** **** **** +17474 FleshRipper **** **** **** **** **** **** **** **** +17475 FountainOfBlood **** **** **** **** **** **** **** **** +17476 GirallonWindmillFleshRip **** **** **** **** **** **** **** **** +17477 HamstringAttack **** **** **** **** **** **** **** **** +17478 HuntersSense **** **** **** **** **** **** **** **** +17479 LeapingDragonStance **** **** **** **** **** **** **** **** +17480 PouncingCharge **** **** **** **** **** **** **** **** +17481 PreyOnTheWeak **** **** **** **** **** **** **** **** +17482 RabidBearStrike **** **** **** **** **** **** **** **** +17483 RabidWolfStrike **** **** **** **** **** **** **** **** +17484 RagingMongoose **** **** **** **** **** **** **** **** +17485 SoaringRaptorStrike **** **** **** **** **** **** **** **** +17486 SuddenLeap **** **** **** **** **** **** **** **** +17487 SwoopingDragonStrike **** **** **** **** **** **** **** **** +17488 WolfClimbsTheMountain **** **** **** **** **** **** **** **** +17489 WolfFangStrike **** **** **** **** **** **** **** **** +17490 WolfPackTactics **** **** **** **** **** **** **** **** +17491 WolverineStance **** **** **** **** **** **** **** **** +17492 BattleLeadersCharge **** **** **** **** **** **** **** **** +17493 BolsteringVoice **** **** **** **** **** **** **** **** +17494 ClarionCall **** **** **** **** **** **** **** **** +17495 CoveringStrike **** **** **** **** **** **** **** **** +17496 DouseTheFlames **** **** **** **** **** **** **** **** +17497 FlankingManeuver **** **** **** **** **** **** **** **** +17498 LeadingTheAttack **** **** **** **** **** **** **** **** +17499 LeadingTheCharge **** **** **** **** **** **** **** **** +17500 LionsRoar **** **** **** **** **** **** **** **** +17501 OrderForgedFromChaos **** **** **** **** **** **** **** **** +17502 PressTheAdvantage **** **** **** **** **** **** **** **** +17503 SwarmTactics **** **** **** **** **** **** **** **** +17504 SwarmingAssault **** **** **** **** **** **** **** **** +17505 TacticalStrike **** **** **** **** **** **** **** **** +17506 TacticsOfTheWolf **** **** **** **** **** **** **** **** +17507 WarLeadersCharge **** **** **** **** **** **** **** **** +17508 WarMastersCharge **** **** **** **** **** **** **** **** +17509 WhiteRavenHammer **** **** **** **** **** **** **** **** +17510 WhiteRavenStrike **** **** **** **** **** **** **** **** +17511 WhiteRavenTactics **** **** **** **** **** **** **** **** +17512 **** **** **** **** **** **** **** **** **** +17513 **** **** **** **** **** **** **** **** **** +17514 **** **** **** **** **** **** **** **** **** +17515 **** **** **** **** **** **** **** **** **** +17516 **** **** **** **** **** **** **** **** **** +17517 **** **** **** **** **** **** **** **** **** +17518 **** **** **** **** **** **** **** **** **** +17519 **** **** **** **** **** **** **** **** **** +17520 ####START_OF_TOB_SPELLBOOK_RESERVE **** **** **** **** **** **** **** **** +17521 Warblade_StanceOfClarity **** **** **** **** **** **** **** **** +17522 Warblade_TimeStandsStill **** **** **** **** **** **** **** **** +17523 Warblade_AbsoluteSteel **** **** **** **** **** **** **** **** +17524 Warblade_AdamantineHurricane **** **** **** **** **** **** **** **** +17525 Warblade_DancingBladeForm **** **** **** **** **** **** **** **** +17526 Warblade_DazingStrike **** **** **** **** **** **** **** **** +17527 Warblade_DisarmingStrike **** **** **** **** **** **** **** **** +17528 Warblade_ExorcismOfSteel **** **** **** **** **** **** **** **** +17529 Warblade_FinishingMove **** **** **** **** **** **** **** **** +17530 Warblade_IronHeartEndurance **** **** **** **** **** **** **** **** +17531 Warblade_IronHeartFocus **** **** **** **** **** **** **** **** +17532 Warblade_IronHeartSurge **** **** **** **** **** **** **** **** +17533 Warblade_LightningRecovery **** **** **** **** **** **** **** **** +17534 Warblade_LightningThrow **** **** **** **** **** **** **** **** +17535 Warblade_ManticoreParry **** **** **** **** **** **** **** **** +17536 Warblade_MithralTornado **** **** **** **** **** **** **** **** +17537 Warblade_PunishingStance **** **** **** **** **** **** **** **** +17538 Warblade_ScythingBlade **** **** **** **** **** **** **** **** +17539 Warblade_SteelWind **** **** **** **** **** **** **** **** +17540 Warblade_SteelyStrike **** **** **** **** **** **** **** **** +17541 Warblade_StrikeOfPerfectClarity **** **** **** **** **** **** **** **** +17542 Warblade_SupremeBladeParry **** **** **** **** **** **** **** **** +17543 Warblade_WallOfBlades **** **** **** **** **** **** **** **** +17544 Warblade_BafflingDefense **** **** **** **** **** **** **** **** +17545 Warblade_BallistaThrow **** **** **** **** **** **** **** **** +17546 Warblade_CleverPositioning **** **** **** **** **** **** **** **** +17547 Warblade_CometThrow **** **** **** **** **** **** **** **** +17548 Warblade_CounterCharge **** **** **** **** **** **** **** **** +17549 Warblade_DevastatingThrow **** **** **** **** **** **** **** **** +17550 Warblade_FeignedOpening **** **** **** **** **** **** **** **** +17551 Warblade_FoolsStrike **** **** **** **** **** **** **** **** +17552 Warblade_GhostlyDefense **** **** **** **** **** **** **** **** +17553 Warblade_GiantKillingStyle **** **** **** **** **** **** **** **** +17554 Warblade_HydraSlayingStrike **** **** **** **** **** **** **** **** +17555 Warblade_MightyThrow **** **** **** **** **** **** **** **** +17556 Warblade_MirroredPursuit **** **** **** **** **** **** **** **** +17557 Warblade_ScorpionParry **** **** **** **** **** **** **** **** +17558 Warblade_ShiftingDefense **** **** **** **** **** **** **** **** +17559 Warblade_SoaringThrow **** **** **** **** **** **** **** **** +17560 Warblade_StalkingShadow **** **** **** **** **** **** **** **** +17561 Warblade_StepOfTheWind **** **** **** **** **** **** **** **** +17562 Warblade_StrikeOfTheBrokenShield **** **** **** **** **** **** **** **** +17563 Warblade_TornadoThrow **** **** **** **** **** **** **** **** +17564 Warblade_AssassinsStance **** **** **** **** **** **** **** **** +17565 Warblade_BalanceOnTheSky **** **** **** **** **** **** **** **** +17566 Warblade_BloodlettingStrike **** **** **** **** **** **** **** **** +17567 Warblade_ChildOfShadow **** **** **** **** **** **** **** **** +17568 Warblade_ClingingShadowStrike **** **** **** **** **** **** **** **** +17569 Warblade_CloakOfDeception **** **** **** **** **** **** **** **** +17570 Warblade_DanceOfTheSpider **** **** **** **** **** **** **** **** +17571 Warblade_DeathInTheDark **** **** **** **** **** **** **** **** +17572 Warblade_DrainVitality **** **** **** **** **** **** **** **** +17573 Warblade_EnervatingShadowStrike **** **** **** **** **** **** **** **** +17574 Warblade_FiveShadowCreepingIceEnervationStrike **** **** **** **** **** **** **** **** +17575 Warblade_GhostBlade **** **** **** **** **** **** **** **** +17576 Warblade_HandOfDeath **** **** **** **** **** **** **** **** +17577 Warblade_IslandOfBlades **** **** **** **** **** **** **** **** +17578 Warblade_ObscuringShadowVeil **** **** **** **** **** **** **** **** +17579 Warblade_OneWithShadow **** **** **** **** **** **** **** **** +17580 Warblade_ShadowBladeTechnique **** **** **** **** **** **** **** **** +17581 Warblade_ShadowBlink **** **** **** **** **** **** **** **** +17582 Warblade_ShadowGarrote **** **** **** **** **** **** **** **** +17583 Warblade_ShadowJaunt **** **** **** **** **** **** **** **** +17584 Warblade_ShadowNoose **** **** **** **** **** **** **** **** +17585 Warblade_ShadowStride **** **** **** **** **** **** **** **** +17586 Warblade_StalkerInTheNight **** **** **** **** **** **** **** **** +17587 Warblade_StepOfTheDancingMoth **** **** **** **** **** **** **** **** +17588 Warblade_StrengthDrainingStrike **** **** **** **** **** **** **** **** +17589 Warblade_AdamantineBones **** **** **** **** **** **** **** **** +17590 Warblade_AncientMountainHammer **** **** **** **** **** **** **** **** +17591 Warblade_BonesplittingStrike **** **** **** **** **** **** **** **** +17592 Warblade_Bonecrusher **** **** **** **** **** **** **** **** +17593 Warblade_BoulderRoll **** **** **** **** **** **** **** **** +17594 Warblade_ChargingMinotaur **** **** **** **** **** **** **** **** +17595 Warblade_ColossusStrike **** **** **** **** **** **** **** **** +17596 Warblade_CrushingVise **** **** **** **** **** **** **** **** +17597 Warblade_CrushingWeightOfTheMountain **** **** **** **** **** **** **** **** +17598 Warblade_EarthstrikeQuake **** **** **** **** **** **** **** **** +17599 Warblade_ElderMountainHammer **** **** **** **** **** **** **** **** +17600 Warblade_GiantsStance **** **** **** **** **** **** **** **** +17601 Warblade_IronBones **** **** **** **** **** **** **** **** +17602 Warblade_IrresistibleMountainStrike **** **** **** **** **** **** **** **** +17603 Warblade_MountainAvalanche **** **** **** **** **** **** **** **** +17604 Warblade_MountainHammer **** **** **** **** **** **** **** **** +17605 Warblade_MountainTombstoneStrike **** **** **** **** **** **** **** **** +17606 Warblade_OverwhelmingMountainStrike **** **** **** **** **** **** **** **** +17607 Warblade_RootsOfTheMountain **** **** **** **** **** **** **** **** +17608 Warblade_StoneBones **** **** **** **** **** **** **** **** +17609 Warblade_StoneDragonsFury **** **** **** **** **** **** **** **** +17610 Warblade_StoneVise **** **** **** **** **** **** **** **** +17611 Warblade_StonefootStance **** **** **** **** **** **** **** **** +17612 Warblade_StrengthOfStone **** **** **** **** **** **** **** **** +17613 Warblade_BloodInTheWater **** **** **** **** **** **** **** **** +17614 Warblade_ClawAtTheMoon **** **** **** **** **** **** **** **** +17615 Warblade_DancingMongoose **** **** **** **** **** **** **** **** +17616 Warblade_DeathFromAbove **** **** **** **** **** **** **** **** +17617 Warblade_FeralDeathBlow **** **** **** **** **** **** **** **** +17618 Warblade_FleshRipper **** **** **** **** **** **** **** **** +17619 Warblade_FountainOfBlood **** **** **** **** **** **** **** **** +17620 Warblade_GirallonWindmillFleshRip **** **** **** **** **** **** **** **** +17621 Warblade_HamstringAttack **** **** **** **** **** **** **** **** +17622 Warblade_HuntersSense **** **** **** **** **** **** **** **** +17623 Warblade_LeapingDragonStance **** **** **** **** **** **** **** **** +17624 Warblade_PouncingCharge **** **** **** **** **** **** **** **** +17625 Warblade_PreyOnTheWeak **** **** **** **** **** **** **** **** +17626 Warblade_RabidBearStrike **** **** **** **** **** **** **** **** +17627 Warblade_RabidWolfStrike **** **** **** **** **** **** **** **** +17628 Warblade_RagingMongoose **** **** **** **** **** **** **** **** +17629 Warblade_SoaringRaptorStrike **** **** **** **** **** **** **** **** +17630 Warblade_SuddenLeap **** **** **** **** **** **** **** **** +17631 Warblade_SwoopingDragonStrike **** **** **** **** **** **** **** **** +17632 Warblade_WolfClimbsTheMountain **** **** **** **** **** **** **** **** +17633 Warblade_WolfFangStrike **** **** **** **** **** **** **** **** +17634 Warblade_WolfPackTactics **** **** **** **** **** **** **** **** +17635 Warblade_WolverineStance **** **** **** **** **** **** **** **** +17636 Warblade_BattleLeadersCharge **** **** **** **** **** **** **** **** +17637 Warblade_BolsteringVoice **** **** **** **** **** **** **** **** +17638 Warblade_ClarionCall **** **** **** **** **** **** **** **** +17639 Warblade_CoveringStrike **** **** **** **** **** **** **** **** +17640 Warblade_DouseTheFlames **** **** **** **** **** **** **** **** +17641 Warblade_FlankingManeuver **** **** **** **** **** **** **** **** +17642 Warblade_LeadingTheAttack **** **** **** **** **** **** **** **** +17643 Warblade_LeadingTheCharge **** **** **** **** **** **** **** **** +17644 Warblade_LionsRoar **** **** **** **** **** **** **** **** +17645 Warblade_OrderForgedFromChaos **** **** **** **** **** **** **** **** +17646 Warblade_PressTheAdvantage **** **** **** **** **** **** **** **** +17647 Warblade_SwarmTactics **** **** **** **** **** **** **** **** +17648 Warblade_SwarmingAssault **** **** **** **** **** **** **** **** +17649 Warblade_TacticalStrike **** **** **** **** **** **** **** **** +17650 Warblade_TacticsOfTheWolf **** **** **** **** **** **** **** **** +17651 Warblade_WarLeadersCharge **** **** **** **** **** **** **** **** +17652 Warblade_WarMastersCharge **** **** **** **** **** **** **** **** +17653 Warblade_WhiteRavenHammer **** **** **** **** **** **** **** **** +17654 Warblade_WhiteRavenStrike **** **** **** **** **** **** **** **** +17655 Warblade_WhiteRavenTactics **** **** **** **** **** **** **** **** +17656 **** **** **** **** **** **** **** **** **** +17657 **** **** **** **** **** **** **** **** **** +17658 **** **** **** **** **** **** **** **** **** +17659 **** **** **** **** **** **** **** **** **** +17660 **** **** **** **** **** **** **** **** **** +17661 **** **** **** **** **** **** **** **** **** +17662 **** **** **** **** **** **** **** **** **** +17663 **** **** **** **** **** **** **** **** **** +17664 **** **** **** **** **** **** **** **** **** +17665 **** **** **** **** **** **** **** **** **** +17666 **** **** **** **** **** **** **** **** **** +17667 **** **** **** **** **** **** **** **** **** +17668 **** **** **** **** **** **** **** **** **** +17669 **** **** **** **** **** **** **** **** **** +17670 **** **** **** **** **** **** **** **** **** +17671 **** **** **** **** **** **** **** **** **** +17672 **** **** **** **** **** **** **** **** **** +17673 **** **** **** **** **** **** **** **** **** +17674 **** **** **** **** **** **** **** **** **** +17675 **** **** **** **** **** **** **** **** **** +17676 **** **** **** **** **** **** **** **** **** +17677 **** **** **** **** **** **** **** **** **** +17678 **** **** **** **** **** **** **** **** **** +17679 **** **** **** **** **** **** **** **** **** +17680 **** **** **** **** **** **** **** **** **** +17681 **** **** **** **** **** **** **** **** **** +17682 **** **** **** **** **** **** **** **** **** +17683 **** **** **** **** **** **** **** **** **** +17684 **** **** **** **** **** **** **** **** **** +17685 **** **** **** **** **** **** **** **** **** +17686 **** **** **** **** **** **** **** **** **** +17687 **** **** **** **** **** **** **** **** **** +17688 **** **** **** **** **** **** **** **** **** +17689 **** **** **** **** **** **** **** **** **** +17690 **** **** **** **** **** **** **** **** **** +17691 **** **** **** **** **** **** **** **** **** +17692 **** **** **** **** **** **** **** **** **** +17693 **** **** **** **** **** **** **** **** **** +17694 **** **** **** **** **** **** **** **** **** +17695 **** **** **** **** **** **** **** **** **** +17696 **** **** **** **** **** **** **** **** **** +17697 **** **** **** **** **** **** **** **** **** +17698 **** **** **** **** **** **** **** **** **** +17699 **** **** **** **** **** **** **** **** **** +17700 **** **** **** **** **** **** **** **** **** +17701 **** **** **** **** **** **** **** **** **** +17702 **** **** **** **** **** **** **** **** **** +17703 **** **** **** **** **** **** **** **** **** +17704 **** **** **** **** **** **** **** **** **** +17705 **** **** **** **** **** **** **** **** **** +17706 **** **** **** **** **** **** **** **** **** +17707 **** **** **** **** **** **** **** **** **** +17708 **** **** **** **** **** **** **** **** **** +17709 **** **** **** **** **** **** **** **** **** +17710 **** **** **** **** **** **** **** **** **** +17711 **** **** **** **** **** **** **** **** **** +17712 **** **** **** **** **** **** **** **** **** +17713 **** **** **** **** **** **** **** **** **** +17714 **** **** **** **** **** **** **** **** **** +17715 **** **** **** **** **** **** **** **** **** +17716 **** **** **** **** **** **** **** **** **** +17717 **** **** **** **** **** **** **** **** **** +17718 **** **** **** **** **** **** **** **** **** +17719 **** **** **** **** **** **** **** **** **** +17720 **** **** **** **** **** **** **** **** **** +17721 **** **** **** **** **** **** **** **** **** +17722 **** **** **** **** **** **** **** **** **** +17723 **** **** **** **** **** **** **** **** **** +17724 **** **** **** **** **** **** **** **** **** +17725 **** **** **** **** **** **** **** **** **** +17726 **** **** **** **** **** **** **** **** **** +17727 **** **** **** **** **** **** **** **** **** +17728 **** **** **** **** **** **** **** **** **** +17729 **** **** **** **** **** **** **** **** **** +17730 **** **** **** **** **** **** **** **** **** +17731 **** **** **** **** **** **** **** **** **** +17732 **** **** **** **** **** **** **** **** **** +17733 **** **** **** **** **** **** **** **** **** +17734 **** **** **** **** **** **** **** **** **** +17735 **** **** **** **** **** **** **** **** **** +17736 **** **** **** **** **** **** **** **** **** +17737 **** **** **** **** **** **** **** **** **** +17738 **** **** **** **** **** **** **** **** **** +17739 **** **** **** **** **** **** **** **** **** +17740 **** **** **** **** **** **** **** **** **** +17741 **** **** **** **** **** **** **** **** **** +17742 **** **** **** **** **** **** **** **** **** +17743 **** **** **** **** **** **** **** **** **** +17744 **** **** **** **** **** **** **** **** **** +17745 **** **** **** **** **** **** **** **** **** +17746 **** **** **** **** **** **** **** **** **** +17747 **** **** **** **** **** **** **** **** **** +17748 **** **** **** **** **** **** **** **** **** +17749 **** **** **** **** **** **** **** **** **** +17750 **** **** **** **** **** **** **** **** **** +17751 **** **** **** **** **** **** **** **** **** +17752 **** **** **** **** **** **** **** **** **** +17753 **** **** **** **** **** **** **** **** **** +17754 **** **** **** **** **** **** **** **** **** +17755 **** **** **** **** **** **** **** **** **** +17756 **** **** **** **** **** **** **** **** **** +17757 **** **** **** **** **** **** **** **** **** +17758 **** **** **** **** **** **** **** **** **** +17759 **** **** **** **** **** **** **** **** **** +17760 **** **** **** **** **** **** **** **** **** +17761 **** **** **** **** **** **** **** **** **** +17762 **** **** **** **** **** **** **** **** **** +17763 **** **** **** **** **** **** **** **** **** +17764 **** **** **** **** **** **** **** **** **** +17765 **** **** **** **** **** **** **** **** **** +17766 **** **** **** **** **** **** **** **** **** +17767 **** **** **** **** **** **** **** **** **** +17768 **** **** **** **** **** **** **** **** **** +17769 **** **** **** **** **** **** **** **** **** +17770 **** **** **** **** **** **** **** **** **** +17771 **** **** **** **** **** **** **** **** **** +17772 **** **** **** **** **** **** **** **** **** +17773 **** **** **** **** **** **** **** **** **** +17774 **** **** **** **** **** **** **** **** **** +17775 **** **** **** **** **** **** **** **** **** +17776 **** **** **** **** **** **** **** **** **** +17777 **** **** **** **** **** **** **** **** **** +17778 **** **** **** **** **** **** **** **** **** +17779 **** **** **** **** **** **** **** **** **** +17780 **** **** **** **** **** **** **** **** **** +17781 **** **** **** **** **** **** **** **** **** +17782 **** **** **** **** **** **** **** **** **** +17783 **** **** **** **** **** **** **** **** **** +17784 **** **** **** **** **** **** **** **** **** +17785 **** **** **** **** **** **** **** **** **** +17786 **** **** **** **** **** **** **** **** **** +17787 **** **** **** **** **** **** **** **** **** +17788 **** **** **** **** **** **** **** **** **** +17789 **** **** **** **** **** **** **** **** **** +17790 **** **** **** **** **** **** **** **** **** +17791 **** **** **** **** **** **** **** **** **** +17792 **** **** **** **** **** **** **** **** **** +17793 **** **** **** **** **** **** **** **** **** +17794 **** **** **** **** **** **** **** **** **** +17795 **** **** **** **** **** **** **** **** **** +17796 **** **** **** **** **** **** **** **** **** +17797 **** **** **** **** **** **** **** **** **** +17798 **** **** **** **** **** **** **** **** **** +17799 **** **** **** **** **** **** **** **** **** +17800 **** **** **** **** **** **** **** **** **** +17801 **** **** **** **** **** **** **** **** **** +17802 **** **** **** **** **** **** **** **** **** +17803 **** **** **** **** **** **** **** **** **** +17804 **** **** **** **** **** **** **** **** **** +17805 **** **** **** **** **** **** **** **** **** +17806 **** **** **** **** **** **** **** **** **** +17807 **** **** **** **** **** **** **** **** **** +17808 **** **** **** **** **** **** **** **** **** +17809 **** **** **** **** **** **** **** **** **** +17810 **** **** **** **** **** **** **** **** **** +17811 **** **** **** **** **** **** **** **** **** +17812 **** **** **** **** **** **** **** **** **** +17813 **** **** **** **** **** **** **** **** **** +17814 **** **** **** **** **** **** **** **** **** +17815 **** **** **** **** **** **** **** **** **** +17816 **** **** **** **** **** **** **** **** **** +17817 **** **** **** **** **** **** **** **** **** +17818 **** **** **** **** **** **** **** **** **** +17819 **** **** **** **** **** **** **** **** **** +17820 **** **** **** **** **** **** **** **** **** +17821 **** **** **** **** **** **** **** **** **** +17822 **** **** **** **** **** **** **** **** **** +17823 **** **** **** **** **** **** **** **** **** +17824 **** **** **** **** **** **** **** **** **** +17825 **** **** **** **** **** **** **** **** **** +17826 **** **** **** **** **** **** **** **** **** +17827 **** **** **** **** **** **** **** **** **** +17828 **** **** **** **** **** **** **** **** **** +17829 **** **** **** **** **** **** **** **** **** +17830 **** **** **** **** **** **** **** **** **** +17831 **** **** **** **** **** **** **** **** **** +17832 **** **** **** **** **** **** **** **** **** +17833 **** **** **** **** **** **** **** **** **** +17834 **** **** **** **** **** **** **** **** **** +17835 **** **** **** **** **** **** **** **** **** +17836 **** **** **** **** **** **** **** **** **** +17837 **** **** **** **** **** **** **** **** **** +17838 **** **** **** **** **** **** **** **** **** +17839 **** **** **** **** **** **** **** **** **** +17840 **** **** **** **** **** **** **** **** **** +17841 **** **** **** **** **** **** **** **** **** +17842 **** **** **** **** **** **** **** **** **** +17843 **** **** **** **** **** **** **** **** **** +17844 **** **** **** **** **** **** **** **** **** +17845 **** **** **** **** **** **** **** **** **** +17846 **** **** **** **** **** **** **** **** **** +17847 **** **** **** **** **** **** **** **** **** +17848 **** **** **** **** **** **** **** **** **** +17849 **** **** **** **** **** **** **** **** **** +17850 **** **** **** **** **** **** **** **** **** +17851 **** **** **** **** **** **** **** **** **** +17852 **** **** **** **** **** **** **** **** **** +17853 **** **** **** **** **** **** **** **** **** +17854 **** **** **** **** **** **** **** **** **** +17855 **** **** **** **** **** **** **** **** **** +17856 **** **** **** **** **** **** **** **** **** +17857 **** **** **** **** **** **** **** **** **** +17858 **** **** **** **** **** **** **** **** **** +17859 **** **** **** **** **** **** **** **** **** +17860 **** **** **** **** **** **** **** **** **** +17861 **** **** **** **** **** **** **** **** **** +17862 **** **** **** **** **** **** **** **** **** +17863 **** **** **** **** **** **** **** **** **** +17864 **** **** **** **** **** **** **** **** **** +17865 **** **** **** **** **** **** **** **** **** +17866 **** **** **** **** **** **** **** **** **** +17867 **** **** **** **** **** **** **** **** **** +17868 **** **** **** **** **** **** **** **** **** +17869 **** **** **** **** **** **** **** **** **** +17870 **** **** **** **** **** **** **** **** **** +17871 **** **** **** **** **** **** **** **** **** +17872 **** **** **** **** **** **** **** **** **** +17873 **** **** **** **** **** **** **** **** **** +17874 **** **** **** **** **** **** **** **** **** +17875 **** **** **** **** **** **** **** **** **** +17876 **** **** **** **** **** **** **** **** **** +17877 **** **** **** **** **** **** **** **** **** +17878 **** **** **** **** **** **** **** **** **** +17879 **** **** **** **** **** **** **** **** **** +17880 **** **** **** **** **** **** **** **** **** +17881 **** **** **** **** **** **** **** **** **** +17882 **** **** **** **** **** **** **** **** **** +17883 **** **** **** **** **** **** **** **** **** +17884 **** **** **** **** **** **** **** **** **** +17885 **** **** **** **** **** **** **** **** **** +17886 **** **** **** **** **** **** **** **** **** +17887 **** **** **** **** **** **** **** **** **** +17888 **** **** **** **** **** **** **** **** **** +17889 **** **** **** **** **** **** **** **** **** +17890 **** **** **** **** **** **** **** **** **** +17891 **** **** **** **** **** **** **** **** **** +17892 **** **** **** **** **** **** **** **** **** +17893 **** **** **** **** **** **** **** **** **** +17894 **** **** **** **** **** **** **** **** **** +17895 **** **** **** **** **** **** **** **** **** +17896 **** **** **** **** **** **** **** **** **** +17897 **** **** **** **** **** **** **** **** **** +17898 **** **** **** **** **** **** **** **** **** +17899 **** **** **** **** **** **** **** **** **** +17900 **** **** **** **** **** **** **** **** **** +17901 **** **** **** **** **** **** **** **** **** +17902 **** **** **** **** **** **** **** **** **** +17903 **** **** **** **** **** **** **** **** **** +17904 **** **** **** **** **** **** **** **** **** +17905 **** **** **** **** **** **** **** **** **** +17906 **** **** **** **** **** **** **** **** **** +17907 **** **** **** **** **** **** **** **** **** +17908 **** **** **** **** **** **** **** **** **** +17909 **** **** **** **** **** **** **** **** **** +17910 **** **** **** **** **** **** **** **** **** +17911 **** **** **** **** **** **** **** **** **** +17912 **** **** **** **** **** **** **** **** **** +17913 **** **** **** **** **** **** **** **** **** +17914 **** **** **** **** **** **** **** **** **** +17915 **** **** **** **** **** **** **** **** **** +17916 **** **** **** **** **** **** **** **** **** +17917 **** **** **** **** **** **** **** **** **** +17918 **** **** **** **** **** **** **** **** **** +17919 **** **** **** **** **** **** **** **** **** +17920 **** **** **** **** **** **** **** **** **** +17921 **** **** **** **** **** **** **** **** **** +17922 **** **** **** **** **** **** **** **** **** +17923 **** **** **** **** **** **** **** **** **** +17924 **** **** **** **** **** **** **** **** **** +17925 **** **** **** **** **** **** **** **** **** +17926 **** **** **** **** **** **** **** **** **** +17927 **** **** **** **** **** **** **** **** **** +17928 **** **** **** **** **** **** **** **** **** +17929 **** **** **** **** **** **** **** **** **** +17930 **** **** **** **** **** **** **** **** **** +17931 **** **** **** **** **** **** **** **** **** +17932 **** **** **** **** **** **** **** **** **** +17933 **** **** **** **** **** **** **** **** **** +17934 **** **** **** **** **** **** **** **** **** +17935 **** **** **** **** **** **** **** **** **** +17936 **** **** **** **** **** **** **** **** **** +17937 **** **** **** **** **** **** **** **** **** +17938 **** **** **** **** **** **** **** **** **** +17939 **** **** **** **** **** **** **** **** **** +17940 **** **** **** **** **** **** **** **** **** +17941 **** **** **** **** **** **** **** **** **** +17942 **** **** **** **** **** **** **** **** **** +17943 **** **** **** **** **** **** **** **** **** +17944 **** **** **** **** **** **** **** **** **** +17945 **** **** **** **** **** **** **** **** **** +17946 **** **** **** **** **** **** **** **** **** +17947 **** **** **** **** **** **** **** **** **** +17948 **** **** **** **** **** **** **** **** **** +17949 **** **** **** **** **** **** **** **** **** +17950 **** **** **** **** **** **** **** **** **** +17951 **** **** **** **** **** **** **** **** **** +17952 **** **** **** **** **** **** **** **** **** +17953 **** **** **** **** **** **** **** **** **** +17954 **** **** **** **** **** **** **** **** **** +17955 **** **** **** **** **** **** **** **** **** +17956 **** **** **** **** **** **** **** **** **** +17957 **** **** **** **** **** **** **** **** **** +17958 **** **** **** **** **** **** **** **** **** +17959 **** **** **** **** **** **** **** **** **** +17960 **** **** **** **** **** **** **** **** **** +17961 **** **** **** **** **** **** **** **** **** +17962 **** **** **** **** **** **** **** **** **** +17963 **** **** **** **** **** **** **** **** **** +17964 **** **** **** **** **** **** **** **** **** +17965 **** **** **** **** **** **** **** **** **** +17966 **** **** **** **** **** **** **** **** **** +17967 **** **** **** **** **** **** **** **** **** +17968 **** **** **** **** **** **** **** **** **** +17969 **** **** **** **** **** **** **** **** **** +17970 **** **** **** **** **** **** **** **** **** +17971 **** **** **** **** **** **** **** **** **** +17972 **** **** **** **** **** **** **** **** **** +17973 **** **** **** **** **** **** **** **** **** +17974 **** **** **** **** **** **** **** **** **** +17975 **** **** **** **** **** **** **** **** **** +17976 **** **** **** **** **** **** **** **** **** +17977 **** **** **** **** **** **** **** **** **** +17978 **** **** **** **** **** **** **** **** **** +17979 **** **** **** **** **** **** **** **** **** +17980 **** **** **** **** **** **** **** **** **** +17981 **** **** **** **** **** **** **** **** **** +17982 **** **** **** **** **** **** **** **** **** +17983 **** **** **** **** **** **** **** **** **** +17984 **** **** **** **** **** **** **** **** **** +17985 **** **** **** **** **** **** **** **** **** +17986 **** **** **** **** **** **** **** **** **** +17987 **** **** **** **** **** **** **** **** **** +17988 **** **** **** **** **** **** **** **** **** +17989 **** **** **** **** **** **** **** **** **** +17990 **** **** **** **** **** **** **** **** **** +17991 **** **** **** **** **** **** **** **** **** +17992 **** **** **** **** **** **** **** **** **** +17993 **** **** **** **** **** **** **** **** **** +17994 **** **** **** **** **** **** **** **** **** +17995 **** **** **** **** **** **** **** **** **** +17996 **** **** **** **** **** **** **** **** **** +17997 **** **** **** **** **** **** **** **** **** +17998 **** **** **** **** **** **** **** **** **** +17999 ####END_OF_TOB_SPELLBOOK_RESERVE **** **** **** **** **** **** **** **** +18000 **BEGIN_INVOCATIONS** **** **** **** **** **** **** **** **** +18001 BeguilingInfluence **** **** **** **** **** **** **** **** +18002 BreathOfTheNight **** **** **** **** **** **** **** **** +18003 Darkness **** **** **** **** **** **** **** **** +18004 DeafeningRoar **** **** **** **** **** **** **** **** +18005 DraconicKnowledge **** **** **** **** **** **** **** **** +18006 EndureExposure **** **** **** **** **** **** **** **** +18007 MagicInsight **** **** **** **** **** **** **** **** +18008 ScaldingGust **** **** **** **** **** **** **** **** +18009 SeeTheUnseen **** **** **** **** **** **** **** **** +18010 Charm **** **** **** **** **** **** **** **** +18011 EnergyResistance **** **** **** **** **** **** **** **** +18012 EnergyResistanceAcid **** **** **** **** **** **** **** **** +18013 EnergyResistanceCold **** **** **** **** **** **** **** **** +18014 EnergyResistanceElectric **** **** **** **** **** **** **** **** +18015 EnergyResistanceFire **** **** **** **** **** **** **** **** +18016 EnergyResistanceSonic **** **** **** **** **** **** **** **** +18017 FrightfulPresence **** **** **** **** **** **** **** **** +18018 HumanoidShape **** **** **** **** **** **** **** **** +18019 HumanoidShape_Select_Form **** **** **** **** **** **** **** **** +18020 HumanoidShape_Options **** **** **** **** **** **** **** **** +18021 HumanoidShape_True_Form **** **** **** **** **** **** **** **** +18022 HumanoidShape_Quickslot_1 **** **** **** **** **** **** **** **** +18023 HumanoidShape_Quickslot_2 **** **** **** **** **** **** **** **** +18024 Voidsense **** **** **** **** **** **** **** **** +18025 VoraciousDispelling **** **** **** **** **** **** **** **** +18026 WalkUnseen **** **** **** **** **** **** **** **** +18027 AuraOfFlame **** **** **** **** **** **** **** **** +18028 ChillingFog **** **** **** **** **** **** **** **** +18029 DevourMagic **** **** **** **** **** **** **** **** +18030 DraconicToughness **** **** **** **** **** **** **** **** +18031 TerrifyingRoar **** **** **** **** **** **** **** **** +18032 EnergyImmunity **** **** **** **** **** **** **** **** +18033 EnergyImmunityAcid **** **** **** **** **** **** **** **** +18034 EnergyImmunityCold **** **** **** **** **** **** **** **** +18035 EnergyImmunityElectric **** **** **** **** **** **** **** **** +18036 EnergyImmunityFire **** **** **** **** **** **** **** **** +18037 EnergyImmunitySonic **** **** **** **** **** **** **** **** +18038 InstillVulnerability **** **** **** **** **** **** **** **** +18039 InstillVulnerability_Acid **** **** **** **** **** **** **** **** +18040 InstillVulnerability_Cold **** **** **** **** **** **** **** **** +18041 InstillVulnerability_Elec **** **** **** **** **** **** **** **** +18042 InstillVulnerability_Fire **** **** **** **** **** **** **** **** +18043 InstillVulnerability_Sonic **** **** **** **** **** **** **** **** +18044 **Warlock_Invocations** **** **** **** **** **** **** **** **** +18045 AllSeeingEyes **** **** **** **** **** **** **** **** +18046 BalefulUtterance **** **** **** **** **** **** **** **** +18047 CallOfTheBeast **** **** **** **** **** **** **** **** +18048 CocoonOfRefuse **** **** **** **** **** **** **** **** +18049 DarkOnesOwnLuck **** **** **** **** **** **** **** **** +18050 DarkOnesOwnLuck_Fort **** **** **** **** **** **** **** **** +18051 DarkOnesOwnLuck_Reflex **** **** **** **** **** **** **** **** +18052 DarkOnesOwnLuck_Will **** **** **** **** **** **** **** **** +18053 DevilsSight **** **** **** **** **** **** **** **** +18054 **Drain_Incarnum** **** **** **** **** **** **** **** **** +18055 EarthenGrasp **** **** **** **** **** **** **** **** +18056 EldritchGlaive **** **** **** **** **** **** **** **** +18057 EldritchGlaiveOnHit **** **** **** **** **** **** **** **** +18058 EldritchSpear **** **** **** **** **** **** **** **** +18059 EntropicWarding **** **** **** **** **** **** **** **** +18060 FrightfulBlast **** **** **** **** **** **** **** **** +18061 HammerBlast **** **** **** **** **** **** **** **** +18062 HideousBlow **** **** **** **** **** **** **** **** +18063 LeapsAndBounds **** **** **** **** **** **** **** **** +18064 MiasmicCloud **** **** **** **** **** **** **** **** +18065 OtherworldlyWhispers **** **** **** **** **** **** **** **** +18066 SerpentsTongue **** **** **** **** **** **** **** **** +18067 SickeningBlast **** **** **** **** **** **** **** **** +18068 SoulreavingAura **** **** **** **** **** **** **** **** +18069 SummonSwarm **** **** **** **** **** **** **** **** +18070 SummonSwarm_Rat **** **** **** **** **** **** **** **** +18071 SummonSwarm_Bat **** **** **** **** **** **** **** **** +18072 SwimmingTheStyx **** **** **** **** **** **** **** **** +18073 BanefulBlastAbberation **** **** **** **** **** **** **** **** +18074 BanefulBlastBeast **** **** **** **** **** **** **** **** +18075 BanefulBlastConstruct **** **** **** **** **** **** **** **** +18076 BanefulBlastDragon **** **** **** **** **** **** **** **** +18077 BanefulBlastDwarf **** **** **** **** **** **** **** **** +18078 BanefulBlastElemental **** **** **** **** **** **** **** **** +18079 BanefulBlastElf **** **** **** **** **** **** **** **** +18080 BanefulBlastFey **** **** **** **** **** **** **** **** +18081 BanefulBlastGiant **** **** **** **** **** **** **** **** +18082 BanefulBlastGoblinoid **** **** **** **** **** **** **** **** +18083 BanefulBlastGnome **** **** **** **** **** **** **** **** +18084 BanefulBlastHalfling **** **** **** **** **** **** **** **** +18085 BanefulBlastHuman **** **** **** **** **** **** **** **** +18086 BanefulBlastMonsterous **** **** **** **** **** **** **** **** +18087 BanefulBlastOrc **** **** **** **** **** **** **** **** +18088 BanefulBlastOutsider **** **** **** **** **** **** **** **** +18089 BanefulBlastPlant **** **** **** **** **** **** **** **** +18090 BanefulBlastReptilian **** **** **** **** **** **** **** **** +18091 BanefulBlastShapechanger **** **** **** **** **** **** **** **** +18092 BanefulBlastUndead **** **** **** **** **** **** **** **** +18093 BanefulBlastVermin **** **** **** **** **** **** **** **** +18094 BeshadowedBlast **** **** **** **** **** **** **** **** +18095 BrimstoneBlast **** **** **** **** **** **** **** **** +18096 ColdComfort **** **** **** **** **** **** **** **** +18097 CurseOfDespair **** **** **** **** **** **** **** **** +18098 DreadSeizure **** **** **** **** **** **** **** **** +18099 EldritchChain **** **** **** **** **** **** **** **** +18100 FleeTheScene **** **** **** **** **** **** **** **** +18101 FleeTheScene_Selected **** **** **** **** **** **** **** **** +18102 FleeTheScene_Direction_and_Distance **** **** **** **** **** **** **** **** +18103 HellrimeBlast **** **** **** **** **** **** **** **** +18104 HungryDarkness **** **** **** **** **** **** **** **** +18105 IgnoreThePyre **** **** **** **** **** **** **** **** +18106 IgnoreThePyreAcid **** **** **** **** **** **** **** **** +18107 IgnoreThePyreCold **** **** **** **** **** **** **** **** +18108 IgnoreThePyreElec **** **** **** **** **** **** **** **** +18109 IgnoreThePyreFire **** **** **** **** **** **** **** **** +18110 IgnoreThePyreSonic **** **** **** **** **** **** **** **** +18111 MaskOfFlesh **** **** **** **** **** **** **** **** +18112 MaskOfFleshFriendly **** **** **** **** **** **** **** **** +18113 MaskOfFleshHostile **** **** **** **** **** **** **** **** +18114 RelentlessDispelling **** **** **** **** **** **** **** **** +18115 SpiderShape **** **** **** **** **** **** **** **** +18116 **Steal_Incarnum** **** **** **** **** **** **** **** **** +18117 StonyGrasp **** **** **** **** **** **** **** **** +18118 TheDeadWalk **** **** **** **** **** **** **** **** +18119 WallOfGloom **** **** **** **** **** **** **** **** +18120 WitchwoodStep **** **** **** **** **** **** **** **** +18121 BewitchingBlast **** **** **** **** **** **** **** **** +18122 CausticMire **** **** **** **** **** **** **** **** +18123 ChillingTentacles **** **** **** **** **** **** **** **** +18124 DragonWard **** **** **** **** **** **** **** **** +18125 EldritchCone **** **** **** **** **** **** **** **** +18126 EldritchLine **** **** **** **** **** **** **** **** +18127 EnervatingShadow **** **** **** **** **** **** **** **** +18128 HellspawnedGrace **** **** **** **** **** **** **** **** +18129 HinderingBlast **** **** **** **** **** **** **** **** +18130 **Incarnum_Blast** **** **** **** **** **** **** **** **** +18131 NightmaresMadeReal **** **** **** **** **** **** **** **** +18132 NoxiousBlast **** **** **** **** **** **** **** **** +18133 PainfulSlumberOfTheAges **** **** **** **** **** **** **** **** +18134 PenetratingBlast **** **** **** **** **** **** **** **** +18135 TenaciousPlague **** **** **** **** **** **** **** **** +18136 VitriolicBlast **** **** **** **** **** **** **** **** +18137 WallOfPerilousFlame **** **** **** **** **** **** **** **** +18138 BindingBlast **** **** **** **** **** **** **** **** +18139 CastersLament **** **** **** **** **** **** **** **** +18140 DarkDiscorporation **** **** **** **** **** **** **** **** +18141 DarkForesight **** **** **** **** **** **** **** **** +18142 EldritchDoom **** **** **** **** **** **** **** **** +18143 **Incarnum_Shroud** **** **** **** **** **** **** **** **** +18144 PathOfShadow **** **** **** **** **** **** **** **** +18145 PathOfShadowSelf **** **** **** **** **** **** **** **** +18146 PathOfShadowParty **** **** **** **** **** **** **** **** +18147 RetributiveInvisibility **** **** **** **** **** **** **** **** +18148 StealSummoning **** **** **** **** **** **** **** **** +18149 UtterdarkBlast **** **** **** **** **** **** **** **** +18150 WordOfChanging **** **** **** **** **** **** **** **** +18151 **Enlightened_Spirit_Invocations** **** **** **** **** **** **** **** **** +18152 **** **** **** **** **** **** **** **** **** +18153 **** **** **** **** **** **** **** **** **** +18154 **** **** **** **** **** **** **** **** **** +18155 **** **** **** **** **** **** **** **** **** +18156 **** **** **** **** **** **** **** **** **** +18157 **** **** **** **** **** **** **** **** **** +18158 ####START_OF_INV_SPELLBOOK_RESERVE **** **** **** **** **** **** **** **** +18159 Warlock_AllSeeingEyes **** **** **** **** **** **** **** **** +18160 Warlock_BalefulUtterance **** **** **** **** **** **** **** **** +18161 Warlock_BeguilingInfluence **** **** **** **** **** **** **** **** +18162 Warlock_BreathOfTheNight **** **** **** **** **** **** **** **** +18163 Warlock_CallOfTheBeast **** **** **** **** **** **** **** **** +18164 Warlock_CocoonOfRefuse **** **** **** **** **** **** **** **** +18165 Warlock_Darkness **** **** **** **** **** **** **** **** +18166 Warlock_DarkOnesOwnLuck **** **** **** **** **** **** **** **** +18167 Warlock_DarkOnesOwnLuck_Fort **** **** **** **** **** **** **** **** +18168 Warlock_DarkOnesOwnLuck_Reflex **** **** **** **** **** **** **** **** +18169 Warlock_DarkOnesOwnLuck_Will **** **** **** **** **** **** **** **** +18170 Warlock_DevilsSight **** **** **** **** **** **** **** **** +18171 Warlock_EarthenGrasp **** **** **** **** **** **** **** **** +18172 Warlock_EldritchGlaive **** **** **** **** **** **** **** **** +18173 Warlock_EldritchSpear **** **** **** **** **** **** **** **** +18174 Warlock_EntropicWarding **** **** **** **** **** **** **** **** +18175 Warlock_FrightfulBlast **** **** **** **** **** **** **** **** +18176 Warlock_HammerBlast **** **** **** **** **** **** **** **** +18177 Warlock_HideousBlow **** **** **** **** **** **** **** **** +18178 Warlock_LeapsAndBounds **** **** **** **** **** **** **** **** +18179 Warlock_MiasmicCloud **** **** **** **** **** **** **** **** +18180 Warlock_OtherworldlyWhispers **** **** **** **** **** **** **** **** +18181 Warlock_SeeTheUnseen **** **** **** **** **** **** **** **** +18182 Warlock_SerpentsTongue **** **** **** **** **** **** **** **** +18183 Warlock_SickeningBlast **** **** **** **** **** **** **** **** +18184 Warlock_SoulreavingAura **** **** **** **** **** **** **** **** +18185 Warlock_SummonSwarm **** **** **** **** **** **** **** **** +18186 Warlock_SummonSwarm_Rat **** **** **** **** **** **** **** **** +18187 Warlock_SummonSwarm_Bat **** **** **** **** **** **** **** **** +18188 Warlock_SwimmingTheStyx **** **** **** **** **** **** **** **** +18189 Warlock_BanefulBlastAbberation **** **** **** **** **** **** **** **** +18190 Warlock_BanefulBlastBeast **** **** **** **** **** **** **** **** +18191 Warlock_BanefulBlastConstruct **** **** **** **** **** **** **** **** +18192 Warlock_BanefulBlastDragon **** **** **** **** **** **** **** **** +18193 Warlock_BanefulBlastDwarf **** **** **** **** **** **** **** **** +18194 Warlock_BanefulBlastElemental **** **** **** **** **** **** **** **** +18195 Warlock_BanefulBlastElf **** **** **** **** **** **** **** **** +18196 Warlock_BanefulBlastFey **** **** **** **** **** **** **** **** +18197 Warlock_BanefulBlastGiant **** **** **** **** **** **** **** **** +18198 Warlock_BanefulBlastGoblinoid **** **** **** **** **** **** **** **** +18199 Warlock_BanefulBlastGnome **** **** **** **** **** **** **** **** +18200 Warlock_BanefulBlastHalfling **** **** **** **** **** **** **** **** +18201 Warlock_BanefulBlastHuman **** **** **** **** **** **** **** **** +18202 Warlock_BanefulBlastMonsterous **** **** **** **** **** **** **** **** +18203 Warlock_BanefulBlastOrc **** **** **** **** **** **** **** **** +18204 Warlock_BanefulBlastOutsider **** **** **** **** **** **** **** **** +18205 Warlock_BanefulBlastPlant **** **** **** **** **** **** **** **** +18206 Warlock_BanefulBlastReptilian **** **** **** **** **** **** **** **** +18207 Warlock_BanefulBlastShapechanger **** **** **** **** **** **** **** **** +18208 Warlock_BanefulBlastUndead **** **** **** **** **** **** **** **** +18209 Warlock_BanefulBlastVermin **** **** **** **** **** **** **** **** +18210 Warlock_BeshadowedBlast **** **** **** **** **** **** **** **** +18211 Warlock_BrimstoneBlast **** **** **** **** **** **** **** **** +18212 Warlock_Charm **** **** **** **** **** **** **** **** +18213 Warlock_ColdComfort **** **** **** **** **** **** **** **** +18214 Warlock_CurseOfDespair **** **** **** **** **** **** **** **** +18215 Warlock_DreadSeizure **** **** **** **** **** **** **** **** +18216 Warlock_EldritchChain **** **** **** **** **** **** **** **** +18217 Warlock_FleeTheScene **** **** **** **** **** **** **** **** +18218 Warlock_FleeTheScene_Selected **** **** **** **** **** **** **** **** +18219 Warlock_FleeTheScene_Direction_and_Distance **** **** **** **** **** **** **** **** +18220 Warlock_HellrimeBlast **** **** **** **** **** **** **** **** +18221 Warlock_HungryDarkness **** **** **** **** **** **** **** **** +18222 Warlock_IgnoreThePyre **** **** **** **** **** **** **** **** +18223 Warlock_IgnoreThePyreAcid **** **** **** **** **** **** **** **** +18224 Warlock_IgnoreThePyreCold **** **** **** **** **** **** **** **** +18225 Warlock_IgnoreThePyreElec **** **** **** **** **** **** **** **** +18226 Warlock_IgnoreThePyreFire **** **** **** **** **** **** **** **** +18227 Warlock_IgnoreThePyreSonic **** **** **** **** **** **** **** **** +18228 Warlock_MaskOfFlesh **** **** **** **** **** **** **** **** +18229 Warlock_MaskOfFleshFriendly **** **** **** **** **** **** **** **** +18230 Warlock_MaskOfFleshHostile **** **** **** **** **** **** **** **** +18231 Warlock_RelentlessDispelling **** **** **** **** **** **** **** **** +18232 Warlock_SpiderShape **** **** **** **** **** **** **** **** +18233 Warlock_StonyGrasp **** **** **** **** **** **** **** **** +18234 Warlock_TheDeadWalk **** **** **** **** **** **** **** **** +18235 Warlock_Voidsense **** **** **** **** **** **** **** **** +18236 Warlock_VoraciousDispelling **** **** **** **** **** **** **** **** +18237 Warlock_WalkUnseen **** **** **** **** **** **** **** **** +18238 Warlock_WallOfGloom **** **** **** **** **** **** **** **** +18239 Warlock_WitchwoodStep **** **** **** **** **** **** **** **** +18240 Warlock_BewitchingBlast **** **** **** **** **** **** **** **** +18241 Warlock_CausticMire **** **** **** **** **** **** **** **** +18242 Warlock_ChillingTentacles **** **** **** **** **** **** **** **** +18243 Warlock_DevourMagic **** **** **** **** **** **** **** **** +18244 Warlock_DragonWard **** **** **** **** **** **** **** **** +18245 Warlock_EldritchCone **** **** **** **** **** **** **** **** +18246 Warlock_EldritchLine **** **** **** **** **** **** **** **** +18247 Warlock_EnervatingShadow **** **** **** **** **** **** **** **** +18248 Warlock_HellspawnedGrace **** **** **** **** **** **** **** **** +18249 Warlock_HinderingBlast **** **** **** **** **** **** **** **** +18250 Warlock_NightmaresMadeReal **** **** **** **** **** **** **** **** +18251 Warlock_NoxiousBlast **** **** **** **** **** **** **** **** +18252 Warlock_PainfulSlumberOfTheAges **** **** **** **** **** **** **** **** +18253 Warlock_PenetratingBlast **** **** **** **** **** **** **** **** +18254 Warlock_TenaciousPlague **** **** **** **** **** **** **** **** +18255 Warlock_VitriolicBlast **** **** **** **** **** **** **** **** +18256 Warlock_WallOfPerilousFlame **** **** **** **** **** **** **** **** +18257 Warlock_BindingBlast **** **** **** **** **** **** **** **** +18258 Warlock_CastersLament **** **** **** **** **** **** **** **** +18259 Warlock_DarkDiscorporation **** **** **** **** **** **** **** **** +18260 Warlock_DarkForesight **** **** **** **** **** **** **** **** +18261 Warlock_EldritchDoom **** **** **** **** **** **** **** **** +18262 Warlock_PathOfShadow **** **** **** **** **** **** **** **** +18263 Warlock_PathOfShadowSelf **** **** **** **** **** **** **** **** +18264 Warlock_PathOfShadowParty **** **** **** **** **** **** **** **** +18265 Warlock_RetributiveInvisibility **** **** **** **** **** **** **** **** +18266 Warlock_StealSummoning **** **** **** **** **** **** **** **** +18267 Warlock_UtterdarkBlast **** **** **** **** **** **** **** **** +18268 Warlock_WordOfChanging **** **** **** **** **** **** **** **** +18269 DragonShaman_BeguilingInfluence **** **** **** **** **** **** **** **** +18270 DragonShaman_BreathOfTheNight **** **** **** **** **** **** **** **** +18271 DragonShaman_Darkness **** **** **** **** **** **** **** **** +18272 DragonShaman_DeafeningRoar **** **** **** **** **** **** **** **** +18273 DragonShaman_DraconicKnowledge **** **** **** **** **** **** **** **** +18274 DragonShaman_EndureExposure **** **** **** **** **** **** **** **** +18275 DragonShaman_MagicInsight **** **** **** **** **** **** **** **** +18276 DragonShaman_ScaldingGust **** **** **** **** **** **** **** **** +18277 DragonShaman_SeeTheUnseen **** **** **** **** **** **** **** **** +18278 Dragonfire_Adept_BeguilingInfluence **** **** **** **** **** **** **** **** +18279 Dragonfire_Adept_BreathOfTheNight **** **** **** **** **** **** **** **** +18280 Dragonfire_Adept_Darkness **** **** **** **** **** **** **** **** +18281 Dragonfire_Adept_DeafeningRoar **** **** **** **** **** **** **** **** +18282 Dragonfire_Adept_DraconicKnowledge **** **** **** **** **** **** **** **** +18283 Dragonfire_Adept_EndureExposure **** **** **** **** **** **** **** **** +18284 Dragonfire_Adept_MagicInsight **** **** **** **** **** **** **** **** +18285 Dragonfire_Adept_ScaldingGust **** **** **** **** **** **** **** **** +18286 Dragonfire_Adept_SeeTheUnseen **** **** **** **** **** **** **** **** +18287 Dragonfire_Adept_Charm **** **** **** **** **** **** **** **** +18288 Dragonfire_Adept_EnergyResistance **** **** **** **** **** **** **** **** +18289 Dragonfire_Adept_EnergyResistanceAcid **** **** **** **** **** **** **** **** +18290 Dragonfire_Adept_EnergyResistanceCold **** **** **** **** **** **** **** **** +18291 Dragonfire_Adept_EnergyResistanceElectric **** **** **** **** **** **** **** **** +18292 Dragonfire_Adept_EnergyResistanceFire **** **** **** **** **** **** **** **** +18293 Dragonfire_Adept_EnergyResistanceSonic **** **** **** **** **** **** **** **** +18294 Dragonfire_Adept_FrightfulPresence **** **** **** **** **** **** **** **** +18295 Dragonfire_Adept_HumanoidShape **** **** **** **** **** **** **** **** +18296 Dragonfire_Adept_HumanoidShape_Select_Form **** **** **** **** **** **** **** **** +18297 Dragonfire_Adept_HumanoidShape_Options **** **** **** **** **** **** **** **** +18298 Dragonfire_Adept_HumanoidShape_True_Form **** **** **** **** **** **** **** **** +18299 Dragonfire_Adept_HumanoidShape_Quickslot_1 **** **** **** **** **** **** **** **** +18300 Dragonfire_Adept_HumanoidShape_Quickslot_2 **** **** **** **** **** **** **** **** +18301 Dragonfire_Adept_Voidsense **** **** **** **** **** **** **** **** +18302 Dragonfire_Adept_VoraciousDispelling **** **** **** **** **** **** **** **** +18303 Dragonfire_Adept_WalkUnseen **** **** **** **** **** **** **** **** +18304 Dragonfire_Adept_AuraOfFlame **** **** **** **** **** **** **** **** +18305 Dragonfire_Adept_ChillingFog **** **** **** **** **** **** **** **** +18306 Dragonfire_Adept_DevourMagic **** **** **** **** **** **** **** **** +18307 Dragonfire_Adept_DraconicToughness **** **** **** **** **** **** **** **** +18308 Dragonfire_Adept_TerrifyingRoar **** **** **** **** **** **** **** **** +18309 Dragonfire_Adept_EnergyImmunity **** **** **** **** **** **** **** **** +18310 Dragonfire_Adept_EnergyImmunityAcid **** **** **** **** **** **** **** **** +18311 Dragonfire_Adept_EnergyImmunityCold **** **** **** **** **** **** **** **** +18312 Dragonfire_Adept_EnergyImmunityElectric **** **** **** **** **** **** **** **** +18313 Dragonfire_Adept_EnergyImmunityFire **** **** **** **** **** **** **** **** +18314 Dragonfire_Adept_EnergyImmunitySonic **** **** **** **** **** **** **** **** +18315 Dragonfire_Adept_InstillVulnerability **** **** **** **** **** **** **** **** +18316 Dragonfire_Adept_InstillVulnerability_Acid **** **** **** **** **** **** **** **** +18317 Dragonfire_Adept_InstillVulnerability_Cold **** **** **** **** **** **** **** **** +18318 Dragonfire_Adept_InstillVulnerability_Elec **** **** **** **** **** **** **** **** +18319 Dragonfire_Adept_InstillVulnerability_Fire **** **** **** **** **** **** **** **** +18320 Dragonfire_Adept_InstillVulnerability_Sonic **** **** **** **** **** **** **** **** +18321 **** **** **** **** **** **** **** **** **** +18322 **** **** **** **** **** **** **** **** **** +18323 **** **** **** **** **** **** **** **** **** +18324 **** **** **** **** **** **** **** **** **** +18325 **** **** **** **** **** **** **** **** **** +18326 **** **** **** **** **** **** **** **** **** +18327 **** **** **** **** **** **** **** **** **** +18328 **** **** **** **** **** **** **** **** **** +18329 **** **** **** **** **** **** **** **** **** +18330 **** **** **** **** **** **** **** **** **** +18331 **** **** **** **** **** **** **** **** **** +18332 **** **** **** **** **** **** **** **** **** +18333 **** **** **** **** **** **** **** **** **** +18334 **** **** **** **** **** **** **** **** **** +18335 **** **** **** **** **** **** **** **** **** +18336 **** **** **** **** **** **** **** **** **** +18337 **** **** **** **** **** **** **** **** **** +18338 **** **** **** **** **** **** **** **** **** +18339 **** **** **** **** **** **** **** **** **** +18340 **** **** **** **** **** **** **** **** **** +18341 **** **** **** **** **** **** **** **** **** +18342 **** **** **** **** **** **** **** **** **** +18343 **** **** **** **** **** **** **** **** **** +18344 **** **** **** **** **** **** **** **** **** +18345 **** **** **** **** **** **** **** **** **** +18346 **** **** **** **** **** **** **** **** **** +18347 **** **** **** **** **** **** **** **** **** +18348 **** **** **** **** **** **** **** **** **** +18349 **** **** **** **** **** **** **** **** **** +18350 ####END_OF_INV_SPELLBOOK_RESERVE **** **** **** **** **** **** **** **** +18351 ####START_OF_SHADOW_MAGIC_RESERVE **** **** **** **** **** **** **** **** +18352 BendPerspective **** **** **** **** **** **** **** **** +18353 CarpetShadow **** **** **** **** **** **** **** **** +18354 DuskAndDawn_Dusk **** **** **** **** **** **** **** **** +18355 DuskAndDawn_Dawn **** **** **** **** **** **** **** **** +18356 LifeFades **** **** **** **** **** **** **** **** +18357 MesmerizingShade **** **** **** **** **** **** **** **** +18358 SteelShadows **** **** **** **** **** **** **** **** +18359 VoiceOfShadow_Approach **** **** **** **** **** **** **** **** +18360 VoiceOfShadow_Drop **** **** **** **** **** **** **** **** +18361 VoiceOfShadow_Fall **** **** **** **** **** **** **** **** +18362 VoiceOfShadow_Flee **** **** **** **** **** **** **** **** +18363 VoiceOfShadow_Halt **** **** **** **** **** **** **** **** +18364 BlackFire **** **** **** **** **** **** **** **** +18365 CongressShadows **** **** **** **** **** **** **** **** +18366 FleshFails_Str **** **** **** **** **** **** **** **** +18367 FleshFails_Dex **** **** **** **** **** **** **** **** +18368 FleshFails_Con **** **** **** **** **** **** **** **** +18369 PiercingSight **** **** **** **** **** **** **** **** +18370 ShadowSkin **** **** **** **** **** **** **** **** +18371 SightEclipsed **** **** **** **** **** **** **** **** +18372 ThoughtsShadow_Int **** **** **** **** **** **** **** **** +18373 ThoughtsShadow_Wis **** **** **** **** **** **** **** **** +18374 ThoughtsShadow_Cha **** **** **** **** **** **** **** **** +18375 AfraidOfTheDark **** **** **** **** **** **** **** **** +18376 ClingingDarkness **** **** **** **** **** **** **** **** +18377 DancingShadows **** **** **** **** **** **** **** **** +18378 Flicker **** **** **** **** **** **** **** **** +18379 KillingShadows **** **** **** **** **** **** **** **** +18380 SharpShadows **** **** **** **** **** **** **** **** +18381 UmbralTouch **** **** **** **** **** **** **** **** +18382 AuraOfShade **** **** **** **** **** **** **** **** +18383 Bolster **** **** **** **** **** **** **** **** +18384 ShadowEvocation **** **** **** **** **** **** **** **** +18385 ShadowEvocation_Conv **** **** **** **** **** **** **** **** +18386 ShadowVision **** **** **** **** **** **** **** **** +18387 ShadowsFade **** **** **** **** **** **** **** **** +18388 StepIntoShadow_Self **** **** **** **** **** **** **** **** +18389 StepIntoShadow_Party **** **** **** **** **** **** **** **** +18390 WarpSpell **** **** **** **** **** **** **** **** +18391 CurtainShadows **** **** **** **** **** **** **** **** +18392 DarkAir **** **** **** **** **** **** **** **** +18393 EchoSpell **** **** **** **** **** **** **** **** +18394 FeignLife **** **** **** **** **** **** **** **** +18395 Languor_Slow **** **** **** **** **** **** **** **** +18396 Languor_Hold **** **** **** **** **** **** **** **** +18397 PassShadow_Self **** **** **** **** **** **** **** **** +18398 PassShadow_Party **** **** **** **** **** **** **** **** +18399 UnravelDweomer **** **** **** **** **** **** **** **** +18400 FloodShadows **** **** **** **** **** **** **** **** +18401 GreaterShadowEvocation **** **** **** **** **** **** **** **** +18402 GreaterShadowEvocation_Conv **** **** **** **** **** **** **** **** +18403 ShadowInvestiture **** **** **** **** **** **** **** **** +18404 ShadowStorm **** **** **** **** **** **** **** **** +18405 ShadowsFade_Greater **** **** **** **** **** **** **** **** +18406 Unveil **** **** **** **** **** **** **** **** +18407 VoyageShadow_Self **** **** **** **** **** **** **** **** +18408 VoyageShadow_Party **** **** **** **** **** **** **** **** +18409 DarkSoul **** **** **** **** **** **** **** **** +18410 EphemeralImage **** **** **** **** **** **** **** **** +18411 LifeFadesGreater **** **** **** **** **** **** **** **** +18412 PrisonNight **** **** **** **** **** **** **** **** +18413 UmbralServant **** **** **** **** **** **** **** **** +18414 TruthRevealed **** **** **** **** **** **** **** **** +18415 FarSight **** **** **** **** **** **** **** **** +18416 GrFleshFails_Str **** **** **** **** **** **** **** **** +18417 GrFleshFails_Dex **** **** **** **** **** **** **** **** +18418 GrFleshFails_Con **** **** **** **** **** **** **** **** +18419 ShadowPlague **** **** **** **** **** **** **** **** +18420 SoulPuppet **** **** **** **** **** **** **** **** +18421 TombNight **** **** **** **** **** **** **** **** +18422 UmbralBody **** **** **** **** **** **** **** **** +18423 ArmyShadow **** **** **** **** **** **** **** **** +18424 ConsumeEssence **** **** **** **** **** **** **** **** +18425 EphemeralStorm **** **** **** **** **** **** **** **** +18426 Reflections **** **** **** **** **** **** **** **** +18427 ShadowSurge **** **** **** **** **** **** **** **** +18428 ShadowTime **** **** **** **** **** **** **** **** +18429 **Class_Mysteries** **** **** **** **** **** **** **** **** +18430 Shadowcaster_BendPerspective **** **** **** **** **** **** **** **** +18431 Shadowcaster_CarpetShadow **** **** **** **** **** **** **** **** +18432 Shadowcaster_DuskAndDawn_RadialMaster **** **** **** **** **** **** **** **** +18433 Shadowcaster_DuskAndDawn_Dusk **** **** **** **** **** **** **** **** +18434 Shadowcaster_DuskAndDawn_Dawn **** **** **** **** **** **** **** **** +18435 Shadowcaster_LifeFades **** **** **** **** **** **** **** **** +18436 Shadowcaster_MesmerizingShade **** **** **** **** **** **** **** **** +18437 Shadowcaster_SteelShadows **** **** **** **** **** **** **** **** +18438 Shadowcaster_VoiceOfShadow_RadialMaster **** **** **** **** **** **** **** **** +18439 Shadowcaster_VoiceOfShadow_Approach **** **** **** **** **** **** **** **** +18440 Shadowcaster_VoiceOfShadow_Drop **** **** **** **** **** **** **** **** +18441 Shadowcaster_VoiceOfShadow_Fall **** **** **** **** **** **** **** **** +18442 Shadowcaster_VoiceOfShadow_Flee **** **** **** **** **** **** **** **** +18443 Shadowcaster_VoiceOfShadow_Halt **** **** **** **** **** **** **** **** +18444 Shadowcaster_BlackFire **** **** **** **** **** **** **** **** +18445 Shadowcaster_CongressShadows **** **** **** **** **** **** **** **** +18446 Shadowcaster_FleshFails_RadialMaster **** **** **** **** **** **** **** **** +18447 Shadowcaster_FleshFails_Str **** **** **** **** **** **** **** **** +18448 Shadowcaster_FleshFails_Dex **** **** **** **** **** **** **** **** +18449 Shadowcaster_FleshFails_Con **** **** **** **** **** **** **** **** +18450 Shadowcaster_PiercingSight **** **** **** **** **** **** **** **** +18451 Shadowcaster_ShadowSkin **** **** **** **** **** **** **** **** +18452 Shadowcaster_SightEclipsed **** **** **** **** **** **** **** **** +18453 Shadowcaster_ThoughtsShadow_RadialMaster **** **** **** **** **** **** **** **** +18454 Shadowcaster_ThoughtsShadow_Int **** **** **** **** **** **** **** **** +18455 Shadowcaster_ThoughtsShadow_Wis **** **** **** **** **** **** **** **** +18456 Shadowcaster_ThoughtsShadow_Cha **** **** **** **** **** **** **** **** +18457 Shadowcaster_AfraidOfTheDark **** **** **** **** **** **** **** **** +18458 Shadowcaster_ClingingDarkness **** **** **** **** **** **** **** **** +18459 Shadowcaster_DancingShadows **** **** **** **** **** **** **** **** +18460 Shadowcaster_Flicker **** **** **** **** **** **** **** **** +18461 Shadowcaster_KillingShadows **** **** **** **** **** **** **** **** +18462 Shadowcaster_SharpShadows **** **** **** **** **** **** **** **** +18463 Shadowcaster_UmbralTouch **** **** **** **** **** **** **** **** +18464 Shadowcaster_AuraOfShade **** **** **** **** **** **** **** **** +18465 Shadowcaster_Bolster **** **** **** **** **** **** **** **** +18466 Shadowcaster_ShadowEvocation_RadialMaster **** **** **** **** **** **** **** **** +18467 Shadowcaster_ShadowEvocation **** **** **** **** **** **** **** **** +18468 Shadowcaster_ShadowEvocation_Conv **** **** **** **** **** **** **** **** +18469 Shadowcaster_ShadowVision **** **** **** **** **** **** **** **** +18470 Shadowcaster_ShadowsFade **** **** **** **** **** **** **** **** +18471 Shadowcaster_StepIntoShadow_RadialMaster **** **** **** **** **** **** **** **** +18472 Shadowcaster_StepIntoShadow_Self **** **** **** **** **** **** **** **** +18473 Shadowcaster_StepIntoShadow_Party **** **** **** **** **** **** **** **** +18474 Shadowcaster_WarpSpell **** **** **** **** **** **** **** **** +18475 Shadowcaster_CurtainShadows **** **** **** **** **** **** **** **** +18476 Shadowcaster_DarkAir **** **** **** **** **** **** **** **** +18477 Shadowcaster_EchoSpell **** **** **** **** **** **** **** **** +18478 Shadowcaster_FeignLife **** **** **** **** **** **** **** **** +18479 Shadowcaster_Languor_RadialMaster **** **** **** **** **** **** **** **** +18480 Shadowcaster_Languor_Slow **** **** **** **** **** **** **** **** +18481 Shadowcaster_Languor_Hold **** **** **** **** **** **** **** **** +18482 Shadowcaster_PassIntoShadow_RadialMaster **** **** **** **** **** **** **** **** +18483 Shadowcaster_PassShadow_Self **** **** **** **** **** **** **** **** +18484 Shadowcaster_PassShadow_Party **** **** **** **** **** **** **** **** +18485 Shadowcaster_UnravelDweomer **** **** **** **** **** **** **** **** +18486 Shadowcaster_FloodShadows **** **** **** **** **** **** **** **** +18487 Shadowcaster_GreaterShadowEvocation_RadialMaster **** **** **** **** **** **** **** **** +18488 Shadowcaster_GreaterShadowEvocation **** **** **** **** **** **** **** **** +18489 Shadowcaster_GreaterShadowEvocation_Conv **** **** **** **** **** **** **** **** +18490 Shadowcaster_ShadowInvestiture **** **** **** **** **** **** **** **** +18491 Shadowcaster_ShadowStorm **** **** **** **** **** **** **** **** +18492 Shadowcaster_ShadowsFade_Greater **** **** **** **** **** **** **** **** +18493 Shadowcaster_Unveil **** **** **** **** **** **** **** **** +18494 Shadowcaster_VoyageShadow_RadialMaster **** **** **** **** **** **** **** **** +18495 Shadowcaster_VoyageShadow_Self **** **** **** **** **** **** **** **** +18496 Shadowcaster_VoyageShadow_Party **** **** **** **** **** **** **** **** +18497 Shadowcaster_DarkSoul **** **** **** **** **** **** **** **** +18498 Shadowcaster_EphemeralImage **** **** **** **** **** **** **** **** +18499 Shadowcaster_LifeFadesGreater **** **** **** **** **** **** **** **** +18500 Shadowcaster_PrisonNight **** **** **** **** **** **** **** **** +18501 Shadowcaster_UmbralServant **** **** **** **** **** **** **** **** +18502 Shadowcaster_TruthRevealed **** **** **** **** **** **** **** **** +18503 Shadowcaster_FarSight **** **** **** **** **** **** **** **** +18504 Shadowcaster_GrFleshFails_RadialMaster **** **** **** **** **** **** **** **** +18505 Shadowcaster_GrFleshFails_Str **** **** **** **** **** **** **** **** +18506 Shadowcaster_GrFleshFails_Dex **** **** **** **** **** **** **** **** +18507 Shadowcaster_GrFleshFails_Con **** **** **** **** **** **** **** **** +18508 Shadowcaster_ShadowPlague **** **** **** **** **** **** **** **** +18509 Shadowcaster_SoulPuppet **** **** **** **** **** **** **** **** +18510 Shadowcaster_TombNight **** **** **** **** **** **** **** **** +18511 Shadowcaster_UmbralBody **** **** **** **** **** **** **** **** +18512 Shadowcaster_ArmyShadow **** **** **** **** **** **** **** **** +18513 Shadowcaster_ConsumeEssence **** **** **** **** **** **** **** **** +18514 Shadowcaster_EphemeralStorm **** **** **** **** **** **** **** **** +18515 Shadowcaster_Reflections **** **** **** **** **** **** **** **** +18516 Shadowcaster_ShadowSurge **** **** **** **** **** **** **** **** +18517 Shadowcaster_ShadowTime **** **** **** **** **** **** **** **** +18518 **Shadowcasting_Feats** **** **** **** **** **** **** **** **** +18519 Flicker_Feat **** **** **** **** **** **** **** **** +18520 DarkSoul_Feat **** **** **** **** **** **** **** **** +18521 ArrowDusk **** **** **** **** **** **** **** **** +18522 BlackCandle_Master **** **** **** **** **** **** **** **** +18523 BlackCandle_Light **** **** **** **** **** **** **** **** +18524 BlackCandle_Dark **** **** **** **** **** **** **** **** +18525 CaulShadow **** **** **** **** **** **** **** **** +18526 MysticReflections **** **** **** **** **** **** **** **** +18527 SightObscured **** **** **** **** **** **** **** **** +18528 ShadowHood **** **** **** **** **** **** **** **** +18529 UmbralHand **** **** **** **** **** **** **** **** +18530 WidenedEyes **** **** **** **** **** **** **** **** +18531 EmpowerMystery **** **** **** **** **** **** **** **** +18532 ExtendMystery **** **** **** **** **** **** **** **** +18533 MaximizeMystery **** **** **** **** **** **** **** **** +18534 QuickenMystery **** **** **** **** **** **** **** **** +18535 StillMystery **** **** **** **** **** **** **** **** +18536 CloakShadows **** **** **** **** **** **** **** **** +18537 DancingShadows **** **** **** **** **** **** **** **** +18538 NightForm **** **** **** **** **** **** **** **** +18539 MastersBidding_Heal **** **** **** **** **** **** **** **** +18540 MastersBidding_Attack **** **** **** **** **** **** **** **** +18541 MastersBidding_Cold **** **** **** **** **** **** **** **** +18542 MastersBidding_DR **** **** **** **** **** **** **** **** +18543 MastersBidding_Speed **** **** **** **** **** **** **** **** +18544 InnateCounterspell **** **** **** **** **** **** **** **** +18545 EldritchDisruption **** **** **** **** **** **** **** **** +18546 EldritchVortex **** **** **** **** **** **** **** **** +18547 Shadowsmith_BendPerspective **** **** **** **** **** **** **** **** +18548 Shadowsmith_CarpetShadow **** **** **** **** **** **** **** **** +18549 Shadowsmith_DuskAndDawn_RadialMaster **** **** **** **** **** **** **** **** +18550 Shadowsmith_DuskAndDawn_Dusk **** **** **** **** **** **** **** **** +18551 Shadowsmith_DuskAndDawn_Dawn **** **** **** **** **** **** **** **** +18552 Shadowsmith_LifeFades **** **** **** **** **** **** **** **** +18553 Shadowsmith_MesmerizingShade **** **** **** **** **** **** **** **** +18554 Shadowsmith_SteelShadows **** **** **** **** **** **** **** **** +18555 Shadowsmith_VoiceOfShadow_RadialMaster **** **** **** **** **** **** **** **** +18556 Shadowsmith_VoiceOfShadow_Approach **** **** **** **** **** **** **** **** +18557 Shadowsmith_VoiceOfShadow_Drop **** **** **** **** **** **** **** **** +18558 Shadowsmith_VoiceOfShadow_Fall **** **** **** **** **** **** **** **** +18559 Shadowsmith_VoiceOfShadow_Flee **** **** **** **** **** **** **** **** +18560 Shadowsmith_VoiceOfShadow_Halt **** **** **** **** **** **** **** **** +18561 Shadowsmith_BlackFire **** **** **** **** **** **** **** **** +18562 Shadowsmith_CongressShadows **** **** **** **** **** **** **** **** +18563 Shadowsmith_FleshFails_RadialMaster **** **** **** **** **** **** **** **** +18564 Shadowsmith_FleshFails_Str **** **** **** **** **** **** **** **** +18565 Shadowsmith_FleshFails_Dex **** **** **** **** **** **** **** **** +18566 Shadowsmith_FleshFails_Con **** **** **** **** **** **** **** **** +18567 Shadowsmith_PiercingSight **** **** **** **** **** **** **** **** +18568 Shadowsmith_ShadowSkin **** **** **** **** **** **** **** **** +18569 Shadowsmith_SightEclipsed **** **** **** **** **** **** **** **** +18570 Shadowsmith_ThoughtsShadow_RadialMaster **** **** **** **** **** **** **** **** +18571 Shadowsmith_ThoughtsShadow_Int **** **** **** **** **** **** **** **** +18572 Shadowsmith_ThoughtsShadow_Wis **** **** **** **** **** **** **** **** +18573 Shadowsmith_ThoughtsShadow_Cha **** **** **** **** **** **** **** **** +18574 TouchOfShadow **** **** **** **** **** **** **** **** +18575 ShroudOfShadow **** **** **** **** **** **** **** **** +18576 ShadowCraft **** **** **** **** **** **** **** **** +18577 ArmorOfShadow **** **** **** **** **** **** **** **** +18578 WidenShroud **** **** **** **** **** **** **** **** +18579 **Web_Enhancement** **** **** **** **** **** **** **** **** +18580 QuickerThanTheEye **** **** **** **** **** **** **** **** +18581 TrailOfHaze **** **** **** **** **** **** **** **** +18582 UmbralFist **** **** **** **** **** **** **** **** +18583 FearfulGloom **** **** **** **** **** **** **** **** +18584 SickeningShadows **** **** **** **** **** **** **** **** +18585 DeadlyShade_Absorb **** **** **** **** **** **** **** **** +18586 DeadlyShade_Deal **** **** **** **** **** **** **** **** +18587 GraspingShadows **** **** **** **** **** **** **** **** +18588 MenagerieOfDarkness **** **** **** **** **** **** **** **** +18589 BlackLabyrinth **** **** **** **** **** **** **** **** +18590 **** **** **** **** **** **** **** **** **** +18591 Shadowcaster_QuickerThanTheEye **** **** **** **** **** **** **** **** +18592 Shadowcaster_TrailOfHaze **** **** **** **** **** **** **** **** +18593 Shadowcaster_UmbralFist **** **** **** **** **** **** **** **** +18594 Shadowcaster_FearfulGloom **** **** **** **** **** **** **** **** +18595 Shadowcaster_SickeningShadows **** **** **** **** **** **** **** **** +18596 Shadowcaster_DeadlyShade_RadialMaster **** **** **** **** **** **** **** **** +18597 Shadowcaster_DeadlyShade_Absorb **** **** **** **** **** **** **** **** +18598 Shadowcaster_DeadlyShade_Deal **** **** **** **** **** **** **** **** +18599 Shadowcaster_GraspingShadows **** **** **** **** **** **** **** **** +18600 Shadowcaster_MenagerieOfDarkness **** **** **** **** **** **** **** **** +18601 Shadowcaster_BlackLabyrinth **** **** **** **** **** **** **** **** +18602 Shadowsmith_QuickerThanTheEye **** **** **** **** **** **** **** **** +18603 Shadowsmith_TrailOfHaze **** **** **** **** **** **** **** **** +18604 **** **** **** **** **** **** **** **** **** +18605 UmbralFist_RadialMaster **** **** **** **** **** **** **** **** +18606 UmbralFist_BullRush **** **** **** **** **** **** **** **** +18607 UmbralFist_Disarm **** **** **** **** **** **** **** **** +18608 UmbralFist_Trip **** **** **** **** **** **** **** **** +18609 **** **** **** **** **** **** **** **** **** +18610 **** **** **** **** **** **** **** **** **** +18611 **** **** **** **** **** **** **** **** **** +18612 **** **** **** **** **** **** **** **** **** +18613 **** **** **** **** **** **** **** **** **** +18614 **** **** **** **** **** **** **** **** **** +18615 **** **** **** **** **** **** **** **** **** +18616 **** **** **** **** **** **** **** **** **** +18617 **** **** **** **** **** **** **** **** **** +18618 **** **** **** **** **** **** **** **** **** +18619 **** **** **** **** **** **** **** **** **** +18620 **** **** **** **** **** **** **** **** **** +18621 **** **** **** **** **** **** **** **** **** +18622 **** **** **** **** **** **** **** **** **** +18623 **** **** **** **** **** **** **** **** **** +18624 **** **** **** **** **** **** **** **** **** +18625 **** **** **** **** **** **** **** **** **** +18626 **** **** **** **** **** **** **** **** **** +18627 **** **** **** **** **** **** **** **** **** +18628 **** **** **** **** **** **** **** **** **** +18629 **** **** **** **** **** **** **** **** **** +18630 **** **** **** **** **** **** **** **** **** +18631 **** **** **** **** **** **** **** **** **** +18632 OpenSoulChakra **** **** **** **** **** **** **** **** +18633 Meldshield_Invest **** **** **** **** **** **** **** **** +18634 Meldshield **** **** **** **** **** **** **** **** +18635 DispellingOrb_Invest **** **** **** **** **** **** **** **** +18636 DispellingOrb **** **** **** **** **** **** **** **** +18637 MageShackles_Invest **** **** **** **** **** **** **** **** +18638 MageShackles **** **** **** **** **** **** **** **** +18639 Abrogation_Invest **** **** **** **** **** **** **** **** +18640 Abrogation **** **** **** **** **** **** **** **** +18641 SpiritFlay_Invest **** **** **** **** **** **** **** **** +18642 SpiritFlay **** **** **** **** **** **** **** **** +18643 Integument_Invest **** **** **** **** **** **** **** **** +18644 Integument **** **** **** **** **** **** **** **** +18645 Blademeld_Rebind **** **** **** **** **** **** **** **** +18646 Blademeld_Throat_Shout **** **** **** **** **** **** **** **** +18647 BladeMeld_Crown **** **** **** **** **** **** **** **** +18648 BladeMeld_Feet **** **** **** **** **** **** **** **** +18649 BladeMeld_Hands **** **** **** **** **** **** **** **** +18650 BladeMeld_Arms **** **** **** **** **** **** **** **** +18651 BladeMeld_Brow **** **** **** **** **** **** **** **** +18652 BladeMeld_Shoulders **** **** **** **** **** **** **** **** +18653 BladeMeld_Throat **** **** **** **** **** **** **** **** +18654 BladeMeld_Waist **** **** **** **** **** **** **** **** +18655 BladeMeld_Heart **** **** **** **** **** **** **** **** +18656 BladeMeld_Soul **** **** **** **** **** **** **** **** +18657 Necrocarnate_Harvest **** **** **** **** **** **** **** **** +18658 Necrocarnate_Soulshield **** **** **** **** **** **** **** **** +18659 Incandescent_Aura_Yes_Its_Blank **** **** **** **** **** **** **** **** +18660 Incandescent_Transcendence **** **** **** **** **** **** **** **** +18661 Incandescent_Aura_Invest **** **** **** **** **** **** **** **** +18662 Incandescent_Ray_Invest **** **** **** **** **** **** **** **** +18663 Incandescent_Ray **** **** **** **** **** **** **** **** +18664 Incandescent_Overload **** **** **** **** **** **** **** **** +18665 Incandescent_Countenance_Invest **** **** **** **** **** **** **** **** +18666 Incandescent_Countenance **** **** **** **** **** **** **** **** +18667 Incandescent_Heal_Invest **** **** **** **** **** **** **** **** +18668 Incandescent_Heal **** **** **** **** **** **** **** **** +18669 Incandescent_Strike_Invest **** **** **** **** **** **** **** **** +18670 Incandescent_Strike **** **** **** **** **** **** **** **** +18671 PRC_Attack **** **** **** **** **** **** **** **** +18672 Umbral_KissShadows_Invest **** **** **** **** **** **** **** **** +18673 Umbral_KissShadows **** **** **** **** **** **** **** **** +18674 Umbral_Soulchilling_Invest **** **** **** **** **** **** **** **** +18675 Umbral_Soulchilling **** **** **** **** **** **** **** **** +18676 Umbral_SightEyeless_Invest **** **** **** **** **** **** **** **** +18677 Umbral_SightEyeless **** **** **** **** **** **** **** **** +18678 Umbral_EmbraceShadow_Invest **** **** **** **** **** **** **** **** +18679 Umbral_EmbraceShadow **** **** **** **** **** **** **** **** +18680 Umbral_StepBodiless_Invest **** **** **** **** **** **** **** **** +18681 Umbral_StepBodiless **** **** **** **** **** **** **** **** +18682 Ironsoul_WeaponBond_Invest **** **** **** **** **** **** **** **** +18683 Ironsoul_WeaponBond **** **** **** **** **** **** **** **** +18684 Ironsoul_ArmorBond_Invest **** **** **** **** **** **** **** **** +18685 Ironsoul_ArmorBond **** **** **** **** **** **** **** **** +18686 Ironsoul_ShieldBond_Invest **** **** **** **** **** **** **** **** +18687 Ironsoul_ShieldBond **** **** **** **** **** **** **** **** +18688 Soulcaster_Distill **** **** **** **** **** **** **** **** +18689 SapphireHierarch_Smite **** **** **** **** **** **** **** **** +18690 Spinemeld_SpineEnhancement_Invest **** **** **** **** **** **** **** **** +18691 Spinemeld_SpineEnhancement **** **** **** **** **** **** **** **** +18692 Totemist_ReshapeTotemSoulmeld **** **** **** **** **** **** **** **** +18693 Totemist_TotemEmbodiment **** **** **** **** **** **** **** **** +18694 Soulborn_ShareDefence **** **** **** **** **** **** **** **** +18695 Soulborn_Smite **** **** **** **** **** **** **** **** +18696 Incarnate_PerfectMeldshaper **** **** **** **** **** **** **** **** +18697 Incarnate_RapidMeldshaping **** **** **** **** **** **** **** **** +18698 Incarnate_IncarnumRadiance **** **** **** **** **** **** **** **** +18699 Incarnate_DetectOpposition **** **** **** **** **** **** **** **** +18700 **INCARNUM** **** **** **** **** **** **** **** **** +18701 AcrobatBoots **** **** **** **** **** **** **** **** +18702 AdamantPauldrons **** **** **** **** **** **** **** **** +18703 CrystalHelm **** **** **** **** **** **** **** **** +18704 AnkhegBreastplate **** **** **** **** **** **** **** **** +18705 ApparitionRibbon **** **** **** **** **** **** **** **** +18706 ArcaneFocus **** **** **** **** **** **** **** **** +18707 ArmguardsofDisruption **** **** **** **** **** **** **** **** +18708 BasiliskMask **** **** **** **** **** **** **** **** +18709 BeastTamerCirclet **** **** **** **** **** **** **** **** +18710 BehirGorget **** **** **** **** **** **** **** **** +18711 BlinkShirt **** **** **** **** **** **** **** **** +18712 Bloodtalons **** **** **** **** **** **** **** **** +18713 BloodwarGauntlets **** **** **** **** **** **** **** **** +18714 BluesteelBracers **** **** **** **** **** **** **** **** +18715 BrassMane **** **** **** **** **** **** **** **** +18716 CeruleanSandals **** **** **** **** **** **** **** **** +18717 DiademofPurelight **** **** **** **** **** **** **** **** +18718 DisenchanterMask **** **** **** **** **** **** **** **** +18719 DisplacerMantle **** **** **** **** **** **** **** **** +18720 DissolvingSpittle **** **** **** **** **** **** **** **** +18721 DreadCarapace **** **** **** **** **** **** **** **** +18722 EnigmaHelm **** **** **** **** **** **** **** **** +18723 FearsomeMask **** **** **** **** **** **** **** **** +18724 FellmistRobe **** **** **** **** **** **** **** **** +18725 FlameCincture **** **** **** **** **** **** **** **** +18726 FrostHelm **** **** **** **** **** **** **** **** +18727 GirallonArms **** **** **** **** **** **** **** **** +18728 GlovesofthePoisonedSoul **** **** **** **** **** **** **** **** +18729 GorgonMask **** **** **** **** **** **** **** **** +18730 GreatRaptorMask **** **** **** **** **** **** **** **** +18731 HeartofFire **** **** **** **** **** **** **** **** +18732 HuntersCirclet **** **** **** **** **** **** **** **** +18733 IllusionVeil **** **** **** **** **** **** **** **** +18734 ImpulseBoots **** **** **** **** **** **** **** **** +18735 IncarnateAvatar **** **** **** **** **** **** **** **** +18736 IncarnateWeapon **** **** **** **** **** **** **** **** +18737 KeeneyeLenses **** **** **** **** **** **** **** **** +18738 KrakenMantle **** **** **** **** **** **** **** **** +18739 KrensharMask **** **** **** **** **** **** **** **** +18740 KruthikClaws **** **** **** **** **** **** **** **** +18741 LamiaBelt **** **** **** **** **** **** **** **** +18742 LammasuMantle **** **** **** **** **** **** **** **** +18743 LandsharkBoots **** **** **** **** **** **** **** **** +18744 LifebondVestments **** **** **** **** **** **** **** **** +18745 LightningGauntlets **** **** **** **** **** **** **** **** +18746 LuckyDice **** **** **** **** **** **** **** **** +18747 MagesSpectacles **** **** **** **** **** **** **** **** +18748 ManticoreBelt **** **** **** **** **** **** **** **** +18749 MantleofFlame **** **** **** **** **** **** **** **** +18750 MaulingGauntlets **** **** **** **** **** **** **** **** +18751 NecrocarnumCirclet **** **** **** **** **** **** **** **** +18752 NecrocarnumMantle **** **** **** **** **** **** **** **** +18753 NecrocarnumShroud **** **** **** **** **** **** **** **** +18754 NecrocarnumTouch **** **** **** **** **** **** **** **** +18755 NecrocarnumVestments **** **** **** **** **** **** **** **** +18756 NecrocarnumWeapon **** **** **** **** **** **** **** **** +18757 PauldronsofHealth **** **** **** **** **** **** **** **** +18758 PegasusCloak **** **** **** **** **** **** **** **** +18759 PhaseCloak **** **** **** **** **** **** **** **** +18760 PhoenixBelt **** **** **** **** **** **** **** **** +18761 PlanarChasuble **** **** **** **** **** **** **** **** +18762 PlanarWard **** **** **** **** **** **** **** **** +18763 Rageclaws **** **** **** **** **** **** **** **** +18764 RidingBracers **** **** **** **** **** **** **** **** +18765 SailorsBracers **** **** **** **** **** **** **** **** +18766 ShadowMantle **** **** **** **** **** **** **** **** +18767 SheduCrown **** **** **** **** **** **** **** **** +18768 SightingGloves **** **** **** **** **** **** **** **** +18769 SilvertongueMask **** **** **** **** **** **** **** **** +18770 SoulsparkFamiliar **** **** **** **** **** **** **** **** +18771 SoulspeakerCirclet **** **** **** **** **** **** **** **** +18772 SpellwardShirt **** **** **** **** **** **** **** **** +18773 SphinxClaws **** **** **** **** **** **** **** **** +18774 StrongheartVest **** **** **** **** **** **** **** **** +18775 TheftGloves **** **** **** **** **** **** **** **** +18776 TherapeuticMantle **** **** **** **** **** **** **** **** +18777 ThreefoldMaskoftheChimera **** **** **** **** **** **** **** **** +18778 ThunderstepBoots **** **** **** **** **** **** **** **** +18779 TotemAvatar **** **** **** **** **** **** **** **** +18780 TruthseekerGoggles **** **** **** **** **** **** **** **** +18781 UnicornHorn **** **** **** **** **** **** **** **** +18782 UrskanGreaves **** **** **** **** **** **** **** **** +18783 VitalityBelt **** **** **** **** **** **** **** **** +18784 WindCloak **** **** **** **** **** **** **** **** +18785 WinterMask **** **** **** **** **** **** **** **** +18786 WorgPelt **** **** **** **** **** **** **** **** +18787 WormtailBelt **** **** **** **** **** **** **** **** +18788 YrthakMask **** **** **** **** **** **** **** **** +18789 AstralVambraces **** **** **** **** **** **** **** **** +18790 CharmingVeil **** **** **** **** **** **** **** **** +18791 PsionsEyes **** **** **** **** **** **** **** **** +18792 PsionKillerMask **** **** **** **** **** **** **** **** +18793 PsychicFocus **** **** **** **** **** **** **** **** +18794 ClawsOfTheWyrm **** **** **** **** **** **** **** **** +18795 DragonMantle **** **** **** **** **** **** **** **** +18796 DragonTail **** **** **** **** **** **** **** **** +18797 DragonfireMask **** **** **** **** **** **** **** **** +18798 ElderSpirit **** **** **** **** **** **** **** **** +18799 **** **** **** **** **** **** **** **** **** +18800 AcrobatBoots **** **** **** **** **** **** **** **** +18801 AdamantPauldrons **** **** **** **** **** **** **** **** +18802 CrystalHelm **** **** **** **** **** **** **** **** +18803 AnkhegBreastplate **** **** **** **** **** **** **** **** +18804 ApparitionRibbon **** **** **** **** **** **** **** **** +18805 ArcaneFocus **** **** **** **** **** **** **** **** +18806 ArmguardsofDisruption **** **** **** **** **** **** **** **** +18807 BasiliskMask **** **** **** **** **** **** **** **** +18808 BeastTamerCirclet **** **** **** **** **** **** **** **** +18809 BehirGorget **** **** **** **** **** **** **** **** +18810 BlinkShirt **** **** **** **** **** **** **** **** +18811 Bloodtalons **** **** **** **** **** **** **** **** +18812 BloodwarGauntlets **** **** **** **** **** **** **** **** +18813 BluesteelBracers **** **** **** **** **** **** **** **** +18814 BrassMane **** **** **** **** **** **** **** **** +18815 CeruleanSandals **** **** **** **** **** **** **** **** +18816 DiademofPurelight **** **** **** **** **** **** **** **** +18817 DisenchanterMask **** **** **** **** **** **** **** **** +18818 DisplacerMantle **** **** **** **** **** **** **** **** +18819 DissolvingSpittle **** **** **** **** **** **** **** **** +18820 DreadCarapace **** **** **** **** **** **** **** **** +18821 EnigmaHelm **** **** **** **** **** **** **** **** +18822 FearsomeMask **** **** **** **** **** **** **** **** +18823 FellmistRobe **** **** **** **** **** **** **** **** +18824 FlameCincture **** **** **** **** **** **** **** **** +18825 FrostHelm **** **** **** **** **** **** **** **** +18826 GirallonArms **** **** **** **** **** **** **** **** +18827 GlovesofthePoisonedSoul **** **** **** **** **** **** **** **** +18828 GorgonMask **** **** **** **** **** **** **** **** +18829 GreatRaptorMask **** **** **** **** **** **** **** **** +18830 HeartofFire **** **** **** **** **** **** **** **** +18831 HuntersCirclet **** **** **** **** **** **** **** **** +18832 IllusionVeil **** **** **** **** **** **** **** **** +18833 ImpulseBoots **** **** **** **** **** **** **** **** +18834 IncarnateAvatar **** **** **** **** **** **** **** **** +18835 IncarnateWeapon **** **** **** **** **** **** **** **** +18836 KeeneyeLenses **** **** **** **** **** **** **** **** +18837 KrakenMantle **** **** **** **** **** **** **** **** +18838 KrensharMask **** **** **** **** **** **** **** **** +18839 KruthikClaws **** **** **** **** **** **** **** **** +18840 LamiaBelt **** **** **** **** **** **** **** **** +18841 LammasuMantle **** **** **** **** **** **** **** **** +18842 LandsharkBoots **** **** **** **** **** **** **** **** +18843 LifebondVestments **** **** **** **** **** **** **** **** +18844 LightningGauntlets **** **** **** **** **** **** **** **** +18845 LuckyDice **** **** **** **** **** **** **** **** +18846 MagesSpectacles **** **** **** **** **** **** **** **** +18847 ManticoreBelt **** **** **** **** **** **** **** **** +18848 MantleofFlame **** **** **** **** **** **** **** **** +18849 MaulingGauntlets **** **** **** **** **** **** **** **** +18850 NecrocarnumCirclet **** **** **** **** **** **** **** **** +18851 NecrocarnumMantle **** **** **** **** **** **** **** **** +18852 NecrocarnumShroud **** **** **** **** **** **** **** **** +18853 NecrocarnumTouch **** **** **** **** **** **** **** **** +18854 NecrocarnumVestments **** **** **** **** **** **** **** **** +18855 NecrocarnumWeapon **** **** **** **** **** **** **** **** +18856 PauldronsofHealth **** **** **** **** **** **** **** **** +18857 PegasusCloak **** **** **** **** **** **** **** **** +18858 PhaseCloak **** **** **** **** **** **** **** **** +18859 PhoenixBelt **** **** **** **** **** **** **** **** +18860 PlanarChasuble **** **** **** **** **** **** **** **** +18861 PlanarWard **** **** **** **** **** **** **** **** +18862 Rageclaws **** **** **** **** **** **** **** **** +18863 RidingBracers **** **** **** **** **** **** **** **** +18864 SailorsBracers **** **** **** **** **** **** **** **** +18865 ShadowMantle **** **** **** **** **** **** **** **** +18866 SheduCrown **** **** **** **** **** **** **** **** +18867 SightingGloves **** **** **** **** **** **** **** **** +18868 SilvertongueMask **** **** **** **** **** **** **** **** +18869 SoulsparkFamiliar **** **** **** **** **** **** **** **** +18870 SoulspeakerCirclet **** **** **** **** **** **** **** **** +18871 SpellwardShirt **** **** **** **** **** **** **** **** +18872 SphinxClaws **** **** **** **** **** **** **** **** +18873 StrongheartVest **** **** **** **** **** **** **** **** +18874 TheftGloves **** **** **** **** **** **** **** **** +18875 TherapeuticMantle **** **** **** **** **** **** **** **** +18876 ThreefoldMaskoftheChimera **** **** **** **** **** **** **** **** +18877 ThunderstepBoots **** **** **** **** **** **** **** **** +18878 TotemAvatar **** **** **** **** **** **** **** **** +18879 TruthseekerGoggles **** **** **** **** **** **** **** **** +18880 UnicornHorn **** **** **** **** **** **** **** **** +18881 UrskanGreaves **** **** **** **** **** **** **** **** +18882 VitalityBelt **** **** **** **** **** **** **** **** +18883 WindCloak **** **** **** **** **** **** **** **** +18884 WinterMask **** **** **** **** **** **** **** **** +18885 WorgPelt **** **** **** **** **** **** **** **** +18886 WormtailBelt **** **** **** **** **** **** **** **** +18887 YrthakMask **** **** **** **** **** **** **** **** +18888 AstralVambraces **** **** **** **** **** **** **** **** +18889 CharmingVeil **** **** **** **** **** **** **** **** +18890 PsionsEyes **** **** **** **** **** **** **** **** +18891 PsionKillerMask **** **** **** **** **** **** **** **** +18892 PsychicFocus **** **** **** **** **** **** **** **** +18893 ClawsOfTheWyrm **** **** **** **** **** **** **** **** +18894 DragonMantle **** **** **** **** **** **** **** **** +18895 DragonTail **** **** **** **** **** **** **** **** +18896 DragonfireMask **** **** **** **** **** **** **** **** +18897 ElderSpirit **** **** **** **** **** **** **** **** +18898 **** **** **** **** **** **** **** **** **** +18899 **** **** **** **** **** **** **** **** **** +18900 InvestEssentiaConversation **** **** **** **** **** **** **** **** +18901 AnkhegBreastplateThroatBind **** **** **** **** **** **** **** **** +18902 ApparitionRibbonThroatBind **** **** **** **** **** **** **** **** +18903 ArmguardsDisruptionArmsBind **** **** **** **** **** **** **** **** +18904 BasiliskMaskTotemBind **** **** **** **** **** **** **** **** +18905 BeastTamerCircletCrownBind **** **** **** **** **** **** **** **** +18906 BeastTamerCircletTotemBind **** **** **** **** **** **** **** **** +18907 BehirGorgetThroatBind **** **** **** **** **** **** **** **** +18908 BlinkShirtDimensionDoor_St **** **** **** **** **** **** **** **** +18909 BlinkShirtHeartBind **** **** **** **** **** **** **** **** +18910 BlinkShirtDimensionDoor_Mv **** **** **** **** **** **** **** **** +18911 BloodwarGauntletsArmBind **** **** **** **** **** **** **** **** +18912 BrassManeThroatBind **** **** **** **** **** **** **** **** +18913 CeruleanSandalsFeetBind **** **** **** **** **** **** **** **** +18914 DisenchanterMaskDetectMagic **** **** **** **** **** **** **** **** +18915 DisenchanterMaskTotemBind **** **** **** **** **** **** **** **** +18916 DisplacerMantleTotemBind **** **** **** **** **** **** **** **** +18917 DissolvingSpittleSpitAcid **** **** **** **** **** **** **** **** +18918 DreadCarapaceFootBind **** **** **** **** **** **** **** **** +18919 FlameCinctureWaistBind **** **** **** **** **** **** **** **** +18920 FrostHelmCrownBind **** **** **** **** **** **** **** **** +18921 FrostHelmTotemBind **** **** **** **** **** **** **** **** +18922 GlovesOfThePoisonedHandAbilityDamage **** **** **** **** **** **** **** **** +18923 GorgonMaskThroatBind **** **** **** **** **** **** **** **** +18924 GorgonMaskTotemBind **** **** **** **** **** **** **** **** +18925 IncarnateWeaponArmsBind **** **** **** **** **** **** **** **** +18926 KrensharMaskTotemBind **** **** **** **** **** **** **** **** +18927 LammasuMantleTotemBind **** **** **** **** **** **** **** **** +18928 LandsharkBootsFeetBind **** **** **** **** **** **** **** **** +18929 LandsharkBootsTotemBind **** **** **** **** **** **** **** **** +18930 LifebondVestmentsHeal **** **** **** **** **** **** **** **** +18931 LifebondVestmentsArmsBind **** **** **** **** **** **** **** **** +18932 LightningGauntletsZap **** **** **** **** **** **** **** **** +18933 LightningGauntletsHandsBind **** **** **** **** **** **** **** **** +18934 LuckyDice_RadialMaster **** **** **** **** **** **** **** **** +18935 LuckyDice_AttackDamage **** **** **** **** **** **** **** **** +18936 LuckyDice_SavingThrows **** **** **** **** **** **** **** **** +18937 LuckyDice_SkillAbilities **** **** **** **** **** **** **** **** +18938 MagesSpectaclesBrowBind **** **** **** **** **** **** **** **** +18939 ManticoreBeltTotemBind **** **** **** **** **** **** **** **** +18940 MantleOfFlameShouldersBind **** **** **** **** **** **** **** **** +18941 PhoenixBeltTotemBind **** **** **** **** **** **** **** **** +18942 PlanarChasubleSoulBind **** **** **** **** **** **** **** **** +18943 ShadowMantleShouldersBind **** **** **** **** **** **** **** **** +18944 SheduCrownHeartBind **** **** **** **** **** **** **** **** +18945 SilvertongueMaskThroatBind **** **** **** **** **** **** **** **** +18946 UnicornHornBrowBind **** **** **** **** **** **** **** **** +18947 WinterMaskColdTouch **** **** **** **** **** **** **** **** +18948 WinterMaskThroatBind **** **** **** **** **** **** **** **** +18949 WormtailBeltTotemBind **** **** **** **** **** **** **** **** +18950 YrthakMaskBrowBind **** **** **** **** **** **** **** **** +18951 YrthakMaskTotemBind **** **** **** **** **** **** **** **** +18952 NecrocarnumCircletCrownBind **** **** **** **** **** **** **** **** +18953 NecrocarnumShroudSoulBind **** **** **** **** **** **** **** **** +18954 NecrocarnumTouchEssentia **** **** **** **** **** **** **** **** +18955 NecrocarnumTouchArmsBind **** **** **** **** **** **** **** **** +18956 SoulsparkFamiliar_Attack **** **** **** **** **** **** **** **** +18957 SoulsparkFamiliar_Essentia **** **** **** **** **** **** **** **** +18958 PsionsEyesBrowBind **** **** **** **** **** **** **** **** +18959 PsionKillerMaskDetectMagic **** **** **** **** **** **** **** **** +18960 PsionKillerMaskTotemBind **** **** **** **** **** **** **** **** +18961 DragonTailSlam **** **** **** **** **** **** **** **** +18962 DragonTailTotemBind **** **** **** **** **** **** **** **** +18963 DragonfireMaskThroatBind **** **** **** **** **** **** **** **** +18964 DragonfireMaskTotemBind **** **** **** **** **** **** **** **** +18965 **** **** **** **** **** **** **** **** **** +18966 **** **** **** **** **** **** **** **** **** +18967 **** **** **** **** **** **** **** **** **** +18968 **** **** **** **** **** **** **** **** **** +18969 **** **** **** **** **** **** **** **** **** +18970 HealingSoul **** **** **** **** **** **** **** **** +18971 MidnightAugmentation **** **** **** **** **** **** **** **** +18972 PsycarnumBlade **** **** **** **** **** **** **** **** +18973 DusklingSpeed **** **** **** **** **** **** **** **** +18974 DivineSoultouch **** **** **** **** **** **** **** **** +18975 PsycarnumInfusion **** **** **** **** **** **** **** **** +18976 Epic_RapidMeldshaping **** **** **** **** **** **** **** **** +18977 Epic_RebindSoulmeld_Crown **** **** **** **** **** **** **** **** +18978 Epic_RebindSoulmeld_Feet **** **** **** **** **** **** **** **** +18979 Epic_RebindSoulmeld_Hands **** **** **** **** **** **** **** **** +18980 Epic_RebindSoulmeld_Arms **** **** **** **** **** **** **** **** +18981 Epic_RebindSoulmeld_Brow **** **** **** **** **** **** **** **** +18982 Epic_RebindSoulmeld_Shoulders **** **** **** **** **** **** **** **** +18983 Epic_RebindSoulmeld_Throat **** **** **** **** **** **** **** **** +18984 Epic_RebindSoulmeld_Waist **** **** **** **** **** **** **** **** +18985 Epic_RebindSoulmeld_Heart **** **** **** **** **** **** **** **** +18986 Epic_RebindSoulmeld_Soul **** **** **** **** **** **** **** **** +18987 Epic_RebindSoulmeld_Totem **** **** **** **** **** **** **** **** +18988 **** **** **** **** **** **** **** **** **** +18989 **** **** **** **** **** **** **** **** **** +18990 **** **** **** **** **** **** **** **** **** +18991 **** **** **** **** **** **** **** **** **** +18992 **** **** **** **** **** **** **** **** **** +18993 **** **** **** **** **** **** **** **** **** +18994 **** **** **** **** **** **** **** **** **** +18995 **** **** **** **** **** **** **** **** **** +18996 **** **** **** **** **** **** **** **** **** +18997 **** **** **** **** **** **** **** **** **** +18998 **** **** **** **** **** **** **** **** **** +18999 **** **** **** **** **** **** **** **** **** +19000 ####END_OF_SHADOW_MAGIC_RESERVE **** **** **** **** **** **** **** **** +19001 Spell_Rage **** **** **** **** **** **** **** **** +19002 Warrior_Cry **** **** **** **** **** **** **** **** +19003 Spell_Fury **** **** **** **** **** **** **** **** +19004 DK_Tactics **** **** **** **** **** **** **** **** +19005 DK_Puissance **** **** **** **** **** **** **** **** +19006 DK_Foe **** **** **** **** **** **** **** **** +19007 DK_DreadSecret **** **** **** **** **** **** **** **** +19008 DK_Foreknowledge **** **** **** **** **** **** **** **** +19009 Archivist_LearnSpell **** **** **** **** **** **** **** **** +19010 Witch_LearnSpell **** **** **** **** **** **** **** **** +19011 ArkamoiStrengthFromMagic **** **** **** **** **** **** **** **** +19012 LashemoiLesserStrengthFromPain **** **** **** **** **** **** **** **** +19013 TurlemoiStrengthFromPain **** **** **** **** **** **** **** **** +19014 HadrimoiSpeedFromPain **** **** **** **** **** **** **** **** +19015 GlouraUnearthlyGrace **** **** **** **** **** **** **** **** +19016 **** **** **** **** **** **** **** **** **** +19017 **** **** **** **** **** **** **** **** **** +19018 **** **** **** **** **** **** **** **** **** +19019 ####START_OF_BINDING **** **** **** **** **** **** **** **** +19020 Amon **** **** **** **** **** **** **** **** +19021 Aym **** **** **** **** **** **** **** **** +19022 Leraje **** **** **** **** **** **** **** **** +19023 Naberius **** **** **** **** **** **** **** **** +19024 Ronove **** **** **** **** **** **** **** **** +19025 DahlverNar **** **** **** **** **** **** **** **** +19026 Haagenti **** **** **** **** **** **** **** **** +19027 Malphas **** **** **** **** **** **** **** **** +19028 Savnok **** **** **** **** **** **** **** **** +19029 Andromalius **** **** **** **** **** **** **** **** +19030 Focalor **** **** **** **** **** **** **** **** +19031 Karsus **** **** **** **** **** **** **** **** +19032 Paimon **** **** **** **** **** **** **** **** +19033 Agares **** **** **** **** **** **** **** **** +19034 Andras **** **** **** **** **** **** **** **** +19035 Buer **** **** **** **** **** **** **** **** +19036 Eurynome **** **** **** **** **** **** **** **** +19037 Tenebrous **** **** **** **** **** **** **** **** +19038 Arete **** **** **** **** **** **** **** **** +19039 Astaroth **** **** **** **** **** **** **** **** +19040 Acererak **** **** **** **** **** **** **** **** +19041 Balam **** **** **** **** **** **** **** **** +19042 Dantalion **** **** **** **** **** **** **** **** +19043 Geryon **** **** **** **** **** **** **** **** +19044 Otiax **** **** **** **** **** **** **** **** +19045 Chupoclops **** **** **** **** **** **** **** **** +19046 Haures **** **** **** **** **** **** **** **** +19047 Ipos **** **** **** **** **** **** **** **** +19048 Shax **** **** **** **** **** **** **** **** +19049 Zagan **** **** **** **** **** **** **** **** +19050 Vanus **** **** **** **** **** **** **** **** +19051 TheTriad **** **** **** **** **** **** **** **** +19052 Desharis **** **** **** **** **** **** **** **** +19053 Zceryll **** **** **** **** **** **** **** **** +19054 Eligor **** **** **** **** **** **** **** **** +19055 Marchosias **** **** **** **** **** **** **** **** +19056 Ashardalon **** **** **** **** **** **** **** **** +19057 Halphax **** **** **** **** **** **** **** **** +19058 Orthos **** **** **** **** **** **** **** **** +19059 Abysm **** **** **** **** **** **** **** **** +19060 **** **** **** **** **** **** **** **** **** +19061 **** **** **** **** **** **** **** **** **** +19062 **** **** **** **** **** **** **** **** **** +19063 **** **** **** **** **** **** **** **** **** +19064 **** **** **** **** **** **** **** **** **** +19065 **** **** **** **** **** **** **** **** **** +19066 **** **** **** **** **** **** **** **** **** +19067 **** **** **** **** **** **** **** **** **** +19068 **** **** **** **** **** **** **** **** **** +19069 **** **** **** **** **** **** **** **** **** +19070 AmonFireBreath **** **** **** **** **** **** **** **** +19071 AymHaloOfFire **** **** **** **** **** **** **** **** +19072 LerajeRicochet **** **** **** **** **** **** **** **** +19073 NaberiusDisguise_Self_Radial_Master **** **** **** **** **** **** **** **** +19074 NaberiusDisguise_Self_Learn **** **** **** **** **** **** **** **** +19075 NaberiusDisguise_Self_Options **** **** **** **** **** **** **** **** +19076 NaberiusDisguise_Self_QS1 **** **** **** **** **** **** **** **** +19077 NaberiusDisguise_Self_QS2 **** **** **** **** **** **** **** **** +19078 NaberiusDisguise_Self_QS3 **** **** **** **** **** **** **** **** +19079 NaberiusCommand_RadialMaster **** **** **** **** **** **** **** **** +19080 NaberiusCommand_Approach **** **** **** **** **** **** **** **** +19081 NaberiusCommand_Drop **** **** **** **** **** **** **** **** +19082 NaberiusCommand_Fall **** **** **** **** **** **** **** **** +19083 NaberiusCommand_Flee **** **** **** **** **** **** **** **** +19084 NaberiusCommand_Halt **** **** **** **** **** **** **** **** +19085 RonoveFar_Hand **** **** **** **** **** **** **** **** +19086 RonoveBullrush **** **** **** **** **** **** **** **** +19087 DahlverNarMaddeningMoan **** **** **** **** **** **** **** **** +19088 DahlverNarSharePainForced **** **** **** **** **** **** **** **** +19089 HaagentiConfusingTouch **** **** **** **** **** **** **** **** +19090 MalphasArcaneEye **** **** **** **** **** **** **** **** +19091 MalphasInvisibility **** **** **** **** **** **** **** **** +19092 SavnokCallArmor **** **** **** **** **** **** **** **** +19093 SavnokMoveAlly **** **** **** **** **** **** **** **** +19094 AndromaliusTashas_Hideous_Laughter **** **** **** **** **** **** **** **** +19095 AndromaliusLocateObject **** **** **** **** **** **** **** **** +19096 AndromaliusSee_Invisibility **** **** **** **** **** **** **** **** +19097 FocalorAuraSadness **** **** **** **** **** **** **** **** +19098 FocalorLightningStrike **** **** **** **** **** **** **** **** +19099 FocalorBreath **** **** **** **** **** **** **** **** +19100 KarsusSenses **** **** **** **** **** **** **** **** +19101 KarsusTouch **** **** **** **** **** **** **** **** +19102 PaimonDanceOfDeath **** **** **** **** **** **** **** **** +19103 AgaresEarthshakingStep **** **** **** **** **** **** **** **** +19104 AgaresElementalCompanion **** **** **** **** **** **** **** **** +19105 AndrasSmite **** **** **** **** **** **** **** **** +19106 AndrasSowDiscord **** **** **** **** **** **** **** **** +19107 AndrasMount **** **** **** **** **** **** **** **** +19108 BuerHealingGift **** **** **** **** **** **** **** **** +19109 TenebrousDeeperDarkness **** **** **** **** **** **** **** **** +19110 TenebrousTouchVoid **** **** **** **** **** **** **** **** +19111 TenebrousTurnUndead **** **** **** **** **** **** **** **** +19112 TenebrousFlicker **** **** **** **** **** **** **** **** +19113 AcererakDetectUndead **** **** **** **** **** **** **** **** +19114 AcererakHideUndead **** **** **** **** **** **** **** **** +19115 AcererakParalyze **** **** **** **** **** **** **** **** +19116 BalamCunning **** **** **** **** **** **** **** **** +19117 BalamGlare **** **** **** **** **** **** **** **** +19118 DantalionAwe **** **** **** **** **** **** **** **** +19119 DantalionReadThoughts **** **** **** **** **** **** **** **** +19120 DantalionThoughtTravel **** **** **** **** **** **** **** **** +19121 GeryonAcidicGlare **** **** **** **** **** **** **** **** +19122 GeryonSwiftFlight **** **** **** **** **** **** **** **** +19123 OtiaxAirBlast **** **** **** **** **** **** **** **** +19124 OtiaxOpen **** **** **** **** **** **** **** **** +19125 OtiaxUnlock **** **** **** **** **** **** **** **** +19126 AreteResistance **** **** **** **** **** **** **** **** +19127 AstarothsBreath **** **** **** **** **** **** **** **** +19128 AstarothWord **** **** **** **** **** **** **** **** +19129 ChupoclopsAuraDespair **** **** **** **** **** **** **** **** +19130 ChupoclopsEthereal **** **** **** **** **** **** **** **** +19131 HauresMajorImage **** **** **** **** **** **** **** **** +19132 HauresPhantasmalKiller **** **** **** **** **** **** **** **** +19133 IposFlashInsight **** **** **** **** **** **** **** **** +19134 ShaxFreedomMovement **** **** **** **** **** **** **** **** +19135 ShaxStormStrike **** **** **** **** **** **** **** **** +19136 ZaganAversion **** **** **** **** **** **** **** **** +19137 VanusFreeAlly **** **** **** **** **** **** **** **** +19138 TheTriadSmite **** **** **** **** **** **** **** **** +19139 DesharisTeleport **** **** **** **** **** **** **** **** +19140 DesharisSmite **** **** **** **** **** **** **** **** +19141 DesharisAnimate **** **** **** **** **** **** **** **** +19142 ZceryllBoltsMadness **** **** **** **** **** **** **** **** +19143 ZceryllSummonAlien **** **** **** **** **** **** **** **** +19144 ZceryllTrueStrike **** **** **** **** **** **** **** **** +19145 EligorChromaticStrike_Radial_Master **** **** **** **** **** **** **** **** +19146 EligorChromaticStrike_Acid **** **** **** **** **** **** **** **** +19147 EligorChromaticStrike_Cold **** **** **** **** **** **** **** **** +19148 EligorChromaticStrike_Elec **** **** **** **** **** **** **** **** +19149 EligorChromaticStrike_Fire **** **** **** **** **** **** **** **** +19150 MarchosiasSmoke **** **** **** **** **** **** **** **** +19151 AshardalonFear **** **** **** **** **** **** **** **** +19152 AshardalonLocate **** **** **** **** **** **** **** **** +19153 HalphaxImprison **** **** **** **** **** **** **** **** +19154 HalphaxBarrier **** **** **** **** **** **** **** **** +19155 HalphaxMansion **** **** **** **** **** **** **** **** +19156 OrthosBreath **** **** **** **** **** **** **** **** +19157 **** **** **** **** **** **** **** **** **** +19158 **** **** **** **** **** **** **** **** **** +19159 **** **** **** **** **** **** **** **** **** +19160 **** **** **** **** **** **** **** **** **** +19161 **** **** **** **** **** **** **** **** **** +19162 **** **** **** **** **** **** **** **** **** +19163 **** **** **** **** **** **** **** **** **** +19164 **** **** **** **** **** **** **** **** **** +19165 **** **** **** **** **** **** **** **** **** +19166 **** **** **** **** **** **** **** **** **** +19167 **** **** **** **** **** **** **** **** **** +19168 **** **** **** **** **** **** **** **** **** +19169 **** **** **** **** **** **** **** **** **** +19170 BindVestige **** **** **** **** **** **** **** **** +19171 PactAugment **** **** **** **** **** **** **** **** +19172 ExpelVestige **** **** **** **** **** **** **** **** +19173 AnimaMageExploitVestige **** **** **** **** **** **** **** **** +19174 AnimaMageVestigeMetamagic **** **** **** **** **** **** **** **** +19175 AnimaMageVestigeCasting **** **** **** **** **** **** **** **** +19176 TenebrousRebuke **** **** **** **** **** **** **** **** +19177 TenebrousDestroyEmpowerUndead **** **** **** **** **** **** **** **** +19178 TenebrousUmbralBody **** **** **** **** **** **** **** **** +19179 TenebrousBlastVoid **** **** **** **** **** **** **** **** +19180 KnightOfTheSacredSealVestigesProtection **** **** **** **** **** **** **** **** +19181 KnightOfTheSacredSealVestigesPower **** **** **** **** **** **** **** **** +19182 KnightOfTheSacredSealVestigesSurge **** **** **** **** **** **** **** **** +19183 DantalionScholarship **** **** **** **** **** **** **** **** +19184 DantalionOverwhelmThoughts **** **** **** **** **** **** **** **** +19185 DantalionGlare **** **** **** **** **** **** **** **** +19186 **** **** **** **** **** **** **** **** **** +19187 **** **** **** **** **** **** **** **** **** +19188 **** **** **** **** **** **** **** **** **** +19189 **** **** **** **** **** **** **** **** **** +19190 **** **** **** **** **** **** **** **** **** +19191 **** **** **** **** **** **** **** **** **** +19192 **** **** **** **** **** **** **** **** **** +19193 **** **** **** **** **** **** **** **** **** +19194 **** **** **** **** **** **** **** **** **** +19195 **** **** **** **** **** **** **** **** **** +19196 **** **** **** **** **** **** **** **** **** +19197 **** **** **** **** **** **** **** **** **** +19198 **** **** **** **** **** **** **** **** **** +19199 **** **** **** **** **** **** **** **** **** +19200 **** **** **** **** **** **** **** **** **** +19201 **** **** **** **** **** **** **** **** **** +19202 **** **** **** **** **** **** **** **** **** +19203 **** **** **** **** **** **** **** **** **** +19204 **** **** **** **** **** **** **** **** **** +19205 **** **** **** **** **** **** **** **** **** +19206 **** **** **** **** **** **** **** **** **** +19207 **** **** **** **** **** **** **** **** **** +19208 **** **** **** **** **** **** **** **** **** +19209 **** **** **** **** **** **** **** **** **** +19210 **** **** **** **** **** **** **** **** **** +19211 **** **** **** **** **** **** **** **** **** +19212 **** **** **** **** **** **** **** **** **** +19213 **** **** **** **** **** **** **** **** **** +19214 **** **** **** **** **** **** **** **** **** +19215 **** **** **** **** **** **** **** **** **** +19216 **** **** **** **** **** **** **** **** **** +19217 **** **** **** **** **** **** **** **** **** +19218 **** **** **** **** **** **** **** **** **** +19219 **** **** **** **** **** **** **** **** **** +19220 **** **** **** **** **** **** **** **** **** +19221 **** **** **** **** **** **** **** **** **** +19222 **** **** **** **** **** **** **** **** **** +19223 **** **** **** **** **** **** **** **** **** +19224 **** **** **** **** **** **** **** **** **** +19225 **** **** **** **** **** **** **** **** **** +19226 **** **** **** **** **** **** **** **** **** +19227 **** **** **** **** **** **** **** **** **** +19228 **** **** **** **** **** **** **** **** **** +19229 **** **** **** **** **** **** **** **** **** +19230 **** **** **** **** **** **** **** **** **** +19231 **** **** **** **** **** **** **** **** **** +19232 **** **** **** **** **** **** **** **** **** +19233 **** **** **** **** **** **** **** **** **** +19234 **** **** **** **** **** **** **** **** **** +19235 **** **** **** **** **** **** **** **** **** +19236 **** **** **** **** **** **** **** **** **** +19237 **** **** **** **** **** **** **** **** **** +19238 **** **** **** **** **** **** **** **** **** +19239 **** **** **** **** **** **** **** **** **** +19240 **** **** **** **** **** **** **** **** **** +19241 **** **** **** **** **** **** **** **** **** +19242 **** **** **** **** **** **** **** **** **** +19243 **** **** **** **** **** **** **** **** **** +19244 **** **** **** **** **** **** **** **** **** +19245 **** **** **** **** **** **** **** **** **** +19246 **** **** **** **** **** **** **** **** **** +19247 **** **** **** **** **** **** **** **** **** +19248 **** **** **** **** **** **** **** **** **** +19249 **** **** **** **** **** **** **** **** **** +19250 **** **** **** **** **** **** **** **** **** +19251 **** **** **** **** **** **** **** **** **** +19252 **** **** **** **** **** **** **** **** **** +19253 **** **** **** **** **** **** **** **** **** +19254 **** **** **** **** **** **** **** **** **** +19255 **** **** **** **** **** **** **** **** **** +19256 **** **** **** **** **** **** **** **** **** +19257 **** **** **** **** **** **** **** **** **** +19258 **** **** **** **** **** **** **** **** **** +19259 **** **** **** **** **** **** **** **** **** +19260 **** **** **** **** **** **** **** **** **** +19261 **** **** **** **** **** **** **** **** **** +19262 **** **** **** **** **** **** **** **** **** +19263 **** **** **** **** **** **** **** **** **** +19264 **** **** **** **** **** **** **** **** **** +19265 **** **** **** **** **** **** **** **** **** +19266 **** **** **** **** **** **** **** **** **** +19267 **** **** **** **** **** **** **** **** **** +19268 **** **** **** **** **** **** **** **** **** +19269 **** **** **** **** **** **** **** **** **** +19270 **** **** **** **** **** **** **** **** **** +19271 **** **** **** **** **** **** **** **** **** +19272 **** **** **** **** **** **** **** **** **** +19273 **** **** **** **** **** **** **** **** **** +19274 **** **** **** **** **** **** **** **** **** +19275 **** **** **** **** **** **** **** **** **** +19276 **** **** **** **** **** **** **** **** **** +19277 Arcane_Boost_Attack_Bonus **** **** **** **** **** **** **** **** +19278 Arcane_Boost_Armor_Bones **** **** **** **** **** **** **** **** +19279 Arcane_Boost_Damage_Bonus **** **** **** **** **** **** **** **** +19280 Arcane_Boost_Elemental_Resistance **** **** **** **** **** **** **** **** +19281 Arcane_Boost_Save_Bonus **** **** **** **** **** **** **** **** +19282 DragonShaman_Fire_Cone **** **** **** **** **** **** **** **** +19283 DragonShaman_Frost_Cone **** **** **** **** **** **** **** **** +19284 DragonShaman_Electric_Cone **** **** **** **** **** **** **** **** +19285 DragonShaman_Acid_Cone **** **** **** **** **** **** **** **** +19286 Jade_Phoenix_SpellSelect **** **** **** **** **** **** **** **** +19287 Jade_Phoenix_SpellSelect_Convo **** **** **** **** **** **** **** **** +19288 Jade_Phoenix_SpellSelect_Quick1 **** **** **** **** **** **** **** **** +19289 Jade_Phoenix_SpellSelect_Quick2 **** **** **** **** **** **** **** **** +19290 Jade_Phoenix_SpellSelect_Quick3 **** **** **** **** **** **** **** **** +19291 Jade_Phoenix_SpellSelect_Quick4 **** **** **** **** **** **** **** **** +19292 Jade_Phoenix_ArcaneWrath **** **** **** **** **** **** **** **** +19293 Jade_Phoenix_RiteOfWaking **** **** **** **** **** **** **** **** +19294 **** **** **** **** **** **** **** **** **** +19295 **** **** **** **** **** **** **** **** **** +19296 Jade_Phoenix_MysticPhoenixStance **** **** **** **** **** **** **** **** +19297 Jade_Phoenix_MysticPhoenixStance_Unaugmented **** **** **** **** **** **** **** **** +19298 Jade_Phoenix_MysticPhoenixStance_Augmented **** **** **** **** **** **** **** **** +19299 Jade_Phoenix_EmpoweringStrike **** **** **** **** **** **** **** **** +19300 Jade_Phoenix_FirebirdStance **** **** **** **** **** **** **** **** +19301 Jade_Phoenix_FirebirdStance_Unaugmented **** **** **** **** **** **** **** **** +19302 Jade_Phoenix_FirebirdStance_Augmented **** **** **** **** **** **** **** **** +19303 Eternal_Blade_Blade_Guide_Dummy **** **** **** **** **** **** **** **** +19304 Jade_Phoenix_QuickeningStrike **** **** **** **** **** **** **** **** +19305 Jade_Phoenix_EmeraldImmolation **** **** **** **** **** **** **** **** +19306 MasterOfNineDualStance **** **** **** **** **** **** **** **** +19307 Eternal_Blade_Maneuver_Quickselects **** **** **** **** **** **** **** **** +19308 Eternal_Blade_Maneuver_Quickselects_Convo **** **** **** **** **** **** **** **** +19309 Eternal_Blade_Maneuver_Quickselects_Quick1 **** **** **** **** **** **** **** **** +19310 Eternal_Blade_Maneuver_Quickselects_Quick2 **** **** **** **** **** **** **** **** +19311 Eternal_Blade_Maneuver_Quickselects_Quick3 **** **** **** **** **** **** **** **** +19312 Eternal_Blade_Maneuver_Quickselects_Quick4 **** **** **** **** **** **** **** **** +19313 Eternal_Blade_Eternal_Training **** **** **** **** **** **** **** **** +19314 Eternal_Blade_Eternal_Training_Maneuver **** **** **** **** **** **** **** **** +19315 Eternal_Blade_Eternal_Training_Racial_Type **** **** **** **** **** **** **** **** +19316 Eternal_Blade_Guided_Strike **** **** **** **** **** **** **** **** +19317 Eternal_Blade_Defensive_Insight **** **** **** **** **** **** **** **** +19318 Eternal_Blade_Tactical_Insight **** **** **** **** **** **** **** **** +19319 Eternal_Blade_Island_In_Time **** **** **** **** **** **** **** **** +19320 ShadowSunNinjaTouchOfTheShadowSun **** **** **** **** **** **** **** **** +19321 ShadowSunNinjaFlameOfTheShadowSun **** **** **** **** **** **** **** **** +19322 ShadowSunNinjaFlameOfTheShadowSunAttack **** **** **** **** **** **** **** **** +19323 ShadowSunNinjaLightWithinDarkness **** **** **** **** **** **** **** **** +19324 ShadowSunNinjaDarknessWithinLight **** **** **** **** **** **** **** **** +19325 ShadowSunNinjaVoidOfTheShadowSun **** **** **** **** **** **** **** **** +19326 ShadowSunNinjaVoidOfTheShadowSunAttack **** **** **** **** **** **** **** **** +19327 ShadowSunNinjaChildOfShadowAnddLight **** **** **** **** **** **** **** **** +19328 ShadowSunNinjaBalanceOfLightAndDark **** **** **** **** **** **** **** **** +19329 ShadowSunNinjaBalanceOfLightAndDarkAttack **** **** **** **** **** **** **** **** +19330 RethDekala_VilefireBlast **** **** **** **** **** **** **** **** +19331 RethDekala_MartialSpirit **** **** **** **** **** **** **** **** +19332 RethDekala_ThicketOfBlades **** **** **** **** **** **** **** **** +19333 RethDekala_DauntingStrike **** **** **** **** **** **** **** **** +19334 RethDekala_DeathFromAbove **** **** **** **** **** **** **** **** +19335 RethDekala_DisarmingStrike **** **** **** **** **** **** **** **** +19336 RethDekala_EntanglingBlade **** **** **** **** **** **** **** **** +19337 RethDekala_WallOfBlades **** **** **** **** **** **** **** **** +19338 RethDekala_RecoverManeuver **** **** **** **** **** **** **** **** +19339 **** **** **** **** **** **** **** **** **** +19340 Shadow_Conjuration_Conversation **** **** **** **** **** **** **** **** +19341 PNP_SHADES **** **** **** **** **** **** **** **** +19342 PNP_SHADES_QS1 **** **** **** **** **** **** **** **** +19343 PNP_SHADES_QS2 **** **** **** **** **** **** **** **** +19344 PNP_SHADES_QS3 **** **** **** **** **** **** **** **** +19345 PNP_SHADES_QS4 **** **** **** **** **** **** **** **** +19346 PNP_SHADES_QS5 **** **** **** **** **** **** **** **** +19347 PNP_SHADOW_CONJURATION **** **** **** **** **** **** **** **** +19348 PNP_SHADOW_CONJURATION_QS1 **** **** **** **** **** **** **** **** +19349 PNP_SHADOW_CONJURATION_QS2 **** **** **** **** **** **** **** **** +19350 PNP_SHADOW_CONJURATION_QS3 **** **** **** **** **** **** **** **** +19351 PNP_SHADOW_CONJURATION_QS4 **** **** **** **** **** **** **** **** +19352 PNP_SHADOW_CONJURATION_QS5 **** **** **** **** **** **** **** **** +19353 PNP_GREATER_SHADOW_CONJURATION **** **** **** **** **** **** **** **** +19354 PNP_GREATER_SHADOW_CONJURATION_QS1 **** **** **** **** **** **** **** **** +19355 PNP_GREATER_SHADOW_CONJURATION_QS2 **** **** **** **** **** **** **** **** +19356 PNP_GREATER_SHADOW_CONJURATION_QS3 **** **** **** **** **** **** **** **** +19357 PNP_GREATER_SHADOW_CONJURATION_QS4 **** **** **** **** **** **** **** **** +19358 PNP_GREATER_SHADOW_CONJURATION_QS5 **** **** **** **** **** **** **** **** +19359 SPELL_MYSTIC_BACKLASH **** **** **** **** **** **** **** **** +19360 SPELL_ACIDIC_SPLATTER **** **** **** **** **** **** **** **** +19361 SPELL_FIERY_BURST **** **** **** **** **** **** **** **** +19362 SPELL_STORM_BOLT **** **** **** **** **** **** **** **** +19363 SPELL_WINTERS_BLAST **** **** **** **** **** **** **** **** +19364 SPELL_CLAP_OF_THUNDER **** **** **** **** **** **** **** **** +19365 SPELL_SICKENING_GRASP **** **** **** **** **** **** **** **** +19366 SPELL_TOUCH_OF_HEALING **** **** **** **** **** **** **** **** +19367 SPELL_DIMENSIONAL_JAUNT **** **** **** **** **** **** **** **** +19368 SPELL_CLUTCH_OF_EARTH **** **** **** **** **** **** **** **** +19369 SPELL_BORNE_ALOFT **** **** **** **** **** **** **** **** +19370 SPELL_PROTECTIVE_WARD **** **** **** **** **** **** **** **** +19371 SPELL_SHADOW_VEIL **** **** **** **** **** **** **** **** +19372 SPELL_SUNLIGHT_EYES **** **** **** **** **** **** **** **** +19373 SPELL_TOUCH_OF_DISTRACTION **** **** **** **** **** **** **** **** +19374 SPELL_UMBRAL_SHROUD **** **** **** **** **** **** **** **** +19375 SPELL_CHARNEL_MIASMA **** **** **** **** **** **** **** **** +19376 SPELL_DROWNING_GLANCE **** **** **** **** **** **** **** **** +19377 SPELL_INVISIBLE_NEEDLE **** **** **** **** **** **** **** **** +19378 SUMMON_ELEMENTAL_MASTER **** **** **** **** **** **** **** **** +19379 SPELL_SUMMON_ELEMENTAL_AIR **** **** **** **** **** **** **** **** +19380 SPELL_SUMMON_ELEMENTAL_EARTH **** **** **** **** **** **** **** **** +19381 SPELL_SUMMON_ELEMENTAL_FIRE **** **** **** **** **** **** **** **** +19382 SPELL_SUMMON_ELEMENTAL_WATER **** **** **** **** **** **** **** **** +19383 SPELL_DIMENSIONAL_REACH **** **** **** **** **** **** **** **** +19384 SPELL_HURRICANE_BREATH **** **** **** **** **** **** **** **** +19385 MINOR_SHAPESHIFT_MASTER **** **** **** **** **** **** **** **** +19386 SPELL_MINOR_SHAPESHIFT_MIGHT **** **** **** **** **** **** **** **** +19387 SPELL_MINOR_SHAPESHIFT_MOBILITY **** **** **** **** **** **** **** **** +19388 SPELL_MINOR_SHAPESHIFT_SAVAGERY **** **** **** **** **** **** **** **** +19389 SPELL_MINOR_SHAPESHIFT_SPEED **** **** **** **** **** **** **** **** +19390 SPELL_MINOR_SHAPESHIFT_VIGOR **** **** **** **** **** **** **** **** +19391 FACECHANGER_MASTER **** **** **** **** **** **** **** **** +19392 Disguise_Self_Learn **** **** **** **** **** **** **** **** +19393 SPELL_FACECHANGER_OPTIONS **** **** **** **** **** **** **** **** +19394 SPELL_FACECHANGER_QS1 **** **** **** **** **** **** **** **** +19395 SPELL_FACECHANGER_QS2 **** **** **** **** **** **** **** **** +19396 SPELL_FACECHANGER_QS3 **** **** **** **** **** **** **** **** diff --git a/src/hakpak/peps_prc8/tga/armor_pallet.tga b/src/hakpak/peps_prc8/tga/armor_pallet.tga new file mode 100644 index 0000000000000000000000000000000000000000..7fae6b206785859e0f3e1a7e58225811d38493ac GIT binary patch literal 180268 zcmeI5cUV-{+P8@fv3Id6Ac_UCqbMk1L9v1gb_9FJib1h=jSXW>>^*9tF={j#O*1BH z>Pa;{CnqQUB1>;h2~hRIFGLRjO1$aBwif!om<99*)+nTf1)U+OsD;rwhept?#1riyK(sN zVO+m{-TI#J@xIT`cl|s#e{^iFUAs0?Qc}G3_sEeWxN+l#^*y2Ed`L(L8V5$BW8-8D z=r|Rld#%Lc^iw#v_BA}c<2v>|_6nAz9mkj+3y~B(263VNaPi_rG-%Mk`cBb&dH<@Y zSE)7HH|vF@xRIDTWHq)dI*F&YU&iLe$1!=pa`b4Miq@gs5mq|V!B?%?1uddRA|_!8 zIu6{4zEj@BqRpQmXa6lM+4ceYjCuo|5;r5dV3R55%NaQ?a%C zE?l1W8s1p@7M`De8SA@k#n?uZky36LI^^%_;MYzXf}?9!;oRY4xb*Zn+_-!dpS}H| z>vr?S*YM(rXYlN{&Dgal)4`Vv@JFT6B~U*k2<=)l$Akg>@Z{oboZY`0PcE8^vB^nj z(q#u13@7>A_P;h4WZ2P0=>qC@ZAXcFBP)$4`9ziesvx!Hf4-U&z? zm4>nNvXHrM1vVZ#h|{mUf@fd4gl8^a!umt|Fm>e$44aXGZs|iE`!DEU07Z%wM%9{u zXwtF)2Bh}J(zSE3@2MSFymmJF4NE|SCZQ-7SPK3D1s%M9fkG(mUj(%(RzvH0O))ZI z5H`G$) zz}k7UF|1btnuLWSuuLfg6msrAUqAo~l`M%ep`i$B*B&t$(~y4X2v%LVh~Wnhq1EIJ zRBh81MXOdr{-Q-4`!7(yAO8NuQ8BO?=rp^l`LYv<9`uPDici0Vo=gj7yg; zp?>}P=+UDGnl^1J_W$I`la~L6m-^4V)PLrs{xdK2pLwbO%uD@eUg|&dQvaEk`p>-7 ze+Mu0pLwbO%uD@eUh2Q$bsM}%lO~q`fz5iOMdyAF|Ks+YaQRRW@{tp~D z&}!35vp@&;Z6M4{)dmBX2t(u**mQGZ}(rvf4_v0(7cZS+F#wDC-r~bx^*u9 zH81s_d8z-*OZ{hF>Ob>R|CyKi&%D%s=B55KFZG{!ss9dM=s)vP|CyKi&%D%s!)yO_ zf1cfco&Wb5J=c-{x9*W@<^S4$&1?UM4IB1{{MUViy8Ul>ssGGN{bye4Kl4)mnV0&{ zywrc@rT#N7^`CjE|IADMckn|0nV0&{ywrc@rT!a!=+L2-|9+7@t@c01|B0)Qy4wHR zf1Uqp|241upEG9;I&|nDj{o!L&$s+Hywrc@rT#N7^`CjE|IADMXI|<*^HTqrm-^4V z)PLrs{yTV~|IADMXI|<*^HTrqd~9s2EB@>LKa>CK{y*b?kMvo2`u{Yq{a>Ro!9gAO#W~Dx3~Xw|DTTk z#($mvYhL@mYu7Go9*;Es&zd#M^55`M|CyKi&%D%s=B55KFZG{!ssGGN{bye4Kl4)m znV0(S;D!D(FZG{!ssGGN{kQXazMsAS&*cBQ|DW@JGybP}<9|d%ggE|>A3xsZzviX> zGcWa@d8z-*OZ{hF>Ob>R|CyKi&%D%s=B55KFZJKS3;kza>Ob>R|CyKiZ|8OX?oIx$ z=l>Z0HLv~OzJ0spu{8dV9zELP3@`Pcd8z-*OZ{hF>Ob>R|CyKi&%D%s=B55KFZG{! zss9dM=s)vP|CyKi&%D%sJFh)9@!vlG&p!Uo`M>6k|9>R@4;eB9HEY(izCZp*{AXV3 zKl4)mnV0&{ywrc@rT#N7^`CjE|IADMXI|>RgBSYGywrc@rT#N7_216x_;38TkN=tZ zzwYM$3?4if)vH&>o;`bzoSbaU0np=s@$vEK+O;d<;^Lsk6?A=%zUlfQT}Pzn8t8hD zUcGvuS+iz7-uLiun71Z@YJ$v@F z=KX*B?YDSE)p@+|!V5Tm{yZ*RxPY@~&*IpzW7xTKC$?_tkGdxcY6K zQ~5rB-{=3J*5B~e@B8Zaef9efu73YP`)BI^rvztUVWZX9)!-~nHM)swJ-)@qbAQB# zSwG^VM}NfY3E$#W!yDM#Y!4PST;{4jHheXyOK9`%qhq$5^L>VcE1({T0ZD%?E11+N@gjbkf^W5KxYm^iQ%QrlK>@S&k4 z(4kuxhL3N7xl5vP^w}P`@xgR_cq<2Qyqk&L&vwJK>}d2)ZHo4B)f{};vISACW=TXe zt%dj=jgUFNE1o$w9xuO{gCnOWV%nT8=+LDB!WvdYg+OQhd|;ezqbS|v~|E*OymTcg9Y&PaZ8Am&|} zk1aR1WB#QD=)ZLk+E0i>!~V@sroHp{E5#(B`B1g~L$+G~VY^!Y;dQnC!zXI}hg)j> zhY!^H4_DOs4{O!>4;h)LJHUDU1XQn$>g_rrGG!n-Oqqt{ZBJs}SalHQ`MQWi^wf1NdnT(julhAkg zc09WBGIDmliL9kBpwHmVXwzW~YS-_JvgM;)ys6)p`fuuw4KMYdd8z-*OZ{hF>Ob>R z|CyKi&%D%s=B55KFZG{!ssGGN{bye4Kl1@X|CyKi&%D%s!<+hjssE<_*zi*SnV0&{ zywrc@rT#N7^`CjE|IADMXI|<*^HTqrm-^4V)PLrs{xdK2pLwbO%uD^Z^LlJR>c6Q! zHtPpS{bye4Kl4)mnV0&{ywrc@rT#N7^`CjE|IADMXI|<*^HTqrm-^4V)PLrs{xdK2 z-|(h>U+TZ9KQ_G7f99qBGcWa@d8z-*OZ{hF>Ob>R|CyKi&%D%s=B55KFZG{!ssGGN z{bye4Kl4)m4R7lArT*LNkM&#wssGGN{bye4Kl4)mnV0&{ywrc@rT#N7^`CjE|IADM zXI|<*^HTqrm-^4V)PLrs{u|!Z?@Rr+*B|S7#8Us6m-^4V)PLrs{xdK2pLwbO%uD@e zUg|&dQvaEk`p>-7f99qBGcWa@d8z-*OZ_*zso$6SZ?8Yr^N*$eGcWa@d8z-*OZ{hF z>Ob>R|CyKi&%D%s=B55KFZG{!ssGGN{bye4Kl4)mnV0%+cvHVG_1|89tk)lq`p>-7 zf99qBGcWa@d8z-*OZ{hF>Ob>R|CyKi&%D%s=B55KFZG{!ssGGN{bye4zn$0hds6@H z^~ai*`p>-7f99qBGcWa@d8z-*OZ{hF>Ob>R|CyKi&%D%s=B55KFZG{!ssGGN{bye4 zzu`^&zSMtv{jpvLSn5CXQvaEk`p>-7f99qBGcWa@d8z-*OZ{hF>Ob>R|CyKi&%D%s z=B55KFZG{!ssDEVkHmj_{qY}(|IADMXI|<*^HTqrm-^4V)PLrs{xdK2pLwbO%uD@e zUg|&dQvaEk`p>-7f99qB8{Sv{?_2-CxBkO_@A?LH#cMX7!u) z8EC8OtD83K;^3=QtA^m5E8`i9f z_D#c))TIN`lasJ`RtENL-iX7ypTy2h>#<t7b}FN7);%A;}pFbwF` z9V_O{!h!9ZvEtDgNJ;2|@X#QXFIgP=wHGg5wAODn=WlHNDp(R3j17Hauy1e|ypTBp z*SD?2^{p%L=9cBSFf$GNk~?5aTmvj>QPaVRnbpjoHgD+AbA4(M}fY1u1(Y|g?OzjedgBj{N+o(RnNkcHLV{=3YRYLXR z0Vq~5zk?r<+6Y-wW3X#Y2R!>^SG;j{G(Nue7(RMK-CkdVYiCB{>FwRHW?>g(PK$Ez z(d{c^@PKekpAdt`7Ien*2U2kJ#YK4kwRL#&g+(~EF9l2HcE+S}tuSCf9S2{zdH~u+ zS3&=zCKx|D29K}ni}NQR#cMC-;M}P!Y-7f99qBGcWa@d8z-*OZ{hF>Ob>R|CyKi&%D%s=B55KFZJK>rhZ@QzrB7~uL&&m zpLwbO%uD@eUg|&dQvaEk`p>-7f99qBGcWa@d8z-*OZ{hF>Ob>R|CyKi&%D%sJFn~i zrT&}xVN?Gv^`CjE|IADMXI|<*^HTqrm-^4V)PLrs{xdK2pLwbO%uD@eUg|&dQvaEk z`p>-7f5V&leX0MZe%SC*|CyKi&%D%s=B55KFZG{!ssGGN{bye4Kl4)mnV0&{ywrc@ zrT#N7^`CjE|IADMH@vC;m-=t&hYc_FpLwbO%uD@eUg|&dQvaEk`p>-7f99qBGcWa@ zd8z-*OZ{hF>Ob>R|CyKi&%D%s!<+hlssE;a*zi*SnV0&{ywrc@rT#N7^`CjE|IADM zXI|<*^HTqrm-^4V)PLrs{xdK2pLwbO%uD?@ys7_}`fuuo4KMYdd8z-*OZ{hF>Ob>R z|CyKi&%D%s=B55KFZG{!ssGGN{bye4Kl4)mnV0&{ywrcgoBDsL|MvP}UH>ojpLwbO z%uD@eUg|&dQvaEk`p>-7f99qBGcWa@d8z-*OZ{hF>Ob>R|CyKi&%D%sJFn~ar2d=w zVg3D~d8z-*OZ{hF>Ob>R|CyKi&%D%s=B55KFZG{!ssGGN{bye4Kl4)mnV0&{ywrc@ zrT!b<)c;HUx7QEr`hTha%uD@eUg|&dQvaEk`p>-7f99qBGcWa@d8z-*OZ{hF>Ob>R z|CyKi&%D%s=B57I`9Bi>P5rR`{`e#DpLwbO%uD@eUg|&dQvaEk`p>-7f99qBGcWa@ zd8z-*OZ{hF>Ob>R|CyKi&%D%s!~5$0ef9so`hQ>jzy96u^XJb)|AzS4vuAPa*s**5 ze)#a=!||Z&mwo&9tzY0wp)*REYLdGcgr zWMn|k&73`ZHWn^ih((JQVa=K~ShZ>ua&mHT>Cz?W?+M@ef4I;8{hmKl{~ZzE88HKs zkvwKJMr6*y!u9L0>*!JJJaPm(jvT_=^=mO~=2Ubam5w$8`Z?;4t2Ste@b>M|At?z- z>1oJVya*fj?8cLa4`KbzotU^_0eYmRp>>}=sNXKu!51lA7FFxkLzCzj#P#fjGJ(c6jl4*qbI_m+MuF(-9@TjFW_Gog#wD8eB~+#i)f7Q0|sE$vK838 z{{UvF`!4-c5Y#Xn#mkn5el7Fm!(!2>YdWIFEJLS9cOWh2IjlMPI@X+e6RV%OhE%nF zLENluh#veX!eR$Ic)$ErP&OnA_2UMjMe;QCoWB?I4qV1#Ctktao#)Vd_71e{Jsv?V zdZI|>W=>wm@ObB|yzrwk>f^OeE^2j4F=Rc} zbDn+%VmOci_v*%*c&VAT$ z{zdG(@+vl-K932TccSl`gncT^&c}`fccuItpRU zTcb>+YVa?T`}vvUZ_}Ob>R|Lwf4|Cjo2>W5AJztn%`rT#N7 z^`CjE|IADMckn|04X^#z{drRV_54rczdrv`|IPl*`Iq|7ywrc@rT#N7^`CjE|IADM zXI|>R;Z6O%)PGYyY-7e+Mu0 z-|*VMs#U9sT`IGu@_HTHp|IADMXI|<*^HTqrm-^4V)PLrs{u|!Z?@RqR z^}~jj`p>-7f99qBGcWa@d8z*nUg*E!$Bi48$9>%n@TUErrp97){5R)M>c82);idjF zFZG{!ssGGN{bye4Kl4)mnV0%+cvHVG_21MF8(!)^^HTqrm-^4V)PLrs{yTV~|AyD+ zv0%Z1dAOb>R{|#^I|E2!h z>xXsyztn%`rT#N7^`CjE|IADMckn|04Zm{bN^2gEwEs`{+v)gk&cD=uvwy=&{bye4 zKl4)mnV0&{ywrc@rT#N7_216x`aP-trheGe|4aR6Ug|&dQvaEk`p>-7e+Mu0-|*W1 zLWK&6<9|Xzg3Et>{-yq#{hRYI^`CjE|IADMXI|<*^HTqrm-^4V)PKX9`hTha_WEI6 z|1b5Qd8z-*OZ{hF>Ob>R{~f&0f5R_cyx8(s8vna=>0)u_{7d~e`!~GQf99qBGcWa@ zd8z-*OZ{hF>Ob>R|Ly!AiT|d4*wp_^{bye4Kl4)mnV0&{ywraOFZAE=+W$Wi|Mi%^ z{?0JxPwKzfzu~3+GcWa@d8z-*OZ{hF>Ob>R|CyKiZ+Kt*|HEDXzk2m*G;iMAnggK6 z0rhVn)~;O}dOegXRjNSO2kBe+^5vmx1$7Oe_Fm^~MT-`N@BBa9=l_1spRa!Y;jW+m z2M%EC)~(QUJoGrP&Jpy#Gcz+WWy%!mHfho%tM<=# z{vYo1f4}GNe(Q&Q{C{`-xbOTw+~@y(>xX^(e|P=3@BBa9=ik&nH>ffek-sU4W6{ICRjn2)MqgkyPs1rEE!51l{+Nq`6A|j+e+BF%ELEScD;k0M5 zWz|cVH~9>b<8sid-gwlhoP>%cA{~5zd__>GKq*ux9g4a&+oMa=R7@Ry5F3|W#H1mI z(Xsh71XYSgiGb=Tn7^2VuM|2Np>38TIyncO(+?nR-iuhV^DT9|fu%ccB6ZG1bR519 zjp8?>R@0>pzF5hws2n;HjoZ&aOyV;1o_G>j8?R#J6K`V9x|h&<%yG1cUyh*0nJ8a< zgo7`TKNuy-#33YnpjrcA61om}92pDFVbzvbF**BrbV%HSuojb1q1qq>6m`~*=X<0q z3KXn}QswHSdPpaCOw5^>#tzoxD#j^or#K7w)NBUJr%eN39FfuG(N zW42_dwG%cdb|+S!*ogGUr=ZjH-e{5@gP=Z59ekn6>fE&qLc{JY5IwXL1}sd+g8eJ8 z<@8Rqj>1axT{sjihQ^{+H&w&lBG|#_E9$T2Jr+T^pg`1)s*g^idt&m|N3s6oc8uSa ziT0xsP_so{6suAe`HMN%e`t}?AKk}|#*pkxj9s$~ix2L`zKiFu_l0xVqize;_NdiM z)Y=9!(0SY#$Nnotw?VT$z0qyNaHPzbhN)XOVe{#yEq2qX6PWz?M)aLJ1?^K)5!R=d zgD+g8Ix4k_MDy+m=savF($xAHD-IvP&U0t6{Lldmn?Fx|E<+HS&=qA`JFoxzrAorT zY#CIn9fEqQZ@0(jQJArP8@8T0iRr2>*m=|_1h;O5;-7f99qBGcWa@d8z-*OZ{hF>Ob>R|CyKi&%D%s z=B55KFZG{!ssGGN{WrX+-W2+4^`CjE|IADMXI|<*^HTqrm-^4V)PLrs{xdK2 zpLwbO%uD@eUg|&dQvaEk`p>-7f5V&lZK?mJe%SC*|CyKi&%D%s=B55KFZG{!ssGGN z{bye4Kl4)mnV0&{ywrc@rT#N7^`CjE|IADMH@vCemilk%hYc_FpLwbO%uD@eUg|&d zQvaEk`p>-7f99qBGcWa@d8z-*OZ{hF>Ob>R|CyKi&%D%s!<+hTssE;a*zi*SnV0&{ zywrc@rT#N7^`CjE|IADMXI|<*^HTqrm-^4V)PLrs{xdK2pLwbO%uD?@ys6)o`fslv z*7g5V|CyKi&%D%s=B55KFZG{!ssGGN{bye4Kl4)mnV0&{ywrc@rT#N7^`CjE|IADM zxAVIGPwKy^A2#*hQvaEk`p>-7f99qBGcWa@d8z-*OZ{hF>Ob>R|CyKi&%D%s=B55K zFZG{!ssGGN{WrX+--7f99qBGcWa@d8z-*OZ~U=eMzls$rT5CP&wV(9w!RqliU6*Ta?b@}2{+%dYr=xFrzJHSX zo$l`4yZe6sUHxWxojP?eK>c3$m@#88cI;Sdt(;Y>Rv{-R2OBo18dg<5xoz7v?A^N; zyLa!l*4ep!{kruz`|96)pWnlL{h0cFzoG%iU%oVo)vk&1ZJHxEr3WH1$D-e+pm_PRs1zEEx@}q^CM5|&r)OaP`p2;6=nMQ*4>(358u2=zdFJBxJL#tv=`<8fYSTc4zIt|Bj*5QTYNAc$6i@5df zJNWC@U*Vs>{o>#&l_-j!iscYlCm8)=qA+PtGM3DofgKyy;pDNW@XCuX;)8eJ#@3WY0HLWMf@RsD2F#P?0Z_{mw=uyPYl9yozlp1*<*ufK=yKl=uM|M71Q zKA=b`lu^H7Up=@!8bozOy8-DKl$nLBO^@Tr6DM%;rOSBrz4!3ZH{akde{=4?K#?*i zUbYIV1T{dDmT^exGYm7P%);i?>+tNMLwN1N1$=z-CcgjtGyLNx=jZQNq$vE#RzTre zbx^r!ESe^yq35V&m^AMMRzLoM`W^c3aOv{j@c#S%i|@XJ^Y*Y%~ zfY69TXw~^LdZ&Jdtd(D5^Pa!rdoKr>F57+@CE!^qhLU1_?H@u;#D`GcH|+n z>2n!L6Fx!q#&59o@L%xki$CGoyT9YJum9!X^X0FDeEFN9fPYW;mz;(wb+@BMrx%el zM)7OE#rDJBs|f7DgXS^EXH z?*A4iU-((^e^=L_bN`h)Pehd-vk@|G6T+7qMbjNGq4k+ti2dl_$o%o2*r9G0fBh#u zRkvUM{%^k6KB=m`S5T5a=ZV+Wow{l<$5R`8in#L z`k+?NiHI1x0&P}4gN$?UVdJ%L@$9YN@b1t5#?Sxwf3Ej$>i6&E|L!XnaQ5AsF8@va zu;K0ghqZ0(@c-3e$baUY{-4g{|2FcUdCULMXv_a{ zZv4+7{~f&D|CWiU)oapS{WrX+|M$j!d;GW859>CC)PLrs{xi@1yNmxHzW0tR{xi@1 zcS#y<#ecj1AKiH075|y{#{bvef8Q1VnK%Ad4Q>eSe`4>Uca8td8~+1>>Uxa-FJAfG z75|yPm;YP#=JlU>_MhYbZU0sLy%YbLclz&)|EFKfjsFhb;s4#^KlAtUU&sGTw)oAw z)Bn8j-}3*rf4TAp=I`ad75{(uw=4cTc=rDu@!!r{Yr(t8{~OO9=gR+e{I~mW>W5AJ zzukY6{|}on)noq8yxo7D|F0R^A5UaWcjf;a|Cu-bx2hZB%Kw+nn&~nBXWsZ;F8r`9J&5 ze6IgvZ2A8cSN_lOpZQ$>d*$Z;s{P?9|99{%|J!+$|1e)#{W8PyvqL#Z|e7@@!!-B8{VD&cWeJM&;E1!pZ#avwEyk?->v=6ygUDO z``?rQ%uCz<%zNwqU%&X=YX39O{@<(p&wOtC|L*?3ey9D{lDG+XWIXL@AUua_;E&nso!_!zdirw{(n;E_LpLyf|-P-^5 z{(t80mH(Umf8#&%x&GhI|8M)BoBx~sf8#&%x&E8{U-|DQ|2O_Sc$fbs|L6X{y#4>o zyZpaL|G)8{d6)mL{{OuFf877iyfpuJ@Wy|W|GV+u-v4iSQ@?*N|GEF))DIip_-~K@ zck`e5d->1#Kl8?a6aRJppF97}_#gAee{bVI^X~k=+xQ>z#{YZ8f8#&%#(!_)Kl8c% zyC474?SFgxXFk_|`}p4#c#8kb=lXBrzv}-}{(Fl54&LRziT}6z|8nF1w|U|}^HTqr zclv+3|IbtWXWr$1p7?(WCjRUGKYRRl@Wy`=|K0Te+2g%YDKFL(Ukb^O=kf6o4Y`}n_u zclmGPzv=&f%{BgS&;ObC=>LcRay$OdyeI$7_&?|W%)9b`)&6%k{>T11c;mm0|9bq- z_`l+5*Z9BPe><=1|Ge?v-v4jvhfV#z-G9^nZ}0!(_CND>|J~*P>_77+{(I{`^Pc?o z)c$8)8vmKM`+v9m-^~AEUg|&dx$&Ro|Ic1Otn2^pKF;Msq7G-en|G)qEql0Jv?>7GT=Rd>2JN-YHXa1jw|EB%#c>k{XeQj`_dLv;X$-zg3(5 z?vLsJH}ij)znlNlRlhyY|6|_ef1dXL?f9Re=Ku2iKL>C8zf1ey-v4KKU;XyOUBB%+ zf4=jVoSbac^mXXa0rBzi=-Ra_;^N{E8yjoY_vsq7wr$%&*NW=7y1HJeSFc`Z)~p$P z_1h13{kHG?`Oe=fue^d6UU&iL&!5KyRVQ}#>{%Q;b__dr?!=ZYTcC4v{qObb*JI_% zmDX+f^5qylT>W0J`cAl?`e7gM`}};@&mXV9f6)H;>eqes>ko7Ny6^hEzw6i3@8|bZ z^}~f5pkmoLgw`C3=$30Sbiht5n0p+1p1g=Nr*GnoYoFn>Pkz9U-#hE43l%PplBKJo zN{t9KY|d0?XQ2p*S|XVulw%`1y)Asum-3e+X>Bv zjX=NI*~rS-f+vrkP_^eT;q~|4$0uKZi@*N%n{)r=3c)X^2>c_ zv1dLWe{K(sUwsa*eDnrB`0i8u`R_kEc>j_CC>2-+Rl{l`Jhr*|4fmcH_2@(_-Lwk( zj~~Lh%NKB6t)Fn~>o4%rZ_f1(g7OtZ{i5X&7g!q;>O^5(yJYN2osJU=*W%)yqquSA z5y@rop{}_M$d05FA&LZdMy04RXg6>!hRs}$1?%@>&#|+3?!~LP{?5nv^y}~N(=Y#UeEx-smqp16 zRZ%@O0ugNz&}-mGOq@9ntJZJ9;isO#3opKmx8L~_zWnN2{QRqP{f46D{ZKAAAA%zT z&?==g`p;~H>8lg5Zud+aIlTifUOkDoKfH>szWW5f{{FpV|3ym`M7c^O5L~YcTE{g& z|6%c%nl%dRHZ8*uwSLCME6?NYcW>a!uRq7HZr0DJ7~qGRWdhK=R$26GQ4`sHn&R;( zi8!(*6BiC|!}W_N@#))F@z*au!asg??!Qz~e^e@03JpT4qf_e$r1$HJIn%~q^V;Qj z`sjXKx%fQZfBOc${_=A*{*`a_PMw6_;2cm4X^z#QL38d ze|Xa#F8`OVe8Teo{DoKZ_|Lp2{|9e8VfnxR%8fk!JNSF}fBN#vxccsUF8>|8_P>^A z|4+PrCXfHj+x>6Up@qZ$=dZkgH`V$H#((DR{!gsi#^L|XvoGfHpLwbO%-_rZH%`Bi z$A9Lv|CLKt_S%2u{XF=;aKk>!|1+0g&*MMycK;isnUiT|Gbcko{LZ;$^DUg$sb#{X*dYQdBL z_V~}dC;y*bw9bnE>_7AD|LC6m?;8J^_vHWKES0;c_^cJKyFBLqrheGe|J(i7`G3cR2^ckD2|UGr z<{kbITx;e3#(&QL9sC{t%hYRV<^N5GrlbF(^IZAAj{kQ59X$D8GqW|~9~`9J&5ygUCFOq}j9|7V{4pWk#Y9#7c_yZ`q5pLuuw zXOGYJnEx|x{4W~P#g+f3&e{M^@t=9S|DN)Hd;Djf{qHv;+{*v${@e3^2XFJ=w|1S`_H^P|L@lRXP*5x?SD`HGcRrbGw;rS z-TwFFKl66~y~+QXH|_ts#ecj14&IIb_Vz#f&%E7#Z{k1mQvVHa>i6yb+uQ%1@_$o5 zYi0SS z*Zu$Q^8e32{n6_GH}%7Y=luU({r}A8`k%M`@2UUa!Mln7_WYmw{~bK#|GNL*p8uQv z{}2Ci%j*AU-uSQE|L*dC)Bpe3H(y%)|IB;x-&6lT^TvOB|G&HZ|Ic5j`Ulnj&%7u9 zJ@x-HFU|j%H~!o6e|P==x4!v{)&I}D-G6WLf95&=zgPdigLf1E?fF0V|1)p=*X@6u z|9k5H`{ApPt^R-J?f$#V|GEF)@TPv>o&S3L&%}Qo|1Tl_1}H`*X@6M z{CDue`0wEF;Xmj9%p3o`jsMJh^50YZXWm=?&G;Ylp8WTe|1yP9{-uYm;c=UH@vC;_muy88vnP~59|7W zlmB!3-_!U%^SSS7;{@<VkjsG)m{Pz_9dHj!gPyXA-|Lyrd^Cti2 z_P?j`e+O@i|L*$#IsP+m{J&fOzukZ4?f!d{|J!+8|K}Ey|OJ^tq@{(rB2|A*hdANjAx|J?bn+yCGG{)2<}#(y3Eb^HIv zUw?A&>_3nHas21^&;ENF|2OS_=GlKe{-@{v+5I=;fB*Q)KOFC0>Ob$_TmMb_pLuWm zH}U_cU!3bVu>bcO|Kt6e`G0!+-<|*V`2WkV&h;C-@n6S()BflE+x^$^KdohB{u#G_UFRK&KPimow>F|E&0obCS%4i4Ifi|Lto zc6bI>qz*#Hq$ms>(%4b|oWG!|f36sWn$;pvzjhBKwV8`E{hoI5i@GGDcVr7hwycI) zHA_4A%8jR@QEVm#q|L<&RkMCm{nowxKfS$r%{n9xpNp{QYzJSZaRzF)S%A2{i;X<2{Pl=UT!I>{mO6Obc(Cx^+X%nl(|pcyZ|0Uc7h_dfjGo{?pUbv2fu+=(?~oXU^akwMMf2 zKfSFV*U#(MG4JQ+2YvJR_qX1I{=E3})9+0`uV2S}$bt9K@wv}2{PH)LfBk!0`u2DG z?yYV8xPD&0j`;x@Ph#5g6Ij0OJa!$wiW~2Lm50~c`f>fdejW4rJ(Vb40@bV6K(nUJ z&@CYWBSwtCyzFdj-MZB}4{uz11D}8XIev4qe#GwSV{v2i3VgbEBTmelij?RUC{?&1 ziWDn>F%u`@<4-=tfBy5oxT)4~)^l%p|D8K`hPO9;V9cA(-`jh`oBI8_T|1%qupx*` znuf0JmLRR)F)T?xi=+Kd;h0%U7<$jT`R$*WV9eG1+eU z2JN!Yci22ET)Iy6_g>3${;#XQm!oo{3#igZ`QIK{S=o86-#P00 zpk8=um;e0!Ej~B{0fF(TqxhMb^YZZ8hui+gTK+Sy*KX|7rw>w6QZRDlNSFUlJ@u5e zhMRV7^5n@@zpeJ4dF`~ml`mf&jT$v_`M+`FMvNUh)>;R$N|h=u|CyKi&%C+ry!D@X zssGGN{bydkfBoHP`LEW+OmO)>&+`A&sZ(nGi)$|bnV;A_4hLpUz*}2a;*&k9ZgTb{ z^oeYYVg(DJWSO#Rs3$G{O^~VjioErL;Gs~&%}Sr ze-;1j^~-wwfpQV^QLFW0ME6>XDYG{?@(2C*<}O^1jw(OUuVemR{=4FT;O+SDjxSg_ z35Cl=A|$*U`VC)-9S5)C)Wy$m_R_m|;(v1#t`K8=&oJMyV@J#Xp+i;8@tyd8;J^VK zI&=t|Hf^$EhJIW>ul;A<_^+?w`t|Eu{_F1y?f-7 zf99qBGw<@hhKm2n|85E0toWZj@3#LZwf}GA#((Bp)vk$*-d%7cYck&1z6Kxf-hkaR z#-dx(h6u?22+CIs#GC~S@R#qu$G`slFUR>aUfZvEcmFo8?=C}(OIp8=_V-{ju^NASRZ~#pGu&Mvo{+Cs?OChZy z(5P1edd|tlsN>JM_-^X^AhLFMG_TYGwMy1>@KqX5w&MTY{9mQ={}dJf>qO6U@D&@+ zLS6N}5TCpdgU4;eW7}T9!klY(bj@pO?Dz}pJaom1|CawziyeG!{@?p{{CAuGw{pdQ zK7Rk83>2)Ch{7dnqhWXirm3~3UU~g}eD&wQVfp5lFlf{ggz5G}`8KMZG2XF%o&RgE z)6&vh{;yrT)`}B42hj61bsSGkO|@Rf`?veAJ=ghvW@e_9|LgC8cJ11shPt**{?EMB zf9B0~=dJ(DOZ{hF>Ob?wfBhNh{69gpmqw^OEPLMV{QuOclelKf|CujUxDeXb4aUr* zZaA*;|M#AF3?DqX4%;V>KwQH*DD=o9sI1x+%T}(&Pe1?cIRD0Lch1`%Gq2iK6d=9Kyl*mX{|VNN1#&`QKbWuR-r!H(Zw zFR1dI8Y-_3ZC(?#d(=bM`D*>YbGdx?-V4!M|1Od0AE>1KH}%J6|5dgB?H@(r(0N$0 z+-^!i|G}33_V%xC{|_Fu7}djvsQBN`EpOWY+JEi&s#U8j_jR78 zZ+h+KQKLp-@ZiB#p1|+FNRc84QEjW*wQHkk)26QcU$_6KPoIufty-zvwz|uI=B55K zZ>~FU{bye4Kl4)mnb+@MxBo5wn>DrK|47yTcl!T@)&6(Kmn~8lvGqeSC%FesE|{VG zUyJwE_dw3LVb*s;fk*sMD>M`vavpbFKgMgj>+b$-UgvKA<{Wr)Z+KI`-?dI_q_%30 zj4?5oKPMg|52j<(nGB3NcLF2Np2mp7$IwHy3pyoEM{JwnRz9lpf5R8dR{%lfDk8F3 zbtJ^sL$@sTH=fJo<5hb)yhAV5KhO#l%LhAn9shOvz1N`ms{QWXf8GC=qWsr!-qbIf z{Tn`Ui0XGx{&V}`wb!pBQS}S9@3X|p|Czt-ziR(iO;YXm4tMGQyY0V&xBTy|;(v(c z|G<$;@Z{mE)+sdohr!`J5Kto(g+pdJ-oM>{-Tv3{-t;>e|8@J{e&$|L^4g zy8VAmwg11k)BneOsj_9Qe$9%-0?@fp80HV`gXflH;=`Tm@b{)2svpZ@= zMxty@wZ56^SJmGihS%}CUd&u{AFu%P7b}0S->@IH)tR4aV)6zwjbDMFs6~$b`v*-{{c@`Ru4@0={;TgRd;hiW|FiPFcM`=9r( z^M9QKG;G)q&6_vRp$~S|CyKi&%A#Bx^3jj z|5g9r$Ppv+^#AMp|BKIW$A9J{+eD*SsnXVWK;;s}kkCY3+r#?d`Q=&oXqUR4)!2aE zj;K+^dJXf&>pT~&n+@|i=FR8t?Y-em{eJVBaaOy2YU@-i?=%w6jLyK>18HjQ$49YE zeTNM`I2wuB6A_a!5$%Q!QT^jtmcNG2ul(2T`p9Y#=oJ=)g$ao`yFZujn3aHtZtYPc zvNw8Cn*2tY5(uh|Hu2+;|KctqsPDnR{oH={0uf9c-Qp_>c6M+ie~XE zQKjVy$Nv3Q?tk0=es2BO`FvP-TNJJoZ?)ff|F`r1K9>KX;c-Y9xEz1_;1j3+Wt*W; z_2G{Fck0y1YS-&|*{1(*_wL;|sDAtJvBw_60@ZgkY0@OCe?a#W@cy;`ItQqwKHKQ% zXv=@i==@)||F!@2{(t7B{xff`J8%7GUg|&dQvaEE`LE)CGb{hs^derWQ`R&Hzf{o9do}yxJQ`Br8f^s#hIQXiK zCt3bl{x5Rxzt#VDr~PlQU)JNwdi=o3AC&(KmaNB<2QRxm!7sl34X2;KYWd$SWufIi z^SVz?e+S&o|6|?e|F`|`qWquWc>lTW|J(h4rv3lx-~NpgXWl~ExJ4>2Q1QQPa}=tU z>fpO{>EiNV_t)$Auls29?>6aw&zLd8>W|j_e|n6N-@m>8&-DLKojTPTKhSMG-5+T0 z|7Tw6KlA3g^VWanrT#N7^`Cjm{}OlNzt#VLd;DL=Nvj=Z_5bCL|1p19^_P#GFcFPZ z-(le*MXm3ET4hTisdZDV9W@A-*UYoV1z%aW2(wflA@jy-*G22$ALez;o6q0ddpob| z|LSzlzrt^N0q|6Bck zZRa_7SNlQvZ?zw6`NLZu{D2jk&Rc(1f4_vNc|!dDUH(@|^w|El{0~(AtNA|;-qrt? z*Z-Zz{)BmJFQMyz6$lOQsKy6dz`uIBgE#rV_FLC>>V6F!zmFU_;>!OgOqgKx{psI! zU7(BAd1c^&WHeE#0v8{X9a*XbON#=|-zDqZFHYOH=r;yx_sdmLv6sPBN(H8?pq z6HC*3A!B%~n*Yz^w{%vAk)OVBc51t!egkf;6d&wu?d*6p~69>a3b zrT-#?ww>?bbxhY|czXVx&fne5{|gImgTi;(|GfX)_vObpshZcI=KtyTfu5Vf`#1iVRsB$rs*lA!|4;wT zmMvRaV*_UVk9n#8%$w`ZTmPAt`p>-7f9CD}>;6AIU(%ZYcW3G*&g=N!ylZoW4^@6K^s3t)t*eKqae_(?UdMkuuQy)# zIY;@g=j+=4GxL82kCd>i|N8If_Wwlnz0g~YFX(;-=5M$E zry-zPii-bnc+_qGpYeaJTfU&~|GU%wZ~WK$*8P8aK4A6m!Rq@ZQRV+b9X$K5$NO}@ zUrtVrHGZf21a$n@V*@(>=l5^?*M5hpF($kJI{(+#v+mn6{xdK2pLui5dFwy(QvaEk z`p>-azqZ8VA$97i zv6e#c&-Vx#R1HL0$7no}F%s8QKLGREYj1D*nquC3{@&gj-dDfZK4`g^ec`Rdnw_3ICF{kre^y}#?%RsZc5 zggJiok>l4C$Nbvhs$VmFQ@s;@j~t9|s&=-v_2V1V^RxZx!PE~MzGD6&Xj-TO5&~*s zRI&P4R4NjC%5}ua3Z1Nby{#Ybrk;-|RNlcisZkr9)cANx+s+u@wIAjWNXLQs%W?UM zy*My$nYFDS?;q6(9U3%q@Veilbm5{14XlQ!dJ#yBj>E*n!N?k-eg|IN>uvpbNMKcz z^e^Jz(-ZwLXS5%39`#dWoqo7_#t+|oULC*x5{YjPCik=y4TzK@owt*h_FJA{Wob;1D#^Sk&@UJ<41N?bFc^C z!2bET{NfYpex9|hAMf8M3LRn^IC$&$OBF_Fa3G>0>mjjcG$xK!^Mqy%vF`P@emo>7 z5G9NIJNV-1>hqi9hjKZ7sCdi|0ayJ{{hL~d{JjmTepA)j){mFl;D=J`Gq_0W2NbHP z)*onE2xSri5ICwBYAh;+I(y2Y_Q?v?z24T3m+2OOViC^c4{A~a5uL)(KBX;sjPHuU z^9Nx5f%$mi@{^c%V4k(DACKuDrRq!FAAdmU!l)D)hz3#h&^|F5{U;_OHEW1(N>5Z=A(=cHE zY<2v5)bU?b$G^wg){jT^?}Y{(+B$fB{tK5biNMex)Qf6~=)~?woHz^k4T)>-j&1m-^4V)PLrs{xdK2pLwbO%uD@eUg|&dQvaEk`p>-7 zf9Cb^OZ<26LjReU`p>-7f99qB8{X9KOZ~Uk59_(5QvaEk`p>-7f99qBGcWa@d8z-* zOZ{hF>Ob>R|CyKi&%D%s2QT!Wd8z-*OZ{hF>c5@W_5V`;P5rQ`|CjpDywrc@rT#N7 z^`CjE|IADMXI|<*^HTqrm-^4V)PLrs{yTV~|IADMXI|<*^HTo}Z|d)*{+s$?!%O{V zUg|&dQvaEk`p>-7f99qBGcWa@d8z-*OZ{hF>Ob>R{~f&0f99qBGcWa@d8z+~H}&&U z|4sd{;idjFFZG{!ssGGN{bye4Kl4)mnV0&{ywrc@rT#N7^`CjE{|;X0Kl4)mnV0&{ zywrcgoBDgH|E7M}@KXPom-^4V)PLrs{xdK2pLwbO%uD@eUg|&dQvaEk`p>-7e+Mu0 zpLwbO%uD@eUh2Q$P5r*qe^Wnfc&Y!)OZ{hF>Ob>R|CyKi&%D%s=B55KFZG{!ssGGN z{bye4zk?V0&%D%s=B55KFZJK>rhZ@QzrB7~*WXM1XI|<*^HTqrm-^4V)PLrs{xdK2 zpLwbO%uD@eUg|&dQvV&i(0}Ho{xdK2pLwbOc3#*2N&PqV!>0aU>Ob>R|CyKi&%D%s z=B55KFZG{!ssGGN{bye4Kl4)mnV0(S;D!D(FZG{!ssGGN{WrX+|Cjo2uOHU)fTaF2 zFZG{!ssGGN{bye4Kl4)mnV0&{ywrc@rT#N7^`CjE{|;X0Kl4)mnV0&{ywra?|3~7# zsUJ4=_fr3vm-^4V)PLrs{xdK2pLwbO%uD@eUg|&dQvaEk`p>-7e+Mu0pLwbO%uD@e zUh2Q$ef8tM`tkdzANO595BK%ss~`8(kKa%IxbOOTxUU~y{q=*bzxI9pzR&+bu0P?c zpT58PY2WAP`}`i}^%G3}e#l()`|BIj@2~GszrX&h`u+8f==ayvwtiecuU~hO>c6WF z-G!j(uc6tpPm#3kOKg4VCw%wY|LCO(@fUTkxAo)tdHp)(%eJ40$|;*sbHaJlU-&U* z9RCj2zx=1gzw^z%tZn_ceqO(h`BKdXLf_2aX}9(>9KG=?{{6rIhvVvAZ);9JuV2T! zbp1%?rdn4#dq=3uYb4RzrNSo`f>fdejW4St$U+g?Dxm+{eO-&_2xuYRz$_2c?^{W|9BG>(J5nZGl6@l$y5^-u8s{^x&j<=Q9E+nUqQ z>(?>w=a;U2mu8N-<*3^+l=i!dHr2mD-^kz5vg$Y1wtn2tZ-ctccJTT0S45#gO%V`~ zfMUf)p;W0wC|7O|s#Z8@-Ro`rctAim^|}ZLU!z77gok%R+qNm_+I2hz515ao^ABLp z6PK}g-T`Y{KOPm;U)7y=aPU_DSK-p?_l-i;?;J&`-#|%Jzo#$}!-iy8_j+4D9vBz` zfB%vWey}?JY3le_sN>(Ij`OPD%WD0L_tg3qU#aykKCrg+5Ik{>4SL z{>5HvTR+}c9e;Zd$6s0wO*9sg`~{Q6#R>&HXX@t3e2zp3As`fuuo z4KMYddE>3O{xdK2pLwbO%uD@e-gxV+|IADMXI|<*^HTqrm-^4V)PLrs{xdK2pLwbO z%i?zwGcWa@d8z-*OZ{hF>Ob>R|CyKi&%D%s z=B55KFZG{!ssGGN{bye4Kl4)mnV0%+cvHVG_21MF8(!)^^HTqrm-^4V)PLrs{xdK2 zpLwbO%uD@eUg|&dQvaEk`p>-7f99qBGcWa@d8z+~H}(5c|4sd{;idjFFZG{!ssGGN z{bye4Kl4)mnV0&{ywrc@rT#N7^`CjE|IADMXI|<*^HTqrm-=sbQ@=0u-_#EqUg|&d zQvaEk`p>-7f99qBGcWa@d8z-*OZ{hF>Ob>R|CyKi&%D%s=B55KFZG{!ssDyI_4`u) zP5rRprT#N7^`CjE|IADMXI|<*^HTqrm-^4V)PLrs{xdK2pLwbO%uD@eUg|&dQvaEk z`fqqs|1b65UO%ks|E2yjFZG{!ssGGN{bye4Kl4)mnV0&{ywrc@rT#N7^`CjE|IADM zXI|<*^HTqrm-=t#b^V{ze^Wnf>i?zwGcWa@d8z-*OZ{hF>Ob>R|CyKi&%D%s=B55K zFZG{!ssGGN{bye4Kl4)mnV0%+cvJr`_1|7Utn2@!{xdK2pLwbO%uD@eUg|&dQvaEk z`p>-7f99qBGcWa@d8z-*OZ{hF>Ob>R|CyKiZ|DC={5SQ(rv6{*Kl4)mnV0&{ywrc@ zrT#N7^`CjE|IADMXI|<*^HTqrm-^4V)PLrs{xdK2pLwbOhWFKPKiu`(zVqihfA_O~ zgRg%3;jZ8Ioj>3CyPx$NeD&wP`tt`_f9|{f9_;n!t6%rkuRqN7>%Qyv{;pqB|DT?o zj)e;sLe~YIIdcZT{PK%cdv5-xxAo)tdHuSJRR7<+d2{G?$n@#cp=%3n-n?m0>t1i` z$My62bXozaCGn99eQly#EBF5zyJF`*Wb|F`f>fdejW3=|3lx*-{k(o1^Tmr7M{sa3^yk>Qb7xGLFacY)Znb#b$EvsW z@3ebXt^e?u zTL0lcYW)XwueUX)pVzNre$dJtn6dLXRvvpEyI*(>H*bCAy7u%x^tOInKd)cMe5bK9 z(Qm;9jM;Pm^A9|WQ`g?XPk+0!{)4*L+xl_+ynY??5nXztecB}Sp1lIY*X_a9voGP} zZ||)C@ZAsAwtiecuV2S}ov2vooB2B#+mGV%dmrCk|KZ(_p|>@spVzN5ys6)p`fuuo z4KMYddE>3O{xdK2pLwbO%uD@e-gxV+|IADMXI|<*^HTqrH{N>dKl4)mnV0&{ywrc@ zjkn(V&%D%s!<+hlssHx+VI9w;{xdK2pLwbO%uD@eUg|&dQvaEk`p>-7f99qBGcWa@ zd8z-*OZ{hF>Ob>R|CyKiZ|8OWztn$IKWys%rT#N7^`CjE|IADMXI|<*^HTqrm-^4V z)PLrs{xdK2pLwbO%uD@eUg|&dQvaEk`fqqszc2OQ)DIh8>Ob>R|CyKi&%D%s=B55K zFZG{!ssGGN{bye4Kl4)mnV0&{ywrc@rT#N7^`CjE|Asg9`%?c+{jlMs{xdK2pLwbO z%uD@eUg|&dQvaEk`p>-7f99qBGcWa@d8z-*OZ{hF>Ob>R|CyKiZ+KI`FZJKl4;xOb>R|CyKi&%D%s=B55KFZG{!ssGGN{bye4Kl4)m znV0%+cvJr`_1|7UtjE=*{xdK2pLwbO%uD@eUg|&dQvaEk`p>-7f99qBGcWa@d8z-* zOZ{hF>Ob>R|CyKiZ|AMw{}s;vG4;cy{$J`p^HTqrm-^4V)PLrs{xdK2pLwbO%uD@e zUg|&dQvaEk`p>-7f99qBGcWa@d8z+~H}(J0_;0Tt*7g5V|CyKi&%D%s=B55KFZG{! zssGGN{bye4Kl4)mnV0&{ywrc@rT#N7^`CjE|IADMxAT7_{+s$?Q~xjZpLwbO%uD@e zUg|&dQvaEk`p>-7f99qBGcWa@d8z-*OZ{hF>Ob>R|CyKi&%D%s!~5#Tef8t_Q$Oyz xeje`Y$5%h@s~^9g`f=a&^Kf53DsQ&_OX}0NW54*s_?|r)CU=TY=os$z{{czD{|*2E literal 0 HcmV?d00001 diff --git a/src/hakpak/peps_prc8/tga/gui_pal_tattoo.tga b/src/hakpak/peps_prc8/tga/gui_pal_tattoo.tga new file mode 100644 index 0000000000000000000000000000000000000000..c8e2a27e7ea55171b70c4ad4b2ba4441873b7509 GIT binary patch literal 180268 zcmeFacU0GBwl&VA8cpoIqaYSUDbl2fAkur24$_Ns>Am+RA{`W|DhgPzWAD8s8l%P- z$7C`|rrepibMJo7d1jHH_ruKn&3{?zeVw(wOV{Y;OYnR4v(G;JJRcdE_hf$g-*5KI zEF7b+ua6lsW?;^oIas`SF_tY`1|=mWXlrZ#@>;iU9rX0{uy*ZQ@zT-JfrEnsEG;eZ z4*%}w_wMua>(vj}<+N$jFl*K<$jZuM>C&ZGxpF16w6uPCagFNg>i$yCT*vnI_OP(9 zfPsMl6ciNT>gtN%;9!J=grKOX2qh&YsHv$zb#*oB>+8|b(17;#cI@1_6FogWxN+l# z;E8wmcR#;(pPyf^e)w#bmzT$;O`HDh`t9xQ#m$>H1yArfFDEAlV|ho|t@ekHeiFjX z^AYDziA0wgByHM`c*ja?vB-z-x;Qwk@rT(82b?-}3W|z~f>Rj3@FPViPSSzaTq_tV zxWZz!A8gcuV6PDhD;0m3tnh&DB1@>w(#MkVN~7@0m&QX)y&T4t4RG|@37?Q2_;1;V zfQUYLhwO#DYZr`+Td-EE0LqHdqwuOSny{5|f$x|wginsg);SqST9AX(MfpgapN;65 zDe#{d2AgrtSo?wgD12jV0D4O^ainD%&UCfm>i!;F@85$P1AB30e>cu_H{(cs8M-o} zQ4#Jv3cqOF2UtG-W2~Js5gX-Z!A4OQ_N(OJuv#A0^m`-v|I}ws!LrHYF#nSeN8$Tx z8*sdNCoXjD!OgxycyRC-9vwb`FNRLx!J!klJ#ZM8d;4&5S0@Gn!24szK<2&QjKW(7ZiY*21pKp75M5e` zl3izWK&uta+;mZ+%wTll&2 z7GklS5|%4!L20!vlvUS3X_XdMD6aZn@iJ4EW6VNbOi{AHTrDRktoOnS@JX(P zMot;zL*gK-=ZbNwU2yvJX{=bW0#;U5P*qihgGvxK8>AqX>ORw_6~!UlsEXQ$iimwE z4(&m%|4!n83IuLQ7921zFd*uG1ixZ}4z%anz+#m@Ty$dKLw_&GA`5}$nb^EB4W0(^ zuvYcQ`X%;)1EhF$?Mj&1H^4i%3*qqx5tnfSDS2m*lzRs8nWqqyGz9m6eK56b7aSnP zTgo`W|C4ZRot2JUg;JERu0f?%BdXOKP@%E|1uH6%G(QW$Q(^=MNb&osa&fe62d*91 zhx`(rV7+Eh%MHwQBo%VO@*C77cik6H4IF^ws4ar#`c+tGu8xg%x-hoYfuW@~bdA-Zs=iwEm&^hG48M4;EY`}az;yLG*lU@> zeVq+9>0855#{!lbM$lAN|6lQo=FNrXiX|}CRE5pDwQ$*J2q$9$*c$4=Oji?{sw)2y zKasd=nw&hQYieWOMia=|+C$dG6$;Lqu++{TOU*2>TuU1Y%a`L{egAXjE{5EawOFNM z3QcVX=&o~v-a1!k>pDPP(-O)mTL1F>Kc?EBy2=vr2A)v04ug(MEDXJqvEDNYdam)% zu#dztBVWwda1b0Y^7G>!T!pxa>wl)2Ez~zUjjDg6UHgBj|M6atqW%X52Sxq6xw(m+ z-b*(D(e{o@=sq-O9>cD@)95HXi)O0D9r1%G2<{Xdz&fC*sY%rT2wrWb8BAAh zrhl`o2)4>WoLePQe0LztuO9L4Rfw=Jgs*W5X@UTu1Ely3*0u1WuOF3s7^(TgD5|-N z^7>n-YPyT!nw!WfxrDg%6M_R+2T1W=?*}4wMk;a?%Tc|y39Tkw=(O%bx9tJ6nf7AG zx?RKx+mXB=Tj&5O{%~^*o%4Hf|I{#^UcQR2?>xZkhmY~*^DpuG?tQ$tb_0)xPYMoT z9U#SP&l(Ri^(}cIldIZ~AVvCaz0)>NRXV<%dO1NWXdhJmxg7(90dJ;#Tz z^H4u3yW0f^unv&oXU>_1Whx7?)>s*)4*GENHG@a6ExbbQ;p}S(Yu61}Z>|M34P|i- zO7Zii&w=(LWjZ4a;bCBhPz!JRJkr0ZV=zLkz3B{bCSEmzmWswd$IqMr^`&w!*H*_S zQzHaAS!0Wb6C%A_5a?_NFDo|6E!q3&B6+c+}yD|I0VX(QBaMJ z!D{;bGH+ijv$4er(gLivrQiSb8S^2#SR2Y})>yaR6XsT7uyc%oy;CeKtwXWFWHYpN z?4hEn{ZH`|mYZO)zB@D=B4Fa13WqI4aNk-5kN9dhMijv;FpD@Ljx>Rv&;cXw&wV>< z_>uFU>t87>R-FId=}qGNf4lzq{Fku^5Z^za|6IT9=Y?4mBFm>46*2p;Gw&q!Zo7&@ zE%!(dKfuAd+r$Is1P8DV;9j7zvhtVuXS{)&E1b0H46)2cl6MUXBHOVor4Kc!2T-xK z7a9Hyf&*9wa4#UmyO8Dx+uBdHe;Va=H_*`W2)hqFMQ8s@wDmqib<+dE0jvYK7m(sZ z$HyXFp$L_0$)~XCMW4?Qj)kA0*LfTb7)F;}zu*AY0o)5n@#nfbaQoN^Jh^loFYY|T zn=hW@$7iqchp*qzudndk!zY3RSO;(~AjNN7Hjh4^Yv5&KKy`16cyBkP1^FQ(*bgaw zUWnXeCpdt00QUk?{Ea>Rcyx3aUtPS0m$x6`yGPIQ)6>`Z;lX3U0jvYK z7m(uL`|MLpoI4wH=*(ZPz6NRr>!4$53SBcgi;N7hLQ`FE0P6tm1*G`c(gKw2Y({H; z9|no%PT#nSs}Jtt%A@-@f9EFp&kYL>U>(4{fD|vgd?wTl6k+0^3)es^glzT1)~sN9 zg&;E358h#pf&*9wa4#UmE6-U9GbKHE=-VRN#vhs9u_z7AKxtS83IdW5=Nv3JfOP=( z0#dw^>|7YHQN||X-f&k3BnNLse(V+$kgmy&3_+B)tKb0E0o)5n@#9vm!o-cHm`}B@ zxFr(W=^5BiR08AT60Fb3gL+J?-~iSE+zUwYv*xUZ;wm#b^F3f?7Yz^ZOazCOA|$*F zenACrq}pW;U>(4{fD}Jl-5$zT!7%nofm>`DLUS6CP|<~i%5FpzwZk)Uo8SP}0o)6W z;JNpm4Ea$zQJ2+^-4&1_dE2T{#I}R>j3Tr*bk86W2Pk| zcV#)6Oxw}tdkClEF5qhJUEIulfXgYj1P8DV;9h|J04e_RKGNQ&&*15ed-(R@S5)(F z@R#p?#^1mHGyd}WN5KKC1GpDpKR}A#xN0e!^|k1%x5QQ-cVveLqj+mH$`WEx5VJ*a z0P6tm1=tUe;%`&W|M{u2`0CnSeEZ-jetPy>{Pp!u`1^N%#9zMsz2E@W0o)6)A0Wkl zNN4)gh4bmNsSI^PLm1iF!Pd(M)*c=(adZ?Mz&e0?0rmr=_>}50Z0p#CK052qT)%?b zUwn=)zxf7Vz5W&tUwkDvfOP=(0_+D!@k>_EgU&`3*n4k8NSqgv@*+{NEe%E6Gmu@D zAUJ?^0QUmy2T1Xn3s#Xf+<;J1Ph@$;Vp~Km+S01go?e57gi^r)tOK|gU_U^LS6drV6s4dHyoRotui9FMm@$F01FLI?Da24FvcJwYk{YJWc-oWD%bQgAKY!^Bp&M8Fr0qhA%@tR8)!+!l*1UuUzZA%cU zvQp7nS%NO|FdIwqgbs-E-X#10_5`K)G1T|ZaB{}d@Ga2E%7t}p9Xxk;Az`~da@-^Q8OFH5ExAP!(1z`X$X0PG1mswj-Y-#l;x z56)bq`hP&@KkJXz`0H=!{3j0h%eOy@Uf}h;&xI%WIe7r-lAr&Wsgp5li9D8TkY{db z4F@{MLXyaLB@SR6z`cN?mZtCo`TUpSb9QV))4pCDJbeO}Zr#G?Prt-BZ+T*%lSRix&_X1r1CiZ$z(Oy0ZueV4A zo2dRHtu`ZXa{}t(O3;~Ihn~D9p#!)Vh$An6J;8M=HAmsKm&wD?P#2*tcB1~v$5Lri}k4fY3@b!@8y?=n6355%;`iRLlidKgbp|v zdtUef>s2pzz^0Q&*#3G!TkXM<9_+^X5oHC2Y4r!o8@UFqK` z6d6TZg$_u}jSzkSdxAU{;Mt%QuRd21cB&f@Y~qfzO~joc8Q2k9EObEimK@;+uqViK z0iF#?@oI7lV5O^$&9>%<^Y=n-TqKwSSO*j(#R@-wJwcue@N7_u|3FP0lgQs&6c_~6 z#1t47mkJJG9bi&cDf|HT1bHsNvq33-&O8nB{_J3E8Ukn6R0M{WAv&&3=zy>Y^6|(I zU{8?e0z4a(;uq?;V67v~R>N`-lu?6}sty!39uPW!dja+X*c0Tr0M7>B#&ce8ME{S} z|J(gP`+t1?kJLZwf5vnDx3#s298a)m0g~M7P!YQa4S7T8puU}T0QUmy2e2o|a{-A3QD!NsDq&sk;L$b{&EPSO;(~u+Qfp zcH8bjm3AYt<%>l=K#D)x)rA{F$8i7rRXn+NPjCS10PY1|Q9sU}AkPJOHpuw^Dc)e& zB3P5R?L*#kDEWWP0jvYK7hpetJwcue@NAIt0aEeE)EzW)o10|6Ukm6TPm4nezEqLkLA==tcZ~*H7?gcVDq7h>oKxe-#OjhZOe1H_c zeC`aaTfG9Vq_0BA|6>l|J|Hzb5D7uP*y8307ZXEl&`=Ti04e@AD-`j`dPB@|^T4w3 zNWlTD1GpE^Oi9Peh$zUqx?!&IMv)JY;-^es358`FpsnW#OPgr8xTOglz`cN*X9le8 zV@UhELrIx@e#!?(@iSCyu*%dACO*mVAl?hk+%9xLRADp1vg_d@K- zoDm8O3;U)18NX(x6^xgYKSMJB<^a|K3EtJh4`5G_=K?$%G*|M2<{ZmWcuS`mcm(dE z89<-l0M-HA3$P!+o*>T!cs9uSfDIP)qwrqu1tDTa64I6y2o7K!z`X$b0qhC#T!3eT zaWm84^Ks}X{PDJCT-e`_o5xNI4qzR?y}(yD9|%v7=K?$%yh<}d&In2W``0a+4wKc( zVXw1BZ~*H7?giKnU{8?e0z4b!d;n*Jr14qzR?y#V_G>e98$(@iMZDA)~H|aVDmM16T(vqd5Tk0qhC#T!3eT z(=@a&ebJ&(_|GQDVa|LlEMI9RIDmD4rA?IR2iOzjxd6`w7t3p7&fEo~@ym>S@$NK%>(f^$P8L5B9bNx3qHi|m7TOA5t z!%V>etON3bccCb}Q+R?r7s&8x6!`$o2ysp@C@4taM(_&bbfGcFR&W680PY36Y2MGC zAkPJOHpm_!XM{K>D8*~8FM{=^TEPLV1ENz0ur>3r@C11-5E^$tQjxni8CBZxbBAI^fRmdE7roTAMsU zo(tSMdR*iKI3u*DENc{AWBNGgFPS4afOP=(0&a%-!V~1VfStCQ$OmvnXvKsvqwvR? zcH$ys0GI<<2i&7te|Y+$@C11-@Nnp~$Omvnh_gb{@1OHOG9P~=IDmBk_X0EJ770&~ z=K>Sv%o6#4_dXpfa)MI4>((el&fds{;+ae0vps;i+liQg#H=+y-AZH zBfms&0P6tm1*SPT3Qv&d0uzi){*e!$jL<*Be=>FwCQMo?IDmBk_X2A)orEXIbAc5~ zrXnA}8KHlM|IJ)&Od{@J4qzR?y@39vIN=HMT!3eTT>G36;+){yKR>SHk@NrU{NLO2 zf2saw{7C)t`E9bqo$5MN=m72o*biV&kmmwC8{~WdXM{K>$XQ`ePfsjdxKQv1;}^WY z8q5K#19W9wzLQ$fwa@KY%?!o(u47kn;gP9|nVSf}9nW;ya2`!5qLk zfO`S<1K1Pfxd6`wIUm3oAj3TrHm+O>_5^t@z_UTl2XID+{~l+B zrTBxC|78wf9l*T+`vL3;-WfOoo(*z7fHOi|`d;TetiCq)c@P_zmfd!Kg<7k&|G-_{Q20mYZqKxTto(d=YXcvFPfQ| z!N|x6JXhfT9)9uu5bqIj)`0gtY;0_xrl$4||L*7a?(_32*N?L^?X*x`a=n_En1~wY zTIRat{UCmEMvr#|IV;HdMQdwok^6u3>J=_f#{J~UlQ@3-I8K~6fuSMt%;?N(ZEZze zU7a}N`S(>-RVXel7O%oW%JcgA;vN3o&+pym=hv&B*RNmWB4tue(LNs6F4yr<@~Hbr zzyAN#uaA$9IMd(lZ~uDx+pMYH{runk{C}p2Q}1ow~3;q{3XyvJI@ zbBqO?J~V*YZ&aWnvj8(>J{yIv_R>RV%tq`jam1k=K{(kOhtoUbai%>Hr`n=$w9XfY zvYgNsZh;D~4WsaWS_`q&OaaB-w3`y8iP{uH)TbMxG1CN%^!pv*Ymw)wfjBc|`0Fek zh1b`XfsND0@C~QgSn?{wk*%)ji{96@C}*;d#gz>)c$A`e!)B$$S;+F z`g$1{+snYx?PJRQenQ#5ajWmbKL_cl(#IGh!u&sSeH`{tI}H7RW`uBsu5;obpvK}r;ZE#Q94bO~DI3(}J`shZexz%F1Sq@}rmUT*U|Aox- zb@)Ke8K0?#WA?^a$U7uqnM)cJ-7+C>myWp`QZQXT7!#H{E15BP`hq(*=Ag>q+r8S9A z(MrV{oeZqjNXCj)^xr4%hq<%uF?oW)FZhxD{r&m}an$TAF1tL$UEi1ZBJ_KF74H^Llq|pJcTJ#eT}zmSBRGYG>c5()Z~H9y&(u4h(`30L_`fGApBq~0{3l!d6PTTN{j^uNbxde6Y!Zo z?f-A3{Bah|>xwCBSLp=nN=KNN*+RF#6pNC`1NU7bI6#V@5u6C+UJ7dKJPjEe~q( z8JH0ii_h%*1P4g*@;3Qc8&m=3q!#!U>_J%NAY!%;A&OpGstzHjct5OD+M&6*UT}aE z|DN0?OwguGj6(tpd~;wHQUcqkD%eC;!6LjIdI3d{x5>h6ohZQpQoO2qCJZ*#z=rDH zBlr*kqfa6{=`6zH&mt&xn9hZxaCGaYeBn010aEa6j-hp2q%+Z_@q~Z*qY*1;B69 z{|n#5{{>%!yb&D0I$&h~cm!X+yb-;c`*GOp6wW$c$F{wg&?ygE(q^499Ix;E?GN^cnP_O|21m%MyeRkm9vu z6lwNH`}X4lkvt<7`LbCkmd`_}LIHAR(~vqR77>$u1qZMWkm7raop8J<7FYJ>P~BJH z%QKC5aj^|AFYm&$vyJ%T#5TbR%mJ(er1*UAm8jZkK{-hus{3#ZH7Cm(oQ{D(xgBXu>~gHQa(13l3l%AjPZYZGc0g8v^%k zLF|zvWSz}N{-qKWUMWM?g#sj;Oh*WPKggPFl`LI+6k8h#~k zN@}J$--o!`A!O}7i~OETDBN=e*}E?yvGEkbDh34yunv&o$F2#)D*HGX`Q^esrW#(9 zy$i@|M^FLn5M;E%C4q9pVP#lin=N#J6t8Po32V1b_(mK-MDiJ=7TrKr`Ca5x-bZTT zEyQG8rhmf|f&*9wNbxi1TwJCa58aK0Fn6k@&p{jQTXfMG(1T5WyJ73rg!L8`P}NEi zI^bXSAqjr2XHSS#ivb8!1krv(N5?6faM{a zbR#ViKz&HiEnM=wisN>t1P8DV;9fwAw~?W}?{TzOFk>r<0CNEA0PY2( z_>#zVXv%cQp2{sa+M0ojd&+R@@DAKPQjhBc)fn!`797AjfO`QcJ}gNE>18IUYIeg; zs=))t(s2B25l&nz!jZE%=s6T4IDmBk_X1M9k^RST^jS#f#41E4=piZF3|U2X$S$!* zdcGy)sq_U0unyo}K#I4jafEMIFk%lUA@6)Kw%y*2mPc)9{gQUMA2p-sdWGNs)&blL zNbw6pXQu=Op116T)eFCfKRN7rI=UN>TE4Njx}%R!wD-E;0M-HA z3rO*@rs2@{%79%oku>CK0c*>V&~b%O{g>Jl8lI)HltDc;1s6&@i2v?o1G zb$=5T&5u#v{S_LzU!i8_3*=Tk5FEfdfO`QcUUqo|(4{ z0Q&(W`^O{rjy3ym*mM{dy>H{r)@OK;`+Iy}{h#=;`oHj|>@R`?SO;(~zF%%|JiojLPtNWZ9Kbq&dja+Xr1+=|P2^Qu z)1Ffx_7A4xbCO-8*@N#cCrd%N%*7E-2sb zgUTJ7QL@cLZ~*H7?giKnkmBv?>Hf&Q5lBCogY8$hqvMMX^uO%K;Ojx``+A??0M-HA z3$Py`#VbXr!6?TJo;!RI(-V)}qXnqGREwG`J5YMAQg8t40PY3Y50K)`imKq<)Q|QVgwoD_DrLEgPn!KHT_pm+IvoL0P6tm1=tUe;w?9I(9XnRBo|yl zdCMKN_C2FrtT)(qf_C2zzY!e3I)Hlt_5-ANh1GG;H7TTfmzofkxF2anr%_UO9c6Tf zR$lcL!2zrTxEEkQU<5z1zkk8`5$T2cjWd#_#-UIyAJvrkZ8P49 zF53Co?|49P0P6tm1=tT@Pf&_y?SH+$1Ye$N#p~;X_`~CK`1`BdM0{Te4qzR?y}$$V z1lSXl;;Z6p&{-0U!;NXU*jI&zr*`A(YX|V%-66cVvRCK;?giKnU{6qrk0I?}QtO14 z?lANp$-$WmwYYV+3!i_v4>#|(2_3+_0Q&*#2}<$iF4HL=y#ia}^^lrljp9l#Y-aJ@!7?i({{jVfe>k9Q^G;p#!)VU_XF8 zK`CCDw7+?w4SXB?>C8<*>8WxwTqh2G(1F@(^+E@5FTj2PdxBCtYyW^*!Nb^g_5vE|-nO#g zvqA@OFTj2PdxBEDQ*tvRs}GRYKaIM>*U@|F3k=a-!870E_?17S@8s`=4&YvZ{Q&j^rTArP@i4L}g|J?uY)b7J!+q1YBa2I!zUf@O9&-lLXzwl!-@Lkp4L@#hF|NS?M81(frz*4U0F z<2H0ycMA?+9l*Un+0sJc3Hpq&8-+jKvK7}4l;Vq1ZFqHU5WoNY9RBw5mf(QDJ-Z}& zfv+#_5}x4j?!-~}s;#!@C<(!#rZimGTZsp!+VPxp#LMgbczV8D^a7`LXA4iTG1Foc zJ~msI>faeHR3rNjlGk{a?jpTKcaq(sJTU11?gcvgqpAMgsQwK{;Vn1Kr21b;+JBv> z|01gYs=6S-0jvYK7l=+-Cp!*I<460jiV*9SULI-d!;1kvjGl%U^S)2aL`;YAJpLMv8+acfLaq>@i zQS=}9e#d_c4qzR?y#V_G>Pr9TNB z@I2=S;RjstxhLiVJR6ka^Je6repLfH40|!)G=$TE7X=5f4&YvZ{Q&j^c`m@SK`Gu- z#vWTIMj>}$HcDytXNNB37B{pC9nhfLB>VvO1bHsNvq33-s6L8v{snXgUjv?<--Fk; zhVa9qvqA@OFTj2PdxAU{;Mt%QUlwJ7w!F=h%}>P1jzU};tfw8Gok9oPIoc%rfWwW6 zVlKe5K`A~WO&$4Fwy4_`fUbQ>ICQiar_R(09dP1ox$pzn6Xdx7&jzJUqPH|kP^ z#AqWv%@kP$PADk%5IP{YgtQU)0qhC#T!3eTQatPbkY3XN$1_oRz7lP>+OX&09-#wv zf4*Dz0U5)&VlKe5K`CBwiwcZ$%;8?+g^2cOWDaBt4qzR?y#V_G>T=2e1yvX&VxL0DFQw7vR~T6mRL$4*%#wNGdo_ z|HjwQ)cX(}178Xq(6a9<;RmD?UKeu#o()Rz@~dN@Z%+3N`ZQ3F(1XOhBjg;f+km9Y#{|o)t52>{8lTSLIIe>Kl_X6w(uqViK z0iF$VK0u1^-xh-5_Eg*&tfafX$@3=;U>(4{z{|^h!V~1V0M7<5Xvn&;i^FuphvlAkPJOHpuw^DL!zk67_yYbmy@fTH7Pg-IpwMz=6Zr=o?7G zu6+@xYH>qWrK!jVNb&1!K7*~tJZuhCMnwEN!2#R{@QeKb_5^*xSBlvn=L4j8^J+VI zlCF;%OhUnl0#se75;}l;0rmsf6O1{WC}xA450K&)2P}hDqCRYk9kIDS5RtoMgbqm9 zn~do0t-=$uA#YGG(@5k4r1H7QoKbZ%^os$A#VF1a_Qc^ z%D(eL2XHUIegJ!dvD=S`*&ycwqhX-47z)&blLuphvlAkPJOHpuw^&In2I zQM8kvH!}~F3flw+unyR3)-U`3_5^t@z_Y=E`B?~=<6$X$a4Xn4SK$BB{D+N_wOn7#gT?+oa@Z|2M3T2;9lVA={DgB@?3ytgU6a>*WOxV;U>$I{IbHYx>%-kBBt7*Q(e=Z~*Io*3K=$ z4`5G_=K?$%jLTk2I&StTysib!|D2}5(R-2L0M-HA3$P!+o*>T!cs6M6I$mUir0;K7 zWCjP~p3NP>f&*9wa4*1q0DFQw7vR|-=L1yo4M)BI6wd`vico`os-fTj)&YKvfx-`9 zPmt#VJR4jdr;f4SGe_aIld{M^sD$fw@~?;kSO=sI9uj^4dxAU{;MpMO1C}S`jKYtz za)!KD0MsL51qZMW;9h|J0QLlVF2J)vS-)_R5t9D*8wHlYF`V95J~hIDmD)t>9O<7yd?gf;<eB2XID+bAoU0 zA9D_{bRPLVOIrm8unrh7JAotCXM`unbAkPaM?^k=GeVpbl;S;PtPwvpT5tgCfI6jm zG^@4Z439Kbr@(%yW!>!V0`f;<;E-<2-%0h|%)iXHv_N%jko6`&(HfOSA? zt}k{M1qx4)=K>Asl;xp(0B3|aCn){?Z9G4t{LfOs0jvY^DsAW)2oAy%J6!`$o z2ysqOieDHK2c480!2zrTyqntKzq3Plf;<;++1@Pj0h|%yoS+mhqi=$#cCLa0SO@6F zCBq;wU3h{#7g!UqRpbLWBg8pDDSo+gI*dcg1P8DV2rlWtmP)Ec@&tJ<;G0W%Jjw@f zMu>BQQoIc1`sNvI797AjfO`S6kOJWe@?1dAGhO5ZI3vV4K`CBYBbW4ht>6IG0e(>j z5xn)N@C11-;1+a1jVo(*z7fHOjz6XdM$+xy3iPoJJBIDmBk_X6w( zuqW81bpSjYc?*YyUa#mQ1 z=lmaY0P6tm1>9&J$etk21$Z{d`2fxc@!#XDuoU08MGwpYtOK|gU_XF8!4u7K;MpMO z12`kZIYG_}OYz|bv%nm{I)Hlt_5;`xtfm*w200(V86nOIa#mQ1H!`REFL40tfS~wQ z!~^PJPmt#VJR9VEfM?hoa88i3!csiv|Cj?<2XHT7;y4BD3G!TkXM>y%;EWLeJ@K-GFJ5L3(5&{R#=LkX_y4&0M-HA3$P!+o*>T!cs9uS0L}<; zPLQ+0QoPI@BQOWB4p_1=80-hIC&+UFo(*z7V4QjoI48(iVJTi=c^sGnSO;(~z);d@5D{q|eI6aP2h-|fHuzq|kbYwzFx z+V9Wj{DKAK4TqM%J*5sIg&o*hOFI~?N07bqIL$&&BBSjn5^4vrrKA^bDYTCrUX1(q z?~7*{kKpHNdyw}T1p}XKSVol7uEP#^q&C7ctr@O_;XOzL-)yY1jmAR#&7<&R#>}C+ z71c3&H9dpDi1rw*>CRK~Pt;uE1%^G9d8*EszF-~3k6%0r{}J8a_{k@q&}%N;&$tW| zr)gmFY#mIQtB1+6*5b3zR$@8 zj}?n$F@MI?QTWe3d>`XK`T#S=)BT%MCqZuZ3@FT-jivMFKz{Bl$kH=EW>21oDdRrD zxDVbNh0n9nM}x}-?Det4kq`$AN4eo_j0eugd107-J-WpeJ%J9W@vuUM-G)(kyH)ZC z)n17#<29(X(nXzc@%!i2QrxbA^Dr*KZ4rSPoX<|67=Uz zfx-M~(3v|GDl;cy$)ry)d)&tu|NiLv4>HrWP*q}tmL1mUZrOzXPH!CS*^I+`{L$a# zi{5tH`=;zw1xrYz~w|a=bF~$+ImhGDKymF{;aHr>k@W3Uc%i6R!qO zzZI}>TrdhRt4Q}V=zfHamQ&#DHWxmAa_|pYilERH@C{IallvkVThqO!>n1>M^#`Ny z6Q|2y+FTjP(brk6Ap3v|5&2T1Xsd@`2mo9?-uvIa90Ofg5z5ep2wF>kFq=4sIV zsVl57X}UJ?gS_B?5&X#g1zuFI!BqPRROcD=yv~B;c$8ui3mk> zfUn?yk^Sir{Cdqbu%hSxxmlYdfH)$;*AuZpn-LqhnfSy9Vcs;0ATDq;HxV2l#V?*c z9m)!eVW6%83%Wbp(aad`w)DJE;u;rA+Ns@WDEL5Id8Ob0DSpC7?_=ipPqBE`G^|)i zvk>}PT8c}tW`zRO=pI}pxrJCVcQ)ovqi2K@2T1Wv&PMdyR7;$TaKYVpFFZ*P!1KH< zc%BoAFEfL2Cp7@Wv0n6SHD|#AQhbEABJwt>qt1@*QSmUv0e@Q@4t1iJGd+XF0lj`U zsB@)UqNTpz04ZL3_GH*Dorf@uWk@kpMWH$ENZPGKxvc^6t!SsgL>mFRDzH^vCOANf zpZAdrR*e4`dNaqvVj<-q6lTL?n8QWTj~#F+qi% zC$bcl4)X*DNbxh~%RqtZTTA}~7@5(XFLsmZIYcvI=QJIb_EWLJd?GaTKY@bEZv+R7 z;CX+K&#-{JHmdJ~*mm$D+J|pr|Fx$$eD@n1x%UeFH=d!B_91F1%gh|WI$-bKy`ug{ z@Oo6U4pjTW`Sfg_?S05=JBE_ZVU*MEQ(?zxq%<5tIOQvu16T)0@iUj2VYx*Z)^E;) zV{8?Cvzmn#2`}jue6or7X=6|!R@=r19U#Sj^2tnmHc1t;m2Dxr&I?M!BWiXrSmO{! zzYl|)aRB|9gWv$x0VDX4`wO^chlKh1uK**YCjr@mwCfpvfsKXvRF$WEtc@GPc#ua!uPsH?(+ zbc3mm7K})j=&n|Tih`Wr0M-Fg{2nheoC|Zn!xTR}%in@mRY{Zq&%h7$S+vKQgjdBe zc$5(&IDmD46rW|Nf;t;r?D00o;V@^MOYp_z)IeOz2*J5TKb(kiM_+)w-~iSEQoQ-1 z83E{!~MOj%f8|?l3{Fr5*zHRD}+Z;uXfek99LXg@fD-c(0U2 zxaLws=_n#bPYEF!E8wFnC-{XqfOUWr-?+^J1G_zOb}$mRPAB2>i~0EKdMTdYET?C} z<>KzS3|u%8B{+a}fE1q?r-YI`Jv7zWkbZC{?GTJ(`y+6I?o2qmHw61Se6X|8L2v-; z04d(c^fLtbEkFuoqlx3mqWEFQU7jwDsPD zmF)yunyo}K#E_e?}N4O$*_woLon@6CvD${+}5KgXg`6hrX$2TbdLdX z0P6tm1*G^fW0qj%3UkOB_+X8F6pVb+U>QQsaSbiN2H#AmInez_%mJhWxEC0~kKA7n z;p2f!I`{d^Z!D)>oBA3Y*wupm-E^l>YXjP<>G{~i0jvYK7Z}-}9>Lqw`RqqE%4dEq z{hg}ZOf-}iqp6|B51GpC$!3P8c zi26@!8NiOg3)oBN{HcfE;`-}9;qLGLhI@bdJMR4cZ-N6@2XHUIegN+cvHl;y+eVcm ztZ*0YIvhsJ&=nlG@)*OPzrpb1?{Jhf1akoE0PY3Y50K)QnufrT&VKJ?%JA5*w4Yh&;SO;(~zFhs4 z&-%NU7lm)=ncqL|D#g$3W%$0iP;db20PY3Y50K(Rlx2}aXMdyHM)XCv<5YSWu9YU? zRz)f<7j6|Cz&e0?0rmr=c!OzU;Vd^3ks3>pPJKuzam+S%bJThe*V6kj2e1y{UV!}o zDgMANH=I8hfjj4N=$UUd^!(R0{OQ$RdiHZ4{`j&-Z~*H7?giKnkm8Fdm)*S07X2MT zID0r1cP^CT>Fs(vyGJ?l8+30BaRBQ8?giKnkmCJ)=8Chwve=Y#f;am2Mq+q~_~t|g zjvq=A9Kbq&dja+XqU_O1qZMW;9h|JfDwE_ zL4kPIM@Gv*G!0$FzRO?W%#$~`{rW%f#ozu5kN*DOf&*9wa4*n&@~-d%OG`^d{g2=s zsm7v8I#ASc6uXXH$I;s_aP`GcxJh5<%;Vn)9l*T+`vL3;O7Th-;V=)$hks@r(x`u^ z*>esZ$M0hQ#jntI^p4O0+zYTDz@DHKKVgPCc>|tMcZh^pKswyFmLep*4qFOZ1qZMW z;9h|J0QLk&@FVvh@cCLqTD^{*ebduahasx@b3=!4nSfsa{iw zLn??vTB(mMz!G1(6c@OLduqP;ef7u!I?5kxC7hGzq1s7>2Cr~_5kPl1qZMW;9lTGZkX@{rT7NxwdfD9 z!G#1Ld|n)fSIq_Zxwi&?>u_$bxIC^6SUGwJ?;7;l`u=nN!3fIUGee#4Bh@Ln+oarA8Q95XFcy3oC=o9)pW=qxyZbpZDQ z><6$XD8(P#?Tsr(66o2F`FM7B2Y&ag3x9btNXzd>1qZMW;9lUyN!sh!L;YQ5rg;9{ z$iH7%t}fc^Trk)ZiVH_G@#yL{ynMJ5-+$GG=l2_h4&YvZ{Q&j^rTAb!%8n*!VOyCM zI@~8t4i*`B ziDx8Q1g6t7R7>a?s!r3E( zf&)$-*eiO07J4QY_XjED0i;Xzw>MdG{d!~WiiR+&C= zze~@!bfB-Zna=zzz8-=DSO+janGufrgQYYVkm4_eJK`SKe|0jxqx%2j{s!PUEq^ly z9BLE2z?-^E;R#-f^%#Y3v>B;?Up%7vf7z6eA9}Xq4|}!?9l*W7)%0K-A#b3W<^t09 zk6p7E#Z><-|A)Qrj>`JXxvPs(C2PXwrM&w*`|PvN z^NS0>3E}_EMLD>;x)}G@EmS&yy}+L2Fsu&sM7F!+&9&d3U#F%>Apb|$V!==RuTBhB zHGn#Ry+E$;pPt~zZf(u*r}rcZ|MP_ZOYzy;RrvPfz4+&!PN*92<5!1NFYwu0<;oL0 zdtizgzFd0to$I6J@12EP=jP+R*Vp2Y_jll{KkUTEcQ>eB;L%vfY=JA3#r#a{g~5U8@Qj;< zkaXF_&R(u`KuFdSyo-2t!ScM&B z6XaZgvq2qyD>V@B6ei=Nidp!wdJ+DzceSbk)B)@T=m*dfG9e7I&FzSy)_>3}cR7AZgAW?q7t3vf25<1+{Lz+&$qsEYEDUOxio=BD6ANw(4f z>;>ot&=cfbfU`jzKdN0r#PsWcY$q$s6EAY9ocAju$0!|87UHS=0D6L)3vf25;&?$r{Gl^5qLzn?XL zI)ER0Hmp^iV8#4-YBtDxfa(79fB^#(=Qu;0AsT&w^y+2OCr}5l7oZJ3!F1B zAE4t0N$);dW{4ByoTdig=TZmoV|GR=vcxxx2^t4~nKLjSpyN9=Zw#Amo#cGC5#Qfg zeLvIz>;>ot&=YjAw^6e}<^y#6mBg`lGj}51TQm(H%UR7DKpntd;J-x6(-Y)efU`m7 z19bcf@4?s};fb?pq0$2+;q8T)N(ZnPpdUa_@Qlm@IU8g?K*z@mcjvg;V8!_1N&_5_ zIU{wziJUkb$(o2=Nr6};XMetzgUSc!_~Ff8Ku|a7e+P*FCmMh?fI5J^0Q~@Zf}9I* zHpqN{jz1vY{G~(5c=f_uymLeDfsq^HDs60W=1vncl+IB|i@Z8+o8vYaS5i8FH7Y&eD%=?cHC>_9F zfPMfyLCys@8)QDfBYr+~e5d{au=Y!Z>x4X21E>QgOaD$kfSw@d0-O!nicipGK(HCU zapSIN(S9g84H&0t0CfPLmrg%`o*?G}oDDJ`z>JXb`s6?N7pI6`o*^D!QFex^0n`EP z1**%JDo>EQpR>VP!b@g^^!;yN@z*29Qg_SwEj55W0{uSv0rUhp7vOA=`2c2wbi7UX z&cf^d%BN=ypblUipdUa_kaGdf20i3_A1LR%j&IwzK6;4;csK*FQ96LV0Q~@Zg4F$- z4fc{gff*qke{AAt+?pDKH)qGG8bBSuUf^?nh$qOo0B3_YG9y$*NXIYsu*HUP!?0(< zXjKEK174Yvr2GJSf}9I*HpqMcGeSB(tVb(M8`K?z?slpMPzSIVpdUa_kaGdf2B!|~ z2Y)Mhk7vkT`?7a#{QU+tmgk7k;0nP?FBV!GQ$T2HbSy^fVtCbRSlpHU@t&FfSw?80GtgbPw4@lfYxUCevS0F50T@K%pndxj=&4i^zNcGeXP> z>i8y22cYx7U{wRC14btm!!K3#!Nn8gT);I(_A>)AR7Qw7K^@?mtkuo#=2?1JvwIW&x$5_2~(6F2K6Ld;mEaA0GVJ z{xsi*ZbJrweK~6YbpU<$OqnUt6C{Rpf!;kcLd*%8?q3t%y=_a_$^4ErfI5J^K)B5M z=m~Nz;OFk5@&VNE%n9oFRt@T*eG_@MxYPjZ0QLeyt@|oZkaGdM9$i#EfEl3{^0_*G zdzc5#O!9eH14IYBJ#Px$6|bM3Am;*a&zhw20n7+(iuN(X&vfdG(vkM622ckajPt{> z$>WtL$hp9t3EnCnz>E-cg8J*bi+?|%R~uCWr~}vwEc0_#o*?G}oDDJ`z>E-cf;zr$ z!#Wt+w2rC))B)@TCfRgSo*?G}fjwHQd;l{-UFz2{!>?ZEgBRRgF4Hm?rG4w>E46XaZAU4@^@2QVYVoS=?( z9$|s75Xk^Y4WJIl&mDqd*~g|QNZxZcm@N4KW`vj%)bTy~Sio-J!x}&xz+NCSvaRw2 zIT!E?Xsq%9%m}rU{ci(L{_^||nqCgp0O|nt0`vpu2^I_IIU8g?fEgj?1UZ9CN=gEE zCJel#=VY)3PzSIVpcbGf7%^*=fEgijpIKo8PyX}#=lqT} zfI5J^0Q~@Zg5*4BgUkm|yOZ0@3LE>=27aim^}`w2>Jo^1UVPrY>@eYaeX?0IYDNHbv*Nb ztO3*k>;=5qHUK?A&ILFdWIliyA$}gS!a9DLXmZv7>Hziv^aJP#axTExAoBst2r(zf ztgw!cjTP@r)c`xN7oZeMO3#Kfo! z!06GV;qUK{fPesadwZ+riE}@JA8u}L@bK_ZSwZd#g@%U0!NCE)cl`7F51!wD@IU$f z1IYhAk$cwf-@lJ{-gyW2?%l&%Z@q=<*RSLF@#EOPf4@58`R{z5cvV%E`dGJaozf7$ zcl>X?fBpRRpWnamTi(CGGyS*RKmNVHey?7=U}0gQKI+t|BYj3g*-vbau3hDxv7bJu zmwNW>iEiDxsSn<>FnsuMrJsIl{O|qu|NQ&^b^QIU_m6+?uivLnAJnT?PxVObiNeCd zFn8|5``wu_C@CpXS;LBoiW=R--GkR(e_hpy-x~jW|NTGz{ykNGZ^DEL;w_}f&d*ep zZ7VA)!`iiLv1W}t2eY~w8#iuz>^=`_e9o@EMaM5`{{(5zht)Nj@j7WEsN z;k_pm@jy2tVc{Ni*K>Nsab&JMDfhn~#gs++C7ZMjq4GI?6N_u`Jmc%ut&28Y z?9sz+6b5)r!tjvk@Rs{t{SxF(Yq|5;XHo%11ZQE8dlY)xd7(qMfjD>W9GWy~qBH{W zb?dc4!)CI-+};}Px;vnowL5ys*Xupd2R-|HqLZZ~T6eG(FS9%9)o*ErH#7*pPQAvR z(XhGPbd|0AUi=JrEqzhiG-&S-=U8Plw*EjzD{_;$`h*`3Ku~2f8a_8oBxrckk zhHc2Lmgh;y-Mg79Wfr?=B__xnoa2*oYJPqL-`{O4oB}6cR6@Eu2WJ+-atkHrwEz?5 zmLM{3K7z93`807;;W~aI26&j?pU|YE_!E`X?!$Xf@3fuEDpm0Ct|R7 z2&{+spj-c8Xw|j9+3Q<0ZU>8IUC>CrP7BKcXlE^Z;QgJ^$<75GY@E=h*B~_Q)DQJq zc7sKOmS*_S$V9{@W+F9nHm1unLh}ksF?W6$@)wk2PH`z_&Rv9z>;fcAnU1iiL^J$g z2RFEn^cR1A0z#vbFfl$|_I2gnSJPhIwF#%$a5!S zFe)fW)c_sex_b}dz8&m@=fix)z*9cYCp-eI8>2%);T|Brw~=138S12JfR4A2dp#Pq zZi|*(yQ5>De&}Iqk6u!fdJh~7OZ!3SYTY00r5-fz*jd#89Uqt}+|S>Pl(NH^UM2UP zY`=!Wy)UC+w>-OX$4i)5eG%#9ML>$f6xne0=^ z=Ndo1fp-dymHX|p5R@|yF-1#}v~-pHzSbkPd>xWYS4&N;P<6m>@^n=LbbPyh^0#vF z#t^xqcVuiT#-`*TFe?v1!pDHLTzJQ4V3_l?U`>sPg(A(7q z{e^4R!pXiPe9_a<6CJIc(4woYssTDaHc7ZIHEPzprSh!Q)mXBk8s+P@VfmUZC|$J) zCCgy+J16n&{V*mV5`pr0Q4>=TJ|P()Qkw##c6fLN$lc%Wss`xz1`S%vY^)19ckPGX zeFvex{V)t1;*J4>N5F1?3#_c=?CfD9_x#D3AT_|i8~g7;@o~b{Or#eUV0P&e%wMw- zOC-Zyy0HoiD_0}Gq72y!=BpY&9boJa8+d1#7mNy#d!uD87$@0)^!$8GFD^!oYQ$$0=imnL3P|s0H z2k7`0o3}&@IpaGC&-*$Ig}tjA9Hd@2iryGF!UO%BhN+ss8bBSONz_kUuE=!Z>6S-cN< zRl=Dq7f`(Yvg97mB2(&0Z2neN1E>R5u3V}3Z{W$PZ(Az28J{6kpAGDKv_ zebk9X@QRYVq({fW($-7q03BcF#pY-r{BABaq-{?J^spE0FxVG;9sSYWcBIrkN3`tN zU)2EW00VFQ{bJl{tl%70?HJ5K-!_8Mw{nBfwymAv|XD?y?{-de}PzM-4 zzk&CNOT+l=xrkpNIq-`0$lJIb^S19r(a!zy-0a=RUb7jKm#kDZfI2|OcN5MI8W)XG ziRrTAHCKLDC78TmIg(4tF=^fsnI#v(PjrWiXaVW~9bdnFAGEP{gr$q<%h7=t8Z<$2 zpp)Pl5wEnw03Uhou+$gU0O|l8KSiDin47;?o|nE3E7osE)%JtfvR6Fs{U=eq;}BMF z+>Ip_8&nOT4$$#q{3B&AHyJ6JdB_pnGjCCaJacgk7D@dpUc3@{@-wg|um(^E==eVU z24k4(82C$#i;7J_lIXFi)8;D8ku2X^Tw)f2r6!CNO+X!>;<^7Ckt*N2oclcUOV+K$itSrabzncL5ADa= zy?d~9;|5g&r~}vw82iKg`xEarE&$_1>+{UdES!hA%a>!(+Da^vIYIHNmB?ARP}KnH z0G{bOzSp3^a1^cYEoXjsatbEr&cyVhVyPkXF*UzHbVrt|0n`EP1$2DFw(TYV+fSYO zgQag6KGq*z(vOb{4THz{Kn#&Oz#2duz+OPdPg=MO(>I($@jiL}@~OA6;o1k-@#^Q; zb^9x9yY)w@1s|vyKpntdz`&Eg%Fm0C++t28QkU$-oa!?u-G5VdCGMc=tlXV+RQ8v* zUQsoGI)J?Z^T#~@4SZ|q39Mbi;3k>H(2P>V&y(lT%6%!*%MT+>bVQ`&Ggt$t1K11b z_!mX0hi$#5P!84f;^(A#0GssYpi>;(+G@%Kv>%|CnRK9rs~ zgSA&~VEe0YVE^5Bap;~rhwjcjY`XQDssYpi>;;UU-@yA$or#I^9-k`j_kyi^PI7iFLC^hs3%r~}vw&<`;7hYkEl(d(gd_9y4f!klGG zu}nONwR?7B{ocJ;wPTyA0n`EP1?UUtcq_-Da`sC;E-oIEXXIjr)QkD6R$-y|7xT(w zmse^4bpU$-`T;t=X~!<2ouz+p9f1-4<3vM5Az1p5(8MHpy-BJDPzSIVpdX;)6G{(a z*49f{cJvKYUzYd$>tEo+yMMvS_x_5b?|i3f0CfO+0r~+3-dFq%^4~LVzB>D}S06#? zUU`1~rFU@nwNG&5w%na`^Fvhwr~}vw&<~(TNd6o64s!Mn92F~m!F(jhe)Md47H#Q{ zE3*4^6Z1D;R5gG)fV}|y03BanbbpIZHt0Fn2ZKk8Rt%Ynv9WpZkDHCrQ8}sxPzSIV zpdVo1jlW-77jL|-Y5;Wrdja|ZIzBXdvO4?c z&R>p-%FWm;b#ni)3pjY<0`?p_t!e;u0DA%Y0Xlx@aBuMrq7j#zh1@xE-$Usdtd?4| zX2VXD%k$1z1E>So3(ybH@f|z&ML%07xQ-mFzD}e(?<9UomfRIE4Kd=$um(^Euos{o zVBn4YWorMN5~*FH``7H+iCrg8;MkQbICJYIRRgF4*bB^BvRHY7#{RH@=UE#~|50>* zp?KXZw{OFiBZsASoI=&UeM$$g7oa|%C#d7Cot@zx7=#evYf4@o@|Vf8f2!o1*|uGD zg!oaS1K0~tJJ1u<@znl32Modhcge`hc|SgO5~5O45i1zh0O|nt0`vpu3F`PM6^Bu< z>l&7ycmtcRy^q6pzQ(x^WOw=V|EL;39l&0Io&Y^T15dxz%F0T17Z=O>f4k%)IU`ETI6imrDGNJY@p#YkJY1M}s+w6$_) z(iYJW<$GRII)J?Z{Q!D`I=+E;eQmlALN5nj4E2qNZ_EsYr!7Eq)?!ryr~}vw&<~&| zXyA>%U*`JFSa|pZ)?B!PU2^uHeDDFT{P9cN`tx_H22cmE7g&7kjPeAHpWncb%gM)- z(iOt-9VkC4_d{KK8AslF2dCcs5PM&HOX&di0`vpu3F`R4!c9LpuVV{JWRHA37VkWO z%HwCT>HIZ$9`9+T15)HXq#r;}P{+5C_rA4gW0$a4_$Emm$(e)1c_m1hzf{!#>Hziv z^aJP#>i8L={Y!;sRonIpZ_nf0)mQM+?R$9r?e|p;pblU!P*%BBd4f8g+CP0p0g4u_ zkms&%$L@nCas1p>oR_b2=;TGE1K11D51=QgI=*?g9_T4O#6Wpg!AN;7f#QF1nyLZR0jy6$q;Aj?Y$yEJ@yRQWDE^n7xQ$I$ z-@}17zQCFHzEd^e*u8I6FF-$l{7+wXvIakM=1lQZ8e>fIQh9#tR>@Aw{)Fr-@4Egj zPRV^q=j0B>L$7|UdV#_%7nL^5%^2ryf2AuooGt~=J%Q;R@Fn8mQnxEgm2Z=sS zCjaHRePu^ZVB0l0H{Q5|qtZL%nQJ9Z9dF5klSSMRDCaOtHtR4=e?pZsmb6U-NnL&rx- z&z_N+ulT=G{DYkbj^pT=D>xzbYv0lHsux&PUa7o+c$p#S_~CAT2$CLRvhaWQJgG%1 z)}u=F(#Gxkl@4GpkS@LmJwa-D9p9x#fARa=Fj9U8<3nXvl>AT6RW*P*fV}|g2K$U2 zJ#B07#{PQrRJotBcpm1hD8uqi8?j-Z)ShFF z+?}~-5lV#bE4FS?I$&v4mGT49=FCwwg0n##-$#6O7wOpp#OI3@Ze-0XR5gG)fV}|y z0D6L)3vf25UJzP#wa;U6-)_^lj|C zc3%+|^aAt)=m~Nzz}cXIH~xN8E2~ko z{|Ht{&%Q~xyYKcLRRgF4*bC4PpeM+=0B3{7&u`%UsQ*irVa7V~%J&?UUD1o!diAE# z0qf6SQGURz>TPN+z}cXVw;vlW{%JZQg{!HHW#%TYv2fcSr32Ut&<~&|$hiP@ypC^W zBff{s%p3!w;1!#Uz_jUz$eyiqK#=f&egHi|_6VE}>iFri7h+LG6)J^u+xH#E;Zv7z z`qE2E2e22QA3#r#a{28b{< z)bT@xjaIY6SkW$-Gv=X4K9@CsI)J?Z{Q!D`oC|O^sN*|`{A3#r#a{Dg8Y) z06&*HfFFt3Im#2H_ILL7QTYHJU%$2F2Q2%D&n0(Ui0{uDKpntdfPMfy!9If>)ohUY z03APJ!7gO3JBi}mH&A};byWkX1K0~}xFq+NiYLgq0B3{D2N-x}ESUFm5&v&oMg@`< z?LeON03~u~33UK_0r~;-1UVPrY>@eYDdJ_2{|3HAw?XLb7@+*W;Ebh+pCdbzq61PF zY)8VpO$f_eCca@N`niOve1MLBLHxfa;_Y>?l3CBN@u~(;2e22QA3#r#a{=WLMq0ORL3@T28?4Hxfgs(hU} zo1|ykdr0X3_5$<+=m~Nzz}X=40Xn{qXMo)QkO2P-dA4T3LfI9sP&y!c#X4jzUyXRt z@qywSdWd(%e1MK`Y-um|Kf1$qjQHJhjP44EgSWX%%aFd5!bCz%h>@vYi) zN6$V3;o$74z7A^ubpU$-`U>;}ITzq;kof>pJon!MCdD9HJiz2Ra?hO90O|nt0t+fv zDNm4d0nP>|NuR)skg-3^zd!K~UY^pw2O=OgR@DINfQ*8CngOr|PzSIVpdUa_ zkh-6So z3(yasC&;+~XM@ZKc*RdO!*_L-=Yz|8)-`6bssYpi>;>ot&=cfbfU`jdnGsqJ^)kcP z@7xdc0J;wwrD_0m0DA%Y0rUhp7vOBLO+QDK5z@c^MB!z&_!33ZXR`)S2e22Y-f>WQ zf}9I*Hpm$vGeSDv+dmwk(Q<=6G{=UN2jp$NC|>^+ zuFsenAS2ch-AbQ?L#EKt4PmsJ1&R(PP0n7+7 zCm15X3-aH<*KgJhO*`7E8bBQ|$U7d6W2Y!jkaK~4!$VX)fEgj?1a-Vc-A1U>Q1XpZ z1E>So3$*GwKzV|k3pA10AoBst2r(;U;ElguaGvxXOUhLZpbp?HV7{E&^aT0uc{}#1 zd;l{-k&^#0etrW#Bs3Q8(sQx~PzS^LK^#=c9kGzrL&Fl6(RpR1KgG zm@M8~TJ~J!36l5m$7qDj&cZ zKJ~kfZ`imknzih#Y5;WrdjUJ~`sfLAE?_C=KJx+02-R=U>M=ae?~y^{)Y(iOz+QlU z06jr+p0h#b1DFwFPLNq)V}F=`f8u+~2WtRz0DA#y0eWuy;B1ij0A_@k6J%Cc$JcAs zTHgPiK^@S|)=uic5XE=S1vndIKA^LeHJB4*R#?X~|Hm3Y9l&0oNrz6LCrHk7HpqMc zGeZ14W`%XUchVBD22cmE7oZ;*Uv zq$kL^0RMfs{C~^{F(=5Zu#bHziv^aJP#axTExAoBst2r(zftgw!6)TJL- z1E>S~ibqF3fSw@d0-OypAJARSFy;iA71r_0|FH&82e21tDRXXmg46_@4Kg3Vj1WJM zSz#T|vzs-5I)J?Z{Q!D`xdltW*!(5Oade3hVgh!d=z?>HzYVegHi|&ILFdq;J>PTJE?M?lUW_5%UmB42w zS5{VHx#S>u#`E77${ZtK@)7))BeM|RwZh;3Z;k&g_s^fd|9<`Z@7MhOcy>MC|L>sg zGUJ{;pDAGMMRK=|A0x#_bQe#8&pG1<^UmD!9XD>AI{Tmh{+|E-co*L9@%{6BfBM($ zPe1?tJ^%f&*Zcq7zyGb@KgRyH|A>VM^IVTu-+h=8coG>Amyi{81=A;7lYd@9TG%Nh z1?@rf*i{Jhnpd+wY~byB1;W`T1zv*-F?LuPLOj+YV$=pij;==dsPzbRUyd;@d2&al z%%l5{H^aAR)EgaJImxprWIoUey@Qx!_!_|K) zyuuGkUiK7%QZ67Q?GnP$uSkyWG6ECNiT8N~qXM_f^HWxv;k$I7ieCNa!gknlIC!pu zi{BQE2-pty@jKxr{~YFB1&86wDF|K^2fw^X zc%%iI;k%8pL%(3Tw;@q>&oX58lsg`yXNSONZWu<-3W3`+@qZJ1U>_>8SZ@b2yhV?e zXlyV3@9@6pKE@tafzIe3>I(Y^nTduBL*KEo*Xv=2)(*YUQ10=*diAQh|J!)~Su|?^ zi&l+b(Y-ld=qr2B13IAbV97){bU_pQuBd0z9(62R!J>ULSTw0`hIbdAJ5c7;u`=gQ zSydsvXC$me8gWlnCCuULt+~oO?VR=IMcs{$pVo7J|M};(Jb%nMXu8 zx&;TKwa;iYa&>`)ovk^(z1)A$r86w7`oLm<9V~_pL0#vec+tffb)6hxF?b*>Z2HOX zNBqy$ZEEnw{&uKGm2h94vk`IyIni%oZu|ojr+$dS$seE~={@Adzkz8JE+HjU=HF5S zjQwE)?`)HSQ4Vr9#PGF<8odJv0dik(@Co@ij-;bpSlzX|TadoX6=5dJV|cf?`1 zkJ}1I_Z6xJ==g?>$o(nk-fu3fhc3Zj_mvnbHN$!II>|e)!6271+272U>}I;E0Xn{} zh5X$uJW;P+ILMy+fHd{)iwc5n?|6)i(^#{(D91<3npN~swqg^ zn2wB{vyii|0Mqx%4(jfiNZmR^>Ols=OOsR$(D7EGa&JYF^hwj@4vhS81eL@hVp)>< z2wxnJ!1*!onH36`WM5SSbbKS*PH5-W7rg@=Fd)tqPANWc&+^BJ%mBDd^}*1D(dZvC z9G0U7s~Vu=Em{lrd&my7eFrpi?yA04r_ue<$y44FBgOxA>5V1>x}aVk;fd4$9UnYT zvMs{>taY;MzHK8G?%#>h!~3x0@LnuBuv_N9+oT>;VY2MUu?Fb)KEhGQDU&fKSN1L> zBOA9&o@KeB98*@7Bfe}oq9s!^W_BK&(^6Fp(DCGc3$Kyr85{(AnZY^Byv<#*bZ%K0 z^7E%kT}ecr$Z)jx_fs{%4Bxd2Ec#i&Vu;*zJz_XojPgVWUzs(H@kT4}QE2Mnrs{!( zU4K;r47{HXV-cRC7$e;2Ga^tQdBk~*)#vf2MfI2|O_iX2fL6)iT z8YFkcxL06;??xm9?m$xTE=&s8BpRX;e#7Tu#Na7P2k7{Qb^4-hBR5#K4Hn+Vz_E{H zzHGAKYCB!-!B4>e%So!fum(^E=y;E?eej!dR_^Jzg@pNckzV$` zu=rvb=ABuLyu*_1+c8Vk0O|l8KVXvhBALGMFOp}JEtf3pTDb$FIu}`+^N_S*I$~C) zA+#h;)d1=M9pA!P_BX~4#NY&XsUh-=)BFeoEr>;kU;+wdr*CEmTvB{tE1G~hK*w8j zZi*M}Hr--anV9#R<4ly3S_tO z$Udw&BRh1Czf) zcEYw)BVF`E%(7Bd1E>RZd?Vp(x4?05kgwx4eVS;IxrkUeA5rr40;M+j$lW_mQWLDA zBb5%&@fN-19?HRk(A>iv9sPXKJ0uwWq$b%!MWR<|2)YFLOMUTtSOY`{nBwVY#rvH` zcJv#<{r9k9&ga-v@(p&E{~dcOe#F+&zhP~`H>w6u2e20~_J@uAZ|}i!-@oS$BnO=k zt?&{`GTugcp6tEO{ure>4^WW&s;U9h0qg~IymjYTjOd?_@vh~F8@m;m6C^)3`7Gun zpTo@f(?|~8t!e;u0DA!)-~2^KbZa>dwp}M-n6+d^9Hbr%FF}CoV)!@}!qqNI)d1=M z_5wP7RNPU?=3bZQl)Q!ME8drVvoBDx^BXMQ{XL4e{ugrBe6DH$bpU$-9dGAWDf!%; z@J~FBi8HStwfHu2%HGC|^;Wi!^lz7?x(Z9vJT<*Eiy2e22=@lL6u zMC*sjd7psP>Kx?mEk@DtB`7+v9CHtqAY)sessYpi>;-guCvR)m#kk0MC(k)5l>N2k zX-HcucVMiaiOFl^&aFj>ss>O8uouwr7JXWvsdG1U_O_Aty%UDSdBQc-7b8-~V(4Vi z4&g4U22cmE7trxj%1e>IRq{Ru_h8-G6WD&^5)Qm}3kTnL8GBy2flXJ=s~SKZz+OPd zdt{^|yl5U$D#|f?%LXjkzek>xcMK~}9mld`@;r^5J5&vz4qz{!koPP=y@Xqn|3Xqv%B?ss>O8uouwr7X7W!*mXEMN%qD@vY|sItK*)U0(a3H z&XXrg9f(pjfI5J^fPpvmx0A+RLEa?UQM5$O8uos{opyRz0&&d6Ex8&Jo_fW9mGc4WnEhRp z0DA%Y0Xlww^!%O?dl8m(R(4KbLEh?jv2e@h^32mOP+0YessYpi>;>ot==k=%XG-2_ z8Qg<53-=F82J*ID&2O>`^s8f&g^MA@ZERRgF4*bC4P(D7Zz*@$=GE`4(- zCY8$b4y$J)fA3-x9#|^b!}+QPPzSIVpdX;)>)5tLOLxgw1P{iLc-aBX5DhU)vN+;b zc<0EyQBnh_1K11D576-$t7NBd=Vq)ten@tfF5=MbmvQdF+qm%leVn|1N7Vr80QLg( z19ZH1wrHG1a^Khb)w27rOVyB_H)NOk)-`OtDtwU|KpntdfPR3E?>f#Oj)@5vKYO<9 zNS9&u=1o{~@Bo&|?%jO3M}swhI)J?Z{QwsX z6EyaR4ZOe8IwbfXMsCb?ES`2xIR8iNUG+VVRQ(Ivmwm5v0DA%Y0rUiQ{JeWR&w9VP}zI+u0UL% z^lM?8RSlpHU@t&FfS#a^_Z6KHGw*e|qvu_@d*XAfIP|^jp8p3D0ai7DI)J@ELebmG z6V&m841QkL&^`JC#d7=G>DMAZ@T22=g8i}VvHOw{nCVu z2#npSY5;Wrdja|Z^aOQ$)QUu8?aW2t@x@qqbv?GdwHJrqKZz5comVx0I)J@E_P%`O z3F`RaSz{2kFcy>7PsiMS3$XmcT2#HV4O`!m`=f4dRyu&a06hVEf;zr?-~iFLqYyAh zYDjrHa<>&>;n8v|Kf4Y^2TPR>2wfDf`~Z4_I=-HLJ9O}pJ21qDa84Qp@9Yo+7sw7t zvFsE{4WJHSFF-$lo}iAOwsr*;?%9UbCl6!ijmtQB=Qgf>_yD&)|5()k>HzivOQkoU zC#d87abgD@4kWEFJD(WfV}|y0D6KtzPo6DSJC%jaz{>v z+?Tar*LJKtaST-#&Z6|lVWk727ndkMfS#a^XW!r6TQc%tp%@|k#rPRHh?05{D|hy> z22cmE7oZ{``amjH&B>-2P^VE68?XUL+k&FvpfH{ssSf9|8La`R2F=tJi%#^ zH){5W4ZOe8dL#<}XT)B|lIi!bVc}=kv-%tCTm6I50qh0xC%-J-z)6`4$gZijzdg9e zbm1-ezft%vy;jy$R1~~{)kSxe4qz{k7_1%Z9I05yIrm zj~~BY)d1=M_5vepvy~^O!he}B3>vve z^4BZHKiH^h0CfO+fj%;up(oh5S+p5GT6+I!;`tSeW?v=z-+FsD4n8=cYQXM$vI8T% zz@qbI$`g!VGt~_5I?WehC6h2^eI{n_n=kxdgQ}Nhm+rM4Sb1%O>IE`||B=fltGR&w z^IHZFz|fRY7^nE3ff-xp$^L=l@Q+m}9l%~7cwrnoq<82a>0~oA2N5MssYpi>;?Kq$$h}$2{swr#SEXlb|n_>-iFGPN3lcB|Ko4Iic9a^S2f`5 zyLVMDu;HTI>n5IHj@*S;r2YNI%AHt=OBZ35@PGLM;r|7>JL}~eIP%&nQctd^ULap~ z=#y7gV0^(GGrXl_>fJ=Ihl{tEAs%C~+?loF=pn2+Dfh674qz`3U9u1!(jQm}kM-BD zJH!DUWjYUQs%Ly#W0HdV-t_a5kvpTh|+jK5e5h zq*o?J${83iVi7_|l_?z%=(be(0rUhp7vOAA$B#}tg~-{rWKZv|Jil1(`rH16ssYpi z>;>ot&=cfbfU`jzZ|_-&k&$~4ntn#^oVbRZinlOt{R5=~X05uf{D6qeOKL8_*`SVZ zYdHfpE~RoeZZ*co?Zu?*Q%K9ds&oK*0r~;-1UVPrY*5Er)DMw+&r{H~|4dlB6v?i| za=49Op>%-Lm~!O@&=cfbfU`jzAGUlFrf!w9`|tuRJ-b5A>`kf$PzSIVpdUa_kaGdf z26eo1`e^CfqcCaJRAg_RgW{vhP;p4#?b)r~CkVf}9I*HmKuYux*339=&9KFc^bl-Qbos7T(i?l@9Po z_g8)ZJwbYaoDJ&u^i|7Iv}2R(YwyR#3#YN~CAs@gY5;Wrdja|Z^aME<;A~LG`($Uy z?!*F2mwnm!J2qp@u|wE${;bjgYtI~4egHYlxd3N_I=-{``c5)C9M66CC35ff`breZ zJ$%#wd7CyWKY*Sf=K`D!>Uiq^)}AB9_msO&Wq#m2HBELevXu@Potduu0D6L)3vf1Q z;Enz5m{Dhu6)w;BPJ3Ip`@X6H)B)@Ts!P67p5Xk{57cas`2f@XVdmvV+ATxyh)tL> zp5Fg86s5kQbO3t+`T_I=sr@+{WIjO0_iiKFz3)r}IF~66kQ};4>3}SmqfL!GfO!9H za`uzd&LNo%G9RGh$1RS)r1dGt-YsX-@kOcz zPzSIVSbkaF)8YwoF2LC!^8q^EA;}FMGXoH@G#<(8vXHZFuF?VQ1?UIR6XaZgvq9zq zbbRYkJHzivTdrPE{d}p+ z0y!IGK0wF2iM|e=EB95DEkT}WfCVx~pblU!KtF(&n7Ygp6PN2 zik#a?(o0YWq{~OL%o`%)E^SY_ch@dPUpWrU3VVPpT> zwci5x4iT@-LwX#k0n`DxlWr(KfSw@d0-OypAHa-|j_=w$7HG zF8EA7CHwnVRSlpHU@wqW{y=$xoC|O^I5zo=$_VLrONUa}%lGUOv{lsr>Hziv^aJP# zaxTExAoBtJotK&Y{0&+rp-t~uuymNOY5;Y>=7cA;J z$a77?(WrHzssYpi>;>ot&=cfbfV06D8-%HhkpBITDGWhGSv(S}(^L(h4qz`(bYh9} z1UVPrY%qG|WR(%p@wTzUFf79x-gAOf4WJH4uF6t=06js@1vndIK475C_;h^JVO`KQ zK)5@>S=9jQ0QLg(1Lz5IF2LDfuknLbMo7n7bZLUR_HEGIMP>j}1E>So3(yasC&;+~ zXM^?a+N+F^j-R-&2$|vm&fO$;4@wQ74qz{^=F}18334vL*6_>HvN%`T_I=ITzq; zu!o%Q%n0dtHUAql5KUzk&l*4-z+QlU06js@1vneDa2TXALI&R0-wqtU2~i`DsTx2X zFk9w)`AK(_C&;1j!S``5jcAAm;+%Be$!3 z05d|&3F`RP4P1r05vm4I2aFsrAKo$#qbJC@0B3{D2QVYVoS=@cZz0dSv9MP)fI5J^ zfK~g6$`j;Vplgc&l@DM>h*=>W@94J~u95py4WJH)$a@JB@?TY+Am;)h)5W`&d;l{- zBLcRW;XB(%M$d7nssYpi9ud1Sdg1})334tlTylfV2QVYVoS^>tbzTfb!#2sP22clB z50kGYdWW7M=K{SP7O8vyGeXP>>UawaTiO40RyBY+fW1JA&XW5PzmIc)MlIyrm-@hr z5VJx$-hGBYe2c?W4WJH4+cFKAJLDc3@dP;+NUV}O^~56>CmEqpdBJA*ULgbJYUMCAjR5n@hIfBm}sTci1iZmI@Q2e21#OqS>iFKmGpET(ss>O8OcdWOPG)`d1UVN7E0h_&aGx0= z<^*-T#Xxzki~9&w1E>RrCdOlU$`s`ZaxP#eb%FT+W`vj(GQ;=m0gFDpVIehuI)J@E z+fiQ16XaZg^@aHWl@aRN7qF;5 z9`pn`7vOA=`2c2w_<76<>-b?AlDCr@KpntdfPMfyLCys@8)QC!86oBbnHARYoyXXK zHGn#Ry#W0HdV>7mY>+%=Mu<5I1pYtgsngIBmfiz#NeD0@V2Q1UVO=H^6*=`fvO^$qF0z z-~0aZ^Y8zE_Wt_wzyGiM`#;~m{%!ZKpa1@!|Nei?{{F9h|2*ISe}4bL^ZN__=iXoN zTkjt~fBonC^S|f)`QQ8dw`PC3Nh7?_t`(a0?TL0HhN5@0+!sDa?)_X>ijt#yRsP|^ zyKm#pSD)jvzkgq|KWyM%Y}#1vr)(pBRc~02aDhj37~;hHn7?`jb{;y2bJwoojeGCl z(=WcjcYpiA3_rT*ix}6g8M3UpVxFfnR>VhPbAB$4%Dm-@ENqrJ%t^^lzI^>U{&4>td@Zm4iPmj8 zp?hyznYVjmq}m*Aj&rvz~(ha=w?z{NltFQ21|1f|37aO-mvo>AOrI(%D z-#i*&A@P_c&#$N|Uxm~A_v2N07So4!@8X-!KE=PjH~;-xG#1~hO?x!7?1#=nyf7pn z34tj~F|GI*%Gdt^dk+5@*KYg+4<7s<{Q1u?`~Dj=43k_?0-CojLZ{xcV=!nxT*ll$ zaKfi3SpFrdc7BVK7k|KOcYnmkpZ(hm|6+sT@@(-j;$NnsS=Tk_J8VBjgxrwl7JP)F z%CAs;;JaDf-PEL?2U)*`nAXSuj5VmU+6W=jQ?-ly!IIXbv*fR*}hE;|EI@BKb8MFzBc|>maSL(f929k zkMUo}lmD$+cYJ34>v&WC4;kkDME-wp=S~g(b^I^ozm9*%|M*(@U%mTr{_A+1|5h%K z^MB*P$N8`0ALsu};s55R^4|<^#(&A#JjVY&J;r|>|8xA`qVZqHoAdw7WBlK!@n6R) z{#&^#{01f8Q|4*vR>B%Ks1UJg7PUb^NpN|J4T%YR-QhZ}7isZ+p4>*&Ct3 zaZf$}b-cm|J3LQ9shIuSLgqC|6Ozbo8fi- z|IGPsis%0SllVV)uH?3U(*HdFP5E!^4;%acru;YbfBdW&wd#KzZ_0n_|BARsY$=#o zqyP2uU&kB#cd_nMqyLx8mU~8O(f>N$;C}~eJEi~0|IF-pkMZAB|Lb_2{~mImeC*tL zwd#KzZ_0n_|DWT(j@S9`;Gg(Z{jcL6@xS*v2I|8@K? z?f-TBv-1Dj&p%WBzmC`W|8xDnj(^nuKb`-t|J48M_-Ez+8}B~s|8@Mc^8XFd5A6TV z@V}7%I{sPt|H)7NzmET<{MYd{{r@xa-wgi?`ETHj{rzX*ziIz(><=4wgZ~}-_IjfK zr}zIl-jx5((*Nstga3yA_jCQfjyL$P`+uhT-<1D4{+IG!#~b{An*V3o|Lb^z|Ih0G z>G((dFMQ(p&;I|!g&$z>U&lY<|3m-J=>Nli^8a}LpSt!v4F2o*NBlSZzlZ&QxaR*E z{5Qkb@Za$N9`^rHsfPdeC!8?x|8#r}|EI2fqW@>~{|5hcd=3Bovwrgb9`^sPKly*u z|Cde9e;r@Lf6f2%_{slc|9{TJ|1-lI{5Sl+C-ncPO#D9sZ|v_siT|ehpZkxd`oBoq ze>V7U>i<7Y|Lb^D{y&TVuj6(7PyRni|NrUBFO~nV;|=~B`v2$re;u#ufBOGV)Bif& z;6MBSr}_WJ`LE**{y(k%H}(H@{Lkrs!~Zw-ZY}*ZBXB`+vIsuj7BI{x`!L{5SOf z6ZmiH{~LH?fB)zBulxVT{;+{J_-}gtKaKx7{^$6w>wg_@@ZUK9>Hj^6|Hk}J#~b{A z*7IM-KZ*ZOoB!!}ga1Ew{u}()@dp2&_59cIkNE%O`5*g#)AL`)KjOdX{O=}eJO6e3 zBmNubzxaQ`|Ju%fGkgvIjr0GZ|M%$p|N61>U&sGa{_A*i{y+5pYCHdRd=38}JO8i2 zIREMYnV$bwg_zqyMGFi>->M1|Iz(_9sex+H_iX(_{aJG^Z6e$e69R9 z`v1rEzmBh!|Fz_Qbo{gM-!%WD<7>|U$NazA^FL;IQ~p0g{>Q)@`~T0vf7A0{-#`92 z{_E$zjyL5$&wtMUO!I%H{QsBa2X*|j@}K?xKmPhxGrZ3KC(Zv2|L@1|{%(fX`Oo=Z zZTkPul3&!nf1UqNn*Z_qr~d!vU;bi-*ZKdn`QM-Z1T(xj|7F+NB>!ie|3?3B_Wjr7 z|BUm0-(&edbpChw$U&I$pZQ-M zZ}8u=|2O7;C*%%gJ^!oY4gTx>zmfmd^}mkS`EQ#4-E#D(S^ihY>-;y>|EKotGt2+# zc%A>I^S`on@0sO)b^Ig#Ke_+c^M5-2(fM!M|3B3Kg_8f(=l?qX5&up4|EJ`C&G0q+ zf4u*Hl>dD^|EJ^4`Tr>YJ6p0phW~Hme|7xR_&-y8dp-ZB<7@c;SpWa<{Lhj6ub%%i z!yEj6O8;-_{~7q_`_sQ}fBO0F@A>a9N}jF34Be0fA~56`TqKExxfDW{rBtMf6w>-pYQ)a-~WHU z|Nnb^e);cx|N8m&|NQ=g-}3$gV}JhzxjVB-LpyY6Ga6Psr^4NNCE_M*!-B%2*tzv8 z&Yii7H*SB5Pe1w&fBD9If4Y9dc4*P6JG%531bc^Z@EMndmKymtMx3 zcm9A+KmQtk`QgW!{bS?xEn0MhMF)8Xy0r%^Mkd1|W)I2KUuJEmxgq)r8vHt8%9DVI9UjE<>{Nc|Z<4^zmiy6K_ zi$-YKu{FBd^uz$Kp%@b%h?M*+ELm5EJ#v@y1-VE5ExAA8lP^EV_kTCP|Dadhrm$_& z4x>BvMP@%&tQr}G?Fln+Y~e~=-FXOi&RxT&Z{EjupZpR3`Of_QgI0~2pmXcC@{H5I z@EbY;X+iRgugqL*EL(*W`w!vP6?$L2tOW9*(%~u~^_( zgmqDCus?qvE^N7g+ox~i!`DB=w;z3re}7}Xf8V-6YjkPZ1@_(T;WyY8md;7;`pIGxOw#=9=vl0U;gnknSVWc{~7!HSfBx*-kMZBwA2#shfAf~z6#oYd8DGQyCCj%c{$INM%47W3@wM?kw(^+b z|DKz79^=0m{%81q=Eg0&cK_WP{+r>+f6LnWf9&;hkMUo}oAQ6)C?_-iU%Yt*Z_51% z2LE-uDgU#qN0{;d?)mGF@n6UPQvU1spX2`>|2m%h@7$vEGxJ}^Thzk;g==;z z{-3+?`eXdp@uvJA>^AO+{D1qM2Q~cH@#KG-UUi40u@Za?OH^cuz{_A*y|K0jqqBj1Up8q<&HvS(k zS*6Z@o&P#s=YMKoVNNmOr&HkMs4T6 zjyL1~#Fa|_8~oSxzZw1~{!T}S%70V+ zuj8M@|DuedTJ^t3`GnU&rhGkC-(;>3>uHo9cfv zyb1pe{hvE8wMPHz=f93O<-ei-t8&6>)&Dx)l>blC|N8lF;EnzLU)uj0`@;s_=>MN~ z{+ssyI^K-`KlT5$@!t%u@n7%%b^e>-f2RM}`LE+m`Ts2EzmC`WulN5t|8@M6`2V#2 zU&rhGH~RnD_^;!CY5%X|pTvLm|F!X7$D8v1S@ge-H~Rmlo&To%H^V=H|EB%F&VL(n` z@?Xc-#{cT&8=mO@>3Dc)R|% zE9>G~th3H}&%G@H|NruDf2a9>ix1>~Q~ZC6xBmaP<^MhSAof4d|F`*ni+B8I{7?VCvHagZ z{q|>?|F`%+{s;5_ZT{ck-TnPw{Ac~o*?(LAbN7cG-toVw_TS>~@jtlzXZ#;%|2=r0 z_TPj57XDlR-{Kwrn`-|pzA^qcX8$d|sr+~KKZ|dS|BdIon|1I9}zp3`$gZF9wE#C3p+5ceqzd-wM@!!UO8~;1JyZ_&q|KC{sKk)uA z@Bcgh-^Txq)&DL29{(G+|AGAX;Dgxz!1}+f|9S8}{eO#h{QqP5|3LrW;>rIWVNYoN zKUn>b_5VQs-{Q&tXCC`Olk5K$-x&X${kQc$i*L;TZ>;`r@s9tE*?(LAv-rmNA6Wkn z^#3j1`TsWlZ>;|B!3Ws?VEKP*|1I9}|BvPW1Nm?9f&6cZ{~w6w{lCWSzvI8H|GE3a z?*6~C|CaxO`TxNBpT#%E|G@Y^u>Z${Zvy`V^Zy=v5c?n4|6}dH#W#ijf%$)nZ_NHX z|KH~SEIye1|6}<-i*Jnof%ZSJ{%7%x+5g7)Z}E-szp?n=;+w+%!2TbLclO`%zp?n= zgAd?;VEpg;e;EG<*8eQNDf|!Y|FQT${s;5_t^Id+cmF?-|IGif{uj*uck#cy|7`is z`XBrM9RCCR|NiOs|J`$c+Qa`K^*?9-fBUch%ZoSsXZ^1+`~Q!4|BwCoLk#~}{|m-{ z#{Yl!KmN&sZwmiu{~7=P^S}MxgSY&*^*?L>?ay!d-&p`Oo?v`~L#@@9Ka5 z^LPK#^Yi=Vzm?xq{=4|!;+w*MXa9fyuinpZu>AkF`k$5W`u|w}561sM`~R>1=KcJJ zrtqKk-^Kq{ejxv8|CdHgzOVl;kpKVwFZcibS^FQD|8LCxyZgiL{=emaVE(V}z>W`_nYtU|KGg7|EK=_x%>AWMu$l6 z$Pk&fGDPAFLnObZgH&7^D#zZLE>+it>YVFSQbMF3_Pzb~+tQ;)4{`XA=^+xb3}5Sh zAR%P~<GRe~opU{8-P5|ygC8_qLMASgkR|IRB)d!=-E~5GAA3_K zT>C`&oPJB^Tn~xG^C`=`@v^d@k^%z^?_KbFOy*zI70M zY)D6071CR_giMp_kR@{I;e7e<#R~ay#8LV1h21*mdQr#}$q4D^kv}~I|8Mxp4hfa* z-+Nh(y*No;du5Tl6~0Wayb>)(yG)eQ@4qZ-L&9{Q)jvKyUJ45fh4;d4+_)kCiqA+6 z{Kq-h`JDSKJ_NG)_0U5P>A9GfmnXmchaZ%dVXbBP$~5`e&wn9*_{0Ave}T_%X78<)KXKwjY3dghvv~LWZ|dmq z?*6`C{=56b4)2%$9=uQfd+`KGE}p_S5l)+;7T1x6jIVzyGF=4)5;& z`{jS&{bAn!_sf3|-Y5S(c%S_D;{EYI7~T*6E#5ExE#5ExE#5ExE#CdzHI@Gs@0b4; z@0b4;-@yOpVE@7Y@TuWy|MLs#`G1xC|LmUqxA>u5J4)uPNpdzfUA{U{CO@mKl-jIh z3Gd%iTKxF~@`ESa$%ajv9beE0ir>KKUU{eQpw zclU?g{eQpw_uzf<--Gwbe=pu2|AXQE@ZaM7^55e9^55e9^55d!-(6GrZ}EQlZ}EQl zZ}E=*&yoM||EGq7|A~o`Ur_J=U%PfyJ`M2yE&h>*zb_+S>MYrF!{s9U|DPP%Dc>C4 zB?r-BkWty!-t(b#!=lf8Q_v-Th&Q_sf3| z-Y5S(c%S_D;{EYI7~T*6E#5ExE#5ExE#5ExE#CdzHI@Gs@0b4;@0b4;&!3<1zw&=T zf3^RKi2uF(|Fy>d!SIi@d|1YIe?d0PpDtH7Wr6?Y@-@zZs+2fA8@~5Ih;(}41*xps zt2t)cf5#uc{0}DI{U0=Cba;1v-!K2&{b7gq%YP5vC;vTopZxdY{qa8--VgsR-Y@?x z-Y@?x-Y@?x-u=xrmH!s+m;V;;m;V;;`2Xy)&r1Km`2Vi|&-njS#Q(p(oBy-;M;?1j z^O{eFwUCLuUzUvvXUp|1Yvrd$cFC7DJESaOp$x`nb3TA`=H;HfGzUojJO23Pzm@NP z|4kho-re8#%YS!&*x~*1--Gwbe-GX#|GjvB{11lr!+(qS%YTda%YTda%YTb^e|Jsg zzs39Izs39Izs2+CXa29j|405WF(L83{6GEwU;nD!{#*Qz5u+sRk+ymUJl#4>ruOS0 zTjJ))o7-~bua8#97pM(z-sibzbdSaR<-f(d-+xm_hj;h){qo=4A9i@Z{P*B}^528^ z$$u~2AOC~l{qW!7{qo=9{qo=9{qo=9-QQhP`ET)l`ET)l`ET(J{D=J?p#DGWf8c+E z{b&5o{C_?FEj}%Cwe%l6R6<*~mOsN;(xGiDnK`(RlrD{uw@dTn=e4`#ld59LUoca; zJ^h4OykGuXy!-t(b#!=l|KBhF1Md&BuIrco9=uQfd+%YS!& z*xmp4%YP5vC;vTopZxdY{qa8--VgsR-Y@?x-Y@?x-Y@?x-u>M*mH!s+m;V;;m;V;8 z{CEC;gZ;mk|6~2{)6eel-{ODqi(g9JiIWnav|PIP?u*aEX@Sqw2$3#NJSGd!3sjXH zCm)m-YJbq3vV5_4zx=m&_xo?^=woP3yIcRede{DI{Qqy>&ktbT z?x%nK*K+7+t;8;kmlwPDln2r4_#krrFFo}GSu}Q->|eQ5KHgm; z%|Czh=La-@e!zTT58t?P<7D#W$ueci6d6B$yo? zQt4W_OL~{q$k2*f8DD)$CLKI0QxBZeaa_$QUGKXcci6X7c z_gw(_vxCTQ0r`(Y{!@_O1@e1A{s71y1o<3$K|a<)pN4$wd)s_|L8nJ6r2Dh`Wynj% zWNg3F5x%p7|~A|_nXaq{pBx<0tuQF*ETeh`y9{DKd(h!Ne&$&IboBfpw%2HYP~?VwT{DAtd3h+FVyv{ut|~>I@*IT z?LAp4hR&7)6BbDAw0JokxkAn^%#d@jnL3_|SfT6HW+Kj~+b92shx6k57qgEJ+ua)gWq;N=x)XeQ5 zmokRRJB8Eb8b;2!p7IR#{kiw^6GlIZ_5Q$51b#8_xxnuQ{v_~Kz+=w!lquNP?;hUW zKki&uA>{Vxy>-g@xph}1>g;t{aOS#>oQEGeC!?$Cbf3FF?C>q8gL~k1SR(%ZS8kF= zRu{{Y8+J&${GB>--YR{QKIcA*?>qzY!R^sWkPpt!&4K(p$j^s-jGTvKeRKlkW1q#h zYz6t?c33ya9{~9yAb$enPlSAoobxOQdnrdk+k54|{LFqKwUnp{P>o`h1}lMDiVB;k@7anq^iwI z+52dQj+~dYUX17Suy2az=dTz%Q^@VQ*~^vlR}qxPK~pMUCgiNAD9R$O~eQg3`9E3Uq$bFR}L7`nUGbALH>Zc@G7 z2ge^@TPj^PS4z*VH8?8{VB9aA3oCVrI23+`55E3 z+|qTP4cr%af0^fN=#!97yAO^(J{Iz4LjF9+UjX?LkUs;&a)vki2N5JpZ1*`p9A>| zAwLoFlOR74@)tlp*LgM!3?lzfm-TAj$?;pWYUEDLarrpmqt96}cLqV {e7>@0@m@9DhA| zgWOuZRo=_pF7I#HDeq#u1^dBu`UADo5~&Uq%#4`3`{@u3|cA3lHEk&q9r4~&8QWXR8ee2koT zo(cK%0}u;X{9y2eK0oa|xt^W;xolkXl@#axrH-8QOyG0I0u~<@mJJ`j2zI{$wcctO z+3S={9(Gw~jk~HN=Py5fQ2heN0v4YL`Skg>;QN#72O#e_9`RgH{Bj*btpMC&i0gJDDxj=n>+Ie#Q^W+Qi)tc+_m$`51$T`mh zK4&ao@!4VF>ho8$fqibjT2A#Ul*_})f{;SK@Dc3(L zsFW{C4#K8B; zuz0`xw|Kw&w|Kw&_uzf<-{IZ;B8M=(=8Vie{kp`Qy(#m6;Th0#+kSn{eHK4( z5#%GzkIIGo?T}vs`KKZOJmjB*e4GJX=X36}_|T4!k2wG7@sN)k!uS-(Uk~}4Ab&mN z;|%CI5AyMx`z(G$uj3l$FPZzMWWw$i=6ofUB|njx%CBYjwx8%3kO4c)=gbROe5+Qu z;Qu!1{OE2O0J}SF)Mbg8{+7hg$C)wXrk(-x1NfZ#EPgrUGtMu;_umWoCn5hb0R$lnh6n<1ZPKmz3RIrmxl$H7m= z`)|%Y0K0!$zRG!Beo}HrzOH;vezNTyJp(?%I-hf&#pkw~sd4`9M_0h^Z;;EQ%H*x- z2j$NETDdu+TF-!^FXRfJGcREAhbF~ood4R2eAxXR@TLS+#b(6;X zeRmvCyB~ArCeD)gWzmH`bAs@ay!TT zAMy`C4(&db>&aVW%J>&hl?)hr>@610eKTJF= zcOsAIoa=iYO9TI7J@OAvUZTD~nMD72n8*2aE{b7f9_W#M89S!zB68VBf=iZb^*#GedPO1HWa$TAF2^QaA z|2IH>5c{871NmzIAs_bN;+_3}at!3(wf~XGBP_~?eAxf-D@y`B7K)$p8TOfZYrHa9VE9ski?Y@9ck7o8=Am|JF?85pZ7IoVg#d#ZKe_a%E4O6t({r@9h6|yfgeh z`w#BZ{(rvxpwRx`Sdpjp-{PJ9-_dKrJ^POu6uEzGIdU8GQZ)}y*85ep{}%7p{#(3X z{#(3X{(JB~`S0-V{(j#QZ~RZr)9&ZJ^O@X>|F3DDz}+8q_|V9E@jv5y#{1+vW`*pYc99PrIK5`7ZvS4*ARz zSbS~w4FU20agG1UdD{Ii*WS>%i~m_0wD|0>R~zDg#`%o*$$7^A7e<%qoa+@hA6Of- z_?lM(6aSff5!QY_sMzM{Zo-Ebr4)5;&2j>4HPuAxE=?7^3A8|i(e_UsMfc*i1_lJ4^|6cyT zKptOLB3(A^RzE=V|A_lJ=Q?8q_6JyeL;fFpjm)jj0n*-U{vRWAf?Q{e!2G|(H{|~Z zL;hIEpAPx(12q2+yU#h-86&VxVDT>hKO6b?m^n8!2S`7F`G4Ad<^;LU`T+X_EZ*h+ z8QXVgQz^aLA5cHQ<^MV7I%5Rp|1CZ+|Gx!tm;4JZTk$! zSp<3X1DOA(-RGR^j1gETu=soV{|dP|2XQ-cfXoBb=l|iuW6pKf2iPBA@h<jW0>^8W>0 zhDvFV39@_GO!Wg?{-1NMGe%&4fW`aezs39Izs39IzX$J=|ABbk|LeS|zWzUI5AxvP zxYqyS>oeYu!dFDyWnJg<-lf%^`^)#$|KW3K{U5$Q<9)^ik7Nhb|4}P&_mAD@2XvlZ zU;iJq4D!Kot^emjKH~i-!~_xRARp^|-a9IY{II+A{})mJM|`jKfB5>0_ZbsBGCHvS z@0H)()&B>dQI0duzXZNE<9)^iF*EDy|Ksp{@JqFxpTA{8{l8G_{H*tPhOfv@-ZB?i>K<4@B z>oeYGOfU^|)&_^*d5<9S_dl~r>-uK~Z&Qvl&re^U@jhdMH)f*e0^C0{xI}7S^4?#M zZ#hKk|AnaUvj)g|KYe}1`-}<7@x}GRR*{m8`oI1EuNX3;zWzTeNjc6uKYe}1`-};$ zAcv>*|CvcrGj5>=AKSK**8kT&i~2umfUNh^*Jr%Xm|$zSvAWLZtp8j2e)(_le)(_l ze);dg`{cjFyZisz|F@-5dwaD1Z{G=-bm**dp85X3{=cr+7kGb|pJS-~f9UJe9w6=i zTd#3Gdw#SJ5H&yAeb@hI@%8nh;Joes>pCll{1$in|JVb>K7ihk zKd|xsKP#X8e?2;&W{=()?f)BfUZx|?roCsrKd}Fg`z*e`|1afk4-n*nXY>Wgd5-t@ z|D|~F+W&{|%ibQ^_cf5e7IMjX+yA#Pi2Ns@f9KE??E#{F9|ieiA(xz|PY~Gu$9?wa zXa8Syhb%ns(x{=oh}?z4FI|D~X>k3B%N?}e?{|F>8<&wPJi{~z~R zJp2DD(f`LDAlmm6@bS+sK>r`?J@fs6{eRqN@%8<{Qxycc~u z6}r#eA9nZu9~wNV{tTGDR6^&apbt1zm=g?(%hXZl^HYR=LW{8xp8Ly>y#o2@0q!yt z@@GRn`T>{|91;up7&-420r@i^ANxG=AA)?I0j(ha2au0`0Okb4o`-ylI)4iCTS0yc zul)9Hb_&mco*nkd0QBOpAAmW*(S1(n$T?#K_6c%dqw-rO;tW`=Hl8^_)&)4y=5w8X zLNNK$AfIPI4CKc{4*LO^6HJACj+`&SI{O5<&&qED{dopF5Bc37hy4J|2@ZgKj-0=M zb@mCi3!?u{)a`i&?CX#zhq~mTZ>K<*6FkwUP)E)Wby+9u6XZTCf6_x;g=at_`T$pl zjfag77v=;v;EN;YtHUM=`vfCe^zz_~5ts7}*fn&9>>V>t*bl&*;NkGaI&!{uOeA`L z;m2d2NB+Z42+x4Hw$DrQ6EET%=q}6&u6m}Ij+`ey{<5%7a8B4W9=u=vTls$ZZ}EQl z@4@@zzr#1*pKrcD-+X`mzkYxIyUw5H`_q5g{psf4U-R$pyZreH&G-MC@BcU7|8Ktk z-+ceS`Tl?N{r~@W@Ba^~#Cz-aAYXiNmrOf~d!r|+CGyk(iNY7h*_d;E!ohMGxu@83 zfBLD7neu#bj&$2uDE%snWa!>)GP1f1eg9=Ta?bT`JMyGcah3-kk{To5UlT8F@-n1d zVJ7zENY~O_d2xHbj?ZDv^)|Vw@*wuv`_mya#>t<}pDqta&yiM(Bjxd>3*?Dqi=b~(UE;lT<3G{v-nY?M(Jn9 z@*GXXdm}S5GquLNe*JnK)6>&+ozHnE+~V7|Z7Ur+b`<7f-S?U`YnIHLH%~Yc!*xFA zJE|<+<)1=BL*?qMmFa@m*U=O3zTq7!)d5!@?wIOdB0D z2ZrhT(k?A^pGW?3$j^ZMJjgGC{Oypx6Y?t{A7kxy$j5rcddN=?BELW6kAVD1kUs{z;kM*T^9yPp$=jUHp*jchldP?5z!Lp@htn8=_mtA!;rTq9@9m{H` z=z3no5Xmm_${#ZOVHp$ELMFwxlvydEGCw0!7G;G=Y)%^;qcX#EebUmFy3gwWOli1u z-8Dyg*Tl)t+9Vl&DqSX>T_sb`t<`bdsWe^hTfIoSRLt`H{4M6SmX`5PN@!YF3Crps zt#SuTtAb(DYSXCtal=4e4_(n2`<`gPyZiei_HI>f&pcM8oR2+!OqN`#lckrDcgDzh z)Tu)<^VnY9=k5({ki|?%cWhock=EoF=#1wQHxGXHB+W zzkbrce}5f0=UKq#+-LD6bGr+d5)=tXXn!OU@$~0)qisgRG6^PCvSp9}dDz4Eh4x(m5odT^q0 ze&4xhIeaNjj$U4>Bj>x0&ysC;&V5$?NOB+Cp1U$sIlnCbDM>5pC>h1i>&SUrPHTNW z8T%~0bH!{Sw@23{E9d84&6B9>8)d=uO*(QOel8o&SLi;ASMGz`VL83Q`7!cH@dSBt z$7E@@bE=MDWemtQ@t>+}b> zFYx{_@87?)ZN1uea(uG-5Bp^P*~1cj_9*&?4ypgZb)F6VDmQ!Zp*hRdzLVp9afXb< z`_jf8s*nkX%4OVvav8p_RM&Yn&=0WkAB>uz_MIGm4!nOMJxRK)S|L4Gr|Q@>BT3hJ zHqbw?c=kimzLVqp449iYZ_4}czb_ws^pU*#?z=kYI-hf&#m|{DN9{W~URqkJ{zGkT zt(-V(vzAPK^Vc*H|i#3p63;E|D z|2*WMh5TcXk9D36HJgLTf2H2;ljECHAb%C)=RtlRED#*t=&j$JdR{wQn{nfsc z<24r{=k;Vc{Z@vYzr9LM-ol+G%(+f~pcwvv#gAW9Z}-XZl+Djdc4-gEtsE!?RYN4V zVvwvU?XK(e2WG=Ru=s9!qSU^Vz5B)phy{PEJs(xq~)^u)Q@_duNV+#e&IG3PqZhOn&e_u+Z}pME`ke%g6*eKmN${_WQ# z|LxawGQWwSpx1am)=>aGGJ|n3|_xl zN6x!uEK|RLv4F*sXY~1L=gIv~KEb`WufLX`|NQ4Va?W)=CzmZgIyzc?e%g8WeQw;i zA-8Ye7LE?b=Zpm`p0=9roS>a2*Lgpa-{>* zIoJ7|v4F+zjvJyr|M`v4%Jn;Yv*qI>8|9O_VjVf>89+aPv4F+X_S5IzIO%CAjqD-& z6G!Sko+sST`F5NE^aB_RSp4n{kiR`#&R0V|xPIpXLQ9g8Us*^gQ9n`F5NE^aB_RSbV|mA?ow*JCDyG0@p9z$(HLMZWF5>pi4!|47|ef%Am>InUnSUFZie7O?ofINRv+&%L%0+%J`k zkN3*DFAmGbzo^rZbDjzG0~iZfd}wNC_4(Uwn*{Dh$iTz#^2(WXnR0Hmj+}SiGgtkB zR)_^0-rXOca%8v0`SBM{z}{bw4dDHj58sl~kKd6kAKcb6ApQDz;dAB#-2GvP?_Iu8 z06yp0ZSnj)u&0_nKkYrw3cfG$$3OnDo+Ug3 zxX$O?XYoUZ3{k$)*Qed*JLfK3xFD~+_L`hKcTUd$`T=}SUR(Slk36DrKF<-_d-@}> zv9bCN8;-o&od&_?&qGi{FzE`H1r`9)Nt<`ybwb z{C6S$L&(1a`8We^orZio=RS*H77qD{^Ea=6{9MT20r@yft{#DW*gu{D73(1%&$-Xy z3-^rFIRC)K#c~FA|HcnD%lltJ?$`J{lrPKm3^)TnfX|s1u=wfAT56oXV)OHo2fJTZ zJ53H=#94JUUTQAj-Z9Pq`T=~-ynw|IJiJun{HWJ9slCtp;;5AT zN6xuEy>_4G1TFsYjp-WqGv0p{en0I#xu13e_g3MLaL#q+7Z@X0d?dfd#+AV zyFadAy-eP`QO0h})j8LnUxEHN?6Y|OKIq%?^Bw8))9&*#AOG_||5HcKxz6{%aG%A~ zF4MPXyicE>cAwn;72X&B)mLBXoa=nfeHKsKOy8gJeo;}8+I@2WgAYEC>({UAoa=nf z7{KD0KcsKZc;Dp^`2MQ2v@|^fh~YY)bDzcUTRKYPd&c{>_pVX9Pwszn`?!34wMyq) zzYIPz2C(>~7ZG=lYOV2p)zV@5y{>MHm$#}i&4`5!|*=3KuFJH{Bm;*+K@?uUHD`&D_6kMDK07V^(S{!w5s=Xy~Z^vpWHwG&22pc=m&5;`g)P(2P{4;6Z}W6 zkMVwAoRPHqF*mo$iubEz(VN9O=X(2{h?B9;;obdxXaAR6y5Ihj`?UYLx39o2I4?`U zf7*ZABKndJ@9h87+Tiv->BtNpilXa5IO;qz((>_53r`#~*?;uE-nIXu^K-!cJQMId;u#Rk{#(4W|Cct$-EaTFecJzzjur~-|K*}Mwf`3H z?0?bpj`!^UrWkpx1ojtWZF;!o0g7gHRQqr7&i-FI2>F5bAKa(?|LAqdhyA~N81iBN zE#BGxqBO{Fu>X*cGvGos*~BVvm*1P$+CL;@9^&a{zTOM?#2Hn)n_N?8UJs%>%+VFpZnbXVTbQo zwy7chXPnP?pPZ-N=hzVcBhFy_Z}E?ANNWApL;){C~2}xy~4Y`G1S&@5AN) zX>Wt&|GDn+{}vyZ|7R@0Ga@km&pFp!{@>yQ^Z%?5WMyTkkLL3KoO7Kq0`vbCADI8| z-MhEu`WWvA=Ks0w^8XeenE$`9@oxSfc>vA-!|pTp$94Mg><_Sbm;cWm-bOY}?tsr7 zME)Il0GI#goa>Ac*dJi=f%*Rn`yn4WK>7ii|A*b@oa^K>>jW0R=x+W$I~wwnARjew z`T?5%hu!C#>x>bY|F?LT|0iD$UWnBkApHR5|7rJ`6XZJU1MCm5c$fcQoZUuNZ0aCu zw)ap!pdtT{IoBB@us^`!@8$oqB=TCG<^b>I|0{IPb;bzn53u-#{6Av*$4ig{+#RWY zKz;r{TIXD+@6Y~#Ks@V0BlebR4PXZ9`{cOR|KaO1-e*j(81|g&Gmh=SzFnUC)6B`U z{yz}!Hf0Tv^?v&LjQ1H6Og>ER@4)jd*yp`J{^x5F@7DjbG`_E||8LWHpFThH3-$H? z)w<8!Uv{4#;OhTvmM&0^*Vq3OHQuMs|LooRKcBNtz~Wu~pLtPooc5c!KF0fj^?yER z{omq))&F^(1grl?MMZh=uKv$=Hj?AaC(zfYoWS}&pOeQ{zN`PUmzNx8Y(}5L*8lmO zwE~MTfz7V3|G%mnXP%$FKI47H1ZVSObp2rRt5O*|*n^L1cenoE8-LrV0c!mpzCPo9 z#svAVK3!k`$8*;IJ@R3*wfbV9co*MXDq&D zJo-8s>i@&*>;Lfe8SgVDc%*ndxX=1OKC1^g5{Gy9|F!=QemU!awC{6|??;?pt(>?0 zf1|K3@cuCW)*AZ%a0Y1qA9@5wR+lR0nePwm|6`w^#cTgx)-vVxxAp&hANxG`8RO)E zsF|k!FGkM-=KBNt|G3ZM$u-(oa+|!R56?V5&jOB|bDht*&*Ev5>6g3yKi2qo#?sz% z4DA2oK8v^ge>_hZ=kqM!$T?;3tY)8}#gqRJJn(>W``h~exXPpF(FcS$pJxH%ecS(M@!J1~x*dCfwEyo!8shv+Jqwuc5A6Tz zihUMe-~V^_3}FA?`hm#v4^_@wW^KYsz>h3%PM(!yQ#sWMCm=g@gS-_EV zuCq^&``rCucmMzKyfi%nI&E1iFP7v9`vI5}e><3^@@CoeY$a(0x<-$He?(^U$zas1bejswXJh*VSupfXq!LYbU9XWq+;VkX_ z4VgK?gI~IIsoGom0gMIccQYr*o*j;ybDht5R#^E12M$zzlBbLXm=9q7jo+6e=UjI@ zw)lr1epq-0&<}X|<(JiVGbhNp07u$#uJbwfSv>jgz8DM8#xp0#y&O5`y4z#%`IFiU z&wy?7dPsS6e_=lWbAtPpjnCbzwxMsQd>!PYAAmW*eT9&Zk@NB#$VZ zf=SaLA0y|nV<8{hpEbZMKPkVx@C;bBt%s~D$7hG2AAmW*!hNH4Z zuCq^&`>gzjCbbYf1C~A|q3CyHKLB%rVVT`@)H(W}*eBQ`0zJu#7O5TiuHRp7{`s3f zzo7Z^3;ye$U(kGiz4`w7clrK$^WX2E_V?R-|G)YEfAjtS=KKH5TQSef*p_vw?c29Y zRaKSVcVjPVO-+r|)zxWD>&%%m^2HZl2`^Dc)LtUu9O*>2PJAf z?hF^6k!8gfBzfCK9T#KH^_i;<;Qbwy9(=p8tMJ*M>!f!?kqnF5A>)&F%j8tl4%5&# zfN?D5T<!!-+q?t%?}Yvs^S45Otf#Mo{@7>n!zV(2d@k{fDCoZw`mccg z>Ck@_^vAdubFR-^2>r3o;@fqF{(YhUFzEj(^q&F!=R*H^&>!PiyuX0!eTGB-K0)+< z3i@}1{x3lPUeJF4^dAiUhe3agJuv5b#}}dhb3ydq3;pqV&uPb@|2gP?1^VN?55=!T ze~kH6dMDt$uQTw@j;P(xzXtjrg8oOKKgPwFbA2Y>2R(js5dGtz z|8nS`3H|Z8|Kkgxe=+pm2K_OP#hmMXGN6A_5dB|;{^8Jn7WAJF{iC6OEc9Ot{W124 zf&N(UI2-z7pZ)olq-4wTj17{JQzY4WC98cAGi_R*ybE|JD=gUriA{7_DklmMlq$B5Ba2Dk5zoq-!{b7e6msF|T zj>$hE$y+Z0ayu9A86oG(_CWs{=zkFUW8{2G8T2oL{@7=K{&6#)Ke!!}1pPCi|2pW8 z^I~lw^vB5ga-0P*%b-8@S$wBn&>!3$H3j-dK>t|ip9uYvpg%^=!*LdjnhgC%1kwLl z=nrmp>kIvdLjTdwe?0V`0R1s?-Vf`1-tna%`X7Y;;CAjs=nu}9y#@X8{^#BAL4S;# zZ^3%*1?Z1`_U9i5?vvXwd!hef=zjwG4j=!nJ z&>!#pS%|$c`=CEY&cksQjLL)lnL+d?_rdLM3!pzZKQs~gr$GM|&>th`{jkpG9p`xU zUj|N-+v_&%P|j~H+b^XR2W7|ZLppNKvtZrE9lFo{{L>>7l-oQB@Yj(dO1&7{|;$t65$%&6KejxN8xX!a7 zD!0yq?=~x6?K?Rhwf?vyY&j>X+pkJ``D+-jNPN*bUFX>_Z1D~czWvZeYTwE65fM2u zK6-;pj@u~VOAB=zw{U~5^K76WVDDe2tbzXEDLKAtKlDEa{ZB&wGtmDe^sj~fSm)W0 zgLevBeE2-*5BpAzugQb{CD4B-^v8S4ig!YP_zzs?*$@>UME^n1ANHLbk6H@-@!o^f zEa<-u`e#A^mCzsSJR62h45EJ*=nwl&j*l1%{ii_x>Ck@`^v5`EGW5qf&j#+ZKYz+m z=ntNfI)PE=}sgk1YdxazY2d?vMh)r7K!4DfhN9{W~9+!mvlJpIdmQ^Sj zYm0Q`oa=l(X?C0k->vURweRHkxXE*6@{A~%HakY9&t0VBr0G$*&a;93L7@J;|DRrd zO@02d)1NBWPrUsLx%koF$hA-ZPDjppCeRNcm)-qgcmIFZ>VxX@XO>^r@3RBnXYZA- z`MtU3mj?@VIzOe-rv+ z=;%7xefB5*B>!3fr&yFhSe;E27hyEBj&&N9b0LB6q-*+VRhtD4o3;n_M z)f=GyR_KrOh$H9mY0w{j0Am4*?*yAppMU6R=nt+>p9}pLLjOh3A0y}Ea3;_XU@Tzq z=_jB+I9m1=^as~Zd({unvunLs~)T(8lUx{odjq^v%%aO^8H%cV9AD2}r32Un)ZcT-r0bJ*E<^?Q%bsqFboL^ZD z{ZB#v8_@qf=>IYFe;4}W3^;lk`r|qGS$sqs^hcbZQvm(Tq5lz{A<+LS^vBu3GoZK} z`r|qGS^U6Ppg-dL=tStB4gE`?|32t{2>S1X{x}0tv!OqpbDza`=??u7=Z_i>{bxXb za6T>(`X@vG1n7@B*ZG|LEPnNA=#MzR5;p$mXVCwr(Eqp4|L>vyZ=gTUfTN#7e>~?t zi;pOW{)qE)VB?G5fd1h8i7%o5PoO`}4xRzUH=sYBbDzZz%!dAm^P{Vve;xD(=XXNZ zp7)_Y-apGTAhizq<2mE;FNXfxpnnnc#~HwNKIcA*U%kFq zRjUcW8pF5lEMfa`qDynw|=CuC}z&)fm+{jR;W!ZYK@iHkb& z4B$GSGcREAG1TB8hq7n&*Z_ju?13o|P z{+>%emfD+tjWgg&opXIr{z=UVT6~vR5~Uw}d&c`y;q%k(C*)K~YJLsQfIT|r`e@_? zm=m=4H3iTgwwCdJ9ejS;eRBWPA4C6-pg-nZuQ~wz5d&EKyd}^dzCGjp(n{zLyHD<4 ze+&9wh5ndxecdMLj~Kz?2aSXN@a-AzXTayD-QRN%`k#XShoC>^Twjy~{ShNre3u^3 ze+cwPygzj|^oQL~SPuQuq5pE|k2%*zPk{c&30nM`v(O*DJ>&g4`24i{6>hyH&L z{W0fy)w|Fi`z(H5CG>}H&v?HSK0oa~xqtl^(En@bk2%-ZorC^}5iEYtTIjzO`Xk=Y zI05}(_xHR9{Xc{LA3%T1xxQ#G^hbH`DGXY=!=1(0?2B$DHe< zlc7Ii0E=Ix-CMxPg(m8oszODeBK1+Twj`!qx&qL{HJfv zcz;GjtlE8Ye|c(_o&od&xIO{T86!BnyT9-3f5rJPjQ#(2wf~ns{w>zOk&5#_s;>u_ z`~S}VXII@c_Ww6(|My+RyR>2dv#Z`z`|s`_JNeH3FU-ZA;k)*~oc90Hmr@S<&wK*y z|H9mpYX2?X+5eFdYa8tUV%qZ^_(EcxshyJkt7Vqr;$g$A>uKiz3`=12;VgKhXg#K9PbJ~B4clN*H4)njz{zHG* z|4ToG{;>ZQcc4G(0apLJ_CNb9^bfTE;6CmDzK@_k?0@!I=nwmE@y`A)tb+b`?SJ_l z+JET(HuOjAK>NS23i`wTTfDRXBbP(}yY_!E-cy;d75c;e&)Wd~vCikT{}%7;KXZQf z*?(|f?fgklKHXclMt-zx(a~CAI(Md!79+Rr_!8&i*f6Ztee(di#&qq2B)I zsQtHiXaC1dzGwgAg4lmPr~P+$cYi-)XF&XqIG;W{IZr>}GRAxH|EC(?yZgfqKYP`^ z_@8k;<9%|Te!zZ=4e|f3>zXI9_5AJ@NQ7V{}%r|a{n&= zXPnP?pPZ*35Q(uN{-2Yj`z$^qF#boJPtKC_wELGa-i!aCKjL_cpS|#2{LeU_@jf|E zyT2b}L;SxU`Xm0g_wjMi+?^K{%4%ec%Pi7-H(ih z{x1F>1N{;ITYLuUehu+I;(T(JoTuHt{0;PPi2tEK;(Lpqz5QPN&p4m)J~>ajzyCw% z@8bVc&>!)?#rH$q&&B_Y^BM1x^R)XLF*d~ic=tT_S^V>;`?>g^aX#aHa-McS5@SRB zkNg1lS$xp=ADpKja13KZ{C_u&xA>^V-uR!KXZ*hlql^DnA5$UK1N z|6%tv|BrRn2Xau?3%ozfKA?vDe+lxxh$YxRz&wEF|6%tz=Q?8q)(I@WA^)GgU+V)2 zMd#HI(ELB_KIg0(Fh*b>fW^1JFaMvdIY8Qb&HrO$PH;p-w#Ep||66=R{vW>mu4?Fy z93cGw&HuyhYyKbWj1gETu=s}j|7z%uSb}E+{Q%AX!|rp=b;by+6IgsVm;aB1{-_Tm ztc3pX12q2+yU#h-86&VxVDatm%l|`v^sLl2O< zKkV+`k6Tt>|Bptko;5(N|HId3yw8|mRYiUMKN|f3GtdKM@tr2u*Z)VNzRwz<*8kz_ zGu~%RFmLTqT_1`5fZpfpMTh#`uabgvroX{<5TPF z|LZqHe{fvu|M2x0?=vRYxwpRlzaI7fw6#I>pI%@8k4CMYH9)QZ!`ElL&zNAI&)Fy7(Z8m?{=XjaJ2|fPfB5>0_ZbuHyj%ZYkN$wP<3aS_RA2v( zMy;MTK&}77*Jr%Xm|)eZ`uczLKIo77zm?x=g4@UF~KUt?ppsxf53dy|1G|u{y+C#{eMYvj>h|p z37B8d`ahntPr%~utN$au*ZMzvea8Fr`CozE53K(?yu1Hj-~V?`dwXc#3l6?5n`__G zvw(eof&G7p#pmw3Kg>EnegEHX?d_@W|2r+qwqDS)fcgHw{=W&yyFK{&{=fCw161Gt zS1FTM?o-a&{=Y6$*L(2w{eRKQ?S}rpscCu^Fy0UB|7$le+Jmp}|AYSM?WynogZ^dE zA7_E>|4YmWqQCb4L4Wl2X#Za-^v{I;I16n5--KB~^zVxPw?5Dx+^+BcgZ>fFADp-S zf81y9e?P+hzvrMoxJ~=6{eMHCKh6T%|Hpk6AEW($&>!5c@Bf4T*P%bo0^9$Wh}yix zYyaP7=nrnwPA{o}{zsrc&H~2!tod=B&nIA?#kXVsUlR0350Li%;XIkV75anow*Qa& zEdCMg|AYSEHtoCi|HVOnoCUW3uU)uTf7k!V9w6=i+q_c>wg&J2W1pav&;GxeQOlIu z_5FYAG|ngInePwm|KmQ3zt{g4*`)qIi)a7ei@k;3$I&~CGZ zXTX#F@eY6?vBG`;<^;Qw~j+}?jgZ}6fH#31*#v{unt=sfGUN6XZUNACLw8(E~hwBlJgpj{N|v3G(}L zv^O^9j&D75bwefH}dzs0(o9yjvRdPlEn&LG*tG`r{0EatidH z0sV0fFelh`9`wh^IoF>EhyK`S<jE4(=Q{la?z8yz zUHYQ0b0Ge|hoZ-Gq%a@AoM7J}<8|bm>+};kVV}b{-=A;3Ki_ ] will try to center the button. -json // Element -NuiSpacer(); +json NuiSpacer(); // Create a label field. Labels are single-line stylable non-editable text fields. -json // Element -NuiLabel( - json jValue, // Bind:String - json jHAlign, // Bind:Int:NUI_HALIGN_* - json jVAlign // Bind:Int:NUI_VALIGN_* -); +// - jValue: Bind:String +// - jHAlign: Bind:Int:NUI_HALIGN_* +// - jVAlign: Bind:Int:NUI_VALIGN_* +json NuiLabel(json jValue, json jHAlign, json jVAlign); // Create a non-editable text field. Note: This text field internally implies a NuiGroup wrapped // around it, which is providing the optional border and scrollbars. -json // Element -NuiText( - json jValue, // Bind:String - int bBorder = TRUE, // Bool - int nScroll = NUI_SCROLLBARS_AUTO // Int:NUI_SCROLLBARS_* -); +// - jValue: Bind:String +// - bBorder: Bool +// - nScroll: Int:NUI_SCROLLBARS_* +json NuiText(json jValue, int bBorder = TRUE, int nScroll = NUI_SCROLLBARS_AUTO); // A clickable button with text as the label. // Sends "click" events on click. -json // Element -NuiButton( - json jLabel // Bind:String -); +// - jLabel: Bind:String +json NuiButton(json jLabel); // A clickable button with an image as the label. // Sends "click" events on click. -json // Element -NuiButtonImage( - json jResRef // Bind:ResRef -); +// - jResRef: Bind:String +json NuiButtonImage(json jResRef); // A clickable button with text as the label. // Same as the normal button, but this one is a toggle. // Sends "click" events on click. -json // Element -NuiButtonSelect( - json jLabel, // Bind:String - json jValue // Bind:Bool -); +// - jLabel: Bind:String +// - jValue: Bind:Bool +json NuiButtonSelect(json jLabel, json jValue); // A checkbox with a label to the right of it. -json // Element -NuiCheck( - json jLabel, // Bind:String - json jBool // Bind:Bool -); +// - jLabel: Bind:String +// - jBool: Bind:Bool +json NuiCheck(json jLabel, json jBool); // A image, with no border or padding. -json // Element -NuiImage( - json jResRef, // Bind:ResRef - json jAspect, // Bind:Int:NUI_ASPECT_* - json jHAlign, // Bind:Int:NUI_HALIGN_* - json jVAlign // Bind:Int:NUI_VALIGN_* -); +// - jResRef: Bind:String +// - jAspect: Bind:Int:NUI_ASPECT_* +// - jHAlign: Bind:Int:NUI_HALIGN_* +// - jVAlign: Bind:Int:NUI_VALIGN_* +json NuiImage(json jResRef, json jAspect, json jHAlign, json jVAlign); -// Optionally render only subregion of jImage. +// Optionally render only subregion of jImage. This property can be set on +// NuiImage and NuiButtonImage widgets. // jRegion is a NuiRect (x, y, w, h) to indicate the render region inside the image. -json // NuiImage -NuiImageRegion( - json jImage, // NuiImage - json jRegion // Bind:NuiRect -); +json NuiImageRegion(json jImage, json jRegion); // A combobox/dropdown. -json // Element -NuiCombo( - json jElements, // Bind:ComboEntry[] - json jSelected // Bind:Int (index into jElements) -); +// - jElements: Bind:ComboEntry[] +// - jSelected: Bind:Int (index into jElements) +json NuiCombo(json jElements, json jSelected); -json // ComboEntry -NuiComboEntry( - string sLabel, - int nValue -); +json NuiComboEntry(string sLabel, int nValue); // A floating-point slider. A good step size for normal-sized sliders is 0.01. -json // Element -NuiSliderFloat( - json jValue, // Bind:Float - json jMin, // Bind:Float - json jMax, // Bind:Float - json jStepSize // Bind:Float -); +// - jValue: Bind:Float +// - jMin: Bind:Float +// - jMax: Bind:Float +// - jStepSize: Bind:Float +json NuiSliderFloat(json jValue, json jMin, json jMax, json jStepSize); // A integer/discrete slider. -json // Element -NuiSlider( - json jValue, // Bind:Int - json jMin, // Bind:Int - json jMax, // Bind:Int - json jStepSize // Bind:Int -); +// - jValue: Bind:Int +// - jMin: Bind:Int +// - jMax: Bind:Int +// - jStepSize: Bind:Int +json NuiSlider(json jValue, json jMin, json jMax, json jStepSize); // A progress bar. Progress is always from 0.0 to 1.0. -json // Element -NuiProgress( - json jValue // Bind:Float (0.0->1.0) -); +// - jValue: Bind:Float (0.0->1.0 +json NuiProgress(json jValue); // A editable text field. -json // Element -NuiTextEdit( - json jPlaceholder, // Bind:String - json jValue, // Bind:String - int nMaxLength, // UInt >= 1, <= 65535 - int bMultiline, // Bool - int bWordWrap = TRUE // Bool -); +// - jPlaceholder: Bind:String +// - jValue: Bind:String +// - nMaxLength: UInt >= 1, <= 65535 +// - bMultiLine: Bool +// - bWordWrap: Bool +json NuiTextEdit(json jPlaceholder, json jValue, int nMaxLength, int bMultiline, int bWordWrap = TRUE); // Creates a list view of elements. // jTemplate needs to be an array of NuiListTemplateCell instances. @@ -339,67 +309,52 @@ NuiTextEdit( // e.g. when rendering a NuiLabel(), the bound label String should be an array of strings. // You can pass in one of the template jRowCount into jSize as a convenience. The array // size will be uses as the Int bind. -// jRowHeight defines the height of the rendered rows. -json // Element -NuiList( - json jTemplate, // NuiListTemplateCell[] (max: 16) - json jRowCount, // Bind:Int - float fRowHeight = NUI_STYLE_ROW_HEIGHT, - int bBorder = TRUE, - int nScroll = NUI_SCROLLBARS_Y // Note: Cannot be AUTO. -); +// fRowHeight defines the height of the rendered rows. +// - jTemplate: NuiListTemplateCell[] (max: 16) +// - jRowCount: Bind:Int +// - bBorder: Bool +// - nScroll: Int:NUI_SCROLLBARS_*, Note: Cannot be AUTO +json NuiList(json jTemplate, json jRowCount, float fRowHeight = NUI_STYLE_ROW_HEIGHT, int bBorder = TRUE, int nScroll = NUI_SCROLLBARS_Y); -json // NuiListTemplateCell -NuiListTemplateCell( - json jElem, // Element - float fWidth, // Float:0 = auto, >1 = pixel width - int bVariable // Bool:Cell can grow if space is available; otherwise static -); +// - jElem: Element +// - fWidth: Float:0 = auto, >1 = pixel width +// - bVariable: Bool:Cell can grow if space is available; otherwise static +json NuiListTemplateCell(json jElem, float fWidth, int bVariable); // A simple color picker, with no border or spacing. -json // Element -NuiColorPicker( - json jColor // Bind:Color -); +// - jColor: Bind:Color +json NuiColorPicker(json jColor); // A list of options (radio buttons). Only one can be selected // at a time. jValue is updated every time a different element is // selected. The special value -1 means "nothing". -json // Element -NuiOptions( - int nDirection, // NUI_DIRECTION_* - json jElements, // JsonArray of string labels - json jValue // Bind:Int -); +// - nDirection: NUI_DIRECTION_* +// - jElements: JsonArray of string labels +// - jValue: Bind:UInt +json NuiOptions(int nDirection, json jElements, json jValue); -// A group of buttons. Only one can be selected at a time. jValue -// is updated every time a different button is selected. The special +// A group of buttons. Only one can be selected at a time. jValue +// is updated every time a different button is selected. The special // value -1 means "nothing". -json // Element -NuiToggles( - int nDirection, // NUI_DIRECTION_* - json jElements, // JsonArray of string labels - json jValue // Bind:Int -); +// - nDirection: NUI_DIRECTION_* +// - jElements: JsonArray of string labels +// - jValue: Bind:Int +json NuiToggles(int nDirection, json jElements, json jValue); const int NUI_CHART_TYPE_LINES = 0; const int NUI_CHART_TYPE_COLUMN = 1; -json // NuiChartSlot -NuiChartSlot( - int nType, // Int:NUI_CHART_TYPE_* - json jLegend, // Bind:String - json jColor, // Bind:NuiColor - json jData // Bind:Float[] -); +// - nType: Int:NUI_CHART_TYPE_* +// - jLegend: Bind:String +// - jColor: Bind:NuiColor +// - jData: Bind:Float[] +json NuiChartSlot(int nType, json jLegend, json jColor, json jData); // Renders a chart. // Currently, min and max values are determined automatically and // cannot be influenced. -json // Element -NuiChart( - json jSlots // NuiChartSlot[] -); +// - jSlots: NuiChartSlot[] +json NuiChart( json jSlots); // ----------------------- // Draw Lists @@ -417,6 +372,7 @@ const int NUI_DRAW_LIST_ITEM_TYPE_ARC = 3; const int NUI_DRAW_LIST_ITEM_TYPE_TEXT = 4; const int NUI_DRAW_LIST_ITEM_TYPE_IMAGE = 5; const int NUI_DRAW_LIST_ITEM_TYPE_LINE = 6; +const int NUI_DRAW_LIST_ITEM_TYPE_RECT = 7; // You can order draw list items to be painted either before, or after the // builtin render of the widget in question. This enables you to paint "behind" @@ -438,100 +394,100 @@ const int NUI_DRAW_LIST_ITEM_RENDER_MOUSE_RIGHT = 4; // Only render while MMB is held down. const int NUI_DRAW_LIST_ITEM_RENDER_MOUSE_MIDDLE = 5; -json // DrawListItem -NuiDrawListPolyLine( - json jEnabled, // Bind:Bool - json jColor, // Bind:Color - json jFill, // Bind:Bool - json jLineThickness, // Bind:Float - json jPoints, // Bind:Float[] Always provide points in pairs - int nOrder = NUI_DRAW_LIST_ITEM_ORDER_AFTER, // Int:NUI_DRAW_LIST_ITEM_ORDER_* - int nRender = NUI_DRAW_LIST_ITEM_RENDER_ALWAYS // Int:NUI_DRAW_LIST_ITEM_RENDER_* -); +// - jEnabled: Bind:Bool +// - jColor: Bind:Color +// - jFill: Bind:Bool +// - jLineThickness: Bind:Float +// - jPoints: Bind:Float[] Always provide points in pairs +// - nOrder: Int:NUI_DRAW_LIST_ITEM_ORDER_* +// - nRender: Int:NUI_DRAW_LIST_ITEM_RENDER_* +// - nBindArrays: Values in binds are considered arrays-of-values +json NuiDrawListPolyLine(json jEnabled, json jColor, json jFill, json jLineThickness, json jPoints, int nOrder = NUI_DRAW_LIST_ITEM_ORDER_AFTER, int nRender = NUI_DRAW_LIST_ITEM_RENDER_ALWAYS, int nBindArrays = FALSE); -json // DrawListItem -NuiDrawListCurve( - json jEnabled, // Bind:Bool - json jColor, // Bind:Color - json jLineThickness, // Bind:Float - json jA, // Bind:Vec2 - json jB, // Bind:Vec2 - json jCtrl0, // Bind:Vec2 - json jCtrl1, // Bind:Vec2 - int nOrder = NUI_DRAW_LIST_ITEM_ORDER_AFTER, // Int:NUI_DRAW_LIST_ITEM_ORDER_* - int nRender = NUI_DRAW_LIST_ITEM_RENDER_ALWAYS // Int:NUI_DRAW_LIST_ITEM_RENDER_* -); +// - jEnabled: Bind:Bool +// - jColor: Bind:Color +// - jLineThickness: Bind:Float +// - jA: Bind:Vec2 +// - jB: Bind:Vec2 +// - jCtrl0: Bind:Vec2 +// - jCtrl1: Bind:Vec2 +// - nOrder: Int:NUI_DRAW_LIST_ITEM_ORDER_* +// - nRender: Int:NUI_DRAW_LIST_ITEM_RENDER_* +// - nBindArrays: Values in binds are considered arrays-of-values +json NuiDrawListCurve(json jEnabled, json jColor, json jLineThickness, json jA, json jB, json jCtrl0, json jCtrl1, int nOrder = NUI_DRAW_LIST_ITEM_ORDER_AFTER, int nRender = NUI_DRAW_LIST_ITEM_RENDER_ALWAYS, int nBindArrays = FALSE); -json // DrawListItem -NuiDrawListCircle( - json jEnabled, // Bind:Bool - json jColor, // Bind:Color - json jFill, // Bind:Bool - json jLineThickness, // Bind:Float - json jRect, // Bind:Rect - int nOrder = NUI_DRAW_LIST_ITEM_ORDER_AFTER, // Int:NUI_DRAW_LIST_ITEM_ORDER_* - int nRender = NUI_DRAW_LIST_ITEM_RENDER_ALWAYS // Int:NUI_DRAW_LIST_ITEM_RENDER_* -); +// - jEnabled: Bind:Bool +// - jColor: Bind:Color +// - jFill: Bind:Bool +// - jLineThickness: Bind:Float +// - jRect: Bind:Rect +// - nOrder: Int:NUI_DRAW_LIST_ITEM_ORDER_* +// - nRender: Int:NUI_DRAW_LIST_ITEM_RENDER_* +// - nBindArrays: Values in binds are considered arrays-of-values +json NuiDrawListCircle(json jEnabled, json jColor, json jFill, json jLineThickness, json jRect, int nOrder = NUI_DRAW_LIST_ITEM_ORDER_AFTER, int nRender = NUI_DRAW_LIST_ITEM_RENDER_ALWAYS, int nBindArrays = FALSE); -json // DrawListItem -NuiDrawListArc( - json jEnabled, // Bind:Bool - json jColor, // Bind:Color - json jFill, // Bind:Bool - json jLineThickness, // Bind:Float - json jCenter, // Bind:Vec2 - json jRadius, // Bind:Float - json jAMin, // Bind:Float - json jAMax, // Bind:Float - int nOrder = NUI_DRAW_LIST_ITEM_ORDER_AFTER, // Int:NUI_DRAW_LIST_ITEM_ORDER_* - int nRender = NUI_DRAW_LIST_ITEM_RENDER_ALWAYS // Int:NUI_DRAW_LIST_ITEM_RENDER_* -); +// - jEnabled: Bind:Bool +// - jColor: Bind:Color +// - jFill: Bind:Bool +// - jLineThickness: Bind:Float +// - jCenter: Bind:Rect +// - jRadius: Bind:Float +// - jAMin: Bind:Float +// - jAMax: Bind:Float +// - nOrder: Int:NUI_DRAW_LIST_ITEM_ORDER_* +// - nRender: Int:NUI_DRAW_LIST_ITEM_RENDER_* +// - nBindArrays: Values in binds are considered arrays-of-values +json NuiDrawListArc(json jEnabled, json jColor, json jFill, json jLineThickness, json jCenter, json jRadius, json jAMin, json jAMax, int nOrder = NUI_DRAW_LIST_ITEM_ORDER_AFTER, int nRender = NUI_DRAW_LIST_ITEM_RENDER_ALWAYS, int nBindArrays = FALSE); -json // DrawListItem -NuiDrawListText( - json jEnabled, // Bind:Bool - json jColor, // Bind:Color - json jRect, // Bind:Rect - json jText, // Bind:String - int nOrder = NUI_DRAW_LIST_ITEM_ORDER_AFTER, // Int:NUI_DRAW_LIST_ITEM_ORDER_* - int nRender = NUI_DRAW_LIST_ITEM_RENDER_ALWAYS // Int:NUI_DRAW_LIST_ITEM_RENDER_* -); +// - jEnabled: Bind:Bool +// - jColor: Bind:Color +// - jRect: Bind:Rect +// - jText: Bind:String +// - nOrder: Int:NUI_DRAW_LIST_ITEM_ORDER_* +// - nRender: Int:NUI_DRAW_LIST_ITEM_RENDER_* +// - nBindArrays: Values in binds are considered arrays-of-values +// - jFont: Bind:String +json NuiDrawListText(json jEnabled, json jColor, json jRect, json jText, int nOrder = NUI_DRAW_LIST_ITEM_ORDER_AFTER, int nRender = NUI_DRAW_LIST_ITEM_RENDER_ALWAYS, int nBindArrays = FALSE, json jFont = JSON_STRING); -json // DrawListItem -NuiDrawListImage( - json jEnabled, // Bind:Bool - json jResRef, // Bind:ResRef - json jPos, // Bind:Rect - json jAspect, // Bind:Int:NUI_ASPECT_* - json jHAlign, // Bind:Int:NUI_HALIGN_* - json jVAlign, // Bind:Int:NUI_VALIGN_* - int nOrder = NUI_DRAW_LIST_ITEM_ORDER_AFTER, // Int:NUI_DRAW_LIST_ITEM_ORDER_* - int nRender = NUI_DRAW_LIST_ITEM_RENDER_ALWAYS // Int:NUI_DRAW_LIST_ITEM_RENDER_* -); +// - jEnabled: Bind:Bool +// - jResRef: Bind:String +// - jPos: Bind:Rect +// - jAspect: Bind:Int:NUI_ASPECT_* +// - jHAlign: Bind:Int:NUI_HALIGN_* +// - jVAlign: Bind:Int:NUI_VALIGN_* +// - nOrder: Int:NUI_DRAW_LIST_ITEM_ORDER_* +// - nRender: Int:NUI_DRAW_LIST_ITEM_RENDER_* +// - nBindArrays: Values in binds are considered arrays-of-values +json NuiDrawListImage(json jEnabled, json jResRef, json jPos, json jAspect, json jHAlign, json jVAlign, int nOrder = NUI_DRAW_LIST_ITEM_ORDER_AFTER, int nRender = NUI_DRAW_LIST_ITEM_RENDER_ALWAYS, int nBindArrays = FALSE); -json // DrawListItemImage -NuiDrawListImageRegion( - json jDrawListImage, // DrawListItemImage - json jRegion // Bind:NuiRect -); +// - jDrawListImage: DrawListItemImage +// - jRegion: Bind:NuiRect +json NuiDrawListImageRegion(json jDrawListImage, json jRegion); -json // DrawListItem -NuiDrawListLine( - json jEnabled, // Bind:Bool - json jColor, // Bind:Color - json jLineThickness, // Bind:Float - json jA, // Bind:Vec2 - json jB, // Bind:Vec2 - int nOrder = NUI_DRAW_LIST_ITEM_ORDER_AFTER, // Int:NUI_DRAW_LIST_ITEM_ORDER_* - int nRender = NUI_DRAW_LIST_ITEM_RENDER_ALWAYS // Int:NUI_DRAW_LIST_ITEM_RENDER_* -); +// - jEnabled: Bind:Bool +// - jColor: Bind:Color +// - jLineThickness: Bind:Float +// - jA: Bind:Vec2 +// - jB: Bind:Vec2 +// - nOrder: Int:NUI_DRAW_LIST_ITEM_ORDER_* +// - nRender: Int:NUI_DRAW_LIST_ITEM_RENDER_* +// - nBindArrays: Values in binds are considered arrays-of-values +json NuiDrawListLine(json jEnabled, json jColor, json jLineThickness, json jA, json jB, int nOrder = NUI_DRAW_LIST_ITEM_ORDER_AFTER, int nRender = NUI_DRAW_LIST_ITEM_RENDER_ALWAYS, int nBindArrays = FALSE); -json // Element -NuiDrawList( - json jElem, // Element - json jScissor, // Bind:Bool Constrain painted elements to widget bounds. - json jList // DrawListItem[] -); +// - jEnabled: Bind:Bool +// - jColor: Bind:Color +// - jFill: Bind:Bool +// - jLineThickness: Bind:Float +// - jRext: Bind:Rect +// - nOrder: Int:NUI_DRAW_LIST_ITEM_ORDER_* +// - nRender: Int:NUI_DRAW_LIST_ITEM_RENDER_* +// - nBindArrays: Values in binds are considered arrays-of-values +json NuiDrawListRect(json jEnabled, json jColor, json jFill, json jLineThickness, json jRect, int nOrder = NUI_DRAW_LIST_ITEM_ORDER_AFTER, int nRender = NUI_DRAW_LIST_ITEM_RENDER_ALWAYS, int nBindArrays = FALSE); + +// - jElem: Element +// - jScissor: Bind:Bool, Constrain painted elements to widget bounds. +// - jList: DrawListItem[] +json NuiDrawList(json jElem, json jScissor, json jList); // ----------------------- // Implementation @@ -546,21 +502,27 @@ NuiWindow( json jClosable, json jTransparent, json jBorder, - json jAcceptsInput + json jAcceptsInput = JSON_TRUE, + json jWindowConstraint = JSON_NULL, + json jEdgeConstraint = JSON_NULL, + json jFont = JSON_STRING ) { json ret = JsonObject(); // Currently hardcoded and here to catch backwards-incompatible data in the future. - ret = JsonObjectSet(ret, "version", JsonInt(1)); - ret = JsonObjectSet(ret, "title", jTitle); - ret = JsonObjectSet(ret, "root", jRoot); - ret = JsonObjectSet(ret, "geometry", jGeometry); - ret = JsonObjectSet(ret, "resizable", jResizable); - ret = JsonObjectSet(ret, "collapsed", jCollapsed); - ret = JsonObjectSet(ret, "closable", jClosable); - ret = JsonObjectSet(ret, "transparent", jTransparent); - ret = JsonObjectSet(ret, "border", jBorder); - ret = JsonObjectSet(ret, "accepts_input", jAcceptsInput); + JsonObjectSetInplace(ret, "version", JsonInt(1)); + JsonObjectSetInplace(ret, "title", jTitle); + JsonObjectSetInplace(ret, "root", jRoot); + JsonObjectSetInplace(ret, "geometry", jGeometry); + JsonObjectSetInplace(ret, "resizable", jResizable); + JsonObjectSetInplace(ret, "collapsed", jCollapsed); + JsonObjectSetInplace(ret, "closable", jClosable); + JsonObjectSetInplace(ret, "transparent", jTransparent); + JsonObjectSetInplace(ret, "border", jBorder); + JsonObjectSetInplace(ret, "accepts_input", jAcceptsInput); + JsonObjectSetInplace(ret, "size_constraint", jWindowConstraint); + JsonObjectSetInplace(ret, "edge_constraint", jEdgeConstraint); + JsonObjectSetInplace(ret, "font", jFont); return ret; } @@ -572,18 +534,26 @@ NuiElement( ) { json ret = JsonObject(); - ret = JsonObjectSet(ret, "type", JsonString(sType)); - ret = JsonObjectSet(ret, "label", jLabel); - ret = JsonObjectSet(ret, "value", jValue); + JsonObjectSetInplace(ret, "type", JsonString(sType)); + JsonObjectSetInplace(ret, "label", jLabel); + JsonObjectSetInplace(ret, "value", jValue); return ret; } json NuiBind( - string sId + string sId, + int nNumberFlags = 0, + int nNumberPrecision = 0, + int nTextFlags = 0 ) { - return JsonObjectSet(JsonObject(), "bind", JsonString(sId)); + json ret = JsonObject(); + JsonObjectSetInplace(ret, "bind", JsonString(sId)); + JsonObjectSetInplace(ret, "number_flags", JsonInt(nNumberFlags)); + JsonObjectSetInplace(ret, "number_precision", JsonInt(nNumberPrecision)); + JsonObjectSetInplace(ret, "text_flags", JsonInt(nTextFlags)); + return ret; } json @@ -601,7 +571,7 @@ NuiStrRef( ) { json ret = JsonObject(); - ret = JsonObjectSet(ret, "strref", JsonInt(nStrRef)); + JsonObjectSetInplace(ret, "strref", JsonInt(nStrRef)); return ret; } @@ -629,9 +599,9 @@ NuiGroup( ) { json ret = NuiElement("group", JsonNull(), JsonNull()); - ret = JsonObjectSet(ret, "children", JsonArrayInsert(JsonArray(), jChild)); - ret = JsonObjectSet(ret, "border", JsonBool(bBorder)); - ret = JsonObjectSet(ret, "scrollbars", JsonInt(nScroll)); + JsonObjectSetInplace(ret, "children", JsonArrayInsert(JsonArray(), jChild)); + JsonObjectSetInplace(ret, "border", JsonBool(bBorder)); + JsonObjectSetInplace(ret, "scrollbars", JsonInt(nScroll)); return ret; } @@ -720,8 +690,8 @@ json NuiVec(float x, float y) { json ret = JsonObject(); - ret = JsonObjectSet(ret, "x", JsonFloat(x)); - ret = JsonObjectSet(ret, "y", JsonFloat(y)); + JsonObjectSetInplace(ret, "x", JsonFloat(x)); + JsonObjectSetInplace(ret, "y", JsonFloat(y)); return ret; } @@ -729,10 +699,10 @@ json NuiRect(float x, float y, float w, float h) { json ret = JsonObject(); - ret = JsonObjectSet(ret, "x", JsonFloat(x)); - ret = JsonObjectSet(ret, "y", JsonFloat(y)); - ret = JsonObjectSet(ret, "w", JsonFloat(w)); - ret = JsonObjectSet(ret, "h", JsonFloat(h)); + JsonObjectSetInplace(ret, "x", JsonFloat(x)); + JsonObjectSetInplace(ret, "y", JsonFloat(y)); + JsonObjectSetInplace(ret, "w", JsonFloat(w)); + JsonObjectSetInplace(ret, "h", JsonFloat(h)); return ret; } @@ -740,10 +710,10 @@ json NuiColor(int r, int g, int b, int a = 255) { json ret = JsonObject(); - ret = JsonObjectSet(ret, "r", JsonInt(r)); - ret = JsonObjectSet(ret, "g", JsonInt(g)); - ret = JsonObjectSet(ret, "b", JsonInt(b)); - ret = JsonObjectSet(ret, "a", JsonInt(a)); + JsonObjectSetInplace(ret, "r", JsonInt(r)); + JsonObjectSetInplace(ret, "g", JsonInt(g)); + JsonObjectSetInplace(ret, "b", JsonInt(b)); + JsonObjectSetInplace(ret, "a", JsonInt(a)); return ret; } @@ -756,6 +726,15 @@ NuiStyleForegroundColor( return JsonObjectSet(jElem, "foreground_color", jColor); } +json +NuiStyleFont( + json jElem, + json jFont +) +{ + return JsonObjectSet(jElem, "font", jFont); +} + json NuiSpacer() { @@ -770,8 +749,8 @@ NuiLabel( ) { json ret = NuiElement("label", JsonNull(), jValue); - ret = JsonObjectSet(ret, "text_halign", jHAlign); - ret = JsonObjectSet(ret, "text_valign", jVAlign); + JsonObjectSetInplace(ret, "text_halign", jHAlign); + JsonObjectSetInplace(ret, "text_valign", jVAlign); return ret; } @@ -783,8 +762,8 @@ NuiText( ) { json ret = NuiElement("text", JsonNull(), jValue); - ret = JsonObjectSet(ret, "border", JsonBool(bBorder)); - ret = JsonObjectSet(ret, "scrollbars", JsonInt(nScroll)); + JsonObjectSetInplace(ret, "border", JsonBool(bBorder)); + JsonObjectSetInplace(ret, "scrollbars", JsonInt(nScroll)); return ret; } @@ -831,9 +810,9 @@ NuiImage( ) { json img = NuiElement("image", JsonNull(), jResRef); - img = JsonObjectSet(img, "image_aspect", jAspect); - img = JsonObjectSet(img, "image_halign", jHAlign); - img = JsonObjectSet(img, "image_valign", jVAlign); + JsonObjectSetInplace(img, "image_aspect", jAspect); + JsonObjectSetInplace(img, "image_halign", jHAlign); + JsonObjectSetInplace(img, "image_valign", jVAlign); return img; } @@ -873,9 +852,9 @@ NuiSliderFloat( ) { json ret = NuiElement("sliderf", JsonNull(), jValue); - ret = JsonObjectSet(ret, "min", jMin); - ret = JsonObjectSet(ret, "max", jMax); - ret = JsonObjectSet(ret, "step", jStepSize); + JsonObjectSetInplace(ret, "min", jMin); + JsonObjectSetInplace(ret, "max", jMax); + JsonObjectSetInplace(ret, "step", jStepSize); return ret; } @@ -888,9 +867,9 @@ NuiSlider( ) { json ret = NuiElement("slider", JsonNull(), jValue); - ret = JsonObjectSet(ret, "min", jMin); - ret = JsonObjectSet(ret, "max", jMax); - ret = JsonObjectSet(ret, "step", jStepSize); + JsonObjectSetInplace(ret, "min", jMin); + JsonObjectSetInplace(ret, "max", jMax); + JsonObjectSetInplace(ret, "step", jStepSize); return ret; } @@ -912,9 +891,9 @@ NuiTextEdit( ) { json ret = NuiElement("textedit", jPlaceholder, jValue); - ret = JsonObjectSet(ret, "max", JsonInt(nMaxLength)); - ret = JsonObjectSet(ret, "multiline", JsonBool(bMultiline)); - ret = JsonObjectSet(ret, "wordwrap", JsonBool(bWordWrap)); + JsonObjectSetInplace(ret, "max", JsonInt(nMaxLength)); + JsonObjectSetInplace(ret, "multiline", JsonBool(bMultiline)); + JsonObjectSetInplace(ret, "wordwrap", JsonBool(bWordWrap)); return ret; } @@ -928,11 +907,11 @@ NuiList( ) { json ret = NuiElement("list", JsonNull(), JsonNull()); - ret = JsonObjectSet(ret, "row_template", jTemplate); - ret = JsonObjectSet(ret, "row_count", jRowCount); - ret = JsonObjectSet(ret, "row_height", JsonFloat(fRowHeight)); - ret = JsonObjectSet(ret, "border", JsonBool(bBorder)); - ret = JsonObjectSet(ret, "scrollbars", JsonInt(nScroll)); + JsonObjectSetInplace(ret, "row_template", jTemplate); + JsonObjectSetInplace(ret, "row_count", jRowCount); + JsonObjectSetInplace(ret, "row_height", JsonFloat(fRowHeight)); + JsonObjectSetInplace(ret, "border", JsonBool(bBorder)); + JsonObjectSetInplace(ret, "scrollbars", JsonInt(nScroll)); return ret; } @@ -944,9 +923,9 @@ NuiListTemplateCell( ) { json ret = JsonArray(); - ret = JsonArrayInsert(ret, jElem); - ret = JsonArrayInsert(ret, JsonFloat(fWidth)); - ret = JsonArrayInsert(ret, JsonBool(bVariable)); + JsonArrayInsertInplace(ret, jElem); + JsonArrayInsertInplace(ret, JsonFloat(fWidth)); + JsonArrayInsertInplace(ret, JsonBool(bVariable)); return ret; } @@ -967,8 +946,8 @@ NuiOptions( ) { json ret = NuiElement("options", JsonNull(), jValue); - ret = JsonObjectSet(ret, "direction", JsonInt(nDirection)); - ret = JsonObjectSet(ret, "elements", jElements); + JsonObjectSetInplace(ret, "direction", JsonInt(nDirection)); + JsonObjectSetInplace(ret, "elements", jElements); return ret; } @@ -980,8 +959,8 @@ NuiToggles( ) { json ret = NuiElement("tabbar", JsonNull(), jValue); - ret = JsonObjectSet(ret, "direction", JsonInt(nDirection)); - ret = JsonObjectSet(ret, "elements", jElements); + JsonObjectSetInplace(ret, "direction", JsonInt(nDirection)); + JsonObjectSetInplace(ret, "elements", jElements); return ret; } @@ -994,10 +973,10 @@ NuiChartSlot( ) { json ret = JsonObject(); - ret = JsonObjectSet(ret, "type", JsonInt(nType)); - ret = JsonObjectSet(ret, "legend", jLegend); - ret = JsonObjectSet(ret, "color", jColor); - ret = JsonObjectSet(ret, "data", jData); + JsonObjectSetInplace(ret, "type", JsonInt(nType)); + JsonObjectSetInplace(ret, "legend", jLegend); + JsonObjectSetInplace(ret, "color", jColor); + JsonObjectSetInplace(ret, "data", jData); return ret; } @@ -1018,17 +997,19 @@ NuiDrawListItem( json jFill, json jLineThickness, int nOrder = NUI_DRAW_LIST_ITEM_ORDER_AFTER, - int nRender = NUI_DRAW_LIST_ITEM_RENDER_ALWAYS + int nRender = NUI_DRAW_LIST_ITEM_RENDER_ALWAYS, + int nBindArrays = FALSE ) { json ret = JsonObject(); - ret = JsonObjectSet(ret, "type", JsonInt(nType)); - ret = JsonObjectSet(ret, "enabled", jEnabled); - ret = JsonObjectSet(ret, "color", jColor); - ret = JsonObjectSet(ret, "fill", jFill); - ret = JsonObjectSet(ret, "line_thickness", jLineThickness); - ret = JsonObjectSet(ret, "order", JsonInt(nOrder)); - ret = JsonObjectSet(ret, "render", JsonInt(nRender)); + JsonObjectSetInplace(ret, "type", JsonInt(nType)); + JsonObjectSetInplace(ret, "enabled", jEnabled); + JsonObjectSetInplace(ret, "color", jColor); + JsonObjectSetInplace(ret, "fill", jFill); + JsonObjectSetInplace(ret, "line_thickness", jLineThickness); + JsonObjectSetInplace(ret, "order", JsonInt(nOrder)); + JsonObjectSetInplace(ret, "render", JsonInt(nRender)); + JsonObjectSetInplace(ret, "arrayBinds", JsonBool(nBindArrays)); return ret; } @@ -1040,11 +1021,12 @@ NuiDrawListPolyLine( json jLineThickness, json jPoints, int nOrder = NUI_DRAW_LIST_ITEM_ORDER_AFTER, - int nRender = NUI_DRAW_LIST_ITEM_RENDER_ALWAYS + int nRender = NUI_DRAW_LIST_ITEM_RENDER_ALWAYS, + int nBindArrays = FALSE ) { - json ret = NuiDrawListItem(NUI_DRAW_LIST_ITEM_TYPE_POLYLINE, jEnabled, jColor, jFill, jLineThickness, nOrder, nRender); - ret = JsonObjectSet(ret, "points", jPoints); + json ret = NuiDrawListItem(NUI_DRAW_LIST_ITEM_TYPE_POLYLINE, jEnabled, jColor, jFill, jLineThickness, nOrder, nRender, nBindArrays); + JsonObjectSetInplace(ret, "points", jPoints); return ret; } @@ -1058,14 +1040,15 @@ NuiDrawListCurve( json jCtrl0, json jCtrl1, int nOrder = NUI_DRAW_LIST_ITEM_ORDER_AFTER, - int nRender = NUI_DRAW_LIST_ITEM_RENDER_ALWAYS + int nRender = NUI_DRAW_LIST_ITEM_RENDER_ALWAYS, + int nBindArrays = FALSE ) { - json ret = NuiDrawListItem(NUI_DRAW_LIST_ITEM_TYPE_CURVE, jEnabled, jColor, JsonBool(0), jLineThickness, nOrder, nRender); - ret = JsonObjectSet(ret, "a", jA); - ret = JsonObjectSet(ret, "b", jB); - ret = JsonObjectSet(ret, "ctrl0", jCtrl0); - ret = JsonObjectSet(ret, "ctrl1", jCtrl1); + json ret = NuiDrawListItem(NUI_DRAW_LIST_ITEM_TYPE_CURVE, jEnabled, jColor, JsonBool(0), jLineThickness, nOrder, nRender, nBindArrays); + JsonObjectSetInplace(ret, "a", jA); + JsonObjectSetInplace(ret, "b", jB); + JsonObjectSetInplace(ret, "ctrl0", jCtrl0); + JsonObjectSetInplace(ret, "ctrl1", jCtrl1); return ret; } @@ -1077,11 +1060,12 @@ NuiDrawListCircle( json jLineThickness, json jRect, int nOrder = NUI_DRAW_LIST_ITEM_ORDER_AFTER, - int nRender = NUI_DRAW_LIST_ITEM_RENDER_ALWAYS + int nRender = NUI_DRAW_LIST_ITEM_RENDER_ALWAYS, + int nBindArrays = FALSE ) { - json ret = NuiDrawListItem(NUI_DRAW_LIST_ITEM_TYPE_CIRCLE, jEnabled, jColor, jFill, jLineThickness, nOrder, nRender); - ret = JsonObjectSet(ret, "rect", jRect); + json ret = NuiDrawListItem(NUI_DRAW_LIST_ITEM_TYPE_CIRCLE, jEnabled, jColor, jFill, jLineThickness, nOrder, nRender, nBindArrays); + JsonObjectSetInplace(ret, "rect", jRect); return ret; } @@ -1096,14 +1080,15 @@ NuiDrawListArc( json jAMin, json jAMax, int nOrder = NUI_DRAW_LIST_ITEM_ORDER_AFTER, - int nRender = NUI_DRAW_LIST_ITEM_RENDER_ALWAYS + int nRender = NUI_DRAW_LIST_ITEM_RENDER_ALWAYS, + int nBindArrays = FALSE ) { - json ret = NuiDrawListItem(NUI_DRAW_LIST_ITEM_TYPE_ARC, jEnabled, jColor, jFill, jLineThickness, nOrder, nRender); - ret = JsonObjectSet(ret, "c", jCenter); - ret = JsonObjectSet(ret, "radius", jRadius); - ret = JsonObjectSet(ret, "amin", jAMin); - ret = JsonObjectSet(ret, "amax", jAMax); + json ret = NuiDrawListItem(NUI_DRAW_LIST_ITEM_TYPE_ARC, jEnabled, jColor, jFill, jLineThickness, nOrder, nRender, nBindArrays); + JsonObjectSetInplace(ret, "c", jCenter); + JsonObjectSetInplace(ret, "radius", jRadius); + JsonObjectSetInplace(ret, "amin", jAMin); + JsonObjectSetInplace(ret, "amax", jAMax); return ret; } @@ -1114,12 +1099,15 @@ NuiDrawListText( json jRect, json jText, int nOrder = NUI_DRAW_LIST_ITEM_ORDER_AFTER, - int nRender = NUI_DRAW_LIST_ITEM_RENDER_ALWAYS + int nRender = NUI_DRAW_LIST_ITEM_RENDER_ALWAYS, + int nBindArrays = FALSE, + json jFont = JSON_STRING ) { - json ret = NuiDrawListItem(NUI_DRAW_LIST_ITEM_TYPE_TEXT, jEnabled, jColor, JsonNull(), JsonNull(), nOrder, nRender); - ret = JsonObjectSet(ret, "rect", jRect); - ret = JsonObjectSet(ret, "text", jText); + json ret = NuiDrawListItem(NUI_DRAW_LIST_ITEM_TYPE_TEXT, jEnabled, jColor, JsonNull(), JsonNull(), nOrder, nRender, nBindArrays); + JsonObjectSetInplace(ret, "rect", jRect); + JsonObjectSetInplace(ret, "text", jText); + ret = NuiStyleFont(ret, jFont); return ret; } @@ -1132,15 +1120,16 @@ NuiDrawListImage( json jHAlign, json jVAlign, int nOrder = NUI_DRAW_LIST_ITEM_ORDER_AFTER, - int nRender = NUI_DRAW_LIST_ITEM_RENDER_ALWAYS + int nRender = NUI_DRAW_LIST_ITEM_RENDER_ALWAYS, + int nBindArrays = FALSE ) { - json ret = NuiDrawListItem(NUI_DRAW_LIST_ITEM_TYPE_IMAGE, jEnabled, JsonNull(), JsonNull(), JsonNull(), nOrder, nRender); - ret = JsonObjectSet(ret, "image", jResRef); - ret = JsonObjectSet(ret, "rect", jRect); - ret = JsonObjectSet(ret, "image_aspect", jAspect); - ret = JsonObjectSet(ret, "image_halign", jHAlign); - ret = JsonObjectSet(ret, "image_valign", jVAlign); + json ret = NuiDrawListItem(NUI_DRAW_LIST_ITEM_TYPE_IMAGE, jEnabled, JsonNull(), JsonNull(), JsonNull(), nOrder, nRender, nBindArrays); + JsonObjectSetInplace(ret, "image", jResRef); + JsonObjectSetInplace(ret, "rect", jRect); + JsonObjectSetInplace(ret, "image_aspect", jAspect); + JsonObjectSetInplace(ret, "image_halign", jHAlign); + JsonObjectSetInplace(ret, "image_valign", jVAlign); return ret; } @@ -1161,12 +1150,30 @@ NuiDrawListLine( json jA, json jB, int nOrder = NUI_DRAW_LIST_ITEM_ORDER_AFTER, - int nRender = NUI_DRAW_LIST_ITEM_RENDER_ALWAYS + int nRender = NUI_DRAW_LIST_ITEM_RENDER_ALWAYS, + int nBindArrays = FALSE ) { - json ret = NuiDrawListItem(NUI_DRAW_LIST_ITEM_TYPE_LINE, jEnabled, jColor, JsonNull(), jLineThickness, nOrder, nRender); - ret = JsonObjectSet(ret, "a", jA); - ret = JsonObjectSet(ret, "b", jB); + json ret = NuiDrawListItem(NUI_DRAW_LIST_ITEM_TYPE_LINE, jEnabled, jColor, JsonNull(), jLineThickness, nOrder, nRender, nBindArrays); + JsonObjectSetInplace(ret, "a", jA); + JsonObjectSetInplace(ret, "b", jB); + return ret; +} + +json +NuiDrawListRect( + json jEnabled, + json jColor, + json jFill, + json jLineThickness, + json jRect, + int nOrder = NUI_DRAW_LIST_ITEM_ORDER_AFTER, + int nRender = NUI_DRAW_LIST_ITEM_RENDER_ALWAYS, + int nBindArrays = FALSE +) +{ + json ret = NuiDrawListItem(NUI_DRAW_LIST_ITEM_TYPE_RECT, jEnabled, jColor, jFill, jLineThickness, nOrder, nRender, nBindArrays); + JsonObjectSetInplace(ret, "rect", jRect); return ret; } @@ -1178,7 +1185,7 @@ NuiDrawList( ) { json ret = JsonObjectSet(jElem, "draw_list", jList); - ret = JsonObjectSet(ret, "draw_list_scissor", jScissor); + JsonObjectSetInplace(ret, "draw_list_scissor", jScissor); return ret; } @@ -1190,4 +1197,3 @@ NuiDrawList( // json ret = NuiElement("canvas", JsonNull(), jList); // return ret; // } - diff --git a/src/include/prc_inc_combat.nss b/src/include/prc_inc_combat.nss index 3cdbab5..df4a5b7 100644 --- a/src/include/prc_inc_combat.nss +++ b/src/include/prc_inc_combat.nss @@ -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 ); } diff --git a/src/include/prc_inc_skills.nss b/src/include/prc_inc_skills.nss index bbca299..0674604 100644 --- a/src/include/prc_inc_skills.nss +++ b/src/include/prc_inc_skills.nss @@ -115,11 +115,11 @@ int PerformJump(object oPC, location lLoc, int bDoKnockDown = TRUE) iBonus = 4; } } - /*if (GetHasSpellEffect(MOVE_TC_LEAPING_DRAGON, oPC)) + if (GetHasSpellEffect(MOVE_TC_LEAPING_DRAGON, oPC)) { bIsRunningJump = TRUE; - iBonus = 10; - } */ + //iBonus = 10; //:: This is granted in the stance. + } // PnP rules are height * 6 for run and height * 2 for jump. // I can't get height so that is assumed to be 6. // Changed maxed jump distance because the NwN distance is rather short @@ -374,6 +374,12 @@ int PRCIsFlying(object oCreature) if(GetRacialType(oCreature) == RACIAL_TYPE_GLOURA) bFlying = TRUE; + + if(GetRacialType(oCreature) == RACIAL_TYPE_AVARIEL) + bFlying = TRUE; + + if(GetRacialType(oCreature) == RACIAL_TYPE_FEYRI) + bFlying = TRUE; if(GetRacialType(oCreature) == RACIAL_TYPE_SPIRETOPDRAGON) bFlying = TRUE; diff --git a/src/include/prc_inc_wpnrest.nss b/src/include/prc_inc_wpnrest.nss index c101e78..9dcf65a 100644 --- a/src/include/prc_inc_wpnrest.nss +++ b/src/include/prc_inc_wpnrest.nss @@ -40,13 +40,31 @@ int IsProficient(object oPC, int nBaseItem) case BASE_ITEM_CLUB: return GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oPC) - || GetHasFeat(FEAT_WEAPON_PROFICIENCY_DRUID, oPC) - || GetHasFeat(FEAT_WEAPON_PROFICIENCY_CLUB, oPC); + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_DRUID, oPC) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_WIZARD, oPC) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_ROGUE, oPC) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_CLUB, oPC); + + case BASE_ITEM_HEAVYCROSSBOW: + return GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oPC) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_DRUID, oPC) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_WIZARD, oPC) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_ROGUE, oPC) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_HEAVY_XBOW, oPC); + + case BASE_ITEM_LIGHTCROSSBOW: + return GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oPC) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_DRUID, oPC) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_WIZARD, oPC) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_ROGUE, oPC) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_LIGHT_XBOW, oPC); case BASE_ITEM_DAGGER: return GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oPC) - || GetHasFeat(FEAT_WEAPON_PROFICIENCY_DRUID, oPC) - || GetHasFeat(FEAT_WEAPON_PROFICIENCY_DAGGER, oPC); + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_DRUID, oPC) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_WIZARD, oPC) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_ROGUE, oPC) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_DAGGER, oPC); case BASE_ITEM_LONGSWORD: return GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oPC) @@ -152,12 +170,14 @@ int IsProficient(object oPC, int nBaseItem) || GetHasFeat(FEAT_WEAPON_PROFICIENCY_ROGUE, oPC); case BASE_ITEM_QUARTERSTAFF: - return GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oPC) + return GetHasFeat(FEAT_WEAPON_PROFICIENCY_QUARTERSTAFF, oPC) + ||GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oPC) || GetHasFeat(FEAT_WEAPON_PROFICIENCY_DRUID, oPC) - || GetHasFeat(FEAT_WEAPON_PROFICIENCY_WIZARD, oPC); + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_WIZARD, oPC); case BASE_ITEM_MAGICSTAFF: - return GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oPC) + return GetHasFeat(FEAT_WEAPON_PROFICIENCY_QUARTERSTAFF, oPC) + ||GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oPC) || GetHasFeat(FEAT_WEAPON_PROFICIENCY_DRUID, oPC) || GetHasFeat(FEAT_WEAPON_PROFICIENCY_WIZARD, oPC); @@ -300,167 +320,185 @@ int GetWeaponProfFeatByType(int nBaseType) { switch(nBaseType) { - case BASE_ITEM_SHORTSWORD: - return FEAT_WEAPON_PROFICIENCY_SHORTSWORD; + case BASE_ITEM_CLUB: + return FEAT_WEAPON_PROFICIENCY_CLUB; + + case BASE_ITEM_QUARTERSTAFF: + return FEAT_WEAPON_PROFICIENCY_QUARTERSTAFF; - case BASE_ITEM_LONGSWORD: - return FEAT_WEAPON_PROFICIENCY_LONGSWORD; + case BASE_ITEM_MAGICSTAFF: + return FEAT_WEAPON_PROFICIENCY_QUARTERSTAFF; + + case BASE_ITEM_DAGGER: + return FEAT_WEAPON_PROFICIENCY_DAGGER; - case BASE_ITEM_BATTLEAXE: - return FEAT_WEAPON_PROFICIENCY_BATTLEAXE; + case BASE_ITEM_HEAVYCROSSBOW: + return FEAT_WEAPON_PROFICIENCY_HEAVY_XBOW; - case BASE_ITEM_BASTARDSWORD: - return FEAT_WEAPON_PROFICIENCY_BASTARD_SWORD; + case BASE_ITEM_LIGHTCROSSBOW: + return FEAT_WEAPON_PROFICIENCY_LIGHT_XBOW; + + case BASE_ITEM_SHORTSWORD: + return FEAT_WEAPON_PROFICIENCY_SHORTSWORD; - case BASE_ITEM_LIGHTFLAIL: - return FEAT_WEAPON_PROFICIENCY_LIGHT_FLAIL; + case BASE_ITEM_LONGSWORD: + return FEAT_WEAPON_PROFICIENCY_LONGSWORD; - case BASE_ITEM_WARHAMMER: - return FEAT_WEAPON_PROFICIENCY_WARHAMMER; + case BASE_ITEM_BATTLEAXE: + return FEAT_WEAPON_PROFICIENCY_BATTLEAXE; - case BASE_ITEM_LONGBOW: - return FEAT_WEAPON_PROFICIENCY_LONGBOW; + case BASE_ITEM_BASTARDSWORD: + return FEAT_WEAPON_PROFICIENCY_BASTARD_SWORD; - case BASE_ITEM_LIGHTMACE: - return FEAT_WEAPON_PROFICIENCY_LIGHT_MACE; + case BASE_ITEM_LIGHTFLAIL: + return FEAT_WEAPON_PROFICIENCY_LIGHT_FLAIL; - case BASE_ITEM_HALBERD: - return FEAT_WEAPON_PROFICIENCY_HALBERD; + case BASE_ITEM_WARHAMMER: + return FEAT_WEAPON_PROFICIENCY_WARHAMMER; - case BASE_ITEM_SHORTBOW: + case BASE_ITEM_LONGBOW: + return FEAT_WEAPON_PROFICIENCY_LONGBOW; + + case BASE_ITEM_LIGHTMACE: + return FEAT_WEAPON_PROFICIENCY_LIGHT_MACE; + + case BASE_ITEM_HALBERD: + return FEAT_WEAPON_PROFICIENCY_HALBERD; + + case BASE_ITEM_SHORTBOW: return FEAT_WEAPON_PROFICIENCY_SHORTBOW; - case BASE_ITEM_TWOBLADEDSWORD: + case BASE_ITEM_TWOBLADEDSWORD: return FEAT_WEAPON_PROFICIENCY_TWO_BLADED_SWORD; - case BASE_ITEM_GREATSWORD: + case BASE_ITEM_GREATSWORD: return FEAT_WEAPON_PROFICIENCY_GREATSWORD; - case BASE_ITEM_GREATAXE: + case BASE_ITEM_GREATAXE: return FEAT_WEAPON_PROFICIENCY_GREATAXE; - case BASE_ITEM_DART: + case BASE_ITEM_DART: return FEAT_WEAPON_PROFICIENCY_DART; - case BASE_ITEM_DIREMACE: + case BASE_ITEM_DIREMACE: return FEAT_WEAPON_PROFICIENCY_DIRE_MACE; - case BASE_ITEM_DOUBLEAXE: + case BASE_ITEM_DOUBLEAXE: return FEAT_WEAPON_PROFICIENCY_DOUBLE_AXE; - case BASE_ITEM_HEAVYFLAIL: + case BASE_ITEM_HEAVYFLAIL: return FEAT_WEAPON_PROFICIENCY_HEAVY_FLAIL; - case BASE_ITEM_LIGHTHAMMER: + case BASE_ITEM_LIGHTHAMMER: return FEAT_WEAPON_PROFICIENCY_LIGHT_HAMMER; - case BASE_ITEM_HANDAXE: + case BASE_ITEM_HANDAXE: return FEAT_WEAPON_PROFICIENCY_HANDAXE; - case BASE_ITEM_KAMA: + case BASE_ITEM_KAMA: return FEAT_WEAPON_PROFICIENCY_KAMA; - case BASE_ITEM_KATANA: + case BASE_ITEM_KATANA: return FEAT_WEAPON_PROFICIENCY_KATANA; - case BASE_ITEM_KUKRI: + case BASE_ITEM_KUKRI: return FEAT_WEAPON_PROFICIENCY_KUKRI; - case BASE_ITEM_MORNINGSTAR: + case BASE_ITEM_MORNINGSTAR: return FEAT_WEAPON_PROFICIENCY_MORNINGSTAR; - case BASE_ITEM_RAPIER: + case BASE_ITEM_RAPIER: return FEAT_WEAPON_PROFICIENCY_RAPIER; - case BASE_ITEM_SCIMITAR: + case BASE_ITEM_SCIMITAR: return FEAT_WEAPON_PROFICIENCY_SCIMITAR; - case BASE_ITEM_SCYTHE: + case BASE_ITEM_SCYTHE: return FEAT_WEAPON_PROFICIENCY_SCYTHE; - case BASE_ITEM_SHORTSPEAR: + case BASE_ITEM_SHORTSPEAR: return FEAT_WEAPON_PROFICIENCY_SHORTSPEAR; - case BASE_ITEM_SHURIKEN: + case BASE_ITEM_SHURIKEN: return FEAT_WEAPON_PROFICIENCY_SHURIKEN; - case BASE_ITEM_SICKLE: + case BASE_ITEM_SICKLE: return FEAT_WEAPON_PROFICIENCY_SICKLE; - case BASE_ITEM_SLING: + case BASE_ITEM_SLING: return FEAT_WEAPON_PROFICIENCY_SLING; - case BASE_ITEM_THROWINGAXE: + case BASE_ITEM_THROWINGAXE: return FEAT_WEAPON_PROFICIENCY_THROWING_AXE; - case BASE_ITEM_CSLASHWEAPON: + case BASE_ITEM_CSLASHWEAPON: return FEAT_WEAPON_PROFICIENCY_CREATURE; - case BASE_ITEM_CPIERCWEAPON: + case BASE_ITEM_CPIERCWEAPON: return FEAT_WEAPON_PROFICIENCY_CREATURE; - case BASE_ITEM_CBLUDGWEAPON: + case BASE_ITEM_CBLUDGWEAPON: return FEAT_WEAPON_PROFICIENCY_CREATURE; - case BASE_ITEM_CSLSHPRCWEAP: + case BASE_ITEM_CSLSHPRCWEAP: return FEAT_WEAPON_PROFICIENCY_CREATURE; - case BASE_ITEM_TRIDENT: + case BASE_ITEM_TRIDENT: return FEAT_WEAPON_PROFICIENCY_TRIDENT; - case BASE_ITEM_DWARVENWARAXE: + case BASE_ITEM_DWARVENWARAXE: return FEAT_WEAPON_PROFICIENCY_DWARVEN_WARAXE; - case BASE_ITEM_WHIP: + case BASE_ITEM_WHIP: return FEAT_WEAPON_PROFICIENCY_WHIP; - case BASE_ITEM_ELVEN_LIGHTBLADE: + case BASE_ITEM_ELVEN_LIGHTBLADE: return FEAT_WEAPON_PROFICIENCY_ELVEN_LIGHTBLADE; - case BASE_ITEM_ELVEN_THINBLADE: + case BASE_ITEM_ELVEN_THINBLADE: return FEAT_WEAPON_PROFICIENCY_ELVEN_THINBLADE; - case BASE_ITEM_ELVEN_COURTBLADE: + case BASE_ITEM_ELVEN_COURTBLADE: return FEAT_WEAPON_PROFICIENCY_ELVEN_COURTBLADE; - case BASE_ITEM_HEAVY_PICK: + case BASE_ITEM_HEAVY_PICK: return FEAT_WEAPON_PROFICIENCY_HEAVY_PICK; - case BASE_ITEM_LIGHT_PICK: + case BASE_ITEM_LIGHT_PICK: return FEAT_WEAPON_PROFICIENCY_LIGHT_PICK; - case BASE_ITEM_SAI: + case BASE_ITEM_SAI: return FEAT_WEAPON_PROFICIENCY_SAI; - case BASE_ITEM_NUNCHAKU: + case BASE_ITEM_NUNCHAKU: return FEAT_WEAPON_PROFICIENCY_NUNCHAKU; - case BASE_ITEM_FALCHION: + case BASE_ITEM_FALCHION: return FEAT_WEAPON_PROFICIENCY_FALCHION; - case BASE_ITEM_SAP: + case BASE_ITEM_SAP: return FEAT_WEAPON_PROFICIENCY_SAP; - case BASE_ITEM_KATAR: + case BASE_ITEM_KATAR: return FEAT_WEAPON_PROFICIENCY_KATAR; - case BASE_ITEM_HEAVY_MACE: + case BASE_ITEM_HEAVY_MACE: return FEAT_WEAPON_PROFICIENCY_HEAVY_MACE; - case BASE_ITEM_MAUL: + case BASE_ITEM_MAUL: return FEAT_WEAPON_PROFICIENCY_MAUL; - case BASE_ITEM_DOUBLE_SCIMITAR: + case BASE_ITEM_DOUBLE_SCIMITAR: return FEAT_WEAPON_PROFICIENCY_DOUBLE_SCIMITAR; - case BASE_ITEM_GOAD: + case BASE_ITEM_GOAD: return FEAT_WEAPON_PROFICIENCY_GOAD; - case BASE_ITEM_EAGLE_CLAW: + case BASE_ITEM_EAGLE_CLAW: return FEAT_WEAPON_PROFICIENCY_EAGLE_CLAW; - default: - return FEAT_WEAPON_PROFICIENCY_SIMPLE; + default: + return FEAT_WEAPON_PROFICIENCY_SIMPLE; } return 0; diff --git a/src/module/dlg/nw_g_animal.dlg.json b/src/module/dlg/nw_g_animal.dlg.json new file mode 100644 index 0000000..a65a225 --- /dev/null +++ b/src/module/dlg/nw_g_animal.dlg.json @@ -0,0 +1,49670 @@ +{ + "__data_type": "DLG ", + "DelayEntry": { + "type": "dword", + "value": 0 + }, + "DelayReply": { + "type": "dword", + "value": 0 + }, + "EndConverAbort": { + "type": "resref", + "value": "" + }, + "EndConversation": { + "type": "resref", + "value": "" + }, + "EntryList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_scout" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 439 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "0c_if_identify" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 438 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "nw_d2_intn" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 7 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "nw_d2_intl" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 6 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 5 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 4 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 3 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 2 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "nw_d2_intn" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 1 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "nw_d2_intl" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 0 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": " You feel warm thoughts from your animal companion, as it wonders what you would like.", + "id": 53321 + } + } + }, + { + "__struct_id": 1, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58454 + } + } + }, + { + "__struct_id": 2, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58455 + } + } + }, + { + "__struct_id": 3, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58456 + } + } + }, + { + "__struct_id": 4, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58457 + } + } + }, + { + "__struct_id": 5, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58458 + } + } + }, + { + "__struct_id": 6, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58459 + } + } + }, + { + "__struct_id": 7, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58460 + } + } + }, + { + "__struct_id": 8, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [] + }, + "Script": { + "type": "resref", + "value": "nw_ch_fm_st_10" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58461 + } + } + }, + { + "__struct_id": 9, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [] + }, + "Script": { + "type": "resref", + "value": "nw_ch_fm_st_10" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58462 + } + } + }, + { + "__struct_id": 10, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [] + }, + "Script": { + "type": "resref", + "value": "nw_ch_fm_st_10" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58463 + } + } + }, + { + "__struct_id": 11, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "The animal seems confused about your actions, but slinks away to appease you.", + "id": 58464 + } + } + }, + { + "__struct_id": 12, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [] + }, + "Script": { + "type": "resref", + "value": "nw_ch_fm_st-11" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58464 + } + } + }, + { + "__struct_id": 13, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58465 + } + } + }, + { + "__struct_id": 14, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [] + }, + "Script": { + "type": "resref", + "value": "nw_ch_fm_st_10" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58466 + } + } + }, + { + "__struct_id": 15, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58467 + } + } + }, + { + "__struct_id": 16, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [] + }, + "Script": { + "type": "resref", + "value": "nw_ch_fm_st_12" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "The animal is quite famished and devours the food you offer. The companion seems content.", + "id": 58468 + } + } + }, + { + "__struct_id": 17, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58469 + } + } + }, + { + "__struct_id": 18, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 151 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "0c_if_has_class" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nClass1" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nClass2" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 2, + "Key": { + "type": "cexostring", + "value": "nClass3" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 3, + "Key": { + "type": "cexostring", + "value": "nClass4" + }, + "Value": { + "type": "cexostring", + "value": "6" + } + }, + { + "__struct_id": 4, + "Key": { + "type": "cexostring", + "value": "nClass5" + }, + "Value": { + "type": "cexostring", + "value": "7" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 141 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "0c_if_has_class" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nClass1" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nClass2" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 2, + "Key": { + "type": "cexostring", + "value": "nClass3" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 3, + "Key": { + "type": "cexostring", + "value": "nClass4" + }, + "Value": { + "type": "cexostring", + "value": "9" + } + }, + { + "__struct_id": 4, + "Key": { + "type": "cexostring", + "value": "nClass5" + }, + "Value": { + "type": "cexostring", + "value": "10" + } + }, + { + "__struct_id": 5, + "Key": { + "type": "cexostring", + "value": "nClass6" + }, + "Value": { + "type": "cexostring", + "value": "47" + } + }, + { + "__struct_id": 6, + "Key": { + "type": "cexostring", + "value": "nClass7" + }, + "Value": { + "type": "cexostring", + "value": "48" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 59 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "0c_if_has_class" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nClass1" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nClass2" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 2, + "Key": { + "type": "cexostring", + "value": "nClass3" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 3, + "Key": { + "type": "cexostring", + "value": "nClass4" + }, + "Value": { + "type": "cexostring", + "value": "9" + } + }, + { + "__struct_id": 4, + "Key": { + "type": "cexostring", + "value": "nClass5" + }, + "Value": { + "type": "cexostring", + "value": "10" + } + }, + { + "__struct_id": 5, + "Key": { + "type": "cexostring", + "value": "nClass6" + }, + "Value": { + "type": "cexostring", + "value": "47" + } + }, + { + "__struct_id": 6, + "Key": { + "type": "cexostring", + "value": "nClass7" + }, + "Value": { + "type": "cexostring", + "value": "48" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "0c_if_has_class" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nClass1" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nClass2" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 2, + "Key": { + "type": "cexostring", + "value": "nClass3" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 3, + "Key": { + "type": "cexostring", + "value": "nClass4" + }, + "Value": { + "type": "cexostring", + "value": "9" + } + }, + { + "__struct_id": 4, + "Key": { + "type": "cexostring", + "value": "nClass5" + }, + "Value": { + "type": "cexostring", + "value": "10" + } + }, + { + "__struct_id": 5, + "Key": { + "type": "cexostring", + "value": "nClass6" + }, + "Value": { + "type": "cexostring", + "value": "47" + } + }, + { + "__struct_id": 6, + "Key": { + "type": "cexostring", + "value": "nClass7" + }, + "Value": { + "type": "cexostring", + "value": "48" + } + }, + { + "__struct_id": 7, + "Key": { + "type": "cexostring", + "value": "nClass8" + }, + "Value": { + "type": "cexostring", + "value": "46" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 10 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 9 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 8 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": " looks up at you, obviously willing to do as you ask.", + "id": 58470 + } + } + }, + { + "__struct_id": 19, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_has_assoc" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAssociate" + }, + "Value": { + "type": "cexostring", + "value": "Companion" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 26 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "0c_if_has_assoc" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAssociate" + }, + "Value": { + "type": "cexostring", + "value": "Familiar" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 25 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "x2_hen_tomishad3" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 24 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 21 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "30" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "174" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 19 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "175" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 18 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "176" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 17 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "177" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 16 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "179" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 15 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 10, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "180" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 14 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 11, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "181" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 13 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 12, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "182" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 12 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 13, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "178" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 11 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 14, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 152 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 15, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 8 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": " waits for you to tell it what to summon." + } + } + }, + { + "__struct_id": 20, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 23 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 22 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "You sure?", + "id": 87721 + } + } + }, + { + "__struct_id": 21, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 58 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 48 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 38 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 28 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "nw_d2_intn" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 7 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 8 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": " Ready to cast it waits for your command.", + "id": 88866 + } + } + }, + { + "__struct_id": 22, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 37 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 36 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "x0_d2_hasfamil" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 35 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "x0_d2_hascompan" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 34 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "x2_d1_hashench1" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 33 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "x2_d1_hashench2" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 32 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "x2_d1_hashench3" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 31 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "x2_d1_hashench4" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 30 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "x2_d1_targetall" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 152 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 10, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 8 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "0c_listhenchman" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "And what is my target?", + "id": 87722 + } + } + }, + { + "__struct_id": 23, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 47 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 46 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "x0_d2_hasfamil" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 45 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "x0_d2_hascompan" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 44 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "x2_d1_hashench1" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 43 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "x2_d1_hashench2" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 42 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "x2_d1_hashench3" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 41 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "x2_d1_hashench4" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 40 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "x2_d1_targetall" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 39 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 152 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 10, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 8 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "0c_listhenchman" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "And what is my target?", + "id": 87722 + } + } + }, + { + "__struct_id": 24, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 57 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "x0_d2_hasfamil" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 55 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "x0_d2_hascompan" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 54 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "x2_d1_hashench1" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 53 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "x2_d1_hashench2" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 52 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "x2_d1_hashench3" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 51 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "x2_d1_hashench4" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 50 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "x2_d1_targetall" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 49 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 152 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 10, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 8 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "0c_listhenchman" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "And what is my target?", + "id": 87722 + } + } + }, + { + "__struct_id": 25, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 140 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "6" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 139 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "9" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 130 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "13" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 129 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "21" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 128 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "419" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 127 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "519" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 126 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "38" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 125 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "41" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 124 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "42" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 123 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 10, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "354" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 122 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 11, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "47" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 121 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 12, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "49" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 120 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 13, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "50" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 119 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 14, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "369" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 116 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 15, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "418" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 115 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 16, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "121" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 114 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 17, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "377" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 113 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 18, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "356" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 112 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 19, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "62" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 111 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 20, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "120" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 110 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 21, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "65" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 109 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 22, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "67" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 108 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 23, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "109" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 107 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 24, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "70" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 106 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 25, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "443" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 105 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 26, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "73" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 104 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 27, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "74" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 103 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 28, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "78" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 102 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 29, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "88" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 101 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 30, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "90" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 100 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 31, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "92" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 99 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 32, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "93" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 98 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 33, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "94" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 97 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 34, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "95" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 96 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 35, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "97" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 95 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 36, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "99" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 94 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 37, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "100" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 93 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 38, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "102" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 92 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 39, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "108" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 91 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 40, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "113" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 90 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 41, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "117" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 89 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 42, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "119" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 88 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 43, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "525" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 87 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 44, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "126" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 86 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 45, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "355" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 85 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 46, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "133" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 84 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 47, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "134" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 83 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 48, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "137" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 82 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 49, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "321" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 81 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 50, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "141" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 80 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 51, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "374" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 79 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 52, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "145" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 78 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 53, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "146" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 77 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 54, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "147" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 76 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 55, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "148" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 75 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 56, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "149" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 74 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 57, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "150" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 73 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 58, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "151" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 72 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 59, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "152" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 71 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 60, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "154" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 70 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 61, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "157" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 69 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 62, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "159" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 68 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 63, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "417" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 67 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 64, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "450" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 66 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 65, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "169" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 65 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 66, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "168" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 64 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 67, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "172" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 63 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 68, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "186" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 62 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 69, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "365" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 61 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 70, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "441" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 60 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 71, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 152 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 72, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 8 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "At the ready your companion listens.", + "id": 87720 + } + } + }, + { + "__struct_id": 26, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 118 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 117 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "You sure?", + "id": 87721 + } + } + }, + { + "__struct_id": 27, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 138 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 137 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "x0_d2_hasfamil" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 136 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "x0_d2_hascompan" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 135 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "x2_d1_hashench1" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 134 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "x2_d1_hashench2" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 133 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "x2_d1_hashench3" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 132 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "x2_d1_hashench4" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 131 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 152 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 8 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "x2_d1_gentags" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Okay. Who shoulds I cast it on?", + "id": 87722 + } + } + }, + { + "__struct_id": 28, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 150 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 149 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "x0_d2_hasfamil" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 148 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "x0_d2_hascompan" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 147 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "x2_d1_hashench1" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 146 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "x2_d1_hashench2" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 145 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "x2_d1_hashench3" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 144 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "x2_d1_hashench4" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 143 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 142 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 152 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 10, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 8 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "x2_d1_gentags" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Looking at you it waits.", + "id": 87722 + } + } + }, + { + "__struct_id": 29, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 180 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 179 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 178 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "0c_if_pickuploot" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 177 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "0c_if_has_class" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nClass1" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nClass2" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 2, + "Key": { + "type": "cexostring", + "value": "nClass3" + }, + "Value": { + "type": "cexostring", + "value": "47" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 170 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "0c_if_has_class" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nClass1" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nClass2" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 2, + "Key": { + "type": "cexostring", + "value": "nClass3" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 3, + "Key": { + "type": "cexostring", + "value": "nClass4" + }, + "Value": { + "type": "cexostring", + "value": "9" + } + }, + { + "__struct_id": 4, + "Key": { + "type": "cexostring", + "value": "nClass5" + }, + "Value": { + "type": "cexostring", + "value": "10" + } + }, + { + "__struct_id": 5, + "Key": { + "type": "cexostring", + "value": "nClass6" + }, + "Value": { + "type": "cexostring", + "value": "47" + } + }, + { + "__struct_id": 6, + "Key": { + "type": "cexostring", + "value": "nClass7" + }, + "Value": { + "type": "cexostring", + "value": "48" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 159 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 158 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 157 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "0c_if_skillrank" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSkill" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nRank" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 153 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 152 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": " looks at you awaiting your instructions on tactics." + } + } + }, + { + "__struct_id": 30, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 156 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 155 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 154 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 151 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 8 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": " Looking around, it listens for you to tell them how to deal with objects." + } + } + }, + { + "__struct_id": 31, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 169 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 168 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 167 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 166 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 165 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 164 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "0c_if_cntrspell" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 163 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "0c_if_com_script" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAIScript" + }, + "Value": { + "type": "cexostring", + "value": "ai_a_cntrspell" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 162 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 161 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 160 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 10, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 151 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 11, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 8 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": " Your companion looks up to the sky while you tell it how to use magic." + } + } + }, + { + "__struct_id": 32, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 176 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 175 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 174 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 173 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 172 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 171 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 151 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 8 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": " Looking at you, waits for instructon on how it should heal.", + "id": 55427 + } + } + }, + { + "__struct_id": 33, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_no_com_script" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 437 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "0c_no_com_script" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAIScript" + }, + "Value": { + "type": "cexostring", + "value": "ai_a_defensive" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 436 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "0c_no_com_script" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAIScript" + }, + "Value": { + "type": "cexostring", + "value": "ai_a_ambusher" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 435 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "0c_no_com_script" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAIScript" + }, + "Value": { + "type": "cexostring", + "value": "ai_a_ranged" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 187 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "0c_no_com_script" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAIScript" + }, + "Value": { + "type": "cexostring", + "value": "ai_a_peaceful" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 186 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "0c_if_taunt" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 185 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "0c_if_taunt" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 184 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 183 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "0c_if_assoc_mode" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nMode" + }, + "Value": { + "type": "cexostring", + "value": "16384" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 182 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 181 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 10, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 151 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 11, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 8 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": " Your companion listens intently for your combat tactics." + } + } + }, + { + "__struct_id": 34, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_no_com_script" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 434 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "0c_no_com_script" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAIScript" + }, + "Value": { + "type": "cexostring", + "value": "ai_a_defensive" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 433 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "0c_no_com_script" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAIScript" + }, + "Value": { + "type": "cexostring", + "value": "ai_a_ambusher" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 432 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "0c_no_com_script" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAIScript" + }, + "Value": { + "type": "cexostring", + "value": "ai_a_ranged" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 187 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 431 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "0c_if_taunt" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 430 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "0c_if_cntrspell" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 429 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 428 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 427 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 426 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 10, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 189 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 11, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 188 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": " What do you think is the best tactic?" + } + } + }, + { + "__struct_id": 35, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 425 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 424 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 423 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "0c_if_pickuploot" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 422 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 415 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 403 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 402 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 401 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 397 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 190 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 10, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 188 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": " What do you have in mind?" + } + } + }, + { + "__struct_id": 36, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 38 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_scout" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 396 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "0c_if_identify" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 395 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "0c_if_open_inven" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 391 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 189 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "0c_if_has_class" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nClass1" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nClass2" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 2, + "Key": { + "type": "cexostring", + "value": "nClass3" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 3, + "Key": { + "type": "cexostring", + "value": "nClass4" + }, + "Value": { + "type": "cexostring", + "value": "6" + } + }, + { + "__struct_id": 4, + "Key": { + "type": "cexostring", + "value": "nClass5" + }, + "Value": { + "type": "cexostring", + "value": "7" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 380 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "0c_if_has_class" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nClass1" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nClass2" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 2, + "Key": { + "type": "cexostring", + "value": "nClass3" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 3, + "Key": { + "type": "cexostring", + "value": "nClass4" + }, + "Value": { + "type": "cexostring", + "value": "9" + } + }, + { + "__struct_id": 4, + "Key": { + "type": "cexostring", + "value": "nClass5" + }, + "Value": { + "type": "cexostring", + "value": "10" + } + }, + { + "__struct_id": 5, + "Key": { + "type": "cexostring", + "value": "nClass6" + }, + "Value": { + "type": "cexostring", + "value": "47" + } + }, + { + "__struct_id": 6, + "Key": { + "type": "cexostring", + "value": "nClass7" + }, + "Value": { + "type": "cexostring", + "value": "48" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 298 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "0c_if_has_class" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nClass1" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nClass2" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 2, + "Key": { + "type": "cexostring", + "value": "nClass3" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 3, + "Key": { + "type": "cexostring", + "value": "nClass4" + }, + "Value": { + "type": "cexostring", + "value": "9" + } + }, + { + "__struct_id": 4, + "Key": { + "type": "cexostring", + "value": "nClass5" + }, + "Value": { + "type": "cexostring", + "value": "10" + } + }, + { + "__struct_id": 5, + "Key": { + "type": "cexostring", + "value": "nClass6" + }, + "Value": { + "type": "cexostring", + "value": "47" + } + }, + { + "__struct_id": 6, + "Key": { + "type": "cexostring", + "value": "nClass7" + }, + "Value": { + "type": "cexostring", + "value": "48" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 266 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "0c_if_has_class" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nClass1" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nClass2" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 2, + "Key": { + "type": "cexostring", + "value": "nClass3" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 3, + "Key": { + "type": "cexostring", + "value": "nClass4" + }, + "Value": { + "type": "cexostring", + "value": "9" + } + }, + { + "__struct_id": 4, + "Key": { + "type": "cexostring", + "value": "nClass5" + }, + "Value": { + "type": "cexostring", + "value": "10" + } + }, + { + "__struct_id": 5, + "Key": { + "type": "cexostring", + "value": "nClass6" + }, + "Value": { + "type": "cexostring", + "value": "47" + } + }, + { + "__struct_id": 6, + "Key": { + "type": "cexostring", + "value": "nClass7" + }, + "Value": { + "type": "cexostring", + "value": "48" + } + }, + { + "__struct_id": 7, + "Key": { + "type": "cexostring", + "value": "nClass8" + }, + "Value": { + "type": "cexostring", + "value": "46" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 251 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 195 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "0c_if_hen_leave" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 192 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 10, + "Active": { + "type": "resref", + "value": "0c_if_convo" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 191 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 11, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 188 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": " What would you like to discuss?" + } + } + }, + { + "__struct_id": 37, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 194 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 193 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 188 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Are you sure you want to do that?" + } + } + }, + { + "__struct_id": 38, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_polymorph" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 250 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "0c_if_has_feat" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nFeat" + }, + "Value": { + "type": "cexostring", + "value": "305" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "sTarget" + }, + "Value": { + "type": "cexostring", + "value": "OBJECT_SELF" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 244 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "0c_if_has_feat" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nFeat" + }, + "Value": { + "type": "cexostring", + "value": "304" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "sTarget" + }, + "Value": { + "type": "cexostring", + "value": "OBJECT_SELF" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 239 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "0c_if_has_feat" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nFeat" + }, + "Value": { + "type": "cexostring", + "value": "898" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "sTarget" + }, + "Value": { + "type": "cexostring", + "value": "OBJECT_SELF" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 233 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "0c_if_has_feat" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nFeat" + }, + "Value": { + "type": "cexostring", + "value": "900" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "sTarget" + }, + "Value": { + "type": "cexostring", + "value": "OBJECT_SELF" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 229 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "0c_if_has_feat" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nFeat" + }, + "Value": { + "type": "cexostring", + "value": "901" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "sTarget" + }, + "Value": { + "type": "cexostring", + "value": "OBJECT_SELF" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 225 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "0c_if_has_feat" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nFeat" + }, + "Value": { + "type": "cexostring", + "value": "903" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "sTarget" + }, + "Value": { + "type": "cexostring", + "value": "OBJECT_SELF" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 221 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "0c_if_has_feat" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nFeat" + }, + "Value": { + "type": "cexostring", + "value": "902" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "sTarget" + }, + "Value": { + "type": "cexostring", + "value": "OBJECT_SELF" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 217 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "0c_if_has_feat" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nFeat" + }, + "Value": { + "type": "cexostring", + "value": "1060" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "sTarget" + }, + "Value": { + "type": "cexostring", + "value": "OBJECT_SELF" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 213 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "0c_if_has_feat" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nFeat" + }, + "Value": { + "type": "cexostring", + "value": "1061" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "sTarget" + }, + "Value": { + "type": "cexostring", + "value": "OBJECT_SELF" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 209 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 10, + "Active": { + "type": "resref", + "value": "0c_if_has_feat" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nFeat" + }, + "Value": { + "type": "cexostring", + "value": "257" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "sTarget" + }, + "Value": { + "type": "cexostring", + "value": "OBJECT_SELF" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 208 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 11, + "Active": { + "type": "resref", + "value": "x2_d2_haslayon" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 198 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 12, + "Active": { + "type": "resref", + "value": "x2_d1_dmight" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 197 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 13, + "Active": { + "type": "resref", + "value": "x2_d1_dshield" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 196 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 14, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 188 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Let's see what I can do...", + "id": 95904 + } + } + }, + { + "__struct_id": 39, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 207 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 206 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "x0_d2_hasfamil" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 205 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "x0_d2_hascompan" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 204 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "x2_d1_hashench1" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 203 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "x2_d1_hashench2" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 202 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "x2_d1_hashench3" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 201 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "x2_d1_hashench4" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 200 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 199 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Script": { + "type": "resref", + "value": "x2_d1_gentags" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "And who should be the target of my healing?", + "id": 87722 + } + } + }, + { + "__struct_id": 40, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 212 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 211 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 210 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 199 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Which form should I take?" + } + } + }, + { + "__struct_id": 41, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 216 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 215 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 214 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 199 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Which form should I take?" + } + } + }, + { + "__struct_id": 42, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 220 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 219 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 218 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 199 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Which form should I take?" + } + } + }, + { + "__struct_id": 43, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 224 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 223 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 222 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 199 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Which form should I take?" + } + } + }, + { + "__struct_id": 44, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 228 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 227 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 226 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 199 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Which form should I take?" + } + } + }, + { + "__struct_id": 45, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 232 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 231 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 230 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 199 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Which form should I take?" + } + } + }, + { + "__struct_id": 46, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 238 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "0c_if_has_feat" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nFeat" + }, + "Value": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 237 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 236 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 235 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 234 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 199 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Which form should I take?" + } + } + }, + { + "__struct_id": 47, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 243 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 242 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 241 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 240 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 199 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Which form should I take?" + } + } + }, + { + "__struct_id": 48, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 249 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 248 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 247 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 246 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 245 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 199 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Which form should I take?" + } + } + }, + { + "__struct_id": 49, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_has_assoc" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAssociate" + }, + "Value": { + "type": "cexostring", + "value": "Companion" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 265 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "0c_if_has_assoc" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAssociate" + }, + "Value": { + "type": "cexostring", + "value": "Familiar" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 264 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "x2_hen_tomishad3" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 263 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 262 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "30" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 261 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "174" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 260 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "175" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 259 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "176" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 258 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "177" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 257 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "179" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 256 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 10, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "180" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 255 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 11, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "181" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 254 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 12, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "182" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 253 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 13, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "178" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 252 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 14, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 190 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 15, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 188 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "What would you have me summon?" + } + } + }, + { + "__struct_id": 50, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 297 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 287 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 277 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 267 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 190 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 188 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": " What would you like to discuss about my defensive spells?", + "id": 88866 + } + } + }, + { + "__struct_id": 51, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 276 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 275 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "x0_d2_hasfamil" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 274 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "x0_d2_hascompan" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 273 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "x2_d1_hashench1" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 272 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "x2_d1_hashench2" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 271 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "x2_d1_hashench3" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 270 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "x2_d1_hashench4" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 269 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 268 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 190 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "0c_listhenchman" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "And what is my target?", + "id": 87722 + } + } + }, + { + "__struct_id": 52, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 286 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 285 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "x0_d2_hasfamil" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 284 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "x0_d2_hascompan" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 283 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "x2_d1_hashench1" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 282 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "x2_d1_hashench2" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 281 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "x2_d1_hashench3" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 280 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "x2_d1_hashench4" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 279 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 278 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 190 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "0c_listhenchman" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "And what is my target?", + "id": 87722 + } + } + }, + { + "__struct_id": 53, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 296 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 295 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "x0_d2_hasfamil" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 294 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "x0_d2_hascompan" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 293 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "x2_d1_hashench1" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 292 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "x2_d1_hashench2" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 291 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "x2_d1_hashench3" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 290 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "x2_d1_hashench4" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 289 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 288 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 190 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "0c_listhenchman" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "And what is my target?", + "id": 87722 + } + } + }, + { + "__struct_id": 54, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 379 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "6" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 378 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "9" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 369 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "13" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 368 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "21" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 367 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "419" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 366 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "519" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 365 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "38" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 364 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "41" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 363 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "42" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 362 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 10, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "354" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 361 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 11, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "47" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 360 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 12, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "49" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 359 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 13, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "50" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 358 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 14, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "369" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 355 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 15, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "418" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 354 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 16, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "121" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 353 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 17, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "377" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 352 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 18, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "356" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 351 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 19, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "62" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 350 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 20, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "120" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 349 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 21, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "65" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 348 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 22, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "67" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 347 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 23, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "109" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 346 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 24, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "70" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 345 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 25, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "443" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 344 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 26, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "73" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 343 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 27, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "74" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 342 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 28, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "78" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 341 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 29, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "88" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 340 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 30, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "90" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 339 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 31, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "92" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 338 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 32, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "93" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 337 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 33, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "94" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 336 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 34, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "95" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 335 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 35, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "97" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 334 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 36, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "99" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 333 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 37, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "100" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 332 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 38, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "102" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 331 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 39, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "108" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 330 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 40, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "113" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 329 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 41, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "117" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 328 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 42, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "119" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 327 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 43, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "525" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 326 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 44, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "126" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 325 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 45, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "355" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 324 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 46, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "133" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 323 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 47, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "134" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 322 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 48, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "137" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 321 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 49, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "321" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 320 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 50, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "141" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 319 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 51, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "374" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 318 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 52, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "145" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 317 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 53, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "146" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 316 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 54, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "147" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 315 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 55, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "148" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 314 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 56, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "149" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 313 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 57, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "150" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 312 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 58, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "151" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 311 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 59, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "152" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 310 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 60, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "154" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 309 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 61, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "157" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 308 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 62, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "159" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 307 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 63, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "417" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 306 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 64, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "450" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 305 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 65, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "169" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 304 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 66, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "168" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 303 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 67, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "172" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 302 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 68, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "186" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 301 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 69, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "365" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 300 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 70, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "441" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 299 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 71, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 381 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "What you want me to cast?", + "id": 87720 + } + } + }, + { + "__struct_id": 55, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 357 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 356 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "You sure?", + "id": 87721 + } + } + }, + { + "__struct_id": 56, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 377 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 376 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "x0_d2_hasfamil" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 375 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "x0_d2_hascompan" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 374 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "x2_d1_hashench1" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 373 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "x2_d1_hashench2" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 372 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "x2_d1_hashench3" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 371 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "x2_d1_hashench4" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 370 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 381 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "x2_d1_gentags" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Okay. Who shoulds I cast it on?", + "id": 87722 + } + } + }, + { + "__struct_id": 57, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 390 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 389 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "x0_d2_hasfamil" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 388 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "x0_d2_hascompan" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 387 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "x2_d1_hashench1" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 386 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "x2_d1_hashench2" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 385 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "x2_d1_hashench3" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 384 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "x2_d1_hashench4" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 383 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 382 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 381 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Script": { + "type": "resref", + "value": "x2_d1_gentags" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "And who should be the target of my healing?", + "id": 87722 + } + } + }, + { + "__struct_id": 58, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 394 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 393 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 392 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 190 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 188 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Sure, what would you like me to do?" + } + } + }, + { + "__struct_id": 59, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_skillrank" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSkill" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nRank" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 400 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "0c_if_skillrank" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSkill" + }, + "Value": { + "type": "cexostring", + "value": "9" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nRank" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 399 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 398 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 189 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 188 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": " Should I do something else?" + } + } + }, + { + "__struct_id": 60, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 414 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 413 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "0c_if_a_magic_m" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nMode" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 412 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 411 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 410 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 409 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 408 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "0c_if_cntrspell" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 407 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "0c_if_com_script" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAIScript" + }, + "Value": { + "type": "cexostring", + "value": "ai_a_cntrspell" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 406 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 405 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 10, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 404 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 11, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 189 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 12, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 188 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": " How would you like me to use magic in combat?" + } + } + }, + { + "__struct_id": 61, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 421 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 420 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 419 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 418 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 417 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 416 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 189 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 188 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": " When do you think I should heal our allies?", + "id": 55427 + } + } + }, + { + "__struct_id": 62, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "The creature looks at you strangely and resumes what it was doing before.", + "id": 53320 + } + } + } + ] + }, + "NumWords": { + "type": "dword", + "value": 2384 + }, + "PreventZoomIn": { + "type": "byte", + "value": 1 + }, + "ReplyList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "nw_ch_fm_st_03" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 3 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "nw_ch_fm_st_04" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 2 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 1 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 53319 + } + } + }, + { + "__struct_id": 1, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "nw_ch_fm_st_03" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 3 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "nw_ch_fm_st_04" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 2 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 1 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 53318 + } + } + }, + { + "__struct_id": 2, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "nw_ch_fm_st_09" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 10 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "nw_ch_fm_st_09" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 9 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "nw_ch_fm_st_09" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 8 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "nw_ch_fm_st_09" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 7 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "nw_ch_fm_st_09" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 6 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "nw_ch_fm_st_09" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 5 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 4 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58436 + } + } + }, + { + "__struct_id": 3, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "nw_ch_fm_st_09" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 12 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 11 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58437 + } + } + }, + { + "__struct_id": 4, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "nw_ch_fm_st_03" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 15 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "nw_ch_fm_st_04" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 14 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 13 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58438 + } + } + }, + { + "__struct_id": 5, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "nw_ch_fm_st_11" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 17 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 16 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58439 + } + } + }, + { + "__struct_id": 6, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 18 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Me needs you to do something for me.", + "id": 58440 + } + } + }, + { + "__struct_id": 7, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 18 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I would like you to do something different for me.", + "id": 58441 + } + } + }, + { + "__struct_id": 8, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Nevermind." + } + } + }, + { + "__struct_id": 9, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "BaseMode" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 0 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lets do something else." + } + } + }, + { + "__struct_id": 10, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 19 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I need you to summon something if you can." + } + } + }, + { + "__struct_id": 11, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "178" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Summon Creature IX.", + "id": 88353 + } + } + }, + { + "__struct_id": 12, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "182" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Summon Creature VIII.", + "id": 88354 + } + } + }, + { + "__struct_id": 13, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "181" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Summon Creature VII.", + "id": 88355 + } + } + }, + { + "__struct_id": 14, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "180" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Summon Creature VI.", + "id": 88356 + } + } + }, + { + "__struct_id": 15, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "179" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Summon Creature V.", + "id": 88358 + } + } + }, + { + "__struct_id": 16, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "177" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Summon Creature IV.", + "id": 88358 + } + } + }, + { + "__struct_id": 17, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "176" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Summon Creature III.", + "id": 88359 + } + } + }, + { + "__struct_id": 18, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "175" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Summon Creature II.", + "id": 88360 + } + } + }, + { + "__struct_id": 19, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "174" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Summon Creature I.", + "id": 88361 + } + } + }, + { + "__struct_id": 20, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "30" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Create Undead.", + "id": 88425 + } + } + }, + { + "__struct_id": 21, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Animate Dead.", + "id": 88446 + } + } + }, + { + "__struct_id": 22, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "No, I've changed my mind.", + "id": 88415 + } + } + }, + { + "__struct_id": 23, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sTarget" + }, + "Value": { + "type": "cexostring", + "value": "Henchmen" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Yes, go ahead.", + "id": 88416 + } + } + }, + { + "__struct_id": 24, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "x2_hen_tomishad4" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Summon Shadow." + } + } + }, + { + "__struct_id": 25, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAssociate" + }, + "Value": { + "type": "cexostring", + "value": "Familiar" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_summon_assoc" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Your Familiar." + } + } + }, + { + "__struct_id": 26, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAssociate" + }, + "Value": { + "type": "cexostring", + "value": "Companion" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_summon_assoc" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Your Companion." + } + } + }, + { + "__struct_id": 27, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 21 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Let us talk about your defensive spells.", + "id": 89061 + } + } + }, + { + "__struct_id": 28, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 22 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast all your defensive spells.", + "id": 89063 + } + } + }, + { + "__struct_id": 29, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast on all the party members.", + "id": 88431 + } + } + }, + { + "__struct_id": 30, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "6" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88437 + } + } + }, + { + "__struct_id": 31, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "5" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88438 + } + } + }, + { + "__struct_id": 32, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88439 + } + } + }, + { + "__struct_id": 33, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88440 + } + } + }, + { + "__struct_id": 34, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "8" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my animal companion.", + "id": 88441 + } + } + }, + { + "__struct_id": 35, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "7" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my familiar.", + "id": 88442 + } + } + }, + { + "__struct_id": 36, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on me.", + "id": 88443 + } + } + }, + { + "__struct_id": 37, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on yourself.", + "id": 88444 + } + } + }, + { + "__struct_id": 38, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 23 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast all your long duration defensive spells.", + "id": 89064 + } + } + }, + { + "__struct_id": 39, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast on all the party members.", + "id": 88431 + } + } + }, + { + "__struct_id": 40, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "6" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88437 + } + } + }, + { + "__struct_id": 41, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "5" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88438 + } + } + }, + { + "__struct_id": 42, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88439 + } + } + }, + { + "__struct_id": 43, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88440 + } + } + }, + { + "__struct_id": 44, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "8" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my animal companion.", + "id": 88441 + } + } + }, + { + "__struct_id": 45, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "7" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my familiar.", + "id": 88442 + } + } + }, + { + "__struct_id": 46, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on me.", + "id": 88443 + } + } + }, + { + "__struct_id": 47, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on yourself.", + "id": 88444 + } + } + }, + { + "__struct_id": 48, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 24 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast all your short duration defensive spells.", + "id": 89065 + } + } + }, + { + "__struct_id": 49, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast on all the party members.", + "id": 88431 + } + } + }, + { + "__struct_id": 50, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "6" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88437 + } + } + }, + { + "__struct_id": 51, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "5" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88438 + } + } + }, + { + "__struct_id": 52, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88439 + } + } + }, + { + "__struct_id": 53, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88440 + } + } + }, + { + "__struct_id": 54, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "8" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my animal companion.", + "id": 88441 + } + } + }, + { + "__struct_id": 55, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "7" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my familiar.", + "id": 88442 + } + } + }, + { + "__struct_id": 56, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on me.", + "id": 88443 + } + } + }, + { + "__struct_id": 57, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on yourself.", + "id": 88444 + } + } + }, + { + "__struct_id": 58, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "RestBuffing" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 21 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change if you cast long duration spells after resting." + } + } + }, + { + "__struct_id": 59, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 25 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I need you to cast a spell.", + "id": 88348 + } + } + }, + { + "__struct_id": 60, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "441" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 26 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Wounding Whispers.", + "id": 88350 + } + } + }, + { + "__struct_id": 61, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "365" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Ultravision.", + "id": 88351 + } + } + }, + { + "__struct_id": 62, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "186" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "True Seeing.", + "id": 88352 + } + } + }, + { + "__struct_id": 63, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "172" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Stoneskin.", + "id": 88362 + } + } + }, + { + "__struct_id": 64, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "168" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Spell Resistance.", + "id": 88363 + } + } + }, + { + "__struct_id": 65, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "169" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 26 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Spell Mantle.", + "id": 88364 + } + } + }, + { + "__struct_id": 66, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "450" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 26 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Shield of Faith.", + "id": 88365 + } + } + }, + { + "__struct_id": 67, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "417" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 26 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Shield.", + "id": 88366 + } + } + }, + { + "__struct_id": 68, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "159" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 26 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Shadow Shield.", + "id": 88367 + } + } + }, + { + "__struct_id": 69, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "157" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "See Invisibility.", + "id": 88368 + } + } + }, + { + "__struct_id": 70, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "154" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 26 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Sanctuary.", + "id": 88369 + } + } + }, + { + "__struct_id": 71, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "152" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Restoration.", + "id": 88370 + } + } + }, + { + "__struct_id": 72, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "151" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Resistance.", + "id": 88371 + } + } + }, + { + "__struct_id": 73, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "150" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Resist Elements.", + "id": 88372 + } + } + }, + { + "__struct_id": 74, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "149" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Remove Paralysis.", + "id": 88373 + } + } + }, + { + "__struct_id": 75, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "148" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Remove Fear.", + "id": 88374 + } + } + }, + { + "__struct_id": 76, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "147" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Remove Disease.", + "id": 88375 + } + } + }, + { + "__struct_id": 77, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "146" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Remove Curse.", + "id": 88376 + } + } + }, + { + "__struct_id": 78, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "145" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 26 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Remove Blindness/Deafness.", + "id": 88377 + } + } + }, + { + "__struct_id": 79, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "374" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Regenerate.", + "id": 88378 + } + } + }, + { + "__struct_id": 80, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "141" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Protection From Spells.", + "id": 88379 + } + } + }, + { + "__struct_id": 81, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "321" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Protection From Evil." + } + } + }, + { + "__struct_id": 82, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "137" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Protection From Elements.", + "id": 88380 + } + } + }, + { + "__struct_id": 83, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "134" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 26 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Premonition.", + "id": 88381 + } + } + }, + { + "__struct_id": 84, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "133" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 26 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Prayer.", + "id": 88382 + } + } + }, + { + "__struct_id": 85, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "355" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Owl's Wisdom.", + "id": 88383 + } + } + }, + { + "__struct_id": 86, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "126" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Neutralize poison.", + "id": 88384 + } + } + }, + { + "__struct_id": 87, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "525" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Monstrous Regeneration.", + "id": 88385 + } + } + }, + { + "__struct_id": 88, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "119" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 26 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Minor Globe of Invulnerability.", + "id": 88386 + } + } + }, + { + "__struct_id": 89, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "117" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Mind Blank.", + "id": 88387 + } + } + }, + { + "__struct_id": 90, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "113" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Mass Haste.", + "id": 88388 + } + } + }, + { + "__struct_id": 91, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "108" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Magical Vestment.", + "id": 88389 + } + } + }, + { + "__struct_id": 92, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "102" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Mage Armor.", + "id": 88390 + } + } + }, + { + "__struct_id": 93, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "100" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Light.", + "id": 88391 + } + } + }, + { + "__struct_id": 94, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "99" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 26 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lesser Spell Mantle.", + "id": 88392 + } + } + }, + { + "__struct_id": 95, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "97" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lesser Restoration.", + "id": 88393 + } + } + }, + { + "__struct_id": 96, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "95" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lesser Mind Blank", + "id": 88394 + } + } + }, + { + "__struct_id": 97, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "94" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lesser Dispel.", + "id": 88395 + } + } + }, + { + "__struct_id": 98, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "93" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 26 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Knock.", + "id": 88396 + } + } + }, + { + "__struct_id": 99, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "92" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 26 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Invisibility Sphere.", + "id": 88397 + } + } + }, + { + "__struct_id": 100, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "90" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Invisibility", + "id": 88398 + } + } + }, + { + "__struct_id": 101, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "88" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Improved Invisibility.", + "id": 88399 + } + } + }, + { + "__struct_id": 102, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "78" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Haste.", + "id": 88400 + } + } + }, + { + "__struct_id": 103, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "74" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Greater Stoneskin.", + "id": 88401 + } + } + }, + { + "__struct_id": 104, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "73" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 26 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Greater Spell Mantle.", + "id": 88402 + } + } + }, + { + "__struct_id": 105, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "443" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 26 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Greater Sanctuary.", + "id": 88403 + } + } + }, + { + "__struct_id": 106, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "70" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Greater Restoration.", + "id": 88404 + } + } + }, + { + "__struct_id": 107, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "109" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Greater Magic Weapon.", + "id": 88405 + } + } + }, + { + "__struct_id": 108, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "67" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Greater Dispelling.", + "id": 88406 + } + } + }, + { + "__struct_id": 109, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "65" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 26 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Globe of Invulnerability.", + "id": 88407 + } + } + }, + { + "__struct_id": 110, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "120" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 26 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Ghostly Visage.", + "id": 88408 + } + } + }, + { + "__struct_id": 111, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "62" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Freedom of Movement.", + "id": 88409 + } + } + }, + { + "__struct_id": 112, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "356" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Fox's Cunning", + "id": 88410 + } + } + }, + { + "__struct_id": 113, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "377" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 26 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Find Traps.", + "id": 88411 + } + } + }, + { + "__struct_id": 114, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "121" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 26 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Ethereal Visage.", + "id": 88412 + } + } + }, + { + "__struct_id": 115, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "418" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 26 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Entropic Shield.", + "id": 88413 + } + } + }, + { + "__struct_id": 116, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "369" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 26 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Energy Buffer.", + "id": 88414 + } + } + }, + { + "__struct_id": 117, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "No, I've changed my mind.", + "id": 88415 + } + } + }, + { + "__struct_id": 118, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Yes, go ahead.", + "id": 88416 + } + } + }, + { + "__struct_id": 119, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "50" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Endure Elements.", + "id": 88417 + } + } + }, + { + "__struct_id": 120, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "49" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Endurance.", + "id": 88418 + } + } + }, + { + "__struct_id": 121, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "47" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 26 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Elemental Shield.", + "id": 88419 + } + } + }, + { + "__struct_id": 122, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "354" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Eagle's Splendour.", + "id": 88420 + } + } + }, + { + "__struct_id": 123, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "42" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 26 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Divine Power.", + "id": 88421 + } + } + }, + { + "__struct_id": 124, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "41" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Dispel Magic.", + "id": 88422 + } + } + }, + { + "__struct_id": 125, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "38" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Death Ward.", + "id": 88423 + } + } + }, + { + "__struct_id": 126, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "519" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 26 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Death Armor.", + "id": 88424 + } + } + }, + { + "__struct_id": 127, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "419" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Continual Flame.", + "id": 88426 + } + } + }, + { + "__struct_id": 128, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "21" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Clarity.", + "id": 88427 + } + } + }, + { + "__struct_id": 129, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "13" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cat's Grace.", + "id": 88428 + } + } + }, + { + "__struct_id": 130, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "9" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Bull's Strength.", + "id": 88429 + } + } + }, + { + "__struct_id": 131, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "6" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88437 + } + } + }, + { + "__struct_id": 132, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "5" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88438 + } + } + }, + { + "__struct_id": 133, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88439 + } + } + }, + { + "__struct_id": 134, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88440 + } + } + }, + { + "__struct_id": 135, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "8" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my animal companion.", + "id": 88441 + } + } + }, + { + "__struct_id": 136, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "7" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my familiar.", + "id": 88442 + } + } + }, + { + "__struct_id": 137, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on me.", + "id": 88443 + } + } + }, + { + "__struct_id": 138, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on yourself.", + "id": 88444 + } + } + }, + { + "__struct_id": 139, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "6" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Bless.", + "id": 88445 + } + } + }, + { + "__struct_id": 140, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Aid.", + "id": 88447 + } + } + }, + { + "__struct_id": 141, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 28 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I need you to cast a healing spell." + } + } + }, + { + "__struct_id": 142, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Heal up the whole party.", + "id": 88431 + } + } + }, + { + "__struct_id": 143, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "6" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88437 + } + } + }, + { + "__struct_id": 144, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "5" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88438 + } + } + }, + { + "__struct_id": 145, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88439 + } + } + }, + { + "__struct_id": 146, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "Target" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88440 + } + } + }, + { + "__struct_id": 147, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "8" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my animal companion.", + "id": 88441 + } + } + }, + { + "__struct_id": 148, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "7" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my familiar.", + "id": 88442 + } + } + }, + { + "__struct_id": 149, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on me.", + "id": 88443 + } + } + }, + { + "__struct_id": 150, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on yourself.", + "id": 88444 + } + } + }, + { + "__struct_id": 151, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Plans" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I want to discuss your tactics." + } + } + }, + { + "__struct_id": 152, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 18 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lets talk about something else." + } + } + }, + { + "__struct_id": 153, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 30 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lets discuss how you deal with objects." + } + } + }, + { + "__struct_id": 154, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Bash" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 30 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change your bashing tactics.", + "id": 96501 + } + } + }, + { + "__struct_id": 155, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Locks" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 30 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change your lock picking tactics.", + "id": 96501 + } + } + }, + { + "__struct_id": 156, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Traps" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 30 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change your trap tactics.", + "id": 96502 + } + } + }, + { + "__struct_id": 157, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Search" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Plans" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I need you to change your search tactics." + } + } + }, + { + "__struct_id": 158, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Stealth" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Plans" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I need you to change your stealth tactics." + } + } + }, + { + "__struct_id": 159, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 31 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Let's change how you use magic in combat." + } + } + }, + { + "__struct_id": 160, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "MagicItems" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 31 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change if you use magic items or not.", + "id": 96498 + } + } + }, + { + "__struct_id": 161, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Dispel" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 31 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change your dispel tactics.", + "id": 96500 + } + } + }, + { + "__struct_id": 162, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "BasicTactics" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 31 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Stop countering the enemies spells.", + "2": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"", + "3": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"" + } + } + }, + { + "__struct_id": 163, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "CounterSpell" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 31 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I want you to counter spell the enemy!", + "2": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"", + "3": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"" + } + } + }, + { + "__struct_id": 164, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "BuffFirst" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 31 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change who you cast defensive spells on first.", + "id": 96500 + } + } + }, + { + "__struct_id": 165, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "OffensiveCasting" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 31 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change if you cast offensive spells.", + "id": 96498 + } + } + }, + { + "__struct_id": 166, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "DefensiveCasting" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 31 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change if you cast defensive spells.", + "id": 96498 + } + } + }, + { + "__struct_id": 167, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "NoMagic" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 31 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change how you use magic spells in combat." + } + } + }, + { + "__struct_id": 168, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "MagicPlus" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 31 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use your magic more in combat." + } + } + }, + { + "__struct_id": 169, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "MagicMinus" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 31 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use your magic less in combat." + } + } + }, + { + "__struct_id": 170, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Healing" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 32 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lets change when you decide to heal me.", + "id": 54985 + } + } + }, + { + "__struct_id": 171, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "HealOutPlus" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Healing" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 32 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Increase the health an one needs for you to heal out of combat.", + "id": 54991 + } + } + }, + { + "__struct_id": 172, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "HealOutMinus" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Healing" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 32 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Reduce the health an one needs for you to heal out of combat.", + "id": 54991 + } + } + }, + { + "__struct_id": 173, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "HealInPlus" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Healing" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 32 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Increase the health an one needs for you to heal during combat.", + "id": 54991 + } + } + }, + { + "__struct_id": 174, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "HealInMinus" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Healing" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 32 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Reduce the health any one needs for you to heal during combat.", + "id": 54991 + } + } + }, + { + "__struct_id": 175, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "HealSelf" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Healing" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 32 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change if you heal yourself.", + "id": 54990 + } + } + }, + { + "__struct_id": 176, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "HealAllies" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Healing" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 32 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change if you heal any allies.", + "id": 54989 + } + } + }, + { + "__struct_id": 177, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Pickup" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Plans" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lets change if you retrieve items and gold." + } + } + }, + { + "__struct_id": 178, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "FollowFarther" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Plans" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Follow farther away from me.", + "id": 96508 + } + } + }, + { + "__struct_id": 179, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "FollowCloser" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Plans" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Follow closer to me.", + "id": 96508 + } + } + }, + { + "__struct_id": 180, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 33 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lets talk about your tactics in combat." + } + } + }, + { + "__struct_id": 181, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "AttackTactics" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 33 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change if you fight every opponent during combat." + } + } + }, + { + "__struct_id": 182, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "AtkAssociates" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 33 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change your tactics against familiars, companions, and summons." + } + } + }, + { + "__struct_id": 183, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Ranged" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 33 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change your ranged combat tactics." + } + } + }, + { + "__struct_id": 184, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "CounterSpell" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 33 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I want you to counter spell the enemy!" + } + } + }, + { + "__struct_id": 185, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Taunt" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 33 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I want you to taunt the enemy!" + } + } + }, + { + "__struct_id": 186, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "PeaceTactics" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 33 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Don't engage in combat." + } + } + }, + { + "__struct_id": 187, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "RangedTactics" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 34 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use agressive ranged tactics, stay out of melee.", + "2": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"", + "3": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"" + } + } + }, + { + "__struct_id": 188, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "That will be all for now." + } + } + }, + { + "__struct_id": 189, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Plans" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 35 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I want to discuss how we can work together." + } + } + }, + { + "__struct_id": 190, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "BaseMode" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 36 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lets talk about something else." + } + } + }, + { + "__struct_id": 191, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_get_convo" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Let us talk about something completely different." + } + } + }, + { + "__struct_id": 192, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 37 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "We should part ways." + } + } + }, + { + "__struct_id": 193, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "No, I like having you around." + } + } + }, + { + "__struct_id": 194, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_fire_henchmen" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Yes I'm sure, Perhapse we'll meet again." + } + } + }, + { + "__struct_id": 195, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 38 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Can you use a special ability?", + "id": 96382 + } + } + }, + { + "__struct_id": 196, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "x2_d2_dshield" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Divine Shield.", + "id": 96383 + } + } + }, + { + "__struct_id": 197, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "x2_d2_dmight" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Divine Might.", + "id": 96384 + } + } + }, + { + "__struct_id": 198, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 39 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lay on Hands.", + "id": 96385 + } + } + }, + { + "__struct_id": 199, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I've changed my mind.", + "id": 88430 + } + } + }, + { + "__struct_id": 200, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "6" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "5" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88437 + } + } + }, + { + "__struct_id": 201, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "5" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "5" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88438 + } + } + }, + { + "__struct_id": 202, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "5" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88439 + } + } + }, + { + "__struct_id": 203, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "5" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88440 + } + } + }, + { + "__struct_id": 204, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "8" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "5" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my animal companion.", + "id": 88441 + } + } + }, + { + "__struct_id": 205, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "7" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "5" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my familiar.", + "id": 88442 + } + } + }, + { + "__struct_id": 206, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "5" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on me.", + "id": 88443 + } + } + }, + { + "__struct_id": 207, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "5" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on yourself.", + "id": 88444 + } + } + }, + { + "__struct_id": 208, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nFeat" + }, + "Value": { + "type": "cexostring", + "value": "257" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_use_feat" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use your bard song.", + "id": 88342 + } + } + }, + { + "__struct_id": 209, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 40 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use your construction shape.", + "id": 88342 + } + } + }, + { + "__struct_id": 210, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "740" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Iron Golem" + } + } + }, + { + "__struct_id": 211, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "739" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Demon Flesh Golem" + } + } + }, + { + "__struct_id": 212, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "738" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Stone Golem" + } + } + }, + { + "__struct_id": 213, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 41 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use your outsider shape.", + "id": 88342 + } + } + }, + { + "__struct_id": 214, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "735" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Death Slaad" + } + } + }, + { + "__struct_id": 215, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "734" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Rakshasa" + } + } + }, + { + "__struct_id": 216, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "733" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Azer" + } + } + }, + { + "__struct_id": 217, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 42 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use your humanoid shape.", + "id": 88342 + } + } + }, + { + "__struct_id": 218, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "684" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Kobold Assasin" + } + } + }, + { + "__struct_id": 219, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "683" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lizard folk" + } + } + }, + { + "__struct_id": 220, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "682" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Drow" + } + } + }, + { + "__struct_id": 221, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 43 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use your greater wild shape V.", + "id": 88342 + } + } + }, + { + "__struct_id": 222, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "691" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Mindflayer" + } + } + }, + { + "__struct_id": 223, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "679" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Medusa" + } + } + }, + { + "__struct_id": 224, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "694" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Dire Tiger" + } + } + }, + { + "__struct_id": 225, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 44 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use your greater wild shape III.", + "id": 88342 + } + } + }, + { + "__struct_id": 226, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "674" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Manticore" + } + } + }, + { + "__struct_id": 227, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "673" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Drider" + } + } + }, + { + "__struct_id": 228, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "670" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Basilisk" + } + } + }, + { + "__struct_id": 229, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 45 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use your greater wild shape II.", + "id": 88342 + } + } + }, + { + "__struct_id": 230, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "680" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Minotaur" + } + } + }, + { + "__struct_id": 231, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "678" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Gargoyle" + } + } + }, + { + "__struct_id": 232, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "672" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Harpy" + } + } + }, + { + "__struct_id": 233, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 46 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use your greater wild shape I.", + "id": 88342 + } + } + }, + { + "__struct_id": 234, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "662" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Green Wyrmling" + } + } + }, + { + "__struct_id": 235, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "661" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "White Wyrmling" + } + } + }, + { + "__struct_id": 236, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "660" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Black Wyrmling" + } + } + }, + { + "__struct_id": 237, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "659" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Blue Wyrmling" + } + } + }, + { + "__struct_id": 238, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "658" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Red Wyrmling" + } + } + }, + { + "__struct_id": 239, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 47 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use your elemental shape.", + "id": 88342 + } + } + }, + { + "__struct_id": 240, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "398" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Water" + } + } + }, + { + "__struct_id": 241, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "397" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Fire" + } + } + }, + { + "__struct_id": 242, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "399" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Earth" + } + } + }, + { + "__struct_id": 243, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "400" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Air" + } + } + }, + { + "__struct_id": 244, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 48 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use your wild shape.", + "id": 88342 + } + } + }, + { + "__struct_id": 245, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "405" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Badger" + } + } + }, + { + "__struct_id": 246, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "404" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Boar" + } + } + }, + { + "__struct_id": 247, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "403" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Wolf" + } + } + }, + { + "__struct_id": 248, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "402" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Panther" + } + } + }, + { + "__struct_id": 249, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "401" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Bear" + } + } + }, + { + "__struct_id": 250, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nEffectType" + }, + "Value": { + "type": "cexostring", + "value": "62" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "BaseMode" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 36 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_remove_effect" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Transform back into your natural form.", + "id": 96384 + } + } + }, + { + "__struct_id": 251, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 49 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I need you to summon something if you can." + } + } + }, + { + "__struct_id": 252, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "178" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 55 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Summon Creature IX.", + "id": 88353 + } + } + }, + { + "__struct_id": 253, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "182" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 55 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Summon Creature VIII.", + "id": 88354 + } + } + }, + { + "__struct_id": 254, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "181" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 55 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Summon Creature VII.", + "id": 88355 + } + } + }, + { + "__struct_id": 255, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "180" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 55 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Summon Creature VI.", + "id": 88356 + } + } + }, + { + "__struct_id": 256, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "179" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 55 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Summon Creature V.", + "id": 88358 + } + } + }, + { + "__struct_id": 257, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "177" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 55 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Summon Creature IV.", + "id": 88358 + } + } + }, + { + "__struct_id": 258, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "176" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 55 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Summon Creature III.", + "id": 88359 + } + } + }, + { + "__struct_id": 259, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "175" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 55 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Summon Creature II.", + "id": 88360 + } + } + }, + { + "__struct_id": 260, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "174" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 55 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Summon Creature I.", + "id": 88361 + } + } + }, + { + "__struct_id": 261, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "30" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 55 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Create Undead.", + "id": 88425 + } + } + }, + { + "__struct_id": 262, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 55 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Animate Dead.", + "id": 88446 + } + } + }, + { + "__struct_id": 263, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "x2_hen_tomishad4" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Summon Shadow." + } + } + }, + { + "__struct_id": 264, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAssociate" + }, + "Value": { + "type": "cexostring", + "value": "Familiar" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_summon_assoc" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Your Familiar." + } + } + }, + { + "__struct_id": 265, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAssociate" + }, + "Value": { + "type": "cexostring", + "value": "Companion" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_summon_assoc" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Your Companion." + } + } + }, + { + "__struct_id": 266, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "RestBuffing" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 50 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Let us talk about your defensive spells.", + "id": 89061 + } + } + }, + { + "__struct_id": 267, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 51 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast all your defensive spells.", + "id": 89063 + } + } + }, + { + "__struct_id": 268, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast on all the party members.", + "id": 88431 + } + } + }, + { + "__struct_id": 269, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "6" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88437 + } + } + }, + { + "__struct_id": 270, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "5" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88438 + } + } + }, + { + "__struct_id": 271, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88439 + } + } + }, + { + "__struct_id": 272, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88440 + } + } + }, + { + "__struct_id": 273, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "8" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my animal companion.", + "id": 88441 + } + } + }, + { + "__struct_id": 274, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "7" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my familiar.", + "id": 88442 + } + } + }, + { + "__struct_id": 275, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on me.", + "id": 88443 + } + } + }, + { + "__struct_id": 276, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on yourself.", + "id": 88444 + } + } + }, + { + "__struct_id": 277, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 52 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast all your long duration defensive spells.", + "id": 89064 + } + } + }, + { + "__struct_id": 278, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast on all the party members.", + "id": 88431 + } + } + }, + { + "__struct_id": 279, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "6" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88437 + } + } + }, + { + "__struct_id": 280, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "5" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88438 + } + } + }, + { + "__struct_id": 281, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88439 + } + } + }, + { + "__struct_id": 282, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88440 + } + } + }, + { + "__struct_id": 283, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "8" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my animal companion.", + "id": 88441 + } + } + }, + { + "__struct_id": 284, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "7" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my familiar.", + "id": 88442 + } + } + }, + { + "__struct_id": 285, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on me.", + "id": 88443 + } + } + }, + { + "__struct_id": 286, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on yourself.", + "id": 88444 + } + } + }, + { + "__struct_id": 287, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 53 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast all your short duration defensive spells.", + "id": 89065 + } + } + }, + { + "__struct_id": 288, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast on all the party members.", + "id": 88431 + } + } + }, + { + "__struct_id": 289, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "6" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88437 + } + } + }, + { + "__struct_id": 290, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "5" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88438 + } + } + }, + { + "__struct_id": 291, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88439 + } + } + }, + { + "__struct_id": 292, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88440 + } + } + }, + { + "__struct_id": 293, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "8" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my animal companion.", + "id": 88441 + } + } + }, + { + "__struct_id": 294, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "7" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my familiar.", + "id": 88442 + } + } + }, + { + "__struct_id": 295, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on me.", + "id": 88443 + } + } + }, + { + "__struct_id": 296, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on yourself.", + "id": 88444 + } + } + }, + { + "__struct_id": 297, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "RestBuffing" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "RestBuffing" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 50 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change if you cast long duration spells after resting." + } + } + }, + { + "__struct_id": 298, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 54 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I need you to cast a spell.", + "id": 88348 + } + } + }, + { + "__struct_id": 299, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "441" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 55 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Wounding Whispers.", + "id": 88350 + } + } + }, + { + "__struct_id": 300, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "365" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Ultravision.", + "id": 88351 + } + } + }, + { + "__struct_id": 301, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "186" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "True Seeing.", + "id": 88352 + } + } + }, + { + "__struct_id": 302, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "172" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Stoneskin.", + "id": 88362 + } + } + }, + { + "__struct_id": 303, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "168" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Spell Resistance.", + "id": 88363 + } + } + }, + { + "__struct_id": 304, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "169" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 55 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Spell Mantle.", + "id": 88364 + } + } + }, + { + "__struct_id": 305, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "450" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 55 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Shield of Faith.", + "id": 88365 + } + } + }, + { + "__struct_id": 306, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "417" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 55 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Shield.", + "id": 88366 + } + } + }, + { + "__struct_id": 307, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "159" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 55 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Shadow Shield.", + "id": 88367 + } + } + }, + { + "__struct_id": 308, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "157" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "See Invisibility.", + "id": 88368 + } + } + }, + { + "__struct_id": 309, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "154" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 55 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Sanctuary.", + "id": 88369 + } + } + }, + { + "__struct_id": 310, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "152" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Restoration.", + "id": 88370 + } + } + }, + { + "__struct_id": 311, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "151" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Resistance.", + "id": 88371 + } + } + }, + { + "__struct_id": 312, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "150" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Resist Elements.", + "id": 88372 + } + } + }, + { + "__struct_id": 313, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "149" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Remove Paralysis.", + "id": 88373 + } + } + }, + { + "__struct_id": 314, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "148" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Remove Fear.", + "id": 88374 + } + } + }, + { + "__struct_id": 315, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "147" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Remove Disease.", + "id": 88375 + } + } + }, + { + "__struct_id": 316, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "146" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Remove Curse.", + "id": 88376 + } + } + }, + { + "__struct_id": 317, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "145" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 55 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Remove Blindness/Deafness.", + "id": 88377 + } + } + }, + { + "__struct_id": 318, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "374" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Regenerate.", + "id": 88378 + } + } + }, + { + "__struct_id": 319, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "141" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Protection From Spells.", + "id": 88379 + } + } + }, + { + "__struct_id": 320, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "321" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Protection From Evil." + } + } + }, + { + "__struct_id": 321, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "137" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Protection From Elements.", + "id": 88380 + } + } + }, + { + "__struct_id": 322, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "134" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 55 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Premonition.", + "id": 88381 + } + } + }, + { + "__struct_id": 323, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "133" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 55 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Prayer.", + "id": 88382 + } + } + }, + { + "__struct_id": 324, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "355" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Owl's Wisdom.", + "id": 88383 + } + } + }, + { + "__struct_id": 325, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "126" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Neutralize poison.", + "id": 88384 + } + } + }, + { + "__struct_id": 326, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "525" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Monstrous Regeneration.", + "id": 88385 + } + } + }, + { + "__struct_id": 327, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "119" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 55 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Minor Globe of Invulnerability.", + "id": 88386 + } + } + }, + { + "__struct_id": 328, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "117" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Mind Blank.", + "id": 88387 + } + } + }, + { + "__struct_id": 329, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "113" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Mass Haste.", + "id": 88388 + } + } + }, + { + "__struct_id": 330, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "108" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Magical Vestment.", + "id": 88389 + } + } + }, + { + "__struct_id": 331, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "102" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Mage Armor.", + "id": 88390 + } + } + }, + { + "__struct_id": 332, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "100" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Light.", + "id": 88391 + } + } + }, + { + "__struct_id": 333, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "99" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 55 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lesser Spell Mantle.", + "id": 88392 + } + } + }, + { + "__struct_id": 334, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "97" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lesser Restoration.", + "id": 88393 + } + } + }, + { + "__struct_id": 335, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "95" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lesser Mind Blank", + "id": 88394 + } + } + }, + { + "__struct_id": 336, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "94" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lesser Dispel.", + "id": 88395 + } + } + }, + { + "__struct_id": 337, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "93" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 55 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Knock.", + "id": 88396 + } + } + }, + { + "__struct_id": 338, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "92" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 55 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Invisibility Sphere.", + "id": 88397 + } + } + }, + { + "__struct_id": 339, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "90" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Invisibility", + "id": 88398 + } + } + }, + { + "__struct_id": 340, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "88" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Improved Invisibility.", + "id": 88399 + } + } + }, + { + "__struct_id": 341, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "78" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Haste.", + "id": 88400 + } + } + }, + { + "__struct_id": 342, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "74" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Greater Stoneskin.", + "id": 88401 + } + } + }, + { + "__struct_id": 343, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "73" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 55 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Greater Spell Mantle.", + "id": 88402 + } + } + }, + { + "__struct_id": 344, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "443" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 55 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Greater Sanctuary.", + "id": 88403 + } + } + }, + { + "__struct_id": 345, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "70" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Greater Restoration.", + "id": 88404 + } + } + }, + { + "__struct_id": 346, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "109" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Greater Magic Weapon.", + "id": 88405 + } + } + }, + { + "__struct_id": 347, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "67" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Greater Dispelling.", + "id": 88406 + } + } + }, + { + "__struct_id": 348, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "65" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 55 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Globe of Invulnerability.", + "id": 88407 + } + } + }, + { + "__struct_id": 349, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "120" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 55 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Ghostly Visage.", + "id": 88408 + } + } + }, + { + "__struct_id": 350, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "62" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Freedom of Movement.", + "id": 88409 + } + } + }, + { + "__struct_id": 351, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "356" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Fox's Cunning", + "id": 88410 + } + } + }, + { + "__struct_id": 352, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "377" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 55 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Find Traps.", + "id": 88411 + } + } + }, + { + "__struct_id": 353, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "121" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 55 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Ethereal Visage.", + "id": 88412 + } + } + }, + { + "__struct_id": 354, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "418" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 55 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Entropic Shield.", + "id": 88413 + } + } + }, + { + "__struct_id": 355, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "369" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 55 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Energy Buffer.", + "id": 88414 + } + } + }, + { + "__struct_id": 356, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "No, I've changed my mind.", + "id": 88415 + } + } + }, + { + "__struct_id": 357, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Yes, go ahead.", + "id": 88416 + } + } + }, + { + "__struct_id": 358, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "50" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Endure Elements.", + "id": 88417 + } + } + }, + { + "__struct_id": 359, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "49" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Endurance.", + "id": 88418 + } + } + }, + { + "__struct_id": 360, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "47" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 55 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Elemental Shield.", + "id": 88419 + } + } + }, + { + "__struct_id": 361, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "354" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Eagle's Splendour.", + "id": 88420 + } + } + }, + { + "__struct_id": 362, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "42" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 55 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Divine Power.", + "id": 88421 + } + } + }, + { + "__struct_id": 363, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "41" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Dispel Magic.", + "id": 88422 + } + } + }, + { + "__struct_id": 364, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "38" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Death Ward.", + "id": 88423 + } + } + }, + { + "__struct_id": 365, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "519" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 55 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Death Armor.", + "id": 88424 + } + } + }, + { + "__struct_id": 366, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "419" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Continual Flame.", + "id": 88426 + } + } + }, + { + "__struct_id": 367, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "21" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Clarity.", + "id": 88427 + } + } + }, + { + "__struct_id": 368, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "13" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cat's Grace.", + "id": 88428 + } + } + }, + { + "__struct_id": 369, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "9" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Bull's Strength.", + "id": 88429 + } + } + }, + { + "__struct_id": 370, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "6" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88437 + } + } + }, + { + "__struct_id": 371, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "5" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88438 + } + } + }, + { + "__struct_id": 372, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88439 + } + } + }, + { + "__struct_id": 373, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88440 + } + } + }, + { + "__struct_id": 374, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "8" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my animal companion.", + "id": 88441 + } + } + }, + { + "__struct_id": 375, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "7" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my familiar.", + "id": 88442 + } + } + }, + { + "__struct_id": 376, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on me.", + "id": 88443 + } + } + }, + { + "__struct_id": 377, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on yourself.", + "id": 88444 + } + } + }, + { + "__struct_id": 378, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "6" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Bless.", + "id": 88445 + } + } + }, + { + "__struct_id": 379, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Aid.", + "id": 88447 + } + } + }, + { + "__struct_id": 380, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 57 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I need you to cast a healing spell." + } + } + }, + { + "__struct_id": 381, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "BaseMode" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 36 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I've changed my mind.", + "id": 88430 + } + } + }, + { + "__struct_id": 382, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Heal up the whole party.", + "id": 88431 + } + } + }, + { + "__struct_id": 383, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "6" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88437 + } + } + }, + { + "__struct_id": 384, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "5" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88438 + } + } + }, + { + "__struct_id": 385, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88439 + } + } + }, + { + "__struct_id": 386, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88440 + } + } + }, + { + "__struct_id": 387, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "8" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my animal companion.", + "id": 88441 + } + } + }, + { + "__struct_id": 388, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "7" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my familiar.", + "id": 88442 + } + } + }, + { + "__struct_id": 389, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on me.", + "id": 88443 + } + } + }, + { + "__struct_id": 390, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on yourself.", + "id": 88444 + } + } + }, + { + "__struct_id": 391, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 58 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Can we talk about your items?" + } + } + }, + { + "__struct_id": 392, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "GiveMagicItems" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Give me all the magical items in your inventory.", + "id": 96514 + } + } + }, + { + "__struct_id": 393, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "GiveUnIdentifiedItems" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Give me all your unidentified items.", + "id": 96514 + } + } + }, + { + "__struct_id": 394, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "x0_d1_hen_inven" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I want to adjust your equipment.", + "id": 96514 + } + } + }, + { + "__struct_id": 395, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "x1_hen_identify" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Can you identify our equipment?", + "id": 88341 + } + } + }, + { + "__struct_id": 396, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Scout" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I would like you to scout the area." + } + } + }, + { + "__struct_id": 397, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Objects" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 59 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lets discuss how you deal with objects." + } + } + }, + { + "__struct_id": 398, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Bash" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Objects" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 59 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change your bashing tactics.", + "id": 96507 + } + } + }, + { + "__struct_id": 399, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Locks" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Objects" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 59 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change your lock picking tactics.", + "id": 96507 + } + } + }, + { + "__struct_id": 400, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Traps" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Objects" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 59 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change your trap tactics.", + "id": 96502 + } + } + }, + { + "__struct_id": 401, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Search" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Plans" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 35 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I need you to change your search tactics.", + "id": 96505 + } + } + }, + { + "__struct_id": 402, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Stealth" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Plans" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 35 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I need you to change your stealth tactics.", + "id": 96505 + } + } + }, + { + "__struct_id": 403, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 60 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Let's change how you use magic in combat." + } + } + }, + { + "__struct_id": 404, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "MagicItems" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 60 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change if you use magic items or not.", + "id": 96498 + } + } + }, + { + "__struct_id": 405, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Dispel" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 60 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change your dispel tactics.", + "id": 96500 + } + } + }, + { + "__struct_id": 406, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "BasicTactics" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 60 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Stop countering the enemies spells.", + "2": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"", + "3": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"" + } + } + }, + { + "__struct_id": 407, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "CounterSpell" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 60 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Counter the enemy spells!", + "2": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"", + "3": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"" + } + } + }, + { + "__struct_id": 408, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "BuffFirst" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 60 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change who you cast defensive spells on first.", + "id": 96500 + } + } + }, + { + "__struct_id": 409, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "OffensiveCasting" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 60 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Only cast offensive spells for now.", + "id": 96498 + } + } + }, + { + "__struct_id": 410, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "DefensiveCasting" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 60 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Only cast defensive spells for now.", + "id": 96498 + } + } + }, + { + "__struct_id": 411, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "NoMagic" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 60 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Don't use any magic until I say otherwise.", + "id": 96497 + } + } + }, + { + "__struct_id": 412, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "UseMagic" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 60 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use any magic spells you have.", + "id": 96498 + } + } + }, + { + "__struct_id": 413, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "MagicPlus" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 60 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use your magic more in combat." + } + } + }, + { + "__struct_id": 414, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "MagicMinus" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 60 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use your magic less in combat." + } + } + }, + { + "__struct_id": 415, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Healing" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 61 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lets change when you should heal.", + "id": 54985 + } + } + }, + { + "__struct_id": 416, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "HealOutPlus" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Healing" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 61 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Increase the health an one needs for you to heal out of combat.", + "id": 54990 + } + } + }, + { + "__struct_id": 417, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "HealOutMinus" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Healing" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 61 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Reduce the health an one needs for you to heal out of combat.", + "id": 54989 + } + } + }, + { + "__struct_id": 418, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "HealInPlus" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Healing" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 61 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Increase the health an one needs for you to heal during combat.", + "id": 54990 + } + } + }, + { + "__struct_id": 419, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "HealInMinus" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Healing" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 61 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Reduce the health any one needs for you to heal during combat.", + "id": 54989 + } + } + }, + { + "__struct_id": 420, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "HealSelf" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Healing" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 61 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change if you heal yourself.", + "id": 54989 + } + } + }, + { + "__struct_id": 421, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "HealAllies" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Healing" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 61 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change if you heal any allies.", + "id": 54989 + } + } + }, + { + "__struct_id": 422, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Pickup" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Plans" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 35 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lets change if you pickup items and gold." + } + } + }, + { + "__struct_id": 423, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "FollowFarther" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Plans" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 35 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Follow farther away from me.", + "id": 96510 + } + } + }, + { + "__struct_id": 424, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "FollowCloser" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Plans" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 35 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Follow closer to me.", + "id": 96511 + } + } + }, + { + "__struct_id": 425, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 34 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lets talk about your tactics in combat." + } + } + }, + { + "__struct_id": 426, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "AttackTactics" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 34 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change if you fight every opponent during combat.", + "2": "\"Je ne veux pas du tout que vous vous engagiez dans un combat à distance rapproché,eloignez vous de l'enemi s'il devient trop proche!\"", + "3": "\"Je ne veux pas du tout que vous vous engagiez dans un combat à distance rapproché,eloignez vous de l'enemi s'il devient trop proche!\"" + } + } + }, + { + "__struct_id": 427, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "AtkAssociates" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 34 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change your tactics against familiars, companions, and summons.", + "id": 62531 + } + } + }, + { + "__struct_id": 428, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Ranged" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 34 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change your ranged combat tactics.", + "id": 62531 + } + } + }, + { + "__struct_id": 429, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "CounterSpell" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 34 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I want you to counter spell the enemy!", + "2": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"", + "3": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"" + } + } + }, + { + "__struct_id": 430, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Taunt" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 34 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I want you to taunt the enemy!", + "2": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"", + "3": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"" + } + } + }, + { + "__struct_id": 431, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "PeaceTactics" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 34 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Don't engage in combat.", + "2": "\"Je ne veux pas du tout que vous vous engagiez dans un combat à distance rapproché,eloignez vous de l'enemi s'il devient trop proche!\"", + "3": "\"Je ne veux pas du tout que vous vous engagiez dans un combat à distance rapproché,eloignez vous de l'enemi s'il devient trop proche!\"" + } + } + }, + { + "__struct_id": 432, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "AmbushTactics" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 34 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use ambush tactics, hide and then strike.", + "2": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"", + "3": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"" + } + } + }, + { + "__struct_id": 433, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "DefensiveTactics" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 34 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use defensive tactics to protect yourself.", + "id": 62532 + } + } + }, + { + "__struct_id": 434, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "BasicTactics" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 34 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use your best judgement in combat.", + "id": 62531 + } + } + }, + { + "__struct_id": 435, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "AmbushTactics" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 33 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use ambush tactics, hide and then strike.", + "2": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"", + "3": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"" + } + } + }, + { + "__struct_id": 436, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "DefensiveTactics" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 33 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use defensive tactics protect yourself.", + "id": 62532 + } + } + }, + { + "__struct_id": 437, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "BasicTactics" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 33 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use basic combat tactics.", + "id": 62531 + } + } + }, + { + "__struct_id": 438, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "x1_hen_identify" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Can you identify my equipment?", + "id": 88341 + } + } + }, + { + "__struct_id": 439, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Scout" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I would like you to scout the area." + } + } + } + ] + }, + "StartingList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "nw_ch_ac_st_01" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 62 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "BaseMode" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 0 + } + } + ] + } +} diff --git a/src/module/dlg/nw_g_fam.dlg.json b/src/module/dlg/nw_g_fam.dlg.json new file mode 100644 index 0000000..5be0aae --- /dev/null +++ b/src/module/dlg/nw_g_fam.dlg.json @@ -0,0 +1,23412 @@ +{ + "__data_type": "DLG ", + "DelayEntry": { + "type": "dword", + "value": 0 + }, + "DelayReply": { + "type": "dword", + "value": 0 + }, + "EndConverAbort": { + "type": "resref", + "value": "" + }, + "EndConversation": { + "type": "resref", + "value": "" + }, + "EntryList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 193 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "0c_if_scout" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 192 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "0c_if_identify" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 191 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "nw_d2_intn" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 7 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "nw_d2_intl" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 6 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 5 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 4 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 3 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 2 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "nw_d2_intn" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 1 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 10, + "Active": { + "type": "resref", + "value": "nw_d2_intl" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 0 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": " What do you require of me ?", + "id": 58490 + } + } + }, + { + "__struct_id": 1, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58491 + } + } + }, + { + "__struct_id": 2, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58492 + } + } + }, + { + "__struct_id": 3, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [] + }, + "Script": { + "type": "resref", + "value": "nw_ch_fm_st_10" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58493 + } + } + }, + { + "__struct_id": 4, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58494 + } + } + }, + { + "__struct_id": 5, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [] + }, + "Script": { + "type": "resref", + "value": "nw_ch_fm_st_10" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58495 + } + } + }, + { + "__struct_id": 6, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58496 + } + } + }, + { + "__struct_id": 7, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [] + }, + "Script": { + "type": "resref", + "value": "nw_ch_fm_st_10" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58497 + } + } + }, + { + "__struct_id": 8, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58498 + } + } + }, + { + "__struct_id": 9, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [] + }, + "Script": { + "type": "resref", + "value": "nw_ch_fm_st_10" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58499 + } + } + }, + { + "__struct_id": 10, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58500 + } + } + }, + { + "__struct_id": 11, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58501 + } + } + }, + { + "__struct_id": 12, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [] + }, + "Script": { + "type": "resref", + "value": "nw_ch_fm_st-11" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58502 + } + } + }, + { + "__struct_id": 13, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [] + }, + "Script": { + "type": "resref", + "value": "nw_ch_fm_st-11" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58503 + } + } + }, + { + "__struct_id": 14, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58506 + } + } + }, + { + "__struct_id": 15, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [] + }, + "Script": { + "type": "resref", + "value": "nw_ch_fm_st_10" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58507 + } + } + }, + { + "__struct_id": 16, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58508 + } + } + }, + { + "__struct_id": 17, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [] + }, + "Script": { + "type": "resref", + "value": "nw_ch_fm_st_10" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58509 + } + } + }, + { + "__struct_id": 18, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [] + }, + "Script": { + "type": "resref", + "value": "nw_ch_fm_st_12" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58504 + } + } + }, + { + "__struct_id": 19, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58505 + } + } + }, + { + "__struct_id": 20, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 151 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "0c_if_has_class" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nClass1" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nClass2" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 2, + "Key": { + "type": "cexostring", + "value": "nClass3" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 3, + "Key": { + "type": "cexostring", + "value": "nClass4" + }, + "Value": { + "type": "cexostring", + "value": "6" + } + }, + { + "__struct_id": 4, + "Key": { + "type": "cexostring", + "value": "nClass5" + }, + "Value": { + "type": "cexostring", + "value": "7" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 141 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "0c_if_has_class" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nClass1" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nClass2" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 2, + "Key": { + "type": "cexostring", + "value": "nClass3" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 3, + "Key": { + "type": "cexostring", + "value": "nClass4" + }, + "Value": { + "type": "cexostring", + "value": "9" + } + }, + { + "__struct_id": 4, + "Key": { + "type": "cexostring", + "value": "nClass5" + }, + "Value": { + "type": "cexostring", + "value": "10" + } + }, + { + "__struct_id": 5, + "Key": { + "type": "cexostring", + "value": "nClass6" + }, + "Value": { + "type": "cexostring", + "value": "47" + } + }, + { + "__struct_id": 6, + "Key": { + "type": "cexostring", + "value": "nClass7" + }, + "Value": { + "type": "cexostring", + "value": "48" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 59 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "0c_if_has_class" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nClass1" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nClass2" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 2, + "Key": { + "type": "cexostring", + "value": "nClass3" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 3, + "Key": { + "type": "cexostring", + "value": "nClass4" + }, + "Value": { + "type": "cexostring", + "value": "9" + } + }, + { + "__struct_id": 4, + "Key": { + "type": "cexostring", + "value": "nClass5" + }, + "Value": { + "type": "cexostring", + "value": "10" + } + }, + { + "__struct_id": 5, + "Key": { + "type": "cexostring", + "value": "nClass6" + }, + "Value": { + "type": "cexostring", + "value": "47" + } + }, + { + "__struct_id": 6, + "Key": { + "type": "cexostring", + "value": "nClass7" + }, + "Value": { + "type": "cexostring", + "value": "48" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "0c_if_has_class" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nClass1" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nClass2" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 2, + "Key": { + "type": "cexostring", + "value": "nClass3" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 3, + "Key": { + "type": "cexostring", + "value": "nClass4" + }, + "Value": { + "type": "cexostring", + "value": "9" + } + }, + { + "__struct_id": 4, + "Key": { + "type": "cexostring", + "value": "nClass5" + }, + "Value": { + "type": "cexostring", + "value": "10" + } + }, + { + "__struct_id": 5, + "Key": { + "type": "cexostring", + "value": "nClass6" + }, + "Value": { + "type": "cexostring", + "value": "47" + } + }, + { + "__struct_id": 6, + "Key": { + "type": "cexostring", + "value": "nClass7" + }, + "Value": { + "type": "cexostring", + "value": "48" + } + }, + { + "__struct_id": 7, + "Key": { + "type": "cexostring", + "value": "nClass8" + }, + "Value": { + "type": "cexostring", + "value": "46" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 10 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "nw_d2_intn" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 9 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "nw_d2_intl" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 8 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "What would you like me to do, my ?", + "id": 58510 + } + } + }, + { + "__struct_id": 21, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_has_assoc" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAssociate" + }, + "Value": { + "type": "cexostring", + "value": "Companion" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 26 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "0c_if_has_assoc" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAssociate" + }, + "Value": { + "type": "cexostring", + "value": "Familiar" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 25 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "x2_hen_tomishad3" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 24 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 21 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "30" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "174" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 19 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "175" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 18 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "176" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 17 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "177" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 16 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "179" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 15 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 10, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "180" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 14 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 11, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "181" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 13 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 12, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "182" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 12 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 13, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "178" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 11 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 14, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 152 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "What would you have me summon?" + } + } + }, + { + "__struct_id": 22, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 23 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 22 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "You sure?", + "id": 87721 + } + } + }, + { + "__struct_id": 23, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 58 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 48 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 38 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 28 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "nw_d2_intn" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 7 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": " What would you like to discuss about my defensive spells?", + "id": 88866 + } + } + }, + { + "__struct_id": 24, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 37 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 36 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "x0_d2_hasfamil" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 35 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "x0_d2_hascompan" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 34 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "x2_d1_hashench1" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 33 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "x2_d1_hashench2" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 32 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "x2_d1_hashench3" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 31 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "x2_d1_hashench4" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 30 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "x2_d1_targetall" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 152 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 10, + "Active": { + "type": "resref", + "value": "nw_d2_intn" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 9 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "0c_listhenchman" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "And what is my target?", + "id": 87722 + } + } + }, + { + "__struct_id": 25, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 47 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 46 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "x0_d2_hasfamil" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 45 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "x0_d2_hascompan" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 44 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "x2_d1_hashench1" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 43 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "x2_d1_hashench2" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 42 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "x2_d1_hashench3" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 41 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "x2_d1_hashench4" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 40 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "x2_d1_targetall" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 39 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 152 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 10, + "Active": { + "type": "resref", + "value": "nw_d2_intn" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 9 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "0c_listhenchman" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "And what is my target?", + "id": 87722 + } + } + }, + { + "__struct_id": 26, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 57 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "x0_d2_hasfamil" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 55 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "x0_d2_hascompan" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 54 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "x2_d1_hashench1" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 53 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "x2_d1_hashench2" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 52 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "x2_d1_hashench3" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 51 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "x2_d1_hashench4" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 50 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "x2_d1_targetall" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 49 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 152 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 10, + "Active": { + "type": "resref", + "value": "nw_d2_intn" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 9 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "0c_listhenchman" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "And what is my target?", + "id": 87722 + } + } + }, + { + "__struct_id": 27, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 140 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "6" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 139 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "9" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 130 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "13" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 129 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "21" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 128 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "419" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 127 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "519" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 126 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "38" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 125 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "41" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 124 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "42" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 123 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 10, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "354" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 122 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 11, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "47" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 121 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 12, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "49" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 120 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 13, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "50" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 119 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 14, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "369" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 116 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 15, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "418" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 115 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 16, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "121" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 114 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 17, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "377" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 113 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 18, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "356" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 112 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 19, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "62" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 111 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 20, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "120" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 110 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 21, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "65" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 109 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 22, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "67" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 108 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 23, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "109" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 107 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 24, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "70" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 106 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 25, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "443" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 105 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 26, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "73" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 104 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 27, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "74" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 103 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 28, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "78" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 102 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 29, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "88" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 101 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 30, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "90" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 100 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 31, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "92" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 99 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 32, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "93" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 98 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 33, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "94" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 97 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 34, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "95" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 96 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 35, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "97" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 95 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 36, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "99" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 94 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 37, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "100" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 93 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 38, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "102" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 92 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 39, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "108" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 91 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 40, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "113" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 90 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 41, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "117" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 89 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 42, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "119" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 88 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 43, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "525" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 87 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 44, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "126" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 86 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 45, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "355" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 85 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 46, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "133" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 84 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 47, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "134" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 83 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 48, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "137" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 82 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 49, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "321" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 81 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 50, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "141" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 80 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 51, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "374" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 79 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 52, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "145" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 78 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 53, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "146" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 77 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 54, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "147" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 76 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 55, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "148" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 75 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 56, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "149" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 74 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 57, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "150" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 73 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 58, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "151" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 72 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 59, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "152" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 71 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 60, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "154" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 70 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 61, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "157" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 69 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 62, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "159" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 68 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 63, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "417" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 67 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 64, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "450" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 66 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 65, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "169" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 65 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 66, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "168" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 64 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 67, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "172" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 63 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 68, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "186" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 62 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 69, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "365" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 61 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 70, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "441" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 60 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 71, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 152 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "What you want me to cast?", + "id": 87720 + } + } + }, + { + "__struct_id": 28, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 118 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 117 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "You sure?", + "id": 87721 + } + } + }, + { + "__struct_id": 29, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 138 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 137 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "x0_d2_hasfamil" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 136 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "x0_d2_hascompan" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 135 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "x2_d1_hashench1" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 134 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "x2_d1_hashench2" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 133 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "x2_d1_hashench3" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 132 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "x2_d1_hashench4" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 131 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 152 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "x2_d1_gentags" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Okay. Who shoulds I cast it on?", + "id": 87722 + } + } + }, + { + "__struct_id": 30, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 150 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 149 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "x0_d2_hasfamil" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 148 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "x0_d2_hascompan" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 147 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "x2_d1_hashench1" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 146 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "x2_d1_hashench2" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 145 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "x2_d1_hashench3" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 144 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "x2_d1_hashench4" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 143 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 142 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 152 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 10, + "Active": { + "type": "resref", + "value": "nw_d2_intn" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 9 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "x2_d1_gentags" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "And who should be the target of my healing?", + "id": 87722 + } + } + }, + { + "__struct_id": 31, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 180 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 179 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 178 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "0c_if_pickuploot" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 177 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "0c_if_has_class" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nClass1" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nClass2" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 2, + "Key": { + "type": "cexostring", + "value": "nClass3" + }, + "Value": { + "type": "cexostring", + "value": "47" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 170 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "0c_if_has_class" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nClass1" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nClass2" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 2, + "Key": { + "type": "cexostring", + "value": "nClass3" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 3, + "Key": { + "type": "cexostring", + "value": "nClass4" + }, + "Value": { + "type": "cexostring", + "value": "9" + } + }, + { + "__struct_id": 4, + "Key": { + "type": "cexostring", + "value": "nClass5" + }, + "Value": { + "type": "cexostring", + "value": "10" + } + }, + { + "__struct_id": 5, + "Key": { + "type": "cexostring", + "value": "nClass6" + }, + "Value": { + "type": "cexostring", + "value": "47" + } + }, + { + "__struct_id": 6, + "Key": { + "type": "cexostring", + "value": "nClass7" + }, + "Value": { + "type": "cexostring", + "value": "48" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 159 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 158 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 157 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 153 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 152 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 10, + "Active": { + "type": "resref", + "value": "nw_d2_intn" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 9 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 11, + "Active": { + "type": "resref", + "value": "nw_d2_intl" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 8 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": " What tactic would you like me to change, ?" + } + } + }, + { + "__struct_id": 32, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 156 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 155 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 154 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 151 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "nw_d2_intn" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 9 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": " My benignant , how can I change my actions?\"" + } + } + }, + { + "__struct_id": 33, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 169 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 168 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 167 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 166 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 165 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 164 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "0c_if_cntrspell" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 163 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "0c_if_com_script" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAIScript" + }, + "Value": { + "type": "cexostring", + "value": "ai_a_cntrspell" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 162 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 161 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 160 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 10, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 151 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 11, + "Active": { + "type": "resref", + "value": "nw_d2_intn" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 9 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": " Almighty , how shall I use magic in combat?" + } + } + }, + { + "__struct_id": 34, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 176 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 175 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 174 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 173 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 172 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 171 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 151 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "nw_d2_intn" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 9 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "nw_d2_intl" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 8 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": " Let me know when to heal, all knowning .", + "id": 55427 + } + } + }, + { + "__struct_id": 35, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_no_com_script" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 190 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "0c_no_com_script" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAIScript" + }, + "Value": { + "type": "cexostring", + "value": "ai_a_defensive" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 189 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "0c_no_com_script" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAIScript" + }, + "Value": { + "type": "cexostring", + "value": "ai_a_ambusher" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 188 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "0c_no_com_script" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAIScript" + }, + "Value": { + "type": "cexostring", + "value": "ai_a_ranged" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 187 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "0c_no_com_script" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAIScript" + }, + "Value": { + "type": "cexostring", + "value": "ai_a_peaceful" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 186 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "0c_if_taunt" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 185 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "0c_if_cntrspell" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 184 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 183 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 182 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 181 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 10, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 151 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 11, + "Active": { + "type": "resref", + "value": "nw_d2_intn" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 9 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 12, + "Active": { + "type": "resref", + "value": "nw_d2_intl" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 8 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": " Oh powerful ! How would you like to change my tactics?" + } + } + }, + { + "__struct_id": 36, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 194 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 63861 + } + } + }, + { + "__struct_id": 37, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 195 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 63862 + } + } + }, + { + "__struct_id": 38, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 63863 + } + } + }, + { + "__struct_id": 39, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58520 + } + } + } + ] + }, + "NumWords": { + "type": "dword", + "value": 1302 + }, + "PreventZoomIn": { + "type": "byte", + "value": 1 + }, + "ReplyList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 1 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58472 + } + } + }, + { + "__struct_id": 1, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 1 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58473 + } + } + }, + { + "__struct_id": 2, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "nw_ch_fm_st_09" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 9 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "nw_ch_fm_st_09" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 8 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "nw_ch_fm_st_09" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 7 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "nw_ch_fm_st_09" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 6 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "nw_ch_fm_st_09" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 5 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "nw_ch_fm_st_09" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 4 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "nw_ch_fm_st_09" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 3 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 2 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58474 + } + } + }, + { + "__struct_id": 3, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "nw_ch_fm_st_09" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 13 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "nw_ch_fm_st_09" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 12 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "nw_ch_fm_st_09" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 11 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 10 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "nw_s0_heal" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58475 + } + } + }, + { + "__struct_id": 4, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "nw_ch_fm_st_04" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 17 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "nw_ch_fm_st_09" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 16 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "nw_ch_fm_st_09" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 15 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 14 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58477 + } + } + }, + { + "__struct_id": 5, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "nw_ch_fm_st_11" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 19 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 18 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58476 + } + } + }, + { + "__struct_id": 6, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58478 + } + } + }, + { + "__struct_id": 7, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I need you to change how you are doing things.", + "id": 58479 + } + } + }, + { + "__struct_id": 8, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 1 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58480 + } + } + }, + { + "__struct_id": 9, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 1 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 58481 + } + } + }, + { + "__struct_id": 10, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 21 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I need you to summon something if you can." + } + } + }, + { + "__struct_id": 11, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "178" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 22 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Summon Creature IX.", + "id": 88353 + } + } + }, + { + "__struct_id": 12, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "182" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 22 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Summon Creature VIII.", + "id": 88354 + } + } + }, + { + "__struct_id": 13, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "181" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 22 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Summon Creature VII.", + "id": 88355 + } + } + }, + { + "__struct_id": 14, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "180" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 22 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Summon Creature VI.", + "id": 88356 + } + } + }, + { + "__struct_id": 15, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "179" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 22 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Summon Creature V.", + "id": 88358 + } + } + }, + { + "__struct_id": 16, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "177" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 22 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Summon Creature IV.", + "id": 88358 + } + } + }, + { + "__struct_id": 17, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "176" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 22 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Summon Creature III.", + "id": 88359 + } + } + }, + { + "__struct_id": 18, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "175" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 22 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Summon Creature II.", + "id": 88360 + } + } + }, + { + "__struct_id": 19, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "174" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 22 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Summon Creature I.", + "id": 88361 + } + } + }, + { + "__struct_id": 20, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "30" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 22 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Create Undead.", + "id": 88425 + } + } + }, + { + "__struct_id": 21, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 22 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Animate Dead.", + "id": 88446 + } + } + }, + { + "__struct_id": 22, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "No, I've changed my mind.", + "id": 88415 + } + } + }, + { + "__struct_id": 23, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Yes, go ahead.", + "id": 88416 + } + } + }, + { + "__struct_id": 24, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "x2_hen_tomishad4" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Summon Shadow." + } + } + }, + { + "__struct_id": 25, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAssociate" + }, + "Value": { + "type": "cexostring", + "value": "Familiar" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_summon_assoc" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Your Familiar." + } + } + }, + { + "__struct_id": 26, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAssociate" + }, + "Value": { + "type": "cexostring", + "value": "Companion" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_summon_assoc" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Your Companion." + } + } + }, + { + "__struct_id": 27, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "RestBuffing" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 23 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Let us talk about your defensive spells.", + "id": 89061 + } + } + }, + { + "__struct_id": 28, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 24 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast all your defensive spells.", + "id": 89063 + } + } + }, + { + "__struct_id": 29, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast on all the party members.", + "id": 88431 + } + } + }, + { + "__struct_id": 30, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "6" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88437 + } + } + }, + { + "__struct_id": 31, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "5" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88438 + } + } + }, + { + "__struct_id": 32, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88439 + } + } + }, + { + "__struct_id": 33, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88440 + } + } + }, + { + "__struct_id": 34, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my animal companion.", + "id": 88441 + } + } + }, + { + "__struct_id": 35, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my familiar.", + "id": 88442 + } + } + }, + { + "__struct_id": 36, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on me.", + "id": 88443 + } + } + }, + { + "__struct_id": 37, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on yourself.", + "id": 88444 + } + } + }, + { + "__struct_id": 38, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 25 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast all your long duration defensive spells.", + "id": 89064 + } + } + }, + { + "__struct_id": 39, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast on all the party members.", + "id": 88431 + } + } + }, + { + "__struct_id": 40, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "6" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88437 + } + } + }, + { + "__struct_id": 41, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "5" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88438 + } + } + }, + { + "__struct_id": 42, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88439 + } + } + }, + { + "__struct_id": 43, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88440 + } + } + }, + { + "__struct_id": 44, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "8" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my animal companion.", + "id": 88441 + } + } + }, + { + "__struct_id": 45, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "7" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my familiar.", + "id": 88442 + } + } + }, + { + "__struct_id": 46, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on me.", + "id": 88443 + } + } + }, + { + "__struct_id": 47, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on yourself.", + "id": 88444 + } + } + }, + { + "__struct_id": 48, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 26 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast all your short duration defensive spells.", + "id": 89065 + } + } + }, + { + "__struct_id": 49, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast on all the party members.", + "id": 88431 + } + } + }, + { + "__struct_id": 50, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "6" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88437 + } + } + }, + { + "__struct_id": 51, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "5" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88438 + } + } + }, + { + "__struct_id": 52, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88439 + } + } + }, + { + "__struct_id": 53, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88440 + } + } + }, + { + "__struct_id": 54, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "8" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my animal companion.", + "id": 88441 + } + } + }, + { + "__struct_id": 55, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "7" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my familiar.", + "id": 88442 + } + } + }, + { + "__struct_id": 56, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on me.", + "id": 88443 + } + } + }, + { + "__struct_id": 57, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on yourself.", + "id": 88444 + } + } + }, + { + "__struct_id": 58, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "RestBuffing" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "RestBuffing" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 23 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change if you cast long duration spells after resting." + } + } + }, + { + "__struct_id": 59, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I need you to cast a spell.", + "id": 88348 + } + } + }, + { + "__struct_id": 60, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "441" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 28 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Wounding Whispers.", + "id": 88350 + } + } + }, + { + "__struct_id": 61, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "365" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Ultravision.", + "id": 88351 + } + } + }, + { + "__struct_id": 62, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "186" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "True Seeing.", + "id": 88352 + } + } + }, + { + "__struct_id": 63, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "172" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Stoneskin.", + "id": 88362 + } + } + }, + { + "__struct_id": 64, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "168" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Spell Resistance.", + "id": 88363 + } + } + }, + { + "__struct_id": 65, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "169" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 28 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Spell Mantle.", + "id": 88364 + } + } + }, + { + "__struct_id": 66, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "450" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 28 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Shield of Faith.", + "id": 88365 + } + } + }, + { + "__struct_id": 67, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "417" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 28 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Shield.", + "id": 88366 + } + } + }, + { + "__struct_id": 68, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "159" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 28 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Shadow Shield.", + "id": 88367 + } + } + }, + { + "__struct_id": 69, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "157" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "See Invisibility.", + "id": 88368 + } + } + }, + { + "__struct_id": 70, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "154" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 28 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Sanctuary.", + "id": 88369 + } + } + }, + { + "__struct_id": 71, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "152" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Restoration.", + "id": 88370 + } + } + }, + { + "__struct_id": 72, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "151" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Resistance.", + "id": 88371 + } + } + }, + { + "__struct_id": 73, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "150" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Resist Elements.", + "id": 88372 + } + } + }, + { + "__struct_id": 74, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "149" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Remove Paralysis.", + "id": 88373 + } + } + }, + { + "__struct_id": 75, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "148" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Remove Fear.", + "id": 88374 + } + } + }, + { + "__struct_id": 76, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "147" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Remove Disease.", + "id": 88375 + } + } + }, + { + "__struct_id": 77, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "146" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Remove Curse.", + "id": 88376 + } + } + }, + { + "__struct_id": 78, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "145" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 28 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Remove Blindness/Deafness.", + "id": 88377 + } + } + }, + { + "__struct_id": 79, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "374" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Regenerate.", + "id": 88378 + } + } + }, + { + "__struct_id": 80, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "141" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Protection From Spells.", + "id": 88379 + } + } + }, + { + "__struct_id": 81, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "321" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Protection From Evil." + } + } + }, + { + "__struct_id": 82, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "137" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Protection From Elements.", + "id": 88380 + } + } + }, + { + "__struct_id": 83, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "134" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 28 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Premonition.", + "id": 88381 + } + } + }, + { + "__struct_id": 84, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "133" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 28 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Prayer.", + "id": 88382 + } + } + }, + { + "__struct_id": 85, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "355" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Owl's Wisdom.", + "id": 88383 + } + } + }, + { + "__struct_id": 86, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "126" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Neutralize poison.", + "id": 88384 + } + } + }, + { + "__struct_id": 87, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "525" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Monstrous Regeneration.", + "id": 88385 + } + } + }, + { + "__struct_id": 88, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "119" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 28 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Minor Globe of Invulnerability.", + "id": 88386 + } + } + }, + { + "__struct_id": 89, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "117" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Mind Blank.", + "id": 88387 + } + } + }, + { + "__struct_id": 90, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "113" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Mass Haste.", + "id": 88388 + } + } + }, + { + "__struct_id": 91, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "108" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Magical Vestment.", + "id": 88389 + } + } + }, + { + "__struct_id": 92, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "102" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Mage Armor.", + "id": 88390 + } + } + }, + { + "__struct_id": 93, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "100" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Light.", + "id": 88391 + } + } + }, + { + "__struct_id": 94, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "99" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 28 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lesser Spell Mantle.", + "id": 88392 + } + } + }, + { + "__struct_id": 95, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "97" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lesser Restoration.", + "id": 88393 + } + } + }, + { + "__struct_id": 96, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "95" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lesser Mind Blank", + "id": 88394 + } + } + }, + { + "__struct_id": 97, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "94" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lesser Dispel.", + "id": 88395 + } + } + }, + { + "__struct_id": 98, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "93" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 28 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Knock.", + "id": 88396 + } + } + }, + { + "__struct_id": 99, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "92" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 28 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Invisibility Sphere.", + "id": 88397 + } + } + }, + { + "__struct_id": 100, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "90" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Invisibility", + "id": 88398 + } + } + }, + { + "__struct_id": 101, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "88" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Improved Invisibility.", + "id": 88399 + } + } + }, + { + "__struct_id": 102, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "78" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Haste.", + "id": 88400 + } + } + }, + { + "__struct_id": 103, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "74" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Greater Stoneskin.", + "id": 88401 + } + } + }, + { + "__struct_id": 104, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "73" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 28 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Greater Spell Mantle.", + "id": 88402 + } + } + }, + { + "__struct_id": 105, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "443" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 28 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Greater Sanctuary.", + "id": 88403 + } + } + }, + { + "__struct_id": 106, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "70" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Greater Restoration.", + "id": 88404 + } + } + }, + { + "__struct_id": 107, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "109" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Greater Magic Weapon.", + "id": 88405 + } + } + }, + { + "__struct_id": 108, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "67" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Greater Dispelling.", + "id": 88406 + } + } + }, + { + "__struct_id": 109, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "65" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 28 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Globe of Invulnerability.", + "id": 88407 + } + } + }, + { + "__struct_id": 110, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "120" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 28 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Ghostly Visage.", + "id": 88408 + } + } + }, + { + "__struct_id": 111, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "62" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Freedom of Movement.", + "id": 88409 + } + } + }, + { + "__struct_id": 112, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "356" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Fox's Cunning", + "id": 88410 + } + } + }, + { + "__struct_id": 113, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "377" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 28 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Find Traps.", + "id": 88411 + } + } + }, + { + "__struct_id": 114, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "121" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 28 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Ethereal Visage.", + "id": 88412 + } + } + }, + { + "__struct_id": 115, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "418" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 28 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Entropic Shield.", + "id": 88413 + } + } + }, + { + "__struct_id": 116, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "369" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 28 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Energy Buffer.", + "id": 88414 + } + } + }, + { + "__struct_id": 117, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "No, I've changed my mind.", + "id": 88415 + } + } + }, + { + "__struct_id": 118, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Yes, go ahead.", + "id": 88416 + } + } + }, + { + "__struct_id": 119, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "50" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Endure Elements.", + "id": 88417 + } + } + }, + { + "__struct_id": 120, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "49" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Endurance.", + "id": 88418 + } + } + }, + { + "__struct_id": 121, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "47" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 28 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Elemental Shield.", + "id": 88419 + } + } + }, + { + "__struct_id": 122, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "354" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Eagle's Splendour.", + "id": 88420 + } + } + }, + { + "__struct_id": 123, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "42" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 28 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Divine Power.", + "id": 88421 + } + } + }, + { + "__struct_id": 124, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "41" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Dispel Magic.", + "id": 88422 + } + } + }, + { + "__struct_id": 125, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "38" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Death Ward.", + "id": 88423 + } + } + }, + { + "__struct_id": 126, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "519" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 28 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Death Armor.", + "id": 88424 + } + } + }, + { + "__struct_id": 127, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "419" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Continual Flame.", + "id": 88426 + } + } + }, + { + "__struct_id": 128, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "21" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Clarity.", + "id": 88427 + } + } + }, + { + "__struct_id": 129, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "13" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cat's Grace.", + "id": 88428 + } + } + }, + { + "__struct_id": 130, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "9" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Bull's Strength.", + "id": 88429 + } + } + }, + { + "__struct_id": 131, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "6" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88437 + } + } + }, + { + "__struct_id": 132, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "5" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88438 + } + } + }, + { + "__struct_id": 133, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88439 + } + } + }, + { + "__struct_id": 134, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88440 + } + } + }, + { + "__struct_id": 135, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "8" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my animal companion.", + "id": 88441 + } + } + }, + { + "__struct_id": 136, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "7" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my familiar.", + "id": 88442 + } + } + }, + { + "__struct_id": 137, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on me.", + "id": 88443 + } + } + }, + { + "__struct_id": 138, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on yourself.", + "id": 88444 + } + } + }, + { + "__struct_id": 139, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "6" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Bless.", + "id": 88445 + } + } + }, + { + "__struct_id": 140, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Aid.", + "id": 88447 + } + } + }, + { + "__struct_id": 141, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 30 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I need you to cast a healing spell." + } + } + }, + { + "__struct_id": 142, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Heal up the whole party.", + "id": 88431 + } + } + }, + { + "__struct_id": 143, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88437 + } + } + }, + { + "__struct_id": 144, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88438 + } + } + }, + { + "__struct_id": 145, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88439 + } + } + }, + { + "__struct_id": 146, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88440 + } + } + }, + { + "__struct_id": 147, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "8" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my animal companion.", + "id": 88441 + } + } + }, + { + "__struct_id": 148, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "7" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my familiar.", + "id": 88442 + } + } + }, + { + "__struct_id": 149, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on me.", + "id": 88443 + } + } + }, + { + "__struct_id": 150, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on yourself.", + "id": 88444 + } + } + }, + { + "__struct_id": 151, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Plans" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 31 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I want to discuss your tactics." + } + } + }, + { + "__struct_id": 152, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lets talk about something else." + } + } + }, + { + "__struct_id": 153, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Object" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 32 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lets discuss how you deal with objects." + } + } + }, + { + "__struct_id": 154, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Bash" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Object" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 32 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change your bashing tactics.", + "id": 96501 + } + } + }, + { + "__struct_id": 155, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Locks" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Object" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 32 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change your lock picking tactics.", + "id": 96501 + } + } + }, + { + "__struct_id": 156, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Traps" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Object" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 32 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change your trap tactics.", + "id": 96502 + } + } + }, + { + "__struct_id": 157, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Search" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Plans" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 31 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I need you to change your search tactics." + } + } + }, + { + "__struct_id": 158, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Stealth" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Plans" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 31 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I need you to change your stealth tactics." + } + } + }, + { + "__struct_id": 159, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 33 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Let's change how you use magic in combat." + } + } + }, + { + "__struct_id": 160, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "MagicItems" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 33 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change if you use magic items or not.", + "id": 96498 + } + } + }, + { + "__struct_id": 161, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Dispel" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 33 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change your dispel tactics.", + "id": 96500 + } + } + }, + { + "__struct_id": 162, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "BasicTactics" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 33 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Stop countering the enemies spells.", + "2": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"", + "3": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"" + } + } + }, + { + "__struct_id": 163, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "CounterSpell" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 33 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I want you to counter spell the enemy!", + "2": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"", + "3": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"" + } + } + }, + { + "__struct_id": 164, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "BuffFirst" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 33 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change who you cast defensive spells on first.", + "id": 96500 + } + } + }, + { + "__struct_id": 165, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "OffensiveCasting" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 33 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change if you cast offensive spells.", + "id": 96498 + } + } + }, + { + "__struct_id": 166, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "DefensiveCasting" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 33 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change if you cast defensive spells.", + "id": 96498 + } + } + }, + { + "__struct_id": 167, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "NoMagic" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 33 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change how you use magic spells in combat.", + "id": 96498 + } + } + }, + { + "__struct_id": 168, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "MagicPlus" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 33 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use your magic more in combat." + } + } + }, + { + "__struct_id": 169, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "MagicMinus" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 33 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use your magic less in combat." + } + } + }, + { + "__struct_id": 170, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Healing" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 34 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lets change when you decide to heal me.", + "id": 54985 + } + } + }, + { + "__struct_id": 171, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "HealOutPlus" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Healing" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 34 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Increase the health an one needs for you to heal out of combat.", + "id": 54991 + } + } + }, + { + "__struct_id": 172, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "HealOutMinus" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Healing" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 34 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Reduce the health an one needs for you to heal out of combat.", + "id": 54991 + } + } + }, + { + "__struct_id": 173, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "HealInPlus" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Healing" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 34 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Increase the health an one needs for you to heal during combat.", + "id": 54991 + } + } + }, + { + "__struct_id": 174, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "HealInMinus" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Healing" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 34 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Reduce the health any one needs for you to heal during combat.", + "id": 54991 + } + } + }, + { + "__struct_id": 175, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "HealSelf" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Healing" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 34 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change if you heal yourself.", + "id": 54991 + } + } + }, + { + "__struct_id": 176, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "HealAllies" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Healing" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 34 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change if you heal any allies.", + "id": 54991 + } + } + }, + { + "__struct_id": 177, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Pickup" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Plans" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 31 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lets change if you retrieve items and gold." + } + } + }, + { + "__struct_id": 178, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "FollowFarther" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Plans" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 31 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Follow farther away from me.", + "id": 96508 + } + } + }, + { + "__struct_id": 179, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "FollowCloser" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Plans" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 31 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Follow closer to me.", + "id": 96508 + } + } + }, + { + "__struct_id": 180, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 35 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lets talk about your tactics in combat." + } + } + }, + { + "__struct_id": 181, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "AttackTactics" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 35 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change if you fight every opponent during combat." + } + } + }, + { + "__struct_id": 182, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "AtkAssociates" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 35 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change your tactics against familiars, companions, and summons.", + "id": 62531 + } + } + }, + { + "__struct_id": 183, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Ranged" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 35 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change your ranged combat tactics.", + "id": 62531 + } + } + }, + { + "__struct_id": 184, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "CounterSpell" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 35 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I want you to counter spell the enemy!", + "2": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"", + "3": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"" + } + } + }, + { + "__struct_id": 185, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Taunt" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 35 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I want you to taunt the enemy!", + "2": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"", + "3": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"" + } + } + }, + { + "__struct_id": 186, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "PeaceTactics" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 35 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Don't engage in combat.", + "2": "\"Je ne veux pas du tout que vous vous engagiez dans un combat à distance rapproché,eloignez vous de l'enemi s'il devient trop proche!\"", + "3": "\"Je ne veux pas du tout que vous vous engagiez dans un combat à distance rapproché,eloignez vous de l'enemi s'il devient trop proche!\"" + } + } + }, + { + "__struct_id": 187, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "RangedTactics" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 35 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use agressive ranged tactics, stay out of melee.", + "2": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"", + "3": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"" + } + } + }, + { + "__struct_id": 188, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "AmbushTactics" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 35 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use ambush tactics, hide and then strike.", + "2": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"", + "3": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"" + } + } + }, + { + "__struct_id": 189, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "DefensiveTactics" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 35 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use defensive tactics protect yourself.", + "id": 62532 + } + } + }, + { + "__struct_id": 190, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "BasicTactics" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 35 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use basic combat tactics.", + "id": 62531 + } + } + }, + { + "__struct_id": 191, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "x1_hen_identify" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Can you identify my equipment?", + "id": 88341 + } + } + }, + { + "__struct_id": 192, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Scout" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I would like you to scout the area." + } + } + }, + { + "__struct_id": 193, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 36 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "id": 63860 + } + } + }, + { + "__struct_id": 194, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 37 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": {} + } + }, + { + "__struct_id": 195, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 38 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": {} + } + } + ] + }, + "StartingList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "nw_ch_fm_st_01" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 39 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "BaseMode" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 0 + } + } + ] + } +} diff --git a/src/module/dlg/oc_ai_henchmen.dlg.json b/src/module/dlg/oc_ai_henchmen.dlg.json new file mode 100644 index 0000000..d9ca1b6 --- /dev/null +++ b/src/module/dlg/oc_ai_henchmen.dlg.json @@ -0,0 +1,27180 @@ +{ + "__data_type": "DLG ", + "DelayEntry": { + "type": "dword", + "value": 0 + }, + "DelayReply": { + "type": "dword", + "value": 0 + }, + "EndConverAbort": { + "type": "resref", + "value": "" + }, + "EndConversation": { + "type": "resref", + "value": "" + }, + "EntryList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 38 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_scout" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 247 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "0c_if_identify" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 246 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "0c_if_open_inven" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 242 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 202 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "0c_if_has_class" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nClass1" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nClass2" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 2, + "Key": { + "type": "cexostring", + "value": "nClass3" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 3, + "Key": { + "type": "cexostring", + "value": "nClass4" + }, + "Value": { + "type": "cexostring", + "value": "6" + } + }, + { + "__struct_id": 4, + "Key": { + "type": "cexostring", + "value": "nClass5" + }, + "Value": { + "type": "cexostring", + "value": "7" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 191 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "0c_if_has_class" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nClass1" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nClass2" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 2, + "Key": { + "type": "cexostring", + "value": "nClass3" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 3, + "Key": { + "type": "cexostring", + "value": "nClass4" + }, + "Value": { + "type": "cexostring", + "value": "9" + } + }, + { + "__struct_id": 4, + "Key": { + "type": "cexostring", + "value": "nClass5" + }, + "Value": { + "type": "cexostring", + "value": "10" + } + }, + { + "__struct_id": 5, + "Key": { + "type": "cexostring", + "value": "nClass6" + }, + "Value": { + "type": "cexostring", + "value": "47" + } + }, + { + "__struct_id": 6, + "Key": { + "type": "cexostring", + "value": "nClass7" + }, + "Value": { + "type": "cexostring", + "value": "48" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 109 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "0c_if_has_class" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nClass1" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nClass2" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 2, + "Key": { + "type": "cexostring", + "value": "nClass3" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 3, + "Key": { + "type": "cexostring", + "value": "nClass4" + }, + "Value": { + "type": "cexostring", + "value": "9" + } + }, + { + "__struct_id": 4, + "Key": { + "type": "cexostring", + "value": "nClass5" + }, + "Value": { + "type": "cexostring", + "value": "10" + } + }, + { + "__struct_id": 5, + "Key": { + "type": "cexostring", + "value": "nClass6" + }, + "Value": { + "type": "cexostring", + "value": "47" + } + }, + { + "__struct_id": 6, + "Key": { + "type": "cexostring", + "value": "nClass7" + }, + "Value": { + "type": "cexostring", + "value": "48" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 77 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "0c_if_has_class" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nClass1" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nClass2" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 2, + "Key": { + "type": "cexostring", + "value": "nClass3" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 3, + "Key": { + "type": "cexostring", + "value": "nClass4" + }, + "Value": { + "type": "cexostring", + "value": "9" + } + }, + { + "__struct_id": 4, + "Key": { + "type": "cexostring", + "value": "nClass5" + }, + "Value": { + "type": "cexostring", + "value": "10" + } + }, + { + "__struct_id": 5, + "Key": { + "type": "cexostring", + "value": "nClass6" + }, + "Value": { + "type": "cexostring", + "value": "47" + } + }, + { + "__struct_id": 6, + "Key": { + "type": "cexostring", + "value": "nClass7" + }, + "Value": { + "type": "cexostring", + "value": "48" + } + }, + { + "__struct_id": 7, + "Key": { + "type": "cexostring", + "value": "nClass8" + }, + "Value": { + "type": "cexostring", + "value": "46" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 62 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 6 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 5 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 10, + "Active": { + "type": "resref", + "value": "0c_if_hen_leave" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 2 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 11, + "Active": { + "type": "resref", + "value": "0c_if_convo" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 1 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 12, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 0 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": " What would you like to discuss?" + } + } + }, + { + "__struct_id": 1, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 4 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 3 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 0 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Are you sure you want to do that?" + } + } + }, + { + "__struct_id": 2, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_polymorph" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 61 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "0c_if_has_feat" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nFeat" + }, + "Value": { + "type": "cexostring", + "value": "305" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "sTarget" + }, + "Value": { + "type": "cexostring", + "value": "OBJECT_SELF" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 55 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "0c_if_has_feat" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nFeat" + }, + "Value": { + "type": "cexostring", + "value": "304" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "sTarget" + }, + "Value": { + "type": "cexostring", + "value": "OBJECT_SELF" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 50 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "0c_if_has_feat" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nFeat" + }, + "Value": { + "type": "cexostring", + "value": "898" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "sTarget" + }, + "Value": { + "type": "cexostring", + "value": "OBJECT_SELF" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 44 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "0c_if_has_feat" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nFeat" + }, + "Value": { + "type": "cexostring", + "value": "900" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "sTarget" + }, + "Value": { + "type": "cexostring", + "value": "OBJECT_SELF" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 40 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "0c_if_has_feat" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nFeat" + }, + "Value": { + "type": "cexostring", + "value": "901" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "sTarget" + }, + "Value": { + "type": "cexostring", + "value": "OBJECT_SELF" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 36 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "0c_if_has_feat" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nFeat" + }, + "Value": { + "type": "cexostring", + "value": "903" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "sTarget" + }, + "Value": { + "type": "cexostring", + "value": "OBJECT_SELF" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 32 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "0c_if_has_feat" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nFeat" + }, + "Value": { + "type": "cexostring", + "value": "902" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "sTarget" + }, + "Value": { + "type": "cexostring", + "value": "OBJECT_SELF" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 28 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "0c_if_has_feat" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nFeat" + }, + "Value": { + "type": "cexostring", + "value": "1060" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "sTarget" + }, + "Value": { + "type": "cexostring", + "value": "OBJECT_SELF" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 24 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "0c_if_has_feat" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nFeat" + }, + "Value": { + "type": "cexostring", + "value": "1061" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "sTarget" + }, + "Value": { + "type": "cexostring", + "value": "OBJECT_SELF" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 10, + "Active": { + "type": "resref", + "value": "0c_if_has_feat" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nFeat" + }, + "Value": { + "type": "cexostring", + "value": "257" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "sTarget" + }, + "Value": { + "type": "cexostring", + "value": "OBJECT_SELF" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 19 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 11, + "Active": { + "type": "resref", + "value": "x2_d2_haslayon" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 9 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 12, + "Active": { + "type": "resref", + "value": "x2_d1_dmight" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 8 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 13, + "Active": { + "type": "resref", + "value": "x2_d1_dshield" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 7 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 14, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 0 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Let's see what I can do...", + "id": 95904 + } + } + }, + { + "__struct_id": 3, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 18 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 17 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "x0_d2_hasfamil" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 16 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "x0_d2_hascompan" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 15 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "x2_d1_hashench1" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 14 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "x2_d1_hashench2" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 13 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "x2_d1_hashench3" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 12 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "x2_d1_hashench4" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 11 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 10 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Script": { + "type": "resref", + "value": "x2_d1_gentags" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "And who should be the target of my healing?", + "id": 87722 + } + } + }, + { + "__struct_id": 4, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 23 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 22 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 21 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 10 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Which form should I take?" + } + } + }, + { + "__struct_id": 5, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 26 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 25 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 10 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Which form should I take?" + } + } + }, + { + "__struct_id": 6, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 31 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 30 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 29 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 10 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Which form should I take?" + } + } + }, + { + "__struct_id": 7, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 35 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 34 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 33 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 10 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Which form should I take?" + } + } + }, + { + "__struct_id": 8, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 39 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 38 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 37 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 10 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Which form should I take?" + } + } + }, + { + "__struct_id": 9, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 43 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 42 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 41 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 10 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Which form should I take?" + } + } + }, + { + "__struct_id": 10, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 49 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "0c_if_has_feat" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nFeat" + }, + "Value": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 48 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 47 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 46 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 45 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 10 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Which form should I take?" + } + } + }, + { + "__struct_id": 11, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 54 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 53 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 52 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 51 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 10 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Which form should I take?" + } + } + }, + { + "__struct_id": 12, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 60 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 59 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 58 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 57 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 56 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 10 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Which form should I take?" + } + } + }, + { + "__struct_id": 13, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_has_assoc" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAssociate" + }, + "Value": { + "type": "cexostring", + "value": "Companion" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 76 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "0c_if_has_assoc" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAssociate" + }, + "Value": { + "type": "cexostring", + "value": "Familiar" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 75 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "x2_hen_tomishad3" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 74 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 73 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "30" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 72 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "174" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 71 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "175" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 70 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "176" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 69 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "177" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 68 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "179" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 67 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 10, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "180" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 66 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 11, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "181" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 65 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 12, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "182" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 64 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 13, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "178" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 63 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 14, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 203 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 15, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 0 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "What would you have me summon?" + } + } + }, + { + "__struct_id": 14, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 108 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 98 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 88 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 78 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 203 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 0 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": " What would you like to discuss about my defensive spells?", + "id": 88866 + } + } + }, + { + "__struct_id": 15, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 87 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 86 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "x0_d2_hasfamil" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 85 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "x0_d2_hascompan" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 84 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "x2_d1_hashench1" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 83 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "x2_d1_hashench2" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 82 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "x2_d1_hashench3" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 81 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "x2_d1_hashench4" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 80 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 79 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 203 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "0c_listhenchman" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "And what is my target?", + "id": 87722 + } + } + }, + { + "__struct_id": 16, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 97 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 96 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "x0_d2_hasfamil" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 95 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "x0_d2_hascompan" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 94 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "x2_d1_hashench1" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 93 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "x2_d1_hashench2" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 92 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "x2_d1_hashench3" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 91 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "x2_d1_hashench4" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 90 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 89 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 203 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "0c_listhenchman" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "And what is my target?", + "id": 87722 + } + } + }, + { + "__struct_id": 17, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 107 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 106 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "x0_d2_hasfamil" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 105 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "x0_d2_hascompan" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 104 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "x2_d1_hashench1" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 103 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "x2_d1_hashench2" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 102 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "x2_d1_hashench3" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 101 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "x2_d1_hashench4" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 100 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 99 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 203 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "0c_listhenchman" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "And what is my target?", + "id": 87722 + } + } + }, + { + "__struct_id": 18, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 190 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "6" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 189 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "9" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 180 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "13" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 179 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "21" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 178 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "419" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 177 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "519" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 176 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "38" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 175 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "41" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 174 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "42" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 173 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 10, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "354" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 172 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 11, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "47" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 171 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 12, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "49" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 170 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 13, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "50" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 169 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 14, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "369" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 166 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 15, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "418" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 165 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 16, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "121" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 164 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 17, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "377" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 163 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 18, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "356" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 162 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 19, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "62" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 161 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 20, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "120" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 160 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 21, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "65" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 159 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 22, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "67" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 158 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 23, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "109" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 157 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 24, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "70" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 156 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 25, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "443" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 155 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 26, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "73" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 154 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 27, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "74" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 153 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 28, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "78" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 152 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 29, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "88" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 151 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 30, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "90" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 150 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 31, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "92" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 149 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 32, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "93" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 148 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 33, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "94" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 147 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 34, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "95" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 146 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 35, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "97" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 145 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 36, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "99" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 144 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 37, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "100" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 143 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 38, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "102" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 142 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 39, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "108" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 141 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 40, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "113" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 140 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 41, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "117" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 139 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 42, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "119" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 138 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 43, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "525" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 137 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 44, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "126" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 136 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 45, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "355" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 135 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 46, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "133" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 134 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 47, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "134" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 133 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 48, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "137" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 132 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 49, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "321" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 131 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 50, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "141" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 130 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 51, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "374" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 129 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 52, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "145" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 128 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 53, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "146" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 127 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 54, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "147" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 126 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 55, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "148" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 125 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 56, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "149" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 124 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 57, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "150" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 123 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 58, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "151" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 122 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 59, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "152" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 121 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 60, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "154" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 120 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 61, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "157" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 119 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 62, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "159" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 118 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 63, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "417" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 117 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 64, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "450" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 116 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 65, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "169" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 115 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 66, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "168" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 114 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 67, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "172" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 113 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 68, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "186" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 112 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 69, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "365" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 111 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 70, + "Active": { + "type": "resref", + "value": "0c_if_has_spell" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell1" + }, + "Value": { + "type": "cexostring", + "value": "441" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 110 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 71, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 192 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "What you want me to cast?", + "id": 87720 + } + } + }, + { + "__struct_id": 19, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 168 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 167 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "You sure?", + "id": 87721 + } + } + }, + { + "__struct_id": 20, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 188 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 187 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "x0_d2_hasfamil" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 186 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "x0_d2_hascompan" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 185 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "x2_d1_hashench1" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 184 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "x2_d1_hashench2" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 183 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "x2_d1_hashench3" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 182 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "x2_d1_hashench4" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 181 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 192 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "x2_d1_gentags" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Okay. Who shoulds I cast it on?", + "id": 87722 + } + } + }, + { + "__struct_id": 21, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 201 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 200 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "x0_d2_hasfamil" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 199 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "x0_d2_hascompan" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 198 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "x2_d1_hashench1" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 197 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "x2_d1_hashench2" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 196 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "x2_d1_hashench3" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 195 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "x2_d1_hashench4" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 194 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 193 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 192 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Script": { + "type": "resref", + "value": "x2_d1_gentags" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "And who should be the target of my healing?", + "id": 87722 + } + } + }, + { + "__struct_id": 22, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 231 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 230 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 229 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "0c_if_pickuploot" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 228 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 221 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 210 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 209 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 208 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 204 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 203 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 10, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 0 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": " What do you have in mind?" + } + } + }, + { + "__struct_id": 23, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_skillrank" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSkill" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nRank" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 207 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "0c_if_skillrank" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSkill" + }, + "Value": { + "type": "cexostring", + "value": "9" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nRank" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 206 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 205 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 202 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 0 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": " Should I do something else?" + } + } + }, + { + "__struct_id": 24, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 220 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 219 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "0c_if_a_magic_m" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nMode" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 218 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 217 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 216 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 215 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "0c_if_cntrspell" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 214 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "0c_if_com_script" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAIScript" + }, + "Value": { + "type": "cexostring", + "value": "ai_a_cntrspell" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 213 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 212 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 211 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 10, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 202 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 11, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 0 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": " How would you like me to use magic in combat?" + } + } + }, + { + "__struct_id": 25, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 227 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 226 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 225 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 224 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 223 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 222 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 202 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 0 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": " When do you think I should heal our allies?", + "id": 55427 + } + } + }, + { + "__struct_id": 26, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_no_com_script" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 241 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "0c_no_com_script" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAIScript" + }, + "Value": { + "type": "cexostring", + "value": "ai_a_defensive" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 240 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "0c_no_com_script" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAIScript" + }, + "Value": { + "type": "cexostring", + "value": "ai_a_ambusher" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 239 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "0c_no_com_script" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAIScript" + }, + "Value": { + "type": "cexostring", + "value": "ai_a_ranged" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 238 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "0c_no_com_script" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAIScript" + }, + "Value": { + "type": "cexostring", + "value": "ai_a_peaceful" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 237 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 5, + "Active": { + "type": "resref", + "value": "0c_if_taunt" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 236 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 6, + "Active": { + "type": "resref", + "value": "0c_if_cntrspell" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 235 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 7, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 234 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 8, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 233 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 9, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 232 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 10, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 202 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 11, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 0 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": " What do you think is the best tactic?" + } + } + }, + { + "__struct_id": 27, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 245 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 244 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 2, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 243 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 3, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 203 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + }, + { + "__struct_id": 4, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 0 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Sure, what would you like me to do?" + } + } + }, + { + "__struct_id": 28, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 29 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "RepliesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 249 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 248 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Speaker": { + "type": "cexostring", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Wel-met. I think we should work together, what do you say?" + } + } + } + ] + }, + "NumWords": { + "type": "dword", + "value": 1148 + }, + "PreventZoomIn": { + "type": "byte", + "value": 1 + }, + "ReplyList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "That will be all for now." + } + } + }, + { + "__struct_id": 1, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_get_convo" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Let us talk about something completely different." + } + } + }, + { + "__struct_id": 2, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 1 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "We should part ways." + } + } + }, + { + "__struct_id": 3, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "No, I like having you around." + } + } + }, + { + "__struct_id": 4, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_fire_henchmen" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Yes I'm sure, Perhapse we'll meet again." + } + } + }, + { + "__struct_id": 5, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Speaking" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "BaseMode" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 0 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lets change how much you speak.", + "id": 96511 + } + } + }, + { + "__struct_id": 6, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 2 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Can you use a special ability?", + "id": 96382 + } + } + }, + { + "__struct_id": 7, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "x2_d2_dshield" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Divine Shield.", + "id": 96383 + } + } + }, + { + "__struct_id": 8, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "x2_d2_dmight" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Divine Might.", + "id": 96384 + } + } + }, + { + "__struct_id": 9, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 3 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lay on Hands.", + "id": 96385 + } + } + }, + { + "__struct_id": 10, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I've changed my mind.", + "id": 88430 + } + } + }, + { + "__struct_id": 11, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "6" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "5" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88437 + } + } + }, + { + "__struct_id": 12, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "5" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "5" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88438 + } + } + }, + { + "__struct_id": 13, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "5" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88439 + } + } + }, + { + "__struct_id": 14, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "5" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88440 + } + } + }, + { + "__struct_id": 15, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "8" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "5" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my animal companion.", + "id": 88441 + } + } + }, + { + "__struct_id": 16, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "7" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "5" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my familiar.", + "id": 88442 + } + } + }, + { + "__struct_id": 17, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "5" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on me.", + "id": 88443 + } + } + }, + { + "__struct_id": 18, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "5" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on yourself.", + "id": 88444 + } + } + }, + { + "__struct_id": 19, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nFeat" + }, + "Value": { + "type": "cexostring", + "value": "257" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_use_feat" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use your bard song.", + "id": 88342 + } + } + }, + { + "__struct_id": 20, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 4 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use your construction shape.", + "id": 88342 + } + } + }, + { + "__struct_id": 21, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "740" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Iron Golem" + } + } + }, + { + "__struct_id": 22, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "739" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Demon Flesh Golem" + } + } + }, + { + "__struct_id": 23, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "738" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Stone Golem" + } + } + }, + { + "__struct_id": 24, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 5 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use your outsider shape.", + "id": 88342 + } + } + }, + { + "__struct_id": 25, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "735" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Death Slaad" + } + } + }, + { + "__struct_id": 26, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "734" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Rakshasa" + } + } + }, + { + "__struct_id": 27, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "733" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Azer" + } + } + }, + { + "__struct_id": 28, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 6 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use your humanoid shape.", + "id": 88342 + } + } + }, + { + "__struct_id": 29, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "684" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Kobold Assasin" + } + } + }, + { + "__struct_id": 30, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "683" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lizard folk" + } + } + }, + { + "__struct_id": 31, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "682" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Drow" + } + } + }, + { + "__struct_id": 32, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 7 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use your greater wild shape V.", + "id": 88342 + } + } + }, + { + "__struct_id": 33, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "691" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Mindflayer" + } + } + }, + { + "__struct_id": 34, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "679" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Medusa" + } + } + }, + { + "__struct_id": 35, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "694" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Dire Tiger" + } + } + }, + { + "__struct_id": 36, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 8 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use your greater wild shape III.", + "id": 88342 + } + } + }, + { + "__struct_id": 37, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "674" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Manticore" + } + } + }, + { + "__struct_id": 38, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "673" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Drider" + } + } + }, + { + "__struct_id": 39, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "670" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Basilisk" + } + } + }, + { + "__struct_id": 40, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 9 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use your greater wild shape II.", + "id": 88342 + } + } + }, + { + "__struct_id": 41, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "680" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Minotaur" + } + } + }, + { + "__struct_id": 42, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "678" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Gargoyle" + } + } + }, + { + "__struct_id": 43, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "672" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Harpy" + } + } + }, + { + "__struct_id": 44, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 10 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use your greater wild shape I.", + "id": 88342 + } + } + }, + { + "__struct_id": 45, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "662" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Green Wyrmling" + } + } + }, + { + "__struct_id": 46, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "661" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "White Wyrmling" + } + } + }, + { + "__struct_id": 47, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "660" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Black Wyrmling" + } + } + }, + { + "__struct_id": 48, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "659" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Blue Wyrmling" + } + } + }, + { + "__struct_id": 49, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "658" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Red Wyrmling" + } + } + }, + { + "__struct_id": 50, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 11 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use your elemental shape.", + "id": 88342 + } + } + }, + { + "__struct_id": 51, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "398" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Water" + } + } + }, + { + "__struct_id": 52, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "397" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Fire" + } + } + }, + { + "__struct_id": 53, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "399" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Earth" + } + } + }, + { + "__struct_id": 54, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "400" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Air" + } + } + }, + { + "__struct_id": 55, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 12 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use your wild shape.", + "id": 88342 + } + } + }, + { + "__struct_id": 56, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "405" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Badger" + } + } + }, + { + "__struct_id": 57, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "404" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Boar" + } + } + }, + { + "__struct_id": 58, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "403" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Wolf" + } + } + }, + { + "__struct_id": 59, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "402" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Panther" + } + } + }, + { + "__struct_id": 60, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "401" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_cast_polymorp" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Bear" + } + } + }, + { + "__struct_id": 61, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nEffectType" + }, + "Value": { + "type": "cexostring", + "value": "62" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "BaseMode" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 0 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_remove_effect" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Transform back into your natural form.", + "id": 96384 + } + } + }, + { + "__struct_id": 62, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 13 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I need you to summon something if you can." + } + } + }, + { + "__struct_id": 63, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "178" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 19 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Summon Creature IX.", + "id": 88353 + } + } + }, + { + "__struct_id": 64, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "182" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 19 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Summon Creature VIII.", + "id": 88354 + } + } + }, + { + "__struct_id": 65, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "181" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 19 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Summon Creature VII.", + "id": 88355 + } + } + }, + { + "__struct_id": 66, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "180" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 19 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Summon Creature VI.", + "id": 88356 + } + } + }, + { + "__struct_id": 67, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "179" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 19 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Summon Creature V.", + "id": 88358 + } + } + }, + { + "__struct_id": 68, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "177" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 19 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Summon Creature IV.", + "id": 88358 + } + } + }, + { + "__struct_id": 69, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "176" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 19 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Summon Creature III.", + "id": 88359 + } + } + }, + { + "__struct_id": 70, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "175" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 19 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Summon Creature II.", + "id": 88360 + } + } + }, + { + "__struct_id": 71, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "174" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 19 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Summon Creature I.", + "id": 88361 + } + } + }, + { + "__struct_id": 72, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "30" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 19 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Create Undead.", + "id": 88425 + } + } + }, + { + "__struct_id": 73, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 19 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Animate Dead.", + "id": 88446 + } + } + }, + { + "__struct_id": 74, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "x2_hen_tomishad4" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Summon Shadow." + } + } + }, + { + "__struct_id": 75, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAssociate" + }, + "Value": { + "type": "cexostring", + "value": "Familiar" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_summon_assoc" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Your Familiar." + } + } + }, + { + "__struct_id": 76, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAssociate" + }, + "Value": { + "type": "cexostring", + "value": "Companion" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_summon_assoc" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Your Companion." + } + } + }, + { + "__struct_id": 77, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "RestBuffing" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 14 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Let us talk about your defensive spells.", + "id": 89061 + } + } + }, + { + "__struct_id": 78, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 15 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast all your defensive spells.", + "id": 89063 + } + } + }, + { + "__struct_id": 79, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast on all the party members.", + "id": 88431 + } + } + }, + { + "__struct_id": 80, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "6" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88437 + } + } + }, + { + "__struct_id": 81, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "5" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88438 + } + } + }, + { + "__struct_id": 82, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88439 + } + } + }, + { + "__struct_id": 83, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88440 + } + } + }, + { + "__struct_id": 84, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "8" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my animal companion.", + "id": 88441 + } + } + }, + { + "__struct_id": 85, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "7" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my familiar.", + "id": 88442 + } + } + }, + { + "__struct_id": 86, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on me.", + "id": 88443 + } + } + }, + { + "__struct_id": 87, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on yourself.", + "id": 88444 + } + } + }, + { + "__struct_id": 88, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 16 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast all your long duration defensive spells.", + "id": 89064 + } + } + }, + { + "__struct_id": 89, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast on all the party members.", + "id": 88431 + } + } + }, + { + "__struct_id": 90, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "6" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88437 + } + } + }, + { + "__struct_id": 91, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "5" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88438 + } + } + }, + { + "__struct_id": 92, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88439 + } + } + }, + { + "__struct_id": 93, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88440 + } + } + }, + { + "__struct_id": 94, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "8" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my animal companion.", + "id": 88441 + } + } + }, + { + "__struct_id": 95, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "7" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my familiar.", + "id": 88442 + } + } + }, + { + "__struct_id": 96, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on me.", + "id": 88443 + } + } + }, + { + "__struct_id": 97, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on yourself.", + "id": 88444 + } + } + }, + { + "__struct_id": 98, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 17 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast all your short duration defensive spells.", + "id": 89065 + } + } + }, + { + "__struct_id": 99, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast on all the party members.", + "id": 88431 + } + } + }, + { + "__struct_id": 100, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "6" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88437 + } + } + }, + { + "__struct_id": 101, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "5" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88438 + } + } + }, + { + "__struct_id": 102, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88439 + } + } + }, + { + "__struct_id": 103, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88440 + } + } + }, + { + "__struct_id": 104, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "8" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my animal companion.", + "id": 88441 + } + } + }, + { + "__struct_id": 105, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "7" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my familiar.", + "id": 88442 + } + } + }, + { + "__struct_id": 106, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on me.", + "id": 88443 + } + } + }, + { + "__struct_id": 107, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on yourself.", + "id": 88444 + } + } + }, + { + "__struct_id": 108, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "RestBuffing" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "RestBuffing" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 14 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change if you cast long duration spells after resting." + } + } + }, + { + "__struct_id": 109, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 18 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I need you to cast a spell.", + "id": 88348 + } + } + }, + { + "__struct_id": 110, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "441" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 19 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Wounding Whispers.", + "id": 88350 + } + } + }, + { + "__struct_id": 111, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "365" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Ultravision.", + "id": 88351 + } + } + }, + { + "__struct_id": 112, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "186" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "True Seeing.", + "id": 88352 + } + } + }, + { + "__struct_id": 113, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "172" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Stoneskin.", + "id": 88362 + } + } + }, + { + "__struct_id": 114, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "168" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Spell Resistance.", + "id": 88363 + } + } + }, + { + "__struct_id": 115, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "169" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 19 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Spell Mantle.", + "id": 88364 + } + } + }, + { + "__struct_id": 116, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "450" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 19 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Shield of Faith.", + "id": 88365 + } + } + }, + { + "__struct_id": 117, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "417" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 19 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Shield.", + "id": 88366 + } + } + }, + { + "__struct_id": 118, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "159" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 19 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Shadow Shield.", + "id": 88367 + } + } + }, + { + "__struct_id": 119, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "157" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "See Invisibility.", + "id": 88368 + } + } + }, + { + "__struct_id": 120, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "154" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 19 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Sanctuary.", + "id": 88369 + } + } + }, + { + "__struct_id": 121, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "152" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Restoration.", + "id": 88370 + } + } + }, + { + "__struct_id": 122, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "151" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Resistance.", + "id": 88371 + } + } + }, + { + "__struct_id": 123, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "150" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Resist Elements.", + "id": 88372 + } + } + }, + { + "__struct_id": 124, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "149" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Remove Paralysis.", + "id": 88373 + } + } + }, + { + "__struct_id": 125, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "148" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Remove Fear.", + "id": 88374 + } + } + }, + { + "__struct_id": 126, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "147" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Remove Disease.", + "id": 88375 + } + } + }, + { + "__struct_id": 127, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "146" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Remove Curse.", + "id": 88376 + } + } + }, + { + "__struct_id": 128, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "145" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 19 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Remove Blindness/Deafness.", + "id": 88377 + } + } + }, + { + "__struct_id": 129, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "374" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Regenerate.", + "id": 88378 + } + } + }, + { + "__struct_id": 130, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "141" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Protection From Spells.", + "id": 88379 + } + } + }, + { + "__struct_id": 131, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "321" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Protection From Evil." + } + } + }, + { + "__struct_id": 132, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "137" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Protection From Elements.", + "id": 88380 + } + } + }, + { + "__struct_id": 133, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "134" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 19 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Premonition.", + "id": 88381 + } + } + }, + { + "__struct_id": 134, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "133" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 19 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Prayer.", + "id": 88382 + } + } + }, + { + "__struct_id": 135, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "355" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Owl's Wisdom.", + "id": 88383 + } + } + }, + { + "__struct_id": 136, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "126" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Neutralize poison.", + "id": 88384 + } + } + }, + { + "__struct_id": 137, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "525" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Monstrous Regeneration.", + "id": 88385 + } + } + }, + { + "__struct_id": 138, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "119" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 19 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Minor Globe of Invulnerability.", + "id": 88386 + } + } + }, + { + "__struct_id": 139, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "117" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Mind Blank.", + "id": 88387 + } + } + }, + { + "__struct_id": 140, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "113" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Mass Haste.", + "id": 88388 + } + } + }, + { + "__struct_id": 141, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "108" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Magical Vestment.", + "id": 88389 + } + } + }, + { + "__struct_id": 142, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "102" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Mage Armor.", + "id": 88390 + } + } + }, + { + "__struct_id": 143, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "100" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Light.", + "id": 88391 + } + } + }, + { + "__struct_id": 144, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "99" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 19 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lesser Spell Mantle.", + "id": 88392 + } + } + }, + { + "__struct_id": 145, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "97" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lesser Restoration.", + "id": 88393 + } + } + }, + { + "__struct_id": 146, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "95" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lesser Mind Blank", + "id": 88394 + } + } + }, + { + "__struct_id": 147, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "94" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lesser Dispel.", + "id": 88395 + } + } + }, + { + "__struct_id": 148, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "93" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 19 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Knock.", + "id": 88396 + } + } + }, + { + "__struct_id": 149, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "92" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 19 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Invisibility Sphere.", + "id": 88397 + } + } + }, + { + "__struct_id": 150, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "90" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Invisibility", + "id": 88398 + } + } + }, + { + "__struct_id": 151, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "88" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Improved Invisibility.", + "id": 88399 + } + } + }, + { + "__struct_id": 152, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "78" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Haste.", + "id": 88400 + } + } + }, + { + "__struct_id": 153, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "74" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Greater Stoneskin.", + "id": 88401 + } + } + }, + { + "__struct_id": 154, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "73" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 19 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Greater Spell Mantle.", + "id": 88402 + } + } + }, + { + "__struct_id": 155, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "443" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 19 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Greater Sanctuary.", + "id": 88403 + } + } + }, + { + "__struct_id": 156, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "70" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Greater Restoration.", + "id": 88404 + } + } + }, + { + "__struct_id": 157, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "109" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Greater Magic Weapon.", + "id": 88405 + } + } + }, + { + "__struct_id": 158, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "67" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Greater Dispelling.", + "id": 88406 + } + } + }, + { + "__struct_id": 159, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "65" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 19 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Globe of Invulnerability.", + "id": 88407 + } + } + }, + { + "__struct_id": 160, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "120" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 19 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Ghostly Visage.", + "id": 88408 + } + } + }, + { + "__struct_id": 161, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "62" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Freedom of Movement.", + "id": 88409 + } + } + }, + { + "__struct_id": 162, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "356" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Fox's Cunning", + "id": 88410 + } + } + }, + { + "__struct_id": 163, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "377" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 19 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Find Traps.", + "id": 88411 + } + } + }, + { + "__struct_id": 164, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "121" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 19 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Ethereal Visage.", + "id": 88412 + } + } + }, + { + "__struct_id": 165, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "418" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 19 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Entropic Shield.", + "id": 88413 + } + } + }, + { + "__struct_id": 166, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "369" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 19 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Energy Buffer.", + "id": 88414 + } + } + }, + { + "__struct_id": 167, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "No, I've changed my mind.", + "id": 88415 + } + } + }, + { + "__struct_id": 168, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Yes, go ahead.", + "id": 88416 + } + } + }, + { + "__struct_id": 169, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "50" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Endure Elements.", + "id": 88417 + } + } + }, + { + "__struct_id": 170, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "49" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Endurance.", + "id": 88418 + } + } + }, + { + "__struct_id": 171, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "47" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 19 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Elemental Shield.", + "id": 88419 + } + } + }, + { + "__struct_id": 172, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "354" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Eagle's Splendour.", + "id": 88420 + } + } + }, + { + "__struct_id": 173, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "42" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 19 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Divine Power.", + "id": 88421 + } + } + }, + { + "__struct_id": 174, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "41" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Dispel Magic.", + "id": 88422 + } + } + }, + { + "__struct_id": 175, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "38" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Death Ward.", + "id": 88423 + } + } + }, + { + "__struct_id": 176, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "519" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 19 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Death Armor.", + "id": 88424 + } + } + }, + { + "__struct_id": 177, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "419" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Continual Flame.", + "id": 88426 + } + } + }, + { + "__struct_id": 178, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "21" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Clarity.", + "id": 88427 + } + } + }, + { + "__struct_id": 179, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "13" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cat's Grace.", + "id": 88428 + } + } + }, + { + "__struct_id": 180, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "9" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Bull's Strength.", + "id": 88429 + } + } + }, + { + "__struct_id": 181, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "6" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88437 + } + } + }, + { + "__struct_id": 182, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "5" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88438 + } + } + }, + { + "__struct_id": 183, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88439 + } + } + }, + { + "__struct_id": 184, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88440 + } + } + }, + { + "__struct_id": 185, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "8" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my animal companion.", + "id": 88441 + } + } + }, + { + "__struct_id": 186, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "7" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my familiar.", + "id": 88442 + } + } + }, + { + "__struct_id": 187, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on me.", + "id": 88443 + } + } + }, + { + "__struct_id": 188, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on yourself.", + "id": 88444 + } + } + }, + { + "__struct_id": 189, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "6" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Bless.", + "id": 88445 + } + } + }, + { + "__struct_id": 190, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nSpell" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 20 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_h_cast_spell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Aid.", + "id": 88447 + } + } + }, + { + "__struct_id": 191, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 21 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I need you to cast a healing spell." + } + } + }, + { + "__struct_id": 192, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "BaseMode" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 0 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I've changed my mind.", + "id": 88430 + } + } + }, + { + "__struct_id": 193, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "0" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Heal up the whole party.", + "id": 88431 + } + } + }, + { + "__struct_id": 194, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "6" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88437 + } + } + }, + { + "__struct_id": 195, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "5" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88438 + } + } + }, + { + "__struct_id": 196, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88439 + } + } + }, + { + "__struct_id": 197, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "3" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on .", + "id": 88440 + } + } + }, + { + "__struct_id": 198, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "8" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my animal companion.", + "id": 88441 + } + } + }, + { + "__struct_id": 199, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "7" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on my familiar.", + "id": 88442 + } + } + }, + { + "__struct_id": 200, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "1" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on me.", + "id": 88443 + } + } + }, + { + "__struct_id": 201, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "nTarget" + }, + "Value": { + "type": "cexostring", + "value": "2" + } + }, + { + "__struct_id": 1, + "Key": { + "type": "cexostring", + "value": "nBuffType" + }, + "Value": { + "type": "cexostring", + "value": "4" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_henchmenspell" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Cast it on yourself.", + "id": 88444 + } + } + }, + { + "__struct_id": 202, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Plans" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 22 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I want to discuss how we can work together." + } + } + }, + { + "__struct_id": 203, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "BaseMode" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 0 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lets talk about something else." + } + } + }, + { + "__struct_id": 204, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Objects" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 23 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lets discuss how you deal with objects." + } + } + }, + { + "__struct_id": 205, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Bash" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Objects" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 23 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change your bashing tactics.", + "id": 96507 + } + } + }, + { + "__struct_id": 206, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Locks" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Objects" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 23 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change your lock picking tactics.", + "id": 96507 + } + } + }, + { + "__struct_id": 207, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Traps" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Objects" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 23 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change your trap tactics.", + "id": 96502 + } + } + }, + { + "__struct_id": 208, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Search" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Plans" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 22 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I need you to change your search tactics.", + "id": 96505 + } + } + }, + { + "__struct_id": 209, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Stealth" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Plans" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 22 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I need you to change your stealth tactics.", + "id": 96505 + } + } + }, + { + "__struct_id": 210, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 24 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Let's change how you use magic in combat." + } + } + }, + { + "__struct_id": 211, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "MagicItems" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 24 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change if you use magic items or not.", + "id": 96498 + } + } + }, + { + "__struct_id": 212, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Dispel" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 24 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change your dispel tactics.", + "id": 96500 + } + } + }, + { + "__struct_id": 213, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "BasicTactics" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 24 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Stop countering the enemies spells.", + "2": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"", + "3": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"" + } + } + }, + { + "__struct_id": 214, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "CounterSpell" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 24 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Counter the enemy spells!", + "2": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"", + "3": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"" + } + } + }, + { + "__struct_id": 215, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "BuffFirst" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 24 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change who you cast defensive spells on first.", + "id": 96500 + } + } + }, + { + "__struct_id": 216, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "OffensiveCasting" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 24 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change if you cast offensive spells.", + "id": 96498 + } + } + }, + { + "__struct_id": 217, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "DefensiveCasting" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 24 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change if you cast defensive spells.", + "id": 96498 + } + } + }, + { + "__struct_id": 218, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "NMagic" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 24 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change how you use magic spells in combat.", + "id": 96498 + } + } + }, + { + "__struct_id": 219, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "MagicPlus" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 24 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use your magic more in combat." + } + } + }, + { + "__struct_id": 220, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "MagicMinus" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Spells" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 24 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use your magic less in combat." + } + } + }, + { + "__struct_id": 221, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Healing" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 25 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lets change when you should heal.", + "id": 54985 + } + } + }, + { + "__struct_id": 222, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "HealOutPlus" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Healing" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 25 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Increase the health an one needs for you to heal out of combat.", + "id": 54990 + } + } + }, + { + "__struct_id": 223, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "HealOutMinus" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Healing" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 25 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Reduce the health an one needs for you to heal out of combat.", + "id": 54989 + } + } + }, + { + "__struct_id": 224, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "HealInPlus" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Healing" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 25 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Increase the health an one needs for you to heal during combat.", + "id": 54990 + } + } + }, + { + "__struct_id": 225, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "HealInMinus" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Healing" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 25 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Reduce the health any one needs for you to heal during combat.", + "id": 54989 + } + } + }, + { + "__struct_id": 226, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "HealSelf" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Healing" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 25 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change if you heal yourself.", + "id": 54989 + } + } + }, + { + "__struct_id": 227, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "HealAllies" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Healing" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 25 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change if you heal any allies.", + "id": 54989 + } + } + }, + { + "__struct_id": 228, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Pickup" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Plans" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 22 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lets change if you pickup items and gold." + } + } + }, + { + "__struct_id": 229, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "FollowFarther" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Plans" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 22 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Follow farther away from me.", + "id": 96510 + } + } + }, + { + "__struct_id": 230, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "FollowCloser" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "Plans" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 22 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Follow closer to me.", + "id": 96511 + } + } + }, + { + "__struct_id": 231, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 26 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Lets talk about your tactics in combat." + } + } + }, + { + "__struct_id": 232, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "AttackTactics" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 26 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change if you fight every opponent during combat.", + "2": "\"Je ne veux pas du tout que vous vous engagiez dans un combat à distance rapproché,eloignez vous de l'enemi s'il devient trop proche!\"", + "3": "\"Je ne veux pas du tout que vous vous engagiez dans un combat à distance rapproché,eloignez vous de l'enemi s'il devient trop proche!\"" + } + } + }, + { + "__struct_id": 233, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "AtkAssociates" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 26 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change your tactics against familiars, companions, and summons.", + "id": 62531 + } + } + }, + { + "__struct_id": 234, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Ranged" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 26 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Change your ranged combat tactics.", + "id": 62531 + } + } + }, + { + "__struct_id": 235, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "CounterSpell" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 26 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I want you to counter spell the enemy!", + "2": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"", + "3": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"" + } + } + }, + { + "__struct_id": 236, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Taunt" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 26 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I want you to taunt the enemy!", + "2": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"", + "3": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"" + } + } + }, + { + "__struct_id": 237, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "PeaceTactics" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 26 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Don't engage in combat.", + "2": "\"Je ne veux pas du tout que vous vous engagiez dans un combat à distance rapproché,eloignez vous de l'enemi s'il devient trop proche!\"", + "3": "\"Je ne veux pas du tout que vous vous engagiez dans un combat à distance rapproché,eloignez vous de l'enemi s'il devient trop proche!\"" + } + } + }, + { + "__struct_id": 238, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "RangedTactics" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 26 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use agressive ranged tactics, stay out of melee.", + "2": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"", + "3": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"" + } + } + }, + { + "__struct_id": 239, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "AmbushTactics" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 26 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use ambush tactics, hide and then strike.", + "2": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"", + "3": "\"Je veux que vous fassiez confiance à votre instinct du moment où il faut changer entre armes de mélée ou à projectiles.\"" + } + } + }, + { + "__struct_id": 240, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "DefensiveTactics" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 26 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use defensive tactics to protect yourself.", + "id": 62532 + } + } + }, + { + "__struct_id": 241, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "BasicTactics" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 1 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "CombatTactics" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 26 + }, + "IsChild": { + "type": "byte", + "value": 1 + }, + "LinkComment": { + "type": "cexostring", + "value": "" + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Use your best judgement in combat.", + "id": 62531 + } + } + }, + { + "__struct_id": 242, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 27 + }, + "IsChild": { + "type": "byte", + "value": 0 + } + } + ] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Can we talk about your items?" + } + } + }, + { + "__struct_id": 243, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "GiveMagicItems" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Give me all the magical items in your inventory.", + "id": 96514 + } + } + }, + { + "__struct_id": 244, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "GiveUnIdentifiedItems" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Give me all your unidentified items.", + "id": 96514 + } + } + }, + { + "__struct_id": 245, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "x0_d1_hen_inven" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I want to adjust your equipment.", + "id": 96514 + } + } + }, + { + "__struct_id": 246, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Identify" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Can you identify our equipment?", + "id": 88341 + } + } + }, + { + "__struct_id": 247, + "ActionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sAction" + }, + "Value": { + "type": "cexostring", + "value": "Scout" + } + } + ] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_assoc_actions" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "I would like you to scout the area." + } + } + }, + { + "__struct_id": 248, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 0 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Not right now." + } + } + }, + { + "__struct_id": 249, + "ActionParams": { + "type": "list", + "value": [] + }, + "Animation": { + "type": "dword", + "value": 45 + }, + "AnimLoop": { + "type": "byte", + "value": 1 + }, + "Comment": { + "type": "cexostring", + "value": "" + }, + "Delay": { + "type": "dword", + "value": 4294967295 + }, + "EntriesList": { + "type": "list", + "value": [] + }, + "Quest": { + "type": "cexostring", + "value": "" + }, + "Script": { + "type": "resref", + "value": "0c_get_henchman" + }, + "Sound": { + "type": "resref", + "value": "" + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Yea, thats a good idea." + } + } + } + ] + }, + "StartingList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Active": { + "type": "resref", + "value": "0c_if_not_master" + }, + "ConditionParams": { + "type": "list", + "value": [] + }, + "Index": { + "type": "dword", + "value": 28 + } + }, + { + "__struct_id": 1, + "Active": { + "type": "resref", + "value": "0c_if_ass_convo" + }, + "ConditionParams": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Key": { + "type": "cexostring", + "value": "sOption" + }, + "Value": { + "type": "cexostring", + "value": "BaseMode" + } + } + ] + }, + "Index": { + "type": "dword", + "value": 0 + } + } + ] + } +} diff --git a/src/module/ifo/module.ifo.json b/src/module/ifo/module.ifo.json index abd4cc2..b7c56a4 100644 --- a/src/module/ifo/module.ifo.json +++ b/src/module/ifo/module.ifo.json @@ -606,7 +606,7 @@ "Mod_Description": { "type": "cexolocstring", "value": { - "0": "HardCore DND Rules Base Module Project\nStarted by Archaegeo, 20 Jun 2002\nModified by Jamos.\nFurther modified by Harkinian.\nCurrent revision: 3.2.0\n\nRead the about_ scripts for info on the scripts.\n\nIt had started simple enough. Seek the leaders of the Giant alliance that was raiding mankinds lands and destroy them. Well, the Giant alliance is no more but you are no nearer to finding the true leader behind their actions. True you now know the Drow were behind it but who is the true leader?\nYour quest has seen you pass deep into the Underdark and through the ancient Shrine of the Kuo Toa. Now having at last escaped the Shrine the quest continues....the Vault of the Drow beckons" + "0": "HardCore DND Rules Base Module Project\nStarted by Archaegeo, 20 Jun 2002\nModified by Jamos.\nFurther modified by Harkinian.\nCurrent revision: 3.2.0\n\nNOW WITH PEPS!\n\nRead the about_ scripts for info on the scripts.\n\nIt had started simple enough. Seek the leaders of the Giant alliance that was raiding mankinds lands and destroy them. Well, the Giant alliance is no more but you are no nearer to finding the true leader behind their actions. True you now know the Drow were behind it but who is the true leader?\nYour quest has seen you pass deep into the Underdark and through the ancient Shrine of the Kuo Toa. Now having at last escaped the Shrine the quest continues....the Vault of the Drow beckons" } }, "Mod_DuskHour": { @@ -648,6 +648,13 @@ "Mod_HakList": { "type": "list", "value": [ + { + "__struct_id": 8, + "Mod_Hak": { + "type": "cexostring", + "value": "peps_prc8" + } + }, { "__struct_id": 8, "Mod_Hak": { diff --git a/src/module/nss/0c_assoc_actions.nss b/src/module/nss/0c_assoc_actions.nss new file mode 100644 index 0000000..74975d4 --- /dev/null +++ b/src/module/nss/0c_assoc_actions.nss @@ -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); +} diff --git a/src/module/nss/0c_cast_polymorp.nss b/src/module/nss/0c_cast_polymorp.nss new file mode 100644 index 0000000..b06f183 --- /dev/null +++ b/src/module/nss/0c_cast_polymorp.nss @@ -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); +} + diff --git a/src/module/nss/0c_fire_henchmen.nss b/src/module/nss/0c_fire_henchmen.nss new file mode 100644 index 0000000..5505be9 --- /dev/null +++ b/src/module/nss/0c_fire_henchmen.nss @@ -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); +} + diff --git a/src/module/nss/0c_get_convo.nss b/src/module/nss/0c_get_convo.nss new file mode 100644 index 0000000..7cdfd40 --- /dev/null +++ b/src/module/nss/0c_get_convo.nss @@ -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())); +} diff --git a/src/module/nss/0c_get_henchman.nss b/src/module/nss/0c_get_henchman.nss new file mode 100644 index 0000000..e0952d5 --- /dev/null +++ b/src/module/nss/0c_get_henchman.nss @@ -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); +} + + diff --git a/src/module/nss/0c_h_cast_spell.nss b/src/module/nss/0c_h_cast_spell.nss new file mode 100644 index 0000000..40868d8 --- /dev/null +++ b/src/module/nss/0c_h_cast_spell.nss @@ -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"))); +} diff --git a/src/module/nss/0c_henchmenspell.nss b/src/module/nss/0c_henchmenspell.nss new file mode 100644 index 0000000..5e64cba --- /dev/null +++ b/src/module/nss/0c_henchmenspell.nss @@ -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; +} diff --git a/src/module/nss/0c_if_a_magic_m.nss b/src/module/nss/0c_if_a_magic_m.nss new file mode 100644 index 0000000..7ef4832 --- /dev/null +++ b/src/module/nss/0c_if_a_magic_m.nss @@ -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); +} diff --git a/src/module/nss/0c_if_ass_convo.nss b/src/module/nss/0c_if_ass_convo.nss new file mode 100644 index 0000000..190a0f7 --- /dev/null +++ b/src/module/nss/0c_if_ass_convo.nss @@ -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; +} diff --git a/src/module/nss/0c_if_assoc_mode.nss b/src/module/nss/0c_if_assoc_mode.nss new file mode 100644 index 0000000..342bfff --- /dev/null +++ b/src/module/nss/0c_if_assoc_mode.nss @@ -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); +} diff --git a/src/module/nss/0c_if_cntrspell.nss b/src/module/nss/0c_if_cntrspell.nss new file mode 100644 index 0000000..a0a5c87 --- /dev/null +++ b/src/module/nss/0c_if_cntrspell.nss @@ -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"); +} diff --git a/src/module/nss/0c_if_com_script.nss b/src/module/nss/0c_if_com_script.nss new file mode 100644 index 0000000..34d8370 --- /dev/null +++ b/src/module/nss/0c_if_com_script.nss @@ -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); +} diff --git a/src/module/nss/0c_if_convo.nss b/src/module/nss/0c_if_convo.nss new file mode 100644 index 0000000..83e1db4 --- /dev/null +++ b/src/module/nss/0c_if_convo.nss @@ -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; +} diff --git a/src/module/nss/0c_if_has_assoc.nss b/src/module/nss/0c_if_has_assoc.nss new file mode 100644 index 0000000..cd16680 --- /dev/null +++ b/src/module/nss/0c_if_has_assoc.nss @@ -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); +} diff --git a/src/module/nss/0c_if_has_class.nss b/src/module/nss/0c_if_has_class.nss new file mode 100644 index 0000000..1251c0a --- /dev/null +++ b/src/module/nss/0c_if_has_class.nss @@ -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; +} diff --git a/src/module/nss/0c_if_has_feat.nss b/src/module/nss/0c_if_has_feat.nss new file mode 100644 index 0000000..fc111d8 --- /dev/null +++ b/src/module/nss/0c_if_has_feat.nss @@ -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)); +} diff --git a/src/module/nss/0c_if_has_spell.nss b/src/module/nss/0c_if_has_spell.nss new file mode 100644 index 0000000..02004ff --- /dev/null +++ b/src/module/nss/0c_if_has_spell.nss @@ -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; +} diff --git a/src/module/nss/0c_if_hen_leave.nss b/src/module/nss/0c_if_hen_leave.nss new file mode 100644 index 0000000..e2b2bbd --- /dev/null +++ b/src/module/nss/0c_if_hen_leave.nss @@ -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; +} diff --git a/src/module/nss/0c_if_identify.nss b/src/module/nss/0c_if_identify.nss new file mode 100644 index 0000000..b593baf --- /dev/null +++ b/src/module/nss/0c_if_identify.nss @@ -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); +} diff --git a/src/module/nss/0c_if_not_master.nss b/src/module/nss/0c_if_not_master.nss new file mode 100644 index 0000000..73cb84e --- /dev/null +++ b/src/module/nss/0c_if_not_master.nss @@ -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()); +} diff --git a/src/module/nss/0c_if_open_inven.nss b/src/module/nss/0c_if_open_inven.nss new file mode 100644 index 0000000..2755c99 --- /dev/null +++ b/src/module/nss/0c_if_open_inven.nss @@ -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; +} diff --git a/src/module/nss/0c_if_pickuploot.nss b/src/module/nss/0c_if_pickuploot.nss new file mode 100644 index 0000000..f4edfdb --- /dev/null +++ b/src/module/nss/0c_if_pickuploot.nss @@ -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; +} diff --git a/src/module/nss/0c_if_polymorph.nss b/src/module/nss/0c_if_polymorph.nss new file mode 100644 index 0000000..e2317f6 --- /dev/null +++ b/src/module/nss/0c_if_polymorph.nss @@ -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; +} diff --git a/src/module/nss/0c_if_scout.nss b/src/module/nss/0c_if_scout.nss new file mode 100644 index 0000000..9f7b0a3 --- /dev/null +++ b/src/module/nss/0c_if_scout.nss @@ -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; +} diff --git a/src/module/nss/0c_if_skillrank.nss b/src/module/nss/0c_if_skillrank.nss new file mode 100644 index 0000000..e0d7729 --- /dev/null +++ b/src/module/nss/0c_if_skillrank.nss @@ -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); +} diff --git a/src/module/nss/0c_if_taunt.nss b/src/module/nss/0c_if_taunt.nss new file mode 100644 index 0000000..3e0fde6 --- /dev/null +++ b/src/module/nss/0c_if_taunt.nss @@ -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"); +} diff --git a/src/module/nss/0c_listhenchman.nss b/src/module/nss/0c_listhenchman.nss new file mode 100644 index 0000000..802f100 --- /dev/null +++ b/src/module/nss/0c_listhenchman.nss @@ -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); + } +} diff --git a/src/module/nss/0c_no_com_script.nss b/src/module/nss/0c_no_com_script.nss new file mode 100644 index 0000000..ca5c386 --- /dev/null +++ b/src/module/nss/0c_no_com_script.nss @@ -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); +} diff --git a/src/module/nss/0c_remove_effect.nss b/src/module/nss/0c_remove_effect.nss new file mode 100644 index 0000000..aa95a0c --- /dev/null +++ b/src/module/nss/0c_remove_effect.nss @@ -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); +} + diff --git a/src/module/nss/0c_summon_assoc.nss b/src/module/nss/0c_summon_assoc.nss new file mode 100644 index 0000000..19544de --- /dev/null +++ b/src/module/nss/0c_summon_assoc.nss @@ -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 (); +} diff --git a/src/module/nss/0c_use_feat.nss b/src/module/nss/0c_use_feat.nss new file mode 100644 index 0000000..ec3ddcc --- /dev/null +++ b/src/module/nss/0c_use_feat.nss @@ -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); +} diff --git a/src/module/nss/0e_c2_1_hb.nss b/src/module/nss/0e_c2_1_hb.nss new file mode 100644 index 0000000..05fbfc2 --- /dev/null +++ b/src/module/nss/0e_c2_1_hb.nss @@ -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"); +} diff --git a/src/module/nss/0e_c2_7_ondeath.nss b/src/module/nss/0e_c2_7_ondeath.nss new file mode 100644 index 0000000..129e81e --- /dev/null +++ b/src/module/nss/0e_c2_7_ondeath.nss @@ -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")); +} + diff --git a/src/module/nss/0e_ch_1_hb.nss b/src/module/nss/0e_ch_1_hb.nss new file mode 100644 index 0000000..d04eeb8 --- /dev/null +++ b/src/module/nss/0e_ch_1_hb.nss @@ -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"); +} diff --git a/src/module/nss/0e_ch_7_ondeath.nss b/src/module/nss/0e_ch_7_ondeath.nss new file mode 100644 index 0000000..76d955d --- /dev/null +++ b/src/module/nss/0e_ch_7_ondeath.nss @@ -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")); +} + diff --git a/src/module/nss/0e_do_combat_rnd.nss b/src/module/nss/0e_do_combat_rnd.nss new file mode 100644 index 0000000..f1cb9c0 --- /dev/null +++ b/src/module/nss/0e_do_combat_rnd.nss @@ -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); + } +} diff --git a/src/module/nss/0e_gui_events.nss b/src/module/nss/0e_gui_events.nss new file mode 100644 index 0000000..401c825 --- /dev/null +++ b/src/module/nss/0e_gui_events.nss @@ -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); + } + } + } + } +} diff --git a/src/module/nss/0e_m1_3_endround.nss b/src/module/nss/0e_m1_3_endround.nss new file mode 100644 index 0000000..e8a0125 --- /dev/null +++ b/src/module/nss/0e_m1_3_endround.nss @@ -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)); + } +} + + + + diff --git a/src/module/nss/0e_nui.nss b/src/module/nss/0e_nui.nss new file mode 100644 index 0000000..7d18c65 --- /dev/null +++ b/src/module/nss/0e_nui.nss @@ -0,0 +1,1975 @@ +/*////////////////////////////////////////////////////////////////////////////// + Script Name: 0e_nui + Programmer: Philos +//////////////////////////////////////////////////////////////////////////////// + Menu event script + sEvent: close, click, mousedown, mouseup, watch (if bindwatch is set). +/*////////////////////////////////////////////////////////////////////////////// +#include "nw_inc_gff" +#include "x0_i0_assoc" +#include "0i_menus" +#include "0i_player_target" +// Save a window ID to the database. +void ai_SaveWindowLocation(object oPC, int nToken, string sAssociateType, string sWindowID); +// Sets the Widget Buttons state to sElem Checkbox state. +void ai_SetWidgetButtonToCheckbox(object oPC, int nButton, object oAssociate, string sAssociateType, int nToken, string sElem); +// Flips an AI Buttons state to sElem Checkbox state. +void ai_SetAIButtonToCheckbox(object oPC, int nButton, object oAssociate, string sAssociateType, int nToken, string sElem); +// Flips the flag for the loot filter to sElem Checkbox state. +void ai_SetLootFilterToCheckbox(object oPC, object oAssociate, int nFilterBit, int nToken, string sElem); +// Sets an associates companion type. Cannot set companion for a player! +void ai_SetCompanionType(object oPC, object oAssociate, int nToken, int nCompanionType); +// Sets an associates companion name. Cannot set companion for a player! +void ai_SetCompanionName(object oPC, object oAssociate, int nToken, int nCompanionType); +// Sets an associates AI script via a combo box. +void ai_SetAIScript(object oPC, object oAssociate, int nToken); +// Increments/Decrements the Perception Range use variable for the AI. +void ai_PercRangeIncrement(object oPC, object oAssociate, int nIncrement, string sAssociateType, int nToken); +// Saves an associates perception range changed on the button. +void ai_Perc_Range(object oPC, object oAssociate, int nToken, string sAssociateType); +// Changes Perception Distance Rule for monsters. +void ai_RulePercDistInc(object oPC, object oModule, int nIncrement, int nToken); +// Adds a spell to a json AI restricted spell list then returns jRules. +// bRestrict = TRUE will add to the list FALSE will remove it from the list. +json ai_AddRestrictedSpell(json jRules, int nSpell, int bRestrict = TRUE); +// Turns on oAssociate AI, Setting all event scripts. +void ai_TurnOn(object oPC, object oAssociate, string sAssociateType); +// Turns off oAssociate AI, Setting all event scripts. +void ai_TurnOff(object oPC, object oAssociate, string sAssociateType); +// Adds a henchman back into the players party. +object ai_AddHenchman(object oPC, json jHenchman, location lLocation, int nFamiliar, int nCompanion); + +void ai_SaveWindowLocation(object oPC, int nToken, string sAssociateType, string sWindowID) +{ + json jGeometry = NuiGetBind(oPC, nToken, "window_geometry"); + float fX = JsonGetFloat(JsonObjectGet(jGeometry, "x")); + float fY = JsonGetFloat(JsonObjectGet(jGeometry, "y")); + json jLocations = ai_GetAssociateDbJson(oPC, sAssociateType, "locations"); + if(JsonGetType(jLocations) == JSON_TYPE_NULL) jLocations = JsonObject(); + json jWindow = JsonObjectGet(jLocations, sWindowID); + if(JsonGetType(jWindow) == JSON_TYPE_NULL) jWindow = JsonObject(); + jWindow = JsonObjectSet(jWindow, "x", JsonFloat(fX)); + jWindow = JsonObjectSet(jWindow, "y", JsonFloat(fY)); + jLocations = JsonObjectSet(jLocations, sWindowID, jWindow); + //SendMessageToPC(oPC, "0e_nui, 52, sAssociateType: " + sAssociateType + + // " sWindowID: " + sWindowID + + // " jLocations: " + JsonDump(jLocations, 1)); + ai_SetAssociateDbJson(oPC, sAssociateType, "locations", jLocations); +} +void ai_ToggleAssociateWidgetOnOff(object oPC, int nToken, object oAssociate, string sAssociateType) +{ + string sText, sText2, sName = GetName(oAssociate); + if(GetStringRight(sName, 1) == "s") sName = sName + "'"; + else sName = sName + "'s"; + int bWidget = !ai_GetWidgetButton(oPC, BTN_WIDGET_OFF, oAssociate, sAssociateType); + ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oAssociate, sAssociateType, bWidget); + NuiSetBind(oPC, nToken, "btn_widget_onoff", JsonBool (!bWidget)); + if(bWidget) + { + sText = "on"; + sText2 = "Off"; + IsWindowClosed(oPC, sAssociateType + AI_WIDGET_NUI); + } + else + { + sText = "off"; + sText2 = "On"; + ai_CreateWidgetNUI(oPC, oAssociate); + } + NuiSetBind(oPC, nToken, "btn_widget_onoff_label", JsonString("Widget " + sText2)); + NuiSetBind(oPC, nToken, "btn_widget_onoff_tooltip", JsonString(" Turn " + sName + " widget " + sText)); +} +void main() +{ + object oPC = NuiGetEventPlayer(); + int nToken = NuiGetEventWindow(); + string sEvent = NuiGetEventType(); + string sElem = NuiGetEventElement(); + int nIndex = NuiGetEventArrayIndex(); + string sWndId = NuiGetWindowId(oPC, nToken); + //SendMessageToPC(oPC, "0e_nui , 64 sWndId: " + sWndId + " sEvent: " + sEvent + " sElem: " + sElem + + // " nToken: " + IntToString(nToken) + " nIndex: " + IntToString(nIndex) + + // " oPC: " + GetName(oPC)); + // Get if the menu has an associate attached. + json jData = NuiGetUserData(oPC, nToken); + object oAssociate = StringToObject(JsonGetString(JsonArrayGet(jData, 0))); + string sAssociateType = ai_GetAssociateType(oPC, oAssociate); + if(!ai_GetIsCharacter(oAssociate) && !GetLocalInt(oPC, "AI_IGNORE_NO_ASSOCIATE") && + (oAssociate == OBJECT_INVALID || GetMaster(oAssociate) != oPC)) + { + ai_SendMessages("This creature is no longer in your party!", AI_COLOR_RED, oPC); + DelayCommand(0.0, NuiDestroy(oPC, nToken)); + return; + } + if(sAssociateType == "") return; + //************************************************************************** + // Watch to see if the window moves and save. + if(sElem == "window_geometry" && sEvent == "watch") + { + if(GetLocalInt(oPC, AI_NO_NUI_SAVE)) return; + // If the widget is locked then don't save. + if(sWndId == sAssociateType + AI_WIDGET_NUI && + ai_GetWidgetButton(oPC, BTN_WIDGET_LOCK, oAssociate, sAssociateType)) return; + ai_SaveWindowLocation(oPC, nToken, sAssociateType, sWndId); + return; + } + //************************************************************************** + // Main AI events. + if(sWndId == AI_MAIN_NUI) + { + //if(GetLocalInt(oPC, AI_NO_NUI_SAVE)) return; + if(sEvent == "click") + { + if(sElem == "btn_plugin_manager") + { + DelayCommand(0.0, NuiDestroy(oPC, nToken)); + ai_CreatePluginNUI(oPC); + } + else if(sElem == "btn_action_ghost") + { + // We set ghost mode differently for each AI. + if(ResManGetAliasFor("ai_a_default", RESTYPE_NCS) == "") + { + if(GetLocalInt(oPC, sGhostModeVarname)) + { + DeleteLocalInt(oPC, sGhostModeVarname); + ai_SendMessages("Action Ghost mode is turned off when using commands.", AI_COLOR_YELLOW, 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_RemoveASpecificEffect(oAssociate, EFFECT_TYPE_CUTSCENEGHOST); + DeleteLocalInt(oAssociate, sGhostModeVarname); + } + } + for(nIndex = 2; nIndex < 6; nIndex++) + { + oAssociate = GetAssociate(nIndex, oPC); + if(oAssociate != OBJECT_INVALID) + { + ai_RemoveASpecificEffect(oAssociate, EFFECT_TYPE_CUTSCENEGHOST); + DeleteLocalInt(oAssociate, sGhostModeVarname); + } + } + } + else + { + SetLocalInt(oPC, sGhostModeVarname, TRUE); + ai_SendMessages("Action Ghost mode is turned on when using commands.", AI_COLOR_YELLOW, oPC); + } + } + else + { + if(ai_GetAIMode(oPC, AI_MODE_ACTION_GHOST)) + { + ai_SetAIMode(oPC, AI_MODE_ACTION_GHOST, FALSE); + ai_SendMessages("Action Ghost mode is turned off when using commands.", AI_COLOR_YELLOW, 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_GetAIMode(oAssociate, AI_MODE_GHOST)) + { + 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)) + { + ai_RemoveASpecificEffect(oAssociate, EFFECT_TYPE_CUTSCENEGHOST); + DeleteLocalInt(oAssociate, sGhostModeVarname); + } + } + } + else + { + ai_SetAIMode(oPC, AI_MODE_ACTION_GHOST); + ai_SendMessages("Action Ghost mode is turned on when using commands.", AI_COLOR_YELLOW, oPC); + } + aiSaveAssociateModesToDb(oPC, oPC); + } + } + else if(sElem == "btn_toggle_assoc_widget") + { + int bWidgetOff = !ai_GetWidgetButton(oPC, BTN_WIDGET_OFF, oPC, "pc"); + string sAssocType; + ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oPC, "pc", bWidgetOff); + object oAssoc = GetAssociate(ASSOCIATE_TYPE_FAMILIAR, oPC); + if(oAssoc != OBJECT_INVALID) + { + sAssocType = ai_GetAssociateType(oPC, oAssoc); + ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oAssoc, sAssocType, bWidgetOff); + if(bWidgetOff) IsWindowClosed(oPC, sAssocType + AI_WIDGET_NUI); + else ai_CreateWidgetNUI(oPC, oAssoc); + } + oAssoc = GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION, oPC); + if(oAssoc != OBJECT_INVALID) + { + sAssocType = ai_GetAssociateType(oPC, oAssoc); + ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oAssoc, sAssocType, bWidgetOff); + if(bWidgetOff) IsWindowClosed(oPC, sAssocType + AI_WIDGET_NUI); + else ai_CreateWidgetNUI(oPC, oAssoc); + } + oAssoc = GetAssociate(ASSOCIATE_TYPE_SUMMONED, oPC); + if(oAssoc != OBJECT_INVALID) + { + sAssocType = ai_GetAssociateType(oPC, oAssoc); + ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oAssoc, sAssocType, bWidgetOff); + if(bWidgetOff) IsWindowClosed(oPC, sAssocType + AI_WIDGET_NUI); + else ai_CreateWidgetNUI(oPC, oAssoc); + } + oAssoc = GetAssociate(ASSOCIATE_TYPE_DOMINATED, oPC); + if(oAssoc != OBJECT_INVALID) + { + sAssocType = ai_GetAssociateType(oPC, oAssoc); + ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oAssoc, sAssocType, bWidgetOff); + if(bWidgetOff) IsWindowClosed(oPC, sAssocType + AI_WIDGET_NUI); + else ai_CreateWidgetNUI(oPC, oAssoc); + } + int nIndex; + object oHenchman; + for(nIndex = 1; nIndex <= AI_MAX_HENCHMAN; nIndex++) + { + oHenchman = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex); + if(oHenchman != OBJECT_INVALID) + { + sAssocType = ai_GetAssociateType(oPC, oHenchman); + ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oHenchman, sAssocType, bWidgetOff); + if(bWidgetOff) IsWindowClosed(oPC, sAssocType + AI_WIDGET_NUI); + else ai_CreateWidgetNUI(oPC, oHenchman); + } + } + } + else if(sElem == "btn_effect_icon") + { + if(ai_GetMagicMode(oPC, AI_MAGIC_EFFECT_ICON_REPORT)) + { + ai_SetMagicMode(oPC, AI_MAGIC_EFFECT_ICON_REPORT, FALSE); + ai_SendMessages("All effect icons will be reported in a menu at the top of the screen.", AI_COLOR_YELLOW, oPC); + } + else + { + ai_SetMagicMode(oPC, AI_MAGIC_EFFECT_ICON_REPORT); + ai_SendMessages("All effect icons will be reported in the chat screen.", AI_COLOR_YELLOW, oPC); + } + aiSaveAssociateModesToDb(oPC, oPC); + } + if(sElem == "btn_default_xp") + { + int nDefaultXP = GetLocalInt(GetModule(), AI_RULE_DEFAULT_XP_SCALE); + SetModuleXPScale(nDefaultXP); + NuiSetBind(oPC, nToken, "txt_xp_scale", JsonString(IntToString(nDefaultXP))); + } + } + if(sEvent == "watch") + { + string sPreElem = GetStringLeft(sElem, 4); + if(sPreElem == "txt_") + { + object oModule = GetModule(); + json jRules = ai_GetCampaignDbJson("rules"); + string sText = JsonGetString(NuiGetBind(oPC, nToken, sElem)); + if(sElem == "txt_max_henchman") + { + int nMaxHenchmen = StringToInt(sText); + if(nMaxHenchmen < 1) nMaxHenchmen = 1; + if(nMaxHenchmen > 12) + { + nMaxHenchmen = 12; + ai_SendMessages("The maximum henchmen for this mod is 12!", AI_COLOR_RED, oPC); + } + SetMaxHenchmen(nMaxHenchmen); + SetLocalInt(oModule, AI_RULE_MAX_HENCHMAN, nMaxHenchmen); + jRules = JsonObjectSet(jRules, AI_RULE_MAX_HENCHMAN, JsonInt(nMaxHenchmen)); + ai_SendMessages("Maximum henchmen has been changed to " + IntToString(nMaxHenchmen), AI_COLOR_YELLOW, oPC); + } + else if(sElem == "txt_ai_difficulty") + { + int nChance = StringToInt(sText); + if(nChance < 0) nChance = 0; + else if(nChance > 100) nChance = 100; + SetLocalInt(oModule, AI_RULE_AI_DIFFICULTY, nChance); + jRules = JsonObjectSet(jRules, AI_RULE_AI_DIFFICULTY, JsonInt(nChance)); + } + else if(sElem == "txt_perception_distance") + { + float fDistance = StringToFloat(sText); + if(fDistance < 10.0) fDistance = 10.0; + else if(fDistance > 60.0) fDistance = 60.0; + SetLocalFloat(oModule, AI_RULE_PERCEPTION_DISTANCE, fDistance); + jRules = JsonObjectSet(jRules, AI_RULE_PERCEPTION_DISTANCE, JsonFloat(fDistance)); + } + else if(sElem == "txt_inc_enc") + { + float fNumber = StringToFloat(sText); + if(fNumber < 0.0) fNumber = 0.0; + else if(fNumber > 9.0) fNumber = 9.0; + SetLocalFloat(oModule, AI_INCREASE_ENC_MONSTERS, fNumber); + jRules = JsonObjectSet(jRules, AI_INCREASE_ENC_MONSTERS, JsonFloat(fNumber)); + } + else if(sElem == "txt_inc_hp") + { + int nNumber = StringToInt(sText); + if(nNumber < 0) nNumber = 0; + else if(nNumber > 100) nNumber = 100; + SetLocalInt(oModule, AI_INCREASE_MONSTERS_HP, nNumber); + jRules = JsonObjectSet(jRules, AI_INCREASE_MONSTERS_HP, JsonInt(nNumber)); + } + else if(sElem == "txt_wander_distance") + { + float fDistance = StringToFloat(sText); + if(fDistance < 0.0) fDistance = 0.0; + else if(fDistance > 99.0) fDistance = 99.0; + SetLocalFloat(oModule, AI_RULE_WANDER_DISTANCE, fDistance); + jRules = JsonObjectSet(jRules, AI_RULE_WANDER_DISTANCE, JsonFloat(fDistance)); + } + else if(sElem == "txt_xp_scale") + { + int nNumber = StringToInt(sText); + if(nNumber < 0) nNumber = 0; + else if(nNumber > 200) nNumber = 200; + SetModuleXPScale(nNumber); + return; + } + ai_SetCampaignDbJson("rules", jRules); + } + else if(sPreElem == "chbx") + { + object oModule = GetModule(); + int bCheck = JsonGetInt(NuiGetBind(oPC, 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_WANDER, JsonInt(bCheck)); + NuiSetBind(oPC, nToken, "txt_wander_distance_event", JsonBool(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(oPC); + } + 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(oPC, nToken, "chbx_party_scale_tooltip", JsonString(" PEPS adjusts your XP based on party size from (" + sText + ").")); + sText = IntToString(GetModuleXPScale()); + NuiSetBind(oPC, 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(oPC, 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(oPC, GetModule(), -1, nToken); + } + } + return; + } + //************************************************************************** + // Associate Command events. + if(sWndId == sAssociateType + AI_COMMAND_NUI) + { + if(sEvent == "click") + { + if(sElem == "btn_ai_menu") + { + DelayCommand(0.0, NuiDestroy(oPC, nToken)); + ai_CreateAssociateAINUI(oPC, oAssociate); + } + if(sElem == "btn_vertical_widget") + { + int bVertical = !ai_GetWidgetButton(oPC, BTN_WIDGET_VERTICAL, oAssociate, sAssociateType); + ai_SetWidgetButton(oPC, BTN_WIDGET_VERTICAL, oAssociate, sAssociateType, bVertical); + if(oPC == oAssociate || + (oPC != oAssociate && !ai_GetWidgetButton(oPC, BTN_WIDGET_OFF, oAssociate, sAssociateType))) + { + DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, sAssociateType + AI_WIDGET_NUI))); + DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oAssociate)); + } + } + else if(sElem == "btn_main_menu") + { + if(ai_GetIsCharacter(oAssociate)) ai_CreateAIMainNUI(oPC); + } + else if(sElem == "btn_widget_onoff") + { + ai_ToggleAssociateWidgetOnOff(oPC, nToken, oAssociate, sAssociateType); + } + else if(sElem == "btn_widget_lock") + { + int bLocked = !ai_GetWidgetButton(oPC, BTN_WIDGET_LOCK, oAssociate, sAssociateType); + ai_SetWidgetButton(oPC, BTN_WIDGET_LOCK, oAssociate, sAssociateType, bLocked); + if(!ai_GetWidgetButton(oPC, BTN_WIDGET_OFF, oAssociate, sAssociateType) || oPC == oAssociate) + { + DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, sAssociateType + AI_WIDGET_NUI))); + DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oAssociate)); + } + } + else if(sElem == "btn_copy_settings") + { + ai_CreateCopySettingsNUI(oPC, oAssociate); + } + else if(sElem == "btn_cmd_action") ai_Action(oPC, oAssociate); + else if(sElem == "btn_cmd_guard") ai_DoCommand(oPC, oAssociate, 1); + else if(sElem == "btn_cmd_hold") ai_DoCommand(oPC, oAssociate, 3); + else if(sElem == "btn_cmd_search") ai_DoCommand(oPC, oAssociate, 5); + else if(sElem == "btn_cmd_stealth") ai_DoCommand(oPC, oAssociate, 6); + else if(sElem == "btn_cmd_attack") ai_DoCommand(oPC, oAssociate, 4); + else if(sElem == "btn_cmd_follow") ai_DoCommand(oPC, oAssociate, 2); + else if(sElem == "btn_follow_target") ai_FollowTarget(oPC, oAssociate); + else if(sElem == "btn_cmd_ai_script") ai_AIScript(oPC, oAssociate, sAssociateType, nToken); + else if(sElem == "btn_cmd_place_trap") ai_HavePCPlaceTrap(oPC, oAssociate); + else if(sElem == "btn_quick_widget") + { + DelayCommand(0.0, NuiDestroy(oPC, nToken)); + ai_CreateQuickWidgetSelectionNUI(oPC, oAssociate); + } + else if(sElem == "btn_spell_memorize") + { + DelayCommand(0.0, NuiDestroy(oPC, nToken)); + ai_CreateSpellMemorizationNUI(oPC, oAssociate); + } + else if(sElem == "btn_spell_known") + { + DelayCommand(0.0, NuiDestroy(oPC, nToken)); + ai_CreateSpellKnownNUI(oPC, oAssociate); + } + else if(sElem == "btn_buff_short") + { + ai_Buff_Button(oPC, oAssociate, 2, sAssociateType); + DelayCommand(6.0, ai_UpdateAssociateWidget(oPC, oAssociate)); + } + else if(sElem == "btn_buff_long") + { + ai_Buff_Button(oPC, oAssociate, 3, sAssociateType); + DelayCommand(6.0, ai_UpdateAssociateWidget(oPC, oAssociate)); + } + else if(sElem == "btn_buff_all") + { + ai_Buff_Button(oPC, oAssociate, 1, sAssociateType); + DelayCommand(6.0, ai_UpdateAssociateWidget(oPC, oAssociate)); + } + else if(sElem == "btn_buff_rest") ai_Buff_Button(oPC, oAssociate, 0, sAssociateType); + else if(sElem == "btn_jump_to") ai_JumpToPC(oPC, oAssociate); + else if(sElem == "btn_ghost_mode") ai_GhostMode(oPC, oAssociate, nToken, sAssociateType); + else if(sElem == "btn_camera") ai_ChangeCameraView(oPC, oAssociate); + else if(sElem == "btn_inventory") ai_OpenInventory(oAssociate, oPC); + else if(sElem == "btn_familiar_name") ai_SetCompanionName(oPC, oAssociate, nToken, ASSOCIATE_TYPE_FAMILIAR); + else if(sElem == "btn_companion_name") ai_SetCompanionName(oPC, oAssociate, nToken, ASSOCIATE_TYPE_ANIMALCOMPANION); + else if(GetStringLeft(sElem, 11) == "btn_plugin_") ai_Plugin_Execute(oPC, sElem); + } + else if(sEvent == "watch") + { + if(sElem == "txt_familiar_name") + { + string sName = JsonGetString(NuiGetBind(oPC, nToken, sElem)); + if(sName != "") NuiSetBind(oPC, nToken, "btn_familiar_name_event", JsonBool(TRUE)); + else NuiSetBind(oPC, nToken, "btn_familiar_name_event", JsonBool(FALSE)); + } + if(GetStringLeft(sElem, 12) == "chbx_plugin_" && GetStringRight(sElem, 6) == "_check") + { + int nIndex = StringToInt(GetSubString(sElem, 12, 1)); + json jPlugins = ai_GetAssociateDbJson(oPC, "pc", "plugins"); + json jPlugin = JsonArrayGet(jPlugins, nIndex); + int bCheck = JsonGetInt(NuiGetBind(oPC, nToken, sElem)); + jPlugin = JsonArraySet(jPlugin, 1, JsonBool(bCheck)); + jPlugins = JsonArraySet(jPlugins, nIndex, jPlugin); + ai_SetAssociateDbJson(oPC, "pc", "plugins", jPlugins); + DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, "pc" + AI_WIDGET_NUI))); + DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oPC)); + } + else if(sElem == "chbx_buff_rest_check") ai_SetWidgetButtonToCheckbox(oPC, BTN_BUFF_REST, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_cmd_action_check") ai_SetWidgetButtonToCheckbox(oPC, BTN_CMD_ACTION, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_cmd_guard_check") ai_SetWidgetButtonToCheckbox(oPC, BTN_CMD_GUARD, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_cmd_hold_check") ai_SetWidgetButtonToCheckbox(oPC, BTN_CMD_HOLD, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_cmd_search_check") ai_SetWidgetButtonToCheckbox(oPC, BTN_CMD_SEARCH, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_cmd_stealth_check") ai_SetWidgetButtonToCheckbox(oPC, BTN_CMD_STEALTH, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_cmd_attack_check") ai_SetWidgetButtonToCheckbox(oPC, BTN_CMD_ATTACK, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_cmd_follow_check") ai_SetWidgetButtonToCheckbox(oPC, BTN_CMD_FOLLOW, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_cmd_ai_script_check") ai_SetWidgetButtonToCheckbox(oPC, BTN_CMD_AI_SCRIPT, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_cmd_place_trap_check") ai_SetWidgetButtonToCheckbox(oPC, BTN_CMD_PLACE_TRAP, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_quick_widget_check") ai_SetWidgetButtonToCheckbox(oPC, BTN_CMD_SPELL_WIDGET, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_follow_target_check") ai_SetAIButtonToCheckbox(oPC, BTN_AI_FOLLOW_TARGET, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_buff_short_check") ai_SetWidgetButtonToCheckbox(oPC, BTN_BUFF_SHORT, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_buff_long_check") ai_SetWidgetButtonToCheckbox(oPC, BTN_BUFF_LONG, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_buff_all_check") ai_SetWidgetButtonToCheckbox(oPC, BTN_BUFF_ALL, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_jump_to_check") ai_SetWidgetButtonToCheckbox(oPC, BTN_CMD_JUMP_TO, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_ghost_mode_check") ai_SetWidgetButtonToCheckbox(oPC, BTN_CMD_GHOST_MODE, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_camera_check") ai_SetWidgetButtonToCheckbox(oPC, BTN_CMD_CAMERA, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_inventory_check") ai_SetWidgetButtonToCheckbox(oPC, BTN_CMD_INVENTORY, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_familiar_check") ai_SetWidgetButtonToCheckbox(oPC, BTN_CMD_FAMILIAR, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_companion_check") ai_SetWidgetButtonToCheckbox(oPC, BTN_CMD_COMPANION, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "cmb_familiar_selected") ai_SetCompanionType(oPC, oAssociate, nToken, ASSOCIATE_TYPE_FAMILIAR); + else if(sElem == "cmb_companion_selected") ai_SetCompanionType(oPC, oAssociate, nToken, ASSOCIATE_TYPE_ANIMALCOMPANION); + DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, sAssociateType + AI_WIDGET_NUI))); + DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oAssociate)); + } + 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 == "btn_cmd_follow" && + oPC != oAssociate) ai_FollowIncrement(oPC, oAssociate, 1.0, sAssociateType); + else if(sElem == "btn_follow_target") ai_FollowIncrement(oPC, oAssociate, 1.0, sAssociateType); + } + else if(nMouseScroll == -1.0) // Scroll down + { + // Follow range is only changed on non-pc's + if(sElem == "btn_cmd_follow" && + oPC != oAssociate) ai_FollowIncrement(oPC, oAssociate, -1.0, sAssociateType); + else if(sElem == "btn_follow_target") ai_FollowIncrement(oPC, oAssociate, -1.0, sAssociateType); + } + } + return; + } + //************************************************************************** + // Associate AI events. + if(sWndId == sAssociateType + AI_NUI) + { + if(sEvent == "click") + { + if(sElem == "btn_command_menu") + { + DelayCommand(0.0, NuiDestroy(oPC, nToken)); + ai_CreateAssociateCommandNUI(oPC, oAssociate); + } + if(sElem == "btn_main_menu") + { + if(ai_GetIsCharacter(oAssociate)) ai_CreateAIMainNUI(oPC); + } + else if(sElem == "btn_loot_filter") + { + ai_CreateLootFilterNUI(oPC, oAssociate); + } + else if(sElem == "btn_ai") + { + if(GetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT) == "xx_pc_1_hb") ai_TurnOff(oPC, oAssociate, sAssociateType); + else ai_TurnOn(oPC, oAssociate, sAssociateType); + } + else if(sElem == "btn_quiet") ai_ReduceSpeech(oPC, oAssociate, sAssociateType); + else if(sElem == "btn_ranged") AssignCommand(oAssociate, ai_Ranged(oPC, oAssociate, sAssociateType)); + else if(sElem == "btn_equip_weapon") ai_EquipWeapons(oPC, oAssociate, sAssociateType); + else if(sElem == "btn_search") ai_Search(oPC, oAssociate, sAssociateType); + else if(sElem == "btn_stealth") ai_Stealth(oPC, oAssociate, sAssociateType); + else if(sElem == "btn_open_door") ai_OpenDoor(oPC, oAssociate, sAssociateType); + else if(sElem == "btn_traps") ai_Traps(oPC, oAssociate, sAssociateType); + else if(sElem == "btn_pick_locks") ai_Locks(oPC, oAssociate, sAssociateType, 1); + else if(sElem == "btn_bash_locks") ai_Locks(oPC, oAssociate, sAssociateType, 2); + else if(sElem == "btn_magic") ai_UseMagic(oPC, oAssociate, sAssociateType); + else if(sElem == "btn_magic_items") ai_UseMagicItems(oPC, oAssociate, sAssociateType); + else if(sElem == "btn_def_magic") ai_UseOffensiveMagic(oPC, oAssociate, TRUE, FALSE, sAssociateType); + else if(sElem == "btn_off_magic") ai_UseOffensiveMagic(oPC, oAssociate, FALSE, TRUE, sAssociateType); + else if(sElem == "btn_spontaneous") ai_Spontaneous(oPC, oAssociate, sAssociateType); + else if(sElem == "btn_heals_onoff") ai_Heal_OnOff(oPC, oAssociate, sAssociateType, 1); + else if(sElem == "btn_healp_onoff") ai_Heal_OnOff(oPC, oAssociate, sAssociateType, 2); + else if(sElem == "btn_cure_onoff") ai_Cure_OnOff(oPC, oAssociate, sAssociateType); + else if(sElem == "btn_loot") ai_Loot(oPC, oAssociate, sAssociateType); + else if(sElem == "btn_ignore_assoc") ai_Ignore_Associates(oPC, oAssociate, sAssociateType); + else if(sElem == "btn_ignore_traps") ai_Ignore_Traps(oPC, oAssociate, sAssociateType); + else if(sElem == "btn_perc_range") ai_Perc_Range(oPC, oAssociate, nToken, sAssociateType); + else if(sElem == "btn_ai_script") ai_SaveAIScript(oPC, oAssociate, nToken); + } + else if(sEvent == "watch") + { + SetLocalInt (oPC, AI_NO_NUI_SAVE, TRUE); + if(sElem == "chbx_ai_check") ai_SetAIButtonToCheckbox(oPC, BTN_AI_FOR_PC, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_quiet_check") ai_SetAIButtonToCheckbox(oPC, BTN_AI_REDUCE_SPEECH, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_ranged_check") ai_SetAIButtonToCheckbox(oPC, BTN_AI_USE_RANGED, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_equip_weapon_check") ai_SetAIButtonToCheckbox(oPC, BTN_AI_STOP_WEAPON_EQUIP, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_search_check") ai_SetAIButtonToCheckbox(oPC, BTN_AI_USE_SEARCH, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_stealth_check") ai_SetAIButtonToCheckbox(oPC, BTN_AI_USE_STEALTH, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_open_door_check") ai_SetAIButtonToCheckbox(oPC, BTN_AI_OPEN_DOORS, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_traps_check") ai_SetAIButtonToCheckbox(oPC, BTN_AI_REMOVE_TRAPS, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_pick_locks_check") ai_SetAIButtonToCheckbox(oPC, BTN_AI_PICK_LOCKS, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_bash_locks_check") ai_SetAIButtonToCheckbox(oPC, BTN_AI_BASH_LOCKS, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_magic_level_check") ai_SetAIButtonToCheckbox(oPC, BTN_AI_MAGIC_LEVEL, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_spontaneous_check") ai_SetAIButtonToCheckbox(oPC, BTN_AI_NO_SPONTANEOUS, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_magic_check") ai_SetAIButtonToCheckbox(oPC, BTN_AI_NO_MAGIC_USE, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_magic_items_check") ai_SetAIButtonToCheckbox(oPC, BTN_AI_NO_MAGIC_ITEM_USE, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_def_magic_check") ai_SetAIButtonToCheckbox(oPC, BTN_AI_DEF_MAGIC_USE, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_off_magic_check") ai_SetAIButtonToCheckbox(oPC, BTN_AI_OFF_MAGIC_USE, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_heal_out_check") ai_SetAIButtonToCheckbox(oPC, BTN_AI_HEAL_OUT, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_heal_in_check") ai_SetAIButtonToCheckbox(oPC, BTN_AI_HEAL_IN, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_heals_onoff_check") ai_SetAIButtonToCheckbox(oPC, BTN_AI_STOP_SELF_HEALING, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_healp_onoff_check") ai_SetAIButtonToCheckbox(oPC, BTN_AI_STOP_PARTY_HEALING, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_cure_onoff_check") ai_SetAIButtonToCheckbox(oPC, BTN_AI_STOP_CURE_SPELLS, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_loot_check") ai_SetAIButtonToCheckbox(oPC, BTN_AI_LOOT, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_ignore_assoc_check") ai_SetAIButtonToCheckbox(oPC, BTN_AI_IGNORE_ASSOCIATES, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_ignore_traps_check") ai_SetAIButtonToCheckbox(oPC, BTN_AI_IGNORE_TRAPS, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "chbx_perc_range_check") ai_SetAIButtonToCheckbox(oPC, BTN_AI_PERC_RANGE, oAssociate, sAssociateType, nToken, sElem); + else if(sElem == "cmb_ai_script_selected") ai_SetAIScript(oPC, oAssociate, nToken); + DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, sAssociateType + AI_WIDGET_NUI))); + DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oAssociate)); + } + else if(sEvent == "mousescroll") + { + float nMouseScroll = JsonGetFloat(JsonObjectGet(JsonObjectGet(NuiGetEventPayload(), "mouse_scroll"), "y")); + if(nMouseScroll == 1.0) // Scroll up + { + if(sElem == "btn_magic_level") ai_MagicIncrement(oPC, oAssociate, 1, sAssociateType); + else if(sElem == "btn_open_door") ai_OpenDoorIncrement(oPC, oAssociate, 1.0, sAssociateType); + else if(sElem == "btn_traps") ai_TrapRangeIncrement(oPC, oAssociate, 1.0, sAssociateType); + else if(sElem == "btn_pick_locks") ai_LockRangeIncrement(oPC, oAssociate, 1.0, sAssociateType); + else if(sElem == "btn_bash_locks") ai_LockRangeIncrement(oPC, oAssociate, 1.0, sAssociateType); + else if(sElem == "btn_heal_out") ai_Heal_Button(oPC, oAssociate, 5, AI_HEAL_OUT_OF_COMBAT_LIMIT, sAssociateType); + else if(sElem == "btn_heal_in") ai_Heal_Button(oPC, oAssociate, 5, AI_HEAL_IN_COMBAT_LIMIT, sAssociateType); + else if(sElem == "btn_loot") ai_LootRangeIncrement(oPC, oAssociate, 1.0, sAssociateType); + else if(sElem == "btn_perc_range") ai_PercRangeIncrement(oPC, oAssociate, 1, sAssociateType, nToken); + } + else if(nMouseScroll == -1.0) // Scroll down + { + if(sElem == "btn_magic_level") ai_MagicIncrement(oPC, oAssociate, -1, sAssociateType); + else if(sElem == "btn_open_door") ai_OpenDoorIncrement(oPC, oAssociate, -1.0, sAssociateType); + else if(sElem == "btn_traps") ai_TrapRangeIncrement(oPC, oAssociate, -1.0, sAssociateType); + else if(sElem == "btn_pick_locks") ai_LockRangeIncrement(oPC, oAssociate, -1.0, sAssociateType); + else if(sElem == "btn_bash_locks") ai_LockRangeIncrement(oPC, oAssociate, -1.0, sAssociateType); + else if(sElem == "btn_heal_out") ai_Heal_Button(oPC, oAssociate, -5, AI_HEAL_OUT_OF_COMBAT_LIMIT, sAssociateType); + else if(sElem == "btn_heal_in") ai_Heal_Button(oPC, oAssociate, -5, AI_HEAL_IN_COMBAT_LIMIT, sAssociateType); + else if(sElem == "btn_loot") ai_LootRangeIncrement(oPC, oAssociate, -1.0, sAssociateType); + else if(sElem == "btn_perc_range") ai_PercRangeIncrement(oPC, oAssociate, -1, sAssociateType, nToken); + } + } + return; + } + //************************************************************************** + // Associate Widget events. + if(sWndId == sAssociateType + AI_WIDGET_NUI) + { + if(sEvent == "click") + { + if(sElem == "btn_open_main") + { + // If all the Command buttons are blocked then don't load the menu. + if(GetLocalInt(GetModule(), sDMWidgetAccessVarname) != 7340028) + { + 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); + if(ai_GetIsCharacter(oAssociate)) + { + IsWindowClosed(oPC, AI_MAIN_NUI); + IsWindowClosed(oPC, AI_PLUGIN_NUI); + } + } + } + else if(sElem == "btn_ai") + { + if(GetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT) == "xx_pc_1_hb") + { + ai_TurnOff(oPC, oAssociate, sAssociateType); + } + else ai_TurnOn(oPC, oAssociate, sAssociateType); + } + else if(sElem == "btn_quiet") ai_ReduceSpeech(oPC, oAssociate, sAssociateType); + else if(sElem == "btn_ranged") AssignCommand(oAssociate, ai_Ranged(oPC, oAssociate, sAssociateType)); + else if(sElem == "btn_equip_weapon") ai_EquipWeapons(oPC, oAssociate, sAssociateType); + else if(sElem == "btn_search") ai_Search(oPC, oAssociate, sAssociateType); + else if(sElem == "btn_stealth") ai_Stealth(oPC, oAssociate, sAssociateType); + else if(sElem == "btn_open_door") ai_OpenDoor(oPC, oAssociate, sAssociateType); + else if(sElem == "btn_traps") ai_Traps(oPC, oAssociate, sAssociateType); + else if(sElem == "btn_pick_locks") ai_Locks(oPC, oAssociate, sAssociateType, 1); + else if(sElem == "btn_bash_locks") ai_Locks(oPC, oAssociate, sAssociateType, 2); + else if(sElem == "btn_magic_minus") ai_MagicIncrement(oPC, oAssociate, -1, sAssociateType); + else if(sElem == "btn_magic_plus") ai_MagicIncrement(oPC, oAssociate, 1, sAssociateType); + else if(sElem == "btn_magic") ai_UseMagic(oPC, oAssociate, sAssociateType); + else if(sElem == "btn_magic_items") ai_UseMagicItems(oPC, oAssociate, sAssociateType); + else if(sElem == "btn_def_magic") ai_UseOffensiveMagic(oPC, oAssociate, TRUE, FALSE, sAssociateType); + else if(sElem == "btn_off_magic") ai_UseOffensiveMagic(oPC, oAssociate, FALSE, TRUE, sAssociateType); + else if(sElem == "btn_cure_onoff") ai_Cure_OnOff(oPC, oAssociate, sAssociateType); + else if(sElem == "btn_loot") ai_Loot(oPC, oAssociate, sAssociateType); + else if(sElem == "btn_ignore_assoc") ai_Ignore_Associates(oPC, oAssociate, sAssociateType); + else if(sElem == "btn_ignore_traps") ai_Ignore_Traps(oPC, oAssociate, sAssociateType); + else if(sElem == "btn_perc_range") ai_Perc_Range(oPC, oAssociate, nToken, sAssociateType); + else if(sElem == "btn_spontaneous") ai_Spontaneous(oPC, oAssociate, sAssociateType); + else if(sElem == "btn_buff_short") + { + ai_Buff_Button(oPC, oAssociate, 2, sAssociateType); + DelayCommand(6.0, ai_UpdateAssociateWidget(oPC, oAssociate)); + } + else if(sElem == "btn_buff_long") + { + ai_Buff_Button(oPC, oAssociate, 3, sAssociateType); + DelayCommand(6.0, ai_UpdateAssociateWidget(oPC, oAssociate)); + } + else if(sElem == "btn_buff_all") + { + ai_Buff_Button(oPC, oAssociate, 1, sAssociateType); + DelayCommand(6.0, ai_UpdateAssociateWidget(oPC, oAssociate)); + } + else if(sElem == "btn_buff_rest") ai_Buff_Button(oPC, oAssociate, 0, sAssociateType); + else if(sElem == "btn_jump_to") ai_JumpToPC(oPC, oAssociate); + else if(sElem == "btn_ghost_mode") ai_GhostMode(oPC, oAssociate, nToken, sAssociateType); + else if(sElem == "btn_camera") ai_ChangeCameraView(oPC, oAssociate); + else if(sElem == "btn_inventory") ai_OpenInventory(oAssociate, oPC); + else if(sElem == "btn_familiar") + { + if(GetHasFeat(FEAT_SUMMON_FAMILIAR, oAssociate)) + { + DecrementRemainingFeatUses(oAssociate, FEAT_SUMMON_FAMILIAR); + SummonFamiliar(oAssociate); + } + } + else if(sElem == "btn_companion") + { + if(GetHasFeat(FEAT_ANIMAL_COMPANION, oAssociate)) + { + DecrementRemainingFeatUses(oAssociate, FEAT_ANIMAL_COMPANION); + SummonAnimalCompanion(oAssociate); + } + } + else if(sElem == "btn_heals_onoff") ai_Heal_OnOff(oPC, oAssociate, sAssociateType, 1); + else if(sElem == "btn_healp_onoff") ai_Heal_OnOff(oPC, oAssociate, sAssociateType, 2); + else if(sElem == "btn_cmd_action") ai_Action(oPC, oAssociate); + else if(sElem == "btn_cmd_guard") ai_DoCommand(oPC, oAssociate, 1); + else if(sElem == "btn_cmd_hold") ai_DoCommand(oPC, oAssociate, 3); + else if(sElem == "btn_cmd_search") ai_DoCommand(oPC, oAssociate, 5); + else if(sElem == "btn_cmd_stealth") ai_DoCommand(oPC, oAssociate, 6); + else if(sElem == "btn_cmd_attack") ai_DoCommand(oPC, oAssociate, 4); + else if(sElem == "btn_cmd_follow") ai_DoCommand(oPC, oAssociate, 2); + else if(sElem == "btn_cmd_ai_script") ai_AIScript(oPC, oAssociate, sAssociateType, nToken); + else if(sElem == "btn_cmd_place_trap") ai_HavePCPlaceTrap(oPC, oAssociate); + else if(sElem == "btn_follow_target") ai_FollowTarget(oPC, oAssociate); + else if(sElem == "btn_update_widget") ai_UpdateAssociateWidget(oPC, oAssociate); + else if(GetStringLeft(sElem, 15) == "btn_exe_plugin_") ai_Plugin_Execute(oPC, sElem); + else if(GetStringLeft(sElem, 11) == "btn_widget_") ai_SelectWidgetSpellTarget(oPC, oAssociate, sElem); + } + if(sEvent == "mousescroll") + { + float nMouseScroll = JsonGetFloat(JsonObjectGet(JsonObjectGet(NuiGetEventPayload(), "mouse_scroll"), "y")); + if(nMouseScroll == 1.0) // Scroll up + { + if(sElem == "btn_cmd_follow" && + oPC != oAssociate) ai_FollowIncrement(oPC, oAssociate, 1.0, sAssociateType); + else if(sElem == "btn_follow_target") ai_FollowIncrement(oPC, oAssociate, 1.0, sAssociateType); + else if(sElem == "btn_magic_level") ai_MagicIncrement(oPC, oAssociate, 1, sAssociateType); + else if(sElem == "btn_pick_locks") ai_LockRangeIncrement(oPC, oAssociate, 1.0, sAssociateType); + else if(sElem == "btn_bash_locks") ai_LockRangeIncrement(oPC, oAssociate, 1.0, sAssociateType); + else if(sElem == "btn_traps") ai_TrapRangeIncrement(oPC, oAssociate, 1.0, sAssociateType); + else if(sElem == "btn_open_door") ai_OpenDoorIncrement(oPC, oAssociate, 1.0, sAssociateType); + else if(sElem == "btn_heal_out") ai_Heal_Button(oPC, oAssociate, 5, AI_HEAL_OUT_OF_COMBAT_LIMIT, sAssociateType); + else if(sElem == "btn_heal_in") ai_Heal_Button(oPC, oAssociate, 5, AI_HEAL_IN_COMBAT_LIMIT, sAssociateType); + else if(sElem == "btn_loot") ai_LootRangeIncrement(oPC, oAssociate, 1.0, sAssociateType); + else if(sElem == "btn_perc_range") ai_PercRangeIncrement(oPC, oAssociate, 1, sAssociateType, -1); + } + if(nMouseScroll == -1.0) // Scroll down + { + if(sElem == "btn_cmd_follow" && + oPC != oAssociate) ai_FollowIncrement(oPC, oAssociate, -1.0, sAssociateType); + else if(sElem == "btn_follow_target") ai_FollowIncrement(oPC, oAssociate, -1.0, sAssociateType); + else if(sElem == "btn_magic_plus") ai_MagicIncrement(oPC, oAssociate, -1, sAssociateType); + if(sElem == "btn_magic_level") ai_MagicIncrement(oPC, oAssociate, -1, sAssociateType); + else if(sElem == "btn_pick_locks") ai_LockRangeIncrement(oPC, oAssociate, -1.0, sAssociateType); + else if(sElem == "btn_bash_locks") ai_LockRangeIncrement(oPC, oAssociate, -1.0, sAssociateType); + else if(sElem == "btn_traps") ai_TrapRangeIncrement(oPC, oAssociate, -1.0, sAssociateType); + else if(sElem == "btn_open_door") ai_OpenDoorIncrement(oPC, oAssociate, -1.0, sAssociateType); + else if(sElem == "btn_heal_out") ai_Heal_Button(oPC, oAssociate, -5, AI_HEAL_OUT_OF_COMBAT_LIMIT, sAssociateType); + else if(sElem == "btn_heal_in") ai_Heal_Button(oPC, oAssociate, -5, AI_HEAL_IN_COMBAT_LIMIT, sAssociateType); + else if(sElem == "btn_loot") ai_LootRangeIncrement(oPC, oAssociate, -1.0, sAssociateType); + else if(sElem == "btn_perc_range") ai_PercRangeIncrement(oPC, oAssociate, -1, sAssociateType, -1); + } + } + if(sEvent == "mousedown") + { + int nMouseButton = JsonGetInt(JsonObjectGet(NuiGetEventPayload(), "mouse_btn")); + if(nMouseButton == NUI_MOUSE_BUTTON_RIGHT) + { + AssignCommand(oPC, PlaySound("gui_button")); + if(sElem == "btn_open_main") + { + // If all the AI buttons are blocked then don't load the menu. + if(GetLocalInt(GetModule(), sDMAIAccessVarname) != 203423743) + { + if(IsWindowClosed(oPC, sAssociateType + AI_NUI)) + { + ai_CreateAssociateAINUI(oPC, oAssociate); + } + } + IsWindowClosed(oPC, sAssociateType + AI_COMMAND_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); + if(ai_GetIsCharacter(oAssociate)) + { + IsWindowClosed(oPC, AI_MAIN_NUI); + IsWindowClosed(oPC, AI_PLUGIN_NUI); + } + } + else if(sElem == "btn_follow_range") ai_FollowIncrement(oPC, oAssociate, -1.0, sAssociateType); + else if(GetStringLeft(sElem, 11) == "btn_widget_") + { + if(GetStringLength(sElem) == 13) nIndex = StringToInt(GetStringRight(sElem, 2)); + else nIndex = StringToInt(GetStringRight(sElem, 1)); + json jAIData = ai_GetAssociateDbJson(oPC, ai_GetAssociateType(oPC, oAssociate), "aidata"); + json jSpells = JsonArrayGet(jAIData, 10); + json jWidget = JsonArrayGet(jSpells, 2); + json jSpell = JsonArrayGet(jWidget, nIndex); + ai_CreateDescriptionNUI(oPC, jSpell); + } + } + } + return; + } + //************************************************************************** + // Associate Loot events. + if(sWndId == sAssociateType + AI_LOOTFILTER_NUI) + { + if(sEvent == "click") + { + if(sElem == "btn_set_all") + { + SetLocalInt(oPC, "AI_BLOCK_CHECKS", TRUE); + SetLocalInt(oAssociate, sLootFilterVarname, 65535); + int nIndex; + for(nIndex = 2; nIndex < 20; nIndex++) + { + NuiSetBind(oPC, nToken, "chbx_" + IntToString(nIndex) + "_check", JsonBool (TRUE)); + } + json jLootFilter = ai_GetAssociateDbJson(oPC, sAssociateType, "lootfilters"); + jLootFilter = JsonArraySet(jLootFilter, 1, JsonInt(65535)); + ai_SetAssociateDbJson(oPC, sAssociateType, "lootfilters", jLootFilter); + DelayCommand(1.0, DeleteLocalInt(oPC, "AI_BLOCK_CHECKS")); + } + else if(sElem == "btn_clear_all") + { + SetLocalInt(oPC, "AI_BLOCK_CHECKS", TRUE); + SetLocalInt(oAssociate, sLootFilterVarname, 0); + int nIndex; + for(nIndex = 2; nIndex < 20; nIndex++) + { + NuiSetBind(oPC, nToken, "chbx_" + IntToString(nIndex) + "_check", JsonBool (FALSE)); + } + json jLootFilter = ai_GetAssociateDbJson(oPC, sAssociateType, "lootfilters"); + jLootFilter = JsonArraySet(jLootFilter, 1, JsonInt(0)); + ai_SetAssociateDbJson(oPC, sAssociateType, "lootfilters", jLootFilter); + DelayCommand(1.0, DeleteLocalInt(oPC, "AI_BLOCK_CHECKS")); + } + } + else if(sEvent == "watch") + { + if(GetStringLeft(sElem, 5) == "chbx_") + { + if(GetLocalInt(oPC, "AI_BLOCK_CHECKS")) return; + if(sElem == "chbx_give_loot_check") ai_SetLootFilterToCheckbox(oPC, oAssociate, AI_LOOT_GIVE_TO_PC, nToken, sElem); + else if(sElem == "chbx_2_check") ai_SetLootFilterToCheckbox(oPC, oAssociate, AI_LOOT_PLOT, nToken, sElem); + else if(sElem == "chbx_3_check") ai_SetLootFilterToCheckbox(oPC, oAssociate, AI_LOOT_ARMOR, nToken, sElem); + else if(sElem == "chbx_4_check") ai_SetLootFilterToCheckbox(oPC, oAssociate, AI_LOOT_BELTS, nToken, sElem); + else if(sElem == "chbx_5_check") ai_SetLootFilterToCheckbox(oPC, oAssociate, AI_LOOT_BOOTS, nToken, sElem); + else if(sElem == "chbx_6_check") ai_SetLootFilterToCheckbox(oPC, oAssociate, AI_LOOT_CLOAKS, nToken, sElem); + else if(sElem == "chbx_7_check") ai_SetLootFilterToCheckbox(oPC, oAssociate, AI_LOOT_GEMS, nToken, sElem); + else if(sElem == "chbx_8_check") ai_SetLootFilterToCheckbox(oPC, oAssociate, AI_LOOT_GLOVES, nToken, sElem); + else if(sElem == "chbx_9_check") ai_SetLootFilterToCheckbox(oPC, oAssociate, AI_LOOT_HEADGEAR, nToken, sElem); + else if(sElem == "chbx_10_check") ai_SetLootFilterToCheckbox(oPC, oAssociate, AI_LOOT_JEWELRY, nToken, sElem); + else if(sElem == "chbx_11_check") ai_SetLootFilterToCheckbox(oPC, oAssociate, AI_LOOT_MISC, nToken, sElem); + else if(sElem == "chbx_12_check") ai_SetLootFilterToCheckbox(oPC, oAssociate, AI_LOOT_POTIONS, nToken, sElem); + else if(sElem == "chbx_13_check") ai_SetLootFilterToCheckbox(oPC, oAssociate, AI_LOOT_SCROLLS, nToken, sElem); + else if(sElem == "chbx_14_check") ai_SetLootFilterToCheckbox(oPC, oAssociate, AI_LOOT_SHIELDS, nToken, sElem); + else if(sElem == "chbx_15_check") ai_SetLootFilterToCheckbox(oPC, oAssociate, AI_LOOT_WANDS_RODS_STAVES, nToken, sElem); + else if(sElem == "chbx_16_check") ai_SetLootFilterToCheckbox(oPC, oAssociate, AI_LOOT_WEAPONS, nToken, sElem); + else if(sElem == "chbx_17_check") ai_SetLootFilterToCheckbox(oPC, oAssociate, AI_LOOT_ARROWS, nToken, sElem); + else if(sElem == "chbx_18_check") ai_SetLootFilterToCheckbox(oPC, oAssociate, AI_LOOT_BOLTS, nToken, sElem); + else if(sElem == "chbx_19_check") ai_SetLootFilterToCheckbox(oPC, oAssociate, AI_LOOT_BULLETS, nToken, sElem); + json jLootFilter = ai_GetAssociateDbJson(oPC, sAssociateType, "lootfilters"); + int nLootFilter = GetLocalInt(oAssociate, sLootFilterVarname); + jLootFilter = JsonArraySet(jLootFilter, 1, JsonInt(nLootFilter)); + ai_SetAssociateDbJson(oPC, sAssociateType, "lootfilters", jLootFilter); + } + else if(GetStringLeft(sElem, 4) == "txt_") + { + if(sElem == "txt_max_weight") + { + int nMaxWeight = StringToInt(JsonGetString(NuiGetBind(oPC, nToken, sElem))); + if(nMaxWeight > 1000) nMaxWeight = 1000; + if(nMaxWeight < 1) nMaxWeight = 1; + SetLocalInt(oAssociate, AI_MAX_LOOT_WEIGHT, nMaxWeight); + json jLootFilter = ai_GetAssociateDbJson(oPC, sAssociateType, "lootfilters"); + jLootFilter = JsonArraySet(jLootFilter, 0, JsonInt(nMaxWeight)); + ai_SetAssociateDbJson(oPC, sAssociateType, "lootfilters", jLootFilter); + return; + } + if(GetStringLeft(sElem, 9) == "txt_gold_") + { + int nAmount = StringToInt(JsonGetString(NuiGetBind(oPC, nToken, sElem))); + int nIndex; + if(GetStringLength(sElem) == 11) nIndex = StringToInt(GetStringRight(sElem, 2)); + else nIndex = StringToInt(GetStringRight(sElem, 1)); + SetLocalInt(oAssociate, AI_MIN_GOLD_ + IntToString(nIndex), nAmount); + json jLootFilter = ai_GetAssociateDbJson(oPC, sAssociateType, "lootfilters"); + jLootFilter = JsonArraySet(jLootFilter, nIndex, JsonInt(nAmount)); + ai_SetAssociateDbJson(oPC, sAssociateType, "lootfilters", jLootFilter); + } + } + } + return; + } + //************************************************************************** + // Associate Paste events. + if(sWndId == sAssociateType + AI_COPY_NUI) + { + if(sEvent == "click") + { + int nIndex, nAssociateType = GetAssociateType(oAssociate); + string sAssociateType = ai_GetAssociateType(oPC, oAssociate); + object oAssoc; + string sAssocType; + json jModes = ai_GetAssociateDbJson(oPC, sAssociateType, "modes"); + json jButtons = ai_GetAssociateDbJson(oPC, sAssociateType, "buttons"); + json jAIData = ai_GetAssociateDbJson(oPC, sAssociateType, "aidata"); + json jLootFilters = ai_GetAssociateDbJson(oPC, sAssociateType, "lootfilters"); + string sCombatScript = GetLocalString(oAssociate, AI_COMBAT_SCRIPT); + string sDefaultScript = GetLocalString(oAssociate, AI_DEFAULT_SCRIPT); + if(sElem == "btn_paste_all") + { + // Check all non-henchman associates. + for(nIndex = 2; nIndex < 6; nIndex++) + { + if(nAssociateType != nIndex) + { + oAssoc = GetAssociate(nIndex, oPC); + sAssocType = ai_GetAssociateType(oPC, oAssoc); + ai_SetAssociateDbJson(oPC, sAssocType, "modes", jModes); + ai_SetAssociateDbJson(oPC, sAssocType, "buttons", jButtons); + ai_SetAssociateDbJson(oPC, sAssocType, "aidata", jAIData); + ai_SetAssociateDbJson(oPC, sAssocType, "lootfilters", jLootFilters); + SetLocalString(oAssoc, AI_COMBAT_SCRIPT, sCombatScript); + SetLocalString(oAssoc, AI_DEFAULT_SCRIPT, sDefaultScript); + if(oAssoc != OBJECT_INVALID) + { + // Clear the creatures Perception distance so we can + // repopulate the local variables. + SetLocalFloat(oAssoc, AI_ASSOC_PERCEPTION_DISTANCE, 0.0); + ai_CheckAssociateData(oPC, oAssoc, sAssocType); + if(!ai_GetWidgetButton(oPC, BTN_WIDGET_OFF, oAssoc, sAssocType)) + { + DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, sAssocType + AI_WIDGET_NUI))); + DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oAssoc)); + } + } + } + } + // Check all of our henchman. + for(nIndex = 1; nIndex <= AI_MAX_HENCHMAN; nIndex++) + { + oAssoc = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex); + if(oAssoc != OBJECT_INVALID) + { + sAssocType = ai_GetAssociateType(oPC, oAssoc); + ai_SetAssociateDbJson(oPC, sAssocType, "modes", jModes); + ai_SetAssociateDbJson(oPC, sAssocType, "buttons", jButtons); + ai_SetAssociateDbJson(oPC, sAssocType, "aidata", jAIData); + ai_SetAssociateDbJson(oPC, sAssocType, "lootfilters", jLootFilters); + SetLocalString(oAssoc, AI_COMBAT_SCRIPT, sCombatScript); + SetLocalString(oAssoc, AI_DEFAULT_SCRIPT, sDefaultScript); + // Clear the creatures Perception distance so we can + // repopulate the local variables. + SetLocalFloat(oAssoc, AI_ASSOC_PERCEPTION_DISTANCE, 0.0); + ai_CheckAssociateData(oPC, oAssoc, sAssocType); + if(!ai_GetWidgetButton(oPC, BTN_WIDGET_OFF, oAssoc, sAssocType)) + { + DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, sAssocType + AI_WIDGET_NUI))); + DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oAssoc)); + } + } + else break; + } + ai_SendMessages(GetName(oAssociate) + "'s settings have been copied to all associates.", AI_COLOR_GREEN, oPC); + return; + } + else if(GetStringLeft(sElem, 18) == "btn_paste_henchman") + { + int nIndex = StringToInt(GetStringRight(sElem, 1)); + oAssoc = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex); + if(oAssoc != OBJECT_INVALID) + { + sAssocType = ai_GetAssociateType(oPC, oAssoc); + ai_SetAssociateDbJson(oPC, sAssocType, "modes", jModes); + ai_SetAssociateDbJson(oPC, sAssocType, "buttons", jButtons); + ai_SetAssociateDbJson(oPC, sAssocType, "aidata", jAIData); + ai_SetAssociateDbJson(oPC, sAssocType, "lootfilters", jLootFilters); + SetLocalString(oAssoc, AI_COMBAT_SCRIPT, sCombatScript); + SetLocalString(oAssoc, AI_DEFAULT_SCRIPT, sDefaultScript); + // Clear the creatures Perception distance so we can + // repopulate the local variables. + SetLocalFloat(oAssoc, AI_ASSOC_PERCEPTION_DISTANCE, 0.0); + ai_CheckAssociateData(oPC, oAssoc, sAssocType); + if(!ai_GetWidgetButton(oPC, BTN_WIDGET_OFF, oAssoc, sAssocType)) + { + DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, sAssocType + AI_WIDGET_NUI))); + DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oAssoc)); + } + ai_SendMessages(GetName(oAssociate) + "'s settings have been copied to " + GetName(oAssoc) + ".", AI_COLOR_GREEN, oPC); + } + return; + } + else if(sElem == "btn_paste_familiar") nIndex = ASSOCIATE_TYPE_FAMILIAR; + else if(sElem == "btn_paste_companion") nIndex = ASSOCIATE_TYPE_ANIMALCOMPANION; + else if(sElem == "btn_paste_summons") nIndex = ASSOCIATE_TYPE_SUMMONED; + else if(sElem == "btn_paste_dominated") nIndex = ASSOCIATE_TYPE_DOMINATED; + if(nIndex > 1 && nIndex < 6) + { + oAssoc = GetAssociate(nIndex, oPC); + sAssocType = ai_GetAssociateType(oPC, oAssoc); + ai_SetAssociateDbJson(oPC, sAssocType, "modes", jModes); + ai_SetAssociateDbJson(oPC, sAssocType, "buttons", jButtons); + ai_SetAssociateDbJson(oPC, sAssocType, "aidata", jAIData); + ai_SetAssociateDbJson(oPC, sAssocType, "lootfilters", jLootFilters); + SetLocalString(oAssoc, AI_COMBAT_SCRIPT, sCombatScript); + SetLocalString(oAssoc, AI_DEFAULT_SCRIPT, sDefaultScript); + if(oAssoc != OBJECT_INVALID) + { + // Clear the creatures Perception distance so we can + // repopulate the local variables. + SetLocalFloat(oAssoc, AI_ASSOC_PERCEPTION_DISTANCE, 0.0); + ai_CheckAssociateData(oPC, oAssoc, sAssocType); + if(!ai_GetWidgetButton(oPC, BTN_WIDGET_OFF, oAssoc, sAssocType)) + { + DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, sAssocType + AI_WIDGET_NUI))); + DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oAssoc)); + } + ai_SendMessages(GetName(oAssociate) + "'s settings have been copied to " + GetName(oAssoc) + ".", AI_COLOR_GREEN, oPC); + } + } + } + return; + } + //************************************************************************** + // Plugins events. + if(sWndId == AI_PLUGIN_NUI) + { + if(sEvent == "click") + { + if(sElem == "btn_load_plugins") + { + json jPlugins = ai_GetAssociateDbJson(oPC, "pc", "plugins"); + jPlugins = ai_Plugin_Add(oPC, jPlugins, "pi_buffing"); + jPlugins = ai_Plugin_Add(oPC, jPlugins, "pi_forcerest"); + jPlugins = ai_Plugin_Add(oPC, jPlugins, "pi_henchmen"); + jPlugins = ai_Plugin_Add(oPC, jPlugins, "pi_crafting"); + jPlugins = ai_Plugin_Add(oPC, jPlugins, "pi_mod_set"); + jPlugins = ai_Plugin_Add(oPC, jPlugins, "pi_debug"); + jPlugins = ai_Plugin_Add(oPC, jPlugins, "pi_test"); + ai_SetAssociateDbJson(oPC, "pc", "plugins", jPlugins); + DelayCommand(0.0, NuiDestroy(oPC, nToken)); + DelayCommand(0.1, ai_CreatePluginNUI(oPC)); + } + if(sElem == "btn_load_m_mods") + { + json jPlugins = ai_GetAssociateDbJson(oPC, "pc", "plugins"); + jPlugins = ai_Plugin_Add(oPC, jPlugins, "mm_prc_spells"); + ai_SetAssociateDbJson(oPC, "pc", "plugins", jPlugins); + DelayCommand(0.0, NuiDestroy(oPC, nToken)); + DelayCommand(0.1, ai_CreatePluginNUI(oPC)); + } + if(sElem == "btn_check_plugins") + { + json jPlugins = ai_GetAssociateDbJson(oPC, "pc", "plugins"); + int nIndex; + json jPlugin = JsonArrayGet(jPlugins, nIndex); + while(JsonGetType(jPlugin) != JSON_TYPE_NULL) + { + if(JsonGetInt(JsonArrayGet(jPlugin, 1)) < 3) + { + jPlugin = JsonArraySet(jPlugin, 1, JsonBool(TRUE)); + jPlugins = JsonArraySet(jPlugins, nIndex, jPlugin); + } + jPlugin = JsonArrayGet(jPlugins, ++nIndex); + } + ai_SetAssociateDbJson(oPC, "pc", "plugins", jPlugins); + DelayCommand(0.0, NuiDestroy(oPC, nToken)); + DelayCommand(0.1, ai_CreatePluginNUI(oPC)); + DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, "pc" + AI_WIDGET_NUI))); + DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oPC)); + } + if(sElem == "btn_clear_plugins") + { + json jPlugins = ai_GetAssociateDbJson(oPC, "pc", "plugins"); + int nIndex; + json jPlugin = JsonArrayGet(jPlugins, nIndex); + while(JsonGetType(jPlugin) != JSON_TYPE_NULL) + { + if(JsonGetInt(JsonArrayGet(jPlugin, 1)) < 3) + { + jPlugin = JsonArraySet(jPlugin, 1, JsonBool(FALSE)); + jPlugins = JsonArraySet(jPlugins, nIndex, jPlugin); + } + jPlugin = JsonArrayGet(jPlugins, ++nIndex); + } + ai_SetAssociateDbJson(oPC, "pc", "plugins", jPlugins); + DelayCommand(0.0, NuiDestroy(oPC, nToken)); + DelayCommand(0.1, ai_CreatePluginNUI(oPC)); + DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, "pc" + AI_WIDGET_NUI))); + DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oPC)); + } + else if(sElem == "btn_add_plugin") + { + string sScript = JsonGetString(NuiGetBind (oPC, nToken, "txt_plugin")); + json jPlugins = ai_GetAssociateDbJson(oPC, "pc", "plugins"); + jPlugins = ai_Plugin_Add(oPC, jPlugins, sScript); + ai_SetAssociateDbJson(oPC, "pc", "plugins", jPlugins); + DelayCommand(0.0, NuiDestroy(oPC, nToken)); + DelayCommand(0.1, ai_CreatePluginNUI(oPC)); + } + else if(GetStringLeft(sElem, 18) == "btn_remove_plugin_") + { + int nIndex = StringToInt(GetStringRight(sElem, 1)); + json jPlugins = ai_GetAssociateDbJson(oPC, "pc", "plugins"); + jPlugins = JsonArrayDel(jPlugins, nIndex); + ai_SetAssociateDbJson(oPC, "pc", "plugins", jPlugins); + DelayCommand(0.0, NuiDestroy(oPC, nToken)); + DelayCommand(0.1, ai_CreatePluginNUI(oPC)); + DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, "pc" + AI_WIDGET_NUI))); + DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oPC)); + } + else if(GetStringLeft(sElem, 11) == "btn_plugin_") ai_Plugin_Execute(oPC, sElem); + } + else if(sEvent == "watch") + { + if(GetStringLeft(sElem, 12) == "chbx_plugin_" && GetStringRight(sElem, 6) == "_check") + { + int nIndex = StringToInt(GetSubString(sElem, 12, 1)); + json jPlugins = ai_GetAssociateDbJson(oPC, "pc", "plugins"); + json jPlugin = JsonArrayGet(jPlugins, nIndex); + int bCheck = JsonGetInt(NuiGetBind(oPC, nToken, sElem)); + jPlugin = JsonArraySet(jPlugin, 1, JsonBool(bCheck)); + jPlugins = JsonArraySet(jPlugins, nIndex, jPlugin); + ai_SetAssociateDbJson(oPC, "pc", "plugins", jPlugins); + DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, "pc" + AI_WIDGET_NUI))); + DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oPC)); + } + } + return; + } + //************************************************************************** + // Quick Use Widget events. + if(sWndId == sAssociateType + AI_QUICK_WIDGET_NUI) + { + if(sEvent == "click") + { + if(GetStringLeft(sElem, 10) == "btn_class_") // Changes the class. + { + string sClassPosition = GetStringRight(sElem, 1); + json jAIData = ai_GetAssociateDbJson(oPC, sAssociateType, "aidata"); + json jSpells = JsonArrayGet(jAIData, 10); + jSpells = JsonArraySet(jSpells, 0, JsonInt(StringToInt(sClassPosition))); + jAIData = JsonArraySet(jAIData, 10, jSpells); + ai_SetAssociateDbJson(oPC, sAssociateType, "aidata", jAIData); + DelayCommand(0.0, NuiDestroy(oPC, nToken)); + DelayCommand(0.1, ai_CreateQuickWidgetSelectionNUI(oPC, oAssociate)); + } + else if(GetStringLeft(sElem, 10) == "btn_level_") // Changes the level. + { + string sLevel; + if(GetStringLength(sElem) == 12) sLevel = GetStringRight(sElem, 2); + else sLevel = GetStringRight(sElem, 1); + json jAIData = ai_GetAssociateDbJson(oPC, sAssociateType, "aidata"); + json jSpells = JsonArrayGet(jAIData, 10); + jSpells = JsonArraySet(jSpells, 1, JsonInt(StringToInt(sLevel))); + jAIData = JsonArraySet(jAIData, 10, jSpells); + ai_SetAssociateDbJson(oPC, sAssociateType, "aidata", jAIData); + DelayCommand(0.0, NuiDestroy(oPC, nToken)); + DelayCommand(0.1, ai_CreateQuickWidgetSelectionNUI(oPC, oAssociate)); + } + else if(sElem == "btn_text_spell") // Adds abilities to quick use widget. + { + json jAIData = ai_GetAssociateDbJson(oPC, sAssociateType, "aidata"); + json jSpells = JsonArrayGet(jAIData, 10); + json jWidget = JsonArrayGet(jSpells, 2); + if(JsonGetType(jWidget) == JSON_TYPE_NULL) + { + jWidget = JsonArray(); + if(JsonGetLength(jSpells) == 2) jSpells = JsonArrayInsert(jSpells, JsonArray()); + } + if(JsonGetLength(jWidget) < 20) + { + json jData = NuiGetUserData(oPC, nToken); + json jQuickListArray = JsonArrayGet(jData, 1); + json jSpell = JsonArrayGet(jQuickListArray, nIndex); + jWidget = JsonArrayInsert(jWidget, jSpell); + jSpells = JsonArraySet(jSpells, 2, jWidget); + jAIData = JsonArraySet(jAIData, 10, jSpells); + ai_SetAssociateDbJson(oPC, sAssociateType, "aidata", jAIData); + DelayCommand(0.0, NuiDestroy(oPC, nToken)); + DelayCommand(0.1, ai_CreateQuickWidgetSelectionNUI(oPC, oAssociate)); + } + else ai_SendMessages("The quick widget can only have 20 abilities or spells!", AI_COLOR_RED, oPC); + } + else if(sElem == "btn_info_spell") + { + json jQuickListArray = JsonArrayGet(jData, 1); + json jSpell = JsonArrayGet(jQuickListArray, nIndex); + ai_CreateDescriptionNUI(oPC, jSpell); + } + else if(GetStringLeft(sElem, 11) == "btn_widget_") + { + string sIndex; + if(GetStringLength(sElem) == 13) sIndex = GetStringRight(sElem, 2); + else sIndex = GetStringRight(sElem, 1); + json jAIData = ai_GetAssociateDbJson(oPC, sAssociateType, "aidata"); + json jSpells = JsonArrayGet(jAIData, 10); + json jWidget = JsonArrayGet(jSpells, 2); + jWidget = JsonArrayDel(jWidget, StringToInt(sIndex)); + jSpells = JsonArraySet(jSpells, 2, jWidget); + jAIData = JsonArraySet(jAIData, 10, jSpells); + ai_SetAssociateDbJson(oPC, sAssociateType, "aidata", jAIData); + DelayCommand(0.0, NuiDestroy(oPC, nToken)); + DelayCommand(0.1, ai_CreateQuickWidgetSelectionNUI(oPC, oAssociate)); + } + } + else if(sEvent == "close") + { + int nUIToken = NuiFindWindow(oPC, sAssociateType + AI_QUICK_WIDGET_NUI); + if(nUIToken) + { + DelayCommand(0.0, NuiDestroy(oPC, nUIToken)); + DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oAssociate)); + } + } + return; + } + //************************************************************************** + // Spell Memorization events. + if(sWndId == sAssociateType + AI_SPELL_MEMORIZE_NUI) + { + if(sEvent == "click") + { + if(GetStringLeft(sElem, 10) == "btn_class_") // Changes the class. + { + string sClassPosition = GetStringRight(sElem, 1); + json jAIData = ai_GetAssociateDbJson(oPC, sAssociateType, "aidata"); + json jSpells = JsonArrayGet(jAIData, 10); + jSpells = JsonArraySet(jSpells, 0, JsonInt(StringToInt(sClassPosition))); + jAIData = JsonArraySet(jAIData, 10, jSpells); + ai_SetAssociateDbJson(oPC, sAssociateType, "aidata", jAIData); + DelayCommand(0.0, NuiDestroy(oPC, nToken)); + DelayCommand(0.1, ai_CreateSpellMemorizationNUI(oPC, oAssociate)); + } + else if(GetStringLeft(sElem, 10) == "btn_level_") // Changes the level. + { + string sLevel = GetStringRight(sElem, 1); + json jAIData = ai_GetAssociateDbJson(oPC, sAssociateType, "aidata"); + json jSpells = JsonArrayGet(jAIData, 10); + jSpells = JsonArraySet(jSpells, 1, JsonInt(StringToInt(sLevel))); + jAIData = JsonArraySet(jAIData, 10, jSpells); + ai_SetAssociateDbJson(oPC, sAssociateType, "aidata", jAIData); + DelayCommand(0.0, NuiDestroy(oPC, nToken)); + DelayCommand(0.1, ai_CreateSpellMemorizationNUI(oPC, oAssociate)); + } + else if(sElem == "btn_text_spell") // Adds spell to memorization. + { + json jAIData = ai_GetAssociateDbJson(oPC, sAssociateType, "aidata"); + json jSpells = JsonArrayGet(jAIData, 10); + int nClass = GetClassByPosition(JsonGetInt(JsonArrayGet(jSpells, 0)), oAssociate); + int nLevel = JsonGetInt(JsonArrayGet(jSpells, 1)); + json jSpellArray = JsonArrayGet(jData, 1); + int nMaxMemorizationSlot = GetMemorizedSpellCountByLevel(oAssociate, nClass, nLevel); + int nSlot, nSpell; + while(nSlot < nMaxMemorizationSlot) + { + if(GetMemorizedSpellId(oAssociate, nClass, nLevel, nSlot) == -1) + { + nSpell = JsonGetInt(JsonArrayGet(jSpellArray, nIndex)); + SetMemorizedSpell(oAssociate, nClass, nLevel, nSlot, nSpell, FALSE); + //NuiDestroy(oPC, nToken); + //ai_CreateSpellMemorizationNUI(oPC, oAssociate); + string sClass = GetStringByStrRef(StringToInt(Get2DAString("classes", "Name", nClass))); + string sName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); + string sSpellIcon = Get2DAString("spells", "IconResRef", nSpell); + string sIndex = IntToString(nSlot); + NuiSetBind(oPC, nToken, "btn_memorized_" + sIndex + "_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_memorized_" + sIndex + "_image", JsonString(sSpellIcon)); + NuiSetBind(oPC, nToken, "btn_memorized_" + sIndex + "_tooltip", JsonString(" " + sName + " (" + sClass + " / " + IntToString(nLevel) + ")")); + return; + } + nSlot++; + } + if(nSlot >= nMaxMemorizationSlot) ai_SendMessages("All spell memorization slots are full!", AI_COLOR_RED, oPC); + } + else if(sElem == "btn_info_spell") + { + json jSpellArray = JsonArrayGet(jData, 1); + int nSpell = JsonGetInt(JsonArrayGet(jSpellArray, nIndex)); + ai_CreateDescriptionNUI(oPC, JsonArray(), nSpell); + } + else if(GetStringLeft(sElem, 14) == "btn_memorized_") + { + json jAIData = ai_GetAssociateDbJson(oPC, sAssociateType, "aidata"); + json jSpells = JsonArrayGet(jAIData, 10); + int nClass = GetClassByPosition(JsonGetInt(JsonArrayGet(jSpells, 0)), oAssociate); + int nLevel = JsonGetInt(JsonArrayGet(jSpells, 1)); + string sIndex = GetStringRight(sElem, 1); + ClearMemorizedSpell(oAssociate, nClass, nLevel, StringToInt(sIndex)); + NuiSetBind(oPC, nToken, "btn_memorized_" + sIndex + "_image", JsonString("ctl_cg_btn_splvl")); + NuiSetBind(oPC, nToken, "btn_memorized_" + sIndex + "_tooltip", JsonString("")); + NuiSetBind(oPC, nToken, "btn_memorized_" + sIndex + "_event", JsonBool(FALSE)); + //NuiDestroy(oPC, nToken); + //ai_CreateSpellMemorizationNUI(oPC, oAssociate); + } + } + else if(sEvent == "close") + { + int nUIToken = NuiFindWindow(oPC, sAssociateType + AI_QUICK_WIDGET_NUI); + if(nUIToken) + { + DelayCommand(0.0, NuiDestroy(oPC, nUIToken)); + DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oAssociate)); + } + } + return; + } + //************************************************************************** + // Spell Known events. + if(sWndId == sAssociateType + AI_SPELL_KNOWN_NUI) + { + if(sEvent == "click") + { + if(GetStringLeft(sElem, 10) == "btn_class_") // Changes the class. + { + string sClassPosition = GetStringRight(sElem, 1); + json jAIData = ai_GetAssociateDbJson(oPC, sAssociateType, "aidata"); + json jSpells = JsonArrayGet(jAIData, 10); + jSpells = JsonArraySet(jSpells, 0, JsonInt(StringToInt(sClassPosition))); + jAIData = JsonArraySet(jAIData, 10, jSpells); + ai_SetAssociateDbJson(oPC, sAssociateType, "aidata", jAIData); + DelayCommand(0.0, NuiDestroy(oPC, nToken)); + DelayCommand(0.1, ai_CreateSpellKnownNUI(oPC, oAssociate)); + } + else if(GetStringLeft(sElem, 10) == "btn_level_") // Changes the level. + { + string sLevel = GetStringRight(sElem, 1); + json jAIData = ai_GetAssociateDbJson(oPC, sAssociateType, "aidata"); + json jSpells = JsonArrayGet(jAIData, 10); + jSpells = JsonArraySet(jSpells, 1, JsonInt(StringToInt(sLevel))); + jAIData = JsonArraySet(jAIData, 10, jSpells); + ai_SetAssociateDbJson(oPC, sAssociateType, "aidata", jAIData); + DelayCommand(0.0, NuiDestroy(oPC, nToken)); + DelayCommand(0.1, ai_CreateSpellKnownNUI(oPC, oAssociate)); + } + else if(sElem == "btn_text_spell") // Adds spell to known list. + { + json jAIData = ai_GetAssociateDbJson(oPC, sAssociateType, "aidata"); + json jSpells = JsonArrayGet(jAIData, 10); + int nClass = GetClassByPosition(JsonGetInt(JsonArrayGet(jSpells, 0)), oAssociate); + int nLevel = JsonGetInt(JsonArrayGet(jSpells, 1)); + json jSpellArray = JsonArrayGet(jData, 1); + int nSpell = JsonGetInt(JsonArrayGet(jSpellArray, nIndex)); + json jClassList = GetLocalJson(oAssociate, AI_CLASS_LIST_JSON); + // Get the correct class array. + int bAddList, nClassIndex = 0; + json jClass = JsonArrayGet(jClassList, nClassIndex); + while(JsonGetInt(GffGetInt(jClass, "Class")) != nClass) + { + jClass = JsonArrayGet(jClassList, ++nClassIndex); + } + string sLevel = IntToString(nLevel); + json jSpell, jKnownList = GffGetList(jClass, "KnownList" + sLevel); + if(JsonGetType(jKnownList) == JSON_TYPE_NULL) + { + bAddList = TRUE; + jKnownList = JsonArray(); + } + int nMaxKnownSlots, nSlot; + string sSpellKnownTable = Get2DAString("classes", "SpellKnownTable", nClass); + if(sSpellKnownTable != "") nMaxKnownSlots = StringToInt(Get2DAString(sSpellKnownTable, "SpellLevel" + sLevel, GetLevelByClass(nClass, oAssociate) - 1)); + else nMaxKnownSlots = 20; + while(nSlot < nMaxKnownSlots) + { + jSpell = JsonArrayGet(jKnownList, nSlot); + if(JsonGetType(jSpell) == JSON_TYPE_NULL) + { + jSpell = GffAddWord(JsonObject(), "Spell", nSpell); + jSpell = JsonObjectSet(jSpell, "__struct_id", JsonInt(3)); + jKnownList = JsonArrayInsert(jKnownList, jSpell); + string sClass = GetStringByStrRef(StringToInt(Get2DAString("classes", "Name", nClass))); + string sName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); + string sSpellIcon = Get2DAString("spells", "IconResRef", nSpell); + string sIndex = IntToString(nSlot); + NuiSetBind(oPC, nToken, "btn_known_" + sIndex + "_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_known_" + sIndex + "_image", JsonString(sSpellIcon)); + NuiSetBind(oPC, nToken, "btn_known_" + sIndex + "_tooltip", JsonString(" " + sName + " (" + sClass + " / " + sLevel + ")")); + SetLocalInt(oAssociate, "AI_KNOWN_SPELL_CHANGE", TRUE); + break; + } + else if(JsonGetInt(GffGetWord(jSpell, "Spell")) == nSpell) + { + string sName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); + ai_SendMessages(sName + " is already in the known spell list!", AI_COLOR_RED, oPC); + return; + } + nSlot++; + } + if(nSlot >= nMaxKnownSlots) + { + ai_SendMessages("All known spell slots are full!", AI_COLOR_RED, oPC); + return; + } + if(bAddList) jClass = GffAddList(jClass, "KnownList" + sLevel, jKnownList); + else jClass = GffReplaceList(jClass, "KnownList" + sLevel, jKnownList); + jClassList = JsonArraySet(jClassList, nClassIndex, jClass); + SetLocalJson(oAssociate, AI_CLASS_LIST_JSON, jClassList); + } + else if(sElem == "btn_info_spell") + { + json jSpellArray = JsonArrayGet(jData, 1); + int nSpell = JsonGetInt(JsonArrayGet(jSpellArray, nIndex)); + ai_CreateDescriptionNUI(oPC, JsonArray(), nSpell); + } + else if(GetStringLeft(sElem, 10) == "btn_known_") // Remove a known spell. + { + json jAIData = ai_GetAssociateDbJson(oPC, sAssociateType, "aidata"); + json jSpells = JsonArrayGet(jAIData, 10); + int nClass = GetClassByPosition(JsonGetInt(JsonArrayGet(jSpells, 0)), oAssociate); + int nLevel = JsonGetInt(JsonArrayGet(jSpells, 1)); + string sIndex = GetStringRight(sElem, 1); + // Check to see if there is a spell in this slot. + string sImageName = JsonGetString(NuiGetBind(oPC, nToken, "btn_known_" + sIndex + "_image")); + if(sImageName == "ctl_cg_btn_splvl") return; + json jClassList = GetLocalJson(oAssociate, AI_CLASS_LIST_JSON); + // Get the correct class array. + int nClassIndex = 0; + json jClass = JsonArrayGet(jClassList, nClassIndex); + while(JsonGetInt(GffGetInt(jClass, "Class")) != nClass) + { + jClass = JsonArrayGet(jClassList, ++nClassIndex); + } + string sLevel = IntToString(nLevel); + json jKnownList = GffGetList(jClass, "KnownList" + sLevel); + jKnownList = JsonArrayDel(jKnownList, StringToInt(sIndex)); + jClass = GffReplaceList(jClass, "KnownList" + sLevel, jKnownList); + jClassList = JsonArraySet(jClassList, nClassIndex, jClass); + SetLocalJson(oAssociate, AI_CLASS_LIST_JSON, jClassList); + SetLocalInt(oAssociate, "AI_KNOWN_SPELL_CHANGE", TRUE); + // Relist all known spells so they match the index. + int nMaxKnownSlots, nSpell; + string sName, sSpellIcon, sClass = IntToString(nClass); + string sSpellKnownTable = Get2DAString("classes", "SpellKnownTable", nClass); + json jSpell; + if(sSpellKnownTable != "") nMaxKnownSlots = StringToInt(Get2DAString(sSpellKnownTable, "SpellLevel" + IntToString(nLevel), GetLevelByClass(nClass, oAssociate) - 1)); + else nMaxKnownSlots = 20; + nIndex = 0; + while(nIndex < 20) + { + sIndex = IntToString(nIndex); + NuiSetBind(oPC, nToken, "btn_known_" + sIndex + "_event", JsonBool(TRUE)); + if(nIndex < nMaxKnownSlots) + { + jSpell = JsonArrayGet(jKnownList, nIndex); + if(JsonGetType(jSpell) == JSON_TYPE_NULL) + { + NuiSetBind(oPC, nToken, "btn_known_" + sIndex + "_image", JsonString("ctl_cg_btn_splvl")); + NuiSetBind(oPC, nToken, "btn_known_" + sIndex + "_tooltip", JsonString(" Empty known spell slot")); + } + else + { + nSpell = JsonGetInt(GffGetWord(jSpell, "Spell")); + sName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); + //nMetaMagic = 255; + //nDomain = 0; + sSpellIcon = Get2DAString("spells", "IconResRef", nSpell); + NuiSetBind(oPC, nToken, "btn_known_" + sIndex + "_image", JsonString(sSpellIcon)); + NuiSetBind(oPC, nToken, "btn_known_" + sIndex + "_tooltip", JsonString(" " + sName + " (" + sClass + " / " + IntToString(nLevel) + ")")); + //sMetaMagicText = ai_GetSpellIconAttributes(oAssociate, -1, -1, -1, nMetaMagic, nDomain); + //NuiSetBind(oPC, nToken, "metamagic_" + sIndex + "_text", JsonString(sMetaMagicText)); + } + } + else + { + NuiSetBind(oPC, nToken, "btn_known_" + sIndex + "_image", JsonString("ctl_cg_btn_splvl")); + //NuiSetBind(oPC, nToken, "metamagic_" + sIndex + "_text", JsonString("")); + NuiSetBind(oPC, nToken, "btn_known_" + sIndex + "_event", JsonBool(FALSE)); + } + ++nIndex; + } + } + } + else if(sEvent == "close") + { + if(GetLocalInt(oAssociate, "AI_KNOWN_SPELL_CHANGE")) + { + RemoveHenchman(oPC, oAssociate); + json jHenchman = ObjectToJson(oAssociate, TRUE); + json jClassList = GetLocalJson(oAssociate, AI_CLASS_LIST_JSON); + jHenchman = GffReplaceList(jHenchman, "ClassList", jClassList); + location lLocation = GetLocation(oAssociate); + int nFamiliar, nCompanion; + object oCompanion = GetAssociate(ASSOCIATE_TYPE_FAMILIAR, oAssociate); + if(oCompanion != OBJECT_INVALID) nFamiliar = TRUE; + oCompanion = GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION, oAssociate); + if(oCompanion != OBJECT_INVALID) nCompanion = TRUE; + AssignCommand(oAssociate, SetIsDestroyable(TRUE, FALSE, FALSE)); + DestroyObject(oAssociate); + oAssociate = ai_AddHenchman(oPC, jHenchman, lLocation, nFamiliar, nCompanion); + DeleteLocalInt(oAssociate, "AI_KNOWN_SPELL_CHANGE"); + DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oAssociate)); + } + } + return; + } + //************************************************************************** + // Spell Description events. + if(sWndId == AI_SPELL_DESCRIPTION_NUI) + { + if(sEvent == "click" && sElem == "btn_ok") DelayCommand(0.0, NuiDestroy(oPC, nToken)); + } + //************************************************************************** + // Effect Icon NUI events. + if(sWndId == AI_EFFECT_ICON_NUI) + { + if(sEvent == "click") + { + if(GetStringLeft(sElem, 18) == "btn_remove_effect_") + { + int nEffectIndex = StringToInt(GetStringRight(sElem, GetStringLength(sElem) - 18)); + json jEffectID = JsonArrayGet(jData, 2); + string sEffectLinkID = JsonGetString(JsonArrayGet(jEffectID, nEffectIndex)); + int nIndex; + effect eEffect = GetFirstEffect(oPC); + while(GetIsEffectValid(eEffect)) + { + if(GetEffectLinkId(eEffect) == sEffectLinkID) + { + RemoveEffect(oPC, eEffect); + int nEffectIconToken = NuiFindWindow(oPC, AI_EFFECT_ICON_NUI); + if(nEffectIconToken) DelayCommand(0.0, NuiDestroy(oPC, nEffectIconToken)); + } + nIndex++; + eEffect = GetNextEffect(oPC); + } + } + } + else if(sEvent == "mousedown") + { + AssignCommand(oPC, PlaySound("gui_button")); + DelayCommand(0.0, NuiDestroy(oPC, nToken)); + } + } +} +void ai_SetWidgetButtonToCheckbox(object oPC, int nButton, object oAssociate, string sAssociateType, int nToken, string sElem) +{ + int bCheck = JsonGetInt(NuiGetBind(oPC, nToken, sElem)); + ai_SetWidgetButton(oPC, nButton, oAssociate, sAssociateType, bCheck); +} +void ai_SetAIButtonToCheckbox(object oPC, int nButton, object oAssociate, string sAssociateType, int nToken, string sElem) +{ + int bCheck = JsonGetInt(NuiGetBind(oPC, nToken, sElem)); + ai_SetAIButton(oPC, nButton, oAssociate, sAssociateType, bCheck); +} +void ai_SetLootFilterToCheckbox(object oPC, object oAssociate, int nFilterBit, int nToken, string sElem) +{ + int bCheck = JsonGetInt(NuiGetBind(oPC, nToken, sElem)); + ai_SetLootFilter(oAssociate, nFilterBit, bCheck); +} +void ai_AddAssociate(object oPC, int nToken, json jAssociate, location lLocation, int nFamiliar, int nCompanion, int nRange = 0) +{ + object oAssociate = JsonToObject(jAssociate, lLocation, OBJECT_INVALID, TRUE); + //ChangeToStandardFaction(oAssociate, STANDARD_FACTION_COMMONER); + //SetStandardFactionReputation(STANDARD_FACTION_COMMONER, 50, oAssociate); + //SetStandardFactionReputation(STANDARD_FACTION_DEFENDER, 50, oAssociate); + //SetStandardFactionReputation(STANDARD_FACTION_MERCHANT, 50, oAssociate); + //SetStandardFactionReputation(STANDARD_FACTION_HOSTILE, 0, oAssociate); + AddHenchman(oPC, oAssociate); + DeleteLocalInt(oPC, "AI_IGNORE_NO_ASSOCIATE"); + DelayCommand(0.0, NuiDestroy(oPC, nToken)); + DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oAssociate)); + if(nRange) SetLocalInt(oAssociate, AI_ASSOCIATE_PERCEPTION, nRange); + if(nFamiliar) SummonFamiliar(oAssociate); + if(nCompanion) SummonAnimalCompanion(oAssociate); +} +void ai_SetCompanionType(object oPC, object oAssociate, int nToken, int nAssociateType) +{ + if(ai_GetIsCharacter(oAssociate)) return; + SetLocalInt(oPC, "AI_IGNORE_NO_ASSOCIATE", TRUE); + int nSelection; + // Need to remove the henchman before we copy them to keep factions correct. + ai_FireHenchman(oPC, oAssociate); + json jAssociate = ObjectToJson(oAssociate, TRUE); + if(nAssociateType == ASSOCIATE_TYPE_FAMILIAR) + { + nSelection = JsonGetInt(NuiGetBind(oPC, nToken, "cmb_familiar_selected")); + jAssociate = GffReplaceInt(jAssociate, "FamiliarType", nSelection); + } + else if(nAssociateType == ASSOCIATE_TYPE_ANIMALCOMPANION) + { + nSelection = JsonGetInt(NuiGetBind(oPC, nToken, "cmb_companion_selected")); + jAssociate = GffReplaceInt(jAssociate, "CompanionType", nSelection); + } + //ai_Debug("0e_nui", "916", JsonDump(jAssociate, 1)); + location lLocation = GetLocation(oAssociate); + int nFamiliar, nCompanion; + object oCompanion = GetAssociate(ASSOCIATE_TYPE_FAMILIAR, oAssociate); + if(oCompanion != OBJECT_INVALID) nFamiliar = TRUE; + oCompanion = GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION, oAssociate); + if(oCompanion != OBJECT_INVALID) nCompanion = TRUE; + SetIsDestroyable(TRUE, FALSE, FALSE, oAssociate); + DestroyObject(oAssociate); + DelayCommand(0.1, ai_AddAssociate(oPC, nToken, jAssociate, lLocation, nFamiliar, nCompanion)); +} +void ai_SetCompanionName(object oPC, object oAssociate, int nToken, int nAssociateType) +{ + if(ai_GetIsCharacter(oAssociate)) return; + SetLocalInt(oPC, "AI_IGNORE_NO_ASSOCIATE", TRUE); + string sAssociateType; + string sName; + // Need to remove the henchman before we copy them to keep factions correct. + ai_FireHenchman(oPC, oAssociate); + json jAssociate = ObjectToJson(oAssociate, TRUE); + if(nAssociateType == ASSOCIATE_TYPE_FAMILIAR) + { + sName = JsonGetString(NuiGetBind(oPC, nToken, "txt_familiar_name")); + jAssociate = GffReplaceString(jAssociate, "FamiliarName", sName); + } + else if(nAssociateType == ASSOCIATE_TYPE_ANIMALCOMPANION) + { + sAssociateType = "txt_companion_name"; + sName = JsonGetString(NuiGetBind(oPC, nToken, "txt_companion_name")); + jAssociate = GffReplaceString(jAssociate, "FamiliarName", sName); + } + location lLocation = GetLocation(oAssociate); + int nFamiliar, nCompanion; + object oCompanion = GetAssociate(ASSOCIATE_TYPE_FAMILIAR, oAssociate); + if(oCompanion != OBJECT_INVALID) nFamiliar = TRUE; + oCompanion = GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION, oAssociate); + if(oCompanion != OBJECT_INVALID) nCompanion = TRUE; + SetIsDestroyable(TRUE, FALSE, FALSE, oAssociate); + DestroyObject(oAssociate); + DelayCommand(0.1, ai_AddAssociate(oPC, nToken, jAssociate, lLocation, nFamiliar, nCompanion)); +} +void ai_SetAIScript(object oPC, object oAssociate, int nToken) +{ + int nSelection = JsonGetInt(NuiGetBind(oPC, nToken, "cmb_ai_script_selected")); + if(nSelection == 0) return; + string sScript = sScript = ResManFindPrefix("ai_a_", RESTYPE_NCS, nSelection); + NuiSetBind(oPC, nToken, "txt_ai_script", JsonString(sScript)); + string sOldScript = GetLocalString(oAssociate, AI_COMBAT_SCRIPT); + if(sScript != sOldScript) + { + SetLocalString(oAssociate, AI_COMBAT_SCRIPT, sScript); + SetLocalString(oAssociate, AI_DEFAULT_SCRIPT, sScript); + string sAssociateType = ai_GetAssociateType(oPC, oAssociate); + json jAIData = ai_GetAssociateDbJson(oPC, sAssociateType, "aidata"); + if(JsonGetType(JsonArrayGet(jAIData, 8)) == JSON_TYPE_NULL) jAIData = JsonArrayInsert(jAIData, JsonString(sScript)); + else jAIData = JsonArraySet(jAIData, 8, JsonString(sScript)); + ai_SetAssociateDbJson(oPC, sAssociateType, "aidata", jAIData); + ai_SendMessages(GetName(oAssociate) + " is now using " + sScript + " AI script!", AI_COLOR_GREEN, oPC); + } + else ai_SendMessages(GetName(oAssociate) + " is already using this script! Did not change AI script.", AI_COLOR_RED, oPC); +} +void ai_PercRangeIncrement(object oPC, object oAssociate, int nIncrement, string sAssociateType, int nToken) +{ + int nAdjustment = GetLocalInt(oAssociate, AI_ASSOCIATE_PERCEPTION + "_MENU"); + nAdjustment += nIncrement; + if(nAdjustment < 8 || nAdjustment > 11) return; + SetLocalInt(oAssociate, AI_ASSOCIATE_PERCEPTION + "_MENU", nAdjustment); + json jAssociate = ObjectToJson(oAssociate, TRUE); + int nHenchPercRange = JsonGetInt(GffGetByte(jAssociate, "PerceptionRange")); + string sText, sInfo; + if(nAdjustment == nHenchPercRange) + { + if(nAdjustment == 8) sText = " Perception Range Short [10 meters Sight / 10 meters Listen]"; + else if(nAdjustment == 9) sText = " Perception Range Medium [20 meters Sight / 20 meters Listen]"; + else if(nAdjustment == 10) sText = " Perception Range Long [35 meters Sight / 20 meters Listen]"; + else sText = " Perception Range Default [20 meters Sight / 20 meters Listen]"; + sInfo = " "; + } + else + { + if(nAdjustment == 8) sText = " !!! Click the Perception Range button to set to short range !!!"; + else if(nAdjustment == 9) sText = " !!! Click the Perception Range button to set to medium range !!!"; + else if(nAdjustment == 10) sText = " !!! Click the Perception Range button to set to long range !!!"; + else sText = " !!! Click the Perception Range button to set to the default range !!!"; + sInfo = sText; + } + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_perc_range_tooltip", sText); + if(nToken > -1) NuiSetBind (oPC, nToken, "lbl_info_label", JsonString(sInfo)); +} +void ai_Perc_Range(object oPC, object oAssociate, int nToken, string sAssociateType) +{ + if(ai_GetIsCharacter(oAssociate)) return; + SetLocalInt(oPC, "AI_IGNORE_NO_ASSOCIATE", TRUE); + int nBtnPercRange = GetLocalInt(oAssociate, AI_ASSOCIATE_PERCEPTION + "_MENU"); + string sText, sText2; + float fRange = 20.0; + if(nBtnPercRange == 8) + { + sText = "short"; + sText2 = " Perception Range Short [10 meters Sight / 10 meters Listen]"; + fRange = 10.0; + } + else if(nBtnPercRange == 9) + { + sText = "medium"; + sText2 = " Perception Range Medium [20 meters Sight / 20 meters Listen]"; + } + else if(nBtnPercRange == 10) + { + sText = "long"; + sText2 = " Perception Range Long [35 meters Sight / 20 meters Listen]"; + fRange = 35.0; + } + else if(nBtnPercRange == 11) + { + sText = "default"; + sText2 = " Perception Range Default [20 meters Sight / 20 meters Listen]"; + } + SetLocalFloat(oAssociate, AI_ASSOC_PERCEPTION_DISTANCE, fRange); + SetLocalInt(oAssociate, AI_ASSOCIATE_PERCEPTION, nBtnPercRange); + json jAIData = ai_GetAssociateDbJson(oPC, sAssociateType, "aidata"); + jAIData = JsonArraySet(jAIData, 7, JsonInt(nBtnPercRange)); + ai_SetAssociateDbJson(oPC, sAssociateType, "aidata", jAIData); + // Need to remove the henchman before we copy them to keep factions correct. + ai_FireHenchman(oPC, oAssociate); + json jAssociate = ObjectToJson(oAssociate, TRUE); + int nHenchPercRange = JsonGetInt(GffGetByte(jAssociate, "PerceptionRange")); + if(nBtnPercRange == nHenchPercRange) + { + ai_SendMessages(GetName(oAssociate) + " already has this perception set.", AI_COLOR_YELLOW, oPC); + AddHenchman(oPC, oAssociate); + DeleteLocalInt(oPC, "AI_IGNORE_NO_ASSOCIATE"); + return; + } + DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, sAssociateType + AI_NUI))); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_perc_range_tooltip", sText2); + ai_SendMessages(GetName(oAssociate) + " has updated their perception range to " + sText + ".", AI_COLOR_YELLOW, oPC); + location lLocation = GetLocation(oAssociate); + jAssociate = GffReplaceByte(jAssociate, "PerceptionRange", nBtnPercRange); + int nFamiliar, nCompanion; + object oCompanion = GetAssociate(ASSOCIATE_TYPE_FAMILIAR, oAssociate); + if(oCompanion != OBJECT_INVALID) nFamiliar = TRUE; + oCompanion = GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION, oAssociate); + if(oCompanion != OBJECT_INVALID) nCompanion = TRUE; + SetIsDestroyable(TRUE, FALSE, FALSE, oAssociate); + DestroyObject(oAssociate); + DelayCommand(0.1, ai_AddAssociate(oPC, nToken, jAssociate, lLocation, nFamiliar, nCompanion, nBtnPercRange)); +} +void ai_RulePercDistInc(object oPC, 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(oPC, 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); + if(JsonGetType(jRSpells) == JSON_TYPE_NULL) jRSpells = JsonArray(); + 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_TurnOn(object oPC, object oTarget, string sAssociateType) +{ + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_ai_tooltip", " AI On"); + ai_SendMessages("AI turned on for " + GetName(oTarget) + ".", AI_COLOR_YELLOW, oPC); + SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "xx_pc_1_hb"); + SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_NOTICE, "xx_pc_2_percept"); + SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND, "xx_pc_3_endround"); + SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_DIALOGUE, "xx_pc_4_convers"); + SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED, "xx_pc_5_phyatked"); + SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_DAMAGED, "xx_pc_6_damaged"); + //SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_DEATH, ""); + SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_DISTURBED, "xx_pc_8_disturb"); + //SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_SPAWN_IN, ""); + //SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_RESTED, ""); + SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, "xx_pc_b_castat"); + SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR, "xx_pc_e_blocked"); + //SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_USER_DEFINED_EVENT, ""); + // This sets the script for the PC to run AI based on class. + ai_SetAssociateAIScript(oTarget, FALSE); + // Set so PC can hear associates talking in combat. + ai_SetListeningPatterns(oTarget); +} +void ai_TurnOff(object oPC, object oAssociate, string sAssociateType) +{ + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_ai_tooltip", " AI Off"); + ai_SendMessages("AI Turned off for " + GetName(oAssociate) + ".", AI_COLOR_YELLOW, oPC); + SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, ""); + SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_NOTICE, ""); + SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND, ""); + SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_DIALOGUE, ""); + SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED, ""); + SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_DAMAGED, ""); + //SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_DEATH, ""); + SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_DISTURBED, ""); + //SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_SPAWN_IN, ""); + //SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_RESTED, ""); + SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, ""); + SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR, ""); + //SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_USER_DEFINED_EVENT, ""); + DeleteLocalInt(oAssociate, "AI_I_AM_BEING_HEALED"); + DeleteLocalString(oAssociate, "AIScript"); + ai_ClearCreatureActions(); +} +object ai_AddHenchman(object oPC, json jHenchman, location lLocation, int nFamiliar, int nCompanion) +{ + jHenchman = GffReplaceResRef(jHenchman, "ScriptSpawn", ""); + object oHenchman = JsonToObject(jHenchman, lLocation, OBJECT_INVALID, TRUE); + AddHenchman(oPC, oHenchman); + DeleteLocalInt(oPC, "AI_IGNORE_NO_ASSOCIATE"); + string sAssociateType = ai_GetAssociateType(oPC, oHenchman); + NuiDestroy(oPC, NuiFindWindow(oPC, sAssociateType + AI_WIDGET_NUI)); + if(nFamiliar) SummonFamiliar(oHenchman); + if(nCompanion) SummonAnimalCompanion(oHenchman); + return oHenchman; +} + diff --git a/src/module/nss/0e_nui_dm.nss b/src/module/nss/0e_nui_dm.nss new file mode 100644 index 0000000..4ffd851 --- /dev/null +++ b/src/module/nss/0e_nui_dm.nss @@ -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)); +} diff --git a/src/module/nss/0e_onclientload.nss b/src/module/nss/0e_onclientload.nss new file mode 100644 index 0000000..041d49f --- /dev/null +++ b/src/module/nss/0e_onclientload.nss @@ -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); + } +} diff --git a/src/module/nss/0e_player_target.nss b/src/module/nss/0e_player_target.nss new file mode 100644 index 0000000..16b83fb --- /dev/null +++ b/src/module/nss/0e_player_target.nss @@ -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); + } + } +} diff --git a/src/module/nss/0e_prc_ch_events.nss b/src/module/nss/0e_prc_ch_events.nss new file mode 100644 index 0000000..3028e9c --- /dev/null +++ b/src/module/nss/0e_prc_ch_events.nss @@ -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; + } + } +} diff --git a/src/module/nss/0i_actions.nss b/src/module/nss/0i_actions.nss new file mode 100644 index 0000000..7d7d2d7 --- /dev/null +++ b/src/module/nss/0i_actions.nss @@ -0,0 +1,2325 @@ +/*//////////////////////////////////////////////////////////////////////////////////////////////////// +// Script Name: 0i_actions +////////////////////////////////////////////////////////////////////////////////////////////////////// + Include scripts for action in and out of combat. + + Detect Mode: + Passive(default) mode + * Trap detection radius: 5ft + * Trap detection rate: every 6 seconds + * Trap detection roll: d20 + 1/2 skill + * Spot/Listen roll: d10 + 1/2 skill + + Active(Detect) mode + * Trap detection radius: 10ft + * Trap detection rate: every 3 seconds + * Trap detection roll: d20 + skill + * Spot/Listen roll: d20 + skill + + Stealth checks + * Player detects stealth: 5 times per second. + * Player rolls for hide/move silently & spot/listen: every 6 seconds. + * NPC detects stealth: 4 seconds + * NPC rolls for hide/move silently & spot/listen: every 6 seconds. + + Listen/Move Silently: + * Cannot detect silenced creatures. + * Cannot detect sanctuaried creatures. + * Can only detect invisible (or when your blind) creatures within max attack range. + * Listen checks are made each round for success and failur. + * Outdoors: Objects between you and the target gives a +5 DC for every 40cm of thickness. + * Indoors: No Line of sight and the target is within 40 meters gives a +2 DC. + * +10 DC in combat for the target. + * +5 DC if the target is standing still. + * -5 DC if the listener is standing still. + * +1 DC for every 3 meters of distance to the target. + * Relative size modifiers for both: Tiny +8, Small +4, Medium 0, Larget -4, Huge -8. + * Favored enemy bonuses. + + Spot/Hide: + * Cannot spot invisible creatures. + * Cannot spot any creatures while blinded. + * Night time: Spotter has not light or darkvision +5 DC. + * Night time: Target has a light no them -10 DC. + * +5 DC if target is behind the spotter. + * +10 DC if the spotter are in combat. + * +5 DC if the target is standing still. + * -5 DC if the spotter is standing still. + * Relative size modifiers for both: Tiny +8, Small +4, Medium 0, Larget -4, Huge -8. + * Favored enemy bonuses. + +*///////////////////////////////////////////////////////////////////////////////////////////////////// +// Programmer: Philos +////////////////////////////////////////////////////////////////////////////////////////////////////// +#include "0i_talents" +#include "x0_inc_henai" +#include "X0_I0_ANIMS" +// Chooses an action in combat and executes it for oCreature that is an associate. +void ai_DoAssociateCombatRound(object oCreature, object oTarget = OBJECT_INVALID); +// Sets variables and states for oAssociate to start combat. +void ai_StartAssociateCombat(object oAssociate, object oTarget = OBJECT_INVALID); +// Chooses an action in combat and executes it for oCreature that is a monster. +void ai_DoMonsterCombatRound(object oCreature); +// Sets variables and states for oMonster to start combat. +void ai_StartMonsterCombat(object oMonster); +// Return the distance that is set for how close we should follow our master. +float ai_GetFollowDistance(object oCreature); +// Returns TRUE if the caller's distance is greater than fDistance from who they +// are following. Unless they are cowardly or in stand ground mode. +// This will also force the caller to move towards them. +int ai_StayClose(object oCreature); +// Returns TRUE if oCreature becomes invisible or hides. +int ai_TryToBecomeInvisible(object oCreature); +// Returns TRUE if oCreature continues to bash a door. +int ai_BashDoorCheck(object oCreature); +// Returns TRUE if we find an hidden creature within battle and do an action. +// If oCreature is too far away they will run upto 14 meters of the invisible creature. +// If oCreature is close they will attempt to cast a spell or search for them. +// bMonster needs to be set for monsters otherwise we do associate perception checks. +// fRange is how close we want to get to hidden targets. +int ai_SearchForHiddenCreature(object oCreature, int bMonster, object oHidden = OBJECT_INVALID, float fRange = 1.0); +// Returns TRUE if oCreature fails a moral check. +// We only make moral checks once we are below AI_HEALTH_WOUNDED health percent. +// If we are at AI_HEALTH_BLOODY hp percent then add + AI_MORAL_INC_DC to the Check. +int ai_MoralCheck(object oCreature); +// Returns TRUE if oCreature is in and nSpell is a dangerous Area Of Effect. +// Used in the on spell cast at scripts. [nw_c2_defaultb and nw_ch_acb]. +int ai_GetInAOEReaction(object oCreature, object oCaster, int nSpell); +// Have the associate speak a random voice from VOICE_CHAT_*. +// nRoll is the number to roll. If nRoll is 0 then it will SpeakString(sVoiceChatArray); +// sVoiceChatArray is an array of VOICE_CHAT_* numbers over nRoll. +// example(4, ":3:4:8:7:") will roll a d4() picking from 3,4,8,7 of VOICE_CHAT_*. +// if nRoll is higher than the number of VOICE_CHAT_* then it will not speak. +void ai_HaveCreatureSpeak(object oCreature, int nRoll, string sVoiceChatArray, int bImportant = FALSE); +// Returns if a spell talent was used. +// This is a common set of AI scripts ran on associate spell casters. +int ai_CheckForAssociateSpellTalent(object oAssociate, int nInMelee, int nMaxLevel, int nRound = 0); +// Targets the best creature oCreature it can see. +// This checks all physcal attack talents starting with ranged attacks then melee. +// Using TALENT_CATEGORY_HARMFUL_MELEE [22] talents. +// If no talents are used it will do either a ranged attack or a melee attack. +void ai_DoPhysicalAttackOnBest(object oCreature, int nInMelee, int bAlwaysAtk = TRUE); +// Targets the nearest creature oCreature it can see. +// This checks all physcal attack talents starting with ranged attacks then melee. +// Using TALENT_CATEGORY_HARMFUL_MELEE [22] talents. +// If no talents are used it will do either a ranged attack or a melee attack. +void ai_DoPhysicalAttackOnNearest(object oCreature, int nInMelee, int bAlwaysAtk = TRUE); +// Targets the weakest creature oCreature can see. +// This checks all physcal attack talents starting with ranged attacks then melee. +// Using TALENT_CATEGORY_HARMFUL_MELEE [22] talents. +// If no talents are used it will do either a ranged attack or a melee attack. +void ai_DoPhysicalAttackOnLowestCR(object oCreature, int nInMelee, int bAlwaysAtk = TRUE); +// Returns TRUE if they equip a melee weapon, FALSE if they don't. +// This also calls for the next combat round. +int ai_InCombatEquipBestMeleeWeapon(object oCreature); +// Returns TRUE if they equip a ranged weapon, FALSE if they don't. +// This also calls for the next combat round. +int ai_InCombatEquipBestRangedWeapon(object oCreature); +// Action wrapper for ai_TryHealing. +void ai_ActionTryHealing(object oCreature, object oTarget); +// Returns TRUE if oCreature heals oTarget. +// This uses an action and must use AssignCommand or OBJECT_SELF is the caster! +int ai_TryHealing(object oCreature, object oTarget, int bForce = FALSE); +// oCreature will move into the area looking for creatures. +void ai_ScoutAhead(object oCreature); +// Have oCreature search one object, may continue from that object. +void ai_SearchObject(object oCreature, object oObject, object oMaster, int bOnce = FALSE); +// Returns TRUE if oCreature disarms oTrap. +// bForce if TRUE, oCreature will try to disarm the trap even if they have tried before. +int ai_ReactToTrap(object oCreature, object oTrap, int bForce = FALSE); +// Returns TRUE if oCreature opens oLocked object. +// This will make oCreature open oLocked either by picking or casting a spell. +// bForce if TRUE, oCreature will try to pick the lock even if they have tried before. +int ai_AttemptToByPassLock(object oCreature, object oLocked, int bForce = FALSE); +// Returns TRUE if oCreature opens oDoor. +// bForce if TRUE, oCreature will try to open the door even if they have tried before. +int ai_AttemptToOpenDoor(object oCreature, object oDoor, int bForce = FALSE); +// Action for Checking nearby objects for traps, locks and loot. +void ai_ActionCheckNearbyObjects(object oCreature); +// oCreature will check nearby objects and see what they should do based upon +// selected actions by the player. +int ai_CheckNearbyObjects(object oCreature); +// Used to determine special behaviors for oCeature. +void ai_DetermineSpecialBehavior(object oCreature); +// The target object flees to the specified way point and then destroys itself, +// to be respawned at a later point. For unkillable sign post characters +// who are not meant to fight back. +void ai_ActivateFleeToExit(object oCreature); +// Returns TRUE if oCreature should flee to an exit. +int ai_GetFleeToExit(object oCreature); +// Does random animation in a close distance for creatures. +void ai_AmbientAnimations(); + +void ai_DoAssociateCombatRound(object oCreature, object oTarget = OBJECT_INVALID) +{ + if(ai_StayClose(oCreature)) return; + // Is the target our Player has locked in dead? If so then clear it. + if(GetIsDead(GetLocalObject(oCreature, AI_PC_LOCKED_TARGET))) DeleteLocalObject(oCreature, AI_PC_LOCKED_TARGET); + // Setup the combat state for this round of combat. + object oNearestEnemy = ai_SetCombatState(oCreature); + // If we are in standground mode we only fight if the enemy is near us. + if(ai_GetAIMode(oCreature, AI_MODE_STAND_GROUND) && + ai_GetEnemyAttackingMe(oCreature) == OBJECT_INVALID) oNearestEnemy = OBJECT_INVALID; + // If we found an Enemy or we have a Target then continue into the combat round. + if(oNearestEnemy != OBJECT_INVALID || oTarget != OBJECT_INVALID) + { + // In combat we should stop searching. + if(GetActionMode(oCreature, ACTION_MODE_DETECT) && !GetHasFeat(FEAT_KEEN_SENSE)) + { + SetActionMode(oCreature, ACTION_MODE_DETECT, FALSE); + } + ai_SetCombatRound(oCreature); + string sAI = GetLocalString(oCreature, AI_COMBAT_SCRIPT); + if(AI_DEBUG) ai_Debug("0i_actions", "167", " AI not Coward/Peaceful: " + + IntToString(sAI != "ai_coward" && sAI != "ai_a_peaceful")); + // If we are using a normal AI script and are polymorphed we should use + // the polymorph AI script. + if(sAI != "ai_coward" && sAI != "ai_a_peaceful") + { + if(AI_DEBUG) ai_Debug("0i_actions", "173", "Should we use polymorph? " + + IntToString(GetAppearanceType(oCreature) != ai_GetNormalAppearance(oCreature))); + if(AI_DEBUG) + { + if(ai_GetIsHidden(oCreature)) + { + ai_Debug("0i_actions", "179", "We are hidden!" + + " Can they see us? " + IntToString(ai_GetNearestIndexThatSeesUs(oCreature))); + } + } + if(GetAppearanceType(oCreature) != ai_GetNormalAppearance(oCreature)) + { + sAI = "ai_a_polymorphed"; + } + else if(ai_GetIsHidden(oCreature) && !ai_GetNearestIndexThatSeesUs(oCreature)) sAI = "ai_a_invisible"; + } + if(sAI == "") sAI = "ai_a_default"; + if(AI_DEBUG) ai_Debug("0i_actions", "190", "********** " + GetName (oCreature) + " **********"); + if(AI_DEBUG) ai_Debug("0i_actions", "191", "********** " + sAI + " **********"); + ai_ClearCreatureActions(); + if(AI_DEBUG) ai_Counter_Start(); + // Execute this creatures AI routine. + ExecuteScript(sAI, oCreature); + if(AI_DEBUG) ai_Counter_End(GetName(oCreature) + " has finalized round action."); + return; + } + // We have exhausted our check for an enemy. Combat is over. + if(AI_DEBUG) ai_Debug("0i_actions", "200", "---------- " + GetName (OBJECT_SELF) + "'s combat has ended! ----------"); + ai_ClearCombatState(oCreature); + // Run the heartbeat script so we start doing our actions out of combat. + ExecuteScript("nw_ch_ac1", oCreature); +} +void ai_StartAssociateCombat(object oAssociate, object oTarget = OBJECT_INVALID) +{ + if(AI_DEBUG) ai_Debug("0i_actions", "217", "---------- " + GetName(oAssociate) + " is starting combat! ----------"); + ai_SetCreatureTalents(oAssociate, FALSE); + ai_CheckXPPartyScale(oAssociate); + ai_DoAssociateCombatRound(oAssociate, oTarget); +} +void ai_DoMonsterCombatRound(object oMonster) +{ + object oNearestEnemy = ai_SetCombatState(oMonster); + if(oNearestEnemy != OBJECT_INVALID) + { + if(GetActionMode(oMonster, ACTION_MODE_DETECT) && !GetHasFeat(FEAT_KEEN_SENSE, oMonster)) + SetActionMode(oMonster, ACTION_MODE_DETECT, FALSE); + ai_SetCombatRound(oMonster); + string sAI = GetLocalString(oMonster, AI_COMBAT_SCRIPT); + if(sAI != "ai_coward") + { + if(GetAppearanceType(oMonster) != ai_GetNormalAppearance(oMonster)) + { + sAI = "ai_polymorphed"; + } + else if(ai_GetIsHidden(oMonster) && !ai_GetNearestIndexThatSeesUs(oMonster)) sAI = "ai_invisible"; + } + if(sAI == "") sAI = "ai_default"; + if(AI_DEBUG) ai_Debug("0i_actions", "230", "********** " + GetName (oMonster) + " **********"); + if(AI_DEBUG) ai_Debug("0i_actions", "231", "********** " + sAI + " **********"); + // We clear actions here and setup multiple actions to the queue for oCreature. + ai_ClearCreatureActions(); + ai_Counter_Start(); + ExecuteScript(sAI, oMonster); + ai_Counter_End(GetName(oMonster) + " is ending round calculations."); + return; + } + // Check to see if we just didn't see the enemies. + if(GetLocalInt(oMonster, AI_ENEMY_NUMBERS) && + ai_SearchForHiddenCreature(oMonster, TRUE)) return; + // We have exhausted our check for an enemy. Combat is over. + ai_EndCombatRound(oMonster); + ai_ClearCombatState(oMonster); + // Run the heartbeat script so we start doing our actions out of combat. + ExecuteScript("nw_c2_default1", oMonster); + if(AI_DEBUG) ai_Debug("0i_actions", "247", GetName(oMonster) + "'s combat has ended!"); + return; +} +void ai_StartMonsterCombat(object oMonster) +{ + if(AI_DEBUG) ai_Debug("0i_actions", "264", "---------- " + GetName(oMonster) + " is starting combat! ----------"); + ai_SetCreatureTalents(oMonster, TRUE); + ai_DoMonsterCombatRound(oMonster); +} +float ai_GetFollowDistance(object oCreature) +{ + // Also check for size of creature and adjust based on that. + float fDistance = StringToFloat(Get2DAString("appearance", "PREFATCKDIST", GetAppearanceType(oCreature))); + return GetLocalFloat(oCreature, AI_FOLLOW_RANGE) + fDistance; +} +int ai_StayClose(object oCreature) +{ + if(ai_GetIsCharacter(oCreature) || + ai_GetAIMode(oCreature, AI_MODE_STAND_GROUND) || + GetLocalString(oCreature, AI_COMBAT_SCRIPT) == "ai_a_peaceful" || + GetLocalString(oCreature, AI_COMBAT_SCRIPT) == "ai_coward") return FALSE; + object oMaster = GetMaster(oCreature); + // We stay within our perception range of who we are following. + float fPerceptionDistance = GetLocalFloat(oCreature, AI_ASSOC_PERCEPTION_DISTANCE); + if(fPerceptionDistance == 0.0) + { + fPerceptionDistance = GetLocalFloat(oMaster, AI_ASSOC_PERCEPTION_DISTANCE); + if(fPerceptionDistance == 0.0) fPerceptionDistance = 20.0; + } + object oTarget = GetLocalObject(oCreature, AI_FOLLOW_TARGET); + if(oTarget == OBJECT_INVALID) oTarget = oMaster; + if(AI_DEBUG) ai_Debug("0i_associates", "214", "Distance from who we are following in combat." + + " oFollowing: " + FloatToString(GetDistanceBetween(oTarget, oCreature), 0, 2) + " fPerceptionDistance: " + FloatToString(fPerceptionDistance, 0, 2)); + if(GetDistanceBetween(oTarget, oCreature) < fPerceptionDistance) return FALSE; + ai_ClearCreatureActions(); + if(AI_DEBUG) ai_Debug("0i_associates", "218", "We are too far away! Move back to our master."); + ActionMoveToObject(oTarget, TRUE, ai_GetFollowDistance(oCreature)); + return TRUE; +} +int ai_TryToBecomeInvisible(object oCreature) +{ + // If we are invisible then we don't need to check this. + if(!ai_GetIsHidden(oCreature)) return FALSE; + // If we are not invisible lets try. + int nDarkness; + if(GetHasSpell(SPELL_DARKNESS, oCreature) && ai_GetHasEffectType(oCreature, EFFECT_TYPE_ULTRAVISION)) nDarkness = TRUE; + if(GetHasSpell(SPELL_IMPROVED_INVISIBILITY, oCreature) || GetHasSpell(SPELL_INVISIBILITY, oCreature) || + GetHasSpell(SPELL_INVISIBILITY_SPHERE, oCreature) ||(nDarkness) || + GetHasSpell(SPELL_SANCTUARY, oCreature) || GetHasSpell(SPELL_ETHEREALNESS, oCreature) || + GetHasSpell(799/*SPELLABILITY_VAMPIRE_INVISIBILITY*/) || + GetHasFeat(FEAT_HIDE_IN_PLAIN_SIGHT, oCreature) == TRUE) + { + // This bit ported directly from Jasperre + // Can anyone see me?(has spell effects of X) + // The point of this is to see if its even worthwhile to go invisbile + // or will it be immediately dispeled. + object oSeeMe = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, oCreature, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN, CREATURE_TYPE_HAS_SPELL_EFFECT, SPELL_TRUE_SEEING); + if(oSeeMe == OBJECT_INVALID) + { + oSeeMe = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, oCreature, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN, CREATURE_TYPE_HAS_SPELL_EFFECT, SPELL_SEE_INVISIBILITY); + } + if(oSeeMe == OBJECT_INVALID) + { + // Check non-invisibility options first. Since they can be used + // while near enemies. + if(GetHasFeat(FEAT_HIDE_IN_PLAIN_SIGHT, oCreature)) + { + // Go into stealth mode + SetActionMode(oCreature, ACTION_MODE_STEALTH, TRUE); + if(AI_DEBUG) ai_Debug("0i_actions", "207", "Using HIDE_IN_PLAIN_SIGHT!"); + return TRUE; + } + if(nDarkness) + { + ai_SetLastAction(oCreature, SPELL_DARKVISION); + ActionCastSpellAtObject(SPELL_DARKVISION, oCreature); + return TRUE; + } + if(GetHasSpell(SPELL_ETHEREALNESS, oCreature)) + { + ai_SetLastAction(oCreature, SPELL_ETHEREALNESS); + ActionCastSpellAtObject(SPELL_ETHEREALNESS, oCreature); + return TRUE; + } + if(GetHasSpell(SPELL_SANCTUARY, oCreature)) + { + ai_SetLastAction(oCreature, SPELL_SANCTUARY); + ActionCastSpellAtObject(SPELL_SANCTUARY, oCreature); + return TRUE; + } + // Get the nearest Enemy and how close they are. + // Use this to keep invisibility from being spammed in melee. + object oEnemy = ai_GetNearestEnemy(oCreature); + if(GetDistanceBetween(oCreature, oEnemy) > AI_RANGE_MELEE) + { + if(GetHasSpell(SPELL_IMPROVED_INVISIBILITY, oCreature)) + { + ai_SetLastAction(oCreature, SPELL_IMPROVED_INVISIBILITY); + ActionCastSpellAtObject(SPELL_IMPROVED_INVISIBILITY, oCreature); + return TRUE; + } + if(GetHasSpell(SPELL_INVISIBILITY, oCreature)) + { + ai_SetLastAction(oCreature, SPELL_INVISIBILITY); + ActionCastSpellAtObject(SPELL_INVISIBILITY, oCreature); + return TRUE; + } + if(GetHasSpell(SPELL_INVISIBILITY_SPHERE, oCreature)) + { + ai_SetLastAction(oCreature, SPELL_INVISIBILITY_SPHERE); + ActionCastSpellAtObject(SPELL_INVISIBILITY_SPHERE, oCreature); + return TRUE; + } + if(GetHasSpell(799/*SPELLABILITY_VAMPIRE_INVISIBILITY*/, oCreature)) + { + ai_SetLastAction(oCreature, 799/*SPELLABILITY_VAMPIRE_INVISIBILITY*/); + ActionCastSpellAtObject(799/*SPELLABILITY_VAMPIRE_INVISIBILITY*/, oCreature); + return TRUE; + } + } + } + } + return FALSE; +} +int ai_SearchForHiddenCreature(object oCreature, int bMonster, object oInvisible = OBJECT_INVALID, float fRange = 1.0) +{ + if(AI_DEBUG) ai_Debug("0i_actions", "358", GetName(oCreature) + " is searching for an invisible creature (" + + GetName(oInvisible) + ")."); + if(oInvisible == OBJECT_INVALID) + { + // Have we seen anyone go invisible? + oInvisible = GetLocalObject(oCreature, AI_IS_INVISIBLE); + if(oInvisible == OBJECT_INVALID || GetIsDead(oInvisible)) + { + oInvisible = ai_GetNearestEnemy(oCreature, 1, 7, PERCEPTION_HEARD_AND_NOT_SEEN); + if(oInvisible == OBJECT_INVALID) oInvisible = ai_GetNearestEnemy(oCreature); + } + } + float fPerceptionDistance, fDistance; + if(bMonster) + { + GetDistanceBetween(oCreature, oInvisible); + fPerceptionDistance = GetLocalFloat(GetModule(), AI_RULE_PERCEPTION_DISTANCE); + } + else + { + // We want to use the distance between the PC and target not us. + object oMaster = GetMaster(); + if(oMaster != OBJECT_INVALID) fDistance = GetDistanceBetween(oMaster, oInvisible); + else GetDistanceBetween(oCreature, oInvisible); + fPerceptionDistance = GetLocalFloat(oCreature, AI_ASSOC_PERCEPTION_DISTANCE); + if(fPerceptionDistance == 0.0) fPerceptionDistance = 20.0; + } + if(AI_DEBUG) ai_Debug("0i_actions", "383", "Is invisible: " + GetName(oInvisible) + + " fDistance: " + FloatToString(fDistance, 0, 2) + + " fPerceptionDistance: " + FloatToString(fPerceptionDistance, 0, 2)); + // Might need to end combat at this point? + if(fDistance > fPerceptionDistance) return FALSE; + // If we are close enough then lets look for them. + if(fDistance < AI_RANGE_LONG) + { + // nHidden 1 = Invisible effects, 2 = Darkness effects, 3 = Sanctuary effects, 4 Stealth. + int nHidden = ai_GetIsHidden(oInvisible); + if(nHidden) + { + // They have a magical effect! Is there a spell we can use to see? + if(nHidden < 4) + { + if(AI_DEBUG) ai_Debug("0i_actions", "399", " They are using magic to hide: " + + IntToString(nHidden)); + // True Seeing pierces all types of magical hiding. + if(GetHasSpell(SPELL_TRUE_SEEING, oCreature)) + { + ai_SetLastAction(oCreature, SPELL_TRUE_SEEING); + ActionCastSpellAtObject(SPELL_TRUE_SEEING, oCreature); + return TRUE; + } + if(nHidden == 1 || nHidden == 3) // Invisibility or Ethereal effect. + { + if(GetHasSpell(SPELL_SEE_INVISIBILITY, oCreature)) + { + ai_SetLastAction(oCreature, SPELL_SEE_INVISIBILITY); + ActionCastSpellAtObject(SPELL_SEE_INVISIBILITY, oCreature); + return TRUE; + } + if(GetHasSpell(SPELL_INVISIBILITY_PURGE, oCreature)) + { + ai_SetLastAction(oCreature, SPELL_INVISIBILITY_PURGE); + ActionCastSpellAtObject(SPELL_INVISIBILITY_PURGE, oCreature); + return TRUE; + } + } + if(nHidden == 2) // Darkness spell effect. + { + if(GetHasSpell(SPELL_DARKVISION)) + { + ai_SetLastAction(oCreature, SPELL_DARKVISION); + ActionCastSpellAtObject(SPELL_DARKVISION, oCreature); + return TRUE; + } + } + // To be able to attack a magically hidden foe we have to be + // with in melee attack range. Cannot hear Ethereal foes! + // We will automatically hear them once we are within range. + // We also walk so we don't give attacks of opportunity. + if(nHidden < 3) + { + if(AI_DEBUG) ai_Debug("0i_actions", "437", " We have no spells to counter with. Moving up to attack!"); + SetLocalInt(oCreature, AI_AM_I_SEARCHING, TRUE); + ActionMoveToObject(oInvisible); + ActionDoCommand(DeleteLocalInt(oCreature, AI_AM_I_SEARCHING)); + if(ai_GetIsInCombat(oCreature)) ActionDoCommand(ExecuteScript("0e_do_combat_rnd", oCreature)); + return TRUE; + } + } + else // They are using stealth! + { + if(AI_DEBUG) ai_Debug("0i_actions", "447", " Using Detect mode and moving up."); + SetActionMode(oCreature, ACTION_MODE_DETECT, TRUE); + SetLocalInt(oCreature, AI_AM_I_SEARCHING, TRUE); + // We use to move to the object but that is creepy! + //ActionMoveToObject(oInvisible, FALSE, fRange); + ActionMoveToLocation(GetLocation(oInvisible), FALSE); + ActionDoCommand(DeleteLocalInt(oCreature, AI_AM_I_SEARCHING)); + if(ai_GetIsInCombat(oCreature)) ActionDoCommand(ExecuteScript("0e_do_combat_rnd", oCreature)); + return TRUE; + } + } + else // They are not hidden, then that means we can hear them but not see them. + // Probably behind a wall or door. + { + SetLocalInt(oCreature, AI_AM_I_SEARCHING, TRUE); + // We use to move to the object but that is creepy! + //ActionMoveToObject(oInvisible, FALSE, fRange); + ActionMoveToLocation(GetLocation(oInvisible), FALSE); + ActionDoCommand(DeleteLocalInt(oCreature, AI_AM_I_SEARCHING)); + if(ai_GetIsInCombat(oCreature)) ActionDoCommand(ExecuteScript("0e_do_combat_rnd", oCreature)); + return TRUE; + } + } + else // We need to get closer to start looking for them. + { + if(AI_DEBUG) ai_Debug("0i_actions", "469", "Moving towards invisible creature from a distance: " + GetName(oInvisible)); + SetLocalInt(oCreature, AI_AM_I_SEARCHING, TRUE); + // We use to move to the object but that is creepy! + //ActionMoveToObject(oInvisible, TRUE, 14.0); + ActionMoveToLocation(GetLocation(oInvisible), FALSE); + AssignCommand(oCreature, ActionDoCommand(DeleteLocalInt(oCreature, AI_AM_I_SEARCHING))); + if(ai_GetIsInCombat(oCreature)) ActionDoCommand(ExecuteScript("0e_do_combat_rnd", oCreature)); + return TRUE; + } + return FALSE; +} +int ai_MoralCheck(object oCreature) +{ + // If we are immune to fear then we are immune to MoralChecks! + // Constructs and Undead are also immune to fear. + int nRaceType = GetRacialType(oCreature); + if(!GetLocalInt(GetModule(), AI_RULE_MORAL_CHECKS) || GetIsImmune(oCreature, IMMUNITY_TYPE_FEAR) || + nRaceType == RACIAL_TYPE_UNDEAD || + nRaceType == RACIAL_TYPE_CONSTRUCT || + ai_GetIsCharacter(oCreature)) return FALSE; + // Moral DC is AI_WOUNDED_MORAL_DC - The number of allies. + // or AI_BLOODY_MORAL_DC - number of allies. + int nDC; + int nHpPercent = ai_GetPercHPLoss(oCreature); + object oNearestEnemy = GetLocalObject(oCreature, AI_ENEMY_NEAREST); + // We only make moral checks if we are below half hitpoints and the Difficulty should be adjusted to -10 at 0. + if(nHpPercent <= AI_HEALTH_WOUNDED) + { + // Debug code to look for multiple moral checks at once by one creature? + if(GetLocalString(GetModule(), AI_RULE_DEBUG_CREATURE) == "") + { + SetLocalString(GetModule(), AI_RULE_DEBUG_CREATURE, GetName(oCreature)); + ai_Debug("0i_actions", "424", GetName(oCreature) + " starting debug mode to test Moral checks!"); + } + if(nHpPercent <= AI_HEALTH_BLOODY) nDC = AI_BLOODY_MORAL_DC; + else nDC = AI_WOUNDED_MORAL_DC; + nDC = nDC - GetLocalInt(oCreature, AI_ALLY_NUMBERS); + if(nDC < 1) nDC = 1; + if(AI_DEBUG) ai_Debug("0i_talents", "367", "Moral check DC: " + IntToString(nDC) + "."); + //SendMessageToPC(GetFirstPC(), "0i_talents, 431, " + GetName(oCreature) + " Moral check DC: " + IntToString(nDC) + "."); + if(!WillSave(oCreature, nDC, SAVING_THROW_TYPE_FEAR, oNearestEnemy)) + { + if(AI_DEBUG) ai_Debug("0i_talents", "370", "Moral check failed, we are fleeing!"); + SetLocalString(oCreature, AI_COMBAT_SCRIPT, "ai_coward"); + effect eVFX = EffectVisualEffect(VFX_DUR_MIND_AFFECTING_FEAR); + ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eVFX, oCreature, 6.0f); + ActionMoveAwayFromObject(oNearestEnemy, TRUE, AI_RANGE_LONG); + if(!ai_GetAIMode(oCreature, AI_MODE_DO_NOT_SPEAK)) + { + int nRoll = d4(); + if(nRoll == 1) PlayVoiceChat(VOICE_CHAT_FLEE, oCreature); + else if(nRoll == 2) PlayVoiceChat(VOICE_CHAT_GUARDME, oCreature); + else if(nRoll == 3) PlayVoiceChat(VOICE_CHAT_HELP, oCreature); + else if(nRoll == 4 && nHpPercent < 100) PlayVoiceChat(VOICE_CHAT_HEALME, oCreature); + } + return TRUE; + } + if(nDC >= 11 && !ai_GetAIMode(oCreature, AI_MODE_DO_NOT_SPEAK)) + { + int nRoll = d6(); + // Cry out when you are overwhelmed! + if(nRoll == 1) PlayVoiceChat(VOICE_CHAT_CUSS, oCreature); + else if(nRoll == 2) PlayVoiceChat(VOICE_CHAT_BADIDEA, oCreature); + else if(nRoll == 3) PlayVoiceChat(VOICE_CHAT_ENEMIES, oCreature); + } + } + return FALSE; +} +int ai_GetInAOEReaction(object oCreature, object oCaster, int nSpell) +{ + switch(nSpell) + { + case SPELL_ACID_FOG: + case SPELL_CLOUDKILL: + case SPELL_CREEPING_DOOM: + { + // Nothing but bad times with these spells. + return TRUE; + } + case SPELL_STORM_OF_VENGEANCE: + { + // This only harms our enemies! + return (oCaster != oCreature && GetIsEnemy(oCaster, oCreature)); + } + // They should only flee Silence if they want to cast a spell! + //case SPELL_SILENCE: + case SPELL_BLADE_BARRIER: + case SPELL_WALL_OF_FIRE: + case SPELL_INCENDIARY_CLOUD: + { + // Check reflex feats and saves. + return (!GetHasFeat(FEAT_EVASION, oCreature) && + !GetHasFeat(FEAT_IMPROVED_EVASION, oCreature) && + GetReflexSavingThrow(oCreature) < 21 + d6()); + } + case SPELL_STINKING_CLOUD: + { + // Do we have a high fortitude save? 20 + 5 + return (GetFortitudeSavingThrow(oCreature) < 20 + d6()); + } + case SPELL_GREASE: + case SPELL_ENTANGLE: + case SPELL_VINE_MINE_ENTANGLE: + case SPELL_WEB: + { + // Do we have a high reflex save? d20 + 1 + return (!GetHasFeat(FEAT_WOODLAND_STRIDE, oCreature) && + !GetLocalInt(oCreature, "X2_L_IS_INCORPOREAL") && + GetReflexSavingThrow(oCreature) < 15 + d6()); + } + case SPELL_EVARDS_BLACK_TENTACLES: + { + // Small creatures are immune and can they hit me? d20 + 8 + caster lvl(7) + return (GetCreatureSize(oCreature) > 2 && + GetAC(oCreature) < 30 + d6()); + } + case SPELL_CLOUD_OF_BEWILDERMENT: + { + // Do we have a high fortitude save? 20 + 2 + return (GetFortitudeSavingThrow(oCreature) < 17 + d6()); + } + case SPELL_MIND_FOG: + case SPELL_STONEHOLD: + { + // Do we have a high enough will save? 20 + 6 + return (GetWillSavingThrow(oCreature) < 21 + d6()); + } + case SPELL_SPIKE_GROWTH: + case SPELL_VINE_MINE_HAMPER_MOVEMENT: + { + // Do we have a high reflex save? d20 + 3 + return (GetReflexSavingThrow(oCreature) < 18 + d6()); + } + } + return FALSE; +} +void ai_HaveCreatureSpeak(object oCreature, int nRoll, string sVoiceChatArray, int bImportant = FALSE) +{ + if(ai_GetAIMode(oCreature, AI_MODE_DO_NOT_SPEAK) && !bImportant) return; + if(nRoll == 0) + { + // Some races shouldn't talk. + int nRacialType = GetRacialType(oCreature); + if(nRacialType == RACIAL_TYPE_ANIMAL || nRacialType == RACIAL_TYPE_BEAST || + nRacialType == RACIAL_TYPE_MAGICAL_BEAST || nRacialType == RACIAL_TYPE_OOZE || + nRacialType == RACIAL_TYPE_UNDEAD || nRacialType == RACIAL_TYPE_VERMIN) return; + SpeakString(sVoiceChatArray); + return; + } + nRoll = Random(nRoll); + string sVoice = ai_GetStringArray(sVoiceChatArray, nRoll); + if(sVoice != "") PlayVoiceChat(StringToInt(sVoice), oCreature); +} +int ai_CheckForAssociateSpellTalent(object oAssociate, int nInMelee, int nMaxLevel, int nRound = 0) +{ + // ******************* 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(oAssociate, AI_MAGIC_DEFENSIVE_CASTING)) + { + if(ai_UseCreatureTalent(oAssociate, AI_TALENT_INDISCRIMINANT_AOE, nInMelee, nMaxLevel)) return TRUE; + if(ai_UseCreatureTalent(oAssociate, AI_TALENT_DISCRIMINANT_AOE, nInMelee, nMaxLevel)) return TRUE; + } + if(ai_GetMagicMode(oAssociate, AI_MAGIC_OFFENSIVE_CASTING)) return FALSE; + // ********** PROTECTION/ENHANCEMENT/SUMMON TALENTS ************ + // Does our master want to be buffed first? + object oTarget = OBJECT_INVALID; + if(ai_GetMagicMode(oAssociate, AI_MAGIC_BUFF_MASTER)) oTarget = GetMaster(oAssociate); + return ai_TryDefensiveTalents(oAssociate, nInMelee, nMaxLevel, nRound, oTarget); +} +void ai_DoPhysicalAttackOnBest(object oCreature, int nInMelee, int bAlwaysAtk = TRUE) +{ + talent tUse; + object oTarget; + if(AI_DEBUG) ai_Debug("0i_actions", "496", "Check for ranged attack on nearest 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) 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("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("0i_actions", "525", "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) oTarget = ai_GetBestTargetForMeleeCombat(oCreature, nInMelee, bAlwaysAtk); + // 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("0i_actions", "536", "Do melee attack against nearest: " + GetName(oTarget) + "!"); + ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); + } + else ai_SearchForHiddenCreature(oCreature, TRUE); +} +void ai_DoPhysicalAttackOnNearest(object oCreature, int nInMelee, int bAlwaysAtk = TRUE) +{ + talent tUse; + object oTarget; + if(AI_DEBUG) ai_Debug("0i_actions", "496", "Check for ranged attack on nearest 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) oTarget = ai_GetNearestTarget(oCreature); + } + else + { + if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); + if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature, AI_RANGE_MELEE); + if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestTarget(oCreature, AI_RANGE_MELEE); + } + if(oTarget != OBJECT_INVALID) + { + 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("0i_actions", "525", "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) oTarget = ai_GetNearestTargetForMeleeCombat(oCreature, nInMelee, bAlwaysAtk); + // 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("0i_actions", "536", "Do melee attack against nearest: " + GetName(oTarget) + "!"); + ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); + } + else ai_SearchForHiddenCreature(oCreature, TRUE); +} +void ai_DoPhysicalAttackOnLowestCR(object oCreature, int nInMelee, int bAlwaysAtk = TRUE) +{ + if(AI_DEBUG) ai_Debug("0i_actions", "533", "Check for ranged attack on weakest enemy!"); + object oTarget; + // ************************** 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("0i_actions", "559", GetName(OBJECT_SELF) + " does ranged attack on weakest: " + GetName(oTarget) + "!"); + ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE); + return; + } + else + { + ai_SearchForHiddenCreature(oCreature, FALSE); + return; + } + } + else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return; + } + if(AI_DEBUG) ai_Debug("0i_actions", "571", "Check for melee attack on weakest enemy!"); + // ************************** Melee feat attacks ************************* + if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return; + if(ai_TrySneakAttack(oCreature, nInMelee, bAlwaysAtk)) return; + if(ai_TryWhirlwindFeat(oCreature)) return; + if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); + if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature, AI_RANGE_PERCEPTION, bAlwaysAtk); + if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTargetForMeleeCombat(oCreature, nInMelee, bAlwaysAtk); + if(oTarget != OBJECT_INVALID) + { + if(ai_TryMeleeTalents(oCreature, oTarget)) return; + if(AI_DEBUG) ai_Debug("0i_actions", "577", GetName(OBJECT_SELF) + " does melee attack against weakest: " + GetName(oTarget) + "!"); + ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); + } + else ai_SearchForHiddenCreature(oCreature, FALSE); +} +int ai_InCombatEquipBestMeleeWeapon(object oCreature) +{ + if(ai_GetIsMeleeWeapon(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oCreature))) return FALSE; + if(ai_EquipBestMeleeWeapon(oCreature)) + { + // We delay 1 second since ActionEquip is not an action we can check for. + // This keeps event scripts from clearing before we actually equip. + SetLocalInt(oCreature, AI_COMBAT_WAIT_IN_SECONDS, 2); + ActionDoCommand(ExecuteScript("0e_do_combat_rnd", oCreature)); + return TRUE; + } + return FALSE; +} +int ai_InCombatEquipBestRangedWeapon(object oCreature) +{ + if(ai_EquipBestRangedWeapon(oCreature)) + { + // We delay 1 second since ActionEquip is not an action we can check for. + // This keeps event scripts from clearing before we actually equip. + SetLocalInt(oCreature, AI_COMBAT_WAIT_IN_SECONDS, 1); + ActionDoCommand(ExecuteScript("0e_do_combat_rnd", oCreature)); + return TRUE; + } + return FALSE; +} +int ai_CheckItemForHealing(object oCreature, object oTarget, object oItem, int nHpLost, int bEquiped = FALSE) +{ + if(AI_DEBUG) ai_Debug("0i_actions", "629", "Checking Item properties on " + GetName(oItem)); + int nIprpSubType, nSpell, nLevel, nIPType; + itemproperty ipProp = GetFirstItemProperty(oItem); + // Lets skip this if there are no properties. + if(!GetIsItemPropertyValid(ipProp)) return FALSE; + // Check for cast spell property and add them to the talent list. + int nIndex; + ipProp = GetFirstItemProperty(oItem); + while(GetIsItemPropertyValid(ipProp)) + { + if(AI_DEBUG) ai_Debug("0i_actions", "639", "ItempropertyType(15): " + IntToString(GetItemPropertyType(ipProp))); + nIPType = GetItemPropertyType(ipProp); + if(nIPType == ITEM_PROPERTY_CAST_SPELL) + { + nIprpSubType = GetItemPropertySubType(ipProp); + nSpell = StringToInt(Get2DAString("iprp_spells", "SpellIndex", nIprpSubType)); + if(ai_ShouldWeCastThisCureSpell(nSpell, nHpLost)) + { + // We have established that we can use the item if it is equiped. + if(!bEquiped) ai_CheckIfCanUseItem(oCreature, oItem); + // Get how they use the item (charges or uses per day). + int nUses = GetItemPropertyCostTableValue(ipProp); + if(nUses > 1 && nUses < 7) + { + int nCharges = GetItemCharges(oItem); + if(AI_DEBUG) ai_Debug("0i_actions", "654", "Item charges: " + IntToString(nCharges)); + if(nUses == 6 && nCharges < 1 || nUses == 5 && nCharges < 3 || + nUses == 4 && nCharges < 5 || nUses == 3 && nCharges < 7 || + nUses == 2 && nCharges < 9) return FALSE; + } + else if(nUses > 7 && nUses < 13) + { + int nPerDay = GetItemPropertyUsesPerDayRemaining(oItem, ipProp); + if(AI_DEBUG) ai_Debug("0i_actions", "662", "Item uses: " + IntToString(nPerDay)); + if(nPerDay == 0) return FALSE; + } + // SubType is the ip spell index for iprp_spells.2da + nIprpSubType = GetItemPropertySubType(ipProp); + if(AI_DEBUG) ai_Debug("0i_actions", "667", GetName(oCreature) + " is using " + GetName(oItem) + " on " + GetName(oTarget) + "."); + ActionUseItemOnObject(oItem, ipProp, oTarget, nIprpSubType); + return TRUE; + } + } + nIndex++; + ipProp = GetNextItemProperty(oItem); + } + return FALSE; +} +int ai_HealSickness(object oCreature, object oTarget, object oPC, int nSickness, int bForce = FALSE) +{ + // If the player is not forcing a check. + if(!bForce) + { + // Is Casting Cure spells off? + if(ai_GetMagicMode(oCreature, AI_MAGIC_CURE_SPELLS_OFF)) return FALSE; + // Do we have no magic on? + if(ai_GetMagicMode(oCreature, AI_MAGIC_NO_MAGIC)) return FALSE; + // Should we ignore associates? + if(ai_GetAIMode(oCreature, AI_MODE_IGNORE_ASSOCIATES) && + GetAssociateType(oTarget) > 1) return FALSE; + } + // Check for spells. + if(nSickness == AI_ALLY_IS_DISEASED) + { + if(AI_DEBUG) ai_Debug("0i_actions", "717", "Attempting to remove disease."); + if(ai_CheckAndCastSpell(oCreature, SPELL_REMOVE_DISEASE, 0, 0.0, oTarget)) return TRUE; + } + else if(nSickness == AI_ALLY_IS_POISONED) + { + if(AI_DEBUG) ai_Debug("0i_actions", "726", "Attempting to remove poison."); + if(ai_CheckAndCastSpell(oCreature, SPELL_NEUTRALIZE_POISON, 0, 0.0, oTarget)) return TRUE; + } + else if(nSickness == AI_ALLY_IS_WEAK) + { + if(AI_DEBUG) ai_Debug("0i_actions", "735", "Attempting to remove ability score drain."); + if(ai_CheckAndCastSpell(oCreature, SPELL_LESSER_RESTORATION, 0, 0.0, oTarget)) return TRUE; + if(ai_CheckAndCastSpell(oCreature, SPELL_RESTORATION, 0, 0.0, oTarget)) return TRUE; + if(ai_CheckAndCastSpell(oCreature, SPELL_GREATER_RESTORATION, 0, 0.0, oTarget)) return TRUE; + } + else return FALSE; + // Check for healing kits. + if(!GetLocalInt(GetModule(), AI_RULE_HEALERSKITS)) return FALSE; + int nIprpSubType, nSpell; + itemproperty ipProp; + object oItem = GetFirstItemInInventory(oCreature); + while(oItem != OBJECT_INVALID) + { + if(GetIdentified(oItem)) + { + int nBaseItemType = GetBaseItemType(oItem); + if(nBaseItemType == BASE_ITEM_HEALERSKIT && + (nSickness == AI_ALLY_IS_DISEASED || + nSickness == AI_ALLY_IS_POISONED)) + { + ipProp = GetFirstItemProperty(oItem); + while(GetIsItemPropertyValid(ipProp)) + { + if(GetItemPropertyType(ipProp) == ITEM_PROPERTY_HEALERS_KIT) + { + if(AI_DEBUG) ai_Debug("0i_actions", "772", "Attempting to remove (" + IntToString(nSickness) + ") with a healing kit."); + if(ai_GetIsCharacter(oPC)) ai_SendMessages(GetName(oCreature) + " uses " + GetName(oItem) + " on " + GetName(oTarget) + ".", AI_COLOR_YELLOW, oPC); + ActionUseItemOnObject(oItem, ipProp, oTarget); + return TRUE; + } + ipProp = GetNextItemProperty(oItem); + } + } + else if(nBaseItemType == BASE_ITEM_POTIONS || + nBaseItemType == BASE_ITEM_ENCHANTED_POTION || + nBaseItemType == FEAT_BREW_POTION) + { + ipProp = GetFirstItemProperty(oItem); + while(GetIsItemPropertyValid(ipProp)) + { + nIprpSubType = GetItemPropertySubType(ipProp); + nSpell = StringToInt(Get2DAString("iprp_spells", "SpellIndex", nIprpSubType)); + if(AI_DEBUG) ai_Debug("0i_actions", "789", "Checking potion, " + IntToString(nSpell)); + if(nSpell == SPELL_REMOVE_DISEASE && nSickness == AI_ALLY_IS_DISEASED) + { + if(AI_DEBUG) ai_Debug("0i_actions", "786", "Using a potion of Remove Disease."); + ActionUseItemOnObject(oItem, ipProp, oTarget); + return TRUE; + } + if(nSpell == SPELL_NEUTRALIZE_POISON && nSickness == AI_ALLY_IS_POISONED) + { + if(AI_DEBUG) ai_Debug("0i_actions", "786", "Using a potion of Neturalize Poison."); + ActionUseItemOnObject(oItem, ipProp, oTarget); + return TRUE; + } + if(nSpell == SPELL_LESSER_RESTORATION && nSickness == AI_ALLY_IS_WEAK) + { + if(AI_DEBUG) ai_Debug("0i_actions", "781", "Using a potion of Lesser Restoration."); + ActionUseItemOnObject(oItem, ipProp, oTarget); + return TRUE; + } + if(nSpell == SPELL_RESTORATION && nSickness == AI_ALLY_IS_WEAK) + { + if(AI_DEBUG) ai_Debug("0i_actions", "791", "Using a potion of Restoration."); + ActionUseItemOnObject(oItem, ipProp, oTarget); + return TRUE; + } + ipProp = GetNextItemProperty(oItem); + } + } + else if(nBaseItemType == BASE_ITEM_SCROLL || + nBaseItemType == BASE_ITEM_ENCHANTED_SCROLL || + nBaseItemType == BASE_ITEM_SPELLSCROLL || + nBaseItemType == BASE_ITEM_ENCHANTED_WAND || + nBaseItemType == BASE_ITEM_MAGICWAND || + nBaseItemType == BASE_ITEM_MAGICSTAFF) + { + if(ai_CheckIfCanUseItem(oCreature, oItem)) + { + ipProp = GetFirstItemProperty(oItem); + while(GetIsItemPropertyValid(ipProp)) + { + nSpell = StringToInt(Get2DAString("iprp_spells", "SpellIndex", nIprpSubType)); + if(nSpell == SPELL_REMOVE_DISEASE && nSickness == AI_ALLY_IS_DISEASED) + { + if(AI_DEBUG) ai_Debug("0i_actions", "786", "Using a potion of Remove Disease."); + ActionUseItemOnObject(oItem, ipProp, oTarget); + return TRUE; + } + if(nSpell == SPELL_NEUTRALIZE_POISON && nSickness == AI_ALLY_IS_POISONED) + { + if(AI_DEBUG) ai_Debug("0i_actions", "786", "Using a potion of Neturalize Poison."); + ActionUseItemOnObject(oItem, ipProp, oTarget); + return TRUE; + } + if(nSpell == SPELL_LESSER_RESTORATION && nSickness == AI_ALLY_IS_WEAK) + { + if(AI_DEBUG) ai_Debug("0i_actions", "781", "Using a potion of Lesser Restoration."); + ActionUseItemOnObject(oItem, ipProp, oTarget); + return TRUE; + } + if(nSpell == SPELL_RESTORATION && nSickness == AI_ALLY_IS_WEAK) + { + if(AI_DEBUG) ai_Debug("0i_actions", "791", "Using a potion of Restoration."); + ActionUseItemOnObject(oItem, ipProp, oTarget); + return TRUE; + } + ipProp = GetNextItemProperty(oItem); + } + } + } + } + oItem = GetNextItemInInventory(oCreature); + } + return FALSE; +} +int ai_UseHealingItem(object oCreature, object oTarget, object oPC) +{ + if(ai_GetMagicMode(oCreature, AI_MAGIC_NO_MAGIC_ITEMS)) return FALSE; + string sSlots; + int nDamage = GetMaxHitPoints(oTarget) - GetCurrentHitPoints(oTarget); + itemproperty ipProp; + // Cycle through all the creatures equiped items. + int nSlot; + object oItem = GetItemInSlot(nSlot, oCreature); + while(nSlot < 11) + { + if(oItem != OBJECT_INVALID && + ai_CheckItemForHealing(oCreature, oTarget, oItem, nDamage, TRUE)) return TRUE; + oItem = GetItemInSlot(++nSlot, oCreature); + } + oItem = GetFirstItemInInventory(oCreature); + while(oItem != OBJECT_INVALID) + { + if(GetIdentified(oItem)) + { + // Does the item need to be equiped to use its powers? + sSlots = Get2DAString("baseitems", "EquipableSlots", GetBaseItemType(oItem)); + if(AI_DEBUG) ai_Debug("0i_actions", "696", GetName(oItem) + " requires " + Get2DAString("baseitems", "EquipableSlots", GetBaseItemType(oItem)) + " slots."); + if(sSlots == "0x00000") + { + int nBaseItemType = GetBaseItemType(oItem); + // Lets not use up our healing kits on minor damage. + if(nBaseItemType == BASE_ITEM_HEALERSKIT) + { + if(!GetLocalInt(GetModule(), AI_RULE_HEALERSKITS)) return FALSE; + ipProp = GetFirstItemProperty(oItem); + if(GetItemPropertyType(ipProp) == ITEM_PROPERTY_HEALERS_KIT) + { + if(ai_GetIsCharacter(oPC)) ai_SendMessages(GetName(oCreature) + " uses " + GetName(oItem) + " on " + GetName(oTarget) + ".", AI_COLOR_YELLOW, oPC); + ActionUseItemOnObject(oItem, ipProp, oTarget); + return TRUE; + } + } + // Do we want Player AI and Associates to use potions on others? + //else if(nBaseItemType == BASE_ITEM_ENCHANTED_POTION || + // nBaseItemType == BASE_ITEM_POTIONS) + //{ + // if(oCaster == oTarget) + // { + // if(ai_CheckItemForHealing(oCreature, oTarget, oItem, nDamage)) return TRUE; + // } + //} + else if(ai_CheckItemForHealing(oCreature, oTarget, oItem, nDamage)) return TRUE; + } + } + oItem = GetNextItemInInventory(oCreature); + } + return FALSE; +} +void ai_ActionTryHealing(object oCreature, object oTarget) +{ + ai_TryHealing(oCreature, oTarget, TRUE); +} +int ai_TryHealing(object oCreature, object oTarget, int bForce = FALSE) +{ + if(AI_DEBUG) ai_Debug("0i_actions", "733", "Try healing: oCreature: " + GetName(oCreature) + + " oTarget: " + GetName(oTarget) + " No Party Healing: " + IntToString(ai_GetAIMode(oCreature, AI_MODE_PARTY_HEALING_OFF)) + + " No Self Healing: " + IntToString(ai_GetAIMode(oCreature, AI_MODE_SELF_HEALING_OFF)) + + " AI_I_AM_BEING_HEALED: " + IntToString(GetLocalInt(oTarget, "AI_I_AM_BEING_HEALED")) + + " Undead: " + IntToString(GetRacialType(oTarget) == RACIAL_TYPE_UNDEAD)); + // If the player is not forcing a check. + if(!bForce) + { + // Should we ignore associates? + if(ai_GetAIMode(oCreature, AI_MODE_IGNORE_ASSOCIATES) && + GetAssociateType(oTarget) > 1) return FALSE; + } + // Limits the number of times a wounded creature will ask for help. + if(GetLocalInt(oCreature, "AI_WOUNDED_SHOUT_LIMIT") > 3) return FALSE; + // This keeps everyone from healing the same character in one round and over healing! + if(oCreature == oTarget) DeleteLocalInt(oTarget, "AI_I_AM_BEING_HEALED"); + else if(GetLocalInt(oTarget, "AI_I_AM_BEING_HEALED")) return FALSE; + if(ai_GetAIMode(oCreature, AI_MODE_PARTY_HEALING_OFF) && + oCreature != oTarget) return FALSE; + if(ai_GetAIMode(oCreature, AI_MODE_SELF_HEALING_OFF) && + oCreature == oTarget) return FALSE; + // Undead don't heal so lets skip this for them, maybe later we can fix this. + if(GetRacialType(oTarget) == RACIAL_TYPE_UNDEAD) return FALSE; + int nHpLost = ai_GetPercHPLoss(oTarget); + if(bForce && nHpLost < 100) nHpLost = 0; + if(AI_DEBUG) ai_Debug("0i_actions", "743", "nHpLost: " + IntToString(nHpLost) + + " limit: " + IntToString(ai_GetHealersHpLimit(oTarget, FALSE))); + if(nHpLost >= ai_GetHealersHpLimit(oTarget, FALSE)) + { + // Check to see if we need poison, disease, or ability drain removed. + int nEffectType; + effect eEffect = GetFirstEffect(oTarget); + while(GetIsEffectValid(eEffect)) + { + nEffectType = GetEffectType(eEffect); + if(AI_DEBUG) ai_Debug("0i_actions", "1094", "Checking to cure(31/32/39) nEffectType: " + IntToString(nEffectType)); + if(nEffectType == EFFECT_TYPE_DISEASE) + { + if(AI_DEBUG) ai_Debug("0i_actions", "1097", "I am diseased!"); + if(ai_HealSickness(oCreature, oTarget, ai_GetPlayerMaster(oCreature), AI_ALLY_IS_DISEASED, bForce)) return TRUE; + if(oCreature == oTarget) + { + if(!d20()) ai_HaveCreatureSpeak(oCreature, 5, ":43:4:14:15:16:"); + SpeakString(AI_I_AM_DISEASED, TALKVOLUME_SILENT_TALK); + } + } + else if(nEffectType == EFFECT_TYPE_POISON) + { + if(AI_DEBUG) ai_Debug("0i_actions", "1107", "I am poisoned!"); + if(ai_HealSickness(oCreature, oTarget, ai_GetPlayerMaster(oCreature), AI_ALLY_IS_POISONED, bForce)) return TRUE; + if(oCreature == oTarget) + { + if(!d20()) ai_HaveCreatureSpeak(oCreature, 6, ":43:4:14:15:16:19:"); + SpeakString(AI_I_AM_POISONED, TALKVOLUME_SILENT_TALK); + } + } + else if(nEffectType == EFFECT_TYPE_ABILITY_DECREASE) + { + if(AI_DEBUG) ai_Debug("0i_actions", "1117", "I am weak!"); + if(ai_HealSickness(oCreature, oTarget, ai_GetPlayerMaster(oCreature), AI_ALLY_IS_WEAK, bForce)) return TRUE; + if(oCreature == oTarget) + { + if(!d20()) ai_HaveCreatureSpeak(oCreature, 3, ":43:4:5:"); + SpeakString(AI_I_AM_WEAK, TALKVOLUME_SILENT_TALK); + } + } + eEffect = GetNextEffect(oTarget); + } + return FALSE; + } + // Do they have Lay on Hands? + if(GetHasFeat(FEAT_LAY_ON_HANDS, oCreature)) + { + int nCanHeal = GetAbilityModifier(ABILITY_CHARISMA, oCreature) * ai_GetCharacterLevels(oCreature); + if(nCanHeal <= nHpLost) + { + ai_UseFeat(oCreature, FEAT_LAY_ON_HANDS, oTarget); + return TRUE; + } + } + object oMaster = ai_GetPlayerMaster(oCreature); + // Do we have no magic on? + if(!ai_GetMagicMode(oCreature, AI_MAGIC_NO_MAGIC)) + { + int nClass, nPosition = 1; + string sMemorized; + while(nPosition <= AI_MAX_CLASSES_PER_CHARACTER) + { + nClass = GetClassByPosition(nPosition, oCreature); + if(AI_DEBUG) ai_Debug("0i_actions", "753", "nClass: " + IntToString(nClass)); + if(nClass == CLASS_TYPE_INVALID) break; + sMemorized = Get2DAString("classes", "MemorizesSpells", nClass); + // If Memorized column is "" then they are not a caster. + if(sMemorized != "") + { + if(sMemorized == "1") + { + if(ai_CastMemorizedHealing(oCreature, oTarget, oMaster, nClass)) + { + SetLocalInt(oTarget, "AI_I_AM_BEING_HEALED", TRUE); + return TRUE; + } + } + else if(ai_CastKnownHealing(oCreature, oTarget, oMaster, nClass)) + { + SetLocalInt(oTarget, "AI_I_AM_BEING_HEALED", TRUE); + return TRUE; + } + } + nPosition++; + } + } + // We have exhausted all attempts to use normal healing spells. + if(ai_UseHealingItem(oCreature, oTarget, oMaster)) + { + SetLocalInt(oTarget, "AI_I_AM_BEING_HEALED", TRUE); + return TRUE; + } + // Final attempt to heal oTarget, check for Spontaneous cure spells. + if(ai_CastSpontaneousCure(oCreature, oTarget, oMaster)) + { + SetLocalInt(oTarget, "AI_I_AM_BEING_HEALED", TRUE); + return TRUE; + } + // We can't heal ourselves! Can any of our allies? Lets ask. + if(oCreature == oTarget) + { + SetLocalInt(oCreature, "AI_WOUNDED_SHOUT_LIMIT", GetLocalInt(oCreature, "AI_WOUNDED_SHOUT_LIMIT") + 1); + SpeakString(AI_I_AM_WOUNDED, TALKVOLUME_SILENT_TALK); + } + return FALSE; +} +int ai_PerceiveEnemy(object oCreature, object oEnemy) +{ + float fDistance = GetDistanceBetween(oCreature, oEnemy); + if(fDistance < 50.0) + { + // Game is in meters, so 1 foot = 3.333 meter + // penalty is -1 per 10' so divide it by 10 to use 0.3333f + int nDC = 10 + FloatToInt(fDistance * 0.3333f); + // Check to see if the creature is hiding and add the creatures checks. + int nEnemyMoveSilent, nEnemyHide; + if(GetStealthMode(oEnemy)) + { + nEnemyMoveSilent =(d20() + GetSkillRank(SKILL_MOVE_SILENTLY, oEnemy)); + nEnemyHide =(d20() + GetSkillRank(SKILL_HIDE, oEnemy)); + } + if(GetIsSkillSuccessful (oCreature, SKILL_SPOT, nDC + nEnemyHide)) return TRUE; + if(GetIsSkillSuccessful (oCreature, SKILL_LISTEN, nDC + nEnemyMoveSilent)) return TRUE; + } + return FALSE; +} +void ai_ScoutAhead(object oCreature) +{ + object oPerceived; + object oEnemy = ai_GetNearestEnemy(oCreature, 1, -1, -1, -1, -1, TRUE); + // We see them so fight! + if(oEnemy != OBJECT_INVALID) + { + if(ai_PerceiveEnemy(oCreature, oEnemy)) + { + if(!ai_GetAIMode(oCreature, AI_MODE_DO_NOT_SPEAK)) + { + int nRoll = d10(); + if(nRoll == 1) PlayVoiceChat(VOICE_CHAT_ENEMIES, oCreature); + else if(nRoll == 2) PlayVoiceChat(VOICE_CHAT_FOLLOWME, oCreature); + else if(nRoll == 3) PlayVoiceChat(VOICE_CHAT_LOOKHERE, oCreature); + } + ActionMoveToObject(oEnemy, TRUE, AI_RANGE_LONG); + return; + } + // There are enemies here so lets go to them. + else + { + if(!ai_GetAIMode(oCreature, AI_MODE_DO_NOT_SPEAK)) + { + int nRoll = d3(); + if(nRoll == 1) PlayVoiceChat(VOICE_CHAT_BADIDEA, oCreature); + else if(nRoll == 2) PlayVoiceChat(VOICE_CHAT_SEARCH, oCreature); + else if(nRoll == 3) PlayVoiceChat(VOICE_CHAT_FOLLOWME, oCreature); + } + ActionMoveToObject(oEnemy, TRUE, AI_RANGE_CLOSE); + } + } + // There are no more enemies, but we must look like we are patroling so + // go to encounter points. + else + { + if(!ai_GetAIMode(oCreature, AI_MODE_DO_NOT_SPEAK)) + { + int nRoll = d10(); + if(nRoll == 1) PlayVoiceChat(VOICE_CHAT_BADIDEA, oCreature); + else if(nRoll == 2) PlayVoiceChat(VOICE_CHAT_SEARCH, oCreature); + else if(nRoll == 3) PlayVoiceChat(VOICE_CHAT_FOLLOWME, oCreature); + } + // No enemy so lets get a spawn point! + object oSpawnPoint = GetNearestObjectByTag("ip_encounter", oCreature, d6()); + ActionMoveToObject(oSpawnPoint, TRUE, AI_RANGE_CLOSE); + } +} +int ai_ShouldIPickItUp(object oCreature, object oItem) +{ + int nMinGold; + if(GetResRef(oItem) == "nw_it_gold001") return TRUE; + int nBaseItem = GetBaseItemType(oItem); + if(GetPlotFlag(oItem)) + { + if(ai_GetLootFilter(oCreature, AI_LOOT_PLOT)) nMinGold = GetLocalInt(oCreature, "AI_MIN_GOLD_2"); + else return FALSE; + } + else if(nBaseItem == BASE_ITEM_ARMOR) + { + if (ai_GetLootFilter(oCreature, AI_LOOT_ARMOR)) nMinGold = GetLocalInt(oCreature, "AI_MIN_GOLD_3"); + else return FALSE; + } + else if(nBaseItem == BASE_ITEM_BELT) + { + if(ai_GetLootFilter(oCreature, AI_LOOT_BELTS)) nMinGold = GetLocalInt(oCreature, "AI_MIN_GOLD_4"); + else return FALSE; + } + else if(nBaseItem == BASE_ITEM_BOOTS) + { + if(ai_GetLootFilter(oCreature, AI_LOOT_BOOTS)) nMinGold = GetLocalInt(oCreature, "AI_MIN_GOLD_5"); + else return FALSE; + } + else if(nBaseItem == BASE_ITEM_CLOAK) + { + if(ai_GetLootFilter(oCreature, AI_LOOT_CLOAKS)) nMinGold = GetLocalInt(oCreature, "AI_MIN_GOLD_6"); + else return FALSE; + } + else if(nBaseItem == BASE_ITEM_GEM) + { + if(ai_GetLootFilter(oCreature, AI_LOOT_GEMS)) nMinGold = GetLocalInt(oCreature, "AI_MIN_GOLD_7"); + else return FALSE; + } + else if((nBaseItem == BASE_ITEM_BRACER|| nBaseItem == BASE_ITEM_GLOVES)) + { + if(ai_GetLootFilter(oCreature, AI_LOOT_GLOVES)) nMinGold = GetLocalInt(oCreature, "AI_MIN_GOLD_8"); + else return FALSE; + } + else if(nBaseItem == BASE_ITEM_HELMET) + { + if(ai_GetLootFilter(oCreature, AI_LOOT_HEADGEAR)) nMinGold = GetLocalInt(oCreature, "AI_MIN_GOLD_9"); + else return FALSE; + } + else if(nBaseItem == BASE_ITEM_AMULET || nBaseItem == BASE_ITEM_RING) + { + if(ai_GetLootFilter(oCreature, AI_LOOT_JEWELRY)) nMinGold = GetLocalInt(oCreature, "AI_MIN_GOLD_10"); + else return FALSE; + } + else if(nBaseItem == BASE_ITEM_BLANK_POTION || nBaseItem == BASE_ITEM_POTIONS || + nBaseItem == BASE_ITEM_ENCHANTED_POTION) + { + if(ai_GetLootFilter(oCreature, AI_LOOT_POTIONS)) nMinGold = GetLocalInt(oCreature, "AI_MIN_GOLD_12"); + else return FALSE; + } + else if(nBaseItem == BASE_ITEM_BLANK_SCROLL || nBaseItem == BASE_ITEM_SCROLL || + nBaseItem == BASE_ITEM_ENCHANTED_SCROLL || nBaseItem == BASE_ITEM_SPELLSCROLL) + { + if(ai_GetLootFilter(oCreature, AI_LOOT_SCROLLS)) nMinGold = GetLocalInt(oCreature, "AI_MIN_GOLD_13"); + else return FALSE; + } + else if(nBaseItem == BASE_ITEM_BLANK_WAND || nBaseItem == BASE_ITEM_ENCHANTED_WAND || + nBaseItem == BASE_ITEM_MAGICWAND || nBaseItem == BASE_ITEM_MAGICROD || + nBaseItem == BASE_ITEM_MAGICSTAFF) + { + if(ai_GetLootFilter(oCreature, AI_LOOT_WANDS_RODS_STAVES)) nMinGold = GetLocalInt(oCreature, "AI_MIN_GOLD_15"); + else return FALSE; + } + else if(nBaseItem == BASE_ITEM_ARROW) + { + if(ai_GetLootFilter(oCreature, AI_LOOT_ARROWS)) nMinGold = GetLocalInt(oCreature, "AI_MIN_GOLD_17"); + else return FALSE; + } + else if(nBaseItem == BASE_ITEM_BOLT) + { + if(ai_GetLootFilter(oCreature, AI_LOOT_BOLTS)) nMinGold = GetLocalInt(oCreature, "AI_MIN_GOLD_18"); + else return FALSE; + } + else if(nBaseItem == BASE_ITEM_BULLET) + { + if(ai_GetLootFilter(oCreature, AI_LOOT_BULLETS)) nMinGold = GetLocalInt(oCreature, "AI_MIN_GOLD_19"); + else return FALSE; + } + else if(ai_GetIsWeapon(oItem)) + { + if(ai_GetLootFilter(oCreature, AI_LOOT_WEAPONS)) nMinGold = GetLocalInt(oCreature, "AI_MIN_GOLD_16"); + else return FALSE; + } + else if(ai_GetIsShield(oItem)) + { + if(ai_GetLootFilter(oCreature, AI_LOOT_SHIELDS)) nMinGold = GetLocalInt(oCreature, "AI_MIN_GOLD_14"); + else return FALSE; + } + else if(ai_GetLootFilter(oCreature, AI_LOOT_MISC)) nMinGold = GetLocalInt(oCreature, "AI_MIN_GOLD_11"); + else return FALSE; + // Check if it is too heavy. + int nItemWeight = GetWeight(oItem); + if(AI_DEBUG) ai_Debug("0i_actions", "1146", GetName(oItem) + " nItemWeight: " + + IntToString(nItemWeight) + " Max Weight: " + IntToString(GetLocalInt(oCreature, AI_MAX_LOOT_WEIGHT) * 10)); + if(nItemWeight > GetLocalInt(oCreature, AI_MAX_LOOT_WEIGHT) * 10) return FALSE; + // Check if it is not valuable enough. + int bID = GetIdentified(oItem); + if(!bID) SetIdentified(oItem, TRUE); + int nItemValue = GetGoldPieceValue(oItem); + if(!bID) SetIdentified(oItem, FALSE); + if(AI_DEBUG) ai_Debug("0i_actions", "998", GetName(oItem) + " nMinGold: " + IntToString(nMinGold) + " nItemValue: " + + IntToString(nItemValue) + " bID: " + IntToString(bID)); + if(nMinGold > nItemValue) return FALSE; + return TRUE; +} +void ai_TakeItemMessage(object oCreature, object oObject, object oItem, object oMaster) +{ + int bId = GetIdentified(oItem); + int nCreatureSkill = GetSkillRank(SKILL_LORE, oCreature); + int nMasterSkill = GetSkillRank(SKILL_LORE, oMaster); + if(nCreatureSkill + nMasterSkill > 0) + { + if(nCreatureSkill > nMasterSkill) ai_IdentifyItemVsKnowledge(oCreature, oItem); + else ai_IdentifyItemVsKnowledge(oMaster, oItem); + } + if(!ai_GetIsCharacter(oCreature)) + { + if(GetIdentified(oItem)) + { + if(bId) ai_SendMessages(GetName(oCreature) + " has found a " + GetName(oItem) + " from the " + GetName(oObject) + ".", AI_COLOR_GRAY, oMaster); + else ai_SendMessages(GetName(oCreature) + " has found and identified " + GetName(oItem) + " from the " + GetName(oObject) + ".", AI_COLOR_GREEN, oMaster); + } + else if(!ai_GetIsCharacter(oCreature)) + { + string sBaseName = GetStringByStrRef(StringToInt(Get2DAString("baseitems", "name", GetBaseItemType(oItem)))); + ai_SendMessages(GetName(oCreature) + " has found a " + sBaseName + " from the " + GetName(oObject) + ".", AI_COLOR_GRAY, oMaster); + } + } + else if(GetIdentified(oItem) && !bId) + { + ai_SendMessages(GetName(oCreature) + " has identified " + GetName(oItem) + " from the " + GetName(oObject) + ".", AI_COLOR_GREEN, oMaster); + } + if(GetPlotFlag(oItem)) + { + if(!ai_GetAIMode(oCreature, AI_MODE_DO_NOT_SPEAK)) PlayVoiceChat(VOICE_CHAT_LOOKHERE, oCreature); + } +} +void ai_SearchObject(object oCreature, object oObject, object oMaster, int bOnce = FALSE) +{ + ai_Debug("0i_actions", "966", GetName(OBJECT_SELF) + " is opening " + GetName(oObject)); + string sTag = GetTag(oCreature); + AssignCommand(oObject, ActionPlayAnimation(ANIMATION_PLACEABLE_OPEN)); + if(GetIsTrapped(oObject)) DoPlaceableObjectAction(oObject, PLACEABLE_ACTION_USE); + SetLocalInt(oObject, "AI_LOOTED_" + sTag, TRUE); + // Big Hack to allow NPC's to loot! + string sLootScript = GetEventScript(oObject, EVENT_SCRIPT_PLACEABLE_ON_OPEN); + //ai_Debug("0i_actions", "972", "Loot script: " + sLootScript); + if(sLootScript != "") + { + // Used in Original Campaign, and SOU for loot scripts to get treasure to work. + SetLocalObject(oObject, "AI_GET_LAST_OPENED_BY", oMaster); + ExecuteScript(sLootScript, oObject); + } + AssignCommand(oObject, ActionWait(2.0f)); + AssignCommand(oObject, ActionPlayAnimation(ANIMATION_PLACEABLE_CLOSE)); + int nItemType, nGold; + object oItem = GetFirstItemInInventory(oObject); + //ai_Debug("0i_actions", "983", "Found: " + GetName(oItem) + " ResRef: " + GetResRef(oItem) + + // " in " + GetName(oObject)); + while(oItem != OBJECT_INVALID) + { + ai_Debug("0i_actions", "987", "Found: " + GetName(oItem) + " ResRef: " + GetResRef(oItem)); + if(ai_ShouldIPickItUp(oCreature, oItem)) + { + ai_Debug("0i_actions", "1002", "Taking: " + GetName(oItem)); + if(GetResRef(oItem) == "nw_it_gold001") + { + if(!ai_GetIsCharacter(oCreature)) + { + int nGold = GetItemStackSize(oItem); + DestroyObject(oItem); + ActionDoCommand(GiveGoldToCreature(oMaster, nGold)); + ActionDoCommand(ai_SendMessages(GetName(oCreature) + " has retrieved " + IntToString(nGold) + + " gold from the " + GetName(oObject) + ".", AI_COLOR_GRAY, oMaster)); + } + else AssignCommand(oCreature, ActionTakeItem(oItem, oObject)); + } + // Check if they are a henchman, companions and familiars give all items to the pc. + else if(!ai_GetLootFilter(oCreature, AI_LOOT_GIVE_TO_PC) && + GetAssociateType(oCreature) == ASSOCIATE_TYPE_HENCHMAN && + !GetPlotFlag(oItem)) + { + if(GetBaseItemFitsInInventory(GetBaseItemType(oItem), oCreature)) + { + ActionDoCommand(ai_TakeItemMessage(oCreature, oObject, oItem, oMaster)); + ActionTakeItem(oItem, oObject); + } + else + { + if(GetIdentified(oItem)) SpeakString("My inventory is full! I cannot pick up the " + GetName(oItem) + "."); + else + { + string sBaseName = GetStringByStrRef(StringToInt(Get2DAString("baseitems", "name", GetBaseItemType(oItem)))); + SpeakString("My inventory is full! I cannot pick up the " + sBaseName + "."); + } + } + } + else + { + if(GetBaseItemFitsInInventory(GetBaseItemType(oItem), oMaster)) + { + //ai_Debug("0i_actions", "1010", "Giving to master: " + GetName(oItem)); + ActionDoCommand(ai_TakeItemMessage(oCreature, oObject, oItem, oMaster)); + AssignCommand(oObject, ActionGiveItem(oItem, oMaster)); + } + else + { + if(GetIdentified(oItem)) SpeakString("Your inventory is full! You cannot take the " + GetName(oItem) + "."); + else + { + string sBaseName = GetStringByStrRef(StringToInt(Get2DAString("baseitems", "name", GetBaseItemType(oItem)))); + SpeakString("Your inventory is full! You cannot take the " + sBaseName + "."); + } + } + } + } + oItem = GetNextItemInInventory(oObject); + //ai_Debug("0i_actions", "1016", GetName(oItem) + " is the next item."); + } + //ai_Debug("0i_actions", "1018", "Setting object as looted. Check for a new Placeable."); + if(!bOnce) ActionDoCommand(ai_ActionCheckNearbyObjects(oCreature)); +} +int ai_IsContainerLootable(object oCreature, object oObject) +{ + string sTag = GetTag(oCreature); + //ai_Debug("0i_actions", "1303", GetName(oObject) + " (sTag " + GetTag(oObject) + ") " + + // "has inventory: " + IntToString(GetHasInventory(oObject)) + " Has been looted: " + + // IntToString(GetLocalInt(oObject, "AI_LOOTED_" + sTag)) + " Is Useable? " + + // IntToString(GetUseableFlag(oObject))); + if(!GetHasInventory(oObject) || !GetUseableFlag(oObject)) return FALSE; + // This associate has already looted this object, skip. + if(GetLocalInt(oObject, "AI_LOOTED_" + sTag) || ai_GetIsCharacter(oObject)) return FALSE; + return TRUE; +} +int ai_AttempToCastKnockSpell(object oCreature, object oLocked) +{ + if(GetHasSpell(SPELL_KNOCK, oCreature) && + (GetIsDoorActionPossible(oLocked, DOOR_ACTION_KNOCK) || + GetIsPlaceableObjectActionPossible(oLocked, PLACEABLE_ACTION_KNOCK)) && + ai_GetIsInLineOfSight(oCreature, oLocked)) + { + SetLocalInt(oLocked, AI_OBJECT_IN_USE, TRUE); + DelayCommand(6.0, DeleteLocalInt(oLocked, AI_OBJECT_IN_USE)); + AssignCommand(oCreature, ai_ClearCreatureActions()); + AssignCommand(oCreature, ActionWait(1.0)); + AssignCommand(oCreature, ActionCastSpellAtObject(SPELL_KNOCK, oLocked)); + AssignCommand(oCreature, ActionWait(1.0)); + AssignCommand(oCreature, ActionDoCommand(DeleteLocalInt(oLocked, AI_OBJECT_IN_USE))); + return TRUE; + } + return FALSE; +} +int ai_ReactToTrap(object oCreature, object oTrap, int bForce = FALSE) +{ + int nTrapDC = GetTrapDisarmDC(oTrap); + if(AI_DEBUG) ai_Debug("0i_actions", "1520", "Reacting to trap on " + GetName(oTrap) + + " bForce: " + IntToString(bForce) + " nTrapDC: " + IntToString(nTrapDC) + + " [AI_OBJECT_IN_USE: " + IntToString(GetLocalInt(oTrap, AI_OBJECT_IN_USE)) + "]."); + if(nTrapDC == 0) return FALSE; + string sTag = GetTag(oCreature); + if(bForce || ai_GetAIMode(oCreature, AI_MODE_DISARM_TRAPS)) + { + if(GetTrapDisarmable(oTrap)) + { + if(GetLocalInt(oTrap, AI_OBJECT_IN_USE)) return FALSE; + // We must have ranks in disable traps to actually disable the trap! + if(GetSkillRank(SKILL_DISABLE_TRAP, oCreature, TRUE)) + { + int nSkill = GetSkillRank(SKILL_DISABLE_TRAP, oCreature); + if(AI_DEBUG) ai_Debug("0i_actions", "1534", "nSkill: " + IntToString(nSkill) + + " + 20 = " + IntToString(nSkill + 20) + " nTrapDC: " + IntToString(nTrapDC)); + if(nSkill + 20 >= nTrapDC) + { + SetLocalInt(oTrap, AI_OBJECT_IN_USE, TRUE); + DelayCommand(18.0, DeleteLocalInt(oTrap, AI_OBJECT_IN_USE)); + AssignCommand(oCreature, ai_ClearCreatureActions()); + AssignCommand(oCreature, ActionUseSkill(SKILL_DISABLE_TRAP, oTrap, 0)); + // Let them know we did it! + AssignCommand(oCreature, ActionDoCommand(ai_HaveCreatureSpeak(oCreature, 6, ":44:42:31:35:"))); + AssignCommand(oCreature, ActionDoCommand(DeleteLocalInt(oTrap, AI_OBJECT_IN_USE))); + // Continue checking for traps, locks, and loot. + AssignCommand(oCreature, ActionDoCommand(ai_ActionCheckNearbyObjects(oCreature))); + return TRUE; + } + if(GetHasSpell(SPELL_FIND_TRAPS, oCreature)) + { + AssignCommand(oCreature, ai_ClearCreatureActions()); + AssignCommand(oCreature, ActionCastSpellAtObject(SPELL_FIND_TRAPS, oTrap)); + // Continue checking for traps, locks, and loot. + AssignCommand(oCreature, ActionDoCommand(ai_ActionCheckNearbyObjects(oCreature))); + return TRUE; + } + } + if(GetLocalInt(oTrap, "AI_CANNOT_TRAP_" + sTag) && !bForce) return FALSE; + // Let them know we can't get this done!. + //StrRef(40551) "I cannot disarm this trap!" + ActionDoCommand(ai_HaveCreatureSpeak(oCreature, 0, GetStringByStrRef(40551))); + ActionDoCommand(ai_HaveCreatureSpeak(oCreature, 8, ":47:30:43:5:36:")); + SetLocalInt(oTrap, "AI_CANNOT_TRAP_" + sTag, TRUE); + return FALSE; + } + if(GetLocalInt(oTrap, "AI_SAW_TRAP_" + sTag) && !bForce) return FALSE; + // Let them know we can't get this done!. + ai_HaveCreatureSpeak(oCreature, 0, "I'm not skilled enough to disable the trap!", TRUE); + ActionDoCommand(ai_HaveCreatureSpeak(oCreature, 8, ":47:30:43:5:36:")); + SetLocalInt(oTrap, "AI_SAW_TRAP_" + sTag, TRUE); + return FALSE; + } + if(GetObjectType(oTrap) == OBJECT_TYPE_TRIGGER) + { + object oMaster = ai_GetPlayerMaster(oCreature); + if(oMaster != OBJECT_INVALID && !ai_GetIsCharacter(oCreature) && + !ai_GetAIMode(oCreature, AI_MODE_IGNORE_TRAPS)) + { + ai_SetAIMode(oCreature, AI_MODE_SCOUT_AHEAD, FALSE); + ai_SetAIMode(oCreature, AI_MODE_STAND_GROUND, TRUE); + ai_SetAIMode(oCreature, AI_MODE_FOLLOW, FALSE); + ai_SetAIMode(oCreature, AI_MODE_COMMANDED, FALSE); + int nToken = NuiFindWindow(oMaster, ai_GetAssociateType(oMaster, oCreature) + AI_WIDGET_NUI); + ai_HighlightWidgetMode(oMaster, oCreature, nToken); + aiSaveAssociateModesToDb(oMaster, oCreature); + if(ai_IsInCombatRound(oCreature)) ai_ClearCombatState(oCreature); + ai_ClearCreatureActions(TRUE); + ai_SendMessages(GetName(oCreature) + " has went into hold mode after seeing a trap!", AI_COLOR_YELLOW, oMaster); + return TRUE; + } + } + if(ai_GetAIMode(oCreature, AI_MODE_PICKUP_ITEMS)) + { + if(GetLocalInt(oTrap, "AI_SAW_TRAP_" + sTag) && !bForce) return FALSE; + ActionDoCommand(ai_HaveCreatureSpeak(oCreature, 0, "This " + GetName(oTrap) + " is trapped!", TRUE)); + ActionDoCommand(ai_HaveCreatureSpeak(oCreature, 8, ":47:30:43:5:36:")); + SetLocalInt(oTrap, "AI_SAW_TRAP_" + sTag, TRUE); + } + return FALSE; +} +int ai_AttemptToByPassLock(object oCreature, object oLocked, int bForce = FALSE) +{ + if(AI_DEBUG) ai_Debug("0i_actions", "1446", "Attempting to bypass lock on " + + GetName(oLocked) + " [AI_OBJECT_IN_USE: " + + IntToString(GetLocalInt(oLocked, AI_OBJECT_IN_USE)) + "]" + + " bForce: " + IntToString(bForce)); + if(GetLocalInt(oLocked, AI_OBJECT_IN_USE)) return FALSE; + string sTag = GetTag(oCreature); + // Attempt to cast knock because its always safe to cast it, even on a trapped object. + if(ai_AttempToCastKnockSpell(oLocked, oCreature)) return TRUE; + // First, let's see if we notice that it's trapped + if(GetTrapDetectedBy(oCreature, oLocked)) + { + // Ick! Try and disarm the trap first + if(ai_ReactToTrap(oCreature, oLocked, bForce)) return TRUE; + } + if(GetLockKeyRequired(oLocked)) + { + // We might be able to open this. + string sKeyTag = GetLockKeyTag(oLocked); + // Do we have the key? + object oKey = ai_GetCreatureHasItem(oCreature, sKeyTag, FALSE); + if(AI_DEBUG) ai_Debug("0i_actions", "1469", "Requires a Key! sKeyTag: " + + sKeyTag + " Has key oKey: " + GetName(oKey)); + if(oKey != OBJECT_INVALID) + { + int nObjectType = GetObjectType(oLocked); + if(nObjectType == OBJECT_TYPE_DOOR) return ai_AttemptToOpenDoor(oCreature, oLocked, bForce); + else if (nObjectType == OBJECT_TYPE_PLACEABLE) + { + SetLocalInt(oLocked, AI_OBJECT_IN_USE, TRUE); + DelayCommand(18.0, DeleteLocalInt(oLocked, AI_OBJECT_IN_USE)); + AssignCommand(oCreature, ActionUnlockObject(oLocked)); + // Let them know we did it! + ActionDoCommand(ai_HaveCreatureSpeak(oCreature, 6, ":44:42:31:35:")); + AssignCommand(oCreature, ActionDoCommand(DeleteLocalInt(oLocked, AI_OBJECT_IN_USE))); + // Continue checking for traps, locks, and loot. + AssignCommand(oCreature, ActionDoCommand(ai_ActionCheckNearbyObjects(oCreature))); + return TRUE; + } + } + else + { + if(GetLocalInt(oLocked, "AI_LOCKED_" + sTag) && !bForce) return FALSE; + // Let them know we can't get this done!. + AssignCommand(oCreature, ActionDoCommand(ai_HaveCreatureSpeak(oCreature, 0, "This " + GetName(oLocked) + " is special! It requires a special key to open."))); + ActionDoCommand(ai_HaveCreatureSpeak(oCreature, 8, ":47:30:43:5:36:")); + SetLocalInt(oLocked, "AI_LOCKED_" + sTag, TRUE); + return FALSE; + } + } + if(bForce || ai_GetAIMode(oCreature, AI_MODE_PICK_LOCKS)) + { + // We must have ranks in open locks to actually open the lock! + if(GetSkillRank(SKILL_OPEN_LOCK, oCreature, TRUE)) + { + int nSkill = GetSkillRank(SKILL_OPEN_LOCK, oCreature); + int nLockDC = GetLockUnlockDC(oLocked); + object oPicks = ai_GetBestPicks(oCreature, nLockDC); + int nPickBonus = GetLocalInt(oPicks, "AI_BONUS"); + if(AI_DEBUG) ai_Debug("0i_actions", "1497", "I have picks: " + GetName(oPicks) + + " nSkill :" + IntToString(nSkill) + " nPickBonus: " + + IntToString(nPickBonus) + " + 20 = " + + IntToString(nSkill + nPickBonus + 20) + + " nLockDC: " + IntToString(nLockDC)); + if(nSkill + 20 + nPickBonus >= nLockDC) + { + SetLocalInt(oLocked, AI_OBJECT_IN_USE, TRUE); + DelayCommand(18.0, DeleteLocalInt(oLocked, AI_OBJECT_IN_USE)); + AssignCommand(oCreature, ai_ClearCreatureActions()); + AssignCommand(oCreature, ActionWait(1.0)); + AssignCommand(oCreature, ActionUseSkill(SKILL_OPEN_LOCK, oLocked, 0, oPicks)); + AssignCommand(oCreature, ActionWait(1.0)); + // Let them know we did it! + ActionDoCommand(ai_HaveCreatureSpeak(oCreature, 8, ":44:42:26:31:35:")); + AssignCommand(oCreature, ActionDoCommand(DeleteLocalInt(oLocked, AI_OBJECT_IN_USE))); + // Continue checking for traps, locks, and loot. + AssignCommand(oCreature, ActionDoCommand(ai_ActionCheckNearbyObjects(oCreature))); + return TRUE; + } + else if(!GetLocalInt(oLocked, "AI_LOCKED_" + sTag)) + { + // Let them know we can't get this done! + AssignCommand(oCreature, ActionDoCommand(ai_HaveCreatureSpeak(oCreature, 0, "I'm not skilled enough to pick the lock on this " + GetName(oLocked) + "!", TRUE))); + ActionDoCommand(ai_HaveCreatureSpeak(oCreature, 8, ":47:30:43:5:36:")); + SetLocalInt(oLocked, "AI_LOCKED_" + sTag, TRUE); + return FALSE; + } + } + } + if(bForce || ai_GetAIMode(oCreature, AI_MODE_BASH_LOCKS)) + { + //AssignCommand(oCreature, ai_ClearCreatureActions()); + // Check to make sure we are not using a ranged weapon. + if(!ai_GetIsRangeWeapon(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oCreature))) + { + if(ai_CheckClassType(oCreature, CLASS_TYPE_MONK)) ai_EquipBestMonkMeleeWeapon(oCreature); + else ai_EquipBestMeleeWeapon(oCreature); + AssignCommand(oCreature, ActionWait(1.0)); + if(ai_TryImprovedPowerAttackFeat(oCreature, oLocked)) return TRUE; + if(ai_TryPowerAttackFeat(oCreature, oLocked)) return TRUE; + if(ai_TryFlurryOfBlowsFeat(oCreature, oLocked)) return TRUE; + AssignCommand(oCreature, ActionAttack(oLocked)); + return TRUE; + } + if(GetLocalInt(oLocked, "AI_LOCKED_" + sTag) && !bForce) return FALSE; + // Let them know we can't get this done!. + AssignCommand(oCreature, ActionDoCommand(ai_HaveCreatureSpeak(oCreature, 0, "I cannot bash this " + GetName(oLocked) + " open!", TRUE))); + SetLocalInt(oLocked, "AI_LOCKED_" + sTag, TRUE); + return FALSE; + } + if(bForce || ai_GetAIMode(oCreature, AI_MODE_PICKUP_ITEMS)) + { + if(GetLocalInt(oLocked, "AI_LOCKED_" + sTag) && !bForce) return FALSE; + AssignCommand(oCreature, ActionDoCommand(ai_HaveCreatureSpeak(oCreature, 0, "This " + GetName(oLocked) + " is locked!", TRUE))); + ActionDoCommand(ai_HaveCreatureSpeak(oCreature, 8, ":47:30:43:5:36:")); + SetLocalInt(oLocked, "AI_LOCKED_" + sTag, TRUE); + } + return FALSE; +} +int ai_AttemptToOpenDoor(object oCreature, object oDoor, int bForce = FALSE) +{ + if(AI_DEBUG) ai_Debug("0i_actions", "1542", "Attempting to open " + + GetName(oDoor) + " [AI_OBJECT_IN_USE: " + + IntToString(GetLocalInt(oDoor, AI_OBJECT_IN_USE)) + "] " + + " IsOpen: " + IntToString(GetIsOpen(oDoor)) + + " Plot: " + IntToString(GetPlotFlag(oDoor)) + "."); + if(!ai_GetAIMode(oCreature, AI_MODE_OPEN_DOORS) && !bForce) return FALSE; + if(GetLocalInt(oDoor, AI_OBJECT_IN_USE)) return FALSE; + if(GetIsOpen(oDoor)) return FALSE; + string sTag = GetTag(oCreature); + if(GetIsTrapped(oDoor)) + { + if(GetTrapDetectedBy(oDoor, GetMaster(oCreature))) SetTrapDetectedBy(oDoor, oCreature); + if(GetTrapDetectedBy(oDoor, oCreature)) + { + if(GetLocalInt(oDoor, "AI_SAW_TRAP_" + sTag)) return FALSE; + ActionDoCommand(ai_HaveCreatureSpeak(oCreature, 0, "This " + GetName(oDoor) + " is trapped!", TRUE)); + ActionDoCommand(ai_HaveCreatureSpeak(oCreature, 8, ":47:30:43:5:36:")); + SetLocalInt(oDoor, "AI_SAW_TRAP_" + sTag, TRUE); + return FALSE; + } + } + if(GetLocked(oDoor)) + { + if(GetLocalInt(oDoor, "AI_LOCKED_" + sTag)) return FALSE; + AssignCommand(oCreature, ActionDoCommand(ai_HaveCreatureSpeak(oCreature, 0, "This " + GetName(oDoor) + " is locked!", TRUE))); + ActionDoCommand(ai_HaveCreatureSpeak(oCreature, 8, ":47:30:43:5:36:")); + SetLocalInt(oDoor, "AI_LOCKED_" + sTag, TRUE); + return FALSE; + } + SetLocalInt(oDoor, AI_OBJECT_IN_USE, TRUE); + DelayCommand(18.0, DeleteLocalInt(oDoor, AI_OBJECT_IN_USE)); + AssignCommand(oCreature, ActionOpenDoor(oDoor, TRUE)); + AssignCommand(oCreature, ActionDoCommand(DeleteLocalInt(oDoor, AI_OBJECT_IN_USE))); + return TRUE; +} +void ai_ActionCheckNearbyObjects(object oCreature) +{ + if(ai_GetIsBusy(oCreature)) return; + ai_CheckNearbyObjects(oCreature); +} +int ai_CheckNearbyObjects(object oCreature) +{ + object oMaster = ai_GetPlayerMaster(oCreature); + location lMaster = GetLocation(oMaster); + int nObjectType, bIgnore; + int nFilter = OBJECT_TYPE_DOOR | OBJECT_TYPE_PLACEABLE | OBJECT_TYPE_TRIGGER | OBJECT_TYPE_ITEM; + float fLockRange, fDoorRange, fLootRange, fObjectDistance; + float fTrapRange = GetLocalFloat(oCreature, AI_TRAP_CHECK_RANGE); + if(ai_GetAIMode(oCreature, AI_MODE_PICK_LOCKS) || + ai_GetAIMode(oCreature, AI_MODE_BASH_LOCKS)) fLockRange = GetLocalFloat(oCreature, AI_LOCK_CHECK_RANGE); + if(ai_GetAIMode(oCreature, AI_MODE_PICKUP_ITEMS)) fLootRange = GetLocalFloat(oCreature, AI_LOOT_CHECK_RANGE); + if(ai_GetAIMode(oCreature, AI_MODE_OPEN_DOORS)) fDoorRange = GetLocalFloat(oCreature, AI_OPEN_DOORS_RANGE); + if(AI_DEBUG && fTrapRange != 0.0) ai_Debug("0i_actions", "1579", " Checking " + FloatToString(fTrapRange, 0, 0) + " foot area for traps."); + if(AI_DEBUG && fLootRange != 0.0) ai_Debug("0i_actions", "1580", " Checking " + FloatToString(fLootRange, 0, 0) + " foot area for traps."); + if(AI_DEBUG && fLockRange != 0.0) ai_Debug("0i_actions", "1581", " Checking " + FloatToString(fLockRange, 0, 0) + " foot area for locks."); + if(AI_DEBUG && fDoorRange != 0.0) ai_Debug("0i_actions", "1582", " Checking " + FloatToString(fDoorRange, 0, 0) + " foot area for doors."); + float fLongestRange = fTrapRange; + vector vCreature = GetPositionFromLocation(GetLocation(oCreature)); + if(fLongestRange < fLootRange) fLongestRange = fLootRange; + if(fLongestRange < fLockRange) fLongestRange = fLockRange; + if(fLongestRange < fDoorRange) fLongestRange = fDoorRange; + object oObject = GetFirstObjectInShape(SHAPE_SPHERE, fLongestRange, lMaster, TRUE, nFilter); + while(oObject != OBJECT_INVALID) + { + fObjectDistance = GetDistanceBetween(oMaster, oObject); + if(AI_DEBUG) ai_Debug("0i_actions", "1651", "Checking Nearby Objects: " + + GetName(oObject) + " fDistance: " + FloatToString(fObjectDistance, 0, 2)); + if(GetTrapDetectedBy(oObject, oCreature)) + { + if(fTrapRange >= fObjectDistance) + { + if(ai_ReactToTrap(oCreature, oObject)) return TRUE; + } + } + if(GetLocked(oObject)) + { + if(fLockRange >= fObjectDistance) + { + if(ai_AttemptToByPassLock(oCreature, oObject)) return TRUE; + } + } + nObjectType = GetObjectType(oObject); + if(fDoorRange >= fObjectDistance && nObjectType == OBJECT_TYPE_DOOR) + { + if(ai_AttemptToOpenDoor(oCreature, oObject)) return TRUE; + } + if(fLootRange >= fObjectDistance) + { + if(nObjectType == OBJECT_TYPE_PLACEABLE) + { + if(!GetLocalInt(oObject, AI_OBJECT_IN_USE) && + ai_IsContainerLootable(oCreature, oObject)) + { + if(GetLocked(oObject)) + { + string sTag = GetTag(oCreature); + if(GetLocalInt(oObject, "AI_LOCKED_" + sTag)) return FALSE; + AssignCommand(oCreature, ActionDoCommand(ai_HaveCreatureSpeak(oCreature, 0, "This " + GetName(oObject) + " is locked!", TRUE))); + ActionDoCommand(ai_HaveCreatureSpeak(oCreature, 8, ":47:30:43:5:36:")); + SetLocalInt(oObject, "AI_LOCKED_" + sTag, TRUE); + return FALSE; + } + ai_ClearCreatureActions(); + ActionMoveToObject(oObject, TRUE); + AssignCommand(oCreature, ActionDoCommand(ai_SearchObject(oCreature, oObject, oMaster))); + return TRUE; + } + } + else if(nObjectType == OBJECT_TYPE_ITEM) + { + if(ai_ShouldIPickItUp(oCreature, oObject)) + { + ActionPickUpItem(oObject); + return TRUE; + } + } + } + oObject = GetNextObjectInShape(SHAPE_SPHERE, fLongestRange, lMaster, TRUE, nFilter); + } + return FALSE; +} +void ai_DetermineSpecialBehavior(object oCreature) +{ + object oTarget = ai_GetNearestEnemy(oCreature, 1, 7, 7, -1, -1, TRUE); + if(ai_GetBehaviorState(NW_FLAG_BEHAVIOR_OMNIVORE)) + { + if(ai_GetIsInCombat(oCreature)) ai_DoMonsterCombatRound(oTarget); + // * if not attacking, then wander. + else + { + AssignCommand(oCreature, ai_ClearCreatureActions()); + AssignCommand(oCreature, ActionRandomWalk()); + return; + } + } + else if(ai_GetBehaviorState(NW_FLAG_BEHAVIOR_HERBIVORE)) + { + if(GetIsObjectValid(ai_GetAttackedTarget(oCreature, TRUE, TRUE))) + { + if(oTarget != OBJECT_INVALID && GetDistanceBetween(oCreature, oTarget) <= 6.0) + { + if(!GetIsFriend(oTarget)) + { + if(GetLevelByClass(CLASS_TYPE_DRUID, oTarget) == 0 && GetLevelByClass(CLASS_TYPE_RANGER, oTarget) == 0) + { + SetLocalString(oCreature, AI_COMBAT_SCRIPT, "ai_coward"); + ActionMoveAwayFromObject(oTarget, TRUE, AI_RANGE_LONG); + } + } + } + } + else if(!IsInConversation(OBJECT_SELF)) + { + AssignCommand(oCreature, ai_ClearCreatureActions()); + AssignCommand(oCreature, ActionRandomWalk()); + return; + } + } +} +//This function is used only because ActionDoCommand can only accept void functions +void ai_CreateSignPostNPC(string sTag, location lLocal) +{ + CreateObject(OBJECT_TYPE_CREATURE, sTag, lLocal); +} +void ai_ActivateFleeToExit(object oCreature) +{ + //minor optimizations - only grab these variables when actually needed + //can make for larger code, but it's faster + //object oExitWay = GetWaypointByTag("EXIT_" + GetTag(OBJECT_SELF)); + //location lLocal = GetLocalLocation(OBJECT_SELF, "NW_GENERIC_START_POINT"); + //string sTag = GetTag(OBJECT_SELF); + int nPlot = GetLocalInt(oCreature, "NW_GENERIC_MASTER"); + if(nPlot & NW_FLAG_TELEPORT_RETURN || nPlot & NW_FLAG_TELEPORT_LEAVE) + { + effect eVis = EffectVisualEffect(VFX_IMP_UNSUMMON); + ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oCreature); + if(nPlot & NW_FLAG_TELEPORT_RETURN) + { + location lLocal = GetLocalLocation(oCreature, "NW_GENERIC_START_POINT"); + string sTag = GetTag(oCreature); + DelayCommand(6.0, AssignCommand(oCreature, ActionDoCommand(ai_CreateSignPostNPC(sTag, lLocal)))); + } + AssignCommand(oCreature, ActionDoCommand(DestroyObject(oCreature, 0.75))); + } + else + { + if(nPlot & NW_FLAG_ESCAPE_LEAVE) + { + object oExitWay = GetWaypointByTag("EXIT_" + GetTag(oCreature)); + ActionMoveToObject(oExitWay, TRUE); + AssignCommand(oCreature, ActionDoCommand(DestroyObject(oCreature, 1.0))); + } + else if(nPlot & NW_FLAG_ESCAPE_RETURN) + { + string sTag = GetTag(oCreature); + object oExitWay = GetWaypointByTag("EXIT_" + sTag); + ActionMoveToObject(oExitWay, TRUE); + location lLocal = GetLocalLocation(oCreature, "NW_GENERIC_START_POINT"); + DelayCommand(6.0, AssignCommand(oCreature, ActionDoCommand(ai_CreateSignPostNPC(sTag, lLocal)))); + AssignCommand(oCreature, ActionDoCommand(DestroyObject(oCreature, 1.0))); + } + } +} +int ai_GetFleeToExit(object oCreature) +{ + int nPlot = GetLocalInt(oCreature, "NW_GENERIC_MASTER"); + if(nPlot & NW_FLAG_ESCAPE_RETURN) return TRUE; + else if(nPlot & NW_FLAG_ESCAPE_LEAVE) return TRUE; + else if(nPlot & NW_FLAG_TELEPORT_RETURN) return TRUE; + else if(nPlot & NW_FLAG_TELEPORT_LEAVE) return TRUE; + return FALSE; +} +void ai_ActionInitialization() +{ + SetAnimationCondition(NW_ANIM_FLAG_IS_ACTIVE); + SetAnimationCondition(NW_ANIM_FLAG_INITIALIZED); + SetLocalLocation(OBJECT_SELF, "ANIM_START_LOCATION", GetLocation(OBJECT_SELF)); +} +// Start interacting with a placeable object +void ai_ActionStartInteracting(object oPlaceable) +{ + SetAnimationCondition(NW_ANIM_FLAG_IS_INTERACTING); + ActionMoveToObject(oPlaceable, FALSE, DISTANCE_TINY); + ActionDoCommand(SetFacingPoint(GetPosition(oPlaceable))); + SetCurrentInteractionTarget(oPlaceable); + AnimActionPlayRandomInteractAnimation(oPlaceable); +} + +void ai_ActionStopInteracting() +{ + AnimActionRandomMoveAway(GetCurrentInteractionTarget(), DISTANCE_LARGE); + SetCurrentInteractionTarget(OBJECT_INVALID); + SetAnimationCondition(NW_ANIM_FLAG_IS_INTERACTING, FALSE); + AnimActionTurnAround(); + AnimActionPlayRandomAnimation(); +} + +// Start talking with a friend +void ai_ActionStartTalking(object oFriend, int nHDiff=0) +{ + object oMe = OBJECT_SELF; + ActionMoveToObject(oFriend, FALSE, DISTANCE_TINY); + AnimActionPlayRandomGreeting(nHDiff); + AssignCommand(oFriend, ActionMoveToObject(oMe, FALSE, DISTANCE_TINY)); + AssignCommand(oFriend, AnimActionPlayRandomGreeting(0 - nHDiff)); + SetCurrentFriend(oFriend); + AssignCommand(oFriend, SetCurrentFriend(oMe)); + ActionDoCommand(SetFacingPoint(GetPosition(oFriend))); + AssignCommand(oFriend, ActionDoCommand(SetFacingPoint(GetPosition(oMe)))); + SetAnimationCondition(NW_ANIM_FLAG_IS_TALKING); + SetAnimationCondition(NW_ANIM_FLAG_IS_TALKING, TRUE, oFriend); +} +void ai_ActionStopTalking(object oFriend, int nHDiff=0) +{ + object oMe = OBJECT_SELF; + AnimActionPlayRandomGoodbye(nHDiff); + AnimActionRandomMoveAway(oFriend, DISTANCE_LARGE); + AssignCommand(oFriend, AnimActionPlayRandomGoodbye(0 - nHDiff)); + AssignCommand(oFriend, AnimActionRandomMoveAway(oMe, DISTANCE_HUGE)); + SetAnimationCondition(NW_ANIM_FLAG_IS_TALKING, FALSE); + SetAnimationCondition(NW_ANIM_FLAG_IS_TALKING, FALSE, oFriend); +} +object ai_GetRandomFriend(float fMaxDistance) +{ + object oCreature = OBJECT_SELF; + location lStartLocation = GetLocalLocation(oCreature, "ANIM_START_LOCATION"); + object oFriend = GetNearestCreature(CREATURE_TYPE_REPUTATION, + REPUTATION_TYPE_FRIEND, + oCreature, d2(), + CREATURE_TYPE_PERCEPTION, + PERCEPTION_SEEN); + //SendMessageToPC(GetFirstPC(), " 0i_actions, 1748 oFriend: " + GetName(oFriend) + + // " AnimationCondition: " + IntToString(GetAnimationCondition(NW_ANIM_FLAG_IS_ACTIVE, oFriend)) + + // " Conversation: " + IntToString(IsInConversation(oFriend)) + + // " Combat: " + IntToString(GetIsInCombat(oFriend)) + + // " Distance: " + FloatToString(GetDistanceBetweenLocations(GetLocation(oFriend), lStartLocation), 0,0 )); + if(fMaxDistance > 20.0) fMaxDistance = 20.0; + if(GetIsObjectValid(oFriend) + && !GetIsPC(oFriend) + && !GetAnimationCondition(NW_ANIM_FLAG_IS_TALKING, oFriend) + && !IsInConversation(oFriend) + && !GetIsInCombat(oFriend) + && GetDistanceBetweenLocations(GetLocation(oFriend), lStartLocation) <= fMaxDistance) + { + return oFriend; + } + + return OBJECT_INVALID; +} +int ai_ActionFindFriend(float fMaxDistance) +{ + // Try and find a friend to talk to. + object oFriend = ai_GetRandomFriend(fMaxDistance); + //SendMessageToPC(GetFirstPC(), GetName(oFriend) + " TALKING: " + IntToString(GetAnimationCondition(NW_ANIM_FLAG_IS_TALKING, oFriend))); + if(GetIsObjectValid(oFriend) && !GetAnimationCondition(NW_ANIM_FLAG_IS_TALKING, oFriend)) + { + int nHDiff = GetHitDice(OBJECT_SELF) - GetHitDice(oFriend); + ai_ActionStartTalking(oFriend, nHDiff); + return TRUE; + } + return FALSE; +} +object ai_GetRandomObjectbyTag(string sTag, float fMaxDistance) +{ + int nIndex; + if(fMaxDistance < DISTANCE_MEDIUM) nIndex = d4(); + else if (fMaxDistance < DISTANCE_HUGE) nIndex = d8(); + else nIndex = d10(); + location lStartLocation = GetLocalLocation(OBJECT_SELF, "ANIM_START_LOCATION"); + if(fMaxDistance > 20.0) fMaxDistance = 20.0; + object oObject = GetNearestObjectToLocation(OBJECT_TYPE_PLACEABLE, lStartLocation, nIndex); + while(nIndex > 0) + { + if(GetTag(oObject) == sTag && + GetDistanceBetweenLocations(GetLocation(oObject), lStartLocation) <= fMaxDistance) break; + oObject = GetNearestObjectToLocation(OBJECT_TYPE_PLACEABLE, lStartLocation, --nIndex); + } + if(GetIsObjectValid(oObject)) + return oObject; + return OBJECT_INVALID; +} +int ai_ActionSitInChair(float fMaxDistance) +{ + object oChair = GetRandomObjectByTag("Chair", fMaxDistance); + if (GetIsObjectValid(oChair) && + !GetIsObjectValid(GetSittingCreature(oChair))) + { + ActionSit(oChair); + SetAnimationCondition(NW_ANIM_FLAG_IS_INTERACTING); + return TRUE; + } + return FALSE; +} +object ai_GetRandomUseableObject(float fMaxDistance) +{ + int nIndex; + if(fMaxDistance < DISTANCE_MEDIUM) nIndex = d2(); + else if (fMaxDistance < DISTANCE_HUGE) nIndex = d4(); + else nIndex = d6(); + location lStartLocation = GetLocalLocation(OBJECT_SELF, "ANIM_START_LOCATION"); + if(fMaxDistance > 20.0) fMaxDistance = 20.0; + object oObject = GetNearestObjectToLocation(OBJECT_TYPE_PLACEABLE, lStartLocation, nIndex); + while(nIndex > 0) + { + if(GetUseableFlag(oObject) && !GetLocked(oObject) && + GetDistanceBetweenLocations(GetLocation(oObject), lStartLocation) <= fMaxDistance) break; + oObject = GetNearestObjectToLocation(OBJECT_TYPE_PLACEABLE, lStartLocation, --nIndex); + } + if(GetIsObjectValid(oObject)) + return oObject; + return OBJECT_INVALID; +} +int ai_ActionFindPlaceable(float fMaxDistance) +{ + object oPlaceable = ai_GetRandomUseableObject(fMaxDistance); + if(GetIsObjectValid(oPlaceable)) + { + ai_ActionStartInteracting(oPlaceable); + return 1; + } + return 0; +} +int ai_ActionCheckDoor(float fMaxDistance) +{ + int nIndex = 1; + object oCreature = OBJECT_SELF; + location lStartLocation = GetLocalLocation(oCreature, "ANIM_START_LOCATION"); + if(fMaxDistance > 20.0) fMaxDistance = 20.0; + object oDoor = GetNearestObject(OBJECT_TYPE_DOOR, oCreature); + while(oDoor != OBJECT_INVALID) + { + if(GetDistanceBetweenLocations(GetLocation(oDoor), lStartLocation) <= fMaxDistance) + { + // Make sure everyone doesn't run to close or open the same door. + if(!GetLocalInt(oDoor, "DOOR_INTERACTION")) + { + if(GetIsOpen(oDoor)) + { + //SendMessageToPC(GetFirstPC(), GetName(oCreature) + + // " Closing " + GetName(oDoor) + "."); + SetLocalInt(oDoor, "DOOR_INTERACTION", TRUE); + ActionCloseDoor(oDoor); + AssignCommand(oDoor, ActionDoCommand(SetLocalInt(oDoor, "DOOR_INTERACTION", FALSE))); + return TRUE; + } + else if(GetLocalInt(GetModule(), AI_RULE_OPEN_DOORS)) + { + //SendMessageToPC(GetFirstPC(), GetName(oDoor) + " Locked: " + + // IntToString(GetLocked(oDoor)) + " Trapped: " + + // IntToString(GetIsTrapped(oDoor)) + + // " Plot: " + IntToString(GetPlotFlag(oDoor))); + if(!GetLocked(oDoor) && + !GetIsTrapped(oDoor) && + !GetPlotFlag(oDoor)) + { + //SendMessageToPC(GetFirstPC(), GetName(oCreature) + + // " Opening " + GetName(oDoor) + "."); + SetLocalInt(oDoor, "DOOR_INTERACTION", TRUE); + ActionOpenDoor(oDoor); + // If a door has been opened lets not go right behind and close for a minute. + DelayCommand(60.0, SetLocalInt(oDoor, "DOOR_INTERACTION", FALSE)); + return TRUE; + } + } + } + } + oDoor = GetNearestObject(OBJECT_TYPE_DOOR, oCreature, ++nIndex); + } + return FALSE; +} +int ai_ActionInteraction() +{ + // If we're talking, either keep going or stop. + // Low prob of stopping, since both parties have + // a chance and conversations are cool. + if(GetAnimationCondition(NW_ANIM_FLAG_IS_TALKING)) + { + object oFriend = GetCurrentFriend(); + //SendMessageToPC(GetFirstPC(), GetName(OBJECT_SELF) + " Is talking to " + GetName(oFriend)); + int nHDiff = GetHitDice(OBJECT_SELF) - GetHitDice(oFriend); + if(Random(100) < 20) + { + //SendMessageToPC(GetFirstPC(), GetName(OBJECT_SELF) + " I'm done talking!"); + ai_ActionStopTalking(oFriend, nHDiff); + return TRUE; + } + AnimActionPlayRandomTalkAnimation(nHDiff); + return TRUE; + } + // If we're interacting with a placeable, either keep going or stop. + // High probability of stopping, since looks silly to + // constantly turn something on-and-off. + if(GetAnimationCondition(NW_ANIM_FLAG_IS_INTERACTING)) + { + //SendMessageToPC(GetFirstPC(), GetName(OBJECT_SELF) + " Is interacting."); + if(Random(100) < 40) + { + //SendMessageToPC(GetFirstPC(), GetName(OBJECT_SELF) + " I'm done interacting!"); + ai_ActionStopInteracting(); + return TRUE; + } + AnimActionPlayRandomInteractAnimation(GetCurrentInteractionTarget()); + return TRUE; + } + return FALSE; +} +location ai_GetWalkingLocation(object oSource, float fDistance) +{ + location lStart = GetLocation(oSource); + // Try to move in a north/south/east/west direction that will allow better + // movement around the map! + float fFacing = GetFacing(oSource); + if(Random(100) < 25) fFacing = IntToFloat(Random(360)); + float fAngle; + if(fFacing > 315.0 || fFacing < 45.0) fAngle = DIRECTION_EAST; + else if(fFacing < 135.0) fAngle = DIRECTION_NORTH; + else if(fFacing < 225.0) fAngle = DIRECTION_WEST; + else fAngle = DIRECTION_SOUTH; + fAngle += IntToFloat(Random(20) - 10); + float fOrientation = fAngle; + return GenerateNewLocationFromLocation(lStart, fDistance, fAngle, fOrientation); +} +void ai_ActionRandomWalk(float fMaxDistance) +{ + // If we stay within our alloted distance then we can walk to the new location. + location lStartLocation = GetLocalLocation(OBJECT_SELF, "ANIM_START_LOCATION"); + int nRandom = FloatToInt(fMaxDistance); + if(nRandom > 20) nRandom = 20; + float fRandom = IntToFloat(Random(nRandom) + 1); + location lNewLocation = ai_GetWalkingLocation(OBJECT_SELF, fRandom); + if(AI_DEBUG) ai_Debug("0i_actions", "2092", GetName(OBJECT_SELF) + " is walking " + + FloatToString(GetDistanceBetweenLocations(lNewLocation, lStartLocation), 0, 0) + + " distance of fMaxDistance: " + FloatToString(fMaxDistance, 0, 0)); + ActionMoveToLocation(lNewLocation); +} +void ai_Actions() +{ + float fMaxDistance = GetLocalFloat(GetModule(), AI_RULE_WANDER_DISTANCE); + // Are we interacting? If so continue else see what else there is to do. + if(ai_ActionInteraction()) return; + // If we got here, we're not busy + ClearAllActions(); + // Check for chance to do an action to keep things interesting. + int nRoll = Random(100); + if(fMaxDistance < 2.0) + { + if(nRoll < 51) AnimActionPlayRandomAnimation(); + return; + } + int nRace = GetRacialType(OBJECT_SELF); + if(nRace != RACIAL_TYPE_ABERRATION && nRace != RACIAL_TYPE_ANIMAL && + nRace != RACIAL_TYPE_BEAST && nRace != RACIAL_TYPE_MAGICAL_BEAST && + nRace != RACIAL_TYPE_OOZE && nRace != RACIAL_TYPE_VERMIN) + { + if(nRoll < 5) if(ai_ActionSitInChair(fMaxDistance)) return; + // Open or close a door + if(nRoll < 20) if(ai_ActionCheckDoor(fMaxDistance)) return; + // Fiddle with a placeable + if(nRoll < 40) if(ai_ActionFindPlaceable(fMaxDistance)) return; + // Start talking to a friend + if(nRoll < 50) if(ai_ActionFindFriend(fMaxDistance)) return; + } + // Lets walk around. + if(nRoll < 80) + { + ai_ActionRandomWalk(fMaxDistance); + return; + } + // If we find nothing interesting to do then just stay put and look interesting. + AnimActionPlayRandomAnimation(); +} +int ai_CheckCurrentAction() +{ + int nAction = GetCurrentAction(); + if(nAction == ACTION_SIT) + { + // low prob of getting up, so we don't bop up and down constantly + if (Random(10) == 0) + { + AnimActionGetUpFromChair(); + return TRUE; + } + } + else if(nAction != ACTION_INVALID) + { + // Sometimes we cannot do an action so lets break out sometimes. + if((nAction == ACTION_CLOSEDOOR || + nAction == ACTION_OPENDOOR || + nAction == ACTION_MOVETOPOINT) && Random(100) < 20) return FALSE; + // we're doing *something*, don't switch + //AnimDebug("performing action"); + return TRUE; + } + return FALSE; +} +void ai_AmbientAnimations() +{ + if(!GetAnimationCondition(NW_ANIM_FLAG_INITIALIZED)) ai_ActionInitialization(); + // Check if we should turn off + if(!CheckIsAnimActive(OBJECT_SELF)) return; + // Check current actions so we don't interrupt something in progress + if(ai_CheckCurrentAction()) return; + // First check: go back to starting position and rest if we are hurt + //if(AnimActionRest()) return; + // If we get here then lets go see what we can do! + ai_Actions(); +} diff --git a/src/module/nss/0i_associates.nss b/src/module/nss/0i_associates.nss new file mode 100644 index 0000000..2309160 --- /dev/null +++ b/src/module/nss/0i_associates.nss @@ -0,0 +1,2192 @@ +/*////////////////////////////////////////////////////////////////////////////// + Script: 0i_associates + Programmer: Philos +//////////////////////////////////////////////////////////////////////////////// + Scripts used for Associates. +*/////////////////////////////////////////////////////////////////////////////// +#include "0i_actions" +#include "nw_inc_gff" +// Return TRUE if oCreature can attack based on current modes and actions. +int ai_CanIAttack(object oCreature); +// Returns the nearest locked object from oMaster. +object ai_GetNearestLockedObject(object oCreature); +// Will look for the oTarget or go to the oSpeaker depending on the situation. +void ai_FindTheEnemy(object oCreature, object oSpeaker, object oTarget, int bMonster); +// Selects the correct response base on nCommand from oCommander. +// These are given from either a radial menu option or voice command. +void ai_SelectAssociateCommand(object oCreature, object oCommander, int nCommand); +// Set nAction for the caller to pass to their associates. i.e. For henchmans summons. +void ai_PassActionToAssociates(object oCreature, int nAction, int bStatus = TRUE); +// Set Set the AI Mode to oAssociate and their associates. +void ai_PassAIModeToAssociates(object oAssociate, int nAIMode, int bStatus = TRUE); +// Set oCreature's ai scripts based on its first class or the variable "AI_DEFAULT_SCRIPT". +// bSetBasicAIScript set to TRUE will skip defensive and ambush tactic type scripts. +void ai_SetAssociateAIScript(object oCreature, int bCheckTacticScripts = TRUE); +// Returns TRUE if oCreature can speak. +int ai_CanISpeak(object oCreature); +// Cleansup any henchman actions and then removes them from the PC's faction. +void ai_FireHenchman(object oPC, object oHenchman); +// Will cast defensive spells (Buffs) on oPC's party from oCreature. +void ai_HenchmanCastDefensiveSpells(object oCreature, object oPC); +// Returns TRUE if we are starting combat due to an enemy being near. +// This should be checked after any "is in combat" checks. +int ai_CheckForCombat(object oCreature, int bMonster); +// Checks all perceived creatures to see if we should calculate a combat round +// or start combat for Associates. +void ai_AssociateEvaluateNewThreat(object oCreature, object oLastPerceived, string sPerception); +// Checks all perceived creatures to see if we should calculate a combat round +// or start combat for Monsters. +void ai_MonsterEvaluateNewThreat(object oCreature, object oLastPerceived, string sPerception); +// Copies all int, float, and string variables from oOldObject to oNewObject. +void ai_CopyObjectVariables(object oOldObject, object oNewObject); +//****************************************************************************** +//********************* Creature event scripts ********************************* +//****************************************************************************** + +// Add to nw_ch_aca OnRested event script of henchman. +void ai_OnRested(object oCreature); + +//****************************************************************************** +//******************* Associate AI option scripts ****************************** +//****************************************************************************** + +// Increments/Decrements the following distance of associates. +void ai_FollowIncrement(object oPC, object oAssociate, float fIncrement, string sAssociateType); +// Turns on/off Ranged combat for oAssociate. +void ai_Ranged(object oPC, object oAssociate, string sAssociateType); +// Turns on/off Ignore enemy associates for oAssociate. +void ai_Ignore_Associates(object oPC, object oAssociate, string sAssociateType); +// Turns on/off Ignore floor traps for oAssociate. +void ai_Ignore_Traps(object oPC, object oAssociate, string sAssociateType); +// Turns on/off Search for oAssociate. +void ai_Search(object oPC, object oAssociate, string sAssociateType); +// Turns on/off Stealth for oAssociate. +void ai_Stealth(object oPC, object oAssociate, string sAssociateType); +// Turns on/off Open Doors for oAssociate. +void ai_OpenDoor(object oPC, object oAssociate, string sAssociateType); +// Turns on/off Picking/Bashing locks for oAssociate. +void ai_Locks(object oPC, object oAssociate, string sAssociateType, int nMode); +// Turns on/off Disarming of Traps for oAssociate. +void ai_Traps(object oPC, object oAssociate, string sAssociateType); +// Turns on/off the amount of speaking for oAssociate. +void ai_ReduceSpeech(object oPC, object oAssociate, string sAssociateType); +// Turns on/off use of offensive/defensive spells. +void ai_UseOffensiveMagic(object oPC, object oAssociate, int bDefensive, int bOffensive, string sAssociateType); +// Turns on/off magic use. +void ai_UseMagic(object oPC, object oAssociate, string sAssociateType); +// Turn Magic Item use on/off for oAssociates. +void ai_UseMagicItems(object oPC, object oAssociate, string sAssociateType); +// Adjusts loot options for oAssociate +void ai_Loot(object oPC, object oAssociate, string sAssociateType); +// Adjust loot options for oAssociate +void ai_Spontaneous(object oPC, object oAssociate, string sAssociateType); +// Increments/Decrements the magic use variable for the AI. +void ai_MagicIncrement(object oPC, object oAssociate, int nIncrement, string sAssociateType); +// Increments/Decrements the Loot Range use variable for the AI. +void ai_LootRangeIncrement(object oPC, object oAssociate, float fIncrement, string sAssociateType); +// Increments/Decrements the Lock Range use variable for the AI. +void ai_LockRangeIncrement(object oPC, object oAssociate, float fIncrement, string sAssociateType); +// Increments/Decrements the Trap Range use variable for the AI. +void ai_TrapRangeIncrement(object oPC, object oAssociate, float fIncrement, string sAssociateType); +// Increments/Decrements the Open Door Range use variable for the AI. +void ai_OpenDoorIncrement(object oPC, object oAssociate, float fIncrement, string sAssociateType); +// Saves a new AI script for oAssociate. +void ai_SaveAIScript(object oPC, object oAssociate, int nToken); +// Button action for buffing a PC. +void ai_Buff_Button(object oPC, object oAssociate, int nOption, string sAssociateType); +// Button action for setting healing ranges. +void ai_Heal_Button(object oPC, object oAssociate, int nIncrement, string sVar, string sAssociateType); +// Button action for turning healing on/off. +void ai_Heal_OnOff(object oPC, object oAssociate, string sAssociateType, int nMode); +// Button action for selecting a target to follow. +void ai_FollowTarget(object oPC, object oAssociate); +// Code to make oCreature guard oMaster. +void ai_Philos_Guard(object oMaster, object oCreature); +// Code to make OBJECT_SELF follow oMaster. +void ai_Philos_Follow(object oMaster); +// Code to make OBJECT_SELF hold at their location. +void ai_Philos_StandGround(object oMaster); +// Code to make oCreature attack the nearest enemy. +void ai_Philos_AttackNearest(object oMaster, object oCreature); +// Code to make oCreature turn search mode on. +void ai_Philos_SetSearch(object oMaster, object oCreature, string sAssociateType, int bTurnOn); +// Code to make oCreature turn stealth mode on. +void ai_Philos_SetStealth(object oMaster, object oCreature, string sAssociateType, int bTurnOn); +// Button action for giving commands to associates. +void ai_DoCommand(object oPC, object oAssociate, int nCommand); +// Button action to have associate do an action based on the target via OnPlayer Target event. +void ai_Action(object oPC, object oAssociate); +// Toggles between normal ai script and special tactic ai scripts. +void ai_AIScript(object oPC, object oAssociate, string sAssociate, int nToken); +// Has the PC select a Trap and then place it on the ground from an associate. +void ai_HavePCPlaceTrap(object oPC, object oAssociate); +// Jumps oAssociate to oPC, if oPC == oAssociate it jumps all oAssocites to oPC. +void ai_JumpToPC(object oPC, object oAssociate); +// Allow oAssociate to use no clipping. +void ai_GhostMode(object oPC, object oAssociate, int nToken, string sAssociateType); +// Changes the camera view from either the player to the associate or back. +void ai_ChangeCameraView(object oPC, object oAssociate); +// Checks that the oAssociate is within sight and then opens the inventory. +void ai_OpenInventory(object oAssociate, object oPC); +// Executes an installed plugin. +void ai_Plugin_Execute(object oPC, string sElem, int bUser = 0); + +int ai_CanIAttack(object oCreature) +{ + if(AI_DEBUG) ai_Debug("0i_associate", "122", "Can I attack? Hold mode: " + + IntToString(ai_GetAIMode(oCreature, AI_MODE_STAND_GROUND)) + + " Follow mode: " + IntToString(ai_GetAIMode(oCreature, AI_MODE_FOLLOW)) + + " Action (19/4): " + IntToString(GetCurrentAction(oCreature))); + if(ai_GetIsCharacter(oCreature)) return TRUE; + int nAction = GetCurrentAction(oCreature); + return (!ai_GetAIMode(oCreature, AI_MODE_STAND_GROUND) && + !ai_GetAIMode(oCreature, AI_MODE_FOLLOW) && + nAction != ACTION_ITEMCASTSPELL && + nAction != ACTION_CASTSPELL); +} +object ai_GetNearestLockedObject(object oCreature) +{ + int nCnt = 1; + object oMaster = GetMaster(oCreature); + float fRange = GetLocalFloat(oCreature, AI_TRAP_CHECK_RANGE); + location lCreature = GetLocation(oCreature); + object oObject = GetNearestObjectToLocation(OBJECT_TYPE_DOOR | OBJECT_TYPE_PLACEABLE, lCreature, nCnt); + while (oObject != OBJECT_INVALID || GetDistanceBetween(oMaster, oObject) > fRange) + { + if(GetLocked(oObject) && ai_GetIsInLineOfSight(oMaster, oObject)) return oObject; + oObject = GetNearestObjectToLocation(OBJECT_TYPE_DOOR | OBJECT_TYPE_PLACEABLE, lCreature, ++nCnt); + } + return OBJECT_INVALID; +} +void ai_FindTheEnemy(object oCreature, object oSpeaker, object oTarget, int bMonster) +{ + if(GetLocalInt(oCreature, AI_AM_I_SEARCHING)) return; + if(oSpeaker == oTarget && d100() < 34) + { + // Let them know we heard something in the distance!. + if(!ai_GetAIMode(oCreature, AI_MODE_DO_NOT_SPEAK)) + { + string sSpeak = "I heard something!"; + int nRoll = d8(); + if(nRoll == 1) sSpeak = "Did you hear that?"; + if(nRoll == 2) sSpeak = "What was that noise?"; + if(nRoll == 3) sSpeak = "Something is moving."; + if(nRoll == 4) sSpeak = "Lookout! I heard a noise."; + if(nRoll == 5) sSpeak = "Listen! We have company."; + AssignCommand(oCreature, ai_HaveCreatureSpeak(oCreature, 0, sSpeak)); + } + ai_HaveCreatureSpeak(oCreature, 8, ":43:6:9:10:23:42:"); + } + if(GetLocalString(oCreature, AI_COMBAT_SCRIPT) == "ai_a_peaceful" || + GetLocalString(oCreature, AI_COMBAT_SCRIPT) == "ai_coward") return; + float fDistance, fPerceptionDistance; + if(bMonster) + { + // Check distance from the creature hearing this and the target. + fDistance = GetDistanceBetween(oCreature, oTarget); + fPerceptionDistance = GetLocalFloat(GetModule(), AI_RULE_PERCEPTION_DISTANCE); + } + else + { + // We want to use the distance between the PC and target not us. + fDistance = GetDistanceBetween(GetMaster(), oTarget); + fPerceptionDistance = GetLocalFloat(oCreature, AI_ASSOC_PERCEPTION_DISTANCE); + } + if(AI_DEBUG) ai_Debug("0i_associates", "175", " fDistance: " + FloatToString(fDistance, 0, 2) + + " fPerceptionDistance: " + FloatToString(fPerceptionDistance, 0, 2) + + " Hiding? " + IntToString(GetStealthMode(oTarget))); + if(fDistance <= fPerceptionDistance) + { + SetLocalInt(oCreature, AI_AM_I_SEARCHING, TRUE); + if(LineOfSightObject(oCreature, oTarget)) + { + if(fDistance > AI_RANGE_CLOSE) + { + int bMoveForward = TRUE; + // We check this because if the enemy is moving or has not + // started acting then we don't want to move up on them as they + // might move towards us! Just attack! Only sneak attack if they are busy. + int nAction = GetCurrentAction(oTarget); + if(AI_DEBUG) ai_Debug("0i_associates", "189", GetName(oTarget) + " current action: " + IntToString(nAction)); + if(nAction == ACTION_MOVETOPOINT || + nAction == ACTION_INVALID || + nAction == ACTION_RANDOMWALK) bMoveForward = FALSE; + // If they are attacking make sure it is in melee? + // If not then don't move since they might be moving toward us. + if(nAction == ACTION_ATTACKOBJECT) + { + if(!ai_GetNumOfEnemiesInRange(oTarget)) bMoveForward = FALSE; + } + if(bMoveForward) + { + if(AI_DEBUG) ai_Debug("0i_associates", "201", "Running towards combat to engage " + GetName(oTarget)); + ActionMoveToObject(oTarget, TRUE, AI_RANGE_CLOSE); + AssignCommand(oCreature, ActionDoCommand(DeleteLocalInt(oCreature, AI_AM_I_SEARCHING))); + return; + } + if(AI_DEBUG) ai_Debug("0i_associates", "207", "Searching for " + GetName(oTarget) + " while moving towards " + GetName(oSpeaker)); + SetActionMode(oCreature, ACTION_MODE_DETECT, TRUE); + ActionMoveToObject(oSpeaker); + return; + } + if(AI_DEBUG) ai_Debug("0i_associates", "176", "Moving and searching for " + GetName(oTarget)); + SetActionMode(oCreature, ACTION_MODE_DETECT, TRUE); + ActionMoveToLocation(GetLocation(oTarget), FALSE); + //ActionMoveToObject(oTarget, FALSE, AI_RANGE_MELEE); + AssignCommand(oCreature, ActionDoCommand(DeleteLocalInt(oCreature, AI_AM_I_SEARCHING))); + return; + } + if(AI_DEBUG) ai_Debug("0i_associates", "218", "No line of sight for " + GetName(oTarget) + ". Moving towards " + GetName(oSpeaker)); + ActionMoveToObject(oSpeaker, TRUE); + AssignCommand(oCreature, ActionDoCommand(DeleteLocalInt(oCreature, AI_AM_I_SEARCHING))); + } + +} +void ai_ReactToAssociate(object oCreature, object oCommander, int bMonster) +{ + object oTarget = GetLocalObject(oCommander, AI_MY_TARGET); + if (oTarget == OBJECT_INVALID) return; + if(ai_GetIsInCombat(oCreature)) + { + if(oCommander == GetMaster(oCreature) && ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) + { + ai_DoAssociateCombatRound(oCreature, oTarget); + } + else ai_DoAssociateCombatRound(oCreature); + return; + } + ai_FindTheEnemy(oCreature, oCommander, oTarget, bMonster); +} +void ai_SelectAssociateCommand(object oCreature, object oCommander, int nCommand) +{ + object oMaster = GetMaster(oCreature); + // These nCommands can be issued even when the caller is busy. + switch(nCommand) + { + // Master is being attacked by the enemy. + case ASSOCIATE_COMMAND_MASTERGOINGTOBEATTACKED: + { + object oAttacker = GetGoingToBeAttackedBy(oMaster); + if(AI_DEBUG) ai_Debug("0i_associate", "120", GetName(oMaster) + " has been attack by " + + GetName(GetGoingToBeAttackedBy(oMaster)) + "!"); + // Used to set who monsters are attacking. + int nAction = GetCurrentAction(oAttacker); + if(nAction == ACTION_ATTACKOBJECT) SetLocalObject(oAttacker, AI_ATTACKED_PHYSICAL, oMaster); + else if(nAction == ACTION_CASTSPELL || nAction == ACTION_ITEMCASTSPELL) + { + SetLocalObject(oAttacker, AI_ATTACKED_SPELL, oMaster); + } + if(!ai_GetIsBusy(oCreature) && ai_CanIAttack(oCreature)) + { + if(ai_GetIsInCombat(oCreature)) ai_DoAssociateCombatRound(oCreature); + else ai_FindTheEnemy(oCreature, oCommander, oAttacker, FALSE); + } + return; + } + // Menu used by a player to have the henchman follow them. + case ASSOCIATE_COMMAND_FOLLOWMASTER: + { + if(AI_DEBUG) ai_Debug("0i_associate", "135", GetName(oMaster) + " has commanded " + + GetName(oCreature) + " to FOLLOW."); + AssignCommand(oCreature, ai_Philos_Follow(oMaster)); + return; + } + // Menu used by a player to have the henchman go into NORMAL MODE. + // We also attack the nearest, this keeps henchman going into combat quickly. + case ASSOCIATE_COMMAND_ATTACKNEAREST: + { + if(AI_DEBUG) ai_Debug("0i_associates", "158", GetName(oMaster) + " has commanded " + + GetName(oCreature) + " to attack nearest(NORMAL MODE)."); + ai_Philos_AttackNearest(oMaster, oCreature); + return; + } + // Menu used by a player to have the henchman stay where they are standing. + case ASSOCIATE_COMMAND_STANDGROUND: + { + if(AI_DEBUG) ai_Debug("0i_associate", "189", GetName(oMaster) + " has commanded " + + GetName(OBJECT_SELF) + " to STANDGROUND."); + AssignCommand(oCreature, ai_Philos_StandGround(oMaster)); + return; + } + // Menu used by a player to have the henchman attack anyone who attacks them. + case ASSOCIATE_COMMAND_GUARDMASTER: + { + if(AI_DEBUG) ai_Debug("0i_associate", "211", GetName(oMaster) + " has commanded " + + GetName(oCreature) + " to GAURDMASTER."); + ai_Philos_Guard(oMaster, oCreature); + return; + } + // Menu used by a player to have the henchman heal them as soon as possible. + case ASSOCIATE_COMMAND_HEALMASTER: + { + // Player will be stuck with this variable if they are not using the AI. + DeleteLocalInt(oCommander, "AI_I_AM_BEING_HEALED"); + if(ai_GetIsInCombat(oCreature)) ai_TryHealingTalent(oCreature, ai_GetNumOfEnemiesInRange(oCreature), oCommander); + else AssignCommand(oCreature, ai_ActionTryHealing(oCreature, oCommander)); + return; + } + // Menu used by a player to toggle a henchmans casting options. + case ASSOCIATE_COMMAND_TOGGLECASTING: + { + if(ai_GetMagicMode(oCreature, AI_MAGIC_NO_MAGIC)) + { + ai_SetMagicMode(oCreature, AI_MAGIC_NO_MAGIC, FALSE); + ai_SetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING, TRUE); + ai_SetMagicMode(oCreature, AI_MAGIC_OFFENSIVE_CASTING, FALSE); + ai_SendMessages(GetName(oCreature) + " will now cast defensive spells only.", AI_COLOR_GRAY, oCommander); + } + else if(ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING)) + { + ai_SetMagicMode(oCreature, AI_MAGIC_NO_MAGIC, FALSE); + ai_SetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING, FALSE); + ai_SetMagicMode(oCreature, AI_MAGIC_OFFENSIVE_CASTING, TRUE); + ai_SendMessages(GetName(oCreature) + " will now cast offensive spells only.", AI_COLOR_GRAY, oCommander); + } + else if(ai_GetMagicMode(oCreature, AI_MAGIC_OFFENSIVE_CASTING)) + { + ai_SetMagicMode(oCreature, AI_MAGIC_NO_MAGIC, FALSE); + ai_SetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING, FALSE); + ai_SetMagicMode(oCreature, AI_MAGIC_OFFENSIVE_CASTING, FALSE); + ai_SendMessages(GetName(oCreature) + " will now cast any spell.", AI_COLOR_GRAY, oCommander); + } + else + { + ai_SetMagicMode(oCreature, AI_MAGIC_NO_MAGIC, TRUE); + ai_SetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING, FALSE); + ai_SetMagicMode(oCreature, AI_MAGIC_OFFENSIVE_CASTING, FALSE); + ai_SendMessages(GetName(oCreature) + " will not use any magic.", AI_COLOR_GRAY, oCommander); + } + aiSaveAssociateModesToDb(oMaster, oCreature); + return; + } + } + // If we are busy then these nCommands are ignored. + if(!ai_GetIsBusy(oCreature)) + { + // Respond to shouts from friendly non-PCs only. + if (ai_CanIAttack(oCreature)) + { + if(nCommand == AI_ALLY_IS_WOUNDED) + { + if(ai_TryHealing(oCreature, oCommander)) return; + } + else if(nCommand == AI_ALLY_IS_DISEASED || + nCommand == AI_ALLY_IS_POISONED || + nCommand == AI_ALLY_IS_WEAK) + { + if(ai_HealSickness(oCreature, oCommander, oMaster, nCommand)) return; + } + // A friend sees an enemy. If we are not in combat lets seek them out too! + else if(nCommand == AI_ALLY_SEES_AN_ENEMY || + nCommand == AI_ALLY_HEARD_AN_ENEMY) + { + if(AI_DEBUG) ai_Debug("0i_associates", "282", GetName(oCreature) + " receives notice that " + + GetName(oCommander) + " has seen1/heard2(" + IntToString(nCommand) + " an enemy: " + + GetName(GetLocalObject(oCommander, AI_MY_TARGET)) + "!"); + ai_ReactToAssociate(oCreature, oCommander, FALSE); + return; + } + // A friend is in combat. Make some checks to see if we should help. + else if(nCommand == AI_ALLY_ATKED_BY_WEAPON || + nCommand == AI_ALLY_ATKED_BY_SPELL) + { + if(AI_DEBUG) ai_Debug("0i_associates", "291", GetName(oCreature) + " receives notice that " + + GetName(oCommander) + " was attacked by an enemy!" + + GetName(GetLocalObject(oCommander, AI_MY_TARGET)) + "!"); + ai_ReactToAssociate(oCreature, oCommander, FALSE); + return; + } + else if(nCommand == AI_ALLY_IS_DEAD) + { // Nothing at the moment. + if(AI_DEBUG) ai_Debug("0i_associates", "298", GetName(oCreature) + " receives notice that " + + GetName(oCommander) + " has died!"); + return; + } + } + switch(nCommand) + { + case ASSOCIATE_COMMAND_MASTERATTACKEDOTHER: + { + if(AI_DEBUG) ai_Debug("0i_associate", "307", GetName(oMaster) + " has attacked!"); + if(ai_CanIAttack(oCreature)) + { + if(ai_GetIsInCombat(oCreature)) ai_DoAssociateCombatRound(oCreature); + else ai_FindTheEnemy(oCreature, oCommander, ai_GetAttackedTarget(oCommander, TRUE, TRUE), FALSE); + } + return; + } + // Master tried to open a door or chest that is locked. + case ASSOCIATE_COMMAND_MASTERFAILEDLOCKPICK: + { + // In command mode we let the player tell us what to do. + if(ai_CanIAttack(oCreature)) + { + object oLock = ai_GetNearestLockedObject(oMaster); + //Check and see if our master want's us to open locks. + if(ai_GetAIMode(oCreature, AI_MODE_PICK_LOCKS) || + ai_GetAIMode(oCreature, AI_MODE_BASH_LOCKS)) + { + ai_SetAIMode(oCreature, AI_MODE_SCOUT_AHEAD, FALSE); + ai_SetAIMode(oCreature, AI_MODE_STAND_GROUND, FALSE); + ai_AttemptToByPassLock(oCreature, oLock); + } + } + return; + } + // Master saw a trap. + case ASSOCIATE_COMMAND_MASTERSAWTRAP: + { + // In command mode we let the player tell us what to do. + if(ai_CanIAttack(oCreature)) + { + object oTrap = GetLastTrapDetected(oMaster); + // Sometimes GetLastTrapDetected seems to fail. + if(oTrap == OBJECT_INVALID) oTrap = GetNearestTrapToObject(oMaster, TRUE); + //Check and see if our master want's us to disarm the trap. + ai_SetAIMode(oCreature, AI_MODE_SCOUT_AHEAD, FALSE); + ai_SetAIMode(oCreature, AI_MODE_STAND_GROUND, FALSE); + SetTrapDetectedBy(oTrap, oCreature); + ai_ReactToTrap(oCreature, oTrap); + } + return; + } + // Menu used by a player to toggle henchmans search on and off. + case ASSOCIATE_COMMAND_TOGGLESEARCH: + { + int bTurnOn = !ai_GetAIMode(oCreature, AI_MODE_AGGRESSIVE_SEARCH); + string sAssociateType = ai_GetAssociateType(oMaster, oCreature); + ai_Philos_SetSearch(oMaster, oCreature, sAssociateType, bTurnOn); + return; + } + // Menu used by a player to toggle henchmans stealth on and off. + case ASSOCIATE_COMMAND_TOGGLESTEALTH: + { + int bTurnOn = !ai_GetAIMode(oCreature, AI_MODE_AGGRESSIVE_STEALTH); + string sAssociateType = ai_GetAssociateType(oMaster, oCreature); + ai_Philos_SetStealth(oMaster, oCreature, sAssociateType, bTurnOn); + return; + } + // Menu used by a player to have the henchman try to bypass the nearest lock. + case ASSOCIATE_COMMAND_PICKLOCK: + { + ai_SetAIMode(oCreature, AI_MODE_DEFEND_MASTER, FALSE); + ai_SetAIMode(oCreature, AI_MODE_SCOUT_AHEAD, FALSE); + ai_SetAIMode(oCreature, AI_MODE_STAND_GROUND, FALSE); + ai_SetAIMode(oCreature, AI_MODE_FOLLOW, FALSE); + object oLock = ai_GetNearestLockedObject(oMaster); + // Clear locked variable incase we tried already. + string sID = ObjectToString(oCreature); + SetLocalInt(oLock, "AI_LOCKED_" + sID, FALSE); + ai_AttemptToByPassLock(oCreature, oLock); + aiSaveAssociateModesToDb(oMaster, oCreature); + return; + } + // Menu used by a player to have the henchman try to disarm the nearest trap. + case ASSOCIATE_COMMAND_DISARMTRAP: + { + ai_SetAIMode(oCreature, AI_MODE_DEFEND_MASTER, FALSE); + ai_SetAIMode(oCreature, AI_MODE_SCOUT_AHEAD, FALSE); + ai_SetAIMode(oCreature, AI_MODE_STAND_GROUND, FALSE); + ai_SetAIMode(oCreature, AI_MODE_FOLLOW, FALSE); + object oTrap = GetNearestTrapToObject(oMaster); + // Clear trapped variable incase we tried already. + string sID = ObjectToString(oCreature); + ai_ReactToTrap(oCreature, oTrap, TRUE); + aiSaveAssociateModesToDb(oMaster, oCreature); + return; + } + // Menu used by a player to open a henchmans inventory to give, move, or take. + case ASSOCIATE_COMMAND_INVENTORY: + { + if(AI_OPEN_INVENTORY) + { + ai_HaveCreatureSpeak(oCreature, 4, ":29:46:35:"); + OpenInventory(oCreature, oCommander); + } + // Can't look at an associate's inventory. + else + { + ai_HaveCreatureSpeak(oCreature, 6, ":47:30:36:8:48:"); + ai_SendMessages("You cannot open " + GetName(oCreature) + "'s inventory.", AI_COLOR_GRAY, oMaster); + } + return; + } + case ASSOCIATE_COMMAND_LEAVEPARTY: + { + if(AI_REMOVE_HENCHMAN_ON) + { + ai_ClearCreatureActions(); + ai_FireHenchman (GetPCSpeaker(), oCreature); + PlayVoiceChat (VOICE_CHAT_GOODBYE, oCreature); + } + } + } + } +} +void ai_PassActionToAssociates(object oCreature, int nAction, int bStatus = TRUE) +{ + int nAssociateType; + object oAssociate; + for(nAssociateType = 2; nAssociateType < 6; nAssociateType ++) + { + oAssociate = GetAssociate(nAssociateType); + if(oAssociate != OBJECT_INVALID) SetActionMode(oAssociate, nAction, bStatus); + } +} +void ai_PassToAssociate(object oAssociate, int nAIMode, int bStatus) +{ + ai_ClearCreatureActions(TRUE); + ai_SetAIMode(oAssociate, nAIMode, bStatus); +} +void ai_PassAIModeToAssociates(object oAssociate, int nAIMode, int bStatus = TRUE) +{ + ai_SetAIMode(oAssociate, nAIMode, bStatus); + int nAssociateType; + object oAssoc; + for(nAssociateType = 2; nAssociateType < 6; nAssociateType ++) + { + oAssoc = GetAssociate(nAssociateType, oAssociate); + if(oAssoc != OBJECT_INVALID) AssignCommand(oAssoc, ai_PassToAssociate(oAssoc, nAIMode, bStatus)); + } +} +void ai_SetAssociateAIScript(object oCreature, int bCheckTacticScripts = TRUE) +{ + string sCombatAI; + object oMaster = GetMaster(); + if(ai_GetIsCharacter(oMaster)) + { + string sAssociateType = ai_GetAssociateType(oMaster, oCreature); + json jAIData = ai_GetAssociateDbJson(oMaster, sAssociateType, "aidata"); + sCombatAI = JsonGetString(JsonArrayGet(jAIData, 8)); + } + else sCombatAI = GetLocalString(oCreature, AI_DEFAULT_SCRIPT); + int nAssociateType = GetAssociateType(oCreature); + if (nAssociateType == ASSOCIATE_TYPE_FAMILIAR && sCombatAI == "") + { + sCombatAI = "ai_a_default"; + } + else if(sCombatAI == "ai_coward") + { + SetLocalString(oCreature, AI_COMBAT_SCRIPT, sCombatAI); + return; + } + else if(bCheckTacticScripts && GetLocalInt(GetModule(), AI_RULE_AMBUSH)) + { + // They should have a skill ranks equal to their level + 1 to use a special AI. + int nSkillNeeded = GetHitDice(oCreature) + 1; + if(sCombatAI == "" || sCombatAI == "ai_a_ambusher") + { + // Ambusher: requires either Improved Invisibility or Invisibility. + if(GetHasSpell(SPELL_IMPROVED_INVISIBILITY, oCreature) || + GetHasSpell(SPELL_INVISIBILITY, oCreature)) + { + int bCast = ai_TryToCastSpell(oCreature, SPELL_IMPROVED_INVISIBILITY, oCreature); + if(!bCast) bCast = ai_TryToCastSpell(oCreature, SPELL_INVISIBILITY, oCreature); + if(bCast) + { + SetLocalString(oCreature, AI_COMBAT_SCRIPT, "ai_a_ambusher"); + return; + } + } + // Ambusher: Requires a Hide and Move silently skill equal to your level + 1. + else if(GetSkillRank(SKILL_HIDE, oCreature) >= nSkillNeeded && + GetSkillRank(SKILL_MOVE_SILENTLY, oCreature) >= nSkillNeeded) + { + SetLocalString(oCreature, AI_COMBAT_SCRIPT, "ai_a_ambusher"); + return; + } + } + // Defensive : requires Parry skill equal to your level or Expertise. + else if(sCombatAI == "ai_a_defensive" || + (sCombatAI == "" && + (GetSkillRank(SKILL_PARRY, oCreature) >= nSkillNeeded || + GetHasFeat(FEAT_EXPERTISE, oCreature) || + GetHasFeat(FEAT_IMPROVED_EXPERTISE, oCreature)))) + { + SetLocalString(oCreature, AI_COMBAT_SCRIPT, "ai_a_defensive"); + return; + } + else if(sCombatAI == "ai_cntrspell" || GetHasSpell(SPELL_LESSER_DISPEL, oCreature) || + GetHasSpell(SPELL_DISPEL_MAGIC, oCreature) || GetHasSpell(SPELL_GREATER_DISPELLING, oCreature)) + { + SetLocalString(oCreature, AI_COMBAT_SCRIPT, "ai_cntrspell"); + return; + } + } + if(sCombatAI == "") + { + // Select the best ai for this henchmen based on class. + int nClass = GetClassByPosition(1, oCreature); + // If they have more than one class use the default ai. + if(GetClassByPosition(2, oCreature) != CLASS_TYPE_INVALID) sCombatAI = "ai_a_default"; + else if(nClass == CLASS_TYPE_BARBARIAN) sCombatAI = "ai_a_barbarian"; + else if(nClass == CLASS_TYPE_BARD) sCombatAI = "ai_a_bard"; + else if(nClass == CLASS_TYPE_CLERIC) sCombatAI = "ai_a_cleric"; + else if(nClass == CLASS_TYPE_DRUID) sCombatAI = "ai_a_druid"; + else if(nClass == CLASS_TYPE_FIGHTER) sCombatAI = "ai_a_fighter"; + else if(nClass == CLASS_TYPE_MONK) sCombatAI = "ai_a_monk"; + else if(nClass == CLASS_TYPE_PALADIN) sCombatAI = "ai_a_paladin"; + else if(nClass == CLASS_TYPE_RANGER) sCombatAI = "ai_a_ranger"; + else if(nClass == CLASS_TYPE_ROGUE) sCombatAI = "ai_a_rogue"; + else if(nClass == CLASS_TYPE_SORCERER) sCombatAI = "ai_a_sorcerer"; + else if(nClass == CLASS_TYPE_WIZARD) sCombatAI = "ai_a_wizard"; + //else if(nClass == CLASS_TYPE_ABERRATION) sCombatAI = "ai_a_default"; + //else if(nClass == CLASS_TYPE_ANIMAL) sCombatAI = "ai_a_animal"; + //else if(nClass == CLASS_TYPE_CONSTRUCT) sCombatAI = "ai_a_animal"; + //else if(nClass == CLASS_TYPE_DRAGON) sCombatAI = "ai_a_dragon"; + //else if(nClass == CLASS_TYPE_ELEMENTAL) sCombatAI = "ai_a_default"; + //else if(nClass == CLASS_TYPE_FEY) sCombatAI = "ai_a_default"; + //else if(nClass == CLASS_TYPE_GIANT) sCombatAI = "ai_a_default"; + //else if(nClass == CLASS_TYPE_HUMANOID) sCombatAI = "ai_a_default"; + //else if(nClass == CLASS_TYPE_MAGICAL_BEAST) sCombatAI = "ai_a_default"; + //else if(nClass == CLASS_TYPE_MONSTROUS) sCombatAI = "ai_a_default"; + //else if(nClass == CLASS_TYPE_OOZE) sCombatAI = "ai_a_default"; + //else if(nClass == CLASS_TYPE_OUTSIDER) sCombatAI = "ai_a_default"; + //else if(nClass == CLASS_TYPE_UNDEAD) sCombatAI = "ai_a_default"; + //else if(nClass == CLASS_TYPE_VERMIN) sCombatAI = "ai_a_animal"; + else sCombatAI = "ai_a_default"; + } + if(AI_DEBUG) ai_Debug("0i_associates", "530", GetName(oCreature) + " is setting AI to " + sCombatAI); + SetLocalString(oCreature, AI_COMBAT_SCRIPT, sCombatAI); + SetLocalString(oCreature, AI_DEFAULT_SCRIPT, sCombatAI); +} +int ai_CanISpeak (object oCreature) +{ + int nRace = GetRacialType (oCreature); + if (nRace == RACIAL_TYPE_ANIMAL || nRace == RACIAL_TYPE_BEAST || + nRace == RACIAL_TYPE_CONSTRUCT || nRace == RACIAL_TYPE_OOZE) return FALSE; + return (GetAbilityScore (oCreature, ABILITY_INTELLIGENCE) > 7); +} +void ai_FireHenchman(object oPC, object oHenchman) +{ + if(oPC == OBJECT_INVALID || oHenchman == OBJECT_INVALID) return; + // Now double-check that this is actually our master + if(GetMaster(oHenchman) != oPC) return; + // Turn off stealth mode + SetActionMode(oHenchman, ACTION_MODE_STEALTH, FALSE); + // Remove the henchman + RemoveHenchman (oPC, oHenchman); + ChangeToStandardFaction(oHenchman, STANDARD_FACTION_DEFENDER); +} +void ai_HenchmanCastDefensiveSpells (object oCreature, object oPC) +{ + ai_CastBuffs(oCreature, 3, 0, oPC); +} +int ai_CheckForCombat(object oCreature, int bMonster) +{ + object oEnemy = ai_GetNearestEnemy(oCreature, 1, 7, 7, 7, 5, TRUE); + //object oEnemy = ai_GetNearestEnemy(oCreature, 1, -1, -1, -1, -1, TRUE); + if(AI_DEBUG) ai_Debug("0i_associate", "586", "Checking for Combat: oEnemy is " + GetName(oEnemy) + + " Distance: " + FloatToString(GetDistanceBetween(oEnemy, oCreature), 0, 2)); + if(oEnemy != OBJECT_INVALID) + { + float fPerceptionDistance, fDistance; + if(bMonster) + { + fDistance = GetDistanceBetween(oCreature, oEnemy); + fPerceptionDistance = GetLocalFloat(GetModule(), AI_RULE_PERCEPTION_DISTANCE); + } + else + { + // We want to use the distance between the PC and target not us. + object oMaster = GetMaster(); + if(oMaster != OBJECT_INVALID) fDistance = GetDistanceBetween(oMaster, oEnemy); + else fDistance = GetDistanceBetween(oCreature, oEnemy); + fPerceptionDistance = GetLocalFloat(oCreature, AI_ASSOC_PERCEPTION_DISTANCE); + if(fPerceptionDistance == 0.0) fPerceptionDistance = 20.0; + } + if(fDistance < fPerceptionDistance) + { + ai_HaveCreatureSpeak(oCreature, 5, ":0:1:2:3:6:"); + SetLocalObject (oCreature, AI_MY_TARGET, oEnemy); + SpeakString(AI_I_SEE_AN_ENEMY, TALKVOLUME_SILENT_TALK); + if(bMonster) ai_StartMonsterCombat(oCreature); + else if(ai_CanIAttack(oCreature)) ai_StartAssociateCombat(oCreature); + return TRUE; + } + } + return FALSE; +} +void ai_AssociateEvaluateNewThreat(object oCreature, object oLastPerceived, string sPerception) +{ + if(!ai_CanIAttack(oCreature)) return; + int nAction = GetCurrentAction(oCreature); + if(AI_DEBUG) ai_Debug("0i_associates", "775", "Our current action: " + IntToString(nAction)); + switch(nAction) + { + // These actions are uninteruptable. + case ACTION_CASTSPELL : + case ACTION_ITEMCASTSPELL : + case ACTION_COUNTERSPELL : return; + // Might be doing a special action that is not a defined action. + case ACTION_INVALID : + { + int nCombatWait = GetLocalInt(oCreature, AI_COMBAT_WAIT_IN_SECONDS); + if(AI_DEBUG) ai_Debug("0i_associate", "761", "Doing a special action (nCombatWait): " + IntToString(nCombatWait)); + if(nCombatWait) + { + if(ai_IsInCombatRound(oCreature, nCombatWait)) return; + DeleteLocalInt(oCreature, AI_COMBAT_WAIT_IN_SECONDS); + } + } + // We need to reevaluate combat during these actions when we see a new enemy. + //case ACTION_ATTACKOBJECT : + //case ACTION_MOVETOPOINT : + } + if(ai_GetIsInCombat(oCreature)) + { + object oTarget = ai_GetAttackedTarget(oCreature); + if(AI_DEBUG) ai_Debug("0i_associates", "775", "Should we recalculate our combat round? oTarget: " + GetName(oTarget) + + " oTarget Distance: " + FloatToString(GetDistanceBetween(oCreature, oTarget), 0, 2) + + " oLastPerceived Distance: " + FloatToString(GetDistanceBetween(oCreature, oLastPerceived), 0, 2)); + // If the LastPerceived is our target then don't recalculate. + if(oTarget == oLastPerceived) return; + // If we don't have a target or the lastperceived is closer than our + // target then recalculate. + if(oTarget == OBJECT_INVALID || + GetDistanceBetween(oCreature, oTarget) > GetDistanceBetween(oCreature, oLastPerceived)) + { + // We should clear any skill cooldowns that are at at max since that means they were skipped. + if(GetLocalInt(oCreature, "AI_EMPATHY_COOLDOWN") == AI_EMPATHY_COOLDOWN) + { DeleteLocalInt(oCreature, "AI_EMPATHY_COOLDOWN"); } + else if (GetLocalInt(oCreature, "AI_TAUNT_COOLDOWN") == AI_TAUNT_COOLDOWN) + { DeleteLocalInt(oCreature, "AI_EMPATHY_COOLDOWN"); } + ai_DoAssociateCombatRound(oCreature); + return; + } + // Lets only reevaluate combat if the new enemy is more powerful + // than the average enemies we already know about. + int nPower = ai_GetCharacterLevels(oLastPerceived) / 2; + int nEnemyPower = GetLocalInt(oCreature, AI_ENEMY_POWER) / (GetLocalInt(oCreature, AI_ENEMY_NUMBERS) + 1); + if(AI_DEBUG) ai_Debug("0i_associates", "797", " Is the new opponent more powerful? " + + GetName(oLastPerceived) + " nPower: " + IntToString(nPower) + + " nEnemyPower: " + IntToString(nEnemyPower)); + if(nEnemyPower < nPower) ai_DoAssociateCombatRound(oCreature); + return; + } + // Heard fires first, but Heard and Seen are both set at the same time. + // So lets skip the hearing code if they are also seen. + if(sPerception == AI_I_SEE_AN_ENEMY || GetObjectSeen(oLastPerceived, oCreature)) + { + // We are not in combat and we see the enemy so alert our allies! + ai_HaveCreatureSpeak(oCreature, 5, ":0:1:2:3:6:"); + SetLocalObject (oCreature, AI_MY_TARGET, oLastPerceived); + SpeakString(sPerception, TALKVOLUME_SILENT_TALK); + ai_StartAssociateCombat(oCreature); + } + else ai_FindTheEnemy(oCreature, oLastPerceived, oLastPerceived, FALSE); +} +void ai_MonsterEvaluateNewThreat(object oCreature, object oLastPerceived, string sPerception) +{ + if(!ai_CanIAttack(oCreature)) return; + int nAction = GetCurrentAction(oCreature); + if(AI_DEBUG) ai_Debug("0i_associates", "672", "nAction: " + IntToString(nAction)); + switch(nAction) + { + // These actions are uninteruptable. + case ACTION_CASTSPELL : + case ACTION_ITEMCASTSPELL : + case ACTION_COUNTERSPELL : return; + // Might be doing a special action that is not a defined action. + case ACTION_INVALID : + { + int nCombatWait = GetLocalInt(oCreature, AI_COMBAT_WAIT_IN_SECONDS); + if(AI_DEBUG) ai_Debug("0i_associates", "683", "nCombatWait: " + IntToString(nCombatWait)); + if(nCombatWait) + { + if(ai_IsInCombatRound(oCreature, nCombatWait)) return; + DeleteLocalInt(oCreature, AI_COMBAT_WAIT_IN_SECONDS); + } + } + // We need to reevaluate combat during these actions when we see a new enemy. + //case ACTION_ATTACKOBJECT : + //case ACTION_MOVETOPOINT : + } + if(ai_GetIsInCombat(oCreature)) + { + object oTarget = ai_GetAttackedTarget(oCreature); + if(AI_DEBUG) ai_Debug("0i_associates", "697", "oTarget: " + GetName(oTarget) + + " oTarget Distance: " + FloatToString(GetDistanceBetween(oCreature, oTarget), 0, 2) + + " oLastPerceived Distance: " + FloatToString(GetDistanceBetween(oCreature, oLastPerceived), 0, 2)); + // If the LastPerceived is our target then don't recalculate. + if(oTarget == oLastPerceived) return; + // If we don't have a target or the lastperceived is closer than our + // target then recalculate. + if(oTarget == OBJECT_INVALID || + GetDistanceBetween(oCreature, oTarget) > GetDistanceBetween(oCreature, oLastPerceived)) + { + ai_DoMonsterCombatRound(oCreature); + return; + } + // Now only reevaluate combat if the new enemy is more powerful + // than the average enemies we already know about. + int nPower = ai_GetCharacterLevels(oLastPerceived) / 2; + int nEnemyPower = GetLocalInt(oCreature, AI_ENEMY_POWER) / (GetLocalInt(oCreature, AI_ENEMY_NUMBERS) + 1); + if(AI_DEBUG) ai_Debug("0i_associates", "714", GetName(oLastPerceived) + " nPower: " + IntToString(nPower) + + " nEnemyPower: " + IntToString(nEnemyPower)); + if(nEnemyPower < nPower) ai_DoMonsterCombatRound(oCreature); + return; + } + if(sPerception == AI_I_SEE_AN_ENEMY) + { + if(d100() < 34) + { + // We are not in combat so alert our allies! + ai_HaveCreatureSpeak(oCreature, 5, ":0:1:2:3:6:"); + } + SetLocalObject(oCreature, AI_MY_TARGET, oLastPerceived); + SpeakString(sPerception, TALKVOLUME_SILENT_TALK); + ai_StartMonsterCombat(oCreature); + } + else ai_FindTheEnemy(oCreature, oLastPerceived, oLastPerceived, TRUE); +} +void ai_CopyObjectVariables(object oOldObject, object oNewObject) +{ + json jObject = ObjectToJson(oOldObject, TRUE); + json jVarTable = GffGetList(jObject, "VarTable"); + string sVariable, sName; + int nIndex, nVarType; + json jVar = JsonArrayGet(jVarTable, nIndex); + while(JsonGetType(jVar) != JSON_TYPE_NULL) + { + sName = JsonGetString(GffGetString(jVar, "Name")); + nVarType = JsonGetInt(GffGetDword(jVar, "Type")); + if(nVarType == 1) SetLocalInt(oNewObject, sName, JsonGetInt(GffGetInt(jVar, "Value"))); + else if(nVarType == 2) SetLocalFloat(oNewObject, sName, JsonGetFloat(GffGetFloat(jVar, "Value"))); + else if(nVarType == 3) SetLocalString(oNewObject, sName, JsonGetString(GffGetString(jVar, "Value"))); + jVar = JsonArrayGet(jVarTable, ++nIndex); + } +} +//****************************************************************************** +//********************* Creature event scripts ********************************* +//****************************************************************************** + +void ai_OnRested(object oCreature) +{ + if(ai_GetMagicMode(oCreature, AI_MAGIC_BUFF_AFTER_REST)) + { + int nLevel = ai_GetCharacterLevels(oCreature); + float fDelay = StringToFloat(Get2DAString("restduration", "DURATION", nLevel)); + fDelay = (fDelay / 1000.0f) + 2.0f; + DelayCommand(fDelay, ai_HenchmanCastDefensiveSpells(oCreature, GetMaster())); + } +} + +//****************************************************************************** +//******************* Associate AI option scripts ****************************** +//****************************************************************************** +void ai_UpdateToolTipUI(object oPC, string sWindowID1, string sWindowID2, string sToolTipBind, string sText) +{ + int nMenuToken = NuiFindWindow(oPC, sWindowID1); + if(nMenuToken) NuiSetBind (oPC, nMenuToken, sToolTipBind, JsonString (sText)); + if(sWindowID2 != "") + { + int nWidgetToken = NuiFindWindow(oPC, sWindowID2); + if(nWidgetToken) NuiSetBind (oPC, nWidgetToken, sToolTipBind, JsonString (sText)); + } +} +void ai_FollowIncrement(object oPC, object oAssociate, float fIncrement, string sAssociateType) +{ + float fAdjustment = GetLocalFloat(oAssociate, AI_FOLLOW_RANGE) + fIncrement; + if(fAdjustment > 10.0) fAdjustment = 10.0; + else if(fAdjustment < 1.0) fAdjustment = 1.0; + SetLocalFloat(oAssociate, AI_FOLLOW_RANGE, fAdjustment); + json jAIData = ai_GetAssociateDbJson(oPC, sAssociateType, "aidata"); + jAIData = JsonArraySet(jAIData, 6, JsonFloat(fAdjustment)); + ai_SetAssociateDbJson(oPC, sAssociateType, "aidata", jAIData); + string sName; + object oTarget = GetLocalObject(oAssociate, AI_FOLLOW_TARGET); + string sTarget; + if(oTarget != OBJECT_INVALID) sTarget = GetName(oTarget); + else + { + if(ai_GetIsCharacter(oAssociate)) sTarget = "nobody"; + else sTarget = GetName(oPC); + } + float fRange = fAdjustment + + StringToFloat(Get2DAString("appearance", "PREFATCKDIST", GetAppearanceType(oAssociate))); + string sRange = FloatToString(fRange, 0, 0); + if(oPC == oAssociate) + { + sName = " All associates"; + ai_UpdateToolTipUI(oPC, sAssociateType + AI_COMMAND_NUI, sAssociateType + AI_WIDGET_NUI, "btn_cmd_follow_tooltip", sName + " enter follow mode "); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_COMMAND_NUI, sAssociateType + AI_WIDGET_NUI, "btn_follow_target_tooltip", " " + GetName(oAssociate) + " following " + sTarget + " [" + sRange + " meters]"); + } + else + { + sName = " " + GetName(oAssociate); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_COMMAND_NUI, sAssociateType + AI_WIDGET_NUI, "btn_cmd_follow_tooltip", sName + " enter follow mode [" + sRange + " meters]"); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_COMMAND_NUI, sAssociateType + AI_WIDGET_NUI, "btn_follow_target_tooltip", " " + GetName(oAssociate) + " following " + sTarget + " [" + sRange + " meters]"); + } +} +void ai_Ranged(object oPC, object oAssociate, string sAssociateType) +{ + //ai_ClearCreatureActions(); + if(ai_GetAIMode(oAssociate, AI_MODE_STOP_RANGED)) + { + ai_SendMessages(GetName(oAssociate) + " is using ranged combat.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_ranged_tooltip", " Ranged On"); + ai_SetAIMode(oAssociate, AI_MODE_STOP_RANGED, FALSE); + ai_EquipBestRangedWeapon(oAssociate); + } + else + { + ai_SendMessages(GetName(oAssociate) + " is using melee combat only.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_ranged_tooltip", " Ranged Off"); + ai_SetAIMode(oAssociate, AI_MODE_STOP_RANGED, TRUE); + ai_EquipBestMeleeWeapon(oAssociate); + } + aiSaveAssociateModesToDb(oPC, oAssociate); +} +void ai_EquipWeapons(object oPC, object oAssociate, string sAssociateType) +{ + if(ai_GetAIMode(oAssociate, AI_MODE_EQUIP_WEAPON_OFF)) + { + ai_SendMessages(GetName(oAssociate) + " will be equiping their best weapons.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_equip_weapon_tooltip", " Equiping Best Weapons On"); + ai_SetAIMode(oAssociate, AI_MODE_EQUIP_WEAPON_OFF, FALSE); + } + else + { + ai_SendMessages(GetName(oAssociate) + " will not equip their best weapons.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_equip_weapon_tooltip", " Equiping Best Weapons Off"); + ai_SetAIMode(oAssociate, AI_MODE_EQUIP_WEAPON_OFF, TRUE); + } + aiSaveAssociateModesToDb(oPC, oAssociate); +} +void ai_Search(object oPC, object oAssociate, string sAssociateType) +{ + if(ai_GetAIMode(oAssociate, AI_MODE_AGGRESSIVE_SEARCH)) + { + ai_SendMessages(GetName(oAssociate) + " is turning search off.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_search_tooltip", " Search mode Off"); + SetActionMode(oAssociate, ACTION_MODE_DETECT, FALSE); + ai_SetAIMode(oAssociate, AI_MODE_AGGRESSIVE_SEARCH, FALSE); + } + else + { + ai_SendMessages(GetName(oAssociate) + " is turning search on.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_search_tooltip", " Search mode On"); + SetActionMode(oAssociate, ACTION_MODE_DETECT, TRUE); + ai_SetAIMode(oAssociate, AI_MODE_AGGRESSIVE_SEARCH, TRUE); + } + aiSaveAssociateModesToDb(oPC, oAssociate); +} +void ai_Stealth(object oPC, object oAssociate, string sAssociateType) +{ + if(ai_GetAIMode(oAssociate, AI_MODE_AGGRESSIVE_STEALTH)) + { + ai_SendMessages(GetName(oAssociate) + " is turning stealth off.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_stealth_tooltip", " Stealth mode Off"); + SetActionMode(oAssociate, ACTION_MODE_STEALTH, FALSE); + ai_SetAIMode(oAssociate, AI_MODE_AGGRESSIVE_STEALTH, FALSE); + } + else + { + ai_SendMessages(GetName(oAssociate) + " is turning stealth on.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_stealth_tooltip", " Stealth mode On"); + SetActionMode(oAssociate, ACTION_MODE_STEALTH, TRUE); + ai_SetAIMode(oAssociate, AI_MODE_AGGRESSIVE_STEALTH, TRUE); + } + aiSaveAssociateModesToDb(oPC, oAssociate); +} +void ai_OpenDoor(object oPC, object oAssociate, string sAssociateType) +{ + string sRange = FloatToString(GetLocalFloat(oAssociate, AI_OPEN_DOORS_RANGE), 0, 0); + if(ai_GetAIMode(oAssociate, AI_MODE_OPEN_DOORS)) + { + ai_SendMessages(GetName(oAssociate) + " is turning open doors off.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_open_door_tooltip", " Open Doors Off [" + sRange + " meters]"); + ai_SetAIMode(oAssociate, AI_MODE_OPEN_DOORS, FALSE); + } + else + { + ai_SendMessages(GetName(oAssociate) + " is turning open doors on.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_open_door_tooltip", " Open Doors On [" + sRange + " meters]"); + ai_SetAIMode(oAssociate, AI_MODE_OPEN_DOORS, TRUE); + } + aiSaveAssociateModesToDb(oPC, oAssociate); +} +void ai_Locks(object oPC, object oAssociate, string sAssociateType, int nMode) +{ + string sRange = FloatToString(GetLocalFloat(oAssociate, AI_LOCK_CHECK_RANGE), 0, 0); + if(nMode == 1) + { + if(ai_GetAIMode(oAssociate, AI_MODE_PICK_LOCKS)) + { + ai_SendMessages(GetName(oAssociate) + " will stop picking locks.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_pick_locks_tooltip", " Pick Locks Off [" + sRange + " meters]"); + ai_SetAIMode(oAssociate, AI_MODE_PICK_LOCKS, FALSE); + } + else + { + ai_SendMessages(GetName(oAssociate) + " will now pick locks.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_pick_locks_tooltip", " Pick Locks On [" + sRange + " meters]"); + ai_SetAIMode(oAssociate, AI_MODE_PICK_LOCKS, TRUE); + } + } + else if(nMode == 2) + { + if(ai_GetAIMode(oAssociate, AI_MODE_BASH_LOCKS)) + { + ai_SendMessages(GetName(oAssociate) + " will stop bashing.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_bash_locks_tooltip", " Bash Locks Off [" + sRange + " meters]"); + ai_SetAIMode(oAssociate, AI_MODE_BASH_LOCKS, FALSE); + } + else + { + ai_SendMessages(GetName(oAssociate) + " will now bash things.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_bash_locks_tooltip", " Bash Locks On [" + sRange + " meters]"); + ai_SetAIMode(oAssociate, AI_MODE_BASH_LOCKS, TRUE); + } + } + aiSaveAssociateModesToDb(oPC, oAssociate); +} +void ai_Traps(object oPC, object oAssociate, string sAssociateType) +{ + string sRange = FloatToString(GetLocalFloat(oAssociate, AI_TRAP_CHECK_RANGE), 0, 0); + if(ai_GetAIMode(oAssociate, AI_MODE_DISARM_TRAPS)) + { + ai_SendMessages(GetName(oAssociate) + " will stop disarming traps.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_traps_tooltip", " Disable Traps Off [" + sRange + " meters]"); + ai_SetAIMode(oAssociate, AI_MODE_DISARM_TRAPS, FALSE); + } + else + { + ai_SendMessages(GetName(oAssociate) + " will now disarm traps.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_traps_tooltip", " Disable Traps On [" + sRange + " meters]"); + ai_SetAIMode(oAssociate, AI_MODE_DISARM_TRAPS, TRUE); + } + aiSaveAssociateModesToDb(oPC, oAssociate); +} +void ai_ReduceSpeech(object oPC, object oAssociate, string sAssociateType) +{ + if(ai_GetAIMode(oAssociate, AI_MODE_DO_NOT_SPEAK)) + { + ai_SendMessages(GetName(oAssociate) + " will increase speech.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_quiet_tooltip", " Reduced Speech Off"); + ai_SetAIMode(oAssociate, AI_MODE_DO_NOT_SPEAK, FALSE); + } + else + { + ai_SendMessages(GetName(oAssociate) + " will reduce speech.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_quiet_tooltip", " Reduced Speech On"); + ai_SetAIMode(oAssociate, AI_MODE_DO_NOT_SPEAK, TRUE); + } + aiSaveAssociateModesToDb(oPC, oAssociate); +} +void ai_UseOffensiveMagic(object oPC, object oAssociate, int bDefensive, int bOffensive, string sAssociateType) +{ + if(bOffensive) + { + if(ai_GetMagicMode(oAssociate, AI_MAGIC_OFFENSIVE_CASTING)) + { + ai_SendMessages(GetName(oAssociate) + " has stopped using offensive magic in combat.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_off_magic_tooltip", " Offensive Magic Off"); + ai_SetMagicMode(oAssociate, AI_MAGIC_OFFENSIVE_CASTING, FALSE); + } + else + { + ai_SendMessages(GetName(oAssociate) + " is now using offensive magic in combat.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_off_magic_tooltip", " Offensive Magic On"); + ai_SetMagicMode(oAssociate, AI_MAGIC_OFFENSIVE_CASTING, TRUE); + } + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_def_magic_tooltip", " Defensive Magic Off"); + ai_SetMagicMode(oAssociate, AI_MAGIC_DEFENSIVE_CASTING, FALSE); + } + else if(bDefensive) + { + if(ai_GetMagicMode(oAssociate, AI_MAGIC_DEFENSIVE_CASTING)) + { + ai_SendMessages(GetName(oAssociate) + " has stopped using defensive magic in combat.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_def_magic_tooltip", " Defensive Magic Off"); + ai_SetMagicMode(oAssociate, AI_MAGIC_DEFENSIVE_CASTING, FALSE); + } + else + { + ai_SendMessages(GetName(oAssociate) + " is now using defensive magic in combat.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_def_magic_tooltip", " Defensive Magic On"); + ai_SetMagicMode(oAssociate, AI_MAGIC_DEFENSIVE_CASTING, TRUE); + } + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_off_magic_tooltip", " Offensive Magic Off"); + ai_SetMagicMode(oAssociate, AI_MAGIC_OFFENSIVE_CASTING, FALSE); + } + aiSaveAssociateModesToDb(oPC, oAssociate); +} +void ai_UseMagic(object oPC, object oAssociate, string sAssociateType) +{ + if(ai_GetMagicMode(oAssociate, AI_MAGIC_NO_MAGIC)) + { + ai_SendMessages(GetName(oAssociate) + " is now using magic in combat.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_magic_tooltip", " Magic On"); + ai_SetMagicMode(oAssociate, AI_MAGIC_NO_MAGIC, FALSE); + } + else + { + ai_SendMessages(GetName(oAssociate) + " has stopped using magic in combat.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_magic_tooltip", " Magic Off"); + ai_SetMagicMode(oAssociate, AI_MAGIC_NO_MAGIC, TRUE); + } + aiSaveAssociateModesToDb(oPC, oAssociate); +} +void ai_UseMagicItems(object oPC, object oAssociate, string sAssociateType) +{ + if(ai_GetMagicMode(oAssociate, AI_MAGIC_NO_MAGIC_ITEMS)) + { + ai_SendMessages(GetName(oAssociate) + " is now using magic items in combat.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_magic_items_tooltip", " Magic Items On"); + ai_SetMagicMode(oAssociate, AI_MAGIC_NO_MAGIC_ITEMS, FALSE); + } + else + { + ai_SendMessages(GetName(oAssociate) + " has stopped using magic items in combat.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_magic_items_tooltip", " Magic Items Off"); + ai_SetMagicMode(oAssociate, AI_MAGIC_NO_MAGIC_ITEMS, TRUE); + } + aiSaveAssociateModesToDb(oPC, oAssociate); +} +void ai_Loot(object oPC, object oAssociate, string sAssociateType) +{ + int bLooting = !ai_GetAIMode(oAssociate, AI_MODE_PICKUP_ITEMS); + string sRange = FloatToString(GetLocalFloat(oAssociate, AI_LOOT_CHECK_RANGE), 0, 0); + string sMessage, sText; + if(bLooting) + { + sMessage = " is picking up items."; + sText = " Looting On [" + sRange + " meters]"; + } + else + { + sMessage = " is not picking up items."; + sText = " Looting Off [" + sRange + " meters]"; + } + ai_SendMessages(GetName(oAssociate) + sMessage, AI_COLOR_YELLOW, oPC); + ai_SetAIMode(oAssociate, AI_MODE_PICKUP_ITEMS, bLooting); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_loot_tooltip", sText); + aiSaveAssociateModesToDb(oPC, oAssociate); +} +void ai_Spontaneous(object oPC, object oAssociate, string sAssociateType) +{ + int bSpontaneous = !ai_GetMagicMode(oAssociate, AI_MAGIC_NO_SPONTANEOUS_CURE); + string sMessage, sText; + + if(bSpontaneous) + { + sMessage = " has stop casting spontaneous healing spells."; + sText = " Spontaneous casting Off"; + } + else + { + sMessage = " will now cast spontaneous healing spells."; + sText = " Spontaneous casting On"; + } + ai_SendMessages(GetName(oAssociate) + sMessage, AI_COLOR_YELLOW, oPC); + ai_SetMagicMode(oAssociate, AI_MAGIC_NO_SPONTANEOUS_CURE, bSpontaneous); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_spontaneous_tooltip", sText); + aiSaveAssociateModesToDb(oPC, oAssociate); +} +void ai_MagicIncrement(object oPC, object oAssociate, int nIncrement, string sAssociateType) +{ + int nAdjustment = GetLocalInt(oAssociate, AI_DIFFICULTY_ADJUSTMENT) + nIncrement; + if(nAdjustment > 100) nAdjustment = 100; + else if(nAdjustment < -100) nAdjustment = -100; + SetLocalInt(oAssociate, AI_DIFFICULTY_ADJUSTMENT, nAdjustment); + json jAIData = ai_GetAssociateDbJson(oPC, sAssociateType, "aidata"); + jAIData = JsonArraySet(jAIData, 0, JsonInt(nAdjustment)); + ai_SetAssociateDbJson(oPC, sAssociateType, "aidata", jAIData); + string sMagic = IntToString(nAdjustment); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_magic_level_tooltip", " Magic Level [" + sMagic + "]"); +} +void ai_LootRangeIncrement(object oPC, object oAssociate, float fIncrement, string sAssociateType) +{ + float fAdjustment = GetLocalFloat(oAssociate, AI_LOOT_CHECK_RANGE) + fIncrement; + if(fAdjustment > 40.0) fAdjustment = 40.0; + else if(fAdjustment < 0.0) fAdjustment = 0.0; + SetLocalFloat(oAssociate, AI_LOOT_CHECK_RANGE, fAdjustment); + json jAIData = ai_GetAssociateDbJson(oPC, sAssociateType, "aidata"); + jAIData = JsonArraySet(jAIData, 3, JsonFloat(fAdjustment)); + ai_SetAssociateDbJson(oPC, sAssociateType, "aidata", jAIData); + string sRange = FloatToString(fAdjustment, 0, 0); + string sLoot = " Looting Off [" + sRange + " meters]"; + if(ai_GetAIMode(oAssociate, AI_MODE_PICKUP_ITEMS)) sLoot = " Looting On [" + sRange + " meters]"; + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_loot_tooltip", sLoot); +} +void ai_LockRangeIncrement(object oPC, object oAssociate, float fIncrement, string sAssociateType) +{ + float fAdjustment = GetLocalFloat(oAssociate, AI_LOCK_CHECK_RANGE) + fIncrement; + if(fAdjustment > 40.0) fAdjustment = 40.0; + else if(fAdjustment < 0.0) fAdjustment = 0.0; + SetLocalFloat(oAssociate, AI_LOCK_CHECK_RANGE, fAdjustment); + json jAIData = ai_GetAssociateDbJson(oPC, sAssociateType, "aidata"); + jAIData = JsonArraySet(jAIData, 4, JsonFloat(fAdjustment)); + ai_SetAssociateDbJson(oPC, sAssociateType, "aidata", jAIData); + string sRange = FloatToString(fAdjustment, 0, 0); + string sPick = " Pick Locks Off [" + sRange + " meters]"; + string sBash = " Bash Off [" + sRange + " meters]"; + if(ai_GetAIMode(oAssociate, AI_MODE_PICK_LOCKS)) sPick = " Pick Locks On [" + sRange + " meters]"; + if(ai_GetAIMode(oAssociate, AI_MODE_BASH_LOCKS)) sBash = " Bash On [" + sRange + " meters]"; + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_pick_locks_tooltip", sPick); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_bash_locks_tooltip", sBash); +} +void ai_TrapRangeIncrement(object oPC, object oAssociate, float fIncrement, string sAssociateType) +{ + float fAdjustment = GetLocalFloat(oAssociate, AI_TRAP_CHECK_RANGE) + fIncrement; + if(fAdjustment > 40.0) fAdjustment = 40.0; + else if(fAdjustment < 0.0) fAdjustment = 0.0; + SetLocalFloat(oAssociate, AI_TRAP_CHECK_RANGE, fAdjustment); + json jAIData = ai_GetAssociateDbJson(oPC, sAssociateType, "aidata"); + jAIData = JsonArraySet(jAIData, 5, JsonFloat(fAdjustment)); + ai_SetAssociateDbJson(oPC, sAssociateType, "aidata", jAIData); + string sRange = FloatToString(fAdjustment, 0, 0); + string sText = " Disable Traps Off [" + sRange + " meters]"; + if(ai_GetAIMode(oAssociate, AI_MODE_DISARM_TRAPS)) sText = " Disable Traps On [" + sRange + " meters]"; + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_traps_tooltip", sText); +} +void ai_OpenDoorIncrement(object oPC, object oAssociate, float fIncrement, string sAssociateType) +{ + float fAdjustment = GetLocalFloat(oAssociate, AI_OPEN_DOORS_RANGE) + fIncrement; + if(fAdjustment > 40.0) fAdjustment = 40.0; + else if(fAdjustment < 0.0) fAdjustment = 0.0; + SetLocalFloat(oAssociate, AI_OPEN_DOORS_RANGE, fAdjustment); + json jAIData = ai_GetAssociateDbJson(oPC, sAssociateType, "aidata"); + jAIData = JsonArraySet(jAIData, 9, JsonFloat(fAdjustment)); + ai_SetAssociateDbJson(oPC, sAssociateType, "aidata", jAIData); + string sRange = FloatToString(fAdjustment, 0, 0); + string sText = " Open Doors Off [" + sRange + " meters]"; + if(ai_GetAIMode(oAssociate, AI_MODE_OPEN_DOORS)) sText = " Open Doors On [" + sRange + " meters]"; + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_open_door_tooltip", sText); +} +void ai_SaveAIScript(object oPC, object oAssociate, int nToken) +{ + string sScript = JsonGetString(NuiGetBind(oPC, nToken, "txt_ai_script")); + string sOldScript = GetLocalString(oAssociate, AI_COMBAT_SCRIPT); + if(GetStringLeft(sScript, 5) != "ai_a_") ai_SendMessages(sScript + " does not have correct prefix it must have ai_a_ for associates! Did not change AI script.", AI_COLOR_RED, oPC); + else if(ResManGetAliasFor(sScript, RESTYPE_NCS) == "") + { + ai_SendMessages(sScript + " not found by ResMan! This is not a valid AI script.", AI_COLOR_RED, oPC); + } + else if(sScript != sOldScript) + { + SetLocalString(oAssociate, AI_COMBAT_SCRIPT, sScript); + SetLocalString(oAssociate, AI_DEFAULT_SCRIPT, sScript); + string sAssociateType = ai_GetAssociateType(oPC, oAssociate); + json jAIData = ai_GetAssociateDbJson(oPC, sAssociateType, "aidata"); + if(JsonGetType(JsonArrayGet(jAIData, 8)) == JSON_TYPE_NULL) jAIData = JsonArrayInsert(jAIData, JsonString(sScript)); + else jAIData = JsonArraySet(jAIData, 8, JsonString(sScript)); + ai_SetAssociateDbJson(oPC, sAssociateType, "aidata", jAIData); + ai_SendMessages(GetName(oAssociate) + " is now using " + sScript + " AI script!", AI_COLOR_GREEN, oPC); + } + else ai_SendMessages(GetName(oAssociate) + " is already using this script! Did not change AI script.", AI_COLOR_RED, oPC); +} +void ai_Buff_Button(object oPC, object oAssociate, int nOption, string sAssociateType) +{ + if(nOption == 0) + { + int bRestBuff = !ai_GetMagicMode(oAssociate, AI_MAGIC_BUFF_AFTER_REST); + ai_SetMagicMode(oAssociate, AI_MAGIC_BUFF_AFTER_REST, bRestBuff); + if(bRestBuff) + { + ai_SendMessages(GetName(oAssociate) + " will cast long buffs after resting.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_COMMAND_NUI, sAssociateType + AI_WIDGET_NUI, "btn_buff_rest_tooltip", " [On] Turn buffing after resting off."); + } + else + { + ai_SendMessages(GetName(oAssociate) + " will not cast long buffs after resting.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_COMMAND_NUI, sAssociateType + AI_WIDGET_NUI, "btn_buff_rest_tooltip", " [Off] Turn buffing after resting on."); + } + aiSaveAssociateModesToDb(oPC, oAssociate); + } + else + { + if(!GetIsPossessedFamiliar(oAssociate)) + { + object oEnemy = GetNearestEnemy(oAssociate); + //ai_Debug("0e_nui", "865", "oEnemy: " + GetName(oEnemy) + " fDistance: " + + // FloatToString(GetDistanceBetween(oAssociate, oEnemy), 0, 2)); + if(GetDistanceBetween(oAssociate, oEnemy) > 30.0 || + oEnemy == OBJECT_INVALID) + { + ai_CastBuffs(oAssociate, nOption, 0, oPC); + } + else ai_SendMessages("You cannot buff while there are enemies nearby.", AI_COLOR_RED, oPC); + } + else ai_SendMessages("You cannot buff while possessing your familiar.", AI_COLOR_RED, oPC); + } +} +void ai_Heal_Button(object oPC, object oAssociate, int nIncrement, string sVar, string sAssociateType) +{ + int nHeal = GetLocalInt(oAssociate, sVar); + if(nIncrement > 0 && nHeal > 100 - nIncrement) nHeal = 100 - nIncrement; + if(nIncrement < 0 && nHeal < abs(nIncrement)) nHeal = abs(nIncrement); + nHeal += nIncrement; + SetLocalInt(oAssociate, sVar, nHeal); + string sHeal = IntToString(nHeal); + json jAIData = ai_GetAssociateDbJson(oPC, sAssociateType, "aidata"); + if(sVar == AI_HEAL_OUT_OF_COMBAT_LIMIT) + { + string sText = " Will heal at or below [" + sHeal + "%] health out of combat"; + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_heal_out_tooltip", sText); + jAIData = JsonArraySet(jAIData, 1, JsonInt(nHeal)); + } + else if(sVar == AI_HEAL_IN_COMBAT_LIMIT) + { + string sText = " Will heal at or below [" + sHeal + "%] health in combat"; + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_heal_in_tooltip", sText); + jAIData = JsonArraySet(jAIData, 2, JsonInt(nHeal)); + } + ai_SetAssociateDbJson(oPC, sAssociateType, "aidata", jAIData); +} +void ai_Heal_OnOff(object oPC, object oAssociate, string sAssociateType, int nMode) +{ + string sText, sText2; + if(nMode == 1) + { + if(ai_GetAIMode(oAssociate, AI_MODE_SELF_HEALING_OFF)) + { + ai_SetAIMode(oAssociate, AI_MODE_SELF_HEALING_OFF, FALSE); + sText = " Self healing On"; + sText2 = " will now use healing on themselves."; + } + else + { + ai_SetAIMode(oAssociate, AI_MODE_SELF_HEALING_OFF, TRUE); + sText = " Self healing Off"; + sText2 = " will stop using healing on themselves."; + } + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_heals_onoff_tooltip", sText); + } + else + { + if(ai_GetAIMode(oAssociate, AI_MODE_PARTY_HEALING_OFF)) + { + ai_SetAIMode(oAssociate, AI_MODE_PARTY_HEALING_OFF, FALSE); + sText = " Party healing On"; + sText2 = " will now use healing on party members."; + } + else + { + ai_SetAIMode(oAssociate, AI_MODE_PARTY_HEALING_OFF, TRUE); + sText = " Party healing Off"; + sText2 = " will stop using healing on party members."; + } + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_healp_onoff_tooltip", sText); + } + ai_SendMessages(GetName(oAssociate) + sText2, AI_COLOR_YELLOW, oPC); + aiSaveAssociateModesToDb(oPC, oAssociate); +} +void ai_Cure_OnOff(object oPC, object oAssociate, string sAssociateType) +{ + if(ai_GetMagicMode(oAssociate, AI_MAGIC_CURE_SPELLS_OFF)) + { + ai_SendMessages(GetName(oAssociate) + " will now cast cure spells.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_cure_onoff_tooltip", " Cast Cure Spells On"); + ai_SetMagicMode(oAssociate, AI_MAGIC_CURE_SPELLS_OFF, FALSE); + } + else + { + ai_SendMessages(GetName(oAssociate) + " will stop casting cure spells.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_cure_onoff_tooltip", " Cast Cure Spells Off"); + ai_SetMagicMode(oAssociate, AI_MAGIC_CURE_SPELLS_OFF, TRUE); + } + aiSaveAssociateModesToDb(oPC, oAssociate); +} +void ai_Ignore_Associates(object oPC, object oAssociate, string sAssociateType) +{ + if(ai_GetAIMode(oAssociate, AI_MODE_IGNORE_ASSOCIATES)) + { + ai_SendMessages(GetName(oAssociate) + " will stop ignoring henchman's associates and enemy associates.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_ignore_assoc_tooltip", " Ignore Enemy Associates Off"); + ai_SetAIMode(oAssociate, AI_MODE_IGNORE_ASSOCIATES, FALSE); + } + else + { + ai_SendMessages(GetName(oAssociate) + " will now ignore henchman's associates and enemy associates.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_ignore_assoc_tooltip", " Ignore Enemy Associates On"); + ai_SetAIMode(oAssociate, AI_MODE_IGNORE_ASSOCIATES, TRUE); + } + aiSaveAssociateModesToDb(oPC, oAssociate); +} +void ai_Ignore_Traps(object oPC, object oAssociate, string sAssociateType) +{ + if(ai_GetAIMode(oAssociate, AI_MODE_IGNORE_TRAPS)) + { + ai_SendMessages(GetName(oAssociate) + " will stop ignoring traps on the floor and will stop moving when one is seen.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_ignore_traps_tooltip", " Ignore Floor Traps Off"); + ai_SetAIMode(oAssociate, AI_MODE_IGNORE_TRAPS, FALSE); + } + else + { + ai_SendMessages(GetName(oAssociate) + " will now ignore traps on the floor and will continue with their actions.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_ignore_traps_tooltip", " Ignore Floor Traps On"); + ai_SetAIMode(oAssociate, AI_MODE_IGNORE_TRAPS, TRUE); + } + aiSaveAssociateModesToDb(oPC, oAssociate); +} +void ai_FollowTarget(object oPC, object oAssociate) +{ + SetLocalObject(oPC, AI_TARGET_ASSOCIATE, oAssociate); + SetLocalString(oPC, AI_TARGET_MODE, "ASSOCIATE_FOLLOW_TARGET"); + EnterTargetingMode(oPC, OBJECT_TYPE_CREATURE, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK); +} +void ai_Original_Guard() +{ + ResetHenchmenState(); + //Companions will only attack the Masters Last Attacker + SetAssociateState(NW_ASC_MODE_DEFEND_MASTER); + SetAssociateState(NW_ASC_MODE_STAND_GROUND, FALSE); + object oMaster = GetMaster(); + object oLastAttacker = GetLastHostileActor(oMaster); + // * for some reason this is too often invalid. still the routine + // * works corrrectly + SetLocalInt(OBJECT_SELF, "X0_BATTLEJOINEDMASTER", TRUE); + HenchmenCombatRound(oLastAttacker); + ai_SendMessages(GetName(OBJECT_SELF) + " is now guarding you!", AI_COLOR_YELLOW, oMaster); +} +void ai_Original_Follow() +{ + ResetHenchmenState(); + SetAssociateState(NW_ASC_MODE_STAND_GROUND, FALSE); + DelayCommand(2.5, VoiceCanDo()); + object oMaster = GetMaster(); + ActionForceFollowObject(oMaster, GetFollowDistance()); + SetAssociateState(NW_ASC_IS_BUSY); + DelayCommand(5.0, SetAssociateState(NW_ASC_IS_BUSY, FALSE)); + ai_SendMessages(GetName(OBJECT_SELF) + " is now following You!", AI_COLOR_YELLOW, oMaster); +} +void ai_Original_StandGround() +{ + SetAssociateState(NW_ASC_MODE_STAND_GROUND); + SetAssociateState(NW_ASC_MODE_DEFEND_MASTER, FALSE); + DelayCommand(2.0, VoiceCanDo()); + ActionAttack(OBJECT_INVALID); + ClearActions(CLEAR_X0_INC_HENAI_RespondToShout1); + ai_SendMessages(GetName(OBJECT_SELF) + " is now standing their ground!", AI_COLOR_YELLOW, GetMaster()); +} +void ai_Original_AttackNearest() +{ + ResetHenchmenState(); + SetAssociateState(NW_ASC_MODE_DEFEND_MASTER, FALSE); + SetAssociateState(NW_ASC_MODE_STAND_GROUND, FALSE); + DetermineCombatRound(); + // * bonus feature. If master is attacking a door or container, issues VWE Attack Nearest + // * will make henchman join in on the fun + object oMaster = GetMaster(); + object oTarget = GetAttackTarget(oMaster); + if (GetIsObjectValid(oTarget) == TRUE) + { + if (GetObjectType(oTarget) == OBJECT_TYPE_PLACEABLE || GetObjectType(oTarget) == OBJECT_TYPE_DOOR) + { + ActionAttack(oTarget); + } + } + ai_SendMessages(GetName(OBJECT_SELF) + " is now in normal mode!", AI_COLOR_YELLOW, oMaster); +} +void ai_Original_SetSearch(object oAssociate, int bTurnOn) +{ + if(GetRacialType(oAssociate) != RACIAL_TYPE_ELF) SetActionMode(oAssociate, ACTION_MODE_DETECT, bTurnOn); +} +void ai_Original_SetStealth(object oAssociate, int bTurnOn) +{ + SetActionMode(oAssociate, ACTION_MODE_STEALTH, bTurnOn); +} +void ai_Philos_Guard(object oMaster, object oCreature) +{ + ai_PassAIModeToAssociates(oCreature, AI_MODE_SCOUT_AHEAD, FALSE); + ai_PassAIModeToAssociates(oCreature, AI_MODE_DEFEND_MASTER, TRUE); + ai_PassAIModeToAssociates(oCreature, AI_MODE_STAND_GROUND, FALSE); + ai_PassAIModeToAssociates(oCreature, AI_MODE_FOLLOW, FALSE); + ai_SetAIMode(oCreature, AI_MODE_COMMANDED, FALSE); + int nToken = NuiFindWindow(oMaster, ai_GetAssociateType(oMaster, oCreature) + AI_WIDGET_NUI); + ai_HighlightWidgetMode(oMaster, oCreature, nToken); + if(!ai_GetIsBusy(oCreature) && ai_GetIsInCombat(oCreature)) + { + object oLastAttacker = GetLastHostileActor(oMaster); + if(oLastAttacker != OBJECT_INVALID) ai_DoAssociateCombatRound(oCreature, oLastAttacker); + else AssignCommand(oCreature, ActionMoveToObject(oMaster, TRUE)); + } + ai_SendMessages(GetName(oCreature) + " is now guarding you!", AI_COLOR_YELLOW, oMaster); + aiSaveAssociateModesToDb(oMaster, oCreature); +} +void ai_Philos_Follow(object oMaster) +{ + object oCreature = OBJECT_SELF; + ai_PassAIModeToAssociates(oCreature, AI_MODE_SCOUT_AHEAD, FALSE); + ai_PassAIModeToAssociates(oCreature, AI_MODE_STAND_GROUND, FALSE); + ai_PassAIModeToAssociates(oCreature, AI_MODE_FOLLOW, TRUE); + ai_SetAIMode(oCreature, AI_MODE_COMMANDED, FALSE); + int nToken = NuiFindWindow(oMaster, ai_GetAssociateType(oMaster, oCreature) + AI_WIDGET_NUI); + ai_HighlightWidgetMode(oMaster, oCreature, nToken); + aiSaveAssociateModesToDb(oMaster, oCreature); + // To follow we probably should be running and not searching or hiding. + if(GetDetectMode(oCreature) && !GetHasFeat(FEAT_KEEN_SENSE, oCreature)) SetActionMode(oCreature, ACTION_MODE_DETECT, FALSE); + if(GetStealthMode(oCreature)) SetActionMode(oCreature, ACTION_MODE_STEALTH, FALSE); + ai_PassActionToAssociates(oCreature, ACTION_FOLLOW); + if(ai_IsInCombatRound(oCreature)) ai_ClearCombatState(oCreature); + ai_ClearCreatureActions(TRUE); + object oTarget = GetLocalObject(oCreature, AI_FOLLOW_TARGET); + if(oTarget == OBJECT_INVALID) oTarget = oMaster; + ActionMoveToObject(oTarget, TRUE, ai_GetFollowDistance(oCreature)); + ai_SendMessages(GetName(oCreature) + " is now following " + GetName(oTarget) + "!", AI_COLOR_YELLOW, oMaster); +} +void ai_Philos_StandGround(object oMaster) +{ + object oCreature = OBJECT_SELF; + ai_PassAIModeToAssociates(oCreature, AI_MODE_SCOUT_AHEAD, FALSE); + ai_PassAIModeToAssociates(oCreature, AI_MODE_STAND_GROUND, TRUE); + ai_PassAIModeToAssociates(oCreature, AI_MODE_DEFEND_MASTER, FALSE); + ai_PassAIModeToAssociates(oCreature, AI_MODE_FOLLOW, FALSE); + ai_PassActionToAssociates(oCreature, ACTION_FOLLOW, FALSE); + ai_SetAIMode(oCreature, AI_MODE_COMMANDED, FALSE); + int nToken = NuiFindWindow(oMaster, ai_GetAssociateType(oMaster, oCreature) + AI_WIDGET_NUI); + ai_HighlightWidgetMode(oMaster, oCreature, nToken); + if(ai_IsInCombatRound(oCreature)) + { + ai_ClearCombatState(oCreature); + DeleteLocalObject(oCreature, AI_ATTACKED_PHYSICAL); + DeleteLocalObject(oCreature, AI_ATTACKED_SPELL); + } + ai_ClearCreatureActions(TRUE); + ai_SendMessages(GetName(oCreature) + " is now standing their ground!", AI_COLOR_YELLOW, oMaster); + aiSaveAssociateModesToDb(oMaster, oCreature); +} +void ai_Philos_AttackNearest(object oMaster, object oCreature) +{ + ai_PassAIModeToAssociates(oCreature, AI_MODE_SCOUT_AHEAD, FALSE); + ai_PassAIModeToAssociates(oCreature, AI_MODE_STAND_GROUND, FALSE); + ai_PassAIModeToAssociates(oCreature, AI_MODE_DEFEND_MASTER, FALSE); + ai_PassAIModeToAssociates(oCreature, AI_MODE_FOLLOW, FALSE); + ai_PassActionToAssociates(oCreature, ACTION_FOLLOW, FALSE); + ai_SetAIMode(oCreature, AI_MODE_COMMANDED, FALSE); + int nToken = NuiFindWindow(oMaster, ai_GetAssociateType(oMaster, oCreature) + AI_WIDGET_NUI); + ai_HighlightWidgetMode(oMaster, oCreature, nToken); + // Removes any targets the PC may have given the associate. + DeleteLocalObject(oCreature, AI_PC_LOCKED_TARGET); + // This resets a henchmens failed Moral save in combat. + string sScript = GetLocalString(oCreature, AI_COMBAT_SCRIPT); + if(sScript == "ai_coward") + { + sScript = GetLocalString(oCreature, AI_DEFAULT_SCRIPT); + SetLocalString(oCreature, AI_COMBAT_SCRIPT, sScript); + } + if(!ai_GetIsBusy(oCreature)) + { + object oEnemy = ai_GetNearestEnemy(oCreature, 1, 7, 7); + if(oEnemy != OBJECT_INVALID && GetDistanceBetween(oCreature, oEnemy) < AI_RANGE_BATTLEFIELD) + { + ai_HaveCreatureSpeak(oCreature, 5, ":0:1:2:3:6:"); + // If master is attacking a target we will attack them too! + if(!ai_GetIsInCombat(oCreature)) ai_StartAssociateCombat(oCreature); + object oTarget = ai_GetAttackedTarget(oMaster); + if(oTarget == OBJECT_INVALID) ai_DoAssociateCombatRound(oCreature); + else ai_DoAssociateCombatRound(oCreature, oTarget); + } + else + { + object oTarget = GetLocalObject(oCreature, AI_FOLLOW_TARGET); + if(oTarget == OBJECT_INVALID) oTarget = oMaster; + AssignCommand(oCreature, ActionMoveToObject(oMaster, TRUE, ai_GetFollowDistance(oCreature))); + } + } + ai_SendMessages(GetName(oCreature) + " is now in normal mode!", AI_COLOR_YELLOW, oMaster); + aiSaveAssociateModesToDb(oMaster, oCreature); +} +void ai_Philos_SetSearch(object oMaster, object oCreature, string sAssociateType, int bTurnOn) +{ + if(bTurnOn) + { + ai_SetAIMode(oCreature, AI_MODE_AGGRESSIVE_SEARCH, TRUE); + SetActionMode(oCreature, ACTION_MODE_DETECT, TRUE); + ai_PassActionToAssociates(oCreature, ACTION_MODE_DETECT, TRUE); + //ai_PassActionToAssociates(oCreature, ACTION_MODE_DETECT, TRUE); + ai_UpdateToolTipUI(oMaster, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_search_tooltip", " Search mode On"); + } + else + { + ai_SetAIMode(oCreature, AI_MODE_AGGRESSIVE_SEARCH, FALSE); + SetActionMode(oCreature, ACTION_MODE_DETECT, FALSE); + ai_PassActionToAssociates(oCreature, ACTION_MODE_DETECT, FALSE); + //ai_PassActionToAssociates(oCreature, ACTION_MODE_DETECT, FALSE); + ai_UpdateToolTipUI(oMaster, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_search_tooltip", " Search mode Off"); + } + aiSaveAssociateModesToDb(oMaster, oCreature); +} +void ai_Philos_SetStealth(object oMaster, object oCreature, string sAssociateType, int bTurnOn) +{ + if(bTurnOn) + { + ai_SetAIMode(oCreature, AI_MODE_AGGRESSIVE_STEALTH); + SetActionMode(oCreature, ACTION_MODE_STEALTH, TRUE); + ai_PassActionToAssociates(oCreature, ACTION_MODE_STEALTH, TRUE); + ai_UpdateToolTipUI(oMaster, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_stealth_tooltip", " Stealth mode On"); + } + else + { + ai_SetAIMode(oCreature, AI_MODE_AGGRESSIVE_STEALTH, FALSE); + SetActionMode(oCreature, ACTION_MODE_STEALTH, FALSE); + ai_PassActionToAssociates(oCreature, ACTION_MODE_STEALTH, FALSE); + //ai_PassActionToAssociates(oCreature, ACTION_MODE_STEALTH, FALSE); + ai_UpdateToolTipUI(oMaster, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_stealth_tooltip", " Stealth mode Off"); + } + aiSaveAssociateModesToDb(oMaster, oCreature); +} +void ai_DoCommand(object oPC, object oAssociate, int nCommand) +{ + int nIndex = 1; + if(oPC == oAssociate) + { + if(nCommand == 1) // Guard PC. + { + // Not using Philos Henchman AI. Use vanilla commands. + if(ResManGetAliasFor("ai_a_default", RESTYPE_NCS) == "") + { + for(nIndex = 1; nIndex <= AI_MAX_HENCHMAN; nIndex++) + { + oAssociate = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex); + if(oAssociate != OBJECT_INVALID) AssignCommand(oAssociate, ai_Original_Guard()); + } + for(nIndex = 2; nIndex < 6; nIndex++) + { + oAssociate = GetAssociate(nIndex, oPC); + if(oAssociate != OBJECT_INVALID) AssignCommand(oAssociate, ai_Original_Guard()); + } + } + // Use Philos AI commands. + else + { + for(nIndex = 1; nIndex <= AI_MAX_HENCHMAN; nIndex++) + { + oAssociate = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex); + if(oAssociate != OBJECT_INVALID) ai_Philos_Guard(oPC, oAssociate); + } + for(nIndex = 2; nIndex < 6; nIndex++) + { + oAssociate = GetAssociate(nIndex, oPC); + if(oAssociate != OBJECT_INVALID) ai_Philos_Guard(oPC, oAssociate); + } + } + } + else if(nCommand == 2) // Follow PC. + { + // Not using Philos Henchman AI. Use vanilla commands. + if(ResManGetAliasFor("ai_a_default", RESTYPE_NCS) == "") + { + for(nIndex = 1; nIndex <= AI_MAX_HENCHMAN; nIndex++) + { + oAssociate = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex); + if(oAssociate != OBJECT_INVALID) AssignCommand(oAssociate, ai_Original_Follow()); + } + for(nIndex = 2; nIndex < 6; nIndex++) + { + oAssociate = GetAssociate(nIndex, oPC); + if(oAssociate != OBJECT_INVALID) AssignCommand(oAssociate, ai_Original_Follow()); + } + } + // Use Philos AI commands. + else + { + for(nIndex = 1; nIndex <= AI_MAX_HENCHMAN; nIndex++) + { + oAssociate = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex); + if(oAssociate != OBJECT_INVALID) AssignCommand(oAssociate, ai_Philos_Follow(oPC)); + } + for(nIndex = 2; nIndex < 6; nIndex++) + { + oAssociate = GetAssociate(nIndex, oPC); + if(oAssociate != OBJECT_INVALID) AssignCommand(oAssociate, ai_Philos_Follow(oPC)); + } + } + } + else if(nCommand == 3) // Standground. + { + // Not using Philos Henchman AI. Use vanilla commands. + if(ResManGetAliasFor("ai_a_default", RESTYPE_NCS) == "") + { + for(nIndex = 1; nIndex <= AI_MAX_HENCHMAN; nIndex++) + { + oAssociate = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex); + if(oAssociate != OBJECT_INVALID) AssignCommand(oAssociate, ai_Original_StandGround()); + } + for(nIndex = 2; nIndex < 6; nIndex++) + { + oAssociate = GetAssociate(nIndex, oPC); + if(oAssociate != OBJECT_INVALID) AssignCommand(oAssociate, ai_Original_StandGround()); + } + } + // Use Philos AI commands. + else + { + for(nIndex = 1; nIndex <= AI_MAX_HENCHMAN; nIndex++) + { + oAssociate = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex); + if(oAssociate != OBJECT_INVALID) AssignCommand(oAssociate, ai_Philos_StandGround(oPC)); + } + for(nIndex = 2; nIndex < 6; nIndex++) + { + oAssociate = GetAssociate(nIndex, oPC); + if(oAssociate != OBJECT_INVALID) AssignCommand(oAssociate, ai_Philos_StandGround(oPC)); + } + } + } + else if(nCommand == 4) // Normal mode - i.e. Attack nearest. + { + // Not using Philos Henchman AI. Use vanilla commands. + if(ResManGetAliasFor("ai_a_default", RESTYPE_NCS) == "") + { + for(nIndex = 1; nIndex <= AI_MAX_HENCHMAN; nIndex++) + { + oAssociate = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex); + if(oAssociate != OBJECT_INVALID) AssignCommand(oAssociate, ai_Original_AttackNearest()); + } + for(nIndex = 2; nIndex < 6; nIndex++) + { + oAssociate = GetAssociate(nIndex, oPC); + if(oAssociate != OBJECT_INVALID) AssignCommand(oAssociate, ai_Original_AttackNearest()); + } + } + // Use Philos AI commands. + else + { + for(nIndex = 1; nIndex <= AI_MAX_HENCHMAN; nIndex++) + { + oAssociate = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex); + if(oAssociate != OBJECT_INVALID) ai_Philos_AttackNearest(oPC, oAssociate); + } + for(nIndex = 2; nIndex < 6; nIndex++) + { + oAssociate = GetAssociate(nIndex, oPC); + if(oAssociate != OBJECT_INVALID) ai_Philos_AttackNearest(oPC, oAssociate); + } + } + } + if(nCommand == 5) // All associates toggle search mode + { + int bTurnOn = !ai_GetAIMode(oPC, AI_MODE_AGGRESSIVE_SEARCH); + // Not using Philos Henchman AI. Use vanilla commands. + if(ResManGetAliasFor("ai_a_default", RESTYPE_NCS) == "") + { + ai_Original_SetSearch(oPC, bTurnOn); + for(nIndex = 1; nIndex <= AI_MAX_HENCHMAN; nIndex++) + { + oAssociate = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex); + if(oAssociate != OBJECT_INVALID) ai_Original_SetSearch(oAssociate, bTurnOn); + } + for(nIndex = 2; nIndex < 6; nIndex++) + { + oAssociate = GetAssociate(nIndex, oPC); + if(oAssociate != OBJECT_INVALID) ai_Original_SetSearch(oAssociate, bTurnOn); + } + } + else + { + ai_Philos_SetSearch(oPC, oPC, "pc", bTurnOn); + string sAssociateType; + for(nIndex = 1; nIndex <= AI_MAX_HENCHMAN; nIndex++) + { + oAssociate = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex); + if(oAssociate != OBJECT_INVALID) + { + sAssociateType = ai_GetAssociateType(oPC, oAssociate); + ai_Philos_SetSearch(oPC, oAssociate, sAssociateType, bTurnOn); + } + } + for(nIndex = 2; nIndex < 6; nIndex++) + { + oAssociate = GetAssociate(nIndex, oPC); + if(oAssociate != OBJECT_INVALID) + { + sAssociateType = ai_GetAssociateType(oPC, oAssociate); + ai_Philos_SetSearch(oPC, oAssociate, sAssociateType, bTurnOn); + } + } + } + if(bTurnOn) + { + ai_SendMessages("Everyone is now in search mode!", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, "pc" + AI_COMMAND_NUI, "pc" + AI_WIDGET_NUI, "btn_cmd_search_tooltip", " Everyone leave search mode"); + } + else + { + ai_SendMessages("Everyone has left search mode!", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, "pc" + AI_COMMAND_NUI, "pc" + AI_WIDGET_NUI, "btn_cmd_search_tooltip", " Everyone enter search mode"); + } + } + if(nCommand == 6) // All associate use stealth mode + { + int bTurnOn = !ai_GetAIMode(oPC, AI_MODE_AGGRESSIVE_STEALTH); + // Not using Philos Henchman AI. Use vanilla commands. + if(ResManGetAliasFor("ai_a_default", RESTYPE_NCS) == "") + { + ai_Original_SetStealth(oPC, bTurnOn); + for(nIndex = 1; nIndex <= AI_MAX_HENCHMAN; nIndex++) + { + oAssociate = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex); + if(oAssociate != OBJECT_INVALID) ai_Original_SetStealth(oAssociate, bTurnOn); + } + for(nIndex = 2; nIndex < 6; nIndex++) + { + oAssociate = GetAssociate(nIndex, oPC); + if(oAssociate != OBJECT_INVALID) ai_Original_SetStealth(oAssociate, bTurnOn); + } + } + else + { + ai_Philos_SetStealth(oPC, oPC, "pc", bTurnOn); + string sAssociateType; + for(nIndex = 1; nIndex <= AI_MAX_HENCHMAN; nIndex++) + { + oAssociate = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex); + if(oAssociate != OBJECT_INVALID) + { + sAssociateType = ai_GetAssociateType(oPC, oAssociate); + ai_Philos_SetStealth(oPC, oAssociate, sAssociateType, bTurnOn); + } + } + for(nIndex = 2; nIndex < 6; nIndex++) + { + oAssociate = GetAssociate(nIndex, oPC); + if(oAssociate != OBJECT_INVALID) + { + sAssociateType = ai_GetAssociateType(oPC, oAssociate); + ai_Philos_SetStealth(oPC, oAssociate, sAssociateType, bTurnOn); + } + } + } + if(bTurnOn) + { + ai_SendMessages("Everyone is now in stealth mode.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, "pc" + AI_COMMAND_NUI, "pc" + AI_WIDGET_NUI, "btn_cmd_stealth_tooltip", " Everyone leave stealth mode"); + } + else + { + ai_SendMessages("Everyone has left stealth mode.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, "pc" + AI_COMMAND_NUI, "pc" + AI_WIDGET_NUI, "btn_cmd_stealth_tooltip", " Everyone enter stealth mode"); + } + } + } + else + { + if(nCommand == 1) + { + // Not using Philos Henchman AI. Use vanilla commands. + if(ResManGetAliasFor("ai_a_default", RESTYPE_NCS) == "") + { + AssignCommand(oAssociate, ai_Original_Guard()); + } + else ai_Philos_Guard(oPC, oAssociate); + } + else if(nCommand == 2) + { + // Not using Philos Henchman AI. Use vanilla commands. + if(ResManGetAliasFor("ai_a_default", RESTYPE_NCS) == "") + { + AssignCommand(oAssociate, ai_Original_Follow()); + } + else AssignCommand(oAssociate, ai_Philos_Follow(oPC)); + } + else if(nCommand == 3) + { + // Not using Philos Henchman AI. Use vanilla commands. + if(ResManGetAliasFor("ai_a_default", RESTYPE_NCS) == "") + { + AssignCommand(oAssociate, ai_Original_StandGround()); + } + else AssignCommand(oAssociate, ai_Philos_StandGround(oPC)); + } + else if(nCommand == 4) + { + // Not using Philos Henchman AI. Use vanilla commands. + if(ResManGetAliasFor("ai_a_default", RESTYPE_NCS) == "") + { + AssignCommand(oAssociate, ai_Original_AttackNearest()); + } + else ai_Philos_AttackNearest(oPC, oAssociate); + } + } +} +void ai_Action(object oPC, object oAssociate) +{ + if(oPC == oAssociate) + { + DeleteLocalObject(oPC, "NW_ASSOCIATE_COMMAND"); + SetLocalString(oPC, AI_TARGET_MODE, "ASSOCIATE_ACTION_ALL"); + ai_SendMessages("Select an action for the party.", AI_COLOR_YELLOW, oPC); + } + else + { + SetLocalObject(oPC, AI_TARGET_ASSOCIATE, oAssociate); + SetLocalString(oPC, AI_TARGET_MODE, "ASSOCIATE_ACTION"); + ai_SendMessages("Select an action for " + GetName(oAssociate) + ".", AI_COLOR_YELLOW, oPC); + } + EnterTargetingMode(oPC, OBJECT_TYPE_ALL, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK); +} +void ai_AIScript(object oPC, object oAssociate, string sAssociateType, int nToken) +{ + if(ResManGetAliasFor("ai_a_default", RESTYPE_NCS) != "") + { + string sScript = GetLocalString(oAssociate, AI_COMBAT_SCRIPT); + string sIcon = "ir_scommand"; + if(sScript == "ai_a_ambusher") + { + sScript = "ai_a_flanker"; + sIcon = "ir_invite"; + SetLocalString(oAssociate, AI_DEFAULT_SCRIPT, sScript); + SetLocalString(oAssociate, AI_COMBAT_SCRIPT, sScript); + ai_SendMessages(GetName(oAssociate) + " is now using flanking tactics in combat.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_COMMAND_NUI, sAssociateType + AI_WIDGET_NUI, "btn_cmd_ai_script_tooltip", " Flanker: Attacks enemies engaged with allies"); + } + else if(sScript == "ai_a_flanker") + { + sScript = "ai_a_peaceful"; + sIcon = "ir_ignore"; + SetLocalString(oAssociate, AI_DEFAULT_SCRIPT, sScript); + SetLocalString(oAssociate, AI_COMBAT_SCRIPT, sScript); + ai_SendMessages(GetName(oAssociate) + " is now using peaceful tactics in combat.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_COMMAND_NUI, sAssociateType + AI_WIDGET_NUI, "btn_cmd_ai_script_tooltip", " Peaceful: Avoids attacking any enemies if possible"); + } + else if(sScript == "ai_a_peaceful") + { + sScript = "ai_a_defensive"; + sIcon = "ir_knockdwn"; + SetLocalString(oAssociate, AI_DEFAULT_SCRIPT, sScript); + SetLocalString(oAssociate, AI_COMBAT_SCRIPT, sScript); + ai_SendMessages(GetName(oAssociate) + " is now using defensive tactics in combat.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_COMMAND_NUI, sAssociateType + AI_WIDGET_NUI, "btn_cmd_ai_script_tooltip", " Defensive: Attacks then uses Expertise/Parry"); + } + else if(sScript == "ai_a_defensive") + { + sScript = "ai_a_ranged"; + sIcon = "ir_ranger"; + SetLocalString(oAssociate, AI_DEFAULT_SCRIPT, sScript); + SetLocalString(oAssociate, AI_COMBAT_SCRIPT, sScript); + ai_SendMessages(GetName(oAssociate) + " is now using ranged tactics in combat.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_COMMAND_NUI, sAssociateType + AI_WIDGET_NUI, "btn_cmd_ai_script_tooltip", " Ranged: Attacks from range as much as possible"); + } + else if(sScript == "ai_a_ranged") + { + sScript = "ai_a_cntrspell"; + sIcon = "ir_dcaster"; + SetLocalString(oAssociate, AI_DEFAULT_SCRIPT, sScript); + SetLocalString(oAssociate, AI_COMBAT_SCRIPT, sScript); + ai_SendMessages(GetName(oAssociate) + " is now using counter spell tactics in combat.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_COMMAND_NUI, sAssociateType + AI_WIDGET_NUI, "btn_cmd_ai_script_tooltip", " Counter Spell: Tries to counter enemy spells"); + } + else if(sScript == "ai_a_cntrspell") + { + DeleteLocalString(oAssociate, AI_DEFAULT_SCRIPT); + ai_SetAssociateAIScript(oAssociate, FALSE); + sScript = GetLocalString(oAssociate, AI_DEFAULT_SCRIPT); + ai_SendMessages(GetName(oAssociate) + " is now using default tactics in combat.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_COMMAND_NUI, sAssociateType + AI_WIDGET_NUI, "btn_cmd_ai_script_tooltip", " Default tactics: Using the creatures base AI script"); + } + else + { + sScript = "ai_a_ambusher"; + sIcon = "ir_rogue"; + SetLocalString(oAssociate, AI_DEFAULT_SCRIPT, sScript); + SetLocalString(oAssociate, AI_COMBAT_SCRIPT, sScript); + ai_SendMessages(GetName(oAssociate) + " is now using ambush tactics in combat.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_COMMAND_NUI, sAssociateType + AI_WIDGET_NUI, "btn_cmd_ai_script_tooltip", " Ambusher: Attacks from a hidden position"); + } + NuiSetBind(oPC, nToken, "btn_cmd_ai_script_image", JsonString(sIcon)); + NuiSetBind(oPC, nToken, "btn_cmd_ai_script_label", JsonString("Tactics: " + sScript)); + json jAIData = ai_GetAssociateDbJson(oPC, sAssociateType, "aidata"); + if(JsonGetType(JsonArrayGet(jAIData, 8)) == JSON_TYPE_NULL) jAIData = JsonArrayInsert(jAIData, JsonString(sScript)); + else jAIData = JsonArraySet(jAIData, 8, JsonString(sScript)); + ai_SetAssociateDbJson(oPC, sAssociateType, "aidata", jAIData); + } + else + { + if(GetCombatCondition(X0_COMBAT_FLAG_AMBUSHER, oAssociate)) + { + SetCombatCondition(X0_COMBAT_FLAG_AMBUSHER, FALSE, oAssociate); + SetCombatCondition(X0_COMBAT_FLAG_COWARDLY, TRUE, oAssociate); + SetCombatCondition(X0_COMBAT_FLAG_DEFENSIVE, FALSE, oAssociate); + SetCombatCondition(X0_COMBAT_FLAG_RANGED, FALSE, oAssociate); + ai_SendMessages(GetName(oAssociate) + " is now using coward tactics in combat.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_COMMAND_NUI, sAssociateType + AI_WIDGET_NUI, "btn_cmd_ai_script_tooltip", " Using coward tactics"); + } + else if(GetCombatCondition(X0_COMBAT_FLAG_COWARDLY, oAssociate)) + { + SetCombatCondition(X0_COMBAT_FLAG_AMBUSHER, FALSE, oAssociate); + SetCombatCondition(X0_COMBAT_FLAG_COWARDLY, FALSE, oAssociate); + SetCombatCondition(X0_COMBAT_FLAG_DEFENSIVE, TRUE, oAssociate); + SetCombatCondition(X0_COMBAT_FLAG_RANGED, FALSE, oAssociate); + ai_SendMessages(GetName(oAssociate) + " is now using defensive tactics in combat.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_COMMAND_NUI, sAssociateType + AI_WIDGET_NUI, "btn_cmd_ai_script_tooltip", " Using defensive tactics"); + } + else if(GetCombatCondition(X0_COMBAT_FLAG_DEFENSIVE, oAssociate)) + { + SetCombatCondition(X0_COMBAT_FLAG_AMBUSHER, FALSE, oAssociate); + SetCombatCondition(X0_COMBAT_FLAG_COWARDLY, FALSE, oAssociate); + SetCombatCondition(X0_COMBAT_FLAG_DEFENSIVE, FALSE, oAssociate); + SetCombatCondition(X0_COMBAT_FLAG_RANGED, TRUE, oAssociate); + ai_SendMessages(GetName(oAssociate) + " is now using ranged tactics in combat.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_COMMAND_NUI, sAssociateType + AI_WIDGET_NUI, "btn_cmd_ai_script_tooltip", " Using ranged tactics"); + } + else if(GetCombatCondition(X0_COMBAT_FLAG_RANGED, oAssociate)) + { + SetCombatCondition(X0_COMBAT_FLAG_AMBUSHER, FALSE, oAssociate); + SetCombatCondition(X0_COMBAT_FLAG_COWARDLY, FALSE, oAssociate); + SetCombatCondition(X0_COMBAT_FLAG_DEFENSIVE, FALSE, oAssociate); + SetCombatCondition(X0_COMBAT_FLAG_RANGED, FALSE, oAssociate); + ai_SendMessages(GetName(oAssociate) + " is now using normal tactics in combat.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_COMMAND_NUI, sAssociateType + AI_WIDGET_NUI, "btn_cmd_ai_script_tooltip", " Using ambush tactics"); + } + else + { + SetCombatCondition(X0_COMBAT_FLAG_AMBUSHER, TRUE, oAssociate); + SetCombatCondition(X0_COMBAT_FLAG_COWARDLY, FALSE, oAssociate); + SetCombatCondition(X0_COMBAT_FLAG_DEFENSIVE, FALSE, oAssociate); + SetCombatCondition(X0_COMBAT_FLAG_RANGED, FALSE, oAssociate); + ai_SendMessages(GetName(oAssociate) + " is now using ambush tactics in combat.", AI_COLOR_YELLOW, oPC); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_COMMAND_NUI, sAssociateType + AI_WIDGET_NUI, "btn_cmd_ai_script_tooltip", " Using ambush tactics"); + } + } +} +void ai_HavePCPlaceTrap(object oPC, object oAssociate) +{ + SetLocalObject(oPC, AI_TARGET_ASSOCIATE, oAssociate); + SetLocalString(oPC, AI_TARGET_MODE, "ASSOCIATE_GET_TRAP"); + ai_SendMessages(GetName(oAssociate) + " select a trap to place.", AI_COLOR_YELLOW, oPC); + OpenInventory(oAssociate, oPC); + EnterTargetingMode(oPC, OBJECT_TYPE_ITEM, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK); +} +void ai_JumpAssociateToPC(object oPC) +{ + ai_ClearCreatureActions(TRUE); + JumpToObject(oPC); +} +void ai_JumpToPC(object oPC, object oAssociate) +{ + int nAssociateType, nHenchman, nHenchAssociate; + object oHenchman, oHenchmanAssociate; + if(oPC != oAssociate) + { + if(nAssociateType == ASSOCIATE_TYPE_HENCHMAN) + { + for(nHenchAssociate = 2; nHenchAssociate <= 5; nHenchAssociate++) + { + oHenchmanAssociate = GetAssociate(nHenchAssociate, oHenchman, 1); + if(oHenchmanAssociate != OBJECT_INVALID) + { + AssignCommand(oHenchmanAssociate, ai_JumpAssociateToPC(oPC)); + } + } + AssignCommand(oHenchman, ai_JumpAssociateToPC(oPC)); + } + else AssignCommand(oAssociate, ai_JumpAssociateToPC(oPC)); + return; + } + for(nAssociateType = 1; nAssociateType <= 5; nAssociateType++) + { + if(nAssociateType == ASSOCIATE_TYPE_HENCHMAN) + { + for(nHenchman = 1; nHenchman <= AI_MAX_HENCHMAN; nHenchman++) + { + oHenchman = GetAssociate(nAssociateType, oPC, nHenchman); + if(oHenchman != OBJECT_INVALID) + { + for(nHenchAssociate = 2; nHenchAssociate <= 5; nHenchAssociate++) + { + oHenchmanAssociate = GetAssociate(nHenchAssociate, oHenchman, 1); + if(oHenchmanAssociate != OBJECT_INVALID) + { + AssignCommand(oHenchmanAssociate, ai_JumpAssociateToPC(oPC)); + } + } + AssignCommand(oHenchman, ai_JumpAssociateToPC(oPC)); + } + } + } + else + { + oHenchman = GetAssociate(nAssociateType, oPC, 1); + if(oHenchman != OBJECT_INVALID) AssignCommand(oHenchman, ai_JumpAssociateToPC(oPC)); + } + } +} +void ai_GhostMode(object oPC, object oAssociate, int nToken, string sAssociateType) +{ + string sText; + if(ai_GetAIMode(oAssociate, AI_MODE_GHOST)) + { + ai_SetAIMode(oAssociate, AI_MODE_GHOST, FALSE); + ai_RemoveASpecificEffect(oAssociate, EFFECT_TYPE_CUTSCENEGHOST); + sText = " Turn On clipping through creatures for " + GetName(oAssociate); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_COMMAND_NUI, sAssociateType + AI_WIDGET_NUI, "btn_ghost_mode_tooltip", sText); + ai_SendMessages(GetName(oAssociate) + " is not in Ghost Mode and will run into creatures.", AI_COLOR_YELLOW, oPC); + } + else + { + ai_SetAIMode(oAssociate, AI_MODE_GHOST, TRUE); + effect eGhost = EffectCutsceneGhost(); + eGhost = UnyieldingEffect(eGhost); + ApplyEffectToObject(DURATION_TYPE_PERMANENT, eGhost, oAssociate); + sText = " Turn Off clipping through creatures for " + GetName(oAssociate); + ai_UpdateToolTipUI(oPC, sAssociateType + AI_COMMAND_NUI, sAssociateType + AI_WIDGET_NUI, "btn_ghost_mode_tooltip", sText); + ai_SendMessages(GetName(oAssociate) + " is now in Ghost Mode and will clip through creatures.", AI_COLOR_YELLOW, oPC); + } +} +void ai_ChangeCameraView(object oPC, object oAssociate) +{ + object oCamAssociate = GetLocalObject(oPC, "AI_CAMERA_ON_ASSOCIATE"); + if(oCamAssociate == oAssociate) + { + DeleteLocalObject(oPC, "AI_CAMERA_ON_ASSOCIATE"); + AttachCamera(oPC, oPC); + } + else + { + SetLocalObject(oPC, "AI_CAMERA_ON_ASSOCIATE", oAssociate); + AttachCamera(oPC, oAssociate); + } +} +void ai_SelectCameraView(object oPC) +{ + SetLocalString(oPC, AI_TARGET_MODE, "DM_SELECT_CAMERA_VIEW"); + ai_SendMessages(GetName(oPC) + " select an object to change the camera view to.", AI_COLOR_YELLOW, oPC); + EnterTargetingMode(oPC, OBJECT_TYPE_ALL, MOUSECURSOR_CREATE, MOUSECURSOR_NOCREATE); +} +void ai_OpenInventory(object oAssociate, object oPC) +{ + // Funny things happen when you open associate inventories when they are not + // within sight. + if(LineOfSightObject(oPC, oAssociate)) + { + OpenInventory(oAssociate, oPC); + } + else ai_SendMessages(GetName(oAssociate) + " is not within sight!", AI_COLOR_RED, oPC); +} +void ai_SelectOpenInventory(object oPC) +{ + SetLocalString(oPC, AI_TARGET_MODE, "DM_SELECT_OPEN_INVENTORY"); + ai_SendMessages(GetName(oPC) + " select an object to open its inventory.", AI_COLOR_YELLOW, oPC); + EnterTargetingMode(oPC, OBJECT_TYPE_CREATURE, MOUSECURSOR_EXAMINE, MOUSECURSOR_NOEXAMINE); +} +void ai_Plugin_Execute(object oPC, string sElem, int bUser = 0) +{ + int nIndex = StringToInt(GetStringRight(sElem, 1)); + json jPlugins, jPlugin; + if(bUser == 1) // From DM command menu. + { + string sName = ai_RemoveIllegalCharacters(GetName(oPC)); + jPlugins = ai_GetCampaignDbJson("plugins", sName, AI_DM_TABLE); + } + else if(bUser == 2) // From DM plugin menu, master plugin list. + { + jPlugins = ai_GetCampaignDbJson("plugins"); + } + else jPlugins = ai_GetAssociateDbJson(oPC, "pc", "plugins"); + jPlugin = JsonArrayGet(jPlugins, nIndex); + string sScript = JsonGetString(JsonArrayGet(jPlugin, 0)); + if(ResManGetAliasFor(sScript, RESTYPE_NCS) == "") + { + ai_SendMessages(sScript + " not found by ResMan!", AI_COLOR_RED, oPC); + } + else + { + string sName = JsonGetString(JsonArrayGet(jPlugin, 2)); + ai_SendMessages("Executing plugin " + sName + ".", AI_COLOR_GREEN, oPC); + ExecuteScript(sScript, oPC); + } +} diff --git a/src/module/nss/0i_color.nss b/src/module/nss/0i_color.nss new file mode 100644 index 0000000..b18fe7a --- /dev/null +++ b/src/module/nss/0i_color.nss @@ -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"; // Nothing. +const string AI_COLOR_WHITE = "999"; // _Debug messages. +const string AI_COLOR_GRAY = "666"; // Server messages +const string AI_COLOR_YELLOW = "990"; // Generic messages to players. +const string AI_COLOR_DARK_YELLOW = "660"; // +const string AI_COLOR_RED = "900"; // Negative message to players. +const string AI_COLOR_DARK_RED = "600"; // +const string AI_COLOR_GREEN = "080"; // Positive message to players. +const string AI_COLOR_DARK_GREEN = "060"; // +const string AI_COLOR_BLUE = "009"; // +const string AI_COLOR_DARK_BLUE = "006"; // In game descriptive text. +const string AI_COLOR_CYAN = "099"; // +const string AI_COLOR_DARK_CYAN = "066"; // +const string AI_COLOR_MAGENTA = "909"; // +const string AI_COLOR_DARK_MAGENTA = "606";// +const string AI_COLOR_LIGHT_MAGENTA = "868"; // <âcâ> Combat text: Enemy name color. +const string AI_COLOR_ORANGE = "950"; // +const string AI_COLOR_DARK_ORANGE = "940"; // Combat text: base text color. +const string AI_COLOR_GOLD = "860"; // +// 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, "" + // End the color token + sText + ""; +} diff --git a/src/module/nss/0i_combat.nss b/src/module/nss/0i_combat.nss new file mode 100644 index 0000000..6c40eb1 --- /dev/null +++ b/src/module/nss/0i_combat.nss @@ -0,0 +1,3498 @@ +/*////////////////////////////////////////////////////////////////////////////// +// Script Name: 0i_combat +//////////////////////////////////////////////////////////////////////////////// + Include scripts for combat scripts. +*/////////////////////////////////////////////////////////////////////////////// +// Programmer: Philos +//////////////////////////////////////////////////////////////////////////////// +#include "0i_messages" +#include "0i_items" +#include "0i_spells" +// This structure is used to represent the number and type of +// enemies that a creature is facing, divided into four main +// categories: FIGHTERS, CLERICS, MAGES, MONSTERS. +struct stClasses +{ + int FIGHTERS; + int FIGHTER_LEVELS; + int CLERICS; + int CLERIC_LEVELS; + int MAGES; + int MAGE_LEVELS; + int MONSTERS; + int MONSTER_LEVELS; + int TOTAL; + int TOTAL_LEVELS; +}; +struct stTarget +{ + object oTarget; + int nValue; + int nBestValue; + int nBestSecondaryValue; + float fNearestRange; + float fNearestSecondaryRange; + int nIndex; + int nSecondaryIndex; + string sTargetType; +}; +//****************************************************************************** +//************ GET TARGETS USING THE OBJECT SEARCH FUNCTIONS ******************* +//****************************************************************************** +// Returns the nearest enemy that is not disabled from oCreature. +// You may pass in any of the CREATURE_TYPE_* constants +// used in GetNearestCreature as nCType1 & nCType2, with +// corresponding values for nCValue1 & nCValue2. +// NOTE: CREATURE_TYPE_PERCEPTION = 7, PERCEPTION_SEEN = 7. +// bDisabled = TRUE will also return any disabled targets that are not dead. +object ai_GetNearestEnemy(object oCreature, int nNth = 1, int nCType1 = -1, int nCValue1 = -1, int nCType2 = -1, int nCValue2 = -1, int bDisabled = FALSE); +// Returns the nearest ally from oCreature. +// You may pass in any of the CREATURE_TYPE_* constants +// used in GetNearestCreature as nCType1 & nCType2, with +// corresponding values for nCValue1 & nCValue2. +// NOTE: CREATURE_TYPE_PERCEPTION = 7, PERCEPTION_SEEN = 7. +object ai_GetNearestAlly(object oCreature, int nNth = 1, int nCType1 = -1, int nCValue1 = -1, int nCType2 = -1, int nCValue2 = -1); +// Returns the number of alive enemies grouped near oCreature within fDistance. +int ai_GetNumOfEnemiesInGroup(object oCreature, float fDistance = AI_RANGE_MELEE); +// Returns the number of alive allies grouped near oCreature within fDistance. +int ai_GetNumOfAlliesInGroup(object oCreature, float fDistance = AI_RANGE_MELEE); +// Returns the number of creatures of nRacial_Type within fDistance that can be seen by oCreature. +int ai_GetRacialTypeCount(object oCreature, int nRacial_Type, float fDistance = AI_RANGE_PERCEPTION); +// Returns the weakest attacker that is in melee or is attacking oCreature's master. +object ai_GetLowestCRAttackerOnMaster(object oCreature); + +//****************************************************************************** +//******************** SET/CLEAR COMBAT STATE FUNCTIONS ************************ +//****************************************************************************** +// Sets oCreatures's combat state by setting variables for AI_ALLIES and AI_ENEMIES. +// Returns the nearest visible enemy. +object ai_SetCombatState(object oCreature); +// Clears all variables that were define for the current round for oCreature. +void ai_ClearCombatState(object oCreature); + +//****************************************************************************** +//*************** GET TARGETS USING COMBAT STATE FUNCTIONS ********************* +//****************************************************************************** +// These functions will find a target or an index to a target based on the +// combat state variables created by the function ai_SetCombatState. + +// Returns the Index of the nearest creature seen within fMaxRange in the combat state. +// If no creature is found then it will return an index of 0. +// sTargetType is either AI_ENEMY or AI_ALLY. +int ai_GetNearestIndex(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE); +// Returns the nearest creature seen within fMaxRange in the combat state. +// Returns OBJECT_INVALID if no creature is found. +// sTargetType is either AI_ENEMY or AI_ALLY. +object ai_GetNearestTarget(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE); +// Returns the index of the nearest creature seen with the lowest combat rating +// within fMaxRange in the combat state. +// If no creature is found then it will return an index of 0. +// sTargetType is either AI_ENEMY or AI_ALLY. +int ai_GetLowestCRIndex(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE); +// Returns the nearest creature seen with the lowest combat rating within fMaxRange +// in the combat state. +// Returns OBJECT_INVALID if no creature is found. +// sTargetType is either AI_ENEMY or AI_ALLY. +object ai_GetLowestCRTarget(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE); +// Returns the index of the nearest creature seen with the highest combat rating +// within fMaxRange in the combat state. +// If no creature is found then it will return an index of 0. +// sTargetType is either AI_ENEMY or AI_ALLY. +int ai_GetHighestCRIndex(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE); +// Returns the nearest creature seen with the highest combat rating within fMaxRange +// in the combat state. +// Returns OBJECT_INVALID if no creature is found. +// sTargetType is either AI_ENEMY or AI_ALLY. +object ai_GetHighestCRTarget(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE); +// Returns the index of the creature seen with the lowest enemies to oCreature that +// they are in melee with minus the number of allies to the caller they are in +// melee with within fMaxRange in the combat state. +// If no creature is found then it will return an index of 0. +// sTargetType is either AI_ENEMY or AI_ALLY. +int ai_GetLowestMeleeIndex(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY); +// Returns the index of the creature seen with the most enemies to the caller that +// they are in melee with minus the number of allies to oCreature they are in +// melee with within fMaxRange in the combat state. +// If no creature is found then it will return an index of 0. +// sTargetType is either AI_ENEMY or AI_ALLY. +int ai_GetHighestMeleeIndex(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY); +// Returns a creature of sTargetType where they have the least number of +// allies and the most number of enemies within fMaxRange in the combat state. +// Returns OBJECT_INVALID if there is not a good creature to select. +// sTargetType is either AI_ENEMY, or AI_ALLY. +object ai_GetGroupedTarget(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY); +// Returns the index of the nearest creature with the least % of hitpoints within +// fMaxRange in the combat state. +// If no creature is found then it will return an index of 0. +// sTargetType is either AI_ENEMY or AI_ALLY. +int ai_GetMostWoundedIndex(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE); +// Returns the creature with the lowest health seen within fMaxRange in the combat state. +// Returns OBJECT_INVALID if no creature is found. +object ai_GetMostWoundedTarget(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE); +// Returns the index of the nearest ally with the least % of hitpoints within +// fMaxRange in the combat state. +// This also filters for AI_MODE_PARTY_HEALING_OFF and AI_MODE_SELF_HEALING_OFF. +// If no ally is found then it will return an index of 0. +int ai_GetAllyToHealIndex(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION); +// Returns the ally with the lowest health seen within fMaxRange in the combat state. +// This also filters for AI_MODE_PARTY_HEALING_OFF and AI_MODE_SELF_HEALING_OFF. +// Returns OBJECT_INVALID if no creature is found. +object ai_GetAllyToHealTarget(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION); +// Returns the creature with the lowest fortitude save seen within fMaxRange in the combat state. +// Returns OBJECT_INVALID if no creature is found. +object ai_GetLowestFortitudeSaveTarget(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION); +// Returns the creature with the lowest reflex save seen within fMaxRange in the combat state. +// Returns OBJECT_INVALID if no creature is found. +object ai_GetLowestReflexSaveTarget(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION); +// Returns the creature with the lowest will save seen within fMaxRange in the combat state. +// Returns OBJECT_INVALID if no creature is found. +object ai_GetLowestWillSaveTarget(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION); +// Returns the creature with the lowest save based on nSpell save type seen +// within fMaxRange in the combat state. +// Returns OBJECT_INVALID if no creature is found. +object ai_GetSpellTargetBasedOnSaves(object oCreature, int nSpell, float fMaxRange = AI_RANGE_PERCEPTION); +// Returns the index of the nearest creature seen that is busy attacking an ally +// within fMaxRange in the combat state. +// If none is found then it will return 0. +int ai_GetSneakAttackIndex(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, int bAlwaysAtk = TRUE); +// Returns the index of the nearest creature seen that is busy attacking an ally +// within fMaxRange in the combat state. +// If none is found then it will return 0. +int ai_GetNearestIndexNotInAOE(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE); +// Returns the nearest combat creature seen within fMaxRange in the combat state. +// Returns OBJECT_INVALID if no creature is found. +// sTargetType is either AI_ENEMY or AI_ALLY. +object ai_GetNearestTargetNotInAOE(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE); +// Returns the index of the nearest creature seen with the lowest combat rating +// that is not in a dangerous area of effect within fMaxRange in the combat state. +// If no creature is found then it will return an index of 0. +// sTargetType is either AI_ENEMY or AI_ALLY. +int ai_GetLowestCRIndexNotInAOE(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE); +// Returns the lowest combat creature seen within fMaxRange in the combat state. +// Returns OBJECT_INVALID if no creature is found. +// sTargetType is either AI_ENEMY or AI_ALLY. +object ai_GetLowestTargetNotInAOE(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE); +// Returns the index of the nearest creature seen with the highest combat rating +// that is not in a dangerous area of effect within fMaxRange in the combat state. +// If no creature is found then it will return an index of 0. +// sTargetType is either AI_ENEMY or AI_ALLY. +int ai_GetHighestCRIndexNotInAOE(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE); +// Returns the highest combat creature seen within fMaxRange in the combat state. +// Returns OBJECT_INVALID if no creature is found. +// sTargetType is either AI_ENEMY or AI_ALLY. +object ai_GetHighestTargetNotInAOE(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE); +// Returns the index of the creature seen with the most enemies to oCreature that +// they are in melee with minus the number of allies to oCreature they are in +// melee with that is not in a dangerous area of effect within fMaxRange in the combat state. +// If no creature is found then it will return an index of 0. +// sTargetType is either AI_ENEMY or AI_ALLY. +int ai_GetHighestMeleeIndexNotInAOE(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY); +// Returns a creature of sTargetType where they have the least number of +// allies and the most number of enemies within fMaxRange that are not in a +// dangerous area of effect in the combat state. +// Returns OBJECT_INVALID if there is not a good creature to select. +// sTargetType is either AI_ENEMY, or AI_ALLY. +object ai_GetGroupedTargetNotInAOE(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY); +// Returns the nearest creature seen of nClassType within fMaxRange in the combat state. +// Returns OBJECT_INVALID if no creature is found. +// sTargetType is either AI_ENEMY or AI_ALLY. +// bAlwaysAtk TRUE we attack everything! FALSE we don't attack strong enemies. +object ai_GetNearestClassTarget(object oCreature, int nClassType, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE); +// Returns the creature with the lowest combat rating seen of nClassType within +// fMaxRange in the combat state. +// Returns OBJECT_INVALID if no creature is found. +// sTargetType is either AI_ENEMY or AI_ALLY. +// bAlwaysAtk TRUE we attack everything! FALSE we don't attack strong enemies. +object ai_GetLowestCRClassTarget(object oCreature, int nClassType, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE); +// Returns the creature with the highest combat rating seen of nClassType within +// fMaxRange in the combat state. +// Returns OBJECT_INVALID if no creature is found. +// sTargetType is either AI_ENEMY or AI_ALLY. +// bAlwaysAtk TRUE we attack everything! FALSE we don't attack strong enemies. +object ai_GetHighestCRClassTarget(object oCreature, int nClassType, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE); +// Returns the nearest creature seen of nRacialType within fMaxRange in the combat state. +// Returns OBJECT_INVALID if no creature is found. +// sTargetType is either AI_ENEMY or AI_ALLY. +// bAlwaysAtk TRUE we attack everything! FALSE we don't attack strong enemies. +object ai_GetNearestRacialTarget(object oCreature, int nRacialType, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE); +// Returns the creature with the lowest combat rating seen of nRacialType within +// fMaxRange in the combat state. Returns OBJECT_INVALID if no creature is found. +// sTargetType is either AI_ENEMY or AI_ALLY. +// bAlwaysAtk TRUE we attack everything! FALSE we don't attack strong enemies. +object ai_GetLowestCRRacialTarget(object oCreature, int nRacialType, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE); +// Returns the creature with the highest combat rating seen of nRacialType within +// fMaxRange in the combat state. Returns OBJECT_INVALID if no creature is found. +// sTargetType is either AI_ENEMY or AI_ALLY. +// bAlwaysAtk TRUE we attack everything! FALSE we don't attack strong enemies. +object ai_GetHighestCRRacialTarget(object oCreature, int nRacialType, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE); +// Returns the nearest enemy seen that is attacking an ally with the least +// number of enemies on them within fMaxRange in the combat state. +// If none is found then it will return 0. +object ai_GetFlankTarget(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, int bAlwaysAtk = TRUE); +// Returns the nearest enemy creature seen wihtin fMaxRange that is a favored enemy +// of the caller in the combat state. +// Returns OBJECT_INVALID if no creature is found. +// bAlwaysAtk TRUE we attack everything! FALSE we don't attack strong enemies. +object ai_GetNearestFavoredEnemyTarget(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, int bAlwaysAtk = TRUE); +// Returns the best target for melee combat based if we are in melee or not. +// If not in melee it will get the nearest target that is not in a dangerous +// area of effect for us to attack in the combat state. +// If in melee it will get the weakest target. +// If it returns OBJECT_INVALID then we should stop the attack. The only way +// to not get a target is if we have been told not to attack strong opponents. +// bAlwaysAtk TRUE we attack everything! FALSE we don't attack strong enemies. +object ai_GetBestCRTargetForMeleeCombat(object oCreature, int nInMelee, int bAlwaysAtk = TRUE); +// Returns the nearest target for melee combat based if we are in melee or not. +// If not in melee it will get the nearest target that is not in a dangerous +// area of effect for us to attack in the combat state. +// If it returns OBJECT_INVALID then we should stop the attack. The only way +// to not get a target is if we have been told not to attack strong opponents. +// bAlwaysAtk TRUE we attack everything! FALSE we don't attack strong enemies. +object ai_GetNearestTargetForMeleeCombat(object oCreature, int nInMelee, int bAlwaysAtk = TRUE); +// Returns the target with the lowest combat rating for melee combat based if +// we are in melee or not. If not in melee it will get the nearest target that +// is not in a dangerous area of effect for us to attack in the combat state. +// If it returns OBJECT_INVALID then we should stop the attack. The only way +// to not get a target is if we have been told not to attack strong opponents. +// bAlwaysAtk TRUE we attack everything! FALSE we don't attack strong enemies. +object ai_GetLowestCRTargetForMeleeCombat(object oCreature, int nInMelee, int bAlwaysAtk = TRUE); +// Returns the target with the highest combat rating for melee combat based if +// we are in melee or not. If not in melee it will get the nearest target that +// is not in a dangerous area of effect for us to attack in the combat state. +// If it returns OBJECT_INVALID then we should stop the attack. +object ai_GetHighestCRTargetForMeleeCombat(object oCreature, int nInMelee); +// Returns the Index of the nearest creature seen within fMaxRange in the combat state. +// If no creature is found then it will return an index of 0. +// sTargetType is either AI_ENEMY or AI_ALLY. +int ai_MonsterGetNearestIndex(object oMonster, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE); +// Returns the index of the nearest enemy creature that can see oCreature. +int ai_GetNearestIndexThatSeesUs(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION); +// Returns the nearest creature attacking the caller within fMaxRange in the combat state. +// Returns OBJECT_INVALID if oCreature is not being attacked. +object ai_GetEnemyAttackingMe(object oCreature, float fMaxRange = AI_RANGE_MELEE); +// Returns the nearest creature attacking oAlly from oCreature within fMaxRange +// in the combat state. +// Returns OBJECT_INVALID if oAlly is not being attacked. +object ai_GetEnemyAttackingMyAlly(object oCreature, object oAlly, float fMaxRange = AI_RANGE_MELEE); +// Returns the number of enemies within fMaxRange of the caller in the combat state. +int ai_GetNumOfEnemiesInRange(object oCreature, float fMaxRange = AI_RANGE_MELEE); +// Returns the best ally target withing fMaxRange for nSpell to be cast on. +// Uses the ai_spells.2da file to pick a target. +object ai_GetAllyBuffTarget(object oCreature, int nSpell, float fMaxRange = AI_RANGE_BATTLEFIELD); + +//****************************************************************************** +//******************** OTHER COMBAT FUNCTIONS ******************************** +//****************************************************************************** + +// Returns the current round that oCreature is in for this combat. +int ai_GetCurrentRound(object oCreature); +// Returns the difficulty of the battle based on the combat state. +// nDifficulty is Enemy level - Ally level + 20 + Player adjustment. +// 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. +int ai_GetDifficulty(object oCreature); +// Returns oCreatures Combat rating. +//(BAB + AC - 10) / 2 +int ai_GetMyCombatRating(object oCreature); +// Returns the last creature oCreature attacked. +// bPhysical checks for creatures attacked in melee or range with a weapon. +// bSpell will look for creatures attacked by a spell. +object ai_GetAttackedTarget(object oCreature, int bPhysical = TRUE, int bSpell = FALSE); +// Returns TRUE if oCreature is of nClassType; +// May also check for general Class types with +// AI_CLASS_TYPE_ARCANE, AI_CLASS_TYPE_DIVINE, AI_CLASS_TYPE_CASTER, AI_CLASS_TYPE_WARRIOR. +int ai_CheckClassType(object oCreature, int nClassType); +// Returns TRUE if oCreature is of nRacialType; +// May also check for general racial types with +// AI_RACIAL_TYPE_ANIMAL_BEAST +int ai_CheckRacialType(object oCreature, int nRacialType); +// Saves oCreatures Normal appearance if they are not polymorphed and it has +// not already been saved. +void ai_SetNormalAppearance(object oCreature); +// Returns the normal appearance of oCreature. +int ai_GetNormalAppearance(object oCreature); +// Return the number and levels of all creatures within fMaxRange. +// They are grouped into Fighters, Clerics, Mages, and Monsters. +struct stClasses ai_GetFactionsClasses(object oCreature, int bEnemy = TRUE, float fMaxRange = AI_RANGE_BATTLEFIELD); +// This will return the class with the most levels. +// Returns a string of "FIGHTER", "CLERIC", "MAGE", or "MONSTER". +// Execute with GetFactionsClasses. +string ai_GetMostDangerousClass(struct stClasses stCount); +// Equips the best weapon, ranged or melee. +// Returns TRUE if equiped, FALSE if not. +// oTarget is the creature the caller is targeting. +void ai_EquipBestWeapons(object oCreature, object oTarget = OBJECT_INVALID); +// Equips a melee weapon AND checks for shield, two weapons, two handed, etc. +// Returns TRUE if equiped, FALSE if not. +// oTarget is the creature the caller is targeting. +int ai_EquipBestMeleeWeapon(object oCreature, object oTarget = OBJECT_INVALID); +// Equips a ranged weapon AND checks for ammo. +// Returns TRUE if equiped, FALSE if not. +// oTarget is the creature the caller is targeting. +int ai_EquipBestRangedWeapon(object oCreature, object oTarget = OBJECT_INVALID); +// Equips the best weapon for a monk character. +// Returns TRUE if equiped, FALSE if not. +// oTarget is the creature the caller is targeting. +int ai_EquipBestMonkMeleeWeapon(object oCreature, object oTarget = OBJECT_INVALID); +// Returns TRUE if oCreature is in a Dangerous Area of Effect in fMaxRange. +// bMove will attempt to move oCreature out of the Dangerous AOE if needed. +int ai_IsInADangerousAOE(object oCreature, float fMaxRange = AI_RANGE_BATTLEFIELD, int bMove = FALSE); +// Returns 1 if oHidden has an Invisiblity effect, Can't be spotted but can be heard. +// Returns 2 if oHidden has a Darkness effect. Can't be spotted but can be heard. +// Returns 3 if oHidden has a Sanctuary effect, Can't be spotted or heard. +// Returns 4 if oHidden is in stealth mode, Can be spotted and heard. +int ai_GetIsHidden(object oHidden); +// Returns TRUE if if oCaster has a good chance of effecting oCreature with nSpell. +int ai_CastOffensiveSpellVsTarget(object oCaster, object oCreature, int nSpell); +// Gets the base DC for a dragon. +int ai_GetDragonDC(object oCreature); +// Set oCreature's ai scripts based on its first class or the variable "AI_DEFAULT_SCRIPT". +void ai_SetCreatureAIScript(object oCreature); +// Returns TRUE if oTarget is immune to sneak attacks. +int ai_IsImmuneToSneakAttacks(object oCreature, object oTarget); +// Returns TRUE if iIndex target has a higher combat rating than oCreature. +int ai_IsStrongerThanMe(object oCreature, int nIndex); +// Returns TRUE if oTarget's CR is within nAdj of oCreature's level, otherwise FALSE. +int ai_StrongOpponent(object oCreature, object oTarget, int nAdj = 2); +// Returns TRUE if attacking oTarget with Power attack is a good option. +int ai_PowerAttackGood(object oCreature, object oTarget, float fAdj); +// Returns TRUE if oTarget's AC - oCreature Atk - nAtkAdj can hit within 25% to 75%. +int ai_AttackPenaltyOk(object oCreature, object oTarget, float fAtkAdj); +// Returns TRUE if oCreature AC - oTarget's Atk is less than 20. +int ai_ACAdjustmentGood(object oCreature, object oTarget, float fACAdj); +// Checks oCreatures melee weapon to see if they can kill oTarget in one hit. +int ai_WillKillInOneHit(object oCreature, object oTarget); +// Returns TRUE if oCreature has Mobility, SpringAttack, or a high Tumble. +int ai_CanIMoveInCombat(object oCreature); +// Returns TRUE if oCreature can safely fire a ranged weapon. +int ai_CanIUseRangedWeapon(object oCreature, int nInMelee); +// Returns TRUE if oCreature moves before the action. FALSE if they do not move. +// and -1 if the action is canceled. +// Checks current combat state to see if oCreature needs to move before using an action. +int ai_CheckCombatPosition(object oCreature, object oTarget, int nInMelee, int nAction, int nBaseItemType = 0); + +//****************************************************************************** +//************ GET TARGETS USING THE OBJECT SEARCH FUNCTIONS ******************* +//****************************************************************************** +object ai_GetNearestEnemy(object oCreature, int nNth = 1, int nCType1 = -1, int nCValue1 = -1, int nCType2 = -1, int nCValue2 = -1, int bDisabled = FALSE) +{ + object oTarget = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, + oCreature, nNth, nCType1, nCValue1, nCType2, nCValue2); + if(bDisabled) + { + while(oTarget != OBJECT_INVALID && GetIsDead(oTarget)) + { + oTarget = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, + oCreature, ++nNth, nCType1, nCValue1, nCType2, nCValue2); + } + } + else + { + while(oTarget != OBJECT_INVALID && ai_Disabled(oTarget)) + { + oTarget = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, + oCreature, ++nNth, nCType1, nCValue1, nCType2, nCValue2); + } + } + return oTarget; +} +object ai_GetNearestAlly(object oCreature, int nNth = 1, int nCType1 = -1, int nCValue1 = -1, int nCType2 = -1, int nCValue2 = -1) +{ + return GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_FRIEND, + oCreature, ++nNth, nCType1, nCValue1, nCType2, nCValue2); +} +int ai_GetNumOfEnemiesInGroup(object oCreature, float fDistance = AI_RANGE_MELEE) +{ + int nCnt; + location lLocation = GetLocation(oCreature); + object oEnemy = GetFirstObjectInShape(SHAPE_SPHERE, fDistance, lLocation); + while(oEnemy != OBJECT_INVALID) + { + if(GetIsEnemy(oEnemy, oCreature) && !GetIsDead(oEnemy)) nCnt++; + oEnemy = GetNextObjectInShape(SHAPE_SPHERE, fDistance, lLocation); + } + return nCnt; +} +int ai_GetNumOfAlliesInGroup(object oCreature, float fDistance = AI_RANGE_MELEE) +{ + int nCnt; + location lLocation = GetLocation(oCreature); + object oAlly = GetFirstObjectInShape(SHAPE_SPHERE, fDistance, lLocation); + while(oAlly != OBJECT_INVALID) + { + if(GetReputation(oCreature, oAlly) > 89 && oAlly != oCreature && !GetIsDead(oAlly)) + { + nCnt++; + } + oAlly = GetNextObjectInShape(SHAPE_SPHERE, fDistance, lLocation); + } + return nCnt; +} +int ai_GetRacialTypeCount(object oCreature, int nRacial_Type, float fDistance = AI_RANGE_PERCEPTION) +{ + int nCnt = 1; + int nCount = 0; + object oEnemy = ai_GetNearestEnemy(oCreature, nCnt, + CREATURE_TYPE_PERCEPTION, + PERCEPTION_SEEN, + CREATURE_TYPE_RACIAL_TYPE, + nRacial_Type); + while(oEnemy != OBJECT_INVALID && GetDistanceBetween(oEnemy, oCreature) <= fDistance) + { + if(!ai_GetHasEffectType(oEnemy, EFFECT_TYPE_TURNED)) nCount++; + nCnt++; + oEnemy = ai_GetNearestEnemy(oCreature, nCnt, + CREATURE_TYPE_PERCEPTION, + PERCEPTION_SEEN, + CREATURE_TYPE_RACIAL_TYPE, + nRacial_Type); + } + return nCount; +} +object ai_GetLowestCRAttackerOnMaster(object oCreature) +{ + object oTarget = OBJECT_INVALID, oMaster = GetMaster(oCreature); + if(AI_DEBUG) ai_Debug("0i_combat", "419", "Checking for weakest attacker on " + GetName(oMaster)); + int nEnemyCombatRating, nWeakestCombatRating, nCntr = 1; + float fNearest = AI_RANGE_MELEE + 1.0f; + // Get the weakest opponent in melee with our master. + object oEnemy = ai_GetNearestEnemy(oMaster, nCntr, 7, 7); + float fDistance = GetDistanceBetween(oMaster, oEnemy); + while (oEnemy != OBJECT_INVALID && fDistance <= AI_RANGE_MELEE) + { + nEnemyCombatRating = ai_GetMyCombatRating(oEnemy); + if(AI_DEBUG) ai_Debug("0i_combat", "428", GetName(oEnemy) + " nECR: " + IntToString(nEnemyCombatRating)); + if (nEnemyCombatRating < nWeakestCombatRating || + nEnemyCombatRating == nWeakestCombatRating && fDistance < fNearest) + { + fNearest = fDistance; + nWeakestCombatRating = nEnemyCombatRating; + oTarget = oEnemy; + } + oEnemy = ai_GetNearestEnemy(oMaster, ++nCntr, 7, 7); + } + // No targets in melee with our master, lets see if there is a ranged attacker. + if (oTarget == OBJECT_INVALID) oTarget = GetLastHostileActor(oMaster); + return oTarget; +} + +//****************************************************************************** +//******************** SET/CLEAR COMBAT STATE FUNCTIONS ************************ +//****************************************************************************** + +object ai_SetCombatState(object oCreature) +{ + if(AI_DEBUG) ai_Counter_Start(); + object oMaster = GetMaster(); + if(oMaster == OBJECT_INVALID) oMaster = oCreature; + int nEnemyNum, nEnemyPower, nAllyNum, nAllyPower, nInMelee, nMagic; + int nHealth, nNth, nAllies, nPower, nDisabled, bThreat,nObjects; + int nEnemyHighestPower, nAllyHighestPower; + float fNearest = AI_RANGE_BATTLEFIELD; + float fDistance; + float fMaxRange = GetLocalFloat(oCreature, AI_ASSOC_PERCEPTION_DISTANCE); + if(fMaxRange == 0.0) fMaxRange = AI_RANGE_PERCEPTION; + string sCnt, sDebugText; + location lLocation = GetLocation(oMaster); + object oMelee, oNearestEnemy = OBJECT_INVALID; + if(AI_DEBUG) ai_Debug("0i_combat", "491", "************************************************************"); + if(AI_DEBUG) ai_Debug("0i_combat", "492", "******************* CREATING COMBAT DATA *******************"); + if(AI_DEBUG) ai_Debug("0i_combat", "493", GetName(oCreature)); + // We want to include ourselves in the combat state. + object oObject = GetFirstObjectInShape(SHAPE_SPHERE, AI_RANGE_BATTLEFIELD, lLocation); + // Get all creatures within 40 meters(5 meters beyond our perception of 35). + // Centered on either the creature or their master. + while(oObject != OBJECT_INVALID) + { + // Process all enemies. + if(GetIsEnemy(oObject, oCreature)) + { + if(GetObjectSeen(oObject, oCreature) || GetObjectHeard(oObject, oCreature)) + { + fDistance = GetDistanceBetween(oObject, oCreature); + if(fDistance <= fMaxRange) + { + // ********** Get the Total levels of the Enemy ********** + nPower = ai_GetCharacterLevels(oObject); + if(nPower < 1) nPower = 1; + if(nEnemyHighestPower < nPower) nEnemyHighestPower = nPower; + nEnemyPower += nPower; + // ********** Check if the Enemy is disabled ********** + bThreat = TRUE; + nDisabled = ai_Disabled(oObject); + if(nDisabled) + { + if(AI_DEBUG) sDebugText += "**** DISABLED(" + IntToString(nDisabled) + ") ****"; + // Decide if they are still a threat: 1 - dead, 2 - Bleeding. + if(nDisabled == 1 || nDisabled == 2 || + //nDisabled == EFFECT_TYPE_CONFUSED || + //nDisabled == EFFECT_TYPE_FRIGHTENED || + //nDisabled == EFFECT_TYPE_PARALYZE || + nDisabled == EFFECT_TYPE_CHARMED || + nDisabled == EFFECT_TYPE_PETRIFY) + { + bThreat = FALSE; + if(AI_DEBUG) ai_Debug("0i_combat", "527", "Enemy: " + GetName(oObject) + sDebugText); + } + } + // If they are using the coward ai then treat them as frightened. + // we place it here as an else so we don't overwrite another disabled effect. + else if(GetLocalString(oObject, AI_COMBAT_SCRIPT) == "ai_coward") + { + nDisabled = EFFECT_TYPE_FRIGHTENED; + // !!!! For /DEBUG CODE !!!! + if(AI_DEBUG) sDebugText += "**** DISABLED(" + IntToString(nDisabled) + ") ****"; + } + if(bThreat) + { + sCnt = IntToString(++nEnemyNum); + // ********** Set if the Enemy is disabled ********** + SetLocalInt(oCreature, AI_ENEMY_DISABLED + sCnt, nDisabled); + // ********** Set the Enemy Object ********** + SetLocalObject(oCreature, AI_ENEMY + sCnt, oObject); + // ********** Set the Enemy Combat Rating ********** + SetLocalInt(oCreature, AI_ENEMY_COMBAT + sCnt, ai_GetMyCombatRating(oObject)); + // ********** Set the Enemy Health Percentage ********** + nHealth = ai_GetPercHPLoss(oObject); + SetLocalInt(oCreature, AI_ENEMY_HEALTH + sCnt, nHealth); + // ********** Set the number of enemies near the enemy ********** + nInMelee = 0; + nNth = 1; + oMelee = GetNearestObject(OBJECT_TYPE_CREATURE, oObject, nNth); + while(oMelee != OBJECT_INVALID && !GetIsDead(oMelee) && + GetDistanceBetween(oMelee, oObject) < AI_RANGE_MELEE) + { + // We add an enemy to the group. + if(GetIsEnemy(oMelee, oCreature)) nInMelee++; + oMelee = GetNearestObject(OBJECT_TYPE_CREATURE, oObject, ++nNth); + } + SetLocalInt(oCreature, AI_ENEMY_MELEE + sCnt, nInMelee); + // ********** Set the Enemies distance ********** + fDistance = GetDistanceBetween(oObject, oCreature); + SetLocalFloat(oCreature, AI_ENEMY_RANGE + sCnt, fDistance); + // ********** Set if the Enemy is perceived ********** + if(GetObjectSeen(oObject, oCreature) || + (GetObjectHeard(oObject, oCreature) && fDistance <= AI_RANGE_MELEE && + ai_GetIsHidden(oObject))) + { + SetLocalInt(oCreature, AI_ENEMY_PERCEIVED + sCnt, TRUE); + if(AI_DEBUG) sDebugText += "**** PERCEIVED Seen: " + + IntToString(GetObjectSeen(oObject, oCreature)) + + " Heard: " + IntToString(GetObjectHeard(oObject, oCreature)) + " ****"; + } + else SetLocalInt(oCreature, AI_ENEMY_PERCEIVED + sCnt, FALSE); + // ********** Set the Nearest Enemy seen ********** + if(fDistance < fNearest) + { + fNearest = fDistance; + oNearestEnemy = oObject; + } + } + } + // !!! Debug code !!! + if(AI_DEBUG && fDistance < AI_RANGE_MELEE) sDebugText += "**** MELEE ****"; + if(AI_DEBUG) ai_Debug("0i_combat", "587", "Enemy(" + IntToString(nEnemyNum) + "): " + + GetName(oObject) + sDebugText); + if(AI_DEBUG) ai_Debug("0i_combat", "589", "nHealth: " + IntToString(nHealth) + + " nInMelee: " + IntToString(nInMelee) + + " fDistance: " + FloatToString(fDistance, 0, 2) + + " nNum: " + IntToString(nEnemyNum) + + " nPower: " + IntToString(nEnemyPower / 2)); + } + else + { + // ********** Also add the levels of Unknown Enemies *********** + nPower = FloatToInt(ai_GetCharacterLevels(oObject) / 1.5); + if(nPower < 1) nPower = 1; + nEnemyPower += nPower; + if(AI_DEBUG) ai_Debug("0i_combat", "601", "Enemy(NOT PERCEIVED): " + + GetName(oObject) + " fDistance: " + + FloatToString(GetDistanceBetween(oObject, oCreature), 0, 2) + + " nPower: " + IntToString(nEnemyPower)); + } + } + // Process all Allies. + else if(GetFactionEqual(oObject, oCreature)) + { + // ********** Set if the Ally is disabled ********** + nDisabled = ai_Disabled(oObject); + if(nDisabled) + { + sDebugText += "**** DISABLED(" + IntToString(nDisabled) + ") ****"; + SetLocalInt(oCreature, AI_ALLY_DISABLED + sCnt, nDisabled); + } + if(nDisabled != 1) + { + sCnt = IntToString(++nAllyNum); + // ********** Set the Ally Object ********** + SetLocalObject(oCreature, AI_ALLY + sCnt, oObject); + // ********** Set the Ally Combat Rating ********** + SetLocalInt(oCreature, AI_ALLY_COMBAT + sCnt, ai_GetMyCombatRating(oObject)); + // ********** Set the Ally Health Percentage ********** + nHealth = ai_GetPercHPLoss(oObject); + SetLocalInt(oCreature, AI_ALLY_HEALTH + sCnt, nHealth); + // ********** Set the number of enemies near the ally ********** + nInMelee = 0; + nNth = 1; + oMelee = GetNearestObject(OBJECT_TYPE_CREATURE, oObject, nNth); + while(oMelee != OBJECT_INVALID && !GetIsDead(oMelee) && + GetDistanceBetween(oMelee, oObject) < AI_RANGE_MELEE) + { + if(GetIsEnemy(oMelee, oCreature)) nInMelee++; + //else nInMelee--; + oMelee = GetNearestObject(OBJECT_TYPE_CREATURE, oObject, ++nNth); + } + SetLocalInt(oCreature, AI_ALLY_MELEE + sCnt, nInMelee); + // ********** Set the Allies distance ********** + SetLocalFloat(oCreature, AI_ALLY_RANGE + sCnt, GetDistanceBetween(oObject, oCreature)); + // ********** All allies are considered to be seen ********** + SetLocalInt(oCreature, AI_ALLY_PERCEIVED + sCnt, TRUE); + // ********** Get the Total levels of the Allies ********** + nPower = ai_GetCharacterLevels(oObject); + if(nAllyHighestPower < nPower) nAllyHighestPower = nPower; + nAllyPower +=(nPower * nHealth) / 100; + if(AI_DEBUG) ai_Debug("0i_combat", "647", "Ally(" + IntToString(nAllyNum) + "): " + + GetName(oObject) + sDebugText); + if(AI_DEBUG) ai_Debug("0i_combat", "649", "nHealth: " + IntToString(nHealth) + + " nInMelee: " + IntToString(nInMelee) + + " fDistance: " + FloatToString(GetDistanceToObject(oObject), 0, 2) + + " nNum: " + IntToString(nAllyNum) + + " nPower: " + IntToString(nAllyPower / 2)); + } + } + if(AI_DEBUG) sDebugText = ""; + oObject = GetNextObjectInShape(SHAPE_SPHERE, AI_RANGE_BATTLEFIELD, lLocation); + } + if(AI_DEBUG) ai_Debug("0i_combat", "659", "Nearest Enemy: " + GetName(oNearestEnemy)); + if(AI_DEBUG) ai_Debug("0i_combat", "660", "****************** FINISHED COMBAT DATA *******************"); + if(AI_DEBUG) ai_Debug("0i_combat", "661", "************************************************************"); + // Lets save processing by only clearing previous enemy data we don't overwrite. + int nPreviousEnd = GetLocalInt(oCreature, AI_ENEMY_NUMBERS); + int nCnt = nEnemyNum + 1; + if(AI_DEBUG) ai_Debug("0i_combat", "665", "Clearing Enemy Combat Data: nPreviousEnd: " + + IntToString(nPreviousEnd) + " nCurrentEnd: " + IntToString(nCnt - 1)); + while(nPreviousEnd >= nCnt) + { + sCnt = IntToString(nCnt); + if(AI_DEBUG) ai_Debug("0i_combat", "670", "Clearing Enemy Combat Data: " + sCnt + " " + + GetName(GetLocalObject(oCreature, AI_ENEMY + sCnt))); + DeleteLocalObject(oCreature, AI_ENEMY + sCnt); + DeleteLocalInt(oCreature, AI_ENEMY_PERCEIVED + sCnt); + DeleteLocalFloat(oCreature, AI_ENEMY_RANGE + sCnt); + DeleteLocalInt(oCreature, AI_ENEMY_COMBAT + sCnt); + DeleteLocalInt(oCreature, AI_ENEMY_MELEE + sCnt); + DeleteLocalInt(oCreature, AI_ENEMY_HEALTH + sCnt); + nCnt ++; + } + // Lets save processing by only clearing previous ally data we don't overwrite. + nPreviousEnd = GetLocalInt(oCreature, AI_ALLY_NUMBERS); + nCnt = nAllyNum + 1; + if(AI_DEBUG) ai_Debug("0i_combat", "683", "Clearing Ally Combat Data: nPreviousEnd: " + + IntToString(nPreviousEnd) + " nCurrentEnd: " + IntToString(nCnt - 1)); + while(nPreviousEnd >= nCnt) + { + sCnt = IntToString(nCnt); + if(AI_DEBUG) ai_Debug("0i_combat", "688", "Clearing Ally Combat Data: " + sCnt + " " + + GetName(GetLocalObject(oCreature, AI_ENEMY + sCnt))); + DeleteLocalObject(oCreature, AI_ALLY + sCnt); + DeleteLocalInt(oCreature, AI_ALLY_PERCEIVED + sCnt); + DeleteLocalFloat(oCreature, AI_ALLY_RANGE + sCnt); + DeleteLocalInt(oCreature, AI_ALLY_COMBAT + sCnt); + DeleteLocalInt(oCreature, AI_ALLY_MELEE + sCnt); + DeleteLocalInt(oCreature, AI_ALLY_HEALTH + sCnt); + nCnt ++; + } + // Finally set all group states. + SetLocalInt(oCreature, AI_ENEMY_NUMBERS, nEnemyNum); + // Total enemy power is half the levels of all enemies + the total levels + // of the highest level enemy. + nEnemyPower = (nEnemyPower / 2) + nEnemyHighestPower; + SetLocalInt(oCreature, AI_ENEMY_POWER, nEnemyPower); + SetLocalObject(oCreature, AI_ENEMY_NEAREST, oNearestEnemy); + SetLocalInt(oCreature, AI_ALLY_NUMBERS, nAllyNum); + // Total ally power is half the levels of all allies + the total levels + // of the highest level ally, only used by associates. + nAllyPower = (nAllyPower / 2) + nAllyHighestPower; + SetLocalInt(oCreature, AI_ALLY_POWER, nAllyPower); + if(AI_DEBUG) ai_Debug("0i_combat", "710", "nEnemyPower: " + IntToString(nEnemyPower) + + " nEnemyHighestPower: " + IntToString(nEnemyHighestPower) + + " nAllyPower: " + IntToString(nAllyPower) + + " nAllyHighestPower: " + IntToString(nAllyHighestPower)); + if(AI_DEBUG) ai_Counter_End(GetName(oCreature) + " has finished the Combat State"); + return oNearestEnemy; +} +void ai_ClearCombatState(object oCreature) +{ + int bEnemyDone, bAllyDone, nCnt = 1; + int nEnemyNum = GetLocalInt(oCreature, AI_ENEMY_NUMBERS); + int nAllyNum = GetLocalInt(oCreature, AI_ALLY_NUMBERS); + if(AI_DEBUG) ai_Debug("0i_combat", "722", "Clearing " + GetName(oCreature) + "'s combat state." + + " nEnemyNum: " + IntToString(nEnemyNum) + " nAllyNum: " + IntToString(nAllyNum)); + string sCnt; + while(!bEnemyDone || !bAllyDone) + { + sCnt = IntToString(nCnt); + if(nCnt <= nEnemyNum) + { + if(AI_DEBUG) ai_Debug("0i_combat", "730", "Clearing " + GetName(GetLocalObject(oCreature, AI_ENEMY + sCnt)) + "."); + DeleteLocalObject(oCreature, AI_ENEMY + sCnt); + DeleteLocalInt(oCreature, AI_ENEMY_DISABLED + sCnt); + DeleteLocalInt(oCreature, AI_ENEMY_PERCEIVED + sCnt); + DeleteLocalFloat(oCreature, AI_ENEMY_RANGE + sCnt); + DeleteLocalInt(oCreature, AI_ENEMY_COMBAT + sCnt); + DeleteLocalInt(oCreature, AI_ENEMY_MELEE + sCnt); + DeleteLocalInt(oCreature, AI_ENEMY_HEALTH + sCnt); + } + else bEnemyDone = TRUE; + if(nCnt <= nAllyNum) + { + if(AI_DEBUG) ai_Debug("0i_combat", "742", "Clearing " + GetName(GetLocalObject(oCreature, AI_ALLY + sCnt)) + "."); + DeleteLocalObject(oCreature, AI_ALLY + sCnt); + DeleteLocalInt(oCreature, AI_ALLY_DISABLED + sCnt); + DeleteLocalInt(oCreature, AI_ALLY_PERCEIVED + sCnt); + DeleteLocalFloat(oCreature, AI_ALLY_RANGE + sCnt); + DeleteLocalInt(oCreature, AI_ALLY_COMBAT + sCnt); + DeleteLocalInt(oCreature, AI_ALLY_MELEE + sCnt); + DeleteLocalInt(oCreature, AI_ALLY_HEALTH + sCnt); + } + else bAllyDone = TRUE; + nCnt++; + } + DeleteLocalObject(oCreature, AI_ENEMY_NEAREST); + DeleteLocalInt(oCreature, AI_ENEMY_NUMBERS); + DeleteLocalInt(oCreature, AI_ENEMY_POWER); + DeleteLocalInt(oCreature, AI_ALLY_NUMBERS); + DeleteLocalObject(oCreature, AI_ALLY_POWER); + // Also clear these combat variables at the end of combat. + DeleteLocalObject(oCreature, AI_ATTACKED_PHYSICAL); + DeleteLocalObject(oCreature, AI_ATTACKED_SPELL); + // Remove Talent variables. + DeleteLocalJson(oCreature, AI_TALENT_CURE); + DeleteLocalJson(oCreature, AI_TALENT_HEALING); + DeleteLocalJson(oCreature, AI_TALENT_ENHANCEMENT); + DeleteLocalJson(oCreature, AI_TALENT_PROTECTION); + DeleteLocalJson(oCreature, AI_TALENT_SUMMON); + DeleteLocalJson(oCreature, AI_TALENT_DISCRIMINANT_AOE); + DeleteLocalJson(oCreature, AI_TALENT_INDISCRIMINANT_AOE); + DeleteLocalJson(oCreature, AI_TALENT_RANGED); + DeleteLocalJson(oCreature, AI_TALENT_TOUCH); + DeleteLocalInt(oCreature, AI_MAX_TALENT + AI_TALENT_CURE); + DeleteLocalInt(oCreature, AI_MAX_TALENT + AI_TALENT_HEALING); + DeleteLocalInt(oCreature, AI_MAX_TALENT + AI_TALENT_ENHANCEMENT); + DeleteLocalInt(oCreature, AI_MAX_TALENT + AI_TALENT_PROTECTION); + DeleteLocalInt(oCreature, AI_MAX_TALENT + AI_TALENT_SUMMON); + DeleteLocalInt(oCreature, AI_MAX_TALENT + AI_TALENT_DISCRIMINANT_AOE); + DeleteLocalInt(oCreature, AI_MAX_TALENT + AI_TALENT_INDISCRIMINANT_AOE); + DeleteLocalInt(oCreature, AI_MAX_TALENT + AI_TALENT_RANGED); + DeleteLocalInt(oCreature, AI_MAX_TALENT + AI_TALENT_TOUCH); + DeleteLocalInt(oCreature, AI_AM_I_SEARCHING); + DeleteLocalInt(oCreature, AI_TRIED_TO_HIDE); + DeleteLocalObject(oCreature, AI_IS_INVISIBLE); + DeleteLocalInt(oCreature, sLastActionVarname); + DeleteLocalInt(oCreature, AI_TALENTS_SET); + DeleteLocalInt(oCreature, AI_ROUND); + DeleteLocalInt(oCreature, sIPHasHasteVarname); + DeleteLocalInt(oCreature, sIPImmuneVarname); + DeleteLocalInt(oCreature, sIPResistVarname); + DeleteLocalInt(oCreature, sIPReducedVarname); + ai_EndCombatRound(oCreature); +} +//****************************************************************************** +//*********************** GET TARGETS INTERNAL FUNCTIONS *********************** +//****************************************************************************** +// These functions are used by the Get Index/ Get Target functions below. + +int ai_TargetIsInRangeofCreature(object oCreature, string sTargetType, string sCounter, float fMaxRange) +{ + if(AI_DEBUG) ai_Debug("0i_combat", "796", "fMaxRange: " + FloatToString(fMaxRange, 0, 2) + + " fTargetRange: " + FloatToString(GetLocalFloat(oCreature, sTargetType + "_RANGE" + sCounter), 0, 2)); + return fMaxRange >= GetLocalFloat(oCreature, sTargetType + "_RANGE" + sCounter); +} +int ai_TargetIsInRangeofMaster(object oCreature, object oTarget) +{ + object oMaster = GetMaster(); + if(oMaster == OBJECT_INVALID) return TRUE; + float fMaxRange = GetLocalFloat(oCreature, AI_ASSOC_PERCEPTION_DISTANCE); + if(fMaxRange == 0.0) fMaxRange = 20.0; + float fTargetRangefromMaster = GetDistanceBetween(oTarget, oMaster); + if(AI_DEBUG) ai_Debug("0i_combat", "807", "fMaxRangefromMaster: " + FloatToString(fMaxRange, 0, 2) + + " fTargetRangefromMaster: " + FloatToString(fTargetRangefromMaster, 0, 2)); + return fMaxRange >= fTargetRangefromMaster; +} +struct stTarget ai_CheckForNearestTarget(object oCreature, struct stTarget sTarget, int nIndex, string sIndex) +{ + if(AI_DEBUG) ai_Debug("0i_combat", "817", "Getting nearest index: " + sIndex + + " fRange: " + FloatToString(GetLocalFloat(oCreature, sTarget.sTargetType + "_RANGE" + sIndex), 0, 2) + + " fNearestRange: " + FloatToString(sTarget.fNearestRange, 0, 2) + + " fNearestSecondaryRange: " + FloatToString(sTarget.fNearestSecondaryRange, 0, 2)); + // Lets put any disabled targets and associates if set in a secondary group. + if(GetLocalInt(oCreature, sTarget.sTargetType + "_DISABLED" + sIndex) || + (ai_GetAIMode(oCreature, AI_MODE_IGNORE_ASSOCIATES) && GetAssociateType(sTarget.oTarget))) + { + if(GetLocalFloat(oCreature, sTarget.sTargetType + "_RANGE" + sIndex) < sTarget.fNearestSecondaryRange) + { + sTarget.fNearestSecondaryRange = GetLocalFloat(oCreature, sTarget.sTargetType + "_RANGE" + sIndex); + sTarget.nSecondaryIndex = nIndex; + } + } + else if(GetLocalFloat(oCreature, sTarget.sTargetType + "_RANGE" + sIndex) < sTarget.fNearestRange) + { + sTarget.fNearestRange = GetLocalFloat(oCreature, sTarget.sTargetType + "_RANGE" + sIndex); + sTarget.nIndex = nIndex; + } + return sTarget; +} +struct stTarget ai_CheckForLowestValueTarget(object oCreature, struct stTarget sTarget, int nIndex, string sIndex) +{ + if(AI_DEBUG) ai_Debug("0i_combat", "835", "Getting lowest value index: " + sIndex + + " fRange: " + FloatToString(GetLocalFloat(oCreature, sTarget.sTargetType + "_RANGE" + sIndex), 0, 2) + + " fNearestRange: " + FloatToString(GetLocalFloat(oCreature, sTarget.sTargetType + "_RANGE" + sIndex), 0, 2) + + " fNearestSecondaryRange: " + FloatToString(sTarget.fNearestSecondaryRange, 0, 2) + + " sTarget.nValue: " + IntToString(sTarget.nValue) + + " sTarget.nBestValue: " + IntToString(sTarget.nBestValue) + + " sTarget.nBestSecondaryValue: " + IntToString(sTarget.nBestSecondaryValue)); + // Lets put any disabled targets and associates if set in a secondary group. + if(GetLocalInt(oCreature, sTarget.sTargetType + "_DISABLED" + sIndex) || + (ai_GetAIMode(oCreature, AI_MODE_IGNORE_ASSOCIATES) && GetAssociateType(sTarget.oTarget))) + { + if(sTarget.nValue < sTarget.nBestSecondaryValue || + (sTarget.nValue == sTarget.nBestSecondaryValue && + GetLocalFloat(oCreature, sTarget.sTargetType + "_RANGE" + sIndex) < sTarget.fNearestSecondaryRange)) + { + sTarget.fNearestSecondaryRange = GetLocalFloat(oCreature, sTarget.sTargetType + "_RANGE" + sIndex); + sTarget.nBestSecondaryValue = sTarget.nValue; + sTarget.nSecondaryIndex = nIndex; + } + } + // Has less value or equal value and is closer. + else if(sTarget.nValue < sTarget.nBestValue || + (sTarget.nBestValue == sTarget.nValue && + GetLocalFloat(oCreature, sTarget.sTargetType + "_RANGE" + sIndex) < sTarget.fNearestRange)) + { + sTarget.fNearestRange = GetLocalFloat(oCreature, sTarget.sTargetType + "_RANGE" + sIndex); + sTarget.nBestValue = sTarget.nValue; + sTarget.nIndex = nIndex; + } + return sTarget; +} +struct stTarget ai_CheckForHighestValueTarget(object oCreature, struct stTarget sTarget, int nIndex, string sIndex) +{ + if(AI_DEBUG) ai_Debug("0i_combat", "865", "Getting highest value index: " + sIndex + + " fRange: " + FloatToString(GetLocalFloat(oCreature, sTarget.sTargetType + "_RANGE" + sIndex), 0, 2) + + " fNearestRange: " + FloatToString(sTarget.fNearestRange, 0, 2) + + " fNearestSecondaryRange: " + FloatToString(sTarget.fNearestSecondaryRange, 0, 2) + + " sTarget.nValue: " + IntToString(sTarget.nValue) + + " sTarget.nBestValue: " + IntToString(sTarget.nBestValue) + + " sTarget.nBestSecondaryValue: " + IntToString(sTarget.nBestSecondaryValue)); + // Lets put any disabled targets and associates if set in a secondary group. + if(GetLocalInt(oCreature, sTarget.sTargetType + "_DISABLED" + sIndex) || + (ai_GetAIMode(oCreature, AI_MODE_IGNORE_ASSOCIATES) && GetAssociateType(sTarget.oTarget))) + { + if(sTarget.nValue > sTarget.nBestSecondaryValue || + (sTarget.nValue == sTarget.nBestSecondaryValue && + GetLocalFloat(oCreature, sTarget.sTargetType + "_RANGE" + sIndex) < sTarget.fNearestSecondaryRange)) + { + sTarget.fNearestSecondaryRange = GetLocalFloat(oCreature, sTarget.sTargetType + "_RANGE" + sIndex); + sTarget.nBestSecondaryValue = sTarget.nValue; + sTarget.nSecondaryIndex = nIndex; + } + } + // Has less value or equal value and is closer. + else if(sTarget.nValue > sTarget.nBestValue || + (sTarget.nBestValue == sTarget.nValue && + GetLocalFloat(oCreature, sTarget.sTargetType + "_RANGE" + sIndex) < sTarget.fNearestRange)) + { + sTarget.fNearestRange = GetLocalFloat(oCreature, sTarget.sTargetType + "_RANGE" + sIndex); + sTarget.nBestValue = sTarget.nValue; + sTarget.nIndex = nIndex; + } + return sTarget; +} +struct stTarget ai_CheckForNearestAllTarget(object oCreature, struct stTarget sTarget, int nIndex, string sIndex) +{ + if(AI_DEBUG) ai_Debug("0i_combat", "895", "Getting nearest (not disabled) index: " + sIndex + + " fRange: " + FloatToString(GetLocalFloat(oCreature, sTarget.sTargetType + "_RANGE" + sIndex), 0, 2) + + " fNearestRange: " + FloatToString(sTarget.fNearestRange, 0, 2)); + // If we are ignoring associates set then ignore them. + // Has lower value or equal value and is closer. Familiars/Companions/Summons/Dominated. + if(AI_DEBUG) ai_Debug("0i_combat", "911", "Don't Ignore Associate: " + IntToString(!ai_GetAIMode(oCreature, AI_MODE_IGNORE_ASSOCIATES)) + + " Not an Associate? " + IntToString(GetAssociateType(sTarget.oTarget) < 2)); + if((!ai_GetAIMode(oCreature, AI_MODE_IGNORE_ASSOCIATES) || GetAssociateType(sTarget.oTarget) < 2) && + GetLocalFloat(oCreature, sTarget.sTargetType + "_RANGE" + sIndex) < sTarget.fNearestRange) + { + sTarget.fNearestRange = GetLocalFloat(oCreature, sTarget.sTargetType + "_RANGE" + sIndex); + sTarget.nIndex = nIndex; + } + return sTarget; +} +struct stTarget ai_CheckForLowestValueAllTarget(object oCreature, struct stTarget sTarget, int nIndex, string sIndex) +{ + if(AI_DEBUG) ai_Debug("0i_combat", "923", "Getting lowest value index: " + sIndex + + " fRange: " + FloatToString(GetLocalFloat(oCreature, sTarget.sTargetType + "_RANGE" + sIndex), 0, 2) + + " fNearestRange: " + FloatToString(sTarget.fNearestRange, 0, 2) + + " sTarget.nValue: " + IntToString(sTarget.nValue) + + " sTarget.nBestValue: " + IntToString(sTarget.nBestValue)); + // Has less value or equal value and is closer. Ignoring only Familiars/Companions/Summons/Dominated. + if(AI_DEBUG) ai_Debug("0i_combat", "922", "Don't Ignore Associate: " + IntToString(!ai_GetAIMode(oCreature, AI_MODE_IGNORE_ASSOCIATES)) + + " Not an Associate? " + IntToString(GetAssociateType(sTarget.oTarget) < 2)); + if((!ai_GetAIMode(oCreature, AI_MODE_IGNORE_ASSOCIATES) || GetAssociateType(sTarget.oTarget) < 2) && + sTarget.nValue < sTarget.nBestValue || + (sTarget.nBestValue == sTarget.nValue && + GetLocalFloat(oCreature, sTarget.sTargetType + "_RANGE" + sIndex) < sTarget.fNearestRange)) + { + sTarget.fNearestRange = GetLocalFloat(oCreature, sTarget.sTargetType + "_RANGE" + sIndex); + sTarget.nBestValue = sTarget.nValue; + sTarget.nIndex = nIndex; + } + return sTarget; +} + +//****************************************************************************** +//************ GET INDEX/TARGETs USING COMBAT STATE FUNCTIONS ****************** +//****************************************************************************** +// These functions will find a target based on the combat state variables created +// by the function ai_SetCombatState for associates. + +int ai_GetNearestIndex(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE) +{ + if(GetLocalInt(oCreature, AI_RULE_AI_DIFFICULTY)) + { + return ai_GetLowestCRIndex(oCreature, fMaxRange, sTargetType, bAlwaysAtk); + } + struct stTarget sTarget; + sTarget.fNearestRange = fMaxRange + 1.0; + sTarget.fNearestSecondaryRange = sTarget.fNearestRange; + sTarget.sTargetType = sTargetType; + int nCounter = 1; + string sCounter = "1"; + sTarget.oTarget = GetLocalObject(oCreature, sTargetType + sCounter); + while(sTarget.oTarget != OBJECT_INVALID) + { + if(AI_DEBUG) ai_Debug("0i_combat", "911", "Getting the nearest index: " + + sCounter + " " + GetName(sTarget.oTarget) + + " Seen: " + IntToString(GetLocalInt(oCreature, sTargetType + "_PERCEIVED" + sCounter)) + + " GetIsDead: " + IntToString(GetIsDead(sTarget.oTarget))); + if(GetLocalInt(oCreature, sTargetType + "_PERCEIVED" + sCounter) && + !GetIsDead(sTarget.oTarget)) + { + if(AI_DEBUG) ai_Debug("0i_combat", "918", "bAlwaysAtk: " + IntToString(bAlwaysAtk)); + if((bAlwaysAtk || !ai_IsStrongerThanMe(oCreature, nCounter)) && + ai_TargetIsInRangeofCreature(oCreature, sTargetType, sCounter, fMaxRange) && + ai_TargetIsInRangeofMaster(oCreature, sTarget.oTarget)) + { + sTarget = ai_CheckForNearestTarget(oCreature, sTarget, nCounter, sCounter); + } + } + sCounter = IntToString(++nCounter); + sTarget.oTarget = GetLocalObject(oCreature, sTargetType + sCounter); + } + // If we do not have a normal target then use our best secondary target. + if(sTarget.nIndex == 0 && sTarget.nSecondaryIndex != 0) sTarget.nIndex = sTarget.nSecondaryIndex; + if(AI_DEBUG) ai_Debug("0i_combat", "931", "Found nearest [" + sTargetType + "] Index: " + IntToString(sTarget.nIndex)); + return sTarget.nIndex; +} +object ai_GetNearestTarget(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE) +{ + if(AI_DEBUG) ai_Debug("0i_combat", "936", "Getting the nearest target."); + string sIndex = IntToString(ai_GetNearestIndex(oCreature, fMaxRange, sTargetType, bAlwaysAtk)); + return GetLocalObject(oCreature, sTargetType + sIndex); +} +int ai_GetLowestCRIndex(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE) +{ + struct stTarget sTarget; + sTarget.fNearestRange = fMaxRange + 1.0; + sTarget.fNearestSecondaryRange = sTarget.fNearestRange; + sTarget.nBestValue = 100; + sTarget.nBestSecondaryValue = 100; + sTarget.sTargetType = sTargetType; + int nCounter = 1; + string sCounter = "1"; + sTarget.oTarget = GetLocalObject(oCreature, sTargetType + sCounter); + while(sTarget.oTarget != OBJECT_INVALID) + { + if(AI_DEBUG) ai_Debug("0i_combat", "953", "Getting the lowest CR index: " + + sCounter + " " + GetName(sTarget.oTarget) + + " Seen: " + IntToString(GetLocalInt(oCreature, sTargetType + "_PERCEIVED" + sCounter)) + + " GetIsDead: " + IntToString(GetIsDead(sTarget.oTarget))); + if(GetLocalInt(oCreature, sTargetType + "_PERCEIVED" + sCounter) && + !GetIsDead(sTarget.oTarget)) + { + if(AI_DEBUG) ai_Debug("0i_combat", "960", "bAlwaysAtk: " + IntToString(bAlwaysAtk)); + if((bAlwaysAtk || !ai_IsStrongerThanMe(oCreature, nCounter)) && + ai_TargetIsInRangeofCreature(oCreature, sTargetType, sCounter, fMaxRange) && + ai_TargetIsInRangeofMaster(oCreature, sTarget.oTarget)) + { + sTarget.nValue = GetLocalInt(oCreature, sTargetType + "_COMBAT" + sCounter); + sTarget = ai_CheckForLowestValueTarget(oCreature, sTarget, nCounter, sCounter); + } + } + sCounter = IntToString(++nCounter); + sTarget.oTarget = GetLocalObject(oCreature, sTargetType + sCounter); + } + // If we do not have a normal target then use our best secondary target. + if(sTarget.nIndex == 0 && sTarget.nSecondaryIndex != 0) sTarget.nIndex = sTarget.nSecondaryIndex; + if(AI_DEBUG) ai_Debug("0i_combat", "974", "Found lowest CR [" + sTargetType + "] Index: " + IntToString(sTarget.nIndex)); + return sTarget.nIndex; +} +object ai_GetLowestCRTarget(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE) +{ + if(AI_DEBUG) ai_Debug("0i_combat", "979", "Getting the lowest CR target."); + string sIndex = IntToString(ai_GetLowestCRIndex(oCreature, fMaxRange, sTargetType, bAlwaysAtk)); + return GetLocalObject(oCreature, sTargetType + sIndex); +} +int ai_GetHighestCRIndex(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE) +{ + struct stTarget sTarget; + sTarget.fNearestRange = fMaxRange + 1.0; + sTarget.fNearestSecondaryRange = sTarget.fNearestRange; + sTarget.nBestValue = -100; + sTarget.nBestSecondaryValue = -100; + sTarget.sTargetType = sTargetType; + int nCounter = 1; + string sCounter = "1"; + sTarget.oTarget = GetLocalObject(oCreature, sTargetType + sCounter); + while(sTarget.oTarget != OBJECT_INVALID) + { + if(AI_DEBUG) ai_Debug("0i_combat", "995", "Getting the highest CR index: " + + sCounter + " " + GetName(sTarget.oTarget) + + " Seen: " + IntToString(GetLocalInt(oCreature, sTargetType + "_PERCEIVED" + sCounter)) + + " GetIsDead: " + IntToString(GetIsDead(sTarget.oTarget))); + if(GetLocalInt(oCreature, sTargetType + "_PERCEIVED" + sCounter) && + !GetIsDead(sTarget.oTarget)) + { + if(AI_DEBUG) ai_Debug("0i_combat", "1002", "bAlwaysAtk: " + IntToString(bAlwaysAtk)); + if((bAlwaysAtk || !ai_IsStrongerThanMe(oCreature, nCounter)) && + ai_TargetIsInRangeofCreature(oCreature, sTargetType, sCounter, fMaxRange) && + ai_TargetIsInRangeofMaster(oCreature, sTarget.oTarget)) + { + sTarget.nValue = GetLocalInt(oCreature, sTargetType + "_COMBAT" + sCounter); + sTarget = ai_CheckForHighestValueTarget(oCreature, sTarget, nCounter, sCounter); + } + } + sCounter = IntToString(++nCounter); + sTarget.oTarget = GetLocalObject(oCreature, sTargetType + sCounter); + } + // If we do not have a normal target then use our best secondary target. + if(sTarget.nIndex == 0 && sTarget.nSecondaryIndex != 0) sTarget.nIndex = sTarget.nSecondaryIndex; + if(AI_DEBUG) ai_Debug("0i_combat", "1016", "Found highest CR [" + sTargetType + "] Index: " + IntToString(sTarget.nIndex)); + return sTarget.nIndex; +} +object ai_GetHighestCRTarget(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE) +{ + if(AI_DEBUG) ai_Debug("0i_combat", "1021", "Getting the highest CR target."); + string sIndex = IntToString(ai_GetHighestCRIndex(oCreature, fMaxRange, sTargetType, bAlwaysAtk)); + return GetLocalObject(oCreature, sTargetType + sIndex); +} +int ai_GetLowestMeleeIndex(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY) +{ + struct stTarget sTarget; + sTarget.fNearestRange = fMaxRange + 1.0; + sTarget.fNearestSecondaryRange = sTarget.fNearestRange; + sTarget.nBestValue = 100; + sTarget.nBestSecondaryValue = 100; + sTarget.sTargetType = sTargetType; + int nCounter = 1; + string sCounter = "1"; + sTarget.oTarget = GetLocalObject(oCreature, sTargetType + sCounter); + while(sTarget.oTarget != OBJECT_INVALID) + { + if(AI_DEBUG) ai_Debug("0i_combat", "1037", "Getting the lowest InMelee index: " + + sCounter + " " + GetName(sTarget.oTarget) + + " Seen: " + IntToString(GetLocalInt(oCreature, sTargetType + "_PERCEIVED" + sCounter)) + + " GetIsDead: " + IntToString(GetIsDead(sTarget.oTarget))); + if(GetLocalInt(oCreature, sTargetType + "_PERCEIVED" + sCounter) && + !GetIsDead(sTarget.oTarget)) + { + if(ai_TargetIsInRangeofCreature(oCreature, sTargetType, sCounter, fMaxRange) && + ai_TargetIsInRangeofMaster(oCreature, sTarget.oTarget)) + { + sTarget.nValue = GetLocalInt(oCreature, sTargetType + "_MELEE" + sCounter); + sTarget = ai_CheckForLowestValueTarget(oCreature, sTarget, nCounter, sCounter); + } + } + sCounter = IntToString(++nCounter); + sTarget.oTarget = GetLocalObject(oCreature, sTargetType + sCounter); + } + // If we do not have a normal target then use our best secondary target. + if(sTarget.nIndex == 0 && sTarget.nSecondaryIndex != 0) sTarget.nIndex = sTarget.nSecondaryIndex; + if(AI_DEBUG) ai_Debug("0i_combat", "1058", "Found lowest InMelee [" + sTargetType + "] Index: " + IntToString(sTarget.nIndex)); + return sTarget.nIndex; +} +int ai_GetHighestMeleeIndex(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY) +{ + struct stTarget sTarget; + sTarget.fNearestRange = fMaxRange + 1.0; + sTarget.fNearestSecondaryRange = sTarget.fNearestRange; + sTarget.nBestValue = -100; + sTarget.nBestSecondaryValue = -100; + sTarget.sTargetType = sTargetType; + int nCounter = 1; + string sCounter = "1"; + sTarget.oTarget = GetLocalObject(oCreature, sTargetType + sCounter); + while(sTarget.oTarget != OBJECT_INVALID) + { + if(AI_DEBUG) ai_Debug("0i_combat", "1073", "Getting the highest InMelee index: " + + sCounter + " " + GetName(sTarget.oTarget) + + " Seen: " + IntToString(GetLocalInt(oCreature, sTargetType + "_PERCEIVED" + sCounter)) + + " GetIsDead: " + IntToString(GetIsDead(sTarget.oTarget))); + if(GetLocalInt(oCreature, sTargetType + "_PERCEIVED" + sCounter) && + !GetIsDead(sTarget.oTarget)) + { + if(ai_TargetIsInRangeofCreature(oCreature, sTargetType, sCounter, fMaxRange) && + ai_TargetIsInRangeofMaster(oCreature, sTarget.oTarget)) + { + sTarget.nValue = GetLocalInt(oCreature, sTargetType + "_MELEE" + sCounter); + sTarget = ai_CheckForHighestValueTarget(oCreature, sTarget, nCounter, sCounter); + } + } + sCounter = IntToString(++nCounter); + sTarget.oTarget = GetLocalObject(oCreature, sTargetType + sCounter); + } + // If we do not have a normal target then use our best secondary target. + if(sTarget.nIndex == 0 && sTarget.nSecondaryIndex != 0) sTarget.nIndex = sTarget.nSecondaryIndex; + if(AI_DEBUG) ai_Debug("0i_combat", "1094", "Found highest InMelee [" + sTargetType + "] Index: " + IntToString(sTarget.nIndex)); + return sTarget.nIndex; +} +object ai_CheckForGroupedTarget(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY) +{ + if(AI_DEBUG) ai_Debug("0i_combat", "1124", "Getting the highest InMelee target."); + string sIndex = IntToString(ai_GetHighestMeleeIndex(oCreature, fMaxRange, sTargetType)); + return GetLocalObject(oCreature, sTargetType + sIndex); +} +int ai_GetMostWoundedIndex(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE) +{ + struct stTarget sTarget; + sTarget.fNearestRange = fMaxRange + 1.0; + sTarget.fNearestSecondaryRange = sTarget.fNearestRange; + sTarget.nBestValue = 200; + sTarget.nBestSecondaryValue = 200; + sTarget.sTargetType = sTargetType; + int nCounter = 1; + string sCounter = "1"; + sTarget.oTarget = GetLocalObject(oCreature, sTargetType + sCounter); + while(sTarget.oTarget != OBJECT_INVALID) + { + if(AI_DEBUG) ai_Debug("0i_combat", "1113", "Getting the most wounded index: " + + sCounter + " " + GetName(sTarget.oTarget) + + " Seen: " + IntToString(GetLocalInt(oCreature, sTargetType + "_PERCEIVED" + sCounter)) + + " GetIsDead: " + IntToString(GetIsDead(sTarget.oTarget))); + if(GetLocalInt(oCreature, sTargetType + "_PERCEIVED" + sCounter) && + !GetIsDead(sTarget.oTarget)) + { + if(AI_DEBUG) ai_Debug("0i_combat", "1120", "bAlwaysAtk: " + IntToString(bAlwaysAtk)); + if((bAlwaysAtk || !ai_IsStrongerThanMe(oCreature, nCounter)) && + ai_TargetIsInRangeofCreature(oCreature, sTargetType, sCounter, fMaxRange) && + ai_TargetIsInRangeofMaster(oCreature, sTarget.oTarget)) + { + sTarget.nValue = GetLocalInt(oCreature, sTargetType + "_HEALTH" + sCounter); + sTarget = ai_CheckForLowestValueTarget(oCreature, sTarget, nCounter, sCounter); + } + } + sCounter = IntToString(++nCounter); + sTarget.oTarget = GetLocalObject(oCreature, sTargetType + sCounter); + } + // If we do not have a normal target then use our best secondary target. + if(sTarget.nIndex == 0 && sTarget.nSecondaryIndex != 0) sTarget.nIndex = sTarget.nSecondaryIndex; + if(AI_DEBUG) ai_Debug("0i_combat", "1130", "Found most wounded [" + sTargetType + "] Index: " + IntToString(sTarget.nIndex)); + return sTarget.nIndex; +} +object ai_GetMostWoundedTarget(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE) +{ + if(AI_DEBUG) ai_Debug("0i_combat", "1139", "Getting the most wounded target."); + string sIndex = IntToString(ai_GetMostWoundedIndex(oCreature, fMaxRange, sTargetType, bAlwaysAtk)); + return GetLocalObject(oCreature, sTargetType + sIndex); +} +int ai_GetAllyToHealIndex(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION) +{ + struct stTarget sTarget; + sTarget.fNearestRange = fMaxRange + 1.0; + sTarget.nBestValue = 200; + sTarget.sTargetType = AI_ALLY; + int nCounter = 1; + string sCounter = "1"; + sTarget.oTarget = GetLocalObject(oCreature, sTarget.sTargetType + sCounter); + while(sTarget.oTarget != OBJECT_INVALID) + { + if(AI_DEBUG) ai_Debug("0i_combat", "1154", "Getting the most wounded ally to heal index: " + + sCounter + " " + GetName(sTarget.oTarget) + + " Seen: " + IntToString(GetLocalInt(oCreature, AI_ALLY_PERCEIVED + sCounter)) + + " GetIsDead: " + IntToString(GetIsDead(sTarget.oTarget))); + if(GetLocalInt(oCreature, AI_ALLY_PERCEIVED + sCounter) && + !GetIsDead(sTarget.oTarget)) + { + if(ai_TargetIsInRangeofCreature(oCreature, AI_ALLY, sCounter, fMaxRange) && + ai_TargetIsInRangeofMaster(oCreature, sTarget.oTarget)) + { + sTarget.nValue = GetLocalInt(oCreature, AI_ALLY_HEALTH + sCounter); + sTarget = ai_CheckForLowestValueAllTarget(oCreature, sTarget, nCounter, sCounter); + } + } + sCounter = IntToString(++nCounter); + sTarget.oTarget = GetLocalObject(oCreature, AI_ALLY + sCounter); + } + // If we do not have a normal target then we are done.. + if(AI_DEBUG) ai_Debug("0i_combat", "1187", "Found most wounded ally to heal Index: " + IntToString(sTarget.nIndex)); + return sTarget.nIndex; +} +object ai_GetAllyToHealTarget(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION) +{ + if(AI_DEBUG) ai_Debug("0i_combat", "1192", "Getting the most wounded ally to heal target."); + string sIndex = IntToString(ai_GetAllyToHealIndex(oCreature, fMaxRange)); + return GetLocalObject(oCreature, AI_ALLY + sIndex); +} +object ai_GetLowestFortitudeSaveTarget(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION) +{ + struct stTarget sTarget; + sTarget.fNearestRange = fMaxRange + 1.0; + sTarget.fNearestSecondaryRange = sTarget.fNearestRange; + sTarget.nBestValue = 200; + sTarget.nBestSecondaryValue = 200; + sTarget.sTargetType = AI_ENEMY; + int nCounter = 1; + string sCounter = "1"; + sTarget.oTarget = GetLocalObject(oCreature, AI_ENEMY + sCounter); + while(sTarget.oTarget != OBJECT_INVALID) + { + if(AI_DEBUG) ai_Debug("0i_combat", "1113", "Getting the lowest fortitude save index: " + + sCounter + " " + GetName(sTarget.oTarget) + + " Seen: " + IntToString(GetLocalInt(oCreature, AI_ENEMY_PERCEIVED + sCounter)) + + " GetIsDead: " + IntToString(GetIsDead(sTarget.oTarget))); + if(GetLocalInt(oCreature, AI_ENEMY_PERCEIVED + sCounter) && + !GetIsDead(sTarget.oTarget)) + { + if(ai_TargetIsInRangeofCreature(oCreature, AI_ENEMY, sCounter, fMaxRange) + + ai_TargetIsInRangeofMaster(oCreature, sTarget.oTarget)) + { + sTarget.nValue = GetFortitudeSavingThrow(sTarget.oTarget); + sTarget = ai_CheckForLowestValueTarget(oCreature, sTarget, nCounter, sCounter); + } + } + sCounter = IntToString(++nCounter); + sTarget.oTarget = GetLocalObject(oCreature, AI_ENEMY + sCounter); + } + // If we do not have a normal target then use our best secondary target. + if(sTarget.nIndex == 0 && sTarget.nSecondaryIndex != 0) sTarget.nIndex = sTarget.nSecondaryIndex; + if(AI_DEBUG) ai_Debug("0i_combat", "1232", "Found lowest fortitude save Index: " + IntToString(sTarget.nIndex)); + return GetLocalObject(oCreature, AI_ENEMY + IntToString(sTarget.nIndex)); +} +object ai_GetLowestReflexSaveTarget(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION) +{ + struct stTarget sTarget; + sTarget.fNearestRange = fMaxRange + 1.0; + sTarget.fNearestSecondaryRange = sTarget.fNearestRange; + sTarget.nBestValue = 200; + sTarget.nBestSecondaryValue = 200; + sTarget.sTargetType = AI_ENEMY; + int nCounter = 1; + string sCounter = "1"; + sTarget.oTarget = GetLocalObject(oCreature, AI_ENEMY + sCounter); + while(sTarget.oTarget != OBJECT_INVALID) + { + if(AI_DEBUG) ai_Debug("0i_combat", "1248", "Getting the lowest reflex save index: " + + sCounter + " " + GetName(sTarget.oTarget) + + " Seen: " + IntToString(GetLocalInt(oCreature, AI_ENEMY_PERCEIVED + sCounter)) + + " GetIsDead: " + IntToString(GetIsDead(sTarget.oTarget))); + if(GetLocalInt(oCreature, AI_ENEMY_PERCEIVED + sCounter) && + !GetIsDead(sTarget.oTarget)) + { + if(ai_TargetIsInRangeofCreature(oCreature, AI_ENEMY, sCounter, fMaxRange) + + ai_TargetIsInRangeofMaster(oCreature, sTarget.oTarget)) + { + sTarget.nValue = GetReflexSavingThrow(sTarget.oTarget); + sTarget = ai_CheckForLowestValueTarget(oCreature, sTarget, nCounter, sCounter); + } + } + sCounter = IntToString(++nCounter); + sTarget.oTarget = GetLocalObject(oCreature, AI_ENEMY + sCounter); + } + // If we do not have a normal target then use our best secondary target. + if(sTarget.nIndex == 0 && sTarget.nSecondaryIndex != 0) sTarget.nIndex = sTarget.nSecondaryIndex; + if(AI_DEBUG) ai_Debug("0i_combat", "1269", "Found lowest reflex save Index: " + IntToString(sTarget.nIndex)); + return GetLocalObject(oCreature, AI_ENEMY + IntToString(sTarget.nIndex)); +} +object ai_GetLowestWillSaveTarget(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION) +{ + struct stTarget sTarget; + sTarget.fNearestRange = fMaxRange + 1.0; + sTarget.fNearestSecondaryRange = sTarget.fNearestRange; + sTarget.nBestValue = 200; + sTarget.nBestSecondaryValue = 200; + sTarget.sTargetType = AI_ENEMY; + int nCounter = 1; + string sCounter = "1"; + sTarget.oTarget = GetLocalObject(oCreature, AI_ENEMY + sCounter); + while(sTarget.oTarget != OBJECT_INVALID) + { + if(AI_DEBUG) ai_Debug("0i_combat", "1285", "Getting the lowest will save index: " + + sCounter + " " + GetName(sTarget.oTarget) + + " Seen: " + IntToString(GetLocalInt(oCreature, AI_ENEMY_PERCEIVED + sCounter)) + + " GetIsDead: " + IntToString(GetIsDead(sTarget.oTarget))); + if(GetLocalInt(oCreature, AI_ENEMY_PERCEIVED + sCounter) && + !GetIsDead(sTarget.oTarget)) + { + if(ai_TargetIsInRangeofCreature(oCreature, AI_ENEMY, sCounter, fMaxRange) + + ai_TargetIsInRangeofMaster(oCreature, sTarget.oTarget)) + { + sTarget.nValue = GetWillSavingThrow(sTarget.oTarget); + sTarget = ai_CheckForLowestValueTarget(oCreature, sTarget, nCounter, sCounter); + } + } + sCounter = IntToString(++nCounter); + sTarget.oTarget = GetLocalObject(oCreature, AI_ENEMY + sCounter); + } + // If we do not have a normal target then use our best secondary target. + if(sTarget.nIndex == 0 && sTarget.nSecondaryIndex != 0) sTarget.nIndex = sTarget.nSecondaryIndex; + if(AI_DEBUG) ai_Debug("0i_combat", "1306", "Found lowest will save Index: " + IntToString(sTarget.nIndex)); + return GetLocalObject(oCreature, AI_ENEMY + IntToString(sTarget.nIndex)); +} +object ai_GetSpellTargetBasedOnSaves(object oCreature, int nSpell, float fMaxRange = AI_RANGE_PERCEPTION) +{ + // Check the spells save type in "ai_spells.2da" and find the weakest + // creature based on that save. + string sSaveType = Get2DAString("ai_spells", "SaveType", nSpell); + if(sSaveType == "Reflex") return ai_GetLowestReflexSaveTarget(oCreature, fMaxRange); + if(sSaveType == "Fortitude") return ai_GetLowestFortitudeSaveTarget(oCreature, fMaxRange); + if(sSaveType == "Will") return ai_GetLowestWillSaveTarget(oCreature, fMaxRange); + // If there is no save then lets see if we can find an enemy with the lowest health. + return ai_GetMostWoundedTarget(oCreature, fMaxRange); +} +int ai_GetNearestIndexThatSeesUs(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION) +{ + struct stTarget sTarget; + sTarget.fNearestRange = fMaxRange + 1.0; + sTarget.fNearestSecondaryRange = sTarget.fNearestRange; + sTarget.sTargetType = AI_ENEMY; + int nCounter = 1; + string sCounter = "1"; + sTarget.oTarget = GetLocalObject(oCreature, AI_ENEMY + sCounter); + while(sTarget.oTarget != OBJECT_INVALID) + { + if(AI_DEBUG) ai_Debug("0i_combat", "1334", "Getting the nearest creature that sees us index: " + + sCounter + " " + GetName(sTarget.oTarget) + + " Seen: " + IntToString(GetLocalInt(oCreature, AI_ENEMY_PERCEIVED + sCounter)) + + " GetIsDead: " + IntToString(GetIsDead(sTarget.oTarget))); + if(GetLocalInt(oCreature, AI_ENEMY_PERCEIVED + sCounter) && + !GetIsDead(sTarget.oTarget)) + { + if(ai_TargetIsInRangeofCreature(oCreature, AI_ENEMY, sCounter, fMaxRange) + + ai_TargetIsInRangeofMaster(oCreature, sTarget.oTarget)) + { + if(AI_DEBUG) ai_Debug("0i_combat", "1373", GetName(sTarget.oTarget) + " can see us? " + + IntToString(GetObjectSeen(oCreature, sTarget.oTarget))); + if(GetObjectSeen(oCreature, sTarget.oTarget)) + { + sTarget = ai_CheckForNearestAllTarget(oCreature, sTarget, nCounter, sCounter); + } + } + } + sCounter = IntToString(++nCounter); + sTarget.oTarget = GetLocalObject(oCreature, AI_ENEMY + sCounter); + } + // If we do not have a normal target then use our best secondary target. + if(AI_DEBUG) ai_Debug("0i_combat", "1354", "Found nearest creature that sees us Index: " + IntToString(sTarget.nIndex)); + return sTarget.nIndex; +} +int ai_GetBestSneakAttackIndex(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, int bAlwaysAtk = TRUE) +{ + struct stTarget sTarget; + sTarget.fNearestRange = fMaxRange + 1.0; + sTarget.fNearestSecondaryRange = sTarget.fNearestRange; + sTarget.sTargetType = AI_ENEMY; + int nCounter = 1; + string sCounter = "1"; + object oAttacking; + sTarget.oTarget = GetLocalObject(oCreature, AI_ENEMY + sCounter); + while(sTarget.oTarget != OBJECT_INVALID) + { + if(AI_DEBUG) ai_Debug("0i_combat", "1372", "Getting the best sneak attack index: " + + sCounter + " " + GetName(sTarget.oTarget) + + " Seen: " + IntToString(GetLocalInt(oCreature, AI_ENEMY_PERCEIVED + sCounter)) + + " GetIsDead: " + IntToString(GetIsDead(sTarget.oTarget))); + if(GetLocalInt(oCreature, AI_ENEMY_PERCEIVED + sCounter) && + !GetIsDead(sTarget.oTarget) && + !ai_IsImmuneToSneakAttacks(oCreature, sTarget.oTarget)) + { + if(ai_TargetIsInRangeofCreature(oCreature, AI_ENEMY, sCounter, fMaxRange) + + ai_TargetIsInRangeofMaster(oCreature, sTarget.oTarget)) + { + oAttacking = ai_GetAttackedTarget(sTarget.oTarget); + if(AI_DEBUG) ai_Debug("0i_combat", "1383", "oTarget: " + GetName(sTarget.oTarget) + + " is attacking " + GetName(oAttacking)); + // They are attacking someone besides us or we are hidden? + if((oAttacking != OBJECT_INVALID && oAttacking != oCreature) || + GetActionMode(oCreature, ACTION_MODE_STEALTH)) + { + sTarget = ai_CheckForNearestTarget(oCreature, sTarget, nCounter, sCounter); + } + } + } + sCounter = IntToString(++nCounter); + sTarget.oTarget = GetLocalObject(oCreature, AI_ENEMY + sCounter); + } + // If we do not have a normal target then use our best secondary target. + if(sTarget.nIndex == 0 && sTarget.nSecondaryIndex != 0) sTarget.nIndex = sTarget.nSecondaryIndex; + if(AI_DEBUG) ai_Debug("0i_combat", "1398", "Found best sneak attack Index: " + IntToString(sTarget.nIndex)); + return sTarget.nIndex; +} +int ai_GetNearestIndexNotInAOE(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE) +{ + if(GetLocalInt(oCreature, AI_RULE_AI_DIFFICULTY)) + { + ai_GetLowestCRIndexNotInAOE(oCreature, fMaxRange, sTargetType, bAlwaysAtk); + } + struct stTarget sTarget; + sTarget.fNearestRange = fMaxRange + 1.0; + sTarget.fNearestSecondaryRange = sTarget.fNearestRange; + sTarget.sTargetType = AI_ENEMY; + int nCounter = 1; + string sCounter = "1"; + sTarget.oTarget = GetLocalObject(oCreature, AI_ENEMY + sCounter); + while(sTarget.oTarget != OBJECT_INVALID) + { + if(AI_DEBUG) ai_Debug("0i_combat", "1416", "Getting the nearest not in AOE index: " + + sCounter + " " + GetName(sTarget.oTarget) + + " Seen: " + IntToString(GetLocalInt(oCreature, AI_ENEMY_PERCEIVED + sCounter)) + + " GetIsDead: " + IntToString(GetIsDead(sTarget.oTarget))); + if(GetLocalInt(oCreature, AI_ENEMY_PERCEIVED + sCounter) && + !GetIsDead(sTarget.oTarget) && !ai_IsInADangerousAOE(sTarget.oTarget)) + { + if(ai_TargetIsInRangeofCreature(oCreature, AI_ENEMY, sCounter, fMaxRange) + + ai_TargetIsInRangeofMaster(oCreature, sTarget.oTarget)) + { + sTarget = ai_CheckForNearestTarget(oCreature, sTarget, nCounter, sCounter); + } + } + sCounter = IntToString(++nCounter); + sTarget.oTarget = GetLocalObject(oCreature, AI_ENEMY + sCounter); + } + // If we do not have a normal target then use our best secondary target. + if(sTarget.nIndex == 0 && sTarget.nSecondaryIndex != 0) sTarget.nIndex = sTarget.nSecondaryIndex; + if(AI_DEBUG) ai_Debug("0i_combat", "1434", "Found nearest not in AOE Index: " + IntToString(sTarget.nIndex)); + return sTarget.nIndex; +} +object ai_GetNearestTargetNotInAOE(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE) +{ + if(AI_DEBUG) ai_Debug("0i_combat", "1439", "Getting the nearest not in AOE target."); + string sIndex = IntToString(ai_GetNearestIndexNotInAOE(oCreature, fMaxRange, sTargetType, bAlwaysAtk)); + return GetLocalObject(oCreature, sTargetType + sIndex); +} +int ai_GetLowestCRIndexNotInAOE(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE) +{ + struct stTarget sTarget; + sTarget.fNearestRange = fMaxRange + 1.0; + sTarget.fNearestSecondaryRange = sTarget.fNearestRange; + sTarget.nBestValue = 100; + sTarget.nBestSecondaryValue = 100; + sTarget.sTargetType = sTargetType; + int nCounter = 1; + string sCounter = "1"; + sTarget.oTarget = GetLocalObject(oCreature, sTargetType + sCounter); + while(sTarget.oTarget != OBJECT_INVALID) + { + if(AI_DEBUG) ai_Debug("0i_combat", "1456", "Getting the lowest CR not in AOE index: " + + sCounter + " " + GetName(sTarget.oTarget) + + " Seen: " + IntToString(GetLocalInt(oCreature, sTargetType + "_PERCEIVED" + sCounter)) + + " GetIsDead: " + IntToString(GetIsDead(sTarget.oTarget))); + if(GetLocalInt(oCreature, sTargetType + "_PERCEIVED" + sCounter) && + !GetIsDead(sTarget.oTarget) && !ai_IsInADangerousAOE(sTarget.oTarget)) + { + if(AI_DEBUG) ai_Debug("0i_combat", "1463", "bAlwaysAtk: " + IntToString(bAlwaysAtk)); + if((bAlwaysAtk || !ai_IsStrongerThanMe(oCreature, nCounter)) && + ai_TargetIsInRangeofCreature(oCreature, sTargetType, sCounter, fMaxRange) && + ai_TargetIsInRangeofMaster(oCreature, sTarget.oTarget)) + { + sTarget.nValue = GetLocalInt(oCreature, sTargetType + "_COMBAT" + sCounter); + sTarget = ai_CheckForLowestValueTarget(oCreature, sTarget, nCounter, sCounter); + } + } + sCounter = IntToString(++nCounter); + sTarget.oTarget = GetLocalObject(oCreature, sTargetType + sCounter); + } + // If we do not have a normal target then use our best secondary target. + if(sTarget.nIndex == 0 && sTarget.nSecondaryIndex != 0) sTarget.nIndex = sTarget.nSecondaryIndex; + if(AI_DEBUG) ai_Debug("0i_combat", "1477", "Found lowest CR not in AOE [" + sTargetType + "] Index: " + IntToString(sTarget.nIndex)); + return sTarget.nIndex; +} +object ai_GetLowestTargetNotInAOE(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE) +{ + if(AI_DEBUG) ai_Debug("0i_combat", "1482", "Getting the lowest cr not in AOE target."); + string sIndex = IntToString(ai_GetLowestCRIndexNotInAOE(oCreature, fMaxRange, sTargetType, bAlwaysAtk)); + return GetLocalObject(oCreature, sTargetType + sIndex); +} +int ai_GetHighestCRIndexNotInAOE(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE) +{ + struct stTarget sTarget; + sTarget.fNearestRange = fMaxRange + 1.0; + sTarget.fNearestSecondaryRange = sTarget.fNearestRange; + sTarget.nBestValue = -100; + sTarget.nBestSecondaryValue = -100; + sTarget.sTargetType = sTargetType; + int nCounter = 1; + string sCounter = "1"; + sTarget.oTarget = GetLocalObject(oCreature, sTargetType + sCounter); + while(sTarget.oTarget != OBJECT_INVALID) + { + if(AI_DEBUG) ai_Debug("0i_combat", "1499", "Getting the highest CR not in AOE index: " + + sCounter + " " + GetName(sTarget.oTarget) + + " Seen: " + IntToString(GetLocalInt(oCreature, sTargetType + "_PERCEIVED" + sCounter)) + + " GetIsDead: " + IntToString(GetIsDead(sTarget.oTarget))); + if(GetLocalInt(oCreature, sTargetType + "_PERCEIVED" + sCounter) && + !GetIsDead(sTarget.oTarget) && !ai_IsInADangerousAOE(sTarget.oTarget)) + { + if(AI_DEBUG) ai_Debug("0i_combat", "1506", "bAlwaysAtk: " + IntToString(bAlwaysAtk)); + if((bAlwaysAtk || !ai_IsStrongerThanMe(oCreature, nCounter)) && + ai_TargetIsInRangeofCreature(oCreature, sTargetType, sCounter, fMaxRange) && + ai_TargetIsInRangeofMaster(oCreature, sTarget.oTarget)) + { + sTarget.nValue = GetLocalInt(oCreature, sTargetType + "_COMBAT" + sCounter); + sTarget = ai_CheckForHighestValueTarget(oCreature, sTarget, nCounter, sCounter); + } + } + sCounter = IntToString(++nCounter); + sTarget.oTarget = GetLocalObject(oCreature, sTargetType + sCounter); + } + // If we do not have a normal target then use our best secondary target. + if(sTarget.nIndex == 0 && sTarget.nSecondaryIndex != 0) sTarget.nIndex = sTarget.nSecondaryIndex; + if(AI_DEBUG) ai_Debug("0i_combat", "1520", "Found highest CR not in AOE [" + sTargetType + "] Index: " + IntToString(sTarget.nIndex)); + return sTarget.nIndex; +} +object ai_GetHighestTargetNotInAOE(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE) +{ + if(AI_DEBUG) ai_Debug("0i_combat", "1525", "Getting the highest cr not in AOE target."); + string sIndex = IntToString(ai_GetHighestCRIndexNotInAOE(oCreature, fMaxRange, sTargetType, bAlwaysAtk)); + return GetLocalObject(oCreature, sTargetType + sIndex); +} +int ai_GetHighestMeleeIndexNotInAOE(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY) +{ + struct stTarget sTarget; + sTarget.fNearestRange = fMaxRange + 1.0; + sTarget.fNearestSecondaryRange = sTarget.fNearestRange; + sTarget.nBestValue = -100; + sTarget.nBestSecondaryValue = -100; + sTarget.sTargetType = sTargetType; + int nCounter = 1; + string sCounter = "1"; + sTarget.oTarget = GetLocalObject(oCreature, sTargetType + sCounter); + while(sTarget.oTarget != OBJECT_INVALID) + { + if(AI_DEBUG) ai_Debug("0i_combat", "1542", "Getting the highest InMelee not in AOE index: " + + sCounter + " " + GetName(sTarget.oTarget) + + " Seen: " + IntToString(GetLocalInt(oCreature, sTargetType + "_PERCEIVED" + sCounter)) + + " GetIsDead: " + IntToString(GetIsDead(sTarget.oTarget))); + if(GetLocalInt(oCreature, sTargetType + "_PERCEIVED" + sCounter) && + !GetIsDead(sTarget.oTarget) && !ai_IsInADangerousAOE(sTarget.oTarget)) + { + if(ai_TargetIsInRangeofCreature(oCreature, sTargetType, sCounter, fMaxRange) && + ai_TargetIsInRangeofMaster(oCreature, sTarget.oTarget)) + { + sTarget.nValue = GetLocalInt(oCreature, sTargetType + "_MELEE" + sCounter); + sTarget = ai_CheckForHighestValueTarget(oCreature, sTarget, nCounter, sCounter); + } + } + sCounter = IntToString(++nCounter); + sTarget.oTarget = GetLocalObject(oCreature, sTargetType + sCounter); + } + // If we do not have a normal target then use our best secondary target. + if(sTarget.nIndex == 0 && sTarget.nSecondaryIndex != 0) sTarget.nIndex = sTarget.nSecondaryIndex; + if(AI_DEBUG) ai_Debug("0i_combat", "1563", "Found highest InMelee not in AOE [" + sTargetType + "] Index: " + IntToString(sTarget.nIndex)); + return sTarget.nIndex; +} +object ai_CheckForGroupedTargetNotInAOE(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY) +{ + if(AI_DEBUG) ai_Debug("0i_combat", "1574", "Getting the highest InMelee not in AOE target."); + string sIndex = IntToString(ai_GetHighestMeleeIndexNotInAOE(oCreature, fMaxRange, sTargetType)); + return GetLocalObject(oCreature, sTargetType + sIndex); +} +object ai_GetNearestClassTarget(object oCreature, int nClassType, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE) +{ + if(GetLocalInt(oCreature, AI_RULE_AI_DIFFICULTY)) + { + ai_GetLowestCRClassTarget(oCreature, nClassType, fMaxRange, sTargetType, bAlwaysAtk); + } + struct stTarget sTarget; + sTarget.fNearestRange = fMaxRange + 1.0; + sTarget.fNearestSecondaryRange = sTarget.fNearestRange; + sTarget.sTargetType = sTargetType; + int nCounter = 1; + string sCounter = "1"; + sTarget.oTarget = GetLocalObject(oCreature, sTargetType + sCounter); + while(sTarget.oTarget != OBJECT_INVALID) + { + if(AI_DEBUG) ai_Debug("0i_combat", "1591", "Getting the nearest class index: " + + sCounter + " " + GetName(sTarget.oTarget) + + " Seen: " + IntToString(GetLocalInt(oCreature, sTargetType + "_PERCEIVED" + sCounter)) + + " GetIsDead: " + IntToString(GetIsDead(sTarget.oTarget))); + if(GetLocalInt(oCreature, sTargetType + "_PERCEIVED" + sCounter) && + !GetIsDead(sTarget.oTarget) && ai_CheckClassType(sTarget.oTarget, nClassType)) + { + if(AI_DEBUG) ai_Debug("0i_combat", "1598", "bAlwaysAtk: " + IntToString(bAlwaysAtk)); + if((bAlwaysAtk || !ai_IsStrongerThanMe(oCreature, nCounter)) && + ai_TargetIsInRangeofCreature(oCreature, sTargetType, sCounter, fMaxRange) && + ai_TargetIsInRangeofMaster(oCreature, sTarget.oTarget)) + { + sTarget = ai_CheckForNearestTarget(oCreature, sTarget, nCounter, sCounter); + } + } + sCounter = IntToString(++nCounter); + sTarget.oTarget = GetLocalObject(oCreature, sTargetType + sCounter); + } + // If we do not have a normal target then use our best secondary target. + if(sTarget.nIndex == 0 && sTarget.nSecondaryIndex != 0) sTarget.nIndex = sTarget.nSecondaryIndex; + if(AI_DEBUG) ai_Debug("0i_combat", "1611", "Found nearest class Index: " + IntToString(sTarget.nIndex)); + return GetLocalObject(oCreature, sTargetType + IntToString(sTarget.nIndex)); +} +object ai_GetLowestCRClassTarget(object oCreature, int nClassType, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE) +{ + struct stTarget sTarget; + sTarget.fNearestRange = fMaxRange + 1.0; + sTarget.fNearestSecondaryRange = sTarget.fNearestRange; + sTarget.nBestValue = 100; + sTarget.nBestSecondaryValue = 100; + sTarget.sTargetType = sTargetType; + int nCounter = 1; + string sCounter = "1"; + sTarget.oTarget = GetLocalObject(oCreature, sTargetType + sCounter); + while(sTarget.oTarget != OBJECT_INVALID) + { + if(AI_DEBUG) ai_Debug("0i_combat", "1626", "Getting the lowest CR class index: " + + sCounter + " " + GetName(sTarget.oTarget) + + " Seen: " + IntToString(GetLocalInt(oCreature, sTargetType + "_PERCEIVED" + sCounter)) + + " GetIsDead: " + IntToString(GetIsDead(sTarget.oTarget))); + if(GetLocalInt(oCreature, sTargetType + "_PERCEIVED" + sCounter) && + !GetIsDead(sTarget.oTarget) && ai_CheckClassType(sTarget.oTarget, nClassType)) + { + if(AI_DEBUG) ai_Debug("0i_combat", "1634", "bAlwaysAtk: " + IntToString(bAlwaysAtk)); + if((bAlwaysAtk || !ai_IsStrongerThanMe(oCreature, nCounter)) && + ai_TargetIsInRangeofCreature(oCreature, sTargetType, sCounter, fMaxRange) && + ai_TargetIsInRangeofMaster(oCreature, sTarget.oTarget)) + { + sTarget.nValue = GetLocalInt(oCreature, sTargetType + "_COMBAT" + sCounter); + sTarget = ai_CheckForLowestValueTarget(oCreature, sTarget, nCounter, sCounter); + } + } + sCounter = IntToString(++nCounter); + sTarget.oTarget = GetLocalObject(oCreature, sTargetType + sCounter); + } + // If we do not have a normal target then use our best secondary target. + if(sTarget.nIndex == 0 && sTarget.nSecondaryIndex != 0) sTarget.nIndex = sTarget.nSecondaryIndex; + if(AI_DEBUG) ai_Debug("0i_combat", "1648", "Found lowest CR class [" + sTargetType + "] Index: " + IntToString(sTarget.nIndex)); + return GetLocalObject(oCreature, sTargetType + IntToString(sTarget.nIndex)); +} +object ai_GetHighestCRClassTarget(object oCreature, int nClassType, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE) +{ + struct stTarget sTarget; + sTarget.fNearestRange = fMaxRange + 1.0; + sTarget.fNearestSecondaryRange = sTarget.fNearestRange; + sTarget.nBestValue = -100; + sTarget.nBestSecondaryValue = -100; + sTarget.sTargetType = sTargetType; + int nCounter = 1; + string sCounter = "1"; + sTarget.oTarget = GetLocalObject(oCreature, sTargetType + sCounter); + while(sTarget.oTarget != OBJECT_INVALID) + { + if(AI_DEBUG) ai_Debug("0i_combat", "1664", "Getting the highest CR class index: " + + sCounter + " " + GetName(sTarget.oTarget) + + " Seen: " + IntToString(GetLocalInt(oCreature, sTargetType + "_PERCEIVED" + sCounter)) + + " GetIsDead: " + IntToString(GetIsDead(sTarget.oTarget))); + if(GetLocalInt(oCreature, sTargetType + "_PERCEIVED" + sCounter) && + !GetIsDead(sTarget.oTarget) && ai_CheckClassType(sTarget.oTarget, nClassType)) + { + if(AI_DEBUG) ai_Debug("0i_combat", "1671", "bAlwaysAtk: " + IntToString(bAlwaysAtk)); + if((bAlwaysAtk || !ai_IsStrongerThanMe(oCreature, nCounter)) && + ai_TargetIsInRangeofCreature(oCreature, sTargetType, sCounter, fMaxRange) && + ai_TargetIsInRangeofMaster(oCreature, sTarget.oTarget)) + { + sTarget.nValue = GetLocalInt(oCreature, sTargetType + "_COMBAT" + sCounter); + sTarget = ai_CheckForHighestValueTarget(oCreature, sTarget, nCounter, sCounter); + } + } + sCounter = IntToString(++nCounter); + sTarget.oTarget = GetLocalObject(oCreature, sTargetType + sCounter); + } + // If we do not have a normal target then use our best secondary target. + if(sTarget.nIndex == 0 && sTarget.nSecondaryIndex != 0) sTarget.nIndex = sTarget.nSecondaryIndex; + if(AI_DEBUG) ai_Debug("0i_combat", "1685", "Found highest CR class [" + sTargetType + "] Index: " + IntToString(sTarget.nIndex)); + return GetLocalObject(oCreature, sTargetType + IntToString(sTarget.nIndex)); +} +object ai_GetNearestRacialTarget(object oCreature, int nRacialType, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE) +{ + if(GetLocalInt(oCreature, AI_RULE_AI_DIFFICULTY)) + { + ai_GetLowestCRRacialTarget(oCreature, nRacialType, fMaxRange, sTargetType, bAlwaysAtk); + } + struct stTarget sTarget; + sTarget.fNearestRange = fMaxRange + 1.0; + sTarget.fNearestSecondaryRange = sTarget.fNearestRange; + sTarget.sTargetType = sTargetType; + int nCounter = 1; + string sCounter = "1"; + sTarget.oTarget = GetLocalObject(oCreature, sTargetType + sCounter); + while(sTarget.oTarget != OBJECT_INVALID) + { + if(AI_DEBUG) ai_Debug("0i_combat", "1703", "Getting the nearest race index: " + + sCounter + " " + GetName(sTarget.oTarget) + + " Seen: " + IntToString(GetLocalInt(oCreature, sTargetType + "_PERCEIVED" + sCounter)) + + " GetIsDead: " + IntToString(GetIsDead(sTarget.oTarget))); + if(GetLocalInt(oCreature, sTargetType + "_PERCEIVED" + sCounter) && + !GetIsDead(sTarget.oTarget) && ai_CheckRacialType(sTarget.oTarget, nRacialType)) + { + if(AI_DEBUG) ai_Debug("0i_combat", "1710", "bAlwaysAtk: " + IntToString(bAlwaysAtk)); + if((bAlwaysAtk || !ai_IsStrongerThanMe(oCreature, nCounter)) && + ai_TargetIsInRangeofCreature(oCreature, sTargetType, sCounter, fMaxRange) && + ai_TargetIsInRangeofMaster(oCreature, sTarget.oTarget)) + { + sTarget = ai_CheckForNearestTarget(oCreature, sTarget, nCounter, sCounter); + } + } + sCounter = IntToString(++nCounter); + sTarget.oTarget = GetLocalObject(oCreature, sTargetType + sCounter); + } + // If we do not have a normal target then use our best secondary target. + if(sTarget.nIndex == 0 && sTarget.nSecondaryIndex != 0) sTarget.nIndex = sTarget.nSecondaryIndex; + if(AI_DEBUG) ai_Debug("0i_combat", "1723", "Found nearest race Index: " + IntToString(sTarget.nIndex)); + return GetLocalObject(oCreature, sTargetType + IntToString(sTarget.nIndex)); +} +object ai_GetLowestCRRacialTarget(object oCreature, int nRacialType, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE) +{ + struct stTarget sTarget; + sTarget.fNearestRange = fMaxRange + 1.0; + sTarget.fNearestSecondaryRange = sTarget.fNearestRange; + sTarget.nBestValue = 100; + sTarget.nBestSecondaryValue = 100; + sTarget.sTargetType = sTargetType; + int nCounter = 1; + string sCounter = "1"; + sTarget.oTarget = GetLocalObject(oCreature, sTargetType + sCounter); + while(sTarget.oTarget != OBJECT_INVALID) + { + if(AI_DEBUG) ai_Debug("0i_combat", "1739", "Getting the lowest CR race index: " + + sCounter + " " + GetName(sTarget.oTarget) + + " Seen: " + IntToString(GetLocalInt(oCreature, sTargetType + "_PERCEIVED" + sCounter)) + + " GetIsDead: " + IntToString(GetIsDead(sTarget.oTarget))); + if(GetLocalInt(oCreature, sTargetType + "_PERCEIVED" + sCounter) && + !GetIsDead(sTarget.oTarget) && ai_CheckRacialType(sTarget.oTarget, nRacialType)) + { + if(AI_DEBUG) ai_Debug("0i_combat", "1746", "bAlwaysAtk: " + IntToString(bAlwaysAtk)); + if((bAlwaysAtk || !ai_IsStrongerThanMe(oCreature, nCounter)) && + ai_TargetIsInRangeofCreature(oCreature, sTargetType, sCounter, fMaxRange) && + ai_TargetIsInRangeofMaster(oCreature, sTarget.oTarget)) + { + sTarget.nValue = GetLocalInt(oCreature, sTargetType + "_COMBAT" + sCounter); + sTarget = ai_CheckForLowestValueTarget(oCreature, sTarget, nCounter, sCounter); + } + } + sCounter = IntToString(++nCounter); + sTarget.oTarget = GetLocalObject(oCreature, sTargetType + sCounter); + } + // If we do not have a normal target then use our best secondary target. + if(sTarget.nIndex == 0 && sTarget.nSecondaryIndex != 0) sTarget.nIndex = sTarget.nSecondaryIndex; + if(AI_DEBUG) ai_Debug("0i_combat", "1760", "Found lowest CR race [" + sTargetType + "] Index: " + IntToString(sTarget.nIndex)); + return GetLocalObject(oCreature, sTargetType + IntToString(sTarget.nIndex)); +} +object ai_GetHighestCRRacialTarget(object oCreature, int nRacialType, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE) +{ + struct stTarget sTarget; + sTarget.fNearestRange = fMaxRange + 1.0; + sTarget.fNearestSecondaryRange = sTarget.fNearestRange; + sTarget.nBestValue = -100; + sTarget.nBestSecondaryValue = -100; + sTarget.sTargetType = sTargetType; + int nCounter = 1; + string sCounter = "1"; + sTarget.oTarget = GetLocalObject(oCreature, sTargetType + sCounter); + while(sTarget.oTarget != OBJECT_INVALID) + { + if(AI_DEBUG) ai_Debug("0i_combat", "1776", "Getting the highest CR race index: " + + sCounter + " " + GetName(sTarget.oTarget) + + " Seen: " + IntToString(GetLocalInt(oCreature, sTargetType + "_PERCEIVED" + sCounter)) + + " GetIsDead: " + IntToString(GetIsDead(sTarget.oTarget))); + if(GetLocalInt(oCreature, sTargetType + "_PERCEIVED" + sCounter) && + !GetIsDead(sTarget.oTarget) && ai_CheckRacialType(sTarget.oTarget, nRacialType)) + { + if(AI_DEBUG) ai_Debug("0i_combat", "1783", "bAlwaysAtk: " + IntToString(bAlwaysAtk)); + if((bAlwaysAtk || !ai_IsStrongerThanMe(oCreature, nCounter)) && + ai_TargetIsInRangeofCreature(oCreature, sTargetType, sCounter, fMaxRange) && + ai_TargetIsInRangeofMaster(oCreature, sTarget.oTarget)) + { + sTarget.nValue = GetLocalInt(oCreature, sTargetType + "_COMBAT" + sCounter); + sTarget = ai_CheckForHighestValueTarget(oCreature, sTarget, nCounter, sCounter); + } + } + sCounter = IntToString(++nCounter); + sTarget.oTarget = GetLocalObject(oCreature, sTargetType + sCounter); + } + // If we do not have a normal target then use our best secondary target. + if(sTarget.nIndex == 0 && sTarget.nSecondaryIndex != 0) sTarget.nIndex = sTarget.nSecondaryIndex; + if(AI_DEBUG) ai_Debug("0i_combat", "1797", "Found highest CR race [" + sTargetType + "] Index: " + IntToString(sTarget.nIndex)); + return GetLocalObject(oCreature, sTargetType + IntToString(sTarget.nIndex)); +} +object ai_GetNearestFavoredEnemyTarget(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, int bAlwaysAtk = TRUE) +{ + struct stTarget sTarget; + sTarget.fNearestRange = fMaxRange + 1.0; + sTarget.fNearestSecondaryRange = sTarget.fNearestRange; + sTarget.nBestValue = -100; + sTarget.nBestSecondaryValue = -100; + sTarget.sTargetType = AI_ENEMY; + int nCounter = 1; + string sCounter = "1"; + int nRace, nRacialType; + while(nRace < 24) + { + // Find which favored enemies we have. + if(nRace < 1 && GetHasFeat(FEAT_FAVORED_ENEMY_ABERRATION, oCreature)) + { + nRace = 1; + nRacialType = RACIAL_TYPE_ABERRATION; + } + else if(nRace < 2 && GetHasFeat(FEAT_FAVORED_ENEMY_ANIMAL, oCreature)) + { + nRace = 2; + nRacialType = RACIAL_TYPE_ANIMAL; + } + else if(nRace < 3 && GetHasFeat(FEAT_FAVORED_ENEMY_BEAST, oCreature)) + { + nRace = 3; + nRacialType = RACIAL_TYPE_BEAST; + } + else if(nRace < 4 && GetHasFeat(FEAT_FAVORED_ENEMY_CONSTRUCT, oCreature)) + { + nRace = 4; + nRacialType = RACIAL_TYPE_CONSTRUCT; + } + else if(nRace < 5 && GetHasFeat(FEAT_FAVORED_ENEMY_DRAGON, oCreature)) + { + nRace = 5; + nRacialType = RACIAL_TYPE_DRAGON; + } + else if(nRace < 6 && GetHasFeat(FEAT_FAVORED_ENEMY_DWARF, oCreature)) + { + nRace = 6; + nRacialType = RACIAL_TYPE_DWARF; + } + else if(nRace < 7 && GetHasFeat(FEAT_FAVORED_ENEMY_ELEMENTAL, oCreature)) + { + nRace = 7; + nRacialType = RACIAL_TYPE_ELEMENTAL; + } + else if(nRace < 8 && GetHasFeat(FEAT_FAVORED_ENEMY_ELF, oCreature)) + { + nRace = 8; + nRacialType = RACIAL_TYPE_ELF; + } + else if(nRace < 9 && GetHasFeat(FEAT_FAVORED_ENEMY_FEY, oCreature)) + { + nRace = 9; + nRacialType = RACIAL_TYPE_FEY; + } + else if(nRace < 10 && GetHasFeat(FEAT_FAVORED_ENEMY_GIANT, oCreature)) + { + nRace = 10; + nRacialType = RACIAL_TYPE_GIANT; + } + else if(nRace < 11 && GetHasFeat(FEAT_FAVORED_ENEMY_GNOME, oCreature)) + { + nRace = 11; + nRacialType = RACIAL_TYPE_GNOME; + } + else if(nRace < 12 && GetHasFeat(FEAT_FAVORED_ENEMY_GOBLINOID, oCreature)) + { + nRace = 12; + nRacialType = RACIAL_TYPE_HUMANOID_GOBLINOID; + } + else if(nRace < 13 && GetHasFeat(FEAT_FAVORED_ENEMY_HALFELF, oCreature)) + { + nRace = 13; + nRacialType = RACIAL_TYPE_HALFELF; + } + else if(nRace < 14 && GetHasFeat(FEAT_FAVORED_ENEMY_HALFLING, oCreature)) + { + nRace = 14; + nRacialType = RACIAL_TYPE_HALFLING; + } + else if(nRace < 15 && GetHasFeat(FEAT_FAVORED_ENEMY_HALFORC, oCreature)) + { + nRace = 15; + nRacialType = RACIAL_TYPE_HALFORC; + } + else if(nRace < 16 && GetHasFeat(FEAT_FAVORED_ENEMY_HUMAN, oCreature)) + { + nRace = 16; + nRacialType = RACIAL_TYPE_HUMAN; + } + else if(nRace < 17 && GetHasFeat(FEAT_FAVORED_ENEMY_MAGICAL_BEAST, oCreature)) + { + nRace = 17; + nRacialType = RACIAL_TYPE_MAGICAL_BEAST; + } + else if(nRace < 18 && GetHasFeat(FEAT_FAVORED_ENEMY_MONSTROUS, oCreature)) + { + nRace = 18; + nRacialType = RACIAL_TYPE_HUMANOID_MONSTROUS; + } + else if(nRace < 19 && GetHasFeat(FEAT_FAVORED_ENEMY_ORC, oCreature)) + { + nRace = 19; + nRacialType = RACIAL_TYPE_HUMANOID_ORC; + } + else if(nRace < 20 && GetHasFeat(FEAT_FAVORED_ENEMY_OUTSIDER, oCreature)) + { + nRace = 20; + nRacialType = RACIAL_TYPE_OUTSIDER; + } + else if(nRace < 21 && GetHasFeat(FEAT_FAVORED_ENEMY_REPTILIAN, oCreature)) + { + nRace = 21; + nRacialType = RACIAL_TYPE_HUMANOID_REPTILIAN; + } + else if(nRace < 22 && GetHasFeat(FEAT_FAVORED_ENEMY_SHAPECHANGER, oCreature)) + { + nRace = 22; + nRacialType = RACIAL_TYPE_SHAPECHANGER; + } + else if(nRace < 23 && GetHasFeat(FEAT_FAVORED_ENEMY_UNDEAD, oCreature)) + { + nRace = 23; + nRacialType = RACIAL_TYPE_UNDEAD; + } + else if(nRace < 24 && GetHasFeat(FEAT_FAVORED_ENEMY_VERMIN, oCreature)) + { + nRace = 24; + nRacialType = RACIAL_TYPE_VERMIN; + } + else nRace = 25; + if(nRace < 25) + { + sTarget.oTarget = GetLocalObject(oCreature, AI_ENEMY + sCounter); + while(sTarget.oTarget != OBJECT_INVALID) + { + if(AI_DEBUG) ai_Debug("0i_combat", "1940", "Getting the nearest favored race index: " + + sCounter + " " + GetName(sTarget.oTarget) + + " Seen: " + IntToString(GetLocalInt(oCreature, AI_ENEMY_PERCEIVED + sCounter)) + + " GetIsDead: " + IntToString(GetIsDead(sTarget.oTarget))); + if(GetLocalInt(oCreature, AI_ENEMY_PERCEIVED + sCounter) && + !GetIsDead(sTarget.oTarget) && ai_CheckRacialType(sTarget.oTarget, nRacialType)) + { + if(AI_DEBUG) ai_Debug("0i_combat", "1947", "bAlwaysAtk: " + IntToString(bAlwaysAtk)); + if((bAlwaysAtk || !ai_IsStrongerThanMe(oCreature, nCounter)) && + ai_TargetIsInRangeofCreature(oCreature, AI_ENEMY, sCounter, fMaxRange) + + ai_TargetIsInRangeofMaster(oCreature, sTarget.oTarget)) + { + sTarget = ai_CheckForNearestTarget(oCreature, sTarget, nCounter, sCounter); + } + } + sCounter = IntToString(++nCounter); + sTarget.oTarget = GetLocalObject(oCreature, AI_ENEMY + sCounter); + } + } + } + // If we do not have a normal target then use our best secondary target. + if(sTarget.nIndex == 0 && sTarget.nSecondaryIndex != 0) sTarget.nIndex = sTarget.nSecondaryIndex; + if(AI_DEBUG) ai_Debug("0i_combat", "1962", "Found nearest favored race Index: " + IntToString(sTarget.nIndex)); + return GetLocalObject(oCreature, AI_ENEMY + IntToString(sTarget.nIndex)); +} +object ai_GetFlankTarget(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, int bAlwaysAtk = TRUE) +{ + int nCnt = 1, nInMelee, nHighestMelee; + string sCnt = "1"; + float fAllyRange; + object oTarget, oAlly = GetLocalObject(oCreature, AI_ALLY + sCnt); + while(oAlly != OBJECT_INVALID) + { + fAllyRange = GetLocalFloat(oCreature, AI_ALLY_RANGE + sCnt); + if(AI_DEBUG) ai_Debug("0i_combat", "1974", "Getting Ally being Flanked Index: " + sCnt + " " + + GetName(oAlly) + " fAllyRange: " + FloatToString(fAllyRange, 0, 2) + + " fMaxRange: " + FloatToString(fMaxRange, 0, 2)); + if(fAllyRange <= fMaxRange) + { + nInMelee = GetLocalInt(oCreature, AI_ALLY_MELEE + sCnt); + if(AI_DEBUG) ai_Debug("0i_combat", "1980", "nInMelee: " + IntToString(nInMelee)); + if(!GetIsDead(oAlly) && nInMelee > nHighestMelee) + { + oTarget = ai_GetEnemyAttackingMyAlly(oCreature, oAlly, fMaxRange); + if(oTarget != OBJECT_INVALID) nHighestMelee = nInMelee; + } + } + sCnt = IntToString(++nCnt); + oAlly = GetLocalObject(oCreature, AI_ALLY + sCnt); + } + // If we do not have a good target then lets see if there are more targets. + if(oTarget == OBJECT_INVALID) + { + // If we just checked within melee then lets check what we can see if + // we can move around in combat. + if (fMaxRange == AI_RANGE_MELEE && ai_CanIMoveInCombat(oCreature)) + { + oTarget = ai_GetFlankTarget(oCreature, AI_RANGE_PERCEPTION, bAlwaysAtk); + } + } + if(AI_DEBUG) ai_Debug("0i_combat", "2000", "oTarget " + GetName(oTarget) + + " is attacking " + GetName(oAlly)); + return oTarget; +} +object ai_GetRangedTarget(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, int bAlwaysAtk = TRUE) +{ + struct stTarget sTarget; + sTarget.fNearestRange = fMaxRange + 1.0; + sTarget.fNearestSecondaryRange = sTarget.fNearestRange; + sTarget.sTargetType = AI_ENEMY; + int nCounter = 1; + string sCounter = "1"; + sTarget.oTarget = GetLocalObject(oCreature, AI_ENEMY + sCounter); + while(sTarget.oTarget != OBJECT_INVALID) + { + if(AI_DEBUG) ai_Debug("0i_combat", "2037", "Getting the nearest ranged index: " + + sCounter + " " + GetName(sTarget.oTarget) + + " Seen: " + IntToString(GetLocalInt(oCreature, AI_ENEMY_PERCEIVED + sCounter)) + + " GetIsDead: " + IntToString(GetIsDead(sTarget.oTarget))); + if(GetLocalInt(oCreature, AI_ENEMY_PERCEIVED + sCounter) && + !GetIsDead(sTarget.oTarget)) + { + if(AI_DEBUG) ai_Debug("0i_combat", "2044", "bAlwaysAtk: " + IntToString(bAlwaysAtk)); + if((bAlwaysAtk || !ai_IsStrongerThanMe(oCreature, nCounter)) && + ai_TargetIsInRangeofCreature(oCreature, AI_ENEMY, sCounter, fMaxRange) && + ai_TargetIsInRangeofMaster(oCreature, sTarget.oTarget)) + { + if(ai_GetIsRangeWeapon(GetItemInSlot(INVENTORY_SLOT_LEFTHAND, sTarget.oTarget))) + { + sTarget = ai_CheckForNearestTarget(oCreature, sTarget, nCounter, sCounter); + } + } + } + sCounter = IntToString(++nCounter); + sTarget.oTarget = GetLocalObject(oCreature, AI_ENEMY + sCounter); + } + // If we do not have a normal target then use our best secondary target. + if(sTarget.nIndex == 0 && sTarget.nSecondaryIndex != 0) sTarget.nIndex = sTarget.nSecondaryIndex; + if(AI_DEBUG) ai_Debug("0i_combat", "2060", "Found nearest ranged Index: " + IntToString(sTarget.nIndex)); + return GetLocalObject(oCreature, AI_ENEMY + IntToString(sTarget.nIndex)); +} +object ai_GetBestTargetForMeleeCombat(object oCreature, int nInMelee, int bAlwaysAtk = TRUE) +{ + object oPCTarget = GetLocalObject(oCreature, AI_PC_LOCKED_TARGET); + if(oPCTarget != OBJECT_INVALID) return oPCTarget; + string sIndex; + // Are we in melee? If so try to get the weakest enemy in melee. + if(nInMelee > 0) + { + if(ai_CanIMoveInCombat(oCreature)) + { + sIndex = IntToString(ai_GetLowestCRIndex(oCreature, AI_RANGE_MELEE)); + } + else sIndex = IntToString(ai_GetNearestIndex(oCreature, AI_RANGE_MELEE)); + } + // If not then lets go find someone to attack! + else + { + // If we are not in melee then we should get the nearest enemy. + sIndex = IntToString(ai_GetNearestIndexNotInAOE(oCreature, AI_RANGE_PERCEPTION, AI_ENEMY, bAlwaysAtk)); + /* Lets stay out of bad AOE's. + // If we didn't get a target then get any target within range. + if(sIndex == "0") + { + sIndex = IntToString(ai_GetLowestCRIndex(oCreature, AI_RANGE_PERCEPTION, AI_ENEMY, bAlwaysAtk)); + } */ + } + object oTarget = GetLocalObject(oCreature, AI_ENEMY + sIndex); + // We might not have a target this is fine as sometimes we don't want to attack! + if(AI_DEBUG) ai_Debug("0i_combat", "2048", GetName(oTarget) + " is the best target for melee combat!"); + return oTarget; +} +object ai_GetNearestTargetForMeleeCombat(object oCreature, int nInMelee, int bAlwaysAtk = TRUE) +{ + object oPCTarget = GetLocalObject(oCreature, AI_PC_LOCKED_TARGET); + if(oPCTarget != OBJECT_INVALID) return oPCTarget; + string sIndex; + // Are we in melee? If so try to get the nearest enemy in melee. + if(nInMelee > 0) sIndex = IntToString(ai_GetNearestIndex(oCreature, AI_RANGE_MELEE)); + // If not then lets go find someone to attack! + else + { + // Get the nearest enemy. + sIndex = IntToString(ai_GetNearestIndexNotInAOE(oCreature, AI_RANGE_PERCEPTION, AI_ENEMY, bAlwaysAtk)); + // If we didn't get a target then get any target within range. + if(sIndex == "0") + { + sIndex = IntToString(ai_GetNearestIndex(oCreature, AI_RANGE_PERCEPTION, AI_ENEMY, bAlwaysAtk)); + } + } + object oTarget = GetLocalObject(oCreature, AI_ENEMY + sIndex); + // We might not have a target this is fine as sometimes we don't want to attack! + if(AI_DEBUG) ai_Debug("0i_combat", "2024", GetName(oTarget) + " is the nearest target for melee combat!"); + return oTarget; +} +object ai_GetLowestCRTargetForMeleeCombat(object oCreature, int nInMelee, int bAlwaysAtk = TRUE) +{ + object oPCTarget = GetLocalObject(oCreature, AI_PC_LOCKED_TARGET); + if(oPCTarget != OBJECT_INVALID) return oPCTarget; + string sIndex; + // Are we in melee? If so try to get the weakest enemy in melee. + if(nInMelee > 0) sIndex = IntToString(ai_GetLowestCRIndex(oCreature, AI_RANGE_MELEE)); + // If not then lets go find someone to attack! + else + { + // Get the weakest combat rated enemy. + sIndex = IntToString(ai_GetLowestCRIndexNotInAOE(oCreature, AI_RANGE_PERCEPTION, AI_ENEMY, bAlwaysAtk)); + /* Lets stay out of bad AOE's. + // If we didn't get a target then get any target within range. + if(sIndex == "0") + { + sIndex = IntToString(ai_GetLowestCRIndex(oCreature, AI_RANGE_PERCEPTION, AI_ENEMY, bAlwaysAtk)); + } */ + } + object oTarget = GetLocalObject(oCreature, AI_ENEMY + sIndex); + // We might not have a target this is fine as sometimes we don't want to attack! + if(AI_DEBUG) ai_Debug("0i_combat", "2048", GetName(oTarget) + " is the weakest target for melee combat!"); + return oTarget; +} +object ai_GetHighestCRTargetForMeleeCombat(object oCreature, int nInMelee) +{ + object oPCTarget = GetLocalObject(oCreature, AI_PC_LOCKED_TARGET); + if(oPCTarget != OBJECT_INVALID) return oPCTarget; + string sIndex; + // Are we in melee? If so try to get the weakest enemy in melee. + if(nInMelee > 0) sIndex = IntToString(ai_GetHighestCRIndex(oCreature, AI_RANGE_MELEE)); + // If not then lets go find someone to attack! + else + { + // Get the weakest combat rated enemy. + sIndex = IntToString(ai_GetHighestCRIndexNotInAOE(oCreature, AI_RANGE_PERCEPTION)); + /* Lets stay out of bad AOE's. + // If we didn't get a target then get any target within range. + if(sIndex == "0") sIndex = IntToString(ai_GetHighestCRIndex(oCreature)); + */ + } + object oTarget = GetLocalObject(oCreature, AI_ENEMY + sIndex); + // We might not have a target this is fine as sometimes we don't want to attack! + if(AI_DEBUG) ai_Debug("0i_combat", "2070", GetName(oTarget) + " is the strongest target for melee combat!"); + return oTarget; +} +object ai_GetEnemyAttackingMe(object oCreature, float fMaxRange = AI_RANGE_MELEE) +{ + int nCtr = 1; + float fDistance; + string sCtr = "1"; + object oAttacked; + object oEnemy = GetLocalObject(oCreature, AI_ENEMY + "1"); + while(oEnemy != OBJECT_INVALID) + { + if(!ai_Disabled(oEnemy)) + { + fDistance = GetLocalFloat(oCreature, AI_ENEMY_RANGE + sCtr); + if(AI_DEBUG) ai_Debug("0i_combat", "2084", "Getting Enemy Attacking Me: " + sCtr + " " + + GetName(oEnemy) + " fTargetRange: " + FloatToString(fDistance, 0, 2) + + " fMaxRange: " + FloatToString(fMaxRange, 0, 2) + " Attacking: " + + GetName(ai_GetAttackedTarget(oEnemy))); + if(fDistance <= fMaxRange) + { + oAttacked = ai_GetAttackedTarget(oEnemy); + // If an enemy isn't attacking someone we must assume we are next! + if(oAttacked == oCreature || oAttacked == OBJECT_INVALID) + { + if(AI_DEBUG) ai_Debug("0i_combat", "2095", "Enemy attacking me: " + GetName(oEnemy) + " has attacked: " + GetName(ai_GetAttackedTarget(oEnemy))); + return oEnemy; + } + } + } + sCtr = IntToString(++nCtr); + oEnemy = GetLocalObject(oCreature, AI_ENEMY + sCtr); + } + return OBJECT_INVALID; +} +object ai_GetEnemyAttackingMyAlly(object oCreature, object oAlly, float fMaxRange = AI_RANGE_MELEE) +{ + int nCtr = 1, nIndex, nDIndex; + int bIngnoreAssociates = ai_GetAIMode(oCreature, AI_MODE_IGNORE_ASSOCIATES); + float fEnemyRange, fNearestEnemyRange = fMaxRange + 1.0; + float fNearestDEnemyRange = fMaxRange + 1.0; + string sCtr = "1"; + object oAttacked; + object oEnemy = GetLocalObject(oCreature, AI_ENEMY + "1"); + while(oEnemy != OBJECT_INVALID) + { + fEnemyRange = GetLocalFloat(oCreature, AI_ENEMY_RANGE + sCtr); + if(AI_DEBUG) ai_Debug("0i_combat", "2117", "Getting Enemy Attacking Ally:" + + GetName(oAlly) + ": " + sCtr + " InMelee:" + + GetName(oEnemy) + " fEnemyRange: " + FloatToString(fEnemyRange, 0, 2) + + " fMaxRange: " + FloatToString(fMaxRange, 0, 2) + " Attacking: " + + GetName(ai_GetAttackedTarget(oEnemy))); + if(fEnemyRange <= fMaxRange) + { + oAttacked = ai_GetAttackedTarget(oEnemy); + if(AI_DEBUG) ai_Debug("0i_combat", "2125", "Enemy attacking " + + GetName(oAlly) + ": " + GetName(oEnemy) + + " has attacked: " + GetName(ai_GetAttackedTarget(oEnemy))); + // If an enemy isn't attacking someone we must assume we are next! + if(oAttacked == oAlly) + { + // Lets put any disabled targets in its own group, if we + // ignore associates lets put them here as well. + if(GetLocalInt(oCreature, AI_ENEMY_DISABLED + sCtr) || + (bIngnoreAssociates && GetAssociateType(oEnemy))) + { + if(fEnemyRange < fNearestDEnemyRange) + { + fNearestDEnemyRange = fEnemyRange; + nDIndex = nCtr; + } + } + else if(fEnemyRange < fNearestEnemyRange) + { + fNearestEnemyRange = fEnemyRange; + nIndex = nCtr; + } + } + } + sCtr = IntToString(++nCtr); + oEnemy = GetLocalObject(oCreature, AI_ENEMY + sCtr); + } + // If we do not have a good target then lets see if there are more targets. + if(nIndex == 0 && nDIndex != 0) + { + // If we just checked within melee then lets check what we can see. + if (fMaxRange == AI_RANGE_MELEE) return ai_GetEnemyAttackingMyAlly(oCreature, oAlly, AI_RANGE_PERCEPTION); + else nIndex = nDIndex; + } + return GetLocalObject(oCreature, AI_ENEMY + IntToString(nIndex)); +} +int ai_GetNumOfEnemiesInRange(object oCreature, float fMaxRange = AI_RANGE_MELEE) +{ + int nNumOfEnemies, nCnt = 1; + float fDistance = GetLocalFloat(oCreature, AI_ENEMY_RANGE + "1"); + while(fDistance != 0.0) + { + if(fDistance < fMaxRange) nNumOfEnemies ++; + fDistance = GetLocalFloat(oCreature, AI_ENEMY_RANGE + IntToString(++nCnt)); + } + if(AI_DEBUG) ai_Debug("0i_combat", "2459", IntToString (nNumOfEnemies) + " enemies within " + FloatToString(fMaxRange, 0, 2) + " meters."); + return nNumOfEnemies; +} +object ai_GetAllyBuffTarget(object oCreature, int nSpell, float fMaxRange = AI_RANGE_BATTLEFIELD) +{ + // Make sure we don't over extend our movement running across the + // battlefield to cast a spell on someone does not look good. + float fNearestEnemy = GetDistanceBetween(oCreature, GetLocalObject(oCreature, AI_ENEMY_NEAREST)) - 3.0f; + // If we are in melee then extend to melee incase an ally is just past the enemy. + if(fNearestEnemy <= AI_RANGE_MELEE) fNearestEnemy = AI_RANGE_MELEE; + if(fMaxRange > fNearestEnemy) fMaxRange = fNearestEnemy; + // Now lets get the best target based on the spell data in ai_spells.2da + string sBuffTarget = Get2DAString("ai_spells", "Buff_Target", nSpell); + if(AI_DEBUG) ai_Debug("0i_combat", "2596", "sBuffTarget: " + sBuffTarget + " fMaxRange: " + FloatToString(fMaxRange, 0, 2)); + if(sBuffTarget == "0") return oCreature; + if(sBuffTarget == "1") + return ai_BuffHighestAbilityScoreTarget(oCreature, nSpell, ABILITY_STRENGTH, "", fMaxRange, AI_ALLY); + else if(sBuffTarget == "2") + return ai_BuffHighestAbilityScoreTarget(oCreature, nSpell, ABILITY_DEXTERITY, "", fMaxRange, AI_ALLY); + else if(sBuffTarget == "3") + return ai_BuffHighestAbilityScoreTarget(oCreature, nSpell, ABILITY_CONSTITUTION, "", fMaxRange, AI_ALLY); + else if(sBuffTarget == "4") + return ai_BuffHighestAbilityScoreTarget(oCreature, nSpell, ABILITY_INTELLIGENCE, "", fMaxRange, AI_ALLY); + else if(sBuffTarget == "5") + return ai_BuffHighestAbilityScoreTarget(oCreature, nSpell, ABILITY_WISDOM, "", fMaxRange, AI_ALLY); + else if(sBuffTarget == "6") + return ai_BuffHighestAbilityScoreTarget(oCreature, nSpell, ABILITY_CHARISMA, "", fMaxRange, AI_ALLY); + else if(sBuffTarget == "7") + return ai_BuffLowestACTarget(oCreature, nSpell, "", fMaxRange, AI_ALLY); + else if(sBuffTarget == "8") + return ai_BuffLowestACWithOutACBonus(oCreature, nSpell, "", fMaxRange, AI_ALLY); + else if(sBuffTarget == "9") + return ai_BuffHighestAttackTarget(oCreature, nSpell, "", fMaxRange, AI_ALLY); + else if(sBuffTarget == "10") + return ai_BuffMostWoundedTarget(oCreature, nSpell, "", fMaxRange, AI_ALLY); + else if(sBuffTarget == "11") + return ai_BuffLowestFortitudeSaveTarget(oCreature, nSpell, "", fMaxRange, AI_ALLY); + else if(sBuffTarget == "12") + return ai_BuffLowestReflexSaveTarget(oCreature, nSpell, "", fMaxRange, AI_ALLY); + else if(sBuffTarget == "13") + return ai_BuffLowestWillSaveTarget(oCreature, nSpell, "", fMaxRange, AI_ALLY); + else if(sBuffTarget == "14") + return ai_BuffLowestSaveTarget(oCreature, nSpell, "", fMaxRange, AI_ALLY); + return OBJECT_INVALID; +} + +//****************************************************************************** +//******************** OTHER COMBAT FUNCTIONS ******************************** +//****************************************************************************** + +int ai_GetCurrentRound(object oCreature) +{ + int nRound = GetLocalInt(oCreature, AI_ROUND) + 1; + SetLocalInt(oCreature, AI_ROUND, nRound); + if(AI_DEBUG) ai_Debug("0i_combat", "2471", "nRound: " + IntToString(nRound)); + return nRound; +} +int ai_GetDifficulty(object oCreature) +{ + int nAdjustment = GetLocalInt(oCreature, AI_DIFFICULTY_ADJUSTMENT); + int nDifficulty = GetLocalInt(oCreature, AI_ENEMY_POWER) - GetLocalInt(oCreature, AI_ALLY_POWER) + 13 + nAdjustment; + if(nDifficulty < 1) nDifficulty = 1; + if(AI_DEBUG) ai_Debug("0i_combat", "2474", "(Difficulty: Enemy Power: " + IntToString(GetLocalInt(oCreature, AI_ENEMY_POWER)) + + " - Ally Power: " + IntToString(GetLocalInt(oCreature, AI_ALLY_POWER)) + + ") + 13 + nAdj: " + IntToString(nAdjustment) + + " = " + IntToString(nDifficulty) + "(Min of 1)"); + return nDifficulty; +} +int ai_GetMyCombatRating(object oCreature) +{ + object oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oCreature); + int nAtkBonus = GetBaseAttackBonus(oCreature); + if(GetHasFeat(FEAT_WEAPON_FINESSE, oCreature) && ai_GetIsFinesseWeapon(oCreature, oWeapon)) + { + nAtkBonus += GetAbilityModifier(ABILITY_DEXTERITY, oCreature); + } + else nAtkBonus += GetAbilityModifier(ABILITY_STRENGTH, oCreature); + if(ai_GetIsMeleeWeapon(oWeapon)) nAtkBonus += ai_GetWeaponAtkBonus(oWeapon); + if(AI_DEBUG) ai_Debug("0i_combat", "2496", "GetMyCombatRating (nAtkBonus: " + IntToString(nAtkBonus) + + " nAC: " + IntToString(GetAC(oCreature)) + " - 10) / 2 = " + + IntToString((nAtkBonus + GetAC(oCreature) - 10) / 2)); + return(nAtkBonus + GetAC(oCreature) - 10) / 2; +} +object ai_GetAttackedTarget(object oCreature, int bPhysical = TRUE, int bSpell = FALSE) +{ + object oTarget = GetAttackTarget(oCreature); + if(!GetIsObjectValid(oTarget) && bPhysical) oTarget = GetLocalObject(oCreature, AI_ATTACKED_PHYSICAL); + if(!GetIsObjectValid(oTarget) && bSpell) oTarget = GetLocalObject(oCreature, AI_ATTACKED_SPELL); + if(!GetIsObjectValid(oTarget) || GetIsDead(oTarget)) return OBJECT_INVALID; + return oTarget; +} +int ai_CheckClassType(object oTarget, int nClassType) +{ + int nCnt = 1, nClass = GetClassByPosition(1, oTarget); + // We check for the group class types. + if(nClassType < 0) + { + while(nCnt <= AI_MAX_CLASSES_PER_CHARACTER) + { + int nCaster = StringToInt(Get2DAString("classes", "SpellCaster", nClass)); + if(nClassType == AI_CLASS_TYPE_WARRIOR && !nCaster) return TRUE; + else if(nClassType == AI_CLASS_TYPE_CASTER && nCaster) return TRUE; + int nSpellType = StringToInt(Get2DAString("classes", "Arcane", nClass)); + if(nClassType == AI_CLASS_TYPE_ARCANE && nSpellType) return TRUE; + else if(nClassType == AI_CLASS_TYPE_DIVINE && !nSpellType) return TRUE; + nClass = GetClassByPosition(++nCnt, oTarget); + } + } + // Checks for normal classes. + else + { + while(nCnt <= AI_MAX_CLASSES_PER_CHARACTER) + { + if(nClass == nClassType) return TRUE; + nClass = GetClassByPosition(++nCnt, oTarget); + } + } + return FALSE; +} +int ai_CheckRacialType(object oTarget, int nRacialType) +{ + int nRace = GetRacialType(oTarget); + if(nRacialType == nRace) return TRUE; + else if(nRacialType == AI_RACIAL_TYPE_ANIMAL_BEAST) + { + if(nRace == RACIAL_TYPE_ANIMAL || + nRace == RACIAL_TYPE_BEAST || + nRace == RACIAL_TYPE_MAGICAL_BEAST) return TRUE; + } + else if(nRacialType == AI_RACIAL_TYPE_HUMANOID) + { + switch (nRace) + { + case RACIAL_TYPE_DWARF : + case RACIAL_TYPE_ELF : + case RACIAL_TYPE_GNOME : + case RACIAL_TYPE_HALFELF : + case RACIAL_TYPE_HALFLING : + case RACIAL_TYPE_HALFORC : + case RACIAL_TYPE_HUMAN : + case RACIAL_TYPE_HUMANOID_GOBLINOID : + case RACIAL_TYPE_HUMANOID_MONSTROUS : + case RACIAL_TYPE_HUMANOID_ORC : + case RACIAL_TYPE_HUMANOID_REPTILIAN : + return TRUE; + } + } + return FALSE; +} +void ai_SetNormalAppearance(object oCreature) +{ + if(!ai_GetHasEffectType(oCreature, EFFECT_TYPE_POLYMORPH)) + { + int nForm = GetAppearanceType(oCreature); + if(AI_DEBUG) ai_Debug("0i_combat", "2729", GetName(oCreature) + " form: " + IntToString(nForm)); + SetLocalInt(oCreature, AI_NORMAL_FORM, nForm + 1); + } +} +int ai_GetNormalAppearance(object oCreature) +{ + int nForm = GetLocalInt(oCreature, AI_NORMAL_FORM) - 1; + if(nForm == -1) + { + ai_SetNormalAppearance(oCreature); + nForm = GetLocalInt(oCreature, AI_NORMAL_FORM) - 1; + } + return nForm; +} +struct stClasses ai_GetFactionsClasses(object oCreature, int bEnemy = TRUE, float fMaxRange = AI_RANGE_BATTLEFIELD) +{ + struct stClasses sCount; + int nCnt = 1, nPosition, nClass, nLevels; + object oTarget; + if(bEnemy) oTarget = ai_GetNearestEnemy(oCreature, 1, 7, 7); + else oTarget = ai_GetNearestAlly(oCreature, 1, 7, 7); + while(oTarget != OBJECT_INVALID && GetDistanceBetween(oTarget, oCreature) <= fMaxRange) + { + for(nPosition = 1; nPosition <= AI_MAX_CLASSES_PER_CHARACTER; nPosition++) + { + nClass = GetClassByPosition(nPosition, oTarget); + nLevels = GetLevelByPosition(nPosition, oTarget); + if(nClass == CLASS_TYPE_ANIMAL || + nClass == CLASS_TYPE_BARBARIAN || + nClass == CLASS_TYPE_COMMONER || + nClass == CLASS_TYPE_CONSTRUCT || + nClass == CLASS_TYPE_ELEMENTAL || + nClass == CLASS_TYPE_FIGHTER || + nClass == CLASS_TYPE_GIANT || + nClass == CLASS_TYPE_HUMANOID || + nClass == CLASS_TYPE_MONSTROUS || + nClass == CLASS_TYPE_PALADIN || + nClass == CLASS_TYPE_RANGER || + nClass == CLASS_TYPE_ROGUE || + nClass == CLASS_TYPE_VERMIN || + nClass == CLASS_TYPE_MONK || + nClass == CLASS_TYPE_SHAPECHANGER) + { + sCount.FIGHTERS += 1; + sCount.FIGHTER_LEVELS += nLevels; + } + else if(nClass == CLASS_TYPE_CLERIC || + nClass == CLASS_TYPE_DRUID) + { + sCount.CLERICS += 1; + sCount.CLERIC_LEVELS += nLevels; + } + else if(nClass == CLASS_TYPE_BARD || + nClass == CLASS_TYPE_FEY || + nClass == CLASS_TYPE_SORCERER || + nClass == CLASS_TYPE_WIZARD) + { + sCount.MAGES += 1; + sCount.MAGE_LEVELS += nLevels; + } + else if(nClass == CLASS_TYPE_ABERRATION || + nClass == CLASS_TYPE_DRAGON || + nClass == 29 || //oozes + nClass == CLASS_TYPE_MAGICAL_BEAST || + nClass == CLASS_TYPE_OUTSIDER) + { + sCount.MONSTERS += 1; + sCount.MONSTER_LEVELS += nLevels; + } + sCount.TOTAL_LEVELS += nLevels; + } + sCount.TOTAL += 1; + if(bEnemy) oTarget = ai_GetNearestEnemy(oCreature, ++nCnt, 7, 7); + else oTarget = ai_GetNearestAlly(oCreature, ++nCnt, 7, 7); + } + if(AI_DEBUG) ai_Debug("0i_combat", "2627", "Enemy: " + IntToString(bEnemy) + " fMaxRange: " + FloatToString(fMaxRange, 0, 2) + + " CLERICS: " + IntToString(sCount.CLERICS) + "(" + IntToString(sCount.CLERIC_LEVELS) + + ") FIGHTERS: " +IntToString(sCount.FIGHTERS) + "(" + IntToString(sCount.FIGHTER_LEVELS) + + ") MAGES: " +IntToString(sCount.MAGES) + "(" + IntToString(sCount.MAGE_LEVELS) + + ") MONSTERS: " +IntToString(sCount.MONSTERS) + "(" + IntToString(sCount.MONSTER_LEVELS) + + ") TOTALS: " +IntToString(sCount.TOTAL) + "(" + IntToString(sCount.TOTAL_LEVELS)); + return sCount; +} +string ai_GetMostDangerousClass(struct stClasses stCount) +{ + string sClass; + // Lets weight the fighter levels 30% higher. + int nFighter =((stCount.FIGHTER_LEVELS) * 13)/10; + if(nFighter >= stCount.CLERIC_LEVELS) + { + if(nFighter >= stCount.MAGE_LEVELS) + { + if(nFighter >= stCount.MONSTER_LEVELS) return "FIGHTER"; + else return "MONSTER"; + } + else if(stCount.MAGE_LEVELS >= stCount.MONSTER_LEVELS) return "MAGE"; + else return "MONSTER"; + } + else if(stCount.CLERIC_LEVELS >= stCount.MAGE_LEVELS) + { + if(stCount.CLERIC_LEVELS >= stCount.MONSTER_LEVELS) return "CLERIC"; + else return "MONSTER"; + } + else if(stCount.MAGE_LEVELS >= stCount.MONSTER_LEVELS) return "MAGE"; + else return "MONSTER"; + return ""; +} +void ai_EquipBestWeapons(object oCreature, object oTarget = OBJECT_INVALID) +{ + // Lets not check for weapons on creatures that can't use them! + int nRacialType = GetRacialType(oCreature); + if(nRacialType == RACIAL_TYPE_ANIMAL || + nRacialType == RACIAL_TYPE_DRAGON || + nRacialType == RACIAL_TYPE_MAGICAL_BEAST || + nRacialType == RACIAL_TYPE_OOZE || + nRacialType == RACIAL_TYPE_VERMIN) return; + //if(Polymorphed()) return; + if(AI_DEBUG) ai_Debug("0i_combat", "2669", GetName(OBJECT_SELF) + " is equiping best weapon!"); + // Determine if I am wielding a ranged weapon, melee weapon, or none. + int bIsWieldingRanged = ai_HasRangedWeaponWithAmmo(oCreature); + int bIsWieldingMelee = ai_GetIsMeleeWeapon(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND)); + if(AI_DEBUG) ai_Debug("0i_combat", "2673", "bIsWieldingRanged: " + IntToString(bIsWieldingRanged) + + " bIsWieldingMelee: " + IntToString(bIsWieldingMelee)); + // If we are hidden then change to a melee weapon so we can move in to attack. + if(ai_GetIsHidden(oCreature)) + { + // Equip a melee weapon unless we already have one. + if(!bIsWieldingMelee) ai_EquipBestMeleeWeapon(oCreature, oTarget); + return; + } + // Equip the appropriate weapon for the distance of the enemy. + int nEnemyGroup = ai_GetNumOfEnemiesInGroup(oCreature); + if(AI_DEBUG) ai_Debug("0i_combat", "2684", GetName(oCreature) + " has " + IntToString(nEnemyGroup) + " enemies within 5.0f them! PointBlank: " + + IntToString(GetHasFeat(FEAT_POINT_BLANK_SHOT, oCreature))); + // We are in melee combat. + if(nEnemyGroup > 0) + { + if(bIsWieldingRanged) + { + // We have the point blank shot feat or there are more than one enemy on us. + // Note: Point Blank shot feat is bad once we have more than one enemy on us. + if(!GetHasFeat(FEAT_POINT_BLANK_SHOT, oCreature) || nEnemyGroup > 1) + { + // If I'm not using a melee weapon. + if(!bIsWieldingMelee) + { + ai_EquipBestMeleeWeapon(oCreature); + if(AI_DEBUG) ai_Debug("0i_combat", "2699", GetName(oCreature) + " is equiping melee weapon due to close enemies!"); + } + } + } + } + // We are not in melee range. + else + { + if(AI_DEBUG) ai_Debug("0i_combat", "2707", GetName(oCreature) + " is not in melee combat with an enemy!"); + // If are at range with the enemy then equip a ranged weapon. + if(!bIsWieldingRanged) + { + ai_EquipBestRangedWeapon(oTarget); + // Make sure that they equiped a range weapon. + bIsWieldingRanged = ai_HasRangedWeaponWithAmmo(oCreature); + bIsWieldingMelee = ai_GetIsMeleeWeapon(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oCreature)); + if(AI_DEBUG) ai_Debug("0i_combat", "2719", GetName(oCreature) + " is attempting to equip a ranged weapon: " + IntToString(bIsWieldingRanged)); + // If we equiped a ranged weapon then drop out. + } + } + // We don't have a weapon out so equip one! We are in combat! + if(!bIsWieldingRanged && !bIsWieldingMelee) ai_EquipBestMeleeWeapon(OBJECT_INVALID); +} +int ai_EquipBestMeleeWeapon(object oCreature, object oTarget = OBJECT_INVALID) +{ + if(ai_GetAIMode(oCreature, AI_MODE_EQUIP_WEAPON_OFF)) return FALSE; + if(AI_DEBUG) ai_Debug("0i_combat", "3049", GetName(oCreature) + " is equiping best melee weapon!"); + float fItemPower, fOffItemPower, fRightPower, fLeftPower, f2HandedPower; + int nItemPower, nShieldPower, nShieldValue, nItemValue, nRightValue; + int n2HandedValue, nLeftValue, bTwoWeaponUser; + int nMaxItemValue = ai_GetMaxItemValueThatCanBeEquiped(GetHitDice(oCreature)); + if(AI_DEBUG) ai_Debug("0i_combat", "3054", "nMaxItemValue: " + IntToString(nMaxItemValue)); + bTwoWeaponUser = GetHasFeat(374/*FEAT_DUAL_WIELD*/, oCreature) || GetHasFeat(FEAT_TWO_WEAPON_FIGHTING, oCreature); + object oShield = OBJECT_INVALID; + object oRight = OBJECT_INVALID; + object oLeft = OBJECT_INVALID; + object o2Handed = OBJECT_INVALID; + object o2HandedHand = OBJECT_INVALID; + object oRightHand = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND); + if(oRightHand != OBJECT_INVALID) + { + // Setup the item in our right hand's avg dmg and gold value as our base. + if(ai_GetIsTwoHandedWeapon(oRightHand, oCreature)) + { + if(ai_GetIsDoubleWeapon(oRightHand)) + { + f2HandedPower = ai_GetMeleeWeaponAvgDmg(oCreature, oRightHand, TRUE, FALSE, oRightHand); + } + else f2HandedPower = ai_GetMeleeWeaponAvgDmg(oCreature, oRightHand, TRUE); + n2HandedValue = GetGoldPieceValue(oRightHand); + if(AI_DEBUG) ai_Debug("0i_combat", "3073", " 2Handed oRightHand: " + GetName(oRightHand) + + " f2HandPower: " + FloatToString(f2HandedPower, 0, 2) + + " n2HandedValue: " + IntToString(n2HandedValue)); + } + else if(ai_GetIsSingleHandedWeapon(oRightHand, oCreature)) + { + fRightPower = ai_GetMeleeWeaponAvgDmg(oCreature, oRightHand); + nRightValue = GetGoldPieceValue(oRightHand); + if(AI_DEBUG) ai_Debug("0i_combat", "3081", " 1Handed oRightHand: " + GetName(oRightHand) + + " fRightPower: " + FloatToString(fRightPower, 0, 2) + + " nRightValue: " + IntToString(nRightValue)); + } + } + object oLeftHand = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oCreature); + if(oLeftHand != OBJECT_INVALID) + { + // Setup the item in our left hand's Shield AC and gold value as our base. + if(ai_GetIsShield(oLeftHand)) + { + nShieldPower = ai_SetShieldAC(oCreature, oLeftHand); + nShieldValue = GetGoldPieceValue(oLeftHand); + if(AI_DEBUG) ai_Debug("0i_combat", "3098", " Shield oLeftHand: " + GetName(oLeftHand) + + " fShieldPower: " + IntToString(nShieldPower) + + " nShieldValue: " + IntToString(nShieldValue)); + } + // Setup the item in our left hand's avg dmg and gold value as our base. + else + { + fLeftPower = ai_GetMeleeWeaponAvgDmg(oCreature, oLeftHand, FALSE, TRUE); + nLeftValue = GetGoldPieceValue(oLeftHand); + if(AI_DEBUG) ai_Debug("0i_combat", "3103", " 1Handed oLeftHand: " + GetName(oLeftHand) + + " fLeftPower: " + FloatToString(fLeftPower, 0, 2) + + " nLeftValue: " + IntToString(nLeftValue)); + } + } + int nWeaponSize, nType, nCreatureSize = GetCreatureSize(oCreature); + // Get the best weapons they have in their inventory. + object oItem = GetFirstItemInInventory(oCreature); + // If they don't have any items then lets stop, we can't equip a weapon/shield. + if(oItem == OBJECT_INVALID) return FALSE; + while(oItem != OBJECT_INVALID) + { + if(AI_DEBUG) ai_Debug("0i_combat", "3114", GetName(oItem) + " MeleeWeapon: " + + IntToString(ai_GetIsMeleeWeapon(oItem)) + " Proficient: " + + IntToString(ai_GetIsProficientWith(oCreature, oItem)) + + " Identified: " + IntToString(GetIdentified(oItem))); + if(ai_GetIsProficientWith(oCreature, oItem) && + GetIdentified(oItem) && ai_CheckIfCanUseItem(oCreature, oItem)) + { + nItemValue = GetGoldPieceValue(oItem); + if(AI_DEBUG) ai_Debug("0i_combat", "3122", " nItemValue: " + IntToString(nItemValue)); + if(!GetLocalInt(GetModule(), AI_RULE_ILR) || nMaxItemValue >= nItemValue) + { + if(ai_GetIsShield(oItem)) + { + nItemPower = ai_SetShieldAC(oCreature, oItem); + if(nItemPower > nShieldPower || + (nItemPower == nShieldPower && nItemValue > nShieldValue)) + { oShield = oItem; nShieldPower = nItemPower; nShieldValue = nItemValue; } + } + else if(ai_GetIsMeleeWeapon(oItem)) + { + // Make sure the creature and weapon are close enough in size. + // Can wield a weapon up to one size larger than their size. + // Can wield a weapon down to two sizes smaller than their size. + nType = GetBaseItemType(oItem); + nWeaponSize = StringToInt(Get2DAString("baseitems", "WeaponSize", nType)); + if(nWeaponSize >= nCreatureSize - 2 && nWeaponSize <= nCreatureSize + 1) + { + // Get item avg damage based on if it is 2handed or 1handed. + if(ai_GetIsSingleHandedWeapon(oItem, oCreature)) + { + fItemPower = ai_GetMeleeWeaponAvgDmg(oCreature, oItem); + fOffItemPower = ai_GetMeleeWeaponAvgDmg(oCreature, oItem, FALSE, TRUE); + // If the new weapon is better than the weapon in our right hand. + if(fItemPower > fRightPower || + (fItemPower == fRightPower && nItemValue > nRightValue)) + { + // We need to check if the weapon in the right hand is + // better than the weapon in the left hand since we are + // replacing our right hand weapon. + // Note: we must find out if we have selected a weapon for the + // right hand i.e. oRight or the best weapon is in our + // right hand i.e. oRightHand! + fOffItemPower = 0.0; + if(oRight != OBJECT_INVALID && ai_GetIsSingleHandedWeapon(oRight, oCreature)) + { + fOffItemPower = ai_GetMeleeWeaponAvgDmg(oCreature, oRight, FALSE, TRUE); + } + else if(oRightHand != OBJECT_INVALID && ai_GetIsSingleHandedWeapon(oRightHand, oCreature)) + { + fOffItemPower = ai_GetMeleeWeaponAvgDmg(oCreature, oRightHand, FALSE, TRUE); + } + // If the right hand weapon is better than the weapon in our left hand. + if(fOffItemPower > fLeftPower || (fOffItemPower > 0.0 && + fOffItemPower == fLeftPower && nRightValue > nLeftValue)) + { + if(oRight != OBJECT_INVALID) oLeft = oRight; + else oLeft = oRightHand; + fLeftPower = fOffItemPower; + nLeftValue = nRightValue; + } + oRight = oItem; + fRightPower = fItemPower; + nRightValue = nItemValue; + } + // If the new weapon is better than the weapon in our left hand. + else if(fOffItemPower > fLeftPower || + (fOffItemPower == fLeftPower && nItemValue > nLeftValue)) + { oLeft = oItem; fLeftPower = fOffItemPower; nLeftValue = nItemValue; } + } + else if(ai_GetIsTwoHandedWeapon(oItem, oCreature)) + { + if(ai_GetIsDoubleWeapon(oItem)) + { + fItemPower = ai_GetMeleeWeaponAvgDmg(oCreature, oItem, TRUE, FALSE, oItem); + } + else fItemPower = ai_GetMeleeWeaponAvgDmg(oCreature, oItem, TRUE); + // If the new weapon is better than the selected weapon. + if(fItemPower > f2HandedPower || + (fItemPower == f2HandedPower && nItemValue > n2HandedValue)) + { + o2Handed = oItem; + f2HandedPower = fItemPower; + n2HandedValue = nItemValue; + } + } + } + } + } + } + oItem = GetNextItemInInventory(); + } + if(AI_DEBUG) ai_Debug("0i_combat", "3197", "oRight: " + GetName(oRight) + " oLeft:" + + GetName(oLeft) + " oShield: " + GetName(oShield) + + "o2Handed: " + GetName(o2Handed)); + // First check for two weapons first. + if(bTwoWeaponUser && oRight != OBJECT_INVALID && oLeft != OBJECT_INVALID) + { + fRightPower = ai_GetMeleeWeaponAvgDmg(oCreature, oRight, FALSE, FALSE, oLeft); + fRightPower += ai_GetMeleeWeaponAvgDmg(oCreature, oLeft, FALSE, TRUE); + if(AI_DEBUG) ai_Debug("0i_combat", "3205", " Right/Left Power: " + + FloatToString(fRightPower, 0, 2) + " 2HandedPower: " + + FloatToString(f2HandedPower, 0, 2)); + if(fRightPower > f2HandedPower) + { + if(AI_DEBUG) ai_Debug("0i_combat", "3210", GetName(oCreature) + " is equiping " + + GetName(oRight) + " in the right hand and " + GetName(oLeft) + + " in the left hand."); + ActionEquipItem(oRight, INVENTORY_SLOT_RIGHTHAND); + ActionEquipItem(oLeft, INVENTORY_SLOT_LEFTHAND); + return TRUE; + } + } + if(f2HandedPower > fRightPower && o2Handed != OBJECT_INVALID) + { + if(AI_DEBUG) ai_Debug("0i_combat", "3220", GetName(oCreature) + " is equiping " + + GetName(o2Handed) + " in both hands."); + ActionEquipItem(o2Handed, INVENTORY_SLOT_RIGHTHAND); + return TRUE; + } + // Now lets just equip the best weapon for the right hand. + if(oRight != OBJECT_INVALID) + { + if(AI_DEBUG) ai_Debug("0i_combat", "3228", GetName(oCreature) + " is equiping " + + GetName(oRight) + " in the right hand. "); + ActionEquipItem(oRight, INVENTORY_SLOT_RIGHTHAND); + } + // Make sure we are not equiping a 2handed weapon and + // If not can we equip a shield? + if((oRight == OBJECT_INVALID || ai_GetIsSingleHandedWeapon(oRight, oCreature) || + !ai_GetIsTwoHandedWeapon(oRightHand, oCreature)) && + oShield != OBJECT_INVALID && GetHasFeat(FEAT_SHIELD_PROFICIENCY, oCreature)) + { + if(AI_DEBUG) ai_Debug("0i_combat", "3238", GetName(oCreature) + " is equiping " + + GetName(oShield) + " in the left hand."); + ActionEquipItem(oShield, INVENTORY_SLOT_LEFTHAND); + return TRUE; + } + // Finally if we don't have a weapon to equip so check to see if we are + // holding a bow. + else if(oRight == OBJECT_INVALID) + { + if(AI_DEBUG) ai_Debug("0i_combat", "3247", GetName(oCreature) + " did not equip a melee weapon"); + // We couldn't find a melee weapon but we are looking to go into melee + // I'm holding a ranged weapon! We better put it up. + if(GetWeaponRanged(oRightHand)) + { + if(AI_DEBUG) ai_Debug("0i_combat", "3252", GetName(oCreature) + " is unequiping " + GetName(oRightHand)); + ActionUnequipItem(oRightHand); + return TRUE; + } + } + if(AI_DEBUG) ai_Debug("0i_combat", "3257", GetName(oCreature) + " is not equiping a weapon!"); + return FALSE; +} +int ai_EquipBestRangedWeapon(object oCreature, object oTarget = OBJECT_INVALID) +{ + if(ai_GetAIMode(oCreature, AI_MODE_EQUIP_WEAPON_OFF)) return FALSE; + if(AI_DEBUG) ai_Debug("0i_combat", "3267", GetName(oCreature) + " is looking for best ranged weapon!"); + int nAmmo, nAmmoSlot, nBestType1, nBestType2, nType, nFeat, nItemValue, nRangedValue; + int nMaxItemValue = ai_GetMaxItemValueThatCanBeEquiped(GetHitDice(oCreature)); + string sAmmo; + object oRightHand = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oCreature); + if(oRightHand != OBJECT_INVALID && ai_GetIsRangeWeapon(oRightHand)) + { + // Setup the item in our right hand as our base gold value to check against. + if(ai_GetIsRangeWeapon(oRightHand)) nRangedValue = GetGoldPieceValue(oRightHand); + } + object oRanged = OBJECT_INVALID, oAmmo = OBJECT_INVALID; + // Find the best type of ranged weapon for this player. + if(GetHasFeat(FEAT_WEAPON_FOCUS_LONGBOW, oCreature)) + { nBestType1 = BASE_ITEM_LONGBOW; nAmmo = BASE_ITEM_ARROW; nAmmoSlot = INVENTORY_SLOT_ARROWS; sAmmo = "arrow";} + else if(GetHasFeat(FEAT_WEAPON_FOCUS_SHORTBOW, oCreature)) + { nBestType1 = BASE_ITEM_SHORTBOW; nAmmo = BASE_ITEM_ARROW; nAmmoSlot = INVENTORY_SLOT_ARROWS; sAmmo = "arrow";} + else if(GetHasFeat(FEAT_WEAPON_FOCUS_HEAVY_CROSSBOW, oCreature)) + { nBestType1 = BASE_ITEM_HEAVYCROSSBOW; nAmmo = BASE_ITEM_BOLT; nAmmoSlot = INVENTORY_SLOT_BOLTS; sAmmo = "bolt";} + else if(GetHasFeat(FEAT_WEAPON_FOCUS_LIGHT_CROSSBOW, oCreature)) + { nBestType1 = BASE_ITEM_LIGHTCROSSBOW; nAmmo = BASE_ITEM_BOLT; nAmmoSlot = INVENTORY_SLOT_BOLTS; sAmmo = "bolt";} + else if(GetHasFeat(FEAT_WEAPON_FOCUS_SLING, oCreature)) + { nBestType1 = BASE_ITEM_SLING; nAmmo = BASE_ITEM_BULLET; nAmmoSlot = INVENTORY_SLOT_BULLETS; sAmmo = "bullet";} + else if(GetHasFeat(FEAT_WEAPON_FOCUS_DART, oCreature)) + { nBestType1 = BASE_ITEM_DART; } + else if(GetHasFeat(FEAT_WEAPON_FOCUS_SHURIKEN, oCreature)) + { nBestType1 = BASE_ITEM_SHURIKEN; } + else if(GetHasFeat(FEAT_WEAPON_FOCUS_THROWING_AXE, oCreature)) + { nBestType1 = BASE_ITEM_THROWINGAXE; } + // These feats require a bow. + else if(GetHasFeat(FEAT_RAPID_SHOT, oCreature)) + { nBestType1 = BASE_ITEM_LONGBOW; nBestType2 = BASE_ITEM_SHORTBOW; + nAmmo = BASE_ITEM_ARROW; nAmmoSlot = INVENTORY_SLOT_ARROWS; sAmmo = "arrow"; } + // This feat requires a xbow. + else if(GetHasFeat(FEAT_RAPID_RELOAD, oCreature)) + { nBestType1 = BASE_ITEM_HEAVYCROSSBOW; nBestType2 = BASE_ITEM_LIGHTCROSSBOW; + nAmmo = BASE_ITEM_BOLT; nAmmoSlot = INVENTORY_SLOT_BOLTS; sAmmo = "bolt"; } + if(AI_DEBUG) ai_Debug("0i_combat", "3262", "nBestType1: " + IntToString(nBestType1) + " nBestType2: " + IntToString(nBestType2) + + " nAmmo: " + IntToString(nAmmo)); + int nCreatureSize = GetCreatureSize(oCreature) + 1; + // Cycle through the inventory looking for a ranged weapon. + object oItem = GetFirstItemInInventory(oCreature); + while(oItem != OBJECT_INVALID) + { + nType = GetBaseItemType(oItem); + if(AI_DEBUG) ai_Debug("0i_combat", "3269", "oItem: " + GetName(oItem) + + " Identified: " + IntToString(GetIdentified(oItem)) + + " Ranged Weapon: " + Get2DAString("baseitems", "RangedWeapon", nType)); + // Make sure it is identified and it is a ranged weapon. + if(GetIdentified(oItem) && Get2DAString("baseitems", "RangedWeapon", nType) != "") + { + if(AI_DEBUG) ai_Debug("0i_combat", "3278", " Proficient: " + + IntToString(ai_GetIsProficientWith(oCreature, oItem)) + + " nMaxItemValue: " + IntToString(nMaxItemValue)); + if(ai_GetIsProficientWith(oCreature, oItem)) + { + if(ai_CheckIfCanUseItem(oCreature, oItem)) + { + nItemValue = GetGoldPieceValue(oItem); + if(AI_DEBUG) ai_Debug("0i_combat", "3284", "nItemValue: " + IntToString(nItemValue)); + if(!GetLocalInt(GetModule(), AI_RULE_ILR) || nMaxItemValue >= nItemValue) + { + if(AI_DEBUG) ai_Debug("0i_combat", "3287", " Creature Size: " + IntToString(nCreatureSize) + + " Weapon Size: " + Get2DAString("baseitems", "WeaponSize", nType)); + // Make sure they are large enough to use it. + if(StringToInt(Get2DAString("baseitems", "WeaponSize", nType)) <= nCreatureSize) + { + if(AI_DEBUG) ai_Debug("0i_combat", "3292", "nItemValue: " + IntToString(nItemValue) + + " nRangedValue: " + IntToString(nRangedValue) + " nType: " + IntToString(nType)); + // Is it of the best range weapon type? 0 is any range weapon. + // Also grab any range weapon until we have a best type. + if(nType == nBestType1 || nType == nBestType2 || + nBestType1 == 0 || oRanged == OBJECT_INVALID) + { + if(nItemValue > nRangedValue) + { + if(ai_GetHasItemProperty(oItem, ITEM_PROPERTY_UNLIMITED_AMMUNITION)) + { + oRanged = oItem; nRangedValue = nItemValue; + if(AI_DEBUG) ai_Debug("0i_combat", "3304", "Selecting oRanged: " + GetName(oRanged) + + " nRangedValue: " + IntToString(nRangedValue) + " and doesn't need ammo!"); + } + else + { + if(nBestType1 == 0) + { + if(nType == BASE_ITEM_LONGBOW || nType == BASE_ITEM_SHORTBOW) + { nAmmo = BASE_ITEM_ARROW; sAmmo = "arrow"; nAmmoSlot = INVENTORY_SLOT_ARROWS; } + else if(nType == BASE_ITEM_HEAVYCROSSBOW || nType == BASE_ITEM_LIGHTCROSSBOW) + { nAmmo = BASE_ITEM_BOLT; sAmmo = "bolt"; nAmmoSlot = INVENTORY_SLOT_BOLTS; } + else if(nType == BASE_ITEM_SLING) + { nAmmo = BASE_ITEM_BULLET; sAmmo = "bullet"; nAmmoSlot = INVENTORY_SLOT_BULLETS; } + else nAmmo = 0; + } + // Now do we have ammo for it? + if(AI_DEBUG) ai_Debug("0i_combat", "3320", "nAmmo: " + IntToString(nAmmo)); + if(nAmmo > 0) + { + if(nAmmo == BASE_ITEM_ARROW || + nAmmo == BASE_ITEM_BOLT || + nAmmo == BASE_ITEM_BULLET) oAmmo = GetItemInSlot(nAmmoSlot); + if(oAmmo == OBJECT_INVALID) + { + // We don't have ammo equiped so lets see if we have any in our inventory. + oAmmo = GetFirstItemInInventory(); + while(oAmmo != OBJECT_INVALID) + { + if(GetBaseItemType(oAmmo) == nAmmo) break; + oAmmo = GetNextItemInInventory(); + } + if(oAmmo != OBJECT_INVALID) ActionEquipItem(oAmmo, nAmmoSlot); + } + } + if(oAmmo != OBJECT_INVALID) + { + oRanged = oItem; nRangedValue = nItemValue; + if(AI_DEBUG) ai_Debug("0i_combat", "3307", "Selecting oRanged: " + GetName(oRanged) + + " nRangedValue: " + IntToString(nRangedValue)); + } + } + } + } + } + } + } + } + } + oItem = GetNextItemInInventory(oCreature); + } + // They don't have a range weapon so lets break out. + if(oRanged == OBJECT_INVALID) + { + if(AI_DEBUG) ai_Debug("0i_combat", "3357", GetName(oCreature) + " did not equip a ranged weapon!"); + return FALSE; + } + ActionEquipItem(oRanged, INVENTORY_SLOT_RIGHTHAND); + return TRUE; +} +int ai_EquipBestMonkMeleeWeapon(object oCreature, object oTarget = OBJECT_INVALID) +{ + if(AI_DEBUG) ai_Debug("0i_combat", "2949", GetName(OBJECT_SELF) + " is equiping best monk melee weapon!"); + int nValue, nRightValue; + int nMaxItemValue = ai_GetMaxItemValueThatCanBeEquiped(GetHitDice(oCreature)); + object oRight = OBJECT_INVALID; + object oRightHand = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oCreature); + if(oRightHand != OBJECT_INVALID) + { + nRightValue = GetGoldPieceValue(oRightHand); + } + // Get the best kama they have in their inventory. + object oItem = GetFirstItemInInventory(oCreature); + // If they don't have any kamas then lets stop, we can't equip a weapon. + if(oItem == OBJECT_INVALID) return FALSE; + while(oItem != OBJECT_INVALID) + { + nValue = GetGoldPieceValue(oItem); + // Make sure they are high enough level to equip this item. + if(nMaxItemValue >= nValue && nValue > 1) + { + // Is it a single handed weapon? + if(GetBaseItemType(oItem) == BASE_ITEM_KAMA) + { + // Replace the lowest value right weapon. + if(nValue > nRightValue) + { + oRight = oItem; nRightValue = nValue; + } + } + } + oItem = GetNextItemInInventory(oCreature); + } + // Finally lets just equip the kama if we have one. + if(oRight == OBJECT_INVALID) + { + if(AI_DEBUG) ai_Debug("0i_combat", "2983", GetName(oCreature) + " did not equip a melee weapon!"); + return FALSE; + } + if(AI_DEBUG) ai_Debug("0i_combat", "2986", GetName(oCreature) + " is equiping " + GetName(oRight) + " in the right hand."); + ActionEquipItem(oRight, INVENTORY_SLOT_RIGHTHAND); + return TRUE; +} +int ai_IsInADangerousAOE(object oCreature, float fMaxRange = AI_RANGE_BATTLEFIELD, int bMove = FALSE) +{ + int bDangerous, nSpell, nCnt = 1; + string sAOEType; + object oAOE = GetNearestObject(OBJECT_TYPE_AREA_OF_EFFECT, oCreature, nCnt); + float fRadius, fDistance = GetDistanceBetween(oCreature, oAOE); + while(oAOE != OBJECT_INVALID && fDistance <= fMaxRange) + { + // AOE's have the tag set to the "LABEL" in vfx_persistent.2da + // I check vs those labels to see if the AOE is offensive. + // Below is the list of Offensive AOE effects. + sAOEType = GetTag(oAOE); + if(sAOEType == "VFX_PER_WEB") { fRadius = 6.7; nSpell = SPELL_WEB; } + else if(sAOEType == "VFX_PER_ENTANGLE") { fRadius = 5.0; nSpell = SPELL_ENTANGLE; } + else if(sAOEType == "VFX_PER_GREASE") { fRadius = 6.0; nSpell = SPELL_GREASE; } + else if(sAOEType == "VFX_PER_EVARDS_BLACK_TENTACLES") + { fRadius = 5.0; nSpell = SPELL_EVARDS_BLACK_TENTACLES; } + //else if(sAOEType == "VFX_PER_DARKNESS") { fRadius = 6.7; nSpell = SPELL_DARKNESS; } + //else if(sAOEType == "VFX_MOB_SILENCE") { fRadius = 4.0; nSpell = SPELL_SILENCE; } + else if(sAOEType == "VFX_PER_FOGSTINK") { fRadius = 6.7; nSpell = SPELL_STINKING_CLOUD; } + else if(sAOEType == "VFX_PER_FOGFIRE") { fRadius = 5.0; nSpell = SPELL_INCENDIARY_CLOUD; } + else if(sAOEType == "VFX_PER_FOGKILL") { fRadius = 5.0; nSpell = SPELL_CLOUDKILL; } + else if(sAOEType == "VFX_PER_FOGMIND") { fRadius = 5.0; nSpell = SPELL_MIND_FOG; } + else if(sAOEType == "VFX_PER_CREEPING_DOOM") { fRadius = 6.7; nSpell = SPELL_CREEPING_DOOM; } + else if(sAOEType == "VFX_PER_FOGACID") { fRadius = 5.0; nSpell = SPELL_ACID_FOG; } + else if(sAOEType == "VFX_PER_FOGBEWILDERMENT") { fRadius = 5.0; nSpell = SPELL_CLOUD_OF_BEWILDERMENT; } + else if(sAOEType == "VFX_PER_WALLFIRE") { fRadius = 10.0; nSpell = SPELL_WALL_OF_FIRE; } + else if(sAOEType == "VFX_PER_WALLBLADE") { fRadius = 10.0; nSpell = SPELL_BLADE_BARRIER; } + else if(sAOEType == "VFX_PER_DELAY_BLAST_FIREBALL") { fRadius = 2.0; nSpell = SPELL_DELAYED_BLAST_FIREBALL; } + else if(sAOEType == "VFX_PER_GLYPH") { fRadius = 2.5; nSpell = SPELL_GLYPH_OF_WARDING; } + else fRadius = 0.0; + if(AI_DEBUG) ai_Debug("0i_combat", "3088", GetName(oCreature) + " distance from AOE is " + FloatToString(fDistance, 0, 2) + + " AOE Radius: " + FloatToString(fRadius, 0, 2) + + " AOE Type: " + GetTag(oAOE)); + // fRadius > 0.0 keeps them from tiggering that they are in a dangerous + // AOE due to having an AOE on them. + if(fRadius > 0.0 && fDistance <= fRadius && + !ai_CreatureImmuneToEffect(GetAreaOfEffectCreator(oAOE), oCreature, nSpell)) + { + bDangerous = TRUE; + if(nSpell == SPELL_WEB || nSpell == SPELL_ENTANGLE) + { + if(ai_HasRangedWeaponWithAmmo(oCreature)) bDangerous = FALSE; + if(GetReflexSavingThrow(oCreature) + GetAbilityModifier(ABILITY_DEXTERITY, oCreature) >= ai_GetCharacterLevels(oCreature)) + bDangerous = FALSE; + } + break; + } + oAOE = GetNearestObject(OBJECT_TYPE_AREA_OF_EFFECT, oCreature, ++nCnt); + fDistance = GetDistanceBetween(oCreature, oAOE); + } + if(bDangerous && bMove) + { + location lLocation; + object oTarget; + if(ai_GetIsInCombat(oCreature)) + { + object oMaster = GetMaster(oCreature); + // If we have a ranged weapon then backout and use that. + if(ai_HasRangedWeaponWithAmmo(oCreature)) + { + lLocation = GetRandomLocation(GetArea(oCreature), oCreature, fRadius + 1.0); + } + else // we must find a target out of the AOE or fight in the AOE. + { + oTarget = ai_GetNearestTargetNotInAOE(oCreature, AI_RANGE_PERCEPTION, AI_ENEMY, TRUE); + if(oTarget != OBJECT_INVALID) lLocation = GetLocation(oTarget); + } + } + else lLocation = GetRandomLocation(GetArea(oCreature), oCreature, fRadius + 1.0); + ai_ClearCreatureActions(); + if(AI_DEBUG) ai_Debug("0i_combat", "3035", GetName(oCreature) + " is moving out of area of effect!"); + ActionMoveToLocation(lLocation, TRUE); + return TRUE; + } + else if(bDangerous) return TRUE; + return FALSE; +} +int ai_GetIsHidden(object oHidden) +{ + int nEffectType; + effect eEffect = GetFirstEffect(oHidden); + while(GetIsEffectValid(eEffect)) + { + nEffectType = GetEffectType(eEffect); + if(nEffectType == EFFECT_TYPE_INVISIBILITY) return 1; + else if(nEffectType == EFFECT_TYPE_IMPROVEDINVISIBILITY) return 1; + else if(nEffectType == EFFECT_TYPE_DARKNESS) return 2; + else if(nEffectType == EFFECT_TYPE_SANCTUARY) return 3; + else if(nEffectType == EFFECT_TYPE_ETHEREAL) return 3; + eEffect = GetNextEffect(oHidden); + } + if(GetActionMode(oHidden, ACTION_MODE_STEALTH)) return 4; + return FALSE; +} +int ai_CastOffensiveSpellVsTarget(object oCaster, object oCreature, int nSpell) +{ + // Check saves. + string sSave = Get2DAString("ai_spells", "SaveType", nSpell); + // There is no save! + if(sSave == "") return TRUE; + // Get the level of the spell. + int nSpellLvl = StringToInt(Get2DAString("spells", "Innate", nSpell)); + // Randomize our check. + nSpellLvl += Random(AI_SPELL_CHECK_DIE) + AI_SPELL_CHECK_BONUS; + // Check feats that might increase our DC. + string sSchool = Get2DAString("spells", "School", nSpell); + if(sSchool == "V") + { + if(GetHasFeat(FEAT_GREATER_SPELL_FOCUS_EVOCATION, oCaster)) nSpellLvl += 4; + else if(GetHasFeat(FEAT_SPELL_FOCUS_EVOCATION, oCaster)) nSpellLvl += 2; + } + else if(sSchool == "C") + { + if(GetHasFeat(FEAT_GREATER_SPELL_FOCUS_CONJURATION, oCaster)) nSpellLvl += 4; + else if(GetHasFeat(FEAT_SPELL_FOCUS_CONJURATION, oCaster)) nSpellLvl += 2; + } + else if(sSchool == "N") + { + if(GetHasFeat(FEAT_GREATER_SPELL_FOCUS_NECROMANCY, oCaster)) nSpellLvl += 4; + else if(GetHasFeat(FEAT_SPELL_FOCUS_NECROMANCY, oCaster)) nSpellLvl += 2; + } + else if(sSchool == "E") + { + if(GetHasFeat(FEAT_GREATER_SPELL_FOCUS_ENCHANTMENT, oCaster)) nSpellLvl += 4; + else if(GetHasFeat(FEAT_SPELL_FOCUS_ENCHANTMENT, oCaster)) nSpellLvl += 2; + } + else if(sSchool == "I") + { + if(GetHasFeat(FEAT_GREATER_SPELL_FOCUS_ILLUSION, oCaster)) nSpellLvl += 4; + else if(GetHasFeat(FEAT_SPELL_FOCUS_ILLUSION, oCaster)) nSpellLvl += 2; + } + else if(sSave == "Reflex") + { + string sImmunityType = Get2DAString("ai_spells", "ImmunityType", nSpell); + // Give a bonus to our check for half dmg spells unless they can dodge it! + if((sImmunityType == "Fire" || sImmunityType == "Electricity" || sImmunityType == "Acid" || + sImmunityType == "Cold" || sImmunityType == "Sonic") && + !GetHasFeat(FEAT_IMPROVED_EVASION, oCreature)) nSpellLvl += AI_SPELL_CHECK_NO_EVASION_BONUS; + if(AI_DEBUG) ai_Debug("0i_combat", "3050", " nSpellLvl: " + IntToString(nSpellLvl) + + " > nMagic: " + IntToString(GetReflexSavingThrow(oCreature))); + return (nSpellLvl > GetReflexSavingThrow(oCreature)); + } + else if(sSave == "Fortitude") return (nSpellLvl > GetFortitudeSavingThrow(oCreature)); + else if(sSave == "Will") return (nSpellLvl > GetWillSavingThrow(oCreature)); + return TRUE; +} +int ai_GetDragonDC(object oCreature) +{ + int nDC, nHitDice = GetHitDice(oCreature); + if(nHitDice < 4) { nDC = 12; } + else if(nHitDice < 7) { nDC = 13; } + else if(nHitDice < 10) { nDC = 14; } + else if(nHitDice < 13) { nDC = 16; } + else if(nHitDice < 16) { nDC = 18; } + else if(nHitDice < 19) { nDC = 20; } + else if(nHitDice < 22) { nDC = 22; } + else if(nHitDice < 25) { nDC = 24; } + else if(nHitDice < 28) { nDC = 26; } + else if(nHitDice < 31) { nDC = 28; } + else if(nHitDice < 34) { nDC = 30; } + else if(nHitDice < 37) { nDC = 32; } + else if(nHitDice < 39) { nDC = 34; } + else { nDC = 36; } + string sTag = GetTag(oCreature); + if(sTag == "gold_dragon") nDC += 5; + if(sTag == "red_dragon" || sTag == "silver_dragon") return nDC + 4; + else if(sTag == "black_dragon" || sTag == "brass_dragon") return nDC + 3; + else if(sTag == "green_dragon" || sTag == "copper_dragon") return nDC + 2; + else if(sTag == "blue_dragon" || sTag == "bronze_dragon") return nDC + 1; + //else if(sTag == "white_dragon") nDC += 0; + return nDC; +} +void ai_SetCreatureAIScript(object oCreature) +{ + string sCombatAI = GetLocalString(oCreature, AI_DEFAULT_SCRIPT); + // Non-Hostile NPC's do not need to use special tactics by default. + if(sCombatAI == "" && GetLocalInt(GetModule(), AI_RULE_AMBUSH) && d100() < 34) + { + // They should have skill ranks equal to their level + 1 to use a special AI. + int nSkillNeeded = GetHitDice(oCreature) + 1; + /*/ Ambusher: requires either Improved Invisibility or Invisibility. + if(GetHasSpell(SPELL_IMPROVED_INVISIBILITY, oCreature) || + GetHasSpell(SPELL_INVISIBILITY, oCreature)) + { + int bCast = ai_TryToCastSpell(oCreature, SPELL_IMPROVED_INVISIBILITY, oCreature); + if(!bCast) bCast = ai_TryToCastSpell(oCreature, SPELL_INVISIBILITY, oCreature); + if(bCast) sCombatAI = "ai_ambusher"; + } */ + if(GetHasFeat(FEAT_SNEAK_ATTACK, oCreature, TRUE)) + { + sCombatAI = "ai_flanker"; + } + // Ambusher: Requires a Hide and Move silently skill equal to your level + 1. + else if(GetSkillRank(SKILL_HIDE, oCreature) >= nSkillNeeded && + GetSkillRank(SKILL_MOVE_SILENTLY, oCreature) >= nSkillNeeded) + { + sCombatAI = "ai_ambusher"; + } + // Defensive : requires Parry skill equal to your level or Expertise. + else if(GetSkillRank(SKILL_PARRY, oCreature) >= nSkillNeeded || + GetHasFeat(FEAT_EXPERTISE, oCreature) || + GetHasFeat(FEAT_IMPROVED_EXPERTISE, oCreature)) + { + sCombatAI = "ai_defensive"; + } + else if(GetHasSpell(SPELL_LESSER_DISPEL, oCreature) || + GetHasSpell(SPELL_DISPEL_MAGIC, oCreature) || GetHasSpell(SPELL_GREATER_DISPELLING, oCreature)) + { + sCombatAI = "ai_cntrspell"; + } + else if(ai_CheckClassType(oCreature, AI_CLASS_TYPE_ARCANE) && + ai_GetCharacterLevels(oCreature) > 4) sCombatAI = "ai_ranged"; + else if(ai_EquipBestRangedWeapon(oCreature)) sCombatAI = "ai_ranged"; + else if(GetSkillRank(SKILL_TAUNT, oCreature) >= nSkillNeeded) sCombatAI = "ai_taunter"; + } + if(sCombatAI == "") + { + int nAssociateType = GetAssociateType(oCreature); + if (nAssociateType == ASSOCIATE_TYPE_FAMILIAR) + { + sCombatAI = "ai_default"; + } + else + { + // Select the best ai for this henchmen based on class. + int nClass = GetClassByPosition(1, oCreature); + // If they have more than one class use the default ai. + if(GetClassByPosition(2, oCreature) != CLASS_TYPE_INVALID) sCombatAI = "ai_default"; + else if(nClass == CLASS_TYPE_BARBARIAN) sCombatAI = "ai_barbarian"; + else if(nClass == CLASS_TYPE_BARD) sCombatAI = "ai_bard"; + else if(nClass == CLASS_TYPE_CLERIC) sCombatAI = "ai_cleric"; + else if(nClass == CLASS_TYPE_DRUID) sCombatAI = "ai_druid"; + else if(nClass == CLASS_TYPE_FIGHTER) sCombatAI = "ai_fighter"; + else if(nClass == CLASS_TYPE_MONK) sCombatAI = "ai_monk"; + else if(nClass == CLASS_TYPE_PALADIN) sCombatAI = "ai_paladin"; + else if(nClass == CLASS_TYPE_RANGER) sCombatAI = "ai_ranger"; + else if(nClass == CLASS_TYPE_ROGUE) sCombatAI = "ai_rogue"; + else if(nClass == CLASS_TYPE_SORCERER) sCombatAI = "ai_sorcerer"; + else if(nClass == CLASS_TYPE_WIZARD) sCombatAI = "ai_wizard"; + //else if(nClass == CLASS_TYPE_ABERRATION) sCombatAI = "ai_default"; + //else if(nClass == CLASS_TYPE_ANIMAL) sCombatAI = "ai_animal"; + //else if(nClass == CLASS_TYPE_CONSTRUCT) sCombatAI = "ai_animal"; + else if(nClass == CLASS_TYPE_DRAGON) sCombatAI = "ai_dragon"; + //else if(nClass == CLASS_TYPE_ELEMENTAL) sCombatAI = "ai_default"; + //else if(nClass == CLASS_TYPE_FEY) sCombatAI = "ai_default"; + //else if(nClass == CLASS_TYPE_GIANT) sCombatAI = "ai_default"; + //else if(nClass == CLASS_TYPE_HUMANOID) sCombatAI = "ai_default"; + //else if(nClass == CLASS_TYPE_MAGICAL_BEAST) sCombatAI = "ai_default"; + //else if(nClass == CLASS_TYPE_MONSTROUS) sCombatAI = "ai_default"; + //else if(nClass == CLASS_TYPE_OOZE) sCombatAI = "ai_default"; + //else if(nClass == CLASS_TYPE_OUTSIDER) sCombatAI = "ai_default"; + //else if(nClass == CLASS_TYPE_UNDEAD) sCombatAI = "ai_default"; + //else if(nClass == CLASS_TYPE_VERMIN) sCombatAI = "ai_animal"; + else sCombatAI = "ai_default"; + } + } + if(AI_DEBUG) ai_Debug("0i_combat", "3740", GetName(oCreature) + " is setting AI to " + sCombatAI); + SetLocalString(oCreature, AI_DEFAULT_SCRIPT, sCombatAI); + SetLocalString(oCreature, AI_COMBAT_SCRIPT, sCombatAI); +} +int ai_IsImmuneToSneakAttacks(object oCreature, object oTarget) +{ + if(GetHasFeat(FEAT_UNCANNY_DODGE_2, oTarget) && + GetLevelByClass(CLASS_TYPE_ROGUE, oCreature) + 3 < GetLevelByClass(CLASS_TYPE_ROGUE, oTarget)) return TRUE; + if(GetIsImmune(oTarget, IMMUNITY_TYPE_SNEAK_ATTACK)) return TRUE; + object oSkin = GetItemInSlot(INVENTORY_SLOT_CARMOUR, oTarget); + if(ai_GetHasItemProperty(oSkin, ITEM_PROPERTY_IMMUNITY_MISCELLANEOUS, IP_CONST_IMMUNITYMISC_BACKSTAB)) return TRUE; + return FALSE; +} +int ai_IsStrongerThanMe(object oCreature, int nIndex) +{ + int nEnemyCombat = GetLocalInt(oCreature, AI_ENEMY_COMBAT + IntToString(nIndex)); + int nCreatureCombat = ai_GetMyCombatRating(oCreature); + if(AI_DEBUG) ai_Debug("0i_combat", "3955", "IsStrongerThanMe: nCreatureCombat: " + + IntToString(nCreatureCombat) + " nEnemyCombat: " + IntToString(nEnemyCombat)); + return (nEnemyCombat > nCreatureCombat); +} +int ai_StrongOpponent(object oCreature, object oTarget, int nAdj = 2) +{ + int nLevel = GetHitDice(oCreature); + if(AI_DEBUG) ai_Debug("0i_combat", "3220", "ai_StrongOpponent"); + nAdj = nAdj *((nAdj + nLevel) / 10); + if(AI_DEBUG) ai_Debug("0i_combat", "3222", "Is the opponent strong? Target CR >= Our level - nAdj(" + + FloatToString(GetChallengeRating(oTarget), 0, 2) + " >= " + IntToString(nLevel - nAdj) + ")"); + return (FloatToInt(GetChallengeRating(oTarget)) >= nLevel - nAdj); +} +int ai_PowerAttackGood(object oCreature, object oTarget, float fAdj) +{ + int nAvgDmg = ai_GetWeaponDamage(oCreature, 2); + if(AI_DEBUG) ai_Debug("0i_combat", "3412", "PowerAttack: (nAvgDmg: " + IntToString(nAvgDmg) + + " > Target HP: " + IntToString(GetCurrentHitPoints(oTarget)) + + ") Skip: " + IntToString(nAvgDmg > GetCurrentHitPoints(oTarget))); + if(nAvgDmg > GetCurrentHitPoints(oTarget)) return FALSE; + float fAvgDmg = IntToFloat(nAvgDmg); + float fTargetAC = IntToFloat(GetAC(oTarget)); + float fCreatureAtk = IntToFloat(ai_GetCreatureAttackBonus(oCreature)); + float fNormalChance = (21.0 - (fTargetAC - fCreatureAtk)) / 20.0; + // Our chance to hit is already minimum of 5% so this doesn't hurt our chance! + if(fNormalChance <= 0.05) return TRUE; + float fAdjDamage = (fAvgDmg + fAdj) * ((21.0-(fTargetAC - fCreatureAtk + fAdj))/20); + if(AI_DEBUG) ai_Debug("0i_combat", "3420", "fNormalDamage: " + FloatToString(fNormalChance * fAvgDmg, 0, 2) + + " < fAdjDamage: " + FloatToString(fAdjDamage, 0, 2) + " = " + IntToString(fNormalChance * fAvgDmg < fAdjDamage)); + return fNormalChance * fAvgDmg < fAdjDamage; +} +int ai_AttackPenaltyOk(object oCreature, object oTarget, float fAtkAdj) +{ + float fTargetAC = IntToFloat(GetAC(oTarget)); + float fCreatureAtk = IntToFloat(ai_GetCreatureAttackBonus(oCreature)); + float fNormalChance = (21.0-(fTargetAC - fCreatureAtk))/20.0; + if(AI_DEBUG) ai_Debug("0i_combat", "3431", "Normal Avg Chance: " + FloatToString(fNormalChance, 0, 2) + " <= 0.05"); + // We already need a 20 to hit so this doesn't hurt our chances! + if(fNormalChance <= 0.05) return TRUE; + float fAdjChance = (21.0-(fTargetAC - fCreatureAtk + fAtkAdj))/20.0; + if(AI_DEBUG) ai_Debug("0i_combat", "3435", "Adjusted Avg Chance: " + FloatToString(fAdjChance, 0, 2) + " > 0.55"); + // if our chance is 55% or better to hit then use it. + return fAdjChance > 0.55; +} +int ai_AttackBonusGood(object oCreature, object oTarget, float fAtkAdj) +{ + float fTargetAC = IntToFloat(GetAC(oTarget)); + float fCreatureAtk = IntToFloat(ai_GetCreatureAttackBonus(oCreature)); + float fNormalChance = (21.0-(fTargetAC - fCreatureAtk))/20.0; + if(AI_DEBUG) ai_Debug("0i_combat", "3450", "Normal Avg Chance: " + FloatToString(fNormalChance, 0, 2) + " > 0.99"); + // We already hit them with any roll so this will not help. + if(fNormalChance > 0.99) return FALSE; + float fAdjChance = (21.0-(fTargetAC - fCreatureAtk - fAtkAdj))/20.0; + if(AI_DEBUG) ai_Debug("0i_combat", "3454", "Adjusted Avg Chance: " + FloatToString(fAdjChance, 0, 2) + " < 0.0"); + // if our chance increases our to hit then this is good. + return fAdjChance > 0.0; +} +int ai_ACAdjustmentGood(object oCreature, object oTarget, float fACAdj) +{ + float fCreatureAC = IntToFloat(GetAC(oCreature)); + float fTargetAtk = IntToFloat(ai_GetCreatureAttackBonus(oTarget)); + float fNormalChance = (21.0-(fCreatureAC - fTargetAtk))/20.0; + if(AI_DEBUG) ai_Debug("0i_combat", "3444", "Normal Chance To Hit: " + FloatToString(fNormalChance, 0, 2) + " <= 0.05"); + // They already need a 20 to hit so adding more AC is worthless. + if(fNormalChance <= 0.05) return FALSE; + float fAdjChance = (21.0-(fCreatureAC - fTargetAtk + fACAdj))/20.0; + if(AI_DEBUG) ai_Debug("0i_combat", "3448", "Adjusted Chance To Hit: " + FloatToString(fAdjChance, 0, 2) + " < 1.00"); + // Anything less than 1 helps are AC! + return fAdjChance < 1.00; +} +int ai_CanIMoveInCombat(object oCreature) +{ + // DC 15 tumble check is required to not give attacks of opportunity. + return (GetHasFeat(FEAT_MOBILITY, oCreature) || GetHasFeat(FEAT_SPRING_ATTACK, oCreature) || + GetSkillRank(SKILL_TUMBLE, oCreature) > 9); +} +int ai_CanIUseRangedWeapon(object oCreature, int nInMelee) +{ + return (!nInMelee || ai_GetEnemyAttackingMe(oCreature) == OBJECT_INVALID); +} +int ai_CheckRangedCombatPosition(object oCreature, object oTarget, int nAction) +{ + if(AI_DEBUG) ai_Debug("0i_combat", "3559", "Ranged attack: See oTarget? " + + IntToString(GetObjectSeen(oTarget, oCreature)) + " Line of Sight? " + + IntToString(LineOfSightObject(oCreature, oTarget))); + if(nAction == AI_LAST_ACTION_RANGED_ATK) + { + // Watch the nearest enemy instead of our target as they could move toward us. + object oNearestEnemy = GetLocalObject(oCreature, AI_ENEMY_NEAREST); + float fDistance = GetDistanceBetween(oCreature, oNearestEnemy); + if(AI_DEBUG) ai_Debug("0i_combat", "3337", "oNearestEnemy: " + GetName(oNearestEnemy) + + " fDistance: " + FloatToString(fDistance, 0, 2)); + // If we have sneak attack then we want to be within 30'. + if(GetHasFeat(FEAT_SNEAK_ATTACK, oCreature)) + { + if(fDistance > AI_RANGE_CLOSE) + { + // We check this because if the enemy is moving or has not + // started acting then we don't want to move up on them as they + // might move towards us. Just attack! Only sneak attack if they are busy. + int nAction = GetCurrentAction(oNearestEnemy); + if(AI_DEBUG) ai_Debug("0i_combat", "3353", GetName(oNearestEnemy) + " current action: " + IntToString(nAction)); + if(nAction == ACTION_MOVETOPOINT || + nAction == ACTION_INVALID || + nAction == ACTION_RANDOMWALK) return FALSE; + // If they are attacking make sure it is in melee? + // If not then don't move since they might be moving toward us. + if(nAction == ACTION_ATTACKOBJECT) + { + if(!ai_GetNumOfEnemiesInRange(oNearestEnemy)) return FALSE; + } + if(AI_DEBUG) ai_Debug("0i_combat", "3355", GetName(oCreature) + " is moving closer [8.0] to " + + GetName(oNearestEnemy) + " to sneak attack with a ranged weapon."); + ai_SetLastAction(oCreature, AI_LAST_ACTION_MOVE); + ActionMoveToObject(oNearestEnemy, TRUE, AI_RANGE_CLOSE); + ActionDoCommand(ExecuteScript("0e_do_combat_rnd", oCreature)); + return TRUE; + } + } + else if(fDistance < AI_RANGE_LONG) + { + // Lets move back a little, too far and we miss attacks! + if(AI_DEBUG) ai_Debug("0i_combat", "3374", GetName(oCreature) + " is moving away from " + + GetName(oNearestEnemy) + "[2.0] to use a ranged weapon."); + ai_SetLastAction(oCreature, AI_LAST_ACTION_MOVE); + ActionMoveAwayFromObject(oNearestEnemy, TRUE, 2.0); + ActionDoCommand(ExecuteScript("0e_do_combat_rnd", oCreature)); + return TRUE; + } + } + // If we are casting a hostile spell then check positioning. + else if(nAction > -1 && Get2DAString("ai_spells", "HostileSetting", nAction) == "1") + { + // We are out of melee and casting a spell on an ally so don't move. + if(GetReputation(oCreature, oTarget) > 89) return FALSE; + float fSpellRange = ai_GetSpellRange(nAction); + float fTargetRange = GetDistanceBetween(oCreature, oTarget); + if(AI_DEBUG) ai_Debug("0i_combat", "3389", "fSpellRange: " + FloatToString(fSpellRange, 0, 2) + + " fTargetRange: " + FloatToString(fTargetRange, 0, 2)); + // Adjust the ranges to see if we are too close. + if(fSpellRange == 5.0) fSpellRange = 4.5f; + //else if(fSpellRange == 8.0) fSpellRange = 8.0f; + else if(fSpellRange > 10.0f) fSpellRange = 10.0f; + if(AI_DEBUG) ai_Debug("0i_combat", "3395", "Adjusted spell range is " + + FloatToString(fSpellRange, 0, 2) + " : " + GetName(oTarget) + " range is " + + FloatToString(fTargetRange, 0, 2) + "."); + // We are closer than we have to be to cast our spell. + if(fTargetRange < fSpellRange) + { + // Lets move back a little, too far and we miss attacks! + if(AI_DEBUG) ai_Debug("0i_combat", "3402", GetName(oCreature) + " is moving away from " + + GetName(oTarget) + "[2.0] to cast a spell."); + ai_SetLastAction(oCreature, AI_LAST_ACTION_MOVE); + ActionMoveAwayFromObject(oTarget, FALSE, 2.0); + ActionDoCommand(ExecuteScript("0e_do_combat_rnd", oCreature)); + return TRUE; + } +} + return FALSE; +} +int ai_CheckMeleeCombatPosition(object oCreature, object oTarget, int nAction, int nBaseItemType = 0) +{ + // If we are not being attacked then we might want to back out of combat. + if(ai_GetEnemyAttackingMe(oCreature) != OBJECT_INVALID) + { + if(AI_DEBUG) ai_Debug("0i_combat", "3417", "I am being attacked so stand my ground!"); + return FALSE; + } + object oNearestEnemy = GetLocalObject(oCreature, AI_ENEMY_NEAREST); + float fDistance = GetDistanceBetween(oCreature, oNearestEnemy); + if(AI_DEBUG) ai_Debug("0i_combat", "3422", "oNearestEnemy: " + GetName(oNearestEnemy) + " fDistance " + FloatToString(fDistance, 0, 2)); + if(nAction == AI_LAST_ACTION_RANGED_ATK) + { + if(AI_DEBUG) ai_Debug("0i_combat", "3425", 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_MELEE - fDistance + 1.0); + ActionDoCommand(ExecuteScript("0e_do_combat_rnd", oCreature)); + return TRUE; + } + // If we want to cast a spell this round then back away! + else if(nAction > -1) + { + // Some items we don't need to move on such as wands, staves, and rods. + if(nBaseItemType == BASE_ITEM_ENCHANTED_WAND || + nBaseItemType == BASE_ITEM_MAGICWAND || + nBaseItemType == BASE_ITEM_MAGICSTAFF || + nBaseItemType == BASE_ITEM_MAGICROD) return FALSE; + float fSpellRange = ai_GetSpellRange(nAction); + // A Touch spell means we should not move if we are not the target. + if(fSpellRange <= 5.0 && oCreature != oTarget) return FALSE; + if(AI_DEBUG) ai_Debug("0i_combat", "3446", GetName(oCreature) + " is moving away from " + + GetName(oTarget) + "[" + FloatToString(AI_RANGE_MELEE - fDistance + 1.0, 0, 2) + "] to cast a spell."); + ai_SetLastAction(oCreature, AI_LAST_ACTION_MOVE); + SetActionMode(oCreature, ACTION_MODE_DEFENSIVE_CAST, FALSE); + // Lets move just out of melee range! + int bRun = ai_CanIMoveInCombat(oCreature); + ActionMoveAwayFromObject(oNearestEnemy, bRun, AI_RANGE_MELEE - fDistance + 1.0); + ActionDoCommand(ExecuteScript("0e_do_combat_rnd", oCreature)); + return TRUE; + } + return FALSE; +} +int ai_CheckCombatPosition(object oCreature, object oTarget, int nInMelee, int nAction, int nBaseItemType = 0) +{ + if(AI_DEBUG) ai_Debug("0i_combat", "3460", "|-----> Checking position in combat: " + + GetName(oCreature) + " nMelee: " + IntToString(nInMelee) + + " Action: " + IntToString(nAction) + + " Hold mode: " + IntToString(ai_GetAIMode(oCreature, AI_MODE_STAND_GROUND)) + + " Use Advanced Movement: " + IntToString(GetLocalInt(GetModule(), AI_RULE_ADVANCED_MOVEMENT))); + // We don't want to move around in combat if we were told to hold. + if(ai_GetAIMode(oCreature, AI_MODE_STAND_GROUND)) return FALSE; + if(!GetLocalInt(GetModule(), AI_RULE_ADVANCED_MOVEMENT)) return FALSE; + if(ai_CompareLastAction(oCreature, AI_LAST_ACTION_MOVE)) return FALSE; + // We are not in melee combat so lets see how close we should get. + if(!nInMelee) return ai_CheckRangedCombatPosition(oCreature, oTarget, nAction); + // If we are in melee we might need to move out of combat. + return ai_CheckMeleeCombatPosition(oCreature, oTarget, nAction, nBaseItemType); +} diff --git a/src/module/nss/0i_constants.nss b/src/module/nss/0i_constants.nss new file mode 100644 index 0000000..5413ac4 --- /dev/null +++ b/src/module/nss/0i_constants.nss @@ -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; diff --git a/src/module/nss/0i_gui_events.nss b/src/module/nss/0i_gui_events.nss new file mode 100644 index 0000000..4628cf3 --- /dev/null +++ b/src/module/nss/0i_gui_events.nss @@ -0,0 +1,1032 @@ +/*//////////////////////////////////////////////////////////////////////////////////////////////////// +// Script Name: 0i_gui_events +// Programmer: Philos +////////////////////////////////////////////////////////////////////////////////////////////////////// + Include scripts for all gui events. See also 0e_gui_events + + GUI Events: + GUIEVENT_EFFECTICON_CLICK: For displaying icon information. + + This was built by DAZ all credit to him. + I just changed it from PostString to a NUI menu. +*///////////////////////////////////////////////////////////////////////////////////////////////////// +#include "0i_constants" +#include "0i_nui" +void ai_SetupModuleGUIEvents(object oCreature) +{ + object oModule = GetModule(); + string sModuleGUIEvents = GetEventScript(oModule, EVENT_SCRIPT_MODULE_ON_PLAYER_GUIEVENT); + if(sModuleGUIEvents != "" || sModuleGUIEvents != "0e_gui_events") + { + SetLocalString(oModule, AI_MODULE_GUI_EVENT, sModuleGUIEvents); + } + SetEventScript(oModule, EVENT_SCRIPT_MODULE_ON_PLAYER_GUIEVENT, "0e_gui_events"); +} +int EffectIconToEffectType(int nEffectIcon) +{ + switch (nEffectIcon) + { + case EFFECT_ICON_INVALID: return EFFECT_TYPE_INVALIDEFFECT; + + // *** No Extra Stats + case EFFECT_ICON_BLIND: return EFFECT_TYPE_BLINDNESS; + case EFFECT_ICON_CHARMED: return EFFECT_TYPE_CHARMED; + case EFFECT_ICON_CONFUSED: return EFFECT_TYPE_CONFUSED; + case EFFECT_ICON_FRIGHTENED: return EFFECT_TYPE_FRIGHTENED; + case EFFECT_ICON_DOMINATED: return EFFECT_TYPE_DOMINATED; + case EFFECT_ICON_PARALYZE: return EFFECT_TYPE_PARALYZE; + case EFFECT_ICON_DAZED: return EFFECT_TYPE_DAZED; + case EFFECT_ICON_STUNNED: return EFFECT_TYPE_STUNNED; + case EFFECT_ICON_SLEEP: return EFFECT_TYPE_SLEEP; + case EFFECT_ICON_SILENCE: return EFFECT_TYPE_SILENCE; + case EFFECT_ICON_TURNED: return EFFECT_TYPE_TURNED; + case EFFECT_ICON_HASTE: return EFFECT_TYPE_HASTE; + case EFFECT_ICON_SLOW: return EFFECT_TYPE_SLOW; + case EFFECT_ICON_ENTANGLE: return EFFECT_TYPE_ENTANGLE; + case EFFECT_ICON_DEAF: return EFFECT_TYPE_DEAF; + case EFFECT_ICON_DARKNESS: return EFFECT_TYPE_DARKNESS; + case EFFECT_ICON_POLYMORPH: return EFFECT_TYPE_POLYMORPH; + case EFFECT_ICON_SANCTUARY: return EFFECT_TYPE_SANCTUARY; + case EFFECT_ICON_TRUESEEING: return EFFECT_TYPE_TRUESEEING; + case EFFECT_ICON_SEEINVISIBILITY: return EFFECT_TYPE_SEEINVISIBLE; + case EFFECT_ICON_ETHEREALNESS: return EFFECT_TYPE_ETHEREAL; + case EFFECT_ICON_PETRIFIED: return EFFECT_TYPE_PETRIFY; + // *** + + case EFFECT_ICON_DAMAGE_RESISTANCE: return EFFECT_TYPE_DAMAGE_RESISTANCE; + case EFFECT_ICON_REGENERATE: return EFFECT_TYPE_REGENERATE; + case EFFECT_ICON_DAMAGE_REDUCTION: return EFFECT_TYPE_DAMAGE_REDUCTION; + case EFFECT_ICON_TEMPORARY_HITPOINTS: return EFFECT_TYPE_TEMPORARY_HITPOINTS; + case EFFECT_ICON_IMMUNITY: return EFFECT_TYPE_IMMUNITY; + case EFFECT_ICON_POISON: return EFFECT_TYPE_POISON; + case EFFECT_ICON_DISEASE: return EFFECT_TYPE_DISEASE; + case EFFECT_ICON_CURSE: return EFFECT_TYPE_CURSE; + case EFFECT_ICON_ATTACK_INCREASE: return EFFECT_TYPE_ATTACK_INCREASE; + case EFFECT_ICON_ATTACK_DECREASE: return EFFECT_TYPE_ATTACK_DECREASE; + case EFFECT_ICON_DAMAGE_INCREASE: return EFFECT_TYPE_DAMAGE_INCREASE; + case EFFECT_ICON_DAMAGE_DECREASE: return EFFECT_TYPE_DAMAGE_DECREASE; + case EFFECT_ICON_AC_INCREASE: return EFFECT_TYPE_AC_INCREASE; + case EFFECT_ICON_AC_DECREASE: return EFFECT_TYPE_AC_DECREASE; + case EFFECT_ICON_MOVEMENT_SPEED_INCREASE: return EFFECT_TYPE_MOVEMENT_SPEED_INCREASE; + case EFFECT_ICON_MOVEMENT_SPEED_DECREASE: return EFFECT_TYPE_MOVEMENT_SPEED_DECREASE; + case EFFECT_ICON_SAVING_THROW_DECREASE: return EFFECT_TYPE_SAVING_THROW_DECREASE; + case EFFECT_ICON_SPELL_RESISTANCE_INCREASE: return EFFECT_TYPE_SPELL_RESISTANCE_INCREASE; + case EFFECT_ICON_SPELL_RESISTANCE_DECREASE: return EFFECT_TYPE_SPELL_RESISTANCE_DECREASE; + case EFFECT_ICON_SKILL_INCREASE: return EFFECT_TYPE_SKILL_INCREASE; + case EFFECT_ICON_SKILL_DECREASE: return EFFECT_TYPE_SKILL_DECREASE; + case EFFECT_ICON_ELEMENTALSHIELD: return EFFECT_TYPE_ELEMENTALSHIELD; + case EFFECT_ICON_LEVELDRAIN: return EFFECT_TYPE_NEGATIVELEVEL; + case EFFECT_ICON_SPELLLEVELABSORPTION: return EFFECT_TYPE_SPELLLEVELABSORPTION; + case EFFECT_ICON_SPELLIMMUNITY: return EFFECT_TYPE_SPELL_IMMUNITY; + case EFFECT_ICON_CONCEALMENT: return EFFECT_TYPE_CONCEALMENT; + case EFFECT_ICON_EFFECT_SPELL_FAILURE: return EFFECT_TYPE_SPELL_FAILURE; + + case EFFECT_ICON_INVISIBILITY: + case EFFECT_ICON_IMPROVEDINVISIBILITY: return EFFECT_TYPE_INVISIBILITY; + + case EFFECT_ICON_ABILITY_INCREASE_STR: + case EFFECT_ICON_ABILITY_INCREASE_DEX: + case EFFECT_ICON_ABILITY_INCREASE_CON: + case EFFECT_ICON_ABILITY_INCREASE_INT: + case EFFECT_ICON_ABILITY_INCREASE_WIS: + case EFFECT_ICON_ABILITY_INCREASE_CHA: return EFFECT_TYPE_ABILITY_INCREASE; + + case EFFECT_ICON_ABILITY_DECREASE_STR: + case EFFECT_ICON_ABILITY_DECREASE_CHA: + case EFFECT_ICON_ABILITY_DECREASE_DEX: + case EFFECT_ICON_ABILITY_DECREASE_CON: + case EFFECT_ICON_ABILITY_DECREASE_INT: + case EFFECT_ICON_ABILITY_DECREASE_WIS: return EFFECT_TYPE_ABILITY_DECREASE; + + case EFFECT_ICON_IMMUNITY_ALL: + case EFFECT_ICON_IMMUNITY_MIND: + case EFFECT_ICON_IMMUNITY_POISON: + case EFFECT_ICON_IMMUNITY_DISEASE: + case EFFECT_ICON_IMMUNITY_FEAR: + case EFFECT_ICON_IMMUNITY_TRAP: + case EFFECT_ICON_IMMUNITY_PARALYSIS: + case EFFECT_ICON_IMMUNITY_BLINDNESS: + case EFFECT_ICON_IMMUNITY_DEAFNESS: + case EFFECT_ICON_IMMUNITY_SLOW: + case EFFECT_ICON_IMMUNITY_ENTANGLE: + case EFFECT_ICON_IMMUNITY_SILENCE: + case EFFECT_ICON_IMMUNITY_STUN: + case EFFECT_ICON_IMMUNITY_SLEEP: + case EFFECT_ICON_IMMUNITY_CHARM: + case EFFECT_ICON_IMMUNITY_DOMINATE: + case EFFECT_ICON_IMMUNITY_CONFUSE: + case EFFECT_ICON_IMMUNITY_CURSE: + case EFFECT_ICON_IMMUNITY_DAZED: + case EFFECT_ICON_IMMUNITY_ABILITY_DECREASE: + case EFFECT_ICON_IMMUNITY_ATTACK_DECREASE: + case EFFECT_ICON_IMMUNITY_DAMAGE_DECREASE: + case EFFECT_ICON_IMMUNITY_DAMAGE_IMMUNITY_DECREASE: + case EFFECT_ICON_IMMUNITY_AC_DECREASE: + case EFFECT_ICON_IMMUNITY_MOVEMENT_SPEED_DECREASE: + case EFFECT_ICON_IMMUNITY_SAVING_THROW_DECREASE: + case EFFECT_ICON_IMMUNITY_SPELL_RESISTANCE_DECREASE: + case EFFECT_ICON_IMMUNITY_SKILL_DECREASE: + case EFFECT_ICON_IMMUNITY_KNOCKDOWN: + case EFFECT_ICON_IMMUNITY_NEGATIVE_LEVEL: + case EFFECT_ICON_IMMUNITY_SNEAK_ATTACK: + case EFFECT_ICON_IMMUNITY_CRITICAL_HIT: + case EFFECT_ICON_IMMUNITY_DEATH_MAGIC: return EFFECT_TYPE_IMMUNITY; + + case EFFECT_ICON_SAVING_THROW_INCREASE: + case EFFECT_ICON_REFLEX_SAVE_INCREASED: + case EFFECT_ICON_FORT_SAVE_INCREASED: + case EFFECT_ICON_WILL_SAVE_INCREASED: return EFFECT_TYPE_SAVING_THROW_INCREASE; + + case EFFECT_ICON_DAMAGE_IMMUNITY_INCREASE: + case EFFECT_ICON_DAMAGE_IMMUNITY_MAGIC: + case EFFECT_ICON_DAMAGE_IMMUNITY_ACID: + case EFFECT_ICON_DAMAGE_IMMUNITY_COLD: + case EFFECT_ICON_DAMAGE_IMMUNITY_DIVINE: + case EFFECT_ICON_DAMAGE_IMMUNITY_ELECTRICAL: + case EFFECT_ICON_DAMAGE_IMMUNITY_FIRE: + case EFFECT_ICON_DAMAGE_IMMUNITY_NEGATIVE: + case EFFECT_ICON_DAMAGE_IMMUNITY_POSITIVE: + case EFFECT_ICON_DAMAGE_IMMUNITY_SONIC: return EFFECT_TYPE_DAMAGE_IMMUNITY_INCREASE; + + case EFFECT_ICON_DAMAGE_IMMUNITY_DECREASE: + case EFFECT_ICON_DAMAGE_IMMUNITY_MAGIC_DECREASE: + case EFFECT_ICON_DAMAGE_IMMUNITY_ACID_DECREASE: + case EFFECT_ICON_DAMAGE_IMMUNITY_COLD_DECREASE: + case EFFECT_ICON_DAMAGE_IMMUNITY_DIVINE_DECREASE: + case EFFECT_ICON_DAMAGE_IMMUNITY_ELECTRICAL_DECREASE: + case EFFECT_ICON_DAMAGE_IMMUNITY_FIRE_DECREASE: + case EFFECT_ICON_DAMAGE_IMMUNITY_NEGATIVE_DECREASE: + case EFFECT_ICON_DAMAGE_IMMUNITY_POSITIVE_DECREASE: + case EFFECT_ICON_DAMAGE_IMMUNITY_SONIC_DECREASE: return EFFECT_TYPE_DAMAGE_IMMUNITY_DECREASE; + + //case EFFECT_ICON_INVULNERABLE: return EFFECT_TYPE_INVULNERABLE; + //case EFFECT_ICON_WOUNDING: return EFFECT_TYPE_INVALIDEFFECT; + //case EFFECT_ICON_TAUNTED: return EFFECT_TYPE_INVALIDEFFECT; + //case EFFECT_ICON_TIMESTOP: return EFFECT_TYPE_TIMESTOP; + //case EFFECT_ICON_BLINDNESS: return EFFECT_TYPE_BLINDNESS; + //case EFFECT_ICON_DISPELMAGICBEST: return EFFECT_TYPE_INVALIDEFFECT; + //case EFFECT_ICON_DISPELMAGICALL: return EFFECT_TYPE_INVALIDEFFECT; + //case EFFECT_ICON_ENEMY_ATTACK_BONUS: return EFFECT_TYPE_INVALIDEFFECT; + //case EFFECT_ICON_FATIGUE: return EFFECT_TYPE_INVALIDEFFECT; + } + return EFFECT_TYPE_INVALIDEFFECT; +} +int AbilityTypeFromEffectIconAbility(int nEffectIcon) +{ + switch (nEffectIcon) + { + case EFFECT_ICON_ABILITY_INCREASE_STR: + case EFFECT_ICON_ABILITY_DECREASE_STR: + return ABILITY_STRENGTH; + case EFFECT_ICON_ABILITY_INCREASE_DEX: + case EFFECT_ICON_ABILITY_DECREASE_DEX: + return ABILITY_DEXTERITY; + case EFFECT_ICON_ABILITY_INCREASE_CON: + case EFFECT_ICON_ABILITY_DECREASE_CON: + return ABILITY_CONSTITUTION; + case EFFECT_ICON_ABILITY_INCREASE_INT: + case EFFECT_ICON_ABILITY_DECREASE_INT: + return ABILITY_INTELLIGENCE; + case EFFECT_ICON_ABILITY_INCREASE_WIS: + case EFFECT_ICON_ABILITY_DECREASE_WIS: + return ABILITY_WISDOM; + case EFFECT_ICON_ABILITY_INCREASE_CHA: + case EFFECT_ICON_ABILITY_DECREASE_CHA: + return ABILITY_CHARISMA; + } + return -1; +} +int DamageTypeFromEffectIconDamageImmunity(int nEffectIcon) +{ + switch (nEffectIcon) + { + case EFFECT_ICON_DAMAGE_IMMUNITY_MAGIC: + case EFFECT_ICON_DAMAGE_IMMUNITY_MAGIC_DECREASE: + return DAMAGE_TYPE_MAGICAL; + case EFFECT_ICON_DAMAGE_IMMUNITY_ACID: + case EFFECT_ICON_DAMAGE_IMMUNITY_ACID_DECREASE: + return DAMAGE_TYPE_ACID; + case EFFECT_ICON_DAMAGE_IMMUNITY_COLD: + case EFFECT_ICON_DAMAGE_IMMUNITY_COLD_DECREASE: + return DAMAGE_TYPE_COLD; + case EFFECT_ICON_DAMAGE_IMMUNITY_DIVINE: + case EFFECT_ICON_DAMAGE_IMMUNITY_DIVINE_DECREASE: + return DAMAGE_TYPE_DIVINE; + case EFFECT_ICON_DAMAGE_IMMUNITY_ELECTRICAL: + case EFFECT_ICON_DAMAGE_IMMUNITY_ELECTRICAL_DECREASE: + return DAMAGE_TYPE_ELECTRICAL; + case EFFECT_ICON_DAMAGE_IMMUNITY_FIRE: + case EFFECT_ICON_DAMAGE_IMMUNITY_FIRE_DECREASE: + return DAMAGE_TYPE_FIRE; + case EFFECT_ICON_DAMAGE_IMMUNITY_NEGATIVE: + case EFFECT_ICON_DAMAGE_IMMUNITY_NEGATIVE_DECREASE: + return DAMAGE_TYPE_NEGATIVE; + case EFFECT_ICON_DAMAGE_IMMUNITY_POSITIVE: + case EFFECT_ICON_DAMAGE_IMMUNITY_POSITIVE_DECREASE: + return DAMAGE_TYPE_POSITIVE; + case EFFECT_ICON_DAMAGE_IMMUNITY_SONIC: + case EFFECT_ICON_DAMAGE_IMMUNITY_SONIC_DECREASE: + return DAMAGE_TYPE_SONIC; + } + return -1; +} + +int ImmunityTypeFromEffectIconImmunity(int nEffectIcon) +{ + switch (nEffectIcon) + { + case EFFECT_ICON_IMMUNITY_MIND: return IMMUNITY_TYPE_MIND_SPELLS; + case EFFECT_ICON_IMMUNITY_POISON: return IMMUNITY_TYPE_POISON; + case EFFECT_ICON_IMMUNITY_DISEASE: return IMMUNITY_TYPE_DISEASE; + case EFFECT_ICON_IMMUNITY_FEAR: return IMMUNITY_TYPE_FEAR; + case EFFECT_ICON_IMMUNITY_TRAP: return IMMUNITY_TYPE_TRAP; + case EFFECT_ICON_IMMUNITY_PARALYSIS: return IMMUNITY_TYPE_PARALYSIS; + case EFFECT_ICON_IMMUNITY_BLINDNESS: return IMMUNITY_TYPE_BLINDNESS; + case EFFECT_ICON_IMMUNITY_DEAFNESS: return IMMUNITY_TYPE_DEAFNESS; + case EFFECT_ICON_IMMUNITY_SLOW: return IMMUNITY_TYPE_SLOW; + case EFFECT_ICON_IMMUNITY_ENTANGLE: return IMMUNITY_TYPE_ENTANGLE; + case EFFECT_ICON_IMMUNITY_SILENCE: return IMMUNITY_TYPE_SILENCE; + case EFFECT_ICON_IMMUNITY_STUN: return IMMUNITY_TYPE_STUN; + case EFFECT_ICON_IMMUNITY_SLEEP: return IMMUNITY_TYPE_SLEEP; + case EFFECT_ICON_IMMUNITY_CHARM: return IMMUNITY_TYPE_CHARM; + case EFFECT_ICON_IMMUNITY_DOMINATE: return IMMUNITY_TYPE_DOMINATE; + case EFFECT_ICON_IMMUNITY_CONFUSE: return IMMUNITY_TYPE_CONFUSED; + case EFFECT_ICON_IMMUNITY_CURSE: return IMMUNITY_TYPE_CURSED; + case EFFECT_ICON_IMMUNITY_DAZED: return IMMUNITY_TYPE_DAZED; + case EFFECT_ICON_IMMUNITY_ABILITY_DECREASE: return IMMUNITY_TYPE_ABILITY_DECREASE; + case EFFECT_ICON_IMMUNITY_ATTACK_DECREASE: return IMMUNITY_TYPE_ATTACK_DECREASE; + case EFFECT_ICON_IMMUNITY_DAMAGE_DECREASE: return IMMUNITY_TYPE_DAMAGE_DECREASE; + case EFFECT_ICON_IMMUNITY_DAMAGE_IMMUNITY_DECREASE: return IMMUNITY_TYPE_DAMAGE_IMMUNITY_DECREASE; + case EFFECT_ICON_IMMUNITY_AC_DECREASE: return IMMUNITY_TYPE_AC_DECREASE; + case EFFECT_ICON_IMMUNITY_MOVEMENT_SPEED_DECREASE: return IMMUNITY_TYPE_MOVEMENT_SPEED_DECREASE; + case EFFECT_ICON_IMMUNITY_SAVING_THROW_DECREASE: return IMMUNITY_TYPE_SAVING_THROW_DECREASE; + case EFFECT_ICON_IMMUNITY_SPELL_RESISTANCE_DECREASE: return IMMUNITY_TYPE_SPELL_RESISTANCE_DECREASE; + case EFFECT_ICON_IMMUNITY_SKILL_DECREASE: return IMMUNITY_TYPE_SKILL_DECREASE; + case EFFECT_ICON_IMMUNITY_KNOCKDOWN: return IMMUNITY_TYPE_KNOCKDOWN; + case EFFECT_ICON_IMMUNITY_NEGATIVE_LEVEL: return IMMUNITY_TYPE_NEGATIVE_LEVEL; + case EFFECT_ICON_IMMUNITY_SNEAK_ATTACK: return IMMUNITY_TYPE_SNEAK_ATTACK; + case EFFECT_ICON_IMMUNITY_CRITICAL_HIT: return IMMUNITY_TYPE_CRITICAL_HIT; + case EFFECT_ICON_IMMUNITY_DEATH_MAGIC: return IMMUNITY_TYPE_DEATH; + } + return -1; +} +void ClearLines(object oPlayer) +{ + int nLine, nLines = GetLocalInt(oPlayer, "BUFFINFO_LAST_NUM_LINES"); + for (nLine = 1; nLine <= nLines; nLine++) + { + PostString(oPlayer, "", 10, nLine + 3, SCREEN_ANCHOR_TOP_RIGHT, 0.1f, 0xFFFFFF00, 0xFFFFFF00, nLine); + } +} +void DisplayLine(object oPlayer, int nLine, string sText, int nColor) +{ + PostString(oPlayer, sText, 10, nLine + 3, SCREEN_ANCHOR_TOP_RIGHT, 10.0f, nColor, 0xFFFFFF00, nLine); +} +string SecondsToTimestamp(int nSeconds) +{ + sqlquery sql; + if (nSeconds > 86400) sql = SqlPrepareQueryObject(GetModule(), "SELECT (@seconds / 3600) || ':' || strftime('%M:%S', @seconds / 86400.0);"); + else sql = SqlPrepareQueryObject(GetModule(), "SELECT time(@seconds, 'unixepoch');"); + SqlBindInt(sql, "@seconds", nSeconds); + SqlStep(sql); + return SqlGetString(sql, 0); +} +string Get2DAStrRef(string s2DA, string sColumn, int nRow) +{ + return GetStringByStrRef(StringToInt(Get2DAString(s2DA, sColumn, nRow))); +} +string GetVersusRacialTypeAndAlignment(int nRacialType, int nLawfulChaotic, int nGoodEvil) +{ + string sRacialType = nRacialType == RACIAL_TYPE_INVALID ? "" : Get2DAStrRef("racialtypes", "NamePlural", nRacialType); + string sLawfulChaotic = nLawfulChaotic == ALIGNMENT_LAWFUL ? "Lawful" : nLawfulChaotic == ALIGNMENT_CHAOTIC ? "Chaotic" : ""; + string sGoodEvil = nGoodEvil == ALIGNMENT_GOOD ? "Good" : nGoodEvil == ALIGNMENT_EVIL ? "Evil" : ""; + string sAlignment = sLawfulChaotic + (sLawfulChaotic == "" ? sGoodEvil : (sGoodEvil == "" ? "" : " " + sGoodEvil)); + return (sRacialType != "" || sAlignment != "") ? (" vs. " + sAlignment + (sAlignment == "" ? sRacialType : (sRacialType == "" ? "" : " " + sRacialType))) : ""; +} +string GetModifierType(int nEffectType, int nPlus, int nMinus) +{ + return nEffectType == nPlus ? "+" : nEffectType == nMinus ? "-" : ""; +} +string ACTypeToString(int nACType) +{ + switch (nACType) + { + case AC_DODGE_BONUS: return "Dodge"; + case AC_NATURAL_BONUS: return "Natural"; + case AC_ARMOUR_ENCHANTMENT_BONUS: return "Armor"; + case AC_SHIELD_ENCHANTMENT_BONUS: return "Shield"; + case AC_DEFLECTION_BONUS: return "Deflection"; + } + return ""; +} + +string SavingThrowToString(int nSavingThrow) +{ + switch (nSavingThrow) + { + case SAVING_THROW_ALL: return "All"; + case SAVING_THROW_FORT: return "Fortitude"; + case SAVING_THROW_REFLEX: return "Reflex"; + case SAVING_THROW_WILL: return "Will"; + } + return ""; +} +string SavingThrowTypeToString(int nSavingThrowType) +{ + switch (nSavingThrowType) + { + case SAVING_THROW_TYPE_MIND_SPELLS: return "Mind Spells"; + case SAVING_THROW_TYPE_POISON: return "Poison"; + case SAVING_THROW_TYPE_DISEASE: return "Disease"; + case SAVING_THROW_TYPE_FEAR: return "Fear"; + case SAVING_THROW_TYPE_SONIC: return "Sonic"; + case SAVING_THROW_TYPE_ACID: return "Acid"; + case SAVING_THROW_TYPE_FIRE: return "Fire"; + case SAVING_THROW_TYPE_ELECTRICITY: return "Electricity"; + case SAVING_THROW_TYPE_POSITIVE: return "Positive"; + case SAVING_THROW_TYPE_NEGATIVE: return "Negative"; + case SAVING_THROW_TYPE_DEATH: return "Death"; + case SAVING_THROW_TYPE_COLD: return "Cold"; + case SAVING_THROW_TYPE_DIVINE: return "Divine"; + case SAVING_THROW_TYPE_TRAP: return "Traps"; + case SAVING_THROW_TYPE_SPELL: return "Spells"; + case SAVING_THROW_TYPE_GOOD: return "Good"; + case SAVING_THROW_TYPE_EVIL: return "Evil"; + case SAVING_THROW_TYPE_LAW: return "Lawful"; + case SAVING_THROW_TYPE_CHAOS: return "Chaotic"; + } + return ""; +} +string AbilityToString(int nAbility) +{ + switch (nAbility) + { + case ABILITY_STRENGTH: return "Strength"; + case ABILITY_DEXTERITY: return "Dexterity"; + case ABILITY_CONSTITUTION: return "Constitution"; + case ABILITY_INTELLIGENCE: return "Intelligence"; + case ABILITY_WISDOM: return "Wisdom"; + case ABILITY_CHARISMA: return "Charisma"; + } + return ""; +} +string DamageTypeToString(int nDamageType) +{ + switch (nDamageType) + { + case DAMAGE_TYPE_BLUDGEONING: return "Bludgeoning"; + case DAMAGE_TYPE_PIERCING: return "Piercing"; + case DAMAGE_TYPE_SLASHING: return "Slashing"; + case DAMAGE_TYPE_MAGICAL: return "Magical"; + case DAMAGE_TYPE_ACID: return "Acid"; + case DAMAGE_TYPE_COLD: return "Cold"; + case DAMAGE_TYPE_DIVINE: return "Divine"; + case DAMAGE_TYPE_ELECTRICAL: return "Electrical"; + case DAMAGE_TYPE_FIRE: return "Fire"; + case DAMAGE_TYPE_NEGATIVE: return "Negative"; + case DAMAGE_TYPE_POSITIVE: return "Positive"; + case DAMAGE_TYPE_SONIC: return "Sonic"; + case DAMAGE_TYPE_BASE_WEAPON: return "Base Weapon"; + } + return ""; +} +string SpellSchoolToString(int nSpellSchool) +{ + switch (nSpellSchool) + { + case SPELL_SCHOOL_GENERAL: return "General"; + case SPELL_SCHOOL_ABJURATION: return "Abjuration"; + case SPELL_SCHOOL_CONJURATION: return "Conjuration"; + case SPELL_SCHOOL_DIVINATION: return "Divination"; + case SPELL_SCHOOL_ENCHANTMENT: return "Enchantment"; + case SPELL_SCHOOL_EVOCATION: return "Evocation"; + case SPELL_SCHOOL_ILLUSION: return "Illusion"; + case SPELL_SCHOOL_NECROMANCY: return "Necromancy"; + case SPELL_SCHOOL_TRANSMUTATION: return "Transmutation"; + } + return ""; +} +string MissChanceToString(int nMissChance) +{ + switch (nMissChance) + { + case MISS_CHANCE_TYPE_VS_RANGED: return "vs. Ranged"; + case MISS_CHANCE_TYPE_VS_MELEE: return "vs. Melee"; + } + return ""; +} +void ai_CreateEffectChatReport(object oPlayer, int nEffectIconID) +{ + int nIconEffectType = EffectIconToEffectType(nEffectIconID); + if(nIconEffectType == EFFECT_TYPE_INVALIDEFFECT) return; + int nLine, nIndex, nEffectIndex; + string sColor = AI_COLOR_YELLOW; + int bSkipDisplay, bHasEffect; + int nEffectType, bIsSpellLevelAbsorptionPretendingToBeSpellImmunity; + string sText; + json jEffectID = JsonArray(); + // ************************************************************************* Width / Height + // Row 1 ******************************************************************* 500 / 27 + sText = Get2DAStrRef("effecticons", "StrRef", nEffectIconID); + ai_SendMessages(sText, AI_COLOR_YELLOW, oPlayer); + effect eEffect = GetFirstEffect(oPlayer); + while(GetIsEffectValid(eEffect)) + { + bSkipDisplay = FALSE; + nEffectType = GetEffectType(eEffect); + // Unlimited EffectSpellLevelAbsorption has a SpellImmunity Icon + if (nIconEffectType == EFFECT_TYPE_SPELL_IMMUNITY && GetEffectInteger(eEffect, 3)) + { + bIsSpellLevelAbsorptionPretendingToBeSpellImmunity = TRUE; + nIconEffectType = EFFECT_TYPE_SPELLLEVELABSORPTION; + } + if (nEffectType == nIconEffectType) + { + bHasEffect = TRUE; + int nSpellID = GetEffectSpellId(eEffect); + string sSpellName = nSpellID == -1 ? "" : Get2DAStrRef("spells", "Name", nSpellID); + int bIsPermanentEffect = GetEffectDurationType(eEffect) == DURATION_TYPE_PERMANENT; + int nDurationRemaining = GetEffectDurationRemaining(eEffect); + string sDurationRemaining = bIsPermanentEffect ? "(Permanent)" : "(" + SecondsToTimestamp(nDurationRemaining) + ")"; + if(bIsPermanentEffect) sColor = AI_COLOR_WHITE; + else + { + if(nDurationRemaining < 61) sColor = AI_COLOR_RED; + else if(nDurationRemaining < 300) sColor = AI_COLOR_YELLOW; + else sColor = AI_COLOR_GREEN; + } + string sStats = ""; + string sRacialTypeAlignment = ""; + switch (nEffectType) + { + case EFFECT_TYPE_AC_INCREASE: + case EFFECT_TYPE_AC_DECREASE: + { + string sModifier = GetModifierType(nEffectType, EFFECT_TYPE_AC_INCREASE, EFFECT_TYPE_AC_DECREASE); + sStats = sModifier + IntToString(GetEffectInteger(eEffect, 1)) + " " + ACTypeToString(GetEffectInteger(eEffect, 0)) + " AC"; + sRacialTypeAlignment = GetVersusRacialTypeAndAlignment(GetEffectInteger(eEffect, 2), GetEffectInteger(eEffect, 3), GetEffectInteger(eEffect, 4)); + break; + } + case EFFECT_TYPE_ATTACK_INCREASE: + case EFFECT_TYPE_ATTACK_DECREASE: + { + string sModifier = GetModifierType(nEffectType, EFFECT_TYPE_ATTACK_INCREASE, EFFECT_TYPE_ATTACK_DECREASE); + sStats = sModifier + IntToString(GetEffectInteger(eEffect, 0)) +" AB"; + sRacialTypeAlignment = GetVersusRacialTypeAndAlignment(GetEffectInteger(eEffect, 2), GetEffectInteger(eEffect, 3), GetEffectInteger(eEffect, 4)); + break; + } + case EFFECT_TYPE_SAVING_THROW_INCREASE: + case EFFECT_TYPE_SAVING_THROW_DECREASE: + { + string sModifier = GetModifierType(nEffectType, EFFECT_TYPE_SAVING_THROW_INCREASE, EFFECT_TYPE_SAVING_THROW_DECREASE); + string sSavingThrow = SavingThrowToString(GetEffectInteger(eEffect, 1)); + string sSavingThrowType = SavingThrowTypeToString(GetEffectInteger(eEffect, 2)); + sStats = sModifier + IntToString(GetEffectInteger(eEffect, 0)) + " " + sSavingThrow + (sSavingThrowType == "" ? "" : " (vs. " + sSavingThrowType + ")"); + sRacialTypeAlignment = GetVersusRacialTypeAndAlignment(GetEffectInteger(eEffect, 3), GetEffectInteger(eEffect, 4), GetEffectInteger(eEffect, 5)); + break; + } + case EFFECT_TYPE_ABILITY_INCREASE: + case EFFECT_TYPE_ABILITY_DECREASE: + { + int nAbility = AbilityTypeFromEffectIconAbility(nEffectIconID); + + if (nAbility != GetEffectInteger(eEffect, 0)) + bSkipDisplay = TRUE; + else + { + string sModifier = GetModifierType(nEffectType, EFFECT_TYPE_ABILITY_INCREASE, EFFECT_TYPE_ABILITY_DECREASE); + sStats = sModifier + IntToString(GetEffectInteger(eEffect, 1)) + " " + AbilityToString(nAbility); + } + break; + } + case EFFECT_TYPE_DAMAGE_INCREASE: + case EFFECT_TYPE_DAMAGE_DECREASE: + { + string sModifier = GetModifierType(nEffectType, EFFECT_TYPE_DAMAGE_INCREASE, EFFECT_TYPE_DAMAGE_DECREASE); + sStats = sModifier + Get2DAStrRef("iprp_damagecost", "Name", GetEffectInteger(eEffect, 0)) + " (" + DamageTypeToString(GetEffectInteger(eEffect, 1)) + ")"; + sRacialTypeAlignment = GetVersusRacialTypeAndAlignment(GetEffectInteger(eEffect, 2), GetEffectInteger(eEffect, 3), GetEffectInteger(eEffect, 4)); + break; + } + case EFFECT_TYPE_SKILL_INCREASE: + case EFFECT_TYPE_SKILL_DECREASE: + { + int nSkill = GetEffectInteger(eEffect, 0); + string sSkill = nSkill == 255 ? "All Skills" : Get2DAStrRef("skills", "Name", nSkill); + string sModifier = GetModifierType(nEffectType, EFFECT_TYPE_SKILL_INCREASE, EFFECT_TYPE_SKILL_DECREASE); + sStats = sModifier + IntToString(GetEffectInteger(eEffect, 1)) + " " + sSkill; + sRacialTypeAlignment = GetVersusRacialTypeAndAlignment(GetEffectInteger(eEffect, 2), GetEffectInteger(eEffect, 3), GetEffectInteger(eEffect, 4)); + break; + } + case EFFECT_TYPE_TEMPORARY_HITPOINTS: + { + sStats = "+" + IntToString(GetEffectInteger(eEffect, 0)) + " HitPoints"; + break; + } + case EFFECT_TYPE_DAMAGE_REDUCTION: + { + int nAmount = GetEffectInteger(eEffect, 0); + int nDamagePower = GetEffectInteger(eEffect, 1); + nDamagePower = nDamagePower > 6 ? --nDamagePower : nDamagePower; + int nRemaining = GetEffectInteger(eEffect, 2); + sStats = IntToString(nAmount) + "/+" + IntToString(nDamagePower) + " (" + (nRemaining == 0 ? "Unlimited" : IntToString(nRemaining) + " Damage Remaining") + ")"; + break; + } + case EFFECT_TYPE_DAMAGE_RESISTANCE: + { + int nAmount = GetEffectInteger(eEffect, 1); + int nRemaining = GetEffectInteger(eEffect, 2); + sStats = IntToString(nAmount) + "/- " + DamageTypeToString(GetEffectInteger(eEffect, 0)) + " Resistance (" + (nRemaining == 0 ? "Unlimited" : IntToString(nRemaining) + " Damage Remaining") + ")"; + break; + } + case EFFECT_TYPE_IMMUNITY: + { + int nImmunity = ImmunityTypeFromEffectIconImmunity(nEffectIconID); + + if (nImmunity != GetEffectInteger(eEffect, 0)) + bSkipDisplay = TRUE; + else + { + sStats = Get2DAStrRef("effecticons", "StrRef", nEffectIconID); + sRacialTypeAlignment = GetVersusRacialTypeAndAlignment(GetEffectInteger(eEffect, 1), GetEffectInteger(eEffect, 2), GetEffectInteger(eEffect, 3)); + } + break; + } + case EFFECT_TYPE_DAMAGE_IMMUNITY_INCREASE: + case EFFECT_TYPE_DAMAGE_IMMUNITY_DECREASE: + { + int nDamageType = GetEffectInteger(eEffect, 0); + int nDamageTypeFromIcon = DamageTypeFromEffectIconDamageImmunity(nEffectIconID); + + if (nDamageTypeFromIcon != -1 && nDamageType != nDamageTypeFromIcon) + bSkipDisplay = TRUE; + + string sModifier = GetModifierType(nEffectType, EFFECT_TYPE_DAMAGE_IMMUNITY_INCREASE, EFFECT_TYPE_DAMAGE_IMMUNITY_DECREASE); + sStats = sModifier + IntToString(GetEffectInteger(eEffect, 1)) + "% " + DamageTypeToString(nDamageType) + " Damage Immunity"; + break; + } + case EFFECT_TYPE_SPELL_IMMUNITY: + { + sStats = "Spell Immunity: " + Get2DAStrRef("spells", "Name", GetEffectInteger(eEffect, 0)); + break; + } + case EFFECT_TYPE_SPELLLEVELABSORPTION: + { + int nMaxSpellLevelAbsorbed = GetEffectInteger(eEffect, 0); + int bUnlimited = GetEffectInteger(eEffect, 3); + string sSpellLevel; + switch (nMaxSpellLevelAbsorbed) + { + case 0: sSpellLevel = "Cantrip"; break; + case 1: sSpellLevel = "1st"; break; + case 2: sSpellLevel = "2nd"; break; + case 3: sSpellLevel = "3rd"; break; + default: sSpellLevel = IntToString(nMaxSpellLevelAbsorbed) + "th"; break; + } + sSpellLevel += " Level" + (nMaxSpellLevelAbsorbed == 0 ? "" : " and Below"); + string sSpellSchool = SpellSchoolToString(GetEffectInteger(eEffect, 2)); + string sRemainingSpellLevels = bUnlimited ? "" : "(" + IntToString(GetEffectInteger(eEffect, 1)) + " Spell Levels Remaining)"; + sStats = sSpellLevel + " " + sSpellSchool + " Spell Immunity " + sRemainingSpellLevels; + + if (bIsSpellLevelAbsorptionPretendingToBeSpellImmunity) + nIconEffectType = EFFECT_TYPE_SPELL_IMMUNITY; + else if (bUnlimited && !bIsSpellLevelAbsorptionPretendingToBeSpellImmunity) + bSkipDisplay = TRUE; + + break; + } + case EFFECT_TYPE_REGENERATE: + { + sStats = "+" + IntToString(GetEffectInteger(eEffect, 0)) + " HP / " + FloatToString((GetEffectInteger(eEffect, 1) / 1000.0f), 0, 2) + "s"; + break; + } + case EFFECT_TYPE_POISON: + { + sStats = "Poison: " + Get2DAStrRef("poison", "Name", GetEffectInteger(eEffect, 0)); + break; + } + case EFFECT_TYPE_DISEASE: + { + sStats = "Disease: " + Get2DAStrRef("disease", "Name", GetEffectInteger(eEffect, 0)); + break; + } + case EFFECT_TYPE_CURSE: + { + int nAbility; + string sAbilityDecrease; + for (nAbility = 0; nAbility < 6; nAbility++) + { + int nAbilityMod = GetEffectInteger(eEffect, nAbility); + if (nAbilityMod > 0) + { + string sAbility = GetStringLeft(AbilityToString(nAbility), 3); + sAbilityDecrease += "-" + IntToString(nAbilityMod) + " " + sAbility + ", "; + } + } + sAbilityDecrease = GetStringLeft(sAbilityDecrease, GetStringLength(sAbilityDecrease) - 2); + sStats = sAbilityDecrease; + break; + } + case EFFECT_TYPE_MOVEMENT_SPEED_INCREASE: + case EFFECT_TYPE_MOVEMENT_SPEED_DECREASE: + { + string sModifier = GetModifierType(nEffectType, EFFECT_TYPE_MOVEMENT_SPEED_INCREASE, EFFECT_TYPE_MOVEMENT_SPEED_DECREASE); + sStats = sModifier + IntToString(GetEffectInteger(eEffect, 0)) + "% Movement Speed"; + break; + } + case EFFECT_TYPE_ELEMENTALSHIELD: + { + sStats = IntToString(GetEffectInteger(eEffect, 0)) + " + " + Get2DAStrRef("iprp_damagecost", "Name", GetEffectInteger(eEffect, 1)) + " (" + DamageTypeToString(GetEffectInteger(eEffect, 2)) + ")"; + break; + } + case EFFECT_TYPE_NEGATIVELEVEL: + { + sStats = "-" + IntToString(GetEffectInteger(eEffect, 0)) + " Levels"; + break; + } + case EFFECT_TYPE_CONCEALMENT: + { + string sMissChance = MissChanceToString(GetEffectInteger(eEffect, 4) - 1); + sStats = IntToString(GetEffectInteger(eEffect, 0)) + "% Concealment" + (sMissChance == "" ? "" : " (" + sMissChance + ")"); + sRacialTypeAlignment = GetVersusRacialTypeAndAlignment(GetEffectInteger(eEffect, 1), GetEffectInteger(eEffect, 2), GetEffectInteger(eEffect, 3)); + break; + } + case EFFECT_TYPE_SPELL_RESISTANCE_INCREASE: + case EFFECT_TYPE_SPELL_RESISTANCE_DECREASE: + { + string sModifier = GetModifierType(nEffectType, EFFECT_TYPE_SPELL_RESISTANCE_INCREASE, EFFECT_TYPE_SPELL_RESISTANCE_DECREASE); + sStats = sModifier + IntToString(GetEffectInteger(eEffect, 0)) + " Spell Resistance"; + break; + } + case EFFECT_TYPE_SPELL_FAILURE: + { + sStats = IntToString(GetEffectInteger(eEffect, 0)) + "% Spell Failure (Spell School: " + SpellSchoolToString(GetEffectInteger(eEffect, 1)) + ")"; + break; + } + case EFFECT_TYPE_INVISIBILITY: + { + int nInvisibilityType = GetEffectInteger(eEffect, 0); + if (nEffectIconID == EFFECT_ICON_INVISIBILITY) + bSkipDisplay = nInvisibilityType != INVISIBILITY_TYPE_NORMAL; + else if (nEffectIconID == EFFECT_ICON_IMPROVEDINVISIBILITY) + bSkipDisplay = nInvisibilityType != INVISIBILITY_TYPE_IMPROVED; + if (!bSkipDisplay) + { + sStats = (nInvisibilityType == INVISIBILITY_TYPE_IMPROVED ? "Improved " : "") + "Invisibility"; + sRacialTypeAlignment = GetVersusRacialTypeAndAlignment(GetEffectInteger(eEffect, 1), GetEffectInteger(eEffect, 2), GetEffectInteger(eEffect, 3)); + } + break; + } + case EFFECT_TYPE_HASTE: + { + sStats = "Hasted"; + } + } + if(!bSkipDisplay) + { + sText = sSpellName + " " + sDurationRemaining + (sStats == "" ? "" : " -> " + sStats + sRacialTypeAlignment); + if(sText != "") + { + ai_SendMessages(sText, sColor, oPlayer); + object oSource = GetEffectCreator(eEffect); + if(GetIsObjectValid(oSource)) + { + sText = GetObjectType(oSource) ? GetName(oSource) : ""; + sText = " Creator: " + sText; + float fLength = IntToFloat(GetStringLength(sText) * 8); + ai_SendMessages(sText, AI_COLOR_YELLOW, oPlayer); + } + } + } + } + nIndex++; + eEffect = GetNextEffect(oPlayer); + } +} +void ai_CreateEffectIconMenu(object oPlayer, int nEffectIconID) +{ + int nIconEffectType = EffectIconToEffectType(nEffectIconID); + if(nIconEffectType == EFFECT_TYPE_INVALIDEFFECT) return; + int nLine, nColor, nIndex, nEffectIndex; + int bSkipDisplay, bHasEffect; + int nEffectType, bIsSpellLevelAbsorptionPretendingToBeSpellImmunity; + string sText; + json jEffectID = JsonArray(); + // ************************************************************************* Width / Height + // Row 1 ******************************************************************* 500 / 27 + sText = Get2DAStrRef("effecticons", "StrRef", nEffectIconID); + json jRow = CreateLabel(JsonArray(), "Effect: " + sText, "lbl_buff_name", 700.0f, 15.0f, NUI_HALIGN_LEFT, NUI_VALIGN_MIDDLE, 0.0); + // Add row to the column. + json jCol = JsonArrayInsert(JsonArray(), NuiRow(jRow)); + float fHeight = 27.0; + effect eEffect = GetFirstEffect(oPlayer); + while(GetIsEffectValid(eEffect)) + { + bSkipDisplay = FALSE; + nEffectType = GetEffectType(eEffect); + // Unlimited EffectSpellLevelAbsorption has a SpellImmunity Icon + if (nIconEffectType == EFFECT_TYPE_SPELL_IMMUNITY && GetEffectInteger(eEffect, 3)) + { + bIsSpellLevelAbsorptionPretendingToBeSpellImmunity = TRUE; + nIconEffectType = EFFECT_TYPE_SPELLLEVELABSORPTION; + } + if (nEffectType == nIconEffectType) + { + bHasEffect = TRUE; + int nSpellID = GetEffectSpellId(eEffect); + string sSpellName = nSpellID == -1 ? "" : Get2DAStrRef("spells", "Name", nSpellID); + int bIsPermanentEffect = GetEffectDurationType(eEffect) == DURATION_TYPE_PERMANENT; + int nDurationRemaining = GetEffectDurationRemaining(eEffect); + string sDurationRemaining = bIsPermanentEffect ? "(Permanent)" : "(" + SecondsToTimestamp(nDurationRemaining) + ")"; + if(bIsPermanentEffect) nColor = 0x0000FFFF; + else + { + float fPercentage = IntToFloat(nDurationRemaining) / IntToFloat(GetEffectDuration(eEffect)); + if(fPercentage > 0.5f) nColor = 0x00FF00FF; + else if(fPercentage < 0.25f) nColor = 0xFF0000FF; + else nColor = 0xFFFF00FF; + } + string sStats = ""; + string sRacialTypeAlignment = ""; + switch (nEffectType) + { + case EFFECT_TYPE_AC_INCREASE: + case EFFECT_TYPE_AC_DECREASE: + { + string sModifier = GetModifierType(nEffectType, EFFECT_TYPE_AC_INCREASE, EFFECT_TYPE_AC_DECREASE); + sStats = sModifier + IntToString(GetEffectInteger(eEffect, 1)) + " " + ACTypeToString(GetEffectInteger(eEffect, 0)) + " AC"; + sRacialTypeAlignment = GetVersusRacialTypeAndAlignment(GetEffectInteger(eEffect, 2), GetEffectInteger(eEffect, 3), GetEffectInteger(eEffect, 4)); + break; + } + case EFFECT_TYPE_ATTACK_INCREASE: + case EFFECT_TYPE_ATTACK_DECREASE: + { + string sModifier = GetModifierType(nEffectType, EFFECT_TYPE_ATTACK_INCREASE, EFFECT_TYPE_ATTACK_DECREASE); + sStats = sModifier + IntToString(GetEffectInteger(eEffect, 0)) +" AB"; + sRacialTypeAlignment = GetVersusRacialTypeAndAlignment(GetEffectInteger(eEffect, 2), GetEffectInteger(eEffect, 3), GetEffectInteger(eEffect, 4)); + break; + } + case EFFECT_TYPE_SAVING_THROW_INCREASE: + case EFFECT_TYPE_SAVING_THROW_DECREASE: + { + string sModifier = GetModifierType(nEffectType, EFFECT_TYPE_SAVING_THROW_INCREASE, EFFECT_TYPE_SAVING_THROW_DECREASE); + string sSavingThrow = SavingThrowToString(GetEffectInteger(eEffect, 1)); + string sSavingThrowType = SavingThrowTypeToString(GetEffectInteger(eEffect, 2)); + sStats = sModifier + IntToString(GetEffectInteger(eEffect, 0)) + " " + sSavingThrow + (sSavingThrowType == "" ? "" : " (vs. " + sSavingThrowType + ")"); + sRacialTypeAlignment = GetVersusRacialTypeAndAlignment(GetEffectInteger(eEffect, 3), GetEffectInteger(eEffect, 4), GetEffectInteger(eEffect, 5)); + break; + } + case EFFECT_TYPE_ABILITY_INCREASE: + case EFFECT_TYPE_ABILITY_DECREASE: + { + int nAbility = AbilityTypeFromEffectIconAbility(nEffectIconID); + + if (nAbility != GetEffectInteger(eEffect, 0)) + bSkipDisplay = TRUE; + else + { + string sModifier = GetModifierType(nEffectType, EFFECT_TYPE_ABILITY_INCREASE, EFFECT_TYPE_ABILITY_DECREASE); + sStats = sModifier + IntToString(GetEffectInteger(eEffect, 1)) + " " + AbilityToString(nAbility); + } + break; + } + case EFFECT_TYPE_DAMAGE_INCREASE: + case EFFECT_TYPE_DAMAGE_DECREASE: + { + string sModifier = GetModifierType(nEffectType, EFFECT_TYPE_DAMAGE_INCREASE, EFFECT_TYPE_DAMAGE_DECREASE); + sStats = sModifier + Get2DAStrRef("iprp_damagecost", "Name", GetEffectInteger(eEffect, 0)) + " (" + DamageTypeToString(GetEffectInteger(eEffect, 1)) + ")"; + sRacialTypeAlignment = GetVersusRacialTypeAndAlignment(GetEffectInteger(eEffect, 2), GetEffectInteger(eEffect, 3), GetEffectInteger(eEffect, 4)); + break; + } + case EFFECT_TYPE_SKILL_INCREASE: + case EFFECT_TYPE_SKILL_DECREASE: + { + int nSkill = GetEffectInteger(eEffect, 0); + string sSkill = nSkill == 255 ? "All Skills" : Get2DAStrRef("skills", "Name", nSkill); + string sModifier = GetModifierType(nEffectType, EFFECT_TYPE_SKILL_INCREASE, EFFECT_TYPE_SKILL_DECREASE); + sStats = sModifier + IntToString(GetEffectInteger(eEffect, 1)) + " " + sSkill; + sRacialTypeAlignment = GetVersusRacialTypeAndAlignment(GetEffectInteger(eEffect, 2), GetEffectInteger(eEffect, 3), GetEffectInteger(eEffect, 4)); + break; + } + case EFFECT_TYPE_TEMPORARY_HITPOINTS: + { + sStats = "+" + IntToString(GetEffectInteger(eEffect, 0)) + " HitPoints"; + break; + } + case EFFECT_TYPE_DAMAGE_REDUCTION: + { + int nAmount = GetEffectInteger(eEffect, 0); + int nDamagePower = GetEffectInteger(eEffect, 1); + nDamagePower = nDamagePower > 6 ? --nDamagePower : nDamagePower; + int nRemaining = GetEffectInteger(eEffect, 2); + sStats = IntToString(nAmount) + "/+" + IntToString(nDamagePower) + " (" + (nRemaining == 0 ? "Unlimited" : IntToString(nRemaining) + " Damage Remaining") + ")"; + break; + } + case EFFECT_TYPE_DAMAGE_RESISTANCE: + { + int nAmount = GetEffectInteger(eEffect, 1); + int nRemaining = GetEffectInteger(eEffect, 2); + sStats = IntToString(nAmount) + "/- " + DamageTypeToString(GetEffectInteger(eEffect, 0)) + " Resistance (" + (nRemaining == 0 ? "Unlimited" : IntToString(nRemaining) + " Damage Remaining") + ")"; + break; + } + case EFFECT_TYPE_IMMUNITY: + { + int nImmunity = ImmunityTypeFromEffectIconImmunity(nEffectIconID); + + if (nImmunity != GetEffectInteger(eEffect, 0)) + bSkipDisplay = TRUE; + else + { + sStats = Get2DAStrRef("effecticons", "StrRef", nEffectIconID); + sRacialTypeAlignment = GetVersusRacialTypeAndAlignment(GetEffectInteger(eEffect, 1), GetEffectInteger(eEffect, 2), GetEffectInteger(eEffect, 3)); + } + break; + } + case EFFECT_TYPE_DAMAGE_IMMUNITY_INCREASE: + case EFFECT_TYPE_DAMAGE_IMMUNITY_DECREASE: + { + int nDamageType = GetEffectInteger(eEffect, 0); + int nDamageTypeFromIcon = DamageTypeFromEffectIconDamageImmunity(nEffectIconID); + + if (nDamageTypeFromIcon != -1 && nDamageType != nDamageTypeFromIcon) + bSkipDisplay = TRUE; + + string sModifier = GetModifierType(nEffectType, EFFECT_TYPE_DAMAGE_IMMUNITY_INCREASE, EFFECT_TYPE_DAMAGE_IMMUNITY_DECREASE); + sStats = sModifier + IntToString(GetEffectInteger(eEffect, 1)) + "% " + DamageTypeToString(nDamageType) + " Damage Immunity"; + break; + } + case EFFECT_TYPE_SPELL_IMMUNITY: + { + sStats = "Spell Immunity: " + Get2DAStrRef("spells", "Name", GetEffectInteger(eEffect, 0)); + break; + } + case EFFECT_TYPE_SPELLLEVELABSORPTION: + { + int nMaxSpellLevelAbsorbed = GetEffectInteger(eEffect, 0); + int bUnlimited = GetEffectInteger(eEffect, 3); + string sSpellLevel; + switch (nMaxSpellLevelAbsorbed) + { + case 0: sSpellLevel = "Cantrip"; break; + case 1: sSpellLevel = "1st"; break; + case 2: sSpellLevel = "2nd"; break; + case 3: sSpellLevel = "3rd"; break; + default: sSpellLevel = IntToString(nMaxSpellLevelAbsorbed) + "th"; break; + } + sSpellLevel += " Level" + (nMaxSpellLevelAbsorbed == 0 ? "" : " and Below"); + string sSpellSchool = SpellSchoolToString(GetEffectInteger(eEffect, 2)); + string sRemainingSpellLevels = bUnlimited ? "" : "(" + IntToString(GetEffectInteger(eEffect, 1)) + " Spell Levels Remaining)"; + sStats = sSpellLevel + " " + sSpellSchool + " Spell Immunity " + sRemainingSpellLevels; + + if (bIsSpellLevelAbsorptionPretendingToBeSpellImmunity) + nIconEffectType = EFFECT_TYPE_SPELL_IMMUNITY; + else if (bUnlimited && !bIsSpellLevelAbsorptionPretendingToBeSpellImmunity) + bSkipDisplay = TRUE; + + break; + } + case EFFECT_TYPE_REGENERATE: + { + sStats = "+" + IntToString(GetEffectInteger(eEffect, 0)) + " HP / " + FloatToString((GetEffectInteger(eEffect, 1) / 1000.0f), 0, 2) + "s"; + break; + } + case EFFECT_TYPE_POISON: + { + sStats = "Poison: " + Get2DAStrRef("poison", "Name", GetEffectInteger(eEffect, 0)); + break; + } + case EFFECT_TYPE_DISEASE: + { + sStats = "Disease: " + Get2DAStrRef("disease", "Name", GetEffectInteger(eEffect, 0)); + break; + } + case EFFECT_TYPE_CURSE: + { + int nAbility; + string sAbilityDecrease; + for (nAbility = 0; nAbility < 6; nAbility++) + { + int nAbilityMod = GetEffectInteger(eEffect, nAbility); + if (nAbilityMod > 0) + { + string sAbility = GetStringLeft(AbilityToString(nAbility), 3); + sAbilityDecrease += "-" + IntToString(nAbilityMod) + " " + sAbility + ", "; + } + } + sAbilityDecrease = GetStringLeft(sAbilityDecrease, GetStringLength(sAbilityDecrease) - 2); + sStats = sAbilityDecrease; + break; + } + case EFFECT_TYPE_MOVEMENT_SPEED_INCREASE: + case EFFECT_TYPE_MOVEMENT_SPEED_DECREASE: + { + string sModifier = GetModifierType(nEffectType, EFFECT_TYPE_MOVEMENT_SPEED_INCREASE, EFFECT_TYPE_MOVEMENT_SPEED_DECREASE); + sStats = sModifier + IntToString(GetEffectInteger(eEffect, 0)) + "% Movement Speed"; + break; + } + case EFFECT_TYPE_ELEMENTALSHIELD: + { + sStats = IntToString(GetEffectInteger(eEffect, 0)) + " + " + Get2DAStrRef("iprp_damagecost", "Name", GetEffectInteger(eEffect, 1)) + " (" + DamageTypeToString(GetEffectInteger(eEffect, 2)) + ")"; + break; + } + case EFFECT_TYPE_NEGATIVELEVEL: + { + sStats = "-" + IntToString(GetEffectInteger(eEffect, 0)) + " Levels"; + break; + } + case EFFECT_TYPE_CONCEALMENT: + { + string sMissChance = MissChanceToString(GetEffectInteger(eEffect, 4) - 1); + sStats = IntToString(GetEffectInteger(eEffect, 0)) + "% Concealment" + (sMissChance == "" ? "" : " (" + sMissChance + ")"); + sRacialTypeAlignment = GetVersusRacialTypeAndAlignment(GetEffectInteger(eEffect, 1), GetEffectInteger(eEffect, 2), GetEffectInteger(eEffect, 3)); + break; + } + case EFFECT_TYPE_SPELL_RESISTANCE_INCREASE: + case EFFECT_TYPE_SPELL_RESISTANCE_DECREASE: + { + string sModifier = GetModifierType(nEffectType, EFFECT_TYPE_SPELL_RESISTANCE_INCREASE, EFFECT_TYPE_SPELL_RESISTANCE_DECREASE); + sStats = sModifier + IntToString(GetEffectInteger(eEffect, 0)) + " Spell Resistance"; + break; + } + case EFFECT_TYPE_SPELL_FAILURE: + { + sStats = IntToString(GetEffectInteger(eEffect, 0)) + "% Spell Failure (Spell School: " + SpellSchoolToString(GetEffectInteger(eEffect, 1)) + ")"; + break; + } + case EFFECT_TYPE_INVISIBILITY: + { + int nInvisibilityType = GetEffectInteger(eEffect, 0); + if (nEffectIconID == EFFECT_ICON_INVISIBILITY) + bSkipDisplay = nInvisibilityType != INVISIBILITY_TYPE_NORMAL; + else if (nEffectIconID == EFFECT_ICON_IMPROVEDINVISIBILITY) + bSkipDisplay = nInvisibilityType != INVISIBILITY_TYPE_IMPROVED; + if (!bSkipDisplay) + { + sStats = (nInvisibilityType == INVISIBILITY_TYPE_IMPROVED ? "Improved " : "") + "Invisibility"; + sRacialTypeAlignment = GetVersusRacialTypeAndAlignment(GetEffectInteger(eEffect, 1), GetEffectInteger(eEffect, 2), GetEffectInteger(eEffect, 3)); + } + break; + } + case EFFECT_TYPE_HASTE: + { + sStats = "Hasted"; + } + } + if(!bSkipDisplay) + { + sText = sSpellName + " " + sDurationRemaining + (sStats == "" ? "" : " -> " + sStats + sRacialTypeAlignment); + if(sText != "") + { + jRow = CreateLabel(JsonArray(), " " + sText, "lbl_buff_info" + IntToString(nIndex), 700.0f, 10.0f, NUI_HALIGN_LEFT, NUI_VALIGN_TOP, 0.0); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight += 10.0; + object oSource = GetEffectCreator(eEffect); + if(GetIsObjectValid(oSource)) + { + sText = GetObjectType(oSource) ? GetName(oSource) : ""; + sText = " Creator: " + sText; + float fLength = IntToFloat(GetStringLength(sText) * 8); + jRow = CreateLabel(JsonArray(), sText, "lbl_buff_source" + IntToString(nIndex), fLength, 15.0f, NUI_HALIGN_LEFT, NUI_VALIGN_BOTTOM, 0.0); + if(oSource == oPlayer) + { + CreateButton(jRow, "Remove", "btn_remove_effect_" + IntToString(nEffectIndex++), 70.0f, 20.0f, 0.0); + jEffectID = JsonArrayInsert(jEffectID, JsonString(GetEffectLinkId(eEffect))); + fHeight += 20.0; + } + else fHeight += 15.0; + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + } + } + } + } + nIndex++; + eEffect = GetNextEffect(oPlayer); + } + float fScale = IntToFloat(GetPlayerDeviceProperty(oPlayer, PLAYER_DEVICE_PROPERTY_GUI_SCALE)) / 100.0; + float fX = IntToFloat(GetPlayerDeviceProperty(oPlayer, PLAYER_DEVICE_PROPERTY_GUI_WIDTH)); + fX = fX - (700.0 * fScale); + float fY = 50 * fScale; + // Set the Layout of the window. + json jLayout = NuiCol(jCol); + int nToken = SetWindow(oPlayer, jLayout, AI_EFFECT_ICON_NUI, "Effect Icon Menu", + fX, fY, 700.0, fHeight * fScale, FALSE, FALSE, FALSE, TRUE, FALSE, "0e_nui"); + // Save the associate to the nui for use in 0e_nui + json jData = JsonArrayInsert(JsonArray(), JsonString(ObjectToString(oPlayer))); + jData = JsonArrayInsert(jData, JsonInt(nEffectIconID)); + jData = JsonArrayInsert(jData, jEffectID); + NuiSetUserData(oPlayer, nToken, jData); + NuiSetBind(oPlayer, nToken, "lbl_buff_name_event", JsonBool(TRUE)); + while(nIndex >= 0) + { + NuiSetBind(oPlayer, nToken, "lbl_buff_info" + IntToString(nIndex) + "_event", JsonBool(TRUE)); + NuiSetBind(oPlayer, nToken, "lbl_buff_source" + IntToString(nIndex) + "_event", JsonBool(TRUE)); + nIndex--; + } + while(nEffectIndex >= 0) + { + NuiSetBind(oPlayer, nToken, "btn_remove_effect_" + IntToString(nEffectIndex) + "_event", JsonBool(TRUE)); + NuiSetBind(oPlayer, nToken, "btn_remove_effect_" + IntToString(nEffectIndex), JsonInt(TRUE)); + nEffectIndex--; + } +} diff --git a/src/module/nss/0i_items.nss b/src/module/nss/0i_items.nss new file mode 100644 index 0000000..87d3ce7 --- /dev/null +++ b/src/module/nss/0i_items.nss @@ -0,0 +1,1243 @@ +/*//////////////////////////////////////////////////////////////////////////////////////////////////// +Script Name: 0i_items +Programmer: Philos +////////////////////////////////////////////////////////////////////////////////////////////////////// + Include scripts for use with items. +*///////////////////////////////////////////////////////////////////////////////////////////////////// +//#include "0i_main" +#include "0i_messages" +// Returns TRUE if oItem is a weapon. +int ai_GetIsWeapon(object oItem); +// Returns TRUE if oItem is a melee weapon. +int ai_GetIsMeleeWeapon(object oItem); +// Returns TRUE if oItem is a slashing weapon. +int ai_GetIsSlashingWeapon(object oItem); +// Returns TRUE if oItem is a piercing weapon. +int ai_GetIsPiercingWeapon(object oItem); +// Returns TRUE if oItem is a bludgeoning weapon. +int ai_GetIsBludgeoningWeapon(object oItem); +// Returns TRUE if oItem is an ammo. +int ai_GetIsAmmo(object oItem); +// Returns TRUE if oItem is a thrown weapon. +int ai_GetIsThrownWeapon(object oItem); +// Returns TRUE if oItem is able to be used single handed by oCreature. +int ai_GetIsSingleHandedWeapon(object oItem, object oCreature); +// Returns TRUE if oItem is a light weapon for oCreature. +int ai_GetIsLightWeapon(object oItem, object oCreature); +// Returns TRUE if oItem is able to be used two handed by oCreature. +int ai_GetIsTwoHandedWeapon(object oItem, object oCreature); +// Returns TRUE if oItem is a double weapon. +int ai_GetIsDoubleWeapon(object oItem); +// Returns TRUE if oCreature has a ranged weapon equiped and has ammo for it. +int ai_HasRangedWeaponWithAmmo(object oCreature); +// Returns TRUE if oItem is a ranged weapon. +int ai_GetIsRangeWeapon(object oItem); +// Returns the amount of damage the weapon oCreature is holding. +// nDamageAmount tells the function the amount of damage to return; +// 1 - Minimum, 2- Average, 3 Maximum. +// bMelee If it is not a melee weapon then return 0; +int ai_GetWeaponDamage(object oCreature, int nDamageAmount = 3, int bMelee = FALSE); +// Returns TRUE if oItem is a shield. +int ai_GetIsShield(object oItem); +// Returns the size of oItem using 1 = small to 6 = large. +int ai_GetItemSize(object oItem); +// Returns TRUE if the caller has a potion that is identified of nSpell. +int ai_CheckPotionIsIdentified(object oCreature, int nSpell); +// Returns an item from oCreature's inventory with sTag. +// bCheckEquiped will also look through the creatures equiped items. +// Returns OBJECT_INVALID if the items does not exist with sTag. +object ai_GetCreatureHasItem(object oCreature, string sTag, int bCheckEquiped = FALSE); +// Returns TRUE if oCreature can identify oItem based on the file SkillVsItemCost.2da +// Reports the findings to oPC unless oPC = OBJECT_INVALID. +// If the item can be identified by oCreature then it will be identified. +int ai_IdentifyItemVsKnowledge(object oCreature, object oItem, object oPC = OBJECT_INVALID); +// Identifies all items on oObject based on the file SkillVsItemCost.2da +// Reports the findings to oPC unless oPC = OBJECT_INVALID +// bIdentifyAll ignores the chart and does what it says! +void ai_IdentifyAllVsKnowledge(object oCreature, object oContainer, object oPC = OBJECT_INVALID); +// Will (Un)Identify all items on oCreature. +// If bIdentify is TRUE they will all be Identified, FALSE Unidentifies them. +void ai_SetIdentifyAllItems(object oCreature, int bIdentify = TRUE); +// Returns oWeapons attack bonus from either Enhancment or Attack bonus. +int ai_GetWeaponAtkBonus(object oWeapon); +// Returns oArmors armor bonus. +int ai_GetArmorBonus(object oArmor); +// Returns the maximum gold value that an item can have to be equiped. +int ai_GetMaxItemValueThatCanBeEquiped(int nLevel); +// Returns the minimum level that is required to equip this item. +int ai_GetMinimumEquipLevel(object oItem); +// Returns oCreatures total attack bonus with melee weapon (Mostly). +int ai_GetCreatureAttackBonus(object oCreature); +// Returns TRUE if oCreature can use oItem based on Class, Race, and Alignment +// restrictions. Also checks UseMagicDevice of oCreature. +int ai_CheckIfCanUseItem(object oCreature, object oItem); +// Returns TRUE if oCreature can use oItem due to feats. +int ai_GetIsProficientWith(object oCreature, object oItem); +// Gets the Average Damage on the weapon for Main and Off Hand to allow +// us to check which weapon is better for oCreature to equip. +// b2Handed set to TRUE returns only checks main avg damage. +// bOffHand set to TRUE returns the OffHand avg damage. +// if b2Handed & bOffHand are set to TRUE it returns main & offhand added together. +// if oOffWeapon is Set then it will return the Avg Damage assuming oItem is +// the Main weapon and oOffWeapon is in the Offhand. +float ai_GetMeleeWeaponAvgDmg(object oCreature, object oItem, int b2Handed = FALSE, int bOffHand = FALSE, object oOffWeapon = OBJECT_INVALID); +// Sets shield AC on the shield to allow us to check which shield is better +// for oCreature to equip. +int ai_SetShieldAC(object oCreature, object oItem); +// Returns TRUE if oItem has nItemPropertyType. +// nItemPropertySubType will not be used if its below 0. +int ai_GetHasItemProperty(object oItem, int nItemPropertyType, int nItemPropertySubType = -1); +// Returns the highest bonus Lock Picks needed to unlock nLockDC in oCreatures inventory. +object ai_GetBestPicks(object oCreature, int nLockDC); +// Removes all items from oCreature. +void ai_RemoveInventory(object oCreature); +// Copies all equiped and inventory items from oOldHenchman to oNewHenchman. +void ai_MoveInventory(object oOldHenchman, object oNewHenchman); +// Returns if oCreature is proficient with nBaseItem. +// PRC lets the creature use any weapon, but gives -4 penalty if not proficient. +int prc_IsProficient(object oCreature, int nBaseItem); + +int ai_GetIsWeapon(object oItem) +{ + int nType = GetBaseItemType(oItem); + int nWeaponType = StringToInt(Get2DAString("baseitems", "WeaponType", nType)); + if(nWeaponType) return TRUE; + return FALSE; +} +int ai_GetIsMeleeWeapon(object oItem) +{ + int nType = GetBaseItemType(oItem); + if(StringToInt(Get2DAString("baseitems", "WeaponType", nType)) > 0) + { + if(StringToInt(Get2DAString("baseitems", "RangedWeapon", nType)) == 0) return TRUE; + } + return FALSE; +} +int ai_GetIsSingleHandedWeapon(object oItem, object oCreature) +{ + if(!ai_GetIsMeleeWeapon(oItem)) return FALSE; + int nBaseItemType = GetBaseItemType(oItem); + // Weapon Size in the baseitems.2da is 1 = Tiny, 2 = Small, 3 = Medium, 4 = Large. + int nWeaponSize = StringToInt(Get2DAString("baseitems", "WeaponSize", nBaseItemType)); + // Creature size is 1 = Tiny, 2 = Small, 3 = Medium, 4 = Large. + int nCreatureSize = GetCreatureSize(oCreature); + return nWeaponSize <= nCreatureSize; +} +int ai_GetIsLightWeapon(object oItem, object oCreature) +{ + if(!ai_GetIsMeleeWeapon(oItem)) return FALSE; + int nBaseItemType = GetBaseItemType(oItem); + // Weapon Size in the baseitems.2da is 1 = Tiny, 2 = Small, 3 = Medium, 4 = Large. + int nWeaponSize = StringToInt(Get2DAString("baseitems", "WeaponSize", nBaseItemType)); + // Creature size is 1 = Tiny, 2 = Small, 3 = Medium, 4 = Large. + int nCreatureSize = GetCreatureSize(oCreature); + return nWeaponSize < nCreatureSize; +} +int ai_GetIsTwoHandedWeapon(object oItem, object oCreature) +{ + if(!ai_GetIsMeleeWeapon(oItem)) return FALSE; + int nBaseItemType = GetBaseItemType(oItem); + // Weapon Size in the baseitems.2da is 1 = Tiny, 2 = Small, 3 = Medium, 4 = Large. + int nWeaponSize = StringToInt(Get2DAString("baseitems", "WeaponSize", nBaseItemType)); + // Ranged weapons have a value greater than 0 in this field. So melee weapons have 0. + int nWeaponMelee = StringToInt(Get2DAString("baseitems", "RangedWeapon", nBaseItemType)); + // Creature size is 1 = Tiny, 2 = Small, 3 = Medium, 4 = Large. + int nCreatureSize = GetCreatureSize(oCreature); + return (nWeaponMelee == 0 && nWeaponSize > nCreatureSize); +} +int ai_GetIsDoubleWeapon(object oItem) +{ + int iType = GetBaseItemType(oItem); + switch(iType) + { + case BASE_ITEM_DIREMACE: + case BASE_ITEM_DOUBLEAXE: + case BASE_ITEM_TWOBLADEDSWORD: return TRUE; + } + return FALSE; +} +int ai_GetIsSlashingWeapon(object oItem) +{ + int iBaseItemType = GetBaseItemType(oItem); + int iWeaponType = StringToInt(Get2DAString("baseitems", "WeaponType", iBaseItemType)); + // Weapon Type in the baseitems.2da is 1 = Piercing, 2 = Bludgeoning, 3 = Slashing. + return (iWeaponType == 3); +} +int ai_GetIsPiercingWeapon(object oItem) +{ + int iBaseItemType = GetBaseItemType(oItem); + int iWeaponType = StringToInt(Get2DAString("baseitems", "WeaponType", iBaseItemType)); + // Weapon Type in the baseitems.2da is 1 = Piercing, 2 = Bludgeoning, 3 = Slashing. + return (iWeaponType == 1); +} +int ai_GetIsBludgeoningWeapon(object oItem) +{ + int iBaseItemType = GetBaseItemType(oItem); + int iWeaponType = StringToInt(Get2DAString("baseitems", "WeaponType", iBaseItemType)); + // Weapon Type in the baseitems.2da is 1 = Piercing, 2 = Bludgeoning, 3 = Slashing. + return (iWeaponType == 2); +} +int ai_GetIsAmmo(object oItem) +{ + switch(GetBaseItemType(oItem)) + { + case BASE_ITEM_ARROW: return TRUE; + case BASE_ITEM_BOLT: return TRUE; + case BASE_ITEM_BULLET: return TRUE; + } + return FALSE; +} +int ai_GetIsThrownWeapon(object oItem) +{ + switch(GetBaseItemType(oItem)) + { + case BASE_ITEM_DART: return TRUE; + case BASE_ITEM_SHURIKEN: return TRUE; + case BASE_ITEM_THROWINGAXE: return TRUE; + } + return FALSE; +} +int ai_HasRangedWeaponWithAmmo(object oCreature) +{ + object oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oCreature); + if(!GetWeaponRanged(oWeapon)) return FALSE; + int nAmmoType, nWeaponType = GetBaseItemType(oWeapon); + object oAmmo = OBJECT_INVALID; + if(nWeaponType == BASE_ITEM_LONGBOW || nWeaponType == BASE_ITEM_SHORTBOW) + { + if(ai_GetHasItemProperty(oWeapon, ITEM_PROPERTY_UNLIMITED_AMMUNITION)) return TRUE; + if(GetItemInSlot(INVENTORY_SLOT_ARROWS, oCreature) != OBJECT_INVALID) return TRUE; + nAmmoType = BASE_ITEM_ARROW; + } + else if(nWeaponType == BASE_ITEM_LIGHTCROSSBOW || nWeaponType == BASE_ITEM_HEAVYCROSSBOW) + { + if(ai_GetHasItemProperty(oWeapon, ITEM_PROPERTY_UNLIMITED_AMMUNITION)) return TRUE; + if(GetItemInSlot(INVENTORY_SLOT_BOLTS, oCreature) != OBJECT_INVALID) return TRUE; + nAmmoType = BASE_ITEM_BOLT; + } + else if(nWeaponType == BASE_ITEM_SLING) + { + if(ai_GetHasItemProperty(oWeapon, ITEM_PROPERTY_UNLIMITED_AMMUNITION)) return TRUE; + if(GetItemInSlot(INVENTORY_SLOT_BULLETS, oCreature) != OBJECT_INVALID) return TRUE; + nAmmoType = BASE_ITEM_BULLET; + } + else if(nWeaponType == BASE_ITEM_THROWINGAXE) return TRUE; + else if(nWeaponType == BASE_ITEM_SHURIKEN) return TRUE; + else if(nWeaponType == BASE_ITEM_DART) return TRUE; + // They don't have any ammo in the slot, but do they have ammo in the inventory? + oAmmo = GetFirstItemInInventory(oCreature); + while(oAmmo != OBJECT_INVALID) + { + if(GetBaseItemType(oAmmo) == nAmmoType) + { + if(nAmmoType == BASE_ITEM_ARROW) ActionEquipItem(oAmmo, INVENTORY_SLOT_ARROWS); + else if(nAmmoType == BASE_ITEM_BOLT) ActionEquipItem(oAmmo, INVENTORY_SLOT_BOLTS); + else if(nAmmoType == BASE_ITEM_BULLET) ActionEquipItem(oAmmo, INVENTORY_SLOT_BULLETS); + return TRUE; + } + oAmmo = GetNextItemInInventory(oCreature); + } + //ai_Debug("0i_items", "254", "They are out of ammo!"); + return FALSE; +} +int ai_GetIsRangeWeapon(object oItem) +{ + switch(GetBaseItemType(oItem)) + { + case BASE_ITEM_DART: return TRUE; + case BASE_ITEM_HEAVYCROSSBOW: return TRUE; + case BASE_ITEM_LIGHTCROSSBOW: return TRUE; + case BASE_ITEM_LONGBOW: return TRUE; + case BASE_ITEM_SHORTBOW: return TRUE; + case BASE_ITEM_SHURIKEN: return TRUE; + case BASE_ITEM_SLING: return TRUE; + case BASE_ITEM_THROWINGAXE: return TRUE; + } + return FALSE; +} +int ai_GetIsFinesseWeapon(object oCreature, object oItem) +{ + switch(GetBaseItemType(oItem)) + { + case BASE_ITEM_DAGGER: return TRUE; + case BASE_ITEM_HANDAXE: return TRUE; + case BASE_ITEM_KAMA: return TRUE; + case BASE_ITEM_KUKRI: return TRUE; + case BASE_ITEM_LIGHTHAMMER: return TRUE; + case BASE_ITEM_LIGHTMACE: return TRUE; + case BASE_ITEM_RAPIER: + { + if(GetCreatureSize(oCreature) > CREATURE_SIZE_SMALL) return TRUE; + return FALSE; + } + case BASE_ITEM_SHORTSWORD: return TRUE; + case BASE_ITEM_SICKLE: return TRUE; + case BASE_ITEM_WHIP: return TRUE; + } + return FALSE; +} +int ai_GetWeaponDamage(object oCreature, int nDamageAmount = 3, int bMelee = FALSE) +{ + object oItem = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oCreature); + if(bMelee && ai_GetIsRangeWeapon(oItem)) return 0; + int nWeaponDamage = GetLocalInt(oItem, "AI_WEAPON_DAMAGE"); + if(!nWeaponDamage) + { + if(ai_GetIsMeleeWeapon(oItem)) + { + nWeaponDamage = GetAbilityModifier(ABILITY_STRENGTH, oCreature); + if(ai_GetIsTwoHandedWeapon(oItem, oCreature)) nWeaponDamage += nWeaponDamage / 2; + } + int nWeaponDice = StringToInt(Get2DAString("baseitems", "NumDice", GetBaseItemType(oItem))); + int nWeaponDie = StringToInt(Get2DAString("baseitems", "DieToRoll", GetBaseItemType(oItem))); + if(nDamageAmount == 1) + { + nWeaponDamage += nWeaponDice; + } + else if(nDamageAmount == 2) + { + nWeaponDamage += nWeaponDice * nWeaponDie / 2; + } + else + { + nWeaponDamage += nWeaponDice * nWeaponDie; + } + SetLocalInt(oItem, "AI_WEAPON_DAMAGE", nWeaponDamage); + } + return nWeaponDamage; +} +int ai_GetIsShield(object oItem) +{ + switch(GetBaseItemType(oItem)) + { + case BASE_ITEM_SMALLSHIELD: return TRUE; + case BASE_ITEM_LARGESHIELD: return TRUE; + case BASE_ITEM_TOWERSHIELD: return TRUE; + } + return FALSE; + } +int ai_GetItemSize(object oItem) +{ + int nBaseItemType = GetBaseItemType(oItem); + int nWidth = StringToInt(Get2DAString("baseitems", "InvSlotWidth", nBaseItemType)); + int nHeight = StringToInt(Get2DAString("baseitems", "InvSlotHeight", nBaseItemType)); + return nWidth + nHeight - 1; +} +int ai_CheckPotionIsIdentified(object oCreature, int nSpell) +{ + int nPotionSpell; + itemproperty ipPotion; + object oPotion = GetFirstItemInInventory(oCreature); + while(oPotion != OBJECT_INVALID) + { + if(GetIdentified(oPotion)) + { + ipPotion = GetFirstItemProperty(oPotion); + nPotionSpell = GetItemPropertySubType(ipPotion); + nPotionSpell = StringToInt(Get2DAString("iprp_spells", "SpellIndex", nPotionSpell)); + //ai_Debug("0i_talents", "318", "Potion ID'ed? nSpell: " + IntToString(nSpell) + " nPotionSpell: " + IntToString(nPotionSpell)); + if(nSpell == nPotionSpell) return TRUE; + } + oPotion = GetNextItemInInventory(oCreature); + } + return FALSE; +} +object ai_GetCreatureHasItem(object oCreature, string sTag, int bCheckEquiped = FALSE) +{ + // Cycle through the creatures unequiped items. + object oItem = GetFirstItemInInventory(oCreature); + while(oItem != OBJECT_INVALID) + { + if(GetTag(oItem) == sTag) return oItem; + oItem = GetNextItemInInventory(oCreature); + } + // Should we check the creatures equiped items. + // If we have already found it then stop looking. + int nSlot = 0; + if(bCheckEquiped) + { + // Check all of the creatures slots(0 - 17). + while(nSlot <= 17) + { + oItem = GetItemInSlot(nSlot, oCreature); + if(GetTag(oItem) == sTag) return oItem; + nSlot ++; + } + } + return OBJECT_INVALID; +} +int ai_IdentifyItemVsKnowledge(object oCreature, object oItem, object oPC = OBJECT_INVALID) +{ + if(GetIdentified(oItem)) return FALSE; + int nKnowledge = GetSkillRank(SKILL_LORE, oCreature); + int nItemValue; // gold value of item + string sBaseName; + string sMaxValue = Get2DAString("SkillVsItemCost", "DeviceCostMax", nKnowledge); + int nMaxValue = StringToInt(sMaxValue); + // * Handle overflow(November 2003 - BK) + if(sMaxValue == "") nMaxValue = 0; + // Setting TRUE to get the true value of the item. + SetIdentified(oItem, TRUE); + nItemValue = GetGoldPieceValue(oItem); + if(nMaxValue <= nItemValue) + { + SetIdentified(oItem, FALSE); + if(oPC != OBJECT_INVALID) + { + sBaseName = GetStringByStrRef(StringToInt(Get2DAString("baseitems", "name", GetBaseItemType(oItem)))); + ai_SendMessages(GetName(oCreature) + " cannot identify " + sBaseName, AI_COLOR_RED, oPC); + } + } + else + { + if(oPC != OBJECT_INVALID) ai_SendMessages(GetName(oCreature) + " has identified " + GetName(oItem), AI_COLOR_GREEN, oPC); + return TRUE; + } + return FALSE; +} +void ai_IdentifyAllVsKnowledge(object oCreature, object oContainer, object oPC = OBJECT_INVALID) +{ + // SkillVsItemCost 2da starts 1 at 0 ... go figure! + int nKnowledge = GetSkillRank(SKILL_LORE, oCreature) - 1; + int nItemValue; // gold value of item + string sBaseName; + string sMaxValue = Get2DAString("SkillVsItemCost", "DeviceCostMax", nKnowledge); + int nMaxValue = StringToInt(sMaxValue); + // * Handle overflow(November 2003 - BK) + if(sMaxValue == "") nMaxValue = 0; + object oItem = GetFirstItemInInventory(oContainer); + while(oItem != OBJECT_INVALID) + { + if(!GetIdentified(oItem)) + { + // setting TRUE to get the true value of the item. + SetIdentified(oItem, TRUE); + nItemValue = GetGoldPieceValue(oItem); + if(nMaxValue < nItemValue) + { + SetIdentified(oItem, FALSE); + sBaseName = GetStringByStrRef(StringToInt(Get2DAString("baseitems", "name", GetBaseItemType(oItem)))); + if(oPC != OBJECT_INVALID) ai_SendMessages(GetName(oCreature) + " cannot identify " + sBaseName, AI_COLOR_RED, oPC); + } + else if(oPC != OBJECT_INVALID) ai_SendMessages(GetName(oCreature) + " has identified " + GetName(oItem), AI_COLOR_GREEN, oPC); + } + oItem = GetNextItemInInventory(oContainer); + } +} +void ai_SetIdentifyAllItems(object oCreature, int bIdentify = TRUE) +{ + object oItem = GetFirstItemInInventory(oCreature); + while(oItem != OBJECT_INVALID) + { + if(!GetIdentified(oItem)) SetIdentified(oItem, bIdentify); + oItem = GetNextItemInInventory(oCreature); + } + int nSlot; + oItem = GetItemInSlot(nSlot, oCreature); + while(nSlot < 11) + { + if(!GetIdentified(oItem)) SetIdentified(oItem, bIdentify); + oItem = GetItemInSlot(++nSlot, oCreature); + } +} +int ai_GetWeaponAtkBonus(object oWeapon) +{ + int nCounter = 1, nPropertyType, nBonus; + // Get first property + itemproperty ipProperty = GetFirstItemProperty(oWeapon); + while(GetIsItemPropertyValid(ipProperty)) + { + // Check to see if the property type matches. + nPropertyType = GetItemPropertyType(ipProperty); + if(nPropertyType == 6/*ITEMPROPERTY_ENHANCEMENT*/ || + nPropertyType == 56/*ITEMPROPERTY_ATTACKBONUS*/) + { + nBonus += GetItemPropertyCostTableValue(ipProperty); + } + // Get the next property. + ipProperty = GetNextItemProperty(oWeapon); + } + //ai_Debug("0i_items", "438", GetName(oWeapon) + " attack bonus is " + IntToString(nBonus)); + return nBonus; +} +int ai_GetArmorBonus(object oArmor) +{ + int nTorsoValue = GetItemAppearance(oArmor, ITEM_APPR_TYPE_ARMOR_MODEL, ITEM_APPR_ARMOR_MODEL_TORSO); + //ai_Debug("0i_items", "444", "Armor Bonus: " + Get2DAString("parts_chest.2da", "ACBONUS", nTorsoValue)); + return StringToInt(Get2DAString("parts_chest", "ACBONUS", nTorsoValue)); +} +int ai_GetMaxItemValueThatCanBeEquiped(int nLevel) +{ + return StringToInt(Get2DAString("itemvalue", "MAXSINGLEITEMVALUE", nLevel - 1)); +} +int ai_GetMinimumEquipLevel(object oItem) +{ + int nIndex, nUnIdentified; + if(!GetIdentified(oItem)) + { + nUnIdentified = TRUE; + SetIdentified(oItem, TRUE); + } + int nGoldValue = GetGoldPieceValue(oItem); + if(nUnIdentified) SetIdentified(oItem, FALSE); + int n2daMaxRow = Get2DARowCount("itemvalue"); + while(nIndex < n2daMaxRow) + { + if(nGoldValue <= StringToInt(Get2DAString("itemvalue", "MAXSINGLEITEMVALUE", nIndex))) + { + return nIndex + 1; + } + nIndex++; + } + return nIndex; +} +int ai_GetCreatureAttackBonus(object oCreature) +{ + object oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oCreature); + int nAtkBonus = GetBaseAttackBonus(oCreature); + if((GetHasFeat(FEAT_WEAPON_FINESSE, oCreature) && ai_GetIsFinesseWeapon(oCreature, oWeapon)) || + ai_GetIsRangeWeapon(oWeapon)) + { + nAtkBonus += GetAbilityModifier(ABILITY_DEXTERITY, oCreature); + } + else nAtkBonus += GetAbilityModifier(ABILITY_STRENGTH, oCreature); + if(ai_GetIsMeleeWeapon(oWeapon)) nAtkBonus += ai_GetWeaponAtkBonus(oWeapon); + return nAtkBonus; + } +int ai_CheckUseMagicDevice(object oCreature, string sColumn, object oItem) +{ + if(!GetLocalInt(GetModule(), AI_RULE_ALLOW_UMD)) return FALSE; + int nUMD = GetSkillRank(SKILL_USE_MAGIC_DEVICE, oCreature); + //ai_Debug("0i_talents", "1600", GetName(oCreature) + " is check UMD: " + IntToString(nUMD)); + if(nUMD < 1) return FALSE; + int nDC, nIndex, nItemValue = GetGoldPieceValue(oItem); + while(nIndex < 55) + { + //ai_Debug("0i_talents", "1605", GetName(oItem) + " has a value of " + + // Get2DAString("skillvsitemcost", "DeviceCostMax", nIndex) + + // " nIndex: " + IntToString(nIndex)); + if(nItemValue < StringToInt(Get2DAString("skillvsitemcost", "DeviceCostMax", nIndex))) + { + //ai_Debug("0i_talents", "1610", "nUMD >= " + Get2DAString("skillvsitemcost", sColumn, nIndex)); + if(nUMD >= StringToInt(Get2DAString("skillvsitemcost", sColumn, nIndex))) return TRUE; + return FALSE; + } + nIndex++; + } + return FALSE; +} +int ai_CheckIfCanUseItem(object oCreature, object oItem) +{ + int bAlign, bClass, bRace, bAlignLimit, bClassLimit, bRaceLimit; + int nIprpSubType, nItemPropertyType; + // Check to see if this item is limited to a specific alignment, class, or race. + int nAlign1 = GetAlignmentLawChaos(oCreature); + int nAlign2 = GetAlignmentGoodEvil(oCreature); + int nRace = GetRacialType(oCreature); + //ai_Debug("0i_items", "615", "nAlign1: " + IntToString(nAlign1) + + // " nAlign2: " + IntToString(nAlign2) + " nRace: " + IntToString(nRace)); + itemproperty ipProp = GetFirstItemProperty(oItem); + while(GetIsItemPropertyValid(ipProp)) + { + nItemPropertyType = GetItemPropertyType(ipProp); + //ai_Debug("0i_items", "620", "ItempropertyType(62/63/64/65): " + IntToString(nItemPropertyType)); + if(nItemPropertyType == ITEM_PROPERTY_USE_LIMITATION_ALIGNMENT_GROUP) + { + bAlignLimit = TRUE; + // SubType is the group index for iprp_aligngrp.2da + nIprpSubType = GetItemPropertySubType(ipProp); + //ai_Debug("0i_items", "626", "nIprpSubType: " + IntToString(nIprpSubType)); + if(nIprpSubType == nAlign1 || nIprpSubType == nAlign2) bAlign = TRUE; + } + else if(nItemPropertyType == ITEM_PROPERTY_USE_LIMITATION_SPECIFIC_ALIGNMENT) + { + bAlignLimit = TRUE; + // SubType is the alignment index for iprp_alignment.2da + nIprpSubType = GetItemPropertySubType(ipProp); + //ai_Debug("0i_items", "634", "nIprpSubType: " + IntToString(nIprpSubType)); + if(nIprpSubType == 0 && nAlign1 == 2 && nAlign2 == 4) bAlign = TRUE; + else if(nIprpSubType == 1 && nAlign1 == 2 && nAlign2 == 1) bAlign = TRUE; + else if(nIprpSubType == 2 && nAlign1 == 2 && nAlign2 == 5) bAlign = TRUE; + else if(nIprpSubType == 3 && nAlign1 == 1 && nAlign2 == 4) bAlign = TRUE; + else if(nIprpSubType == 4 && nAlign1 == 1 && nAlign2 == 1) bAlign = TRUE; + else if(nIprpSubType == 5 && nAlign1 == 1 && nAlign2 == 5) bAlign = TRUE; + else if(nIprpSubType == 6 && nAlign1 == 3 && nAlign2 == 4) bAlign = TRUE; + else if(nIprpSubType == 7 && nAlign1 == 3 && nAlign2 == 1) bAlign = TRUE; + else if(nIprpSubType == 8 && nAlign1 == 3 && nAlign2 == 5) bAlign = TRUE; + } + else if(nItemPropertyType == ITEM_PROPERTY_USE_LIMITATION_CLASS) + { + bClassLimit = TRUE; + // SubType is the class index for classes.2da + nIprpSubType = GetItemPropertySubType(ipProp); + //ai_Debug("0i_items", "650", "nIprpSubType: " + IntToString(nIprpSubType)); + int nClassPosition = 1; + int nClass = GetClassByPosition(nClassPosition, oCreature); + while(nClassPosition <= AI_MAX_CLASSES_PER_CHARACTER) + { + if(nIprpSubType == nClass) bClass = TRUE; + nClass = GetClassByPosition(++nClassPosition, oCreature); + } + } + else if(nItemPropertyType == ITEM_PROPERTY_USE_LIMITATION_RACIAL_TYPE) + { + bRaceLimit = TRUE; + // SubType is the race index for racialtypes.2da + nIprpSubType = GetItemPropertySubType(ipProp); + //ai_Debug("0i_items", "664", "nIprpSubType: " + IntToString(nIprpSubType)); + if(nIprpSubType == nRace) bRace = TRUE; + } + ipProp = GetNextItemProperty(oItem); + } + //ai_Debug("0i_items", "669", "bAlignLimit: " + IntToString(bAlignLimit) + " bAlign: " + IntToString(bAlign) + + // " bClassLimit: " + IntToString(bClassLimit) + " bClass: " + IntToString(bClass) + + // " bRaceLimit: " + IntToString(bRaceLimit) + " bRace: " + IntToString(bRace)); + if(bClassLimit && !bClass && !ai_CheckUseMagicDevice(oCreature, "SkillReq_Class", oItem)) return FALSE; + if(bRaceLimit && !bRace && !ai_CheckUseMagicDevice(oCreature, "SkillReq_Race", oItem)) return FALSE; + if(bAlignLimit && !bAlign && !ai_CheckUseMagicDevice(oCreature, "SkillReq_Align", oItem)) return FALSE; + return TRUE; +} +int ai_GetIsProficientWith(object oCreature, object oItem) +{ + int nWeaponType = GetBaseItemType(oItem); + // In the PRC you can equip any weapon. + if(GetLocalInt(GetModule(), AI_USING_PRC)) return TRUE; + int nFeat = StringToInt(Get2DAString("baseitems", "ReqFeat0", nWeaponType)); + // If it is 0 then it doesn't require a feat or we are at the end of the + // feat requirements. + if(nFeat == 0) return TRUE; + if(GetHasFeat(nFeat, oCreature)) return TRUE; + nFeat = StringToInt(Get2DAString("baseitems", "ReqFeat1", nWeaponType)); + if(nFeat == 0) return FALSE; + if(GetHasFeat(nFeat, oCreature)) return TRUE; + nFeat = StringToInt(Get2DAString("baseitems", "ReqFeat2", nWeaponType)); + if(nFeat == 0) return FALSE; + if(GetHasFeat(nFeat, oCreature)) return TRUE; + nFeat = StringToInt(Get2DAString("baseitems", "ReqFeat3", nWeaponType)); + if(nFeat == 0) return FALSE; + if(GetHasFeat(nFeat, oCreature)) return TRUE; + nFeat = StringToInt(Get2DAString("baseitems", "ReqFeat4", nWeaponType)); + if(nFeat == 0) return FALSE; + if(GetHasFeat(nFeat, oCreature)) return TRUE; + return FALSE; +} +float ai_GetMeleeWeaponAvgDmg(object oCreature, object oItem, int b2Handed = FALSE, int bOffHand = FALSE, object oOffWeapon = OBJECT_INVALID) +{ + // Has this weapon already been calculated for this creature? + if(oCreature == GetLocalObject(oItem, "AI_CREATURE_POSSESSION")) + { + // Return the Main weapons Avg Damage while using a weapon in the off hand. + if(oOffWeapon != OBJECT_INVALID) + { + // We recalculate all OffWeapon avg damage unless its a double weapon. + if(oOffWeapon == oItem) + { + float fMain2WDmg = GetLocalFloat(oItem, "AI_MAIN_2W_HAND_AVG_DMG"); + // If they passed that this is a 2handed weapon then return the total + // Avg Dmg for oItem. Used for double weapons. + if(b2Handed) + { + fMain2WDmg += ai_GetMeleeWeaponAvgDmg(oCreature, oItem, FALSE, TRUE); + } + if(AI_DEBUG) ai_Debug("0i_items", "611", GetName(oItem) + " avg dmg with Offhand weapon (" + GetName(oOffWeapon) + ") " + FloatToString(fMain2WDmg, 0, 2)); + return fMain2WDmg; + } + } + // Return the avg dmg for oItem assuming it is in the OffHand. + else if(bOffHand) + { + float fOffHandDmg = GetLocalFloat(oItem, "AI_OFFHAND_AVG_DMG"); + if(AI_DEBUG) ai_Debug("0i_items", "618", GetName(oItem) + " fOffHandAvgDmg: " + FloatToString(fOffHandDmg, 0, 2)); + return fOffHandDmg; + } + // If we get here then Return the avg dmg for oItem assuming its in the main hand. + else + { + float fMainDmg = GetLocalFloat(oItem, "AI_AVG_DMG"); + if(AI_DEBUG)ai_Debug("0i_items", "623", GetName(oItem) + " fMainDmg: " + FloatToString(fMainDmg, 0, 2)); + return fMainDmg; + } + } + // Set the creature to this item that we are calculationg the avg damages for. + SetLocalObject(oItem, "AI_CREATURE_POSSESSION", oCreature); + int nItemType = GetBaseItemType(oItem); + // Figure average damage for one attack, or two with two weapons. + // We are keeping it simple to reduce time and checks. + // Get the weapons base stats. + int nMinDmg = StringToInt(Get2DAString("baseitems", "NumDice", nItemType)); + int nMaxDmg = nMinDmg * StringToInt(Get2DAString("baseitems", "DieToRoll", nItemType)); + int nThreat = StringToInt(Get2DAString("baseitems", "CritThreat", nItemType)); + int nMultiplier = StringToInt(Get2DAString("baseitems", "CritHitMult", nItemType)); + int nIndex, nBonusMinDmg, nBonusMaxDmg, nItemPropertyType, nNumDice; + // We set ToHit to 10 for a 50% chance to hit without modifiers. + float fCritBonusDmg, fToHit = 10.0; + if(GetLocalInt(GetModule(), AI_USING_PRC)) + { + if(!prc_IsProficient(oCreature, nItemType)) fToHit -= 4.0; + } + // Check oCreature's feats. + if(GetHasFeat(FEAT_WEAPON_FINESSE, oCreature) && + ai_GetIsLightWeapon(oItem, oCreature)) + { + // Add Dexterity modifier to the Attack bonus. + nIndex = GetAbilityModifier(ABILITY_DEXTERITY, oCreature); + } + else + { + // Add Strength modifier to the attack bonus. + nIndex = GetAbilityModifier(ABILITY_STRENGTH, oCreature); + // Add 1/2 strength modifier to damage for 2handed weapons, but not Double weapons. + if(b2Handed && !bOffHand) + { + nMinDmg += nIndex / 2; + nMaxDmg += nIndex / 2; + } + } + fToHit += nIndex; + if(GetHasFeat(StringToInt(Get2DAString("baseitems", "WeaponFocusFeat", nItemType)), oCreature, TRUE)) + { + fToHit += 1.0; + if(GetHasFeat(StringToInt(Get2DAString("baseitems", "WeaponSpecializationFeat", nItemType)), oCreature, TRUE)) + { + nMinDmg += 2; + nMaxDmg += 2; + } + if(GetHasFeat(StringToInt(Get2DAString("baseitems", "EpicWeaponFocusFeat", nItemType)), oCreature, TRUE)) + { + fToHit += 2.0; + if(GetHasFeat(StringToInt(Get2DAString("baseitems", "EpicWeaponSpecializationFeat", nItemType)), oCreature, TRUE)) + { + nMinDmg += 4; + nMaxDmg += 4; + } + } + } + if(GetHasFeat(StringToInt(Get2DAString("baseitems", "WeaponImprovedCriticalFeat", nItemType)), oCreature, TRUE)) + { + nMultiplier += nMultiplier; + if(GetHasFeat(StringToInt(Get2DAString("baseitems", "EpicWeaponOverwhelmingCriticalFeat", nItemType)), oCreature, TRUE)) + { + if(nMultiplier > 3) fCritBonusDmg = 10.5; + else if(nMultiplier == 3) fCritBonusDmg = 7.0; + else fCritBonusDmg = 3.5; + } + } + // Check oItem's properties. + itemproperty ipProperty = GetFirstItemProperty(oItem); + while(GetIsItemPropertyValid(ipProperty)) + { + nItemPropertyType = GetItemPropertyType(ipProperty); + if(nItemPropertyType == ITEM_PROPERTY_ENHANCEMENT_BONUS) + { + nIndex = GetItemPropertyCostTableValue(ipProperty); + nBonusMinDmg += nIndex; + nBonusMaxDmg += nIndex; + fToHit += IntToFloat(nIndex); + } + else if(nItemPropertyType == ITEM_PROPERTY_DAMAGE_BONUS) + { + nIndex = GetItemPropertyCostTableValue(ipProperty); + nNumDice = StringToInt(Get2DAString("iprp_damagecost", "NumDice", nIndex)); + nBonusMinDmg += nNumDice; + nBonusMaxDmg += nNumDice * StringToInt(Get2DAString("iprp_damagecost", "Die", nIndex)); + } + else if(nItemPropertyType == ITEM_PROPERTY_ATTACK_BONUS) + { + nIndex = GetItemPropertyCostTableValue(ipProperty); + fToHit += IntToFloat(nIndex); + } + else if(nItemPropertyType == ITEM_PROPERTY_KEEN) + { + nIndex = GetItemPropertyCostTableValue(ipProperty); + nMultiplier += nMultiplier; + } + else if(nItemPropertyType == ITEM_PROPERTY_HASTE) + { + nIndex = GetItemPropertyCostTableValue(ipProperty); + nMinDmg += nMinDmg; + nMaxDmg += nMaxDmg; + nBonusMinDmg += nBonusMinDmg; + nBonusMaxDmg += nBonusMaxDmg; + nMultiplier += nMultiplier; + } + else if(nItemPropertyType == ITEM_PROPERTY_MASSIVE_CRITICALS) + { + nIndex = GetItemPropertyCostTableValue(ipProperty); + nNumDice = StringToInt(Get2DAString("iprp_damagecost", "NumDice", nIndex)); + fCritBonusDmg += IntToFloat(nNumDice) + IntToFloat(nNumDice * StringToInt(Get2DAString("iprp_damagecost", "Die", nIndex))) / 2.0; + } + else if(nItemPropertyType == ITEM_PROPERTY_DECREASED_ENHANCEMENT_MODIFIER) + { + nIndex = GetItemPropertyCostTableValue(ipProperty); + nBonusMinDmg -= nIndex; + nBonusMaxDmg -= nIndex; + fToHit -= IntToFloat(nIndex); + } + else if(nItemPropertyType == ITEM_PROPERTY_DECREASED_ATTACK_MODIFIER) + { + nIndex = GetItemPropertyCostTableValue(ipProperty); + fToHit -= IntToFloat(nIndex); + } + else if(nItemPropertyType == ITEM_PROPERTY_DECREASED_DAMAGE) + { + nIndex = GetItemPropertyCostTableValue(ipProperty); + nBonusMinDmg -= nIndex; + nBonusMaxDmg -= nIndex; + } + else if(nItemPropertyType == ITEM_PROPERTY_NO_DAMAGE) + { + // A weapon always does a minimum of 1 pnt of damage. + nMinDmg = 1; + nMaxDmg = 1; + } + ipProperty = GetNextItemProperty(oItem); + } + float fAvgDmg = IntToFloat(nMinDmg + nMaxDmg + nBonusMinDmg + nBonusMaxDmg) / 2; + // Set value for Offhand chance to hit. + float fOffHandToHit = fToHit - 10.0; + float fOffHandAvgDmg = fAvgDmg; + // Set value for Main hand chance to hit with a weapon in Off hand. + float fMain2HandToHit = fToHit - 6.0; + float fMain2HandAvgDmg = fAvgDmg; + // Calculate the avg dmg for oItem used in the main hand with no Off hand weapon. + fToHit = fToHit / 20.0; + float fThreatChance = (IntToFloat(nThreat) / 20.0) * fToHit; + fAvgDmg = (fAvgDmg * fToHit) + ((fAvgDmg * IntToFloat(nMultiplier) + fCritBonusDmg) * fThreatChance); + SetLocalFloat(oItem, "AI_AVG_DMG", fAvgDmg); + if(AI_DEBUG) ai_Debug("0i_items", "768", GetName(oItem) + " fSingleAvgDmg: " + FloatToString(fAvgDmg, 0, 2)); + if(!b2Handed || (b2Handed && oOffWeapon != OBJECT_INVALID)) + { + // Calculate chance to hit based on two weapon feats and main hand vs off hand. + if(GetHasFeat(374/*Dual_Wield*/, oCreature)) + { + if(ai_GetArmorBonus(GetItemInSlot(INVENTORY_SLOT_CHEST, oCreature)) < 4) + { + fMain2HandToHit += 2.0; + fOffHandToHit += 6.0; + } + } + else + { + if(GetHasFeat(FEAT_AMBIDEXTERITY, oCreature)) fOffHandToHit += 4.0; + if(GetHasFeat(FEAT_TWO_WEAPON_FIGHTING, oCreature)) + { + fMain2HandToHit += 2.0; + fOffHandToHit += 2.0; + } + } + if(ai_GetIsLightWeapon(oItem, oCreature)) fOffHandToHit += 2.0; + if(oOffWeapon != OBJECT_INVALID && + (ai_GetIsLightWeapon(oOffWeapon, oCreature) || ai_GetIsDoubleWeapon(oItem))) + { + fMain2HandToHit += 2.0; + } + // Calculate the avg dmg for oItem used in the main hand with an off hand weapon. + fMain2HandToHit = fMain2HandToHit / 20.0; + fThreatChance = (IntToFloat(nThreat) / 20.0) * fMain2HandToHit; + fMain2HandAvgDmg = (fMain2HandAvgDmg * fMain2HandToHit) + ((fMain2HandAvgDmg * IntToFloat(nMultiplier) + fCritBonusDmg) * fThreatChance); + SetLocalFloat(oItem, "AI_MAIN_2W_HAND_AVG_DMG", fMain2HandAvgDmg); + if(AI_DEBUG) ai_Debug("0i_items", "768", GetName(oItem) + " fMain2HandAvgDmg: " + FloatToString(fMain2HandAvgDmg, 0, 2)); + // Calculate the avg dmg for oItem used in the off hand. + fOffHandToHit = fOffHandToHit / 20.0; + fThreatChance = (IntToFloat(nThreat) / 20.0) * fOffHandToHit; + fOffHandAvgDmg = (fOffHandAvgDmg * fOffHandToHit) + ((fOffHandAvgDmg * IntToFloat(nMultiplier) + fCritBonusDmg) * fThreatChance); + SetLocalFloat(oItem, "AI_OFFHAND_AVG_DMG", fOffHandAvgDmg); + if(AI_DEBUG) ai_Debug("0i_items", "790", GetName(oItem) + " fOffHandAvgDmg: " + FloatToString(fOffHandAvgDmg, 0, 2)); + // Return the correct value based on params passed. + if(oOffWeapon != OBJECT_INVALID) + { + // This is used only for double weapons! Must pass b2Handed = TRUE and + // oOffWeapon = the double weapon that was passes as oItem. + if(b2Handed) return fMain2HandAvgDmg + fOffHandAvgDmg; + return fMain2HandAvgDmg; + } + if(bOffHand) return fOffHandAvgDmg; + } + return fAvgDmg; +} +int ai_SetShieldAC(object oCreature, object oItem) +{ + if(oCreature == GetLocalObject(oItem, "AI_CREATURE_POSSESSION")) + { + return GetLocalInt(oItem, "AI_SHIELD_AC"); + } + // Set the creature who has this item for setting the power of. + SetLocalObject(oItem, "AI_CREATURE_POSSESSION", oCreature); + int nItemType = GetBaseItemType(oItem); + int nAC, nItemPropertyType; + if(nItemType == BASE_ITEM_SMALLSHIELD) nAC = 1; + else if(nItemType == BASE_ITEM_LARGESHIELD) nAC = 2; + else if(nItemType == BASE_ITEM_TOWERSHIELD) nAC = 3; + itemproperty ipProperty = GetFirstItemProperty(oItem); + while(GetIsItemPropertyValid(ipProperty)) + { + nItemPropertyType = GetItemPropertyType(ipProperty); + if(nItemPropertyType == ITEM_PROPERTY_AC_BONUS) + { + nAC += GetItemPropertyCostTableValue(ipProperty); + } + else if(nItemPropertyType == ITEM_PROPERTY_DECREASED_AC) + { + nAC -= GetItemPropertyCostTableValue(ipProperty); + } + else if(nItemPropertyType == ITEM_PROPERTY_HASTE) + { + nAC += 4; + } + ipProperty = GetNextItemProperty(oItem); + } + SetLocalInt(oItem, "AI_SHIELD_AC", nAC); + if(AI_DEBUG) ai_Debug("0i_items", "718", GetName(oItem) + " nAC: " + IntToString(nAC)); + return nAC; +} +int ai_GetHasItemProperty(object oItem, int nItemPropertyType, int nItemPropertySubType = -1) +{ + itemproperty ipProperty = GetFirstItemProperty(oItem); + while(GetIsItemPropertyValid(ipProperty)) + { + if(GetItemPropertyType(ipProperty) == nItemPropertyType) + { + if(nItemPropertySubType > -1) + { + if(GetItemPropertySubType(ipProperty) == nItemPropertySubType) return TRUE; + } + else return TRUE; + } + ipProperty = GetNextItemProperty(oItem); + } + return FALSE; +} +object ai_GetBestPicks(object oCreature, int nLockDC) +{ + int nSkill = GetSkillRank(SKILL_OPEN_LOCK, oCreature); + int nBonus, nBestBonus = 99, nNeededBonus = nLockDC - nSkill - 20; + //ai_Debug("0i_items", "651", "nNeededBonus: " + IntToString(nNeededBonus)); + // We don't need to use any picks! + if(nNeededBonus < 1) return OBJECT_INVALID; + object oBestItem = OBJECT_INVALID; + object oItem = GetFirstItemInInventory(oCreature); + while(oItem != OBJECT_INVALID) + { + if(GetBaseItemType(oItem) == BASE_ITEM_THIEVESTOOLS) + { + // Get the tools bonus. + itemproperty ipProperty = GetFirstItemProperty(oItem); + while(GetIsItemPropertyValid(ipProperty)) + { + if(GetItemPropertyType(ipProperty) == ITEM_PROPERTY_THIEVES_TOOLS) + { + nBonus = GetItemPropertyCostTableValue(ipProperty); + if(nBonus >= nNeededBonus && nBonus < nBestBonus) + { + nBestBonus = nBonus; + oBestItem = oItem; + SetLocalInt(oBestItem, "AI_BONUS", nBestBonus); + break; + } + } + ipProperty = GetNextItemProperty(oItem); + } + } + oItem = GetNextItemInInventory(oCreature); + } + return oBestItem; +} +void ai_RemoveInventory(object oCreature) +{ + object oItem = GetFirstItemInInventory(oCreature); + while(oItem != OBJECT_INVALID) + { + DestroyObject(oItem); + oItem = GetNextItemInInventory(oCreature); + } + int nIndex; + for(nIndex = 0; nIndex <= 13; nIndex++) + { + oItem = GetItemInSlot(nIndex, oCreature); + DestroyObject(oItem); + } +} +void ai_MoveInventory(object oOldHenchman, object oNewHenchman) +{ + // Move all inventory items. + object oItem = GetFirstItemInInventory(oOldHenchman); + while(oItem != OBJECT_INVALID) + { + CopyItem(oItem, oNewHenchman, TRUE); + oItem = GetNextItemInInventory(oOldHenchman); + } + // Move all equiped items and equip on oNewHenchman. + int nIndex; + object oNewItem; + for(nIndex = 0; nIndex <= 13; nIndex++) + { + oItem = GetItemInSlot(nIndex, oOldHenchman); + if(oItem != OBJECT_INVALID) + { + oNewItem = CopyItem(oItem, oNewHenchman, TRUE); + if(!GetIdentified(oNewItem)) SetIdentified(oNewItem, TRUE); + ActionEquipItem(oNewItem, nIndex); + } + } +} +int prc_IsProficient(object oCreature, int nBaseItem) +{ + switch(nBaseItem) + { + //special case: counts as simple for chitine + case BASE_ITEM_SHORTSWORD: + return GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_ROGUE, oCreature) + || GetHasFeat(3600/*FEAT_MINDBLADE*/, oCreature) + || (GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oCreature) + && GetRacialType(oCreature) == 76/*RACIAL_TYPE_CHITINE*/) + || GetHasFeat(7901/*FEAT_WEAPON_PROFICIENCY_SHORTSWORD*/, oCreature); + + case BASE_ITEM_LONGSWORD: + return GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature) + || GetHasFeat(3600/*FEAT_MINDBLADE*/, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_ELF, oCreature) + || GetHasFeat(7902/*FEAT_WEAPON_PROFICIENCY_LONGSWORD*/, oCreature); + + case BASE_ITEM_BATTLEAXE: + return GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature) + || (GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oCreature) + && GetRacialType(oCreature) == 216/*RACIAL_TYPE_GNOLL*/) + || GetHasFeat(7903/*FEAT_WEAPON_PROFICIENCY_BATTLEAXE*/, oCreature); + + case BASE_ITEM_BASTARDSWORD: + return GetHasFeat(FEAT_WEAPON_PROFICIENCY_EXOTIC, oCreature) + || GetHasFeat(3600/*FEAT_MINDBLADE*/, oCreature) + || GetHasFeat(7904/*FEAT_WEAPON_PROFICIENCY_BASTARD_SWORD*/, oCreature); + + case BASE_ITEM_LIGHTFLAIL: + return GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature) + || GetHasFeat(7905/*FEAT_WEAPON_PROFICIENCY_LIGHT_FLAIL*/, oCreature); + + case BASE_ITEM_WARHAMMER: + return GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature) + || GetHasFeat(7906/*FEAT_WEAPON_PROFICIENCY_WARHAMMER*/, oCreature); + + case BASE_ITEM_LONGBOW: + return GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_ELF, oCreature) + || GetHasFeat(7907/*FEAT_WEAPON_PROFICIENCY_LONGBOW*/, oCreature); + + case BASE_ITEM_LIGHTMACE: + return GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_ROGUE, oCreature) + || GetHasFeat(7908/*FEAT_WEAPON_PROFICIENCY_LIGHT_MACE*/, oCreature); + + case BASE_ITEM_HALBERD: + return GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature) + || GetHasFeat(7909/*FEAT_WEAPON_PROFICIENCY_HALBERD*/, oCreature); + + case BASE_ITEM_SHORTBOW: + return GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_ROGUE, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_ELF, oCreature) + || (GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oCreature) + && GetRacialType(oCreature) == 216/*RACIAL_TYPE_GNOLL*/) + || GetHasFeat(7910/*FEAT_WEAPON_PROFICIENCY_SHORTBOW*/, oCreature); + + case BASE_ITEM_TWOBLADEDSWORD: + return GetHasFeat(FEAT_WEAPON_PROFICIENCY_EXOTIC, oCreature) + || GetHasFeat(7911/*FEAT_WEAPON_PROFICIENCY_TWO_BLADED_SWORD*/, oCreature); + + case BASE_ITEM_GREATSWORD: + return GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature) + || GetHasFeat(7912/*FEAT_WEAPON_PROFICIENCY_GREATSWORD*/, oCreature); + + case BASE_ITEM_GREATAXE: + return GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature) + || GetHasFeat(7913/*FEAT_WEAPON_PROFICIENCY_GREATAXE*/, oCreature); + + case BASE_ITEM_DART: + return GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_ROGUE, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_DRUID, oCreature) + || GetHasFeat(7914/*FEAT_WEAPON_PROFICIENCY_DART*/, oCreature); + + case BASE_ITEM_DIREMACE: + return GetHasFeat(7915/*FEAT_WEAPON_PROFICIENCY_DIRE_MACE*/, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_EXOTIC, oCreature); + + case BASE_ITEM_DOUBLEAXE: + return GetHasFeat(7916/*FEAT_WEAPON_PROFICIENCY_DOUBLE_AXE*/, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_EXOTIC, oCreature); + + case BASE_ITEM_HEAVYFLAIL: + return GetHasFeat(7917/*FEAT_WEAPON_PROFICIENCY_HEAVY_FLAIL*/, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature); + + case BASE_ITEM_LIGHTHAMMER: + return GetHasFeat(7918/*FEAT_WEAPON_PROFICIENCY_LIGHT_HAMMER*/, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature); + + case BASE_ITEM_HANDAXE: + return GetHasFeat(7919/*FEAT_WEAPON_PROFICIENCY_HANDAXE*/, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_ROGUE, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_MONK, oCreature); + + case BASE_ITEM_KAMA: + return GetHasFeat(7920/*FEAT_WEAPON_PROFICIENCY_KAMA*/, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_MONK, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_EXOTIC, oCreature); + + case BASE_ITEM_KATANA: + return GetHasFeat(7921/*FEAT_WEAPON_PROFICIENCY_KATANA*/, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_EXOTIC, oCreature); + + case BASE_ITEM_KUKRI: + return GetHasFeat(7922/*FEAT_WEAPON_PROFICIENCY_KUKRI*/, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_EXOTIC, oCreature); + + case BASE_ITEM_MORNINGSTAR: + return GetHasFeat(7923/*FEAT_WEAPON_PROFICIENCY_MORNINGSTAR*/, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_ROGUE, oCreature); + + case BASE_ITEM_QUARTERSTAFF: + return GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_DRUID, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_WIZARD, oCreature); + + case BASE_ITEM_RAPIER: + return GetHasFeat(7924/*FEAT_WEAPON_PROFICIENCY_RAPIER*/, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_ROGUE, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_ELF, oCreature); + + case BASE_ITEM_SCIMITAR: + return GetHasFeat(7925/*FEAT_WEAPON_PROFICIENCY_SCIMITAR*/, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_DRUID, oCreature); + + case BASE_ITEM_SCYTHE: + return GetHasFeat(7926/*FEAT_WEAPON_PROFICIENCY_SCYTHE*/, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature); + + case BASE_ITEM_SHORTSPEAR: + return GetHasFeat(7927/*FEAT_WEAPON_PROFICIENCY_SHORTSPEAR*/, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_DRUID, oCreature); + + case BASE_ITEM_SHURIKEN: + return GetHasFeat(7928/*FEAT_WEAPON_PROFICIENCY_SHURIKEN*/, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_EXOTIC, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_MONK, oCreature); + + case BASE_ITEM_SICKLE: + return GetHasFeat(7929/*FEAT_WEAPON_PROFICIENCY_SICKLE*/, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_DRUID, oCreature); + + case BASE_ITEM_SLING: + return GetHasFeat(7930/*FEAT_WEAPON_PROFICIENCY_SLING*/, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_ROGUE, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_MONK, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_DRUID, oCreature); + + case BASE_ITEM_THROWINGAXE: + return GetHasFeat(7931/*FEAT_WEAPON_PROFICIENCY_THROWING_AXE*/, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature) + || GetHasFeat(3600/*FEAT_MINDBLADE*/, oCreature); + + case BASE_ITEM_CSLASHWEAPON: + case BASE_ITEM_CPIERCWEAPON: + case BASE_ITEM_CBLUDGWEAPON: + case BASE_ITEM_CSLSHPRCWEAP: + return GetHasFeat(FEAT_WEAPON_PROFICIENCY_CREATURE, oCreature); + + case BASE_ITEM_TRIDENT: + return GetHasFeat(7932/*FEAT_WEAPON_PROFICIENCY_TRIDENT*/, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_DRUID, oCreature); + + case 124://BASE_ITEM_DOUBLE_SCIMITAR: + return GetHasFeat(7948/*FEAT_WEAPON_PROFICIENCY_DOUBLE_SCIMITAR*/, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_EXOTIC, oCreature); + + case 119://BASE_ITEM_FALCHION: + return GetHasFeat(7943/*FEAT_WEAPON_PROFICIENCY_FALCHION*/, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature); + + case 125://BASE_ITEM_GOAD: + return GetHasFeat(7949/*FEAT_WEAPON_PROFICIENCY_GOAD*/, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oCreature); + + case 122://BASE_ITEM_HEAVY_MACE: + return GetHasFeat(7946/*FEAT_WEAPON_PROFICIENCY_HEAVY_MACE*/, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oCreature); + + case 115://BASE_ITEM_HEAVY_PICK: + return GetHasFeat(7939/*FEAT_WEAPON_PROFICIENCY_HEAVY_PICK*/, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature); + + case 116://BASE_ITEM_LIGHT_PICK: + return GetHasFeat(7940/*FEAT_WEAPON_PROFICIENCY_LIGHT_PICK*/, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature); + + case 121://BASE_ITEM_KATAR: + return GetHasFeat(7945/*FEAT_WEAPON_PROFICIENCY_KATAR*/, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_EXOTIC, oCreature); + + case 123://BASE_ITEM_MAUL: + return GetHasFeat(7947/*FEAT_WEAPON_PROFICIENCY_MAUL*/, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature); + + case 118://BASE_ITEM_NUNCHAKU: + return GetHasFeat(7942/*FEAT_WEAPON_PROFICIENCY_NUNCHAKU*/, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_MONK, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_EXOTIC, oCreature); + + case 117://BASE_ITEM_SAI: + return GetHasFeat(7941/*FEAT_WEAPON_PROFICIENCY_SAI*/, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_MONK, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_EXOTIC, oCreature); + + case 120://BASE_ITEM_SAP: + return GetHasFeat(7944/*FEAT_WEAPON_PROFICIENCY_SAP*/, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_ROGUE, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature); + + //special case: counts as martial for dwarves + case BASE_ITEM_DWARVENWARAXE: + return GetHasFeat(7933/*FEAT_WEAPON_PROFICIENCY_DWARVEN_WARAXE*/, oCreature) + || (GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature) + && GetHasFeat(4710/*FEAT_DWARVEN*/, oCreature)) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_EXOTIC, oCreature); + + case BASE_ITEM_WHIP: + return GetHasFeat(7934/*FEAT_WEAPON_PROFICIENCY_WHIP*/, oCreature) + || GetHasFeat(FEAT_WEAPON_PROFICIENCY_EXOTIC, oCreature); + } + return TRUE; +} +int ai_GetItemUses(object oItem, int nItemPropertySubType) +{ + int nUses; + itemproperty ipProperty = GetFirstItemProperty(oItem); + while(GetIsItemPropertyValid(ipProperty)) + { + if(GetItemPropertyType(ipProperty) == ITEM_PROPERTY_HEALERS_KIT) return GetItemStackSize(oItem); + if(nItemPropertySubType > -1) + { + if(GetItemPropertySubType(ipProperty) == nItemPropertySubType) + { + // Get how they use the item (charges or uses per day). + nUses = GetItemPropertyCostTableValue(ipProperty); + if(nUses == 1) return GetItemStackSize(oItem); + else if(nUses > 1 && nUses < 7) return GetItemCharges(oItem); + else if(nUses == 7 || nUses == 13) return 999; + else if(nUses > 7 && nUses < 13) return GetItemPropertyUsesPerDayRemaining(oItem, ipProperty); + } + } + else return TRUE; + ipProperty = GetNextItemProperty(oItem); + } + return FALSE; +} + diff --git a/src/module/nss/0i_main.nss b/src/module/nss/0i_main.nss new file mode 100644 index 0000000..a0a4674 --- /dev/null +++ b/src/module/nss/0i_main.nss @@ -0,0 +1,1328 @@ +/*////////////////////////////////////////////////////////////////////////////// +// Script Name: 0i_main +//////////////////////////////////////////////////////////////////////////////// + Include script for handling main/basic functions not defined by other includes. + + Database structure: Json with indexes. + name (string) - The associatetype to link the data. "pc", "familiar", etc. + modes (jsonarray) - 0-aimodes (int), 1-magicmodes (int) + buttons (jsonarray) - 0-widgetbuttons (int), 1-aibuttons (int) + aidata (jsonarray) - 0-difficulty (int), 1-healoutcombat (int), 2-healincombat (int), + 3-lootrange (float), 4-lockrange (float), 5-traprange (float), + 6-Follow range (float). + lootfilters (jsonarray) - 0-maxweight (int), 1-lootfilters (int), + Item filters in min gold json array; 2-plot, 3-armor, 4-belts, 5-boots, + 6-cloaks, 7-gems, 8-gloves, 9-headgear, 10-jewelry, 11-misc, 12-potions, + 13-scrolls, 14-shields, 15-wands, 16-weapons, 17-arrow, 18-bolt, 19-bullet. + plugins (jsonarray) - 0+ (string). * Only used in the "pc" data. + location (jsonobject) - geometry (json), used in widgets for pc and associates. +*/////////////////////////////////////////////////////////////////////////////// +const string AI_TABLE = "PEPS_TABLE"; +const string AI_CAMPAIGN_DATABASE = "peps_database"; +const string AI_DM_TABLE = "DM_TABLE"; +#include "0i_constants" +#include "0i_messages" +// Sets PEPS RULES from the database to the module. +// Creates default rules if they do not exist. +void ai_SetAIRules(); +// Returns TRUE if oCreature is controlled by a player. +int ai_GetIsCharacter(object oCreature); +// Returns TRUE if oCreature is controlled by a dungeon master. +int ai_GetIsDungeonMaster(object oCreature); +// Returns the Player of oAssociate even if oAssociate is the player. +// If there is no player associated with oAssociate then it returns OBJECT_INVALID. +object ai_GetPlayerMaster(object oAssociate); +// Returns the percentage of hit points oCreature has left. +int ai_GetPercHPLoss(object oCreature); +// Returns a rolled result from sDice string. +// Example: "1d6" will be 1-6 or "3d6" will be 3-18 or 1d6+5 will be 6-11. +int ai_RollDiceString(string sDice); +// Returns the int number of a encoded 0x00000000 hex number from a string. +int ai_HexStringToInt(string sString); +// Returns cosine of the angle between oObject1 and oObject2 +float ai_GetCosAngleBetween(object oObject1, object oObject2); +// Returns a string from sString with only characters in sLegal. +// Used to remove illegal characters for databases. +string ai_RemoveIllegalCharacters(string sString, string sLegal = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"); +// Returns the total levels of oCreature. +int ai_GetCharacterLevels(object oCreature); +// Returns a string where sFind is replaced in any occurrence of sSource with sReplace. +string ai_StringReplaceText(string sSource, string sFind, string sReplace); +// Returns a string of characters between the nIndex of predefined markers of +// sSeperator in sText. +// nIndex is the number of the data we are searching for in the array. +// A 0 nIndex is the first item in the text array. +// sSeperator is the character that seperates the array(Usefull for Multiple arrays). +string ai_GetStringArray(string sText, int nIndex, string sSeperator = ":"); +// Returns a string of characters between the nIndex of predefined markers of +// sSeperator in sText where sField has been set. +// sText is the text holding the array. +// nIndex is the array number in the data we are searching for. +// A 0 nIndex is the first item in the text array. +// sField is the field of characters to replace that index. +// sSeperator is the character that seperates the array(Usefull for Multiple arrays). +string ai_SetStringArray(string sText, int nIndex, string sField, string sSeperator = ":"); +// Returns the number of magical properties oItem has. +int ai_GetNumberOfProperties(object oItem); +// Checks if the campaign database table has been created and initialized. +void ai_CheckCampaignDataAndInitialize(); +// Checks if the dm database table and data has been created and initialized of oDM. +void ai_CheckDMDataAndInitialize(object oDM); +// Sets json to a campaign database. +void ai_SetCampaignDbJson(string sDataField, json jData, string sName = "PEPS_DATA", string sTable = AI_TABLE); +// Gets json from a campaign database. +json ai_GetCampaignDbJson(string sDataField, string sName = "PEPS_DATA", string sTable = AI_TABLE); +// Checks if oMaster has the Table created for Associate data. +// If no table found then the table is created and then initialized. +void ai_CheckAssociateDataAndInitialize(object oPlayer, string sAssociateType); +// Returns the associatetype int string format for oAssociate. +// They are pc, familar, companion, summons, henchman is the henchmans tag +string ai_GetAssociateType(object oPlayer, object oAssociate); +// Sets nData to sDataField for sAssociateType that is on oPlayer. +// sDataField can be modes, magicmodes, lootmodes, widgetbuttons, aibuttons, magic, +// healoutcombat, healincombat, mingold*. +void ai_SetAssociateDbInt(object oPlayer, string sAssociateType, string sDataField, int nData, string sTable = AI_TABLE); +// Returns nData from sDataField for sAssociateType that is on oPlayer. +// sDataField can be modes, magicmodes, lootmodes, widgetbuttons, aibuttons, magic, +// healoutcombat, healincombat, mingold*. +int ai_GetAssociateDbInt(object oPlayer, string sAssociateType, string sDataField, string sTable = AI_TABLE); +// Sets fData to sDataField for sAssociateType that is on oPlayer. +// sDataField can be lootrange, lockrange, traprange. +void ai_SetAssociateDbFloat(object oPlayer, string sAssociatetype, string sDataField, float fData, string sTable = AI_TABLE); +// Returns fData from sDataField for sAssociateType that is on oPlayer. +// sDataField can be lootrange, lockrange, traprange. +float ai_GetAssociateDbFloat(object oPlayer, string sAssociateType, string sDataField, string sTable = AI_TABLE); +// sDataField should be one of the data fields for that table. +// jData is the json data to be saved. +void ai_SetAssociateDbJson(object oPlayer, string sAssociateType, string sDataField, json jData, string sTable = AI_TABLE); +// sDataField should be one of the data fields for the table. +// Returns a string of the data stored. +json ai_GetAssociateDbJson(object oPlayer, string sAssociateType, string sDataField, string sTable = AI_TABLE); +// Saves Associate AIModes and MagicModes to the database. +void aiSaveAssociateModesToDb(object oPlayer, object oAssociate); +// Checks Associate local data and if none is found will initialize or load the +// correct data for oAssociate. +void ai_CheckAssociateData(object oPlayer, object oAssociate, string sAssociateType, int bLoad = FALSE); +// Checks DM's local data and if none is found will initizlize or load the +// correct data for oPlayer. +void ai_CheckDMData(object oPlayer); +// Adds to jPlugins functions after checking if the plugin can be installed. +json ai_Plugin_Add(object oPC, json jPlugins, string sPluginScript); +// Updates the players Plugin list and saves to the database. +json ai_UpdatePluginsForPC(object oPC); +// Updates the DM's Plugin list and saves to the database. +json ai_UpdatePluginsForDM (object oPC); +// Runs all plugins that are loaded into the database. +void ai_StartupPlugins(object oPC); +void ai_SetAIRules() +{ + object oModule = GetModule(); + ai_CheckCampaignDataAndInitialize(); + json jRules = ai_GetCampaignDbJson("rules"); + if(JsonGetType(JsonObjectGet(jRules, AI_RULE_MORAL_CHECKS)) == JSON_TYPE_NULL) + { + jRules = JsonObject(); + // Variable name set to a creatures full name to set debugging on. + jRules = JsonObjectSet(jRules, AI_RULE_DEBUG_CREATURE, JsonString("")); + // Moral checks on or off. + SetLocalInt(oModule, AI_RULE_MORAL_CHECKS, AI_MORAL_CHECKS); + jRules = JsonObjectSet(jRules, AI_RULE_MORAL_CHECKS, JsonInt(AI_MORAL_CHECKS)); + // Allows monsters to prebuff before combat starts. + SetLocalInt(oModule, AI_RULE_BUFF_MONSTERS, AI_PREBUFF); + jRules = JsonObjectSet(jRules, AI_RULE_BUFF_MONSTERS, JsonInt(AI_PREBUFF)); + // Allows monsters cast summons spells when prebuffing. + SetLocalInt(oModule, AI_RULE_PRESUMMON, AI_PRESUMMONS); + jRules = JsonObjectSet(jRules, AI_RULE_PRESUMMON, JsonInt(AI_PRESUMMONS)); + // Allows monsters to use tactical AI scripts. + SetLocalInt(oModule, AI_RULE_AMBUSH, AI_TACTICAL); + jRules = JsonObjectSet(jRules, AI_RULE_AMBUSH, JsonInt(AI_TACTICAL)); + // Enemies may summon familiars and Animal companions and will be randomized. + SetLocalInt(oModule, AI_RULE_SUMMON_COMPANIONS, AI_SUMMON_COMPANIONS); + jRules = JsonObjectSet(jRules, AI_RULE_SUMMON_COMPANIONS, JsonInt(AI_SUMMON_COMPANIONS)); + // Allow the AI to move during combat base on the situation and action taking. + SetLocalInt(oModule, AI_RULE_ADVANCED_MOVEMENT, AI_ADVANCED_MOVEMENT); + jRules = JsonObjectSet(jRules, AI_RULE_ADVANCED_MOVEMENT, JsonInt(AI_ADVANCED_MOVEMENT)); + // Follow Item Level Restrictions for monsters/associates. + SetLocalInt(oModule, AI_RULE_ILR, AI_ITEM_LEVEL_RESTRICTIONS); + jRules = JsonObjectSet(jRules, AI_RULE_ILR, JsonInt(AI_ITEM_LEVEL_RESTRICTIONS)); + // Allow the AI to use Use Magic Device. + SetLocalInt(oModule, AI_RULE_ALLOW_UMD, AI_USE_MAGIC_DEVICE); + jRules = JsonObjectSet(jRules, AI_RULE_ALLOW_UMD, JsonInt(AI_USE_MAGIC_DEVICE)); + // Allow the AI to use healing kits. + SetLocalInt(oModule, AI_RULE_HEALERSKITS, AI_HEALING_KITS); + jRules = JsonObjectSet(jRules, AI_RULE_HEALERSKITS, JsonInt(AI_HEALING_KITS)); + // Associates are permanent and don't get removed when the master dies. + SetLocalInt(oModule, AI_RULE_PERM_ASSOC, AI_COMPANIONS_PERMANENT); + jRules = JsonObjectSet(jRules, AI_RULE_PERM_ASSOC, JsonInt(AI_COMPANIONS_PERMANENT)); + // Monster AI's chance to attack the weakest target instead of the nearest. + SetLocalInt(oModule, AI_RULE_AI_DIFFICULTY, AI_TARGET_WEAKEST); + jRules = JsonObjectSet(jRules, AI_RULE_AI_DIFFICULTY, JsonInt(AI_TARGET_WEAKEST)); + // Monster AI's distance they can search for the enemy. + SetLocalFloat(oModule, AI_RULE_PERCEPTION_DISTANCE, AI_SEARCH_DISTANCE); + jRules = JsonObjectSet(jRules, AI_RULE_PERCEPTION_DISTANCE, JsonFloat(AI_SEARCH_DISTANCE)); + // Enemy corpses remain on the floor instead of dissappearing. + SetLocalInt(oModule, AI_RULE_CORPSES_STAY, AI_CORPSE_REMAIN); + jRules = JsonObjectSet(jRules, AI_RULE_CORPSES_STAY, JsonInt(AI_CORPSE_REMAIN)); + // Monsters will wander around when not in combat. + SetLocalInt(oModule, AI_RULE_WANDER, AI_WANDER); + jRules = JsonObjectSet(jRules, AI_RULE_WANDER, JsonInt(AI_WANDER)); + // Increase the number of encounter creatures. + SetLocalFloat(oModule, AI_INCREASE_ENC_MONSTERS, 0.0); + jRules = JsonObjectSet(jRules, AI_INCREASE_ENC_MONSTERS, JsonFloat(0.0)); + // Increase all monsters hitpoints by this percentage. + SetLocalInt(oModule, AI_INCREASE_MONSTERS_HP, 0); + jRules = JsonObjectSet(jRules, AI_INCREASE_MONSTERS_HP, JsonInt(0)); + // Monster's perception distance. + SetLocalInt(oModule, AI_RULE_MON_PERC_DISTANCE, AI_MONSTER_PERCEPTION); + jRules = JsonObjectSet(jRules, AI_RULE_MON_PERC_DISTANCE, JsonInt(AI_MONSTER_PERCEPTION)); + // Variable name set to hold the maximum number of henchman the player wants. + int nMaxHenchmen = GetMaxHenchmen(); + SetLocalInt(oModule, AI_RULE_MAX_HENCHMAN, nMaxHenchmen); + jRules = JsonObjectSet(jRules, AI_RULE_MAX_HENCHMAN, JsonInt(nMaxHenchmen)); + // Monster AI's distance they can wander away from their spawn point. + SetLocalFloat(oModule, AI_RULE_WANDER_DISTANCE, AI_WANDER_DISTANCE); + jRules = JsonObjectSet(jRules, AI_RULE_WANDER_DISTANCE, JsonFloat(AI_WANDER_DISTANCE)); + // Monsters will open doors when wandering around and not in combat. + SetLocalInt(oModule, AI_RULE_OPEN_DOORS, AI_WANDER); + jRules = JsonObjectSet(jRules, AI_RULE_OPEN_DOORS, JsonInt(AI_OPEN_DOORS)); + // If the modules default XP has not been set then we do it here. + int nDefaultXP = GetLocalInt(oModule, AI_RULE_DEFAULT_XP_SCALE); + if(nDefaultXP == 0) + { + int nValue = GetModuleXPScale(); + if(nValue != 0) SetLocalInt(oModule, AI_RULE_DEFAULT_XP_SCALE, nValue); + } + // Variable name set to allow the game to regulate experience based on party size. + SetLocalInt(oModule, AI_RULE_PARTY_SCALE, AI_PARTY_SCALE); + jRules = JsonObjectSet(jRules, AI_RULE_PARTY_SCALE, JsonInt(AI_PARTY_SCALE)); + SetLocalJson(oModule, AI_RULE_RESTRICTED_SPELLS, JsonArray()); + jRules = JsonObjectSet(jRules, AI_RULE_RESTRICTED_SPELLS, JsonArray()); + // Variable name set to allow access to widget buttons for the players. + SetLocalInt(oModule, sDMWidgetAccessVarname, AI_DM_WIDGET_ACCESS_BUTTONS); + jRules = JsonObjectSet(jRules, sDMWidgetAccessVarname, JsonInt(AI_DM_WIDGET_ACCESS_BUTTONS)); + // Variable name set to allow access to widget buttons for the players. + SetLocalInt(oModule, sDMAIAccessVarname, AI_DM_AI_ACCESS_BUTTONS); + jRules = JsonObjectSet(jRules, sDMAIAccessVarname, JsonInt(AI_DM_AI_ACCESS_BUTTONS)); + ai_SetCampaignDbJson("rules", jRules); + } + else + { + // Variable name set to a creatures full name to set debugging on. + string sValue = JsonGetString(JsonObjectGet(jRules, AI_RULE_DEBUG_CREATURE)); + SetLocalString(oModule, AI_RULE_DEBUG_CREATURE, sValue); + // Moral checks on or off. + int bValue = JsonGetInt(JsonObjectGet(jRules, AI_RULE_MORAL_CHECKS)); + SetLocalInt(oModule, AI_RULE_MORAL_CHECKS, bValue); + // Allows monsters to prebuff before combat starts. + bValue = JsonGetInt(JsonObjectGet(jRules, AI_RULE_BUFF_MONSTERS)); + SetLocalInt(oModule, AI_RULE_BUFF_MONSTERS, bValue); + // Allows monsters cast summons spells when prebuffing. + bValue = JsonGetInt(JsonObjectGet(jRules, AI_RULE_PRESUMMON)); + SetLocalInt(oModule, AI_RULE_PRESUMMON, bValue); + // Allows monsters to use ambush AI scripts. + bValue = JsonGetInt(JsonObjectGet(jRules, AI_RULE_AMBUSH)); + SetLocalInt(oModule, AI_RULE_AMBUSH, bValue); + // Enemies may summon familiars and Animal companions and will be randomized. + bValue = JsonGetInt(JsonObjectGet(jRules, AI_RULE_SUMMON_COMPANIONS)); + SetLocalInt(oModule, AI_RULE_SUMMON_COMPANIONS, bValue); + // Allow the AI to move during combat base on the situation and action taking. + bValue = JsonGetInt(JsonObjectGet(jRules, AI_RULE_ADVANCED_MOVEMENT)); + SetLocalInt(oModule, AI_RULE_ADVANCED_MOVEMENT, bValue); + // Follow Item Level Restrictions for monsters/associates. + bValue = JsonGetInt(JsonObjectGet(jRules, AI_RULE_ILR)); + SetLocalInt(oModule, AI_RULE_ILR, bValue); + // Allow the AI to use Use Magic Device. + bValue = JsonGetInt(JsonObjectGet(jRules, AI_RULE_ALLOW_UMD)); + SetLocalInt(oModule, AI_RULE_ALLOW_UMD, bValue); + // Allow the AI to use healing kits. + bValue = JsonGetInt(JsonObjectGet(jRules, AI_RULE_HEALERSKITS)); + SetLocalInt(oModule, AI_RULE_HEALERSKITS, bValue); + // Associates are permanent and don't get removed when the owner dies. + bValue = JsonGetInt(JsonObjectGet(jRules, AI_RULE_PERM_ASSOC)); + SetLocalInt(oModule, AI_RULE_PERM_ASSOC, bValue); + // Monster AI's chance to attack the weakest target instead of the nearest. + bValue = JsonGetInt(JsonObjectGet(jRules, AI_RULE_AI_DIFFICULTY)); + SetLocalInt(oModule, AI_RULE_AI_DIFFICULTY, bValue); + // Monster AI's perception distance from player. + float fValue = JsonGetFloat(JsonObjectGet(jRules, AI_RULE_PERCEPTION_DISTANCE)); + SetLocalFloat(oModule, AI_RULE_PERCEPTION_DISTANCE, fValue); + // Enemy corpses remain on the floor instead of dissappearing. + bValue = JsonGetInt(JsonObjectGet(jRules, AI_RULE_CORPSES_STAY)); + SetLocalInt(oModule, AI_RULE_CORPSES_STAY, bValue); + // Monsters will wander around when not in combat. + bValue = JsonGetInt(JsonObjectGet(jRules, AI_RULE_WANDER)); + SetLocalInt(oModule, AI_RULE_WANDER, bValue); + // Increase the number of encounter creatures. + fValue = JsonGetFloat(JsonObjectGet(jRules, AI_INCREASE_ENC_MONSTERS)); + SetLocalFloat(oModule, AI_INCREASE_ENC_MONSTERS, fValue); + // Increase all monsters hitpoints by this percentage. + bValue = JsonGetInt(JsonObjectGet(jRules, AI_INCREASE_MONSTERS_HP)); + SetLocalInt(oModule, AI_INCREASE_MONSTERS_HP, bValue); + // Monster's perception distance. + bValue = JsonGetInt(JsonObjectGet(jRules, AI_RULE_MON_PERC_DISTANCE)); + if(bValue < 8 || bValue > 11) bValue = 11; + SetLocalInt(oModule, AI_RULE_MON_PERC_DISTANCE, bValue); + // Variable name set to hold the maximum number of henchman the player wants. + bValue = JsonGetInt(JsonObjectGet(jRules, AI_RULE_MAX_HENCHMAN)); + if(bValue == 0) bValue = GetMaxHenchmen(); + else SetMaxHenchmen(bValue); + SetLocalInt(oModule, AI_RULE_MAX_HENCHMAN, bValue); + // Monster AI's wander distance from their spawn point. + fValue = JsonGetFloat(JsonObjectGet(jRules, AI_RULE_WANDER_DISTANCE)); + SetLocalFloat(oModule, AI_RULE_WANDER_DISTANCE, fValue); + // Monsters will open doors while wandering around and not in combat. + bValue = JsonGetInt(JsonObjectGet(jRules, AI_RULE_OPEN_DOORS)); + SetLocalInt(oModule, AI_RULE_OPEN_DOORS, bValue); + // If the modules default XP has not been set then we do it here. + int nDefaultXP = GetLocalInt(oModule, AI_RULE_DEFAULT_XP_SCALE); + if(nDefaultXP == 0) + { + bValue = GetModuleXPScale(); + if(bValue != 0) SetLocalInt(oModule, AI_RULE_DEFAULT_XP_SCALE, bValue); + } + // Variable name set to allow the game to regulate experience based on party size. + bValue = JsonGetInt(JsonObjectGet(jRules, AI_RULE_PARTY_SCALE)); + if(bValue) + { + int nBasePartyXP = GetLocalInt(oModule, AI_BASE_PARTY_SCALE_XP); + if(nBasePartyXP == 0) + { + nDefaultXP = GetLocalInt(oModule, AI_RULE_DEFAULT_XP_SCALE); + SetLocalInt(oModule, AI_BASE_PARTY_SCALE_XP, nDefaultXP); + } + } + SetLocalInt(oModule, AI_RULE_PARTY_SCALE, bValue); + json jRSpells = JsonObjectGet(jRules, AI_RULE_RESTRICTED_SPELLS); + if(JsonGetType(jRSpells) == JSON_TYPE_NULL) + { + jRSpells = JsonArray(); + jRules = JsonObjectSet(jRules, AI_RULE_RESTRICTED_SPELLS, jRSpells); + ai_SetCampaignDbJson("rules", jRules); + } + SetLocalJson(oModule, AI_RULE_RESTRICTED_SPELLS, jRSpells); + // Variable name set to allow access to widget buttons for the players. + bValue = JsonGetInt(JsonObjectGet(jRules, sDMWidgetAccessVarname)); + SetLocalInt(oModule, sDMWidgetAccessVarname, bValue); + // Variable name set to allow access to widget buttons for the players. + bValue = JsonGetInt(JsonObjectGet(jRules, sDMAIAccessVarname)); + SetLocalInt(oModule, sDMAIAccessVarname, bValue); + } +} +int ai_GetIsCharacter(object oCreature) +{ + return (GetIsPC(oCreature) && !GetIsDM(oCreature) && !GetIsDMPossessed(oCreature)); +} +int ai_GetIsDungeonMaster(object oCreature) +{ + return (GetIsDM(oCreature) || GetIsDMPossessed(oCreature)); +} +object ai_GetPlayerMaster(object oAssociate) +{ + if(ai_GetIsCharacter(oAssociate)) return oAssociate; + object oMaster = GetMaster(oAssociate); + if(ai_GetIsCharacter(oMaster)) return oMaster; + return OBJECT_INVALID; +} +int ai_GetPercHPLoss(object oCreature) +{ + int nHP = GetCurrentHitPoints(oCreature); + if(nHP < 1) return 0; + return(nHP * 100) / GetMaxHitPoints(oCreature); +} +int ai_RollDiceString(string sDice) +{ + int nNegativePos, nBonus = 0; + string sRight = GetStringRight(sDice, GetStringLength(sDice) - FindSubString(sDice, "d") - 1); + int nPlusPos = FindSubString(sRight, "+"); + if(nPlusPos != -1) + { + nBonus = StringToInt(GetStringRight(sRight, GetStringLength(sRight) - nPlusPos - 1)); + sRight = GetStringLeft(sRight, nPlusPos); + } + else + { + nNegativePos = FindSubString(sRight, "-"); + if(nNegativePos != -1) + { + nBonus = StringToInt(GetStringRight(sRight, GetStringLength(sRight) - nNegativePos - 1)); + sRight = GetStringLeft(sRight, nNegativePos); + nBonus = nBonus * -1; + } + } + int nDie = StringToInt(sRight); + int nNumOfDie = StringToInt(GetStringLeft(sDice, FindSubString(sDice, "d"))); + int nResult; + while(nNumOfDie > 0) + { + nResult += Random(nDie) + 1; + nNumOfDie --; + } + return nResult + nBonus; +} +int ai_HexStringToInt(string sString) +{ + sString = GetStringLowerCase(sString); + int nInt = 0; + int nLength = GetStringLength(sString); + int i; + for(i = nLength - 1; i >= 0; i--) + { + int n = FindSubString("0123456789abcdef", GetSubString(sString, i, 1)); + if(n == -1) return nInt; + nInt |= n << ((nLength - i - 1) * 4); + } + return nInt; +} +float ai_GetCosAngleBetween(object oObject1, object oObject2) +{ + vector v1 = GetPositionFromLocation(GetLocation(oObject1)); + vector v2 = GetPositionFromLocation(GetLocation(oObject2)); + vector v3 = GetPositionFromLocation(GetLocation(OBJECT_SELF)); + + v1.x -= v3.x; v1.y -= v3.y; v1.z -= v3.z; + v2.x -= v3.x; v2.y -= v3.y; v2.z -= v3.z; + + float dotproduct = v1.x*v2.x+v1.y*v2.y+v1.z*v2.z; + + return dotproduct/(VectorMagnitude(v1)*VectorMagnitude(v2)); +} +string ai_RemoveIllegalCharacters(string sString, string sLegal = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") +{ + string sOut, sValue; + sString = ai_StripColorCodes(sString); + int nLength = GetStringLength(sString); + int Cnt; + for(Cnt = 0; Cnt != nLength; ++Cnt) + { + sValue = GetSubString(sString, Cnt, 1); + if(TestStringAgainstPattern("**" + sValue + "**", sLegal)) + sOut += sValue; + } + return sOut; +} +int ai_GetCharacterLevels(object oCreature) +{ + int nLevels, nPosition = 1; + while(nPosition <= AI_MAX_CLASSES_PER_CHARACTER) + { + nLevels += GetLevelByPosition(nPosition, oCreature); + nPosition++; + } + return nLevels; +} +string ai_StringReplaceText(string sSource, string sFind, string sReplace) +{ + int nFindLength = GetStringLength(sFind); + int nPosition = 0; + string sReturnValue = ""; + // Locate all occurences of sFind. + int nFound = FindSubString(sSource, sFind); + while(nFound >= 0 ) + { + // Build the return string, replacing this occurence of sFind with sReplace. + sReturnValue += GetSubString(sSource, nPosition, nFound - nPosition) + sReplace; + nPosition = nFound + nFindLength; + nFound = FindSubString(sSource, sFind, nPosition); + } + // Tack on the end of sSource and return. + return sReturnValue + GetStringRight(sSource, GetStringLength(sSource) - nPosition); +} +string ai_GetStringArray(string sArray, int nIndex, string sSeperator = ":") +{ + int nCnt = 0, nMark = 0, nStringLength = GetStringLength(sArray); + string sCharacter; + // Search the string. + while(nCnt < nStringLength) + { + sCharacter = GetSubString(sArray, nCnt, 1); + // Look for the mark. + if(sCharacter == sSeperator) + { + // If we have not found it then lets see if this mark is the one. + if(nMark < 1) + { + // If we are down to 0 in the index then we have found the mark. + if(nIndex > 0) nIndex --; + // Mark the start of the string we need. + else nMark = nCnt + 1; + } + else + { + // We have the first mark so the next mark will mean we have the string we need. + // Now pull it and return. + sArray = GetSubString(sArray, nMark, nCnt - nMark); + return sArray; + } + } + nCnt ++; + } + // If we hit the end without finding it then return "" as an error. + return ""; +} +string ai_SetStringArray(string sArray, int nIndex, string sField, string sSeperator = ":") +{ + int nCnt = 1, nMark = 1, nStringLength = GetStringLength(sArray); + int nIndexCounter = 0; + string sCharacter, sNewArray = sSeperator, sText; + // Check to make sure this is not a new array. + // If it is new then set it with 1 slot. + if(nStringLength < 2) + { + sArray = sSeperator + " " + sSeperator; + nStringLength = 3; + } + // Search the string. + while(nCnt <= nStringLength) + { + sCharacter = GetSubString(sArray, nCnt, 1); + // Look for the mark. + if(sCharacter == sSeperator) + { + // First check to see if this is the index we are replacing. + if(nIndex == nIndexCounter) sText = sField; + else + { + // Get the original text for this field. + sText = GetSubString(sArray, nMark, nCnt - nMark); + } + // Add the field to the new index. + sNewArray = sNewArray + sText + sSeperator; + // Now set the marker to the new starting point. + nMark = nCnt + 1; + // Increase the index counter as well. + nIndexCounter ++; + } + nCnt ++; + } + // if we are at the end of the array and still have not set the data + // then add blank data until we get to the correct index. + while(nIndexCounter <= nIndex) + { + // If they match add the field. + if(nIndexCounter == nIndex) sNewArray = sNewArray + sField + sSeperator; + // Otherwise just add a blank field. + else sNewArray = sNewArray + " " + sSeperator; + nIndexCounter ++; + } + // When done return the new array. + return sNewArray; +} +int ai_GetNumberOfProperties(object oItem) +{ + int nNumOfProperties = 0, nPropertyType, nPropertySubType; + // Get first property + itemproperty ipProperty = GetFirstItemProperty(oItem); + while(GetIsItemPropertyValid(ipProperty)) + { + // Ignore double type properties such as bane. + nPropertyType = GetItemPropertyType(ipProperty); + switch(nPropertyType) + { + // Skip these properties as they don't count. + case 8 : break; // EnhanceAlignmentGroup + case 44 : break; // Light + case 62 : break; // UseLimitationAlignmentGroup + case 63 : break; // UseLimitationClass + case 64 : break; // UseLimitationRacial + case 65 : break; // UseLimitationSpecificAlignment + case 66 : break; // UseLimitationTerrain + case 86 : break; // Quality + case 150 : break; // UseLimitationGender + case 15 : + { + nPropertySubType = GetItemPropertySubType(ipProperty); + if(nPropertySubType == IP_CONST_CASTSPELL_UNIQUE_POWER_SELF_ONLY) break; + if(nPropertySubType == IP_CONST_CASTSPELL_UNIQUE_POWER) break; + } + default : nNumOfProperties ++; + } + // Get the next property + ipProperty = GetNextItemProperty(oItem); + } + // Reduce the number of properties by one on whips. + if(GetBaseItemType(oItem) == BASE_ITEM_WHIP) nNumOfProperties --; + return nNumOfProperties; +} +void ai_CreateCampaignDataTable() +{ + sqlquery sql = SqlPrepareQueryCampaign(AI_CAMPAIGN_DATABASE, + "CREATE TABLE IF NOT EXISTS " + AI_TABLE + "(" + + "name TEXT, " + + "plugins TEXT, " + + "rules TEXT, " + + "PRIMARY KEY(name));"); + SqlStep(sql); + //if(AI_DEBUG) ai_Debug("0i_main", "343", We are creating a campaign table [" + + // AI_TABLE + "] in the database."); +} +void ai_CheckCampaignDataTableAndCreateTable() +{ + string sQuery = "SELECT name FROM sqlite_master WHERE type ='table' " + + "AND name =@table;"; + sqlquery sql = SqlPrepareQueryCampaign(AI_CAMPAIGN_DATABASE, sQuery); + SqlBindString(sql, "@table", AI_TABLE); + if(!SqlStep(sql)) ai_CreateCampaignDataTable(); +} +void ai_InitializeCampaignData() +{ + string sQuery = "INSERT INTO " + AI_TABLE + "(name, plugins, rules) " + + "VALUES(@name, @plugins, @rules);"; + sqlquery sql = SqlPrepareQueryCampaign(AI_CAMPAIGN_DATABASE, sQuery); + SqlBindString(sql, "@name", "PEPS_DATA"); + SqlBindJson(sql, "@plugins", JsonArray()); + SqlBindJson(sql, "@rules", JsonObject()); + SqlStep(sql); +} +void ai_CheckCampaignDataAndInitialize() +{ + ai_CheckCampaignDataTableAndCreateTable(); + string sQuery = "SELECT name FROM " + AI_TABLE + " WHERE name = @name;"; + sqlquery sql = SqlPrepareQueryCampaign(AI_CAMPAIGN_DATABASE, sQuery); + SqlBindString(sql, "@name", "PEPS_DATA"); + if(!SqlStep(sql)) ai_InitializeCampaignData(); +} +void ai_CreateDMDataTable() +{ + sqlquery sql = SqlPrepareQueryCampaign(AI_CAMPAIGN_DATABASE, + "CREATE TABLE IF NOT EXISTS " + AI_DM_TABLE + "(" + + "name TEXT, " + + "buttons TEXT, " + + "plugins TEXT, " + + "locations TEXT, " + + "options TEXT, " + + "saveslots TEXT, " + + "PRIMARY KEY(name));"); + SqlStep(sql); +} +void ai_CheckDMDataTableAndCreateTable() +{ + string sQuery = "SELECT name FROM sqlite_master WHERE type ='table' " + + "AND name =@table;"; + sqlquery sql = SqlPrepareQueryCampaign(AI_CAMPAIGN_DATABASE, sQuery); + SqlBindString(sql, "@table", AI_DM_TABLE); + if(!SqlStep(sql)) ai_CreateDMDataTable(); +} +void ai_InitializeDMData(string sName) +{ + string sQuery = "INSERT INTO " + AI_DM_TABLE + "(name, buttons, plugins, " + + "locations, options, saveslots) " + + "VALUES(@name, @buttons, @plugins, @locations, @options, @saveslots);"; + sqlquery sql = SqlPrepareQueryCampaign(AI_CAMPAIGN_DATABASE, sQuery); + SqlBindString(sql, "@name", sName); + SqlBindJson(sql, "@buttons", JsonArray()); + SqlBindJson(sql, "@plugins", JsonArray()); + SqlBindJson(sql, "@locations", JsonObject()); + SqlBindJson(sql, "@options", JsonObject()); + SqlBindJson(sql, "@saveslots", JsonObject()); + SqlStep(sql); +} +void ai_CheckDMDataAndInitialize(object oDM) +{ + string sName = ai_RemoveIllegalCharacters(ai_StripColorCodes(GetName(oDM))); + string sQuery = "SELECT name FROM " + AI_DM_TABLE + " WHERE name = @name;"; + sqlquery sql = SqlPrepareQueryCampaign(AI_CAMPAIGN_DATABASE, sQuery); + SqlBindString(sql, "@name", sName); + if(!SqlStep(sql)) + { + ai_CheckDMDataTableAndCreateTable(); + ai_InitializeDMData(sName); + } +} +void ai_SetCampaignDbJson(string sDataField, json jData, string sName = "PEPS_DATA", string sTable = AI_TABLE) +{ + string sQuery = "UPDATE " + sTable + " SET " + sDataField + + " = @data WHERE name = @name;"; + sqlquery sql = SqlPrepareQueryCampaign(AI_CAMPAIGN_DATABASE, sQuery); + SqlBindJson(sql, "@data", jData); + SqlBindString(sql, "@name", sName); + SqlStep(sql); +} +json ai_GetCampaignDbJson(string sDataField, string sName = "PEPS_DATA", string sTable = AI_TABLE) +{ + string sQuery = "SELECT " + sDataField + " FROM " + sTable + " WHERE name = @name;"; + sqlquery sql = SqlPrepareQueryCampaign(AI_CAMPAIGN_DATABASE, sQuery); + SqlBindString(sql, "@name", sName); + json jReturn; + if(SqlStep(sql)) return SqlGetJson (sql, 0); + else return JsonArray(); + return jReturn; +} +void ai_CreateAssociateDataTable(object oPlayer) +{ + sqlquery sql = SqlPrepareQueryObject(oPlayer, + "CREATE TABLE IF NOT EXISTS " + AI_TABLE + "(" + + "name TEXT, " + + "modes TEXT, " + + "buttons TEXT, " + + "aidata TEXT, " + + "lootfilters TEXT, " + + "plugins TEXT, " + + "locations TEXT, " + + "PRIMARY KEY(name));"); + SqlStep(sql); + //ai_Debug("0i_main", "665", GetName(oPlayer) + " is creating a table [" + + // AI_TABLE + "] in the database."); +} +void ai_CheckDataTableAndCreateTable(object oPlayer) +{ + string sQuery = "SELECT name FROM sqlite_master WHERE type ='table' " + + "AND name =@table;"; + sqlquery sql = SqlPrepareQueryObject(oPlayer, sQuery); + SqlBindString(sql, "@table", AI_TABLE); + if(!SqlStep(sql)) ai_CreateAssociateDataTable (oPlayer); + //else SendMessageToPC(oPlayer, "0i_main, 675, " + GetName(oPlayer) + " has a database with table [" + AI_TABLE + "]."); +} +void ai_InitializeAssociateData(object oPlayer, string sAssociateType) +{ + string sQuery = "INSERT INTO " + AI_TABLE + "(name, modes, buttons, " + + "aidata, lootfilters, plugins, locations) " + + "VALUES(@name, @modes, @buttons, @aidata, @lootfilters, @plugins, @locations);"; + sqlquery sql = SqlPrepareQueryObject(oPlayer, sQuery); + SqlBindString(sql, "@name", sAssociateType); + SqlBindJson(sql, "@modes", JsonArray()); + SqlBindJson(sql, "@buttons", JsonArray()); + SqlBindJson(sql, "@aidata", JsonArray()); + SqlBindJson(sql, "@lootfilters", JsonArray()); + SqlBindJson(sql, "@plugins", JsonArray()); + SqlBindJson(sql, "@locations", JsonObject()); + //SendMessageToPC(oPlayer, "0i_main, 690, " + GetName(oPlayer) + " is initializing associate " + + // sAssociateType + " data for table [" + AI_TABLE + "]."); + SqlStep(sql); +} +void ai_CheckAssociateDataAndInitialize(object oPlayer, string sAssociateType) +{ + ai_CheckDataTableAndCreateTable(oPlayer); + string sQuery = "SELECT name FROM " + AI_TABLE + " WHERE name = @name;"; + sqlquery sql = SqlPrepareQueryObject (oPlayer, sQuery); + SqlBindString(sql, "@name", sAssociateType); + if(!SqlStep(sql)) ai_InitializeAssociateData(oPlayer, sAssociateType); + //else SendMessageToPC(oPlayer, "0i_main, 701, sAssociateType: " + sAssociateType + + // " returns: " + SqlGetString(sql, 0)); +} +string ai_GetAssociateType(object oPlayer, object oAssociate) +{ + if(GetIsPC(oAssociate)) return "pc"; + string sAITag = GetLocalString(oAssociate, AI_TAG); + if(sAITag == "") + { + int nAssociateType = GetAssociateType(oAssociate); + if(nAssociateType == ASSOCIATE_TYPE_ANIMALCOMPANION) sAITag = "companion"; + else if(nAssociateType == ASSOCIATE_TYPE_FAMILIAR) sAITag = "familiar"; + else if(nAssociateType == ASSOCIATE_TYPE_SUMMONED) sAITag = "summons"; + else if(nAssociateType == ASSOCIATE_TYPE_DOMINATED) sAITag = "dominated"; + else if(nAssociateType == ASSOCIATE_TYPE_HENCHMAN) sAITag = GetTag(oAssociate); + string sCurrentAITag; + // Check for duplicate tags and change. + int nIndex; + object oCreature; + for(nIndex = 1; nIndex <= AI_MAX_HENCHMAN; nIndex++) + { + oCreature = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPlayer, nIndex); + if(oAssociate != oCreature && sAITag == GetTag(oCreature)) sAITag += IntToString(Random(1000)); + } + for(nIndex = 2; nIndex < 6; nIndex++) + { + oCreature = GetAssociate(nIndex, oPlayer, 1); + if(oAssociate != oCreature && sAITag == GetTag(oCreature)) sAITag += IntToString(Random(1000)); + } + SetLocalString(oAssociate, AI_TAG, sAITag); + } + return sAITag; +} +void ai_SetAssociateDbInt(object oPlayer, string sAssociatetype, string sDataField, int nData, string sTable = AI_TABLE) +{ + string sQuery = "UPDATE " + sTable + " SET " + sDataField + + " = @data WHERE name = @name;"; + sqlquery sql = SqlPrepareQueryObject(oPlayer, sQuery); + SqlBindString(sql, "@name", sAssociatetype); + SqlBindInt(sql, "@data", nData); + //ai_Debug("0i_main", "368", "SETTING DATA: " + GetName(oPlayer) + " sAssociatetype: " + + // sAssociatetype + " sDataField: " + sDataField + " nData: " + IntToString(nData)); + SqlStep(sql); +} +int ai_GetAssociateDbInt(object oPlayer, string sAssociatetype, string sDataField, string sTable = AI_TABLE) +{ + string sQuery = "SELECT " + sDataField + " FROM " + sTable + " WHERE name = @name;"; + sqlquery sql = SqlPrepareQueryObject(oPlayer, sQuery); + SqlBindString(sql, "@name", sAssociatetype); + //ai_Debug("0i_main", "377", "GETTING DATA: " + GetName(oPlayer) + " sAssociatetype: " + + // sAssociatetype + " sDataField: " + sDataField); + if(SqlStep(sql)) return SqlGetInt(sql, 0); + else return 0; +} +void ai_SetAssociateDbFloat(object oPlayer, string sAssociatetype, string sDataField, float fData, string sTable = AI_TABLE) +{ + string sQuery = "UPDATE " + sTable + " SET " + sDataField + + " = @data WHERE name = @name;"; + sqlquery sql = SqlPrepareQueryObject(oPlayer, sQuery); + SqlBindString(sql, "@name", sAssociatetype); + SqlBindFloat(sql, "@data", fData); + //ai_Debug("0i_main", "368", "SETTING DATA: " + GetName(oPlayer) + " sAssociatetype: " + + // sAssociatetype + " sDataField: " + sDataField + " fData: " + FloatToString(fData, 0, 0)); + SqlStep(sql); +} +float ai_GetAssociateDbFloat(object oPlayer, string sAssociatetype, string sDataField, string sTable = AI_TABLE) +{ + string sQuery = "SELECT " + sDataField + " FROM " + sTable + " WHERE name = @name;"; + sqlquery sql = SqlPrepareQueryObject(oPlayer, sQuery); + SqlBindString(sql, "@name", sAssociatetype); + //ai_Debug("0i_main", "377", "GETTING DATA: " + GetName(oPlayer) + " sAssociatetype: " + + // sAssociatetype + " sDataField: " + sDataField); + if(SqlStep(sql)) return SqlGetFloat(sql, 0); + else return 0.0; +} +void ai_SetAssociateDbJson(object oPlayer, string sAssociateType, string sDataField, json jData, string sTable = AI_TABLE) +{ + //SendMessageToPC(oPlayer, "0i_main, 629, Set DbJson - sAssociateType: " + sAssociateType + " sDataField: " + sDataField + " jData: " + JsonDump(jData)); + string sQuery = "UPDATE " + sTable + " SET " + sDataField + + " = @data WHERE name = @name;"; + sqlquery sql = SqlPrepareQueryObject(oPlayer, sQuery); + SqlBindJson(sql, "@data", jData); + SqlBindString(sql, "@name", sAssociateType); + SqlStep(sql); +} +json ai_GetAssociateDbJson(object oPlayer, string sAssociateType, string sDataField, string sTable = AI_TABLE) +{ + //SendMessageToPC(oPlayer, "0i_main, 638, Get DbJson - sAssociateType: " + sAssociateType + " sDataField: " + sDataField); + string sQuery = "SELECT " + sDataField + " FROM " + sTable + " WHERE name = @name;"; + sqlquery sql = SqlPrepareQueryObject(oPlayer, sQuery); + SqlBindString (sql, "@name", sAssociateType); + if(SqlStep(sql)) + { + json jReturn = SqlGetJson(sql, 0); + //SendMessageToPC(oPlayer, "0i_main, 646 jReturn: " + JsonDump(jReturn, 1)); + if(JsonGetType(jReturn) == JSON_TYPE_NULL) return JsonArray(); + return jReturn; + } + else return JsonNull(); +} +void aiSaveAssociateModesToDb(object oPlayer, object oAssociate) +{ + string sAssociateType = ai_GetAssociateType(oPlayer, oAssociate); + json jModes = ai_GetAssociateDbJson(oPlayer, sAssociateType, "modes"); + int nAIMode = GetLocalInt(oAssociate, sAIModeVarname); + jModes = JsonArraySet(jModes, 0, JsonInt(nAIMode)); + int nMagicMode = GetLocalInt(oAssociate, sMagicModeVarname); + jModes = JsonArraySet(jModes, 1, JsonInt(nMagicMode)); + ai_SetAssociateDbJson(oPlayer, sAssociateType, "modes", jModes); +} +void ai_SetupModes(object oPlayer, object oAssociate, string sAssociateType) +{ + json jModes = JsonArray(); + jModes = JsonArrayInsert(jModes, JsonInt(0)); // AI Modes. + // Set magic modes to use Normal magic, Bit 256. + jModes = JsonArrayInsert(jModes, JsonInt(256)); // Magic Modes. + SetLocalInt(oAssociate, sMagicModeVarname, 256); + ai_SetAssociateDbJson(oPlayer, sAssociateType, "modes", jModes, AI_TABLE); +} +void ai_SetupButtons(object oPlayer, object oAssociate, string sAssociateType) +{ + json jButtons = JsonArray(); + jButtons = JsonArrayInsert(jButtons, JsonInt(0)); // Command buttons. + jButtons = JsonArrayInsert(jButtons, JsonInt(0)); // AI buttons. + jButtons = JsonArrayInsert(jButtons, JsonInt(0)); // AI buttons 2. + ai_SetAssociateDbJson(oPlayer, sAssociateType, "buttons", jButtons, AI_TABLE); +} +void ai_SetupAIData(object oPlayer, object oAssociate, string sAssociateType) +{ + json jAIData = JsonArray(); + jAIData = JsonArrayInsert(jAIData, JsonInt(0)); // 0 - Difficulty adjustment. + jAIData = JsonArrayInsert(jAIData, JsonInt(70)); // 1 - Heal out of combat. + SetLocalInt(oAssociate, AI_HEAL_OUT_OF_COMBAT_LIMIT, 70); + jAIData = JsonArrayInsert(jAIData, JsonInt(50)); // 2 - Heal in combat. + SetLocalInt(oAssociate, AI_HEAL_IN_COMBAT_LIMIT, 50); + jAIData = JsonArrayInsert(jAIData, JsonFloat(20.0)); // 3 - Loot check range. + SetLocalFloat(oAssociate, AI_LOOT_CHECK_RANGE, 20.0); + jAIData = JsonArrayInsert(jAIData, JsonFloat(20.0)); // 4 - Lock check range. + SetLocalFloat(oAssociate, AI_LOCK_CHECK_RANGE, 20.0); + jAIData = JsonArrayInsert(jAIData, JsonFloat(20.0)); // 5 - Trap check range. + SetLocalFloat(oAssociate, AI_TRAP_CHECK_RANGE, 20.0); + jAIData = JsonArrayInsert(jAIData, JsonFloat(3.0)); // 6 - Associate Distance. + SetLocalFloat(oAssociate, AI_FOLLOW_RANGE, 3.0); + // This can be replaced as it is not used in the database. + // We keep it for now as we don't want to move other data. + jAIData = JsonArrayInsert(jAIData, JsonInt(11)); // 7 - Associate Perception DistanceDistance. + SetLocalInt(oAssociate, AI_ASSOCIATE_PERCEPTION, 11); + SetLocalFloat(oAssociate, AI_ASSOC_PERCEPTION_DISTANCE, 20.0); + jAIData = JsonArrayInsert(jAIData, JsonString("")); // 8 - Associate Combat Tactics. + jAIData = JsonArrayInsert(jAIData, JsonFloat(20.0)); // 9 - Open Doors check range. + SetLocalFloat(oAssociate, AI_OPEN_DOORS_RANGE, 20.0); + json jSpells = JsonArray(); + jAIData = JsonArrayInsert(jAIData, jSpells); // 10 - Castable spells. + ai_SetAssociateDbJson(oPlayer, sAssociateType, "aidata", jAIData, AI_TABLE); +} +void ai_SetupLootFilters(object oPlayer, object oAssociate, string sAssociateType) +{ + json jLootFilters = JsonArray(); + // Maximum weight to pickup an item. + jLootFilters = JsonArrayInsert(jLootFilters, JsonInt(200)); + SetLocalInt(oAssociate, AI_MAX_LOOT_WEIGHT, 200); + // Bitwise int for checkbox pickup filter. + jLootFilters = JsonArrayInsert(jLootFilters, JsonInt(AI_LOOT_ALL_ON)); + SetLocalInt(oAssociate, sLootFilterVarname, AI_LOOT_ALL_ON); + // Minimum gold value to pickup. + int nIndex; + for(nIndex = 2; nIndex < 20; nIndex++) + { + jLootFilters = JsonArrayInsert(jLootFilters, JsonInt(0)); + } + ai_SetAssociateDbJson(oPlayer, sAssociateType, "lootfilters", jLootFilters, AI_TABLE); +} +void ai_SetupLocations(object oPlayer, object oAssociate, string sAssociateType) +{ + json jLocations = JsonObject(); + json jNUI = JsonObject(); + jNUI = JsonObjectSet(jNUI, "x", JsonFloat(-1.0)); + jNUI = JsonObjectSet(jNUI, "y", JsonFloat(-1.0)); + if(ai_GetIsCharacter(oAssociate)) + { + jLocations = JsonObjectSet(jLocations, AI_MAIN_NUI, jNUI); + jLocations = JsonObjectSet(jLocations, AI_PLUGIN_NUI, jNUI); + } + jLocations = JsonObjectSet(jLocations, sAssociateType + AI_COMMAND_NUI, jNUI); + jLocations = JsonObjectSet(jLocations, sAssociateType + AI_NUI, jNUI); + jLocations = JsonObjectSet(jLocations, sAssociateType + AI_LOOTFILTER_NUI, jNUI); + jLocations = JsonObjectSet(jLocations, sAssociateType + AI_COPY_NUI, jNUI); + jLocations = JsonObjectSet(jLocations, sAssociateType + AI_QUICK_WIDGET_NUI, jNUI); + jLocations = JsonObjectSet(jLocations, sAssociateType + AI_SPELL_MEMORIZE_NUI, jNUI); + jLocations = JsonObjectSet(jLocations, sAssociateType + AI_SPELL_KNOWN_NUI, jNUI); + jNUI = JsonObjectSet(jNUI, "x", JsonFloat(0.0)); + jNUI = JsonObjectSet(jNUI, "y", JsonFloat(0.0)); + jLocations = JsonObjectSet(jLocations, sAssociateType + AI_WIDGET_NUI, jNUI); + ai_SetAssociateDbJson(oPlayer, sAssociateType, "locations", jLocations, AI_TABLE); +} +void ai_SetupAssociateData(object oPlayer, object oAssociate, string sAssociateType) +{ + //ai_Debug("0i_main", "744", GetName(oAssociate) + " is initializing associate data."); + ai_CheckAssociateDataAndInitialize(oPlayer, sAssociateType); + // Default behavior for associates at start. + ai_SetupModes(oPlayer, oAssociate, sAssociateType); + ai_SetupButtons(oPlayer, oAssociate, sAssociateType); + ai_SetupAIData(oPlayer, oAssociate, sAssociateType); + ai_SetupLootFilters(oPlayer, oAssociate, sAssociateType); + // ********** Plugins ************ + // These are pulled straight from the database. + ai_SetupLocations(oPlayer, oAssociate, sAssociateType); +} +void ai_RestoreDatabase(object oPlayer, object oAssociate, string sAssociateType) +{ + // ********** Modes ********** + json jModes = JsonArray(); + // AI Modes (0). + int nValue = GetLocalInt(oAssociate, sAIModeVarname); + jModes = JsonArrayInsert(jModes, JsonInt(nValue)); + // Magic Modes (1). + nValue = GetLocalInt(oAssociate, sMagicModeVarname); + jModes = JsonArrayInsert(jModes, JsonInt(nValue)); + ai_SetAssociateDbJson(oPlayer, sAssociateType, "modes", jModes, AI_TABLE); + // ********** Buttons ********** + json jButtons = JsonArray(); + // Command buttons (0). + nValue = GetLocalInt(oAssociate, sWidgetButtonsVarname); + jButtons = JsonArrayInsert(jButtons, JsonInt(nValue)); + // AI buttons Group 1 (1). + nValue = GetLocalInt(oAssociate, sAIButtonsVarname); + jButtons = JsonArrayInsert(jButtons, JsonInt(nValue)); + ai_SetAssociateDbJson(oPlayer, sAssociateType, "buttons", jButtons, AI_TABLE); + // ********** AI Data ********** + json jAIData = JsonArray(); + nValue = GetLocalInt(oAssociate, AI_DIFFICULTY_ADJUSTMENT); + jAIData = JsonArrayInsert(jAIData, JsonInt(nValue)); + nValue = GetLocalInt(oAssociate, AI_HEAL_OUT_OF_COMBAT_LIMIT); + jAIData = JsonArrayInsert(jAIData, JsonInt(nValue)); + nValue = GetLocalInt(oAssociate, AI_HEAL_IN_COMBAT_LIMIT); + jAIData = JsonArrayInsert(jAIData, JsonInt(nValue)); + float fValue = GetLocalFloat(oAssociate, AI_LOOT_CHECK_RANGE); + jAIData = JsonArrayInsert(jAIData, JsonFloat(fValue)); + fValue = GetLocalFloat(oAssociate, AI_LOCK_CHECK_RANGE); + jAIData = JsonArrayInsert(jAIData, JsonFloat(fValue)); + fValue = GetLocalFloat(oAssociate, AI_TRAP_CHECK_RANGE); + jAIData = JsonArrayInsert(jAIData, JsonFloat(fValue)); + fValue = GetLocalFloat(oAssociate, AI_FOLLOW_RANGE); + jAIData = JsonArrayInsert(jAIData, JsonFloat(fValue)); + nValue = GetLocalInt(oAssociate, AI_ASSOCIATE_PERCEPTION); + jAIData = JsonArrayInsert(jAIData, JsonInt(nValue)); + float fRange = 20.0; + if(nValue == 8) fRange = 10.0; + else if(nValue == 10) fRange = 35.0; + SetLocalFloat(oAssociate, AI_ASSOC_PERCEPTION_DISTANCE, fRange); + string sValue = GetLocalString(oAssociate, AI_DEFAULT_SCRIPT); + jAIData = JsonArrayInsert(jAIData, JsonString(sValue)); + fValue = GetLocalFloat(oAssociate, AI_OPEN_DOORS_RANGE); + jAIData = JsonArrayInsert(jAIData, JsonFloat(fValue)); + json jValue = GetLocalJson(oPlayer, AI_SPELLS_WIDGET); + if(JsonGetType(jValue) == JSON_TYPE_NULL) + { + jValue = JsonArray(); + jValue = JsonArrayInsert(jValue, JsonInt(1)); // 0 - Class selected. + jValue = JsonArrayInsert(jValue, JsonInt(10)); // 1 - Level selected. + jValue = JsonArrayInsert(jValue, JsonArray()); // Spell list for widget. + SetLocalJson(oPlayer, AI_SPELLS_WIDGET, jValue); + } + jAIData = JsonArrayInsert(jAIData, jValue); + ai_SetAssociateDbJson(oPlayer, sAssociateType, "aidata", jAIData); + // ********** LootFilters ********** + json jLootFilters = JsonArray(); + nValue = GetLocalInt(oAssociate, AI_MAX_LOOT_WEIGHT); + jLootFilters = JsonArrayInsert(jLootFilters, JsonInt(nValue)); + nValue = GetLocalInt(oAssociate, sLootFilterVarname); + jLootFilters = JsonArrayInsert(jLootFilters, JsonInt(nValue)); + int nIndex; + for(nIndex = 2; nIndex < 20; nIndex++) + { + nValue = GetLocalInt(oAssociate, AI_MIN_GOLD_ + IntToString(nIndex)); + jLootFilters = JsonArrayInsert(jLootFilters, JsonInt(nValue)); + } + ai_SetAssociateDbJson(oPlayer, sAssociateType, "lootfilters", jLootFilters, AI_TABLE); + // ********** Plugins ************ + // These are pulled straight from the database. + // ********** Locations ********** + // These are only in the database. +} +void ai_CheckAssociateData(object oPlayer, object oAssociate, string sAssociateType, int bLoad = FALSE) +{ + //ai_Debug("0i_main", "810", "Checking data for oAssociate: " + GetName(oAssociate)); + // Do quick check to see if they have a variable saved if so then exit. + if(GetLocalFloat(oAssociate, AI_ASSOC_PERCEPTION_DISTANCE) != 0.0) + { + if(!bLoad) return; + // If the database gets destroyed lets drop an error and restore values + // from the locals. + ai_CheckAssociateDataAndInitialize(oPlayer, sAssociateType); + ai_RestoreDatabase(oPlayer, oAssociate, sAssociateType); + return; + } + ai_CheckAssociateDataAndInitialize(oPlayer, sAssociateType); + // ********** Modes ********** + json jModes = ai_GetAssociateDbJson(oPlayer, sAssociateType, "modes"); + if(JsonGetType(JsonArrayGet(jModes, 0)) == JSON_TYPE_NULL) + { + ai_SetupModes(oPlayer, oAssociate, sAssociateType); + } + else + { + SetLocalInt(oAssociate, sAIModeVarname, JsonGetInt(JsonArrayGet(jModes, 0))); + SetLocalInt(oAssociate, sMagicModeVarname, JsonGetInt(JsonArrayGet(jModes, 1))); + } + // ********** Buttons ********** + json jButtons = ai_GetAssociateDbJson(oPlayer, sAssociateType, "buttons"); + if(JsonGetType(JsonArrayGet(jButtons, 0)) == JSON_TYPE_NULL) + { + ai_SetupButtons(oPlayer, oAssociate, sAssociateType); + } + else + { + // ********** Associate Command Buttons ********** + int nWidgetButtons = JsonGetInt(JsonArrayGet(jButtons, 0)); + if(nWidgetButtons) SetLocalInt(oAssociate, sWidgetButtonsVarname, nWidgetButtons); + // ********** Associate AI Buttons ********** + int nAIButtons = JsonGetInt(JsonArrayGet(jButtons, 1)); + if(nAIButtons) SetLocalInt(oAssociate, sAIButtonsVarname, nAIButtons); + } + // ********** AI Data ********** + json jAIData = ai_GetAssociateDbJson(oPlayer, sAssociateType, "aidata"); + if(JsonGetType(JsonArrayGet(jAIData, 0)) == JSON_TYPE_NULL) + { + ai_SetupAIData(oPlayer, oAssociate, sAssociateType); + } + else + { + SetLocalInt(oAssociate, AI_DIFFICULTY_ADJUSTMENT, JsonGetInt(JsonArrayGet(jAIData, 0))); + SetLocalInt(oAssociate, AI_HEAL_OUT_OF_COMBAT_LIMIT, JsonGetInt(JsonArrayGet(jAIData, 1))); + SetLocalInt(oAssociate, AI_HEAL_IN_COMBAT_LIMIT, JsonGetInt(JsonArrayGet(jAIData, 2))); + SetLocalFloat(oAssociate, AI_LOOT_CHECK_RANGE, JsonGetFloat(JsonArrayGet(jAIData, 3))); + SetLocalFloat(oAssociate, AI_LOCK_CHECK_RANGE, JsonGetFloat(JsonArrayGet(jAIData, 4))); + SetLocalFloat(oAssociate, AI_TRAP_CHECK_RANGE, JsonGetFloat(JsonArrayGet(jAIData, 5))); + SetLocalFloat(oAssociate, AI_FOLLOW_RANGE, JsonGetFloat(JsonArrayGet(jAIData, 6))); + int nPercRange = JsonGetInt(JsonArrayGet(jAIData, 7)); + if(nPercRange < 8 || nPercRange > 11) nPercRange = 11; + SetLocalInt(oAssociate, AI_ASSOCIATE_PERCEPTION, nPercRange); + float fRange = 20.0; + if(nPercRange == 8) fRange = 10.0; + else if(nPercRange == 10) fRange = 35.0; + SetLocalFloat(oAssociate, AI_ASSOC_PERCEPTION_DISTANCE, fRange); + string sScript = JsonGetString(JsonArrayGet(jAIData, 8)); + if(sScript != "") SetLocalString(oAssociate, AI_DEFAULT_SCRIPT, sScript); + json jDoorRange = JsonArrayGet(jAIData, 9); + if(JsonGetType(jDoorRange) == JSON_TYPE_NULL) + { + jAIData = JsonArrayInsert(jAIData, JsonFloat(20.0)); + ai_SetAssociateDbJson(oPlayer, sAssociateType, "aidata", jAIData); + SetLocalFloat(oAssociate, AI_OPEN_DOORS_RANGE, 20.0); + } + else SetLocalFloat(oAssociate, AI_OPEN_DOORS_RANGE, JsonGetFloat(jDoorRange)); + json jSpellsWidget = JsonArrayGet(jAIData, 10); + if(JsonGetType(jSpellsWidget) == JSON_TYPE_NULL) + { + jSpellsWidget = JsonArray(); + jSpellsWidget = JsonArrayInsert(jSpellsWidget, JsonInt(0)); // 0 - Class selected. + jSpellsWidget = JsonArrayInsert(jSpellsWidget, JsonInt(0)); // 1 - Level selected. + jAIData = JsonArrayInsert(jAIData, jSpellsWidget); + ai_SetAssociateDbJson(oPlayer, sAssociateType, "aidata", jAIData); + SetLocalJson(oPlayer, AI_SPELLS_WIDGET, jSpellsWidget); + } + } + // ********** LootFilters ********** + json jLootFilters = ai_GetAssociateDbJson(oPlayer, sAssociateType, "lootfilters"); + if(JsonGetType(JsonArrayGet(jLootFilters, 0)) == JSON_TYPE_NULL) + { + ai_SetupLootFilters(oPlayer, oAssociate, sAssociateType); + } + else + { + SetLocalInt(oAssociate, AI_MAX_LOOT_WEIGHT, JsonGetInt(JsonArrayGet(jLootFilters, 0))); + SetLocalInt(oAssociate, sLootFilterVarname, JsonGetInt(JsonArrayGet(jLootFilters, 1))); + int nIndex; + for(nIndex = 2; nIndex < 20; nIndex++) + { + SetLocalInt(oAssociate, AI_MIN_GOLD_ + IntToString(nIndex), JsonGetInt(JsonArrayGet(jLootFilters, nIndex))); + } + } + // ********** Plugins ************ + // These are pulled straight from the database. + // ********** Locations ********** + json jLocations = ai_GetAssociateDbJson(oPlayer, sAssociateType, "locations"); + if(JsonGetType(JsonObjectGet(jLocations, AI_WIDGET_NUI)) == JSON_TYPE_NULL) + { + ai_SetupLocations(oPlayer, oAssociate, sAssociateType); + } + // They are always pulled from the database, so no copies to local variables. +} +void ai_SetupDMData(object oPlayer, string sName) +{ + //ai_Debug("0i_main", "870", GetName(oPlayer) + " is initializing DM data."); + ai_CheckDMDataAndInitialize(oPlayer); + // ********** Buttons ********** + json jButtons = JsonArray(); + jButtons = JsonArrayInsert(jButtons, JsonInt(0)); // DM Widget Buttons. + ai_SetCampaignDbJson("buttons", jButtons, sName, AI_DM_TABLE); + // ********** Plugins ************ + // These are pulled straight from the database. + json jPlugins = JsonArray(); + ai_SetCampaignDbJson("plugins", jPlugins, sName, AI_DM_TABLE); + // ********** Locations ********** + json jLocations = JsonObject(); + json jNUI = JsonObject(); + jNUI = JsonObjectSet(jNUI, "x", JsonFloat(-1.0)); + jNUI = JsonObjectSet(jNUI, "y", JsonFloat(-1.0)); + jLocations = JsonObjectSet(jLocations, AI_MAIN_NUI, jNUI); + jLocations = JsonObjectSet(jLocations, AI_PLUGIN_NUI, jNUI); + jNUI = JsonObjectSet(jLocations, "x", JsonFloat(1.0)); + jNUI = JsonObjectSet(jLocations, "y", JsonFloat(1.0)); + jLocations = JsonObjectSet(jLocations, AI_WIDGET_NUI, jNUI); + ai_SetCampaignDbJson("locations", jLocations, sName, AI_DM_TABLE); + // ********** Options ********** + json jOptions = JsonArray(); + ai_SetCampaignDbJson("options", jOptions, sName, AI_DM_TABLE); + // ********** SaveSlots ********** + json jSaveSlots = JsonObject(); + ai_SetCampaignDbJson("saveslots", jSaveSlots, sName, AI_DM_TABLE); +} +void ai_CheckDMData(object oPlayer) +{ + //ai_Debug("0i_main", "898", "Checking data for DM: " + GetName(oPlayer)); + string sName = ai_RemoveIllegalCharacters(GetName(oPlayer)); + // ********** Buttons ********** + json jButtons = ai_GetCampaignDbJson("buttons", sName, AI_DM_TABLE); + // if there is no saved AImodes then set the defaults. + if(JsonGetType(JsonArrayGet(jButtons, 0)) == JSON_TYPE_NULL) + { + ai_SetupDMData(oPlayer, sName); + } + else + { + //ai_Debug("0i_main", "909", GetName(oPlayer) + " is loading DM data from the database."); + // Get data from the database and place on to the associates and player. + // ********** Buttons ********** + json jButtons = ai_GetCampaignDbJson("buttons", sName, AI_DM_TABLE); + if(JsonGetType(JsonArrayGet(jButtons, 0)) == JSON_TYPE_NULL) + { + ai_SetupDMData(oPlayer, sName); + } + SetLocalInt(oPlayer, sDMWidgetButtonVarname, JsonGetInt(JsonArrayGet(jButtons, 0))); + // ********** Associate Command Buttons ********** + int nWidgetButtons = JsonGetInt(JsonArrayGet(jButtons, 0)); + SetLocalInt(oPlayer, sDMWidgetButtonVarname, nWidgetButtons); + // ********** Plugins ************ + // These are pulled straight from the database. + // ********** Locations ********** + // These are pulled straight from the database. + // ********** Options ********** + // ********** SaveSltos ********** + } +} +json ai_Plugin_Add(object oPC, json jPlugins, string sPluginScript) +{ + if(ResManGetAliasFor(sPluginScript, RESTYPE_NCS) == "") + { + ai_SendMessages("The script (" + sPluginScript + ") was not found by ResMan!", AI_COLOR_RED, oPC); + return jPlugins; + } + int nIndex; + json jPlugin = JsonArrayGet(jPlugins, nIndex); + while(JsonGetType(jPlugin) != JSON_TYPE_NULL) + { + if(JsonGetString(JsonArrayGet(jPlugin, 0)) == sPluginScript) + { + ai_SendMessages("Plugin (" + sPluginScript + ") is already installed!", AI_COLOR_RED, oPC); + return jPlugins; + } + jPlugin = JsonArrayGet(jPlugins, ++nIndex); + } + SetLocalInt(oPC, AI_ADD_PLUGIN, TRUE); + SetLocalJson(oPC, AI_JSON_PLUGINS, jPlugins); + ExecuteScript(sPluginScript, oPC); + int nPluginSet = GetLocalInt(oPC, AI_PLUGIN_SET); + // Setting AI_PLUGIN_SET to -1 means the plugin failed to load. + if(nPluginSet == -1) return jPlugins; + if(nPluginSet) + { + jPlugin = GetLocalJson(oPC, AI_JSON_PLUGINS); + jPlugins = JsonArrayInsert(jPlugins, jPlugin); + } + else + { + jPlugin = JsonArray(); + jPlugin = JsonArrayInsert(jPlugin, JsonString(sPluginScript)); + jPlugin = JsonArrayInsert(jPlugin, JsonBool(FALSE)); + jPlugin = JsonArrayInsert(jPlugin, JsonString(sPluginScript)); + int nCount = JsonGetLength(jPlugins) + 1; + string sIcon = "is_summon" + IntToString(nCount); + jPlugin = JsonArrayInsert(jPlugin, JsonString(sIcon)); + jPlugins = JsonArrayInsert(jPlugins, jPlugin); + } + DeleteLocalInt(oPC, AI_ADD_PLUGIN); + DeleteLocalInt(oPC, AI_PLUGIN_SET); + DeleteLocalJson(oPC, AI_JSON_PLUGINS); + return jPlugins; +} +// Temporary function to addapt old plugin json to new plugin json. +json ai_CheckOldPluginJson(object oPC) +{ + json jPlugins = ai_GetAssociateDbJson(oPC, "pc", "plugins"); + int nIndex; + json jPlugin = JsonArrayGet(jPlugins, nIndex); + // If the first array is not an array then this is the old version. + if(JsonGetType(jPlugin) != JSON_TYPE_ARRAY) + { + string sScript; + json jNewPlugins = JsonArray(); + while(JsonGetType(jPlugin) != JSON_TYPE_NULL) + { + sScript = JsonGetString(jPlugin); + if(sScript != "") jNewPlugins = ai_Plugin_Add(oPC, jNewPlugins, sScript); + jPlugin = JsonArrayGet(jPlugins, ++nIndex); + + } + ai_SetAssociateDbJson(oPC, "pc", "plugins", jNewPlugins); + return jNewPlugins; + } + return jPlugins; +} +json ai_UpdatePluginsForPC(object oPC) +{ + // Check if the server is running or single player. + if(!AI_SERVER) return ai_CheckOldPluginJson(oPC); + int nJsonType, nCounter, nIndex, bWidget, bAllow; + string sScript, sName, sIcon; + json jServerPlugins = ai_GetCampaignDbJson("plugins"); + json jPCPlugin, jPCPlugins = ai_GetAssociateDbJson(oPC, "pc", "plugins"); + json jNewPCPlugins = JsonArray(); + json jServerPlugin = JsonArrayGet(jServerPlugins, nIndex); + while(JsonGetType(jServerPlugin) != JSON_TYPE_NULL) + { + bAllow = JsonGetInt(JsonArrayGet(jServerPlugin, 1)); + if(bAllow) + { + sName = JsonGetString(JsonArrayGet(jServerPlugin, 0)); + nCounter = 0; + jPCPlugin = JsonArrayGet(jPCPlugins, nCounter); + nJsonType = JsonGetType(jPCPlugin); + while(nJsonType != JSON_TYPE_NULL) + { + if(sName == JsonGetString(JsonArrayGet(jPCPlugin, 0))) + { + // Boolean - Add to widget. + bWidget = JsonGetInt(JsonArrayGet(jPCPlugin, 1)); + jServerPlugin = JsonArraySet(jServerPlugin, 1, JsonBool(bWidget)); + break; + } + jPCPlugin = JsonArrayGet(jPCPlugins, ++nCounter); + nJsonType = JsonGetType(jPCPlugin); + } + if(nJsonType == JSON_TYPE_NULL) + { + jServerPlugin = JsonArraySet(jServerPlugin, 1, JsonBool(FALSE)); + } + jNewPCPlugins = JsonArrayInsert(jNewPCPlugins, jServerPlugin); + } + jServerPlugin = JsonArrayGet(jServerPlugins, ++nIndex); + } + ai_SetAssociateDbJson(oPC, "pc", "plugins", jNewPCPlugins); + return jNewPCPlugins; +} +json ai_UpdatePluginsForDM(object oPC) +{ + int nJsonType, nCounter, nIndex, bWidget, bAllow; + string sName, sIcon, sDbName = ai_RemoveIllegalCharacters(GetName(oPC)); + json jServerPlugins = ai_GetCampaignDbJson("plugins"); + ai_CheckDMDataAndInitialize(oPC); + json jDMPlugin, jDMPlugins = ai_GetCampaignDbJson("plugins", sDbName, AI_DM_TABLE); + json jNewDMPlugins = JsonArray(); + json jServerPlugin = JsonArrayGet(jServerPlugins, nIndex); + while(JsonGetType(jServerPlugin) != JSON_TYPE_NULL) + { + sName = JsonGetString(JsonArrayGet(jServerPlugin, 0)); + nCounter = 0; + jDMPlugin = JsonArrayGet(jDMPlugins, nCounter); + nJsonType = JsonGetType(jDMPlugin); + while(nJsonType != JSON_TYPE_NULL) + { + if(sName == JsonGetString(JsonArrayGet(jDMPlugin, 0))) + { + // Boolean - Add to widget. + bWidget = JsonGetInt(JsonArrayGet(jDMPlugin, 1)); + jServerPlugin = JsonArraySet(jServerPlugin, 1, JsonBool(bWidget)); + break; + } + jDMPlugin = JsonArrayGet(jDMPlugins, ++nCounter); + nJsonType = JsonGetType(jDMPlugin); + } + if(nJsonType == JSON_TYPE_NULL) + { + jServerPlugin = JsonArraySet(jServerPlugin, 1, JsonBool(FALSE)); + } + jNewDMPlugins = JsonArrayInsert(jNewDMPlugins, jServerPlugin); + jServerPlugin = JsonArrayGet(jServerPlugins, ++nIndex); + } + ai_SetCampaignDbJson("plugins", jNewDMPlugins, sDbName, AI_DM_TABLE); + return jNewDMPlugins; +} +void ai_StartupPlugins(object oPC) +{ + SetLocalInt(oPC, AI_STARTING_UP, TRUE); + int bUpdatePlugins; + string sScript; + json jPlugins; + if(GetIsDM(oPC)) jPlugins = ai_UpdatePluginsForDM(oPC); + else jPlugins = ai_UpdatePluginsForPC(oPC); + // We delete this so each mod can be added that legally loads. + DeleteLocalJson(GetModule(), AI_MONSTER_MOD_JSON); + int nIndex; + json jPlugin = JsonArrayGet(jPlugins, nIndex); + while(JsonGetType(jPlugin) != JSON_TYPE_NULL) + { + sScript = JsonGetString(JsonArrayGet(jPlugin, 0)); + ExecuteScript(sScript, oPC); + // -1 means if failed to load so lets make sure to remove it from the list. + if(GetLocalInt(oPC, AI_PLUGIN_SET) == -1) + { + jPlugins = JsonArrayDel(jPlugins, nIndex); + bUpdatePlugins = TRUE; + nIndex--; + } + jPlugin = JsonArrayGet(jPlugins, ++nIndex); + } + if(bUpdatePlugins) ai_SetAssociateDbJson(oPC, "pc", "plugins", jPlugins); + DeleteLocalInt(oPC, AI_STARTING_UP); +} diff --git a/src/module/nss/0i_menus.nss b/src/module/nss/0i_menus.nss new file mode 100644 index 0000000..8d6834c --- /dev/null +++ b/src/module/nss/0i_menus.nss @@ -0,0 +1,4823 @@ +/*////////////////////////////////////////////////////////////////////////////// +// Script Name: 0i_menus +//////////////////////////////////////////////////////////////////////////////// + Include script for handling NUI menus. +*/////////////////////////////////////////////////////////////////////////////// +#include "0i_nui" +#include "0i_associates" +// Maximum number of Plugins allowed on the players widget. +const int WIDGET_MAX_PLUGINS = 5; + +// Set one of the BTN_* "Widget" bitwise constants on oPlayer to bValid. +void ai_SetWidgetButton(object oPlayer, int nButton, object oAssociate, string sAssociateType, int bOn = TRUE); +// Return if nButton is set on oPlayer. Uses the BTN_* "Widget" bitwise constants. +int ai_GetWidgetButton(object oPlayer, int nButton, object oAssociate, string sAssociateType); +// Set one of the BTN_AI_* bitwise constants on oPlayer to bValid. +void ai_SetAIButton(object oPlayer, int nButton, object oAssociate, string sAssociateType, int bOn = TRUE); +// Return if nButton is set on oPlayer. Uses the BTN_AI_* "Widget" bitwise constants. +int ai_GetAIButton(object oPlayer, int nButton, object oAssociate, string sAssociateType); +// Set one of the BTN2_AI_* bitwise constants on oPlayer to bValid. +void ai_SetAIButton2(object oPlayer, int nButton, object oAssociate, string sAssociateType, int bOn = TRUE); +// Return if nButton is set on oPlayer. Uses the BTN2_AI_* "Widget" bitwise constants. +int ai_GetAIButton2(object oPlayer, int nButton, object oAssociate, string sAssociateType); +// Creates the json array required to build a companion drop down box for +// Animal Companions or Familiars. +// sCompanion2da should be either "hen_companion" or "hen_familiar". +json ai_CreateCompanionJson(object oPC, string sCompanion2da); +// Return any Metamagic or Domain attributes to place on a spell icon image. +string ai_GetSpellIconAttributes(object oCaster, int nMetaMagic, int nDomain); +// Creates the AI options menu. +void ai_CreateAIMainNUI(object oPC); +// Creates the AI options menu. +void ai_CreateAssociateCommandNUI(object oPC, object oAssociate); +// Creates an associates AI NUI. +void ai_CreateAssociateAINUI(object oPC, object oAssociate); +// Creates a widget for the player or associate. +void ai_CreateWidgetNUI(object oPC, object oAssociate); +// Creates the Loot filter menu. +void ai_CreateLootFilterNUI(object oPC, object oAssociate); +// Creates the Plugin Manager menu. +void ai_CreatePluginNUI(object oPC); +// Creates the Spell menu that selects the spells to go on the Spell Widget. +void ai_CreateQuickWidgetSelectionNUI(object oPC, object oAssociate); +// Creates the Spell menu that lets the player to select the associates castable spells. +void ai_CreateSpellMemorizationNUI(object oPC, object oAssociate); +// Creates the spell description menu so a player can see what a spell does. +// If nSpell > 0 then use that value for the spells description. +void ai_CreateDescriptionNUI(object oPC, json jSpell, int nSpell = 0); + +string ai_GetRandomTip() +{ + int nRoll; + if(AI_SERVER) nRoll = Random(26); + else nRoll = Random(46); + return Get2DAString("ai_messages", "Text", nRoll); +} +void ai_SetWidgetButton(object oPlayer, int nButton, object oAssociate, string sAssociateType, int bOn = TRUE) +{ + int nWidgetButtons = GetLocalInt(oAssociate, sWidgetButtonsVarname); + json jButtons = ai_GetAssociateDbJson(oPlayer, sAssociateType, "buttons"); + if(bOn) nWidgetButtons = nWidgetButtons | nButton; + else nWidgetButtons = nWidgetButtons & ~nButton; + SetLocalInt(oAssociate, sWidgetButtonsVarname, nWidgetButtons); + jButtons = JsonArraySet(jButtons, 0, JsonInt(nWidgetButtons)); + ai_SetAssociateDbJson(oPlayer, sAssociateType, "buttons", jButtons); +} +int ai_GetWidgetButton(object oPlayer, int nButton, object oAssociate, string sAssociateType) +{ + // This is the DM access switch that uses the same bitwise as the players + // to control what widget buttons they can use. + if(ai_GetDMWAccessButton(nButton)) return FALSE; + int nWidgetButtons = GetLocalInt(oAssociate, sWidgetButtonsVarname); + return nWidgetButtons & nButton; +} +void ai_SetAIButton(object oPlayer, int nButton, object oAssociate, string sAssociateType, int bOn = TRUE) +{ + int nAIButtons = GetLocalInt(oAssociate, sAIButtonsVarname); + json jButtons = ai_GetAssociateDbJson(oPlayer, sAssociateType, "buttons"); + if(bOn) nAIButtons = nAIButtons | nButton; + else nAIButtons = nAIButtons & ~nButton; + SetLocalInt(oAssociate, sAIButtonsVarname, nAIButtons); + jButtons = JsonArraySet(jButtons, 1, JsonInt(nAIButtons)); + ai_SetAssociateDbJson(oPlayer, sAssociateType, "buttons", jButtons); +} +int ai_GetAIButton(object oPlayer, int nButton, object oAssociate, string sAssociateType) +{ + // This is the DM access switch that uses the same bitwise as the players + // to control what AI widget buttons they can use. + if(ai_GetDMAIAccessButton(nButton)) return FALSE; + int nAIButtons = GetLocalInt(oAssociate, sAIButtonsVarname); + return nAIButtons & nButton; +} +json ai_CreateAIScriptJson(object oPC) +{ + json jScript = JsonArrayInsert(JsonArray(), NuiComboEntry("", 0)); + int nNth = 1; + string sScript = ResManFindPrefix("ai_a_", RESTYPE_NCS, nNth); + while(sScript != "") + { + jScript = JsonArrayInsert(jScript, NuiComboEntry(sScript, nNth)); + sScript = ResManFindPrefix("ai_a_", RESTYPE_NCS, ++nNth); + } + return jScript; +} +json ai_CreateCompanionJson(object oPC, string sCompanion2da) +{ + int nCnt, nMaxRowCount = Get2DARowCount(sCompanion2da); + string sName; + json jCompanion = JsonArray(); + while(nCnt < nMaxRowCount) + { + sName = GetStringByStrRef(StringToInt(Get2DAString(sCompanion2da, "STRREF", nCnt))); + jCompanion = JsonArrayInsert(jCompanion, NuiComboEntry(sName, nCnt++)); + } + return JsonArrayInsert(jCompanion, NuiComboEntry("Random", nCnt)); +} +string ai_GetSpellIconAttributes(object oCaster, int nMetaMagic, int nDomain) +{ + string sAttributeText; + if(nMetaMagic != METAMAGIC_ANY && nMetaMagic != METAMAGIC_NONE) + { + if(nMetaMagic == METAMAGIC_EXTEND) sAttributeText = "X"; + if(nMetaMagic == METAMAGIC_EMPOWER) sAttributeText = "P"; + if(nMetaMagic == METAMAGIC_MAXIMIZE) sAttributeText = "M"; + if(nMetaMagic == METAMAGIC_QUICKEN) sAttributeText = "Q"; + if(nMetaMagic == METAMAGIC_SILENT) sAttributeText = "I"; + if(nMetaMagic == METAMAGIC_STILL) sAttributeText = "T"; + } + else sAttributeText = ""; + if(nDomain > 0) sAttributeText += "D"; + return sAttributeText; +} +void ai_CreateAIMainNUI(object oPC) +{ + // Set window to not save until it has been created. + SetLocalInt (oPC, AI_NO_NUI_SAVE, TRUE); + DelayCommand (2.0, DeleteLocalInt (oPC, AI_NO_NUI_SAVE)); + int nMonsterAI = (ResManGetAliasFor("ai_default", RESTYPE_NCS) != ""); + int nAssociateAI = (ResManGetAliasFor("ai_a_default", RESTYPE_NCS) != ""); + string sText = " [Single player]"; + if(AI_SERVER) sText = " [Server]"; + // ************************************************************************* Width / Height + // Row 1 ******************************************************************* 500 / 73 + json jRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + jRow = CreateLabel(jRow, PHILOS_VERSION + sText, "lbl_version ", 510.0f, 20.0f, NUI_HALIGN_CENTER); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + // Add row to the column. + json jCol = JsonArrayInsert(JsonArray(), NuiRow(jRow)); + // Row 2 ******************************************************************* 500 / 101 + jRow = CreateLabel(JsonArray(), "", "lbl_ai_info", 510.0f, 20.0f, NUI_HALIGN_CENTER); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 3 ******************************************************************* 500 / 129 + jRow = CreateButton(JsonArray(), "Plugin Manager", "btn_plugin_manager", 120.0f, 20.0f, -1.0, "btn_plugin_manager_tooltip"); + if(nAssociateAI) jRow = CreateButtonSelect(jRow, "Associate Widgets", "btn_toggle_assoc_widget", 140.0f, 20.0f, "btn_assoc_widget_tooltip"); + jRow = CreateButtonSelect(jRow, "Action Ghost Mode", "btn_action_ghost", 160.0f, 20.0f, "btn_action_ghost_tooltip"); + jRow = CreateButtonSelect(jRow, "Effect Icons", "btn_effect_icon", 100.0f, 20.0f, "btn_effect_icon_tooltip"); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 4 ******************************************************************* 500 / 157 + jRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + jRow = CreateLabel(jRow, "MODULE RULES", "lbl_ai_rules", 200.0f, 20.0f, NUI_HALIGN_CENTER); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + float fHeight = 157.0; + // Row 5 ******************************************************************* 500 / --- (28) + // Make the AI options a Group. + json jGroupRow = CreateTextEditBox(JsonArray(), "sPlaceHolder", "txt_max_henchman", 2, FALSE, 30.0f, 20.0f, "txt_max_henchman_tooltip"); + jGroupRow = CreateLabel(jGroupRow, "Max number of henchmen that is allowed in your party.", "lbl_max_hench", 416.0f, 20.0f, NUI_HALIGN_LEFT, 0, -1.0, "txt_max_henchman_tooltip"); + json jGroupCol = JsonArrayInsert(JsonArray(), NuiRow(jGroupRow)); + jGroupRow = CreateTextEditBox(JsonArray(), "sPlaceHolder", "txt_xp_scale", 3, FALSE, 40.0f, 20.0f, "txt_xp_scale_tooltip"); + jGroupRow = CreateLabel(jGroupRow, "Modules experience scale.", "lbl_xp_scale", 175.0f, 20.0f, NUI_HALIGN_LEFT, 0, -1.0, "txt_xp_scale_tooltip"); + jGroupRow = CreateCheckBox(jGroupRow, " scale to party.", "chbx_party_scale", 150.0, 20.0, "chbx_party_scale_tooltip"); + jGroupRow = CreateButton(jGroupRow, "Default", "btn_default_xp", 70.0f, 20.0f, -1.0, "btn_default_xp_tooltip"); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + fHeight += 78.0; + if(nMonsterAI || nAssociateAI) + { + jGroupRow = CreateCheckBox(JsonArray(), " Creatures will use advanced combat movement.", "chbx_advanced_movement", 450.0, 20.0); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupRow = CreateCheckBox(JsonArray(), " Use item level restrictions for creatures [Default is off].", "chbx_ilr", 450.0, 20.0); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupRow = CreateCheckBox(JsonArray(), " Creatures can use the skill Use Magic Device.", "chbx_umd", 450.0, 20.0); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupRow = CreateCheckBox(JsonArray(), " Creatures can use Healing kits.", "chbx_use_healingkits", 450.0, 20.0); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupRow = CreateCheckBox(JsonArray(), " Moral checks, wounded creatures may flee during combat.", "chbx_moral", 450.0, 20.0); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupRow = CreateLabel(JsonArray(), " Spells the AI will not use:", "lbl_restrict_spells", 190.0, 20.0, NUI_HALIGN_LEFT); + jGroupRow = CreateCheckBox(jGroupRow, " Darkness", "chbx_darkness", 90.0, 20.0, "chbx_darkness_tooltip"); + jGroupRow = CreateCheckBox(jGroupRow, " Dispels", "chbx_dispels", 90.0, 20.0, "chbx_dispels_tooltip"); + jGroupRow = CreateCheckBox(jGroupRow, " Time Stop", "chbx_timestop", 90.0, 20.0, "chbx_timestop_tooltip"); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + fHeight += 196.0; + } + if(nMonsterAI) + { + jGroupRow = CreateTextEditBox(JsonArray(), "sPlaceHolder", "txt_ai_difficulty", 3, FALSE, 40.0f, 20.0f, "txt_ai_difficulty_tooltip"); + jGroupRow = CreateLabel(jGroupRow, "% chance monsters will attack the weakest target.", "lbl_ai_difficulty", 406.0f, 20.0f, NUI_HALIGN_LEFT, 0, -1.0, "txt_ai_difficulty_tooltip"); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupRow = CreateTextEditBox(JsonArray(), "sPlaceHolder", "txt_perception_distance", 2, FALSE, 35.0f, 20.0f, "txt_perception_distance_tooltip"); + jGroupRow = CreateLabel(jGroupRow, "meters is the distance a monster can respond to allies.", "lbl_perception_distance", 411.0f, 20.0f, NUI_HALIGN_LEFT, 0, 0.0, "txt_perception_distance_tooltip"); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupRow = CreateCheckBox(JsonArray(), " Monsters can prebuff before combat starts.", "chbx_buff_monsters", 450.0, 20.0); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupRow = CreateCheckBox(JsonArray(), " Monsters can use summons before combat starts.", "chbx_buff_summons", 450.0, 20.0); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupRow = CreateCheckBox(JsonArray(), " Monsters can use tactics (ambush, defensive, flanker, etc).", "chbx_ambush_monsters", 450.0, 20.0); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupRow = CreateLabel(JsonArray(), "Add ", "lbl_inc_enc", 30.0, 20.0, NUI_HALIGN_LEFT, 0, -1.0); + jGroupRow = CreateTextEditBox(jGroupRow, "sPlaceHolder", "txt_inc_enc", 4, FALSE, 55.0f, 20.0f, "txt_inc_enc_tooltip"); + jGroupRow = CreateLabel(jGroupRow, "monsters per spawned encounter monster.", "lbl_inc_enc", 357.0, 20.0, NUI_HALIGN_LEFT, NUI_VALIGN_MIDDLE, 0.0, "txt_inc_enc_tooltip"); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupRow = CreateTextEditBox(JsonArray(), "sPlaceHolder", "txt_inc_hp", 3, FALSE, 40.0f, 20.0f, "txt_inc_hp_tooltip"); + jGroupRow = CreateLabel(jGroupRow, "% increase in all monster's hitpoints.", "lbl_inc_hp", 406.0, 20.0, NUI_HALIGN_LEFT); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupRow = CreateLabel(JsonArray(), "***** WARNING! The options below may break the module! *****", "lbl_warning", 450.0f, 20.0f, NUI_HALIGN_LEFT, 0, 0.0, "chbx_warning_tooltip"); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupRow = CreateCheckBox(JsonArray(), " Monsters can wander upto ", "chbx_wander", 220.0, 20.0, "chbx_warning_tooltip"); + jGroupRow = CreateTextEditBox(jGroupRow, "sPlaceHolder", "txt_wander_distance", 2, FALSE, 35.0f, 20.0f, "chbx_warning_tooltip"); + jGroupRow = CreateLabel(jGroupRow, "meters and ", "lbl_wander_distance", 80.0f, 20.0f, NUI_HALIGN_LEFT, NUI_VALIGN_MIDDLE, 0.0, "chbx_warning_tooltip"); + jGroupRow = CreateCheckBox(jGroupRow, "open doors.", "chbx_open_doors", 100.0, 20.0, "chbx_warning_tooltip"); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupRow = CreateCheckBox(JsonArray(), " Monsters can summon companions.", "chbx_companions", 450.0, 20.0, "chbx_warning_tooltip"); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupRow = CreateCheckBox(JsonArray(), " Summoned associates to remain after masters death.", "chbx_perm_assoc", 450.0, 20.0, "chbx_warning_tooltip"); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupRow = CreateCheckBox(JsonArray(), " Make enemy corpses remain.", "chbx_corpses_stay", 450.0, 20.0, "chbx_warning_tooltip"); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupRow = CreateLabel(JsonArray(), "", "lbl_perc_dist", 450.0f, 20.0f, NUI_HALIGN_LEFT, 0, 0.0, "lbl_perc_dist_tooltip"); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + fHeight += 336.0; + } + jRow = JsonArrayInsert(JsonArray(), NuiGroup(NuiCol(jGroupCol))); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Get the window location to restore it from the database. + json jLocations = ai_GetAssociateDbJson(oPC, "pc", "locations"); + jLocations = JsonObjectGet(jLocations, AI_MAIN_NUI); + float fX = JsonGetFloat(JsonObjectGet(jLocations, "x")); + float fY = JsonGetFloat(JsonObjectGet(jLocations, "y")); + // Set the Layout of the window. + json jLayout = NuiCol(jCol); + string sName = GetName(oPC); + if(GetStringRight(sName, 1) == "s") sName = sName + "'"; + else sName = sName + "'s"; + int nToken = SetWindow(oPC, jLayout, AI_MAIN_NUI, sName + " PEPS Main Menu", + fX, fY, 534.0f, fHeight, FALSE, FALSE, TRUE, FALSE, TRUE, "0e_nui"); + // Save the associate to the nui for use in 0e_nui + json jData = JsonArray(); + jData = JsonArrayInsert(jData, JsonString(ObjectToString(oPC))); + NuiSetUserData(oPC, nToken, jData); + object oModule = GetModule(); + // Set event watches for save window location. + NuiSetBindWatch(oPC, nToken, "window_geometry", TRUE); + // Set all binds, events, and watches. + // Row 1 - Version label. + // Row 2 + int nUsing; + // Check the monster AI. + string sLocation = ResManGetAliasFor("ai_default", RESTYPE_NCS); + if(sLocation != "") + { + nUsing = TRUE; + string sLocation = ResManGetAliasFor("nw_c2_default1", RESTYPE_NCS); + if(sLocation != "OVERRIDE:" && sLocation != "PATCH:peps" && sLocation != "DEVELOPMENT:") nUsing = FALSE; + if(nUsing) sText = "Monster AI working"; + else sText = "Monster AI not working"; + } + else sText = "Monster AI not loaded"; + // Check the associate AI. + sLocation = ResManGetAliasFor("ai_a_default", RESTYPE_NCS); + if(sLocation != "") + { + nUsing = TRUE; + string sLocation = ResManGetAliasFor("nw_ch_ac1", RESTYPE_NCS); + if(sLocation != "OVERRIDE:" && sLocation != "PATCH:peps" && sLocation != "DEVELOPMENT:") nUsing = FALSE; + if(nUsing) sText += ", Associate AI working"; + else sText += ", Associate AI not working"; + } + else sText += ", Associate AI not loaded"; + // Check for PRC. + sLocation = ResManGetAliasFor("prc_ai_fam_percp", RESTYPE_NCS); + if(sLocation != "") sText += ", PRC loaded."; + else + { + // Check the player AI. + sLocation = ResManGetAliasFor("xx_pc_1_hb", RESTYPE_NCS); + if(sLocation != "") sText += ", Player AI loaded."; + else sText += ", Player AI not loaded."; + } + NuiSetBind(oPC, nToken, "lbl_ai_info_label", JsonString(sText)); + // Row 3 + NuiSetBind(oPC, nToken, "btn_plugin_manager_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_plugin_manager_tooltip", JsonString(" Manages external executable scripts.")); + if(nAssociateAI) + { + NuiSetBind(oPC, nToken, "btn_toggle_assoc_widget_event", JsonBool(TRUE)); + int bWidgetOn = !ai_GetWidgetButton(oPC, BTN_WIDGET_OFF, OBJECT_INVALID, "pc"); + NuiSetBind(oPC, nToken, "btn_toggle_assoc_widget", JsonBool(bWidgetOn)); + NuiSetBind(oPC, nToken, "btn_assoc_widget_tooltip", JsonString(" Turns On/Off all associate widgets.")); + } + int bActionGhost = ai_GetAIMode(oPC, AI_MODE_ACTION_GHOST); + NuiSetBind(oPC, nToken, "btn_action_ghost", JsonBool (bActionGhost)); + NuiSetBind(oPC, nToken, "btn_action_ghost_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_action_ghost_tooltip", JsonString(" Allows associates to move through creatures while in command mode.")); + int bEffectIcon = ai_GetMagicMode(oPC, AI_MAGIC_EFFECT_ICON_REPORT); + NuiSetBind(oPC, nToken, "btn_effect_icon", JsonBool (bEffectIcon)); + NuiSetBind(oPC, nToken, "btn_effect_icon_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_effect_icon_tooltip", JsonString(" When on sends effect icon reports to the chat screen.")); + // Row 3 Label for AI RULES + // Row 4 + NuiSetBind(oPC, nToken, "txt_max_henchman", JsonString(IntToString(GetLocalInt(oModule, AI_RULE_MAX_HENCHMAN)))); + NuiSetBindWatch (oPC, nToken, "txt_max_henchman", TRUE); + NuiSetBind(oPC, nToken, "txt_max_henchman_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "txt_max_henchman_tooltip", JsonString(" Set max number of henchman allowed (1-12).")); + NuiSetBind(oPC, nToken, "txt_xp_scale", JsonString(IntToString(GetModuleXPScale()))); + NuiSetBindWatch (oPC, nToken, "txt_xp_scale", TRUE); + NuiSetBind(oPC, nToken, "txt_xp_scale_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "txt_xp_scale_tooltip", JsonString(" Set the modules XP scale (0 - 200) Normal D&D is 10.")); + NuiSetBind(oPC, nToken, "chbx_party_scale_check", JsonBool(GetLocalInt(oModule, AI_RULE_PARTY_SCALE))); + NuiSetBindWatch(oPC, nToken, "chbx_party_scale_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_party_scale_event", JsonBool(TRUE)); + sText = IntToString(GetLocalInt(oModule, AI_BASE_PARTY_SCALE_XP)); + NuiSetBind(oPC, nToken, "chbx_party_scale_tooltip", JsonString(" PEPS adjusts your XP based on party size from (" + sText + ").")); + NuiSetBind(oPC, nToken, "btn_default_xp_event", JsonBool(TRUE)); + sText = IntToString(GetLocalInt(oModule, AI_RULE_DEFAULT_XP_SCALE)); + NuiSetBind(oPC, nToken, "btn_default_xp_tooltip", JsonString(" Reset the Modules XP to (" + sText + ").")); + NuiSetBind(oPC, nToken, "chbx_warning_tooltip", JsonString(" ** This will break some modules! ** See Readme for issues!")); + if(nMonsterAI) + { + NuiSetBind(oPC, nToken, "txt_ai_difficulty", JsonString(IntToString(GetLocalInt(oModule, AI_RULE_AI_DIFFICULTY)))); + NuiSetBindWatch(oPC, nToken, "txt_ai_difficulty", TRUE); + NuiSetBind(oPC, nToken, "txt_ai_difficulty_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "chbx_buff_monsters_check", JsonBool(GetLocalInt(oModule, AI_RULE_BUFF_MONSTERS))); + NuiSetBindWatch(oPC, nToken, "chbx_buff_monsters_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_buff_monsters_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "chbx_buff_summons_check", JsonBool(GetLocalInt(oModule, AI_RULE_PRESUMMON))); + NuiSetBindWatch(oPC, nToken, "chbx_buff_summons_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_buff_summons_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "chbx_ambush_monsters_check", JsonBool(GetLocalInt(oModule, AI_RULE_AMBUSH))); + NuiSetBindWatch(oPC, nToken, "chbx_ambush_monsters_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_ambush_monsters_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "chbx_companions_check", JsonBool(GetLocalInt(oModule, AI_RULE_SUMMON_COMPANIONS))); + NuiSetBindWatch(oPC, nToken, "chbx_companions_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_companions_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "chbx_perm_assoc_check", JsonBool(GetLocalInt(oModule, AI_RULE_PERM_ASSOC))); + string sModuleName = GetModuleName(); + if(!GetLocalInt(oModule, AI_USING_PRC) && + (sModuleName != "Neverwinter Nights - Infinite Dungeons" || + sModuleName != "Infinite Dungeons [PRC8]")) + { + NuiSetBindWatch(oPC, nToken, "chbx_perm_assoc_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_perm_assoc_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "chbx_corpses_stay_check", JsonBool(GetLocalInt(oModule, AI_RULE_CORPSES_STAY))); + NuiSetBindWatch(oPC, nToken, "chbx_corpses_stay_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_corpses_stay_event", JsonBool(TRUE)); + } + NuiSetBind(oPC, nToken, "txt_perception_distance", JsonString(FloatToString(GetLocalFloat(oModule, AI_RULE_PERCEPTION_DISTANCE), 0, 0))); + NuiSetBindWatch(oPC, nToken, "txt_perception_distance", TRUE); + NuiSetBind(oPC, nToken, "txt_perception_distance_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "txt_perception_distance_tooltip", JsonString(" Range [10 to 60 meters] from the player.")); + NuiSetBindWatch(oPC, nToken, "lbl_perc_dist", TRUE); + int nPercDist = GetLocalInt(oModule, AI_RULE_MON_PERC_DISTANCE); + if(nPercDist < 8 || nPercDist > 11) + { + nPercDist = 11; + SetLocalInt(oModule, AI_RULE_MON_PERC_DISTANCE, 11); + } + if(nPercDist == 8) sText = " Monster perception: Short [10 Sight / 10 Listen]"; + else if(nPercDist == 9) sText = " Monster perception: Medium [20 Sight / 20 Listen]"; + else if(nPercDist == 10) sText = " Monster perception: Long [35 Sight / 20 Listen]"; + else sText = " Monster perception: Default [Monster's default values]"; + NuiSetBind(oPC, nToken, "lbl_perc_dist_label", JsonString(sText)); + NuiSetBind(oPC, nToken, "lbl_perc_dist_tooltip", JsonString(" Use the mouse wheel to change values.")); + int bWander = GetLocalInt(oModule, AI_RULE_WANDER); + NuiSetBind(oPC, nToken, "chbx_wander_check", JsonBool(bWander)); + NuiSetBindWatch(oPC, nToken, "chbx_wander_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_wander_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "txt_wander_distance", JsonString(FloatToString(GetLocalFloat(oModule, AI_RULE_WANDER_DISTANCE), 0, 0))); + NuiSetBindWatch(oPC, nToken, "txt_wander_distance", TRUE); + NuiSetBind(oPC, nToken, "txt_wander_distance_event", JsonBool(bWander)); + NuiSetBind(oPC, nToken, "chbx_open_doors_check", JsonBool(GetLocalInt(oModule, AI_RULE_OPEN_DOORS))); + NuiSetBindWatch(oPC, nToken, "chbx_open_doors_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_open_doors_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "chbx_open_doors_tooltip", JsonString(" This allows monsters to open doors to hunt you down!")); + NuiSetBind(oPC, nToken, "txt_inc_enc_tooltip", JsonString(" Spawns one extra monster per counter above 1. Adds value to counter per encounter monster spawned.")); + NuiSetBind(oPC, nToken, "txt_inc_enc", JsonString(FloatToString(GetLocalFloat(oModule, AI_INCREASE_ENC_MONSTERS), 0, 2))); + NuiSetBindWatch(oPC, nToken, "txt_inc_enc", TRUE); + NuiSetBind(oPC, nToken, "txt_inc_enc_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "txt_inc_hp", JsonString(IntToString(GetLocalInt(oModule, AI_INCREASE_MONSTERS_HP)))); + NuiSetBindWatch(oPC, nToken, "txt_inc_hp", TRUE); + NuiSetBind(oPC, nToken, "txt_inc_hp_event", JsonBool(TRUE)); + } + if(nMonsterAI || nAssociateAI) + { + NuiSetBind(oPC, nToken, "chbx_moral_check", JsonBool(GetLocalInt(oModule, AI_RULE_MORAL_CHECKS))); + NuiSetBindWatch (oPC, nToken, "chbx_moral_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_moral_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "chbx_advanced_movement_check", JsonBool(GetLocalInt(oModule, AI_RULE_ADVANCED_MOVEMENT))); + NuiSetBindWatch (oPC, nToken, "chbx_advanced_movement_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_advanced_movement_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "chbx_ilr_check", JsonBool(GetLocalInt(oModule, AI_RULE_ILR))); + NuiSetBindWatch (oPC, nToken, "chbx_ilr_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_ilr_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "chbx_umd_check", JsonBool(GetLocalInt(oModule, AI_RULE_ALLOW_UMD))); + NuiSetBindWatch (oPC, nToken, "chbx_umd_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_umd_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "chbx_use_healingkits_check", JsonBool(GetLocalInt(oModule, AI_RULE_HEALERSKITS))); + NuiSetBindWatch (oPC, nToken, "chbx_use_healingkits_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_use_healingkits_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "chbx_darkness_check", JsonBool(ai_SpellRestricted(SPELL_DARKNESS))); + NuiSetBindWatch (oPC, nToken, "chbx_darkness_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_darkness_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "chbx_darkness_tooltip", JsonString(" AI will not use the Darkness spell in combat.")); + NuiSetBind(oPC, nToken, "chbx_dispels_check", JsonBool(ai_SpellRestricted(SPELL_DISPEL_MAGIC))); + NuiSetBindWatch (oPC, nToken, "chbx_dispels_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_dispels_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "chbx_dispels_tooltip", JsonString(" AI will not use any of the Dispel spells in combat.")); + NuiSetBind(oPC, nToken, "chbx_timestop_check", JsonBool(ai_SpellRestricted(SPELL_TIME_STOP))); + NuiSetBindWatch (oPC, nToken, "chbx_timestop_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_timestop_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "chbx_timestop_tooltip", JsonString(" AI will not use the Time Stop spell in combat.")); + } +} +void ai_CreateAssociateCommandNUI(object oPC, object oAssociate) +{ + // Set window to not save until it has been created. + SetLocalInt (oPC, AI_NO_NUI_SAVE, TRUE); + DelayCommand (2.0, DeleteLocalInt (oPC, AI_NO_NUI_SAVE)); + int bRight, bLeft; + int bIsPC = ai_GetIsCharacter(oAssociate); + int bUsingPCAI = ResManGetAliasFor("xx_pc_1_hb", RESTYPE_NCS) != ""; + int bUsingHenchAI = ResManGetAliasFor("nw_ch_ac1", RESTYPE_NCS) != ""; + float fHeight = 73.0; + // ************************************************************************* Width / Height + // Row 1 ******************************************************************* 500 / 73 + json jRow = JsonArray(); + json jCol = JsonArray(); + // If all the AI buttons are blocked then don't load the menu. + if(GetLocalInt(GetModule(), sDMAIAccessVarname) != 203423743) + { + if(bIsPC) + { + if(bUsingPCAI || !AI_SERVER) + { + if(bUsingPCAI) + { + jRow = CreateButton(jRow, "AI Menu", "btn_ai_menu", 232.0, 20.0, -1.0, "btn_ai_menu_tooltip"); + } + if(!AI_SERVER) + { + jRow = CreateButton(jRow, "Main Menu", "btn_main_menu", 232.0, 20.0, -1.0, "btn_main_menu_tooltip"); + } + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight += 28.0; + } + } + else + { + if(bUsingHenchAI) + { + jRow = CreateButton(jRow, "AI Menu", "btn_ai_menu", 232.0, 20.0, -1.0, "btn_ai_menu_tooltip"); + } + jRow = CreateButtonSelect(jRow, "", "btn_widget_onoff", 232.0, 20.0, "btn_widget_onoff_tooltip"); + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight += 28.0; + } + } + // Row 2 ******************************************************************* 500 / 101 + jRow = JsonArray(); + jRow = CreateButtonSelect(jRow, "Lock Widget", "btn_widget_lock", 154.0, 20.0, "btn_widget_lock_tooltip"); + jRow = CreateButton(jRow, "Copy Settings", "btn_copy_settings", 154.0, 20.0, -1.0, "btn_copy_settings_tooltip"); + jRow = CreateButtonSelect(jRow, "Vertical Widget", "btn_vertical_widget", 154.0, 20.0, "btn_vertical_widget_tooltip"); + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 3 ******************************************************************* 500 / 129 + bRight = !ai_GetDMWAccessButton(BTN_CMD_ACTION); + bLeft = !ai_GetDMWAccessButton(BTN_CMD_GUARD); + if(bRight || bLeft) + { + jRow = JsonArray(); + if(bRight) + { + jRow = CreateButton(jRow, "", "btn_cmd_action", 200.0, 20.0, -1.0, "btn_cmd_action_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_cmd_action", 25.0, 20.0); + } + jRow = JsonArrayInsert(jRow, NuiSpacer()); + if(bLeft) + { + jRow = CreateButton(jRow, "", "btn_cmd_guard", 200.0, 20.0, -1.0, "btn_cmd_guard_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_cmd_guard", 25.0, 20.0); + } + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight += 28.0; + } + // Row 4 ******************************************************************* 500 / 157 + jRow = JsonArray(); + bRight = !ai_GetDMWAccessButton(BTN_CMD_HOLD); + bLeft = !ai_GetDMWAccessButton(BTN_CMD_ATTACK); + if(bRight || bLeft) + { + jRow = JsonArray(); + if(bRight) + { + jRow = CreateButton(jRow, "", "btn_cmd_hold", 200.0, 20.0, -1.0, "btn_cmd_hold_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_cmd_hold", 25.0, 20.0); + } + jRow = JsonArrayInsert(jRow, NuiSpacer()); + if(bLeft) + { + jRow = CreateButton(jRow, "", "btn_cmd_attack", 200.0, 20.0, -1.0, "btn_cmd_attack_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_cmd_attack", 25.0, 20.0); + } + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight += 28.0; + } + // Row 5 ******************************************************************* 500 / 213 + bRight = !ai_GetDMWAccessButton(BTN_CMD_FOLLOW); + bLeft = !ai_GetDMAIAccessButton(BTN_AI_FOLLOW_TARGET); + if(bRight || bLeft) + { + jRow = JsonArray(); + if(bRight) + { + jRow = CreateButton(jRow, "", "btn_cmd_follow", 200.0, 20.0, -1.0, "btn_cmd_follow_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_cmd_follow", 25.0, 20.0); + } + jRow = JsonArrayInsert(jRow, NuiSpacer()); + if(bLeft) + { + jRow = CreateButton(jRow, "Select follow target", "btn_follow_target", 200.0, 20.0, -1.0, "btn_follow_target_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_follow_target", 25.0, 20.0); + } + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight += 28.0; + } + // Row 6 ******************************************************************* 500 / 185 + if(bIsPC) + { + bRight = !ai_GetDMWAccessButton(BTN_CMD_SEARCH); + bLeft = !ai_GetDMWAccessButton(BTN_CMD_STEALTH); + if(bRight || bLeft) + { + jRow = JsonArray(); + if(bRight) + { + jRow = CreateButton(jRow, "All Search Mode", "btn_cmd_search", 200.0, 20.0, -1.0, "btn_cmd_search_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_cmd_search", 25.0, 20.0); + } + jRow = JsonArrayInsert(jRow, NuiSpacer()); + if(bLeft) + { + jRow = CreateButton(jRow, "All Stealth Mode", "btn_cmd_stealth", 200.0, 20.0, -1.0, "btn_cmd_stealth_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_cmd_stealth", 25.0, 20.0); + } + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight = fHeight + 28.0; + } + } + // Row 7 ******************************************************************* 500 / 241 + bRight = !ai_GetDMWAccessButton(BTN_CMD_AI_SCRIPT); + bLeft = !ai_GetDMWAccessButton(BTN_CMD_PLACE_TRAP); + if(bRight || bLeft) + { + jRow = JsonArray(); + if(bRight) + { + jRow = CreateButton(jRow, "Combat Tactics", "btn_cmd_ai_script", 200.0, 20.0, -1.0, "btn_cmd_ai_script_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_cmd_ai_script", 25.0, 20.0); + } + jRow = JsonArrayInsert(jRow, NuiSpacer()); + if(bLeft) + { + jRow = CreateButton(jRow, "Place a Trap", "btn_cmd_place_trap", 200.0, 20.0, -1.0, "btn_cmd_place_trap_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_cmd_place_trap", 25.0, 20.0); + } + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight = fHeight + 28.0; + } + // Row 8 ******************************************************************* 500 / --- + int bMemorize = ai_GetIsSpellCaster(oAssociate); + int bSpellbook = ai_GetIsSpellBookRestrictedCaster(oAssociate); + bRight = !ai_GetDMWAccessButton(BTN_CMD_SPELL_WIDGET); + bLeft = !ai_GetDMWAccessButton(BTN_DM_CMD_MEMORIZE); + if(bRight || bLeft) + { + jRow = JsonArray(); + if(bRight) + { + jRow = CreateButton(jRow, "Set Quick Widget", "btn_quick_widget", 200.0, 20.0, -1.0, "btn_quick_widget_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_quick_widget", 25.0, 20.0); + } + jRow = JsonArrayInsert(jRow, NuiSpacer()); + if(bLeft) // Memorizes their spells. + { + if(bMemorize == 2 && bSpellbook) + { + jRow = CreateButton(jRow, "Memorize Spells", "btn_spell_memorize", 114.0, 20.0, -1.0, "btn_spell_memorize_tooltip"); + jRow = CreateButton(jRow, "Known Spells", "btn_spell_known", 110.0, 20.0, -1.0, "btn_spell_known_tooltip"); + } + else if(bMemorize == 2) + { + jRow = CreateButton(jRow, "Set Memorize Spells", "btn_spell_memorize", 200.0, 20.0, -1.0, "btn_spell_memorize_tooltip"); + jRow = CreateLabel(jRow, "", "blank_label_1", 25.0, 20.0); + } + else if(bSpellbook && !ai_GetIsCharacter(oAssociate)) + { + jRow = CreateButton(jRow, "Set Known Spells", "btn_spell_known", 200.0, 20.0, -1.0, "btn_spell_known_tooltip"); + jRow = CreateLabel(jRow, "", "blank_label_1", 25.0, 20.0); + } + } + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight = fHeight + 28.0; + } + // Row 9 ******************************************************************* 500 / 269 + bRight = !ai_GetDMWAccessButton(BTN_BUFF_SHORT); + bLeft = !ai_GetDMWAccessButton(BTN_BUFF_LONG); + if(bRight || bLeft) + { + jRow = JsonArray(); + if(bRight) + { + jRow = CreateButton(jRow, "Cast Short Buff spells", "btn_buff_short", 200.0, 20.0, -1.0, "btn_buff_short_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_buff_short", 25.0, 20.0); + } + jRow = JsonArrayInsert(jRow, NuiSpacer()); + if(bLeft) + { + jRow = CreateButton(jRow, "Cast Long Buff spells", "btn_buff_long", 200.0, 20.0, -1.0, "btn_buff_long_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_buff_long", 25.0, 20.0); + } + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight = fHeight + 28.0; + } + // Row 10 ******************************************************************* 500 / 297 + bRight = !ai_GetDMWAccessButton(BTN_BUFF_ALL); + bLeft = !ai_GetDMWAccessButton(BTN_BUFF_REST); + if(bRight || bLeft) + { + jRow = JsonArray(); + if(bRight) + { + jRow = CreateButton(jRow, "Cast All Buff spells", "btn_buff_all", 200.0, 20.0, -1.0, "btn_buff_all_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_buff_all", 25.0, 20.0); + } + jRow = JsonArrayInsert(jRow, NuiSpacer()); + if(bLeft) + { + jRow = CreateButton(jRow, "Buff after resting", "btn_buff_rest", 200.0, 20.0, -1.0, "btn_buff_rest_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_buff_rest", 25.0, 20.0); + } + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight = fHeight + 28.0; + } + // Row 11 ******************************************************************* 500 / 325 + bRight = !ai_GetDMWAccessButton(BTN_CMD_JUMP_TO); + bLeft = !ai_GetDMWAccessButton(BTN_CMD_GHOST_MODE); + if(bRight || bLeft) + { + jRow = JsonArray(); + if(bRight) + { + jRow = CreateButton(jRow, "", "btn_jump_to", 200.0, 20.0, -1.0, "btn_jump_to"); + jRow = CreateCheckBox(jRow, "", "chbx_jump_to", 25.0, 20.0); + } + jRow = JsonArrayInsert(jRow, NuiSpacer()); + if(bLeft) + { + jRow = CreateButton(jRow, "Ghost Mode", "btn_ghost_mode", 200.0, 20.0, -1.0, "btn_ghost_mode_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_ghost_mode", 25.0, 20.0); + } + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight = fHeight + 28.0; + } + // Row 12 ****************************************************************** 500 / 353 + bRight = !ai_GetDMWAccessButton(BTN_CMD_CAMERA); + bLeft = !ai_GetDMWAccessButton(BTN_CMD_INVENTORY); + if(bRight || bLeft) + { + jRow = JsonArray(); + if(bRight) + { + jRow = CreateButton(jRow, "Toggle Camera Focus", "btn_camera", 200.0, 20.0, -1.0, "btn_camera_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_camera", 25.0, 20.0); + } + jRow = JsonArrayInsert(jRow, NuiSpacer()); + if(bLeft) + { + jRow = CreateButton(jRow, "Open/Close Inventory", "btn_inventory", 200.0, 20.0, -1.0, "btn_inventory_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_inventory", 25.0, 20.0); + } + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight = fHeight + 28.0; + } + // Row 13 ******************************************************************* 500 / --- + int bFamiliar = GetHasFeat(FEAT_SUMMON_FAMILIAR, oAssociate, TRUE); + if(!ai_GetDMWAccessButton(BTN_CMD_FAMILIAR) && bFamiliar) + { + jRow = JsonArray(); + jRow = CreateLabel(jRow, "", "lbl_familiar_type", 225.0, 20.0); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateLabel(jRow, "", "lbl_familiar_name", 225.0, 20.0); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight = fHeight + 28.0; + // Row 14 ******************************************************************* 500 / --- + jRow = JsonArray(); + jRow = CreateCombo(jRow, ai_CreateCompanionJson(oPC, "hen_familiar"), "cmb_familiar", 200.0, 20.0); + jRow = CreateCheckBox(jRow, "", "chbx_familiar", 25.0, 20.0); + jRow = CreateTextEditBox(jRow, "txtbox", "txt_familiar_name", 50, FALSE, 178.0, 20.0); + jRow = CreateButton(jRow, "", "btn_familiar_name", 55.0, 20.0); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight = fHeight + 28.0; + } + // Row 15 ******************************************************************* 500 / --- + int bCompanion = GetHasFeat(FEAT_ANIMAL_COMPANION, oAssociate, TRUE); + if(!ai_GetDMWAccessButton(BTN_CMD_COMPANION) && bCompanion) + { + jRow = JsonArray(); + jRow = CreateLabel(jRow, "", "lbl_companion_type", 225.0, 20.0); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateLabel(jRow, "", "lbl_companion_name", 225.0, 20.0); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight = fHeight + 28.0; + // Row 16 ******************************************************************* 500 / --- + jRow = JsonArray(); + jRow = CreateCombo(jRow, ai_CreateCompanionJson(oPC, "hen_companion"), "cmb_companion", 200.0, 20.0); + jRow = CreateCheckBox(jRow, "", "chbx_companion", 25.0, 20.0); + jRow = CreateTextEditBox(jRow, "txtbox", "txt_companion_name", 50, FALSE, 178.0, 20.0); + jRow = CreateButton(jRow, "", "btn_companion_name", 55.0, 20.0); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight = fHeight + 28.0; + } + // Row 17+ ****************************************************************** 500 / --- + string sAssociateType = ai_GetAssociateType(oPC, oAssociate); + json jPCPlugins; + if(bIsPC) + { + jPCPlugins = ai_UpdatePluginsForPC(oPC); + // Set the plugins the player can use. + int nIndex; + string sButton, sName; + json jPlugin = JsonArrayGet(jPCPlugins, nIndex); + while(JsonGetType(jPlugin) != JSON_TYPE_NULL) + { + jRow = JsonArray(); + sButton = IntToString(nIndex); + sName = JsonGetString(JsonArrayGet(jPlugin, 2)); + jRow = CreateButton(jRow, sName, "btn_plugin_" + sButton, 200.0f, 20.0f, -1.0, "btn_plugin_" + sButton + "_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_plugin_" + sButton, 25.0, 20.0, "chbx_plugin_tooltip"); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jPlugin = JsonArrayGet(jPCPlugins, ++nIndex); + if(JsonGetType(jPlugin) != JSON_TYPE_NULL) + { + sButton = IntToString(nIndex); + sName = JsonGetString(JsonArrayGet(jPlugin, 2)); + jRow = CreateButton(jRow, sName, "btn_plugin_" + sButton, 200.0f, 20.0f, -1.0, "btn_plugin_" + sButton + "_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_plugin_" + sButton, 25.0, 20.0, "chbx_plugin_tooltip"); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight += 28.0; + } + else + { + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight += 28.0; + break; + } + jPlugin = JsonArrayGet(jPCPlugins, ++nIndex); + } + } + // Row 18 ****************************************************************** 500 / --- + jRow = JsonArray(); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateLabel(jRow, "", "lbl_info_1", 475.0, 20.0, NUI_HALIGN_CENTER); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight = fHeight + 28.0; + // Get the window location to restore it from the database. + float fX, fY; + json jLocations = ai_GetAssociateDbJson(oPC, sAssociateType, "locations"); + jLocations = JsonObjectGet(jLocations, sAssociateType + AI_COMMAND_NUI); + if(JsonGetType(jLocations) == JSON_TYPE_NULL) { fX = -1.0; fY = -1.0; } + else + { + fX = JsonGetFloat(JsonObjectGet(jLocations, "x")); + fY = JsonGetFloat(JsonObjectGet(jLocations, "y")); + } + // Set the Layout of the window. + json jLayout = NuiCol(jCol); + string sName = GetName(oAssociate); + if(GetStringRight(sName, 1) == "s") sName = sName + "'"; + else sName = sName + "'s"; + int nToken = SetWindow(oPC, jLayout, sAssociateType + AI_COMMAND_NUI, sName + " Command Menu", + fX, fY, 500.0, fHeight + 12.0, FALSE, FALSE, TRUE, FALSE, TRUE, "0e_nui"); + // Get which buttons are activated. + int bAIWidgetLock = ai_GetWidgetButton(oPC, BTN_WIDGET_LOCK, oAssociate, sAssociateType); + int bCmdAction = ai_GetWidgetButton(oPC, BTN_CMD_ACTION, oAssociate, sAssociateType); + int bCmdGuard = ai_GetWidgetButton(oPC, BTN_CMD_GUARD, oAssociate, sAssociateType); + int bCmdHold = ai_GetWidgetButton(oPC, BTN_CMD_HOLD, oAssociate, sAssociateType); + int bCmdSearch = ai_GetWidgetButton(oPC, BTN_CMD_SEARCH, oAssociate, sAssociateType); + int bCmdStealth = ai_GetWidgetButton(oPC, BTN_CMD_STEALTH, oAssociate, sAssociateType); + int bCmdAttack = ai_GetWidgetButton(oPC, BTN_CMD_ATTACK, oAssociate, sAssociateType); + int bCmdFollow = ai_GetWidgetButton(oPC, BTN_CMD_FOLLOW, oAssociate, sAssociateType); + int bFollowTarget = ai_GetAIButton(oPC, BTN_AI_FOLLOW_TARGET, oAssociate, sAssociateType); + int bCmdAIScript = ai_GetWidgetButton(oPC, BTN_CMD_AI_SCRIPT, oAssociate, sAssociateType); + int bCmdPlacetrap = ai_GetWidgetButton(oPC, BTN_CMD_PLACE_TRAP, oAssociate, sAssociateType); + int bSpellWidget = ai_GetWidgetButton(oPC, BTN_CMD_SPELL_WIDGET, oAssociate, sAssociateType); + int bBuffRest = ai_GetWidgetButton(oPC, BTN_BUFF_REST, oAssociate, sAssociateType); + int bBuffShort = ai_GetWidgetButton(oPC, BTN_BUFF_SHORT, oAssociate, sAssociateType); + int bBuffLong = ai_GetWidgetButton(oPC, BTN_BUFF_LONG, oAssociate, sAssociateType); + int bBuffAll = ai_GetWidgetButton(oPC, BTN_BUFF_ALL, oAssociate, sAssociateType); + int bJumpTo = ai_GetWidgetButton(oPC, BTN_CMD_JUMP_TO, oAssociate, sAssociateType); + int bGhostMode = ai_GetWidgetButton(oPC, BTN_CMD_GHOST_MODE, oAssociate, sAssociateType); + int bCamera = ai_GetWidgetButton(oPC, BTN_CMD_CAMERA, oAssociate, sAssociateType); + int bInventory = ai_GetWidgetButton(oPC, BTN_CMD_INVENTORY, oAssociate, sAssociateType); + int bBtnFamiliar = ai_GetWidgetButton(oPC, BTN_CMD_FAMILIAR, oAssociate, sAssociateType); + int bBtnCompanion = ai_GetWidgetButton(oPC, BTN_CMD_COMPANION, oAssociate, sAssociateType); + int bVertical = ai_GetWidgetButton(oPC, BTN_WIDGET_VERTICAL, oAssociate, sAssociateType); + // Save the associate to the nui for use in 0e_nui + json jData = JsonArray(); + jData = JsonArrayInsert(jData, JsonString(ObjectToString(oAssociate))); + NuiSetUserData(oPC, nToken, jData); + // Set event watches for save window location. + NuiSetBindWatch(oPC, nToken, "window_geometry", TRUE); + // Set all binds, events, and watches. + string sText; + // Row 1 + // If all the AI buttons are blocked then don't load the menu. + if(GetLocalInt(GetModule(), sDMAIAccessVarname) != 203423743) + { + if(bIsPC) + { + if(bUsingPCAI) + { + NuiSetBind(oPC, nToken, "btn_ai_menu_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "btn_ai_menu_tooltip", JsonString(" " + sName + " AI options")); + } + NuiSetBind(oPC, nToken, "btn_copy_settings_event", JsonBool (TRUE)); + sText = " Copy AI and command settings for one creature to others."; + NuiSetBind(oPC, nToken, "btn_copy_settings_tooltip", JsonString(sText)); + if(!AI_SERVER) + { + NuiSetBind(oPC, nToken, "btn_main_menu_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_main_menu_tooltip", JsonString(" Module Options")); + } + } + else + { + if(bUsingHenchAI) + { + NuiSetBind(oPC, nToken, "btn_ai_menu_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "btn_ai_menu_tooltip", JsonString(" " + sName + " AI options")); + } + NuiSetBind(oPC, nToken, "btn_copy_settings_event", JsonBool (TRUE)); + sText = " Copy AI and command settings for one creature to others."; + NuiSetBind(oPC, nToken, "btn_copy_settings_tooltip", JsonString(sText)); + string sText2; + if(ai_GetWidgetButton(oPC, BTN_WIDGET_OFF, oAssociate, sAssociateType)) + { + sText = "Off"; sText2 = "on"; + NuiSetBind(oPC, nToken, "btn_widget_onoff", JsonBool(FALSE)); + } + else + { + sText = "On"; sText2 = "off"; + NuiSetBind(oPC, nToken, "btn_widget_onoff", JsonBool(TRUE)); + } + NuiSetBind(oPC, nToken, "btn_widget_onoff_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_widget_onoff_label", JsonString("Widget " + sText)); + NuiSetBind(oPC, nToken, "btn_widget_onoff_tooltip", JsonString( + " Turn " + sName + " widget " + sText2)); + } + } + // Row 2 + NuiSetBind(oPC, nToken, "btn_widget_lock_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_widget_lock", JsonBool(bAIWidgetLock)); + NuiSetBind(oPC, nToken, "btn_widget_lock_tooltip", JsonString( + " Locks " + sName + " widget to the current location.")); + NuiSetBind(oPC, nToken, "btn_widget_size_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "btn_widget_size_tooltip", JsonString( + " Adjusts the size of " + sName + " widget buttons")); + NuiSetBind(oPC, nToken, "btn_vertical_widget_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "btn_vertical_widget", JsonBool(bVertical)); + NuiSetBind(oPC, nToken, "btn_vertical_widget_tooltip", JsonString( + " " + sName + " widget will display vertically")); + // Row 3 + NuiSetBind(oPC, nToken, "chbx_cmd_action_check", JsonBool (bCmdAction)); + NuiSetBindWatch(oPC, nToken, "chbx_cmd_action_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_cmd_action_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_cmd_action_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "chbx_cmd_guard_check", JsonBool (bCmdGuard)); + NuiSetBindWatch (oPC, nToken, "chbx_cmd_guard_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_cmd_guard_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_cmd_guard_event", JsonBool (TRUE)); + // Row 4 + NuiSetBind(oPC, nToken, "chbx_cmd_hold_check", JsonBool (bCmdHold)); + NuiSetBindWatch (oPC, nToken, "chbx_cmd_hold_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_cmd_hold_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_cmd_hold_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "chbx_cmd_attack_check", JsonBool (bCmdAttack)); + NuiSetBindWatch (oPC, nToken, "chbx_cmd_attack_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_cmd_attack_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_cmd_attack_event", JsonBool (TRUE)); + // Row 5 + NuiSetBind(oPC, nToken, "chbx_cmd_follow_check", JsonBool (bCmdFollow)); + NuiSetBindWatch (oPC, nToken, "chbx_cmd_follow_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_cmd_follow_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_cmd_follow_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "chbx_follow_target_check", JsonBool (bFollowTarget)); + NuiSetBindWatch (oPC, nToken, "chbx_follow_target_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_follow_target_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_follow_target_event", JsonBool (TRUE)); + // Row 6 + if(bIsPC) + { + NuiSetBind(oPC, nToken, "chbx_cmd_search_check", JsonBool (bCmdSearch)); + NuiSetBindWatch (oPC, nToken, "chbx_cmd_search_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_cmd_search_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_cmd_search_event", JsonBool (TRUE)); + if(ai_GetAIMode(oPC, AI_MODE_AGGRESSIVE_SEARCH)) sText = " leave "; + else sText = " enter "; + NuiSetBind(oPC, nToken, "btn_cmd_search_tooltip", JsonString(" Everyone" + sText + "search mode")); + NuiSetBind(oPC, nToken, "chbx_cmd_stealth_check", JsonBool (bCmdStealth)); + NuiSetBindWatch (oPC, nToken, "chbx_cmd_stealth_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_cmd_stealth_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_cmd_stealth_event", JsonBool (TRUE)); + if(ai_GetAIMode(oPC, AI_MODE_AGGRESSIVE_STEALTH)) sText = " leave "; + else sText = " enter "; + NuiSetBind(oPC, nToken, "btn_cmd_stealth_tooltip", JsonString(" Everyone" + sText + "stealth mode")); + } + // Command labels + if(bIsPC) sText = " All "; + else sText = " "; + NuiSetBind(oPC, nToken, "btn_cmd_action_label", JsonString(sText + "Action")); + NuiSetBind(oPC, nToken, "btn_cmd_guard_label", JsonString(sText + "Guard Mode")); + NuiSetBind(oPC, nToken, "btn_cmd_hold_label", JsonString(sText + "Hold Mode")); + NuiSetBind(oPC, nToken, "btn_cmd_attack_label", JsonString(sText + "Normal Mode")); + NuiSetBind(oPC, nToken, "btn_cmd_follow_label", JsonString(sText + "Follow Mode")); + NuiSetBind(oPC, nToken, "btn_follow_target_label", JsonString(" Follow Target")); + float fRange = GetLocalFloat(oAssociate, AI_FOLLOW_RANGE) + + StringToFloat(Get2DAString("appearance", "PREFATCKDIST", GetAppearanceType(oAssociate))); + string sRange = FloatToString(fRange, 0, 0); + if(bIsPC) + { + sText = " All associates"; + NuiSetBind(oPC, nToken, "btn_cmd_follow_tooltip", JsonString(sText + " enter follow mode")); + } + else + { + sText = " " + GetName(oAssociate); + NuiSetBind(oPC, nToken, "btn_cmd_follow_tooltip", JsonString(sText + " enter follow mode [" + sRange + " meters]")); + } + NuiSetBind(oPC, nToken, "btn_cmd_action_tooltip", JsonString(sText + " do actions")); + NuiSetBind(oPC, nToken, "btn_cmd_guard_tooltip", JsonString(sText + " enter guard mode")); + NuiSetBind(oPC, nToken, "btn_cmd_hold_tooltip", JsonString(sText + " enter hold mode")); + NuiSetBind(oPC, nToken, "btn_cmd_attack_tooltip", JsonString(sText + " enter normal mode")); + object oTarget = GetLocalObject(oAssociate, AI_FOLLOW_TARGET); + string sTarget; + if(oTarget != OBJECT_INVALID) sTarget = GetName(oTarget); + else + { + if(ai_GetIsCharacter(oAssociate)) sTarget = "nobody"; + else sTarget = GetName(oPC); + } + NuiSetBind(oPC, nToken, "btn_follow_target_tooltip", JsonString(" " + GetName(oAssociate) + " following " + sTarget + " [" + sRange + " meters]")); + // Row 7 + NuiSetBind(oPC, nToken, "chbx_cmd_ai_script_check", JsonBool (bCmdAIScript)); + NuiSetBindWatch (oPC, nToken, "chbx_cmd_ai_script_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_cmd_ai_script_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_cmd_ai_script_event", JsonBool (TRUE)); + sText = " Using normal tactics"; + if(ResManGetAliasFor("ai_a_default", RESTYPE_NCS) != "") + { + string sScript = GetLocalString(oAssociate, AI_COMBAT_SCRIPT); + if(sScript == "ai_a_ambusher") sText = " Ambusher: Attacks from a hidden position"; + else if(sScript == "ai_a_flanker") sText = " Flanker: Attacks enemies engaged with allies"; + else if(sScript == "ai_a_peaceful") sText = " Peaceful: Avoids attacking any enemies if possible"; + else if(sScript == "ai_a_defensive") sText = " Defensive: Attacks then uses Expertise/Parry"; + else if(sScript == "ai_a_ranged") sText = " Ranged: Attacks from range as much as possible"; + else if(sScript == "ai_a_cntrspell") sText = " Counter Spell: Tries to counter enemy spells"; + } + else + { + if(GetCombatCondition(X0_COMBAT_FLAG_AMBUSHER, oAssociate)) sText = "Using ambush tactics"; + else if(GetCombatCondition(X0_COMBAT_FLAG_COWARDLY, oAssociate)) sText = "Using coward tactics"; + else if(GetCombatCondition(X0_COMBAT_FLAG_DEFENSIVE, oAssociate)) sText = "Using defensive tactics"; + else if(GetCombatCondition(X0_COMBAT_FLAG_RANGED, oAssociate)) sText = "Using ranged tactics"; + } + NuiSetBind(oPC, nToken, "btn_cmd_ai_script_tooltip", JsonString(sText)); + if(GetSkillRank(SKILL_SET_TRAP, oAssociate, TRUE) > 0) + { + NuiSetBind(oPC, nToken, "chbx_cmd_place_trap_check", JsonBool (bCmdPlacetrap)); + NuiSetBindWatch (oPC, nToken, "chbx_cmd_place_trap_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_cmd_place_trap_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_cmd_place_trap_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "btn_cmd_place_trap_tooltip", JsonString ( + " Place a trap at the location selected")); + } + // Row 8 + NuiSetBind(oPC, nToken, "btn_quick_widget_event", JsonBool(TRUE)); + NuiSetBind (oPC, nToken, "btn_quick_widget_tooltip", JsonString( + " Add/Remove abilities and spells from creatures widget")); + NuiSetBind(oPC, nToken, "chbx_quick_widget_check", JsonBool (bSpellWidget)); + NuiSetBindWatch (oPC, nToken, "chbx_quick_widget_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_quick_widget_event", JsonBool(TRUE)); + if(bMemorize == 2) // Memorizes their spells. + { + NuiSetBind(oPC, nToken, "btn_spell_memorize_event", JsonBool(TRUE)); + NuiSetBind (oPC, nToken, "btn_spell_memorize_tooltip", JsonString( + " Change memorized spell list.")); + } + if(bSpellbook) // Change known spells. + { + NuiSetBind(oPC, nToken, "btn_spell_known_event", JsonBool(TRUE)); + NuiSetBind (oPC, nToken, "btn_spell_known_tooltip", JsonString( + " Change known spell list.")); + } + // Row 9 + NuiSetBind(oPC, nToken, "chbx_buff_short_check", JsonBool (bBuffShort)); + NuiSetBindWatch (oPC, nToken, "chbx_buff_short_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_buff_short_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_buff_short_event", JsonBool (TRUE)); + NuiSetBind (oPC, nToken, "btn_buff_short_tooltip", JsonString ( + " Buff the party with short duration spells")); + NuiSetBind(oPC, nToken, "chbx_buff_long_check", JsonBool (bBuffLong)); + NuiSetBindWatch (oPC, nToken, "chbx_buff_long_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_buff_long_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_buff_long_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "btn_buff_long_tooltip", JsonString ( + " Buff the party with long duration spells")); + // Row 10 + NuiSetBind(oPC, nToken, "chbx_buff_all_check", JsonBool (bBuffAll)); + NuiSetBindWatch (oPC, nToken, "chbx_buff_all_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_buff_all_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_buff_all_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "btn_buff_all_tooltip", JsonString ( + " Buff the party with all our defensive spells")); + if(!bIsPC && ResManGetAliasFor("prc_ai_fam_percp", RESTYPE_NCS) == "") + { + NuiSetBind(oPC, nToken, "chbx_buff_rest_check", JsonBool (bBuffRest)); + NuiSetBindWatch (oPC, nToken, "chbx_buff_rest_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_buff_rest_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_buff_rest_event", JsonBool (TRUE)); + if(ai_GetMagicMode(oAssociate, AI_MAGIC_BUFF_AFTER_REST)) sText = " [On] Turn buffing after resting off"; + else sText = " [Off] Turn buffing after resting on"; + NuiSetBind (oPC, nToken, "btn_buff_rest_tooltip", JsonString (sText)); + } + // Row 11 + NuiSetBind(oPC, nToken, "chbx_jump_to_check", JsonBool(bJumpTo)); + NuiSetBindWatch (oPC, nToken, "chbx_jump_to_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_jump_to_event", JsonBool(TRUE)); + sText = GetName(oPC); + if(oPC == oAssociate) sName = "everyone"; + else sName = GetName(oAssociate); + NuiSetBind(oPC, nToken, "btn_jump_to_label", JsonString("Jump to " + sText)); + NuiSetBind(oPC, nToken, "btn_jump_to_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_jump_to_tooltip", JsonString ( + " Jump " + sName + " to " + sText)); + + NuiSetBind(oPC, nToken, "chbx_ghost_mode_check", JsonBool (bGhostMode)); + NuiSetBindWatch (oPC, nToken, "chbx_ghost_mode_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_ghost_mode_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_ghost_mode_event", JsonBool (TRUE)); + sText = "On"; + if(ai_GetAIMode(oAssociate, AI_MODE_GHOST)) sText = "Off"; + NuiSetBind(oPC, nToken, "btn_ghost_mode_tooltip", JsonString ( + " Turn " + sText + " clipping through creatures for " + GetName(oAssociate))); + // Row 12 + NuiSetBind(oPC, nToken, "chbx_camera_check", JsonBool (bCamera)); + NuiSetBindWatch (oPC, nToken, "chbx_camera_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_camera_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_camera_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "btn_camera_tooltip", JsonString ( + " Toggle camera view for " + sName)); + NuiSetBind(oPC, nToken, "chbx_inventory_check", JsonBool (bInventory)); + NuiSetBindWatch (oPC, nToken, "chbx_inventory_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_inventory_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_inventory_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "btn_inventory_tooltip", JsonString ( + " Open " + sName + " inventory")); + // Row 13 & 14 + if(bFamiliar) + { + NuiSetBind(oPC, nToken, "chbx_familiar_check", JsonBool(bBtnFamiliar)); + NuiSetBindWatch (oPC, nToken, "chbx_familiar_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_familiar_event", JsonBool(TRUE)); + int nFamiliar = GetFamiliarCreatureType(oAssociate); + NuiSetBind(oPC, nToken, "cmb_familiar_selected", JsonInt(nFamiliar)); + string sFamiliarName = GetFamiliarName(oAssociate); + NuiSetBind(oPC, nToken, "txt_familiar_name", JsonString(sFamiliarName)); + if(!bIsPC) + { + NuiSetBind(oPC, nToken, "lbl_familiar_type_label", JsonString("Change familiar type")); + NuiSetBind(oPC, nToken, "lbl_familiar_name_label", JsonString("Change familiar name")); + NuiSetBind(oPC, nToken, "cmb_familiar_event", JsonBool(TRUE)); + NuiSetBindWatch(oPC, nToken, "cmb_familiar_selected", TRUE); + NuiSetBind(oPC, nToken, "txt_familiar_name_event", JsonBool(TRUE)); + NuiSetBindWatch(oPC, nToken, "txt_familiar_name", TRUE); + NuiSetBind(oPC, nToken, "btn_familiar_name_label", JsonString("Save")); + } + else + { + NuiSetBind(oPC, nToken, "lbl_familiar_type_label", JsonString("Familiar type")); + NuiSetBind(oPC, nToken, "lbl_familiar_name_label", JsonString("Familiar name")); + } + } + // Row 15 & 16 + if(bCompanion) + { + NuiSetBind(oPC, nToken, "chbx_companion_check", JsonBool(bBtnCompanion)); + NuiSetBindWatch (oPC, nToken, "chbx_companion_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_companion_event", JsonBool(TRUE)); + int nCompanion = GetAnimalCompanionCreatureType(oAssociate); + NuiSetBind(oPC, nToken, "cmb_companion_selected", JsonInt(nCompanion)); + string sCompanionName = GetAnimalCompanionName(oAssociate); + NuiSetBind(oPC, nToken, "txt_companion_name", JsonString(sCompanionName)); + if(!bIsPC) + { + NuiSetBind(oPC, nToken, "lbl_companion_type_label", JsonString("Change Companion type")); + NuiSetBind(oPC, nToken, "lbl_companion_name_label", JsonString("Change Companion name")); + NuiSetBind(oPC, nToken, "cmb_companion_event", JsonBool(TRUE)); + NuiSetBindWatch(oPC, nToken, "cmb_companion_selected", TRUE); + NuiSetBind(oPC, nToken, "txt_companion_name_event", JsonBool(TRUE)); + NuiSetBindWatch(oPC, nToken, "txt_companion_name", TRUE); + NuiSetBind(oPC, nToken, "btn_companion_name_label", JsonString("Save")); + } + else + { + NuiSetBind(oPC, nToken, "lbl_companion_type_label", JsonString("Companion type")); + NuiSetBind(oPC, nToken, "lbl_companion_name_label", JsonString("Companion name")); + } + } + if(bIsPC) + { + // Row 17+ + int nIndex, bWidget; + string sButton, sText; + json jPlugin = JsonArrayGet(jPCPlugins, nIndex); + while(JsonGetType(jPlugin) != JSON_TYPE_NULL) + { + sButton = IntToString(nIndex); + NuiSetBind(oPC, nToken, "btn_plugin_" + sButton + "_event", JsonBool(TRUE)); + bWidget = JsonGetInt(JsonArrayGet(jPlugin, 1)); + if(bWidget < 3) + { + NuiSetBind(oPC, nToken, "chbx_plugin_" + sButton + "_check", JsonBool(bWidget)); + NuiSetBindWatch (oPC, nToken, "chbx_plugin_" + sButton + "_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_plugin_" + sButton + "_event", JsonBool(TRUE)); + } + sText = " " + JsonGetString(JsonArrayGet(jPlugin, 2)); + NuiSetBind(oPC, nToken, "btn_plugin_" + sButton + "_tooltip", JsonString(sText)); + jPlugin = JsonArrayGet(jPCPlugins, ++nIndex); + } + NuiSetBind(oPC, nToken, "chbx_plugin_tooltip", JsonString(" Adds the plugin to your widget.")); + } + // Row 18 + sText = ai_GetRandomTip(); + NuiSetBind(oPC, nToken, "lbl_info_1_label", JsonString(sText)); +} +void ai_CreateAssociateAINUI(object oPC, object oAssociate) +{ + // Set window to not save until it has been created. + SetLocalInt (oPC, AI_NO_NUI_SAVE, TRUE); + DelayCommand (2.0, DeleteLocalInt (oPC, AI_NO_NUI_SAVE)); + int bRight, bLeft; + float fHeight = 45.0; + // ************************************************************************* Width / Height + int bIsPC = ai_GetIsCharacter(oAssociate); + string sAssociateType = ai_GetAssociateType(oPC, oAssociate); + json jRow = JsonArray(); + json jCol = JsonArray(); + // Row 1 ******************************************************************* 500 / 73 + // If all the AI buttons are blocked then don't load the menu. + if(bIsPC) + { + bRight = GetLocalInt(GetModule(), sDMWidgetAccessVarname) != 7340028; + if(!AI_SERVER || bRight) + { + // If all the Command buttons are blocked then don't load the menu. + if(bRight) + { + jRow = CreateButton(jRow, "Command Menu", "btn_command_menu", 200.0, 20.0, -1.0, "btn_command_menu_tooltip"); + jRow = CreateLabel(jRow, "", "blank_label_2", 25.0, 20.0); + } + jRow = JsonArrayInsert(jRow, NuiSpacer()); + if(!AI_SERVER) + { + CreateButton(jRow, "Main Menu", "btn_main_menu", 200.0, 20.0, -1.0, "btn_main_menu_tooltip"); + CreateLabel(jRow, "", "blank_label_2", 25.0, 20.0); + } + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight += 28.0; + } + } + // Row 2 ******************************************************************* 500 / 73 + bRight = !ai_GetDMAIAccessButton(BTN_AI_LOOT); + if(bRight || !bIsPC) + { + jRow = JsonArray(); + if(!bIsPC) + { + jRow = CreateButton(jRow, "Command Menu", "btn_command_menu", 200.0, 20.0, -1.0, "btn_command_menu_tooltip"); + jRow = CreateLabel(jRow, "", "blank_label_2", 25.0, 20.0); + } + jRow = JsonArrayInsert(jRow, NuiSpacer()); + if(bRight) + { + jRow = CreateButton(jRow, "Loot Filter", "btn_loot_filter", 200.0, 20.0); + jRow = CreateLabel(jRow, "", "blank_label_2", 25.0, 20.0); + } + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight += 28.0; + } + // Row 3 ******************************************************************* 500 / 101 + bRight = !ai_GetDMAIAccessButton(BTN_AI_FOR_PC); + bLeft = !ai_GetDMAIAccessButton(BTN_AI_REDUCE_SPEECH); + if(bRight || bLeft) + { + jRow = JsonArray(); + if(bRight) + { + jRow = CreateButton(jRow, "Player AI On/Off", "btn_ai", 200.0, 20.0, -1.0, "btn_ai_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_ai", 25.0, 20.0); + } + jRow = JsonArrayInsert(jRow, NuiSpacer()); + if(bLeft) + { + jRow = CreateButton(jRow, "Reduce Speech", "btn_quiet", 200.0, 20.0, -1.0, "btn_quiet_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_quiet", 25.0, 20.0); + } + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight += 28.0; + } + // Row 4 ******************************************************************* 500 / 129 + bRight = !ai_GetDMAIAccessButton(BTN_AI_USE_RANGED); + bLeft = !ai_GetDMAIAccessButton(BTN_AI_STOP_WEAPON_EQUIP); + if(bRight || bLeft) + { + jRow = JsonArray(); + if(bRight) + { + jRow = CreateButton(jRow, "Ranged Combat", "btn_ranged", 200.0, 20.0, -1.0, "btn_ranged_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_ranged", 25.0, 20.0); + } + jRow = JsonArrayInsert(jRow, NuiSpacer()); + if(bLeft) + { + jRow = CreateButton(jRow, "Equip Best Weapons", "btn_equip_weapon", 200.0, 20.0, -1.0, "btn_equip_weapon_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_equip_weapon", 25.0, 20.0); + } + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight += 28.0; + } + // Row 5 ******************************************************************* 500 / 157 + bRight = !ai_GetDMAIAccessButton(BTN_AI_USE_SEARCH); + bLeft = !ai_GetDMAIAccessButton(BTN_AI_USE_STEALTH); + if(bRight || bLeft) + { + jRow = JsonArray(); + if(bRight) + { + jRow = CreateButton(jRow, "Search Mode", "btn_search", 200.0, 20.0, -1.0, "btn_search_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_search", 25.0, 20.0); + } + jRow = JsonArrayInsert(jRow, NuiSpacer()); + if(bLeft) + { + jRow = CreateButton(jRow, "Stealth Mode", "btn_stealth", 200.0, 20.0, -1.0, "btn_stealth_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_stealth", 25.0, 20.0); + } + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight += 28.0; + } + // Row 6 ******************************************************************* 500 / 185 + bRight = !ai_GetDMAIAccessButton(BTN_AI_OPEN_DOORS); + bLeft = !ai_GetDMAIAccessButton(BTN_AI_REMOVE_TRAPS); + if(bRight || bLeft) + { + jRow = JsonArray(); + if(bRight) + { + jRow = CreateButton(jRow, "Open Door Mode", "btn_open_door", 200.0, 20.0, -1.0, "btn_open_door_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_open_door", 25.0, 20.0); + } + jRow = JsonArrayInsert(jRow, NuiSpacer()); + if(bLeft) + { + jRow = CreateButton(jRow, "Disarm Traps Mode", "btn_traps", 200.0, 20.0, -1.0, "btn_traps_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_traps", 25.0, 20.0); + } + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight += 28.0; + } + // Row 7 ******************************************************************* 500 / 213 + bRight = !ai_GetDMAIAccessButton(BTN_AI_PICK_LOCKS); + bLeft = !ai_GetDMAIAccessButton(BTN_AI_BASH_LOCKS); + if(bRight || bLeft) + { + jRow = JsonArray(); + if(bRight) + { + jRow = CreateButton(jRow, "Pick Locks Mode", "btn_pick_locks", 200.0, 20.0, -1.0, "btn_pick_locks_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_pick_locks", 25.0, 20.0); + } + jRow = JsonArrayInsert(jRow, NuiSpacer()); + if(bLeft) + { + jRow = CreateButton(jRow, "Bash Mode", "btn_bash_locks", 200.0, 20.0, -1.0, "btn_bash_locks_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_bash_locks", 25.0, 20.0); + } + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight += 28.0; + } + // Row 8 ******************************************************************* 500 / 241 + bRight = !ai_GetDMAIAccessButton(BTN_AI_MAGIC_LEVEL); + bLeft = !ai_GetDMAIAccessButton(BTN_AI_NO_SPONTANEOUS); + if(bRight || bLeft) + { + jRow = JsonArray(); + if(bRight) + { + jRow = CreateButton(jRow, "Magic usage level", "btn_magic_level", 200.0, 20.0f, -1.0, "btn_magic_level_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_magic_level", 25.0, 20.0); + } + jRow = JsonArrayInsert(jRow, NuiSpacer()); + if(bLeft) + { + jRow = CreateButton(jRow, "Cleric Spontaneous Casting", "btn_spontaneous", 200.0, 20.0, -1.0, "btn_spontaneous_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_spontaneous", 25.0, 20.0); + } + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight += 28.0; + } + // Row 9 ******************************************************************* 500 / 269 + bRight = !ai_GetDMAIAccessButton(BTN_AI_NO_MAGIC_USE); + bLeft = !ai_GetDMAIAccessButton(BTN_AI_NO_MAGIC_ITEM_USE); + if(bRight || bLeft) + { + jRow = JsonArray(); + if(bRight) + { + jRow = CreateButton(jRow, "Use Magic", "btn_magic", 200.0, 20.0, -1.0, "btn_magic_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_magic", 25.0, 20.0); + } + jRow = JsonArrayInsert(jRow, NuiSpacer()); + if(bLeft) + { + jRow = CreateButton(jRow, "Use Magic Items", "btn_magic_items", 200.0, 20.0, -1.0, "btn_magic_items_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_magic_items", 25.0, 20.0); + } + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight += 28.0; + } + // Row 10 ****************************************************************** 500 / 297 + bRight = !ai_GetDMAIAccessButton(BTN_AI_DEF_MAGIC_USE); + bLeft = !ai_GetDMAIAccessButton(BTN_AI_OFF_MAGIC_USE); + if(bRight || bLeft) + { + jRow = JsonArray(); + if(bRight) + { + jRow = CreateButton(jRow, "Use Defensive Magic Only", "btn_def_magic", 200.0, 20.0, -1.0, "btn_def_magic_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_def_magic", 25.0, 20.0f); + } + jRow = JsonArrayInsert(jRow, NuiSpacer()); + if(bLeft) + { + jRow = CreateButton(jRow, "Use Offensive Magic Only", "btn_off_magic", 200.0, 20.0, -1.0, "btn_off_magic_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_off_magic", 25.0, 20.0); + } + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight += 28.0; + } + // Row 11 ****************************************************************** 500 / 325 + bRight = !ai_GetDMAIAccessButton(BTN_AI_HEAL_OUT); + bLeft = !ai_GetDMAIAccessButton(BTN_AI_HEAL_IN); + if(bRight || bLeft) + { + jRow = JsonArray(); + if(bRight) + { + jRow = CreateButton(jRow, "Heal % Out of Combat", "btn_heal_out", 200.0, 20.0, -1.0, "btn_heal_out_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_heal_out", 25.0, 20.0); + } + jRow = JsonArrayInsert(jRow, NuiSpacer()); + if(bLeft) + { + jRow = CreateButton(jRow, "Heal % in Combat", "btn_heal_in", 200.0, 20.0, -1.0, "btn_heal_in_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_heal_in", 25.0, 20.0); + } + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight += 28.0; + } + // Row 12 ****************************************************************** 500 / 353 + bRight = !ai_GetDMAIAccessButton(BTN_AI_STOP_SELF_HEALING); + bLeft = !ai_GetDMAIAccessButton(BTN_AI_STOP_PARTY_HEALING); + if(bRight || bLeft) + { + jRow = JsonArray(); + if(bRight) + { + jRow = CreateButton(jRow, "Self Healing", "btn_heals_onoff", 200.0, 20.0, -1.0, "btn_heals_onoff_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_heals_onoff", 25.0, 20.0); + } + jRow = JsonArrayInsert(jRow, NuiSpacer()); + if(bLeft) + { + jRow = CreateButton(jRow, "Party Healing", "btn_healp_onoff", 200.0, 20.0, -1.0, "btn_healp_onoff_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_healp_onoff", 25.0, 20.0); + } + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight += 28.0; + } + // Row 13 ****************************************************************** 500 / 391 + bRight = !ai_GetDMAIAccessButton(BTN_AI_STOP_CURE_SPELLS); + bLeft = !ai_GetDMAIAccessButton(BTN_AI_LOOT); + if(bRight || bLeft) + { + jRow = JsonArray(); + if(bRight) + { + jRow = CreateButton(jRow, "Cast Cure Spells", "btn_cure_onoff", 200.0, 20.0, -1.0, "btn_cure_onoff_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_cure_onoff", 25.0, 20.0); + } + jRow = JsonArrayInsert(jRow, NuiSpacer()); + if(bLeft) + { + if(sAssociateType != "summons" && sAssociateType != "dominated") + { + jRow = CreateButton(jRow, "Auto Looting", "btn_loot", 200.0, 20.0, -1.0, "btn_loot_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_loot", 25.0, 20.0); + } + } + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight += 28.0; + } + // Row 14 ****************************************************************** 500 / --- + bRight = !ai_GetDMAIAccessButton(BTN_AI_IGNORE_ASSOCIATES); + bLeft = !ai_GetDMAIAccessButton(BTN_AI_IGNORE_TRAPS); + if(bRight || bLeft) + { + jRow = JsonArray(); + if(bRight) + { + jRow = CreateButton(jRow, "Ignore Associates", "btn_ignore_assoc", 200.0, 20.0, -1.0, "btn_ignore_assoc_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_ignore_assoc", 25.0, 20.0); + } + jRow = JsonArrayInsert(jRow, NuiSpacer()); + if(bLeft) + { + jRow = CreateButton(jRow, "Ignore floor Traps", "btn_ignore_traps", 200.0, 20.0, -1.0, "btn_ignore_traps_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_ignore_traps", 25.0, 20.0); + } + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight += 28.0; + } + // Row 15 ****************************************************************** 500 / --- + bRight = !ai_GetDMAIAccessButton(BTN_AI_PERC_RANGE); + bLeft = FALSE; //!ai_GetDMAIAccessButton(BTN_AI_PERC_RANGE); + if(bRight || bLeft) + { + jRow = JsonArray(); + if(bRight) + { + if(GetAssociateType(oAssociate) == ASSOCIATE_TYPE_HENCHMAN) + { + jRow = CreateButton(jRow, "Perception Range", "btn_perc_range", 200.0, 20.0, -1.0, "btn_perc_range_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_perc_range", 25.0, 20.0); + } + } + jRow = JsonArrayInsert(jRow, NuiSpacer()); + if(bLeft) + { + } + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight += 28.0; + } + // Row 16 ****************************************************************** 500 / --- + bRight = !ai_GetDMWAccessButton(BTN_CMD_AI_SCRIPT); + if(bRight) + { + jRow = JsonArray(); + jRow = CreateButton(jRow, "Set Current AI:", "btn_ai_script", 175.0f, 20.0f, -1.0, "btn_ai_script_tooltip"); + jRow = CreateTextEditBox(jRow, "sPlaceHolder", "txt_ai_script", 16, FALSE, 145.0f, 20.0f, "txt_ai_script_tooltip"); + jRow = CreateCombo(jRow, ai_CreateAIScriptJson(oPC), "cmb_ai_script", 146.0, 20.0); + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight += 28.0; + } + // Row 17 ****************************************************************** 500 / --- + jRow = JsonArray(); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateLabel(jRow, "", "lbl_info", 475.0, 20.0, NUI_HALIGN_CENTER); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight += 28.0; + // Get the window location to restore it from the database. + float fX, fY; + json jLocations = ai_GetAssociateDbJson(oPC, sAssociateType, "locations"); + jLocations = JsonObjectGet(jLocations, sAssociateType + AI_NUI); + if(JsonGetType(jLocations) == JSON_TYPE_NULL) { fX = -1.0; fY = -1.0; } + else + { + fX = JsonGetFloat(JsonObjectGet(jLocations, "x")); + fY = JsonGetFloat(JsonObjectGet(jLocations, "y")); + } + // Set the Layout of the window. + json jLayout = NuiCol(jCol); + string sText, sName = GetName(oAssociate); + if(GetStringRight(sName, 1) == "s") sName = sName + "'"; + else sName = sName + "'s"; + int nToken = SetWindow(oPC, jLayout, sAssociateType + AI_NUI, sName + " AI Menu", + fX, fY, 500.0, fHeight + 12.0, FALSE, FALSE, TRUE, FALSE, TRUE, "0e_nui"); + // Get which buttons are activated. + int bAI = ai_GetAIButton(oPC, BTN_AI_FOR_PC, oAssociate, sAssociateType); + int bReduceSpeech = ai_GetAIButton(oPC, BTN_AI_REDUCE_SPEECH, oAssociate, sAssociateType); + int bRanged = ai_GetAIButton(oPC, BTN_AI_USE_RANGED, oAssociate, sAssociateType); + int bEquipWeapons = ai_GetAIButton(oPC, BTN_AI_STOP_WEAPON_EQUIP, oAssociate, sAssociateType); + int bSearch = ai_GetAIButton(oPC, BTN_AI_USE_SEARCH, oAssociate, sAssociateType); + int bStealth = ai_GetAIButton(oPC, BTN_AI_USE_STEALTH, oAssociate, sAssociateType); + int bOpenDoors = ai_GetAIButton(oPC, BTN_AI_OPEN_DOORS, oAssociate, sAssociateType); + int bTraps = ai_GetAIButton(oPC, BTN_AI_REMOVE_TRAPS, oAssociate, sAssociateType); + int bPickLocks = ai_GetAIButton(oPC, BTN_AI_PICK_LOCKS, oAssociate, sAssociateType); + int bBashLocks = ai_GetAIButton(oPC, BTN_AI_BASH_LOCKS, oAssociate, sAssociateType); + int bMagicLevel = ai_GetAIButton(oPC, BTN_AI_MAGIC_LEVEL, oAssociate, sAssociateType); + int bSpontaneous = ai_GetAIButton(oPC, BTN_AI_NO_SPONTANEOUS, oAssociate, sAssociateType); + int bNoMagic = ai_GetAIButton(oPC, BTN_AI_NO_MAGIC_USE, oAssociate, sAssociateType); + int bNoMagicItems = ai_GetAIButton(oPC, BTN_AI_NO_MAGIC_ITEM_USE, oAssociate, sAssociateType); + int bDefMagic = ai_GetAIButton(oPC, BTN_AI_DEF_MAGIC_USE, oAssociate, sAssociateType); + int bOffMagic = ai_GetAIButton(oPC, BTN_AI_OFF_MAGIC_USE, oAssociate, sAssociateType); + int bHealOut = ai_GetAIButton(oPC, BTN_AI_HEAL_OUT, oAssociate, sAssociateType); + int bHealIn = ai_GetAIButton(oPC, BTN_AI_HEAL_IN, oAssociate, sAssociateType); + int bSelfHealOnOff = ai_GetAIButton(oPC, BTN_AI_STOP_SELF_HEALING, oAssociate, sAssociateType); + int bPartyHealOnOff = ai_GetAIButton(oPC, BTN_AI_STOP_PARTY_HEALING, oAssociate, sAssociateType); + int bCureOnOff = ai_GetAIButton(oPC, BTN_AI_STOP_CURE_SPELLS, oAssociate, sAssociateType); + int bIgnoreAssociates = ai_GetAIButton(oPC, BTN_AI_IGNORE_ASSOCIATES, oAssociate, sAssociateType); + int bIgnoreTraps = ai_GetAIButton(oPC, BTN_AI_IGNORE_TRAPS, oAssociate, sAssociateType); + int bLoot = ai_GetAIButton(oPC, BTN_AI_LOOT, oAssociate, sAssociateType); + int bPercRange = ai_GetAIButton(oPC, BTN_AI_PERC_RANGE, oAssociate, sAssociateType); + // Save the associate to the nui for use in 0e_nui + json jData = JsonArray(); + jData = JsonArrayInsert(jData, JsonString(ObjectToString(oAssociate))); + NuiSetUserData(oPC, nToken, jData); + // Set event watches for save window location. + NuiSetBindWatch(oPC, nToken, "window_geometry", TRUE); + // Set all binds, events, and watches. + // Row 1 + // If all the AI buttons are blocked then don't load the menu. + if(bIsPC) + { + bRight = GetLocalInt(GetModule(), sDMWidgetAccessVarname) != 7340028; + if(!AI_SERVER || bRight) + { + // If all the Command buttons are blocked then don't load the menu. + if(bRight) + { + NuiSetBind(oPC, nToken, "btn_command_menu_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_command_menu_tooltip", JsonString(" " + sName + " Command options")); + } + if(!AI_SERVER) + { + NuiSetBind(oPC, nToken, "btn_main_menu_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_main_menu_tooltip", JsonString(" Module Options")); + } + fHeight += 28.0; + } + } + // Row 2 + if(!bIsPC) + { + NuiSetBind(oPC, nToken, "btn_command_menu_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_command_menu_tooltip", JsonString(" " + sName + " Command options")); + } + NuiSetBind(oPC, nToken, "btn_loot_filter_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_loot_filter", JsonInt(TRUE)); + // Row 3 + // Only activate ai on/off if this is for the pc. + if(bIsPC && ResManGetAliasFor("prc_ai_fam_percp", RESTYPE_NCS) == "") + { + NuiSetBind(oPC, nToken, "chbx_ai_check", JsonBool(bAI)); + NuiSetBindWatch (oPC, nToken, "chbx_ai_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_ai_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_ai_event", JsonBool(TRUE)); + if(GetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT) == "xx_pc_1_hb") sText = " AI On"; + else sText = " AI Off"; + NuiSetBind(oPC, nToken, "btn_ai_tooltip", JsonString(sText)); + } + NuiSetBind(oPC, nToken, "chbx_quiet_check", JsonBool(bReduceSpeech)); + NuiSetBindWatch (oPC, nToken, "chbx_quiet_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_quiet_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_quiet_event", JsonBool(TRUE)); + if(ai_GetAIMode(oAssociate, AI_MODE_DO_NOT_SPEAK)) sText = " Reduced Speech On"; + else sText = " Reduces Speech Off"; + NuiSetBind (oPC, nToken, "btn_quiet_tooltip", JsonString(sText)); + // Row 4 + NuiSetBind(oPC, nToken, "chbx_ranged_check", JsonBool(bRanged)); + NuiSetBindWatch(oPC, nToken, "chbx_ranged_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_ranged_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_ranged_event", JsonBool(TRUE)); + if(ai_GetAIMode(oAssociate, AI_MODE_STOP_RANGED)) sText = " Ranged Off"; + else sText = " Ranged On"; + NuiSetBind (oPC, nToken, "btn_ranged_tooltip", JsonString(sText)); + NuiSetBind(oPC, nToken, "chbx_equip_weapon_check", JsonBool(bEquipWeapons)); + NuiSetBindWatch(oPC, nToken, "chbx_equip_weapon_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_equip_weapon_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_equip_weapon_event", JsonBool(TRUE)); + if(ai_GetAIMode(oAssociate, AI_MODE_EQUIP_WEAPON_OFF)) sText = " Equiping Best Weapons Off"; + else sText = " Equiping Best Weapons On"; + NuiSetBind (oPC, nToken, "btn_equip_weapon_tooltip", JsonString(sText)); + // Row 5 + if(GetRacialType(oAssociate) != RACIAL_TYPE_ELF) + { + NuiSetBind(oPC, nToken, "chbx_search_check", JsonBool(bSearch)); + NuiSetBindWatch (oPC, nToken, "chbx_search_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_search_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_search_event", JsonBool(TRUE)); + if(ai_GetAIMode(oAssociate, AI_MODE_AGGRESSIVE_SEARCH)) sText = " Search mode On"; + else sText = " Search mode Off"; + NuiSetBind (oPC, nToken, "btn_search_tooltip", JsonString(sText)); + } + NuiSetBind(oPC, nToken, "chbx_stealth_check", JsonBool(bStealth)); + NuiSetBindWatch(oPC, nToken, "chbx_stealth_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_stealth_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_stealth_event", JsonBool(TRUE)); + if(ai_GetAIMode(oAssociate, AI_MODE_AGGRESSIVE_STEALTH)) sText = " Stealth mode On"; + else sText = " Stealth mode Off"; + NuiSetBind (oPC, nToken, "btn_stealth_tooltip", JsonString(sText)); + // Row 6 + string sRange = FloatToString(GetLocalFloat(oAssociate, AI_OPEN_DOORS_RANGE), 0, 0); + NuiSetBind(oPC, nToken, "chbx_open_door_check", JsonBool(bOpenDoors)); + NuiSetBindWatch (oPC, nToken, "chbx_open_door_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_open_door_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_open_door_event", JsonBool(TRUE)); + if(ai_GetAIMode(oAssociate, AI_MODE_OPEN_DOORS)) sText = " Open Doors On [" + sRange + " meters]"; + else sText = " Open Doors Off [" + sRange + " meters]"; + NuiSetBind (oPC, nToken, "btn_open_door_tooltip", JsonString(sText)); + sRange = FloatToString(GetLocalFloat(oAssociate, AI_TRAP_CHECK_RANGE), 0, 0); + NuiSetBind(oPC, nToken, "chbx_traps_check", JsonBool(bTraps)); + NuiSetBindWatch (oPC, nToken, "chbx_traps_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_traps_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_traps_event", JsonBool(TRUE)); + if(ai_GetAIMode(oAssociate, AI_MODE_DISARM_TRAPS)) sText = " Disable Traps On [" + sRange + " meters]"; + else sText = " Disable Traps Off [" + sRange + " meters]"; + NuiSetBind (oPC, nToken, "btn_traps_tooltip", JsonString(sText)); + // Row 7 + sRange = FloatToString(GetLocalFloat(oAssociate, AI_LOCK_CHECK_RANGE), 0, 0); + NuiSetBind(oPC, nToken, "chbx_pick_locks_check", JsonBool(bPickLocks)); + NuiSetBindWatch(oPC, nToken, "chbx_pick_locks_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_pick_locks_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_pick_locks_event", JsonBool(TRUE)); + if(ai_GetAIMode(oAssociate, AI_MODE_PICK_LOCKS)) sText = " Pick locks On [" + sRange + " meters]"; + else sText = " Pick Locks Off [" + sRange + " meters]"; + NuiSetBind (oPC, nToken, "btn_pick_locks_tooltip", JsonString(sText)); + NuiSetBind(oPC, nToken, "chbx_bash_locks_check", JsonBool(bBashLocks)); + NuiSetBindWatch(oPC, nToken, "chbx_bash_locks_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_bash_locks_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_bash_locks_event", JsonBool(TRUE)); + if(ai_GetAIMode(oAssociate, AI_MODE_BASH_LOCKS)) sText = " Bash On [" + sRange + " meters]"; + else sText = " Bash Off [" + sRange + " meters]"; + NuiSetBind (oPC, nToken, "btn_bash_locks_tooltip", JsonString(sText)); + // Row 8 + string sMagic = IntToString(GetLocalInt(oAssociate, AI_DIFFICULTY_ADJUSTMENT)); + NuiSetBind(oPC, nToken, "chbx_magic_level_check", JsonBool(bMagicLevel)); + NuiSetBindWatch (oPC, nToken, "chbx_magic_level_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_magic_level_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_magic_level_event", JsonBool(TRUE)); + NuiSetBind (oPC, nToken, "btn_magic_level_tooltip", JsonString(" Magic level [" + sMagic + "]")); + sText = " Spontaneous casting On"; + if(ai_GetMagicMode(oAssociate, AI_MAGIC_NO_SPONTANEOUS_CURE)) sText = " Spontaneous casting Off"; + NuiSetBind(oPC, nToken, "chbx_spontaneous_check", JsonBool(bSpontaneous)); + NuiSetBindWatch (oPC, nToken, "chbx_spontaneous_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_spontaneous_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_spontaneous_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_spontaneous_tooltip", JsonString(sText)); + // Row 9 + if(ai_GetMagicMode(oAssociate, AI_MAGIC_NO_MAGIC)) sText = " Magic Off"; + else sText = " Magic On"; + NuiSetBind(oPC, nToken, "chbx_magic_check", JsonBool(bNoMagic)); + NuiSetBindWatch (oPC, nToken, "chbx_magic_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_magic_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_magic_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_magic_tooltip", JsonString(sText)); + if(ai_GetMagicMode(oAssociate, AI_MAGIC_NO_MAGIC_ITEMS)) sText = " Magic Items Off"; + else sText = " Magic Items On"; + NuiSetBind(oPC, nToken, "chbx_magic_items_check", JsonBool(bNoMagicItems)); + NuiSetBindWatch (oPC, nToken, "chbx_magic_items_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_magic_items_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_magic_items_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_magic_items_tooltip", JsonString(sText)); + // Row 10 + if(ai_GetMagicMode(oAssociate, AI_MAGIC_DEFENSIVE_CASTING)) sText = " Defensive Magic On"; + else sText = " Defensive Magic Off"; + NuiSetBind(oPC, nToken, "chbx_def_magic_check", JsonBool (bDefMagic)); + NuiSetBindWatch (oPC, nToken, "chbx_def_magic_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_def_magic_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_def_magic_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_def_magic_tooltip", JsonString(sText)); + if(ai_GetMagicMode(oAssociate, AI_MAGIC_OFFENSIVE_CASTING)) sText = " Offensive Magic On"; + else sText = " Offensive Magic Off"; + NuiSetBind(oPC, nToken, "chbx_off_magic_check", JsonBool(bOffMagic)); + NuiSetBindWatch (oPC, nToken, "chbx_off_magic_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_off_magic_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_off_magic_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_off_magic_tooltip", JsonString(sText)); + // Row 11 + int nHeal = GetLocalInt(oAssociate, AI_HEAL_OUT_OF_COMBAT_LIMIT); + NuiSetBind(oPC, nToken, "chbx_heal_out_check", JsonBool(bHealOut)); + NuiSetBindWatch (oPC, nToken, "chbx_heal_out_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_heal_out_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_heal_out_event", JsonBool(TRUE)); + sText = " Will heal at or below [" + IntToString(nHeal) + "%] health out of combat"; + NuiSetBind(oPC, nToken, "btn_heal_out_tooltip", JsonString(sText)); + nHeal = GetLocalInt(oAssociate, AI_HEAL_IN_COMBAT_LIMIT); + NuiSetBind(oPC, nToken, "chbx_heal_in_check", JsonBool(bHealIn)); + NuiSetBindWatch (oPC, nToken, "chbx_heal_in_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_heal_in_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_heal_in_event", JsonBool (TRUE)); + sText = " Will heal at or below [" + IntToString(nHeal) + "%] health in combat"; + NuiSetBind(oPC, nToken, "btn_heal_in_tooltip", JsonString(sText)); + // Row 12 + NuiSetBind(oPC, nToken, "chbx_heals_onoff_check", JsonBool(bSelfHealOnOff)); + NuiSetBindWatch (oPC, nToken, "chbx_heals_onoff_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_heals_onoff_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_heals_onoff_event", JsonBool(TRUE)); + if(ai_GetAIMode(oAssociate, AI_MODE_SELF_HEALING_OFF)) sText = " Self healing Off"; + else sText = " Self healing On"; + NuiSetBind(oPC, nToken, "btn_heals_onoff_tooltip", JsonString(sText)); + NuiSetBind(oPC, nToken, "chbx_healp_onoff_check", JsonBool(bPartyHealOnOff)); + NuiSetBind(oPC, nToken, "chbx_healp_onoff_event", JsonBool(TRUE)); + NuiSetBindWatch (oPC, nToken, "chbx_healp_onoff_check", TRUE); + NuiSetBind(oPC, nToken, "btn_healp_onoff_event", JsonBool(TRUE)); + if(ai_GetAIMode(oAssociate, AI_MODE_PARTY_HEALING_OFF)) sText = " Party healing Off"; + else sText = " Party healing On"; + NuiSetBind(oPC, nToken, "btn_healp_onoff_tooltip", JsonString(sText)); + // Row 13 + NuiSetBind(oPC, nToken, "btn_cure_onoff_tooltip", JsonString(sText)); + NuiSetBind(oPC, nToken, "chbx_cure_onoff_check", JsonBool(bCureOnOff)); + NuiSetBind(oPC, nToken, "chbx_cure_onoff_event", JsonBool(TRUE)); + NuiSetBindWatch (oPC, nToken, "chbx_cure_onoff_check", TRUE); + NuiSetBind(oPC, nToken, "btn_cure_onoff_event", JsonBool(TRUE)); + if(ai_GetMagicMode(oAssociate, AI_MAGIC_CURE_SPELLS_OFF)) sText = " Cast Cure Spells Off"; + else sText = " Cast Cure Spells On"; + NuiSetBind(oPC, nToken, "btn_cure_onoff_tooltip", JsonString(sText)); + if(sAssociateType != "summons" && sAssociateType != "dominated") + { + sRange = FloatToString(GetLocalFloat(oAssociate, AI_LOOT_CHECK_RANGE), 0, 0); + if(ai_GetAIMode(oAssociate, AI_MODE_PICKUP_ITEMS)) sText = " Looting On [" + sRange + " meters]"; + else sText = " Looting Off [" + sRange + " meters]"; + NuiSetBind(oPC, nToken, "chbx_loot_check", JsonBool(bLoot)); + NuiSetBindWatch (oPC, nToken, "chbx_loot_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_loot_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_loot_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_loot_tooltip", JsonString(sText)); + } + // Row 14 + NuiSetBind(oPC, nToken, "chbx_ignore_assoc_check", JsonBool(bIgnoreAssociates)); + NuiSetBindWatch(oPC, nToken, "chbx_ignore_assoc_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_ignore_assoc_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_ignore_assoc_event", JsonBool(TRUE)); + if(ai_GetAIMode(oAssociate, AI_MODE_IGNORE_ASSOCIATES)) sText = " Ignore Enemy Associates On"; + else sText = " Ignore Enemy Associates Off"; + NuiSetBind (oPC, nToken, "btn_ignore_assoc_tooltip", JsonString(sText)); + NuiSetBind(oPC, nToken, "chbx_ignore_traps_check", JsonBool(bIgnoreTraps)); + NuiSetBindWatch(oPC, nToken, "chbx_ignore_traps_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_ignore_traps_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_ignore_traps_event", JsonBool(TRUE)); + if(ai_GetAIMode(oAssociate, AI_MODE_IGNORE_TRAPS)) sText = " Ignore Floor Traps On"; + else sText = " Ignore Floor Traps Off"; + NuiSetBind (oPC, nToken, "btn_ignore_traps_tooltip", JsonString(sText)); + // Row 15 + if(!bIsPC) + { + int nRange = GetLocalInt(oAssociate, AI_ASSOCIATE_PERCEPTION + "_MENU"); + if(nRange < 8 || nRange > 11) + { + nRange = GetLocalInt(oAssociate, AI_ASSOCIATE_PERCEPTION); + SetLocalInt(oAssociate, AI_ASSOCIATE_PERCEPTION + "_MENU", nRange); + } + if(nRange == 8) sText = " Perception Range Short [10 meters Sight / 10 meters Listen]"; + else if(nRange == 9) sText = " Perception Range Medium [20 meters Sight / 20 meters Listen]"; + else if(nRange == 10) sText = " Perception Range Long [35 meters Sight / 20 meters Listen]"; + else sText = " Perception Range Default [20 meters Sight / 20 meters Listen]"; + NuiSetBind(oPC, nToken, "chbx_perc_range_check", JsonBool(bPercRange)); + NuiSetBindWatch (oPC, nToken, "chbx_perc_range_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_perc_range_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_perc_range_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_perc_range_tooltip", JsonString(sText)); + } + // Row 16 + string sScript = GetLocalString(oAssociate, AI_COMBAT_SCRIPT); + if(sScript == "") sScript = GetLocalString(oAssociate, AI_COMBAT_SCRIPT); + NuiSetBind(oPC, nToken, "btn_ai_script_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_ai_script_tooltip", JsonString(" Sets " + GetName(oAssociate) + " to use the ai script in the text box.")); + NuiSetBind(oPC, nToken, "txt_ai_script_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "txt_ai_script", JsonString(sScript)); + NuiSetBind(oPC, nToken, "txt_ai_script_tooltip", JsonString(" Associate AI scripts must start with ai_a_")); + NuiSetBind(oPC, nToken, "cmb_ai_script_event", JsonBool(TRUE)); + NuiSetBindWatch(oPC, nToken, "cmb_ai_script_selected", TRUE); + // Row 17 + sText = ai_GetRandomTip(); + NuiSetBind (oPC, nToken, "lbl_info_label", JsonString(sText)); +} +void ai_SetWidgetBinds(object oPC, object oAssociate, string sAssociateType, int nToken, string sName) +{ + int bBool, bIsPC = ai_GetIsCharacter(oAssociate); + string sText, sRange, sHeal; + // Set event watches for save window location. + NuiSetBindWatch(oPC, nToken, "window_geometry", TRUE); + // Set the buttons to show events. + NuiSetBind(oPC, nToken, "btn_open_main_image", JsonString(GetPortraitResRef(oAssociate) + "s")); + NuiSetBind(oPC, nToken, "btn_open_main_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_open_main_tooltip", JsonString(" " + sName + " widget menu")); + if(bIsPC) sText = " All associates"; + else sText = " " + GetName(oAssociate); + if(ai_GetWidgetButton(oPC, BTN_CMD_ACTION, oAssociate, sAssociateType)) + { + NuiSetBind(oPC, nToken, "btn_cmd_action_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_cmd_action_tooltip", JsonString(sText + " do actions")); + } + if(ai_GetWidgetButton(oPC, BTN_CMD_GUARD, oAssociate, sAssociateType)) + { + NuiSetBind(oPC, nToken, "btn_cmd_guard_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_cmd_guard_tooltip", JsonString(sText + " enter guard mode")); + bBool = ai_GetAIMode(oAssociate, AI_MODE_DEFEND_MASTER); + NuiSetBind(oPC, nToken, "btn_cmd_guard_encouraged", JsonBool(bBool)); + } + if(ai_GetWidgetButton(oPC, BTN_CMD_HOLD, oAssociate, sAssociateType)) + { + NuiSetBind(oPC, nToken, "btn_cmd_hold_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_cmd_hold_tooltip", JsonString(sText + " enter hold mode")); + bBool = ai_GetAIMode(oAssociate, AI_MODE_STAND_GROUND); + NuiSetBind(oPC, nToken, "btn_cmd_hold_encouraged", JsonBool(bBool)); + } + if(ai_GetWidgetButton(oPC, BTN_CMD_ATTACK, oAssociate, sAssociateType)) + { + NuiSetBind(oPC, nToken, "btn_cmd_attack_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_cmd_attack_tooltip", JsonString(sText + " enter normal mode")); + if(!bIsPC) + { + 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; + if(!bIsPC) NuiSetBind(oPC, nToken, "btn_cmd_attack_encouraged", JsonBool(bBool)); + } + } + if(ai_GetWidgetButton(oPC, BTN_CMD_FOLLOW, oAssociate, sAssociateType)) + { + NuiSetBind(oPC, nToken, "btn_cmd_follow_event", JsonBool(TRUE)); + float fRange = GetLocalFloat(oAssociate, AI_FOLLOW_RANGE) + + StringToFloat(Get2DAString("appearance", "PREFATCKDIST", GetAppearanceType(oAssociate))); + string sRange = FloatToString(fRange, 0, 0); + if(bIsPC) + { + sText = " All associates"; + NuiSetBind(oPC, nToken, "btn_cmd_follow_tooltip", JsonString(sText + " enter follow mode")); + } + else + { + sText = " " + GetName(oAssociate); + NuiSetBind(oPC, nToken, "btn_cmd_follow_tooltip", JsonString(sText + " enter follow mode [" + sRange + " meters]")); + } + bBool = ai_GetAIMode(oAssociate, AI_MODE_FOLLOW); + if(!bIsPC) NuiSetBind(oPC, nToken, "btn_cmd_follow_encouraged", JsonBool(bBool)); + } + if(ai_GetAIButton(oPC, BTN_AI_FOLLOW_TARGET, oAssociate, sAssociateType)) + { + NuiSetBind(oPC, nToken, "btn_follow_target_event", JsonBool(TRUE)); + object oTarget = GetLocalObject(oAssociate, AI_FOLLOW_TARGET); + string sTarget; + if(oTarget != OBJECT_INVALID) sTarget = GetName(oTarget); + else + { + if(ai_GetIsCharacter(oAssociate)) sTarget = "nobody"; + else sTarget = GetName(oPC); + } + float fRange = GetLocalFloat(oAssociate, AI_FOLLOW_RANGE) + + StringToFloat(Get2DAString("appearance", "PREFATCKDIST", GetAppearanceType(oAssociate))); + string sRange = FloatToString(fRange, 0, 0); + NuiSetBind(oPC, nToken, "btn_follow_target_tooltip", JsonString(" " + GetName(oAssociate) + " following " + sTarget + " [" + sRange + " meters]")); + } + if(ai_GetWidgetButton(oPC, BTN_CMD_SEARCH, oAssociate, sAssociateType)) + { + NuiSetBind(oPC, nToken, "btn_cmd_search_event", JsonBool(TRUE)); + if(ai_GetAIMode(oPC, AI_MODE_AGGRESSIVE_SEARCH)) sText = " leave "; + else sText = " enter "; + NuiSetBind(oPC, nToken, "btn_cmd_search_tooltip", JsonString(" Everyone" + sText + "search mode")); + } + if(ai_GetWidgetButton(oPC, BTN_CMD_STEALTH, oAssociate, sAssociateType)) + { + NuiSetBind(oPC, nToken, "btn_cmd_stealth_event", JsonBool(TRUE)); + if(ai_GetAIMode(oPC, AI_MODE_AGGRESSIVE_STEALTH)) sText = " leave "; + else sText = " enter "; + NuiSetBind(oPC, nToken, "btn_cmd_stealth_tooltip", JsonString(" Everyone" + sText + "stealth mode")); + } + if(ai_GetWidgetButton(oPC, BTN_CMD_AI_SCRIPT, oAssociate, sAssociateType)) + { + sText = " Default tactics: Using the creatures base AI script"; + string sIcon = "ir_scommand"; + if(ResManGetAliasFor("0e_ch_1_hb", RESTYPE_NCS) != "") + { + string sScript = GetLocalString(oAssociate, AI_COMBAT_SCRIPT); + if(sScript == "ai_a_ambusher") + { + sText = " Ambusher: Attacks from a hidden position"; + sIcon = "ir_rogue"; + } + else if(sScript == "ai_a_flanker") + { + sText = " Flanker: Attacks enemies engaged with allies"; + sIcon = "ir_invite"; + } + else if(sScript == "ai_a_peaceful") + { + sText = " Peaceful: Avoids attacking any enemies if possible"; + sIcon = "ir_ignore"; + } + else if(sScript == "ai_a_defensive") + { + sText = " Defensive: Attacks then uses Expertise/Parry"; + sIcon = "ir_knockdwn"; + } + else if(sScript == "ai_a_ranged") + { + sText = " Ranged: Attacks from range as much as possible"; + sIcon = "ir_ranger"; + } + else if(sScript == "ai_a_cntrspell") + { + sText = " Counter Spell: Tries to counter enemy spells"; + sIcon = "ir_dcaster"; + } + } + else + { + if(GetCombatCondition(X0_COMBAT_FLAG_AMBUSHER, oAssociate)) sText = "Using ambush tactics"; + if(GetCombatCondition(X0_COMBAT_FLAG_COWARDLY, oAssociate)) sText = "Using coward tactics"; + if(GetCombatCondition(X0_COMBAT_FLAG_DEFENSIVE, oAssociate)) sText = "Using defensive tactics"; + if(GetCombatCondition(X0_COMBAT_FLAG_RANGED, oAssociate)) sText = "Using ranged tactics"; + } + NuiSetBind(oPC, nToken, "btn_cmd_ai_script_image", JsonString(sIcon)); + NuiSetBind(oPC, nToken, "btn_cmd_ai_script_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_cmd_ai_script_tooltip", JsonString(sText)); + } + if(ai_GetWidgetButton(oPC, BTN_CMD_PLACE_TRAP, oAssociate, sAssociateType)) + { + NuiSetBind(oPC, nToken, "btn_cmd_place_trap_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_cmd_place_trap_tooltip", JsonString(" Place a trap at the location selected")); + } + if(ai_GetWidgetButton(oPC, BTN_BUFF_SHORT, oAssociate, sAssociateType)) + { + NuiSetBind(oPC, nToken, "btn_buff_short_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_buff_short_tooltip", JsonString(" Buff the party with short duration spells")); + } + if(ai_GetWidgetButton(oPC, BTN_BUFF_LONG, oAssociate, sAssociateType)) + { + NuiSetBind(oPC, nToken, "btn_buff_long_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_buff_long_tooltip", JsonString(" Buff the party with long duration spells")); + } + if(ai_GetWidgetButton(oPC, BTN_BUFF_ALL, oAssociate, sAssociateType)) + { + NuiSetBind(oPC, nToken, "btn_buff_all_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_buff_all_tooltip", JsonString(" Buff the party with all our defensive spells")); + } + if(ai_GetWidgetButton(oPC, BTN_CMD_JUMP_TO, oAssociate, sAssociateType)) + { + NuiSetBind(oPC, nToken, "btn_jump_to_event", JsonBool(TRUE)); + sText = GetName(oPC); + if(oPC == oAssociate) sName = "everyone"; + else sName = GetName(oAssociate); + NuiSetBind(oPC, nToken, "btn_jump_to_tooltip", JsonString(" Jump " + sName + " to " + sText)); + } + if(ai_GetWidgetButton(oPC, BTN_CMD_GHOST_MODE, oAssociate, sAssociateType)) + { + NuiSetBind(oPC, nToken, "btn_ghost_mode_event", JsonBool (TRUE)); + sText = "On"; + if(ai_GetAIMode(oAssociate, AI_MODE_GHOST)) sText = "Off"; + NuiSetBind(oPC, nToken, "btn_ghost_mode_tooltip", JsonString ( + " Turn " + sText + " clipping through creatures for " + GetName(oAssociate))); + } + if(ai_GetWidgetButton(oPC, BTN_CMD_CAMERA, oAssociate, sAssociateType)) + { + NuiSetBind(oPC, nToken, "btn_camera_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_camera_tooltip", JsonString(" Toggle camera view for " + sName)); + } + if(ai_GetWidgetButton(oPC, BTN_CMD_INVENTORY, oAssociate, sAssociateType)) + { + NuiSetBind(oPC, nToken, "btn_inventory_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_inventory_tooltip", JsonString(" Open " + sName + " inventory")); + } + if(ai_GetWidgetButton(oPC, BTN_CMD_FAMILIAR, oAssociate, sAssociateType)) + { + NuiSetBind(oPC, nToken, "btn_familiar_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_familiar_tooltip", JsonString(" Summon " + sName + " familiar.")); + } + if(ai_GetWidgetButton(oPC, BTN_CMD_COMPANION, oAssociate, sAssociateType)) + { + NuiSetBind(oPC, nToken, "btn_companion_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_companion_tooltip", JsonString(" Open " + sName + " Animal Companion.")); + } + if(ai_GetWidgetButton(oPC, BTN_BUFF_REST, oAssociate, sAssociateType)) + { + NuiSetBind(oPC, nToken, "btn_buff_rest_event", JsonBool(TRUE)); + if(ai_GetMagicMode(oAssociate, AI_MAGIC_BUFF_AFTER_REST)) sText = " Turn buffing after resting off"; + else sText = " Turn buffing after resting on."; + NuiSetBind(oPC, nToken, "btn_buff_rest_tooltip", JsonString(sText)); + } + if(ai_GetAIButton(oPC, BTN_AI_FOR_PC, oAssociate, sAssociateType)) + { + NuiSetBind(oPC, nToken, "btn_ai_event", JsonBool(TRUE)); + if(GetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT) == "xx_pc_1_hb") sText = " AI [On] Turn off"; + else sText = " AI [Off] Turn on"; + NuiSetBind(oPC, nToken, "btn_ai_tooltip", JsonString(sText)); + } + if(ai_GetAIButton(oPC, BTN_AI_REDUCE_SPEECH, oAssociate, sAssociateType)) + { + NuiSetBind(oPC, nToken, "btn_quiet_event", JsonBool(TRUE)); + if(ai_GetAIMode(oAssociate, AI_MODE_DO_NOT_SPEAK)) sText = " Reduced Speech On"; + else sText = " Reduced Speech Off"; + NuiSetBind(oPC, nToken, "btn_quiet_tooltip", JsonString(sText)); + } + if(ai_GetAIButton(oPC, BTN_AI_USE_RANGED, oAssociate, sAssociateType)) + { + NuiSetBind(oPC, nToken, "btn_ranged_event", JsonBool(TRUE)); + if(ai_GetAIMode(oAssociate, AI_MODE_STOP_RANGED)) sText = " Ranged Off"; + else sText = " Ranged On"; + NuiSetBind(oPC, nToken, "btn_ranged_tooltip", JsonString(sText)); + } + if(ai_GetAIButton(oPC, BTN_AI_STOP_WEAPON_EQUIP, oAssociate, sAssociateType)) + { + NuiSetBind(oPC, nToken, "btn_equip_weapon_event", JsonBool(TRUE)); + if(ai_GetAIMode(oAssociate, AI_MODE_EQUIP_WEAPON_OFF)) sText = " Equiping Best Weapons Off"; + else sText = " Equiping Best Weapons On"; + NuiSetBind(oPC, nToken, "btn_equip_weapon_tooltip", JsonString(sText)); + } + if(ai_GetAIButton(oPC, BTN_AI_USE_SEARCH, oAssociate, sAssociateType)) + { + NuiSetBind(oPC, nToken, "btn_search_event", JsonBool(TRUE)); + if(ai_GetAIMode(oAssociate, AI_MODE_AGGRESSIVE_SEARCH)) sText = " Search On"; + else sText = " Search Off"; + NuiSetBind(oPC, nToken, "btn_search_tooltip", JsonString(sText)); + } + if(ai_GetAIButton(oPC, BTN_AI_USE_STEALTH, oAssociate, sAssociateType)) + { + NuiSetBind(oPC, nToken, "btn_stealth_event", JsonBool(TRUE)); + if(ai_GetAIMode(oAssociate, AI_MODE_AGGRESSIVE_STEALTH)) sText = " Stealth On"; + else sText = " Stealth Off"; + NuiSetBind(oPC, nToken, "btn_stealth_tooltip", JsonString(sText)); + } + if(ai_GetAIButton(oPC, BTN_AI_OPEN_DOORS, oAssociate, sAssociateType)) + { + sRange = FloatToString(GetLocalFloat(oAssociate, AI_OPEN_DOORS_RANGE), 0, 0); + NuiSetBind(oPC, nToken, "btn_open_door_event", JsonBool(TRUE)); + if(ai_GetAIMode(oAssociate, AI_MODE_OPEN_DOORS)) sText = " Open Doors On [" + sRange + " meters]"; + else sText = " Open Doors Off [" + sRange + " meters]"; + NuiSetBind(oPC, nToken, "btn_open_door_tooltip", JsonString(sText)); + } + if(ai_GetAIButton(oPC, BTN_AI_REMOVE_TRAPS, oAssociate, sAssociateType)) + { + sRange = FloatToString(GetLocalFloat(oAssociate, AI_TRAP_CHECK_RANGE), 0, 0); + NuiSetBind(oPC, nToken, "btn_traps_event", JsonBool(TRUE)); + if(ai_GetAIMode(oAssociate, AI_MODE_DISARM_TRAPS)) sText = " Disable Traps On [" + sRange + " meters]"; + else sText = " Disable Traps Off [" + sRange + " meters]"; + NuiSetBind(oPC, nToken, "btn_traps_tooltip", JsonString(sText)); + } + if(ai_GetAIButton(oPC, BTN_AI_PICK_LOCKS, oAssociate, sAssociateType)) + { + sRange = FloatToString(GetLocalFloat(oAssociate, AI_LOCK_CHECK_RANGE), 0, 0); + NuiSetBind(oPC, nToken, "btn_pick_locks_event", JsonBool(TRUE)); + if(ai_GetAIMode(oAssociate, AI_MODE_PICK_LOCKS)) sText = " Pick locks On [" + sRange + " meters]"; + else sText = " Pick Locks Off [" + sRange + " meters]"; + NuiSetBind(oPC, nToken, "btn_pick_locks_tooltip", JsonString(sText)); + } + if(ai_GetAIButton(oPC, BTN_AI_BASH_LOCKS, oAssociate, sAssociateType)) + { + sRange = FloatToString(GetLocalFloat(oAssociate, AI_LOCK_CHECK_RANGE), 0, 0); + NuiSetBind(oPC, nToken, "btn_bash_locks_event", JsonBool(TRUE)); + if(ai_GetAIMode(oAssociate, AI_MODE_BASH_LOCKS)) sText = " Bash On [" + sRange + " meters]"; + else sText = " Bash Off [" + sRange + " meters]"; + NuiSetBind(oPC, nToken, "btn_bash_locks_tooltip", JsonString(sText)); + } + if(ai_GetAIButton(oPC, BTN_AI_MAGIC_LEVEL, oAssociate, sAssociateType)) + { + NuiSetBind(oPC, nToken, "btn_magic_level_event", JsonBool(TRUE)); + string sMagic = IntToString(GetLocalInt(oAssociate, AI_DIFFICULTY_ADJUSTMENT)); + NuiSetBind(oPC, nToken, "btn_magic_level_tooltip", JsonString(" Magic Level [" + sMagic + "]")); + } + if(ai_GetAIButton(oPC, BTN_AI_NO_SPONTANEOUS, oAssociate, sAssociateType)) + { + string sCasting = " Spontaneous casting On"; + if(ai_GetMagicMode(oAssociate, AI_MAGIC_NO_SPONTANEOUS_CURE)) sCasting = " Spontaneous casting Off"; + NuiSetBind(oPC, nToken, "btn_spontaneous_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_spontaneous_tooltip", JsonString(sCasting)); + } + if(ai_GetAIButton(oPC, BTN_AI_NO_MAGIC_USE, oAssociate, sAssociateType)) + { + if(ai_GetAIMode(oAssociate, AI_MAGIC_NO_MAGIC)) sText = " Magic Off"; + else sText = " Magic On"; + NuiSetBind(oPC, nToken, "btn_magic_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_magic_tooltip", JsonString(sText)); + } + if(ai_GetAIButton(oPC, BTN_AI_NO_MAGIC_ITEM_USE, oAssociate, sAssociateType)) + { + if(ai_GetAIMode(oAssociate, AI_MAGIC_NO_MAGIC_ITEMS)) sText = " Magic Items Off"; + else sText = " Magic Items On"; + NuiSetBind(oPC, nToken, "btn_magic_items_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_magic_items_tooltip", JsonString(sText)); + } + if(ai_GetAIButton(oPC, BTN_AI_DEF_MAGIC_USE, oAssociate, sAssociateType)) + { + if(ai_GetAIMode(oAssociate, AI_MAGIC_DEFENSIVE_CASTING)) sText = " Defensive Magic On"; + else sText = " Defensive Magic Off"; + NuiSetBind(oPC, nToken, "btn_def_magic_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_def_magic_tooltip", JsonString(sText)); + } + if(ai_GetAIButton(oPC, BTN_AI_OFF_MAGIC_USE, oAssociate, sAssociateType)) + { + if(ai_GetAIMode(oAssociate, AI_MAGIC_OFFENSIVE_CASTING)) sText = " Offensive Magic On"; + else sText = " Offensive Magic Off"; + NuiSetBind(oPC, nToken, "btn_off_magic_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_off_magic_tooltip", JsonString(sText)); + } + if(ai_GetAIButton(oPC, BTN_AI_HEAL_OUT, oAssociate, sAssociateType)) + { + NuiSetBind(oPC, nToken, "btn_heal_out_event", JsonBool(TRUE)); + sHeal = IntToString(GetLocalInt(oAssociate, AI_HEAL_OUT_OF_COMBAT_LIMIT)); + sText = " Will heal at or below [" + sHeal + "%] health out of combat"; + NuiSetBind(oPC, nToken, "btn_heal_out_tooltip", JsonString(sText)); + } + if(ai_GetAIButton(oPC, BTN_AI_HEAL_IN, oAssociate, sAssociateType)) + { + NuiSetBind(oPC, nToken, "btn_heal_in_event", JsonBool(TRUE)); + sHeal = IntToString(GetLocalInt(oAssociate, AI_HEAL_IN_COMBAT_LIMIT)); + sText = " Will heal at or below [" + sHeal + "%] health in combat"; + NuiSetBind(oPC, nToken, "btn_heal_in_tooltip", JsonString(sText)); + } + if(ai_GetAIButton(oPC, BTN_AI_STOP_SELF_HEALING, oAssociate, sAssociateType)) + { + NuiSetBind(oPC, nToken, "btn_heals_onoff_event", JsonBool(TRUE)); + if(ai_GetAIMode(oAssociate, AI_MODE_SELF_HEALING_OFF)) sText = " Self healing Off"; + else sText = " Self healing On"; + NuiSetBind(oPC, nToken, "btn_heals_onoff_tooltip", JsonString(sText)); + } + if(ai_GetAIButton(oPC, BTN_AI_STOP_PARTY_HEALING, oAssociate, sAssociateType)) + { + NuiSetBind(oPC, nToken, "btn_healp_onoff_event", JsonBool(TRUE)); + if(ai_GetAIMode(oAssociate, AI_MODE_PARTY_HEALING_OFF)) sText = " Party healing Off"; + else sText = " Party healing On"; + NuiSetBind(oPC, nToken, "btn_healp_onoff_tooltip", JsonString(sText)); + } + if(ai_GetAIButton(oPC, BTN_AI_STOP_CURE_SPELLS, oAssociate, sAssociateType)) + { + NuiSetBind(oPC, nToken, "btn_cure_onoff_event", JsonBool(TRUE)); + if(ai_GetMagicMode(oAssociate, AI_MAGIC_CURE_SPELLS_OFF)) sText = " Cast Cure Spells Off"; + else sText = " Cast Cure Spells On"; + NuiSetBind(oPC, nToken, "btn_cure_onoff_tooltip", JsonString(sText)); + } + if(ai_GetAIButton(oPC, BTN_AI_LOOT, oAssociate, sAssociateType)) + { + sRange = FloatToString(GetLocalFloat(oAssociate, AI_LOOT_CHECK_RANGE), 0, 0); + string sLoot = " Looting Off [" + sRange + " meters]"; + if(ai_GetAIMode(oAssociate, AI_MODE_PICKUP_ITEMS)) sLoot = " Looting On [" + sRange + " meters]"; + NuiSetBind(oPC, nToken, "btn_loot_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_loot_tooltip", JsonString(sLoot)); + } + if(ai_GetAIButton(oPC, BTN_AI_IGNORE_ASSOCIATES, oAssociate, sAssociateType)) + { + NuiSetBind(oPC, nToken, "btn_ignore_assoc_event", JsonBool(TRUE)); + if(ai_GetAIMode(oAssociate, AI_MODE_IGNORE_ASSOCIATES)) sText = " Ignore Enemy Associates On"; + else sText = " Ignore Enemy Associates Off"; + NuiSetBind(oPC, nToken, "btn_ignore_assoc_tooltip", JsonString(sText)); + } + if(ai_GetAIButton(oPC, BTN_AI_IGNORE_TRAPS, oAssociate, sAssociateType)) + { + NuiSetBind(oPC, nToken, "btn_ignore_traps_event", JsonBool(TRUE)); + if(ai_GetAIMode(oAssociate, AI_MODE_IGNORE_TRAPS)) sText = " Ignore Floor Traps On"; + else sText = " Ignore Floor Traps Off"; + NuiSetBind(oPC, nToken, "btn_ignore_traps_tooltip", JsonString(sText)); + } + json jAIData = ai_GetAssociateDbJson(oPC, sAssociateType, "aidata"); + if(ai_GetAIButton(oPC, BTN_AI_PERC_RANGE, oAssociate, sAssociateType)) + { + int nRange = GetLocalInt(oAssociate, AI_ASSOCIATE_PERCEPTION); + if(nRange < 8 || nRange > 11) + { + nRange = 11; + SetLocalInt(oAssociate, AI_ASSOCIATE_PERCEPTION, 11); + jAIData = JsonArraySet(jAIData, 7, JsonInt(11)); + ai_SetAssociateDbJson(oPC, sAssociateType, "aidata", jAIData); + } + if(nRange == 8) sText = " Perception Range Short [10 meters Sight / 10 meters Listen]"; + if(nRange == 9) sText = " Perception Range Medium [20 meters Sight / 20 meters Listen]"; + if(nRange == 10) sText = " Perception Range Long [35 meters Sight / 20 meters Listen]"; + else sText = " Perception Range Default [20 meters Sight / 20 meters Listen]"; + NuiSetBind(oPC, nToken, "btn_perc_range_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_perc_range_tooltip", JsonString(sText)); + } + if(bIsPC) + { + int nIndex, bWidget; + string sButton, sName, sText, sScript; + json jPCPlugins = ai_UpdatePluginsForPC(oPC); + json jPlugin = JsonArrayGet(jPCPlugins, nIndex); + while(JsonGetType(jPlugin) != JSON_TYPE_NULL) + { + bWidget = JsonGetInt(JsonArrayGet(jPlugin, 1)); + if(bWidget) + { + sButton = IntToString(nIndex); + sScript = JsonGetString(JsonArrayGet(jPlugin, 0)); + if(ResManGetAliasFor(sScript, RESTYPE_NCS) == "") + { + sText = " " + sScript + " not found by ResMan!"; + } + else sName = " " + JsonGetString(JsonArrayGet(jPlugin, 2)); + NuiSetBind(oPC, nToken, "btn_exe_plugin_" + sButton + "_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "btn_exe_plugin_" + sButton + "_tooltip", JsonString(sName)); + } + jPlugin = JsonArrayGet(jPCPlugins, ++nIndex); + } + } + if(ai_GetWidgetButton(oPC, BTN_CMD_SPELL_WIDGET, oAssociate, sAssociateType)) + { + NuiSetBind(oPC, nToken, "btn_update_widget_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_update_widget_tooltip", JsonString(" Updates Quick Use Widget")); + json jSpell, jSpells = JsonArrayGet(jAIData, 10); + json jWidget = JsonArrayGet(jSpells, 2); + object oItem; + if(JsonGetType(jWidget) != JSON_TYPE_NULL) + { + int nLevel, nSpell, nIndex, nClass, nMetaMagic, nDomain, nSubSpell, nFeat; + string sSpellIcon, sMetaMagicText, sSubSpell, sClass, sIndex; + while(nIndex < 10) + { + jSpell = JsonArrayGet(jWidget, nIndex); + if(JsonGetType(jSpell) != JSON_TYPE_NULL) + { + sIndex = IntToString(nIndex); + nSpell = JsonGetInt(JsonArrayGet(jSpell, 0)); + nClass = JsonGetInt(JsonArrayGet(jSpell, 1)); + if(nClass == -1) // This is an Item. + { + string sBaseName; + sName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); + int nBaseItemType = JsonGetInt(JsonArrayGet(jSpell, 3)); + int nIprpSubType = JsonGetInt(JsonArrayGet(jSpell, 4)); + if(nSpell == SPELL_HEALINGKIT) + { + sName = "Healer's Kit +" + IntToString(nIprpSubType); + sSpellIcon = "isk_heal"; + sBaseName = "Healer's Kit"; + } + else if(nBaseItemType == BASE_ITEM_ENCHANTED_SCROLL || + nBaseItemType == BASE_ITEM_SCROLL || + nBaseItemType == BASE_ITEM_SPELLSCROLL) + { + sSpellIcon = Get2DAString("iprp_spells", "Icon", nIprpSubType); + sBaseName = "Scroll"; + } + else + { + if(nBaseItemType == BASE_ITEM_ENCHANTED_POTION || + nBaseItemType == BASE_ITEM_POTIONS) sBaseName = "Potion"; + else if(nBaseItemType == BASE_ITEM_ENCHANTED_WAND || + nBaseItemType == BASE_ITEM_MAGICWAND || + nBaseItemType == FEAT_CRAFT_WAND) sBaseName = "Wand"; + else sBaseName = ai_StripColorCodes(GetName(GetObjectByUUID(JsonGetString(JsonArrayGet(jSpell, 5))))); + sSpellIcon = Get2DAString("spells", "IconResRef", nSpell); + } + NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_image", JsonString(sSpellIcon)); + oItem = GetObjectByUUID(JsonGetString(JsonArrayGet(jSpell, 5))); + int nUses = ai_GetItemUses(oItem, nIprpSubType); + if(nUses) + { + NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_event", JsonBool(TRUE)); + if(nUses == 999) sText = "Unlimited"; + else sText = IntToString(nUses); + NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_tooltip", JsonString(" " + sName + " (" + sBaseName + " / " + sText + ")")); + } + else NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_event", JsonBool(FALSE)); + } + else + { + nFeat = JsonGetInt(JsonArrayGet(jSpell, 5)); + if(nFeat) // This is a feat. + { + nSpell = JsonGetInt(JsonArrayGet(jSpell, 0)); + sSpellIcon = ""; + if(nSpell) + { + sName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); + sSpellIcon = Get2DAString("spells", "IconResRef", nSpell); + } + if(sSpellIcon == "" || sSpellIcon == "IR_USE") + { + sName = GetStringByStrRef(StringToInt(Get2DAString("feat", "FEAT", nFeat))); + sSpellIcon = Get2DAString("feat", "ICON", nFeat); + } + NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_image", JsonString(sSpellIcon)); + if(GetHasFeat(nFeat, oAssociate)) + { + NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_tooltip", JsonString(" " + sName)); + } + else NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_event", JsonBool(FALSE)); + } + else // This is a spell. + { + nSpell = JsonGetInt(JsonArrayGet(jSpell, 0)); + nClass = JsonGetInt(JsonArrayGet(jSpell, 1)); + nLevel = JsonGetInt(JsonArrayGet(jSpell, 2)); + nDomain = JsonGetInt(JsonArrayGet(jSpell, 4)); + nMetaMagic = JsonGetInt(JsonArrayGet(jSpell, 3)); + sSpellIcon = Get2DAString("spells", "IconResRef", nSpell); + NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_image", JsonString(sSpellIcon)); + sMetaMagicText = ai_GetSpellIconAttributes(oAssociate, nMetaMagic, nDomain); + NuiSetBind(oPC, nToken, "metamagic_" + sIndex + "_text", JsonString(sMetaMagicText)); + if(GetSpellUsesLeft(oAssociate, nClass, nSpell, nMetaMagic, nDomain)) + { + sName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); + sClass = GetStringByStrRef(StringToInt(Get2DAString("classes", "Name", nClass))); + NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_tooltip", JsonString(" " + sName + " (" + sClass + " / " + IntToString(nLevel) + ")")); + } + else NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_event", JsonBool(FALSE)); + } + } + } + else break; + ++nIndex; + } + while(nIndex < 20) + { + jSpell = JsonArrayGet(jWidget, nIndex); + if(JsonGetType(jSpell) != JSON_TYPE_NULL) + { + sIndex = IntToString(nIndex); + nSpell = JsonGetInt(JsonArrayGet(jSpell, 0)); + nClass = JsonGetInt(JsonArrayGet(jSpell, 1)); + nFeat = JsonGetInt(JsonArrayGet(jSpell, 5)); + if(nClass == -1) // This is an Item. + { + oItem = GetObjectByUUID(JsonGetString(JsonArrayGet(jSpell, 5))); + if(oItem != OBJECT_INVALID) + { + string sBaseName; + sName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); + int nBaseItemType = JsonGetInt(JsonArrayGet(jSpell, 3)); + int nIprpSubType = JsonGetInt(JsonArrayGet(jSpell, 4)); + if(nSpell == SPELL_HEALINGKIT) + { + sName = "Healer's Kit +" + IntToString(nIprpSubType); + sSpellIcon = "isk_heal"; + sBaseName = "Healer's Kit"; + } + else if(nBaseItemType == BASE_ITEM_ENCHANTED_SCROLL || + nBaseItemType == BASE_ITEM_SCROLL || + nBaseItemType == BASE_ITEM_SPELLSCROLL) + { + sSpellIcon = Get2DAString("iprp_spells", "Icon", nIprpSubType); + sBaseName = "Scroll"; + } + else + { + if(nBaseItemType == BASE_ITEM_ENCHANTED_POTION || + nBaseItemType == BASE_ITEM_POTIONS) sBaseName = "Potion"; + else if(nBaseItemType == BASE_ITEM_ENCHANTED_WAND || + nBaseItemType == BASE_ITEM_MAGICWAND || + nBaseItemType == FEAT_CRAFT_WAND) sBaseName = "Wand"; + else sBaseName = ai_StripColorCodes(GetName(GetObjectByUUID(JsonGetString(JsonArrayGet(jSpell, 5))))); + sSpellIcon = Get2DAString("spells", "IconResRef", nSpell); + } + NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_image", JsonString(sSpellIcon)); + int nUses = ai_GetItemUses(oItem, nIprpSubType); + if(nUses) + { + NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_event", JsonBool(TRUE)); + if(nUses == 999) sText = "Unlimited"; + else sText = IntToString(nUses); + NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_tooltip", JsonString(" " + sName + " (" + sBaseName + " / " + sText + ")")); + } + else NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_event", JsonBool(FALSE)); + } + else jWidget = JsonArrayDel(jWidget, nIndex--); + } + else if(nFeat) // This is a feat. + { + nSpell = JsonGetInt(JsonArrayGet(jSpell, 0)); + sSpellIcon = ""; + if(nSpell) + { + sName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); + sSpellIcon = Get2DAString("spells", "IconResRef", nSpell); + } + if(sSpellIcon == "" || sSpellIcon == "IR_USE") + { + sName = GetStringByStrRef(StringToInt(Get2DAString("feat", "FEAT", nFeat))); + sSpellIcon = Get2DAString("feat", "ICON", nFeat); + } + NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_image", JsonString(sSpellIcon)); + if(GetHasFeat(nFeat, oAssociate)) + { + NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_tooltip", JsonString(" " + sName)); + } + else NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_event", JsonBool(FALSE)); + } + else // This is a spell. + { + nSpell = JsonGetInt(JsonArrayGet(jSpell, 0)); + nClass = JsonGetInt(JsonArrayGet(jSpell, 1)); + nDomain = JsonGetInt(JsonArrayGet(jSpell, 4)); + nMetaMagic = JsonGetInt(JsonArrayGet(jSpell, 3)); + sSpellIcon = Get2DAString("spells", "IconResRef", nSpell); + //SendMessageToPC(oPC, GetName(oAssociate) + " nSpell: " + IntToString(nSpell) + + // " nClass: " + IntToString(nClass) + " nMetaMagic: " + IntToString(nMetaMagic) + + // " nDomain: " + IntToString(nDomain) + " nLevel: " + IntToString(nLevel)); + NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_image", JsonString(sSpellIcon)); + sMetaMagicText = ai_GetSpellIconAttributes(oAssociate, nMetaMagic, nDomain); + NuiSetBind(oPC, nToken, "metamagic_" + sIndex + "_text", JsonString(sMetaMagicText)); + sSubSpell = Get2DAString("spells", "Master", nSpell); + if(sSubSpell != "") nSpell = StringToInt(sSubSpell); + if(nDomain == -1 || GetSpellUsesLeft(oAssociate, nClass, nSpell, nMetaMagic, nDomain)) + { + sName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); + if(nDomain == -1) NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_tooltip", JsonString(" " + sName)); + else + { + sClass = GetStringByStrRef(StringToInt(Get2DAString("classes", "Name", nClass))); + NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_tooltip", JsonString(" " + sName + " (" + sClass + " / " + IntToString(nLevel) + ")")); + } + } + else NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_event", JsonBool(FALSE)); + } + } + else break; + ++nIndex; + } + } + } +} +void ai_CreateWidgetNUI(object oPC, object oAssociate) +{ + // Set window to not save until it has been created. + SetLocalInt (oPC, AI_NO_NUI_SAVE, TRUE); + DelayCommand (2.0f, DeleteLocalInt (oPC, AI_NO_NUI_SAVE)); + string sAssociateType = ai_GetAssociateType(oPC, oAssociate); + if(sAssociateType == "") return; + int bAIWidgetLock = ai_GetWidgetButton(oPC, BTN_WIDGET_LOCK, oAssociate, sAssociateType); + int bVertical = ai_GetWidgetButton(oPC, BTN_WIDGET_VERTICAL, oAssociate, sAssociateType); + float fButtons; + // ************************************************************************* Width / Height + // Row 1 (buttons)********************************************************** + // Setup the main associate button to use their portrait. + json jButton = NuiEnabled(NuiId (NuiButtonImage(NuiBind("btn_open_main_image")), "btn_open_main"), NuiBind("btn_open_main_event")); + jButton = NuiWidth(jButton, 35.0); + jButton = NuiHeight(jButton, 35.0); + jButton = NuiMargin(jButton, 0.0); + jButton = NuiTooltip(jButton, NuiBind ("btn_open_main_tooltip")); + jButton = NuiImageRegion(jButton, NuiRect(0.0, 0.0, 32.0, 35.0)); + json jRow = JsonArrayInsert(JsonArray(), jButton); + if(ai_GetWidgetButton(oPC, BTN_CMD_ACTION, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "ir_action", "btn_cmd_action", 35.0f, 35.0f, 0.0, "btn_cmd_action_tooltip"); + fButtons += 1.0; + } + if(ai_GetWidgetButton(oPC, BTN_CMD_GUARD, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "ir_guard", "btn_cmd_guard", 35.0f, 35.0f, 0.0, "btn_cmd_guard_tooltip"); + fButtons += 1.0; + } + if(ai_GetWidgetButton(oPC, BTN_CMD_HOLD, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "ir_standground", "btn_cmd_hold", 35.0f, 35.0f, 0.0, "btn_cmd_hold_tooltip"); + fButtons += 1.0; + } + if(ai_GetWidgetButton(oPC, BTN_CMD_ATTACK, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "ir_attacknearest", "btn_cmd_attack", 35.0f, 35.0f, 0.0, "btn_cmd_attack_tooltip"); + fButtons += 1.0; + } + if(ai_GetWidgetButton(oPC, BTN_CMD_FOLLOW, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "ir_follow", "btn_cmd_follow", 35.0f, 35.0f, 0.0, "btn_cmd_follow_tooltip"); + fButtons += 1.0; + } + if(ai_GetAIButton(oPC, BTN_AI_FOLLOW_TARGET, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "ir_dmchat", "btn_follow_target", 35.0f, 35.0f, 0.0, "btn_follow_target_tooltip"); + fButtons += 1.0; + } + if(ai_GetWidgetButton(oPC, BTN_CMD_SEARCH, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "ife_foc_search", "btn_cmd_search", 35.0f, 35.0f, 0.0, "btn_cmd_search_tooltip"); + fButtons += 1.0; + } + if(ai_GetWidgetButton(oPC, BTN_CMD_STEALTH, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "ife_foc_hide", "btn_cmd_stealth", 35.0f, 35.0f, 0.0, "btn_cmd_stealth_tooltip"); + fButtons += 1.0; + } + if(ai_GetWidgetButton(oPC, BTN_CMD_AI_SCRIPT, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "", "btn_cmd_ai_script", 35.0f, 35.0f, 0.0, "btn_cmd_ai_script_tooltip"); + fButtons += 1.0; + } + if(ai_GetWidgetButton(oPC, BTN_CMD_PLACE_TRAP, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "isk_settrap", "btn_cmd_place_trap", 35.0f, 35.0f, 0.0, "btn_cmd_place_trap_tooltip"); + fButtons += 1.0; + } + if(ai_GetWidgetButton(oPC, BTN_BUFF_SHORT, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "ir_cantrips", "btn_buff_short", 35.0f, 35.0f, 0.0, "btn_buff_short_tooltip"); + fButtons += 1.0; + } + if(ai_GetWidgetButton(oPC, BTN_BUFF_LONG, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "ir_cast", "btn_buff_long", 35.0f, 35.0f, 0.0, "btn_buff_long_tooltip"); + fButtons += 1.0; + } + if(ai_GetWidgetButton(oPC, BTN_BUFF_ALL, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "ir_level789", "btn_buff_all", 35.0f, 35.0f, 0.0, "btn_buff_all_tooltip"); + fButtons += 1.0; + } + if(ai_GetWidgetButton(oPC, BTN_BUFF_REST, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "ir_rest", "btn_buff_rest", 35.0f, 35.0f, 0.0, "btn_buff_rest_tooltip"); + fButtons += 1.0; + } + if(ai_GetWidgetButton(oPC, BTN_CMD_JUMP_TO, oAssociate, sAssociateType)) + { + string sImage; + if(oPC == oAssociate) sImage = "dm_jumpall"; + else sImage = "dm_jump"; + jRow = CreateButtonImage(jRow, sImage, "btn_jump_to", 35.0f, 35.0f, 0.0, "btn_jump_to_tooltip"); + fButtons += 1.0; + } + if(ai_GetWidgetButton(oPC, BTN_CMD_GHOST_MODE, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "dm_limbo", "btn_ghost_mode", 35.0f, 35.0f, 0.0, "btn_ghost_mode_tooltip"); + fButtons += 1.0; + } + if(ai_GetWidgetButton(oPC, BTN_CMD_CAMERA, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "ir_examine", "btn_camera", 35.0f, 35.0f, 0.0, "btn_camera_tooltip"); + fButtons += 1.0; + } + if(ai_GetWidgetButton(oPC, BTN_CMD_INVENTORY, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "ir_pickup", "btn_inventory", 35.0f, 35.0f, 0.0, "btn_inventory_tooltip"); + fButtons += 1.0; + } + if(ai_GetWidgetButton(oPC, BTN_CMD_FAMILIAR, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "ife_familiar", "btn_familiar", 35.0f, 35.0f, 0.0, "btn_familiar_tooltip"); + fButtons += 1.0; + } + if(ai_GetWidgetButton(oPC, BTN_CMD_COMPANION, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "ife_animal", "btn_companion", 35.0f, 35.0f, 0.0, "btn_companion_tooltip"); + fButtons += 1.0; + } + if(ai_GetAIButton(oPC, BTN_AI_FOR_PC, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "dm_ai", "btn_ai", 35.0f, 35.0f, 0.0, "btn_ai_tooltip"); + fButtons += 1.0; + } + if(ai_GetAIButton(oPC, BTN_AI_REDUCE_SPEECH, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "isk_movsilent", "btn_quiet", 35.0f, 35.0f, 0.0, "btn_quiet_tooltip"); + fButtons += 1.0; + } + if(ai_GetAIButton(oPC, BTN_AI_USE_RANGED, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "ir_archer", "btn_ranged", 35.0f, 35.0f, 0.0, "btn_ranged_tooltip"); + fButtons += 1.0; + } + if(ai_GetAIButton(oPC, BTN_AI_STOP_WEAPON_EQUIP, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "dm_takeitem", "btn_equip_weapon", 35.0f, 35.0f, 0.0, "btn_equip_weapon_tooltip"); + fButtons += 1.0; + } + if(ai_GetAIButton(oPC, BTN_AI_USE_SEARCH, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "isk_search", "btn_search", 35.0f, 35.0f, 0.0, "btn_search_tooltip"); + fButtons += 1.0; + } + if(ai_GetAIButton(oPC, BTN_AI_USE_STEALTH, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "isk_hide", "btn_stealth", 35.0f, 35.0f, 0.0, "btn_stealth_tooltip"); + fButtons += 1.0; + } + if(ai_GetAIButton(oPC, BTN_AI_OPEN_DOORS, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "ir_open", "btn_open_door", 35.0f, 35.0f, 0.0, "btn_open_door_tooltip"); + fButtons += 1.0; + } + if(ai_GetAIButton(oPC, BTN_AI_REMOVE_TRAPS, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "isk_distrap", "btn_traps", 35.0f, 35.0f, 0.0, "btn_traps_tooltip"); + fButtons += 1.0; + } + if(ai_GetAIButton(oPC, BTN_AI_PICK_LOCKS, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "isk_olock", "btn_pick_locks", 35.0f, 35.0f, 0.0, "btn_pick_locks_tooltip"); + fButtons += 1.0; + } + if(ai_GetAIButton(oPC, BTN_AI_BASH_LOCKS, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "ir_bash", "btn_bash_locks", 35.0f, 35.0f, 0.0, "btn_bash_locks_tooltip"); + fButtons += 1.0; + } + if(ai_GetAIButton(oPC, BTN_AI_MAGIC_LEVEL, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "dm_control", "btn_magic_level", 35.0f, 35.0f, 0.0, "btn_magic_level_tooltip"); + fButtons += 1.0; + } + if(ai_GetAIButton(oPC, BTN_AI_NO_SPONTANEOUS, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "ir_xability", "btn_spontaneous", 35.0f, 35.0f, 0.0, "btn_spontaneous_tooltip"); + fButtons += 1.0; + } + if(ai_GetAIButton(oPC, BTN_AI_NO_MAGIC_USE, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "ir_cntrspell", "btn_magic", 35.0f, 35.0f, 0.0, "btn_magic_tooltip"); + fButtons += 1.0; + } + if(ai_GetAIButton(oPC, BTN_AI_NO_MAGIC_ITEM_USE, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "ir_moreattacks", "btn_magic_items", 35.0f, 35.0f, 0.0, "btn_magic_items_tooltip"); + fButtons += 1.0; + } + if(ai_GetAIButton(oPC, BTN_AI_DEF_MAGIC_USE, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "ir_orisons", "btn_def_magic", 35.0f, 35.0f, 0.0, "btn_def_magic_tooltip"); + fButtons += 1.0; + } + if(ai_GetAIButton(oPC, BTN_AI_OFF_MAGIC_USE, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "ir_metamagic", "btn_off_magic", 35.0f, 35.0f, 0.0, "btn_off_magic_tooltip"); + fButtons += 1.0; + } + if(ai_GetAIButton(oPC, BTN_AI_HEAL_OUT, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "isk_heal", "btn_heal_out", 35.0f, 35.0f, 0.0, "btn_heal_out_tooltip"); + fButtons += 1.0; + } + if(ai_GetAIButton(oPC, BTN_AI_HEAL_IN, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "dm_heal", "btn_heal_in", 35.0f, 35.0f, 0.0, "btn_heal_in_tooltip"); + fButtons += 1.0; + } + if(ai_GetAIButton(oPC, BTN_AI_STOP_SELF_HEALING, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "ir_heal", "btn_heals_onoff", 35.0f, 35.0f, 0.0, "btn_heals_onoff_tooltip"); + fButtons += 1.0; + } + if(ai_GetAIButton(oPC, BTN_AI_STOP_PARTY_HEALING, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "ir_party", "btn_healp_onoff", 35.0f, 35.0f, 0.0, "btn_healp_onoff_tooltip"); + fButtons += 1.0; + } + if(ai_GetAIButton(oPC, BTN_AI_STOP_CURE_SPELLS, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "ir_accept", "btn_cure_onoff", 35.0f, 35.0f, 0.0, "btn_cure_onoff_tooltip"); + fButtons += 1.0; + } + if(ai_GetAIButton(oPC, BTN_AI_LOOT, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "ir_barter", "btn_loot", 35.0f, 35.0f, 0.0, "btn_loot_tooltip"); + fButtons += 1.0; + } + if(ai_GetAIButton(oPC, BTN_AI_IGNORE_ASSOCIATES, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "ir_ignore", "btn_ignore_assoc", 35.0f, 35.0f, 0.0, "btn_ignore_assoc_tooltip"); + fButtons += 1.0; + } + if(ai_GetAIButton(oPC, BTN_AI_IGNORE_TRAPS, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "ir_abort", "btn_ignore_traps", 35.0f, 35.0f, 0.0, "btn_ignore_traps_tooltip"); + fButtons += 1.0; + } + if(ai_GetAIButton(oPC, BTN_AI_PERC_RANGE, oAssociate, sAssociateType)) + { + jRow = CreateButtonImage(jRow, "ir_dmchat", "btn_perc_range", 35.0f, 35.0f, 0.0, "btn_perc_range_tooltip"); + fButtons += 1.0; + } + int bIsPC = ai_GetIsCharacter(oAssociate); + if(bIsPC) + { + json jPCPlugins = ai_UpdatePluginsForPC(oPC); + // Plug in buttons ***************************************************** + int nIndex, bWidget; + string sIcon, sButton; + json jPlugin = JsonArrayGet(jPCPlugins, nIndex); + while(JsonGetType(jPlugin) != JSON_TYPE_NULL) + { + bWidget = JsonGetInt(JsonArrayGet(jPlugin, 1)); + if(bWidget == 1) + { + sIcon = JsonGetString(JsonArrayGet(jPlugin, 3)); + sButton = IntToString(nIndex); + jRow = CreateButtonImage(jRow, sIcon, "btn_exe_plugin_" + sButton, 35.0f, 35.0f, 0.0, "btn_exe_plugin_" + sButton + "_tooltip"); + fButtons += 1.0; + } + jPlugin = JsonArrayGet(jPCPlugins, ++nIndex); + } + } + float fHeight, fWidth; + if(bAIWidgetLock) + { + fWidth = 50.0f; + fHeight = 50.0; + } + else if(bVertical) + { + fWidth = 88.0f; + fHeight = 55.0f; + } + else + { + fWidth = 55.0f; + fHeight = 88.0f; + } + // Quick Widget. + int nIndex, nSpell, nLevel, nMetaMagic; + float fQuickWidgetColumns; + string sClass, sLevel, sIndex; + object oItem; + json jSpell; + json jAIData = ai_GetAssociateDbJson(oPC, sAssociateType, "aidata"); + json jSpells = JsonArrayGet(jAIData, 10); + json jWidget = JsonArrayGet(jSpells, 2); + json jCol = JsonArray(); + if(ai_GetWidgetButton(oPC, BTN_CMD_SPELL_WIDGET, oAssociate, sAssociateType) && + JsonGetLength(jWidget) > 0) + { + // Row 2 (Widget Row 1)************************************************* + if(JsonGetType(jWidget) != JSON_TYPE_NULL) + { + fQuickWidgetColumns += 1.0; + int bAdd; + float fSpellButtons; + json jButton, jRectangle, jMetaMagic, jDrawList; + // Add row to the column. + if(bVertical) jCol = JsonArrayInsert(jCol, NuiCol(jRow)); + else jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + jRow = CreateButtonImage(JsonArray(), "ir_back", "btn_update_widget", 35.0f, 35.0f, 0.0, "btn_update_widget_tooltip"); + //CreateLabel(jRow, "", "blank_label", 35.0, 35.0, 0, 0, 0.0); + while(nIndex < 10) + { + bAdd = TRUE; + jSpell = JsonArrayGet(jWidget, nIndex); + if(JsonGetType(jSpell) != JSON_TYPE_NULL) + { + if(JsonGetInt(JsonArrayGet(jSpell, 1)) == -1) + { + oItem = GetObjectByUUID(JsonGetString(JsonArrayGet(jSpell, 5))); + if(oItem == OBJECT_INVALID) + { + bAdd = FALSE; + jWidget = JsonArrayDel(jWidget, nIndex--); + jSpells = JsonArrayInsert(jSpells, jWidget, 2); + jAIData = JsonArrayInsert(jAIData, jSpells, 10); + ai_SetAssociateDbJson(oPC, sAssociateType, "aidata", jAIData); + } + } + if(bAdd) + { + sIndex = IntToString(nIndex); + jButton = NuiButtonImage(NuiBind("btn_widget_" + sIndex + "_image")); + jButton = NuiEnabled(jButton, NuiBind("btn_widget_" + sIndex + "_event")); + jButton = NuiId(jButton, "btn_widget_" + sIndex); + jButton = NuiWidth(NuiHeight(jButton, 35.0), 35.0); + jButton = NuiMargin(jButton, 0.0); + jButton = NuiTooltip(jButton, NuiBind("btn_widget_" + sIndex + "_tooltip")); + jRectangle = NuiRect(4.0, 4.0, 10.0, 10.0); + jMetaMagic = NuiDrawListText(JsonBool(TRUE), NuiColor(255, 255, 0), jRectangle, NuiBind("metamagic_" + sIndex + "_text")); + jDrawList = JsonArrayInsert(JsonArray(), jMetaMagic); + jButton = NuiDrawList(jButton, JsonBool(TRUE), jDrawList); + jRow = JsonArrayInsert(jRow, jButton); + fSpellButtons += 1.0; + } + } + else break; + ++nIndex; + } + if(fSpellButtons > fButtons) fButtons = fSpellButtons; + // Row 3 (Widget Row 2)************************************************* + if(nIndex > 9 && JsonGetLength(jWidget) > 10) + { + fQuickWidgetColumns += 1.0; + // Add row to the column. + if(bVertical) jCol = JsonArrayInsert(jCol, NuiCol(jRow)); + else jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + jRow = CreateLabel(JsonArray(), "", "blank_label", 35.0, 35.0, 0, 0, 0.0); + while(nIndex < 20) + { + jSpell = JsonArrayGet(jWidget, nIndex); + if(JsonGetType(jSpell) != JSON_TYPE_NULL) + { + if(JsonGetInt(JsonArrayGet(jSpell, 1)) == -1) + { + oItem = GetObjectByUUID(JsonGetString(JsonArrayGet(jSpell, 5))); + if(oItem == OBJECT_INVALID) + { + bAdd = FALSE; + jWidget = JsonArrayDel(jWidget, nIndex--); + jSpells = JsonArrayInsert(jSpells, jWidget, 2); + jAIData = JsonArrayInsert(jAIData, jSpells, 10); + ai_SetAssociateDbJson(oPC, sAssociateType, "aidata", jAIData); + } + } + if(bAdd) + { + sIndex = IntToString(nIndex); + jButton = NuiButtonImage(NuiBind("btn_widget_" + sIndex + "_image")); + jButton = NuiEnabled(jButton, NuiBind("btn_widget_" + sIndex + "_event")); + jButton = NuiId(jButton, "btn_widget_" + sIndex); + jButton = NuiWidth(NuiHeight(jButton, 35.0), 35.0); + jButton = NuiMargin(jButton, 0.0); + jButton = NuiTooltip(jButton, NuiBind("btn_widget_" + sIndex + "_tooltip")); + jRectangle = NuiRect(4.0, 4.0, 10.0, 10.0); + jMetaMagic = NuiDrawListText(JsonBool(TRUE), NuiColor(255, 255, 0), jRectangle, NuiBind("metamagic_" + sIndex + "_text")); + jDrawList = JsonArrayInsert(JsonArray(), jMetaMagic); + jButton = NuiDrawList(jButton, JsonBool(TRUE), jDrawList); + jRow = JsonArrayInsert(jRow, jButton); + fSpellButtons += 1.0; + } + } + else break; + ++nIndex; + } + } + } + // Add the row to the column. + if(nIndex > 0) + { + if(bVertical) jCol = JsonArrayInsert(jCol, NuiCol(jRow)); + else jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + } + } + else + { + // Add the row to the column. + if(bVertical) jCol = JsonArrayInsert(jCol, NuiCol(jRow)); + else jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + } + float fScale = GetPlayerDeviceProperty(oPC, PLAYER_DEVICE_PROPERTY_GUI_SCALE) / 100.0; + float fButtonScale; + // 1.1 = 2.5 2.0 = 6.0 Ranges we need for scales to work correctly. + if(fScale > 1.0) fButtonScale = (fScale - 1.1) / (2.0 - 1.1) * 3.5 + 2.5; + else fButtonScale = 1.0; + if(fButtons > 0.0f) + { + if(bVertical) fWidth = fWidth + fButtons * 35.0f + fButtons * fButtonScale; + else fWidth = fWidth + fButtons * 35.0f; + } + if(fQuickWidgetColumns > 0.0f) + { + if(bVertical) fHeight = fHeight + fQuickWidgetColumns * 39.0f; + else fHeight = fHeight + fQuickWidgetColumns * 39.0f + fQuickWidgetColumns * fButtonScale; + } + // Get the window location to restore it from the database. + json jLocations = ai_GetAssociateDbJson(oPC, sAssociateType, "locations"); + //SendMessageToPC(oPC, "0i_menu, 2124, sAssociateType: " + sAssociateType + " jLocations: " + JsonDump(jLocations, 1)); + if(JsonGetType(jLocations) == JSON_TYPE_NULL) + { + ai_SetupAssociateData(oPC, oAssociate, sAssociateType); + jLocations = ai_GetAssociateDbJson(oPC, sAssociateType, "locations"); + } + jLocations = JsonObjectGet(jLocations, sAssociateType + AI_WIDGET_NUI); + float fX = JsonGetFloat(JsonObjectGet(jLocations, "x")); + float fY = JsonGetFloat(JsonObjectGet(jLocations, "y")); + // Keeps the widgets from bunching up in the top corner. + if(fY == 0.0 && fX == 0.0) + { + if(sAssociateType == "pc") fY = 1.0; + else if(sAssociateType == "familiar") fY = 96.0 * fScale; + else if(sAssociateType == "companion") fY = 192.0 * fScale; + else if(sAssociateType == "summons") fY = 288.0 * fScale; + else if(sAssociateType == "dominated") fY = 384.0 * fScale; + else + { + int nIndex = 1; + string sAssociateName = GetName(oAssociate); + while(nIndex < AI_MAX_HENCHMAN) + { + if(sAssociateName == GetName(GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex))) + { + fY = (88.0 + 88.0 * IntToFloat(nIndex - 1)); + break; + } + nIndex++; + } + } + fY = fY * fScale; + } + if(bAIWidgetLock) + { + fX += 4.0f; + // GUI scales are a mess, I just figured them out per scale to keep the widget from moving. + if(fScale == 1.0) fY += 37.0; + else if(fScale == 1.1) fY += 38.0; + else if(fScale == 1.2) fY += 40.0; + else if(fScale == 1.3) fY += 42.0; + else if(fScale == 1.4) fY += 43.0; + else if(fScale == 1.5) fY += 45.0; + else if(fScale == 1.6) fY += 47.0; + else if(fScale == 1.7) fY += 48.0; + else if(fScale == 1.8) fY += 50.0; + else if(fScale == 1.9) fY += 52.0; + else if(fScale == 2.0) fY += 54.0; + } + // Set the layout of the window. + json jLayout; + int nToken, bBool; + string sHeal, sText, sRange; + string sName = GetName(oAssociate); + if(GetStringRight(sName, 1) == "s") sName = sName + "'"; + else sName = sName + "'s"; + if(bVertical) + { + jLayout = NuiRow(jCol); + if(bAIWidgetLock) nToken = SetWindow(oPC, jLayout, sAssociateType + AI_WIDGET_NUI, "AI Widget", fX, fY, fHeight, fWidth, FALSE, FALSE, FALSE, TRUE, FALSE, "0e_nui"); + else nToken = SetWindow(oPC, jLayout, sAssociateType + AI_WIDGET_NUI, sName + " Widget", fX, fY, fHeight, fWidth, FALSE, FALSE, FALSE, TRUE, TRUE, "0e_nui"); +} + else + { + jLayout = NuiCol(jCol); + if(bAIWidgetLock) nToken = SetWindow(oPC, jLayout, sAssociateType + AI_WIDGET_NUI, "AI Widget", fX, fY, fWidth, fHeight, FALSE, FALSE, FALSE, TRUE, FALSE, "0e_nui"); + else nToken = SetWindow(oPC, jLayout, sAssociateType + AI_WIDGET_NUI, sName + " Widget", fX, fY, fWidth, fHeight, FALSE, FALSE, FALSE, TRUE, TRUE, "0e_nui"); + } + // Save the associate to the nui. + json jData = JsonArrayInsert(JsonArray(), JsonString(ObjectToString(oAssociate))); + NuiSetUserData(oPC, nToken, jData); + ai_SetWidgetBinds(oPC, oAssociate, sAssociateType, nToken, sName); +} +json ai_CreateLootFilterRow(json jRow, string sLabel, int nIndex) +{ + string sIndex = IntToString(nIndex); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateTextEditBox(jRow, "plc_hold", "txt_gold_" + sIndex, 9, FALSE, 90.0, 20.0); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateCheckBox(jRow, sLabel, "chbx_" + sIndex, 200.0, 20.0); + return JsonArrayInsert(jRow, NuiSpacer()); +} +void ai_SetupLootElements(object oPC, object oAssociate, int nToken, int nLootBit, int nIndex) +{ + string sIndex = IntToString(nIndex); + int bLoot = ai_GetLootFilter(oAssociate, nLootBit); + NuiSetBind(oPC, nToken, "chbx_" + sIndex + "_check", JsonBool(bLoot)); + NuiSetBindWatch (oPC, nToken, "chbx_" + sIndex + "_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_" + sIndex + "_event", JsonBool(TRUE)); + string sGold = IntToString(GetLocalInt(oAssociate, AI_MIN_GOLD_ + sIndex)); + NuiSetBind(oPC, nToken, "txt_gold_" + sIndex + "_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "txt_gold_" + sIndex, JsonString(sGold)); + NuiSetBindWatch (oPC, nToken, "txt_gold_" + sIndex, TRUE); +} +void ai_CreateLootFilterNUI(object oPC, object oAssociate) +{ + // Set window to not save until it has been created. + SetLocalInt (oPC, AI_NO_NUI_SAVE, TRUE); + DelayCommand (2.0, DeleteLocalInt (oPC, AI_NO_NUI_SAVE)); + // ************************************************************************* Width / Height + // Row 1 ******************************************************************* 318 / 73 + int bIsPC = ai_GetIsCharacter(oAssociate); + json jRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + jRow = CreateCheckBox(jRow, "Give all loot to the player", "chbx_give_loot", 200.0, 20.0, "chbx_give_loot_tooltip"); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + // Add row to the column. + json jCol = JsonArrayInsert(JsonArray(), NuiRow(jRow)); + // Row 2 *************************************************************** 388 / 101 + jRow = JsonArray(); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateTextEditBox(jRow, "plc_hold", "txt_max_weight", 9, FALSE, 50.0, 20.0, "txt_max_weight_tooltip"); + jRow = CreateLabel(jRow, "Maximum Weight to pickup", "lbl_weight", 200.0, 20.0, NUI_HALIGN_CENTER); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 3 *************************************************************** 388 / 129 + jRow = JsonArray(); + jRow = CreateButton(jRow, "Set All", "btn_set_all", 110.0, 20.0); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateButton(jRow, "Clear All", "btn_clear_all", 110.0, 20.0); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 4 *************************************************************** 388 / 157 + jRow = JsonArray(); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateLabel(jRow, "Minimum Gold", "lbl_min_gold", 100.0, 20.0, NUI_HALIGN_CENTER); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateLabel(jRow, "Items to Pickup", "lbl_pickup", 140.0, 20.0, NUI_HALIGN_CENTER); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 5 *************************************************************** 388 / 185 + jRow = ai_CreateLootFilterRow(JsonArray(), "Plot items", 2); + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 6 *************************************************************** 388 / 213 + jRow = ai_CreateLootFilterRow(JsonArray(), "Armor", 3); + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 7 *************************************************************** 388 / 241 + jRow = ai_CreateLootFilterRow(JsonArray(), "Belts", 4); + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 8 *************************************************************** 388 / 269 + jRow = ai_CreateLootFilterRow(JsonArray(), "Boots", 5); + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 9 *************************************************************** 388 / 297 + jRow = ai_CreateLootFilterRow(JsonArray(), "Cloaks", 6); + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 10 *************************************************************** 388 / 325 + jRow = ai_CreateLootFilterRow(JsonArray(), "Gems", 7); + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 11 *************************************************************** 388 / 353 + jRow = ai_CreateLootFilterRow(JsonArray(), "Gloves and Bracers", 8); + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 12 *************************************************************** 388 / 381 + jRow = ai_CreateLootFilterRow(JsonArray(), "Headgear", 9); + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 13 *************************************************************** 388 / 409 + jRow = ai_CreateLootFilterRow(JsonArray(), "Jewelry", 10); + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 14 *************************************************************** 388 / 437 + jRow = ai_CreateLootFilterRow(JsonArray(), "Miscellaneous items", 11); + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 15 *************************************************************** 388 / 465 + jRow = ai_CreateLootFilterRow(JsonArray(), "Potions", 12); + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 16 *************************************************************** 388 / 493 + jRow = ai_CreateLootFilterRow(JsonArray(), "Scrolls", 13); + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 17 *************************************************************** 388 / 521 + jRow = ai_CreateLootFilterRow(JsonArray(), "Shields", 14); + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 18 *************************************************************** 388 / 549 + jRow = ai_CreateLootFilterRow(JsonArray(), "Wands, Rods, and Staves", 15); + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 19 ************************************************************** 388 / 577 + jRow = ai_CreateLootFilterRow(JsonArray(), "Weapons", 16); + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 20 ************************************************************** 388 / 605 + jRow = ai_CreateLootFilterRow(JsonArray(), "Arrows", 17); + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 21 ************************************************************** 388 / 633 + jRow = ai_CreateLootFilterRow(JsonArray(), "Bolts", 18); + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 22 ************************************************************** 388 / 661 + jRow = ai_CreateLootFilterRow(JsonArray(), "Bullets", 19); + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + string sAssociateType = ai_GetAssociateType(oPC, oAssociate); + // Get the window location to restore it from the database. + float fX, fY; + json jLocations = ai_GetAssociateDbJson(oPC, sAssociateType, "locations"); + jLocations = JsonObjectGet(jLocations, sAssociateType + AI_LOOTFILTER_NUI); + if(JsonGetType(jLocations) == JSON_TYPE_NULL) { fX = -1.0; fY = -1.0; } + else + { + fX = JsonGetFloat(JsonObjectGet(jLocations, "x")); + fY = JsonGetFloat(JsonObjectGet(jLocations, "y")); + } + // Set the Layout of the window. + json jLayout = NuiCol(jCol); + string sText, sName = GetName(oAssociate); + if(GetStringRight(sName, 1) == "s") sName = sName + "'"; + else sName = sName + "'s"; + int nToken = SetWindow(oPC, jLayout, sAssociateType + AI_LOOTFILTER_NUI, sName + " Loot Filter", + fX, fY, 318.0, 673.0, FALSE, FALSE, TRUE, FALSE, TRUE, "0e_nui"); + // Save the associate to the nui. + json jData = JsonArrayInsert(JsonArray(), JsonString(ObjectToString(oAssociate))); + NuiSetUserData(oPC, nToken, jData); + // Set event watches for save window location. + NuiSetBindWatch(oPC, nToken, "window_geometry", TRUE); + // Set all binds, events, and watches. + // Row 1 + int bGiveLoot = ai_GetLootFilter(oAssociate, AI_LOOT_GIVE_TO_PC); + NuiSetBind(oPC, nToken, "chbx_give_loot_check", JsonBool (bGiveLoot)); + NuiSetBindWatch (oPC, nToken, "chbx_give_loot_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_give_loot_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "chbx_give_loot_tooltip", JsonString( + " Check this to make henchman give any loot picked up to the player.")); + // Row 2 + int nWeight = GetLocalInt(oAssociate, AI_MAX_LOOT_WEIGHT); + if(nWeight == 0) + { + nWeight = 200; + SetLocalInt(oAssociate, AI_MAX_LOOT_WEIGHT, nWeight); + } + NuiSetBind(oPC, nToken, "txt_max_weight_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "txt_max_weight", JsonString(IntToString(nWeight))); + NuiSetBindWatch (oPC, nToken, "txt_max_weight", TRUE); + NuiSetBind(oPC, nToken, "txt_max_weight_tooltip", JsonString(" Max weighted item you will pickup from 1 to 1,000")); + // Row 3 + NuiSetBind(oPC, nToken, "btn_set_all_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "btn_set_all", JsonInt(TRUE)); + NuiSetBind(oPC, nToken, "btn_clear_all_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "btn_clear_all", JsonInt(TRUE)); + // Row 4 + ai_SetupLootElements(oPC, oAssociate, nToken, AI_LOOT_PLOT, 2); + // Row 5 + ai_SetupLootElements(oPC, oAssociate, nToken, AI_LOOT_ARMOR, 3); + // Row 6 + ai_SetupLootElements(oPC, oAssociate, nToken, AI_LOOT_BELTS, 4); + // Row 7 + ai_SetupLootElements(oPC, oAssociate, nToken, AI_LOOT_BOOTS, 5); + // Row 8 + ai_SetupLootElements(oPC, oAssociate, nToken, AI_LOOT_CLOAKS, 6); + // Row 9 + ai_SetupLootElements(oPC, oAssociate, nToken, AI_LOOT_GEMS, 7); + // Row 10 + ai_SetupLootElements(oPC, oAssociate, nToken, AI_LOOT_GLOVES, 8); + // Row 11 + ai_SetupLootElements(oPC, oAssociate, nToken, AI_LOOT_HEADGEAR, 9); + // Row 12 + ai_SetupLootElements(oPC, oAssociate, nToken, AI_LOOT_JEWELRY, 10); + // Row 13 + ai_SetupLootElements(oPC, oAssociate, nToken, AI_LOOT_MISC, 11); + // Row 14 + ai_SetupLootElements(oPC, oAssociate, nToken, AI_LOOT_POTIONS, 12); + // Row 15 + ai_SetupLootElements(oPC, oAssociate, nToken, AI_LOOT_SCROLLS, 13); + // Row 16 + ai_SetupLootElements(oPC, oAssociate, nToken, AI_LOOT_SHIELDS, 14); + // Row 17 + ai_SetupLootElements(oPC, oAssociate, nToken, AI_LOOT_WANDS_RODS_STAVES, 15); + // Row 18 + ai_SetupLootElements(oPC, oAssociate, nToken, AI_LOOT_WEAPONS, 16); + // Row 19 + ai_SetupLootElements(oPC, oAssociate, nToken, AI_LOOT_ARROWS, 17); + // Row 20 + ai_SetupLootElements(oPC, oAssociate, nToken, AI_LOOT_BOLTS, 18); + // Row 21 + ai_SetupLootElements(oPC, oAssociate, nToken, AI_LOOT_BULLETS, 19); +} +void ai_CreateCopySettingsNUI(object oPC, object oAssociate) +{ + // Set window to not save until it has been created. + SetLocalInt (oPC, AI_NO_NUI_SAVE, TRUE); + DelayCommand (2.0, DeleteLocalInt (oPC, AI_NO_NUI_SAVE)); + // ************************************************************************* Width / Height + // Row 1 ******************************************************************* 244 / 73 + string sName = GetName(oAssociate); + if(GetStringRight(sName, 1) == "s") sName = sName + "'"; + else sName = sName + "'s"; + json jRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + jRow = CreateLabel(jRow, "Copy settings to", "lbl_paste", 220.0, 20.0, NUI_HALIGN_CENTER); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + // Add row to the column. + json jCol = JsonArrayInsert(JsonArray(), NuiRow(jRow)); + // Row 2 ******************************************************************* 244 / 101 + jRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + jRow = CreateButton(jRow, "All Associates", "btn_paste_all", 220.0, 20.0); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 2 ******************************************************************* 244 / 129 + jRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + jRow = CreateButton(jRow, "Familiar", "btn_paste_familiar", 220.0, 20.0); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 3 ******************************************************************* 244 / 157 + jRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + jRow = CreateButton(jRow, "Companion", "btn_paste_companion", 220.0, 20.0); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 4 ******************************************************************* 244 / 185 + jRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + jRow = CreateButton(jRow, "Summons", "btn_paste_summons", 220.0, 20.0); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 5 ******************************************************************* 244 / 213 + jRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + jRow = CreateButton(jRow, "Dominated", "btn_paste_dominated", 220.0, 20.0); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 5+ ****************************************************************** 244 / 241 + float fHeight = 241.0; + int nIndex; + string sAssocName; + object oAssoc; + for(nIndex = 1; nIndex < AI_MAX_HENCHMAN; nIndex++) + { + oAssoc = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex); + if(oAssoc != OBJECT_INVALID) + { + sAssocName = GetName(oAssoc); + if(GetStringRight(sAssocName, 1) == "s") sAssocName = sAssocName + "'"; + else sAssocName = sAssocName + "'s"; + jRow = CreateButton(JsonArray(), sAssocName, "btn_paste_henchman" + IntToString(nIndex), 220.0, 20.0); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight += 28.0; + } + else break; + } + string sAssociateType = ai_GetAssociateType(oPC, oAssociate); + // Get the window location to restore it from the database. + float fX, fY; + json jLocations = ai_GetAssociateDbJson(oPC, sAssociateType, "locations"); + jLocations = JsonObjectGet(jLocations, sAssociateType + AI_COPY_NUI); + if(JsonGetType(jLocations) == JSON_TYPE_NULL) { fX = -1.0; fY = -1.0; } + else + { + fX = JsonGetFloat(JsonObjectGet(jLocations, "x")); + fY = JsonGetFloat(JsonObjectGet(jLocations, "y")); + } + // Set the Layout of the window. + json jLayout = NuiCol(jCol); + int nToken = SetWindow(oPC, jLayout, sAssociateType + AI_COPY_NUI, sName + " Copy Settings Menu", + fX, fY, 244.0, fHeight + 12.0, FALSE, FALSE, TRUE, FALSE, TRUE, "0e_nui"); + // Save the associate to the nui. + json jData = JsonArrayInsert(JsonArray(), JsonString(ObjectToString(oAssociate))); + NuiSetUserData(oPC, nToken, jData); + // Set event watches for save window location. + NuiSetBindWatch(oPC, nToken, "window_geometry", TRUE); + // Set all binds, events, and watches. + // Row 1 + NuiSetBind(oPC, nToken, "btn_paste_all_event", JsonBool (TRUE)); + oAssoc = GetAssociate(ASSOCIATE_TYPE_FAMILIAR, oPC); + NuiSetBind(oPC, nToken, "btn_paste_familiar_event", JsonBool(oAssoc != oAssociate && oAssoc != OBJECT_INVALID)); + oAssoc = GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION, oPC); + NuiSetBind(oPC, nToken, "btn_paste_companion_event", JsonBool(oAssoc != oAssociate && oAssoc != OBJECT_INVALID)); + oAssoc = GetAssociate(ASSOCIATE_TYPE_SUMMONED, oPC); + NuiSetBind(oPC, nToken, "btn_paste_summons_event", JsonBool(oAssoc != oAssociate && oAssoc != OBJECT_INVALID)); + oAssoc = GetAssociate(ASSOCIATE_TYPE_DOMINATED, oPC); + NuiSetBind(oPC, nToken, "btn_paste_dominated_event", JsonBool(oAssoc != oAssociate && oAssoc != OBJECT_INVALID)); + for(nIndex = 1; nIndex < AI_MAX_HENCHMAN; nIndex++) + { + oAssoc = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex); + if(oAssoc != OBJECT_INVALID) + { + NuiSetBind(oPC, nToken, "btn_paste_henchman" + IntToString(nIndex) + "_event", JsonBool(oAssoc != oAssociate)); + } + else break; + } +} +void ai_CreatePluginNUI(object oPC) +{ + // Set window to not save until it has been created. + SetLocalInt (oPC, AI_NO_NUI_SAVE, TRUE); + DelayCommand (2.0, DeleteLocalInt (oPC, AI_NO_NUI_SAVE)); + int nIndex, nButton; + string sButton; + // Row 1 ******************************************************************* 500 / 73 + json jRow = CreateButton(JsonArray(), "Load Plugins", "btn_load_plugins", 150.0f, 20.0f, -1.0, "btn_load_plugins_tooltip"); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateButton(jRow, "Load Monster Mods", "btn_load_m_mods", 150.0f, 20.0f, -1.0, "btn_load_m_mods_tooltip"); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateButton(jRow, "Check All", "btn_check_plugins", 80.0f, 20.0f, -1.0, "btn_check_plugins_tooltip"); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateButton(jRow, "Clear All", "btn_clear_plugins", 80.0f, 20.0f, -1.0, "btn_clear_plugins_tooltip"); + // Add row to the column. + json jCol = JsonArrayInsert(JsonArray(), NuiRow(jRow)); + // Row 2 ******************************************************************* 500 / 101 + jRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + jRow = CreateButton(jRow, "Add Plugin", "btn_add_plugin", 150.0f, 20.0f); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateTextEditBox(jRow, "sPlaceHolder", "txt_plugin", 16, FALSE, 310.0f, 20.0f, "txt_plugin_tooltip"); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + float fHeight = 101.0; + // Row 3+ ****************************************************************** 500 / --- + json jPlugins = ai_GetAssociateDbJson(oPC, "pc", "plugins"); + nIndex = 0; + json jPlugin = JsonArrayGet(jPlugins, nIndex); + string sName; + while(JsonGetType(jPlugin) != JSON_TYPE_NULL) + { + sButton = IntToString(nIndex); + jRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + jRow = CreateButton(jRow, "Remove Plugin", "btn_remove_plugin_" + sButton, 150.0f, 20.0f); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + sName = JsonGetString(JsonArrayGet(jPlugin, 2)); + jRow = CreateButton(jRow, sName, "btn_plugin_" + sButton, 290.0f, 20.0f, -1.0, "btn_plugin_" + sButton + "_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_plugin_" + sButton, 25.0, 20.0); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight += 28.0; + jPlugin = JsonArrayGet(jPlugins, ++nIndex); + } + // Get the window location to restore it from the database. + json jLocations = ai_GetAssociateDbJson(oPC, "pc", "locations"); + float fX, fY; + jLocations = JsonObjectGet(jLocations, AI_PLUGIN_NUI); + if(JsonGetType(jLocations) == JSON_TYPE_NULL) { fX = -1.0; fY = -1.0; } + else + { + fX = JsonGetFloat(JsonObjectGet(jLocations, "x")); + fY = JsonGetFloat(JsonObjectGet(jLocations, "y")); + } + // Set the Layout of the window. + json jLayout = NuiCol(jCol); + sName = GetName(oPC); + if(GetStringRight(sName, 1) == "s") sName = sName + "'"; + else sName = sName + "'s"; + int nToken = SetWindow(oPC, jLayout, AI_PLUGIN_NUI, sName + " PEPS Plugin Manager", + fX, fY, 500.0f, fHeight + 12.0f, FALSE, FALSE, TRUE, FALSE, TRUE, "0e_nui"); + // Save the associate to the nui for use in 0e_nui + json jData = JsonArrayInsert(JsonArray(), JsonString(ObjectToString(oPC))); + NuiSetUserData(oPC, nToken, jData); + // Set event watches for save window location. + NuiSetBindWatch(oPC, nToken, "window_geometry", TRUE); + // Row 1 + NuiSetBind(oPC, nToken, "btn_load_plugins_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_load_plugins_tooltip", JsonString(" Load all known PEPS plugins that are in the game files.")); + NuiSetBind(oPC, nToken, "btn_load_m_mods_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_load_m_mods_tooltip", JsonString(" Load all known PEPS monster mods that are in the game files.")); + NuiSetBind(oPC, nToken, "btn_check_plugins_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_check_plugins_tooltip", JsonString(" Add all plugins to the players widget.")); + NuiSetBind(oPC, nToken, "btn_clear_plugins_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_clear_plugins_tooltip", JsonString(" Remove all plugins from the players widget.")); + // Row 2 + NuiSetBind(oPC, nToken, "btn_add_plugin_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "txt_plugin_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "txt_plugin_tooltip", JsonString(" Enter an executable script name.")); + // Row 3+ + nIndex = 0; + int bCheck; + string sText; + jPlugin = JsonArrayGet(jPlugins, nIndex); + while(JsonGetType(jPlugin) != JSON_TYPE_NULL) + { + sButton = IntToString(nIndex); + NuiSetBind(oPC, nToken, "btn_remove_plugin_" + sButton + "_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_plugin_" + sButton + "_event", JsonBool(TRUE)); + bCheck = JsonGetInt(JsonArrayGet(jPlugin, 1)); + if(bCheck < 3) + { + NuiSetBind(oPC, nToken, "chbx_plugin_" + sButton + "_check", JsonBool(bCheck)); + NuiSetBind(oPC, nToken, "chbx_plugin_" + sButton + "_event", JsonBool(TRUE)); + NuiSetBindWatch (oPC, nToken, "chbx_plugin_" + sButton + "_check", TRUE); + } + sText = " " + JsonGetString(JsonArrayGet(jPlugin, 2)); + NuiSetBind(oPC, nToken, "btn_plugin_" + sButton + "_tooltip", JsonString(sText)); + jPlugin = JsonArrayGet(jPlugins, ++nIndex); + } +} +int ai_SpellNotInList(int nSpell, json jSpellArray) +{ + int nMaxArray = JsonGetLength(jSpellArray); + int nIndex; + while(nIndex < nMaxArray) + { + if(nSpell == JsonGetInt(JsonArrayGet(JsonArrayGet(jSpellArray, nIndex), 0))) return FALSE; + nIndex++; + } + return TRUE; +} +json ai_CheckItemAbilities(json jQuickListArray, object oCreature, object oItem, json jSpell_Icon, json jSpell_Text, int bEquiped = FALSE) +{ + // We have established that we can use the item if it is equiped. + if(!bEquiped && !ai_CheckIfCanUseItem(oCreature, oItem)) return jQuickListArray; + int nPerDay, nCharges, nUses, bSaveTalent, nBaseItemType; + int nIprpSubType, nSpell, nLevel, nIPType, nIndex; + string sSpellIcon, sSpellName; + itemproperty ipProp = GetFirstItemProperty(oItem); + json jSpell; + // Lets skip this if there are no properties. + if(!GetIsItemPropertyValid(ipProp)) return jQuickListArray; + // Check for cast spell property and add them to the talent list. + while(GetIsItemPropertyValid(ipProp)) + { + nIPType = GetItemPropertyType(ipProp); + if(nIPType == ITEM_PROPERTY_CAST_SPELL) + { + bSaveTalent = TRUE; + // Get how they use the item (charges or uses per day). + nUses = GetItemPropertyCostTableValue(ipProp); + if(nUses > 1 && nUses < 7) + { + nCharges = GetItemCharges(oItem); + if((nUses == IP_CONST_CASTSPELL_NUMUSES_1_CHARGE_PER_USE && nCharges < 1) || + (nUses == IP_CONST_CASTSPELL_NUMUSES_2_CHARGES_PER_USE && nCharges < 2) || + (nUses == IP_CONST_CASTSPELL_NUMUSES_3_CHARGES_PER_USE && nCharges < 3) || + (nUses == IP_CONST_CASTSPELL_NUMUSES_4_CHARGES_PER_USE && nCharges < 4) || + (nUses == IP_CONST_CASTSPELL_NUMUSES_5_CHARGES_PER_USE && nCharges < 5)) bSaveTalent = FALSE; + } + else if(nUses > 7 && nUses < 13) + { + nPerDay = GetItemPropertyUsesPerDayRemaining(oItem, ipProp); + if(AI_DEBUG) ai_Debug("0i_talents", "1676", "Item uses: " + IntToString(nPerDay)); + if(nPerDay == 0) bSaveTalent = FALSE; + } + if(bSaveTalent) + { + // SubType is the ip spell index for iprp_spells.2da + nIprpSubType = GetItemPropertySubType(ipProp); + nSpell = StringToInt(Get2DAString("iprp_spells", "SpellIndex", nIprpSubType)); + nBaseItemType = GetBaseItemType(oItem); + if(nBaseItemType == BASE_ITEM_ENCHANTED_SCROLL || + nBaseItemType == BASE_ITEM_SCROLL || + nBaseItemType == BASE_ITEM_SPELLSCROLL) + { + sSpellIcon = Get2DAString("iprp_spells", "Icon", nIprpSubType); + sSpellName = ai_StripColorCodes(GetName(oItem)); + nUses = GetNumStackedItems(oItem); + } + else + { + if(nBaseItemType == BASE_ITEM_ENCHANTED_POTION || + nBaseItemType == BASE_ITEM_POTIONS) + { + sSpellName = ai_StripColorCodes(GetName(oItem)); + nUses = GetNumStackedItems(oItem); + } + else if(nBaseItemType == BASE_ITEM_ENCHANTED_WAND || + nBaseItemType == BASE_ITEM_MAGICWAND || + nBaseItemType == FEAT_CRAFT_WAND) + { + sSpellName = ai_StripColorCodes(GetName(oItem)); + nUses = nCharges; + } + else + { + sSpellName = ai_StripColorCodes(GetName(oItem)) + ": "; + sSpellName += GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); + if(nCharges) nUses = nCharges; + else nUses = nPerDay; + } + sSpellIcon = Get2DAString("spells", "iConResRef", nSpell); + } + jSpell_Icon = JsonArrayInsert(jSpell_Icon, JsonString(sSpellIcon)); + jSpell_Text = JsonArrayInsert(jSpell_Text, JsonString(sSpellName)); + jSpell = JsonArray(); + jSpell = JsonArrayInsert(jSpell, JsonInt(nSpell)); + jSpell = JsonArrayInsert(jSpell, JsonInt(-1)); // Class is set to -1 for items + jSpell = JsonArrayInsert(jSpell, JsonInt(nUses)); + jSpell = JsonArrayInsert(jSpell, JsonInt(nBaseItemType)); + jSpell = JsonArrayInsert(jSpell, JsonInt(nIprpSubType)); + jSpell = JsonArrayInsert(jSpell, JsonString(GetObjectUUID(oItem))); + jQuickListArray = JsonArrayInsert(jQuickListArray, jSpell); + } + } + else if(nIPType == ITEM_PROPERTY_HEALERS_KIT) + { + // Must also have ranks in healing kits. + if(GetSkillRank(SKILL_HEAL, oCreature) > 0) + { + jSpell_Icon = JsonArrayInsert(jSpell_Icon, JsonString("isk_heal")); + jSpell_Text = JsonArrayInsert(jSpell_Text, JsonString(ai_StripColorCodes(GetName(oItem)))); + json jSpell = JsonArray(); + jSpell = JsonArrayInsert(jSpell, JsonInt(SPELL_HEALINGKIT)); + jSpell = JsonArrayInsert(jSpell, JsonInt(-1)); // Class is set to -1 for items + jSpell = JsonArrayInsert(jSpell, JsonInt(GetNumStackedItems(oItem))); + jSpell = JsonArrayInsert(jSpell, JsonInt(0)); + jSpell = JsonArrayInsert(jSpell, JsonInt(GetItemPropertyCostTableValue(ipProp))); + jSpell = JsonArrayInsert(jSpell, JsonString(GetObjectUUID(oItem))); + jQuickListArray = JsonArrayInsert(jQuickListArray, jSpell); + } + } + nIndex++; + ipProp = GetNextItemProperty(oItem); + } + SetLocalJson(oCreature, "JSPELL_ICON", jSpell_Icon); + SetLocalJson(oCreature, "JSPELL_NAME", jSpell_Text); + return jQuickListArray; +} +void ai_CreateQuickWidgetSelectionNUI(object oPC, object oAssociate) +{ + string sAssociateType = ai_GetAssociateType(oPC, oAssociate); + // Set window to not save until it has been created. + SetLocalInt (oPC, AI_NO_NUI_SAVE, TRUE); + DelayCommand (2.0, DeleteLocalInt (oPC, AI_NO_NUI_SAVE)); + json jRow = JsonArray(); + // Row 1 Classes************************************************************ 414 / 88 + int nClass, nLevel, nIndex; + string sIndex, sClassIcon, sLevelIcon; + for(nIndex = 1; nIndex <= AI_MAX_CLASSES_PER_CHARACTER; nIndex++) + { + nClass = GetClassByPosition(nIndex, oAssociate); + if(nClass != CLASS_TYPE_INVALID) + { + // This saves the class position in the button id so we can get it later. + sIndex = IntToString(nIndex); + sClassIcon = Get2DAString("classes", "Icon", nClass); + jRow = CreateButtonImage(jRow, sClassIcon, "btn_class_" + sIndex, 35.0f, 35.0f, 0.0, "btn_class_" + sIndex + "_tooltip"); + } + } + jRow = JsonArrayInsert(jRow, NuiSpacer()); + // Add row to the column. + json jCol = JsonArrayInsert(JsonArray(), NuiRow(jRow)); + // Row 2 (Levels) ********************************************************** 414 / 131 + jRow = CreateButtonImage(JsonArray(), "", "btn_level_11" , 35.0f, 35.0f, 0.0, "btn_level_11_tooltip"); + jRow = CreateButtonImage(jRow, "", "btn_level_10" , 35.0f, 35.0f, 0.0, "btn_level_10_tooltip"); + for(nIndex = 0; nIndex <= 9; nIndex++) + { + // This saves the level in the button id so we can get it later. + sIndex = IntToString(nIndex); + jRow = CreateButtonImage(jRow, "", "btn_level_" + sIndex, 35.0f, 35.0f, 0.0, "btn_level_" + sIndex + "_tooltip"); + } + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 3 (Spell List)******************************************************* 414 / 433 + json jButton = JsonArray(); + jButton = NuiButton(NuiBind("text_spell")); + jButton = NuiId(jButton, "btn_text_spell"); + json jRectangle = NuiRect(4.0, 4.0, 27.0, 27.0); + json jDrawList = JsonArrayInsert(JsonArray(), NuiDrawListImage(JsonBool(TRUE), NuiBind("icon_spell"), jRectangle, JsonInt(NUI_ASPECT_FILL), JsonInt(NUI_HALIGN_CENTER), JsonInt(NUI_VALIGN_MIDDLE))); + jRectangle = NuiRect(4.0, 4.0, 10.0, 10.0); + json jMetaMagic = NuiDrawListText(JsonBool(TRUE), NuiColor(255, 255, 0), jRectangle, NuiBind("metamagic_text")); + jDrawList = JsonArrayInsert(jDrawList, jMetaMagic); + jButton = NuiDrawList(jButton, JsonBool(TRUE), jDrawList); + json jListTemplate = JsonArrayInsert(JsonArray(), NuiListTemplateCell(jButton, 345.0, FALSE)); + json jInfo = NuiButtonImage(JsonString("gui_cg_qstn_mark")); + jInfo = NuiId(jInfo, "btn_info_spell"); + jListTemplate = JsonArrayInsert(jListTemplate, NuiListTemplateCell(jInfo, 35.0, FALSE)); + jRow = JsonArrayInsert(JsonArray(), NuiHeight(NuiList(jListTemplate, NuiBind("icon_spell"), 35.0), 282.0)); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 4 (Widget Label)***************************************************** 414 / 461 + jRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + jRow = CreateLabel(jRow, "Quick Widget List", "lbl_quick_list", 150.0, 20.0, 0, 0, 0.0); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 5 (Widget row 1)***************************************************** 414 / 504 + jRow = JsonArray(); + for(nIndex = 0; nIndex < 10; nIndex++) + { + // This saves the index location in the json jWidget in the button id for later use. + sIndex = IntToString(nIndex); + json jButton = NuiButtonImage(NuiBind("btn_widget_" + sIndex + "_image")); + jButton = NuiEnabled(jButton, NuiBind("btn_widget_" + sIndex + "_event")); + jButton = NuiId(jButton, "btn_widget_" + sIndex); + jButton = NuiWidth(NuiHeight(jButton, 35.0), 35.0); + jButton = NuiMargin(jButton, 0.0); + jButton = NuiTooltip(jButton, NuiBind("btn_widget_" + sIndex + "_tooltip")); + json jRectangle = NuiRect(4.0, 4.0, 10.0, 10.0); + json jMetaMagic = NuiDrawListText(JsonBool(TRUE), NuiColor(255, 255, 0), jRectangle, NuiBind("metamagic_" + sIndex + "_text")); + jDrawList = JsonArrayInsert(JsonArray(), jMetaMagic); + jButton = NuiDrawList(jButton, JsonBool(TRUE), jDrawList); + jRow = JsonArrayInsert(jRow, jButton); + } + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 6 (Widget row 2)***************************************************** 414 / 543 + jRow = JsonArray(); + for(nIndex = 10; nIndex < 20; nIndex++) + { + // This saves the index location in the json jWidget in the button id for later use. + sIndex = IntToString(nIndex); + json jButton = NuiButtonImage(NuiBind("btn_widget_" + sIndex + "_image")); + jButton = NuiEnabled(jButton, NuiBind("btn_widget_" + sIndex + "_event")); + jButton = NuiId(jButton, "btn_widget_" + sIndex); + jButton = NuiWidth(NuiHeight(jButton, 35.0), 35.0); + jButton = NuiMargin(jButton, 0.0); + jButton = NuiTooltip(jButton, NuiBind("btn_widget_" + sIndex + "_tooltip")); + json jRectangle = NuiRect(4.0, 4.0, 10.0, 10.0); + json jMetaMagic = NuiDrawListText(JsonBool(TRUE), NuiColor(255, 255, 0), jRectangle, NuiBind("metamagic_" + sIndex + "_text")); + jDrawList = JsonArrayInsert(JsonArray(), jMetaMagic); + jButton = NuiDrawList(jButton, JsonBool(TRUE), jDrawList); + jRow = JsonArrayInsert(jRow, jButton); + } + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Get the window location to restore it from the database. + float fX, fY; + json jLocations = ai_GetAssociateDbJson(oPC, sAssociateType, "locations"); + jLocations = JsonObjectGet(jLocations, sAssociateType + AI_QUICK_WIDGET_NUI); + if(JsonGetType(jLocations) == JSON_TYPE_NULL) { fX = -1.0; fY = -1.0; } + else + { + fX = JsonGetFloat(JsonObjectGet(jLocations, "x")); + fY = JsonGetFloat(JsonObjectGet(jLocations, "y")); + } + // Set the Layout of the window. + json jLayout = NuiCol(jCol); + string sText, sName = GetName(oAssociate); + if(GetStringRight(sName, 1) == "s") sName = sName + "'"; + else sName = sName + "'s"; + int nToken = SetWindow(oPC, jLayout, sAssociateType + AI_QUICK_WIDGET_NUI, sName + " Quick Widget Menu", + fX, fY, 414.0, 543.0 + 12.0, FALSE, FALSE, TRUE, FALSE, TRUE, "0e_nui"); + // Set the Layout of the window. + // Save the associate to the nui for use in 0e_nui + json jData = JsonArrayInsert(JsonArray(), JsonString(ObjectToString(oAssociate))); + // Set event watches for save window location. + NuiSetBindWatch(oPC, nToken, "window_geometry", TRUE); + json jSpells; + json jAIData = ai_GetAssociateDbJson(oPC, sAssociateType, "aidata"); + // Temporary fix for error! :/ + if(JsonGetLength(jAIData) == 0) + { + ai_CheckAssociateData(oPC, oAssociate, sAssociateType, TRUE); + jAIData = ai_GetAssociateDbJson(oPC, sAssociateType, "aidata"); + jSpells = JsonArray(); + jSpells = JsonArrayInsert(jSpells, JsonInt(1)); + jSpells = JsonArrayInsert(jSpells, JsonInt(10)); + jAIData = JsonArrayInsert(jAIData, jSpells); + ai_SetAssociateDbJson(oPC, sAssociateType, "aidata", jAIData); + nLevel = 10; + } + if(JsonGetLength(jAIData) == 9) + { + jSpells = JsonArray(); + jSpells = JsonArrayInsert(jSpells, JsonInt(1)); + jSpells = JsonArrayInsert(jSpells, JsonInt(10)); + jSpells = JsonArrayInsert(jSpells, JsonArray()); + jAIData = JsonArrayInsert(jAIData, jSpells); + ai_SetAssociateDbJson(oPC, sAssociateType, "aidata", jAIData); + nLevel = 10; + } + else + { + jSpells = JsonArrayGet(jAIData, 10); + if(JsonGetLength(jSpells) == 0) + { + jSpells = JsonArray(); + jSpells = JsonArrayInsert(jSpells, JsonInt(1)); + jSpells = JsonArrayInsert(jSpells, JsonInt(10)); + jSpells = JsonArrayInsert(jSpells, JsonArray()); + jAIData = JsonArraySet(jAIData, 10, jSpells); + ai_SetAssociateDbJson(oPC, sAssociateType, "aidata", jAIData); + nLevel = 10; + } + else + { + nClass = JsonGetInt(JsonArrayGet(jSpells, 0)); + nLevel = JsonGetInt(JsonArrayGet(jSpells, 1)); + } + } + if(nClass < 1 || nClass > AI_MAX_CLASSES_PER_CHARACTER) nClass = 1; + nClass = GetClassByPosition(nClass, oAssociate); + // Row 1 & 2 Class & Level + int nSpellLevel, nLevelIndex, nClassIndex, nMaxSpellLevel; + string sClass, sLevel, sLevelImage, sLevelIndex; + NuiSetBind(oPC, nToken, "btn_level_11_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_level_11_tooltip", JsonString(" Item Powers")); + NuiSetBind(oPC, nToken, "btn_level_11_image", JsonString("ir_attack")); + NuiSetBind(oPC, nToken, "btn_level_10_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_level_10_tooltip", JsonString(" Special Abilities")); + NuiSetBind(oPC, nToken, "btn_level_10_image", JsonString("dm_god")); + for(nIndex = 1; nIndex <= AI_MAX_CLASSES_PER_CHARACTER; nIndex++) + { + nClassIndex = GetClassByPosition(nIndex, oAssociate); + if(nClassIndex != CLASS_TYPE_INVALID) + { + sClass = GetStringByStrRef(StringToInt(Get2DAString("classes", "Name", nClassIndex))); + sIndex = IntToString(nIndex); + NuiSetBind(oPC, nToken, "btn_class_" + sIndex + "_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_class_" + sIndex + "_tooltip", JsonString(" " + sClass)); + if(nClass == nClassIndex) + { + if(StringToInt(Get2DAString("classes", "SpellCaster", nClass))) + { + int nClassLevel = GetLevelByClass(nClass, oAssociate); + string sSpellsGained = Get2DAString("classes", "SpellGainTable", nClass); + int nMaxSpellLevel = StringToInt(Get2DAString(sSpellsGained, "NumSpellLevels", nClassLevel - 1)); + for(nLevelIndex = 0; nLevelIndex <= 9; nLevelIndex++) + { + sLevelIndex = IntToString(nLevelIndex); + if(nLevelIndex < nMaxSpellLevel) + { + NuiSetBind(oPC, nToken, "btn_level_" + sLevelIndex + "_event", JsonBool(TRUE)); + if(nLevelIndex == 0) sLevelImage = "ir_cantrips"; + else if(nLevelIndex < 7)sLevelImage = "ir_level" + sLevelIndex; + else sLevelImage = "ir_level789"; + NuiSetBind(oPC, nToken, "btn_level_" + sLevelIndex + "_image", JsonString(sLevelImage)); + if(nLevelIndex == 0) sLevel = " Cantrips"; + else if(nLevelIndex == 1) sLevel = " First level"; + else if(nLevelIndex == 2) sLevel = " Second level"; + else if(nLevelIndex == 3) sLevel = " Third level"; + else if(nLevelIndex == 4) sLevel = " Fourth level"; + else if(nLevelIndex == 5) sLevel = " Fifth level"; + else if(nLevelIndex == 6) sLevel = " Sixth level"; + else if(nLevelIndex == 7) sLevel = " Seventh level"; + else if(nLevelIndex == 8) sLevel = " Eighth level"; + else if(nLevelIndex == 9) sLevel = " Ninth level"; + NuiSetBind(oPC, nToken, "btn_level_" + sLevelIndex + "_tooltip", JsonString(" " + sLevel)); + } + else + { + NuiSetBind(oPC, nToken, "btn_level_" + sLevelIndex + "_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_level_" + sLevelIndex + "_image", JsonString("ctl_cg_btn_splvl")); + NuiSetBind(oPC, nToken, "btn_level_" + sLevelIndex + "_event", JsonBool(FALSE)); + } + } + NuiSetBind(oPC, nToken, "btn_level_" + IntToString(nLevel) + "_encouraged", JsonBool(TRUE)); + } + // Default to the abilities tab since they are not a caster. + else + { + if(nLevel < 10) nLevel = 10; + for(nLevelIndex = 0; nLevelIndex <= 9; nLevelIndex++) + { + sLevelIndex = IntToString(nLevelIndex); + NuiSetBind(oPC, nToken, "btn_level_" + sLevelIndex + "_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_level_" + sLevelIndex + "_image", JsonString("ctl_cg_btn_splvl")); + NuiSetBind(oPC, nToken, "btn_level_" + sLevelIndex + "_event", JsonBool(FALSE)); + } + NuiSetBind(oPC, nToken, "btn_level_10_encouraged", JsonBool(TRUE)); + } + NuiSetBind(oPC, nToken, "btn_class_" + IntToString(nClass) + "_encouraged", JsonBool(TRUE)); + } + } + } + // Row 3 Items/Abilities/Skills/Spells + int nSpell, nMetaMagic, nDomain, nSubSpell, nSubSpellIndex; + int nSpellSlot, nCounter, nMax2daRow, nFeat; + string sSpellIcon, sSpellName, sMetaMagicText, sClassFeats, sSubSpellIndex; + object oItem; + json jQuickListArray = JsonArray(); + json jSpell; + json jSpell_Icon = JsonArray(); + json jSpell_Text = JsonArray(); + SetLocalJson(oAssociate, "JSPELL_ICON", jSpell_Icon); + SetLocalJson(oAssociate, "JSPELL_NAME", jSpell_Text); + json jMetaMagic_Text = JsonArray(); + // Item powers + if(nLevel == 11) + { + string sSlots; + // Cycle through all the creatures inventory items. + oItem = GetFirstItemInInventory(oAssociate); + while(oItem != OBJECT_INVALID) + { + if(GetIdentified(oItem)) + { + // Does the item need to be equiped to use its powers? + sSlots = Get2DAString("baseitems", "EquipableSlots", GetBaseItemType(oItem)); + if(sSlots == "0x00000") + { + jQuickListArray = ai_CheckItemAbilities(jQuickListArray, oAssociate, oItem, jSpell_Icon, jSpell_Text, FALSE); + jSpell_Icon = GetLocalJson(oAssociate, "JSPELL_ICON"); + jSpell_Text = GetLocalJson(oAssociate, "JSPELL_NAME"); + WriteTimestampedLogEntry("0i_menus, 3643, oAssociate: " + GetName(oAssociate) + + " jSpell_Text: " + JsonDump(jSpell_Text, 4)); + } + } + oItem = GetNextItemInInventory(oAssociate); + } + int nSlot; + // Cycle through all the creatures equiped items. + oItem = GetItemInSlot(nSlot, oAssociate); + while(nSlot < 11) + { + if(oItem != OBJECT_INVALID) + { + jQuickListArray = ai_CheckItemAbilities(jQuickListArray, oAssociate, oItem, jSpell_Icon, jSpell_Text, TRUE); + jSpell_Icon = GetLocalJson(oAssociate, "JSPELL_ICON"); + jSpell_Text = GetLocalJson(oAssociate, "JSPELL_NAME"); + } + oItem = GetItemInSlot(++nSlot, oAssociate); + } + oItem = GetItemInSlot(INVENTORY_SLOT_CARMOUR, oAssociate); + if(oItem != OBJECT_INVALID) + { + jQuickListArray = ai_CheckItemAbilities(jQuickListArray, oAssociate, oItem, jSpell_Icon, jSpell_Text, TRUE); + jSpell_Icon = GetLocalJson(oAssociate, "JSPELL_ICON"); + jSpell_Text = GetLocalJson(oAssociate, "JSPELL_NAME"); + } + DeleteLocalJson(oAssociate, "JSPELL_ICON"); + DeleteLocalJson(oAssociate, "JSPELL_NAME"); + } + // Special abilities and skills. + else if(nLevel == 10) + { + for(nIndex = 1; nIndex <= AI_MAX_CLASSES_PER_CHARACTER; nIndex++) + { + nClassIndex = GetClassByPosition(nIndex, oAssociate); + if(nClassIndex != CLASS_TYPE_INVALID) + { + nCounter = 0; + sClassFeats = Get2DAString("classes", "FeatsTable", nClassIndex); + nMax2daRow = Get2DARowCount(sClassFeats); + while(nCounter < nMax2daRow) + { + if(Get2DAString(sClassFeats, "OnMenu", nCounter) != "0") + { + nFeat = StringToInt(Get2DAString(sClassFeats, "FeatIndex", nCounter)); + if(GetHasFeat(nFeat, oAssociate, TRUE)) + { + // Check for subfeats. + nSpell = StringToInt(Get2DAString("feat", "SPELLID", nFeat)); + nSubSpell = StringToInt(Get2DAString("spells", "SubRadSpell1", nSpell)); + //SendMessageToPC(oPC, "nFeat: " + IntToString(nFeat) + + // " nSpell: " + IntToString(nSpell) + + // " nSubSpell: " + IntToString(nSubSpell)); + if(nSubSpell) + { + for(nSubSpellIndex = 1; nSubSpellIndex <= 5; nSubSpellIndex++) + { + sSubSpellIndex = IntToString(nSubSpellIndex); + nSubSpell = StringToInt(Get2DAString("spells", "SubRadSpell" + sSubSpellIndex, nSpell)); + //SendMessageToPC(oPC, " nSpell: " + IntToString(nSpell) + + // " nSubSpell: " + IntToString(nSubSpell)); + if(nSubSpell != 0) + { + sSpellIcon = Get2DAString("spells", "iConResRef", nSubSpell); + jSpell_Icon = JsonArrayInsert(jSpell_Icon, JsonString(sSpellIcon)); + sSpellName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSubSpell))); + jSpell_Text = JsonArrayInsert(jSpell_Text, JsonString(sSpellName)); + jSpell = JsonArray(); + jSpell = JsonArrayInsert(jSpell, JsonInt(nSubSpell)); + jSpell = JsonArrayInsert(jSpell, JsonInt(nClass)); + jSpell = JsonArrayInsert(jSpell, JsonInt(0)); + jSpell = JsonArrayInsert(jSpell, JsonInt(255)); + jSpell = JsonArrayInsert(jSpell, JsonInt(0)); + jSpell = JsonArrayInsert(jSpell, JsonInt(nFeat)); + jQuickListArray = JsonArrayInsert(jQuickListArray, jSpell); + } + } + } + else if((nFeat < 71 || nFeat > 81)) + { + sSpellIcon = Get2DAString("feat", "ICON", nFeat); + jSpell_Icon = JsonArrayInsert(jSpell_Icon, JsonString(sSpellIcon)); + sSpellName = GetStringByStrRef(StringToInt(Get2DAString("feat", "FEAT", nFeat))); + jSpell_Text = JsonArrayInsert(jSpell_Text, JsonString(sSpellName)); + jSpell = JsonArray(); + jSpell = JsonArrayInsert(jSpell, JsonInt(nSpell)); + jSpell = JsonArrayInsert(jSpell, JsonInt(nClass)); + jSpell = JsonArrayInsert(jSpell, JsonInt(0)); + jSpell = JsonArrayInsert(jSpell, JsonInt(255)); + jSpell = JsonArrayInsert(jSpell, JsonInt(0)); + jSpell = JsonArrayInsert(jSpell, JsonInt(nFeat)); + jQuickListArray = JsonArrayInsert(jQuickListArray, jSpell); + } + } + } + nCounter++; + } + } + } + // Used in the execution script to get the special abilities. + //jData = JsonArrayInsert(jData, jQuickListArray); + } + else // Anything else is for spells. + { + // Search all memorized spells for the spell. + //SendMessageToPC(oPC, GetName(oAssociate) + " nClass: " + IntToString(nClass) + + // " nLevelSelected: " + IntToString(nLevel) + + // " nMemorizesSpells: " + Get2DAString("classes", "MemorizesSpells", nClass)); + if(Get2DAString("classes", "MemorizesSpells", nClass) == "1") + { + int nMaxSlot = GetMemorizedSpellCountByLevel(oAssociate, nClass, nLevel); + while(nSpellSlot < nMaxSlot) + { + nSpell = GetMemorizedSpellId(oAssociate, nClass, nLevel, nSpellSlot); + if(nSpell != -1 && ai_SpellNotInList(nSpell, jQuickListArray)) + { + nMetaMagic = GetMemorizedSpellMetaMagic(oAssociate, nClass, nLevel, nSpellSlot); + nDomain = GetMemorizedSpellIsDomainSpell(oAssociate, nClass, nLevel, nSpellSlot); + // Check for subspells. + nSubSpell = StringToInt(Get2DAString("spells", "SubRadSpell1", nSpell)); + if(nSubSpell) + { + for(nSubSpellIndex = 1; nSubSpellIndex < 6; nSubSpellIndex++) + { + sSubSpellIndex = IntToString(nSubSpellIndex); + nSubSpell = StringToInt(Get2DAString("spells", "SubRadSpell" + sSubSpellIndex, nSpell)); + if(nSubSpell && ai_SpellNotInList(nSubSpell, jQuickListArray)) + { + sSpellIcon = Get2DAString("spells", "IconResRef", nSubSpell); + jSpell_Icon = JsonArrayInsert(jSpell_Icon, JsonString(sSpellIcon)); + sSpellName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSubSpell))); + jSpell_Text = JsonArrayInsert(jSpell_Text, JsonString(sSpellName)); + sMetaMagicText = ai_GetSpellIconAttributes(oAssociate, nMetaMagic, nDomain); + jMetaMagic_Text = JsonArrayInsert(jMetaMagic_Text, JsonString(sMetaMagicText)); + jSpell = JsonArray(); + jSpell = JsonArrayInsert(jSpell, JsonInt(nSubSpell)); + jSpell = JsonArrayInsert(jSpell, JsonInt(nClass)); + jSpell = JsonArrayInsert(jSpell, JsonInt(nLevel)); + jSpell = JsonArrayInsert(jSpell, JsonInt(nMetaMagic)); + jSpell = JsonArrayInsert(jSpell, JsonInt(nDomain)); + jSpell = JsonArrayInsert(jSpell, JsonInt(0)); + jQuickListArray = JsonArrayInsert(jQuickListArray, jSpell); + } + } + } + else + { + sSpellIcon = Get2DAString("spells", "IconResRef", nSpell); + jSpell_Icon = JsonArrayInsert(jSpell_Icon, JsonString(sSpellIcon)); + sSpellName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); + jSpell_Text = JsonArrayInsert(jSpell_Text, JsonString(sSpellName)); + sMetaMagicText = ai_GetSpellIconAttributes(oAssociate, nMetaMagic, nDomain); + jMetaMagic_Text = JsonArrayInsert(jMetaMagic_Text, JsonString(sMetaMagicText)); + jSpell = JsonArray(); + jSpell = JsonArrayInsert(jSpell, JsonInt(nSpell)); + jSpell = JsonArrayInsert(jSpell, JsonInt(nClass)); + jSpell = JsonArrayInsert(jSpell, JsonInt(nLevel)); + jSpell = JsonArrayInsert(jSpell, JsonInt(nMetaMagic)); + jSpell = JsonArrayInsert(jSpell, JsonInt(nDomain)); + jSpell = JsonArrayInsert(jSpell, JsonInt(0)); + jQuickListArray = JsonArrayInsert(jQuickListArray, jSpell); + //SendMessageToPC(oPC, "nSpell: " + IntToString(nSpell) + + // " sSpellIcon: " + sSpellIcon + + // " sSpellName: " + sSpellName+ + // " nMaxSlot: " + IntToString(nMaxSlot) + + // " nSpellSlot: " + IntToString(nSpellSlot)); + } + } + ++nSpellSlot; + } + } + // Non-memorized spells. + else + { + int nMaxSlot = GetKnownSpellCount(oAssociate, nClass, nLevel); + while(nSpellSlot < nMaxSlot) + { + nSpell = GetKnownSpellId(oAssociate, nClass, nLevel, nSpellSlot); + if(nSpell != -1)// && ai_SpellNotInList(nSpell, jQuickListArray)) + { + sSpellIcon = Get2DAString("spells", "IconResRef", nSpell); + jSpell_Icon = JsonArrayInsert(jSpell_Icon, JsonString(sSpellIcon)); + sSpellName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); + jSpell_Text = JsonArrayInsert(jSpell_Text, JsonString(sSpellName)); + jSpell = JsonArray(); + jSpell = JsonArrayInsert(jSpell, JsonInt(nSpell)); + jSpell = JsonArrayInsert(jSpell, JsonInt(nClass)); + jSpell = JsonArrayInsert(jSpell, JsonInt(nLevel)); + jSpell = JsonArrayInsert(jSpell, JsonInt(255)); + jSpell = JsonArrayInsert(jSpell, JsonInt(0)); + jQuickListArray = JsonArrayInsert(jQuickListArray, jSpell); + } + ++nSpellSlot; + } + } + } + NuiSetBind(oPC, nToken, "icon_spell", jSpell_Icon); + NuiSetBind(oPC, nToken, "text_spell", jSpell_Text); + NuiSetBind(oPC, nToken, "metamagic_text", jMetaMagic_Text); + jData = JsonArrayInsert(jData, jQuickListArray); + NuiSetUserData(oPC, nToken, jData); + // Row 4 Quick widget list label. + // Row 5 Quick widget List 1 + json jWidget = JsonArrayGet(jSpells, 2); + nIndex = 0; + while(nIndex < 10) + { + jSpell = JsonArrayGet(jWidget, nIndex); + sIndex = IntToString(nIndex); + NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_event", JsonBool(TRUE)); + if(JsonGetType(jSpell) != JSON_TYPE_NULL) + { + nSpell = JsonGetInt(JsonArrayGet(jSpell, 0)); + nClass = JsonGetInt(JsonArrayGet(jSpell, 1)); + nFeat = JsonGetInt(JsonArrayGet(jSpell, 5)); + if(nClass == -1) // This is an Item. + { + string sBaseName; + sName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); + int nBaseItemType = JsonGetInt(JsonArrayGet(jSpell, 3)); + int nIprpSubType = JsonGetInt(JsonArrayGet(jSpell, 4)); + if(nSpell == SPELL_HEALINGKIT) + { + sName = "Healer's Kit +" + IntToString(nIprpSubType); + sSpellIcon = "isk_heal"; + sBaseName = "Healer's Kit"; + } + else if(nBaseItemType == BASE_ITEM_ENCHANTED_SCROLL || + nBaseItemType == BASE_ITEM_SCROLL || + nBaseItemType == BASE_ITEM_SPELLSCROLL) + { + sSpellIcon = Get2DAString("iprp_spells", "Icon", nIprpSubType); + sBaseName = "Scroll"; + } + else + { + if(nBaseItemType == BASE_ITEM_ENCHANTED_POTION || + nBaseItemType == BASE_ITEM_POTIONS) sBaseName = "Potion"; + else if(nBaseItemType == BASE_ITEM_ENCHANTED_WAND || + nBaseItemType == BASE_ITEM_MAGICWAND || + nBaseItemType == FEAT_CRAFT_WAND) sBaseName = "Wand"; + else sBaseName = ai_StripColorCodes(GetName(GetObjectByUUID(JsonGetString(JsonArrayGet(jSpell, 5))))); + sSpellIcon = Get2DAString("spells", "IconResRef", nSpell); + } + NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_image", JsonString(sSpellIcon)); + oItem = GetObjectByUUID(JsonGetString(JsonArrayGet(jSpell, 5))); + int nUses = ai_GetItemUses(oItem, nIprpSubType); + if(nUses) + { + NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_event", JsonBool(TRUE)); + if(nUses == 999) sText = "Unlimited"; + else sText = IntToString(nUses); + NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_tooltip", JsonString(" " + sName + " (" + sBaseName + " / " + sText + ")")); + } + } + else if(nFeat) // This is a feat. + { + sSpellIcon = ""; + if(nSpell) + { + sName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); + sSpellIcon = Get2DAString("spells", "IconResRef", nSpell); + } + if(sSpellIcon == "" || sSpellIcon == "IR_USE") + { + sName = GetStringByStrRef(StringToInt(Get2DAString("feat", "FEAT", nFeat))); + sSpellIcon = Get2DAString("feat", "ICON", nFeat); + } + NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_image", JsonString(sSpellIcon)); + NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_tooltip", JsonString(" " + sName)); + } + else // This is a spell. + { + sName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); + sClass = GetStringByStrRef(StringToInt(Get2DAString("classes", "Name", nClass))); + nLevel = JsonGetInt(JsonArrayGet(jSpell, 2)); + nMetaMagic = JsonGetInt(JsonArrayGet(jSpell, 3)); + nDomain = JsonGetInt(JsonArrayGet(jSpell, 4)); + sSpellIcon = Get2DAString("spells", "IconResRef", nSpell); + NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_image", JsonString(sSpellIcon)); + NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_tooltip", JsonString(" " + sName + " (" + sClass + " / " + IntToString(nLevel) + ")")); + sMetaMagicText = ai_GetSpellIconAttributes(oAssociate, nMetaMagic, nDomain); + NuiSetBind(oPC, nToken, "metamagic_" + sIndex + "_text", JsonString(sMetaMagicText)); + } + } + else + { + NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_image", JsonString("ctl_cg_btn_splvl")); + NuiSetBind(oPC, nToken, "metamagic_" + sIndex + "_text", JsonString("")); + NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_event", JsonBool(FALSE)); + } + ++nIndex; + } + if(nIndex < 10) return; + // Row 6 Quick widget List2 + while(nIndex < 20) + { + jSpell = JsonArrayGet(jWidget, nIndex); + sIndex = IntToString(nIndex); + NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_event", JsonBool(TRUE)); + if(JsonGetType(jSpell) != JSON_TYPE_NULL) + { + nSpell = JsonGetInt(JsonArrayGet(jSpell, 0)); + nClass = JsonGetInt(JsonArrayGet(jSpell, 1)); + nFeat = JsonGetInt(JsonArrayGet(jSpell, 5)); + if(nClass == -1) // This is an Item. + { + string sBaseName; + sName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); + int nBaseItemType = JsonGetInt(JsonArrayGet(jSpell, 3)); + int nIprpSubType = JsonGetInt(JsonArrayGet(jSpell, 4)); + if(nSpell == SPELL_HEALINGKIT) + { + sName = "Healer's Kit +" + IntToString(nIprpSubType); + sSpellIcon = "isk_heal"; + sBaseName = "Healer's Kit"; + } + else if(nBaseItemType == BASE_ITEM_ENCHANTED_SCROLL || + nBaseItemType == BASE_ITEM_SCROLL || + nBaseItemType == BASE_ITEM_SPELLSCROLL) + { + sSpellIcon = Get2DAString("iprp_spells", "Icon", nIprpSubType); + sBaseName = "Scroll"; + } + else + { + if(nBaseItemType == BASE_ITEM_ENCHANTED_POTION || + nBaseItemType == BASE_ITEM_POTIONS) sBaseName = "Potion"; + else if(nBaseItemType == BASE_ITEM_ENCHANTED_WAND || + nBaseItemType == BASE_ITEM_MAGICWAND || + nBaseItemType == FEAT_CRAFT_WAND) sBaseName = "Wand"; + else sBaseName = ai_StripColorCodes(GetName(GetObjectByUUID(JsonGetString(JsonArrayGet(jSpell, 5))))); + sSpellIcon = Get2DAString("spells", "IconResRef", nSpell); + } + NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_image", JsonString(sSpellIcon)); + oItem = GetObjectByUUID(JsonGetString(JsonArrayGet(jSpell, 5))); + int nUses = ai_GetItemUses(oItem, nIprpSubType); + if(nUses) + { + NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_event", JsonBool(TRUE)); + if(nUses == 999) sText = "Unlimited"; + else sText = IntToString(nUses); + NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_tooltip", JsonString(" " + sName + " (" + sBaseName + " / " + sText + ")")); + } + } + else if(nFeat) // This is a feat. + { + sSpellIcon = ""; + if(nSpell) + { + sName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); + sSpellIcon = Get2DAString("spells", "IconResRef", nSpell); + } + if(sSpellIcon == "" || sSpellIcon == "IR_USE") + { + sName = GetStringByStrRef(StringToInt(Get2DAString("feat", "FEAT", nFeat))); + sSpellIcon = Get2DAString("feat", "ICON", nFeat); + } + NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_image", JsonString(sSpellIcon)); + NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_tooltip", JsonString(" " + sName)); + } + else // This is a spell. + { + sName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); + sClass = GetStringByStrRef(StringToInt(Get2DAString("classes", "Name", nClass))); + nLevel = JsonGetInt(JsonArrayGet(jSpell, 2)); + nMetaMagic = JsonGetInt(JsonArrayGet(jSpell, 3)); + sSpellIcon = Get2DAString("spells", "IconResRef", nSpell); + NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_image", JsonString(sSpellIcon)); + NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_tooltip", JsonString(" " + sName + " (" + sClass + " / " + IntToString(nLevel) + ")")); + sMetaMagicText = ai_GetSpellIconAttributes(oAssociate, nMetaMagic, nDomain); + NuiSetBind(oPC, nToken, "metamagic_" + sIndex + "_text", JsonString(sMetaMagicText)); + } + } + else + { + NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_image", JsonString("ctl_cg_btn_splvl")); + NuiSetBind(oPC, nToken, "metamagic_" + sIndex + "_text", JsonString("")); + NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_event", JsonBool(FALSE)); + } + ++nIndex; + } +} +void ai_CreateSpellMemorizationNUI(object oPC, object oAssociate) +{ + // Set window to not save until it has been created. + SetLocalInt (oPC, AI_NO_NUI_SAVE, TRUE); + DelayCommand (2.0, DeleteLocalInt (oPC, AI_NO_NUI_SAVE)); + string sAssociateType = ai_GetAssociateType(oPC, oAssociate); + json jRow = JsonArray(); + // Row 1 Classes************************************************************ 414 / 73 + int nClass, bCaster, nIndex; + string sIndex, sClassIcon, sLevelIcon; + for(nIndex = 1; nIndex <= AI_MAX_CLASSES_PER_CHARACTER; nIndex++) + { + nClass = GetClassByPosition(nIndex, oAssociate); + if(nClass != CLASS_TYPE_INVALID) + { + if(StringToInt(Get2DAString("classes", "MemorizesSpells", nClass))) + { + // This saves the class position in the button id so we can get it later. + sIndex = IntToString(nIndex); + sClassIcon = Get2DAString("classes", "Icon", nClass); + jRow = CreateButtonImage(jRow, sClassIcon, "btn_class_" + sIndex, 35.0f, 35.0f, 0.0, "btn_class_" + sIndex + "_tooltip"); + } + } + } + jRow = JsonArrayInsert(jRow, NuiSpacer()); + // Add row to the column. + json jCol = JsonArrayInsert(JsonArray(), NuiRow(jRow)); + // Row 2 (Levels) ********************************************************** 414 / 116 + jRow = JsonArray(); + for(nIndex = 0; nIndex <= 9; nIndex++) + { + // This saves the level in the button id so we can get it later. + sIndex = IntToString(nIndex); + jRow = CreateButtonImage(jRow, "", "btn_level_" + sIndex, 35.0f, 35.0f, 0.0, "btn_level_" + sIndex + "_tooltip"); + } + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 3 (Spell List)******************************************************* 414 / 398 + json jButton = JsonArray(); + jButton = NuiButton(NuiBind("text_spell")); + jButton = NuiId(jButton, "btn_text_spell"); + json jRectangle = NuiRect(4.0, 4.0, 27.0, 27.0); + json jDrawList = JsonArrayInsert(JsonArray(), NuiDrawListImage(JsonBool(TRUE), NuiBind("icon_spell"), jRectangle, JsonInt(NUI_ASPECT_FILL), JsonInt(NUI_HALIGN_CENTER), JsonInt(NUI_VALIGN_MIDDLE))); + //jRectangle = NuiRect(4.0, 4.0, 10.0, 10.0); + //json jMetaMagic = NuiDrawListText(JsonBool(TRUE), NuiColor(255, 255, 0), jRectangle, NuiBind("metamagic_text")); + //jDrawList = JsonArrayInsert(jDrawList, jMetaMagic); + jButton = NuiDrawList(jButton, JsonBool(TRUE), jDrawList); + json jListTemplate = JsonArrayInsert(JsonArray(), NuiListTemplateCell(jButton, 275.0, FALSE)); + json jInfo = NuiButtonImage(JsonString("gui_cg_qstn_mark")); + jInfo = NuiId(jInfo, "btn_info_spell"); + jListTemplate = JsonArrayInsert(jListTemplate, NuiListTemplateCell(jInfo, 35.0, FALSE)); + jRow = JsonArrayInsert(JsonArray(), NuiHeight(NuiList(jListTemplate, NuiBind("icon_spell"), 35.0), 282.0)); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 4 (Widget Label)***************************************************** 414 / 426 + jRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + CreateLabel(jRow, "Memorized Spell List", "lbl_spell_list", 150.0, 20.0, 0, 0, 0.0); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 5 (Memorize slots)*************************************************** 414 / 469 + // Get the class and level selected from the database. + int nClassSelected, nLevelSelected; + json jSpells; + json jAIData = ai_GetAssociateDbJson(oPC, sAssociateType, "aidata"); + // Temporary fix for error! :/ + if(JsonGetLength(jAIData) == 0) + { + ai_CheckAssociateData(oPC, oAssociate, sAssociateType, TRUE); + jAIData = ai_GetAssociateDbJson(oPC, sAssociateType, "aidata"); + } + if(JsonGetLength(jAIData) == 9) + { + jSpells = JsonArray(); + jSpells = JsonArrayInsert(jSpells, JsonInt(1)); + jSpells = JsonArrayInsert(jSpells, JsonInt(0)); + jAIData = JsonArrayInsert(jAIData, jSpells); + ai_SetAssociateDbJson(oPC, sAssociateType, "aidata", jAIData); + } + else + { + jSpells = JsonArrayGet(jAIData, 10); + if(JsonGetType(jSpells) == JSON_TYPE_NULL) + { + jSpells = JsonArray(); + jSpells = JsonArrayInsert(jSpells, JsonInt(1)); + jSpells = JsonArrayInsert(jSpells, JsonInt(0)); + jAIData = JsonArraySet(jAIData, 10, jSpells); + ai_SetAssociateDbJson(oPC, sAssociateType, "aidata", jAIData); + } + else + { + nClassSelected = JsonGetInt(JsonArrayGet(jSpells, 0)); + nLevelSelected = JsonGetInt(JsonArrayGet(jSpells, 1)); + } + } + // If we left the Quick Use widget on Special Abilities (10) or Items (11) goto level 0 + if(nLevelSelected == 10 || nLevelSelected == 11) + { + nLevelSelected = 0; + jSpells = JsonArraySet(jSpells, 1, JsonInt(0)); + jAIData = JsonArraySet(jAIData, 10, jSpells); + ai_SetAssociateDbJson(oPC, sAssociateType, "aidata", jAIData); + } + if(nClassSelected < 1 || nClassSelected > AI_MAX_CLASSES_PER_CHARACTER) nClassSelected = 1; + nClass = GetClassByPosition(nClassSelected, oAssociate); + int nMaxMemorizationSlots = GetMemorizedSpellCountByLevel(oAssociate, nClass, nLevelSelected); + jRow = JsonArray(); + for(nIndex = 0; nIndex < nMaxMemorizationSlots; nIndex++) + { + // This saves the index location of the spell in the list. + sIndex = IntToString(nIndex); + json jButton = NuiButtonImage(NuiBind("btn_memorized_" + sIndex + "_image")); + jButton = NuiEnabled(jButton, NuiBind("btn_memorized_" + sIndex + "_event")); + jButton = NuiId(jButton, "btn_memorized_" + sIndex); + jButton = NuiWidth(NuiHeight(jButton, 35.0), 35.0); + jButton = NuiMargin(jButton, 0.0); + jButton = NuiTooltip(jButton, NuiBind("btn_memorized_" + sIndex + "_tooltip")); + //json jRectangle = NuiRect(4.0, 4.0, 10.0, 10.0); + //json jMetaMagic = NuiDrawListText(JsonBool(TRUE), NuiColor(255, 255, 0), jRectangle, NuiBind("metamagic_" + sIndex + "_text")); + //jDrawList = JsonArrayInsert(JsonArray(), jMetaMagic); + //jButton = NuiDrawList(jButton, JsonBool(TRUE), jDrawList); + jRow = JsonArrayInsert(jRow, jButton); + } + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Get the window location to restore it from the database. + float fX, fY; + json jLocations = ai_GetAssociateDbJson(oPC, sAssociateType, "locations"); + jLocations = JsonObjectGet(jLocations, sAssociateType + AI_SPELL_MEMORIZE_NUI); + if(JsonGetType(jLocations) == JSON_TYPE_NULL) { fX = -1.0; fY = -1.0; } + else + { + fX = JsonGetFloat(JsonObjectGet(jLocations, "x")); + fY = JsonGetFloat(JsonObjectGet(jLocations, "y")); + } + string sText, sName = GetName(oAssociate); + if(GetStringRight(sName, 1) == "s") sName = sName + "'"; + else sName = sName + "'s"; + // Set the Layout of the window. + json jLayout = NuiCol(jCol); + int nToken = SetWindow(oPC, jLayout, sAssociateType + AI_SPELL_MEMORIZE_NUI, sName + " Spell Memorization Menu", + fX, fY, 375.0, 504.0 + 12.0, FALSE, FALSE, TRUE, FALSE, TRUE, "0e_nui"); + // Set the Layout of the window. + // Save the associate to the nui for use in 0e_nui + json jData = JsonArrayInsert(JsonArray(), JsonString(ObjectToString(oAssociate))); + // Set event watches for save window location. + NuiSetBindWatch(oPC, nToken, "window_geometry", TRUE); + // Row 1 & 2 Class & Level + int nSpellLevel, nIndexLevel, nMaxSpellLevel; + string sClass, sLevel, sLevelImage, sIndexLevel; + for(nIndex = 1; nIndex <= AI_MAX_CLASSES_PER_CHARACTER; nIndex++) + { + nClass = GetClassByPosition(nIndex, oAssociate); + if(nClass != CLASS_TYPE_INVALID) + { + bCaster = StringToInt(Get2DAString("classes", "SpellCaster", nClass)); + if(bCaster) + { + sClass = GetStringByStrRef(StringToInt(Get2DAString("classes", "Name", nClass))); + sIndex = IntToString(nIndex); + NuiSetBind(oPC, nToken, "btn_class_" + sIndex + "_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_class_" + sIndex + "_tooltip", JsonString(" " + sClass)); + if(nClassSelected == nIndex) + { + int nClassLevel = GetLevelByClass(nClass, oAssociate); + string sSpellsGained = Get2DAString("classes", "SpellGainTable", nClass); + int nMaxSpellLevel = StringToInt(Get2DAString(sSpellsGained, "NumSpellLevels", nClassLevel - 1)); + for(nIndexLevel = 0; nIndexLevel <= 9; nIndexLevel++) + { + sIndexLevel = IntToString(nIndexLevel); + if(nIndexLevel < nMaxSpellLevel) + { + if(nIndexLevel == 0) sLevelImage = "ir_cantrips"; + else if(nIndexLevel < 7)sLevelImage = "ir_level" + sIndexLevel; + else sLevelImage = "ir_level789"; + if(nIndexLevel == 0) sLevel = " Cantrips"; + else if(nIndexLevel == 1) sLevel = " First level"; + else if(nIndexLevel == 2) sLevel = " Second level"; + else if(nIndexLevel == 3) sLevel = " Third level"; + else if(nIndexLevel == 4) sLevel = " Fourth level"; + else if(nIndexLevel == 5) sLevel = " Fifth level"; + else if(nIndexLevel == 6) sLevel = " Sixth level"; + else if(nIndexLevel == 7) sLevel = " Seventh level"; + else if(nIndexLevel == 8) sLevel = " Eighth level"; + else if(nIndexLevel == 9) sLevel = " Ninth level"; + NuiSetBind(oPC, nToken, "btn_level_" + sIndexLevel + "_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_level_" + sIndexLevel + "_tooltip", JsonString(" " + sLevel)); + NuiSetBind(oPC, nToken, "btn_level_" + sIndexLevel + "_image", JsonString(sLevelImage)); + } + else + { + NuiSetBind(oPC, nToken, "btn_level_" + sIndexLevel + "_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_level_" + sIndexLevel + "_image", JsonString("ctl_cg_btn_splvl")); + NuiSetBind(oPC, nToken, "btn_level_" + sIndexLevel + "_event", JsonBool(FALSE)); + } + } + NuiSetBind(oPC, nToken, "btn_level_" + IntToString(nLevelSelected) + "_encouraged", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_class_" + IntToString(nClassSelected) + "_encouraged", JsonBool(TRUE)); + } + } + } + } + // Row 3 Spells + int nSpellSlot, nSpell, nMetamagic; + json jSpell; + json jWidget = JsonArrayGet(jSpells, 2); + nClass = GetClassByPosition(nClassSelected, oAssociate); + string sSpellIcon, sSpellName, sMetaMagicText; + json jSpellArray = JsonArray(); + json jSpell_Icon = JsonArray(); + json jSpell_Text = JsonArray(); + json jMetaMagic_Text = JsonArray(); + // List the spells they know from their spellbook. + if(Get2DAString("classes", "SpellbookRestricted", nClass) == "1") + { + int nMaxSpells = GetKnownSpellCount(oAssociate, nClass, nLevelSelected); + //WriteTimestampedLogEntry("Maxspells: " + IntToString(nMaxSpells) + + // " nClass: " + IntToString(nClass) + + // " nLevelSelected: " + IntToString(nLevelSelected)); + while(nSpellSlot < nMaxSpells) + { + nSpell = GetKnownSpellId(oAssociate, nClass, nLevelSelected, nSpellSlot); + if(nSpell != -1) + { + jSpellArray = JsonArrayInsert(jSpellArray, JsonInt(nSpell)); + sSpellIcon = Get2DAString("spells", "IconResRef", nSpell); + sSpellName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); + //SendMessageToPC(oPC, "SpellBook: nSpell: " + IntToString(nSpell) + + // " sSpellIcon: " + sSpellIcon + + // " sSpellName: " + sSpellName+ + // " nMaxSpells: " + IntToString(nMaxSpells) + + // " nSpellSlot: " + IntToString(nSpellSlot)); + //sMetaMagicText = ai_GetSpellIconAttributes(oAssociate, nClass, nLevelSelected, nSpellSlot); + //jMetaMagic_Text = JsonArrayInsert(jMetaMagic_Text, JsonString(sMetaMagicText)); + jSpell_Icon = JsonArrayInsert(jSpell_Icon, JsonString(sSpellIcon)); + jSpell_Text = JsonArrayInsert(jSpell_Text, JsonString(sSpellName)); + } + ++nSpellSlot; + } + } + // List the spells from the spells.2da file (they get to choose from them all!). + else + { + string sSpellTableColumn = Get2DAString("classes", "SpellTableColumn", nClass); + int nMaxSpells = Get2DARowCount("spells"); + while(nSpell < nMaxSpells) + { + sLevel = Get2DAString("spells", sSpellTableColumn, nSpell); + if(sLevel != "") + { + if(StringToInt(sLevel) == nLevelSelected) + { + jSpellArray = JsonArrayInsert(jSpellArray, JsonInt(nSpell)); + sSpellIcon = Get2DAString("spells", "IconResRef", nSpell); + sSpellName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); + jSpell_Icon = JsonArrayInsert(jSpell_Icon, JsonString(sSpellIcon)); + jSpell_Text = JsonArrayInsert(jSpell_Text, JsonString(sSpellName)); + } + } + ++nSpell; + } + } + jData = JsonArrayInsert(jData, jSpellArray); + NuiSetUserData(oPC, nToken, jData); + NuiSetBind(oPC, nToken, "icon_spell", jSpell_Icon); + NuiSetBind(oPC, nToken, "text_spell", jSpell_Text); + NuiSetBind(oPC, nToken, "metamagic_text", jMetaMagic_Text); + // Row 4 Spell memorized list label. + // Row 5 Spell memorized List + int nMetaMagic, nDomain; + nIndex = 0; + while(nIndex < nMaxMemorizationSlots) + { + sIndex = IntToString(nIndex); + NuiSetBind(oPC, nToken, "btn_memorized_" + sIndex + "_event", JsonBool(TRUE)); + if(GetMemorizedSpellId(oAssociate, nClass, nLevelSelected, nIndex) > -1) + { + nSpell = GetMemorizedSpellId(oAssociate, nClass, nLevelSelected, nIndex); + sName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); + //nMetaMagic = 255; + //nDomain = 0; + sSpellIcon = Get2DAString("spells", "IconResRef", nSpell); + NuiSetBind(oPC, nToken, "btn_memorized_" + sIndex + "_image", JsonString(sSpellIcon)); + NuiSetBind(oPC, nToken, "btn_memorized_" + sIndex + "_tooltip", JsonString(" " + sName + " (" + sClass + " / " + IntToString(nLevelSelected) + ")")); + //sMetaMagicText = ai_GetSpellIconAttributes(oAssociate, -1, -1, -1, nMetaMagic, nDomain); + //NuiSetBind(oPC, nToken, "metamagic_" + sIndex + "_text", JsonString(sMetaMagicText)); + } + else + { + NuiSetBind(oPC, nToken, "btn_memorized_" + sIndex + "_image", JsonString("ctl_cg_btn_splvl")); + //NuiSetBind(oPC, nToken, "metamagic_" + sIndex + "_text", JsonString("")); + NuiSetBind(oPC, nToken, "btn_memorized_" + sIndex + "_event", JsonBool(FALSE)); + } + ++nIndex; + } +} +void ai_CreateSpellKnownNUI(object oPC, object oAssociate) +{ + // Set window to not save until it has been created. + SetLocalInt (oPC, AI_NO_NUI_SAVE, TRUE); + DelayCommand (2.0, DeleteLocalInt (oPC, AI_NO_NUI_SAVE)); + string sAssociateType = ai_GetAssociateType(oPC, oAssociate); + json jRow = JsonArray(); + // Row 1 Classes************************************************************ 414 / 73 + int nClass, bCaster, nIndex; + string sIndex, sClassIcon, sLevelIcon; + for(nIndex = 1; nIndex <= AI_MAX_CLASSES_PER_CHARACTER; nIndex++) + { + nClass = GetClassByPosition(nIndex, oAssociate); + if(nClass != CLASS_TYPE_INVALID) + { + if(StringToInt(Get2DAString("classes", "SpellbookRestricted", nClass))) + { + // This saves the class position in the button id so we can get it later. + sIndex = IntToString(nIndex); + sClassIcon = Get2DAString("classes", "Icon", nClass); + jRow = CreateButtonImage(jRow, sClassIcon, "btn_class_" + sIndex, 35.0f, 35.0f, 0.0, "btn_class_" + sIndex + "_tooltip"); + } + } + } + jRow = JsonArrayInsert(jRow, NuiSpacer()); + // Add row to the column. + json jCol = JsonArrayInsert(JsonArray(), NuiRow(jRow)); + // Row 2 (Levels) ********************************************************** 414 / 116 + jRow = JsonArray(); + for(nIndex = 0; nIndex <= 9; nIndex++) + { + // This saves the level in the button id so we can get it later. + sIndex = IntToString(nIndex); + jRow = CreateButtonImage(jRow, "", "btn_level_" + sIndex, 35.0f, 35.0f, 0.0, "btn_level_" + sIndex + "_tooltip"); + } + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 3 (Spell List)******************************************************* 414 / 398 + json jButton = JsonArray(); + jButton = NuiButton(NuiBind("text_spell")); + jButton = NuiId(jButton, "btn_text_spell"); + json jRectangle = NuiRect(4.0, 4.0, 27.0, 27.0); + json jDrawList = JsonArrayInsert(JsonArray(), NuiDrawListImage(JsonBool(TRUE), NuiBind("icon_spell"), jRectangle, JsonInt(NUI_ASPECT_FILL), JsonInt(NUI_HALIGN_CENTER), JsonInt(NUI_VALIGN_MIDDLE))); + //jRectangle = NuiRect(4.0, 4.0, 10.0, 10.0); + //json jMetaMagic = NuiDrawListText(JsonBool(TRUE), NuiColor(255, 255, 0), jRectangle, NuiBind("metamagic_text")); + //jDrawList = JsonArrayInsert(jDrawList, jMetaMagic); + jButton = NuiDrawList(jButton, JsonBool(TRUE), jDrawList); + json jListTemplate = JsonArrayInsert(JsonArray(), NuiListTemplateCell(jButton, 275.0, FALSE)); + json jInfo = NuiButtonImage(JsonString("gui_cg_qstn_mark")); + jInfo = NuiId(jInfo, "btn_info_spell"); + jListTemplate = JsonArrayInsert(jListTemplate, NuiListTemplateCell(jInfo, 35.0, FALSE)); + jRow = JsonArrayInsert(JsonArray(), NuiHeight(NuiList(jListTemplate, NuiBind("icon_spell"), 35.0), 282.0)); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 4 (Widget Label)***************************************************** 414 / 426 + jRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + CreateLabel(jRow, "Known Spell List", "lbl_spell_list", 150.0, 20.0, 0, 0, 0.0); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 5 (Memorize slots)*************************************************** 414 / 469 + // Get the class and level selected from the database. + int nClassSelected, nLevelSelected; + json jSpells; + json jAIData = ai_GetAssociateDbJson(oPC, sAssociateType, "aidata"); + // Temporary fix for error! :/ + if(JsonGetLength(jAIData) == 0) + { + ai_CheckAssociateData(oPC, oAssociate, sAssociateType, TRUE); + jAIData = ai_GetAssociateDbJson(oPC, sAssociateType, "aidata"); + } + if(JsonGetLength(jAIData) == 9) + { + jSpells = JsonArray(); + jSpells = JsonArrayInsert(jSpells, JsonInt(1)); + jSpells = JsonArrayInsert(jSpells, JsonInt(0)); + jAIData = JsonArrayInsert(jAIData, jSpells); + ai_SetAssociateDbJson(oPC, sAssociateType, "aidata", jAIData); + } + else + { + jSpells = JsonArrayGet(jAIData, 10); + if(JsonGetType(jSpells) == JSON_TYPE_NULL) + { + jSpells = JsonArray(); + jSpells = JsonArrayInsert(jSpells, JsonInt(1)); + jSpells = JsonArrayInsert(jSpells, JsonInt(0)); + jAIData = JsonArraySet(jAIData, 10, jSpells); + ai_SetAssociateDbJson(oPC, sAssociateType, "aidata", jAIData); + } + else + { + nClassSelected = JsonGetInt(JsonArrayGet(jSpells, 0)); + nLevelSelected = JsonGetInt(JsonArrayGet(jSpells, 1)); + } + } + // If we left the Quick Use widget on Special Abilities (10) or Items (11) goto level 0 + if(nLevelSelected == 10 || nLevelSelected == 11) + { + nLevelSelected = 0; + jSpells = JsonArraySet(jSpells, 1, JsonInt(0)); + jAIData = JsonArraySet(jAIData, 10, jSpells); + ai_SetAssociateDbJson(oPC, sAssociateType, "aidata", jAIData); + } + if(nClassSelected < 1 || nClassSelected > AI_MAX_CLASSES_PER_CHARACTER) nClassSelected = 1; + nClass = GetClassByPosition(nClassSelected, oAssociate); + jRow = JsonArray(); + for(nIndex = 0; nIndex < 10; nIndex++) + { + // This saves the index location of the spell in the list. + sIndex = IntToString(nIndex); + json jButton = NuiButtonImage(NuiBind("btn_known_" + sIndex + "_image")); + jButton = NuiEnabled(jButton, NuiBind("btn_known_" + sIndex + "_event")); + jButton = NuiId(jButton, "btn_known_" + sIndex); + jButton = NuiWidth(NuiHeight(jButton, 35.0), 35.0); + jButton = NuiMargin(jButton, 0.0); + jButton = NuiTooltip(jButton, NuiBind("btn_known_" + sIndex + "_tooltip")); + //json jRectangle = NuiRect(4.0, 4.0, 10.0, 10.0); + //json jMetaMagic = NuiDrawListText(JsonBool(TRUE), NuiColor(255, 255, 0), jRectangle, NuiBind("metamagic_" + sIndex + "_text")); + //jDrawList = JsonArrayInsert(JsonArray(), jMetaMagic); + //jButton = NuiDrawList(jButton, JsonBool(TRUE), jDrawList); + jRow = JsonArrayInsert(jRow, jButton); + } + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Do the second row. + jRow = JsonArray(); + for(nIndex = 10; nIndex < 20; nIndex++) + { + // This saves the index location of the spell in the list. + sIndex = IntToString(nIndex); + json jButton = NuiButtonImage(NuiBind("btn_known_" + sIndex + "_image")); + jButton = NuiEnabled(jButton, NuiBind("btn_known_" + sIndex + "_event")); + jButton = NuiId(jButton, "btn_known_" + sIndex); + jButton = NuiWidth(NuiHeight(jButton, 35.0), 35.0); + jButton = NuiMargin(jButton, 0.0); + jButton = NuiTooltip(jButton, NuiBind("btn_known_" + sIndex + "_tooltip")); + //json jRectangle = NuiRect(4.0, 4.0, 10.0, 10.0); + //json jMetaMagic = NuiDrawListText(JsonBool(TRUE), NuiColor(255, 255, 0), jRectangle, NuiBind("metamagic_" + sIndex + "_text")); + //jDrawList = JsonArrayInsert(JsonArray(), jMetaMagic); + //jButton = NuiDrawList(jButton, JsonBool(TRUE), jDrawList); + jRow = JsonArrayInsert(jRow, jButton); + } + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Get the window location to restore it from the database. + float fX, fY; + json jLocations = ai_GetAssociateDbJson(oPC, sAssociateType, "locations"); + jLocations = JsonObjectGet(jLocations, sAssociateType + AI_SPELL_KNOWN_NUI); + if(JsonGetType(jLocations) == JSON_TYPE_NULL) { fX = -1.0; fY = -1.0; } + else + { + fX = JsonGetFloat(JsonObjectGet(jLocations, "x")); + fY = JsonGetFloat(JsonObjectGet(jLocations, "y")); + } + string sText, sName = GetName(oAssociate); + if(GetStringRight(sName, 1) == "s") sName = sName + "'"; + else sName = sName + "'s"; + // Set the Layout of the window. + json jLayout = NuiCol(jCol); + int nToken = SetWindow(oPC, jLayout, sAssociateType + AI_SPELL_KNOWN_NUI, sName + " Spell Known Menu", + fX, fY, 375.0, 539.0 + 12.0, FALSE, FALSE, TRUE, FALSE, TRUE, "0e_nui"); + // Set the Layout of the window. + // Save the associate to the nui for use in 0e_nui + json jData = JsonArrayInsert(JsonArray(), JsonString(ObjectToString(oAssociate))); + // Set event watches for save window location. + NuiSetBindWatch(oPC, nToken, "window_geometry", TRUE); + // Row 1 & 2 Class & Level + int nSpellLevel, nIndexLevel, nMaxSpellLevel, nClassLevel; + string sClass, sLevel, sLevelImage, sIndexLevel, sSpellsGained; + for(nIndex = 1; nIndex <= AI_MAX_CLASSES_PER_CHARACTER; nIndex++) + { + nClass = GetClassByPosition(nIndex, oAssociate); + if(nClass != CLASS_TYPE_INVALID) + { + bCaster = StringToInt(Get2DAString("classes", "SpellbookRestricted", nClass)); + if(bCaster) + { + sClass = GetStringByStrRef(StringToInt(Get2DAString("classes", "Name", nClass))); + sIndex = IntToString(nIndex); + NuiSetBind(oPC, nToken, "btn_class_" + sIndex + "_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_class_" + sIndex + "_tooltip", JsonString(" " + sClass)); + if(nClassSelected == nIndex) + { + nClassLevel = GetLevelByClass(nClass, oAssociate); + sSpellsGained = Get2DAString("classes", "SpellGainTable", nClass); + nMaxSpellLevel = StringToInt(Get2DAString(sSpellsGained, "NumSpellLevels", nClassLevel - 1)); + for(nIndexLevel = 0; nIndexLevel <= 9; nIndexLevel++) + { + sIndexLevel = IntToString(nIndexLevel); + if(nIndexLevel < nMaxSpellLevel) + { + if(nIndexLevel == 0) sLevelImage = "ir_cantrips"; + else if(nIndexLevel < 7)sLevelImage = "ir_level" + sIndexLevel; + else sLevelImage = "ir_level789"; + if(nIndexLevel == 0) sLevel = " Cantrips"; + else if(nIndexLevel == 1) sLevel = " First level"; + else if(nIndexLevel == 2) sLevel = " Second level"; + else if(nIndexLevel == 3) sLevel = " Third level"; + else if(nIndexLevel == 4) sLevel = " Fourth level"; + else if(nIndexLevel == 5) sLevel = " Fifth level"; + else if(nIndexLevel == 6) sLevel = " Sixth level"; + else if(nIndexLevel == 7) sLevel = " Seventh level"; + else if(nIndexLevel == 8) sLevel = " Eighth level"; + else if(nIndexLevel == 9) sLevel = " Ninth level"; + NuiSetBind(oPC, nToken, "btn_level_" + sIndexLevel + "_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_level_" + sIndexLevel + "_tooltip", JsonString(" " + sLevel)); + NuiSetBind(oPC, nToken, "btn_level_" + sIndexLevel + "_image", JsonString(sLevelImage)); + } + else + { + NuiSetBind(oPC, nToken, "btn_level_" + sIndexLevel + "_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_level_" + sIndexLevel + "_image", JsonString("ctl_cg_btn_splvl")); + NuiSetBind(oPC, nToken, "btn_level_" + sIndexLevel + "_event", JsonBool(FALSE)); + } + } + NuiSetBind(oPC, nToken, "btn_level_" + IntToString(nLevelSelected) + "_encouraged", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_class_" + IntToString(nClassSelected) + "_encouraged", JsonBool(TRUE)); + } + } + } + } + // Row 3 Spells + int nSpellSlot, nSpell, nMetamagic; + json jSpell; + json jWidget = JsonArrayGet(jSpells, 2); + nClass = GetClassByPosition(nClassSelected, oAssociate); + string sSpellIcon, sSpellName, sMetaMagicText; + json jSpellArray = JsonArray(); + json jSpell_Icon = JsonArray(); + json jSpell_Text = JsonArray(); + json jMetaMagic_Text = JsonArray(); + // List the spells from the spells.2da file (they get to choose from them all!). + string sSpellTableColumn = Get2DAString("classes", "SpellTableColumn", nClass); + int nMaxSpells = Get2DARowCount("spells"); + while(nSpell < nMaxSpells) + { + sLevel = Get2DAString("spells", sSpellTableColumn, nSpell); + if(sLevel != "") + { + if(StringToInt(sLevel) == nLevelSelected) + { + jSpellArray = JsonArrayInsert(jSpellArray, JsonInt(nSpell)); + sSpellIcon = Get2DAString("spells", "IconResRef", nSpell); + sSpellName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); + jSpell_Icon = JsonArrayInsert(jSpell_Icon, JsonString(sSpellIcon)); + jSpell_Text = JsonArrayInsert(jSpell_Text, JsonString(sSpellName)); + } + } + ++nSpell; + } + jData = JsonArrayInsert(jData, jSpellArray); + NuiSetUserData(oPC, nToken, jData); + NuiSetBind(oPC, nToken, "icon_spell", jSpell_Icon); + NuiSetBind(oPC, nToken, "text_spell", jSpell_Text); + NuiSetBind(oPC, nToken, "metamagic_text", jMetaMagic_Text); + // Row 4 Spell known list label. + // Row 5 Spell known List + int nMetaMagic, nDomain, nMaxKnownSlots; + json jClassList = GetLocalJson(oAssociate, AI_CLASS_LIST_JSON); + if(JsonGetType(jClassList) == JSON_TYPE_NULL) + { + jClassList = ObjectToJson(oAssociate); + jClassList = GffGetList(jClassList, "ClassList"); + SetLocalJson(oAssociate, AI_CLASS_LIST_JSON, jClassList); + } + // Get the correct class array. + nIndex = 0; + json jClass = JsonArrayGet(jClassList, nIndex); + while(JsonGetInt(GffGetInt(jClass, "Class")) != nClass) + { + jClass = JsonArrayGet(jClassList, ++nIndex); + } + json jKnownList = GffGetList(jClass, "KnownList" + IntToString(nLevelSelected)); + string sSpellKnownTable = Get2DAString("classes", "SpellKnownTable", nClass); + if(sSpellKnownTable != "") nMaxKnownSlots = StringToInt(Get2DAString(sSpellKnownTable, "SpellLevel" + IntToString(nLevelSelected), nClassLevel - 1)); + else nMaxKnownSlots = 20; + nIndex = 0; + while(nIndex < 20) + { + sIndex = IntToString(nIndex); + NuiSetBind(oPC, nToken, "btn_known_" + sIndex + "_event", JsonBool(TRUE)); + if(nIndex < nMaxKnownSlots) + { + jSpell = JsonArrayGet(jKnownList, nIndex); + if(JsonGetType(jSpell) == JSON_TYPE_NULL) + { + NuiSetBind(oPC, nToken, "btn_known_" + sIndex + "_image", JsonString("ctl_cg_btn_splvl")); + NuiSetBind(oPC, nToken, "btn_known_" + sIndex + "_tooltip", JsonString(" Empty known spell slot")); + } + else + { + nSpell = JsonGetInt(GffGetWord(jSpell, "Spell")); + sName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); + //nMetaMagic = 255; + //nDomain = 0; + sSpellIcon = Get2DAString("spells", "IconResRef", nSpell); + NuiSetBind(oPC, nToken, "btn_known_" + sIndex + "_image", JsonString(sSpellIcon)); + NuiSetBind(oPC, nToken, "btn_known_" + sIndex + "_tooltip", JsonString(" " + sName + " (" + sClass + " / " + IntToString(nLevelSelected) + ")")); + //sMetaMagicText = ai_GetSpellIconAttributes(oAssociate, -1, -1, -1, nMetaMagic, nDomain); + //NuiSetBind(oPC, nToken, "metamagic_" + sIndex + "_text", JsonString(sMetaMagicText)); + } + } + else + { + NuiSetBind(oPC, nToken, "btn_known_" + sIndex + "_image", JsonString("ctl_cg_btn_splvl")); + //NuiSetBind(oPC, nToken, "metamagic_" + sIndex + "_text", JsonString("")); + NuiSetBind(oPC, nToken, "btn_known_" + sIndex + "_event", JsonBool(FALSE)); + } + ++nIndex; + } +} +void ai_CreateDescriptionNUI(object oPC, json jSpell, int nSpell = 0) +{ + // Row 1 ******************************************************************* 500 / 469 + json jRow = CreateImage(JsonArray(), "", "spell_icon", NUI_ASPECT_FIT, NUI_HALIGN_CENTER, NUI_VALIGN_MIDDLE, 40.0, 40.0); + jRow = CreateTextBox(jRow, "spell_text", 380.0, 400.0, FALSE, NUI_SCROLLBARS_Y); + // Add row to the column. + json jCol = JsonArrayInsert(JsonArray(), NuiRow(jRow)); + // Row 1 ******************************************************************* 500 / 522 + jRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + jRow = CreateButton(jRow, "OK", "btn_ok", 150.0f, 45.0f); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Set the Layout of the window. + json jLayout = NuiCol(jCol); + string sName, sIcon, sDescription; + int nFeat, nDescription; + int nClass; + if(nSpell) nClass = 0; + else + { + nSpell = JsonGetInt(JsonArrayGet(jSpell, 0)); + nClass = JsonGetInt(JsonArrayGet(jSpell, 1)); + } + if(nClass == -1) + { + if(nSpell == SPELL_HEALINGKIT) + { + sName = "Healer's Kit"; + sIcon = "isk_heal"; + sDescription = GetStringByStrRef(1720); + } + else + { + sName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); + sIcon = Get2DAString("spells", "IconResRef", nSpell); + nDescription = StringToInt(Get2DAString("spells", "SpellDesc", nSpell)); + if(nDescription) sDescription = GetStringByStrRef(nDescription); + else + { + object oItem = GetObjectByUUID(JsonGetString(JsonArrayGet(jSpell, 5))); + sDescription = GetDescription(oItem); + } + } + } + else + { + nFeat = JsonGetInt(JsonArrayGet(jSpell, 5)); + if(nFeat) + { + if(nSpell) + { + sName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); + sIcon = Get2DAString("spells", "IconResRef", nSpell); + } + else + { + sName = GetStringByStrRef(StringToInt(Get2DAString("feat", "FEAT", nFeat))); + sIcon = Get2DAString("feat", "ICON", nFeat); + } + sDescription = GetStringByStrRef(StringToInt(Get2DAString("feat", "DESCRIPTION", nFeat))); + } + else + { + sName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); + sIcon = Get2DAString("spells", "IconResRef", nSpell); + nDescription = StringToInt(Get2DAString("spells", "SpellDesc", nSpell)); + if(nDescription) sDescription = GetStringByStrRef(nDescription); + else + { + object oItem = GetObjectByUUID(JsonGetString(JsonArrayGet(jSpell, 5))); + sDescription = GetDescription(oItem); + } + } + } + int nToken = SetWindow(oPC, jLayout, AI_SPELL_DESCRIPTION_NUI, sName, + -1.0, -1.0, 460.0f, 537.0 + 12.0f, FALSE, FALSE, TRUE, FALSE, TRUE, "0e_nui"); + json jData = JsonArray(); + jData = JsonArrayInsert(jData, JsonString(ObjectToString(oPC))); + NuiSetUserData(oPC, nToken, jData); + // Row 1 + NuiSetBind(oPC, nToken, "spell_icon_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "spell_icon_image", JsonString(sIcon)); + NuiSetBind(oPC, nToken, "spell_text_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "spell_text", JsonString(sDescription)); + // Row 2 + NuiSetBind(oPC, nToken, "btn_ok_event", JsonBool(TRUE)); +} + diff --git a/src/module/nss/0i_menus_dm.nss b/src/module/nss/0i_menus_dm.nss new file mode 100644 index 0000000..a2a2cfc --- /dev/null +++ b/src/module/nss/0i_menus_dm.nss @@ -0,0 +1,1386 @@ +/*////////////////////////////////////////////////////////////////////////////// +// Script Name: 0i_menus_dm +//////////////////////////////////////////////////////////////////////////////// + Include script for handling NUI menus for DMs. +*/////////////////////////////////////////////////////////////////////////////// +#include "0i_nui" +#include "0i_associates" +string ai_GetRandomDMTip() +{ + int nRoll = Random(44); + return Get2DAString("ai_messages", "Text", nRoll); +} +void ai_SetDMWidgetButton(object oPlayer, int nButton, int bOn = TRUE) +{ + int nWidgetButtons = GetLocalInt(oPlayer, sDMWidgetButtonVarname); + string sName = ai_RemoveIllegalCharacters(GetName(oPlayer)); + json jButtons = ai_GetCampaignDbJson("buttons", sName, AI_DM_TABLE); + if(nWidgetButtons == 0) nWidgetButtons = JsonGetInt(JsonArrayGet(jButtons, 0)); + if(bOn) nWidgetButtons = nWidgetButtons | nButton; + else nWidgetButtons = nWidgetButtons & ~nButton; + SetLocalInt(oPlayer, sDMWidgetButtonVarname, nWidgetButtons); + jButtons = JsonArraySet(jButtons, 0, JsonInt(nWidgetButtons)); + ai_SetCampaignDbJson("buttons", jButtons, sName, AI_DM_TABLE); +} +int ai_GetDMWidgetButton(object oPlayer, int nButton) +{ + int nWidgetButtons = GetLocalInt(oPlayer, sDMWidgetButtonVarname); + if(nWidgetButtons == 0) + { + string sName = ai_RemoveIllegalCharacters(GetName(oPlayer)); + json jButtons = ai_GetCampaignDbJson("buttons", sName, AI_DM_TABLE); + nWidgetButtons = JsonGetInt(JsonArrayGet(jButtons, 0)); + } + return nWidgetButtons & nButton; +} +void ai_CreateDMWidgetNUI(object oPC) +{ + // Set window to not save until it has been created. + SetLocalInt(oPC, AI_NO_NUI_SAVE, TRUE); + DelayCommand(0.5f, DeleteLocalInt (oPC, AI_NO_NUI_SAVE)); + int bAIWidgetLock = ai_GetDMWidgetButton(oPC, BTN_DM_WIDGET_LOCK); + int bCmdGroup1 = ai_GetDMWidgetButton(oPC, BTN_DM_CMD_GROUP1); + int bCmdGroup2 = ai_GetDMWidgetButton(oPC, BTN_DM_CMD_GROUP2); + int bCmdGroup3 = ai_GetDMWidgetButton(oPC, BTN_DM_CMD_GROUP3); + int bCmdGroup4 = ai_GetDMWidgetButton(oPC, BTN_DM_CMD_GROUP4); + int bCmdGroup5 = ai_GetDMWidgetButton(oPC, BTN_DM_CMD_GROUP5); + int bCmdGroup6 = ai_GetDMWidgetButton(oPC, BTN_DM_CMD_GROUP6); + int bCmdCamera = ai_GetDMWidgetButton(oPC, BTN_DM_CMD_CAMERA); + int bCmdInventory = ai_GetDMWidgetButton(oPC, BTN_DM_CMD_INVENTORY); + // Get which buttons are activated. + float fHeight = 92.0f; + if(bAIWidgetLock) fHeight = 59.0f; + float fButtons, fWidth = 86.0f; + // ************************************************************************* Width / Height + // Row 1 (buttons)********************************************************** + // Setup the main associate button to use their portrait. + json jButton = NuiEnabled(NuiId (NuiButtonImage(NuiBind("btn_open_main_image")), "btn_open_main"), NuiBind("btn_open_main_event")); + jButton = NuiWidth(jButton, 35.0); + jButton = NuiHeight(jButton, 35.0); + jButton = NuiMargin(jButton, 0.0); + jButton = NuiTooltip(jButton, NuiBind ("btn_open_main_tooltip")); + jButton = NuiImageRegion(jButton, NuiRect(0.0, 0.0, 32.0, 35.0)); + json jRow = JsonArrayInsert(JsonArray(), jButton); + if(bCmdGroup1) + { + jRow = CreateButtonImage(jRow, "ir_level1", "btn_cmd_group1", 35.0f, 35.0f, 0.0, "btn_cmd_group1_tooltip"); + fButtons += 1.0; + } + if(bCmdGroup2) + { + jRow = CreateButtonImage(jRow, "ir_level2", "btn_cmd_group2", 35.0f, 35.0f, 0.0, "btn_cmd_group2_tooltip"); + fButtons += 1.0; + } + if(bCmdGroup3) + { + jRow = CreateButtonImage(jRow, "ir_level3", "btn_cmd_group3", 35.0f, 35.0f, 0.0, "btn_cmd_group3_tooltip"); + fButtons += 1.0; + } + if(bCmdGroup4) + { + jRow = CreateButtonImage(jRow, "ir_level4", "btn_cmd_group4", 35.0f, 35.0f, 0.0, "btn_cmd_group4_tooltip"); + fButtons += 1.0; + } + if(bCmdGroup5) + { + jRow = CreateButtonImage(jRow, "ir_level5", "btn_cmd_group5", 35.0f, 35.0f, 0.0, "btn_cmd_group5_tooltip"); + fButtons += 1.0; + } + if(bCmdGroup6) + { + jRow = CreateButtonImage(jRow, "ir_level6", "btn_cmd_group6", 35.0f, 35.0f, 0.0, "btn_cmd_group6_tooltip"); + fButtons += 1.0; + } + if(bCmdCamera) + { + jRow = CreateButtonImage(jRow, "ir_examine", "btn_camera", 35.0f, 35.0f, 0.0, "btn_camera_tooltip"); + fButtons += 1.0; + } + if(bCmdInventory) + { + jRow = CreateButtonImage(jRow, "ir_pickup", "btn_inventory", 35.0f, 35.0f, 0.0, "btn_inventory_tooltip"); + fButtons += 1.0; + } + // Plug in buttons ********************************************************* + int nIndex, bWidget; + string sButton, sIcon; + json jPlugins = ai_UpdatePluginsForDM(oPC); + json jPlugin = JsonArrayGet(jPlugins, nIndex); + while(JsonGetType(jPlugin) != JSON_TYPE_NULL) + { + bWidget = JsonGetInt(JsonArrayGet(jPlugin, 1)); + if(bWidget) + { + sIcon = JsonGetString(JsonArrayGet(jPlugin, 3)); + sButton = IntToString(nIndex); + jRow = CreateButtonImage(jRow, sIcon, "btn_exe_plugin_" + sButton, 35.0f, 35.0f, 0.0, "btn_exe_plugin_" + sButton + "_tooltip"); + fButtons += 1.0; + } + jPlugin = JsonArrayGet(jPlugins, ++nIndex); + } + if(fButtons > 1.0f) fWidth = fWidth + ((fButtons - 1.0) * 39.0f); + // Add the row to the column. + json jCol = JsonArrayInsert(JsonArray(), NuiRow(jRow)); + // Get the window location to restore it from the database. + string sName = ai_RemoveIllegalCharacters(GetName(oPC)); + json jLocations = ai_GetCampaignDbJson("locations", sName, AI_DM_TABLE); + jLocations = JsonObjectGet(jLocations, "dm" + AI_WIDGET_NUI); + float fX = JsonGetFloat(JsonObjectGet(jLocations, "x")); + float fY = JsonGetFloat(JsonObjectGet(jLocations, "y")); + if(bAIWidgetLock) + { + fX = fX + 4.0f; + fY = fY + 37.0f; + } + // Set the layout of the window. + json jLayout = NuiCol(jCol); + int nToken; + string sHeal, sText, sRange; + string sDisplayName = GetName(oPC); + if(GetStringRight(sDisplayName, 1) == "s") sDisplayName = sDisplayName + "'"; + else sDisplayName = sDisplayName + "'s"; + if(bAIWidgetLock) nToken = SetWindow(oPC, jLayout, "dm" + AI_WIDGET_NUI, sDisplayName + " Widget", fX, fY, fWidth + 8.0f, fHeight, FALSE, FALSE, FALSE, TRUE, FALSE, "0e_nui_dm"); + else nToken = SetWindow(oPC, jLayout, "dm" + AI_WIDGET_NUI, sDisplayName + " Widget", fX, fY, fWidth + 12.0f, fHeight, FALSE, FALSE, FALSE, TRUE, TRUE, "0e_nui_dm"); + // Set event watches for window inspector and save window location. + NuiSetBindWatch(oPC, nToken, "window_geometry", TRUE); + // Set the buttons to show events. + NuiSetBind(oPC, nToken, "btn_open_main_image", JsonString(GetPortraitResRef(oPC) + "s")); + NuiSetBind(oPC, nToken, "btn_open_main_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_open_main_tooltip", JsonString(" " + sDisplayName + " widget menu")); + string sUUID, sText2, sSpeed; + string sAction = " (Left Action/Right Add)"; + if(bCmdGroup1) + { + NuiSetBind(oPC, nToken, "btn_cmd_group1_event", JsonBool(TRUE)); + json jGroup = GetLocalJson(oPC, "DM_GROUP1"); + if(JsonGetInt(JsonArrayGet(jGroup, 0)) == 0) sSpeed = " [Walk]"; + else sSpeed = " [Run]"; + string sUUID = JsonGetString(JsonArrayGet(jGroup, 1)); + if(sUUID == "") { sText = "Group 1"; sText2 = sAction; } + else { sText = GetName(GetObjectByUUID(sUUID)) + "'s group"; sText2 = sSpeed; } + NuiSetBind(oPC, nToken, "btn_cmd_group1_tooltip", JsonString(" " + sText + sText2)); + } + if(bCmdGroup2) + { + NuiSetBind(oPC, nToken, "btn_cmd_group2_event", JsonBool(TRUE)); + json jGroup = GetLocalJson(oPC, "DM_GROUP2"); + if(JsonGetInt(JsonArrayGet(jGroup, 0)) == 0) sSpeed = " [Walk]"; + else sSpeed = " [Run]"; + string sUUID = JsonGetString(JsonArrayGet(jGroup, 1)); + if(sUUID == "") { sText = "Group 2"; sText2 = sAction; } + else { sText = GetName(GetObjectByUUID(sUUID)) + "'s group"; sText2 = sSpeed; } + NuiSetBind(oPC, nToken, "btn_cmd_group2_tooltip", JsonString(" " + sText + sText2)); + } + if(bCmdGroup3) + { + NuiSetBind(oPC, nToken, "btn_cmd_group3_event", JsonBool(TRUE)); + json jGroup = GetLocalJson(oPC, "DM_GROUP3"); + if(JsonGetInt(JsonArrayGet(jGroup, 0)) == 0) sSpeed = " [Walk]"; + else sSpeed = " [Run]"; + string sUUID = JsonGetString(JsonArrayGet(jGroup, 1)); + if(sUUID == "") { sText = "Group 3"; sText2 = sAction; } + else { sText = GetName(GetObjectByUUID(sUUID)) + "'s group"; sText2 = sSpeed; } + NuiSetBind(oPC, nToken, "btn_cmd_group3_tooltip", JsonString(" " + sText + sText2)); + } + if(bCmdGroup4) + { + NuiSetBind(oPC, nToken, "btn_cmd_group4_event", JsonBool(TRUE)); + json jGroup = GetLocalJson(oPC, "DM_GROUP4"); + if(JsonGetInt(JsonArrayGet(jGroup, 0)) == 0) sSpeed = " [Walk]"; + else sSpeed = " [Run]"; + string sUUID = JsonGetString(JsonArrayGet(jGroup, 1)); + if(sUUID == "") { sText = "Group 4"; sText2 = sAction; } + else { sText = GetName(GetObjectByUUID(sUUID)) + "'s group"; sText2 = sSpeed; } + NuiSetBind(oPC, nToken, "btn_cmd_group4_tooltip", JsonString(" " + sText + sText2)); + } + if(bCmdGroup5) + { + NuiSetBind(oPC, nToken, "btn_cmd_group5_event", JsonBool(TRUE)); + json jGroup = GetLocalJson(oPC, "DM_GROUP5"); + if(JsonGetInt(JsonArrayGet(jGroup, 0)) == 0) sSpeed = " [Walk]"; + else sSpeed = " [Run]"; + string sUUID = JsonGetString(JsonArrayGet(jGroup, 1)); + if(sUUID == "") { sText = "Group 5"; sText2 = sAction; } + else { sText = GetName(GetObjectByUUID(sUUID)) + "'s group"; sText2 = sSpeed; } + NuiSetBind(oPC, nToken, "btn_cmd_group5_tooltip", JsonString(" " + sText + sText2)); + } + if(bCmdGroup6) + { + NuiSetBind(oPC, nToken, "btn_cmd_group6_event", JsonBool(TRUE)); + json jGroup = GetLocalJson(oPC, "DM_GROUP6"); + if(JsonGetInt(JsonArrayGet(jGroup, 0)) == 0) sSpeed = " [Walk]"; + else sSpeed = " [Run]"; + string sUUID = JsonGetString(JsonArrayGet(jGroup, 1)); + if(sUUID == "") { sText = "Group 6"; sText2 = sAction; } + else { sText = GetName(GetObjectByUUID(sUUID)) + "'s group"; sText2 = sSpeed; } + NuiSetBind(oPC, nToken, "btn_cmd_group6_tooltip", JsonString(" " + sText + sText2)); + } + if(bCmdCamera) + { + NuiSetBind(oPC, nToken, "btn_camera_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_camera_tooltip", JsonString(" Select new object to have the camera view.")); + } + if(bCmdInventory) + { + NuiSetBind(oPC, nToken, "btn_inventory_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_inventory_tooltip", JsonString(" Open selected creatures inventory.")); + } + /*if(bSearch) + { + NuiSetBind(oPC, nToken, "btn_search_event", JsonBool(TRUE)); + if(ai_GetAIMode(oAssociate, AI_MODE_AGGRESSIVE_SEARCH)) sText = " Search On"; + else sText = " Search Off"; + NuiSetBind(oPC, nToken, "btn_search_tooltip", JsonString(sText)); + } + if(bStealth) + { + NuiSetBind(oPC, nToken, "btn_stealth_event", JsonBool(TRUE)); + if(ai_GetAIMode(oAssociate, AI_MODE_AGGRESSIVE_STEALTH)) sText = " Stealth On"; + else sText = " Stealth Off"; + NuiSetBind(oPC, nToken, "btn_stealth_tooltip", JsonString(sText)); + } */ + nIndex = 0; + string sScript; + jPlugin = JsonArrayGet(jPlugins, nIndex); + while(JsonGetType(jPlugin) != JSON_TYPE_NULL) + { + bWidget = JsonGetInt(JsonArrayGet(jPlugin, 1)); + if(bWidget) + { + sButton = IntToString(nIndex); + sScript = JsonGetString(JsonArrayGet(jPlugin, 0)); + if(ResManGetAliasFor(sScript, RESTYPE_NCS) == "") + { + sText = " " + sScript + " not found by ResMan!"; + } + else sName = " " + JsonGetString(JsonArrayGet(jPlugin, 2)); + NuiSetBind(oPC, nToken, "btn_exe_plugin_" + sButton + "_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "btn_exe_plugin_" + sButton + "_tooltip", JsonString(sName)); + } + jPlugin = JsonArrayGet(jPlugins, ++nIndex); + } +} +void ai_CreateDMOptionsNUI(object oPC) +{ + // Set window to not save until it has been created. + SetLocalInt (oPC, AI_NO_NUI_SAVE, TRUE); + DelayCommand (2.0, DeleteLocalInt (oPC, AI_NO_NUI_SAVE)); + int nMonsterAI = (ResManGetAliasFor("ai_default", RESTYPE_NCS) != ""); + int nAssociateAI = (ResManGetAliasFor("ai_a_default", RESTYPE_NCS) != ""); + string sText = " [Single player]"; + if(AI_SERVER) sText = " [Server]"; + // ************************************************************************* Width / Height + // Row 1 ******************************************************************* 500 / 73 + json jRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + jRow = CreateLabel(jRow, PHILOS_VERSION + sText, "lbl_version ", 510.0f, 20.0f, NUI_HALIGN_CENTER); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + // Add row to the column. + json jCol = JsonArrayInsert(JsonArray(), NuiRow(jRow)); + // Row 2 ******************************************************************* 500 / 101 + jRow = CreateLabel(JsonArray(), "", "lbl_ai_info", 510.0f, 20.0f, NUI_HALIGN_CENTER); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 3 ******************************************************************* 500 / 129 + jRow = CreateButton(JsonArray(), "Plugin Manager", "btn_plugin_manager", 160.0f, 20.0f, -1.0, "btn_plugin_manager_tooltip"); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateButton(jRow, "Widget Manager", "btn_widget_manager", 160.0f, 20.0f, -1.0, "btn_widget_manager_tooltip"); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 4 ******************************************************************* 500 / 157 + jRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + jRow = CreateLabel(jRow, "SERVER RULES", "lbl_ai_rules", 100.0f, 20.0f, NUI_HALIGN_CENTER); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + float fHeight = 112.0; + // Row 5 ******************************************************************* 500 / --- (28) + // Make the AI options a Group. + json jGroupRow = CreateTextEditBox(JsonArray(), "sPlaceHolder", "txt_max_henchman", 2, FALSE, 30.0f, 20.0f, "txt_max_henchman_tooltip"); + jGroupRow = CreateLabel(jGroupRow, "Max number of henchmen that is allowed in your party.", "lbl_max_hench", 416.0f, 20.0f, NUI_HALIGN_LEFT, 0, -1.0, "txt_max_henchman_tooltip"); + json jGroupCol = JsonArrayInsert(JsonArray(), NuiRow(jGroupRow)); + jGroupRow = CreateTextEditBox(JsonArray(), "sPlaceHolder", "txt_xp_scale", 3, FALSE, 40.0f, 20.0f, "txt_xp_scale_tooltip"); + jGroupRow = CreateLabel(jGroupRow, "Modules experience scale.", "lbl_xp_scale", 175.0f, 20.0f, NUI_HALIGN_LEFT, 0, -1.0, "txt_xp_scale_tooltip"); + jGroupRow = CreateCheckBox(jGroupRow, " scale to party.", "chbx_party_scale", 130.0, 20.0, "chbx_party_scale_tooltip"); + jGroupRow = CreateButton(jGroupRow, "Default", "btn_default_xp", 70.0f, 20.0f, -1.0, "btn_default_xp_tooltip"); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + fHeight += 112.0; + if(nMonsterAI || nAssociateAI) + { + jGroupRow = CreateCheckBox(JsonArray(), " Creatures will use advanced combat movement.", "chbx_advanced_movement", 450.0, 20.0); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupRow = CreateCheckBox(JsonArray(), " Use item level restrictions for creatures [Default is off].", "chbx_ilr", 450.0, 20.0); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupRow = CreateCheckBox(JsonArray(), " Creatures can use the skill Use Magic Device.", "chbx_umd", 450.0, 20.0); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupRow = CreateCheckBox(JsonArray(), " Creatures can use Healing kits.", "chbx_use_healingkits", 450.0, 20.0); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupRow = CreateCheckBox(JsonArray(), " Moral checks, wounded creatures may flee during combat.", "chbx_moral", 450.0, 20.0); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupRow = CreateLabel(JsonArray(), " Spells the AI will not use:", "lbl_restrict_spells", 190.0, 20.0, NUI_HALIGN_LEFT); + jGroupRow = CreateCheckBox(jGroupRow, " Darkness", "chbx_darkness", 90.0, 20.0, "chbx_darkness_tooltip"); + jGroupRow = CreateCheckBox(jGroupRow, " Dispels", "chbx_dispels", 90.0, 20.0, "chbx_dispels_tooltip"); + jGroupRow = CreateCheckBox(jGroupRow, " Time Stop", "chbx_timestop", 90.0, 20.0, "chbx_timestop_tooltip"); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + fHeight += 168.0; + } + if(nMonsterAI) + { + jGroupRow = CreateTextEditBox(JsonArray(), "sPlaceHolder", "txt_ai_difficulty", 3, FALSE, 40.0f, 20.0f, "txt_ai_difficulty_tooltip"); + jGroupRow = CreateLabel(jGroupRow, "% chance monsters will attack the weakest target.", "lbl_ai_difficulty", 406.0f, 20.0f, NUI_HALIGN_LEFT, 0, -1.0, "txt_ai_difficulty_tooltip"); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupRow = CreateTextEditBox(JsonArray(), "sPlaceHolder", "txt_perception_distance", 2, FALSE, 35.0f, 20.0f, "txt_perception_distance_tooltip"); + jGroupRow = CreateLabel(jGroupRow, "meters is the distance a monster can respond to allies.", "lbl_perception_distance", 411.0f, 20.0f, NUI_HALIGN_LEFT, 0, 0.0, "txt_perception_distance_tooltip"); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupRow = CreateCheckBox(JsonArray(), " Monsters can prebuff before combat starts.", "chbx_buff_monsters", 450.0, 20.0); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupRow = CreateCheckBox(JsonArray(), " Monsters can use summons before combat starts.", "chbx_buff_summons", 450.0, 20.0); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupRow = CreateCheckBox(JsonArray(), " Monsters can use tactics (ambush, defensive, flanker, etc).", "chbx_ambush_monsters", 450.0, 20.0); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupRow = CreateLabel(JsonArray(), "Add ", "lbl_inc_enc", 30.0, 20.0, NUI_HALIGN_LEFT, 0, -1.0); + jGroupRow = CreateTextEditBox(jGroupRow, "sPlaceHolder", "txt_inc_enc", 4, FALSE, 55.0f, 20.0f, "txt_inc_enc_tooltip"); + jGroupRow = CreateLabel(jGroupRow, "monsters per spawned encounter monster.", "lbl_inc_enc", 357.0, 20.0, NUI_HALIGN_LEFT, NUI_VALIGN_MIDDLE, 0.0, "txt_inc_enc_tooltip"); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupRow = CreateTextEditBox(JsonArray(), "sPlaceHolder", "txt_inc_hp", 3, FALSE, 40.0f, 20.0f, "txt_inc_hp_tooltip"); + jGroupRow = CreateLabel(jGroupRow, "% increase in all monster's hitpoints.", "lbl_inc_hp", 406.0, 20.0, NUI_HALIGN_LEFT); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupRow = CreateLabel(JsonArray(), "***** WARNING! The options below may break the module! *****", "lbl_warning", 450.0f, 20.0f, NUI_HALIGN_LEFT, 0, 0.0, "chbx_warning_tooltip"); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupRow = CreateCheckBox(JsonArray(), " Monsters can wander upto ", "chbx_wander", 220.0, 20.0, "chbx_warning_tooltip"); + jGroupRow = CreateTextEditBox(jGroupRow, "sPlaceHolder", "txt_wander_distance", 2, FALSE, 35.0f, 20.0f, "chbx_warning_tooltip"); + jGroupRow = CreateLabel(jGroupRow, "meters and ", "lbl_wander_distance", 80.0f, 20.0f, NUI_HALIGN_LEFT, NUI_VALIGN_MIDDLE, 0.0, "chbx_warning_tooltip"); + jGroupRow = CreateCheckBox(jGroupRow, "open doors.", "chbx_open_doors", 100.0, 20.0, "chbx_warning_tooltip"); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupRow = CreateCheckBox(JsonArray(), " Monsters can summon companions.", "chbx_companions", 450.0, 20.0, "chbx_warning_tooltip"); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupRow = CreateCheckBox(JsonArray(), " Summoned associates to remain after masters death.", "chbx_perm_assoc", 450.0, 20.0, "chbx_warning_tooltip"); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupRow = CreateCheckBox(JsonArray(), " Make enemy corpses remain.", "chbx_corpses_stay", 450.0, 20.0, "chbx_warning_tooltip"); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupRow = CreateLabel(JsonArray(), "", "lbl_perc_dist", 450.0f, 20.0f, NUI_HALIGN_LEFT, 0, 0.0, "lbl_perc_dist_tooltip"); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + fHeight += 364.0; + } + jRow = JsonArrayInsert(JsonArray(), NuiGroup(NuiCol(jGroupCol))); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Get the window location to restore it from the database. + string sName = ai_RemoveIllegalCharacters(GetName(oPC)); + json jLocations = ai_GetCampaignDbJson("locations", sName, AI_DM_TABLE); + jLocations = JsonObjectGet(jLocations, "dm" + AI_MAIN_NUI); + float fX = JsonGetFloat(JsonObjectGet(jLocations, "x")); + float fY = JsonGetFloat(JsonObjectGet(jLocations, "y")); + // Set the Layout of the window. + json jLayout = NuiCol(jCol); + sName = GetName(oPC); + if(GetStringRight(sName, 1) == "s") sName = sName + "'"; + else sName = sName + "'s"; + int nToken = SetWindow(oPC, jLayout, "dm" + AI_MAIN_NUI, sName + " PEPS Main Menu", + fX, fY, 534.0f, fHeight, FALSE, FALSE, TRUE, FALSE, TRUE, "0e_nui_dm"); + // Save the associate to the nui for use in 0e_nui + json jData = JsonArrayInsert(JsonArray(), JsonString(ObjectToString(oPC))); + NuiSetUserData(oPC, nToken, jData); + object oModule = GetModule(); + // Set event watches for save window location. + NuiSetBindWatch(oPC, nToken, "window_geometry", TRUE); + // Set all binds, events, and watches. + // Row 1 - Version label. + // Row 2 + int nUsing; + // Check the monster AI. + string sLocation = ResManGetAliasFor("ai_default", RESTYPE_NCS); + if(sLocation != "") + { + nUsing = TRUE; + string sLocation = ResManGetAliasFor("nw_c2_default1", RESTYPE_NCS); + if(sLocation != "OVERRIDE:" && sLocation != "PATCH:peps" && sLocation != "DEVELOPMENT:") nUsing = FALSE; + if(nUsing) sText = "Monster AI working"; + else sText = "Monster AI not working"; + } + else sText = "Monster AI not loaded"; + // Check the associate AI. + sLocation = ResManGetAliasFor("ai_a_default", RESTYPE_NCS); + if(sLocation != "") + { + nUsing = TRUE; + string sLocation = ResManGetAliasFor("nw_ch_ac1", RESTYPE_NCS); + if(sLocation != "OVERRIDE:" && sLocation != "PATCH:peps" && sLocation != "DEVELOPMENT:") nUsing = FALSE; + if(nUsing) sText += ", Associate AI working"; + else sText += ", Associate AI not working"; + } + else sText += ", Associate AI not loaded"; + // Check for PRC. + sLocation = ResManGetAliasFor("prc_ai_fam_percp", RESTYPE_NCS); + if(sLocation != "") sText += ", PRC loaded."; + else + { + // Check the player AI. + sLocation = ResManGetAliasFor("xx_pc_1_hb", RESTYPE_NCS); + if(sLocation != "") sText += ", Player AI loaded."; + else sText += ", Player AI not loaded."; + } + NuiSetBind(oPC, nToken, "lbl_ai_info_label", JsonString(sText)); + // Row 3 + NuiSetBind(oPC, nToken, "btn_plugin_manager_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_plugin_manager_tooltip", JsonString(" Manages external executable scripts.")); + NuiSetBind(oPC, nToken, "btn_widget_manager_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_widget_manager_tooltip", JsonString(" Manages widgets the players have access to.")); + // Row 3 Label for AI RULES + // Row 4 + NuiSetBind(oPC, nToken, "txt_max_henchman_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "txt_max_henchman", JsonString(IntToString(GetLocalInt(oModule, AI_RULE_MAX_HENCHMAN)))); + NuiSetBindWatch (oPC, nToken, "txt_max_henchman", TRUE); + NuiSetBind(oPC, nToken, "txt_max_henchman_tooltip", JsonString(" Set max number of henchman allowed (1-12).")); + NuiSetBind(oPC, nToken, "txt_xp_scale_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "txt_xp_scale", JsonString(IntToString(GetModuleXPScale()))); + NuiSetBindWatch (oPC, nToken, "txt_xp_scale", TRUE); + NuiSetBind(oPC, nToken, "txt_xp_scale_tooltip", JsonString(" Set the modules XP scale (0 - 200) Normal D&D is 10.")); + NuiSetBind(oPC, nToken, "chbx_party_scale_check", JsonBool(GetLocalInt(oModule, AI_RULE_PARTY_SCALE))); + NuiSetBindWatch(oPC, nToken, "chbx_party_scale_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_party_scale_event", JsonBool(TRUE)); + sText = IntToString(GetLocalInt(oModule, AI_BASE_PARTY_SCALE_XP)); + NuiSetBind(oPC, nToken, "chbx_party_scale_tooltip", JsonString(" PEPS adjusts your XP based on party size from (" + sText + ").")); + NuiSetBind(oPC, nToken, "btn_default_xp_event", JsonBool(TRUE)); + sText = IntToString(GetLocalInt(oModule, AI_RULE_DEFAULT_XP_SCALE)); + NuiSetBind(oPC, nToken, "btn_default_xp_tooltip", JsonString(" Reset the Modules XP to (" + sText + ").")); + if(nMonsterAI) + { + NuiSetBind(oPC, nToken, "txt_ai_difficulty_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "txt_ai_difficulty", JsonString(IntToString(GetLocalInt(oModule, AI_RULE_AI_DIFFICULTY)))); + NuiSetBindWatch(oPC, nToken, "txt_ai_difficulty", TRUE); + NuiSetBind(oPC, nToken, "chbx_buff_monsters_check", JsonBool(GetLocalInt(oModule, AI_RULE_BUFF_MONSTERS))); + NuiSetBindWatch(oPC, nToken, "chbx_buff_monsters_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_buff_monsters_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "chbx_buff_summons_check", JsonBool(GetLocalInt(oModule, AI_RULE_PRESUMMON))); + NuiSetBindWatch(oPC, nToken, "chbx_buff_summons_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_buff_summons_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "chbx_ambush_monsters_check", JsonBool(GetLocalInt(oModule, AI_RULE_AMBUSH))); + NuiSetBindWatch(oPC, nToken, "chbx_ambush_monsters_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_ambush_monsters_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "chbx_companions_check", JsonBool(GetLocalInt(oModule, AI_RULE_SUMMON_COMPANIONS))); + NuiSetBindWatch(oPC, nToken, "chbx_companions_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_companions_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "chbx_companions_tooltip", JsonString(" ** This will break some modules! ** See Readme for issues!")); + NuiSetBind(oPC, nToken, "chbx_perm_assoc_check", JsonBool(GetLocalInt(oModule, AI_RULE_PERM_ASSOC))); + NuiSetBindWatch(oPC, nToken, "chbx_perm_assoc_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_perm_assoc_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "chbx_corpses_stay_check", JsonBool(GetLocalInt(oModule, AI_RULE_CORPSES_STAY))); + NuiSetBindWatch(oPC, nToken, "chbx_corpses_stay_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_corpses_stay_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "chbx_corpses_stay_tooltip", JsonString(" ** This will break some modules! ** See Readme for issues!")); + NuiSetBind(oPC, nToken, "txt_perception_distance_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "txt_perception_distance", JsonString(FloatToString(GetLocalFloat(oModule, AI_RULE_PERCEPTION_DISTANCE), 0, 0))); + NuiSetBindWatch(oPC, nToken, "txt_perception_distance", TRUE); + NuiSetBind(oPC, nToken, "txt_perception_distance_tooltip", JsonString(" Range [10 to 60 meters] from the player.")); + NuiSetBindWatch(oPC, nToken, "lbl_perc_dist", TRUE); + int nPercDist = GetLocalInt(oModule, AI_RULE_MON_PERC_DISTANCE); + if(nPercDist < 8 || nPercDist > 11) + { + nPercDist = 11; + SetLocalInt(oModule, AI_RULE_MON_PERC_DISTANCE, 11); + } + if(nPercDist == 8) sText = " Monster perception: Short [10 Sight / 10 Listen]"; + else if(nPercDist == 9) sText = " Monster perception: Medium [20 Sight / 20 Listen]"; + else if(nPercDist == 10) sText = " Monster perception: Long [35 Sight / 20 Listen]"; + else sText = " Monster perception: Default [Monster's default values]"; + NuiSetBind(oPC, nToken, "lbl_perc_dist_label", JsonString(sText)); + NuiSetBind(oPC, nToken, "lbl_perc_dist_tooltip", JsonString(" Use the mouse wheel to change values.")); + int bWander = GetLocalInt(oModule, AI_RULE_WANDER); + NuiSetBind(oPC, nToken, "chbx_wander_check", JsonBool(bWander)); + NuiSetBindWatch(oPC, nToken, "chbx_wander_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_wander_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "txt_wander_distance_event", JsonBool(bWander)); + NuiSetBind(oPC, nToken, "txt_wander_distance", JsonString(FloatToString(GetLocalFloat(oModule, AI_RULE_WANDER_DISTANCE), 0, 0))); + NuiSetBindWatch(oPC, nToken, "txt_wander_distance", TRUE); + NuiSetBind(oPC, nToken, "chbx_wander_tooltip", JsonString(" ** This will break some modules! ** See Readme for issues!")); + NuiSetBind(oPC, nToken, "chbx_open_doors_check", JsonBool(GetLocalInt(oModule, AI_RULE_OPEN_DOORS))); + NuiSetBindWatch(oPC, nToken, "chbx_open_doors_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_open_doors_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "chbx_open_doors_tooltip", JsonString(" This allows monsters to open doors to hunt you down!")); + NuiSetBind(oPC, nToken, "txt_inc_enc_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "txt_inc_enc_tooltip", JsonString(" Spawns one extra monster per counter above 1. Adds value to counter per encounter monster spawned.")); + NuiSetBind(oPC, nToken, "txt_inc_enc", JsonString(FloatToString(GetLocalFloat(oModule, AI_INCREASE_ENC_MONSTERS), 0, 2))); + NuiSetBindWatch(oPC, nToken, "txt_inc_enc", TRUE); + NuiSetBind(oPC, nToken, "txt_inc_hp_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "txt_inc_hp", JsonString(IntToString(GetLocalInt(oModule, AI_INCREASE_MONSTERS_HP)))); + NuiSetBindWatch(oPC, nToken, "txt_inc_hp", TRUE); + } + if(nMonsterAI || nAssociateAI) + { + NuiSetBind(oPC, nToken, "chbx_moral_check", JsonBool(GetLocalInt(oModule, AI_RULE_MORAL_CHECKS))); + NuiSetBindWatch (oPC, nToken, "chbx_moral_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_moral_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "chbx_advanced_movement_check", JsonBool(GetLocalInt(oModule, AI_RULE_ADVANCED_MOVEMENT))); + NuiSetBindWatch (oPC, nToken, "chbx_advanced_movement_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_advanced_movement_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "chbx_ilr_check", JsonBool(GetLocalInt(oModule, AI_RULE_ILR))); + NuiSetBindWatch (oPC, nToken, "chbx_ilr_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_ilr_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "chbx_umd_check", JsonBool(GetLocalInt(oModule, AI_RULE_ALLOW_UMD))); + NuiSetBindWatch (oPC, nToken, "chbx_umd_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_umd_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "chbx_use_healingkits_check", JsonBool(GetLocalInt(oModule, AI_RULE_HEALERSKITS))); + NuiSetBindWatch (oPC, nToken, "chbx_use_healingkits_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_use_healingkits_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "chbx_darkness_check", JsonBool(ai_SpellRestricted(SPELL_DARKNESS))); + NuiSetBindWatch (oPC, nToken, "chbx_darkness_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_darkness_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "chbx_darkness_tooltip", JsonString(" AI will not use the Darkness spell in combat.")); + NuiSetBind(oPC, nToken, "chbx_dispels_check", JsonBool(ai_SpellRestricted(SPELL_DISPEL_MAGIC))); + NuiSetBindWatch (oPC, nToken, "chbx_dispels_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_dispels_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "chbx_dispels_tooltip", JsonString(" AI will not use any of the Dispel spells in combat.")); + NuiSetBind(oPC, nToken, "chbx_timestop_check", JsonBool(ai_SpellRestricted(SPELL_TIME_STOP))); + NuiSetBindWatch (oPC, nToken, "chbx_timestop_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_timestop_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "chbx_timestop_tooltip", JsonString(" AI will not use the Time Stop spell in combat.")); + } +} +void ai_CreateDMCommandNUI(object oPC) +{ + SetLocalInt(oPC, AI_NO_NUI_SAVE, TRUE); + DelayCommand(0.5f, DeleteLocalInt (oPC, AI_NO_NUI_SAVE)); + // ************************************************************************* Width / Height + // Row 1 ******************************************************************* 500 / 73 + json jRow = CreateButtonSelect(JsonArray(), "Lock Widget", "btn_widget_lock", 200.0, 20.0, "btn_widget_lock_tooltip"); + jRow = CreateLabel(jRow, "", "blank_label_1", 25.0, 20.0); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateButton(jRow, "Main Menu", "btn_main_menu", 200.0, 20.0, -1.0, "btn_main_menu_tooltip"); + jRow = CreateLabel(jRow, "", "blank_label_2", 25.0, 20.0); + json jCol = JsonArrayInsert(JsonArray(), NuiRow(jRow)); + // Row 2 ******************************************************************* 500 / 101 + jRow = CreateButton(JsonArray(), "", "btn_cmd_group1", 200.0, 20.0, -1.0, "btn_cmd_group1_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_cmd_group1", 25.0, 20.0); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateButton(jRow, "", "btn_cmd_group2", 200.0, 20.0, -1.0, "btn_cmd_group2_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_cmd_group2", 25.0, 20.0); + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 3 ******************************************************************* 500 / 129 + jRow = CreateButton(JsonArray(), "", "btn_cmd_group3", 200.0, 20.0, -1.0, "btn_cmd_group3_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_cmd_group3", 25.0, 20.0); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateButton(jRow, "", "btn_cmd_group4", 200.0, 20.0, -1.0, "btn_cmd_group4_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_cmd_group4", 25.0, 20.0); + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 4 ******************************************************************* 500 / 157 + jRow = CreateButton(JsonArray(), "", "btn_cmd_group5", 200.0, 20.0, -1.0, "btn_cmd_group5_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_cmd_group5", 25.0, 20.0); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateButton(jRow, "", "btn_cmd_group6", 200.0, 20.0, -1.0, "btn_cmd_group6_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_cmd_group6", 25.0, 20.0); + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + float fHeight = 157.0; + // Row 5 ******************************************************************* 500 / --- + jRow = CreateButton(JsonArray(), "Toggle Camera Focus", "btn_camera", 200.0, 20.0, -1.0, "btn_camera_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_camera", 25.0, 20.0); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateButton(jRow, "Open/Close Inventory", "btn_inventory", 200.0, 20.0, -1.0, "btn_inventory_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_inventory", 25.0, 20.0); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight = fHeight + 28.0; + // Row 6+ ****************************************************************** 500 / --- + json jDMPlugins = ai_UpdatePluginsForDM(oPC); + // Set the plugins the dm can use. + int nIndex; + string sButton, sName; + json jPlugin = JsonArrayGet(jDMPlugins, nIndex); + while(JsonGetType(jPlugin) != JSON_TYPE_NULL) + { + sButton = IntToString(nIndex); + sName = JsonGetString(JsonArrayGet(jPlugin, 2)); + jRow = CreateButton(JsonArray(), sName, "btn_plugin_" + sButton, 200.0f, 20.0f, -1.0, "btn_plugin_" + sButton + "_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_plugin_" + sButton, 25.0, 20.0, "chbx_plugin_tooltip"); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jPlugin = JsonArrayGet(jDMPlugins, ++nIndex); + if(JsonGetType(jPlugin) != JSON_TYPE_NULL) + { + sButton = IntToString(nIndex); + sName = JsonGetString(JsonArrayGet(jPlugin, 2)); + jRow = CreateButton(jRow, sName, "btn_plugin_" + sButton, 200.0f, 20.0f, -1.0, "btn_plugin_" + sButton + "_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_plugin_" + sButton, 25.0, 20.0, "chbx_plugin_tooltip"); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight += 28.0; + } + else + { + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight += 28.0; + break; + } + jPlugin = JsonArrayGet(jDMPlugins, ++nIndex); + } + // Row 7 ****************************************************************** 500 / --- + jRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + jRow = CreateLabel(jRow, "", "lbl_info_1", 475.0, 20.0, NUI_HALIGN_CENTER); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight = fHeight + 28.0; + // Get the window location to restore it from the database. + sName = ai_RemoveIllegalCharacters(GetName(oPC)); + json jLocations = ai_GetCampaignDbJson("locations", sName, AI_DM_TABLE); + jLocations = JsonObjectGet(jLocations, "dm" + AI_COMMAND_NUI); + float fX = JsonGetFloat(JsonObjectGet(jLocations, "x")); + float fY = JsonGetFloat(JsonObjectGet(jLocations, "y")); + // Set the Layout of the window. + json jLayout = NuiCol(jCol); + string sDMName = GetName(oPC); + if(GetStringRight(sDMName, 1) == "s") sDMName = sDMName + "'"; + else sDMName = sDMName + "'s"; + int nToken = SetWindow(oPC, jLayout, "dm" + AI_COMMAND_NUI, sDMName + " Command Menu", + fX, fY, 500.0, fHeight + 12.0, FALSE, FALSE, TRUE, FALSE, TRUE, "0e_nui_dm"); + // Get which buttons are activated. + int bAIWidgetLock = ai_GetDMWidgetButton(oPC, BTN_DM_WIDGET_LOCK); + int bCmdGroup1 = ai_GetDMWidgetButton(oPC, BTN_DM_CMD_GROUP1); + int bCmdGroup2 = ai_GetDMWidgetButton(oPC, BTN_DM_CMD_GROUP2); + int bCmdGroup3 = ai_GetDMWidgetButton(oPC, BTN_DM_CMD_GROUP3); + int bCmdGroup4 = ai_GetDMWidgetButton(oPC, BTN_DM_CMD_GROUP4); + int bCmdGroup5 = ai_GetDMWidgetButton(oPC, BTN_DM_CMD_GROUP5); + int bCmdGroup6 = ai_GetDMWidgetButton(oPC, BTN_DM_CMD_GROUP6); + int bCmdCamera = ai_GetDMWidgetButton(oPC, BTN_DM_CMD_CAMERA); + int bCmdInventory = ai_GetDMWidgetButton(oPC, BTN_DM_CMD_INVENTORY); + // Set event watches for save window location. + NuiSetBindWatch(oPC, nToken, "window_geometry", TRUE); + // Set all binds, events, and watches. + // Row 1 + NuiSetBind(oPC, nToken, "btn_widget_lock_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_widget_lock", JsonBool(bAIWidgetLock)); + NuiSetBind(oPC, nToken, "btn_widget_lock_tooltip", JsonString( + " Locks widget to the current location.")); + NuiSetBind(oPC, nToken, "btn_main_menu_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "btn_main_menu", JsonInt(TRUE)); + NuiSetBind(oPC, nToken, "btn_main_menu_tooltip", JsonString(" Server menu options")); + NuiSetBind(oPC, nToken, "btn_group_options_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "btn_group_options", JsonInt(TRUE)); + //NuiSetBind(oPC, nToken, "btn_empty_button_event", JsonBool (TRUE)); + //NuiSetBind(oPC, nToken, "btn_empty_button", JsonInt(TRUE)); + //sText = " Copy AI and command settings for one creature to others."; + //NuiSetBind(oPC, nToken, "btn_empty_button_tooltip", JsonString(sText)); + // Row 2 + NuiSetBind(oPC, nToken, "chbx_cmd_group1_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "chbx_cmd_group1_check", JsonBool (bCmdGroup1)); + NuiSetBindWatch (oPC, nToken, "chbx_cmd_group1_check", TRUE); + NuiSetBind(oPC, nToken, "btn_cmd_group1_event", JsonBool (TRUE)); + string sText, sText2, sSpeed; + string sAction = " (Left Action/Right Add)"; + json jGroup = GetLocalJson(oPC, "DM_GROUP1"); + if(JsonGetInt(JsonArrayGet(jGroup, 0)) == 0) sSpeed = " [Walk]"; + else sSpeed = " [Run]"; + string sUUID = JsonGetString(JsonArrayGet(jGroup, 1)); + if(sUUID == "") { sText = "Group 1"; sText2 = sText + sAction; } + else { sText = GetName(GetObjectByUUID(sUUID)) + "'s group"; sText2 = sText + sSpeed; } + NuiSetBind(oPC, nToken, "btn_cmd_group1_label", JsonString(sText)); + NuiSetBind(oPC, nToken, "btn_cmd_group1_tooltip", JsonString(" " + sText2)); + NuiSetBind(oPC, nToken, "chbx_cmd_group2_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "chbx_cmd_group2_check", JsonBool (bCmdGroup2)); + NuiSetBindWatch (oPC, nToken, "chbx_cmd_group2_check", TRUE); + NuiSetBind(oPC, nToken, "btn_cmd_group2_event", JsonBool (TRUE)); + jGroup = GetLocalJson(oPC, "DM_GROUP2"); + if(JsonGetInt(JsonArrayGet(jGroup, 0)) == 0) sSpeed = " [Walk]"; + else sSpeed = " [Run]"; + sUUID = JsonGetString(JsonArrayGet(jGroup, 1)); + if(sUUID == "") { sText = "Group 2"; sText2 = sText + sAction; } + else { sText = GetName(GetObjectByUUID(sUUID)) + "'s group"; sText2 = sText + sSpeed; } + NuiSetBind(oPC, nToken, "btn_cmd_group2_label", JsonString(sText)); + NuiSetBind(oPC, nToken, "btn_cmd_group2_tooltip", JsonString(" " + sText2)); + // Row 3 + NuiSetBind(oPC, nToken, "chbx_cmd_group3_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "chbx_cmd_group3_check", JsonBool (bCmdGroup3)); + NuiSetBindWatch (oPC, nToken, "chbx_cmd_group3_check", TRUE); + NuiSetBind(oPC, nToken, "btn_cmd_group3_event", JsonBool (TRUE)); + jGroup = GetLocalJson(oPC, "DM_GROUP3"); + if(JsonGetInt(JsonArrayGet(jGroup, 0)) == 0) sSpeed = " [Walk]"; + else sSpeed = " [Run]"; + sUUID = JsonGetString(JsonArrayGet(jGroup, 1)); + if(sUUID == "") { sText = "Group 3"; sText2 = sText + sAction; } + else { sText = GetName(GetObjectByUUID(sUUID)) + "'s group"; sText2 = sText + sSpeed; } + NuiSetBind(oPC, nToken, "btn_cmd_group3_label", JsonString(sText)); + NuiSetBind(oPC, nToken, "btn_cmd_group3_tooltip", JsonString(" " + sText2)); + NuiSetBind(oPC, nToken, "chbx_cmd_group4_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "chbx_cmd_group4_check", JsonBool (bCmdGroup4)); + NuiSetBindWatch (oPC, nToken, "chbx_cmd_group4_check", TRUE); + NuiSetBind(oPC, nToken, "btn_cmd_group4_event", JsonBool (TRUE)); + jGroup = GetLocalJson(oPC, "DM_GROUP4"); + if(JsonGetInt(JsonArrayGet(jGroup, 0)) == 0) sSpeed = " [Walk]"; + else sSpeed = " [Run]"; + sUUID = JsonGetString(JsonArrayGet(jGroup, 1)); + if(sUUID == "") { sText = "Group 4"; sText2 = sText + sAction; } + else { sText = GetName(GetObjectByUUID(sUUID)) + "'s group"; sText2 = sText + sSpeed; } + NuiSetBind(oPC, nToken, "btn_cmd_group4_label", JsonString(sText)); + NuiSetBind(oPC, nToken, "btn_cmd_group4_tooltip", JsonString(" " + sText2)); + // Row 4 + NuiSetBind(oPC, nToken, "chbx_cmd_group5_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "chbx_cmd_group5_check", JsonBool (bCmdGroup5)); + NuiSetBindWatch (oPC, nToken, "chbx_cmd_group5_check", TRUE); + NuiSetBind(oPC, nToken, "btn_cmd_group5_event", JsonBool (TRUE)); + jGroup = GetLocalJson(oPC, "DM_GROUP5"); + if(JsonGetInt(JsonArrayGet(jGroup, 0)) == 0) sSpeed = " [Walk]"; + else sSpeed = " [Run]"; + sUUID = JsonGetString(JsonArrayGet(jGroup, 1)); + if(sUUID == "") { sText = "Group 5"; sText2 = sText + sAction; } + else { sText = GetName(GetObjectByUUID(sUUID)) + "'s group"; sText2 = sText + sSpeed; } + NuiSetBind(oPC, nToken, "btn_cmd_group5_label", JsonString(sText)); + NuiSetBind(oPC, nToken, "btn_cmd_group5_tooltip", JsonString(" " + sText2)); + NuiSetBind(oPC, nToken, "chbx_cmd_group6_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "chbx_cmd_group6_check", JsonBool (bCmdGroup6)); + NuiSetBindWatch (oPC, nToken, "chbx_cmd_group6_check", TRUE); + NuiSetBind(oPC, nToken, "btn_cmd_group6_event", JsonBool (TRUE)); + jGroup = GetLocalJson(oPC, "DM_GROUP6"); + if(JsonGetInt(JsonArrayGet(jGroup, 0)) == 0) sSpeed = " [Walk]"; + else sSpeed = " [Run]"; + sUUID = JsonGetString(JsonArrayGet(jGroup, 1)); + if(sUUID == "") { sText = "Group 6"; sText2 = sText + sAction; } + else { sText = GetName(GetObjectByUUID(sUUID)) + "'s group"; sText2 = sText + sSpeed; } + NuiSetBind(oPC, nToken, "btn_cmd_group6_label", JsonString(sText)); + NuiSetBind(oPC, nToken, "btn_cmd_group6_tooltip", JsonString(" " + sText2)); + // Row 5 + NuiSetBind(oPC, nToken, "chbx_camera_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "chbx_camera_check", JsonBool (bCmdCamera)); + NuiSetBindWatch (oPC, nToken, "chbx_camera_check", TRUE); + NuiSetBind(oPC, nToken, "btn_camera_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "btn_camera_tooltip", JsonString ( + " Toggle camera view for " + sDMName)); + NuiSetBind(oPC, nToken, "chbx_inventory_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "chbx_inventory_check", JsonBool (bCmdInventory)); + NuiSetBindWatch (oPC, nToken, "chbx_inventory_check", TRUE); + NuiSetBind(oPC, nToken, "btn_inventory_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "btn_inventory_tooltip", JsonString ( + " Open " + sDMName + " inventory")); + // Row 6+ + nIndex = 0; + int bWidget; + jPlugin = JsonArrayGet(jDMPlugins, nIndex); + while(JsonGetType(jPlugin) != JSON_TYPE_NULL) + { + sButton = IntToString(nIndex); + NuiSetBind(oPC, nToken, "btn_plugin_" + sButton + "_event", JsonBool(TRUE)); + bWidget = JsonGetInt(JsonArrayGet(jPlugin, 1)); + NuiSetBind(oPC, nToken, "chbx_plugin_" + sButton + "_check", JsonBool(bWidget)); + NuiSetBindWatch (oPC, nToken, "chbx_plugin_" + sButton + "_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_plugin_" + sButton + "_event", JsonBool(TRUE)); + sText = " " + JsonGetString(JsonArrayGet(jPlugin, 2)); + NuiSetBind(oPC, nToken, "btn_plugin_" + sButton + "_tooltip", JsonString(sText)); + jPlugin = JsonArrayGet(jDMPlugins, ++nIndex); + } + NuiSetBind(oPC, nToken, "chbx_plugin_tooltip", JsonString(" Adds the plugin to your widget.")); + // Row 7 + sText = ai_GetRandomDMTip(); + NuiSetBind(oPC, nToken, "lbl_info_1_label", JsonString(sText)); +} +void ai_CreateDMPluginManagerNUI(object oPC) +{ + SetLocalInt(oPC, AI_NO_NUI_SAVE, TRUE); + DelayCommand(0.5f, DeleteLocalInt (oPC, AI_NO_NUI_SAVE)); + // Row 1 ******************************************************************* 500 / 73 + json jRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + jRow = CreateButton(jRow, "Load All Plugins", "btn_load_plugins", 150.0f, 20.0f, -1.0, "btn_load_plugins_tooltip"); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateButton(jRow, "Check All", "btn_check_plugins", 150.0f, 20.0f, -1.0, "btn_check_plugins_tooltip"); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateButton(jRow, "Clear All", "btn_clear_plugins", 150.0f, 20.0f, -1.0, "btn_clear_plugins_tooltip"); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + // Add row to the column. + json jCol = JsonArrayInsert(JsonArray(), NuiRow(jRow)); + // Row 2 ******************************************************************* 500 / 101 + jRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + jRow = CreateButton(jRow, "Add Plugin", "btn_add_plugin", 150.0f, 20.0f); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateTextEditBox(jRow, "sPlaceHolder", "txt_plugin", 16, FALSE, 310.0f, 20.0f, "txt_plugin_tooltip"); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + float fHeight = 101.0; + // Row 3+ ****************************************************************** 500 / --- + json jPlugins = ai_GetCampaignDbJson("plugins"); + int nIndex = 0; + json jPlugin = JsonArrayGet(jPlugins, nIndex); + string sName, sButton; + while(JsonGetType(jPlugin) != JSON_TYPE_NULL) + { + sButton = IntToString(nIndex); + jRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + jRow = CreateButton(jRow, "Remove Plugin", "btn_remove_plugin_" + sButton, 150.0f, 20.0f); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + sName = JsonGetString(JsonArrayGet(jPlugin, 2)); + jRow = CreateButton(jRow, sName, "btn_plugin_" + sButton, 290.0f, 20.0f, -1.0, "btn_plugin_" + sButton + "_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_plugin_" + sButton, 25.0, 20.0); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight += 28.0; + jPlugin = JsonArrayGet(jPlugins, ++nIndex); + } + // Get the window location to restore it from the database. + sName = ai_RemoveIllegalCharacters(GetName(oPC)); + json jLocations = ai_GetCampaignDbJson("locations", sName, AI_DM_TABLE); + jLocations = JsonObjectGet(jLocations, "dm" + AI_PLUGIN_NUI); + float fX = JsonGetFloat(JsonObjectGet(jLocations, "x")); + float fY = JsonGetFloat(JsonObjectGet(jLocations, "y")); + // Set the Layout of the window. + json jLayout = NuiCol(jCol); + sName = GetName(oPC); + if(GetStringRight(sName, 1) == "s") sName = sName + "'"; + else sName = sName + "'s"; + int nToken = SetWindow(oPC, jLayout, "dm" + AI_PLUGIN_NUI, sName + " PEPS Plugin Manager", + fX, fY, 500.0f, fHeight + 12.0f, FALSE, FALSE, TRUE, FALSE, TRUE, "0e_nui_dm"); + // Set event watches for save window location. + NuiSetBindWatch(oPC, nToken, "window_geometry", TRUE); + // Row 1 + NuiSetBind(oPC, nToken, "btn_load_plugins_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_load_plugins_tooltip", JsonString(" Load all known PEPS plugins that are in the game files.")); + NuiSetBind(oPC, nToken, "btn_check_plugins_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_check_plugins_tooltip", JsonString(" Add all plugins to the players widget.")); + NuiSetBind(oPC, nToken, "btn_clear_plugins_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_clear_plugins_tooltip", JsonString(" Remove all plugins from the players widget.")); + // Row 2 + NuiSetBind(oPC, nToken, "btn_add_plugin_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "txt_plugin_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "txt_plugin_tooltip", JsonString(" Enter an executable script name.")); + // Row 3+ + nIndex = 0; + int bCheck; + string sText; + jPlugin = JsonArrayGet(jPlugins, nIndex); + while(JsonGetType(jPlugin) != JSON_TYPE_NULL) + { + sButton = IntToString(nIndex); + NuiSetBind(oPC, nToken, "btn_remove_plugin_" + sButton + "_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_plugin_" + sButton + "_event", JsonBool(TRUE)); + bCheck = JsonGetInt(JsonArrayGet(jPlugin, 1)); + NuiSetBind(oPC, nToken, "chbx_plugin_" + sButton + "_check", JsonBool(bCheck)); + NuiSetBind(oPC, nToken, "chbx_plugin_" + sButton + "_event", JsonBool(TRUE)); + NuiSetBindWatch (oPC, nToken, "chbx_plugin_" + sButton + "_check", TRUE); + sText = " " + JsonGetString(JsonArrayGet(jPlugin, 2)); + NuiSetBind(oPC, nToken, "btn_plugin_" + sButton + "_tooltip", JsonString(sText)); + jPlugin = JsonArrayGet(jPlugins, ++nIndex); + } + NuiSetBind(oPC, nToken, "chbx_plugin_tooltip", JsonString(" Allows players to use this plugin.")); +} +void ai_CreateDMWidgetManagerNUI(object oPC) +{ + SetLocalInt(oPC, AI_NO_NUI_SAVE, TRUE); + DelayCommand(0.5f, DeleteLocalInt (oPC, AI_NO_NUI_SAVE)); + // Row 1 ******************************************************************* 575 / 73 + json jRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + jRow = CreateButton(jRow, "Check All", "btn_check_buttons", 150.0f, 20.0f, -1.0, "btn_check_buttons_tooltip"); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateButton(jRow, "Clear All", "btn_clear_buttons", 150.0f, 20.0f, -1.0, "btn_clear_buttons_tooltip"); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + json jCol = JsonArrayInsert(JsonArray(), NuiRow(jRow)); + // Row 2 ******************************************************************* 575 / 96 + jRow = CreateLabel(JsonArray(), "This menu manages the PEPS buttons a player may have access to.", "lbl_info1", 636.0, 15.0); + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 3 ******************************************************************* 575 / 119 + jRow = CreateLabel(JsonArray(), "Having a check next to a button will remove that button from the players menus.", "lbl_info2", 636.0, 15.0); + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 4 ******************************************************************* 575 / 162 + jRow = CreateButtonImage(JsonArray(), "ir_action", "btn_cmd_action", 35.0f, 35.0f, 0.0, "btn_cmd_action_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_cmd_action", 25.0, 20.0, "btn_cmd_action_tooltip"); + + jRow = CreateButtonImage(jRow, "ir_guard", "btn_cmd_guard", 35.0f, 35.0f, 0.0, "btn_cmd_guard_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_cmd_guard", 25.0, 20.0, "btn_cmd_guard_tooltip"); + + jRow = CreateButtonImage(jRow, "ir_standground", "btn_cmd_hold", 35.0f, 35.0f, 0.0, "btn_cmd_hold_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_cmd_hold", 25.0, 20.0, "btn_cmd_hold_tooltip"); + + jRow = CreateButtonImage(jRow, "ir_attacknearest", "btn_cmd_attack", 35.0f, 35.0f, 0.0, "btn_cmd_attack_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_cmd_attack", 25.0, 20.0, "btn_cmd_attack_tooltip"); + + jRow = CreateButtonImage(jRow, "ir_follow", "btn_cmd_follow", 35.0f, 35.0f, 0.0, "btn_cmd_follow_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_cmd_follow", 25.0, 20.0, "btn_cmd_follow_tooltip"); + + jRow = CreateButtonImage(jRow, "ir_dmchat", "btn_follow_target", 35.0f, 35.0f, 0.0, "btn_follow_target_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_follow_target", 25.0, 20.0, "btn_follow_target_tooltip"); + + jRow = CreateButtonImage(jRow, "ife_foc_search", "btn_cmd_search", 35.0f, 35.0f, 0.0, "btn_cmd_search_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_cmd_search", 25.0, 20.0, "btn_cmd_search_tooltip"); + + jRow = CreateButtonImage(jRow, "ife_foc_hide", "btn_cmd_stealth", 35.0f, 35.0f, 0.0, "btn_cmd_stealth_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_cmd_stealth", 25.0, 20.0, "btn_cmd_stealth_tooltip"); + + jRow = CreateButtonImage(jRow, "ir_scommand", "btn_cmd_ai_script", 35.0f, 35.0f, 0.0, "btn_cmd_ai_script_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_cmd_ai_script", 25.0, 20.0, "btn_cmd_ai_script_tooltip"); + + jRow = CreateButtonImage(jRow, "isk_settrap", "btn_cmd_place_trap", 35.0f, 35.0f, 0.0, "btn_cmd_place_trap_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_cmd_place_trap", 25.0, 20.0, "btn_cmd_place_trap_tooltip"); + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 5 ******************************************************************* 575 / 205 + jRow = CreateButtonImage(JsonArray(), "isk_spellcraft", "btn_quick_widget", 35.0f, 35.0f, 0.0, "btn_quick_widget_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_quick_widget", 25.0, 20.0, "btn_quick_widget_tooltip"); + + jRow = CreateButtonImage(jRow, "isk_lore", "btn_spell_memorize", 35.0f, 35.0f, 0.0, "btn_spell_memorize_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_spell_memorize", 25.0, 20.0, "btn_spell_memorize_tooltip"); + + jRow = CreateButtonImage(jRow, "ir_cantrips", "btn_buff_short", 35.0f, 35.0f, 0.0, "btn_buff_short_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_buff_short", 25.0, 20.0, "btn_buff_short_tooltip"); + + jRow = CreateButtonImage(jRow, "ir_cast", "btn_buff_long", 35.0f, 35.0f, 0.0, "btn_buff_long_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_buff_long", 25.0, 20.0, "btn_buff_long_tooltip"); + + jRow = CreateButtonImage(jRow, "ir_level789", "btn_buff_all", 35.0f, 35.0f, 0.0, "btn_buff_all_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_buff_all", 25.0, 20.0, "btn_buff_all_tooltip"); + + jRow = CreateButtonImage(jRow, "ir_rest", "btn_buff_rest", 35.0f, 35.0f, 0.0, "btn_buff_rest_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_buff_rest", 25.0, 20.0, "btn_buff_rest_tooltip"); + + jRow = CreateButtonImage(jRow, "dm_jump", "btn_jump_to", 35.0f, 35.0f, 0.0, "btn_jump_to_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_jump_to", 25.0, 20.0, "btn_jump_to_tooltip"); + + jRow = CreateButtonImage(jRow, "dm_limbo", "btn_ghost_mode", 35.0f, 35.0f, 0.0, "btn_ghost_mode_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_ghost_mode", 25.0, 20.0, "btn_ghost_mode_tooltip"); + + jRow = CreateButtonImage(jRow, "ir_examine", "btn_camera", 35.0f, 35.0f, 0.0, "btn_camera_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_camera", 25.0, 20.0, "btn_camera_tooltip"); + + jRow = CreateButtonImage(jRow, "ir_pickup", "btn_inventory", 35.0f, 35.0f, 0.0, "btn_inventory_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_inventory", 25.0, 20.0, "btn_inventory_tooltip"); + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 6 ******************************************************************* 575 / 248 + + jRow = CreateButtonImage(JsonArray(), "ife_familiar", "btn_familiar", 35.0f, 35.0f, 0.0, "btn_familiar_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_familiar", 25.0, 20.0, "btn_familiar_tooltip"); + + jRow = CreateButtonImage(jRow, "ife_animal", "btn_companion", 35.0f, 35.0f, 0.0, "btn_companion_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_companion", 25.0, 20.0, "btn_companion_tooltip"); + + jRow = CreateButtonImage(jRow, "dm_ai", "btn_ai", 35.0f, 35.0f, 0.0, "btn_ai_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_ai", 25.0, 20.0, "btn_companion_tooltip"); + + jRow = CreateButtonImage(jRow, "isk_movsilent", "btn_quiet", 35.0f, 35.0f, 0.0, "btn_quiet_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_quiet", 25.0, 20.0, "btn_quiet_tooltip"); + + jRow = CreateButtonImage(jRow, "ir_archer", "btn_ranged", 35.0f, 35.0f, 0.0, "btn_ranged_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_ranged", 25.0, 20.0, "btn_ranged_tooltip"); + + jRow = CreateButtonImage(jRow, "dm_takeitem", "btn_equip_weapon", 35.0f, 35.0f, 0.0, "btn_equip_weapon_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_equip_weapon", 25.0, 20.0, "btn_equip_weapon_tooltip"); + + jRow = CreateButtonImage(jRow, "isk_search", "btn_search", 35.0f, 35.0f, 0.0, "btn_search_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_search", 25.0, 20.0, "btn_search_tooltip"); + + jRow = CreateButtonImage(jRow, "isk_hide", "btn_stealth", 35.0f, 35.0f, 0.0, "btn_stealth_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_stealth", 25.0, 20.0, "btn_stealth_tooltip"); + + jRow = CreateButtonImage(jRow, "ir_open", "btn_open_door", 35.0f, 35.0f, 0.0, "btn_open_door_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_open_door", 25.0, 20.0, "btn_open_door_tooltip"); + + jRow = CreateButtonImage(jRow, "isk_distrap", "btn_traps", 35.0f, 35.0f, 0.0, "btn_traps_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_traps", 25.0, 20.0, "btn_traps_tooltip"); + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 7 ******************************************************************* 575 / 291 + + jRow = CreateButtonImage(JsonArray(), "isk_olock", "btn_pick_locks", 35.0f, 35.0f, 0.0, "btn_pick_locks_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_pick_locks", 25.0, 20.0, "btn_pick_locks_tooltip"); + + jRow = CreateButtonImage(jRow, "ir_bash", "btn_bash_locks", 35.0f, 35.0f, 0.0, "btn_bash_locks_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_bash_locks", 25.0, 20.0, "btn_bash_locks_tooltip"); + + jRow = CreateButtonImage(jRow, "dm_control", "btn_magic_level", 35.0f, 35.0f, 0.0, "btn_magic_level_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_magic_level", 25.0, 20.0, "btn_magic_level_tooltip"); + + jRow = CreateButtonImage(jRow, "ir_xability", "btn_spontaneous", 35.0f, 35.0f, 0.0, "btn_spontaneous_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_spontaneous", 25.0, 20.0, "btn_spontaneous_tooltip"); + + jRow = CreateButtonImage(jRow, "ir_cntrspell", "btn_magic", 35.0f, 35.0f, 0.0, "btn_magic_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_magic", 25.0, 20.0, "btn_magic_tooltip"); + + jRow = CreateButtonImage(jRow, "ir_moreattacks", "btn_magic_items", 35.0f, 35.0f, 0.0, "btn_magic_items_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_magic_items", 25.0, 20.0, "btn_magic_items_tooltip"); + + jRow = CreateButtonImage(jRow, "ir_orisons", "btn_def_magic", 35.0f, 35.0f, 0.0, "btn_def_magic_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_def_magic", 25.0, 20.0, "btn_def_magic_tooltip"); + + jRow = CreateButtonImage(jRow, "ir_metamagic", "btn_off_magic", 35.0f, 35.0f, 0.0, "btn_off_magic_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_off_magic", 25.0, 20.0, "btn_off_magic_tooltip"); + + jRow = CreateButtonImage(jRow, "isk_heal", "btn_heal_out", 35.0f, 35.0f, 0.0, "btn_heal_out_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_heal_out", 25.0, 20.0, "btn_heal_out_tooltip"); + + jRow = CreateButtonImage(jRow, "dm_heal", "btn_heal_in", 35.0f, 35.0f, 0.0, "btn_heal_in_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_heal_in", 25.0, 20.0, "btn_heal_in_tooltip"); + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 8 ******************************************************************* 575 / 334 + jRow = CreateButtonImage(JsonArray(), "ir_heal", "btn_heals_onoff", 35.0f, 35.0f, 0.0, "btn_heals_onoff_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_heals_onoff", 25.0, 20.0, "btn_heals_onoff_tooltip"); + + jRow = CreateButtonImage(jRow, "ir_party", "btn_healp_onoff", 35.0f, 35.0f, 0.0, "btn_healp_onoff_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_healp_onoff", 25.0, 20.0, "btn_healp_onoff_tooltip"); + + jRow = CreateButtonImage(jRow, "ir_accept", "btn_cure_onoff", 35.0f, 35.0f, 0.0, "btn_cure_onoff_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_cure_onoff", 25.0, 20.0, "btn_cure_onoff_tooltip"); + + jRow = CreateButtonImage(jRow, "ir_barter", "btn_loot", 35.0f, 35.0f, 0.0, "btn_loot_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_loot", 25.0, 20.0, "btn_loot_tooltip"); + + jRow = CreateButtonImage(jRow, "ir_ignore", "btn_ignore_assoc", 35.0f, 35.0f, 0.0, "btn_ignore_assoc_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_ignore_assoc", 25.0, 20.0, "btn_ignore_assoc_tooltip"); + + jRow = CreateButtonImage(jRow, "ir_abort", "btn_ignore_traps", 35.0f, 35.0f, 0.0, "btn_ignore_traps_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_ignore_traps", 25.0, 20.0, "btn_ignore_traps_tooltip"); + + jRow = CreateButtonImage(jRow, "ir_dmchat", "btn_perc_range", 35.0f, 35.0f, 0.0, "btn_perc_range_tooltip"); + jRow = CreateCheckBox(jRow, "", "chbx_perc_range", 25.0, 20.0, "btn_perc_range_tooltip"); + + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + float fHeight = 334.0; + // Get the window location to restore it from the database. + string sName = ai_RemoveIllegalCharacters(GetName(oPC)); + json jLocations = ai_GetCampaignDbJson("locations", sName, AI_DM_TABLE); + jLocations = JsonObjectGet(jLocations, "dm_widget_manager_nui"); + float fX = JsonGetFloat(JsonObjectGet(jLocations, "x")); + float fY = JsonGetFloat(JsonObjectGet(jLocations, "y")); + // Set the Layout of the window. + json jLayout = NuiCol(jCol); + sName = GetName(oPC); + if(GetStringRight(sName, 1) == "s") sName = sName + "'"; + else sName = sName + "'s"; + int nToken = SetWindow(oPC, jLayout, "dm_widget_manager_nui", sName + " PEPS DM Widget Manager", + fX, fY, 660.0f, fHeight + 12.0f, FALSE, FALSE, TRUE, FALSE, TRUE, "0e_nui_dm"); + // Set event watches for save window location. + NuiSetBindWatch(oPC, nToken, "window_geometry", TRUE); + // Row 1 + NuiSetBind(oPC, nToken, "btn_check_buttons_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_check_buttons_tooltip", JsonString(" Check all buttons, removing them for all players.")); + NuiSetBind(oPC, nToken, "btn_clear_buttons_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_clear_buttons_tooltip", JsonString(" Clear all buttons, allowing use for all players.")); + // Row 2 & 3 Labels. + // Load all the buttons states. + //int bAIWidgetLock = ai_GetDMWAccessButton(BTN_WIDGET_LOCK); + int bCmdAction = ai_GetDMWAccessButton(BTN_CMD_ACTION); + int bCmdGuard = ai_GetDMWAccessButton(BTN_CMD_GUARD); + int bCmdHold = ai_GetDMWAccessButton(BTN_CMD_HOLD); + int bCmdSearch = ai_GetDMWAccessButton(BTN_CMD_SEARCH); + int bCmdStealth = ai_GetDMWAccessButton(BTN_CMD_STEALTH); + int bCmdAttack = ai_GetDMWAccessButton(BTN_CMD_ATTACK); + int bCmdFollow = ai_GetDMWAccessButton(BTN_CMD_FOLLOW); + int bCmdAIScript = ai_GetDMWAccessButton(BTN_CMD_AI_SCRIPT); + int bCmdPlacetrap = ai_GetDMWAccessButton(BTN_CMD_PLACE_TRAP); + int bSpellWidget = ai_GetDMWAccessButton(BTN_CMD_SPELL_WIDGET); + int bMemorizeSpells = ai_GetDMWAccessButton(BTN_DM_CMD_MEMORIZE); + int bBuffShort = ai_GetDMWAccessButton(BTN_BUFF_SHORT); + int bBuffLong = ai_GetDMWAccessButton(BTN_BUFF_LONG); + int bBuffAll = ai_GetDMWAccessButton(BTN_BUFF_ALL); + int bBuffRest = ai_GetDMWAccessButton(BTN_BUFF_REST); + int bJumpTo = ai_GetDMWAccessButton(BTN_CMD_JUMP_TO); + int bGhostMode = ai_GetDMWAccessButton(BTN_CMD_GHOST_MODE); + int bCamera = ai_GetDMWAccessButton(BTN_CMD_CAMERA); + int bInventory = ai_GetDMWAccessButton(BTN_CMD_INVENTORY); + int bFamiliar = ai_GetDMWAccessButton(BTN_CMD_FAMILIAR); + int bCompanion = ai_GetDMWAccessButton(BTN_CMD_COMPANION); + int bFollowTarget = ai_GetDMAIAccessButton(BTN_AI_FOLLOW_TARGET); + int bAI = ai_GetDMAIAccessButton(BTN_AI_FOR_PC); + int bReduceSpeech = ai_GetDMAIAccessButton(BTN_AI_REDUCE_SPEECH); + int bRanged = ai_GetDMAIAccessButton(BTN_AI_USE_RANGED); + int bEquipWeapons = ai_GetDMAIAccessButton(BTN_AI_STOP_WEAPON_EQUIP); + int bSearch = ai_GetDMAIAccessButton(BTN_AI_USE_SEARCH); + int bStealth = ai_GetDMAIAccessButton(BTN_AI_USE_STEALTH); + int bOpenDoors = ai_GetDMAIAccessButton(BTN_AI_OPEN_DOORS); + int bTraps = ai_GetDMAIAccessButton(BTN_AI_REMOVE_TRAPS); + int bPickLocks = ai_GetDMAIAccessButton(BTN_AI_PICK_LOCKS); + int bBashLocks = ai_GetDMAIAccessButton(BTN_AI_BASH_LOCKS); + int bMagicLevel = ai_GetDMAIAccessButton(BTN_AI_MAGIC_LEVEL); + int bSpontaneous = ai_GetDMAIAccessButton(BTN_AI_NO_SPONTANEOUS); + int bNoMagic = ai_GetDMAIAccessButton(BTN_AI_NO_MAGIC_USE); + int bNoMagicItems = ai_GetDMAIAccessButton(BTN_AI_NO_MAGIC_ITEM_USE); + int bDefMagic = ai_GetDMAIAccessButton(BTN_AI_DEF_MAGIC_USE); + int bOffMagic = ai_GetDMAIAccessButton(BTN_AI_OFF_MAGIC_USE); + int bHealOut = ai_GetDMAIAccessButton(BTN_AI_HEAL_OUT); + int bHealIn = ai_GetDMAIAccessButton(BTN_AI_HEAL_IN); + int bSelfHealOnOff = ai_GetDMAIAccessButton(BTN_AI_STOP_SELF_HEALING); + int bPartyHealOnOff = ai_GetDMAIAccessButton(BTN_AI_STOP_PARTY_HEALING); + int bCureOnOff = ai_GetDMAIAccessButton(BTN_AI_STOP_CURE_SPELLS); + int bLoot = ai_GetDMAIAccessButton(BTN_AI_LOOT); + int bIgnoreAssociates = ai_GetDMAIAccessButton(BTN_AI_IGNORE_ASSOCIATES); + int bIgnoreTraps = ai_GetDMAIAccessButton(BTN_AI_IGNORE_TRAPS); + int bPercRange = ai_GetDMAIAccessButton(BTN_AI_PERC_RANGE); + int bBtnFamiliar = ai_GetDMWAccessButton(BTN_CMD_FAMILIAR); + int bBtnCompanion = ai_GetDMWAccessButton(BTN_CMD_COMPANION); + SetLocalInt(oPC, "CHBX_SKIP", TRUE); + DelayCommand(2.0, DeleteLocalInt(oPC, "CHBX_SKIP")); + // Row 4 + NuiSetBind(oPC, nToken, "chbx_cmd_action_check", JsonBool (bCmdAction)); + NuiSetBindWatch(oPC, nToken, "chbx_cmd_action_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_cmd_action_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_cmd_action_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "btn_cmd_action_tooltip", JsonString(" Action button")); + + NuiSetBind(oPC, nToken, "chbx_cmd_guard_check", JsonBool (bCmdGuard)); + NuiSetBindWatch (oPC, nToken, "chbx_cmd_guard_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_cmd_guard_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_cmd_guard_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "btn_cmd_guard_tooltip", JsonString(" Guard button")); + + NuiSetBind(oPC, nToken, "chbx_cmd_hold_check", JsonBool (bCmdHold)); + NuiSetBindWatch (oPC, nToken, "chbx_cmd_hold_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_cmd_hold_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_cmd_hold_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "btn_cmd_hold_tooltip", JsonString(" Hold button")); + + NuiSetBind(oPC, nToken, "chbx_cmd_attack_check", JsonBool (bCmdAttack)); + NuiSetBindWatch (oPC, nToken, "chbx_cmd_attack_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_cmd_attack_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_cmd_attack_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "btn_cmd_attack_tooltip", JsonString(" Attack button")); + + NuiSetBind(oPC, nToken, "chbx_cmd_follow_check", JsonBool (bCmdFollow)); + NuiSetBindWatch (oPC, nToken, "chbx_cmd_follow_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_cmd_follow_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_cmd_follow_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "btn_cmd_follow_tooltip", JsonString(" Follow button")); + + NuiSetBind(oPC, nToken, "chbx_follow_target_check", JsonBool (bFollowTarget)); + NuiSetBindWatch (oPC, nToken, "chbx_follow_target_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_follow_target_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_follow_target_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "btn_follow_target_tooltip", JsonString(" Follow Target button")); + + NuiSetBind(oPC, nToken, "chbx_cmd_search_check", JsonBool (bCmdSearch)); + NuiSetBindWatch (oPC, nToken, "chbx_cmd_search_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_cmd_search_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_cmd_search_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "btn_cmd_search_tooltip", JsonString(" Search All button")); + + NuiSetBind(oPC, nToken, "chbx_cmd_stealth_check", JsonBool (bCmdStealth)); + NuiSetBindWatch (oPC, nToken, "chbx_cmd_stealth_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_cmd_stealth_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_cmd_stealth_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "btn_cmd_stealth_tooltip", JsonString(" Stealth All button")); + + NuiSetBind(oPC, nToken, "chbx_cmd_ai_script_check", JsonBool (bCmdAIScript)); + NuiSetBindWatch (oPC, nToken, "chbx_cmd_ai_script_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_cmd_ai_script_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_cmd_ai_script_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "btn_cmd_ai_script_tooltip", JsonString(" Combat Tactics button")); + + NuiSetBind(oPC, nToken, "chbx_cmd_place_trap_check", JsonBool (bCmdPlacetrap)); + NuiSetBindWatch (oPC, nToken, "chbx_cmd_place_trap_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_cmd_place_trap_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_cmd_place_trap_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "btn_cmd_place_trap_tooltip", JsonString (" Place Trap button")); + // Row 5 + NuiSetBind(oPC, nToken, "chbx_quick_widget_check", JsonBool (bSpellWidget)); + NuiSetBindWatch (oPC, nToken, "chbx_quick_widget_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_quick_widget_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_quick_widget_event", JsonBool(TRUE)); + NuiSetBind (oPC, nToken, "btn_quick_widget_tooltip", JsonString(" Quick Use button")); + + NuiSetBind(oPC, nToken, "chbx_spell_memorize_check", JsonBool (bMemorizeSpells)); + NuiSetBindWatch (oPC, nToken, "chbx_spell_memorize_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_spell_memorize_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_spell_memorize_event", JsonBool(TRUE)); + NuiSetBind (oPC, nToken, "btn_spell_memorize_tooltip", JsonString(" Memorize Spells button")); + + NuiSetBind(oPC, nToken, "chbx_buff_short_check", JsonBool (bBuffShort)); + NuiSetBindWatch (oPC, nToken, "chbx_buff_short_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_buff_short_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_buff_short_event", JsonBool (TRUE)); + NuiSetBind (oPC, nToken, "btn_buff_short_tooltip", JsonString(" Short Buffing button")); + + NuiSetBind(oPC, nToken, "chbx_buff_long_check", JsonBool (bBuffLong)); + NuiSetBindWatch (oPC, nToken, "chbx_buff_long_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_buff_long_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_buff_long_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "btn_buff_long_tooltip", JsonString(" Long Buffing button")); + + NuiSetBind(oPC, nToken, "chbx_buff_all_check", JsonBool (bBuffAll)); + NuiSetBindWatch (oPC, nToken, "chbx_buff_all_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_buff_all_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_buff_all_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "btn_buff_all_tooltip", JsonString(" All Buffing button")); + + NuiSetBind(oPC, nToken, "chbx_buff_rest_check", JsonBool (bBuffRest)); + NuiSetBindWatch (oPC, nToken, "chbx_buff_rest_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_buff_rest_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_buff_rest_event", JsonBool (TRUE)); + NuiSetBind (oPC, nToken, "btn_buff_rest_tooltip", JsonString(" Rest Buffing button")); + + NuiSetBind(oPC, nToken, "chbx_jump_to_check", JsonBool(bJumpTo)); + NuiSetBindWatch (oPC, nToken, "chbx_jump_to_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_jump_to_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_jump_to_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_jump_to_tooltip", JsonString(" Jump Associates button")); + + NuiSetBind(oPC, nToken, "chbx_ghost_mode_check", JsonBool (bGhostMode)); + NuiSetBindWatch (oPC, nToken, "chbx_ghost_mode_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_ghost_mode_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_ghost_mode_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "btn_ghost_mode_tooltip", JsonString(" Ghost mode button")); + + NuiSetBind(oPC, nToken, "chbx_camera_check", JsonBool (bCamera)); + NuiSetBindWatch (oPC, nToken, "chbx_camera_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_camera_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_camera_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "btn_camera_tooltip", JsonString(" Change Camera button")); + + NuiSetBind(oPC, nToken, "chbx_inventory_check", JsonBool (bInventory)); + NuiSetBindWatch (oPC, nToken, "chbx_inventory_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_inventory_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_inventory_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "btn_inventory_tooltip", JsonString(" Open Inventory button")); + // Row 6 + NuiSetBind(oPC, nToken, "chbx_familiar_check", JsonBool(bBtnFamiliar)); + NuiSetBindWatch (oPC, nToken, "chbx_familiar_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_familiar_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_familiar_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "btn_familiar_tooltip", JsonString(" Change Familiar buttons")); + + NuiSetBind(oPC, nToken, "chbx_companion_check", JsonBool(bBtnCompanion)); + NuiSetBindWatch (oPC, nToken, "chbx_companion_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_companion_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_companion_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "btn_companion_tooltip", JsonString(" Change Animal Companion buttons")); + + NuiSetBind(oPC, nToken, "chbx_ai_check", JsonBool(bAI)); + NuiSetBindWatch (oPC, nToken, "chbx_ai_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_ai_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_ai_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_ai_tooltip", JsonString(" Player AI button")); + + NuiSetBind(oPC, nToken, "chbx_quiet_check", JsonBool(bReduceSpeech)); + NuiSetBindWatch (oPC, nToken, "chbx_quiet_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_quiet_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_quiet_event", JsonBool(TRUE)); + NuiSetBind (oPC, nToken, "btn_quiet_tooltip", JsonString(" Reduce Speech button")); + + NuiSetBind(oPC, nToken, "chbx_ranged_check", JsonBool(bRanged)); + NuiSetBindWatch(oPC, nToken, "chbx_ranged_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_ranged_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_ranged_event", JsonBool(TRUE)); + NuiSetBind (oPC, nToken, "btn_ranged_tooltip", JsonString(" Ranged button")); + + NuiSetBind(oPC, nToken, "chbx_equip_weapon_check", JsonBool(bEquipWeapons)); + NuiSetBindWatch(oPC, nToken, "chbx_equip_weapon_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_equip_weapon_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_equip_weapon_event", JsonBool(TRUE)); + NuiSetBind (oPC, nToken, "btn_equip_weapon_tooltip", JsonString(" Auto Equip Weapons button")); + + NuiSetBind(oPC, nToken, "chbx_search_check", JsonBool(bSearch)); + NuiSetBindWatch (oPC, nToken, "chbx_search_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_search_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_search_event", JsonBool(TRUE)); + NuiSetBind (oPC, nToken, "btn_search_tooltip", JsonString(" Search button")); + + NuiSetBind(oPC, nToken, "chbx_stealth_check", JsonBool(bStealth)); + NuiSetBindWatch(oPC, nToken, "chbx_stealth_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_stealth_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_stealth_event", JsonBool(TRUE)); + NuiSetBind (oPC, nToken, "btn_stealth_tooltip", JsonString(" Stealth button")); + + NuiSetBind(oPC, nToken, "chbx_open_door_check", JsonBool(bOpenDoors)); + NuiSetBindWatch (oPC, nToken, "chbx_open_door_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_open_door_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_open_door_event", JsonBool(TRUE)); + NuiSetBind (oPC, nToken, "btn_open_door_tooltip", JsonString(" Open Door button")); + + NuiSetBind(oPC, nToken, "chbx_traps_check", JsonBool(bTraps)); + NuiSetBindWatch (oPC, nToken, "chbx_traps_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_traps_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_traps_event", JsonBool(TRUE)); + NuiSetBind (oPC, nToken, "btn_traps_tooltip", JsonString(" Disable Traps button")); + // Row 7 + NuiSetBind(oPC, nToken, "chbx_pick_locks_check", JsonBool(bPickLocks)); + NuiSetBindWatch(oPC, nToken, "chbx_pick_locks_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_pick_locks_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_pick_locks_event", JsonBool(TRUE)); + NuiSetBind (oPC, nToken, "btn_pick_locks_tooltip", JsonString(" Pick Locks button")); + + NuiSetBind(oPC, nToken, "chbx_bash_locks_check", JsonBool(bBashLocks)); + NuiSetBindWatch(oPC, nToken, "chbx_bash_locks_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_bash_locks_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_bash_locks_event", JsonBool(TRUE)); + NuiSetBind (oPC, nToken, "btn_bash_locks_tooltip", JsonString(" Bash button")); + + NuiSetBind(oPC, nToken, "chbx_magic_level_check", JsonBool(bMagicLevel)); + NuiSetBindWatch (oPC, nToken, "chbx_magic_level_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_magic_level_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_magic_level_event", JsonBool(TRUE)); + NuiSetBind (oPC, nToken, "btn_magic_level_tooltip", JsonString(" Magic Level button")); + + NuiSetBind(oPC, nToken, "chbx_spontaneous_check", JsonBool(bSpontaneous)); + NuiSetBindWatch (oPC, nToken, "chbx_spontaneous_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_spontaneous_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_spontaneous_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_spontaneous_tooltip", JsonString(" Spontaneous Spells button")); + + NuiSetBind(oPC, nToken, "chbx_magic_check", JsonBool(bNoMagic)); + NuiSetBindWatch (oPC, nToken, "chbx_magic_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_magic_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_magic_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_magic_tooltip", JsonString(" Use Magic button")); + + NuiSetBind(oPC, nToken, "chbx_magic_items_check", JsonBool(bNoMagicItems)); + NuiSetBindWatch (oPC, nToken, "chbx_magic_items_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_magic_items_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_magic_items_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_magic_items_tooltip", JsonString(" Use Magic Items button")); + + NuiSetBind(oPC, nToken, "chbx_def_magic_check", JsonBool (bDefMagic)); + NuiSetBindWatch (oPC, nToken, "chbx_def_magic_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_def_magic_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_def_magic_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_def_magic_tooltip", JsonString(" Use Defensive Magic button")); + + NuiSetBind(oPC, nToken, "chbx_off_magic_check", JsonBool(bOffMagic)); + NuiSetBindWatch (oPC, nToken, "chbx_off_magic_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_off_magic_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_off_magic_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_off_magic_tooltip", JsonString(" Use Offensive Magic button")); + + NuiSetBind(oPC, nToken, "chbx_heal_out_check", JsonBool(bHealOut)); + NuiSetBindWatch (oPC, nToken, "chbx_heal_out_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_heal_out_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_heal_out_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_heal_out_tooltip", JsonString(" Heal Out of Combat button")); + + NuiSetBind(oPC, nToken, "chbx_heal_in_check", JsonBool(bHealIn)); + NuiSetBindWatch (oPC, nToken, "chbx_heal_in_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_heal_in_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_heal_in_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "btn_heal_in_tooltip", JsonString(" Heal In Combat button")); + // Row 8 + NuiSetBind(oPC, nToken, "chbx_heals_onoff_check", JsonBool(bSelfHealOnOff)); + NuiSetBindWatch (oPC, nToken, "chbx_heals_onoff_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_heals_onoff_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_heals_onoff_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_heals_onoff_tooltip", JsonString(" Heal Self On/Off button")); + + NuiSetBind(oPC, nToken, "chbx_healp_onoff_check", JsonBool(bPartyHealOnOff)); + NuiSetBind(oPC, nToken, "chbx_healp_onoff_event", JsonBool(TRUE)); + NuiSetBindWatch (oPC, nToken, "chbx_healp_onoff_check", TRUE); + NuiSetBind(oPC, nToken, "btn_healp_onoff_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_healp_onoff_tooltip", JsonString(" Heal Party On/Off button")); + + NuiSetBind(oPC, nToken, "chbx_cure_onoff_check", JsonBool(bCureOnOff)); + NuiSetBind(oPC, nToken, "chbx_cure_onoff_event", JsonBool(TRUE)); + NuiSetBindWatch (oPC, nToken, "chbx_cure_onoff_check", TRUE); + NuiSetBind(oPC, nToken, "btn_cure_onoff_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_cure_onoff_tooltip", JsonString(" Cure Spells On/Off button")); + + NuiSetBind(oPC, nToken, "chbx_loot_check", JsonBool(bLoot)); + NuiSetBindWatch (oPC, nToken, "chbx_loot_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_loot_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_loot_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_loot_tooltip", JsonString(" Auto Looting button")); + + NuiSetBind(oPC, nToken, "chbx_ignore_assoc_check", JsonBool(bIgnoreAssociates)); + NuiSetBindWatch(oPC, nToken, "chbx_ignore_assoc_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_ignore_assoc_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_ignore_assoc_event", JsonBool(TRUE)); + NuiSetBind (oPC, nToken, "btn_ignore_assoc_tooltip", JsonString(" Ignore Associates On/Off button")); + + NuiSetBind(oPC, nToken, "chbx_ignore_traps_check", JsonBool(bIgnoreTraps)); + NuiSetBindWatch(oPC, nToken, "chbx_ignore_traps_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_ignore_traps_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_ignore_traps_event", JsonBool(TRUE)); + NuiSetBind (oPC, nToken, "btn_ignore_traps_tooltip", JsonString(" Ignore Floor Traps On/Off button")); + + NuiSetBind(oPC, nToken, "chbx_perc_range_check", JsonBool(bPercRange)); + NuiSetBindWatch (oPC, nToken, "chbx_perc_range_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_perc_range_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_perc_range_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_perc_range_tooltip", JsonString(" Perception Range button")); +} + diff --git a/src/module/nss/0i_messages.nss b/src/module/nss/0i_messages.nss new file mode 100644 index 0000000..ff01269 --- /dev/null +++ b/src/module/nss/0i_messages.nss @@ -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); +} diff --git a/src/module/nss/0i_module.nss b/src/module/nss/0i_module.nss new file mode 100644 index 0000000..6d50182 --- /dev/null +++ b/src/module/nss/0i_module.nss @@ -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"); +} diff --git a/src/module/nss/0i_nui.nss b/src/module/nss/0i_nui.nss new file mode 100644 index 0000000..eab5ee7 --- /dev/null +++ b/src/module/nss/0i_nui.nss @@ -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; +} + diff --git a/src/module/nss/0i_player_target.nss b/src/module/nss/0i_player_target.nss new file mode 100644 index 0000000..bed4834 --- /dev/null +++ b/src/module/nss/0i_player_target.nss @@ -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; +} diff --git a/src/module/nss/0i_spells.nss b/src/module/nss/0i_spells.nss new file mode 100644 index 0000000..b7b75e2 --- /dev/null +++ b/src/module/nss/0i_spells.nss @@ -0,0 +1,2157 @@ +/*//////////////////////////////////////////////////////////////////////////////////////////////////// + Script Name: 0i_spells + Programmer: Philos +////////////////////////////////////////////////////////////////////////////////////////////////////// + Include scripts for base spells. + +Category: + Enhancement E + Protection P +Indiscriminant I + Discriminant D + Range R + Touch T + Summon S + Healing H + Cure C + +Buff Duration: +1 - All +2 - Short +3 - Long + +Buff Target: + 0 - Caster only + 1-6 Str, Dex, Con, Int, Wis, Cha: Highest Ability Score + 7 - Lowest AC + 8 - Lowest AC without AC Bonus + 9 - Highest Atk + 10 - Most Wounded + 11 - Lowest Fortitude + 12 - Lowest Reflex + 13 - Lowest Will + 14 - Lowest total saves + 15 - Buffs an Item + +Buff Groups: +-1 - Elemental Resistances. +-2 - Summons +-3 - AC (Non armor) +-4 - AC (for Armor/Shield) +-5 - Chance to Miss (Invisibility) +-6 - Regeneration +-7 - Globes of Invulnerablitity +-8 - Damage Reduction +-9 - Mantles +-10 - Alignment vs Chaos +-11 - Alignment vs Evil +-12 - Alignment vs Good +-13 - Alignment vs Law +-14 - Atk Bonus (for Weapon) +-15 - Light effects +-16 - Haste effects +-17 - Polymorph effects +*///////////////////////////////////////////////////////////////////////////////////////////////////// +#include "0i_messages" +#include "0i_states_cond" +#include "0i_items" +#include "X0_I0_POSITION" +struct stSpell +{ + object oPC; + object oCaster; + object oTarget; + int nBuffType; + int nTarget; + int nPosition; + int nClass; + int nLevel; + int nMaxSlots; + int nSlot; +}; +// Returns TRUE if oCreature can cast nSpell from nLevel. +int ai_GetCanCastSpell(object oCreature, int nSpell, int nClass, int nLevel, int nMetaMagic = 0, int nDomain = 0); +// Returns TRUE if oCreature is immune to petrification. +int ai_IsImmuneToPetrification(object oCaster, object oCreature); +// Returns TRUE if oCreature has an effect from a mind affecting spell. +int ai_DoIHaveAMindAffectingSpellOnMe(object oCreature); +// Returns TRUE if nSpell is a cure spell. +int ai_IsCureSpell(int nSpell); +// Returns TRUE if nSpell is an inflict spell. +int ai_IsInflictSpell(int nSpell); +// Returns TRUE if nSpell is an area of effect spell. +int ai_IsAreaOfEffectSpell(int nSpell); +// Returns 1(TRUE) if oAssociate is a spellcaster. +// Rturns 2(TRUE) if oAssociate is a memorizing spellcaster. +int ai_GetIsSpellCaster(object oAssociate); +// Returns TRUE if oCreature is immune to nSpells effects. +int ai_CreatureImmuneToEffect(object oCaster, object oCreature, int nSpell); +// Returns the ranged of nSpell from the spells.2da(Column "Range"). +// S = 8.0f, M = 20.0f, L = 40.0f, T = 5.0f, else = 0.1f; +float ai_GetSpellRange(int nSpell); +// Returns TRUE if oTarget has a spell that we would want to dispel. +// Checks for harmful effects as well as buffing effects. +int ai_CreatureHasDispelableEffect(object oCaster, object oCreature); +// Remove nEffectType of Type specified on oCreature; +// nEffectType uses the constants EFFECT_TYPE_* +void ai_RemoveASpecificEffect(object oCreature, int nEffectType); +// Returns TRUE if oCreature has nEffectType. +// nEffectType uses the constants EFFECT_TYPE_* +int ai_GetHasEffectType(object oCreature, int nEffectType); +// Checks oCreature for special abilities have a long duration. +void ai_CheckCreatureSpecialAbilities(object oCreature); +// Checks oCreature for the silence effect and if the spell only has a somatic component. +int ai_IsSilenced(object oCreature, int nSpell); +// Returns TRUE if ArcaneSpellFailure is too high to chance casting the spell. +int ai_ArcaneSpellFailureTooHigh(object oCreature, int nClass, int nLevel, int nSlot); +// Returns TRUE if oCaster casts nSpell on oTarget. +// This will only cast the spell if oTarget DOES NOT already have the spell +// effect, and the caster has the spell ready. +int ai_TryToCastSpell(object oCaster, int nSpell, object oTarget); +// In "Buff_Target" column the value of 0 in the "ai_spells.2da" references the Caster. +// In "Buff_Target" column this is value 1-6(STR, DEX, CON, INT, WIS, CHA) in the "ai_spells.2da". +object ai_BuffHighestAbilityScoreTarget(object oCaster, int nSpell, int nAbilityScore, string sBuffGroup, float fRange, string sTargetType = "AI_ALLY_TARGET_"); +// In "Buff_Target" column this is value 7 in the "ai_spells.2da". +object ai_BuffLowestACTarget(object oCaster, int nSpell, string sBuffGroup, float fRange, string sTargetType = "AI_ALLY_TARGET_"); +// In "Buff_Target" column this is value 8 in the "ai_spells.2da". +object ai_BuffLowestACWithOutACBonus(object oCaster, int nSpell, string sBuffGroup, float fRange, string sTargetType = "AI_ALLY_TARGET_"); +// In "Buff_Target" column this is value 9 in the "ai_spells.2da". +object ai_BuffHighestAttackTarget(object oCaster, int nSpell, string sBuffGroup, float fRange, string sTargetType = "AI_ALLY_TARGET_"); +// In "Buff_Target" column this is value 10 in the "ai_spells.2da". +object ai_BuffMostWoundedTarget(object oCaster, int nSpell, string sBuffGroup, float fRange, string sTargetType = "AI_ALLY_TARGET_"); +// In "Buff_Target" column this is value 11 in the "ai_spells.2da". +object ai_BuffLowestFortitudeSaveTarget(object oCaster, int nSpell, string sBuffGroup, float fRange, string sTargetType = "AI_ALLY_TARGET_"); +// In "Buff_Target" column this is value 12 in the "ai_spells.2da". +object ai_BuffLowestReflexSaveTarget(object oCaster, int nSpell, string sBuffGroup, float fRange, string sTargetType = "AI_ALLY_TARGET_"); +// In "Buff_Target" column this is value 13 in the "ai_spells.2da". +object ai_BuffLowestWillSaveTarget(object oCaster, int nSpell, string sBuffGroup, float fRange, string sTargetType = "AI_ALLY_TARGET_"); +// In "Buff_Target" column this is value 14 in the "ai_spells.2da". +object ai_BuffLowestSaveTarget(object oCaster, int nSpell, string sBuffGroup, float fRange, string sTargetType = "AI_ALLY_TARGET_"); +// In "Buff_Target" column this is value 15 in the "ai_spells.2da". +object ai_BuffItemTarget(object oCaster, int nSpell, string sBuffGroup, float fRange, string sTargetType = "AI_ALLY_TARGET_"); +// Returns a target for nSpell cast by oCaster based on ai_spells.2da file. +object ai_GetBuffTarget(object oCaster, int nSpell); +// Casts a memorized spell from oCaster of nClass, nSpellLevel, nSpellSlot on oTarget. +void ai_CastMemorizedSpell(object oCaster, int nClass, int nSpellLevel, int nSpellSlot, object oTarget, int bInstant, object oPC = OBJECT_INVALID); +// Casts a known spell from oCaster of nClass, nSpell on oTarget. +void ai_CastKnownSpell(object oCaster, int nClass, int nSpell, object oTarget, int bInstant, object oPC = OBJECT_INVALID); +// Returns true if the spell is cast. +// Checks if they have the spell and will cast it if possible. +int ai_CheckAndCastSpell(object oCaster, int nSpell, int nSpellGroup, float fDelay, object oTarget, object oPC = OBJECT_INVALID); +// Setup monsters for oCaster to buff in ai_CastSpells. +void ai_SetupMonsterBuffTargets(object oCaster); +// Setup the targets for an NPC to buff one of the PC's members or the whole group. +void ai_SetupAllyTargets(object oCaster, object oPC); +// Setup the targets for an NPC to heal one of the PC's members. +void ai_SetupAllyHealingTargets(object oCaster, object oPC); +// Clears the casters buff targets. +void ai_ClearBuffTargets(object oCaster, string sVariable); +// Cycles through a casters spells casting all buffs via actions. +void ai_ActionCastMemorizedBuff(struct stSpell stSpell); +// Cycles through a casters spells casting all buffs via actions. +void ai_ActionCastKnownBuff(struct stSpell stSpell); +// Checks oCaster for buffing spells and casts them based on nTarget; +// These are cast as actions and will happen at the speed based on +// AI_HENCHMAN_BUFF_DELAY, but are still actions. +// nTarget is 0-9 where 0 is all targets, 1 is oPC, 2 is the caster +// 3 Familiar, 4 is Animal Companion, 5 is Summons, 6 is Dominated, and 7+ is henchman. +// Targets must be defined in variable AI_ALLY_TARGET_* where * is 1 to #. +// nBuffType is the duration 1 - all, 2 - short, 3 - long. +void ai_CastBuffs(object oCaster, int nBuffType, int nTarget, object oPC); +// Returns TRUE if oCaster cast spontaneous cure spell on oTarget. +// This uses an action and must use AssignCommand or OBJECT_SELF is the caster! +int ai_CastSpontaneousCure(object oCreature, object oTarget, object oPC); +// Returns TRUE if oCaster casts a memorized cure spell on oTarget. +// This uses an action and must use AssignCommand or OBJECT_SELF is the caster! +int ai_CastMemorizedHealing(object oCreature, object oTarget, object oPC, int nClass); +// Returns TRUE if oCaster casts a known cure spell on oTarget. +// This uses an action and must use AssignCommand or OBJECT_SELF is the caster! +int ai_CastKnownHealing(object oCreature, object oTarget, object oPC, int nClass); +// Returns TRUE if oCreature has an effect that will break their concentration. +int ai_ConcentrationCondition(object oCreature); +// Check to see if a spell's concentration has been broken, works for summons as well. +void ai_SpellConcentrationCheck(object oCaster); +// Returns TRUE if oCreature can safely cast nSpell defensively or has a good +// chance of casting while in melee. +int ai_CastInMelee(object oCreature, int nSpell, int nInMelee); +// Returns a float range for the caster to search for a target of an offensive spell. +float ai_GetOffensiveSpellSearchRange(object oCreature, int nSpell); +// Returns TRUE if nSpell is a cure spell and will not over heal for nDamage. +int ai_ShouldWeCastThisCureSpell(int nSpell, int nDamage); +// Casts the spell on the current target for oAssociate. +void ai_CastWidgetSpell(object oPC, object oAssociate, object oTarget, location lLocation); +// Uses the feat on the current target for oAssociate. +void ai_UseWidgetFeat(object oPC, object oAssociate, object oTarget, location lLocation); +// Uses the item on the current target for oAssociate. +void ai_UseWidgetItem(object oPC, object oAssociate, object oTarget, location lLocation); +int ai_GetCanCastSpell(object oCreature, int nSpell, int nClass, int nLevel, int nMetaMagic = 0, int nDomain = 0) +{ + int nIndex, nSpellCount, nClassPosition, nSlot, nMaxSlots, nPosition = 1; + while(nPosition <= AI_MAX_CLASSES_PER_CHARACTER) + { + nClassPosition = GetClassByPosition(nPosition, oCreature); + if(nClassPosition == CLASS_TYPE_INVALID) return FALSE; + if(nClass = nClassPosition) + { + if(Get2DAString("classes", "SpellCaster", nClass) == "1") + { + nSlot = 0; + if(Get2DAString("classes", "MemorizesSpells", nClass) == "1") + { + nMaxSlots = GetMemorizedSpellCountByLevel(oCreature, nClass, nLevel); + while(nSlot < nMaxSlots) + { + if(GetMemorizedSpellId(oCreature, nClass, nLevel, nSlot) == nSpell && + GetMemorizedSpellReady(oCreature, nClass, nLevel, nSlot)) return TRUE; + nSlot++; + } + } + else return GetSpellUsesLeft(oCreature, nClass, nSpell, nMetaMagic, nDomain); + } + } + nPosition++; + } + return FALSE; +} +int ai_IsImmuneToPetrification(object oCaster, object oCreature) +{ + int nAppearance = GetAppearanceType(oCreature); + switch(nAppearance) + { + case APPEARANCE_TYPE_BASILISK: + case APPEARANCE_TYPE_COCKATRICE: + case APPEARANCE_TYPE_MEDUSA: + case APPEARANCE_TYPE_ALLIP: + case APPEARANCE_TYPE_ELEMENTAL_AIR: + case APPEARANCE_TYPE_ELEMENTAL_AIR_ELDER: + case APPEARANCE_TYPE_ELEMENTAL_EARTH: + case APPEARANCE_TYPE_ELEMENTAL_EARTH_ELDER: + case APPEARANCE_TYPE_ELEMENTAL_FIRE: + case APPEARANCE_TYPE_ELEMENTAL_FIRE_ELDER: + case APPEARANCE_TYPE_ELEMENTAL_WATER: + case APPEARANCE_TYPE_ELEMENTAL_WATER_ELDER: + case APPEARANCE_TYPE_GOLEM_STONE: + case APPEARANCE_TYPE_GOLEM_IRON: + case APPEARANCE_TYPE_GOLEM_CLAY: + case APPEARANCE_TYPE_GOLEM_BONE: + case APPEARANCE_TYPE_GORGON: + case APPEARANCE_TYPE_HEURODIS_LICH: + case APPEARANCE_TYPE_LANTERN_ARCHON: + case APPEARANCE_TYPE_SHADOW: + case APPEARANCE_TYPE_SHADOW_FIEND: + case APPEARANCE_TYPE_SHIELD_GUARDIAN: + case APPEARANCE_TYPE_SKELETAL_DEVOURER: + case APPEARANCE_TYPE_SKELETON_CHIEFTAIN: + case APPEARANCE_TYPE_SKELETON_COMMON: + case APPEARANCE_TYPE_SKELETON_MAGE: + case APPEARANCE_TYPE_SKELETON_PRIEST: + case APPEARANCE_TYPE_SKELETON_WARRIOR: + case APPEARANCE_TYPE_SKELETON_WARRIOR_1: + case APPEARANCE_TYPE_SPECTRE: + case APPEARANCE_TYPE_WILL_O_WISP: + case APPEARANCE_TYPE_WRAITH: + case APPEARANCE_TYPE_BAT_HORROR: + case 405: // Dracolich: + case 415: // Alhoon + case 418: // shadow dragon + case 420: // mithral golem + case 421: // admantium golem + case 430: // Demi Lich + case 469: // animated chest + case 474: // golems + case 475: // golems + return TRUE; + } + // Petrification immunity can also be granted as an item property. + if(ResistSpell(oCaster, oCreature) == 2 ) return TRUE; + // Prevent people from petrifying DM, resulting in GUI even when effect is not successful. + if(!GetPlotFlag(oCreature) && GetIsDM(oCreature)) return TRUE; + return FALSE; +} +int ai_DoIHaveAMindAffectingSpellOnMe(object oCreature) +{ + if(GetHasSpellEffect(SPELL_SLEEP, oCreature) || + GetHasSpellEffect(SPELL_DAZE, oCreature) || + GetHasSpellEffect(SPELL_HOLD_ANIMAL, oCreature) || + GetHasSpellEffect(SPELL_HOLD_MONSTER, oCreature) || + GetHasSpellEffect(SPELL_HOLD_PERSON, oCreature) || + GetHasSpellEffect(SPELL_CHARM_MONSTER, oCreature) || + GetHasSpellEffect(SPELL_CHARM_PERSON, oCreature) || + GetHasSpellEffect(SPELL_CHARM_PERSON_OR_ANIMAL, oCreature) || + GetHasSpellEffect(SPELL_MASS_CHARM, oCreature) || + GetHasSpellEffect(SPELL_DOMINATE_ANIMAL, oCreature) || + GetHasSpellEffect(SPELL_DOMINATE_MONSTER, oCreature) || + GetHasSpellEffect(SPELL_DOMINATE_PERSON, oCreature) || + GetHasSpellEffect(SPELL_CONFUSION, oCreature) || + GetHasSpellEffect(SPELL_MIND_FOG, oCreature) || + GetHasSpellEffect(SPELL_CLOUD_OF_BEWILDERMENT, oCreature) || + GetHasSpellEffect(SPELLABILITY_BOLT_DOMINATE,oCreature) || + GetHasSpellEffect(SPELLABILITY_BOLT_CHARM,oCreature) || + GetHasSpellEffect(SPELLABILITY_BOLT_CONFUSE,oCreature) || + GetHasSpellEffect(SPELLABILITY_BOLT_DAZE,oCreature)) return TRUE; + return FALSE; +} +int ai_IsCureSpell(int nSpell) +{ + switch(nSpell) + { + case SPELL_CURE_CRITICAL_WOUNDS: + case SPELL_CURE_LIGHT_WOUNDS: + case SPELL_CURE_MINOR_WOUNDS: + case SPELL_CURE_MODERATE_WOUNDS: + case SPELL_CURE_SERIOUS_WOUNDS: + case SPELL_HEAL: return TRUE; break; + } + return FALSE; +} +int ai_IsInflictSpell(int nSpell) +{ + switch(nSpell) + { + case SPELL_INFLICT_CRITICAL_WOUNDS: + case SPELL_INFLICT_LIGHT_WOUNDS: + case SPELL_INFLICT_MINOR_WOUNDS: + case SPELL_INFLICT_MODERATE_WOUNDS: + case SPELL_INFLICT_SERIOUS_WOUNDS: + case SPELL_HARM: return TRUE; break; + } + return FALSE; +} +int ai_IsAreaOfEffectSpell(int nSpell) +{ + switch(nSpell) + { + case SPELL_ACID_FOG : + case SPELL_MIND_FOG : + case SPELL_STORM_OF_VENGEANCE: + case SPELL_WEB : + case SPELL_GREASE : + case SPELL_CREEPING_DOOM : +// case SPELL_DARKNESS : + case SPELL_SILENCE : + case SPELL_BLADE_BARRIER : + case SPELL_CLOUDKILL : + case SPELL_STINKING_CLOUD : + case SPELL_WALL_OF_FIRE : + case SPELL_INCENDIARY_CLOUD : + case SPELL_ENTANGLE : + case SPELL_EVARDS_BLACK_TENTACLES: + case SPELL_CLOUD_OF_BEWILDERMENT : + case SPELL_STONEHOLD : + case SPELL_VINE_MINE : + case SPELL_SPIKE_GROWTH : + case SPELL_DIRGE : + case 530 : // vine mine + case 531 : // vine mine + case 532 : // vine mine + case 961 : // Prismatic Sphere + return TRUE; + } + return FALSE; +} +int ai_GetIsSpellCaster(object oAssociate) +{ + int nIndex, nSpellCaster, nClass; + for(nIndex = 1; nIndex <= AI_MAX_CLASSES_PER_CHARACTER; nIndex++) + { + nClass = GetClassByPosition(nIndex, oAssociate); + if(nClass == CLASS_TYPE_INVALID) return nSpellCaster; + if(Get2DAString("classes", "SpellCaster", nClass) == "1") + { + if(Get2DAString("classes", "MemorizesSpells", nClass) == "1") return 2; + else nSpellCaster = 1; + } + } + return nSpellCaster; +} +int ai_GetIsSpellBookRestrictedCaster(object oAssociate) +{ + int nIndex, nSpellCaster, nClass; + for(nIndex = 1; nIndex <= AI_MAX_CLASSES_PER_CHARACTER; nIndex++) + { + nClass = GetClassByPosition(nIndex, oAssociate); + if(nClass == CLASS_TYPE_INVALID) return FALSE; + if(Get2DAString("classes", "SpellbookRestricted", nClass) == "1") return TRUE; + } + return FALSE; +} +int ai_CreatureImmuneToEffect(object oCaster, object oCreature, int nSpell) +{ + string sIType = Get2DAString("ai_spells", "ImmunityType", nSpell); + if(sIType != "") + { + if(AI_DEBUG) ai_Debug("0i_spells", "290", "Checking spell immunity type(" + sIType + ")."); + if(sIType == "Death" && GetIsImmune(oCreature, IMMUNITY_TYPE_DEATH)) return TRUE; + else if(sIType == "Level_Drain" && GetIsImmune(oCreature, IMMUNITY_TYPE_NEGATIVE_LEVEL)) return TRUE; + else if(sIType == "Ability_Drain" && GetIsImmune(oCreature, IMMUNITY_TYPE_ABILITY_DECREASE)) return TRUE; + else if(sIType == "Poison" && GetIsImmune(oCreature, IMMUNITY_TYPE_POISON)) return TRUE; + else if(sIType == "Disease" && GetIsImmune(oCreature, IMMUNITY_TYPE_DISEASE)) return TRUE; + else if(sIType == "Curse" && GetIsImmune(oCreature, IMMUNITY_TYPE_CURSED)) return TRUE; + else if(sIType == "Mind_Affecting" && GetIsImmune(oCreature, IMMUNITY_TYPE_MIND_SPELLS)) return TRUE; + else if(sIType == "Petrification" && ai_IsImmuneToPetrification(oCaster, oCreature)) return TRUE; + else if(sIType == "Fear" && + (GetIsImmune(oCreature, IMMUNITY_TYPE_FEAR) || + GetIsImmune(oCreature, IMMUNITY_TYPE_MIND_SPELLS))) return TRUE; + else if(sIType == "Sleep" && + (GetIsImmune(oCreature, IMMUNITY_TYPE_SLEEP) || + GetIsImmune(oCreature, IMMUNITY_TYPE_MIND_SPELLS))) return TRUE; + else if(sIType == "Paralysis" && + (GetIsImmune(oCreature, IMMUNITY_TYPE_PARALYSIS) || + GetIsImmune(oCreature, IMMUNITY_TYPE_MIND_SPELLS))) return TRUE; + else if(sIType == "Domination" && + (GetIsImmune(oCreature, IMMUNITY_TYPE_DOMINATE) || + GetIsImmune(oCreature, IMMUNITY_TYPE_MIND_SPELLS))) return TRUE; + else if(sIType == "Confusion" && + (GetIsImmune(oCreature, IMMUNITY_TYPE_CONFUSED) || + GetIsImmune(oCreature, IMMUNITY_TYPE_MIND_SPELLS))) return TRUE; + else if(sIType == "Blindness" && + (GetIsImmune(oCreature, IMMUNITY_TYPE_BLINDNESS) || + GetIsImmune(oCreature, IMMUNITY_TYPE_MIND_SPELLS))) return TRUE; + else if(sIType == "Dazed" && + (GetIsImmune(oCreature, IMMUNITY_TYPE_DAZED) || + GetIsImmune(oCreature, IMMUNITY_TYPE_MIND_SPELLS))) return TRUE; + else if(sIType == "Charm" && + (GetIsImmune(oCreature, IMMUNITY_TYPE_CHARM) || + GetIsImmune(oCreature, IMMUNITY_TYPE_MIND_SPELLS))) return TRUE; + // Check for damage immunities. + // Negative damage does not work on undead! + else if(sIType == "Negative" && GetRacialType(oCreature) == RACIAL_TYPE_UNDEAD) + { + if(AI_DEBUG) ai_Debug("0i_spell", "325", "Undead are immune to Negative energy!"); + return TRUE; + } + // Elemental damage resistances should be checked. + if(sIType == "Acid" || sIType == "Cold" || sIType == "Fire" || + sIType == "Electricty" || sIType == "Sonic") + { + if(ai_GetHasEffectType(oCreature, EFFECT_TYPE_DAMAGE_RESISTANCE)) + { + if(AI_DEBUG) ai_Debug("0i_spell", "334", GetName(oCreature) + " has damage resistance to my " + sIType + " spell!"); + return TRUE; + } + // Check for resistances and immunities. Treat resistance as immune. + int nIPResist = GetLocalInt(oCreature, sIPResistVarname); + if(AI_DEBUG) ai_Debug("0i_spell", "372", "nIPResist:" + IntToString(nIPResist)); + int nIPImmune = GetLocalInt(oCreature, sIPImmuneVarname) | nIPResist; + if(AI_DEBUG) ai_Debug("0i_spell", "374", "nIPImmune:" + IntToString(nIPImmune)); + if(nIPImmune > 0) + { + if(AI_DEBUG) ai_Debug("0i_spell", "391", GetName(oCreature) + " is immune/resistant to my " + sIType + " spell through an item!"); + if(sIType == "Acid" && (nIPImmune & DAMAGE_TYPE_ACID)) return TRUE; + else if(sIType == "Cold" && (nIPImmune & DAMAGE_TYPE_COLD)) return TRUE; + else if(sIType == "Fire" && (nIPImmune & DAMAGE_TYPE_FIRE)) return TRUE; + else if(sIType == "Electricity" && (nIPImmune & DAMAGE_TYPE_ELECTRICAL)) return TRUE; + else if(sIType == "Sonic" && (nIPImmune & DAMAGE_TYPE_SONIC)) return TRUE; + } + } + } + int nLevel = StringToInt(Get2DAString("spells", "Innate", nSpell)); + // Globe spells should be checked... + if((GetHasSpellEffect(SPELL_MINOR_GLOBE_OF_INVULNERABILITY, oCreature) || + GetHasSpellEffect(SPELL_GREATER_SHADOW_CONJURATION_MINOR_GLOBE, oCreature)) && + nLevel < 4 && d100() < 75) return TRUE; + if(GetHasSpellEffect(SPELL_GLOBE_OF_INVULNERABILITY, oCreature) && + nLevel < 5 && d100() < 75) return TRUE; + // Check creatures items for immunity. + int nIndex; + json jSpellImmunity = GetLocalJson(oCreature, AI_TALENT_IMMUNITY); + json jSpell = JsonArrayGet(jSpellImmunity, nIndex); + while(JsonGetType(jSpell) != JSON_TYPE_NULL) + { + if(nSpell == JsonGetInt(jSpell)) + { + if(AI_DEBUG) ai_Debug("0i_spells", "407", GetName(oCreature) + " is immune to the spell via an Item!"); + return TRUE; + } + jSpell = JsonArrayGet(jSpellImmunity, ++nIndex); + } + if(AI_DEBUG) ai_Debug("0i_spell", "347", GetName(oCreature) + " is not immune to the spell."); + return FALSE; +} +float ai_GetSpellRange(int nSpell) +{ + string sRange = Get2DAString("spells", "Range", nSpell); + if(sRange == "S") return AI_SHORT_DISTANCE; + else if(sRange == "M") return AI_MEDIUM_DISTANCE; + else if(sRange == "L") return AI_LONG_DISTANCE; + else if(sRange == "T") return AI_RANGE_MELEE; + return 0.1; +} +int ai_CreatureHasDispelableEffect(object oCaster, object oCreature) +{ + int nSpellID, nLastSpellID, bSpell, nDispelChance; + // Cycle through the targets effects. + effect eEffect = GetFirstEffect(oCreature); + if(AI_DEBUG) ai_Debug("0i_spells", "485", "nSpell: " + GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", GetEffectSpellId(eEffect)))) + + " oCreature: " + GetName(oCreature)); + while(GetIsEffectValid(eEffect)) + { + nSpellID = GetEffectSpellId(eEffect); + // -1 is not a spell. + if(AI_DEBUG) ai_Debug("0i_spells", "491", "nSpell: (" + IntToString(nSpellID) + ") " + + GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpellID)))); + if(nSpellID > -1 && nLastSpellID != nSpellID) + { + // We check if the spell is Hostile(-1) or Helpful(+1). + if(Get2DAString("ai_spells", "HostileSetting", nSpellID) == "1") nDispelChance--; + else nDispelChance++; + if(AI_DEBUG) ai_Debug("0i_spells", "497", "HostileSetting: " + Get2DAString("ai_spells", "HostileSetting", nSpellID) + + " nDispelChance: " + IntToString(nDispelChance)); + } + nLastSpellID = nSpellID; + eEffect = GetNextEffect(oCreature); + } + // if the target has more Helpful spells than harmful spells effecting them + // then use dispel! + if(AI_DEBUG) ai_Debug("0i_spells", "505", "nDispelChance: " + IntToString(nDispelChance)); + return (nDispelChance > 0); +} +void ai_RemoveASpecificEffect(object oCreature, int nEffectType) +{ + effect eEffect = GetFirstEffect(oCreature); + //Search for the effect. + while(GetIsEffectValid(eEffect)) + { + if(GetEffectType(eEffect) == nEffectType) + { + //Remove effect. + RemoveEffect(oCreature, eEffect); + eEffect = GetFirstEffect(oCreature); + } + else eEffect = GetNextEffect(oCreature); + } +} +int ai_GetHasEffectType(object oCreature, int nEffectType) +{ + effect eEffect = GetFirstEffect(oCreature); + while(GetIsEffectValid(eEffect)) + { + if(GetEffectType(eEffect, TRUE) == nEffectType) return TRUE; + eEffect = GetNextEffect(oCreature); + } + return FALSE; +} +void ai_CheckCreatureSpecialAbilities(object oCreature) +{ + int nMaxSpecialAbilities = GetSpellAbilityCount(oCreature); + if(nMaxSpecialAbilities) + { + int nIndex, bCanCast; + // Struct is id, ready, level. + int nSpell; + while(nIndex < nMaxSpecialAbilities) + { + nSpell = GetSpellAbilitySpell(oCreature, nIndex); + if(GetSpellAbilityReady(oCreature, nSpell)) + { + bCanCast = FALSE; + if(GetSpellAbilityCasterLevel(oCreature, nIndex) > 4) + { + // 1 Min/Lvl spell that is too low of level so it must be cast at 5th lvl or greater. + if(nSpell == SPELL_FLAME_WEAPON) bCanCast = TRUE; + else if(nSpell == SPELL_BLESS) bCanCast = TRUE; + else if(nSpell == SPELL_AID) bCanCast = TRUE; + else if(nSpell == SPELL_DEATH_WARD) bCanCast = TRUE; + } + if(nSpell == SPELL_ENERGY_BUFFER) bCanCast = TRUE; + else if(nSpell == SPELL_PROTECTION_FROM_ELEMENTS) bCanCast = TRUE; + else if(nSpell == SPELL_RESIST_ELEMENTS) bCanCast = TRUE; + else if(nSpell == SPELL_ENDURE_ELEMENTS) bCanCast = TRUE; + else if(nSpell == SPELL_MAGE_ARMOR) bCanCast = TRUE; + else if(nSpell == SPELL_MAGIC_VESTMENT) bCanCast = TRUE; + else if(nSpell == SPELL_GREATER_MAGIC_WEAPON) bCanCast = TRUE; + else if(nSpell == SPELL_MAGIC_WEAPON) bCanCast = TRUE; + else if(nSpell == SPELL_SUMMON_CREATURE_IX) bCanCast = TRUE; + else if(nSpell == SPELL_SUMMON_CREATURE_VIII) bCanCast = TRUE; + else if(nSpell == SPELL_SUMMON_CREATURE_VII) bCanCast = TRUE; + else if(nSpell == SPELL_SUMMON_CREATURE_VI) bCanCast = TRUE; + else if(nSpell == SPELL_SUMMON_CREATURE_V) bCanCast = TRUE; + else if(nSpell == SPELL_SUMMON_CREATURE_IV) bCanCast = TRUE; + else if(nSpell == SPELL_SUMMON_CREATURE_III) bCanCast = TRUE; + else if(nSpell == SPELL_SUMMON_CREATURE_II) bCanCast = TRUE; + else if(nSpell == SPELL_SUMMON_CREATURE_I) bCanCast = TRUE; + else if(nSpell == SPELL_BARKSKIN) bCanCast = TRUE; + else if(nSpell == SPELL_SHIELD) bCanCast = TRUE; + else if(nSpell == SPELL_ENTROPIC_SHIELD) bCanCast = TRUE; + else if(nSpell == SPELL_SHIELD_OF_FAITH) bCanCast = TRUE; + else if(nSpell == SPELL_REMOVE_FEAR) bCanCast = TRUE; + else if(nSpell == SPELL_IRONGUTS) bCanCast = TRUE; + else if(nSpell == SPELL_PREMONITION) bCanCast = TRUE; + else if(nSpell == SPELL_GREATER_STONESKIN) bCanCast = TRUE; + else if(nSpell == SPELL_GHOSTLY_VISAGE) bCanCast = TRUE; + else if(nSpell == SPELL_IMPROVED_INVISIBILITY) bCanCast = TRUE; + else if(nSpell == SPELL_INVISIBILITY_SPHERE) bCanCast = TRUE; + else if(nSpell == SPELL_INVISIBILITY) bCanCast = TRUE; + else if(nSpell == SPELL_GREATER_BULLS_STRENGTH) bCanCast = TRUE; + else if(nSpell == SPELL_BULLS_STRENGTH) bCanCast = TRUE; + else if(nSpell == SPELL_GREATER_CATS_GRACE) bCanCast = TRUE; + else if(nSpell == SPELL_CATS_GRACE) bCanCast = TRUE; + else if(nSpell == SPELL_GREATER_EAGLE_SPLENDOR) bCanCast = TRUE; + else if(nSpell == SPELL_EAGLE_SPLEDOR) bCanCast = TRUE; + else if(nSpell == SPELL_GREATER_ENDURANCE) bCanCast = TRUE; + else if(nSpell == SPELL_ENDURANCE) bCanCast = TRUE; + else if(nSpell == SPELL_GREATER_FOXS_CUNNING) bCanCast = TRUE; + else if(nSpell == SPELL_FOXS_CUNNING) bCanCast = TRUE; + else if(nSpell == SPELL_GREATER_OWLS_WISDOM) bCanCast = TRUE; + else if(nSpell == SPELL_OWLS_WISDOM) bCanCast = TRUE; + else if(nSpell == SPELL_KEEN_EDGE) bCanCast = TRUE; + else if(nSpell == SPELL_ANIMATE_DEAD) bCanCast = TRUE; + else if(nSpell == SPELL_INVISIBILITY_PURGE) bCanCast = TRUE; + else if(nSpell == SPELL_CLAIRAUDIENCE_AND_CLAIRVOYANCE) bCanCast = TRUE; + else if(nSpell == SPELL_DARKFIRE) bCanCast = TRUE; + else if(nSpell == SPELL_NEGATIVE_ENERGY_PROTECTION) bCanCast = TRUE; + else if(nSpell == SPELL_MAGIC_CIRCLE_AGAINST_GOOD) bCanCast = TRUE; + else if(nSpell == SPELL_FREEDOM_OF_MOVEMENT) bCanCast = TRUE; + else if(nSpell == SPELL_NEUTRALIZE_POISON) bCanCast = TRUE; + else if(nSpell == SPELL_MIND_BLANK) bCanCast = TRUE; + else if(nSpell == SPELL_LESSER_MIND_BLANK) bCanCast = TRUE; + else if(nSpell == SPELL_SPELL_RESISTANCE) bCanCast = TRUE; + else if(nSpell == SPELL_PROTECTION_FROM_GOOD) bCanCast = TRUE; + else if(nSpell == SPELL_CREATE_UNDEAD) bCanCast = TRUE; + else if(nSpell == SPELL_PLANAR_ALLY) bCanCast = TRUE; + else if(nSpell == SPELL_LESSER_PLANAR_BINDING) bCanCast = TRUE; + else if(nSpell == SPELL_ETHEREALNESS) bCanCast = TRUE; + else if(nSpell == SPELL_PROTECTION_FROM_SPELLS) bCanCast = TRUE; + else if(nSpell == SPELL_SHADOW_SHIELD) bCanCast = TRUE; + else if(nSpell == SPELL_CREATE_GREATER_UNDEAD) bCanCast = TRUE; + else if(nSpell == SPELL_GREATER_PLANAR_BINDING) bCanCast = TRUE; + if(bCanCast && GetSpellAbilityReady(oCreature, nIndex)) + { + ActionCastSpellAtObject(nSpell, oCreature, 255, 0, 0, 0, TRUE); + } + } + nIndex++; + } + } +} +int ai_IsSilenced(object oCreature, int nSpell) +{ + if(Get2DAString("spells", "VS", nSpell) == "s") return FALSE; + if(ai_GetHasEffectType(oCreature, EFFECT_TYPE_SILENCE)) return TRUE; + return FALSE; +} +int ai_ArcaneSpellFailureTooHigh(object oCreature, int nClass, int nLevel, int nSlot) +{ + if(AI_DEBUG) ai_Debug("0i_spells", "561", "Arcane Spells: " + Get2DAString("classes", "ASF", nClass) + + " Arcane Spell Failure: " + IntToString(GetArcaneSpellFailure(oCreature)) + + " AI_ASF_WILL_USE: " + IntToString(AI_ASF_WILL_USE)); + if(Get2DAString("classes", "ASF", nClass) == "1" && + GetArcaneSpellFailure(oCreature) > AI_ASF_WILL_USE) + { + if(GetMemorizedSpellMetaMagic(oCreature, nClass, nLevel, nSlot) == METAMAGIC_STILL) return FALSE; + return TRUE; + } + return FALSE; +} +int ai_TryToCastSpell(object oCaster, int nSpell, object oTarget) +{ + if(GetHasSpell(nSpell, oCaster) && !GetHasSpellEffect(nSpell, oTarget)) + { + ActionCastSpellAtObject(nSpell, oTarget); + return TRUE; + } + return FALSE; +} +int ai_SpellGroupNotCast(object oCreature, string sBuffGroup) +{ + return !GetLocalInt(oCreature, sBuffGroup); +} +void ai_ClearSpellsCastGroups(object oCreature) +{ + int nCounter; + for(nCounter = -1; nCounter <= AI_BUFF_GROUPS; nCounter--) + { + DeleteLocalInt(oCreature, "AI_USED_SPELL_GROUP_" + IntToString(nCounter)); + } +} +int ai_CanUseSpell(object oCaster, object oTarget, int nSpell, int nTargetType) +{ + // Should we ignore associates? + if(ai_GetAIMode(oCaster, AI_MODE_IGNORE_ASSOCIATES) && + GetAssociateType(oTarget) > 1) return FALSE; + // For ability scores we return a bonus to the ability to be checked against + // the target with the highest ability getting the spell first. + if(nTargetType == 1) // Ability score buff for strength. + { + // We don't want to buff the strength for someone using weapon finesse! + if(GetHasFeat(FEAT_WEAPON_FINESSE, oTarget)) return -5; + return TRUE; + } + if(nTargetType == 7) // Lowest AC. + { + // Stone bones only effects the undead. + if(nSpell == SPELL_STONE_BONES) + { + if(GetRacialType(oTarget) != RACIAL_TYPE_UNDEAD) return FALSE; + } + return TRUE; + } + if(nTargetType == 8) // Lowest AC without AC Bonus. + { + if(nSpell == SPELL_MAGIC_VESTMENT) + { + object oArmor = GetItemInSlot(INVENTORY_SLOT_CHEST, oTarget); + if(oArmor == OBJECT_INVALID) return FALSE; + } + return TRUE; + } + if(nTargetType == 9) // Highest Attack. + { + return TRUE; + } + if(nTargetType == 10) // Most wounded, Lowest Hp. + { + return TRUE; + } + if(nTargetType == 11) // Lowest Fortitude save. + { + return TRUE; + } + if(nTargetType == 12) // Lowest Reflex save. + { + return TRUE; + } + if(nTargetType == 13) // Lowest Will save. + { + return TRUE; + } + if(nTargetType == 14) // Lowest Save. + { + return TRUE; + } + if(nSpell == SPELL_MAGIC_FANG) + { + object oCompanion = GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION, oCaster); + if(oTarget != oCompanion) return FALSE; + } + return TRUE; +} +// Used to check if the targets weapon can be buffed by the spells effects. +int ai_CanItemBeBuffed(int nSpell, object oTarget) +{ + object oWeapon, oArmor; + if(nSpell == SPELL_MAGIC_WEAPON || nSpell == SPELL_GREATER_MAGIC_WEAPON || + nSpell == SPELL_BLADE_THIRST) + { + oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTarget); + if(!ai_GetIsMeleeWeapon(oWeapon)) return FALSE; + if(ai_GetHasItemProperty(oWeapon, ITEM_PROPERTY_ENHANCEMENT_BONUS)) return FALSE; + } + else if(nSpell == SPELL_MAGIC_VESTMENT) + { + oArmor = GetItemInSlot(INVENTORY_SLOT_CHEST, oTarget); + if(oArmor == OBJECT_INVALID) return FALSE; + if(ai_GetHasItemProperty(oArmor, ITEM_PROPERTY_AC_BONUS)) return FALSE; + } + else if(nSpell == SPELL_DARKFIRE) + { + oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTarget); + if(!ai_GetIsMeleeWeapon(oWeapon)) return FALSE; + if(ai_GetHasItemProperty(oWeapon, ITEM_PROPERTY_ON_HIT_PROPERTIES, 127)) return FALSE; + } + else if(nSpell == SPELL_FLAME_WEAPON) + { + oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTarget); + if(!ai_GetIsMeleeWeapon(oWeapon)) return FALSE; + if(ai_GetHasItemProperty(oWeapon, ITEM_PROPERTY_ON_HIT_PROPERTIES, 124)) return FALSE; + } + else if(nSpell == SPELL_KEEN_EDGE) + { + oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTarget); + if(!ai_GetIsSlashingWeapon(oWeapon)) return FALSE; + if(ai_GetHasItemProperty(oWeapon, ITEM_PROPERTY_KEEN)) return FALSE; + } + else if(nSpell == SPELL_DEAFENING_CLANG) + { + oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTarget); + if(!ai_GetIsMeleeWeapon(oWeapon)) return FALSE; + if(ai_GetHasItemProperty(oWeapon, ITEM_PROPERTY_ON_HIT_PROPERTIES, 137)) return FALSE; + } + else if(nSpell == SPELL_BLESS_WEAPON) + { + oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTarget); + if(!ai_GetIsMeleeWeapon(oWeapon)) return FALSE; + if(ai_GetHasItemProperty(oWeapon, ITEM_PROPERTY_DAMAGE_BONUS_VS_RACIAL_GROUP, IP_CONST_RACIALTYPE_UNDEAD)) return FALSE; + } + else if(nSpell == SPELL_HOLY_SWORD) + { + oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTarget); + if(!ai_GetIsMeleeWeapon(oWeapon)) return FALSE; + if(ai_GetHasItemProperty(oWeapon, ITEM_PROPERTY_HOLY_AVENGER)) return FALSE; + } + else if(nSpell == SPELL_BLACKSTAFF) + { + oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTarget); + if(GetBaseItemType(oWeapon) != BASE_ITEM_QUARTERSTAFF) return FALSE; + if(ai_GetHasItemProperty(oWeapon, ITEM_PROPERTY_ON_HIT_PROPERTIES, IP_CONST_ONHIT_DISPELMAGIC)) return FALSE; + } + return TRUE; +} +// In "Buff_Target" column the value of 0 in the "ai_spells.2da" references the Caster. +// In "Buff_Target" column this is value 1-6(STR, DEX, CON, INT, WIS, CHA) in the "ai_spells.2da". +object ai_BuffHighestAbilityScoreTarget(object oCaster, int nSpell, int nAbilityScore, string sBuffGroup, float fRange, string sTargetType = "AI_ALLY_TARGET_") +{ + if(ai_GetMagicMode(oCaster, AI_MAGIC_BUFF_MASTER)) + { + object oMaster = GetMaster(); + if(!GetHasSpellEffect(nSpell, oMaster) && + ai_SpellGroupNotCast(oMaster, sBuffGroup)) return oMaster; + } + int nCntr = 1, nAB, nHighAB, nTarget, nUseSpell; + object oTarget = GetLocalObject(oCaster, sTargetType + IntToString(nCntr)); + while (nCntr < 10) + { + if(oTarget != OBJECT_INVALID && !GetHasSpellEffect(nSpell, oTarget) && + GetDistanceBetween(oCaster, oTarget) <= fRange) + { + nUseSpell = ai_CanUseSpell(oCaster, oTarget, nSpell, nAbilityScore + 1); + if(nUseSpell == 0) {} + else + { + nAB = GetAbilityScore(oTarget, nAbilityScore) + nUseSpell; + if(nAB > nHighAB) + {nHighAB = nAB; nTarget = nCntr; } + } + } + oTarget = GetLocalObject(oCaster, sTargetType + IntToString(++nCntr)); + } + if(nTarget == 0) return OBJECT_INVALID; + else return GetLocalObject(oCaster, sTargetType + IntToString(nTarget)); +} +// In "Buff_Target" column this is value 7 in the "ai_spells.2da". +object ai_BuffLowestACTarget(object oCaster, int nSpell, string sBuffGroup, float fRange, string sTargetType = "AI_ALLY_TARGET_") +{ + object oMaster = GetMaster(); + if(ai_GetMagicMode(oCaster, AI_MAGIC_BUFF_MASTER)) + { + if(!GetHasSpellEffect(nSpell, oMaster) && + ai_SpellGroupNotCast(oMaster, sBuffGroup) && + ai_CanUseSpell(oCaster, oMaster, nSpell, 7)) return oMaster; + } + int nCntr = 1, nAC, nLowAC = 100, nTarget; + object oTarget = GetLocalObject(oCaster, sTargetType + IntToString(nCntr)); + while (nCntr < 10) + { + if(oTarget != OBJECT_INVALID && !GetHasSpellEffect(nSpell, oTarget) && + GetDistanceBetween(oCaster, oTarget) <= fRange && ai_SpellGroupNotCast(oTarget, sBuffGroup)) + { + nAC = GetAC(oTarget); + if(nAC < nLowAC && ai_CanUseSpell(oCaster, oTarget, nSpell, 7)) + {nLowAC = nAC; nTarget = nCntr; } + } + oTarget = GetLocalObject(oCaster, sTargetType + IntToString(++nCntr)); + } + if(nTarget == 0) return OBJECT_INVALID; + oTarget = GetLocalObject(oCaster, sTargetType + IntToString(nTarget)); + return oTarget; +} +// In "Buff_Target" column this is value 8 in the "ai_spells.2da". +object ai_BuffLowestACWithOutACBonus(object oCaster, int nSpell, string sBuffGroup, float fRange, string sTargetType = "AI_ALLY_TARGET_") +{ + if(ai_GetMagicMode(oCaster, AI_MAGIC_BUFF_MASTER)) + { + object oMaster = GetMaster(); + if(!GetHasSpellEffect(nSpell, oMaster) && + ai_SpellGroupNotCast(oMaster, sBuffGroup) && + ai_CanUseSpell(oCaster, oMaster, nSpell, 8)) return oMaster; + } + int nCntr = 1, nAC, nLowAC = 50, nTarget; + object oItem, oTarget = GetLocalObject(oCaster, sTargetType + IntToString(nCntr)); + while (nCntr < 10) + { + if(oTarget != OBJECT_INVALID && !GetHasSpellEffect(nSpell, oTarget) && + GetDistanceBetween(oCaster, oTarget) <= fRange && ai_SpellGroupNotCast(oTarget, sBuffGroup)) + { + nAC = GetAC(oTarget); + oItem = GetItemInSlot(INVENTORY_SLOT_CHEST, oTarget); + if(nAC < nLowAC && ai_CanUseSpell(oCaster, oTarget, nSpell, 8) && + !GetItemHasItemProperty(oItem, ITEM_PROPERTY_AC_BONUS)) + { + nLowAC = nAC; + nTarget = nCntr; + } + } + oTarget = GetLocalObject(oCaster, sTargetType + IntToString(++nCntr)); + } + if(nTarget == 0) return OBJECT_INVALID; + else return GetLocalObject(oCaster, sTargetType + IntToString(nTarget)); +} +// In "Buff_Target" column this is value 9 in the "ai_spells.2da". +object ai_BuffHighestAttackTarget(object oCaster, int nSpell, string sBuffGroup, float fRange, string sTargetType = "AI_ALLY_TARGET_") +{ + if(ai_GetMagicMode(oCaster, AI_MAGIC_BUFF_MASTER)) + { + object oMaster = GetMaster(); + if(!GetHasSpellEffect(nSpell, oMaster) && + ai_SpellGroupNotCast(oMaster, sBuffGroup) && + ai_CanUseSpell(oCaster, oMaster, nSpell, 9)) return oMaster; + } + int nCntr = 1, nAtk, nHighAtk, nTarget; + object oTarget = GetLocalObject(oCaster, sTargetType + IntToString(nCntr)); + while (nCntr < 10) + { + if(oTarget != OBJECT_INVALID && !GetHasSpellEffect(nSpell, oTarget) && + GetDistanceBetween(oCaster, oTarget) <= fRange && ai_SpellGroupNotCast(oTarget, sBuffGroup)) + { + nAtk = GetBaseAttackBonus(oTarget); + if(nAtk > nHighAtk && ai_CanUseSpell(oCaster, oTarget, nSpell, 9)) + {nHighAtk = nAtk; nTarget = nCntr; } + } + oTarget = GetLocalObject(oCaster, sTargetType + IntToString(++nCntr)); + } + if(nTarget == 0) return OBJECT_INVALID; + oTarget = GetLocalObject(oCaster, sTargetType + IntToString(nTarget)); + return oTarget; +} +// In "Buff_Target" column this is value 10 in the "ai_spells.2da". +object ai_BuffMostWoundedTarget(object oCaster, int nSpell, string sBuffGroup, float fRange, string sTargetType = "AI_ALLY_TARGET_") +{ + if(ai_GetMagicMode(oCaster, AI_MAGIC_BUFF_MASTER)) + { + object oMaster = GetMaster(); + if(!GetHasSpellEffect(nSpell, oMaster) && + ai_SpellGroupNotCast(oMaster, sBuffGroup) && + ai_CanUseSpell(oCaster, oMaster, nSpell, 9)) return oMaster; + } + int nCntr = 1, nDmg, nMostDmg, nHp, nLowHp = 10000, nTarget, nHpTarget; + object oTarget = GetLocalObject(oCaster, sTargetType + IntToString(nCntr)); + while (nCntr < 10) + { + if(oTarget != OBJECT_INVALID && !GetHasSpellEffect(nSpell, oTarget) && + GetDistanceBetween(oCaster, oTarget) <= fRange && + ai_SpellGroupNotCast(oTarget, sBuffGroup) && + ai_CanUseSpell(oCaster, oTarget, nSpell, 10)) + { + nHp = GetCurrentHitPoints(oTarget); + nDmg = GetMaxHitPoints(oTarget) - nHp; + if(nDmg > nMostDmg) { nMostDmg = nDmg; nTarget = nCntr; } + if(nHp < nLowHp) { nLowHp = nHp; nHpTarget = nCntr; } + } + // If no one is damage then put regeneration on the lowest hp target. + if(nMostDmg == 0) nTarget = nHpTarget; + oTarget = GetLocalObject(oCaster, sTargetType + IntToString(++nCntr)); + } + if(nTarget == 0) return OBJECT_INVALID; + else return GetLocalObject(oCaster, sTargetType + IntToString(nTarget)); +} +// In "Buff_Target" column this is value 11 in the "ai_spells.2da". +object ai_BuffLowestFortitudeSaveTarget(object oCaster, int nSpell, string sBuffGroup, float fRange, string sTargetType = "AI_ALLY_TARGET_") +{ + if(ai_GetMagicMode(oCaster, AI_MAGIC_BUFF_MASTER)) + { + object oMaster = GetMaster(); + if(!GetHasSpellEffect(nSpell, oMaster) && + ai_SpellGroupNotCast(oMaster, sBuffGroup) && + ai_CanUseSpell(oCaster, oMaster, nSpell, 11)) return oMaster; + } + int nCntr = 1, nSave, nLowSave = 100, nTarget; + object oTarget = GetLocalObject(oCaster, sTargetType + IntToString(nCntr)); + while (nCntr < 10) + { + if(oTarget != OBJECT_INVALID && !GetHasSpellEffect(nSpell, oTarget) && + GetDistanceBetween(oCaster, oTarget) <= fRange && ai_SpellGroupNotCast(oTarget, sBuffGroup)) + { + nSave = GetFortitudeSavingThrow(oTarget); + if(nSave < nLowSave && ai_CanUseSpell(oCaster, oTarget, nSpell, 11)) + {nLowSave = nSave; nTarget = nCntr; } + } + oTarget = GetLocalObject(oCaster, sTargetType + IntToString(++nCntr)); + } + if(nTarget == 0) return OBJECT_INVALID; + else return GetLocalObject(oCaster, sTargetType + IntToString(nTarget)); +} +// In "Buff_Target" column this is value 12 in the "ai_spells.2da". +object ai_BuffLowestReflexSaveTarget(object oCaster, int nSpell, string sBuffGroup, float fRange, string sTargetType = "AI_ALLY_TARGET_") +{ + if(ai_GetMagicMode(oCaster, AI_MAGIC_BUFF_MASTER)) + { + object oMaster = GetMaster(); + if(!GetHasSpellEffect(nSpell, oMaster) && + ai_SpellGroupNotCast(oMaster, sBuffGroup) && + ai_CanUseSpell(oCaster, oMaster, nSpell, 12)) return oMaster; + } + int nCntr = 1, nSave, nLowSave = 100, nTarget; + object oTarget = GetLocalObject(oCaster, sTargetType + IntToString(nCntr)); + while (nCntr < 10) + { + if(oTarget != OBJECT_INVALID && !GetHasSpellEffect(nSpell, oTarget) && + GetDistanceBetween(oCaster, oTarget) <= fRange && ai_SpellGroupNotCast(oTarget, sBuffGroup)) + { + nSave = GetReflexSavingThrow(oTarget); + if(nSave < nLowSave && ai_CanUseSpell(oCaster, oTarget, nSpell, 12)) + {nLowSave = nSave; nTarget = nCntr; } + } + oTarget = GetLocalObject(oCaster, sTargetType + IntToString(++nCntr)); + } + if(nTarget == 0) return OBJECT_INVALID; + else return GetLocalObject(oCaster, sTargetType + IntToString(nTarget)); +} +// In "Buff_Target" column this is value 13 in the "ai_spells.2da". +object ai_BuffLowestWillSaveTarget(object oCaster, int nSpell, string sBuffGroup, float fRange, string sTargetType = "AI_ALLY_TARGET_") +{ + if(ai_GetMagicMode(oCaster, AI_MAGIC_BUFF_MASTER)) + { + object oMaster = GetMaster(); + if(!GetHasSpellEffect(nSpell, oMaster) && + ai_SpellGroupNotCast(oMaster, sBuffGroup) && + ai_CanUseSpell(oCaster, oMaster, nSpell, 13)) return oMaster; + } + int nCntr = 1, nSave, nLowSave = 100, nTarget; + object oTarget = GetLocalObject(oCaster, sTargetType + IntToString(nCntr)); + while (nCntr < 10) + { + if(oTarget != OBJECT_INVALID && !GetHasSpellEffect(nSpell, oTarget) && + GetDistanceBetween(oCaster, oTarget) <= fRange && ai_SpellGroupNotCast(oTarget, sBuffGroup)) + { + nSave = GetWillSavingThrow(oTarget); + if(nSave < nLowSave && ai_CanUseSpell(oCaster, oTarget, nSpell, 13)) + {nLowSave = nSave; nTarget = nCntr; } + } + oTarget = GetLocalObject(oCaster, sTargetType + IntToString(++nCntr)); + } + if(nTarget == 0) return OBJECT_INVALID; + else return GetLocalObject(oCaster, sTargetType + IntToString(nTarget)); +} +// In "Buff_Target" column this is value 14 in the "ai_spells.2da". +object ai_BuffLowestSaveTarget(object oCaster, int nSpell, string sBuffGroup, float fRange, string sTargetType = "AI_ALLY_TARGET_") +{ + if(ai_GetMagicMode(oCaster, AI_MAGIC_BUFF_MASTER)) + { + object oMaster = GetMaster(); + if(!GetHasSpellEffect(nSpell, oMaster) && + ai_SpellGroupNotCast(oMaster, sBuffGroup) && + ai_CanUseSpell(oCaster, oMaster, nSpell, 14)) return oMaster; + } + int nCntr = 1, nSave, nLowSave = 200, nTarget; + object oTarget = GetLocalObject(oCaster, sTargetType + IntToString(nCntr)); + while (nCntr < 10) + { + if(oTarget != OBJECT_INVALID && !GetHasSpellEffect(nSpell, oTarget) && + GetDistanceBetween(oCaster, oTarget) <= fRange && ai_SpellGroupNotCast(oTarget, sBuffGroup)) + { + nSave = GetFortitudeSavingThrow(oTarget) + GetReflexSavingThrow(oTarget) + GetWillSavingThrow(oTarget); + if(nSave < nLowSave && ai_CanUseSpell(oCaster, oTarget, nSpell, 14)) + {nLowSave = nSave; nTarget = nCntr; } + } + oTarget = GetLocalObject(oCaster, sTargetType + IntToString(++nCntr)); + } + if(nTarget == 0) return OBJECT_INVALID; + else return GetLocalObject(oCaster, sTargetType + IntToString(nTarget)); +} +// In "Buff_Target" column this is value 15 in the "ai_spells.2da". +object ai_BuffItemTarget(object oCaster, int nSpell, string sBuffGroup, float fRange, string sTargetType = "AI_ALLY_TARGET_") +{ + if(ai_GetMagicMode(oCaster, AI_MAGIC_BUFF_MASTER)) + { + object oMaster = GetMaster(); + if(ai_CanItemBeBuffed(nSpell, oMaster) && + ai_SpellGroupNotCast(oMaster, sBuffGroup)) return oMaster; + } + int nCntr = 1, nAtk, nHighAtk = -9999, nTarget; + object oTarget = GetLocalObject(oCaster, sTargetType + IntToString(nCntr)); + while (nCntr < 10) + { + if(oTarget != OBJECT_INVALID && ai_CanItemBeBuffed(nSpell, oTarget) && + GetDistanceBetween(oCaster, oTarget) <= fRange && ai_SpellGroupNotCast(oTarget, sBuffGroup)) + { + nAtk = GetBaseAttackBonus(oTarget); + if(nAtk > nHighAtk) + { nHighAtk = nAtk; nTarget = nCntr; } + } + oTarget = GetLocalObject(oCaster, sTargetType + IntToString(++nCntr)); + } + if(nTarget == 0) return OBJECT_INVALID; + oTarget = GetLocalObject(oCaster, sTargetType + IntToString(nTarget)); + return oTarget; +} +object ai_GetBuffTarget(object oCaster, int nSpell) +{ + object oTarget = OBJECT_INVALID; + string sGroup = Get2DAString("ai_spells", "Buff_Group", nSpell); + if(sGroup == "") sGroup = IntToString(nSpell); + string sBuffGroup = "AI_USED_SPELL_GROUP_" + sGroup; + string sBuffTarget = Get2DAString("ai_spells", "Buff_Target", nSpell); + if(AI_DEBUG) ai_Debug("0i_spells", "769", "BuffTarget: " + sBuffTarget); + if(sBuffTarget == "0") + { + if(ai_SpellGroupNotCast(oCaster, sBuffGroup) && + !GetHasSpellEffect(nSpell, oCaster) && + ai_CanUseSpell(oCaster, oTarget, nSpell, 0)) + { + oTarget = oCaster; + } + } + else if(sBuffTarget == "1") + oTarget = ai_BuffHighestAbilityScoreTarget(oCaster, nSpell, ABILITY_STRENGTH, "", AI_RANGE_BATTLEFIELD); + else if(sBuffTarget == "2") + oTarget = ai_BuffHighestAbilityScoreTarget(oCaster, nSpell, ABILITY_DEXTERITY, "", AI_RANGE_BATTLEFIELD); + else if(sBuffTarget == "3") + oTarget = ai_BuffHighestAbilityScoreTarget(oCaster, nSpell, ABILITY_CONSTITUTION, "", AI_RANGE_BATTLEFIELD); + else if(sBuffTarget == "4") + oTarget = ai_BuffHighestAbilityScoreTarget(oCaster, nSpell, ABILITY_INTELLIGENCE, "", AI_RANGE_BATTLEFIELD); + else if(sBuffTarget == "5") + oTarget = ai_BuffHighestAbilityScoreTarget(oCaster, nSpell, ABILITY_WISDOM, "", AI_RANGE_BATTLEFIELD); + else if(sBuffTarget == "6") + oTarget = ai_BuffHighestAbilityScoreTarget(oCaster, nSpell, ABILITY_CHARISMA, "", AI_RANGE_BATTLEFIELD); + else if(sBuffTarget == "7") + oTarget = ai_BuffLowestACTarget(oCaster, nSpell, sBuffGroup, AI_RANGE_BATTLEFIELD); + else if(sBuffTarget == "8") + oTarget = ai_BuffLowestACWithOutACBonus(oCaster, nSpell, sBuffGroup, AI_RANGE_BATTLEFIELD); + else if(sBuffTarget == "9") + oTarget = ai_BuffHighestAttackTarget(oCaster, nSpell, sBuffGroup, AI_RANGE_BATTLEFIELD); + else if(sBuffTarget == "10") + oTarget = ai_BuffMostWoundedTarget(oCaster, nSpell, sBuffGroup, AI_RANGE_BATTLEFIELD); + else if(sBuffTarget == "11") + oTarget = ai_BuffLowestFortitudeSaveTarget(oCaster, nSpell, sBuffGroup, AI_RANGE_BATTLEFIELD); + else if(sBuffTarget == "12") + oTarget = ai_BuffLowestReflexSaveTarget(oCaster, nSpell, sBuffGroup, AI_RANGE_BATTLEFIELD); + else if(sBuffTarget == "13") + oTarget = ai_BuffLowestWillSaveTarget(oCaster, nSpell, sBuffGroup, AI_RANGE_BATTLEFIELD); + else if(sBuffTarget == "14") + oTarget = ai_BuffLowestSaveTarget(oCaster, nSpell, sBuffGroup, AI_RANGE_BATTLEFIELD); + else if(sBuffTarget == "15") + oTarget = ai_BuffItemTarget(oCaster, nSpell, sBuffGroup, AI_RANGE_BATTLEFIELD); + if(oTarget != OBJECT_INVALID) + { + SetLocalInt(oTarget, sBuffGroup, TRUE); + DelayCommand(6.0, DeleteLocalInt(oTarget, sBuffGroup)); + } + if(AI_DEBUG) ai_Debug("0i_spells", "939", GetName(oCaster) + " is targeting " + GetName(oTarget) + + " with " + GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))) + " spell" + + " sBuffGroup: " + sBuffGroup + "."); + return oTarget; +} +void ai_CastMemorizedSpell(object oCaster, int nClass, int nSpellLevel, int nSpellSlot, object oTarget, int bInstant, object oPC = OBJECT_INVALID) +{ + int nDomain; + int nSpell = GetMemorizedSpellId(oCaster, nClass, nSpellLevel, nSpellSlot); + if(GetMemorizedSpellIsDomainSpell(oCaster, nClass, nSpellLevel, nSpellSlot) == 1) nDomain = nSpellLevel; + else nDomain = 0; + int nMetaMagic = GetMemorizedSpellMetaMagic(oCaster, nClass, nSpellLevel, nSpellSlot); + if(AI_DEBUG) ai_Debug("0i_spells", "951", "nSpell: " + IntToString(nSpell) + " oTarget: " + GetName(oTarget) + + " nMetaMagic: " + IntToString(nMetaMagic) + " nDomain: " + IntToString(nDomain) + + " bInstant: " + IntToString(bInstant) + " nClass: " + IntToString(nClass)); + ActionCastSpellAtObject(nSpell, oTarget, nMetaMagic, FALSE, nDomain, 0, bInstant); + // Right now I cannot get nClass to work here... + //DelayCommand(fDelay, ActionCastSpellAtObject(nSpell, oTarget, nMetaMagic, FALSE, nDomain, 0, TRUE, nClass)); + if(oPC != OBJECT_INVALID) + { + string sSpellName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); + ai_SendMessages(GetName(oCaster) + " has cast " + sSpellName + " on " + GetName(oTarget) + ".", AI_COLOR_GREEN, oPC); + } +} +void ai_CastKnownSpell(object oCaster, int nClass, int nSpell, object oTarget, int bInstant, object oPC = OBJECT_INVALID) +{ + if(AI_DEBUG) ai_Debug("0i_Spells", "965", GetName(oCaster) + " is casting " + IntToString(nSpell)); + ActionCastSpellAtObject(nSpell, oTarget, 255, FALSE, 0, 0, bInstant); + // Right now I cannot get nClass to work here... + //ActionCastSpellAtObject(nSpell, oTarget, 255, FALSE, 0, 0, TRUE, nClass); + if(oPC != OBJECT_INVALID) + { + string sSpellName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); + ai_SendMessages(GetName(oCaster) + " has cast " + sSpellName + " on " + GetName(oTarget) + ".", AI_COLOR_GREEN, oPC); + } +} +int ai_CheckAndCastSpell(object oCaster, int nSpell, int nSpellGroup, float fDelay, object oTarget, object oPC = OBJECT_INVALID) +{ + int nClassCnt = 1, nClass, nMaxSlot, nSpellLevel, nSpellSlot, nMemorizedSpell, nDomain, nMetaMagic; + string sSpellName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); + while(nClassCnt <= AI_MAX_CLASSES_PER_CHARACTER && nClass != CLASS_TYPE_INVALID) + { + nClass = GetClassByPosition(nClassCnt); + // Search all memorized spells for the spell. + if(Get2DAString("classes", "MemorizesSpells", nClass) == "1") + { + // Check each level starting with the highest to lowest. + nSpellLevel = 0; + while(nSpellLevel < 10) + { + // Check each slot within each level. + nMaxSlot = GetMemorizedSpellCountByLevel(oCaster, nClass, nSpellLevel); + nSpellSlot = 0; + while(nSpellSlot < nMaxSlot) + { + if(GetMemorizedSpellReady(oCaster, nClass, nSpellLevel, nSpellSlot)) + { + nMemorizedSpell = GetMemorizedSpellId(oCaster, nClass, nSpellLevel, nSpellSlot); + if(nMemorizedSpell == nSpell) + { + ai_CastMemorizedSpell(oCaster, nClass, nSpellLevel, nSpellSlot, oTarget, FALSE, oPC); + return TRUE; + } + } + nSpellSlot++; + } + nSpellLevel++; + } + } + // Check non-memorized known lists for the spell. + else if(GetSpellUsesLeft(oCaster, nClass, nSpell)) + { + ai_CastKnownSpell(oCaster, nClass, nSpell, oTarget, FALSE, oPC); + return TRUE; + } + nClassCnt++; + } + return FALSE; +} +void ai_SetupMonsterBuffTargets(object oCaster) +{ + if(AI_DEBUG) ai_Debug("0i_spells", "1020", GetName(oCaster) + " is setting buff targets."); + SetLocalObject (oCaster, "AI_ALLY_TARGET_1" , oCaster); + SetLocalObject (oCaster, "AI_ALLY_TARGET_2", oCaster); + int nCntr = 1; + object oCreature = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_FRIEND, oCaster, nCntr); + if(AI_DEBUG) ai_Debug("0i_spells", "864", GetName(oCreature) + " nCntr: " + IntToString(nCntr) + + " Distance: " + FloatToString(GetDistanceBetween(oCaster, oCreature), 0, 2)); + while(oCreature != OBJECT_INVALID && nCntr < 8 && GetDistanceBetween(oCaster, oCreature) < AI_RANGE_CLOSE) + { + if(AI_DEBUG) ai_Debug("0i_spells", "1133", "Setting " + GetName(oCreature) + " as AI_ALLY_TARGET_" + IntToString(nCntr + 2)); + SetLocalObject (oCaster, "AI_ALLY_TARGET_" + IntToString(nCntr + 2), oCreature); + oCreature = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_FRIEND, oCaster, ++nCntr); + if(AI_DEBUG) ai_Debug("0i_spells", "1136", GetName(oCreature) + " nCntr: " + IntToString(nCntr) + + " Distance: " + FloatToString(GetDistanceBetween(oCaster, oCreature), 0, 2)); + } +} +void ai_SetupAllyTargets(object oCaster, object oPC) +{ + // Setup our targets. + int nTarget; + if(oCaster != oPC) SetLocalObject (oCaster, "AI_ALLY_TARGET_" + IntToString(++nTarget), oPC); + SetLocalObject(oCaster, "AI_ALLY_TARGET_" + IntToString(++nTarget), oCaster); + object oCreature = GetAssociate(ASSOCIATE_TYPE_FAMILIAR, oPC); + if(oCreature != OBJECT_INVALID) SetLocalObject(oCaster, "AI_ALLY_TARGET_" + IntToString(++nTarget), oCreature); + oCreature = GetAssociate(ASSOCIATE_TYPE_FAMILIAR, oCaster); + if(oCreature != OBJECT_INVALID) SetLocalObject(oCaster, "AI_ALLY_TARGET_" + IntToString(++nTarget), oCreature); + oCreature = GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION, oPC); + if(oCreature != OBJECT_INVALID) SetLocalObject(oCaster, "AI_ALLY_TARGET_" + IntToString(++nTarget), oCreature); + oCreature = GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION, oCaster); + if(oCreature != OBJECT_INVALID) SetLocalObject(oCaster, "AI_ALLY_TARGET_" + IntToString(++nTarget), oCreature); + oCreature = GetAssociate(ASSOCIATE_TYPE_SUMMONED, oPC); + if(oCreature != OBJECT_INVALID) SetLocalObject(oCaster, "AI_ALLY_TARGET_" + IntToString(++nTarget), oCreature); + oCreature = GetAssociate(ASSOCIATE_TYPE_SUMMONED, oCaster); + if(oCreature != OBJECT_INVALID) SetLocalObject(oCaster, "AI_ALLY_TARGET_" + IntToString(++nTarget), oCreature); + oCreature = GetAssociate(ASSOCIATE_TYPE_DOMINATED, oPC); + if(oCreature != OBJECT_INVALID) SetLocalObject(oCaster, "AI_ALLY_TARGET_" + IntToString(++nTarget), oCreature); + oCreature = GetAssociate(ASSOCIATE_TYPE_DOMINATED, oCaster); + if(oCreature != OBJECT_INVALID) SetLocalObject(oCaster, "AI_ALLY_TARGET_" + IntToString(++nTarget), oCreature); + int nCntr = 1; + int nMaxHenchman = GetMaxHenchmen() + nTarget; + object oHenchman = GetHenchman(oPC, nCntr); + while(oHenchman != OBJECT_INVALID && nCntr <= nMaxHenchman) + { + if(oHenchman == OBJECT_INVALID) break; + if(oHenchman != oCaster) SetLocalObject(oCaster, "AI_ALLY_TARGET_" + IntToString(++nTarget), oHenchman); + oHenchman = GetHenchman(oPC, ++nCntr); + } + nCntr = 1; + while(nCntr <= nMaxHenchman) + { + if(AI_DEBUG) ai_Debug("0i_spells", "1166", "AI_ALLY_TARGET_" + IntToString(nCntr) + ": " + + GetName(GetLocalObject(oCaster, "AI_ALLY_TARGET_" + IntToString(nCntr)))); + nCntr++; + } +} +void ai_SetupAllyHealingTargets(object oCaster, object oPC) +{ + int nMaxHenchman = 1; + if(oPC == OBJECT_INVALID) oPC = oCaster; + if(ai_GetAIMode(oCaster, AI_MODE_PARTY_HEALING_OFF)) + { + if(!ai_GetAIMode(oCaster, AI_MODE_SELF_HEALING_OFF)) SetLocalObject(oCaster, "AI_ALLY_HEAL_1", oCaster); + } + else + { + int nTarget; + if(oCaster != oPC) + { + SetLocalObject (oCaster, "AI_ALLY_HEAL_1", oPC); + nTarget++; + } + if(!ai_GetAIMode(oCaster, AI_MODE_SELF_HEALING_OFF)) + { + SetLocalObject(oCaster, "AI_ALLY_HEAL_" + IntToString(++nTarget), oCaster); + } + object oCreature = GetAssociate(ASSOCIATE_TYPE_FAMILIAR, oPC); + if(oCreature != OBJECT_INVALID) SetLocalObject(oCaster, "AI_ALLY_HEAL_" + IntToString(++nTarget), oCreature); + oCreature = GetAssociate(ASSOCIATE_TYPE_FAMILIAR, oCaster); + if(oCreature != OBJECT_INVALID) SetLocalObject(oCaster, "AI_ALLY_HEAL_" + IntToString(++nTarget), oCreature); + oCreature = GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION, oPC); + if(oCreature != OBJECT_INVALID) SetLocalObject(oCaster, "AI_ALLY_HEAL_" + IntToString(++nTarget), oCreature); + oCreature = GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION, oCaster); + if(oCreature != OBJECT_INVALID) SetLocalObject(oCaster, "AI_ALLY_HEAL_" + IntToString(++nTarget), oCreature); + oCreature = GetAssociate(ASSOCIATE_TYPE_SUMMONED, oPC); + if(oCreature != OBJECT_INVALID) SetLocalObject(oCaster, "AI_ALLY_HEAL_" + IntToString(++nTarget), oCreature); + oCreature = GetAssociate(ASSOCIATE_TYPE_SUMMONED, oCaster); + if(oCreature != OBJECT_INVALID) SetLocalObject(oCaster, "AI_ALLY_HEAL_" + IntToString(++nTarget), oCreature); + oCreature = GetAssociate(ASSOCIATE_TYPE_DOMINATED, oPC); + if(oCreature != OBJECT_INVALID) SetLocalObject(oCaster, "AI_ALLY_HEAL_" + IntToString(++nTarget), oCreature); + oCreature = GetAssociate(ASSOCIATE_TYPE_DOMINATED, oCaster); + if(oCreature != OBJECT_INVALID) SetLocalObject(oCaster, "AI_ALLY_HEAL_" + IntToString(++nTarget), oCreature); + int nCntr = 1; + nMaxHenchman = GetMaxHenchmen() + nTarget; + object oHenchman = GetHenchman(oPC, nCntr); + while(oHenchman != OBJECT_INVALID && nTarget <= nMaxHenchman) + { + if(oHenchman == OBJECT_INVALID) break; + if(oHenchman != oCaster) SetLocalObject(oCaster, "AI_ALLY_HEAL_" + IntToString(++nTarget), oHenchman); + oHenchman = GetHenchman(oPC, ++nCntr); + } + } + int nCntr = 1; + while(nCntr <= nMaxHenchman) + { + if(AI_DEBUG) ai_Debug("0i_spells", "1211", "AI_ALLY_HEAL_" + IntToString(nCntr) + ": " + + GetName(GetLocalObject(oCaster, "AI_ALLY_HEAL_" + IntToString(nCntr++)))); + } +} +void ai_ClearBuffTargets(object oCaster, string sVariable) +{ + if(AI_DEBUG) ai_Debug("0i_spells", "1216", GetName(oCaster) + " is clearing " + sVariable + " targets."); + int nIndex; + int nMaxTargets = GetMaxHenchmen() + 6; + for(nIndex = 1; nIndex < nMaxTargets; nIndex++) + { + DeleteLocalObject (oCaster, sVariable + IntToString(nIndex)); + } +} +void ai_CheckForPerDayProperties(object oCreature, object oItem, int nBuffType, int bEquiped = FALSE) +{ + if(AI_DEBUG) ai_Debug("0i_spells", "1150", "Checking Item properties on " + GetName(oItem)); + // We have established that we can use the item if it is equiped. + if(!bEquiped && !ai_CheckIfCanUseItem(oCreature, oItem)) return; + int nPerDay, nCharges, nUses, nSpellBuffDuration; + int nIprpSubType, nSpell, nLevel, nIPType, nIndex; + object oTarget; + itemproperty ipProp = GetFirstItemProperty(oItem); + // Lets skip this if there are no properties. + if(!GetIsItemPropertyValid(ipProp)) return; + // Check for cast spell property and add them to the talent list. + while(GetIsItemPropertyValid(ipProp)) + { + if(AI_DEBUG) ai_Debug("0i_spells", "1163", "ItempropertyType(15): " + IntToString(GetItemPropertyType(ipProp))); + nIPType = GetItemPropertyType(ipProp); + if(nIPType == ITEM_PROPERTY_CAST_SPELL) + { + // Get how they use the item (charges or uses per day). + nUses = GetItemPropertyCostTableValue(ipProp); + // We only check uses per day. + if(AI_DEBUG) ai_Debug("0i_spells", "1172", "Item uses: " + IntToString(nPerDay)); + if(nUses > 7 && nUses < 13) + { + nPerDay = GetItemPropertyUsesPerDayRemaining(oItem, ipProp); + if(AI_DEBUG) ai_Debug("0i_spells", "1176", "Item uses per day: " + IntToString(nPerDay)); + if(nPerDay > 0) + { + // SubType is the ip spell index for iprp_spells.2da + nIprpSubType = GetItemPropertySubType(ipProp); + nSpell = StringToInt(Get2DAString("iprp_spells", "SpellIndex", nIprpSubType)); + nSpellBuffDuration = StringToInt(Get2DAString("ai_spells", "Buff_Duration", nSpell)); + if(AI_DEBUG) ai_Debug("0i_spells", "1183", "nSpell: " + IntToString(nSpell) + + " nBuffType: " + IntToString(nBuffType) + + " nSpellBuffDuration: " + IntToString(nSpellBuffDuration)); + if(nBuffType == nSpellBuffDuration || nBuffType == 1) + { + oTarget = ai_GetBuffTarget(oCreature, nSpell); + if(oTarget != OBJECT_INVALID) + { + if(AI_DEBUG) ai_Debug("0i_spells", "1190", GetName(oCreature) + " is using" + + GetName(oItem) + " to cast " + IntToString(nSpell) + + " on " + GetName(oTarget)); + ActionUseItemOnObject(oItem, ipProp, oTarget); + } + } + } + } + } + ipProp = GetNextItemProperty(oItem); + } +} +void ai_CheckForPerDayItems(object oCreature, object oPC, int nBuffType) +{ + if(AI_DEBUG) ai_Debug("0i_spells", "1198", GetName(oCreature) + ": Checking items for per day buffs."); + if(!ai_GetMagicMode(oCreature, AI_MAGIC_NO_MAGIC_ITEMS)) + { + int bEquiped; + string sSlots; + // Cycle through all the creatures inventory items. + object oItem = GetFirstItemInInventory(oCreature); + while(oItem != OBJECT_INVALID) + { + if(GetIdentified(oItem)) + { + // Does the item need to be equiped to use its powers? + sSlots = Get2DAString("baseitems", "EquipableSlots", GetBaseItemType(oItem)); + if(AI_DEBUG) ai_Debug("0i_talents", "1211", GetName(oItem) + " requires " + Get2DAString("baseitems", "EquipableSlots", GetBaseItemType(oItem)) + " slots."); + if(sSlots == "0x00000") ai_CheckForPerDayProperties(oCreature, oItem, nBuffType); + } + oItem = GetNextItemInInventory(oCreature); + } + int nSlot; + // Cycle through all the creatures equiped items. + oItem = GetItemInSlot(nSlot, oCreature); + while(nSlot < 11) + { + if(oItem != OBJECT_INVALID) ai_CheckForPerDayProperties(oCreature, oItem, nBuffType, TRUE); + oItem = GetItemInSlot(++nSlot, oCreature); + } + oItem = GetItemInSlot(INVENTORY_SLOT_CARMOUR, oCreature); + if(oItem != OBJECT_SELF) ai_CheckForPerDayProperties(oCreature, oItem, nBuffType, TRUE); + } + // Clean up our variables. Must be done here since these are actions! + int nCntr; + object oTarget; + while(nCntr < 11) + { + oTarget = GetLocalObject(oCreature, "AI_ALLY_TARGET_" + IntToString(nCntr)); + if(oTarget != OBJECT_INVALID) + { + ai_ClearSpellsCastGroups(oTarget); + DeleteLocalObject(oCreature, "AI_ALLY_TARGET_" + IntToString(nCntr)); + } + nCntr++; + } +} +void ai_CheckForBuffSpells(struct stSpell stSpell) +{ + ai_SetupAllyTargets(stSpell.oCaster, stSpell.oPC); + stSpell.nPosition = 1; + stSpell.nClass = GetClassByPosition(stSpell.nPosition, stSpell.oCaster); + stSpell.nLevel = (GetLevelByPosition(stSpell.nPosition, stSpell.oCaster) + 1) / 2; + stSpell.nMaxSlots = GetMemorizedSpellCountByLevel(stSpell.oCaster, stSpell.nClass, stSpell.nLevel); + stSpell.nSlot = 0; + while(stSpell.nPosition <= AI_MAX_CLASSES_PER_CHARACTER) + { + stSpell.nClass = GetClassByPosition(stSpell.nPosition, stSpell.oCaster); + if(AI_DEBUG) ai_Debug("0i_spells", "1208", "nClass: " + IntToString(stSpell.nClass)); + if(stSpell.nClass == CLASS_TYPE_INVALID) break; + if(AI_DEBUG) ai_Debug("0i_spells", "1210", "SpellCaster: " + Get2DAString("classes", "SpellCaster", stSpell.nClass)); + if(Get2DAString("classes", "SpellCaster", stSpell.nClass) == "1") + { + stSpell.nLevel = (GetLevelByPosition(stSpell.nPosition, stSpell.oCaster) + 1) / 2; + if(AI_DEBUG) ai_Debug("0i_spells", "1214", "Memorizes Spells: " + Get2DAString("classes", "MemorizesSpells", stSpell.nClass)); + if(Get2DAString("classes", "MemorizesSpells", stSpell.nClass) == "1") + { + stSpell.nMaxSlots = GetMemorizedSpellCountByLevel(stSpell.oCaster, stSpell.nClass, stSpell.nLevel); + AssignCommand(stSpell.oCaster, ai_ActionCastMemorizedBuff(stSpell)); + return; + } + else + { + stSpell.nMaxSlots = GetKnownSpellCount(stSpell.oCaster, stSpell.nClass, stSpell.nLevel); + AssignCommand(stSpell.oCaster, ai_ActionCastKnownBuff(stSpell)); + return; + } + } + stSpell.nPosition++; + } + ai_CheckForPerDayItems(stSpell.oCaster, stSpell.oPC, stSpell.nBuffType); +} +void ai_ActionCastMemorizedSummons(struct stSpell stSpell) +{ + if(AI_DEBUG) ai_Debug("0i_spells", "1122", "Start of ActionCastMemorizedSummons!"); + int nSpell; + string sBuffGroup, sBuffTarget; + object oTarget; + while(stSpell.nPosition <= AI_MAX_CLASSES_PER_CHARACTER) + { + //ai_Debug("0i_spells", "1128", "SpellCaster: " + Get2DAString("classes", "SpellCaster", stSpell.nClass)); + if(Get2DAString("classes", "SpellCaster", stSpell.nClass) == "1") + { + //ai_Debug("0i_spells", "1131", "nLevel: " + IntToString(stSpell.nLevel)); + while(stSpell.nLevel > -1) + { + //ai_Debug("0i_spells", "1134", "nMaxSlots: " + IntToString(stSpell.nMaxSlots) + + // " nSlots: " + IntToString(stSpell.nSlot)); + while(stSpell.nSlot < stSpell.nMaxSlots) + { + //ai_Debug("0i_spells", "1238", "Ready: " + IntToString(GetMemorizedSpellReady(stSpell.oCaster, stSpell.nClass, stSpell.nLevel, stSpell.nSlot))); + if(GetMemorizedSpellReady(stSpell.oCaster, stSpell.nClass, stSpell.nLevel, stSpell.nSlot)) + { + nSpell = GetMemorizedSpellId(stSpell.oCaster, stSpell.nClass, stSpell.nLevel, stSpell.nSlot); + //ai_Debug("0i_spells", "1142", "nSpell: " + IntToString(nSpell)); + if(Get2DAString("ai_spells", "Category", nSpell) == "S") + { + SetLocalInt(stSpell.oCaster, "AI_USED_SPELL_GROUP_-2", TRUE); + ai_CastMemorizedSpell(stSpell.oCaster, stSpell.nClass, stSpell.nLevel, stSpell.nSlot, stSpell.oCaster, TRUE, stSpell.oPC); + stSpell.nPosition = 1; + stSpell.nClass = GetClassByPosition(stSpell.nPosition, stSpell.oCaster); + stSpell.nLevel = (GetLevelByPosition(stSpell.nPosition, stSpell.oCaster) + 1) / 2; + stSpell.nMaxSlots = GetMemorizedSpellCountByLevel(stSpell.oCaster, stSpell.nClass, stSpell.nLevel); + stSpell.nSlot = 0; + DelayCommand(2.0, ai_SetupAllyTargets(stSpell.oCaster, stSpell.oPC)); + DelayCommand(2.0 + 0.5, AssignCommand(stSpell.oCaster, ai_ActionCastMemorizedBuff(stSpell))); + return; + } + } + stSpell.nSlot++; + } + stSpell.nLevel--; + //ai_Debug("0i_spells", "1153", "nLevel: " + IntToString(stSpell.nLevel)); + if(stSpell.nLevel > -1) + { + stSpell.nMaxSlots = GetMemorizedSpellCountByLevel(stSpell.oCaster, stSpell.nClass, stSpell.nLevel); + stSpell.nSlot = 0; + } + } + } + stSpell.nPosition++; + stSpell.nClass = GetClassByPosition(stSpell.nPosition, stSpell.oCaster); + //ai_Debug("0i_spells", "1164", "nClass: " + IntToString(stSpell.nClass)); + if(stSpell.nClass == CLASS_TYPE_INVALID) break; + if(Get2DAString("classes", "SpellCaster", stSpell.nClass) == "1") + { + stSpell.nLevel = (GetLevelByPosition(stSpell.nPosition, stSpell.oCaster) + 1) / 2; + stSpell.nSlot = 0; + if(Get2DAString("classes", "MemorizesSpells", stSpell.nClass) == "1") + { + stSpell.nMaxSlots = GetMemorizedSpellCountByLevel(stSpell.oCaster, stSpell.nClass, stSpell.nLevel); + } + else + { + stSpell.nMaxSlots = GetKnownSpellCount(stSpell.oCaster, stSpell.nClass, stSpell.nLevel); + AssignCommand(stSpell.oCaster, ai_ActionCastKnownBuff(stSpell)); + return; + } + } + } + ai_CheckForBuffSpells(stSpell); +} +void ai_ActionCastKnownSummons(struct stSpell stSpell) +{ + //ai_Debug("0i_spells", "1184", "Start of ActionCastKnownSummons!"); + int nSpell; + string sBuffGroup, sBuffTarget; + object oTarget; + while(stSpell.nPosition <= AI_MAX_CLASSES_PER_CHARACTER) + { + //ai_Debug("0i_spells", "1190", "SpellCaster: " + Get2DAString("classes", "SpellCaster", stSpell.nClass)); + if(Get2DAString("classes", "SpellCaster", stSpell.nClass) == "1") + { + //ai_Debug("0i_spells", "1193", "nLevel: " + IntToString(stSpell.nLevel)); + while(stSpell.nLevel > -1) + { + if(stSpell.nMaxSlots) + { + //ai_Debug("0i_spells", "1198", "nMaxSlots: " + IntToString(stSpell.nMaxSlots) + + // " nSlots: " + IntToString(stSpell.nSlot)); + while(stSpell.nSlot < stSpell.nMaxSlots) + { + nSpell = GetKnownSpellId(stSpell.oCaster, stSpell.nClass, stSpell.nLevel, stSpell.nSlot); + //ai_Debug("0i_spells", "1203", "Ready: " + IntToString(GetSpellUsesLeft(stSpell.oCaster, stSpell.nClass, nSpell))); + if(GetSpellUsesLeft(stSpell.oCaster, stSpell.nClass, nSpell)) + { + if(Get2DAString("ai_spells", "Category", nSpell) == "S") + { + SetLocalInt(stSpell.oCaster, "AI_USED_SPELL_GROUP_S", TRUE); + //ai_Debug("0i_spells", "1209", "nSpell: " + IntToString(nSpell)); + ai_CastKnownSpell(stSpell.oCaster, stSpell.nClass, nSpell, stSpell.oCaster, TRUE, stSpell.oPC); + stSpell.nPosition = 1; + stSpell.nClass = GetClassByPosition(stSpell.nPosition, stSpell.oCaster); + stSpell.nLevel = (GetLevelByPosition(stSpell.nPosition, stSpell.oCaster) + 1) / 2; + stSpell.nMaxSlots = GetMemorizedSpellCountByLevel(stSpell.oCaster, stSpell.nClass, stSpell.nLevel); + stSpell.nSlot = 0; + ai_SetupAllyTargets(stSpell.oCaster, stSpell.oPC); + DelayCommand(AI_HENCHMAN_BUFF_DELAY, AssignCommand(stSpell.oCaster, ai_ActionCastKnownBuff(stSpell))); + return; + } + } + stSpell.nSlot++; + } + } + stSpell.nLevel--; + //ai_Debug("0i_spells", "1218", "nLevel: " + IntToString(stSpell.nLevel)); + if(stSpell.nLevel > -1) + { + stSpell.nMaxSlots = GetKnownSpellCount(stSpell.oCaster, stSpell.nClass, stSpell.nLevel); + stSpell.nSlot = 0; + } + } + } + stSpell.nPosition++; + stSpell.nClass = GetClassByPosition(stSpell.nPosition, stSpell.oCaster); + if(stSpell.nClass == CLASS_TYPE_INVALID) break; + //ai_Debug("0i_spells", "1229", "nClass: " + IntToString(stSpell.nClass)); + if(Get2DAString("classes", "SpellCaster", stSpell.nClass) == "1") + { + stSpell.nLevel = (GetLevelByPosition(stSpell.nPosition, stSpell.oCaster) + 1) / 2; + stSpell.nSlot = 0; + if(Get2DAString("classes", "MemorizesSpells", stSpell.nClass) == "1") + { + stSpell.nMaxSlots = GetMemorizedSpellCountByLevel(stSpell.oCaster, stSpell.nClass, stSpell.nLevel); + AssignCommand(stSpell.oCaster, ai_ActionCastMemorizedBuff(stSpell)); + return; + } + else stSpell.nMaxSlots = GetKnownSpellCount(stSpell.oCaster, stSpell.nClass, stSpell.nLevel); + } + } + ai_CheckForBuffSpells(stSpell); +} +void ai_ActionCastMemorizedBuff(struct stSpell stSpell) +{ + int nSpell; + string sBuffGroup, sBuffTarget; + object oTarget; + while(stSpell.nPosition <= AI_MAX_CLASSES_PER_CHARACTER) + { + ai_Debug("0i_spells", "1252", "SpellCaster: " + Get2DAString("classes", "SpellCaster", stSpell.nClass)); + if(Get2DAString("classes", "SpellCaster", stSpell.nClass) == "1") + { + ai_Debug("0i_spells", "1255", "nLevel: " + IntToString(stSpell.nLevel)); + while(stSpell.nLevel > -1) + { + ai_Debug("0i_spells", "1258", "nMaxSlots: " + IntToString(stSpell.nMaxSlots) + + " nSlots: " + IntToString(stSpell.nSlot)); + while(stSpell.nSlot < stSpell.nMaxSlots) + { + ai_Debug("0i_spells", "1262", "Ready: " + IntToString(GetMemorizedSpellReady(stSpell.oCaster, stSpell.nClass, stSpell.nLevel, stSpell.nSlot))); + if(GetMemorizedSpellReady(stSpell.oCaster, stSpell.nClass, stSpell.nLevel, stSpell.nSlot)) + { + nSpell = GetMemorizedSpellId(stSpell.oCaster, stSpell.nClass, stSpell.nLevel, stSpell.nSlot); + int nSpellBuffDuration = StringToInt(Get2DAString("ai_spells", "Buff_Duration", nSpell)); + ai_Debug("0i_spells", "1267", "nBuffType: " + IntToString(stSpell.nBuffType) + + " nSpellBuffDuration: " + IntToString(nSpellBuffDuration) + + " sBuffGroup: " + Get2DAString("ai_spells", "Buff_Group", nSpell)); + if(stSpell.nBuffType == nSpellBuffDuration || stSpell.nBuffType == 1) + { + if(stSpell.nTarget > 0) + { + sBuffTarget = Get2DAString("ai_spells", "Buff_Target", nSpell); + oTarget = GetLocalObject(stSpell.oCaster, "AI_ALLY_TARGET_" + IntToString(stSpell.nTarget)); + if(sBuffTarget != "0" || (sBuffTarget == "0" && stSpell.oCaster == oTarget)) + { + sBuffGroup = "AI_USED_SPELL_GROUP_" + Get2DAString("ai_spells", "Buff_Group", nSpell); + if(!ai_SpellGroupNotCast(oTarget, sBuffGroup)) oTarget == OBJECT_INVALID; + } + else oTarget == OBJECT_INVALID; + } + else oTarget = ai_GetBuffTarget(stSpell.oCaster, nSpell); + ai_Debug("0i_spells", "1284", "nSpell: " + IntToString(nSpell) + + " oTarget: " + GetName(oTarget)); + if(oTarget != OBJECT_INVALID) + { + ai_CastMemorizedSpell(stSpell.oCaster, stSpell.nClass, stSpell.nLevel, stSpell.nSlot, oTarget, TRUE, stSpell.oPC); + stSpell.nSlot++; + DelayCommand(AI_HENCHMAN_BUFF_DELAY, AssignCommand(stSpell.oCaster, ai_ActionCastMemorizedBuff(stSpell))); + return; + } + } + } + stSpell.nSlot++; + } + stSpell.nLevel--; + ai_Debug("0i_spells", "1298", "nLevel: " + IntToString(stSpell.nLevel)); + if(stSpell.nLevel > -1) + { + stSpell.nMaxSlots = GetMemorizedSpellCountByLevel(stSpell.oCaster, stSpell.nClass, stSpell.nLevel); + stSpell.nSlot = 0; + } + } + } + stSpell.nPosition++; + stSpell.nClass = GetClassByPosition(stSpell.nPosition, stSpell.oCaster); + if(stSpell.nClass == CLASS_TYPE_INVALID) break; + ai_Debug("0i_spells", "1309", "nClass: " + IntToString(stSpell.nClass)); + if(Get2DAString("classes", "SpellCaster", stSpell.nClass) == "1") + { + stSpell.nLevel = (GetLevelByPosition(stSpell.nPosition, stSpell.oCaster) + 1) / 2; + stSpell.nSlot = 0; + if(Get2DAString("classes", "MemorizesSpells", stSpell.nClass) == "1") + { + stSpell.nMaxSlots = GetMemorizedSpellCountByLevel(stSpell.oCaster, stSpell.nClass, stSpell.nLevel); + } + else + { + stSpell.nMaxSlots = GetKnownSpellCount(stSpell.oCaster, stSpell.nClass, stSpell.nLevel); + AssignCommand(stSpell.oCaster, ai_ActionCastKnownBuff(stSpell)); + return; + } + } + } + ai_CheckForPerDayItems(stSpell.oCaster, stSpell.oPC, stSpell.nBuffType); +} +void ai_ActionCastKnownBuff(struct stSpell stSpell) +{ + int nSpell; + string sBuffGroup, sBuffTarget; + object oTarget; + while(stSpell.nPosition <= AI_MAX_CLASSES_PER_CHARACTER) + { + //ai_Debug("0i_spells", "1347", "SpellCaster: " + Get2DAString("classes", "SpellCaster", stSpell.nClass)); + if(Get2DAString("classes", "SpellCaster", stSpell.nClass) == "1") + { + //ai_Debug("0i_spells", "1350", "nLevel: " + IntToString(stSpell.nLevel)); + while(stSpell.nLevel > -1) + { + if(stSpell.nMaxSlots) + { + //ai_Debug("0i_spells", "1356", "nMaxSlots: " + IntToString(stSpell.nMaxSlots) + + // " nSlots: " + IntToString(stSpell.nSlot)); + while(stSpell.nSlot < stSpell.nMaxSlots) + { + nSpell = GetKnownSpellId(stSpell.oCaster, stSpell.nClass, stSpell.nLevel, stSpell.nSlot); + int nSpellBuffDuration = StringToInt(Get2DAString("ai_spells", "Buff_Duration", nSpell)); + //ai_Debug("0i_spells", "1361", "nBuffType: " + IntToString(stSpell.nBuffType) + + // " nSpellBuffDuration: " + IntToString(nSpellBuffDuration) + + // " sBuffGroup: " + Get2DAString("ai_spells", "Buff_Group", nSpell)); + if(stSpell.nBuffType == nSpellBuffDuration || stSpell.nBuffType == 1) + { + //ai_Debug("0i_spells", "1367", "Ready: " + IntToString(GetSpellUsesLeft(stSpell.oCaster, stSpell.nClass, nSpell))); + if(GetSpellUsesLeft(stSpell.oCaster, stSpell.nClass, nSpell)) + { + if(stSpell.nTarget > 0) + { + sBuffTarget = Get2DAString("ai_spells", "Buff_Target", nSpell); + oTarget = GetLocalObject(stSpell.oCaster, "AI_ALLY_TARGET_" + IntToString(stSpell.nTarget)); + if(sBuffTarget != "0" || (sBuffTarget == "0" && stSpell.oCaster == oTarget)) + { + sBuffGroup = "AI_USED_SPELL_GROUP_" + Get2DAString("ai_spells", "Buff_Group", nSpell); + if(!ai_SpellGroupNotCast(oTarget, sBuffGroup)) oTarget == OBJECT_INVALID; + } + else oTarget == OBJECT_INVALID; + } + else oTarget = ai_GetBuffTarget(stSpell.oCaster, nSpell); + //ai_Debug("0i_spells", "1382", "nSpell: " + IntToString(nSpell) + + // " oTarget: " + GetName(oTarget)); + if(oTarget != OBJECT_INVALID) + { + ai_CastKnownSpell(stSpell.oCaster, stSpell.nClass, nSpell, oTarget, TRUE, stSpell.oPC); + stSpell.nSlot++; + DelayCommand(AI_HENCHMAN_BUFF_DELAY, AssignCommand(stSpell.oCaster, ai_ActionCastKnownBuff(stSpell))); + return; + } + } + } + stSpell.nSlot++; + } + } + stSpell.nLevel--; + //ai_Debug("0i_spells", "1396", "nLevel: " + IntToString(stSpell.nLevel)); + if(stSpell.nLevel > -1) + { + stSpell.nMaxSlots = GetKnownSpellCount(stSpell.oCaster, stSpell.nClass, stSpell.nLevel); + stSpell.nSlot = 0; + } + } + } + stSpell.nPosition++; + stSpell.nClass = GetClassByPosition(stSpell.nPosition, stSpell.oCaster); + if(stSpell.nClass == CLASS_TYPE_INVALID) break; + //ai_Debug("0i_spells", "921", "nClass: " + IntToString(stSpell.nClass)); + if(Get2DAString("classes", "SpellCaster", stSpell.nClass) == "1") + { + stSpell.nLevel = (GetLevelByPosition(stSpell.nPosition, stSpell.oCaster) + 1) / 2; + stSpell.nSlot = 0; + if(Get2DAString("classes", "MemorizesSpells", stSpell.nClass) == "1") + { + stSpell.nMaxSlots = GetMemorizedSpellCountByLevel(stSpell.oCaster, stSpell.nClass, stSpell.nLevel); + AssignCommand(stSpell.oCaster, ai_ActionCastMemorizedBuff(stSpell)); + return; + } + else stSpell.nMaxSlots = GetKnownSpellCount(stSpell.oCaster, stSpell.nClass, stSpell.nLevel); + } + } + ai_CheckForPerDayItems(stSpell.oCaster, stSpell.oPC, stSpell.nBuffType); +} +void ai_CastBuffs(object oCaster, int nBuffType, int nTarget, object oPC) +{ + // buff types: 1 - All, 2 - Short duration, 3 - Long duration + // Buff groups are used to prevent a henchmen to cast spells that have the same effect, + // for example: resist elements and protection from elements are similiar so the henchmen + // would cast only the most powerful among these if he has them both. + if(AI_DEBUG) ai_Debug("0i_spells", "1670", GetName(oCaster) + " is casting buffs: " + IntToString(nBuffType) + + " nTarget: " + IntToString(nTarget) + "!"); + struct stSpell stSpell; + stSpell.oPC = oPC; + stSpell.oCaster = oCaster; + stSpell.nBuffType = nBuffType; + stSpell.nTarget = nTarget; + stSpell.nPosition = 1; + // Look for summons spells on All, Long durations and the whole party. + if((nBuffType == 1 || nBuffType == 3) && nTarget == 0) + { + while(stSpell.nPosition <= AI_MAX_CLASSES_PER_CHARACTER) + { + stSpell.nClass = GetClassByPosition(stSpell.nPosition, stSpell.oCaster); + if(AI_DEBUG) ai_Debug("0i_spells", "1684", "nClass: " + IntToString(stSpell.nClass)); + if(stSpell.nClass == CLASS_TYPE_INVALID) break; + if(AI_DEBUG) ai_Debug("0i_spells", "1686", "SpellCaster: " + Get2DAString("classes", "SpellCaster", stSpell.nClass)); + if(Get2DAString("classes", "SpellCaster", stSpell.nClass) == "1") + { + stSpell.nLevel = (GetLevelByPosition(stSpell.nPosition, stSpell.oCaster) + 1) / 2; + if(AI_DEBUG) ai_Debug("0i_spells", "1692", "MemorizesSpells: " + Get2DAString("classes", "MemorizesSpells", stSpell.nClass)); + if(Get2DAString("classes", "MemorizesSpells", stSpell.nClass) == "1") + { + stSpell.nMaxSlots = GetMemorizedSpellCountByLevel(stSpell.oCaster, stSpell.nClass, stSpell.nLevel); + AssignCommand(stSpell.oCaster, ai_ActionCastMemorizedSummons(stSpell)); + return; + } + else + { + stSpell.nMaxSlots = GetKnownSpellCount(stSpell.oCaster, stSpell.nClass, stSpell.nLevel); + AssignCommand(stSpell.oCaster, ai_ActionCastKnownSummons(stSpell)); + return; + } + } + stSpell.nPosition++; + } + // Exit here; if we summoned a monster then it linked off of that spell + // cast to continue the action queue for all buff spell cast actions. + } + ai_CheckForBuffSpells(stSpell); +} +int ai_CastSpontaneousCure(object oCreature, object oTarget, object oPC) +{ + if(ai_GetMagicMode(oCreature, AI_MAGIC_NO_MAGIC)) return FALSE; + if(ai_GetMagicMode(oCreature, AI_MAGIC_NO_SPONTANEOUS_CURE)) return FALSE; + if(AI_DEBUG) ai_Debug("0i_spells", "1643", GetName(oCreature) + " is looking to cast a spontaneous cure spell."); + if(!GetLevelByClass(CLASS_TYPE_CLERIC, oCreature)) return FALSE; + int nDamage = GetMaxHitPoints(oTarget) - GetCurrentHitPoints(oTarget); + int nSpell, nSlot, nMaxSlots, nLevel = 4; + int nSpellSave, nSlotSave, nLevelSave = 5; + string sSpellName; + while(nLevel > -1) + { + // We check CLASS_TYPE_CLERIC as thats the only class with spontaneous cure spells. + nMaxSlots = GetMemorizedSpellCountByLevel(oCreature, CLASS_TYPE_CLERIC, nLevel); + nSlot = 0; + if(AI_DEBUG) ai_Debug("0i_spells", "1653", "nLevel: " + IntToString(nLevel) + " nMaxSlots: " + IntToString(nMaxSlots)); + while(nSlot < nMaxSlots) + { + if(AI_DEBUG) ai_Debug("0i_spells", "1656", "nSlot: " + IntToString(nSlot) + + " Spell Ready: " + IntToString(GetMemorizedSpellReady(oCreature, CLASS_TYPE_CLERIC, nLevel, nSlot))); + if(GetMemorizedSpellReady(oCreature, CLASS_TYPE_CLERIC, nLevel, nSlot)) + { + if(nLevel == 4) nSpell = SPELL_CURE_CRITICAL_WOUNDS; + else if(nLevel == 3) nSpell = SPELL_CURE_SERIOUS_WOUNDS; + else if(nLevel == 2) nSpell = SPELL_CURE_MODERATE_WOUNDS; + else if(nLevel == 1) nSpell = SPELL_CURE_LIGHT_WOUNDS; + else nSpell = 0; + if(AI_DEBUG) ai_Debug("0i_spells", "1665", "nSpell: " + IntToString(nSpell)); + if(nSpell) + { + if(ai_ShouldWeCastThisCureSpell(nSpell, nDamage)) + { + SetMemorizedSpellReady(oCreature, CLASS_TYPE_CLERIC, nLevel, nSlot, FALSE); + sSpellName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); + ai_SendMessages(GetName(oCreature) + " has spontaneously cast " + sSpellName + " on " + GetName(oTarget) + ".", AI_COLOR_MAGENTA, oPC); + if(AI_DEBUG) ai_Debug("0i_spells", "1673", GetName(oCreature) + " has spontaneously cast " + sSpellName + " on " + GetName(oTarget) + "."); + ActionCastSpellAtObject(nSpell, oTarget, 255, TRUE); + return TRUE; + } + // Save the lowest level cure spell as we might need to cast it. + else if(nLevel < nLevelSave) + { + nSpellSave = nSpell; + nLevelSave = nLevel; + nSlotSave = nSlot; + } + } + } + nSlot++; + } + nLevel--; + } + // Did we find a cure spell? If we did then use it. + if(nSpellSave) + { + if(AI_DEBUG) ai_Debug("0i_spells", "1693", GetName(oCreature) + " has cast the lowest level cure spell on " + GetName(oTarget) + "."); + SetMemorizedSpellReady(oCreature, CLASS_TYPE_CLERIC, nLevelSave, nSlotSave, FALSE); + sSpellName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpellSave))); + ai_SendMessages(GetName(oCreature) + " has spontaneously cast " + sSpellName + " on " + GetName(oTarget) + ".", AI_COLOR_MAGENTA, oPC); + ActionCastSpellAtObject(nSpellSave, oTarget, 255, TRUE); + return TRUE; + } + return FALSE; +} +int ai_CastMemorizedHealing(object oCreature, object oTarget, object oPC, int nClass) +{ + if(AI_DEBUG) ai_Debug("0i_spells", "1702", GetName(oCreature) + " is looking to cast a memorized cure spell."); + int nDamage = GetMaxHitPoints(oTarget) - GetCurrentHitPoints(oTarget); + int nSpell, nSlot, nMaxSlots, nLevel = 9; + int nClassSave, nSlotSave, nLevelSave = 10; + while(nLevel > -1) + { + nMaxSlots = GetMemorizedSpellCountByLevel(oCreature, nClass, nLevel); + nSlot = 0; + if(AI_DEBUG) ai_Debug("0i_spells", "1710", "nLevel: " + IntToString(nLevel) + " nMaxSlots: " + IntToString(nMaxSlots)); + while(nSlot < nMaxSlots) + { + if(AI_DEBUG) ai_Debug("0i_spells", "1713", "nSlot: " + IntToString(nSlot) + + " Spell Ready: " + IntToString(GetMemorizedSpellReady(oCreature, nClass, nLevel, nSlot))); + if(GetMemorizedSpellReady(oCreature, nClass, nLevel, nSlot)) + { + nSpell = GetMemorizedSpellId(oCreature, nClass, nLevel, nSlot); + if(ai_ShouldWeCastThisCureSpell(nSpell, nDamage)) + { + string sSpellName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); + if(AI_DEBUG) ai_Debug("0i_spells", "1721", GetName(oCreature) + " has cast " + sSpellName + " on " + GetName(oTarget) + "."); + ai_CastMemorizedSpell(oCreature, nClass, nLevel, nSlot, oTarget, FALSE, oPC); + return TRUE; + } + // Save the lowest level cure spell as we might need to cast it. + else if(nLevel < nLevelSave && (nSpell > 26 && nSpell < 32)) + { + nClassSave = nClass; + nLevelSave = nLevel; + nSlotSave = nSlot; + } + } + nSlot++; + } + nLevel--; + } + // Did we find a cure spell? If we did then use it. + if(nLevelSave < 10) + { + if(AI_DEBUG) ai_Debug("0i_spells", "1740", GetName(oCreature) + " has cast the lowest level cure spell on " + GetName(oTarget) + "."); + ai_CastMemorizedSpell(oCreature, nClassSave, nLevelSave, nSlotSave, oTarget, FALSE, oPC); + return TRUE; + } + return FALSE; +} +int ai_CastKnownHealing(object oCreature, object oTarget, object oPC, int nClass) +{ + if(AI_DEBUG) ai_Debug("0i_spells", "1748", GetName(oCreature) + " is looking to cast a known cure spell."); + int nDamage = GetMaxHitPoints(oTarget) - GetCurrentHitPoints(oTarget); + int nSpell, nSlot, nMaxSlots, nLevel = 9; + int nClassSave, nSpellSave, nLevelSave = 10; + while(nLevel > -1) + { + nMaxSlots = GetKnownSpellCount(oCreature, nClass, nLevel); + nSlot = 0; + if(AI_DEBUG) ai_Debug("0i_spells", "1756", "nLevel: " + IntToString(nLevel) + " nMaxSlots: " + IntToString(nMaxSlots)); + while(nSlot < nMaxSlots) + { + nSpell = GetKnownSpellId(oCreature, nClass, nLevel, nSlot); + if(AI_DEBUG) ai_Debug("0i_spells", "1760", "nSlot: " + IntToString(nSlot) + + " Spell Ready: " + IntToString(GetSpellUsesLeft(oCreature, nClass, nSpell))); + if(GetSpellUsesLeft(oCreature, nClass, nSpell)) + { + if(ai_ShouldWeCastThisCureSpell(nSpell, nDamage)) + { + string sSpellName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); + if(AI_DEBUG) ai_Debug("0i_spells", "1767", GetName(oCreature) + " has cast " + sSpellName + " on " + GetName(oTarget) + "."); + ai_CastKnownSpell(oCreature, nClass, nSpell, oTarget, FALSE, oPC); + return TRUE; + } + // Save the lowest level cure spell as we might need to cast it. + else if(nLevel < nLevelSave && (nSpell > 26 && nSpell < 32)) + { + nClassSave = nClass; + nLevelSave = nLevel; + nSpellSave = nSpell; + } + } + nSlot++; + } + nLevel--; + } + return FALSE; + // Did we find a cure spell? If we did then use it. + if(nLevelSave < 10) + { + if(AI_DEBUG) ai_Debug("0i_spells", "1781", GetName(oCreature) + " has cast the lowest level cure spell on " + GetName(oTarget) + "."); + ai_CastKnownSpell(oCreature, nClassSave, nSpellSave, oTarget, FALSE, oPC); + return TRUE; + } +} +int ai_ConcentrationCondition(object oCreature) +{ + int nType; + effect eEffect = GetFirstEffect(oCreature); + while(GetIsEffectValid(eEffect)) + { + nType = GetEffectType(eEffect); + if(nType == EFFECT_TYPE_STUNNED || nType == EFFECT_TYPE_PARALYZE || + nType == EFFECT_TYPE_SLEEP || nType == EFFECT_TYPE_FRIGHTENED || + nType == EFFECT_TYPE_PETRIFY || nType == EFFECT_TYPE_CONFUSED || + nType == EFFECT_TYPE_DOMINATED || nType == EFFECT_TYPE_POLYMORPH) + { + return TRUE; + } + eEffect = GetNextEffect(oCreature); + } + return FALSE; +} +void ai_SpellConcentrationCheck(object oCaster = OBJECT_SELF) +{ + object oMaster = GetMaster(); + if(GetLocalInt(oCaster,"X2_L_CREATURE_NEEDS_CONCENTRATION")) + { + if(GetIsObjectValid(oMaster)) + { + int nAction = GetCurrentAction(oMaster); + // master doing anything that requires attention and breaks concentration + if(nAction == ACTION_DISABLETRAP || nAction == ACTION_TAUNT || + nAction == ACTION_PICKPOCKET || nAction ==ACTION_ATTACKOBJECT || + nAction == ACTION_COUNTERSPELL || nAction == ACTION_FLAGTRAP || + nAction == ACTION_CASTSPELL || nAction == ACTION_ITEMCASTSPELL) + { + SignalEvent(oCaster,EventUserDefined(X2_EVENT_CONCENTRATION_BROKEN)); + } + else if(ai_ConcentrationCondition(oMaster)) + { + SignalEvent(oCaster,EventUserDefined(X2_EVENT_CONCENTRATION_BROKEN)); + } + } + } +} +int ai_CastInMelee(object oCreature, int nSpell, int nInMelee) +{ + // If this is a spell and we are in melee. + if(nInMelee > 0 && !GetHasFeat(FEAT_EPIC_IMPROVED_COMBAT_CASTING, oCreature)) + { + // Using DC 19 so we will use with up to a 50% failure. + int nSpellLevel = StringToInt(Get2DAString("spells", "Innate", nSpell)); + int nDC = AI_DEFENSIVE_CASTING_DC + nSpellLevel; + int nRoll = Random(AI_DEFENSIVE_CASTING_DIE) + 1; + int nConcentration = GetSkillRank(SKILL_CONCENTRATION, oCreature); + if(GetHasFeat(FEAT_COMBAT_CASTING, oCreature)) nConcentration += 4; + if(AI_DEBUG) ai_Debug("0i_spells", "1081", "Use Defensive Casting? nDC: " + IntToString(nDC) + " FEAT_COMBAT_CASTING: " + + IntToString(GetHasFeat(FEAT_COMBAT_CASTING, oCreature)) + + " nConcentration: " + IntToString(nConcentration) + " + nRoll: " + IntToString(nRoll)); + if(nConcentration + nRoll > nDC) + { + if(AI_DEBUG) ai_Debug("0i_spells", "1086", GetName(oCreature) + " is casting defensively!"); + SetActionMode(oCreature, ACTION_MODE_DEFENSIVE_CAST, TRUE); + } + // Defensive casting is a bad idea so maybe casting anyspell is a bad idea. + else + { + object oMelee = GetLocalObject(oCreature, AI_ENEMY_NEAREST); + if(GetIsObjectValid(oMelee)) + { + nRoll = Random(AI_CASTING_IN_MELEE_ROLL) + 1; + nDC = AI_CASTING_IN_MELEE_DC + nSpellLevel + nInMelee * ai_GetCreatureAttackBonus(oMelee); + if(AI_DEBUG) ai_Debug("0i_spells", "1097", "Cast anyway: nConcentration: " + IntToString(nConcentration) + + " nRoll: " + IntToString(nRoll) + " nDC: " + IntToString(nDC) + + " oMelee: " + GetName(oMelee)); + if(nConcentration + nRoll > nDC) return TRUE; + if(AI_DEBUG) ai_Debug("0i_spells", "1101", GetName(oCreature) + " is not casting in melee against " + GetName(oMelee)); + return FALSE; + } + } + } + // We don't need to cast defensively so lets make sure it's off. + else if(GetActionMode(oCreature, ACTION_MODE_DEFENSIVE_CAST)) + { + SetActionMode(oCreature, ACTION_MODE_DEFENSIVE_CAST, FALSE); + } + return TRUE; +} +float ai_GetOffensiveSpellSearchRange(object oCreature, int nSpell) +{ + // Search the spell range + the distance to the closest enemy - 7.5 meters). + // This will keep the caster from running up on an enemy to cast. + // But allow them to move up some if needed. + float fRange = ai_GetSpellRange(nSpell); + object oNearestEnemy = GetLocalObject(oCreature, AI_ENEMY_NEAREST); + float fEnemyDistance = GetDistanceBetween(oCreature, oNearestEnemy); + // Spell range is less than the nearest enemy. Restrict based on nearest enemy. + // Spell range is less than the nearestenemy. Check enemy action then adjust. + if(fRange < fEnemyDistance) + { + // We check this because if the enemy is moving or has not started acting + // then we don't want to move up on them as they might move towards us! + int nAction = GetCurrentAction(oNearestEnemy); + if(AI_DEBUG) ai_Debug("0i_spells", "1130", GetName(oNearestEnemy) + " current action: " + IntToString(nAction)); + if(nAction != ACTION_MOVETOPOINT || nAction != ACTION_ITEMCASTSPELL || + nAction != ACTION_INVALID || nAction != ACTION_USEOBJECT || + nAction != ACTION_RANDOMWALK) fRange = fEnemyDistance + (fRange - 7.5); + } + if(fRange > AI_RANGE_BATTLEFIELD) return AI_RANGE_BATTLEFIELD; + else if(fRange < 0.1f) return 0.1f; + return fRange; +} +int ai_ShouldWeCastThisCureSpell(int nSpell, int nDamage) +{ + if(AI_DEBUG) ai_Debug("0i_spells", "1127", "nSpell: " + IntToString(nSpell) + " nDamage: " + + IntToString(nDamage)); + if(nSpell == SPELL_HEAL && nDamage > 50) return TRUE; + else if(nSpell == SPELL_CURE_CRITICAL_WOUNDS && nDamage > 31) return TRUE; + else if(nSpell == SPELL_CURE_SERIOUS_WOUNDS && nDamage > 23) return TRUE; + else if(nSpell == SPELL_CURE_MODERATE_WOUNDS && nDamage > 15) return TRUE; + else if(nSpell == SPELL_CURE_LIGHT_WOUNDS && nDamage > 6) return TRUE; + else if(nSpell == SPELL_CURE_MINOR_WOUNDS) return TRUE; + return FALSE; +} +void ai_CastWidgetSpell(object oPC, object oAssociate, object oTarget, location lLocation) +{ + int nIndex = GetLocalInt(oAssociate, "AI_WIDGET_SPELL_INDEX"); + DeleteLocalInt(oAssociate, "AI_WIDGET_SPELL_INDEX"); + 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)); + int nMetaMagic = JsonGetInt(JsonArrayGet(jSpell, 3)); + int nDomain = JsonGetInt(JsonArrayGet(jSpell, 4)); + //SendMessageToPC(oPC, "nSpell: " + IntToString(nSpell) + + // " oTarget: " + GetName(oTarget) + + // " nMetaMagic: " + IntToString(nMetaMagic) + + // " nDomain: " + IntToString(nDomain)); + if(GetCurrentAction(oAssociate) != ACTION_CASTSPELL) AssignCommand(oAssociate, ai_ClearCreatureActions(TRUE)); + if(!GetIsObjectValid(oTarget)) + { + AssignCommand(oAssociate, ActionCastSpellAtLocation(nSpell, lLocation, nMetaMagic, FALSE, 0, FALSE, -1, FALSE, nDomain)); + } + else AssignCommand(oAssociate, ActionCastSpellAtObject(nSpell, oTarget, nMetaMagic, FALSE, nDomain)); + +} +void ai_UseWidgetFeat(object oPC, object oAssociate, object oTarget, location lLocation) +{ + int nIndex = GetLocalInt(oAssociate, "AI_WIDGET_SPELL_INDEX"); + DeleteLocalInt(oAssociate, "AI_WIDGET_SPELL_INDEX"); + string sAssociateType = ai_GetAssociateType(oPC, oAssociate); + json jAIData = ai_GetAssociateDbJson(oPC, sAssociateType, "aidata"); + json jSpells = JsonArrayGet(jAIData, 10); + json jWidget = JsonArrayGet(jSpells, 2); + json jFeat = JsonArrayGet(jWidget, nIndex); + int nFeat = JsonGetInt(JsonArrayGet(jFeat, 5)); + if(ai_GetIsInCombat(oAssociate)) AssignCommand(oAssociate, ai_ClearCreatureActions(TRUE)); + //SendMessageToPC(oPC, "0i_spells, 2104, nFeat: " + IntToString(nFeat) + " oTarget: " + GetName(oTarget)); + if(!GetIsObjectValid(oTarget)) + { + AssignCommand(oAssociate, ActionUseFeat(nFeat, OBJECT_INVALID, 0, lLocation)); + } + else AssignCommand(oAssociate, ActionUseFeat(nFeat, oTarget)); +} +void ai_UseWidgetItem(object oPC, object oAssociate, object oTarget, location lLocation) +{ + int nIndex = GetLocalInt(oAssociate, "AI_WIDGET_SPELL_INDEX"); + DeleteLocalInt(oAssociate, "AI_WIDGET_SPELL_INDEX"); + string sAssociateType = ai_GetAssociateType(oPC, oAssociate); + json jAIData = ai_GetAssociateDbJson(oPC, sAssociateType, "aidata"); + json jSpells = JsonArrayGet(jAIData, 10); + json jWidget = JsonArrayGet(jSpells, 2); + json jItem = JsonArrayGet(jWidget, nIndex); + int nSpell = JsonGetInt(JsonArrayGet(jItem, 0)); + int nIprpSubType = JsonGetInt(JsonArrayGet(jItem, 4)); + object oItem = GetObjectByUUID(JsonGetString(JsonArrayGet(jItem, 5))); + itemproperty ipProperty; + if(ai_GetIsInCombat(oAssociate)) AssignCommand(oAssociate, ai_ClearCreatureActions(TRUE)); + if(nSpell == SPELL_HEALINGKIT) + { + ipProperty = GetFirstItemProperty(oItem); + if(GetItemPropertyType(ipProperty) == ITEM_PROPERTY_HEALERS_KIT) + { + if(ai_GetIsCharacter(oPC)) ai_SendMessages(GetName(oAssociate) + " uses " + GetName(oItem) + " on " + GetName(oTarget) + ".", AI_COLOR_YELLOW, oPC); + AssignCommand(oAssociate, ActionUseItemOnObject(oItem, ipProperty, oTarget)); + return; + } + } + ipProperty = GetFirstItemProperty(oItem); + while(GetIsItemPropertyValid(ipProperty)) + { + if(nIprpSubType == GetItemPropertySubType(ipProperty)) break; + ipProperty = GetNextItemProperty(oItem); + } + if(!GetIsObjectValid(oTarget)) + { + AssignCommand(oAssociate, ActionUseItemAtLocation(oItem, ipProperty, lLocation)); + } + else AssignCommand(oAssociate, ActionUseItemOnObject(oItem, ipProperty, oTarget)); +} diff --git a/src/module/nss/0i_states_cond.nss b/src/module/nss/0i_states_cond.nss new file mode 100644 index 0000000..4c77ccf --- /dev/null +++ b/src/module/nss/0i_states_cond.nss @@ -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); +} + diff --git a/src/module/nss/0i_talents.nss b/src/module/nss/0i_talents.nss new file mode 100644 index 0000000..fa773b9 --- /dev/null +++ b/src/module/nss/0i_talents.nss @@ -0,0 +1,3098 @@ +/*////////////////////////////////////////////////////////////////////////////// + Script: 0i_talents + Programmer: Philos +//////////////////////////////////////////////////////////////////////////////// + Fuctions to use a category of skills, feats, spells, or items. +*/////////////////////////////////////////////////////////////////////////////// +#include "0i_combat" +// ***************************************************************************** +// ************************* Try * Defensive Talents *************************** +// ***************************************************************************** +// These functions try to find and use a specific set of talents intelligently. + +// Returns TRUE if oCreature uses a healing talent on oTarge. +// nInMelee is the number of enemies the caller is in melee with. +// If oTarget is set then they will heal that target if they need it. +// Otherwise checks all allies to see who we should heal based on the talent. +int ai_TryHealingTalent(object oCreature, int nInMelee, object oTarget = OBJECT_INVALID); +// Returns TRUE if oCreature uses a cure condition talent on an ally or self. +int ai_TryCureConditionTalent(object oCreature, int nInMelee, object oTarget = OBJECT_INVALID); +// Returns TRUE if oCreature uses a defensive talent. +// Checks for a Defensive talent(Protection, Enhancement, or Summons). +// Randomizes the order to mix up spells in combat. +// if oTarget is set then the defensive talent will be cast on them or OBJECT_SELF. +int ai_TryDefensiveTalents(object oCreature, int nInMelee, int nMaxLevel, int nRound = 0, object oTarget = OBJECT_INVALID); +// Returns TRUE if oCreature uses a defensive talent. +// Checks the enemy faction for most powerful class and picks a buff based on it. +//int ai_TryAdvancedBuffOnSelf(object oCreature, int nInMelee); +// Set any auras this oCreature has instantly. +// This can be done in the OnSpawn script, heart beat, or Perception. +void ai_SetAura(object oCreature); + +// ***************************************************************************** +// ************************ Try Physical Attack Talents ************************ +// ***************************************************************************** +// These functions try to find and use melee attack talents intelligently. + +// Wrapper for ActionAttack, oCreature uses nAction (attack) on oTarget. +// nInMelee is only used in AI_LAST_ACTION_RANGED_ATK actions. +// bPassive TRUE oCreature will not move while attacking. +// nActionMode, pass the action mode if one is being used. +void ai_ActionAttack(object oCreature, int nAction, object oTarget, int nInMelee = 0, int bPassive = FALSE, int nActionMode = 0); +// Returns TRUE if oCreature uses a dragons breath talent +// Check for dragon's attacks under TALENT_CATEGORY_DRAGONS_BREATH(19). +// nRound must be supplied so we can keep track of the breath uses. +int ai_TryDragonBreathAttack(object oCreature, int nRound, object oTarget = OBJECT_INVALID); +// Returns TRUE if oCreature uses a dragons wing attacks. +// Checks to see if a dragon can use its wings on a nearby enemy. +// Checks the right side and then the left side to see if it can attack. +int ai_TryWingAttacks(object oCreature); +// Returns TRUE if oCreature uses a dragons tail slap. +// Looks behind the dragon to see if it can use it's tail slap on an enemy. +int ai_TryTailSlap(object oCreature); +// Returns TRUE if oCreature uses a dragons crush attack. +// Dragon can fly up and crash down on opponents to do bludgeoning damage. +// If 3 times smaller than the dragon they will take extra damage and be +// Knocked Down for 1 round if Reflex save is not made. +int ai_TryCrushAttack(object oCreature, object oTarget); +// Returns TRUE if oCreature uses a dragons tail sweep attack. +// If the enemy is 4 sizes smaller than it the dragon to use its tail to sweep +// behind it doing damage and knocking the opponents down. +int ai_TryTailSweepAttack(object oCreature); +// Returns TRUE if oCreature finds a good target and uses Sneak Attack. +int ai_TrySneakAttack(object oCreature, int nInMelee, int bAlwaysAtk = TRUE); +// Returns TRUE if oCreature finds a good ranged target and uses Sneak Attack. +int ai_TryRangedSneakAttack(object oCreature, int nInMelee); +// Returns TRUE if oCreature uses a harmful melee talent. +int ai_TryMeleeTalents(object oCreature, object oTarget); +// ***************************************************************************** +// ******************************* Try * Skills ******************************** +// ***************************************************************************** +// These functions try to find and use a specific set of skills intelligently. + +// Wrapper to have oCreature use nSkill on oTarget. +void ai_UseSkill(object oCreature, int nSkill, object oTarget); +// Returns TRUE if oCreature uses the parry skill on someone attacking them. +// Checks if doing a parry might be successful. +int ai_TryParry(object oCreature); +// Returns TRUE if oCreature uses the Taunt skill on oTarget. +// Checks if doing a taunt might be successful against oTarget. +int ai_TryTaunt(object oCreature, object oTarget); +// Returns TRUE if oCreature uses the Animial emapthy skill on oTarget. +// For it to work oTarget must be an Animal, Beast, or Magical Beast. +// Checks if doing Animal Empathy might be successful against oTarget. +int ai_TryAnimalEmpathy(object oCreature, object oTarget = OBJECT_INVALID); +// ***************************************************************************** +// ******************************** Try * Feats ******************************** +// ***************************************************************************** +// These functions try to find and use a specific set of feats intelligently. + +// Wrapper to have oCreature use nFeat on oTarget. +void ai_UseFeat(object oCreature, int nFeat, object oTarget, int nSubFeat = 0); +// Wrapper to have oCreature use nActionMode on oTarget. +// nInMelee is only used in AI_LAST_ACTION_RANGED_ATK actions. +// bPassive TRUE oCreature will not move while attacking. +void ai_UseFeatAttackMode(object oCreature, int nActionMode, int nAction, object oTarget, int nInMelee = 0, int bPassive = FALSE); +// Returns TRUE if oCreature uses Rage. +// This checks if they are already in a rage and if they have the Rage feat. +int ai_TryBarbarianRageFeat(object oCreature); +// Returns TRUE if oCreature uses Bard song. +// This checks if they have any uses left, have the feat and if its viable. +int ai_TryBardSongFeat(object oCreature); +// Returns TRUE if oCreature uses Called shot. +// This checks if they have the feat and if its viable. +int ai_TryCalledShotFeat(object oCreature, object oTarget); +// Returns TRUE if oCreature uses Disarm. +// This checks if they have the feat and if its viable. +int ai_TryDisarmFeat(object oCreature, object oTarget); +// Returns TRUE if oCreature uses Divine Might. +// This only checks if they can use the feat and have turn undead uses left. +int ai_TryDivineMightFeat(object oCreature, int nInMelee); +// Returns TRUE if oCreature uses Divine Shield. +// This only checks if they can use the feat and have turn undead uses left. +int ai_TryDivineShieldFeat(object oCreature, int nInMelee); +// Returns TRUE if oCreature uses Expertise. +// This checks if they have the feat and if its viable. +// Also checks to see if the Improved Expertise feat would be better. +int ai_TryExpertiseFeat(object oCreature); +// Returns TRUE if oCreature uses Flurry of Blows. +// This checks if they have the feat and if its viable. +int ai_TryFlurryOfBlowsFeat(object oCreature, object oTarget); +// Returns TRUE if oCreature uses Improved Expertise. +// This checks if they have the feat and if its viable. +// Also checks to see if the Expertise feat would be better. +int ai_TryImprovedExpertiseFeat(object oCreature); +// Returns TRUE if oCreature uses Improved Power Attack. +// This checks if they have the feat and if its viable. +// Also checks to see if the Power Attack feat would be better. +int ai_TryImprovedPowerAttackFeat(object oCreature, object oTarget); +// Returns TRUE if oCreature uses Ki Damage. +// This checks if they have any uses left, have the feat and if its viable. +int ai_TryKiDamageFeat(object oCreature, object oTarget); +// Returns TRUE if oCreature uses Knockdown. +// This checks if they have the feat and if its viable. +int ai_TryKnockdownFeat(object oCreature, object oTarget); +// Returns TRUE if oCreature uses a polymorph self feat. +// This checks if they have the feat and will use the best one. +int ai_TryPolymorphSelfFeat(object oCreature); +// Returns TRUE if oCreature uses Power Attack. +// This checks if they have the feat and if its viable. +// Also checks to see if the Improved Power Attack would be better. +int ai_TryPowerAttackFeat(object oCreature, object oEnemy); +// Returns TRUE if oCreature uses Quivering palm. +// This checks if they have any uses left, have the feat and if its viable. +int ai_TryQuiveringPalmFeat(object oCreature, object oTarget); +// Returns TRUE if oCreature uses Power Attack. +// This checks if they have the feat and if its viable. +// Using a bow and having arrows should be checked before calling this. +int ai_TryRapidShotFeat(object oCreature, object oTarget, int nInMelee); +// Returns TRUE if oCreature uses Sap. +// This checks if they have the feat and if its viable. +int ai_TrySapFeat(object oCreature, object oTarget); +// Returns TRUE if oCreature uses Smite evil. +// This checks if they have any uses left, have the feat and if its viable. +int ai_TrySmiteEvilFeat(object oCreature, object oTarget); +// Returns TRUE if oCreature uses Smite good. +// This checks if they have any uses left, have the feat and if its viable. +int ai_TrySmiteGoodFeat(object oCreature, object oTarget); +// Returns TRUE if oCreature uses Stunning fists. +// This checks if they have any uses left, have the feat and if its viable. +int ai_TryStunningFistFeat(object oCreature, object oTarget); +// Returns TRUE if oCreature uses a summon animal companion talent. +int ai_TrySummonAnimalCompanionTalent(object oCreature); +// Returns TRUE if oCreature uses a summon familiar talent. +int ai_TrySummonFamiliarTalent(object oCreature); +// Returns TRUE if oCreature uses the Lay on Hands feat talent. +int ai_TryLayOnHands(object oCreature); +// Returns TRUE if oCreature uses a turning talent. +int ai_TryTurningTalent(object oCreature); +// Returns TRUE if oCreature uses Whirlwind. +// This checks if they have the feat and if its viable. +int ai_TryWhirlwindFeat(object oCreature); +// Returns TRUE if oCreature uses Wholeness of Body. +// This checks if they have any uses left, have the feat and if its viable. +int ai_TryWholenessOfBodyFeat(object oCreature); +// ***************************************************************************** +// ***************************** TALENT SCRIPTS ****************************** +// ***************************************************************************** +// These functions do not fall into another section. + +// Returns the MaxLevel used in GetCreatureTalent for oCreature. +// This checks the intelligence and the level of oCreature. +// Returns either -1 (random) or 10 for all talents. +int ai_GetMonsterTalentMaxLevel(object oCreature); +// Returns the nMaxLevel used in GetCreatureTalent for oCreature. +// This checks the difficulty of the combat and the level of oCreature. +// Return a number equal to 1 and half the level of oCreature upto 10. +// The max spell level used is equal to nMaxLevel or less. +int ai_GetAssociateTalentMaxLevel(object oCreature, int nDifficulty); +// Returns TRUE if oCreature has nTalent. +// nTalent will be a spell in the spells.2da. +int ai_GetHasTalent(object oCreature, int nTalent); +// Saves a talent in JsonArray. +// Array: 0-Type (1-spell, 2-sp ability, 4-feat, 3-item) +// Type 1)spell 0-type, 1-spell, 2-class, 3-level, 4-slot. +// Type 2)sp Ability 0-type, 1-spell, 2-class, 3-level, 4-slot. +// Type 3)feat 0-type, 1-spell, 2- class, 3- level. +// Type 4)item 0-type, 1-spell, 2-item object, 3-level, 4-slot. +// jJsonLevel is the level to place the talent in the json array +// maybe different then the talents actual level which is passed in nLevel. +void ai_SaveTalent(object oCreature, int nClass, int nJsonLevel, int nLevel, int nSlot, int nSpell, int nType, int bBuff, object oItem = OBJECT_INVALID); +// Removes a talent nSlotIndex from jLevel in jCategory. +void ai_RemoveTalent(object oCreature, json jCategory, json jLevel, string sCategory, int nLevel, int nSlotIndex); +// Saves a creatures talents to variables upon them for combat use. +// bMonster will check to see if they should be buffed when we set the talents. +void ai_SetCreatureTalents(object oCreature, int bMonster); +// Return TRUE if oCreature spontaneously casts a cure spell from a talent in sCategory. +int ai_UseSpontaneousCureTalentFromCategory(object oCreature, string sCategory, int nInMelee, int nDamage, object oTarget = OBJECT_INVALID); +// Returns TRUE if oCreature uses jTalent on oTarget. +// also Returns -1 if oCreature uses jTalent on oTarget with a memorized spell. +// This allows the user to remove jTalent from jLevel in jCategory. +int ai_UseCreatureSpellTalent(object oCreature, json jLevel, json jTalent, string sCategory, int nInMelee, object oTarget = OBJECT_INVALID); +// Return TRUE if oCreature uses a jTalent from oItem on oTarget. +int ai_UseCreatureItemTalent(object oCreature, json jLevel, json jTalent, string sCategory, int nInMelee, object oTarget = OBJECT_INVALID); +// Returns TRUE if oCreature uses a talent from sCategory of nLevel or less. +int ai_UseCreatureTalent(object oCreature, string sCategory, int nInMelee, int nLevel = 10, object oTarget = OBJECT_INVALID); +// Return TRUE if oCreature uses nTalent on oTarget. +int ai_UseTalent(object oCreature, int nTalent, object oTarget); +// Returns TRUE if jTalent is used on oTarget by oCaster. +// Checks the talent type and casts the correct spell. For items it checks uses. +int ai_UseTalentOnObject(object oCaster, json jTalent, object oTarget, int nInMelee); +// Returns TRUE if jTalent is used at lTarget location by oCaster. +// Checks the talent type and cast the correct spell. For items it checks uses. +int ai_UseTalentAtLocation(object oCaster, json jTalent, object oTarget, int nInMelee); +// Return TRUE if oCreature uses jTalent on oTarget after checking special cases. +int ai_CheckSpecialTalentsandUse(object oCreature, json jTalent, string sCategory, int nInMelee, object oTarget); + +int ai_TryHealingTalent(object oCreature, int nInMelee, object oTarget = OBJECT_INVALID) +{ + // First lets evaluate oTarget and see how strong of a spell we will need. + if(oTarget != OBJECT_INVALID) + { + if(oTarget == oCreature) + { + if(ai_GetAIMode(oCreature, AI_MODE_SELF_HEALING_OFF)) return FALSE; + } + else if(ai_GetAIMode(oCreature, AI_MODE_PARTY_HEALING_OFF)) return FALSE; + } + // We don't have a target so lets go check for one. + else + { + if(!ai_GetAIMode(oCreature, AI_MODE_PARTY_HEALING_OFF)) + { + // Lets not run past an enemy to heal unless we have the feats, bad tactics! + float fRange; + if(ai_CanIMoveInCombat(oCreature)) fRange = AI_RANGE_PERCEPTION; + else + { + fRange = GetDistanceBetween(oCreature, GetLocalObject(oCreature, AI_ENEMY_NEAREST)) - 3.0f; + // Looks bad when your right next to an ally, but technically the enemy is closer. + if(fRange < AI_RANGE_MELEE) fRange = AI_RANGE_MELEE; + } + oTarget = ai_GetAllyToHealTarget(oCreature, fRange); + } + else oTarget = oCreature; + if(oTarget == OBJECT_INVALID) return FALSE; + } + // Should we ignore associates? + if(ai_GetAIMode(oCreature, AI_MODE_IGNORE_ASSOCIATES) && + GetAssociateType(oTarget) > 1) return FALSE; + int nHp = ai_GetPercHPLoss(oTarget); + int nHpLimit = ai_GetHealersHpLimit(oCreature); + if(AI_DEBUG) ai_Debug("0i_talents", "256", "nHp: " + IntToString(nHp) + + "< nHpLimit: " + IntToString(nHpLimit)); + if(nHp > nHpLimit) return FALSE; + int nDamage = GetMaxHitPoints(oTarget) - GetCurrentHitPoints(oTarget); + if(AI_DEBUG) ai_Debug("0i_talents", "260", GetName(oTarget) + " has lost " + IntToString(nDamage) + " hitpoints!"); + // Do they have Lay on Hands? + int bUseMagic = !ai_GetMagicMode(oCreature, AI_MAGIC_NO_MAGIC); + if(bUseMagic && GetHasFeat(FEAT_LAY_ON_HANDS, oCreature)) + { + int nCanHeal = GetAbilityModifier(ABILITY_CHARISMA, oCreature) * ai_GetCharacterLevels(oCreature); + if(nCanHeal <= nDamage) + { + ai_UseFeat(oCreature, FEAT_LAY_ON_HANDS, oTarget); + return TRUE; + } + } + int nMaxLevel = 9; + // If they are about to die then throw caution to the wind and HEAL! + if(nHp <= AI_HEALTH_BLOODY || nHp < 11) nInMelee = 0; + if(ai_UseCreatureTalent(oCreature, AI_TALENT_HEALING, nInMelee, nMaxLevel, oTarget)) return TRUE; + if(AI_DEBUG) ai_Debug("0i_talents", "275", GetName(oCreature) + " has no healing spells!" + + " Cleric lvls: " + IntToString(GetLevelByClass(CLASS_TYPE_CLERIC, oCreature)) + + " Sontaneous casting: " + IntToString(ai_GetMagicMode(oCreature, AI_MAGIC_NO_SPONTANEOUS_CURE))); + if(bUseMagic && GetLevelByClass(CLASS_TYPE_CLERIC, oCreature) && + !ai_GetMagicMode(oCreature, AI_MAGIC_NO_SPONTANEOUS_CURE)) + { + // We need to check our talents and see what spells we can convert. + if(ai_UseSpontaneousCureTalentFromCategory(oCreature, AI_TALENT_ENHANCEMENT, nInMelee, nDamage, oTarget)) return TRUE; + if(ai_UseSpontaneousCureTalentFromCategory(oCreature, AI_TALENT_PROTECTION, nInMelee, nDamage, oTarget)) return TRUE; + if(ai_UseSpontaneousCureTalentFromCategory(oCreature, AI_TALENT_DISCRIMINANT_AOE, nInMelee, nDamage, oTarget)) return TRUE; + if(ai_UseSpontaneousCureTalentFromCategory(oCreature, AI_TALENT_INDISCRIMINANT_AOE, nInMelee, nDamage, oTarget)) return TRUE; + if(ai_UseSpontaneousCureTalentFromCategory(oCreature, AI_TALENT_TOUCH, nInMelee, nDamage, oTarget)) return TRUE; + if(ai_UseSpontaneousCureTalentFromCategory(oCreature, AI_TALENT_RANGED, nInMelee, nDamage, oTarget)) return TRUE; + if(ai_UseSpontaneousCureTalentFromCategory(oCreature, AI_TALENT_SUMMON, nInMelee, nDamage, oTarget)) return TRUE; + if(ai_UseSpontaneousCureTalentFromCategory(oCreature, AI_TALENT_CURE, nInMelee, nDamage, oTarget)) return TRUE; + } + return FALSE; +} +int ai_CheckTargetVsConditions(object oTarget, json jTalent, int nConditions) +{ + // Check nCondition for any negative effects based on the talent we have. + switch(JsonGetInt(JsonArrayGet(jTalent, 1))) + { + case SPELL_NEUTRALIZE_POISON : + if(ai_GetHasNegativeCondition(AI_CONDITION_POISON, nConditions)) return TRUE; + break; + case SPELL_REMOVE_DISEASE : + if(ai_GetHasNegativeCondition(AI_CONDITION_DISEASE, nConditions)) return TRUE; + break; + case SPELL_REMOVE_BLINDNESS_AND_DEAFNESS : + if(ai_GetHasNegativeCondition(AI_CONDITION_BLINDDEAF, nConditions)) return TRUE; + break; + case SPELL_REMOVE_FEAR : + if(ai_GetHasNegativeCondition(AI_CONDITION_FRIGHTENED, nConditions)) return TRUE; + break; + case SPELL_REMOVE_CURSE : + if(ai_GetHasNegativeCondition(AI_CONDITION_CURSE, nConditions)) return TRUE; + break; + case SPELL_REMOVE_PARALYSIS : + if(ai_GetHasNegativeCondition(AI_CONDITION_PARALYZE, nConditions)) return TRUE; + break; + case SPELL_CLARITY : + if(ai_GetHasNegativeCondition(AI_CONDITION_DAZED, nConditions)) return TRUE; + if(ai_GetHasNegativeCondition(AI_CONDITION_CHARMED, nConditions)) return TRUE; + if(ai_GetHasNegativeCondition(AI_CONDITION_CONFUSED, nConditions)) return TRUE; + if(ai_GetHasNegativeCondition(AI_CONDITION_STUNNED, nConditions)) return TRUE; + break; + case SPELL_GREATER_RESTORATION : + if(ai_GetHasNegativeCondition(AI_CONDITION_DAZED, nConditions)) return TRUE; + if(ai_GetHasNegativeCondition(AI_CONDITION_CONFUSED, nConditions)) return TRUE; + if(ai_GetHasNegativeCondition(AI_CONDITION_DOMINATED, nConditions)) return TRUE; + if(ai_GetHasNegativeCondition(AI_CONDITION_SLOW, nConditions)) return TRUE; + if(ai_GetHasNegativeCondition(AI_CONDITION_FRIGHTENED, nConditions)) return TRUE; + if(ai_GetHasNegativeCondition(AI_CONDITION_STUNNED, nConditions)) return TRUE; + if(ai_GetHasNegativeCondition(AI_CONDITION_CHARMED, nConditions)) return TRUE; + case SPELL_RESTORATION : + if(ai_GetHasNegativeCondition(AI_CONDITION_LEVEL_DRAIN, nConditions)) return TRUE; + if(ai_GetHasNegativeCondition(AI_CONDITION_BLINDDEAF, nConditions)) return TRUE; + if(ai_GetHasNegativeCondition(AI_CONDITION_PARALYZE, nConditions)) return TRUE; + case SPELL_LESSER_RESTORATION : + if(ai_GetHasNegativeCondition(AI_CONDITION_ABILITY_DRAIN, nConditions)) return TRUE; + if(ai_GetHasNegativeCondition(AI_CONDITION_SAVE_DECREASE, nConditions)) return TRUE; + if(ai_GetHasNegativeCondition(AI_CONDITION_SR_DECREASE, nConditions)) return TRUE; + if(ai_GetHasNegativeCondition(AI_CONDITION_SKILL_DECREASE, nConditions)) return TRUE; + if(ai_GetHasNegativeCondition(AI_CONDITION_AC_DECREASE , nConditions)) return TRUE; + if(ai_GetHasNegativeCondition(AI_CONDITION_ATK_DECREASE, nConditions)) return TRUE; + if(ai_GetHasNegativeCondition(AI_CONDITION_DMG_DECREASE, nConditions)) return TRUE; + if(ai_GetHasNegativeCondition(AI_CONDITION_DMG_I_DECREASE, nConditions)) return TRUE; + } + return FALSE; +} +int ai_CheckTalentsVsConditions(object oCreature, int nConditions, int nInMelee, int nLevel, object oTarget) +{ + // Get the saved category from oCreature. + json jCategory = GetLocalJson(oCreature, AI_TALENT_CURE); + if(AI_DEBUG) ai_Debug("0i_talents", "357", "jCategory: " + AI_TALENT_CURE + " " + JsonDump(jCategory, 2)); + if(JsonGetType(jCategory) == JSON_TYPE_NULL) + { + SetLocalInt(oCreature, AI_MAX_TALENT + AI_TALENT_CURE, -1); + return FALSE; + } + // Get the max talent level so we can skip the higher ones and save time. + int nMaxTalentLevel = GetLocalInt(oCreature, AI_MAX_TALENT + AI_TALENT_CURE); + if(AI_DEBUG) ai_Debug("0i_talents", "365", AI_MAX_TALENT + AI_TALENT_CURE + ": " + + IntToString(nMaxTalentLevel) + + " nLevel: " + IntToString(nLevel)); + if(nMaxTalentLevel < nLevel) nLevel = nMaxTalentLevel; + if(nLevel < 0 || nLevel > 10) nLevel = 9; + json jLevel, jTalent; + int nClass, nSlot, nType, nSlotIndex, nMaxSlotIndex, nTalentUsed; + int bUseMagic = !ai_GetMagicMode(oCreature, AI_MAGIC_NO_MAGIC); + int bUseMagicItems = !ai_GetMagicMode(oCreature, AI_MAGIC_NO_MAGIC_ITEMS); + if(AI_DEBUG) ai_Debug("0i_talents", "374", "bUseMagic: " + IntToString(bUseMagic) + + " bUseMagicItems: " + IntToString(bUseMagicItems)); + // Loop through nLevels down to 0 looking for the first talent (i.e. the highest). + while(nLevel >= 0) + { + // Get the array of nLevel cycling down to 0. + jLevel = JsonArrayGet(jCategory, nLevel); + nMaxSlotIndex = JsonGetLength(jLevel); + if(AI_DEBUG) ai_Debug("0i_talents", "382", "nLevel: " + IntToString(nLevel) + + " nMaxSlotIndex: " + IntToString(nMaxSlotIndex)); + if(nMaxSlotIndex > 0) + { + // Get the talent within nLevel cycling from the first to the last. + nSlotIndex = 0; + while (nSlotIndex <= nMaxSlotIndex) + { + jTalent= JsonArrayGet(jLevel, nSlotIndex); + if(AI_DEBUG) ai_Debug("0i_talents", "391", "nSlotIndex: " + IntToString(nSlotIndex) + + " jTalent Type: " + IntToString(JsonGetType(jTalent))); + // Check to see if the talent matches oTargets nConditionss. + if(ai_CheckTargetVsConditions(oTarget, jTalent, nConditions)) + { + nType = JsonGetInt(JsonArrayGet(jTalent, 0)); + if(bUseMagic) + { + if(nType == AI_TALENT_TYPE_SPELL) + { + if(ai_CastInMelee(oCreature, JsonGetInt(JsonArrayGet(jTalent, 1)), nInMelee)) + { + nTalentUsed = ai_UseCreatureSpellTalent(oCreature, jLevel, jTalent, AI_TALENT_CURE, nInMelee, oTarget); + // -1 means it was a memorized spell and we need to remove it. + if(nTalentUsed == -1) + { + ai_RemoveTalent(oCreature, jCategory, jLevel, AI_TALENT_CURE, nLevel, nSlotIndex); + return TRUE; + } + else if(nTalentUsed) return TRUE; + } + } + else if(nType == AI_TALENT_TYPE_SP_ABILITY) + { + // Special ability spells do not need to concentrate?! + if(ai_CheckSpecialTalentsandUse(oCreature, jTalent, AI_TALENT_CURE, nInMelee, oTarget)) + { + // When the ability is used that slot is now not readied. + // Multiple uses of the same spell are stored in different slots. + ai_RemoveTalent(oCreature, jCategory, jLevel, AI_TALENT_CURE, nLevel, nSlotIndex); + return TRUE; + } + } + } + if(bUseMagicItems && nType == AI_TALENT_TYPE_ITEM) + { + // Items do not need to concentrate. + if(ai_UseCreatureItemTalent(oCreature, jLevel, jTalent, AI_TALENT_CURE, nInMelee, oTarget)) + { + if(AI_DEBUG) ai_Debug("0i_talents", "430", "Checking if Item is used up: " + + IntToString(JsonGetInt(JsonArrayGet(jTalent, 4)))); + if(JsonGetInt(JsonArrayGet(jTalent, 4)) == -1) + { + ai_RemoveTalent(oCreature, jCategory, jLevel, AI_TALENT_CURE, nLevel, nSlotIndex); + } + return TRUE; + } + } + } + nSlotIndex++; + } + } + else SetLocalInt(oCreature, AI_MAX_TALENT + AI_TALENT_CURE, nLevel - 1); + nLevel--; + } + return FALSE; +} +int ai_TryCureConditionTalent(object oCreature, int nInMelee, object oTarget = OBJECT_INVALID) +{ + // Is Casting Cure spells off? + if(ai_GetMagicMode(oCreature, AI_MAGIC_CURE_SPELLS_OFF)) return FALSE; + if(AI_DEBUG) ai_Debug("0i_talents", "450", AI_MAX_TALENT + AI_TALENT_CURE + ": " + + IntToString(GetLocalInt(oCreature, AI_MAX_TALENT + AI_TALENT_CURE))); + // If the creature doesn't have cure talents then we set it to -1. + if(GetLocalInt(oCreature, AI_MAX_TALENT + AI_TALENT_CURE) == -1) return FALSE; + // We check targets to see if they need to be cured. + int nNegativeConditions, nTargetNegConds, nIndex, nCnt = 1; + object oTarget; + if(oTarget == OBJECT_INVALID) + { + oTarget = GetLocalObject(oCreature, AI_ALLY + "1"); + while(oTarget != OBJECT_INVALID) + { + nTargetNegConds = ai_GetNegativeConditions(oTarget); + // Should we ignore associates? + if(!ai_GetAIMode(oCreature, AI_MODE_IGNORE_ASSOCIATES) || + GetAssociateType(oTarget) < 2) + { + if(nNegativeConditions < nTargetNegConds) + { + nNegativeConditions = nTargetNegConds; + nIndex = nCnt; + } + } + oTarget = GetLocalObject(oCreature, AI_ALLY + IntToString(++nCnt)); + } + // No one has a negative condition then get out. + if(!nNegativeConditions) return FALSE; + oTarget = GetLocalObject(oCreature, AI_ALLY + IntToString(nIndex)); + } + else + { + nNegativeConditions = ai_GetNegativeConditions(oTarget); + if(!nNegativeConditions) return FALSE; + } + if(oTarget == oCreature) + { + if(ai_GetAIMode(oCreature, AI_MODE_SELF_HEALING_OFF)) return FALSE; + } + else if(ai_GetAIMode(oCreature, AI_MODE_PARTY_HEALING_OFF)) return FALSE; + if(AI_DEBUG) ai_Debug("0i_talents", "489", "nNegativeConditions: " + IntToString(nNegativeConditions) + + " on " + GetName(oTarget)); + if(ai_CheckTalentsVsConditions(oCreature, nNegativeConditions, nInMelee, 9, oTarget)) return TRUE; + return FALSE; +} +// ***************************************************************************** +// ************************* Try * Defensive Talents *************************** +// ***************************************************************************** +// These functions try to find and use a specific set of talents intelligently. + +int ai_TryDefensiveTalents(object oCreature, int nInMelee, int nMaxLevel, int nRound = 0, object oTarget = OBJECT_INVALID) +{ + // Summons are powerfull and should be used as much as possible. + if(ai_UseCreatureTalent(oCreature, AI_TALENT_SUMMON, nInMelee, nMaxLevel, oTarget)) return TRUE; + // Added to reduce casting defensive talents later in combat and constantly. + if(nRound >= d8()) return FALSE; + // Try to mix them up so we don't always cast spells in the same order. + int nRoll = d2(); + if(AI_DEBUG) ai_Debug("0i_talents", "507", "Lets help someone(Check Talents: " +IntToString(nRoll) + + " nMaxLevel: " + IntToString(nMaxLevel) + ")!"); + if(nRoll == 1) + { + if(ai_UseCreatureTalent(oCreature, AI_TALENT_ENHANCEMENT, nInMelee, nMaxLevel, oTarget)) return TRUE; + if(ai_UseCreatureTalent(oCreature, AI_TALENT_PROTECTION, nInMelee, nMaxLevel, oTarget)) return TRUE; + } + else if(nRoll == 2) + { + if(ai_UseCreatureTalent(oCreature, AI_TALENT_PROTECTION, nInMelee, nMaxLevel, oTarget)) return TRUE; + if(ai_UseCreatureTalent(oCreature, AI_TALENT_ENHANCEMENT, nInMelee, nMaxLevel, oTarget)) return TRUE; + } + return FALSE; +} +void ai_SetAura(object oCreature) +{ + // Cycle through a creatures special abilities and use any auras. + int bCanUse, nIndex = 0, nMaxSpAbility = GetSpellAbilityCount(oCreature); + int nSpell = GetSpellAbilitySpell(oCreature, nIndex); + while(nIndex < nMaxSpAbility) + { + bCanUse = FALSE; + if(GetSpellAbilityReady(oCreature, nIndex)) + { + if(nSpell == SPELLABILITY_AURA_BLINDING) bCanUse = TRUE; + else if(nSpell == SPELLABILITY_AURA_COLD) bCanUse = TRUE; + else if(nSpell == SPELLABILITY_AURA_ELECTRICITY) bCanUse = TRUE; + else if(nSpell == SPELLABILITY_AURA_FEAR) bCanUse = TRUE; + else if(nSpell == SPELLABILITY_AURA_FIRE) bCanUse = TRUE; + else if(nSpell == SPELLABILITY_AURA_HORRIFICAPPEARANCE) bCanUse = TRUE; + else if(nSpell == SPELLABILITY_AURA_MENACE) bCanUse = TRUE; + else if(nSpell == SPELLABILITY_AURA_HORRIFICAPPEARANCE) bCanUse = TRUE; + else if(nSpell == SPELLABILITY_AURA_PROTECTION) bCanUse = TRUE; + else if(nSpell == SPELLABILITY_AURA_STUN) bCanUse = TRUE; + else if(nSpell == SPELLABILITY_AURA_UNEARTHLY_VISAGE) bCanUse = TRUE; + else if(nSpell == SPELLABILITY_AURA_UNNATURAL) bCanUse = TRUE; + else if(nSpell == SPELLABILITY_AURA_HORRIFICAPPEARANCE) bCanUse = TRUE; + else if(nSpell == 306 /*SPELLABILITY_AURA_TYRANT_FOG_MIST*/) bCanUse = TRUE; + else if(nSpell == 412 /*SPELLABILITY_AURA_DRAGON_FEAR*/) bCanUse = TRUE; + else if(nSpell == 761 /*SPELLABILITY_AURA_HELLFIRE*/) bCanUse = TRUE; + else if(nSpell == 805/*SPELLABILITY_AURA_TROGLODYTE_STENCH*/) bCanUse = TRUE; + } + if(bCanUse) ActionCastSpellAtObject(nSpell, oCreature, 255, FALSE, 0, 0, TRUE); + nSpell = GetSpellAbilitySpell(oCreature, ++nIndex); + } +} +// ***************************************************************************** +// ************************* Try * Skills ************************************** +// ***************************************************************************** +// These functions try to find and use a specific set of skills intelligently. + +void ai_UseSkill(object oCreature, int nSkill, object oTarget) +{ + ai_SetLastAction(oCreature, AI_LAST_ACTION_USED_SKILL); + if(GetIsEnemy(oTarget, oCreature)) SetLocalObject(oCreature, AI_ATTACKED_PHYSICAL, oTarget); + if(AI_DEBUG) ai_Debug("0i_talents", "498", GetName(oCreature) + " is using skill: " + + GetStringByStrRef(StringToInt(Get2DAString("skills", "Name", nSkill))) + + " on " + GetName(oTarget)); + ActionUseSkill(nSkill, oTarget); + ActionDoCommand(ExecuteScript("0e_do_combat_rnd", oCreature)); +} +int ai_TryParry(object oCreature) +{ + // Only use parry on an active melee attacker + object oTarget = GetLastHostileActor(oCreature); + // If we are already in parry mode then lets keep it up. + if(GetActionMode(oCreature, ACTION_MODE_PARRY) && + GetCurrentAction(oCreature) == ACTION_ATTACKOBJECT) return TRUE; + if(oTarget == OBJECT_INVALID || + ai_GetAttackedTarget(oTarget) != oCreature || + !ai_GetIsMeleeWeapon(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTarget))) return FALSE; + // Only if our parry skill > their attack bonus + 5 + d10 + // Parry has a -4 atk adjustment. Our chance to hit should be 75% + d10. + // EnemyAtk(20) - OurParrySkill(10) = 0 + d10(75% to 25% chance to hit). + int nParrySkill = GetSkillRank(SKILL_PARRY, oCreature); + int nAtk = ai_GetCreatureAttackBonus(oTarget); + if(nAtk - nParrySkill >= 0 + d10()) return FALSE; + ai_EquipBestMeleeWeapon(oCreature, oTarget); + SetActionMode(oCreature, ACTION_MODE_PARRY, TRUE); + ai_SetLastAction(oCreature, AI_LAST_ACTION_USED_SKILL); + ActionAttack(oTarget); + if(AI_DEBUG) ai_Debug("0i_talents", "524", "Using parry against " + GetName(oTarget) + "!"); + return TRUE; +} +int ai_TryTaunt(object oCreature, object oTarget) +{ + int nCoolDown = GetLocalInt(oCreature, "AI_TAUNT_COOLDOWN"); + if(AI_DEBUG) ai_Debug("0i_talents", "530", "Has Taunt Effect? " + + IntToString(ai_GetHasEffectType(oTarget, EFFECT_TYPE_TAUNT)) + + " Cooldown: " + IntToString(nCoolDown)); + if(nCoolDown > 0) + { + SetLocalInt(oCreature, "AI_TAUNT_COOLDOWN", --nCoolDown); + return FALSE; + } + if(!ai_GetHasEffectType(oTarget, EFFECT_TYPE_TAUNT)) return FALSE; + // Check to see if we have a good chance for it to work. + int nTauntRnk = GetSkillRank(SKILL_TAUNT, oCreature); + if(AI_DEBUG) ai_Debug("0i_talents", "542", "Check Taunt: TauntRnk: " + IntToString(nTauntRnk) + + " HitDice + 1: " + IntToString(GetHitDice(oCreature) + 1) + + " Concentration: " + IntToString(GetSkillRank(SKILL_CONCENTRATION, oTarget)) + "."); + int nConcentration = GetSkillRank(SKILL_CONCENTRATION, oTarget); + // Our chance is greater than 50%. + if(nTauntRnk <= nConcentration) return FALSE; + ai_UseSkill(oCreature, SKILL_TAUNT, oTarget); + SetLocalInt(oCreature, "AI_TAUNT_COOLDOWN", AI_TAUNT_COOLDOWN); + return TRUE; +} +int ai_TryAnimalEmpathy(object oCreature, object oTarget = OBJECT_INVALID) +{ + if(!GetSkillRank(SKILL_ANIMAL_EMPATHY, oCreature)) return FALSE; + int nCoolDown = GetLocalInt(oCreature, "AI_EMPATHY_COOLDOWN"); + if(AI_DEBUG) ai_Debug("0i_talents", "556", "Has Dominate Effect? " + + IntToString(ai_GetHasEffectType(oTarget, EFFECT_TYPE_DOMINATED)) + + " Cooldown: " + IntToString(nCoolDown)); + if(nCoolDown > 0) + { + SetLocalInt(oCreature, "AI_EMPATHY_COOLDOWN", --nCoolDown); + return FALSE; + } + if(oTarget == OBJECT_INVALID) + { + oTarget = ai_GetNearestRacialTarget(oCreature, AI_RACIAL_TYPE_ANIMAL_BEAST); + if(oTarget == OBJECT_INVALID) return FALSE; + } + if(!GetObjectSeen(oCreature, oTarget)) return FALSE; + if(ai_GetHasEffectType(oTarget, EFFECT_TYPE_DOMINATED) || + GetIsImmune(oTarget, IMMUNITY_TYPE_MIND_SPELLS) || + GetIsImmune(oTarget, IMMUNITY_TYPE_DOMINATE) || + GetAssociateType(oTarget) != ASSOCIATE_TYPE_NONE) return FALSE; + // Get the race of the target, it only works on Animals, Beasts, and Magical Beasts. + int nRace = GetRacialType(oTarget); + int nDC; + if(nRace == RACIAL_TYPE_ANIMAL) nDC = 5; + else if(nRace == RACIAL_TYPE_BEAST || nRace == RACIAL_TYPE_MAGICAL_BEAST) nDC = 9; + else return FALSE; + // Check to see if we have a good chance for it to work. + int nEmpathyRnk = GetSkillRank(SKILL_ANIMAL_EMPATHY, oCreature); + nDC += GetHitDice(oTarget); + if(AI_DEBUG) ai_Debug("0i_talents", "632", "Check Animal Empathy: Rnk: " + IntToString(nEmpathyRnk) + + " nDC: " + IntToString(nDC) + "."); + // Our chance is greater than 50%. + if(nEmpathyRnk <= nDC) return FALSE; + ai_UseSkill(oCreature, SKILL_ANIMAL_EMPATHY, oTarget); + SetLocalInt(oCreature, "AI_EMPATHY_COOLDOWN", AI_EMPATHY_COOLDOWN); + return TRUE; +} +// ***************************************************************************** +// ************************* Try * Feats *************************************** +// ***************************************************************************** +// These functions try to find and use a specific set of feats intelligently. + +void ai_UseFeat(object oCreature, int nFeat, object oTarget, int nSubFeat = 0) +{ + ai_SetLastAction(oCreature, AI_LAST_ACTION_USED_FEAT); + if(GetIsEnemy(oTarget, oCreature)) SetLocalObject(oCreature, AI_ATTACKED_PHYSICAL, oTarget); + if(AI_DEBUG) ai_Debug("0i_talents", "600", GetName(oCreature) + " is using feat: " + + GetStringByStrRef(StringToInt(Get2DAString("feat", "FEAT", nFeat))) + + " on " + GetName(oTarget)); + ActionUseFeat(nFeat, oTarget, nSubFeat); + ActionDoCommand(ExecuteScript("0e_do_combat_rnd", oCreature)); +} +void ai_UseFeatAttackMode(object oCreature, int nActionMode, int nAction, object oTarget, int nInMelee = 0, int bPassive = FALSE) +{ + if(AI_DEBUG) ai_Debug("0i_talents", "608", "Action mode (" + IntToString(nActionMode) + ") Is it set?: " + + IntToString(GetActionMode(oCreature, nActionMode))); + if(!GetActionMode(oCreature, nActionMode)) + { + if(AI_DEBUG) ai_Debug("0i_talents", "612", "Setting action mode: " + IntToString(nActionMode)); + SetActionMode(oCreature, nActionMode, TRUE); + SetLocalInt(oCreature, AI_CURRENT_ACTION_MODE, nActionMode); + } + ai_ActionAttack(oCreature, nAction, oTarget, nInMelee, bPassive, nActionMode); +} +int ai_TryBarbarianRageFeat(object oCreature) +{ + // Must not have rage already, must have the feat, and enemy must be strong enough. + if(GetHasFeatEffect(FEAT_BARBARIAN_RAGE, oCreature) || + !GetHasFeat(FEAT_BARBARIAN_RAGE, oCreature)) return FALSE; + ai_UseFeat(oCreature, FEAT_BARBARIAN_RAGE, oCreature); + return TRUE; +} +int ai_TryBardSongFeat(object oCreature) +{ + if(AI_DEBUG) ai_Debug("0i_talents", "629", "BardSong Effect: " + IntToString(GetHasSpellEffect(411/*SPELL_BARD_SONG*/)) + + " Level: " + IntToString(GetLevelByClass(CLASS_TYPE_BARD)) + + " HasFeat: " + IntToString(GetHasFeat(FEAT_BARD_SONGS))); + if(GetHasSpellEffect(411/*SPELL_BARD_SONG*/, oCreature) || + !GetHasFeat(FEAT_BARD_SONGS, oCreature)) return FALSE; + ai_UseFeat(oCreature, FEAT_BARD_SONGS, oCreature); + return TRUE; +} +int ai_TryCalledShotFeat(object oCreature, object oTarget) +{ + if(!GetHasFeat(FEAT_CALLED_SHOT, oCreature)) return FALSE; + // Called shot has a -4 to hit adjustment. + if(!ai_AttackPenaltyOk(oCreature, oTarget, -4.0)) return FALSE; + ai_UseFeat(oCreature, FEAT_CALLED_SHOT, oTarget); + return TRUE; +} +int ai_TryDisarmFeat(object oCreature, object oTarget) +{ + if(!GetHasFeat(FEAT_DISARM, oCreature)) return FALSE; + // If we can't disarm them then get out! + if(!GetIsCreatureDisarmable(oTarget)) return FALSE; + int nEAC = GetAC(oTarget); + int nOAtk = ai_GetCreatureAttackBonus(oCreature); + // The combatant with the larger weapon gains +4 per size category. + // Weapon Size in the baseitems.2da is 1 = Tiny, 2 = Small, 3 = Medium, 4 = Large. + int nOWeaponType = GetBaseItemType(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND)); + int nOWeaponSize = StringToInt(Get2DAString("baseitems", "WeaponSize", nOWeaponType)); + int nEWeaponType = GetBaseItemType(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTarget)); + int nEWeaponSize = StringToInt(Get2DAString("baseitems", "WeaponSize", nEWeaponType)); + nOAtk +=(nOWeaponSize - nEWeaponSize) * 4; + // Do they have Improved Disarm? + if(GetHasFeat(FEAT_IMPROVED_DISARM, oCreature)) nOAtk += 2; + // Disarm has a -6 atk adjustment. + if(!ai_AttackPenaltyOk(oCreature, oTarget, -6.0)) return FALSE; + ai_UseFeat(oCreature, FEAT_DISARM, oTarget); + return TRUE; +} +int ai_TryDivineMightFeat(object oCreature, int nInMelee) +{ + if(!GetHasFeat(FEAT_TURN_UNDEAD)) return FALSE; + if(!GetHasFeat(FEAT_DIVINE_MIGHT)) return FALSE; + if(GetHasFeatEffect(FEAT_DIVINE_MIGHT, oCreature)) return FALSE; + if(!nInMelee) return FALSE; + object oTarget = ai_GetEnemyAttackingMe(oCreature); + if(oTarget == OBJECT_INVALID) return FALSE; + float fAtkAdj = IntToFloat(GetAbilityModifier(ABILITY_CHARISMA, oCreature)); + if(!ai_AttackBonusGood(oCreature, oTarget, fAtkAdj)) return FALSE; + if(AI_DEBUG) ai_Debug("0i_talents", "722", "USING DIVINE MIGHT on " + GetName(oCreature) + "."); + ai_UseFeat(oCreature, FEAT_DIVINE_MIGHT, oCreature); + return TRUE; +} +int ai_TryDivineShieldFeat(object oCreature, int nInMelee) +{ + if(!GetHasFeat(FEAT_TURN_UNDEAD)) return FALSE; + if(!GetHasFeat(FEAT_DIVINE_SHIELD)) return FALSE; + if(GetHasFeatEffect(FEAT_DIVINE_SHIELD, oCreature)) return FALSE; + if(!nInMelee) return FALSE; + object oTarget = ai_GetEnemyAttackingMe(oCreature); + if(oTarget == OBJECT_INVALID) return FALSE; + float fACAdj = IntToFloat(GetAbilityModifier(ABILITY_CHARISMA, oCreature)); + if(!ai_ACAdjustmentGood(oCreature, oTarget, fACAdj)) return FALSE; + if(AI_DEBUG) ai_Debug("0i_talents", "736", "USING DIVINE SHIELD on " + GetName(oCreature) + "."); + ai_UseFeat(oCreature, FEAT_DIVINE_SHIELD, oCreature); + return TRUE; +} +int ai_TryExpertiseFeat(object oCreature) +{ + if(!GetHasFeat(FEAT_EXPERTISE, oCreature)) return FALSE; + object oTarget = ai_GetEnemyAttackingMe(oCreature); + // Expertise has a -5 atk and a +5 AC adjustment. + if(oTarget == OBJECT_INVALID || + !ai_AttackPenaltyOk(oCreature, oTarget, -5.0) || + !ai_ACAdjustmentGood(oCreature, oTarget, 5.0)) + { + SetActionMode(oCreature, ACTION_MODE_EXPERTISE, FALSE); + DeleteLocalInt(oCreature, AI_CURRENT_ACTION_MODE); + return FALSE; + } + if(AI_DEBUG) ai_Debug("0i_talents", "704", "USING EXPERTISE on " + GetName(oTarget) + "."); + ai_UseFeatAttackMode(oCreature, ACTION_MODE_EXPERTISE, AI_LAST_ACTION_MELEE_ATK, oTarget); + return TRUE; +} +int ai_TryFlurryOfBlowsFeat(object oCreature, object oTarget) +{ + if(!GetHasFeat(FEAT_FLURRY_OF_BLOWS, oCreature)) return FALSE; + // Flurry of Blows has a -2 atk adjustment. + if(!ai_AttackPenaltyOk(oCreature, oTarget, -2.0)) + { + SetActionMode(oCreature, ACTION_MODE_FLURRY_OF_BLOWS, FALSE); + DeleteLocalInt(oCreature, AI_CURRENT_ACTION_MODE); + return FALSE; + } + if(AI_DEBUG) ai_Debug("0i_talents", "718", "USING FLURRY OF BLOWS on " + GetName(oTarget) + "."); + ai_UseFeatAttackMode(oCreature, ACTION_MODE_FLURRY_OF_BLOWS, AI_LAST_ACTION_MELEE_ATK, oTarget, TRUE); + return TRUE; +} +int ai_TryImprovedExpertiseFeat(object oCreature) +{ + if(!GetHasFeat(FEAT_IMPROVED_EXPERTISE, oCreature)) return FALSE; + object oTarget = ai_GetEnemyAttackingMe(oCreature); + // Improved expertise has a -10 atk +10 AC adjustment. + if(oTarget == OBJECT_INVALID || + !ai_AttackPenaltyOk(oCreature, oTarget, -10.0) || + !ai_ACAdjustmentGood(oCreature, oTarget, 10.0)) + { + SetActionMode(oCreature, ACTION_MODE_IMPROVED_EXPERTISE, FALSE); + DeleteLocalInt(oCreature, AI_CURRENT_ACTION_MODE); + return FALSE; + } + if(AI_DEBUG) ai_Debug("0i_talents", "735", "USING IMPROVED EXPERTISE on " + GetName(oTarget) + "."); + ai_UseFeatAttackMode(oCreature, ACTION_MODE_IMPROVED_EXPERTISE, AI_LAST_ACTION_MELEE_ATK, oTarget); + return TRUE; +} +int ai_TryImprovedPowerAttackFeat(object oCreature, object oTarget) +{ + if(!GetHasFeat(FEAT_IMPROVED_POWER_ATTACK, oCreature)) return FALSE; + // Improved Power Attack has a -10 atk adjustment. + // If we cannot hit or will kill in one hit then maybe we should use Power Attack instead. + if(ai_PowerAttackGood(oCreature, oTarget, 10.0)) + { + ai_UseFeatAttackMode(oCreature, ACTION_MODE_IMPROVED_POWER_ATTACK, AI_LAST_ACTION_MELEE_ATK, oTarget); + return TRUE; + } + SetActionMode(oCreature, ACTION_MODE_IMPROVED_POWER_ATTACK, FALSE); + DeleteLocalInt(oCreature, AI_CURRENT_ACTION_MODE); + return ai_TryPowerAttackFeat(oCreature, oTarget); +} +int ai_TryKiDamageFeat(object oCreature, object oTarget) +{ + if(!GetHasFeat(FEAT_KI_DAMAGE, oCreature)) return FALSE; + // Must have > 40 hitpoints AND + // Damage reduction OR damage resistance + // or just have over 200 hitpoints + int bHasDamageReduction = FALSE; + int bHasDamageResistance = FALSE; + int bHasHitpoints = FALSE; + int bHasMassiveHitpoints = FALSE; + int bOutNumbered; + int nCurrentHP = GetCurrentHitPoints(oTarget); + if(nCurrentHP > 40) bHasHitpoints = TRUE; + if(nCurrentHP > 200) bHasMassiveHitpoints = TRUE; + if(ai_GetHasEffectType(oTarget, EFFECT_TYPE_DAMAGE_REDUCTION)) bHasDamageReduction = TRUE; + if(ai_GetHasEffectType(oTarget, EFFECT_TYPE_DAMAGE_RESISTANCE)) bHasDamageResistance = TRUE; + if(ai_GetNearestEnemy(oCreature, 3, 7, 7) != OBJECT_INVALID) bOutNumbered = TRUE; + if((!bHasHitpoints || (!bHasDamageReduction && !bHasDamageResistance)) && + (!bHasMassiveHitpoints) && (!bHasHitpoints || !bOutNumbered)) return FALSE; + ai_UseFeat(oCreature, FEAT_KI_DAMAGE, oTarget); + return TRUE; +} +int ai_TryKnockdownFeat(object oCreature, object oTarget) +{ + if(!GetHasFeat(FEAT_KNOCKDOWN, oCreature)) return FALSE; + int nMySize = GetCreatureSize(oCreature); + if(GetHasFeat(FEAT_IMPROVED_KNOCKDOWN, oCreature)) nMySize++; + // Prevent silly use of knockdown on immune or too-large targets. + // Knockdown has a -4 atk adjustment. + if(GetIsImmune(oTarget, IMMUNITY_TYPE_KNOCKDOWN) || + GetCreatureSize(oTarget) > nMySize + 1 || + !ai_AttackPenaltyOk(oCreature, oTarget, -4.0)) return FALSE; + ai_UseFeat(oCreature, FEAT_KNOCKDOWN, oTarget); + return TRUE; +} +int ai_TryPolymorphSelfFeat(object oCreature) +{ + if(GetHasFeat(FEAT_EPIC_OUTSIDER_SHAPE)) + { + int nSubFeat = Random(3) + 733; // 733 azer, 734 rakshasa, 735 Slaad. + if(ai_UseFeat(oCreature, FEAT_EPIC_OUTSIDER_SHAPE, oCreature, nSubFeat)) return TRUE; + } + else if(GetHasFeat(FEAT_EPIC_CONSTRUCT_SHAPE)) + { + int nSubFeat = Random(3) + 738; // 738 Stone, 739 Flesh, 740 Iron. + if(ai_UseFeat(oCreature, FEAT_EPIC_CONSTRUCT_SHAPE, oCreature, nSubFeat)) return TRUE; + } + else if(GetHasFeat(FEAT_EPIC_WILD_SHAPE_DRAGON)) + { + int nSubFeat = Random(3) + 707; // 707 Red, 708 Blue, 709 Green. + if(ai_UseFeat(oCreature, FEAT_EPIC_WILD_SHAPE_DRAGON, oCreature, nSubFeat)) return TRUE; + } + else if(GetHasFeat(FEAT_EPIC_WILD_SHAPE_UNDEAD)) + { + int nSubFeat = Random(3) + 704; // 704 Risen Lord, 705 Vampire, 706 Spectre. + if(ai_UseFeat(oCreature, FEAT_EPIC_WILD_SHAPE_UNDEAD, oCreature, nSubFeat)) return TRUE; + } + else if(GetHasFeat(FEAT_GREATER_WILDSHAPE_4)) + { + int nSubFeat; + int nRoll = d3(); + if(nRoll == 1) nSubFeat = 679; // Medusa + else if(nRoll == 2) nSubFeat = 691; // Mindflayer + else nSubFeat = 694; // DireTiger + if(ai_UseFeat(oCreature, FEAT_GREATER_WILDSHAPE_4, oCreature, nSubFeat)) return TRUE; + } + else if(GetHasFeat(FEAT_GREATER_WILDSHAPE_3)) + { + int nSubFeat; + int nRoll = d3(); + if(nRoll == 1) nSubFeat = 670; // Basilisk + else if(nRoll == 2) nSubFeat = 673; // Drider + else nSubFeat = 674; // Manticore + if(ai_UseFeat(oCreature, FEAT_GREATER_WILDSHAPE_3, oCreature, nSubFeat)) return TRUE; + } + else if(GetHasFeat(FEAT_GREATER_WILDSHAPE_2)) + { + int nSubFeat; + int nRoll = d3(); + if(nRoll == 1) nSubFeat = 672; // Harpy + else if(nRoll == 2) nSubFeat = 678; // Gargoyle + else nSubFeat = 680; // Minotaur + if(ai_UseFeat(oCreature, FEAT_GREATER_WILDSHAPE_2, oCreature, nSubFeat)) return TRUE; + } + else if(GetHasFeat(FEAT_GREATER_WILDSHAPE_1)) + { + int nSubFeat = Random(5) + 658; // Wyrmling + if(ai_UseFeat(oCreature, FEAT_GREATER_WILDSHAPE_1, oCreature, nSubFeat)) return TRUE; + } + if(GetHasFeat(FEAT_HUMANOID_SHAPE)) + { + int nSubFeat = Random(3) + 682; // 682 Drow, 683 Lizard, 684 Kobold. + if(ai_UseFeat(oCreature, FEAT_HUMANOID_SHAPE, oCreature, nSubFeat)) return TRUE; + } + else if(GetHasFeat(FEAT_ELEMENTAL_SHAPE)) + { + int nSubFeat = Random(4) + SUBFEAT_ELEMENTAL_SHAPE_EARTH; + if(ai_UseFeat(oCreature, FEAT_ELEMENTAL_SHAPE, oCreature, nSubFeat)) return TRUE; + } + else if(GetHasFeat(FEAT_WILD_SHAPE)) + { + int nSubFeat; + int nCompanionType = GetAnimalCompanionCreatureType(oCreature); + if(nCompanionType == ANIMAL_COMPANION_CREATURE_TYPE_NONE) + nSubFeat = Random(5) + SUBFEAT_WILD_SHAPE_BROWN_BEAR; + else + { + if(nCompanionType == ANIMAL_COMPANION_CREATURE_TYPE_BADGER) + nSubFeat = SUBFEAT_WILD_SHAPE_BADGER; + else if(nCompanionType == ANIMAL_COMPANION_CREATURE_TYPE_BOAR) + nSubFeat = SUBFEAT_WILD_SHAPE_BOAR; + else if(nCompanionType == ANIMAL_COMPANION_CREATURE_TYPE_BEAR) + nSubFeat = SUBFEAT_WILD_SHAPE_BROWN_BEAR; + else if(nCompanionType == ANIMAL_COMPANION_CREATURE_TYPE_PANTHER) + nSubFeat = SUBFEAT_WILD_SHAPE_PANTHER; + else if(nCompanionType == ANIMAL_COMPANION_CREATURE_TYPE_WOLF) + nSubFeat = SUBFEAT_WILD_SHAPE_WOLF; + else nSubFeat = Random(5) + SUBFEAT_WILD_SHAPE_BROWN_BEAR; + } + if(AI_DEBUG) ai_Debug("0i_talents", "885", " Using wild shape feat: " + IntToString(nSubFeat)); + ai_UseFeat(oCreature, FEAT_WILD_SHAPE, oCreature, nSubFeat); + return TRUE; + } + return FALSE; +} +int ai_TryPowerAttackFeat(object oCreature, object oTarget) +{ + if(!GetHasFeat(FEAT_POWER_ATTACK, oCreature)) return FALSE; + // Power Attack has a -5 atk adjustment. + if(ai_PowerAttackGood(oCreature, oTarget, 5.0)) + { + ai_UseFeatAttackMode(oCreature, ACTION_MODE_POWER_ATTACK, AI_LAST_ACTION_MELEE_ATK, oTarget); + return TRUE; + } + SetActionMode(oCreature, ACTION_MODE_POWER_ATTACK, FALSE); + DeleteLocalInt(oCreature, AI_CURRENT_ACTION_MODE); + return FALSE; +} +int ai_TryQuiveringPalmFeat(object oCreature, object oTarget) +{ + // Must have the feat, and enemy must be lower level, and not immune to crits. + if(!GetHasFeat(FEAT_QUIVERING_PALM, oCreature) || + GetHitDice(oTarget) >= GetHitDice(oCreature) || + GetIsImmune(oTarget, IMMUNITY_TYPE_CRITICAL_HIT)) return FALSE; + ai_UseFeat(oCreature, FEAT_QUIVERING_PALM, oTarget); + return TRUE; +} +int ai_TryRapidShotFeat(object oCreature, object oTarget, int nInMelee) +{ + if(!GetHasFeat(FEAT_RAPID_SHOT, oCreature)) return FALSE; + // Rapidshot has a -4 atk adjustment. + if(!ai_AttackPenaltyOk(oCreature, oTarget, -4.0)) + { + SetActionMode(oCreature, ACTION_MODE_RAPID_SHOT, FALSE); + DeleteLocalInt(oCreature, AI_CURRENT_ACTION_MODE); + return FALSE; + } + ai_UseFeatAttackMode(oCreature, ACTION_MODE_RAPID_SHOT, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE); + return TRUE; +} +int ai_TrySapFeat(object oCreature, object oTarget) +{ + if(!GetHasFeat(FEAT_SAP, oCreature)) return FALSE; + // Does not work on creatures that cannot be hit by criticals or stunned. + // Sap has a -4 atk adjustment. + if(GetIsImmune(oTarget, IMMUNITY_TYPE_CRITICAL_HIT) || + GetIsImmune(oTarget, IMMUNITY_TYPE_STUN) || + !ai_AttackPenaltyOk(oCreature, oTarget, -4.0)) return FALSE; + ai_UseFeat(oCreature, FEAT_SAP, oTarget); + return TRUE; +} +int ai_TrySmiteEvilFeat(object oCreature, object oTarget) +{ + if(!GetHasFeat(FEAT_SMITE_EVIL, oCreature) || + GetAlignmentGoodEvil(oTarget) != ALIGNMENT_EVIL || + !ai_StrongOpponent(oCreature, oTarget)) return FALSE; + ai_UseFeat(oCreature, FEAT_SMITE_EVIL, oTarget); + return TRUE; +} +int ai_TrySmiteGoodFeat(object oCreature, object oTarget) +{ + if(!GetHasFeat(FEAT_SMITE_GOOD, oCreature) || + GetAlignmentGoodEvil(oTarget) != ALIGNMENT_GOOD || + !ai_StrongOpponent(oCreature, oTarget)) return FALSE; + ai_UseFeat(oCreature, FEAT_SMITE_GOOD, oTarget); + return TRUE; +} +int ai_TryStunningFistFeat(object oCreature, object oTarget) +{ + // Cannot use if we have a weapon equiped. + if(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oCreature) != OBJECT_INVALID) return FALSE; + // Does not work on creatures that cannot be hit by criticals or stunned. + // Stunning Fists has a -4 atk adjustment. + if(!GetHasFeat(FEAT_STUNNING_FIST, oCreature) || + GetIsImmune(oTarget, IMMUNITY_TYPE_CRITICAL_HIT) || + GetIsImmune(oTarget, IMMUNITY_TYPE_STUN) || + !ai_StrongOpponent(oCreature, oTarget) || + !ai_AttackPenaltyOk(oCreature, oTarget, -4.0)) return FALSE; + ai_UseFeat(oCreature, FEAT_STUNNING_FIST, oTarget); + return TRUE; +} +void ai_NameAssociate(object oCreature, int nAssociateType, string sName) +{ + object oAssociate = GetAssociate(nAssociateType, oCreature); + if(GetName(oCreature) != "") return; + SetName(oAssociate, sName); + ChangeFaction(oAssociate, oCreature); +} +int ai_TrySummonAnimalCompanionTalent(object oCreature) +{ + if(!GetHasFeat(FEAT_ANIMAL_COMPANION, oCreature)) return FALSE; + if(GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION, oCreature) != OBJECT_INVALID) return FALSE; + ai_UseFeat(oCreature, FEAT_ANIMAL_COMPANION, oCreature); + DelayCommand(0.0, ai_NameAssociate(oCreature, ASSOCIATE_TYPE_FAMILIAR, "Animal Companion")); + return TRUE; +} +int ai_TrySummonFamiliarTalent(object oCreature) +{ + if(!GetHasFeat(FEAT_SUMMON_FAMILIAR, oCreature)) return FALSE; + if(GetAssociate(ASSOCIATE_TYPE_FAMILIAR, oCreature) != OBJECT_INVALID) return FALSE; + ai_UseFeat(oCreature, FEAT_SUMMON_FAMILIAR, oCreature); + DelayCommand(0.0, ai_NameAssociate(oCreature, ASSOCIATE_TYPE_FAMILIAR, "Familiar")); + return TRUE; +} +int ai_TryLayOnHands(object oCreature) +{ + if(!GetHasFeat(FEAT_LAY_ON_HANDS, oCreature)) return FALSE; + // Lets not run past an enemy to use touch atk unless we have the feats, bad tactics! + float fRange; + if(ai_CanIMoveInCombat(oCreature)) fRange = AI_RANGE_PERCEPTION; + else + { + fRange = GetDistanceBetween(oCreature, GetLocalObject(oCreature, AI_ENEMY_NEAREST)) - 3.0f; + // Looks bad when your right next to an ally, but technically the enemy is closer. + if(fRange < AI_RANGE_MELEE) fRange = AI_RANGE_MELEE; + } + object oTarget = ai_GetLowestCRRacialTarget(oCreature, RACIAL_TYPE_UNDEAD, fRange); + if(oTarget == OBJECT_INVALID) return FALSE; + ai_UseFeat(oCreature, FEAT_LAY_ON_HANDS, oTarget); + return TRUE; +} +int ai_TryTurningTalent(object oCreature) +{ + if(!GetHasFeat(FEAT_TURN_UNDEAD, oCreature)) return FALSE; + if(AI_DEBUG) ai_Debug("0i_talents", "1043", "Checking for Turning Targets."); + int nHDCount, nHDCount2, nRacial, nHD; + // Get characters levels. + int nClericLevel = GetLevelByClass(CLASS_TYPE_CLERIC, oCreature); + int nPaladinLevel = GetLevelByClass(CLASS_TYPE_PALADIN, oCreature); + int nBlackguardlevel = GetLevelByClass(CLASS_TYPE_BLACKGUARD, oCreature); + int nTotalLevel = GetHitDice(oCreature); + int nTurnLevel = nClericLevel; + int nClassLevel = nClericLevel; + // GZ: Since paladin levels stack when turning, blackguard levels should stack as well + // GZ: but not with the paladin levels (thus else if). + if(nBlackguardlevel - 2 > 0 && nBlackguardlevel > nPaladinLevel) + { + nClassLevel += (nBlackguardlevel - 2); + nTurnLevel += (nBlackguardlevel - 2); + } + else if(nPaladinLevel - 2 > 0) + { + nClassLevel += (nPaladinLevel - 2); + nTurnLevel += (nPaladinLevel - 2); + } + //Flags for bonus turning types + int nElemental = GetHasFeat(FEAT_AIR_DOMAIN_POWER, oCreature) + + GetHasFeat(FEAT_EARTH_DOMAIN_POWER, oCreature) + + GetHasFeat(FEAT_FIRE_DOMAIN_POWER, oCreature) + + GetHasFeat(FEAT_WATER_DOMAIN_POWER, oCreature); + int nVermin = GetHasFeat(FEAT_PLANT_DOMAIN_POWER, oCreature); + int nConstructs = GetHasFeat(FEAT_DESTRUCTION_DOMAIN_POWER, oCreature); + int nGoodOrEvilDomain = GetHasFeat(FEAT_GOOD_DOMAIN_POWER, oCreature) + + GetHasFeat(FEAT_EVIL_DOMAIN_POWER, oCreature); + int nPlanar = GetHasFeat(854, oCreature); + // Get turning check average, modify if have the Sun Domain + int nChrMod = GetAbilityModifier(ABILITY_CHARISMA, oCreature); + int nTurnCheck = 15 + nChrMod; //The roll to apply to the max HD of undead that can be turned --> nTurnLevel + int nTurnHD = 12 + nChrMod + nClassLevel; //The number of HD of undead that can be turned. + if(GetHasFeat(FEAT_SUN_DOMAIN_POWER, oCreature)) + { + nTurnCheck += 2; + nTurnHD += 3; + } + //Determine the maximum HD of the undead that can be turned using a roll of 15 + ChrMod. + if(nTurnCheck == 15) nTurnLevel += 1; + else if(nTurnCheck >= 16 && nTurnCheck <= 18) nTurnLevel += 2; + else if(nTurnCheck >= 19 && nTurnCheck <= 21) nTurnLevel += 3; + else if(nTurnCheck >= 22) nTurnLevel += 4; + // Collect the number of HitDice we will affect. + int nCnt = 1; + object oEnemy = GetNearestCreature(7, 7, oCreature, nCnt); + while(oEnemy != OBJECT_INVALID && nHDCount < nTurnHD && GetDistanceBetween(oEnemy, oCreature) <= 20.0) + { + if(GetIsEnemy(oEnemy, oCreature) && !ai_Disabled(oEnemy)) + { + nRacial = GetRacialType(oEnemy); + nHD = 0; + if(nRacial == RACIAL_TYPE_UNDEAD) nHD = GetHitDice(oEnemy) + GetTurnResistanceHD(oEnemy); + else if(nRacial == RACIAL_TYPE_OUTSIDER && nGoodOrEvilDomain + nPlanar > 0) + { + //Planar turning decreases spell resistance against turning by 1/2 + if(nPlanar) nHD = GetHitDice(oEnemy) + (GetSpellResistance(oEnemy) / 2); + else nHD = GetHitDice(oEnemy) + GetSpellResistance(oEnemy); + } + else if(nRacial == RACIAL_TYPE_VERMIN && nVermin > 0) nHD = GetHitDice(oEnemy); + else if(nRacial == RACIAL_TYPE_ELEMENTAL && nElemental > 0) nHD = GetHitDice(oEnemy); + else if (nRacial == RACIAL_TYPE_CONSTRUCT && nConstructs > 0) nHD = GetHitDice(oEnemy); + // Only count undead we can defeat! + if(AI_DEBUG) ai_Debug("0i_talents", "1110", " nHD: " + IntToString(nHD) + + " nTurnLevel: " + IntToString(nTurnLevel) + + " nTurnHD: " + IntToString(nTurnHD) + + " nHDCount: " + IntToString(nHDCount)); + if(nHD > 0 && nHD <= nTurnLevel && nHD <= (nTurnHD - nHDCount)) nHDCount += nHD; + } + oEnemy = GetNearestCreature(7, 7, oCreature, ++nCnt); + } + if(AI_DEBUG) ai_Debug("0i_talents", "1089", "Found " + IntToString(nHDCount) + " hitdice to turn from my location."); + // Lets do one more check to see if we can get a better position to use TurnUndead. + nCnt = 1; + object oNearestEnemy = GetLocalObject(oCreature, AI_ENEMY_NEAREST); + if(GetDistanceBetween(oCreature, oNearestEnemy) > AI_RANGE_MELEE) + { + oEnemy = oNearestEnemy; + if(AI_DEBUG) ai_Debug("0i_talents", "1126", GetName(oEnemy)); + while(oEnemy != OBJECT_INVALID && nHDCount2 < nTurnHD && GetDistanceBetween(oEnemy, oNearestEnemy) <= 20.0) + { + if(AI_DEBUG) ai_Debug("0i_talents", "1129", GetName(oEnemy)); + if(GetIsEnemy(oEnemy, oCreature) && !ai_Disabled(oEnemy)) + { + nRacial = GetRacialType(oEnemy); + nHD = 0; + if(nRacial == RACIAL_TYPE_UNDEAD) nHD = GetHitDice(oEnemy) + GetTurnResistanceHD(oEnemy); + else if(nRacial == RACIAL_TYPE_OUTSIDER && nGoodOrEvilDomain + nPlanar > 0) + { + //Planar turning decreases spell resistance against turning by 1/2 + if(nPlanar) nHD = GetHitDice(oEnemy) + (GetSpellResistance(oEnemy) / 2); + else nHD = GetHitDice(oEnemy) + GetSpellResistance(oEnemy); + } + else if(nRacial == RACIAL_TYPE_VERMIN && nVermin > 0) nHD = GetHitDice(oEnemy); + else if(nRacial == RACIAL_TYPE_ELEMENTAL && nElemental > 0) nHD = GetHitDice(oEnemy); + else if (nRacial == RACIAL_TYPE_CONSTRUCT && nConstructs > 0) nHD = GetHitDice(oEnemy); + // Only count undead we can defeat! + if(AI_DEBUG) ai_Debug("0i_talents", "1140", " nHD: " + IntToString(nHD) + + " nTurnLevel: " + IntToString(nTurnLevel) + + " nTurnHD: " + IntToString(nTurnHD) + + " nHDCount2: " + IntToString(nHDCount2)); + if(nHD > 0 && nHD <= nTurnLevel && nHD <= (nTurnHD - nHDCount2)) nHDCount2 += nHD; + } + oEnemy = GetNearestCreature(7, 7, oNearestEnemy, ++nCnt); + } + } + if(AI_DEBUG) ai_Debug("0i_talents", "1148", "Found " + IntToString(nHDCount2) + " hitdice to turn from enemy location."); + if(nHDCount > nHDCount2) + { + if(AI_DEBUG) ai_Debug("0i_talents", "1176", " My Location - nHDCount: " + IntToString(nHDCount) + + " >= nTurnHD / 2: " + IntToString(nTurnHD / 2)); + if(nHDCount < nTurnHD / 2) return FALSE; + ai_UseFeat(oCreature, FEAT_TURN_UNDEAD, oCreature); + return TRUE; + } + else + { + if(AI_DEBUG) ai_Debug("0i_talents", "1184", " Better location - nHDCount2: " + IntToString(nHDCount2) + + " >= nTurnHD / 2: " + IntToString(nTurnHD / 2)); + if(nHDCount2 < nTurnHD / 2) return FALSE; + ActionMoveToObject(oNearestEnemy, TRUE, 1.0f); + ai_UseFeat(oCreature, FEAT_TURN_UNDEAD, oCreature); + return TRUE; + } + return FALSE; +} +int ai_TryWhirlwindFeat(object oCreature) +{ + if(!GetHasFeat(FEAT_WHIRLWIND_ATTACK, oCreature)) return FALSE; + // Only worth using if there are 3+ targets. + if(AI_DEBUG) ai_Debug("0i_talents", "860", "WHIRLWIND : NumOfEnemies: " + IntToString(ai_GetNumOfEnemiesInGroup(oCreature, 3.0)) + "."); + // Shortened distance so its more effective(went from 5.0 to 2.0 and up to 3.0) + if(ai_GetNumOfEnemiesInGroup(oCreature, 3.0) < d3() + 1) return FALSE; + // * DO NOT WHIRLWIND if any of the targets are "large" or bigger + // * it seldom works against such large opponents. + // * Though its okay to use Improved Whirlwind against these targets + if((!GetHasFeat(FEAT_IMPROVED_WHIRLWIND, oCreature)) || + (GetCreatureSize(ai_GetNearestEnemy(oCreature, 1, 7, 7)) >= CREATURE_SIZE_LARGE && + GetCreatureSize(ai_GetNearestEnemy(oCreature, 2, 7, 7)) >= CREATURE_SIZE_LARGE)) + ai_UseFeat(oCreature, FEAT_WHIRLWIND_ATTACK, oCreature); + return TRUE; +} +int ai_TryWholenessOfBodyFeat(object oCreature) +{ + if(!GetHasFeat(FEAT_WHOLENESS_OF_BODY, oCreature)) return FALSE; + // Get when we are suppose to heal base off conversation with PC or + // on spawn generation. + int nHp = ai_GetPercHPLoss(oCreature); + if(nHp >= AI_HEALTH_WOUNDED) return FALSE; + ai_UseFeat(oCreature, FEAT_WHOLENESS_OF_BODY, oCreature); + return TRUE; +} +// ***************************************************************************** +// ******************** Try Physical Attack Talents **************************** +// ***************************************************************************** +// These functions try to find and use physical attack talents intelligently. + +void ai_ActionAttack(object oCreature, int nAction, object oTarget, int nInMelee = 0, int bPassive = FALSE, int nActionMode = 0) +{ + // If we are doing a ranged attack then check our position on the battlefield. + if(nAction == AI_LAST_ACTION_RANGED_ATK && ai_CheckCombatPosition(oCreature, oTarget, nInMelee, nAction)) return; + ai_SetLastAction(oCreature, nAction); + SetLocalObject(oCreature, AI_ATTACKED_PHYSICAL, oTarget); + if(AI_DEBUG) ai_Debug("0i_talents", "894", GetName(oCreature) + " is attacking(" + IntToString(nAction) + + ") " + GetName(oTarget) + " Current Action: " + IntToString(GetCurrentAction(oCreature)) + + " Lastround Attacked Target: " + GetName(ai_GetAttackedTarget(oCreature)) + + " bPassive: " + IntToString(bPassive) + " nActionMode: " + IntToString(nActionMode)); + ActionAttack(oTarget, bPassive); + if(nActionMode == 0) ActionDoCommand(ExecuteScript("0e_do_combat_rnd", oCreature)); +} +void ai_FlyToAttacks(object oCreature, object oTarget) +{ + ai_TryWingAttacks(oCreature); + // If we don't do a Tail sweep attack then see if we can do a Tail slap! + if(!ai_TryTailSweepAttack(oCreature)) ai_TryTailSlap(oCreature); + ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); +} +void ai_FlyToTarget(object oCreature, object oTarget) +{ + if(AI_DEBUG) ai_Debug("0i_talents", "908", GetName(OBJECT_SELF) + " is flying to " + GetName(oTarget) + "!"); + effect eFly = EffectDisappearAppear(GetLocation(oTarget)); + ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eFly, oCreature, 3.0f); + DelayCommand(4.0f, ai_FlyToAttacks(oCreature, oTarget)); + // Used to make creature wait before starting its next round. + SetLocalInt(oCreature, AI_COMBAT_WAIT_IN_SECONDS, 5); +} +int ai_TryDragonBreathAttack(object oCreature, int nRound, object oTarget = OBJECT_INVALID) +{ + int nCnt = GetLocalInt(oCreature, "AI_DRAGONS_BREATH"); + if(AI_DEBUG) ai_Debug("0i_talents", "918", "Try Dragon Breath Attack: nRound(" + IntToString(nRound) + ")" + + " <= nCnt(" + IntToString(nCnt) + ")!"); + if(nRound <= nCnt) return FALSE; + talent tUse = GetCreatureTalentBest(TALENT_CATEGORY_DRAGONS_BREATH, 20, oCreature); + if(!GetIsTalentValid(tUse)) return FALSE; + if(oTarget == OBJECT_INVALID) + { + string sIndex = IntToString(ai_GetHighestMeleeIndexNotInAOE(oCreature)); + oTarget = GetLocalObject(oCreature, AI_ENEMY + sIndex); + if(oTarget == OBJECT_INVALID) return FALSE; + } + SetLocalInt(oCreature, "AI_DRAGONS_BREATH", d4() + nRound); + ActionCastSpellAtObject(GetIdFromTalent(tUse), oTarget); + if(AI_DEBUG) ai_Debug("0i_talents", "1019", GetName(oCreature) + " breaths on " + GetName(oTarget) + "!"); + return TRUE; +} +void ai_DragonMeleeAttack(object oCreature, object oTarget, string sDmgDice, string sText) +{ + if(AI_DEBUG) ai_Debug("0i_talents", "941", "oAttacker: " + GetName(oCreature) + + " oTarget: " + GetName(oTarget)); + int nDmg, nCheck, nAB = ai_GetCreatureAttackBonus(oCreature) - 5; + int nAC = GetAC(oTarget); + int nRoll = d20(); + string sHit; + // nCheck is a hit if nCheck > -1 and a miss if < 0; + if(nRoll == 20) nCheck = 20; + // We add one to the check so a equal result is still a hit. + else if(nRoll > 1) nCheck = nRoll + nAB - nAC + 1; + else nCheck == 0; + if(nCheck > 0) + { + nDmg = ai_RollDiceString(sDmgDice); + if(nCheck == 20) nDmg = nDmg * 2; + } + if(nCheck > 0) sHit = "*hit*"; + else sHit = "*miss*"; + string sMessage = ai_AddColorToText(GetName(oCreature) + "'s", AI_COLOR_LIGHT_MAGENTA) + + ai_AddColorToText(sText + "attacks " + GetName(oTarget) + " : " + sHit + " :(" + + IntToString(nRoll) + " + " + IntToString(nAB) + + " = " + IntToString(nRoll + nAB) + ")", AI_COLOR_DARK_ORANGE); + if(ai_GetIsCharacter(oTarget)) SendMessageToPC(oCreature, sMessage); + if(ai_GetIsCharacter(oTarget)) SendMessageToPC(oTarget, sMessage); + if(AI_DEBUG) ai_Debug("0i_talents", "965", "nAB: " + IntToString(nAB) + + " nAC: " + IntToString(nAC) + " nRoll: " + IntToString(nRoll) + + " nCheck: " + IntToString(nCheck) + " nDmg: " + IntToString(nDmg)); + if(nCheck <= 0) return; + // Apply any damage to the target! + effect eDmg = EffectDamage(nDmg, DAMAGE_TYPE_BLUDGEONING); + ApplyEffectToObject(DURATION_TYPE_INSTANT, eDmg, oTarget); +} +// Checks to see if a dragon can use its wings on a nearby enemy. +// Checks the right side and then the left side to see if it can attack. +int ai_TryWingAttacks(object oCreature) +{ + if(AI_DEBUG) ai_Debug("0i_talents", "977", GetName(oCreature) + " is checking for wing Attacks!"); + // Only Medium size dragons can use thier wings in combat. + // We use HitDice to base size S:1-5, M:6-11, L:12-17, H:18-29, G:30-39, C:40+. + int nHitDice = GetHitDice(oCreature); + if(nHitDice <= 5) return FALSE; + int nDragonSize; + string sDmgDice, sMessage; + float fSize; + // Get the stats based on the size of the dragon. + if(nHitDice < 12) { fSize = 5.0f; nDragonSize = 3; sDmgDice = "1d4"; } // Medium + else if(nHitDice < 18) { fSize = 10.0f; nDragonSize = 4; sDmgDice = "1d6"; } // Large + else if(nHitDice < 30) { fSize = 10.0f; nDragonSize = 5; sDmgDice = "1d8"; } // Huge + else if(nHitDice < 40) { fSize = 15.0f; nDragonSize = 6; sDmgDice = "2d6"; } // Gargantuan + else { fSize = 15.0f; nDragonSize = 7; sDmgDice = "2d8"; } // Colossal + // Add half the dragons strength modifier. + int nDmg = GetAbilityModifier(ABILITY_STRENGTH, oCreature); + if(nDmg > 0) sDmgDice = sDmgDice + "+" + IntToString(nDmg / 2); + if(AI_DEBUG) ai_Debug("0i_talents", "994", "nHitDice: " + IntToString(nHitDice) + + " nDragonSize: " + IntToString(nDragonSize) + + " sDmgDice: " + sDmgDice + " nDmg: " + IntToString(nDmg)); + // Get the closest enemy to our right wing. + location lWing = GetFlankingRightLocation(oCreature); + object oTarget = GetFirstObjectInShape(SHAPE_SPHERE, fSize, lWing); + while(oTarget != OBJECT_INVALID) + { + if(AI_DEBUG) ai_Debug("0i_talents", "1002", "oTarget: " + GetName(oTarget)); + if(GetIsEnemy(oTarget, oCreature) && !GetIsDead(oTarget)) break; + oTarget = GetNextObjectInShape(SHAPE_SPHERE, fSize, lWing); + } + if(oTarget != OBJECT_INVALID) ai_DragonMeleeAttack(oCreature, oTarget, sDmgDice, " right wing "); + // Get the closest enemy to our left wing. + lWing = GetFlankingLeftLocation(oCreature); + oTarget = GetFirstObjectInShape(SHAPE_SPHERE, fSize, lWing); + while(oTarget != OBJECT_INVALID) + { + if(AI_DEBUG) ai_Debug("0i_talents", "1012", "oTarget: " + GetName(oTarget)); + if(GetIsEnemy(oTarget, oCreature) && !GetIsDead(oTarget)) break; + oTarget = GetNextObjectInShape(SHAPE_SPHERE, fSize, lWing); + } + if(oTarget != OBJECT_INVALID) ai_DragonMeleeAttack(oCreature, oTarget, sDmgDice, " left wing "); + return TRUE; +} +// Looks behind the dragon to see if it can use it's tail slap on an enemy. +int ai_TryTailSlap(object oCreature) +{ + if(AI_DEBUG) ai_Debug("0i_talents", "1022", GetName(OBJECT_SELF) + " is checking for tail slap Attack!"); + // Only Large size dragons can use thier tail in combat. + // We use HitDice to base size S:1-5, M:6-11, L:12-17, H:18-29, G:30-39, C:40+. + int nHitDice = GetHitDice(oCreature); + if(nHitDice <= 11) return FALSE; + int nDragonSize; + string sDmgDice, sMessage; + float fSize; + // Get the stats based on the size of the dragon. + if(nHitDice < 12) { fSize = 5.0f; nDragonSize = 3; sDmgDice = "1d4"; } // Medium + else if(nHitDice < 18) { fSize = 10.0f; nDragonSize = 4; sDmgDice = "1d6"; } // Large + else if(nHitDice < 30) { fSize = 10.0f; nDragonSize = 5; sDmgDice = "1d8"; } // Huge + else if(nHitDice < 40) { fSize = 15.0f; nDragonSize = 6; sDmgDice = "2d6"; } // Gargantuan + else { fSize = 15.0f; nDragonSize = 7; sDmgDice = "2d8"; } // Colossal + // Add one and a half the dragons strength modifier. + int nDmg = GetAbilityModifier(ABILITY_STRENGTH, oCreature); + if(nDmg > 0) sDmgDice = sDmgDice + "+" + IntToString(nDmg + nDmg / 2); + if(AI_DEBUG) ai_Debug("0i_talents", "1039", "nHitDice: " + IntToString(nHitDice) + + " nDragonSize: " + IntToString(nDragonSize) + + " sDmgDice: " + sDmgDice + " nDmg: " + IntToString(nDmg)); + // Get the closest enemy to our tail. + location lTail = GetBehindLocation(oCreature); + object oTarget = GetFirstObjectInShape(SHAPE_SPHERE, fSize, lTail); + while(oTarget != OBJECT_INVALID) + { + if(GetIsEnemy(oTarget, oCreature) && !GetIsDead(oTarget)) break; + oTarget = GetNextObjectInShape(SHAPE_SPHERE, fSize, lTail); + } + if(oTarget != OBJECT_INVALID) ai_DragonMeleeAttack(oCreature, oTarget, sDmgDice, " tail ");\ + return TRUE; +} +void ai_CrushEffect(object oCreature, object oBaseTarget, int nHitDice) +{ + int nDragonSize, nAtkValue, nDC = ai_GetDragonDC(oCreature); + string sDmgDice, sMessage; + location lImpact = GetLocation(oBaseTarget); + float fSize; + // Get the stats based on the size of the dragon. + if(nHitDice < 30) { fSize = 15.0f; nDragonSize = 5; sDmgDice = "2d8"; } // Huge + else if(nHitDice < 40) { fSize = 25.0f; nDragonSize = 6; sDmgDice = "4d6"; } // Gargantuan + else { fSize = 45.0f; nDragonSize = 7; sDmgDice = "4d8"; } // Colossal + // Add the dragons strength modifier 1.5 times. + int nDmgBonus = GetAbilityModifier(ABILITY_STRENGTH, oCreature); + if(nDmgBonus > 0) sDmgDice = sDmgDice + "+" + IntToString(nDmgBonus + nDmgBonus / 2); + // Dragon flies up and then crushes the area below it. + effect eDmg, eKnockDown = EffectKnockdown(); + effect eImpact = EffectVisualEffect(VFX_FNF_SCREEN_SHAKE); + object oTarget = GetFirstObjectInShape(SHAPE_SPHERE, fSize, lImpact); + while(oTarget != OBJECT_INVALID) + { + if(ai_GetIsCharacter(oTarget)) DelayCommand(1.0, ApplyEffectToObject(DURATION_TYPE_INSTANT, eImpact, oTarget)); + // If they have evasion they automatically dodge the crush attack. + if(!GetHasFeat(FEAT_EVASION, oTarget) && oTarget != oCreature) + { + if(!ReflexSave(oTarget, nDC, SAVING_THROW_TYPE_NONE, oCreature)) + { + eDmg =EffectDamage(ai_RollDiceString(sDmgDice), DAMAGE_TYPE_BLUDGEONING); + ApplyEffectToObject(DURATION_TYPE_INSTANT, eDmg, oTarget); + sMessage = ai_AddColorToText(GetName(oCreature), AI_COLOR_LIGHT_MAGENTA) + + ai_AddColorToText(" crushes " + GetName(oTarget) + ".", AI_COLOR_DARK_ORANGE); + if(ai_GetIsCharacter(oTarget)) SendMessageToPC(oTarget, sMessage); + // Must be 3 sizes smaller to be affected by extra damage and knockdown. + if(nDragonSize - 2 < GetCreatureSize(oTarget)) + { + if(!GetIsImmune(oTarget, IMMUNITY_TYPE_KNOCKDOWN)) + { + ApplyEffectToObject(DURATION_TYPE_INSTANT, eDmg, oTarget); + ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eKnockDown, oTarget, 6.0f); + } + } + } + } + else + { + if(ai_GetIsCharacter(oTarget)) + { + sMessage = ai_AddColorToText(GetName(oTarget), AI_COLOR_LIGHT_MAGENTA) + + ai_AddColorToText(" dodges the crush attack from " + GetName(oTarget) + ".", AI_COLOR_DARK_ORANGE); + if(ai_GetIsCharacter(oTarget)) SendMessageToPC(oTarget, sMessage); + } + } + oTarget = GetNextObjectInShape(SHAPE_SPHERE, fSize, lImpact); + } + // Now do normal attacks! + ai_FlyToAttacks(oCreature, oBaseTarget); +} +int ai_TryCrushAttack(object oCreature, object oTarget) +{ + if(AI_DEBUG) ai_Debug("0i_talents", "1110", GetName(OBJECT_SELF) + " is checking for crush Attack!"); + // Only Huge size dragons can use crush attack. + // We use HitDice to base size S:1-5, M:6-11, L:12-17, H:18-29, G:30-39, C:40+. + int nHitDice = GetHitDice(oCreature); + if(nHitDice <= 17) return FALSE; + int nCrush = GetLocalInt(oCreature, "0_DRAGON_CRUSH") - 1; + if(nCrush > 0) + { + SetLocalInt(oCreature, "0_DRAGON_CRUSH", nCrush); + return FALSE; + } + effect eFly = EffectDisappearAppear(GetLocation(oTarget)); + ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eFly, oCreature, 3.0f); + DelayCommand(4.0f, ai_CrushEffect(oCreature, oTarget, nHitDice)); + // Used to make creature wait before starting its next round. + SetLocalInt(oCreature, AI_COMBAT_WAIT_IN_SECONDS, 5); + // We only crush every 3 rounds if we can. + SetLocalInt(oCreature, "0_DRAGON_CRUSH", 3); + return TRUE; +} +int ai_TryTailSweepAttack(object oCreature) +{ + if(AI_DEBUG) ai_Debug("0i_talents", "1132", GetName(oCreature) + " is checking for tail sweep Attack!"); + // Only Gargantuan size dragons can use tail sweep attack. + // We use HitDice to base size S:1-5, M:6-11, L:12-17, H:18-29, G:30-40, C:40+. + int nHitDice = GetHitDice(oCreature); + if(nHitDice <= 29) return FALSE; + int nSweep = GetLocalInt(oCreature, "0_DRAGON_SWEEP") - 1; + if(nSweep > 0) + { + SetLocalInt(oCreature, "0_DRAGON_SWEEP", nSweep); + return FALSE; + } + int nDragonSize, nAtkValue, nDC = ai_GetDragonDC(oCreature); + string sDmgDice, sMessage; + float fSize; + // Get the stats based on the size of the dragon. + if(nHitDice < 33) { fSize = 15.0f; nDragonSize = 6; sDmgDice = "2d6"; } // Gargantuan + else { fSize = 40.0f; nDragonSize = 7; sDmgDice = "2d8"; } // Colossal + location lImpact = GetBehindLocation(oCreature); + // We always sweep if we have the opportunity. + // Add the dragons strength modifier 1.5 times. + int nDmgBonus = GetAbilityModifier(ABILITY_STRENGTH, oCreature); + if(nDmgBonus > 0) sDmgDice = sDmgDice + "+" + IntToString(nDmgBonus + nDmgBonus / 2); + // Sweeps any creatures behind them. + effect eDmg; + effect eKnockDown = EffectKnockdown(); + object oTarget = GetFirstObjectInShape(SHAPE_SPHERE, fSize, lImpact); + while(oTarget != OBJECT_INVALID) + { + sMessage = ai_AddColorToText(GetName(oCreature), AI_COLOR_LIGHT_MAGENTA) + + ai_AddColorToText(" sweeps " + GetName(oTarget) + ".", AI_COLOR_ORANGE); + if(ai_GetIsCharacter(oTarget)) SendMessageToPC(oTarget, sMessage); + // If they have evasion they automatically dodge the sweep attack. + if(!GetHasFeat(FEAT_EVASION, oTarget) && oTarget != oCreature) + { + if(!ReflexSave(oTarget, nDC, SAVING_THROW_TYPE_NONE, oCreature)) + { + eDmg = EffectDamage(ai_RollDiceString(sDmgDice), DAMAGE_TYPE_BLUDGEONING); + ApplyEffectToObject(DURATION_TYPE_INSTANT, eDmg, oTarget); + // Must be 4 sizes smaller to be affected by extra damage and knockdown. + if(nDragonSize - 3 < GetCreatureSize(oTarget)) + { + if(!GetIsImmune(oTarget, IMMUNITY_TYPE_KNOCKDOWN)) + { + ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eKnockDown, oTarget, 12.0f); + } + } + } + } + oTarget = GetNextObjectInShape(SHAPE_SPHERE, fSize, lImpact); + } + // We only sweep every 3 rounds if we can. + SetLocalInt(oCreature, "0_DRAGON_SWEEP", 3); + return TRUE; +} +int ai_TrySneakAttack(object oCreature, int nInMelee, int bAlwaysAtk = TRUE) +{ + if(AI_DEBUG) ai_Debug("0i_talents", "1188", GetName(OBJECT_SELF) + " is checking for melee Sneak Attack!"); + if(!GetHasFeat(FEAT_SNEAK_ATTACK, oCreature)) return FALSE; + // Lets get the nearest target that is attacking someone besides me. + object oTarget = OBJECT_INVALID; + oTarget = GetLocalObject(oCreature, AI_PC_LOCKED_TARGET); + if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); + if(oTarget == OBJECT_INVALID) + { + string sIndex; + // Check if we have Mobility, Spring Attack or a good tumble. + // if we do then look for other targets besides who we are in melee with. + if(!nInMelee) sIndex = IntToString(ai_GetBestSneakAttackIndex(oCreature, AI_RANGE_PERCEPTION, bAlwaysAtk)); + // If there are few enemies then we can safely move around. + else if(nInMelee < 3 || ai_CanIMoveInCombat(oCreature)) + { + sIndex = IntToString(ai_GetBestSneakAttackIndex(oCreature, AI_RANGE_MELEE)); + } + // Ok we are in a serious fight so lets not give attack of opportunities. + else sIndex = IntToString(ai_GetNearestIndex(oCreature, AI_RANGE_MELEE)); + oTarget = GetLocalObject(oCreature, AI_ENEMY + sIndex); + } + if(oTarget == OBJECT_INVALID) return FALSE; + int nRacialType = GetRacialType(oTarget); + if(nRacialType == RACIAL_TYPE_CONSTRUCT || nRacialType == RACIAL_TYPE_UNDEAD) return FALSE; + if(ai_GetHasEffectType(oTarget, IMMUNITY_TYPE_CRITICAL_HIT)) return FALSE; + ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); + return TRUE; +} +int ai_TryRangedSneakAttack(object oCreature, int nInMelee) +{ + if(AI_DEBUG) ai_Debug("0i_talents", "1209", GetName(oCreature) + " is checking for a Ranged Sneak Attack!"); + // If we have Sneak Attack then we should be attacking targets that + // are busy fighting so we can get extra damage. + if(!GetHasFeat(FEAT_SNEAK_ATTACK, oCreature)) return FALSE; + object oTarget = OBJECT_INVALID; + oTarget = GetLocalObject(oCreature, AI_PC_LOCKED_TARGET); + if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); + if(oTarget == OBJECT_INVALID) oTarget = GetLocalObject(oCreature, AI_ENEMY + IntToString(ai_GetBestSneakAttackIndex(oCreature))); + if(oTarget == OBJECT_INVALID) return FALSE; + int nRacialType = GetRacialType(oTarget); + if(nRacialType == RACIAL_TYPE_CONSTRUCT || nRacialType == RACIAL_TYPE_UNDEAD) return FALSE; + if(ai_GetHasEffectType(oTarget, IMMUNITY_TYPE_CRITICAL_HIT)) return FALSE; + // If we have a target and are not within 30' then move within 30'. + if(GetDistanceToObject(oTarget) > AI_RANGE_CLOSE) ActionMoveToObject(oTarget, TRUE, AI_RANGE_CLOSE); + ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE); + return TRUE; +} +int ai_TryMeleeTalents(object oCreature, object oTarget) +{ + if(AI_DEBUG) ai_Debug("0i_talents", "1224", "Check category melee talents!"); + talent tUse = GetCreatureTalentBest(TALENT_CATEGORY_HARMFUL_MELEE, 20, oCreature); + if(!GetIsTalentValid(tUse)) return FALSE; + int nId = GetIdFromTalent(tUse); + if(AI_DEBUG) ai_Debug("0i_talents", "1228", "TALENT_CATEGORY_MELEE_TALENTS nId: " + IntToString(nId)); + if(nId == FEAT_POWER_ATTACK) { if(ai_TryPowerAttackFeat(oCreature, oTarget)) return TRUE; } + else if(nId == FEAT_EXPERTISE) { if(ai_TryExpertiseFeat(oCreature)) return TRUE; } + else if(nId == FEAT_KNOCKDOWN) { if(ai_TryKnockdownFeat(oCreature, oTarget)) return TRUE; } + else if(nId == FEAT_SMITE_EVIL) { if(ai_TrySmiteEvilFeat(oCreature, oTarget)) return TRUE; } + else if(nId == FEAT_SMITE_GOOD) { if(ai_TrySmiteGoodFeat(oCreature, oTarget)) return TRUE; } + else if(nId == FEAT_IMPROVED_POWER_ATTACK) { if(ai_TryImprovedPowerAttackFeat(oCreature, oTarget)) return TRUE; } + else if(nId == FEAT_IMPROVED_EXPERTISE) { if(ai_TryImprovedExpertiseFeat(oCreature)) return TRUE; } + else if(nId == FEAT_FLURRY_OF_BLOWS) { if(ai_TryFlurryOfBlowsFeat(oCreature, oTarget)) return TRUE; } + else if(nId == FEAT_STUNNING_FIST) { if(ai_TryStunningFistFeat(oCreature, oTarget)) return TRUE; } + else if(nId == FEAT_SAP) { if(ai_TrySapFeat(oCreature, oTarget)) return TRUE; } + else if(nId == FEAT_DISARM) { if(ai_TryDisarmFeat(oCreature, oTarget)) return TRUE; } + else if(nId == FEAT_KI_DAMAGE) { if(ai_TryKiDamageFeat(oCreature, oTarget)) return TRUE; } + else if(nId == FEAT_CALLED_SHOT) { if(ai_TryCalledShotFeat(oCreature, oTarget)) return TRUE; } + return FALSE; +} +// ***************************************************************************** +// ***************************** TALENT SCRIPTS ****************************** +// ***************************************************************************** +// These functions do not fall into another section. + +int ai_GetMonsterTalentMaxLevel(object oCreature) +{ + // Monsters should use either the best spell they have or a random spell so + // they all don't look robotic. Mix it up based on an Intelligence check. + int nMaxLevel = (ai_GetCharacterLevels(oCreature) + 1) / 2; + if(nMaxLevel > 9) nMaxLevel = 9; + if(AI_DEBUG) ai_Debug("0i_talents", "1258", "nMaxLevel: " + IntToString(nMaxLevel)); + return nMaxLevel; +} +int ai_GetAssociateTalentMaxLevel(object oCreature, int nDifficulty) +{ + int nLevel = (ai_GetCharacterLevels(oCreature) + 1) / 2; + if(nLevel > 20) nLevel = 20; + int nMaxLevel = (nLevel * nDifficulty) / 20; + if(nMaxLevel < 1) nMaxLevel = 1; + if(AI_DEBUG) ai_Debug("0i_talents", "1267", "nLevel: " + IntToString(nLevel) + + " nMaxLevel: " + IntToString(nMaxLevel)); + return nMaxLevel; +} +int ai_GetHasTalent(object oCreature, int nTalent) +{ + string sCategory = Get2DAString("ai_spells", "Category", nTalent); + json jCategory = GetLocalJson(oCreature, sCategory); + if(JsonGetType(jCategory) == JSON_TYPE_NULL) return FALSE; + int nLevel, nSlot, nSlotIndex, nMaxSlotIndex, nSpell; + json jLevel, jTalent; + // Loop through nLevels looking for nTalent + while(nLevel <= 9) + { + // Get the array of nLevel. + jLevel = JsonArrayGet(jCategory, nLevel); + nMaxSlotIndex = JsonGetLength(jLevel); + if(nMaxSlotIndex > 0) + { + // Get the talent within nLevel cycling from the first to the last. + nSlotIndex = 0; + while (nSlotIndex < nMaxSlotIndex) + { + jTalent= JsonArrayGet(jLevel, nSlotIndex); + nSpell = JsonGetInt(JsonArrayGet(jTalent, 1)); + if(nSpell == nTalent) return TRUE; + nSlotIndex++; + } + } + nLevel++; + } + return FALSE; +} +object ai_CheckTalentForBuffing(object oCreature, string sCategory, int nSpell) +{ + // Should we buff this monster caster? Added legacy code just in case. + if((sCategory == "P" || sCategory == "E" || sCategory == "S") && + (GetLocalInt(GetModule(), AI_RULE_BUFF_MONSTERS) || + GetLocalInt(oCreature, "NW_GENERIC_MASTER") & 0x04000000)) return ai_GetBuffTarget(oCreature, nSpell); + //if(sCategory == "S" && GetLocalInt(GetModule(), AI_RULE_PRESUMMON)) return oCreature; + return OBJECT_INVALID; +} +int ai_UseBuffTalent(object oCreature, int nClass, int nLevel, int nSlot, int nSpell, int nType, object oTarget, object oItem) +{ + if(nType == AI_TALENT_TYPE_SPELL) + { + if(Get2DAString("classes", "MemorizesSpells", nClass) == "1") + { + if(GetMemorizedSpellReady(oCreature, nClass, nLevel, nSlot)) + { + ai_CastMemorizedSpell(oCreature, nClass, nLevel, nSlot, oTarget, TRUE); + return TRUE; + } + } + else if(GetSpellUsesLeft(oCreature, nClass, nSpell)) + { + ai_CastKnownSpell(oCreature, nClass, nSpell, oTarget, TRUE); + return TRUE; + } + } + else if(nType == AI_TALENT_TYPE_SP_ABILITY) + { + ActionCastSpellAtObject(nSpell, oTarget, 255, FALSE, 0, 0, TRUE, 255); + } + /* This will not work as there is no cheat option for using an item. + else if(nType == AI_TALENT_TYPE_ITEM) + { + int nBaseItem = GetBaseItemType(oItem); + if(!AI_BUFF_MONSTER_POTIONS && + (nBaseItem == BASE_ITEM_POTIONS || nBaseItem == BASE_ITEM_ENCHANTED_POTION)) return FALSE; + itemproperty ipProp = GetFirstItemProperty(oItem); + while(GetIsItemPropertyValid(ipProp)) + { + if(nIndex++ == nSlot) break; + ipProp = GetNextItemProperty(oItem); + } + // Cast items have the following: + // 1)Single_Use. + // 2-6) Charges/Use [Note: 7 is 0 charges per use]. + // 8-12) Uses/Day [Note: 13 is unlimited uses per day]. + // We set the slot to -1 to let the other function know we need this talent removed. + int nUses = GetItemPropertyCostTableValue(ipProp); + if(nUses == 1) jTalent = JsonArrayInsert(jTalent, JsonInt(-1), 4); + else if(nUses > 1 && nUses < 7) + { + if(AI_DEBUG) ai_Debug("0i_talents", "1319", "Item charges: " + IntToString(GetItemCharges(oItem))); + int nCharges = GetItemCharges(oItem); + if(nUses == 6 && nCharges == 1 || nUses == 5 && nCharges < 4 || + nUses == 4 && nCharges < 6 || nUses == 3 && nCharges < 8 || + nUses == 2 && nCharges < 10) return FALSE; + } + else if(nUses > 7 && nUses < 13) + { + if(AI_DEBUG) ai_Debug("0i_talents", "1327", "Item uses: " + IntToString(GetItemPropertyUsesPerDayRemaining(oItem, ipProp))); + int nPerDay = GetItemPropertyUsesPerDayRemaining(oItem, ipProp); + if(nUses == 8 && nPerDay == 1 || nUses == 9 && nPerDay < 4 || + nUses == 10 && nPerDay < 6 || nUses == 11 && nPerDay < 8 || + nUses == 12 && nPerDay < 10) return FASLE; + } + ActionUseItemOnObject(oItem, ipProp, oTarget, nSubIndex); + return TRUE; + } */ + return FALSE; +} +int ai_SpellRestricted(int nSpell) +{ + json jRSpells = GetLocalJson(GetModule(), AI_RULE_RESTRICTED_SPELLS); + int nIndex, nMaxIndex = JsonGetLength(jRSpells); + while(nIndex < nMaxIndex) + { + if(JsonGetInt(JsonArrayGet(jRSpells, nIndex)) == nSpell) + { + if(AI_DEBUG) ai_Debug("0i_talents", "1703", IntToString(nSpell) + " is has been restricted and will be ignored!"); + return TRUE; + } + nIndex++; + } + return FALSE; +} +void ai_SaveTalent(object oCreature, int nClass, int nJsonLevel, int nLevel, int nSlot, int nSpell, int nType, int bMonster, object oItem = OBJECT_INVALID) +{ + // Players/Admins can restrict some spells. + if(ai_SpellRestricted(nSpell)) return; + // Get the talent category, we organize all talents by categories. + string sCategory = Get2DAString("ai_spells", "Category", nSpell); + // If it is a blank talent or it is an Area of Effect talent we skip. + if(sCategory == "" || sCategory == "A") return; + // Check to see if we should be prebuffing. + if(bMonster) + { + int nSpellBuffDuration = StringToInt(Get2DAString("ai_spells", "Buff_Duration", nSpell)); + if(nSpellBuffDuration == 3) + { + if(AI_DEBUG) ai_Debug("0i_talents", "1600", GetName(oCreature) + " is buffing with spell " + IntToString(nSpell)); + object oTarget = ai_CheckTalentForBuffing(oCreature, sCategory, nSpell); + if(oTarget != OBJECT_INVALID && + ai_UseBuffTalent(oCreature, nClass, nLevel, nSlot, nSpell, nType, oTarget, oItem)) return; + } + } + json jCategory = GetLocalJson(oCreature, sCategory); + // With no jCategory then we make one with all 0-9 levels. + if(JsonGetType(jCategory) == JSON_TYPE_NULL) + { + jCategory = JsonArray(); + jCategory = JsonArrayInsert(jCategory, JsonArray(), 0); + int nNewLevel = 9; + while(nNewLevel > 0) + { + jCategory = JsonArrayInsert(jCategory, JsonArray()); + nNewLevel--; + } + } + // Get the current Level so we can save to it. + json jLevel = JsonArrayGet(jCategory, nJsonLevel); + json jTalent = JsonArray(); + if(nType == AI_TALENT_TYPE_SPELL || nType == AI_TALENT_TYPE_SP_ABILITY) + { + jTalent = JsonArrayInsert(jTalent, JsonInt(nType), 0); + jTalent = JsonArrayInsert(jTalent, JsonInt(nSpell)); + jTalent = JsonArrayInsert(jTalent, JsonInt(nClass)); + jTalent = JsonArrayInsert(jTalent, JsonInt(nLevel)); + jTalent = JsonArrayInsert(jTalent, JsonInt(nSlot)); + } + else if(nType == AI_TALENT_TYPE_ITEM) + { + jTalent = JsonArrayInsert(jTalent, JsonInt(nType), 0); + jTalent = JsonArrayInsert(jTalent, JsonInt(nSpell)); + jTalent = JsonArrayInsert(jTalent, JsonString(ObjectToString(oItem))); + jTalent = JsonArrayInsert(jTalent, JsonInt(nLevel)); + jTalent = JsonArrayInsert(jTalent, JsonInt(nSlot)); + } + jLevel = JsonArrayInsert(jLevel, jTalent); + jCategory = JsonArraySet(jCategory, nJsonLevel, jLevel); + SetLocalJson(oCreature, sCategory, jCategory); + if(AI_DEBUG) ai_Debug("0i_talents", "1777", sCategory + ": " + JsonDump(jCategory, 1)); + if(AI_DEBUG) ai_Debug("0i_talents", "1778", "AI_MAX_TALENT: " + + IntToString(GetLocalInt(oCreature, AI_MAX_TALENT + sCategory)) + + " nJsonLevel: " + IntToString(nJsonLevel)); + // Set AI_MAX_TALENT if this talent is higher than the maximum. + if(nJsonLevel > GetLocalInt(oCreature, AI_MAX_TALENT + sCategory)) + { + SetLocalInt(oCreature, AI_MAX_TALENT + sCategory, nJsonLevel); + } +} +// For removing used up spell slots. +void ai_RemoveTalent(object oCreature, json jCategory, json jLevel, string sCategory, int nLevel, int nSlotIndex) +{ + if(AI_DEBUG) ai_Debug("0i_talents", "1400", "removing Talent from slot: " + IntToString(nSlotIndex)); + jLevel = JsonArrayDel(jLevel, nSlotIndex); + if(AI_DEBUG) ai_Debug("0i_talents", "1402", "jLevel: " + JsonDump(jLevel, 2)); + jCategory = JsonArraySet(jCategory, nLevel, jLevel); + if(AI_DEBUG) ai_Debug("0i_talents", "1404", "jCategory: " + JsonDump(jCategory, 2)); + SetLocalJson(oCreature, sCategory, jCategory); +} +// For removing Sorcerer/Bard spell levels once used up. +void ai_RemoveTalentLevel(object oCreature, json jCategory, json jLevel, string sCategory, int nLevel) +{ + if(AI_DEBUG) ai_Debug("0i_talents", "1410", "removing Talent level: " + IntToString(nLevel)); + jCategory = JsonArrayDel(jCategory, nLevel); + if(AI_DEBUG) ai_Debug("0i_talents", "1412", "jCategory: " + JsonDump(jCategory, 2)); + SetLocalJson(oCreature, sCategory, jCategory); +} +void ai_SetCreatureSpellTalents(object oCreature, int bMonster) +{ + if(AI_DEBUG) ai_Debug("0i_talents", "1417", GetName(oCreature) + ": Setting Spell Talents for combat [Buff: " + + IntToString(bMonster) + "]."); + // Cycle through all classes and spells. + int nClassPosition = 1, nMaxSlot, nLevel, nSlot, nSpell, nIndex, nMetaMagic; + int nClass = GetClassByPosition(nClassPosition, oCreature); + while(nClassPosition <= AI_MAX_CLASSES_PER_CHARACTER && nClass != CLASS_TYPE_INVALID) + { + if(AI_DEBUG) ai_Debug("0i_talents", "1824", "nClass: " + IntToString(nClass) + + " nClassPosition: " + IntToString(nClassPosition) + + " SpellCaster: " + Get2DAString("classes", "SpellCaster", nClass) + + " Memorized: " + Get2DAString("classes", "MemorizesSpells", nClass)); + if(Get2DAString("classes", "SpellCaster", nClass) == "1") + { + // Search all memorized spells for the spell. + if(Get2DAString("classes", "MemorizesSpells", nClass) == "1") + { + // Check each level organizing from highest to lowest. + nLevel = (GetLevelByPosition(nClassPosition, oCreature) + 1) / 2; + if(nLevel > 9) nLevel = 9; + while(nLevel > -1) + { + // Check each slot within each level. + nMaxSlot = GetMemorizedSpellCountByLevel(oCreature, nClass, nLevel); + if(AI_DEBUG) ai_Debug("0i_talents", "1434", "nClass: " + IntToString(nClass) + + " nLevel: " + IntToString(nLevel) + " nMaxSlot: " + + IntToString(nMaxSlot)); + nSlot = 0; + while(nSlot < nMaxSlot) + { + if(AI_DEBUG) ai_Debug("0i_talents", "1440", "nSlot: " + IntToString(nSlot) + " nSpell: " + + IntToString(GetMemorizedSpellId(oCreature, nClass, nLevel, nSlot)) + " spell memorized: " + + IntToString(GetMemorizedSpellReady(oCreature, nClass, nLevel, nSlot))); + if(GetMemorizedSpellReady(oCreature, nClass, nLevel, nSlot) == 1) + { + nSpell = GetMemorizedSpellId(oCreature, nClass, nLevel, nSlot); + /* Spells are already at the higher level when saved as a talent. + // Move a spell up to a different JsonLevel as higher Jsonlevel + // spells usually get cast first. + nMetaMagic = GetMemorizedSpellMetaMagic(oCreature, nClass, nLevel, nSlot); + if(nMetaMagic > 0) + { + if(nMetaMagic == METAMAGIC_STILL) nMetaMagic = 1; + else if(nMetaMagic == METAMAGIC_EXTEND) nMetaMagic = 1; + else if(nMetaMagic == METAMAGIC_SILENT) nMetaMagic = 1; + else if(nMetaMagic == METAMAGIC_EMPOWER) nMetaMagic = 2; + else if(nMetaMagic == METAMAGIC_MAXIMIZE) nMetaMagic = 3; + else if(nMetaMagic == METAMAGIC_QUICKEN) nMetaMagic = 4; + nAdjLevel = nLevel + nMetaMagic; + if(nAdjLevel > 9) nAdjLevel = 9; + } + else nAdjLevel = nLevel; */ + ai_SaveTalent(oCreature, nClass, nLevel, nLevel, nSlot, nSpell, AI_TALENT_TYPE_SPELL, bMonster); + } + nSlot++; + } + nLevel--; + } + } + // Check non-memorized known lists for the spell. + else + { + // Check each level starting with the highest to lowest. + nLevel = (GetLevelByPosition(nClassPosition, oCreature) + 1) / 2; + if(nLevel > 9) nLevel = 9; + while(nLevel > -1) + { + // Check each slot within each level. + nMaxSlot = GetKnownSpellCount(oCreature, nClass, nLevel); + if(AI_DEBUG) ai_Debug("0i_talents", "1462", "nClass: " + IntToString(nClass) + + " nLevel: " + IntToString(nLevel) + " nMaxSlot: " + + IntToString(nMaxSlot)); + nSlot = 0; + while(nSlot < nMaxSlot) + { + nSpell = GetKnownSpellId(oCreature, nClass, nLevel, nSlot); + if(AI_DEBUG) ai_Debug("0i_talents", "1469", "nSlot: " + IntToString(nSlot) + + " nSpell: " + IntToString(nSpell) + " nUsesLeft: " + + IntToString(GetSpellUsesLeft(oCreature, nClass, nSpell))); + if(GetSpellUsesLeft(oCreature, nClass, nSpell) > 0) + { + ai_SaveTalent(oCreature, nClass, nLevel, nLevel, nSlot, nSpell, AI_TALENT_TYPE_SPELL, bMonster); + } + nSlot++; + } + nLevel--; + } + } + } + nClassPosition++; + nClass = GetClassByPosition(nClassPosition, oCreature); + } +} +void ai_SetCreatureSpecialAbilityTalents(object oCreature, int bMonster) +{ + if(AI_DEBUG) ai_Debug("0i_talents", "1488", GetName(oCreature) + ": Setting Special Ability Talents for combat."); + // Cycle through all the creatures special abilities. + int nMaxSpecialAbilities = GetSpellAbilityCount(oCreature); + if(AI_DEBUG) ai_Debug("0i_talents", "1491", IntToString(GetSpellAbilityCount(oCreature)) + " Spell abilities."); + if(nMaxSpecialAbilities) + { + int nIndex, nSpell, nLevel; + while(nIndex < nMaxSpecialAbilities) + { + nSpell = GetSpellAbilitySpell(oCreature, nIndex); + if(GetSpellAbilityReady(oCreature, nSpell)) + { + nLevel = StringToInt(Get2DAString("spells", "Innate", nSpell)); + ai_SaveTalent(oCreature, 255, nLevel, nLevel, nIndex, nSpell, AI_TALENT_TYPE_SP_ABILITY, bMonster); + } + nIndex++; + } + } +} +void ai_CheckItemProperties(object oCreature, object oItem, int bMonster, int bEquiped = FALSE) +{ + if(AI_DEBUG) ai_Debug("0i_talents", "1509", "Checking Item properties on " + GetName(oItem)); + // We have established that we can use the item if it is equiped. + if(!bEquiped && !ai_CheckIfCanUseItem(oCreature, oItem)) return; + // Get or create an Immunity in json so we can check item immunities quickly. + int nSpellImmunity, bHasItemImmunity, nPerDay, nCharges, nUses, bSaveTalent; + json jImmunity = GetLocalJson(oCreature, AI_TALENT_IMMUNITY); + if(JsonGetType(jImmunity) == JSON_TYPE_NULL) jImmunity = JsonArray(); + int nIprpSubType, nSpell, nLevel, nIPType, nIndex; + itemproperty ipProp = GetFirstItemProperty(oItem); + // Lets skip this if there are no properties. + if(!GetIsItemPropertyValid(ipProp)) return; + // Check for cast spell property and add them to the talent list. + while(GetIsItemPropertyValid(ipProp)) + { + nIPType = GetItemPropertyType(ipProp); + if(AI_DEBUG) ai_Debug("0i_talents", "1895", "ItempropertyType(15/80/53): " + IntToString(nIPType)); + if(nIPType == ITEM_PROPERTY_CAST_SPELL) + { + bSaveTalent = TRUE; + // Get how they use the item (charges or uses per day). + nUses = GetItemPropertyCostTableValue(ipProp); + if(nUses > 1 && nUses < 7) + { + nCharges = GetItemCharges(oItem); + if(AI_DEBUG) ai_Debug("0i_talents", "1530", "Charges per use: " + IntToString(nUses) + + " Item charges: " + IntToString(nCharges)); + if((nUses == IP_CONST_CASTSPELL_NUMUSES_1_CHARGE_PER_USE && nCharges < 1) || + (nUses == IP_CONST_CASTSPELL_NUMUSES_2_CHARGES_PER_USE && nCharges < 2) || + (nUses == IP_CONST_CASTSPELL_NUMUSES_3_CHARGES_PER_USE && nCharges < 3) || + (nUses == IP_CONST_CASTSPELL_NUMUSES_4_CHARGES_PER_USE && nCharges < 4) || + (nUses == IP_CONST_CASTSPELL_NUMUSES_5_CHARGES_PER_USE && nCharges < 5)) bSaveTalent = FALSE; + } + else if(nUses > 7 && nUses < 13) + { + nPerDay = GetItemPropertyUsesPerDayRemaining(oItem, ipProp); + if(AI_DEBUG) ai_Debug("0i_talents", "1676", "Item uses: " + IntToString(nPerDay)); + if(nPerDay == 0) bSaveTalent = FALSE; + } + if(bSaveTalent) + { + // SubType is the ip spell index for iprp_spells.2da + nIprpSubType = GetItemPropertySubType(ipProp); + nSpell = StringToInt(Get2DAString("iprp_spells", "SpellIndex", nIprpSubType)); + nLevel = StringToInt(Get2DAString("iprp_spells", "InnateLvl", nIprpSubType)); + ai_SaveTalent(oCreature, 255, nLevel, nLevel, nIndex, nSpell, AI_TALENT_TYPE_ITEM, bMonster, oItem); + } + } + else if(nIPType == ITEM_PROPERTY_HEALERS_KIT) + { + // Lets set Healing kits as Cure Light Wounds since they heal 1d20 in combat. + nSpell = SPELL_CURE_MINOR_WOUNDS; + // Save the healer kit as level 9 so we can use them first. + // Must also have ranks in healing kits. + if(GetSkillRank(SKILL_HEAL, oCreature) > 0) + { + ai_SaveTalent(oCreature, 255, 7, 0, nIndex, nSpell, AI_TALENT_TYPE_ITEM, bMonster, oItem); + } + } + if(bEquiped) + { + if(nIPType == ITEM_PROPERTY_IMMUNITY_SPECIFIC_SPELL) + { + bHasItemImmunity = TRUE; + nSpellImmunity = GetItemPropertyCostTableValue(ipProp); + nSpellImmunity = StringToInt(Get2DAString("iprp_spellcost", "SpellIndex", nSpellImmunity)); + //if(AI_DEBUG) ai_Debug("0i_talents", "1950", "SpellImmunity to " + Get2DAString("spells", "Label", nSpellImmunity)); + jImmunity = JsonArrayInsert(jImmunity, JsonInt(nSpellImmunity)); + } + else if(nIPType == ITEM_PROPERTY_HASTE) + { + SetLocalInt(oCreature, sIPHasHasteVarname, TRUE); + } + else if(nIPType == ITEM_PROPERTY_IMMUNITY_DAMAGE_TYPE) + { + int nBit, nIpSubType = GetItemPropertySubType(ipProp); + if(AI_DEBUG) ai_Debug("0i_talents", "1957", "nIPSubType: " + IntToString(nIpSubType)); + if(nIpSubType == 0) nBit = DAMAGE_TYPE_BLUDGEONING; + else if(nIpSubType == 1) nBit = DAMAGE_TYPE_PIERCING; + else if(nIpSubType == 2) nBit = DAMAGE_TYPE_SLASHING; + else if(nIpSubType == 5) nBit = DAMAGE_TYPE_MAGICAL; + else if(nIpSubType == 6) nBit = DAMAGE_TYPE_ACID; + else if(nIpSubType == 7) nBit = DAMAGE_TYPE_COLD; + else if(nIpSubType == 8) nBit = DAMAGE_TYPE_DIVINE; + else if(nIpSubType == 9) nBit = DAMAGE_TYPE_ELECTRICAL; + else if(nIpSubType == 10) nBit = DAMAGE_TYPE_FIRE; + else if(nIpSubType == 11) nBit = DAMAGE_TYPE_NEGATIVE; + else if(nIpSubType == 12) nBit = DAMAGE_TYPE_POSITIVE; + else if(nIpSubType == 13) nBit = DAMAGE_TYPE_SONIC; + if(nBit > 0) ai_SetItemProperty(oCreature, sIPImmuneVarname, nBit, TRUE); + } + else if(nIPType == ITEM_PROPERTY_DAMAGE_RESISTANCE) + { + int nBit, nIpSubType = GetItemPropertySubType(ipProp); + if(nIpSubType == 0) nBit = DAMAGE_TYPE_BLUDGEONING; + else if(nIpSubType == 1) nBit = DAMAGE_TYPE_PIERCING; + else if(nIpSubType == 2) nBit = DAMAGE_TYPE_SLASHING; + else if(nIpSubType == 5) nBit = DAMAGE_TYPE_MAGICAL; + else if(nIpSubType == 6) nBit = DAMAGE_TYPE_ACID; + else if(nIpSubType == 7) nBit = DAMAGE_TYPE_COLD; + else if(nIpSubType == 8) nBit = DAMAGE_TYPE_DIVINE; + else if(nIpSubType == 9) nBit = DAMAGE_TYPE_ELECTRICAL; + else if(nIpSubType == 10) nBit = DAMAGE_TYPE_FIRE; + else if(nIpSubType == 11) nBit = DAMAGE_TYPE_NEGATIVE; + else if(nIpSubType == 12) nBit = DAMAGE_TYPE_POSITIVE; + else if(nIpSubType == 13) nBit = DAMAGE_TYPE_SONIC; + if(nBit > 0) ai_SetItemProperty(oCreature, sIPResistVarname, nBit, TRUE); + } + else if(nIPType == ITEM_PROPERTY_DAMAGE_REDUCTION) + { + int nIpSubType = GetItemPropertySubType(ipProp); + SetLocalInt(oCreature, sIPReducedVarname, nIpSubType); + } + } + nIndex++; + ipProp = GetNextItemProperty(oItem); + } + // If nSpellImmunity has been set then we need to save our Immunity json. + if(bHasItemImmunity) SetLocalJson(oCreature, AI_TALENT_IMMUNITY, jImmunity); +} +void ai_SetCreatureItemTalents(object oCreature, int bMonster) +{ + if(AI_DEBUG) ai_Debug("0i_talents", "1561", GetName(oCreature) + ": Setting Item Talents for combat."); + int bEquiped; + string sSlots; + // Cycle through all the creatures inventory items. + object oItem = GetFirstItemInInventory(oCreature); + while(oItem != OBJECT_INVALID) + { + if(GetIdentified(oItem)) + { + // Does the item need to be equiped to use its powers? + sSlots = Get2DAString("baseitems", "EquipableSlots", GetBaseItemType(oItem)); + if(AI_DEBUG) ai_Debug("0i_talents", "1572", GetName(oItem) + " requires " + Get2DAString("baseitems", "EquipableSlots", GetBaseItemType(oItem)) + " slots."); + if(sSlots == "0x00000") ai_CheckItemProperties(oCreature, oItem, bMonster); + } + oItem = GetNextItemInInventory(oCreature); + } + int nSlot; + // Cycle through all the creatures equiped items. + oItem = GetItemInSlot(nSlot, oCreature); + while(nSlot < 11) + { + if(oItem != OBJECT_INVALID) ai_CheckItemProperties(oCreature, oItem, bMonster, TRUE); + oItem = GetItemInSlot(++nSlot, oCreature); + } + oItem = GetItemInSlot(INVENTORY_SLOT_CARMOUR, oCreature); + if(oItem != OBJECT_INVALID) ai_CheckItemProperties(oCreature, oItem, bMonster, TRUE); +} +void ai_SetCreatureTalents(object oCreature, int bMonster) +{ + json jCreature = ObjectToJson(oCreature); + //if(AI_DEBUG) ai_Debug("0i_talents", "2072", GetName(oCreature) + " jCreature: " + JsonDump(jCreature, 4)); + if(GetLocalInt(oCreature, AI_TALENTS_SET)) return; + SetLocalInt(oCreature, AI_TALENTS_SET, TRUE); + object oModule = GetModule(); + ai_Counter_Start(); + ai_SetCreatureSpellTalents(oCreature, bMonster); + ai_Counter_End(GetName(oCreature) + ": Spell Talents"); + ai_SetCreatureSpecialAbilityTalents(oCreature, bMonster); + ai_Counter_End(GetName(oCreature) + ": Special Ability Talents"); + DeleteLocalJson(oCreature, AI_TALENT_IMMUNITY); + ai_SetCreatureItemTalents(oCreature, bMonster); + ai_Counter_End(GetName(oCreature) + ": Item Talents"); + if(GetLocalInt(oModule, AI_RULE_SUMMON_COMPANIONS) && GetLocalInt(oModule, AI_RULE_PRESUMMON) && bMonster) + { + ai_TrySummonFamiliarTalent(oCreature); + ai_TrySummonAnimalCompanionTalent(oCreature); + } + // AI_CAT_CURE is setup differently we save the level as the highest. + //if(JsonGetType(GetLocalJson(oCreature, AI_TALENT_CURE)) != JSON_TYPE_NULL) SetLocalInt(oCreature, AI_MAX_TALENT + AI_TALENT_CURE, 9); + // With spontaneous cure spells we need to clear this as the number of spells don't count. + //if(GetLevelByClass(CLASS_TYPE_CLERIC, oCreature)) SetLocalInt(oCreature, AI_MAX_TALENT + AI_TALENT_HEALING, 0); +} +int ai_UseSpontaneousCureTalentFromCategory(object oCreature, string sCategory, int nInMelee, int nDamage, object oTarget = OBJECT_INVALID) +{ + // Get the saved category from oCreature. + json jCategory = GetLocalJson(oCreature, sCategory); + if(AI_DEBUG) ai_Debug("0i_talents", "2095", "jCategory: " + sCategory + " " + JsonDump(jCategory, 2)); + if(JsonGetType(jCategory) == JSON_TYPE_NULL) return FALSE; + int nLevel = 4; + // If there are no talents at lower levels then start at the lower level. + int nMaxTalentLevel = GetLocalInt(oCreature, AI_MAX_TALENT + sCategory); + if(AI_DEBUG) ai_Debug("0i_talents", "2100", AI_MAX_TALENT + sCategory + ": " + + IntToString(nMaxTalentLevel) + + " nLevel: " + IntToString(nLevel)); + if(nMaxTalentLevel < nLevel) nLevel = nMaxTalentLevel; + if(nLevel < 0 || nLevel > 5) nLevel = 4; + json jLevel, jTalent, jLevelSave; + int nTalentType, nTalentClass, nTalentSlot, nSpell; + int nSlotIndex, nMaxSlotIndex, nMaxNoTalentLevel, nSpellSave, nLevelSave, nSlotSave; + string sSpellName; + // Loop through nLevels down to nMinNoTalentLevel looking for the first talent + // (i.e. the highest or best?). + while(nLevel > -1) + { + // Get the array of nLevel cycling down to 0. + jLevel = JsonArrayGet(jCategory, nLevel); + nMaxSlotIndex = JsonGetLength(jLevel); + if(AI_DEBUG) ai_Debug("0i_talents", "2116", "nLevel: " + IntToString(nLevel) + + " nMaxSlotIndex: " + IntToString(nMaxSlotIndex)); + if(nMaxSlotIndex > 0) + { + // Get the talent within nLevel cycling from the first to the last. + nSlotIndex = 0; + while (nSlotIndex < nMaxSlotIndex) + { + jTalent= JsonArrayGet(jLevel, nSlotIndex); + if(AI_DEBUG) ai_Debug("0i_talents", "2125", "nSlotIndex: " + IntToString(nSlotIndex) + + " jTalent Type: " + IntToString(JsonGetInt(JsonArrayGet(jTalent, 0)))); + nTalentType = JsonGetInt(JsonArrayGet(jTalent, 0)); + nTalentClass = JsonGetInt(JsonArrayGet(jTalent, 2)); + // We can only convert spells from the cleric class. + if(nTalentType == AI_TALENT_TYPE_SPELL && nTalentClass == CLASS_TYPE_CLERIC) + { + if(nLevel == 4) nSpell = SPELL_CURE_CRITICAL_WOUNDS; + else if(nLevel == 3) nSpell = SPELL_CURE_SERIOUS_WOUNDS; + else if(nLevel == 2) nSpell = SPELL_CURE_MODERATE_WOUNDS; + else if(nLevel == 1) nSpell = SPELL_CURE_LIGHT_WOUNDS; + else nSpell = 0; + if(AI_DEBUG) ai_Debug("0i_talents", "2137", "nSpell: " + IntToString(nSpell)); + if(nSpell) + { + if(ai_ShouldWeCastThisCureSpell(nSpell, nDamage)) + { + + nTalentSlot = JsonGetInt(JsonArrayGet(jTalent, 4)); + SetMemorizedSpellReady(oCreature, nTalentClass, nLevel, nTalentSlot, FALSE); + ai_RemoveTalent(oCreature, jCategory, jLevel, sCategory, nLevel, nSlotIndex); + sSpellName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); + if(ai_GetIsCharacter(oCreature)) ai_SendMessages(GetName(oCreature) + " has spontaneously cast " + sSpellName + " on " + GetName(oTarget) + ".", AI_COLOR_MAGENTA, oCreature); + if(AI_DEBUG) ai_Debug("0i_talents", "2148", GetName(oCreature) + " has spontaneously cast " + sSpellName + " on " + GetName(oTarget) + "."); + ActionCastSpellAtObject(nSpell, oTarget, 255, TRUE); + return TRUE; + } + // Save the lowest level cure spell as we might need to cast it. + else if(nLevel < nLevelSave) + { + jLevelSave = jLevel; + nLevelSave = nLevel; + nSlotSave = nTalentSlot; + nSpellSave = nSpell; + } + } + } + nSlotIndex++; + } + } + else SetLocalInt(oCreature, AI_MAX_TALENT + sCategory, nLevel - 1); + nLevel--; + } + // Did we find a spell? If we did then use it. + if(nSpellSave) + { + if(AI_DEBUG) ai_Debug("0i_talents", "2171", GetName(oCreature) + " has cast the lowest level cure spell on " + GetName(oTarget) + "."); + SetMemorizedSpellReady(oCreature, CLASS_TYPE_CLERIC, nLevelSave, nSlotSave, FALSE); + ai_RemoveTalent(oCreature, jCategory, jLevelSave, sCategory, nLevelSave, nSlotSave); + sSpellName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpellSave))); + if(ai_GetIsCharacter(oCreature)) ai_SendMessages(GetName(oCreature) + " has spontaneously cast " + sSpellName + " on " + GetName(oTarget) + ".", AI_COLOR_MAGENTA, oCreature); + ActionCastSpellAtObject(nSpellSave, oTarget, 255, TRUE); + return TRUE; + } + return FALSE; +} +int ai_UseCreatureSpellTalent(object oCreature, json jLevel, json jTalent, string sCategory, int nInMelee, object oTarget = OBJECT_INVALID) +{ + // Check for polymorph, spells cannot be used while polymorphed. + if(GetAppearanceType(oCreature) != ai_GetNormalAppearance(oCreature)) return FALSE; + // Get the spells information so we can check if they still have it. + int nClass = JsonGetInt(JsonArrayGet(jTalent, 2)); + int nLevel = JsonGetInt(JsonArrayGet(jTalent, 3)); + int nSlot = JsonGetInt(JsonArrayGet(jTalent, 4)); + if(ai_IsSilenced(oCreature, JsonGetInt(JsonArrayGet(jTalent, 2)))) + { + if(GetMemorizedSpellMetaMagic(oCreature, nClass, nLevel, nSlot) != METAMAGIC_SILENT) + { + object oAOE = GetNearestObjectByTag("VFX_MOB_SILENCE", oCreature); + float fDistance = GetDistanceBetween(oAOE, oCreature); + if(fDistance != 0.0 && fDistance <= 4.0) + { + location lLocation = GetRandomLocation(GetArea(oCreature), oCreature, 5.0); + ai_ClearCreatureActions(); + if(AI_DEBUG) ai_Debug("0i_talents", "2225", GetName(oCreature) + " is moving out of a silence effect!"); + ActionMoveToLocation(lLocation, TRUE); + return TRUE; + } + else return FALSE; + } + } + if(ai_ArcaneSpellFailureTooHigh(oCreature, nClass, nLevel, nSlot)) return FALSE; + if(Get2DAString("classes", "MemorizesSpells", nClass) == "1") + { + // Shouldn't need this anymore, we need to do a debug looking at this. + if(GetMemorizedSpellReady(oCreature, nClass, nLevel, nSlot) < 1) return FALSE; + if(ai_CheckSpecialTalentsandUse(oCreature, jTalent, sCategory, nInMelee, oTarget)) + { + if(ai_CompareLastAction(oCreature, AI_LAST_ACTION_CAST_SPELL)) return -1; + return TRUE; + } + return FALSE; + } + if(AI_DEBUG) ai_Debug("0i_talents", "1629", "Known caster Level: " + IntToString(nLevel) + + " Uses : " + IntToString(GetSpellUsesLeft(oCreature, nClass, JsonGetInt(JsonArrayGet(jTalent, 1))))); + if(!GetSpellUsesLeft(oCreature, nClass, JsonGetInt(JsonArrayGet(jTalent, 1)))) return -2; + return ai_CheckSpecialTalentsandUse(oCreature, jTalent, sCategory, nInMelee, oTarget); +} +int ai_UseCreatureItemTalent(object oCreature, json jLevel, json jTalent, string sCategory, int nInMelee, object oTarget = OBJECT_INVALID) +{ + object oItem = StringToObject(JsonGetString(JsonArrayGet(jTalent, 2))); + int nItemType = GetBaseItemType(oItem); + // Check if the item is a potion since there are some special cases. + if(nItemType == BASE_ITEM_POTIONS || nItemType == BASE_ITEM_ENCHANTED_POTION) + { + // Potions cause attack of opportunities and this could be deadly! + // Removed for healing potions as that is one time you would use potions in melee. + if(sCategory != AI_TALENT_HEALING) + { + if(AI_DEBUG) ai_Debug("0i_talents", "1925", "Using a non-healing potion nInMelee: " + IntToString(nInMelee)); + if(nInMelee > 1) return FALSE; + // Don't use potions on allies that are not within 3 meters. + if(GetDistanceBetween(oCreature, oTarget) > 3.1) return FALSE; + } + // For now we are allowing creatures to use "give" potions to others + // unless the player is using a healing potion and has party healing turned off. + else if(oCreature != oTarget && ai_GetAIMode(oCreature, AI_MODE_PARTY_HEALING_OFF)) return FALSE; + } + // Check for polymorph, only potions can be used while polymorphed. + else if(GetAppearanceType(oCreature) != ai_GetNormalAppearance(oCreature)) return FALSE; + else if(nItemType == BASE_ITEM_HEALERSKIT) + { + if(!GetLocalInt(GetModule(), AI_RULE_HEALERSKITS)) return FALSE; + if(oCreature != oTarget && ai_GetAIMode(oCreature, AI_MODE_PARTY_HEALING_OFF)) return FALSE; + if(AI_DEBUG) ai_Debug("0i_talents", "1724", "Using " + GetName(oItem) + " nInMelee: " + IntToString(nInMelee) + + " targeting: " + GetName(oTarget)); + ai_SetLastAction(oCreature, AI_LAST_ACTION_USED_ITEM); + ActionUseItemOnObject(oItem, GetFirstItemProperty(oItem), oTarget); + ActionDoCommand(ExecuteScript("0e_do_combat_rnd", oCreature)); + // We also must check for stack size. + if(GetItemStackSize(oItem) == 1) JsonArrayInsertInplace(jTalent, JsonInt(-1), 4); + return TRUE; + } + if(ai_CheckSpecialTalentsandUse(oCreature, jTalent, sCategory, nInMelee, oTarget)) return TRUE; + return FALSE; +} +int ai_UseCreatureTalent(object oCreature, string sCategory, int nInMelee, int nLevel = 10, object oTarget = OBJECT_INVALID) +{ + // Get the saved category from oCreature. + json jCategory = GetLocalJson(oCreature, sCategory); + if(AI_DEBUG) ai_Debug("0i_talents", "2292", "jCategory: " + sCategory + " " + JsonDump(jCategory, 2)); + if(JsonGetType(jCategory) == JSON_TYPE_NULL) return FALSE; + // If there are no talents at lower levels then start at the lower level. + int nMaxTalentLevel = GetLocalInt(oCreature, AI_MAX_TALENT + sCategory); + if(AI_DEBUG) ai_Debug("0i_talents", "2297", AI_MAX_TALENT + sCategory + ": " + + IntToString(nMaxTalentLevel) + + " nLevel: " + IntToString(nLevel)); + if(nMaxTalentLevel < nLevel) nLevel = nMaxTalentLevel; + if(nLevel < 0 || nLevel > 10) nLevel = 9; + json jLevel, jTalent; + int nClass, nSlot, nType, nSlotIndex, nMaxSlotIndex, nTalentUsed, nSpell; + int bUseMagic = !ai_GetMagicMode(oCreature, AI_MAGIC_NO_MAGIC); + int bUseMagicItems = !ai_GetMagicMode(oCreature, AI_MAGIC_NO_MAGIC_ITEMS); + if(AI_DEBUG) ai_Debug("0i_talents", "2305", "bUseMagic: " + IntToString(bUseMagic) + + " bUseMagicItems: " + IntToString(bUseMagicItems) + + " nLevel: " + IntToString(nLevel)); + // Loop through nLevels down to nMinNoTalentLevel looking for the first talent + // (i.e. the highest or best?). + while(nLevel > -1) + { + // Get the array of nLevel cycling down to 0. + jLevel = JsonArrayGet(jCategory, nLevel); + nMaxSlotIndex = JsonGetLength(jLevel); + if(AI_DEBUG) ai_Debug("0i_talents", "2288", "nLevel: " + IntToString(nLevel) + + " nMaxSlotIndex: " + IntToString(nMaxSlotIndex)); + if(nMaxSlotIndex > 0) + { + // Get the talent within nLevel cycling from the first to the last. + nSlotIndex = 0; + while (nSlotIndex < nMaxSlotIndex) + { + jTalent= JsonArrayGet(jLevel, nSlotIndex); + if(AI_DEBUG) ai_Debug("0i_talents", "2300", "nSlotIndex: " + IntToString(nSlotIndex) + + " jTalent Type: " + IntToString(JsonGetInt(JsonArrayGet(jTalent, 0)))); + nType = JsonGetInt(JsonArrayGet(jTalent, 0)); + if(bUseMagic) + { + if(nType == AI_TALENT_TYPE_SPELL) + { + nTalentUsed = ai_UseCreatureSpellTalent(oCreature, jLevel, jTalent, sCategory, nInMelee, oTarget); + // -1 means it was a memorized spell and we need to remove it. + if(nTalentUsed == -1) + { + ai_RemoveTalent(oCreature, jCategory, jLevel, sCategory, nLevel, nSlotIndex); + return TRUE; + } + else if(nTalentUsed == -2) + { + ai_RemoveTalentLevel(oCreature, jCategory, jLevel, sCategory, nLevel); + } + else if(nTalentUsed) return TRUE; + } + else if(nType == AI_TALENT_TYPE_SP_ABILITY) + { + // Special ability spells do not need to concentrate?! + if(ai_CheckSpecialTalentsandUse(oCreature, jTalent, sCategory, nInMelee, oTarget)) + { + // When the ability is used that slot is now not readied. + // Multiple uses of the same spell are stored in different slots. + ai_RemoveTalent(oCreature, jCategory, jLevel, sCategory, nLevel, nSlotIndex); + return TRUE; + } + } + } + if(bUseMagicItems && nType == AI_TALENT_TYPE_ITEM) + { + // Items do not need to concentrate. + if(ai_UseCreatureItemTalent(oCreature, jLevel, jTalent, sCategory, nInMelee, oTarget)) + { + if(AI_DEBUG) ai_Debug("0i_talents", "2337", "Checking if Item is used up: " + + IntToString(JsonGetInt(JsonArrayGet(jTalent, 4)))); + if(JsonGetInt(JsonArrayGet(jTalent, 4)) == -1) + { + ai_RemoveTalent(oCreature, jCategory, jLevel, sCategory, nLevel, nSlotIndex); + } + return TRUE; + } + } + //else if(nType == AI_TALENT_TYPE_FEAT) {} + nSlotIndex++; + } + } + else SetLocalInt(oCreature, AI_MAX_TALENT + sCategory, nLevel - 1); + nLevel--; + } + return FALSE; +} +int ai_UseTalent(object oCreature, int nTalent, object oTarget) +{ + if(AI_DEBUG) ai_Debug("0i_talents", "1912", GetName(oCreature) + " is trying to use " + GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nTalent))) + + " on " + GetName(oTarget)); + // Get the saved category from oCreature. + string sCategory = Get2DAString("ai_spells", "Category", nTalent); + json jCategory = GetLocalJson(oCreature, sCategory); + if(AI_DEBUG) ai_Debug("0i_talents", "1917", "jCategory: " + sCategory + " " + JsonDump(jCategory, 2)); + if(JsonGetType(jCategory) == JSON_TYPE_NULL) return FALSE; + json jLevel, jTalent; + int nLevel, nClass, nSlot, nType, nSlotIndex, nMaxSlotIndex, nTalentUsed, nSpell; + // Loop through nLevels down to nMinNoTalentLevel looking for the first talent + // (i.e. the highest or best?). + while(nLevel <= 9) + { + // Get the array of nLevel. + jLevel = JsonArrayGet(jCategory, nLevel); + nMaxSlotIndex = JsonGetLength(jLevel); + if(AI_DEBUG) ai_Debug("0i_talents", "1925", "nLevel: " + IntToString(nLevel) + + " nMaxSlotIndex: " + IntToString(nMaxSlotIndex)); + if(nMaxSlotIndex > 0) + { + // Get the talent within nLevel cycling from the first to the last. + nSlotIndex = 0; + while (nSlotIndex < nMaxSlotIndex) + { + jTalent= JsonArrayGet(jLevel, nSlotIndex); + if(AI_DEBUG) ai_Debug("0i_talents", "1936", "nSlotIndex: " + IntToString(nSlotIndex) + + " jTalent Type: " + IntToString(JsonGetInt(JsonArrayGet(jTalent, 0)))); + nSpell = JsonGetInt(JsonArrayGet(jTalent, 1)); + if(nSpell == nTalent) + { + nType = JsonGetInt(JsonArrayGet(jTalent, 0)); + if(nType == AI_TALENT_TYPE_SPELL || nType == AI_TALENT_TYPE_SP_ABILITY) + { + if(ai_UseTalentOnObject(oCreature, jTalent, oTarget, 0)) + { + ai_RemoveTalent(oCreature, jCategory, jLevel, sCategory, nLevel, nSlotIndex); + return TRUE; + } + } + else if(nType == AI_TALENT_TYPE_ITEM) + { + // Items do not need to concentrate. + if(ai_UseCreatureItemTalent(oCreature, jLevel, jTalent, sCategory, 0, oTarget)) + { + if(AI_DEBUG) ai_Debug("0i_talents", "1955", "Checking if Item is used up: " + + IntToString(JsonGetInt(JsonArrayGet(jTalent, 4)))); + if(JsonGetInt(JsonArrayGet(jTalent, 4)) == -1) + { + ai_RemoveTalent(oCreature, jCategory, jLevel, sCategory, nLevel, nSlotIndex); + } + return TRUE; + } + } + } + nSlotIndex++; + } + } + nLevel++; + } + return FALSE; +} +int ai_UseTalentOnObject(object oCreature, json jTalent, object oTarget, int nInMelee) +{ + int nClass, nLevel, nSlot, nMetaMagic, nDomain; + int nSpell = JsonGetInt(JsonArrayGet(jTalent, 1)); + int nType = JsonGetInt(JsonArrayGet(jTalent, 0)); + if(nType == AI_TALENT_TYPE_SPELL) + { + if(!ai_CastInMelee(oCreature, nSpell, nInMelee)) return FALSE; + nClass = JsonGetInt(JsonArrayGet(jTalent, 2)); + if(Get2DAString("classes", "MemorizesSpells", nClass) == "1") + { + nLevel = JsonGetInt(JsonArrayGet(jTalent, 3)); + nSlot = JsonGetInt(JsonArrayGet(jTalent, 4)); + if(GetMemorizedSpellIsDomainSpell(oCreature, nClass, nLevel, nSlot) == 1) nDomain = nLevel; + else nDomain = 0; + nMetaMagic = GetMemorizedSpellMetaMagic(oCreature, nClass, nLevel, nSlot); + } + else + { + nMetaMagic = METAMAGIC_NONE; + nDomain = 0; + } + if(ai_CheckCombatPosition(oCreature, oTarget, nInMelee, nSpell)) return TRUE; + } + else if(nType == AI_TALENT_TYPE_SP_ABILITY) + { + if(AI_DEBUG) ai_Debug("0i_talents", "1790", GetName(oCreature) + " is using a special ability!"); + nSpell = JsonGetInt(JsonArrayGet(jTalent, 1)); + nClass = 255; + if(ai_CheckCombatPosition(oCreature, oTarget, nInMelee, nSpell)) return TRUE; + } + else if(nType == AI_TALENT_TYPE_ITEM) + { + object oItem = StringToObject(JsonGetString(JsonArrayGet(jTalent, 2))); + int nBaseItemType = GetBaseItemType(oItem); + if(ai_CheckCombatPosition(oCreature, oTarget, nInMelee, nSpell, nBaseItemType)) return TRUE; + int nIndex, nSubIndex = 0; + nSlot = JsonGetInt(JsonArrayGet(jTalent, 4)); + itemproperty ipProp = GetFirstItemProperty(oItem); + while(GetIsItemPropertyValid(ipProp)) + { + if(nIndex++ == nSlot) break; + ipProp = GetNextItemProperty(oItem); + } + // Cast items have the following: + // 1)Single_Use. + // 2-6) Charges/Use [Note: 7 is 0 charges per use]. + // 8-12) Uses/Day [Note: 13 is unlimited uses per day]. + // We set the slot to -1 to let the other function know we need this talent removed. + int nUses = GetItemPropertyCostTableValue(ipProp); + if(nUses == 1) + { + if(AI_DEBUG) ai_Debug("0i_talents", "1816", "Single Use item."); + if(AI_DEBUG) ai_Debug("0i_talents", "1817", "Stack size: " + IntToString(GetItemStackSize(oItem))); + // We also must check for stack size. + if(GetItemStackSize(oItem) == 1) JsonArrayInsertInplace(jTalent, JsonInt(-1), 4); + } + else if(nUses > 1 && nUses < 7) + { + int nCharges = GetItemCharges(oItem); + // If the item is equipable then do not use the last charge! + if(Get2DAString("baseitems", "EquipableSlots", GetBaseItemType(oItem)) != "0x00000") + { + if(nCharges <= 7 - nUses) return FALSE; + } + if(AI_DEBUG) ai_Debug("0i_talents", "1824", "Item charges: " + IntToString(nCharges)); + if(nCharges < (7 - nUses) * 2) + { + if(AI_DEBUG) ai_Debug("0i_talents", "1829", "Stack size: " + IntToString(GetItemStackSize(oItem))); + // We also must check for stack size. + if(GetItemStackSize(oItem) == 1) JsonArrayInsertInplace(jTalent, JsonInt(-1), 4); + } + } + else if(nUses > 7 && nUses < 13) + { + int nPerDay = GetItemPropertyUsesPerDayRemaining(oItem, ipProp); + if(AI_DEBUG) ai_Debug("0i_talents", "1837", "Item uses: " + IntToString(nPerDay)); + if(nPerDay == 1) + { + if(AI_DEBUG) ai_Debug("0i_talents", "1842", "Stack size: " + IntToString(GetItemStackSize(oItem))); + // We also must check for stack size. + if(GetItemStackSize(oItem) == 1) JsonArrayInsertInplace(jTalent, JsonInt(-1), 4); + } + } + // Lets not always use unlimited items! + else if(nUses == 7 || nUses == 13) + { + if(ai_CompareLastAction(oCreature, nSpell)) return FALSE; + } + ai_SetLastAction(oCreature, nSpell); + ActionUseItemOnObject(oItem, ipProp, oTarget, nSubIndex); + ActionDoCommand(ExecuteScript("0e_do_combat_rnd", oCreature)); + if(AI_DEBUG) ai_Debug("0i_talents", "1850", GetName(oCreature) + " is using " + GetName(oItem) + " on " + GetName(oTarget)); + return TRUE; + } + if(AI_DEBUG) ai_Debug("0i_talents", "1853", "nMetaMagic: " + IntToString(nMetaMagic) + + " nDomain: " + IntToString(nDomain) + " nClass: " + IntToString(nClass)); + ai_SetLastAction(oCreature, nSpell); + ActionCastSpellAtObject(nSpell, oTarget, nMetaMagic, FALSE, nDomain, 0, FALSE, nClass, FALSE); + ActionDoCommand(ExecuteScript("0e_do_combat_rnd", oCreature)); + if(AI_DEBUG) + { + string sSpellName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); + ai_Debug("0i_talents", "1859", GetName(oCreature) + " is casting " + sSpellName + " on " + GetName(oTarget)); + } + return TRUE; +} +int ai_UseTalentAtLocation(object oCreature, json jTalent, object oTarget, int nInMelee) +{ + int nSpell, nClass, nLevel, nSlot, nMetaMagic, nDomain; + int nType = JsonGetInt(JsonArrayGet(jTalent, 0)); + if(nType == AI_TALENT_TYPE_SPELL) + { + if(!ai_CastInMelee(oCreature, nSpell, nInMelee)) return FALSE; + nClass = JsonGetInt(JsonArrayGet(jTalent, 2)); + if(Get2DAString("classes", "MemorizesSpells", nClass) == "1") + { + nSpell = JsonGetInt(JsonArrayGet(jTalent, 1)); + nLevel = JsonGetInt(JsonArrayGet(jTalent, 3)); + nSlot = JsonGetInt(JsonArrayGet(jTalent, 4)); + if(GetMemorizedSpellIsDomainSpell(oCreature, nClass, nLevel, nSlot) == 1) nDomain = nLevel; + else nDomain = 0; + nMetaMagic = GetMemorizedSpellMetaMagic(oCreature, nClass, nLevel, nSlot); + } + else + { + nSpell = JsonGetInt(JsonArrayGet(jTalent, 1)); + nMetaMagic = METAMAGIC_NONE; + nDomain = 0; + } + } + else if(nType == AI_TALENT_TYPE_SP_ABILITY) + { + if(AI_DEBUG) ai_Debug("0i_talents", "1888", GetName(oCreature) + " is using a special ability!"); + nSpell = JsonGetInt(JsonArrayGet(jTalent, 1)); + nClass = 255; + } + else if(nType == AI_TALENT_TYPE_ITEM) + { + object oItem = StringToObject(JsonGetString(JsonArrayGet(jTalent, 2))); + int nBaseItemType = GetBaseItemType(oItem); + if(ai_CheckCombatPosition(oCreature, oTarget, nInMelee, nSpell, nBaseItemType)) return TRUE; + int nIndex; + int nSubIndex = JsonGetInt(JsonArrayGet(jTalent, 3));; + nSlot = JsonGetInt(JsonArrayGet(jTalent, 4)); + itemproperty ipProp = GetFirstItemProperty(oItem); + while(GetIsItemPropertyValid(ipProp)) + { + if(nIndex++ == nSlot) break; + ipProp = GetNextItemProperty(oItem); + } + // Cast items have the following: + // 1)Single_Use. + // 2-6) Charges/Use [Note: 7 is 0 charges per use]. + // 8-12) Uses/Day [Note: 13 is unlimited uses per day]. + // We set the slot to -1 to let the other function know we need this talent removed. + int nUses = GetItemPropertyCostTableValue(ipProp); + if(nUses == 1) JsonArrayInsertInplace(jTalent, JsonInt(-1), 4); + else if(nUses > 1 && nUses < 7) + { + if(AI_DEBUG) ai_Debug("0i_talents", "1915", "Item charges: " + IntToString(GetItemCharges(oItem))); + int nCharges = GetItemCharges(oItem); + // If the item is equipable then do not use the last charge! + if(Get2DAString("baseitems", "EquipableSlots", GetBaseItemType(oItem)) != "0x00000") + { + if(nCharges <= 7 - nUses) return FALSE; + } + if(AI_DEBUG) ai_Debug("0i_talents", "1824", "Item charges: " + IntToString(nCharges)); + if(nCharges < (7 - nUses) * 2) + { + if(AI_DEBUG) ai_Debug("0i_talents", "1829", "Stack size: " + IntToString(GetItemStackSize(oItem))); + // We also must check for stack size. + if(GetItemStackSize(oItem) == 1) JsonArrayInsertInplace(jTalent, JsonInt(-1), 4); + } + } + else if(nUses > 7 && nUses < 13) + { + if(AI_DEBUG) ai_Debug("0i_talents", "1923", "Item uses: " + IntToString(GetItemPropertyUsesPerDayRemaining(oItem, ipProp))); + int nPerDay = GetItemPropertyUsesPerDayRemaining(oItem, ipProp); + if(nUses == 8 && nPerDay == 1 || nUses == 9 && nPerDay < 4 || + nUses == 10 && nPerDay < 6 || nUses == 11 && nPerDay < 8 || + nUses == 12 && nPerDay < 10) JsonArrayInsertInplace(jTalent, JsonInt(-1), 4); + } + // Lets not always use unlimited items! + else if(nUses == 7 || nUses == 13) + { + if(ai_CompareLastAction(oCreature, nSpell)) return FALSE; + } + if(ai_CheckCombatPosition(oCreature, oTarget, nInMelee, nSpell)) return TRUE; + ai_SetLastAction(oCreature, nSpell); + ActionUseItemAtLocation(oItem, ipProp, GetLocation(oTarget), nSubIndex); + ActionDoCommand(ExecuteScript("0e_do_combat_rnd", oCreature)); + if(AI_DEBUG) ai_Debug("0i_talents", "1934", GetName(oCreature) + " is using " + GetName(oItem) + " at a location."); + return TRUE; + } + if(ai_CheckCombatPosition(oCreature, oTarget, nInMelee, nSpell)) return TRUE; + ai_SetLastAction(oCreature, nSpell); + ActionCastSpellAtLocation(nSpell, GetLocation(oTarget), nMetaMagic, FALSE, 0, FALSE, nClass, FALSE, nDomain); + ActionDoCommand(ExecuteScript("0e_do_combat_rnd", oCreature)); + string sSpellName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); + if(AI_DEBUG) ai_Debug("0i_talents", "1943", GetName(oCreature) + " is casting " + sSpellName + " at a location!"); + return TRUE; +} +int ai_CheckSpecialTalentsandUse(object oCreature, json jTalent, string sCategory, int nInMelee, object oTarget) +{ + int nSpell = JsonGetInt(JsonArrayGet(jTalent, 1)); + if(AI_DEBUG) ai_Debug("0i_talents", "1949", "nSpell: " + GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))) + + " sCategory: " + sCategory); + if(sCategory == AI_TALENT_DISCRIMINANT_AOE) + { + //ai_Debug("0i_talents", "1953", "CompareLastAction: " + + // IntToString(ai_CompareLastAction(oCreature, nSpell))); + // If we used this spell talent last round then don't use it this round. + //if(ai_CompareLastAction(oCreature, nSpell)) return FALSE; + // Check to see if Disjunction should *not* be cast. + if(nSpell == SPELL_MORDENKAINENS_DISJUNCTION) + { + // Our master does not want us using any type of dispel! + if(ai_GetMagicMode(oCreature, AI_MAGIC_STOP_DISPEL)) return FALSE; + float fRange; + if(nInMelee) fRange = AI_RANGE_MELEE; + else fRange = ai_GetOffensiveSpellSearchRange(oCreature, nSpell); + // Get the biggest group we can. + string sIndex = IntToString(ai_GetHighestMeleeIndexNotInAOE(oCreature)); + oTarget = GetLocalObject(oCreature, AI_ENEMY + sIndex); + if(!ai_CreatureHasDispelableEffect(oCreature, oTarget)) return FALSE; + // Maybe we should do an area of effect instead? + int nEnemies = ai_GetNumOfEnemiesInRange(oTarget, 5.0); + if(nEnemies > 2) + { + if(ai_UseTalentAtLocation(oCreature, jTalent, oTarget, nInMelee)) return TRUE; + } + } + // These spells have a Range of Personal i.e. cast on themselves, and + // an Area of Effect of Colossal (10.0). + else if(nSpell == SPELL_FIRE_STORM || nSpell == SPELL_STORM_OF_VENGEANCE) + { + // Make sure we have enough enemies to use this on. + int nEnemies = ai_GetNumOfEnemiesInRange(oCreature, 10.0); + if(nEnemies < 2) return FALSE; + // Get the nearest target to check defenses on. + oTarget = ai_GetNearestTarget(oCreature, 10.0); + if(!ai_CastOffensiveSpellVsTarget(oCreature, oTarget, nSpell) || + ai_CreatureImmuneToEffect(oCreature, oTarget, nSpell)) return FALSE; + if(ai_UseTalentAtLocation(oCreature, jTalent, oTarget, nInMelee)) return TRUE; + } + else if(nSpell == SPELL_UNDEATH_TO_DEATH) + { + float fRange = ai_GetOffensiveSpellSearchRange(oCreature, nSpell); + int nUndead = ai_GetRacialTypeCount(oCreature, RACIAL_TYPE_UNDEAD, fRange); + if(nUndead < 3) return FALSE; + oTarget = ai_GetLowestCRRacialTarget(oCreature, RACIAL_TYPE_UNDEAD, fRange); + } + // Get a target for discriminant spells if one is not already set. + if(oTarget == OBJECT_INVALID) + { + float fRange; + if(nInMelee) fRange = AI_RANGE_MELEE; + else fRange = ai_GetOffensiveSpellSearchRange(oCreature, nSpell); + oTarget = ai_CheckForGroupedTargetNotInAOE(oCreature, fRange); + } + if(oTarget == OBJECT_INVALID || GetHasSpellEffect(nSpell, oTarget) || + !ai_CastOffensiveSpellVsTarget(oCreature, oTarget, nSpell) || + ai_CreatureImmuneToEffect(oCreature, oTarget, nSpell)) return FALSE; + } + else if(sCategory == AI_TALENT_INDISCRIMINANT_AOE) + { + //ai_Debug("0i_talents", "1991", "CompareLastAction: " + + // IntToString(ai_CompareLastAction(oCreature, nSpell))); + // If we used this spell talent last round then don't use it this round. + //if(ai_CompareLastAction(oCreature, nSpell)) return FALSE; + // These spells have a Range of Personal i.e. cast on themselves, and + // an Area of Effect of Colossal (10.0). + if(nSpell == SPELL_METEOR_SWARM) + { + // Make sure we have enough enemies and few allies to hit. + int nAllies = ai_GetNumOfAlliesInGroup(oCreature, 10.0); + int nEnemies = ai_GetNumOfEnemiesInRange(oCreature, 10.0); + if(nAllies > 1 || nEnemies < 2) return FALSE; + // Get the nearest target to check defenses on. + oTarget = ai_GetNearestTarget(oCreature, 10.0); + if(!ai_CastOffensiveSpellVsTarget(oCreature, oTarget, nSpell) || + ai_CreatureImmuneToEffect(oCreature, oTarget, nSpell)) return FALSE; + if(ai_UseTalentAtLocation(oCreature, jTalent, oCreature, nInMelee)) return TRUE; + } + // Get a target for indiscriminant spells if one is not already set. + if(oTarget == OBJECT_INVALID) + { + float fRange = ai_GetOffensiveSpellSearchRange(oCreature, nSpell); + oTarget = ai_CheckForGroupedTargetNotInAOE(oCreature, fRange); + // Check for the number of allies, if there are too many then skip. + if(oTarget == OBJECT_INVALID) return FALSE; + int nRoll = d6() + 1; + if(GetAssociateType(oCreature)) nRoll = d3(); + int nAllies = ai_GetNumOfAlliesInGroup(oTarget, AI_RANGE_CLOSE); + if(AI_DEBUG) ai_Debug("0i_talents", "2084", "Num of Allies in range: " + IntToString(nAllies)+ + " < nRoll: " + IntToString(nRoll)); + if(nAllies >= nRoll) return FALSE; + } + if(oTarget == OBJECT_INVALID || GetHasSpellEffect(nSpell, oTarget) || + !ai_CastOffensiveSpellVsTarget(oCreature, oTarget, nSpell) || + ai_CreatureImmuneToEffect(oCreature, oTarget, nSpell)) return FALSE; + //********************************************************************** + //********** These spells are checked after picking a target *********** + //********************************************************************** + // Check if the Sleep spells are being used appropriately. + if(nSpell == SPELL_SLEEP) + { + if(GetHitDice(oTarget) > 4) return FALSE; + } + // Lets only use silence on casters. + else if(nSpell == SPELL_SILENCE) + { + if(!ai_CheckClassType(oTarget, AI_CLASS_TYPE_CASTER)) + { + oTarget = ai_GetNearestClassTarget(oCreature, AI_CLASS_TYPE_CASTER); + if(oTarget == OBJECT_INVALID) return FALSE; + } + } + } + else if(sCategory == AI_TALENT_RANGED) + { + //ai_Debug("0i_talents", "2045", "CompareLastAction: " + + // IntToString(ai_CompareLastAction(oCreature, nSpell))); + // If we used this spell talent last round then don't use it this round. + //if(ai_CompareLastAction(oCreature, nSpell)) return FALSE; + // Check to see if Dispel Magic and similar spells should *not* be cast + if(nSpell == SPELL_DISPEL_MAGIC || nSpell == SPELL_LESSER_DISPEL || + nSpell == SPELL_GREATER_DISPELLING) + { + // Our master does not want us using any type of dispel! + if(ai_GetMagicMode(oCreature, AI_MAGIC_STOP_DISPEL)) return FALSE; + float fRange; + if(nInMelee) fRange = AI_RANGE_MELEE; + else fRange = ai_GetOffensiveSpellSearchRange(oCreature, nSpell); + // Lets get a caster as they should have more buffs. + oTarget = ai_GetNearestClassTarget(oCreature, AI_CLASS_TYPE_CASTER, fRange); + // No caster then get the most powerful enemy! + if(oTarget == OBJECT_INVALID) oTarget = ai_GetHighestCRTarget(oCreature, fRange); + if(oTarget != OBJECT_INVALID) + { + if(!ai_CreatureHasDispelableEffect(oCreature, oTarget)) return FALSE; + // Maybe we should do an area of effect instead? + int nEnemies = ai_GetNumOfEnemiesInRange(oTarget, 5.0); + if(nEnemies > 2) + { + if(ai_UseTalentAtLocation(oCreature, jTalent, oTarget, nInMelee)) return TRUE; + } + } + if(oTarget == OBJECT_INVALID) return FALSE; + } + // Make sure the spell will work on the target. + else if(nSpell == SPELL_HOLD_PERSON || nSpell == SPELL_DOMINATE_PERSON || + nSpell == SPELL_CHARM_PERSON) + { + if(oTarget != OBJECT_INVALID) + { + int nRaceType = GetRacialType(oTarget); + if(AI_DEBUG) ai_Debug("0i_talents", "2075", " Person Spell race: " + IntToString(nRaceType)); + if((nRaceType > 6 && nRaceType < 12) || nRaceType > 15) oTarget = OBJECT_INVALID; + } + if(oTarget == OBJECT_INVALID) + { + float fRange; + if(nInMelee) fRange = AI_RANGE_MELEE; + else fRange = ai_GetOffensiveSpellSearchRange(oCreature, nSpell); + oTarget = ai_GetNearestRacialTarget(oCreature, AI_RACIAL_TYPE_HUMANOID, fRange); + if(oTarget == OBJECT_INVALID) return FALSE; + } + } + else if(nSpell == SPELL_HOLD_ANIMAL || nSpell == SPELL_DOMINATE_ANIMAL) + { + if(oTarget != OBJECT_INVALID) + { + if(GetRacialType(oTarget) != RACIAL_TYPE_ANIMAL) oTarget = OBJECT_INVALID; + } + if(oTarget == OBJECT_INVALID) + { + float fRange; + if(nInMelee) fRange = AI_RANGE_MELEE; + else fRange = ai_GetOffensiveSpellSearchRange(oCreature, nSpell); + oTarget = ai_GetNearestRacialTarget(oCreature, AI_RACIAL_TYPE_ANIMAL_BEAST, fRange); + if(oTarget == OBJECT_INVALID) return FALSE; + } + } + // Get a target for ranged spells if one is not already set. + if(oTarget == OBJECT_INVALID) + { + float fRange; + if(nInMelee) fRange = AI_RANGE_MELEE; + else fRange = ai_GetOffensiveSpellSearchRange(oCreature, nSpell); + oTarget = ai_GetSpellTargetBasedOnSaves(oCreature, nSpell, fRange); + } + if(oTarget == OBJECT_INVALID || GetHasSpellEffect(nSpell, oTarget) || + !ai_CastOffensiveSpellVsTarget(oCreature, oTarget, nSpell) || + ai_CreatureImmuneToEffect(oCreature, oTarget, nSpell)) return FALSE; + //********************************************************************** + //********** These spells are checked after picking a target *********** + //********************************************************************** + // Don't use Domination spells on players! They don't work. + if((nSpell == SPELL_DOMINATE_MONSTER || nSpell == SPELL_DOMINATE_PERSON)) + { + if(ai_GetIsCharacter(oTarget)) return FALSE; + } + // Check to see if they have the shield spell up. + else if(nSpell == SPELL_MAGIC_MISSILE) + { + if(GetHasSpellEffect(SPELL_SHIELD, oTarget)) return FALSE; + } + // Scare only works on 5 hitdice or less. + else if(nSpell == SPELL_SCARE) + { + if(GetHitDice(oTarget) > 5) return FALSE; + } + // Don't use drown against nonliving opponents. + else if(nSpell == SPELL_DROWN) + { + if(ai_IsNonliving(GetRacialType(oTarget))) return FALSE; + } + // Don't use Power Word Kill on Targets with more than 100hp + else if(nSpell == SPELL_POWER_WORD_KILL) + { + if(GetCurrentHitPoints(oTarget) <= 100) return FALSE; + } + } + else if(sCategory == AI_TALENT_TOUCH) + { + //ai_Debug("0i_talents", "2139", "CompareLastAction: " + + // IntToString(ai_CompareLastAction(oCreature, nSpell))); + // If we used this spell talent last round then don't use it this round. + //if(ai_CompareLastAction(oCreature, nSpell)) return FALSE; + // Get a target for touch spells if one is not already set. + if(oTarget == OBJECT_INVALID) + { + oTarget = ai_GetSpellTargetBasedOnSaves(oCreature, nSpell, AI_RANGE_MELEE); + } + if(oTarget == OBJECT_INVALID || GetHasSpellEffect(nSpell, oTarget) || + !ai_CastOffensiveSpellVsTarget(oCreature, oTarget, nSpell) || + ai_CreatureImmuneToEffect(oCreature, oTarget, nSpell)) return FALSE; + } + else if(sCategory == AI_TALENT_HEALING) + { + int nHpLost = ai_GetPercHPLoss(oTarget); + // If the target is bloody then just use the best we have! + if(nHpLost > AI_HEALTH_BLOODY) + { + // Make sure we should use a mass heal on us or an ally! + // Two allies need healing or one is almost dead to use mass heal! + if(nSpell == SPELL_MASS_HEAL) + { + int bWoundedAlly; + object oAlly = ai_GetNearestAlly(oTarget); + if(oAlly != OBJECT_INVALID) + { + // If we don't have a nearby ally that needs healed then skip. + if(ai_GetPercHPLoss(oAlly) > AI_HEALTH_WOUNDED || + GetDistanceBetween(oCreature, oAlly) > 9.0f) return FALSE; + } + } + // Make sure they have taken enough damage. + int nHpDmg = GetMaxHitPoints(oTarget) - GetCurrentHitPoints(oTarget); + if(!ai_ShouldWeCastThisCureSpell(nSpell, nHpDmg)) return FALSE; + } + } + else if(sCategory == AI_TALENT_ENHANCEMENT) + { + if(AI_DEBUG) ai_Debug("0i_talents", "2713", "CompareLastAction: " + + IntToString(ai_CompareLastAction(oCreature, nSpell))); + // If we used this spell talent last round then don't use it this round. + if(ai_CompareLastAction(oCreature, nSpell)) return FALSE; + if(nSpell == SPELL_INVISIBILITY || nSpell == SPELL_SANCTUARY) + { + // Lets not run past an enemy to cast an enhancement unless we have + // the ability to move in combat, bad tactics! + float fRange; + if(ai_CanIMoveInCombat(oCreature)) fRange = AI_RANGE_PERCEPTION; + else + { + fRange = GetDistanceBetween(oCreature, GetLocalObject(oCreature, AI_ENEMY_NEAREST)) - 3.0f; + // Looks bad when your right next to an ally, but technically the enemy is closer. + if(fRange < AI_RANGE_MELEE) fRange = AI_RANGE_MELEE; + } + oTarget = ai_GetAllyToHealTarget(oCreature, fRange); + if(oTarget != OBJECT_INVALID) + { + int nHp = ai_GetPercHPLoss(oTarget); + int nHpLimit = ai_GetHealersHpLimit(oCreature); + if(nHp > nHpLimit) return FALSE; + } + } + if(nSpell == SPELL_PRAYER) + { + int nEnemies = ai_GetNumOfEnemiesInRange(oCreature, 10.0); + int nAllies = ai_GetNumOfAlliesInGroup(oCreature, 10.0); + if(nEnemies + nAllies < 5) return FALSE; + oTarget = oCreature; + } + // Since haste does not have an effect when it comes from items when we + // check for item properties we set this variable so we know they have it. + else if(nSpell == SPELL_HASTE && GetLocalInt(oCreature, sIPHasHasteVarname)) return FALSE; + // Only reason to cast Ultravision(Darkvision) in combat is if a Darkness + // spell is nearby. + else if(nSpell == SPELL_DARKVISION) + { + int nCnt = 1, bCastSpell; + string sAOEType; + object oAOE = GetNearestObject(OBJECT_TYPE_AREA_OF_EFFECT, oCreature, nCnt); + while(oAOE != OBJECT_INVALID && GetDistanceBetween(oCreature, oAOE) <= AI_RANGE_PERCEPTION) + { + // AOE's have the tag set to the "LABEL" in vfx_persistent.2da + sAOEType = GetTag(oAOE); + if(AI_DEBUG) ai_Debug("0i_talents", "2759", "Ultravision check; AOE tag: " + sAOEType); + if(sAOEType == "VFX_PER_DARKNESS") + { + if(!GetHasFeat(FEAT_DARKVISION)) bCastSpell = TRUE; + break; + } + oAOE = GetNearestObject(OBJECT_TYPE_AREA_OF_EFFECT, oCreature, ++nCnt); + } + if(!bCastSpell) return FALSE; + } + // Get a target for enhancement spells if one is not already set. + if(oTarget == OBJECT_INVALID) + { + // Get talents range and target. + float fRange = ai_GetSpellRange(nSpell); + // Personal spell + if(fRange == 0.1f) oTarget = oCreature; + // Range/Touch spell + else oTarget = ai_GetAllyBuffTarget(oCreature, nSpell, fRange); + } + if(AI_DEBUG) ai_Debug("0i_talents", "2260", " oTarget: " + GetName(oTarget) + + " HasSpellEffect: " + IntToString(GetHasSpellEffect(nSpell, oTarget))); + if(oTarget == OBJECT_INVALID || GetHasSpellEffect(nSpell, oTarget)) return FALSE; + //********************************************************************** + //********** These spells are checked after picking a target *********** + //********************************************************************** + // Weapon enhancing spells only work on melee weapons! + if(nSpell == SPELL_MAGIC_WEAPON || nSpell == SPELL_GREATER_MAGIC_WEAPON || + nSpell == SPELL_BLESS_WEAPON || nSpell == SPELL_FLAME_WEAPON || + nSpell == SPELL_DARKFIRE) + { + object oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTarget); + if(!ai_GetIsMeleeWeapon(oWeapon)) return FALSE; + } + // Should we ignore associates? + if(ai_GetAIMode(oCreature, AI_MODE_IGNORE_ASSOCIATES) && + GetAssociateType(oTarget) > 1) return FALSE; + } + else if(sCategory == AI_TALENT_PROTECTION) + { + if(AI_DEBUG) ai_Debug("0i_talents", "2281", "CompareLastAction: " + + IntToString(ai_CompareLastAction(oCreature, nSpell))); + // If we used this spell talent last round then don't use it this round. + if(ai_CompareLastAction(oCreature, nSpell)) return FALSE; + // Stone bones only effects the undead. + if(nSpell == SPELL_STONE_BONES) + { + if(oTarget != OBJECT_INVALID) + { + if(GetRacialType(oTarget) != RACIAL_TYPE_UNDEAD) oTarget = OBJECT_INVALID; + } + if(oTarget == OBJECT_INVALID) + { + float fRange; + if(nInMelee) fRange = AI_RANGE_MELEE; + else fRange = ai_GetOffensiveSpellSearchRange(oCreature, nSpell); + oTarget = ai_GetNearestRacialTarget(oCreature, RACIAL_TYPE_UNDEAD, fRange); + if(oTarget == OBJECT_INVALID) return FALSE; + } + } + else if(nSpell == SPELL_MAGIC_FANG) + { + oTarget = GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION, oCreature); + if(oTarget == OBJECT_INVALID) return FALSE; + } + // Lets see if we should cast resistances in our current situation, + // lets check for enemy casters that may have energy damaging spells, or energy weapons. + else if(nSpell == SPELL_ENDURE_ELEMENTS || nSpell == SPELL_PROTECTION_FROM_ELEMENTS || + nSpell == SPELL_RESIST_ELEMENTS || nSpell == SPELL_ENERGY_BUFFER) + { + int bCastSpell; + object oEnemy = ai_GetEnemyAttackingMe(oCreature); + if(oEnemy != OBJECT_INVALID) + { + object oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oEnemy); + if(oWeapon == OBJECT_INVALID) oWeapon = GetItemInSlot(INVENTORY_SLOT_CWEAPON_R, oEnemy); + if(oWeapon == OBJECT_INVALID) oWeapon = GetItemInSlot(INVENTORY_SLOT_CWEAPON_B, oEnemy); + if(AI_DEBUG) ai_Debug("0i_talents", "2812", GetName(oEnemy) + " is using weapon: " + GetName(oWeapon)); + if(oWeapon != OBJECT_INVALID) + { + itemproperty nProperty = GetFirstItemProperty(oWeapon); + while(GetIsItemPropertyValid(nProperty)) + { + if(GetItemPropertyType(nProperty) == ITEM_PROPERTY_DAMAGE_BONUS) + { + int nSubType = GetItemPropertySubType(nProperty); + if(AI_DEBUG) ai_Debug("0i_talents", "2821", GetName(oWeapon) + " has PropertySubType: " + + IntToString(nSubType) + " If equals [6,7,9,10,13] don't cast!"); + if(nSubType == 6 || nSubType == 7 || nSubType == 9 || + nSubType == 10 || nSubType == 13) + { + bCastSpell = TRUE; + break; + } + } + nProperty = GetNextItemProperty(oWeapon); + } + } + } + if(ai_GetNearestClassTarget(oCreature, AI_CLASS_TYPE_CASTER) != OBJECT_INVALID) bCastSpell = TRUE; + if(!bCastSpell) return FALSE; + } + // Get a target for protection spells if one is not already set. + if(oTarget == OBJECT_INVALID) + { + // Get talents range and target. + float fRange = ai_GetSpellRange(nSpell); + // Personal spell + if(fRange == 0.1f) oTarget = oCreature; + // Range/Touch spell + else oTarget = ai_GetAllyBuffTarget(oCreature, nSpell, fRange); + } + if(oTarget == OBJECT_INVALID || GetHasSpellEffect(nSpell, oTarget)) return FALSE; + //********************************************************************** + //********** These spells are checked after picking a target *********** + //********************************************************************** + // Don't double up Stoneskin, Ghostly visage, or Ethereal visage. + if(nSpell == SPELL_GHOSTLY_VISAGE || nSpell == SPELL_ETHEREAL_VISAGE || + nSpell == SPELL_STONESKIN) + { + if(GetHasSpellEffect(SPELL_ETHEREAL_VISAGE, oTarget) || + GetHasSpellEffect(SPELL_STONESKIN, oTarget) || + GetHasSpellEffect(SPELL_GHOSTLY_VISAGE, oTarget)) return FALSE; + } + // Don't use displacement if we are invisible! + else if(nSpell == SPELL_DISPLACEMENT) + { + if(GetHasSpellEffect(SPELL_INVISIBILITY, oTarget) || + GetHasSpellEffect(SPELL_IMPROVED_INVISIBILITY, oTarget) || + GetHasSpellEffect(SPELL_INVISIBILITY_SPHERE, oTarget) || + GetHasSpellEffect(SPELL_DISPLACEMENT, oTarget)) return FALSE; + } + // Should we ignore associates? + if(ai_GetAIMode(oCreature, AI_MODE_IGNORE_ASSOCIATES) && + GetAssociateType(oTarget) > 1) return FALSE; + } + else if(sCategory == AI_TALENT_SUMMON) + { + if(GetAssociate(ASSOCIATE_TYPE_SUMMONED, oCreature) != OBJECT_INVALID) return FALSE; + if(oTarget == OBJECT_INVALID) + { + /* Removed for now, summons creature in location that enemy was... looks bad. + float fRange; + if(nInMelee) fRange = AI_RANGE_MELEE; + else fRange = ai_GetOffensiveSpellSearchRange(oCreature, nSpell); + // Select lowest enemy combat target for summons. + oTarget = ai_GetLowestCRTarget(oCreature, fRange); + if(oTarget == OBJECT_INVALID) oTarget = oCreature; + */ + oTarget = oCreature; + if(ai_UseTalentAtLocation(oCreature, jTalent, oTarget, nInMelee)) + { + DelayCommand(4.0, ai_NameAssociate(oCreature, ASSOCIATE_TYPE_SUMMONED, "")); + return TRUE; + } + } + } + else if(sCategory == AI_TALENT_CURE) + { + } + if(ai_UseTalentOnObject(oCreature, jTalent, oTarget, nInMelee)) return TRUE; + return FALSE; +} diff --git a/src/module/nss/0i_time.nss b/src/module/nss/0i_time.nss new file mode 100644 index 0000000..3052ea6 --- /dev/null +++ b/src/module/nss/0i_time.nss @@ -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"); +} diff --git a/src/module/nss/ai_a_ambusher.nss b/src/module/nss/ai_a_ambusher.nss new file mode 100644 index 0000000..f3f424b --- /dev/null +++ b/src/module/nss/ai_a_ambusher.nss @@ -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); +} diff --git a/src/module/nss/ai_a_atk_casters.nss b/src/module/nss/ai_a_atk_casters.nss new file mode 100644 index 0000000..362ba4b --- /dev/null +++ b/src/module/nss/ai_a_atk_casters.nss @@ -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); +} + diff --git a/src/module/nss/ai_a_atk_nearest.nss b/src/module/nss/ai_a_atk_nearest.nss new file mode 100644 index 0000000..1261dc7 --- /dev/null +++ b/src/module/nss/ai_a_atk_nearest.nss @@ -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)); +} + diff --git a/src/module/nss/ai_a_atk_warrior.nss b/src/module/nss/ai_a_atk_warrior.nss new file mode 100644 index 0000000..4821e53 --- /dev/null +++ b/src/module/nss/ai_a_atk_warrior.nss @@ -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); +} + diff --git a/src/module/nss/ai_a_barbarian.nss b/src/module/nss/ai_a_barbarian.nss new file mode 100644 index 0000000..12521c9 --- /dev/null +++ b/src/module/nss/ai_a_barbarian.nss @@ -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); +} diff --git a/src/module/nss/ai_a_bard.nss b/src/module/nss/ai_a_bard.nss new file mode 100644 index 0000000..975bac2 --- /dev/null +++ b/src/module/nss/ai_a_bard.nss @@ -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); +} diff --git a/src/module/nss/ai_a_cleric.nss b/src/module/nss/ai_a_cleric.nss new file mode 100644 index 0000000..5de1cc2 --- /dev/null +++ b/src/module/nss/ai_a_cleric.nss @@ -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); +} diff --git a/src/module/nss/ai_a_cntrspell.nss b/src/module/nss/ai_a_cntrspell.nss new file mode 100644 index 0000000..a1bc9ec --- /dev/null +++ b/src/module/nss/ai_a_cntrspell.nss @@ -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"); +} diff --git a/src/module/nss/ai_a_default.nss b/src/module/nss/ai_a_default.nss new file mode 100644 index 0000000..7540340 --- /dev/null +++ b/src/module/nss/ai_a_default.nss @@ -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)); +} + diff --git a/src/module/nss/ai_a_defensive.nss b/src/module/nss/ai_a_defensive.nss new file mode 100644 index 0000000..f19523c --- /dev/null +++ b/src/module/nss/ai_a_defensive.nss @@ -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)); +} diff --git a/src/module/nss/ai_a_druid.nss b/src/module/nss/ai_a_druid.nss new file mode 100644 index 0000000..6b82c26 --- /dev/null +++ b/src/module/nss/ai_a_druid.nss @@ -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); +} diff --git a/src/module/nss/ai_a_fighter.nss b/src/module/nss/ai_a_fighter.nss new file mode 100644 index 0000000..a5f3720 --- /dev/null +++ b/src/module/nss/ai_a_fighter.nss @@ -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); +} diff --git a/src/module/nss/ai_a_flanker.nss b/src/module/nss/ai_a_flanker.nss new file mode 100644 index 0000000..fb6845a --- /dev/null +++ b/src/module/nss/ai_a_flanker.nss @@ -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); +} diff --git a/src/module/nss/ai_a_invisible.nss b/src/module/nss/ai_a_invisible.nss new file mode 100644 index 0000000..9772b32 --- /dev/null +++ b/src/module/nss/ai_a_invisible.nss @@ -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); +} + diff --git a/src/module/nss/ai_a_monk.nss b/src/module/nss/ai_a_monk.nss new file mode 100644 index 0000000..607ce4c --- /dev/null +++ b/src/module/nss/ai_a_monk.nss @@ -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); +} diff --git a/src/module/nss/ai_a_no_cmb_mode.nss b/src/module/nss/ai_a_no_cmb_mode.nss new file mode 100644 index 0000000..1ffedb4 --- /dev/null +++ b/src/module/nss/ai_a_no_cmb_mode.nss @@ -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); +} + diff --git a/src/module/nss/ai_a_paladin.nss b/src/module/nss/ai_a_paladin.nss new file mode 100644 index 0000000..24520a7 --- /dev/null +++ b/src/module/nss/ai_a_paladin.nss @@ -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); +} diff --git a/src/module/nss/ai_a_peaceful.nss b/src/module/nss/ai_a_peaceful.nss new file mode 100644 index 0000000..b9bd310 --- /dev/null +++ b/src/module/nss/ai_a_peaceful.nss @@ -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."); +} diff --git a/src/module/nss/ai_a_polymorphed.nss b/src/module/nss/ai_a_polymorphed.nss new file mode 100644 index 0000000..107e6e9 --- /dev/null +++ b/src/module/nss/ai_a_polymorphed.nss @@ -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); +} diff --git a/src/module/nss/ai_a_ranged.nss b/src/module/nss/ai_a_ranged.nss new file mode 100644 index 0000000..477937d --- /dev/null +++ b/src/module/nss/ai_a_ranged.nss @@ -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); +} + diff --git a/src/module/nss/ai_a_ranger.nss b/src/module/nss/ai_a_ranger.nss new file mode 100644 index 0000000..179298f --- /dev/null +++ b/src/module/nss/ai_a_ranger.nss @@ -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); +} diff --git a/src/module/nss/ai_a_rogue.nss b/src/module/nss/ai_a_rogue.nss new file mode 100644 index 0000000..10e1ae0 --- /dev/null +++ b/src/module/nss/ai_a_rogue.nss @@ -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); +} diff --git a/src/module/nss/ai_a_sorcerer.nss b/src/module/nss/ai_a_sorcerer.nss new file mode 100644 index 0000000..5e4a3b7 --- /dev/null +++ b/src/module/nss/ai_a_sorcerer.nss @@ -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); +} diff --git a/src/module/nss/ai_a_taunter.nss b/src/module/nss/ai_a_taunter.nss new file mode 100644 index 0000000..b06fed8 --- /dev/null +++ b/src/module/nss/ai_a_taunter.nss @@ -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)); +} diff --git a/src/module/nss/ai_a_wizard.nss b/src/module/nss/ai_a_wizard.nss new file mode 100644 index 0000000..dfad8c3 --- /dev/null +++ b/src/module/nss/ai_a_wizard.nss @@ -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); +} diff --git a/src/module/nss/ai_ambusher.nss b/src/module/nss/ai_ambusher.nss new file mode 100644 index 0000000..829a3da --- /dev/null +++ b/src/module/nss/ai_ambusher.nss @@ -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); +} diff --git a/src/module/nss/ai_barbarian.nss b/src/module/nss/ai_barbarian.nss new file mode 100644 index 0000000..69efcb4 --- /dev/null +++ b/src/module/nss/ai_barbarian.nss @@ -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); +} diff --git a/src/module/nss/ai_bard.nss b/src/module/nss/ai_bard.nss new file mode 100644 index 0000000..9dde198 --- /dev/null +++ b/src/module/nss/ai_bard.nss @@ -0,0 +1,67 @@ +/*////////////////////////////////////////////////////////////////////////////// + Script Name: ai_bard +//////////////////////////////////////////////////////////////////////////////// + ai script for creatures using the class Bard. + 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; + 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_TryBardSongFeat(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 ******************************* + object oTarget; + 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; + 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); +} diff --git a/src/module/nss/ai_cleric.nss b/src/module/nss/ai_cleric.nss new file mode 100644 index 0000000..34bd1e6 --- /dev/null +++ b/src/module/nss/ai_cleric.nss @@ -0,0 +1,68 @@ +/*////////////////////////////////////////////////////////////////////////////// + Script Name: ai_cleric +//////////////////////////////////////////////////////////////////////////////// + ai script for creatures using the class Cleric. + 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; + 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_TryTurningTalent(oCreature)) return; + //************************** DEFENSIVE TALENTS *************************** + int nRound = ai_GetCurrentRound(oCreature); + if(ai_TryDefensiveTalents(oCreature, nInMelee, nMaxLevel, nRound)) return; + if(ai_TryDivineShieldFeat(oCreature, nInMelee)) return; + if(ai_TryDivineMightFeat(oCreature, nInMelee)) 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 ******************************* + object oTarget; + 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) + { + 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; + 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); +} diff --git a/src/module/nss/ai_cntrspell.nss b/src/module/nss/ai_cntrspell.nss new file mode 100644 index 0000000..04939c9 --- /dev/null +++ b/src/module/nss/ai_cntrspell.nss @@ -0,0 +1,68 @@ +/*//////////////////////////////////////////////////////////////////////////////////////////////////// +// Script Name: ai_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 then setup for counter spelling. + if(!bAttack) + { + //*************************** HEALING & CURES **************************** + if(ai_TryHealingTalent(oCreature, nInMelee)) return; + if(ai_TryCureConditionTalent(oCreature, nInMelee)) return; + if(AI_DEBUG) ai_Debug("ai_cntrspell", "29", " 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_cntrspell", "41", "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", "49", "Opponent is hasted! Using ranged AI."); + ExecuteScript("ai_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_cntrspell", "60", "Setting Counterspell mode!"); + ActionCounterSpell(oTarget); + return; + } + } + } + if(AI_DEBUG) ai_Debug("ai_cntrspell", "66", "Situation is not good for counterspelling! Using ranged AI."); + ExecuteScript("ai_ranged"); +} diff --git a/src/module/nss/ai_coward.nss b/src/module/nss/ai_coward.nss new file mode 100644 index 0000000..b88e424 --- /dev/null +++ b/src/module/nss/ai_coward.nss @@ -0,0 +1,133 @@ +/*////////////////////////////////////////////////////////////////////////////// + Script Name: ai_coward +//////////////////////////////////////////////////////////////////////////////// + ai script for cowardly creatures (Any) used when they fail a moral check or + when associates are to 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 us. + int nInMelee = ai_GetNumOfEnemiesInRange(oCreature); + object oNearestEnemy = GetLocalObject(oCreature, AI_ENEMY_NEAREST); + // If we have been healed up then get back in there! + if(ai_GetPercHPLoss(oCreature) > AI_HEALTH_WOUNDED) + { + string sDefaultCombatScript = GetLocalString(oCreature, AI_DEFAULT_SCRIPT); + SetLocalString(oCreature, AI_COMBAT_SCRIPT, sDefaultCombatScript); + ExecuteScript(sDefaultCombatScript, oCreature); + return; + } + // In Melee combat! + if(nInMelee) + { + 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; + } + else + { + // 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; + // If we are seen by the enemy we need to move back so we can hide. + int nEnemyIndex = ai_GetNearestIndexThatSeesUs(oCreature); + 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_coward", "74", 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_coward", "85", "fDistance: " + FloatToString(fEnemyDistance, 0, 2)); + if(fEnemyDistance >= AI_RANGE_CLOSE) + { + int bTried = GetLocalInt(oCreature, AI_TRIED_TO_HIDE); + if(!bTried) + { + // Move away so we can hide. + if(AI_DEBUG) ai_Debug("ai_coward", "93", 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 lets get there. + else if(!GetActionMode(oCreature, ACTION_MODE_STEALTH)) + { + // Use any hiding talents we have + if(AI_DEBUG) ai_Debug("ai_coward", "113", GetName(oCreature) + " is trying to hide!"); + SetActionMode(oCreature, ACTION_MODE_STEALTH, TRUE); + SetLocalInt(oCreature, AI_TRIED_TO_HIDE, 3); + return; + } + } + // Either we cannot go into stealth or we are in stealth so do something else. + //************************* OUT OF MELEE COMBAT ************************** + //*************************** HEALING & CURES **************************** + if(ai_TryHealingTalent(oCreature, 0, oCreature)) return; + if(ai_TryCureConditionTalent(oCreature, 0)) return; + int nMaxLevel = ai_GetMonsterTalentMaxLevel(oCreature); + //************************** DEFENSIVE TALENTS *************************** + if(GetLocalInt(GetModule(), AI_RULE_SUMMON_COMPANIONS)) + { + if(ai_TrySummonFamiliarTalent(oCreature)) return; + if(ai_TrySummonAnimalCompanionTalent(oCreature)) return; + } + if(ai_TryDefensiveTalents(oCreature, nInMelee, nMaxLevel)) return; + // Stand and watch the battle we don't want to provoke anyone! + if(AI_DEBUG) ai_Debug("ai_coward", "132", GetName(oCreature) + " is holding here."); +} diff --git a/src/module/nss/ai_default.nss b/src/module/nss/ai_default.nss new file mode 100644 index 0000000..cfe8e8f --- /dev/null +++ b/src/module/nss/ai_default.nss @@ -0,0 +1,49 @@ +/*//////////////////////////////////////////////////////////////////////////////////////////////////// +// Script Name: ai_default +////////////////////////////////////////////////////////////////////////////////////////////////////// + ai script for default 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); + //*************************** 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; + //**************************** SKILL FEATURES **************************** + if(ai_TryAnimalEmpathy(oCreature)) return; + //**************************** CLASS FEATURES **************************** + if(ai_TryBarbarianRageFeat(oCreature)) return; + if(ai_TryBardSongFeat(oCreature)) return; + if(ai_TryTurningTalent(oCreature)) return; + if(GetLocalInt(GetModule(), AI_RULE_SUMMON_COMPANIONS)) + { + if(ai_TrySummonFamiliarTalent(oCreature)) return; + if(ai_TrySummonAnimalCompanionTalent(oCreature)) return; + } + if(ai_TryPolymorphSelfFeat(oCreature)) return; + //************************** DEFENSIVE TALENTS *************************** + int nRound = ai_GetCurrentRound(oCreature); + if(ai_TryDefensiveTalents(oCreature, nInMelee, nMaxLevel, nRound)) return; + if(ai_TryDivineShieldFeat(oCreature, nInMelee)) return; + if(ai_TryDivineMightFeat(oCreature, nInMelee)) 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. + ai_DoPhysicalAttackOnNearest(oCreature, nInMelee); +} diff --git a/src/module/nss/ai_defensive.nss b/src/module/nss/ai_defensive.nss new file mode 100644 index 0000000..15f5275 --- /dev/null +++ b/src/module/nss/ai_defensive.nss @@ -0,0 +1,48 @@ +/*//////////////////////////////////////////////////////////////////////////////////////////////////// +// Script Name: ai_defensive +////////////////////////////////////////////////////////////////////////////////////////////////////// + ai script for creatures put in to a defensive mode to protect themselves(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); + object oNearestEnemy = GetLocalObject(oCreature, AI_ENEMY_NEAREST); + //*************************** 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); + //**************************** SKILL FEATURES **************************** + if(ai_TryAnimalEmpathy(oCreature)) return; + //**************************** CLASS FEATURES **************************** + if(ai_TryBardSongFeat(oCreature)) return; + if(ai_TryTurningTalent(oCreature)) return; + if(GetLocalInt(GetModule(), AI_RULE_SUMMON_COMPANIONS)) + { + if(ai_TrySummonFamiliarTalent(oCreature)) return; + if(ai_TrySummonAnimalCompanionTalent(oCreature)) return; + } + //************************** DEFENSIVE TALENTS *************************** + if(ai_TryDefensiveTalents(oCreature, nInMelee, nMaxLevel)) return; + //******************** DEFENSIVE MELEE FEATS ***************************** + if(nInMelee > 0) + { + 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; + } + //********************** PHYSICAL ATTACKS ******************************** + // Even in defensive mode we want to be in battle so go find someone! + ai_DoPhysicalAttackOnNearest(oCreature, nInMelee); +} diff --git a/src/module/nss/ai_dragon.nss b/src/module/nss/ai_dragon.nss new file mode 100644 index 0000000..a82362c --- /dev/null +++ b/src/module/nss/ai_dragon.nss @@ -0,0 +1,51 @@ +/*//////////////////////////////////////////////////////////////////////////////////////////////////// +// Script Name: ai_dragon +////////////////////////////////////////////////////////////////////////////////////////////////////// + ai script for dragons. + OBJECT_SELF is the dragons 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; + // Dragons do not flee! 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; + //************************** 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; + // ************************ MELEE ATTACKS ******************************** + object oTarget = ai_GetLowestCRTargetForMeleeCombat(oCreature, nInMelee); + if(oTarget != OBJECT_INVALID) + { + if(GetDistanceBetween(oCreature, oTarget) > AI_RANGE_CLOSE) + { + // Can we do a crush attack(HD 18+)? + if(ai_TryCrushAttack(oCreature, oTarget)) return; + ai_FlyToTarget(oCreature, oTarget); + return; + } + if(ai_TryDragonBreathAttack(oCreature, nRound)) return; + ai_TryWingAttacks(oCreature); + // If we don't do a Tail sweep attack(HD 30+) then see if we can do a Tail slap(HD 12+)! + if(!ai_TryTailSweepAttack(oCreature)) ai_TryTailSlap(oCreature); + ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); + } + else ai_SearchForHiddenCreature(oCreature, TRUE); +} diff --git a/src/module/nss/ai_druid.nss b/src/module/nss/ai_druid.nss new file mode 100644 index 0000000..95cb82b --- /dev/null +++ b/src/module/nss/ai_druid.nss @@ -0,0 +1,70 @@ +/*//////////////////////////////////////////////////////////////////////////////////////////////////// +// Script Name: ai_druid +////////////////////////////////////////////////////////////////////////////////////////////////////// + ai script for creatures using the class Druid. + 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); + 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; + //**************************** SKILL FEATURES **************************** + if(ai_TryAnimalEmpathy(oCreature)) return; + //**************************** CLASS FEATURES **************************** + if(GetLocalInt(GetModule(), AI_RULE_SUMMON_COMPANIONS) && ai_TrySummonAnimalCompanionTalent(oCreature)) return; + if(ai_TryPolymorphSelfFeat(oCreature)) return; + //************************** DEFENSIVE TALENTS *************************** + int nRound = ai_GetCurrentRound(oCreature); + if(ai_TryDefensiveTalents(oCreature, nInMelee, nMaxLevel, nRound)) return; + //********************** 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; + // All else fails lets see if we have any good potions. + // PHYSICAL ATTACKS - Either we don't have talents or we are saving them. + // ************************ RANGED ATTACKS ******************************* + object oTarget; + if(ai_CanIUseRangedWeapon(oCreature, nInMelee)) + { + if(ai_HasRangedWeaponWithAmmo(oCreature)) + { + // Lets pick off the nearest targets. + if(!nInMelee) oTarget = ai_GetNearestTarget(oCreature); + else oTarget = ai_GetNearestTarget(oCreature, AI_RANGE_MELEE); + if(oTarget != OBJECT_INVALID) + { + 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; + 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); +} diff --git a/src/module/nss/ai_fighter.nss b/src/module/nss/ai_fighter.nss new file mode 100644 index 0000000..04f4ce0 --- /dev/null +++ b/src/module/nss/ai_fighter.nss @@ -0,0 +1,65 @@ +/*////////////////////////////////////////////////////////////////////////////// + Script Name: ai_fighter +//////////////////////////////////////////////////////////////////////////////// + ai script for creatures using the class Fighter. + 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); + 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; + // *********************** 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 **************************** + object oTarget; + 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); +} diff --git a/src/module/nss/ai_flanker.nss b/src/module/nss/ai_flanker.nss new file mode 100644 index 0000000..20a6538 --- /dev/null +++ b/src/module/nss/ai_flanker.nss @@ -0,0 +1,102 @@ +/*//////////////////////////////////////////////////////////////////////////////////////////////////// +// Script Name: ai_flanker +////////////////////////////////////////////////////////////////////////////////////////////////////// + ai script for monsters 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); + 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; + // *********************** 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; + //**************************** SKILL FEATURES **************************** + if(ai_TryAnimalEmpathy(oCreature)) return; + //**************************** CLASS FEATURES **************************** + if(ai_TryBarbarianRageFeat(oCreature)) return; + if(ai_TryBardSongFeat(oCreature)) return; + if(ai_TryTurningTalent(oCreature)) return; + if(GetLocalInt(GetModule(), AI_RULE_SUMMON_COMPANIONS)) + { + if(ai_TrySummonFamiliarTalent(oCreature)) return; + if(ai_TrySummonAnimalCompanionTalent(oCreature)) return; + } + // PHYSICAL ATTACKS - Either we don't have talents or we are saving them. + object oTarget; + // ************************** Melee feat attacks ************************* + // 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_GetNearestTargetForMeleeCombat(oCreature, nInMelee); + if(oTarget != OBJECT_INVALID) + { + ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); + return; + } + } + // ************************** Ranged feat attacks ************************** + if(!ai_GetAIMode(oCreature, AI_MODE_STOP_RANGED) && ai_CanIUseRangedWeapon(oCreature, nInMelee)) + { + if(ai_HasRangedWeaponWithAmmo(oCreature)) + { + if(ai_TryRangedSneakAttack(oCreature, nInMelee)) return; + oTarget = ai_GetNearestTarget(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; + } + ai_SearchForHiddenCreature(oCreature, FALSE, OBJECT_INVALID, AI_RANGE_CLOSE); +} diff --git a/src/module/nss/ai_incorporeal.nss b/src/module/nss/ai_incorporeal.nss new file mode 100644 index 0000000..cdd20bd --- /dev/null +++ b/src/module/nss/ai_incorporeal.nss @@ -0,0 +1,83 @@ +/*//////////////////////////////////////////////////////////////////////////////////////////////////// +// Script Name: ai_incorporeal +////////////////////////////////////////////////////////////////////////////////////////////////////// + ai script for creatures that are incorporeal. + oCreature 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); + 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; + //**************************** SKILL FEATURES **************************** + if(ai_TryAnimalEmpathy(oCreature)) return; + //**************************** CLASS FEATURES **************************** + if(ai_TryBarbarianRageFeat(oCreature)) return; + if(ai_TryBardSongFeat(oCreature)) return; + if(ai_TryTurningTalent(oCreature)) return; + if(ai_TrySummonAnimalCompanionTalent(oCreature)) return; + if(ai_TrySummonFamiliarTalent(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 ******************************* + object oTarget; + if (!GetHasFeatEffect (FEAT_BARBARIAN_RAGE, oCreature) && ai_CanIUseRangedWeapon(oCreature, nInMelee)) + { + if(ai_HasRangedWeaponWithAmmo(oCreature)) + { + if (ai_TryRangedSneakAttack (oCreature, nInMelee)) return; + string sIndex; + 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; + } + } + if(ai_InCombatEquipBestRangedWeapon(oCreature)) return; + } + // ************************* MELEE ATTACKS ******************************* + if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return; + oTarget = ai_GetNearestTargetForMeleeCombat (oCreature, nInMelee); + if (oTarget != OBJECT_INVALID) + { + // If we are using our hands then do a touch attack instead. + if (GetItemInSlot (INVENTORY_SLOT_RIGHTHAND) == OBJECT_INVALID) + { + if (GetItemInSlot (INVENTORY_SLOT_CWEAPON_L) != OBJECT_INVALID) + { + // Randomize so they don't appear synchronized. + float fDelay = IntToFloat(Random(2) + 1); + DelayCommand(fDelay, ActionCastSpellAtObject (769/*Shadow_Attack*/, oTarget, METAMAGIC_ANY, TRUE)); + ai_SetLastAction(oCreature, AI_LAST_ACTION_MELEE_ATK); + SetLocalObject (oCreature, AI_ATTACKED_PHYSICAL, oTarget); + } + } + else ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); + } + else ai_SearchForHiddenCreature(oCreature, TRUE); +} diff --git a/src/module/nss/ai_invisible.nss b/src/module/nss/ai_invisible.nss new file mode 100644 index 0000000..7d42b21 --- /dev/null +++ b/src/module/nss/ai_invisible.nss @@ -0,0 +1,93 @@ +/*//////////////////////////////////////////////////////////////////////////////////////////////////// +// Script Name: ai_invisible +////////////////////////////////////////////////////////////////////////////////////////////////////// + ai script for creatures(Any) that 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); + //*************************** 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); + // Skill, Class, Offensive AOE's, and Defensive talents. + // *************************** SPELL TALENTS *************************** + // ********** PROTECTION/ENHANCEMENT/SUMMON TALENTS ************ + int nRound = ai_GetCurrentRound(oCreature); + if(ai_TryDefensiveTalents(oCreature, nInMelee, nMaxLevel, nRound)) return; + // ************************** CLASS FEATURES *************************** + if(GetLocalInt(GetModule(), AI_RULE_SUMMON_COMPANIONS)) + { + if(ai_TrySummonFamiliarTalent(oCreature)) return; + if(ai_TrySummonAnimalCompanionTalent(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_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; + // PHYSICAL ATTACKS - Either we don't have talents or we are saving them. + // 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_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 feat attacks ************************* + if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return; + if(ai_TrySneakAttack(oCreature, nInMelee)) return; + 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, TRUE); +} diff --git a/src/module/nss/ai_monk.nss b/src/module/nss/ai_monk.nss new file mode 100644 index 0000000..d6ff1b6 --- /dev/null +++ b/src/module/nss/ai_monk.nss @@ -0,0 +1,65 @@ +/*//////////////////////////////////////////////////////////////////////////////////////////////////// +// Script Name: ai_monk +////////////////////////////////////////////////////////////////////////////////////////////////////// + ai script for creatures using the class Monk. + 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; + 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; + //************************** 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 ******************************* + object oTarget; + 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) + { + 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; + 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); +} diff --git a/src/module/nss/ai_paladin.nss b/src/module/nss/ai_paladin.nss new file mode 100644 index 0000000..d45d223 --- /dev/null +++ b/src/module/nss/ai_paladin.nss @@ -0,0 +1,71 @@ +/*//////////////////////////////////////////////////////////////////////////////////////////////////// +// Script Name: ai_paladin +////////////////////////////////////////////////////////////////////////////////////////////////////// + ai script for creatures using the class Paladin. + Paladins face the strongest opponents on the battlefield 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; + 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_TryTurningTalent(oCreature)) return; + //************************** DEFENSIVE TALENTS *************************** + int nRound = ai_GetCurrentRound(oCreature); + if(ai_TryDefensiveTalents(oCreature, nInMelee, nMaxLevel, nRound)) return; + if(ai_TryDivineShieldFeat(oCreature, nInMelee)) return; + if(ai_TryDivineMightFeat(oCreature, nInMelee)) 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 ******************************* + object oTarget; + if(ai_CanIUseRangedWeapon(oCreature, nInMelee)) + { + if(ai_HasRangedWeaponWithAmmo(oCreature)) + { + // Paladins face the biggest challenges first! + if(!nInMelee) oTarget = ai_GetHighestCRTarget(oCreature); + else oTarget = ai_GetHighestCRTarget(oCreature, AI_RANGE_MELEE); + if(oTarget != OBJECT_INVALID) + { + 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; + // Paladins face the biggest challenges first! + 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, TRUE); +} diff --git a/src/module/nss/ai_polymorphed.nss b/src/module/nss/ai_polymorphed.nss new file mode 100644 index 0000000..9a7630a --- /dev/null +++ b/src/module/nss/ai_polymorphed.nss @@ -0,0 +1,55 @@ +/*//////////////////////////////////////////////////////////////////////////////////////////////////// +// Script Name: ai_polymorphed +////////////////////////////////////////////////////////////////////////////////////////////////////// + ai script for polymorphed creatures. + 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) + { + if(AI_DEBUG) ai_Debug("ai_polymorphed", "19", "We are wounded and are transforming back!"); + ai_RemoveASpecificEffect(oCreature, EFFECT_TYPE_POLYMORPH); + return; + } + int nMaxLevel = ai_GetMonsterTalentMaxLevel(oCreature); + // When polymorphed we turn back then check moral. + // if(nInMelee && ai_MoralCheck(oCreature)) return; + // Skill, Class, Offensive AOE's, and Defensive talents. + // *************************** SPELL TALENTS *************************** + if(ai_CheckForAssociateSpellTalent(oCreature, nInMelee, nMaxLevel)) return; + // Class and Offensive single target talents. + // *************************** SPELL TALENTS *************************** + if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return; + if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return; + // PHYSICAL ATTACKS - Either we don't have talents or we are saving them. + object oTarget = ai_GetNearestTargetForMeleeCombat(oCreature, nInMelee); + // If we don't find a target then we don't want to fight anyone! + if(oTarget != OBJECT_INVALID) ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); + else ai_SearchForHiddenCreature(oCreature, TRUE); +} +void main() +{ + object oCreature = OBJECT_SELF; + // Need to know who we are so we can use thier abilities. + int nForm = GetAppearanceType(oCreature); + // Check to see if we are back to our normal form?(-1 to get the actual form #) + if(nForm == GetLocalInt(oCreature, AI_NORMAL_FORM) - 1) + { + // If we are transformed back then go back to our primary ai. + ai_SetCreatureAIScript(oCreature); + DeleteLocalInt(oCreature, AI_NORMAL_FORM); + string sAI = GetLocalString(oCreature, AI_COMBAT_SCRIPT); + if(sAI == "ai_polymorphed" || sAI == "") sAI = "ai_default"; + ExecuteScript(sAI, oCreature); + } + else ai_DoActions(oCreature, nForm); +} diff --git a/src/module/nss/ai_ranged.nss b/src/module/nss/ai_ranged.nss new file mode 100644 index 0000000..3a46228 --- /dev/null +++ b/src/module/nss/ai_ranged.nss @@ -0,0 +1,116 @@ +/*//////////////////////////////////////////////////////////////////////////////////////////////////// +// Script Name: ai_ranged +////////////////////////////////////////////////////////////////////////////////////////////////////// + ai script for monsters to use the ranged ai. + OBJECT_SELF is the creature running the ai. + Will attempt to use ranged weapons/spells 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; + // Check for moral and get the maximum spell level we should use. + 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; + //**************************** SKILL FEATURES **************************** + if(ai_TryAnimalEmpathy(oCreature)) return; + //**************************** CLASS FEATURES **************************** + if(ai_TryBarbarianRageFeat(oCreature)) return; + if(ai_TryBardSongFeat(oCreature)) return; + if(ai_TryTurningTalent(oCreature)) return; + if(GetLocalInt(GetModule(), AI_RULE_SUMMON_COMPANIONS)) + { + if(ai_TrySummonFamiliarTalent(oCreature)) return; + if(ai_TrySummonAnimalCompanionTalent(oCreature)) return; + } + //************************** DEFENSIVE TALENTS *************************** + int nRound = ai_GetCurrentRound(oCreature); + if(ai_TryDefensiveTalents(oCreature, nInMelee, nMaxLevel, nRound)) return; + // ************************** CLASS FEATURES ******************************* + if(ai_TryTurningTalent(oCreature)) 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. + object oTarget; + // ************************** Ranged feat attacks ************************** + if(!GetHasFeatEffect(FEAT_BARBARIAN_RAGE, oCreature) && + (nInMelee < 3 || ai_GetEnemyAttackingMe(oCreature) == OBJECT_INVALID)) + { + if(ai_HasRangedWeaponWithAmmo(oCreature)) + { + // Lets pick off the ranged then nearest targets. + if(!nInMelee) + { + if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature); + if(oTarget == OBJECT_INVALID) oTarget == ai_GetRangedTarget(oCreature); + if(oTarget == OBJECT_INVALID && ai_TryRangedSneakAttack(oCreature, nInMelee)) return; + if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestTarget(oCreature); + } + else + { + if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature, AI_RANGE_MELEE); + if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestTarget(oCreature, AI_RANGE_MELEE); + } + if(oTarget != OBJECT_INVALID) + { + 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(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(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); +} + diff --git a/src/module/nss/ai_ranger.nss b/src/module/nss/ai_ranger.nss new file mode 100644 index 0000000..5878cfb --- /dev/null +++ b/src/module/nss/ai_ranger.nss @@ -0,0 +1,79 @@ +/*//////////////////////////////////////////////////////////////////////////////////////////////////// +// Script Name: ai_ranger +////////////////////////////////////////////////////////////////////////////////////////////////////// + ai script for creatures using the class Ranger. + Need to add ---> 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; + 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; + //**************************** SKILL FEATURES **************************** + if(ai_TryAnimalEmpathy(oCreature)) return; + //**************************** CLASS FEATURES **************************** + if(GetLocalInt(GetModule(), AI_RULE_SUMMON_COMPANIONS) && ai_TrySummonAnimalCompanionTalent(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 ******************************* + object oTarget; + if(ai_CanIUseRangedWeapon(oCreature, nInMelee)) + { + if(ai_HasRangedWeaponWithAmmo(oCreature)) + { + if(!nInMelee) + { + oTarget = ai_GetNearestFavoredEnemyTarget(oCreature); + if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestTarget(oCreature); + } + else + { + oTarget = ai_GetNearestFavoredEnemyTarget(oCreature, AI_RANGE_MELEE); + if(oTarget == OBJECT_INVALID) 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; + oTarget = ai_GetNearestFavoredEnemyTarget(oCreature, AI_RANGE_MELEE); + 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); + } + else ai_SearchForHiddenCreature(oCreature, TRUE); +} diff --git a/src/module/nss/ai_rogue.nss b/src/module/nss/ai_rogue.nss new file mode 100644 index 0000000..81c4500 --- /dev/null +++ b/src/module/nss/ai_rogue.nss @@ -0,0 +1,66 @@ +/*//////////////////////////////////////////////////////////////////////////////////////////////////// +// Script Name: ai_rogue +////////////////////////////////////////////////////////////////////////////////////////////////////// + ai script for creatures using the class Rogue. + 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; + 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; + //************************** 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 ******************************* + object oTarget; + if(ai_CanIUseRangedWeapon(oCreature, nInMelee)) + { + if(ai_HasRangedWeaponWithAmmo(oCreature)) + { + if (ai_TryRangedSneakAttack (oCreature, nInMelee)) return; + oTarget = ai_GetNearestTarget (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 + { + ai_SearchForHiddenCreature(oCreature, TRUE); + return; + } + } + else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return; + } + // ************************* MELEE ATTACKS ******************************* + if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return; + if (ai_TrySneakAttack (oCreature, nInMelee)) 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); +} diff --git a/src/module/nss/ai_shadow.nss b/src/module/nss/ai_shadow.nss new file mode 100644 index 0000000..3d6419f --- /dev/null +++ b/src/module/nss/ai_shadow.nss @@ -0,0 +1,77 @@ +/*//////////////////////////////////////////////////////////////////////////////////////////////////// +// Script Name: ai_shadow +////////////////////////////////////////////////////////////////////////////////////////////////////// + ai script for creatures that are incorporeal. + 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; + // Shadows do not flee! if(nInMelee && ai_MoralCheck()) return; + int nMaxLevel = ai_GetMonsterTalentMaxLevel(oCreature); + //******************* OFFENSIVE AREA OF EFFECT TALENTS ******************* + // Check the battlefield for a group of enemies to shoot a big talent at! + // We are checking here since these opportunities are rare and we need + // to take advantage of them as often as possible. + if(ai_UseCreatureTalent(oCreature, AI_TALENT_INDISCRIMINANT_AOE, nInMelee, nMaxLevel)) return; + if(ai_UseCreatureTalent(oCreature, AI_TALENT_DISCRIMINANT_AOE, nInMelee, nMaxLevel)) return; + //************************** DEFENSIVE TALENTS *************************** + 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 ******************************* + object oTarget; + if(ai_CanIUseRangedWeapon(oCreature, nInMelee)) + { + if(ai_HasRangedWeaponWithAmmo(oCreature)) + { + string sIndex; + 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; + oTarget = ai_GetNearestTargetForMeleeCombat(oCreature, nInMelee); + if(oTarget != OBJECT_INVALID) + { + // If we are using our hands then do a touch attack instead. + if(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND) == OBJECT_INVALID) + { + if(GetItemInSlot(INVENTORY_SLOT_CWEAPON_L) != OBJECT_INVALID) + { + // Randomize so they don't appear synchronized. + float fDelay = IntToFloat(Random(2) + 1); + DelayCommand(fDelay, ActionCastSpellAtObject (769/*Shadow_Attack*/, oTarget, METAMAGIC_ANY, TRUE)); + ai_SetLastAction(oCreature, AI_LAST_ACTION_MELEE_ATK); + SetLocalObject (oCreature, AI_ATTACKED_PHYSICAL, oTarget); + } + } + else ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); + } + else ai_SearchForHiddenCreature(oCreature, TRUE); +} diff --git a/src/module/nss/ai_sorcerer.nss b/src/module/nss/ai_sorcerer.nss new file mode 100644 index 0000000..f1fdcc3 --- /dev/null +++ b/src/module/nss/ai_sorcerer.nss @@ -0,0 +1,61 @@ +/*//////////////////////////////////////////////////////////////////////////////////////////////////// +// Script Name: ai_sorcerer +////////////////////////////////////////////////////////////////////////////////////////////////////// + ai script for creatures using the class Sorcerer. + 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; + 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; + //************************** 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 ***************************** + object oTarget; + 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) + { + ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE); + return; + } + else + { + ai_SearchForHiddenCreature(oCreature, TRUE, OBJECT_INVALID, AI_RANGE_CLOSE); + return; + } + } + else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return; + } + // ************************* MELEE ATTACKS ******************************* + if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return; + oTarget = ai_GetNearestTargetForMeleeCombat(oCreature, nInMelee, FALSE); + // I have a target now lets see if we want to move in! + if(oTarget != OBJECT_INVALID) ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); + else ai_SearchForHiddenCreature(oCreature, TRUE, OBJECT_INVALID, AI_RANGE_CLOSE); +} diff --git a/src/module/nss/ai_taunter.nss b/src/module/nss/ai_taunter.nss new file mode 100644 index 0000000..825d025 --- /dev/null +++ b/src/module/nss/ai_taunter.nss @@ -0,0 +1,78 @@ +/*////////////////////////////////////////////////////////////////////////////// + Script Name: ai_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; + 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; + //**************************** SKILL FEATURES **************************** + if(ai_TryAnimalEmpathy(oCreature)) return; + //**************************** CLASS FEATURES **************************** + if(ai_TryBarbarianRageFeat(oCreature)) return; + if(ai_TryBardSongFeat(oCreature)) return; + if(ai_TryTurningTalent(oCreature)) return; + if(GetLocalInt(GetModule(), AI_RULE_SUMMON_COMPANIONS)) + { + if(ai_TrySummonFamiliarTalent(oCreature)) return; + if(ai_TrySummonAnimalCompanionTalent(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 ***************************** + // We use a bow when we are not in melee, or only 1 enemy with PBS. + object oTarget; + 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; + oTarget = ai_GetNearestTargetForMeleeCombat (oCreature, nInMelee); + if (oTarget != OBJECT_INVALID) + { + if (ai_TryTaunt (oCreature, oTarget)) return; + if (ai_TryMeleeTalents (oCreature, oTarget)) return; + ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); + } + else ai_SearchForHiddenCreature(oCreature, TRUE); +} diff --git a/src/module/nss/ai_wizard.nss b/src/module/nss/ai_wizard.nss new file mode 100644 index 0000000..6baa4c8 --- /dev/null +++ b/src/module/nss/ai_wizard.nss @@ -0,0 +1,63 @@ +/*////////////////////////////////////////////////////////////////////////////// +// Script Name: ai_wizard +//////////////////////////////////////////////////////////////////////////////// + ai script for creatures using the class Wizard. + 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; + 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(GetLocalInt(GetModule(), AI_RULE_SUMMON_COMPANIONS) && ai_TrySummonFamiliarTalent(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 ***************************** + object oTarget; + 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) + { + ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE); + return; + } + else + { + ai_SearchForHiddenCreature(oCreature, TRUE, OBJECT_INVALID, AI_RANGE_CLOSE); + return; + } + } + else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return; + } + // ************************* MELEE ATTACKS ******************************* + if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return; + oTarget = ai_GetNearestTargetForMeleeCombat(oCreature, nInMelee, TRUE); + // I have a target now lets see if we want to move in! + if(oTarget != OBJECT_INVALID) ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); + else ai_SearchForHiddenCreature(oCreature, TRUE, OBJECT_INVALID, AI_RANGE_CLOSE); +} diff --git a/src/module/nss/hc_on_cl_enter.nss b/src/module/nss/hc_on_cl_enter.nss index 3610d99..a6eabfd 100644 --- a/src/module/nss/hc_on_cl_enter.nss +++ b/src/module/nss/hc_on_cl_enter.nss @@ -146,6 +146,7 @@ void main() { if (!preEvent()) return; + object oPC = GetEnteringObject(); object oGear; @@ -159,6 +160,12 @@ void main() int nPKT = GetLocalInt(oMod, "PKTRACKER"); int nDM = GetIsDM(oPC); int nSlot; + + ExecuteScript("0e_onclientload", oPC); + + AddJournalQuestEntry("JRNL_XPCHART", 1, oPC, FALSE, FALSE, FALSE); + AddJournalQuestEntry("JRNL_LA_BUYOFF", 1, oPC, FALSE, FALSE, FALSE); + AddJournalQuestEntry("JRNL_PRC8", 1, oPC, FALSE, FALSE, FALSE); // Strip player corpses on enter. // Could happen if server restarts while carrying one. diff --git a/src/module/nss/inc_spell_track.nss b/src/module/nss/inc_spell_track.nss index 223b22b..954b749 100644 --- a/src/module/nss/inc_spell_track.nss +++ b/src/module/nss/inc_spell_track.nss @@ -14,14 +14,19 @@ Purpose: Tracks each use of a spell, or a feat with an See manual for more about using this with HCR. #*#*#*#*#*#*#**#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#* */ +#include "prc_inc_spells" + void spell_track() { // SPELL TRACKING BEGIN - if(PRCGetSpellCastItem()==OBJECT_INVALID) + if(PRCGetSpellCastItem() == OBJECT_INVALID) { object oW=GetLastSpellCaster(); - if(oW==OBJECT_INVALID) oW=OBJECT_SELF; - string sNm=GetName(oW); + if(oW==OBJECT_INVALID) + { + oW=OBJECT_SELF; + } + string sNm=GetName(oW); string sPC=GetPCPlayerName(oW); int nSp=PRCGetSpellId(); object oMd=GetModule(); @@ -31,3 +36,5 @@ void spell_track() // END SPELL TRACKING } + +//;; void main (){} \ No newline at end of file diff --git a/src/module/nss/mm_prc_spells.nss b/src/module/nss/mm_prc_spells.nss new file mode 100644 index 0000000..4aeb8e0 --- /dev/null +++ b/src/module/nss/mm_prc_spells.nss @@ -0,0 +1,161 @@ +#include "0i_menus" +// Does startup check if the game has just been loaded. +int StartingUp(object oPC); +json ai_CheckToReplaceSpell(json jSpellList, int nClass, int nLevel, int nSlot) +{ + //if(d100() > 49) return jSpellList; + string sSpellTableColumn = Get2DAString("classes", "SpellTableColumn", nClass); + int nRoll = d10() + 1 + nLevel * 10; + int nSpell = StringToInt(Get2DAString("prc_add_spells", sSpellTableColumn, nRoll)); + if(nSpell > 0) + { + //WriteTimestampedLogEntry("mm_prc_spells, 13 nSpell: " + IntToString(nSpell) + + // " nLevel: " + IntToString(nLevel) + " nSlot: " + IntToString(nSlot)); + json jSpellArray = JsonArrayGet(jSpellList, nSlot); + json jSpell = JsonObjectGet(jSpellArray, "Spell"); + jSpell = JsonObjectSet(jSpell, "value", JsonInt(nSpell)); + jSpellArray = JsonObjectSet(jSpellArray, "Spell", jSpell); + return JsonArraySet(jSpellList, nSlot, jSpellArray); + } + return jSpellList; +} +void main() +{ + object oPC = OBJECT_SELF; + if(StartingUp(oPC)) return; + int bChanged, bCreatureChanged, nPosition, nClass, nLevel, nSlot, nMaxSlots; + json jClass, jMemorizedList, jKnownList; + object oModule = GetModule(); + json jCreature = GetLocalJson(oModule, AI_MONSTER_JSON); + object oCreature = GetLocalObject(oModule, AI_MONSTER_OBJECT); + json jClassList = GffGetList(jCreature, "ClassList"); + while(nPosition <= AI_MAX_CLASSES_PER_CHARACTER) + { + nClass = GetClassByPosition(nPosition, oCreature); + if(Get2DAString("classes", "SpellCaster", nClass) == "1") + { + //WriteTimestampedLogEntry("mm_prc_spells, 39 " + GetName(oCreature) + JsonDump(jClassList, 4)); + jClass = JsonArrayGet(jClassList, nPosition - 1); + if(Get2DAString("classes", "MemorizesSpells", nClass) == "1") + { + nLevel = 1; + while(nLevel < 9) + { + jMemorizedList = GffGetList(jClass, "MemorizedList" + IntToString(nLevel)); + if(JsonGetType(jMemorizedList) != JSON_TYPE_NULL) + { + nSlot = 0; + nMaxSlots = GetMemorizedSpellCountByLevel(oCreature, nClass, nLevel); + while(nSlot < nMaxSlots) + { + jMemorizedList = ai_CheckToReplaceSpell(jMemorizedList, nClass, nLevel, nSlot); + nSlot++; + } + //WriteTimestampedLogEntry("nClass: " + IntToString(nClass) + " nLevel: " + IntToString(nLevel) + + // " nSlot: " + IntToString(nSlot) + " jMemorizedList " + JsonDump(jMemorizedList, 4)); + jClass = GffReplaceList(jClass, "MemorizedList" + IntToString(nLevel), jMemorizedList); + bChanged = TRUE; + } + nLevel++; + } + } + else + { + nLevel = 1; + while(nLevel < 9) + { + jKnownList = GffGetList(jClass, "KnownList" + IntToString(nLevel)); + if(JsonGetType(jMemorizedList) != JSON_TYPE_NULL) + { + nSlot = 0; + nMaxSlots = GetKnownSpellCount(oCreature, nClass, nLevel); + while(nSlot < nMaxSlots) + { + jKnownList = ai_CheckToReplaceSpell(jKnownList, nClass, nLevel, nSlot); + nSlot++; + } + jClass = GffReplaceList(jClass, "KnownList" + IntToString(nLevel), jKnownList); + bChanged = TRUE; + } + nLevel++; + } + } + if(bChanged) + { + //WriteTimestampedLogEntry("0i_module, 87 " + GetName(oCreature) + " jClass: " + JsonDump(jClass, 4)); + jClassList = JsonArraySet(jClassList, nPosition - 1, jClass); + //if(AI_DEBUG) ai_Debug("0i_module, 89 " + GetName(oCreature) + " jClassList: " + JsonDump(jClassList, 4)); + jCreature = GffReplaceList(jCreature, "ClassList", jClassList); + bCreatureChanged = TRUE; + bChanged = FALSE; + } + } + nPosition++; + } + if(bCreatureChanged) + { + //WriteTimestampedLogEntry("mm_prc_spells, 99 " + GetName(oCreature) + " jClassList: " + JsonDump(jClassList, 4)); + SetLocalJson(oModule, AI_MONSTER_JSON, jCreature); + SetLocalInt(oModule, AI_MONSTER_CHANGED, TRUE); + } +} +int PRCSpellsSetup(object oPC) +{ + // Check to make sure prc_add_spells.2da is loaded. + if(ResManGetAliasFor("prc_add_spells", RESTYPE_2DA) == "") + { + SendMessageToPC(oPC, "prc_add_spells.2da is not loaded! Make sure it is in the override or development folder."); + return FALSE; + } + // Check to make sure PRC is loaded. + if(!GetLocalInt(GetModule(), AI_USING_PRC)) + { + SendMessageToPC(oPC, "PRC is not being used. PRC must be active for this mod to work."); + return FALSE; + } + return TRUE; +} +void SetMonsterModJson(object oPC) +{ + object oModule = GetModule(); + json jMonsterMods = GetLocalJson(oModule, AI_MONSTER_MOD_JSON); + if(JsonGetType(jMonsterMods) == JSON_TYPE_NULL) jMonsterMods = JsonArray(); + int nIndex; + string sMonsterMod = JsonGetString(JsonArrayGet(jMonsterMods, nIndex)); + while(sMonsterMod != "") + { + if(sMonsterMod == "mm_prc_spells") return; + sMonsterMod = JsonGetString(JsonArrayGet(jMonsterMods, ++nIndex)); + } + jMonsterMods = JsonArrayInsert(jMonsterMods, JsonString("mm_prc_spells")); + SetLocalJson(oModule, AI_MONSTER_MOD_JSON, jMonsterMods); + ai_SendMessages("mm_prc_spells loaded! Monsters will be using PRC spells.", AI_COLOR_YELLOW, oPC); +} +int StartingUp(object oPC) +{ + if(!PRCSpellsSetup(oPC)) + { + SendMessageToPC(oPC, "mm_prc_spells monster mod has failed to load due to an error."); + // Return -1 in AI_PLUGIN_SET to tell PEPS that we failed to load. + SetLocalInt(oPC, AI_PLUGIN_SET, -1); + return TRUE; + } + if(GetLocalInt(oPC, AI_ADD_PLUGIN)) + { + json jPlugin = JsonArray(); + jPlugin = JsonArrayInsert(jPlugin, JsonString("mm_prc_spells")); + jPlugin = JsonArrayInsert(jPlugin, JsonInt(3)); + jPlugin = JsonArrayInsert(jPlugin, JsonString("Monsters will use PRC spells!")); + jPlugin = JsonArrayInsert(jPlugin, JsonString("")); + json jPlugins = GetLocalJson(oPC, AI_JSON_PLUGINS); + jPlugins = JsonArrayInsert(jPlugins, jPlugin); + SetLocalJson(oPC, AI_JSON_PLUGINS, jPlugin); + SetLocalInt(oPC, AI_PLUGIN_SET, TRUE); + SetMonsterModJson(oPC); + return TRUE; + } + if(!GetLocalInt(oPC, AI_STARTING_UP)) return FALSE; + SetMonsterModJson(oPC); + return TRUE; +} + diff --git a/src/module/nss/nw_c2_default1.nss b/src/module/nss/nw_c2_default1.nss index 62ac86b..4801a4d 100644 --- a/src/module/nss/nw_c2_default1.nss +++ b/src/module/nss/nw_c2_default1.nss @@ -1,108 +1,94 @@ -//::////////////////////////////////////////////////// -//:: NW_C2_DEFAULT1 -/* - Default OnHeartbeat script for NPCs. - - This script causes NPCs to perform default animations - while not otherwise engaged. - - This script duplicates the behavior of the default - script and just cleans up the code and removes - redundant conditional checks. - - */ -//::////////////////////////////////////////////////// -//:: Copyright (c) 2002 Floodgate Entertainment -//:: Created By: Naomi Novik -//:: Created On: 12/22/2002 -//::////////////////////////////////////////////////// - -#include "nw_i0_generic" -#include "prc_inc_spells" - +/*////////////////////////////////////////////////////////////////////////////// + Script: nw_c2_default1 + Programmer: Philos +//////////////////////////////////////////////////////////////////////////////// + Monster OnHeartbeat script; + This will usually fire every 6 seconds (1 game round). +*/////////////////////////////////////////////////////////////////////////////// +#include "0i_module" void main() { - - // * if not runnning normal or better Ai then exit for performance reasons - if (GetAILevel() == AI_LEVEL_VERY_LOW) return; + // If not runnning normal or better AI then exit for performance reasons + if (GetAILevel(OBJECT_SELF) == AI_LEVEL_VERY_LOW) return; ExecuteScript("prc_npc_hb", OBJECT_SELF); - - // Buff ourselves up right away if we should - if(GetSpawnInCondition(NW_FLAG_FAST_BUFF_ENEMY)) - { - // This will return TRUE if an enemy was within 40.0 m - // and we buffed ourselves up instantly to respond -- - // simulates a spellcaster with protections enabled - // already. - if(TalentAdvancedBuff(40.0)) - { - // This is a one-shot deal - SetSpawnInCondition(NW_FLAG_FAST_BUFF_ENEMY, FALSE); - - // This return means we skip sending the user-defined - // heartbeat signal in this one case. - return; - } - } - - - if(PRCGetHasEffect(EFFECT_TYPE_SLEEP)) + + object oCreature = OBJECT_SELF; + if(AI_DEBUG) ai_Debug("nw_c2_default1", "16", GetName(oCreature) + " Heartbeat." + + " OnSpawn: " + IntToString(GetLocalInt(oCreature, AI_ONSPAWN_EVENT))); + // We run our OnSpawn in the heartbeat so the creator can use the original + // OnSpawn for their own use. If we have to recreate the creature then we + // skip the rest of the heartbeat since this version is being destroyed! + if(ai_OnMonsterSpawn(oCreature)) return; + if(AI_DEBUG) ai_Debug("nw_c2_default1", "16", GetName(oCreature) + " Heartbeat." + + " Searching: " + IntToString(GetLocalInt(oCreature, AI_AM_I_SEARCHING))); + if(ai_GetHasEffectType(oCreature, EFFECT_TYPE_SLEEP)) { // If we're asleep and this is the result of sleeping // at night, apply the floating 'z's visual effect // every so often - if(GetSpawnInCondition(NW_FLAG_SLEEPING_AT_NIGHT)) { effect eVis = EffectVisualEffect(VFX_IMP_SLEEP); if(d10() > 6) { - ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, OBJECT_SELF); + ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oCreature); } } } - - // If we have the 'constant' waypoints flag set, walk to the next - // waypoint. - else if ( GetWalkCondition(NW_WALK_FLAG_CONSTANT) ) - { - WalkWayPoints(); - } - - // Check to see if we should be playing default animations - // - make sure we don't have any current targets - else if ( !GetIsObjectValid(GetAttemptedAttackTarget()) - && !GetIsObjectValid(GetAttemptedSpellTarget()) - // && !GetIsPostOrWalking()) - && !GetIsObjectValid(GetNearestSeenEnemy())) - { - if (GetBehaviorState(NW_FLAG_BEHAVIOR_SPECIAL) || GetBehaviorState(NW_FLAG_BEHAVIOR_OMNIVORE) || - GetBehaviorState(NW_FLAG_BEHAVIOR_HERBIVORE)) - { - // This handles special attacking/fleeing behavior - // for omnivores & herbivores. - DetermineSpecialBehavior(); - } - else if (!IsInConversation(OBJECT_SELF)) - { - if (GetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS) - || GetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS_AVIAN) - || GetIsEncounterCreature()) - { - PlayMobileAmbientAnimations(); - } - else if (GetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS)) - { - PlayImmobileAmbientAnimations(); - } - } - } - - // Send the user-defined event signal if specified + // Send the user-defined event signal if specified here so it doesn't get skipped. if(GetSpawnInCondition(NW_FLAG_HEARTBEAT_EVENT)) { - SignalEvent(OBJECT_SELF, EventUserDefined(EVENT_HEARTBEAT)); + SignalEvent(oCreature, EventUserDefined(EVENT_HEARTBEAT)); } + if(ai_GetIsBusy(oCreature) || ai_Disabled(oCreature) || + GetLocalInt(oCreature, AI_AM_I_SEARCHING)) return; + if(ai_GetIsInCombat(oCreature)) + { + if(ai_GetBehaviorState(NW_FLAG_BEHAVIOR_HERBIVORE)) + { + object oTarget = ai_GetNearestEnemy(oCreature, 1, 7, 7, -1, -1, TRUE); + if(GetDistanceBetween(oCreature, oTarget) <= 6.0) + { + if(GetLevelByClass(CLASS_TYPE_DRUID, oTarget) == 0 && GetLevelByClass(CLASS_TYPE_RANGER, oTarget) == 0) + { + SetLocalString(oCreature, AI_COMBAT_SCRIPT, "ai_coward"); + ActionMoveAwayFromObject(oTarget, TRUE, AI_RANGE_LONG); + return; + } + } + } + ai_DoMonsterCombatRound(oCreature); + return; + } + if(ai_CheckForCombat(oCreature, TRUE)) return; + // If we have not set up our talents then we need to check to see if we should. + if(!GetLocalInt(oCreature, AI_TALENTS_SET)) + { + // We setup our talents when a PC gets withing Battlefield range 40.0 meters. + object oPC = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC, oCreature, 1, CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY); + if(oPC != OBJECT_INVALID && GetDistanceBetween(oCreature, oPC) <= AI_RANGE_BATTLEFIELD) + { + if(AI_DEBUG) ai_Debug("nw_c2_default1", "72", GetName(oCreature) + " is " + + FloatToString(GetDistanceBetween(oCreature, oPC), 0, 2) + " from " + GetName(oPC)); + if(AI_DEBUG) ai_Debug("nw_c2_default1", "74", GetName(oCreature) + " is Setting Creature Talents and buffing!"); + ai_SetupMonsterBuffTargets(oCreature); + // To save steps and time we set the talents while we buff! + ai_SetCreatureTalents(oCreature, TRUE); + ai_ClearBuffTargets(oCreature, "AI_ALLY_TARGET_"); + } + } + if(!IsInConversation (oCreature)) + { + if(GetWalkCondition(NW_WALK_FLAG_CONSTANT)) WalkWayPoints(); + if(GetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS)) PlayMobileAmbientAnimations_NonAvian(); + else if(GetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS_AVIAN)) PlayMobileAmbientAnimations_Avian(); + else if(GetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS)) PlayImmobileAmbientAnimations(); + else if(GetLocalInt(GetModule(), AI_RULE_WANDER) && GetStandardFactionReputation(STANDARD_FACTION_HOSTILE, oCreature) > 89) + { + ai_AmbientAnimations(); + } + } + if(ai_TryHealing(oCreature, oCreature)) return; } diff --git a/src/module/nss/nw_c2_default2.nss b/src/module/nss/nw_c2_default2.nss index 34499fd..b7d5e07 100644 --- a/src/module/nss/nw_c2_default2.nss +++ b/src/module/nss/nw_c2_default2.nss @@ -1,166 +1,138 @@ -//::////////////////////////////////////////////////// -//:: NW_C2_DEFAULT2 -/* - Default OnPerception event handler for NPCs. - - Handles behavior when perceiving a creature for the - first time. - */ -//::////////////////////////////////////////////////// - -#include "nw_i0_generic" -#include "prc_inc_spells" - +/*////////////////////////////////////////////////////////////////////////////// + Script: nw_c2_default2 + Programmer: Philos +//////////////////////////////////////////////////////////////////////////////// + Monster OnPerception script when not in combat; + There are 4 types of perception - Heard, Inaudible, Seen, Vanished. + Only one type will ever be true in an event trigger. + The order of trigger is Heard/Seen and Inaudible/Vanished. + There are two states of percepion Heard and Seen. + These states can be set at the same time thus a heard event can see the creature. + Fires when ever one of these states changes from TRUE to FALSE or FALSE to TRUE. +*/////////////////////////////////////////////////////////////////////////////// +#include "0i_associates" void main() { - // * if not runnning normal or better Ai then exit for performance reasons - if (GetAILevel() == AI_LEVEL_VERY_LOW) return; - + // * if not runnning normal or better AI then exit for performance reasons + //if (GetAILevel() == AI_LEVEL_VERY_LOW) return; + object oCreature = OBJECT_SELF; ExecuteScript("prc_npc_percep", OBJECT_SELF); - - object oPercep = GetLastPerceived(); + if(AI_DEBUG) ai_Debug("nw_c2_default2", "19", "AI_ONSPAWN_EVENT: " + IntToString(GetLocalInt(oCreature, AI_ONSPAWN_EVENT))); + if(!GetLocalInt(oCreature, AI_ONSPAWN_EVENT)) return; + if(GetLastPerceptionSeen()) + { + if(AI_DEBUG) ai_Debug("nw_c2_default2", "22", GetName(oCreature) + " sees " + + GetName(GetLastPerceived()) + " Distance: " + + FloatToString(GetDistanceBetween(GetLastPerceived(), oCreature), 0, 2) + "."); + } + if(GetLastPerceptionHeard()) + { + if(AI_DEBUG) ai_Debug("nw_c2_default2", "28", GetName(oCreature) + " heard " + + GetName(GetLastPerceived()) + " Distance: " + + FloatToString(GetDistanceBetween(GetLastPerceived(), oCreature), 0, 2) + "."); + } + if(GetLastPerceptionVanished ()) + { + if(AI_DEBUG) ai_Debug("nw_c2_default2", "34", GetName(oCreature) + " lost sight of " + + GetName(GetLastPerceived ()) + "."); + } + // We do nothing on Inaudibles so drop out early! + if(GetLastPerceptionInaudible()) + { + if(AI_DEBUG) ai_Debug("nw_c2_default2", "41", GetName(oCreature) + " lost sound of " + + GetName(GetLastPerceived()) + "."); + return; + } + object oLastPerceived = GetLastPerceived(); + if(AI_DEBUG) ai_Debug("nw_c2_default2", "45", "Dead? " + IntToString(GetIsDead(oLastPerceived)) + + " Enemy? " + IntToString(GetIsEnemy(oLastPerceived, oCreature))); + if(ai_Disabled(oCreature)) return; + if(GetIsDead(oLastPerceived)) return; int bSeen = GetLastPerceptionSeen(); - int bHeard = GetLastPerceptionHeard(); - if (bHeard == FALSE) + // This will cause all NPC's to speak their one-liner conversation + // on perception even if they are already in combat. + if(GetIsPC(oLastPerceived) && bSeen) { - // Has someone vanished in front of me? - bHeard = GetLastPerceptionVanished(); - } - - // This will cause the NPC to speak their one-liner - // conversation on perception even if they are already - // in combat. - if(GetSpawnInCondition(NW_FLAG_SPECIAL_COMBAT_CONVERSATION) - && GetIsPC(oPercep) - && bSeen) - { - SpeakOneLinerConversation(); - } - - // March 5 2003 Brent - // Had to add this section back in, since modifications were not taking this specific - // example into account -- it made invisibility basically useless. - //If the last perception event was hearing based or if someone vanished then go to search mode - if ((GetLastPerceptionVanished()) && GetIsEnemy(GetLastPerceived())) - { - object oGone = GetLastPerceived(); - if((GetAttemptedAttackTarget() == GetLastPerceived() || - GetAttemptedSpellTarget() == GetLastPerceived() || - GetAttackTarget() == GetLastPerceived()) && GetArea(GetLastPerceived()) != GetArea(OBJECT_SELF)) + if(GetSpawnInCondition(NW_FLAG_SPECIAL_COMBAT_CONVERSATION)) { - ClearAllActions(); - DetermineCombatRound(); + SpeakOneLinerConversation(); } } - - // This section has been heavily revised while keeping the - // pre-existing behavior: - // - If we're in combat, keep fighting. - // - If not and we've perceived an enemy, start to fight. - // Even if the perception event was a 'vanish', that's - // still what we do anyway, since that will keep us - // fighting any visible targets. - // - If we're not in combat and haven't perceived an enemy, - // see if the perception target is a PC and if we should - // speak our attention-getting one-liner. - if (GetIsInCombat(OBJECT_SELF)) + if(GetIsEnemy(oLastPerceived, oCreature)) { - // don't do anything else, we're busy - //MyPrintString("GetIsFighting: TRUE"); - - } - // * BK FEB 2003 Only fight if you can see them. DO NOT RELY ON HEARING FOR ENEMY DETECTION - else if (GetIsEnemy(oPercep) && bSeen) - { // SpawnScriptDebugger(); - //MyPrintString("GetIsEnemy: TRUE"); - // We spotted an enemy and we're not already fighting - if(!PRCGetHasEffect(EFFECT_TYPE_SLEEP)) { - if(GetBehaviorState(NW_FLAG_BEHAVIOR_SPECIAL)) + // ************************** ENEMY SEEN ******************************* + if(bSeen) + { + // If the creature we are perceiving was our invisible creature then + // remove that they are invisible. + if(oLastPerceived == GetLocalObject(oCreature, AI_IS_INVISIBLE)) { - //MyPrintString("DetermineSpecialBehavior"); - DetermineSpecialBehavior(); - } else - { - //MyPrintString("DetermineCombatRound"); - SetFacingPoint(GetPosition(oPercep)); - SpeakString("NW_I_WAS_ATTACKED", TALKVOLUME_SILENT_TALK); - DetermineCombatRound(); + DeleteLocalObject(oCreature, AI_IS_INVISIBLE); } + ai_MonsterEvaluateNewThreat(oCreature, oLastPerceived, AI_I_SEE_AN_ENEMY); } + // ************************** ENEMY HEARD ****************************** + else if(GetLastPerceptionHeard()) + { + ai_MonsterEvaluateNewThreat(oCreature, oLastPerceived, AI_I_HEARD_AN_ENEMY); + } + // ************************** ENEMY VANISHED *************************** + else if(GetLastPerceptionVanished()) + { + // Lets keep a mental note of the invisible creature. + SetLocalObject(oCreature, AI_IS_INVISIBLE, oLastPerceived); + if(AI_DEBUG) ai_Debug("0e_c2_2_percept", "82", " We saw " + GetName(oLastPerceived) + " disappear!"); + if(ai_GetIsBusy(oCreature)) return; + // If in combat check to see if our target disappeared. + // If they have and we are not in melee with them then reevaluate combat + // since we lost our target. + if(ai_GetIsInCombat(oCreature)) + { + if(AI_DEBUG) ai_Debug("nw_c2_default2", "89", "Is this our target? " + + IntToString(ai_GetAttackedTarget(oCreature, TRUE, TRUE) == oLastPerceived)); + if(ai_GetAttackedTarget(oCreature, TRUE, TRUE) == oLastPerceived) + { + ai_DoMonsterCombatRound(oCreature); + } + } + // We are not in combat so lets move to that location and check it out. + else ActionMoveToLocation(GetLocation(oLastPerceived), TRUE); + // we use to move to the object but thats a bit creepy! + //else ActionMoveToObject(oLastPerceived, TRUE, AI_RANGE_CLOSE); + } + // ************************ ENEMY INAUDIBLE***************************** + // Not used. } else { - if (bSeen) + // ************************ NON_ENEMY SEEN ***************************** + if(bSeen) { - //MyPrintString("GetLastPerceptionSeen: TRUE"); - if(GetBehaviorState(NW_FLAG_BEHAVIOR_SPECIAL)) { - DetermineSpecialBehavior(); - } else if (GetSpawnInCondition(NW_FLAG_SPECIAL_CONVERSATION) - && GetIsPC(oPercep)) + if(ai_GetBehaviorState(NW_FLAG_BEHAVIOR_SPECIAL)) ai_DetermineSpecialBehavior(oCreature); + else if(GetSpawnInCondition(NW_FLAG_SPECIAL_CONVERSATION) && GetIsPC(oLastPerceived)) { - // The NPC will speak their one-liner conversation - // This should probably be: - // SpeakOneLinerConversation(oPercep); - // instead, but leaving it as is for now. - ActionStartConversation(OBJECT_SELF); + ActionStartConversation(oCreature); } } - else - // * July 14 2003: Some minor reactions based on invisible creatures being nearby - if (bHeard && GetIsEnemy(oPercep)) - { - // SpeakString("vanished"); - // * don't want creatures wandering too far after noises - if (GetDistanceToObject(oPercep) <= 7.0) - { -// if (GetHasSpell(SPELL_TRUE_SEEING) == TRUE) - if (GetHasSpell(SPELL_TRUE_SEEING)) - { - ActionCastSpellAtObject(SPELL_TRUE_SEEING, OBJECT_SELF); - } - else -// if (GetHasSpell(SPELL_SEE_INVISIBILITY) == TRUE) - if (GetHasSpell(SPELL_SEE_INVISIBILITY)) - { - ActionCastSpellAtObject(SPELL_SEE_INVISIBILITY, OBJECT_SELF); - } - else -// if (GetHasSpell(SPELL_INVISIBILITY_PURGE) == TRUE) - if (GetHasSpell(SPELL_INVISIBILITY_PURGE)) - { - ActionCastSpellAtObject(SPELL_INVISIBILITY_PURGE, OBJECT_SELF); - } - else - { - ActionPlayAnimation(ANIMATION_FIREFORGET_HEAD_TURN_LEFT, 0.5); - ActionPlayAnimation(ANIMATION_FIREFORGET_HEAD_TURN_RIGHT, 0.5); - ActionPlayAnimation(ANIMATION_FIREFORGET_PAUSE_SCRATCH_HEAD, 0.5); - } - } - } - - // activate ambient animations or walk waypoints if appropriate - if (!IsInConversation(OBJECT_SELF)) { - if (GetIsPostOrWalking()) { - WalkWayPoints(); - } else if (GetIsPC(oPercep) && - (GetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS) - || GetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS_AVIAN) - || GetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS) - || GetIsEncounterCreature())) - { - SetAnimationCondition(NW_ANIM_FLAG_IS_ACTIVE); - } - } } - + if(!IsInConversation(oCreature)) + { + if(GetIsPostOrWalking()) + { + WalkWayPoints(); + } + else if(GetIsPC(oLastPerceived) && + (GetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS) || + GetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS_AVIAN) || + GetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS) || + GetIsEncounterCreature())) + { + SetAnimationCondition(NW_ANIM_FLAG_IS_ACTIVE); + } + } // Send the user-defined event if appropriate - if(GetSpawnInCondition(NW_FLAG_PERCIEVE_EVENT) && GetLastPerceptionSeen()) + if(GetSpawnInCondition(NW_FLAG_PERCIEVE_EVENT) && bSeen) { SignalEvent(OBJECT_SELF, EventUserDefined(EVENT_PERCEIVE)); } } - - - - diff --git a/src/module/nss/nw_c2_default3.nss b/src/module/nss/nw_c2_default3.nss index 767913f..567b327 100644 --- a/src/module/nss/nw_c2_default3.nss +++ b/src/module/nss/nw_c2_default3.nss @@ -1,45 +1,70 @@ -// HCR v3.2.0 - Added code so creatures would stop attacking dying PC's. -//:://////////////////////////////////////////////////////////////////////////// -//:: FileName: NW_C2_Default3 -//:://////////////////////////////////////////////////////////////////////////// -/* - Calls the end of combat script every round -*/ -//:://////////////////////////////////////////////////////////////////////////// -//:: Created By: Preston Watamaniuk -//:: Created On: Oct 16, 2001 -//:://////////////////////////////////////////////////////////////////////////// -#include "NW_I0_GENERIC" -//:://////////////////////////////////////////////////////////////////////////// +/*////////////////////////////////////////////////////////////////////////////// + Script: nw_c2_default3 + Programmer: Philos +//////////////////////////////////////////////////////////////////////////////// + Monster OnCombatRoundEnd event script; + 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() { - ExecuteScript("prc_npc_combat", OBJECT_SELF); - - // Determine current target. - object oTarget = GetAttackTarget(); - if (!GetIsObjectValid(oTarget)) + object oCreature = OBJECT_SELF; + ExecuteScript("prc_npc_combat", OBJECT_SELF); + if(AI_DEBUG) ai_Debug("nw_c2_default3", "20", GetName(oCreature) + " ends combat round." + + " Current action: " + IntToString(GetCurrentAction(oCreature))); + if(GetSpawnInCondition(NW_FLAG_END_COMBAT_ROUND_EVENT)) { - oTarget = GetAttemptedAttackTarget(); - if (!GetIsObjectValid(oTarget)) - oTarget = GetAttemptedSpellTarget(); - } - - // If the current target is dead or dying then look for a new one. - if (GetIsObjectValid(oTarget) && GetIsDead(oTarget)) - { - ClearAllActions(); - DetermineCombatRound(); - } - else if (GetBehaviorState(NW_FLAG_BEHAVIOR_SPECIAL)) - { - DetermineSpecialBehavior(); - } - else if (!GetSpawnInCondition(NW_FLAG_SET_WARNINGS)) - { - DetermineCombatRound(); - } - - if (GetSpawnInCondition(NW_FLAG_END_COMBAT_ROUND_EVENT)) SignalEvent(OBJECT_SELF, EventUserDefined(1003)); + } + if(ai_Disabled(oCreature)) return; + // 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); + } + int nAction = GetCurrentAction(oCreature); + if(AI_DEBUG) ai_Debug("nw_c2_default3", "37", "nAction: " + IntToString(nAction)); + switch(nAction) + { + // These actions are uninteruptable. + case ACTION_MOVETOPOINT : + case ACTION_CASTSPELL : + case ACTION_ITEMCASTSPELL : + case ACTION_COUNTERSPELL : return; + // Might be doing a special action that is not a defined action. + case ACTION_INVALID : + { + int nCombatWait = GetLocalInt(oCreature, AI_COMBAT_WAIT_IN_SECONDS); + if(AI_DEBUG) ai_Debug("nw_c2_default3", "49", "nCombatWait: " + IntToString(nCombatWait)); + if(nCombatWait) + { + if(ai_IsInCombatRound(oCreature, nCombatWait)) return; + DeleteLocalInt(oCreature, AI_COMBAT_WAIT_IN_SECONDS); + } + } + // We always want to interupt an attack action at the end of a round. + //case ACTION_ATTACKOBJECT : + } + if(ai_GetIsInCombat(oCreature)) + { + ai_DoAssociateCombatRound (oCreature); + return; + } + if(ai_GetBehaviorState(NW_FLAG_BEHAVIOR_SPECIAL)) ai_DetermineSpecialBehavior(oCreature); } -//:://////////////////////////////////////////////////////////////////////////// + + + + diff --git a/src/module/nss/nw_c2_default4.nss b/src/module/nss/nw_c2_default4.nss index 24ec6d8..cd1f616 100644 --- a/src/module/nss/nw_c2_default4.nss +++ b/src/module/nss/nw_c2_default4.nss @@ -1,68 +1,70 @@ -//:://///////////////////////////////////////////// -//:: SetListeningPatterns -//:: NW_C2_DEFAULT4 -//:: Copyright (c) 2001 Bioware Corp. -//::////////////////////////////////////////////// -/* - Determines the course of action to be taken - by the generic script after dialogue or a - shout is initiated. -*/ -//::////////////////////////////////////////////// -//:: Created By: Preston Watamaniuk -//:: Created On: Oct 24, 2001 -//::////////////////////////////////////////////// - -#include "NW_I0_GENERIC" - +/*////////////////////////////////////////////////////////////////////////////// + Script: 0e_c2_4_convers + Programmer: Philos +//////////////////////////////////////////////////////////////////////////////// + Monster OnConversation; + Fires when oCreature has been clicked on for conversation. + Fires when oCreature hears a shout from another creature. + If SetListening is FALSE then oCreature will not "hear" anything. +*/////////////////////////////////////////////////////////////////////////////// +#include "0i_associates" +void ai_MonsterCommands(object oCreature, object oSpeaker, int nMatch); void main() { - int nMatch = GetListenPatternNumber(); - object oShouter = GetLastSpeaker(); - object oIntruder; - + object oCreature = OBJECT_SELF; ExecuteScript("prc_npc_conv", OBJECT_SELF); - ExecuteScript("dmfi_voice_exe", OBJECT_SELF); - - if (nMatch == -1 && GetIsPC(oShouter) &&(GetLocalInt(GetModule(), "dmfi_AllMute") || GetLocalInt(OBJECT_SELF, "dmfi_Mute"))) + if(AI_DEBUG) ai_Debug("nw_c2_default4", "15", GetName(oCreature) + " listens " + + IntToString(GetListenPatternNumber()) + " to " + GetName(GetLastSpeaker()) + "." + + " AI_AM_I_SEARCHING: " + IntToString(GetLocalInt(oCreature, AI_AM_I_SEARCHING))); + if(ai_GetIsBusy(oCreature) || ai_Disabled(oCreature) || GetLocalInt(oCreature, AI_AM_I_SEARCHING)) return; + if(ai_GetIsInCombat(oCreature)) { - SendMessageToAllDMs(GetName(oShouter) + " is trying to speak to a muted NPC, " + GetName(OBJECT_SELF) + ", in area " + GetName(GetArea(OBJECT_SELF))); - SendMessageToPC(oShouter, "This NPC is muted. A DM will be here shortly."); + ai_DoMonsterCombatRound(oCreature); + return; } - else if (nMatch == -1 && GetCommandable(OBJECT_SELF) && !GetLocalInt(GetModule(), "dmfi_AllMute") && !GetLocalInt(OBJECT_SELF, "dmfi_Mute")) + object oLastSpeaker = GetLastSpeaker(); + int nMatch = GetListenPatternNumber(); + if(nMatch != -1) { - SetLocalObject(oShouter, "hls_MyNPCSpeaker", OBJECT_SELF); - ClearAllActions(); + if(GetFactionEqual(oLastSpeaker, oCreature)) ai_MonsterCommands(oCreature, oLastSpeaker, nMatch); + } + else + { + ai_ClearCreatureActions(); BeginConversation(); } - else if(nMatch != -1 && GetIsObjectValid(oShouter) && !GetIsPC(oShouter) && GetIsFriend(oShouter)) - { - if(nMatch == 4) - { - oIntruder = GetLocalObject(oShouter, "NW_BLOCKER_INTRUDER"); - } - else if (nMatch == 5) - { - oIntruder = GetLastHostileActor(oShouter); - if(!GetIsObjectValid(oIntruder)) - { - oIntruder = GetAttemptedAttackTarget(); - if(!GetIsObjectValid(oIntruder)) - { - oIntruder = GetAttemptedSpellTarget(); - if(!GetIsObjectValid(oIntruder)) - { - oIntruder = OBJECT_INVALID; - } - } - } - } - RespondToShout(oShouter, nMatch, oIntruder); - } - - + // Send the user-defined event if appropriate if(GetSpawnInCondition(NW_FLAG_ON_DIALOGUE_EVENT)) { - SignalEvent(OBJECT_SELF, EventUserDefined(1004)); + SignalEvent(OBJECT_SELF, EventUserDefined(EVENT_DIALOGUE)); } } +void ai_MonsterCommands(object oCreature, object oSpeaker, int nMatch) +{ + object oTarget = GetLocalObject(oSpeaker, AI_MY_TARGET); + if(nMatch == AI_ALLY_SEES_AN_ENEMY || nMatch == AI_ALLY_HEARD_AN_ENEMY) + { + if(AI_DEBUG) ai_Debug("nw_c2_default4", "46", GetName(oCreature) + " heard " + + GetName(oSpeaker) + " has seen an enemy!"); + if(ai_CanIAttack(oCreature)) ai_FindTheEnemy(oCreature, oSpeaker, oTarget, TRUE); + } + else if(nMatch == AI_ALLY_ATKED_BY_WEAPON || + nMatch == AI_ALLY_ATKED_BY_SPELL) + { + if(AI_DEBUG) ai_Debug("nw_c2_default4", "53", GetName(oCreature) + " heard " + + GetName(oSpeaker) + " has been attacked by " + + GetName(GetLocalObject(oSpeaker, AI_MY_TARGET)) + "!"); + if(ai_CanIAttack(oCreature)) ai_FindTheEnemy(oCreature, oSpeaker, oTarget, TRUE); + } + else if(nMatch == AI_ALLY_IS_WOUNDED) + { + if(AI_DEBUG) ai_Debug("nw_c2_default4", "60", GetName(oCreature) + " heard " + + GetName(oSpeaker) + " is wounded!"); + if(ai_GetIsInCombat(oCreature)) ai_TryHealingTalent(oCreature, ai_GetNumOfEnemiesInRange(oCreature), oSpeaker); + else ai_TryHealing(oCreature, oSpeaker); + } + /*else if(nMatch == AI_ALLY_IS_DEAD) + { + } */ +} + diff --git a/src/module/nss/nw_c2_default5.nss b/src/module/nss/nw_c2_default5.nss index d6e2e63..acc3b3e 100644 --- a/src/module/nss/nw_c2_default5.nss +++ b/src/module/nss/nw_c2_default5.nss @@ -1,71 +1,37 @@ -//:://///////////////////////////////////////////// -//:: Default On Attacked -//:: NW_C2_DEFAULT5 -//:: Copyright (c) 2001 Bioware Corp. -//::////////////////////////////////////////////// -/* - If already fighting then ignore, else determine - combat round -*/ -//::////////////////////////////////////////////// -//:: Created By: Preston Watamaniuk -//:: Created On: Oct 16, 2001 -//::////////////////////////////////////////////// -//::////////////////////////////////////////////// -//:: Modified By: Deva Winblood -//:: Modified On: Jan 4th, 2008 -//:: Added Support for Mounted Combat Feat Support -//::////////////////////////////////////////////// - -#include "nw_i0_generic" - +/*////////////////////////////////////////////////////////////////////////////// + Script: nw_c2_default5 + Programmer: Philos +//////////////////////////////////////////////////////////////////////////////// + Monster OnPhysicalAttacked event script; + Fires for all physical attacks, claws, weapons, fists, bow, etc. + Fires for taunt skill, animal empathy skill. +*/////////////////////////////////////////////////////////////////////////////// +#include "0i_actions" void main() { + object oCreature = OBJECT_SELF; ExecuteScript("prc_npc_physatt", OBJECT_SELF); - - if (!GetLocalInt(GetModule(),"X3_NO_MOUNTED_COMBAT_FEAT")) - { // set variables on target for mounted combat - SetLocalInt(OBJECT_SELF,"bX3_LAST_ATTACK_PHYSICAL",TRUE); - SetLocalInt(OBJECT_SELF,"nX3_HP_BEFORE",GetCurrentHitPoints(OBJECT_SELF)); - } // set variables on target for mounted combat - - if(GetFleeToExit()) { - // Run away! - ActivateFleeToExit(); - } else if (GetSpawnInCondition(NW_FLAG_SET_WARNINGS)) { - // We give an attacker one warning before we attack - // This is not fully implemented yet - SetSpawnInCondition(NW_FLAG_SET_WARNINGS, FALSE); - - //Put a check in to see if this attacker was the last attacker - //Possibly change the GetNPCWarning function to make the check - } else { - object oAttacker = GetLastAttacker(); - if (!GetIsObjectValid(oAttacker)) { - // Don't do anything, invalid attacker - - } else if (!GetIsFighting(OBJECT_SELF)) { - // We're not fighting anyone else, so - // start fighting the attacker - if(GetBehaviorState(NW_FLAG_BEHAVIOR_SPECIAL)) { - SetSummonHelpIfAttacked(); - DetermineSpecialBehavior(oAttacker); - } else if (GetArea(oAttacker) == GetArea(OBJECT_SELF)) { - SetSummonHelpIfAttacked(); - DetermineCombatRound(oAttacker); - } - - //Shout Attack my target, only works with the On Spawn In setup - SpeakString("NW_ATTACK_MY_TARGET", TALKVOLUME_SILENT_TALK); - - //Shout that I was attacked - SpeakString("NW_I_WAS_ATTACKED", TALKVOLUME_SILENT_TALK); - } + object oAttacker = GetLastAttacker(oCreature); + if(AI_DEBUG) ai_Debug("nw_c2_default5", "14", GetName(oCreature) + " was attacked by " + + GetName(oAttacker) + "."); + SetLocalObject(oAttacker, AI_ATTACKED_PHYSICAL, oCreature); + // Run away! + if(ai_GetFleeToExit(oCreature)) + { + ai_ActivateFleeToExit(oCreature); + return; } - - if(GetSpawnInCondition(NW_FLAG_ATTACK_EVENT)) { - SignalEvent(OBJECT_SELF, EventUserDefined(EVENT_ATTACKED)); + SignalEvent(oCreature, EventUserDefined(EVENT_ATTACKED)); } + if(ai_GetIsBusy(oCreature) || ai_Disabled(oCreature)) return; + if(ai_GetIsInCombat(oCreature)) return; + // We only inform others if attacked when not busy, not disabled & not in combat. + if(AI_DEBUG) ai_Debug("nw_c2_default5", "30", "Tell my allies I've been attacked!"); + SetLocalObject (oCreature, AI_MY_TARGET, oAttacker); + SpeakString(AI_ATKED_BY_WEAPON, TALKVOLUME_SILENT_TALK); + // Now move towards the attack in the hopes we can see them. + if(GetDistanceBetween(oCreature, oAttacker) < AI_RANGE_CLOSE) ai_DoMonsterCombatRound(oCreature); + else ActionMoveToObject(oAttacker, TRUE, AI_RANGE_CLOSE); } diff --git a/src/module/nss/nw_c2_default6.nss b/src/module/nss/nw_c2_default6.nss index d362ecf..5347842 100644 --- a/src/module/nss/nw_c2_default6.nss +++ b/src/module/nss/nw_c2_default6.nss @@ -1,109 +1,36 @@ -//::////////////////////////////////////////////////// -//:: NW_C2_DEFAULT6 -//:: Default OnDamaged handler -/* - If already fighting then ignore, else determine - combat round - */ -//::////////////////////////////////////////////////// -//:: Copyright (c) 2002 Floodgate Entertainment -//:: Created By: Naomi Novik -//:: Created On: 12/22/2002 -//::////////////////////////////////////////////////// -//::////////////////////////////////////////////////// -//:: Modified By: Deva Winblood -//:: Modified On: Jan 17th, 2008 -//:: Added Support for Mounted Combat Feat Support -//::////////////////////////////////////////////////// - -#include "nw_i0_generic" -#include "x3_inc_horse" - +/*////////////////////////////////////////////////////////////////////////////// + Script: nw_c2_default6 + Programmer: Philos +//////////////////////////////////////////////////////////////////////////////// + Monster OnDamaged event script; + Does not fire if the creature dies from the damage. + Does not fire for plot creatures as they take no damage. + May fire before or after OnPhysicalAttacked event. + Fires when EffectDamage is applied to oCreature even if 0 damage. + Fires when a weapon damages a oCreature, but not if resisted. +*/////////////////////////////////////////////////////////////////////////////// +#include "0i_actions" void main() { - ExecuteScript("prc_npc_damaged", OBJECT_SELF); - - object oDamager = GetLastDamager(); - object oMe=OBJECT_SELF; - int nHPBefore; - if (!GetLocalInt(GetModule(),"X3_NO_MOUNTED_COMBAT_FEAT")) - if (GetHasFeat(FEAT_MOUNTED_COMBAT)&&HorseGetIsMounted(OBJECT_SELF)) - { // see if can negate some damage - if (GetLocalInt(OBJECT_SELF,"bX3_LAST_ATTACK_PHYSICAL")) - { // last attack was physical - nHPBefore=GetLocalInt(OBJECT_SELF,"nX3_HP_BEFORE"); - if (!GetLocalInt(OBJECT_SELF,"bX3_ALREADY_MOUNTED_COMBAT")) - { // haven't already had a chance to use this for the round - SetLocalInt(OBJECT_SELF,"bX3_ALREADY_MOUNTED_COMBAT",TRUE); - int nAttackRoll=GetBaseAttackBonus(oDamager)+d20(); - int nRideCheck=GetSkillRank(SKILL_RIDE,OBJECT_SELF)+d20(); - if (nRideCheck>=nAttackRoll&&!GetIsDead(OBJECT_SELF)) - { // averted attack - if (GetIsPC(oDamager)) SendMessageToPC(oDamager,GetName(OBJECT_SELF)+GetStringByStrRef(111991)); - //if (GetIsPC(OBJECT_SELF)) SendMessageToPCByStrRef(OBJECT_SELF,111992"); - if (GetCurrentHitPoints(OBJECT_SELF) (GetMaxHitPoints(OBJECT_SELF) / 4) - || (GetHitDice(oDamager) - 2) > GetHitDice(oTarget) - ) - ) - ) - { - // Switch targets - DetermineCombatRound(oDamager); - } - } - } - + object oCreature = OBJECT_SELF; + + ExecuteScript("prc_npc_damaged", OBJECT_SELF); + // Send the user-defined event signal if(GetSpawnInCondition(NW_FLAG_DAMAGED_EVENT)) { - SignalEvent(OBJECT_SELF, EventUserDefined(EVENT_DAMAGED)); + SignalEvent(oCreature, EventUserDefined(EVENT_DAMAGED)); + return; } + if(ai_Disabled(oCreature)) return; + // Make sure to clear wounded shout limit if we take damage. See ai_TryHealing. + DeleteLocalInt(oCreature, "AI_WOUNDED_SHOUT_LIMIT"); + object oDamager = GetLastDamager(oCreature); + if(AI_DEBUG) ai_Debug("nw_c2_default6", "23", GetName(oCreature) + " has been damaged by " + GetName(oDamager)); + if(ai_GetFleeToExit(oCreature)) return; + if(GetObjectType(oDamager) == OBJECT_TYPE_AREA_OF_EFFECT && + ai_IsInADangerousAOE(oCreature, AI_RANGE_BATTLEFIELD, TRUE)) return; + if(ai_GetIsBusy(oCreature) || ai_GetIsInCombat(oCreature)) return; + if(GetDistanceBetween(oCreature, oDamager) < AI_RANGE_CLOSE) ai_DoMonsterCombatRound(oCreature); + else ActionMoveToObject(oDamager, TRUE, AI_RANGE_CLOSE - 1.0); } diff --git a/src/module/nss/nw_c2_default8.nss b/src/module/nss/nw_c2_default8.nss index 3e49428..fa7ef11 100644 --- a/src/module/nss/nw_c2_default8.nss +++ b/src/module/nss/nw_c2_default8.nss @@ -1,30 +1,26 @@ -//::////////////////////////////////////////////////// -//:: NW_C2_DEFAULT8 -/* - Default OnDisturbed event handler for NPCs. - */ -//::////////////////////////////////////////////////// -//:: Copyright (c) 2002 Floodgate Entertainment -//:: Created By: Naomi Novik -//:: Created On: 12/22/2002 -//::////////////////////////////////////////////////// - -#include "nw_i0_generic" - +/*////////////////////////////////////////////////////////////////////////////// + Script: nw_c2_default8 + Programmer: Philos +//////////////////////////////////////////////////////////////////////////////// + Monster OnDisturbed event script; + Fires when the inventory of oCreature is changed i.e. added or removed. + Creatures can't have items added or removed from its inventory (it's not a + container), then the only way this fires for creatures if something is stolen. +*/////////////////////////////////////////////////////////////////////////////// +#include "0i_actions" void main() { ExecuteScript("prc_npc_disturb", OBJECT_SELF); - - object oTarget = GetLastDisturbed(); - - // If we've been disturbed and are not already fighting, - // attack our disturber. - if (GetIsObjectValid(oTarget) && !GetIsFighting(OBJECT_SELF)) { - DetermineCombatRound(oTarget); - } - + + if(AI_DEBUG) ai_Debug("nw_c2_default8", "13", GetName(OBJECT_SELF) + " is been disturbed!"); + // We do nothing at the moment... lets not mess up our factions ok? + // This should be defined by the server admins and is commented out. + //if(ai_GetIsBusy(OBJECT_SELF, FALSE) || ai_Disabled()) return; + //object oTarget = GetLastDisturbed(); + //if (oTarget != OBJECT_INVALID) ai_DoMonsterCombatRound (); // Send the disturbed flag if appropriate. - if(GetSpawnInCondition(NW_FLAG_DISTURBED_EVENT)) { + if(GetSpawnInCondition(NW_FLAG_DISTURBED_EVENT)) + { SignalEvent(OBJECT_SELF, EventUserDefined(EVENT_DISTURBED)); } -} \ No newline at end of file +} diff --git a/src/module/nss/nw_c2_defaultb.nss b/src/module/nss/nw_c2_defaultb.nss index 1338544..3150026 100644 --- a/src/module/nss/nw_c2_defaultb.nss +++ b/src/module/nss/nw_c2_defaultb.nss @@ -1,159 +1,42 @@ -//:://///////////////////////////////////////////// -//:: Default: On Spell Cast At -//:: NW_C2_DEFAULTB -//:: Copyright (c) 2001 Bioware Corp. -//::////////////////////////////////////////////// -/* - This determines if the spell just cast at the - target is harmful or not. - - GZ 2003-Oct-02 : - New AoE Behavior AI. Will use - Dispel Magic against AOES - - Flying Creatures will ignore - Grease - -*/ -//::////////////////////////////////////////////// -//:: Created By: Preston Watamaniuk -//:: Created On: Dec 6, 2001 -//:: Last Modified On: 2003-Oct-13 -//::////////////////////////////////////////////// -//::////////////////////////////////////////////// -//:: Modified By: Deva Winblood -//:: Modified On: Jan 4th, 2008 -//:: Added Support for Mounted Combat Feat Support -//::////////////////////////////////////////////// - -#include "nw_i0_generic" -#include "x2_i0_spells" - +/*////////////////////////////////////////////////////////////////////////////// + Script: nw_c2_defaultb + Programmer: Philos +//////////////////////////////////////////////////////////////////////////////// + Monster OnSpellCastAt event script; + Fires when oCreature becomes the target of a spell via SignalEvent. + Fires when a healing kit is used on a creature. +*/////////////////////////////////////////////////////////////////////////////// +#include "0i_associates" void main() { - ExecuteScript("prc_npc_spellat", OBJECT_SELF); - + object oCreature = OBJECT_SELF; object oCaster = GetLastSpellCaster(); - - - if(GetLastSpellHarmful()) - { - SetCommandable(TRUE); - - if (!GetLocalInt(GetModule(),"X3_NO_MOUNTED_COMBAT_FEAT")) - { // set variables on target for mounted combat - DeleteLocalInt(OBJECT_SELF,"bX3_LAST_ATTACK_PHYSICAL"); - } // set variables on target for mounted combat - - // ------------------------------------------------------------------ - // If I was hurt by someone in my own faction - // Then clear any hostile feelings I have against them - // After all, we're all just trying to do our job here - // if we singe some eyebrow hair, oh well. - // ------------------------------------------------------------------ - if (GetFactionEqual(oCaster, OBJECT_SELF) == TRUE) - { - ClearPersonalReputation(oCaster, OBJECT_SELF); - ClearAllActions(TRUE); - DelayCommand(1.2, ActionDoCommand(DetermineCombatRound(OBJECT_INVALID))); - // Send the user-defined event as appropriate - if(GetSpawnInCondition(NW_FLAG_SPELL_CAST_AT_EVENT)) - { - SignalEvent(OBJECT_SELF, EventUserDefined(EVENT_SPELL_CAST_AT)); - } - return; - } - - int bAttack = TRUE; - // ------------------------------------------------------------------ - // GZ, 2003-Oct-02 - // Try to do something smart if we are subject to an AoE Spell. - // ------------------------------------------------------------------ - if (MatchAreaOfEffectSpell(GetLastSpell()) == TRUE) - { - int nAI = (GetBestAOEBehavior(GetLastSpell())); // from x2_i0_spells - switch (nAI) - { - case X2_SPELL_AOEBEHAVIOR_DISPEL_L: - case X2_SPELL_AOEBEHAVIOR_DISPEL_N: - case X2_SPELL_AOEBEHAVIOR_DISPEL_M: - case X2_SPELL_AOEBEHAVIOR_DISPEL_G: - case X2_SPELL_AOEBEHAVIOR_DISPEL_C: - bAttack = FALSE; - ActionCastSpellAtLocation(nAI, GetLocation(OBJECT_SELF)); - ActionDoCommand(SetCommandable(TRUE)); - SetCommandable(FALSE); - break; - - case X2_SPELL_AOEBEHAVIOR_FLEE: - ClearActions(CLEAR_NW_C2_DEFAULTB_GUSTWIND); - oCaster = GetLastSpellCaster(); - ActionForceMoveToObject(oCaster, TRUE, 2.0); - DelayCommand(1.2, ActionDoCommand(DetermineCombatRound(oCaster))); - bAttack = FALSE; - break; - - case X2_SPELL_AOEBEHAVIOR_IGNORE: - // well ... nothing - break; - - case X2_SPELL_AOEBEHAVIOR_GUST: - ActionCastSpellAtLocation(SPELL_GUST_OF_WIND, GetLocation(OBJECT_SELF)); - ActionDoCommand(SetCommandable(TRUE)); - SetCommandable(FALSE); - bAttack = FALSE; - break; - } - - } - // --------------------------------------------------------------------- - // Not an area of effect spell, but another hostile spell. - // If we're not already fighting someone else, - // attack the caster. - // --------------------------------------------------------------------- - if( !GetIsFighting(OBJECT_SELF) && bAttack) - { - if(GetBehaviorState(NW_FLAG_BEHAVIOR_SPECIAL)) - { - DetermineSpecialBehavior(oCaster); - } - else - { - DetermineCombatRound(oCaster); - } - } - - // We were attacked, so yell for help - SetCommandable(TRUE); - //Shout Attack my target, only works with the On Spawn In setup - SpeakString("NW_ATTACK_MY_TARGET", TALKVOLUME_SILENT_TALK); - - //Shout that I was attacked - SpeakString("NW_I_WAS_ATTACKED", TALKVOLUME_SILENT_TALK); - } - else - { - // --------------------------------------------------------------------- - // July 14, 2003 BK - // If there is a valid enemy nearby and a NON HARMFUL spell has been - // cast on me I should call DetermineCombatRound - // I may be invisible and casting spells on myself to buff myself up - // --------------------------------------------------------------------- - // Fix: JE - let's only do this if I'm currently in combat. If I'm not - // in combat, and something casts a spell on me, it'll make me search - // out the nearest enemy, no matter where they are on the level, which - // is kinda dumb. - object oEnemy =GetNearestEnemy(); - if ((GetIsObjectValid(oEnemy) == TRUE) && (GetIsInCombat() == TRUE)) - { - // SpeakString("keep me in combat"); - DetermineCombatRound(oEnemy); - } - } - + SetLocalObject(oCaster, AI_ATTACKED_SPELL, oCreature); + if(ai_Disabled(oCreature)) return; + ExecuteScript("prc_npc_spellat", OBJECT_SELF); + if(!GetLastSpellHarmful()) return; // Send the user-defined event as appropriate if(GetSpawnInCondition(NW_FLAG_SPELL_CAST_AT_EVENT)) { SignalEvent(OBJECT_SELF, EventUserDefined(EVENT_SPELL_CAST_AT)); } - - + // If the spell came from an ally, we don't want to hold it against them. + if(GetFactionEqual(oCaster, oCreature)) ClearPersonalReputation(oCaster, oCreature); + // Lets see what kind of area of effect this is and select an appropriate action. + int nSpell = GetLastSpell(); + if(AI_DEBUG) ai_Debug("nw_c2_defaultb", "26", GetName(oCreature) + " has been hit by a harmful spell(" + + Get2DAString("spells", "Label", nSpell) + ")!"); + if(ai_GetInAOEReaction(oCreature, oCaster, nSpell) && + ai_IsInADangerousAOE(oCreature, AI_RANGE_BATTLEFIELD, TRUE)) return; + if(ai_GetIsBusy(oCreature)) return; + if(ai_CheckForCombat(oCreature, TRUE)) return; + // We have been attacked out of combat, so let our allies know. + SetLocalObject(oCreature, AI_MY_TARGET, oCaster); + SpeakString(AI_ATKED_BY_SPELL, TALKVOLUME_SILENT_TALK); + if(GetDistanceBetween(oCreature, oCaster) < AI_RANGE_CLOSE) + { + if(ai_GetBehaviorState(NW_FLAG_BEHAVIOR_SPECIAL)) ai_DetermineSpecialBehavior(oCreature); + else ai_DoMonsterCombatRound(oCreature); + } + else ActionMoveToObject(oCaster, TRUE, AI_RANGE_CLOSE); } diff --git a/src/module/nss/nw_c2_defaulte.nss b/src/module/nss/nw_c2_defaulte.nss index 3d8ab2c..76f62db 100644 --- a/src/module/nss/nw_c2_defaulte.nss +++ b/src/module/nss/nw_c2_defaulte.nss @@ -1,51 +1,53 @@ -//:://///////////////////////////////////////////// -//:: Default On Blocked -//:: NW_C2_DEFAULTE -//:: Copyright (c) 2001 Bioware Corp. -//::////////////////////////////////////////////// -/* - This will cause blocked creatures to open - or smash down doors depending on int and - str. -*/ -//::////////////////////////////////////////////// -//:: Created By: Preston Watamaniuk -//:: Created On: Nov 23, 2001 -//::////////////////////////////////////////////// - +/*////////////////////////////////////////////////////////////////////////////// + Script: nw_c2_defaulte + Programmer: Philos +//////////////////////////////////////////////////////////////////////////////// + Monsters OnBlocked event script; + Can be blocked by a creature or door. +*/////////////////////////////////////////////////////////////////////////////// +#include "0i_associates" void main() { - ExecuteScript("prc_npc_blocked", OBJECT_SELF); - - object oDoor = GetBlockingDoor(); - if (GetObjectType(oDoor) == OBJECT_TYPE_CREATURE) + object oCreature = OBJECT_SELF; + // This actually gets either a Creature or Door that is blocking OBJECT_SELF. + object oObject = GetBlockingDoor(); + if(AI_DEBUG) ai_Debug("nw_c2_defaulte", "14", GetName(oCreature) + " is being blocked by " + GetName(oObject)); + int nObjectType = GetObjectType(oObject); + if(nObjectType == OBJECT_TYPE_CREATURE) { - // * Increment number of times blocked - /*SetLocalInt(OBJECT_SELF, "X2_NUMTIMES_BLOCKED", GetLocalInt(OBJECT_SELF, "X2_NUMTIMES_BLOCKED") + 1); - if (GetLocalInt(OBJECT_SELF, "X2_NUMTIMES_BLOCKED") > 3) + if(GetIsEnemy(oObject, oCreature)) { - SpeakString("Blocked by creature"); - SetLocalInt(OBJECT_SELF, "X2_NUMTIMES_BLOCKED",0); - ClearAllActions(); - object oEnemy = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY); - if (GetIsObjectValid(oEnemy) == TRUE) + if(ai_CanIAttack(oCreature) && ai_GetIsInCombat(oCreature)) { - ActionEquipMostDamagingRanged(oEnemy); - ActionAttack(oEnemy); + ai_DoMonsterCombatRound(oCreature); + return; } - return; - } */ + if(ai_CheckForCombat(oCreature, TRUE)) return; + } + } + // Anything below blocking us is a door. + if(nObjectType != OBJECT_TYPE_DOOR) return; + // Only open the door if the player has turned door opening on. + if(!GetLocalInt(GetModule(), AI_RULE_OPEN_DOORS)) return; + //if(GetLockKeyTag(oObject) != "") return; + else if(GetIsDoorActionPossible(oObject, DOOR_ACTION_OPEN) && + GetAbilityScore(oCreature, ABILITY_INTELLIGENCE) >= 5) + { + if(AI_DEBUG) ai_Debug("nw_c2_defaulte", "33", GetName(oCreature) + " is opening " + GetName(oObject)); + DoDoorAction(oObject, DOOR_ACTION_OPEN); return; } - if(GetAbilityScore(OBJECT_SELF, ABILITY_INTELLIGENCE) >= 5) + // If we are in combat we should ignore doors that do not easily open. + if(GetIsDoorActionPossible(oObject, DOOR_ACTION_BASH) && + ai_GetWeaponDamage(oCreature, 3, TRUE) > GetHardness(oObject) && + GetLockKeyTag(oObject) == "") { - if(GetIsDoorActionPossible(oDoor, DOOR_ACTION_OPEN) && GetAbilityScore(OBJECT_SELF, ABILITY_INTELLIGENCE) >= 7 ) - { - DoDoorAction(oDoor, DOOR_ACTION_OPEN); - } - else if(GetIsDoorActionPossible(oDoor, DOOR_ACTION_BASH)) - { - DoDoorAction(oDoor, DOOR_ACTION_BASH); - } + ActionWait(1.0); + ActionAttack(oObject); + // Give them 3 rounds to break through a door. + DelayCommand(18.0, ai_ClearCreatureActions(TRUE)); + return; } } + + diff --git a/src/module/nss/nw_ch_ac1.nss b/src/module/nss/nw_ch_ac1.nss index 9835290..6ed2fea 100644 --- a/src/module/nss/nw_ch_ac1.nss +++ b/src/module/nss/nw_ch_ac1.nss @@ -1,228 +1,158 @@ -// HCR v3.2.0 - -//:://////////////////////////////////////////////////////////////////////////// -//:: FileName: NW_CH_AC1 -//:://////////////////////////////////////////////////////////////////////////// -/* - Move towards master or wait for him. -*/ -//:://////////////////////////////////////////////////////////////////////////// -//:: Created By: Preston Watamaniuk -//:: Created On: Nov 21, 2001 -//:: Updated On: Jul 25, 2003 - Georg Zoeller -//:://////////////////////////////////////////////////////////////////////////// -#include "X0_INC_HENAI" -#include "X2_INC_SUMMSCALE" -#include "X2_INC_SPELLHOOK" -#include "inc_utility" -//:://////////////////////////////////////////////////////////////////////////// +/*////////////////////////////////////////////////////////////////////////////// + Script: nw_ch_ac1 + 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" +#include "0i_menus" +void ai_ActionFollow(object oCreature, object oTarget) +{ + if(GetLocalInt(OBJECT_SELF, AI_CURRENT_ACTION_MODE) == AI_LAST_ACTION_MOVE) + { + float fDistance = GetDistanceBetween(oCreature, oTarget); + float fFollowDistance = ai_GetFollowDistance(oCreature); + if(fDistance > fFollowDistance) + { + if(fDistance > fFollowDistance * 5.0 && + ai_GetIsInCombat(oCreature)) AssignCommand(oCreature, JumpToObject(oTarget)); + else + { + ClearAllActions(); + ActionMoveToObject(oTarget, TRUE, fFollowDistance); + } + } + DelayCommand(1.0, ai_ActionFollow(oCreature, oTarget)); + } +} void main() { - //SpawnScriptDebugger(); - - // GZ: Fallback for timing issue sometimes preventing epic summoned - // creatures from leveling up to their master's level. There is a timing - // issue with the GetMaster() function not returning the master of a - // creature immediately after spawn. Some code which might appear to make no - // sense has been added to the nw_ch_ac1 and x2_inc_summon files to work - // around this. This code is only run on the first hearbeat. - int nLevel = SSMGetSummonFailedLevelUp(OBJECT_SELF); - if (nLevel != 0) + if (GetAILevel(OBJECT_SELF) == AI_LEVEL_VERY_LOW) return; + object oCreature = OBJECT_SELF; + if(AI_DEBUG) ai_Counter_Start(); + // We run our OnSpawn in the heartbeat so the creator can use the original + // OnSpawn for their own use. + ai_OnAssociateSpawn(oCreature); + if(AI_DEBUG) ai_Counter_End(GetName(oCreature) + ": Heartbeat, ai_OnAssociateSpawn"); + if(AI_DEBUG) ai_Debug("nw_ch_ac1", "37", GetName(oCreature) + " Heartbeat." + + " MODE_FOLLOW: " + IntToString(ai_GetAIMode(oCreature, AI_MODE_FOLLOW)) + + " Action: " + IntToString(GetCurrentAction(oCreature))); + if(ai_GetIsBusy(oCreature) || ai_Disabled(oCreature)) return; + if(AI_DEBUG) ai_Counter_End(GetName(oCreature) + ": Heartbeat, ai_GetIsBusy/ai_Disabled"); + // If we are an associate and don't have a master then exit. + object oMaster = GetMaster(oCreature); + if(AI_DEBUG) ai_Debug("nw_ch_ac1", "43", "oMaster: " + GetName(oMaster)); + if(oMaster == OBJECT_INVALID) { - int nRet; - if (nLevel == -1)// Special Shadow Lord treatment. + if(ai_GetIsInCombat(oCreature)) { - SSMScaleEpicShadowLord(OBJECT_SELF); + ai_DoAssociateCombatRound(oCreature); + return; } - else if (nLevel == -2) + ai_CheckForCombat(oCreature, FALSE); + return; + } + // ***** Code for Henchman data and menus ***** + if(ai_GetIsCharacter(oMaster)) + { + string sAssociateType = ai_GetAssociateType(oMaster, oCreature); + ai_CheckAssociateData(oMaster, oCreature, sAssociateType); + ai_CheckPCStart(oMaster); + if(AI_HENCHMAN_WIDGET) { - SSMScaleEpicFiendishServant(OBJECT_SELF); + // This keeps widgets from disappearing and reappearing. + int nUiToken = NuiFindWindow(oMaster, sAssociateType + AI_WIDGET_NUI); + if(nUiToken) + { + json jData = NuiGetUserData(oMaster, nUiToken); + object oAssociate = StringToObject(JsonGetString(JsonArrayGet(jData, 0))); + if(oAssociate != oCreature) NuiDestroy(oMaster, nUiToken); + } + else + { + if(!ai_GetWidgetButton(oMaster, BTN_WIDGET_OFF, oCreature, sAssociateType)) + { + ai_CreateWidgetNUI(oMaster, oCreature); + } + } + } + if(AI_DEBUG) ai_Counter_End(GetName(oCreature) + ": Heartbeat, Get Associate data/Build widget"); + } + // If follow mode we do not want the NPC doing anything but follow. + if(!ai_GetAIMode(oCreature, AI_MODE_FOLLOW)) + { + if(ai_GetAIMode(oCreature, AI_MODE_STAND_GROUND)) + { + ai_TryHealing(oCreature, oCreature); + return; + } + if(ai_GetIsInCombat(oCreature)) + { + ai_DoAssociateCombatRound(oCreature); + return; + } + if(ai_CheckForCombat(oCreature, FALSE)) return; + if(AI_DEBUG) ai_Counter_End(GetName(oCreature) + ": Heartbeat, ai_CheckForCombat"); + if(IsInConversation(oCreature)) return; + // In command mode we let the player tell us what to do. + if(!ai_GetAIMode(oCreature, AI_MODE_COMMANDED)) + { + if(ai_TryHealing(oCreature, oCreature)) return; + if(AI_DEBUG) ai_Counter_End(GetName(oCreature) + ": Heartbeat: TryHealing"); + if(ai_CheckNearbyObjects(oCreature)) return; + if(AI_DEBUG) ai_Counter_End(GetName(oCreature) + ": Heartbeat: CheckNearbyObjects"); + if(ai_GetAIMode(oCreature, AI_MODE_SCOUT_AHEAD)) + { + ai_ScoutAhead(oCreature); + return; + } + } + } + // Finally we check to make sure we are following our master. + if(GetCurrentAction(oCreature) != ACTION_FOLLOW) + { + //ai_Debug("nw_ch_ac1", "66", "Follow master: " + + // " Stealth: " + IntToString(ai_GetAIMode(oCreature, AI_MODE_AGGRESSIVE_STEALTH)) + + // " Search: " + IntToString(ai_GetAIMode(oCreature, AI_MODE_AGGRESSIVE_SEARCH))); + if(ai_GetAIMode(oCreature, AI_MODE_AGGRESSIVE_STEALTH)) + { + if(AI_DEBUG) ai_Debug("nw_ch_ac1", "120", "Going into stealth mode!"); + int nStealth = GetSkillRank(SKILL_HIDE, oCreature); + nStealth += GetSkillRank(SKILL_MOVE_SILENTLY, oCreature); + if(nStealth / 2 >= ai_GetCharacterLevels(oCreature)) + { + SetActionMode(oCreature, ACTION_MODE_STEALTH, TRUE); + SetActionMode(oCreature, ACTION_MODE_DETECT, FALSE); + } } else { - nRet = SSMLevelUpCreature(OBJECT_SELF, nLevel, CLASS_TYPE_INVALID); - if (nRet == FALSE) - WriteTimestampedLogEntry("WARNING - nw_ch_ac1:: could not level up " + GetTag(OBJECT_SELF) + "!"); - } - - // Regardless if the actual levelup worked, we give up here, because we do - // not want to run through this script more than once. - SSMSetSummonLevelUpOK(OBJECT_SELF); - } - - // Check if concentration is required to maintain this creature. - X2DoBreakConcentrationCheck(); - - object oMod = GetModule(); - object oMaster = GetMaster(); - - // HCR - Remark out the following "if" block of code if you want to use the - // alternative method below. - - // *** Start original Real Familiar code. *** - if (GetLocalInt(oMod, "REALFAM")) - { - if (GetAssociate(ASSOCIATE_TYPE_FAMILIAR, oMaster) == OBJECT_SELF) - { - // Check to see if critter is a familiar. - // If so, limit it to 1/2 hp of master per PHB. - if (GetIsObjectValid(oMaster)) + SetActionMode(oCreature, ACTION_MODE_STEALTH, FALSE); + if(ai_GetAIMode(oCreature, AI_MODE_AGGRESSIVE_SEARCH)) { - int nMHP = GetMaxHitPoints(); - int nCHP = GetCurrentHitPoints(); - int nMax = (GetMaxHitPoints(oMaster)/2); - if ((nMHP - nCHP) >= nMax) - { - effect eDeath = EffectDeath(FALSE, FALSE); - ApplyEffectToObject(DURATION_TYPE_INSTANT, eDeath, OBJECT_SELF); - } + if(AI_DEBUG) ai_Debug("nw_ch_ac1", "134", "Going into search mode!"); + SetActionMode(oCreature, ACTION_MODE_DETECT, TRUE); + } + else SetActionMode(oCreature, ACTION_MODE_DETECT, FALSE); + } + // Follow master. + if(GetDistanceBetween(oCreature, oMaster) > ai_GetFollowDistance(oCreature)) + { + if(!ai_GetAIMode(oCreature, AI_MODE_COMMANDED)) + { + object oTarget = GetLocalObject(oCreature, AI_FOLLOW_TARGET); + if(oTarget == OBJECT_INVALID) oTarget = oMaster; + //ActionForceFollowObject(oTarget, ai_GetFollowDistance(oCreature)); + //ActionMoveToObject(oTarget, TRUE, ai_GetFollowDistance(oCreature)); + SetLocalInt(oCreature, AI_CURRENT_ACTION_MODE, AI_LAST_ACTION_MOVE); + ai_ActionFollow(oCreature, oTarget); } } } - // *** End original Real Familiar code. *** - - // HCR - Unremark this "if" block of code and remark out the above code for - // alternative Familiar hit points. -/* - // *** Start alternate Real Familiar code. *** - if (GetLocalInt(oMod, "REALFAM")) + if(AI_DEBUG) ai_Counter_End(GetName(oCreature) + ": Heartbeat, end"); + if(GetSpawnInCondition(NW_FLAG_HEARTBEAT_EVENT)) { - if (GetAssociate(ASSOCIATE_TYPE_FAMILIAR, oMaster) == OBJECT_SELF) - { - // Check to see if critter is a familiar. - // If so, limit it to 1/2 hp of master per PHB. - if (GetIsObjectValid(oMaster)) - { - if (!GetIsResting(oMaster)) - { - int nMHP = GetMaxHitPoints(); - int nCHP = GetCurrentHitPoints(); - int nMax = (GetMaxHitPoints(oMaster)/2); - if (nCHP > nMax) - { - int nDam = (nCHP - nMax); - effect eDam = EffectDamage(nDam); - ApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, OBJECT_SELF); - - if (!GetLocalInt(OBJECT_SELF, "FAMMSG")) - { - SendMessageToPC(oMaster, "Familiar's Hit Points adjusted to 1/2 of master's in accordance with 3rd edition rules."); - SetLocalInt(OBJECT_SELF, "FAMMSG", TRUE); - } - } - } - } - } - } - // *** End alternate Real Familiar code. *** -*/ - - if (!GetAssociateState(NW_ASC_IS_BUSY)) - { - // Seek out and disable undisabled traps. - object oTrap = GetNearestTrapToObject(); - if (bkAttemptToDisarmTrap(oTrap) == TRUE) - return;// Succesful trap found and disarmed. - - if (GetIsObjectValid(oMaster) && - GetCurrentAction() != ACTION_FOLLOW && - GetCurrentAction() != ACTION_DISABLETRAP && - GetCurrentAction() != ACTION_OPENLOCK && - GetCurrentAction() != ACTION_REST && - GetCurrentAction() != ACTION_ATTACKOBJECT) - { - if (!GetIsObjectValid(GetAttackTarget()) && - !GetIsObjectValid(GetAttemptedSpellTarget()) && - !GetIsObjectValid(GetAttemptedAttackTarget()) && - !GetIsObjectValid(GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN))) - { - if (GetIsObjectValid(oMaster) == TRUE) - { - if (GetDistanceToObject(oMaster) > 6.0) - { - if (GetAssociateState(NW_ASC_HAVE_MASTER)) - { - if (!GetIsFighting(OBJECT_SELF)) - { - if (!GetAssociateState(NW_ASC_MODE_STAND_GROUND)) - { - if (GetDistanceToObject(oMaster) > GetFollowDistance()) - { - ClearActions(CLEAR_NW_CH_AC1_49); - - if (GetAssociateState(NW_ASC_AGGRESSIVE_STEALTH) || - GetAssociateState(NW_ASC_AGGRESSIVE_SEARCH)) - { - if (GetAssociateState(NW_ASC_AGGRESSIVE_STEALTH)) - { - //ActionUseSkill(SKILL_HIDE, OBJECT_SELF); - //ActionUseSkill(SKILL_MOVE_SILENTLY,OBJECT_SELF); - } - - if (GetAssociateState(NW_ASC_AGGRESSIVE_SEARCH)) - ActionUseSkill(SKILL_SEARCH, OBJECT_SELF); - - MyPrintString("GENERIC SCRIPT DEBUG STRING ********** " + "Assigning Force Follow Command with Search and/or Stealth"); - ActionForceFollowObject(oMaster, GetFollowDistance()); - } - else - { - MyPrintString("GENERIC SCRIPT DEBUG STRING ********** " + "Assigning Force Follow Normal"); - ActionForceFollowObject(oMaster, GetFollowDistance()); - } - } - } - } - } - } - } - else if (!GetAssociateState(NW_ASC_MODE_STAND_GROUND)) - { - if (GetIsObjectValid(oMaster)) - { - if (GetCurrentAction(oMaster) != ACTION_REST) - { - ClearActions(CLEAR_NW_CH_AC1_81); - - if (GetAssociateState(NW_ASC_AGGRESSIVE_STEALTH) || - GetAssociateState(NW_ASC_AGGRESSIVE_SEARCH)) - { - if (GetAssociateState(NW_ASC_AGGRESSIVE_STEALTH)) - { - //ActionUseSkill(SKILL_HIDE, OBJECT_SELF); - //ActionUseSkill(SKILL_MOVE_SILENTLY,OBJECT_SELF); - } - - if (GetAssociateState(NW_ASC_AGGRESSIVE_SEARCH)) - ActionUseSkill(SKILL_SEARCH, OBJECT_SELF); - - MyPrintString("GENERIC SCRIPT DEBUG STRING ********** " + "Assigning Force Follow Command with Search and/or Stealth"); - ActionForceFollowObject(oMaster, GetFollowDistance()); - } - else - { - MyPrintString("GENERIC SCRIPT DEBUG STRING ********** " + "Assigning Force Follow Normal"); - ActionForceFollowObject(oMaster, GetFollowDistance()); - } - } - } - } - } - else if (!GetIsObjectValid(GetAttackTarget()) && - !GetIsObjectValid(GetAttemptedSpellTarget()) && - !GetIsObjectValid(GetAttemptedAttackTarget()) && - !GetAssociateState(NW_ASC_MODE_STAND_GROUND)) - { - //DetermineCombatRound(); - } - } - - // * If I am dominated, ask for some help. - if (PRCGetHasEffect(EFFECT_TYPE_DOMINATED, OBJECT_SELF) == TRUE && - GetIsEncounterCreature(OBJECT_SELF) == FALSE) - SendForHelp(); - - if (GetSpawnInCondition(NW_FLAG_HEARTBEAT_EVENT)) - SignalEvent(OBJECT_SELF, EventUserDefined(1001)); + SignalEvent(OBJECT_SELF, EventUserDefined(1001)); } } -//:://////////////////////////////////////////////////////////////////////////// diff --git a/src/module/nss/nw_ch_ac2.nss b/src/module/nss/nw_ch_ac2.nss new file mode 100644 index 0000000..04a56f9 --- /dev/null +++ b/src/module/nss/nw_ch_ac2.nss @@ -0,0 +1,107 @@ +/*////////////////////////////////////////////////////////////////////////////// + Script: nw_ch_ac2 + Programmer: Philos +//////////////////////////////////////////////////////////////////////////////// + Associate(Summons, Familiars, Companions) OnPerception script when not in combat; + There are 4 types of perception - Heard, Inaudible, Seen, Vanished. + Only one type will ever be true in an event trigger. + The order of trigger is Heard/Seen and Inaudible/Vanished. + There are two states of percepion Heard and Seen. + These states can be set at the same time thus a heard event can see the creature. + Fires when ever one of these states changes from TRUE to FALSE or FALSE to TRUE. +*/////////////////////////////////////////////////////////////////////////////// +#include "0i_associates" +void main() +{ + object oCreature = OBJECT_SELF; + object oLastPerceived = GetLastPerceived(); + if(AI_DEBUG) + { + if(GetLastPerceptionHeard ()) + { + ai_Debug("nw_ch_ac2", "21", GetName(oCreature) + " heard " + + GetName(GetLastPerceived()) + " Distance: " + + FloatToString(GetDistanceBetween(GetLastPerceived(), oCreature), 0, 2) + + " Seen: " + IntToString(GetObjectSeen(oLastPerceived, oCreature)) + "."); + } + if(GetLastPerceptionSeen ()) + { + ai_Debug("nw_ch_ac2", "29", GetName(oCreature) + " sees " + + GetName(GetLastPerceived()) + " Distance: " + + FloatToString(GetDistanceBetween(GetLastPerceived(), oCreature), 0, 2) + "."); + } + if(GetLastPerceptionVanished ()) + { + ai_Debug("nw_ch_ac2", "35", GetName(oCreature) + " lost sight of " + + GetName(GetLastPerceived()) + "."); + } + } + // We do nothing on Inaudibles so drop out early! + if(GetLastPerceptionInaudible()) + { + ai_Debug("nw_ch_ac2", "42", GetName(oCreature) + " lost sound of " + + GetName(GetLastPerceived()) + "."); + return; + } + if(AI_DEBUG) ai_Debug("nw_ch_ac2", "46", "Dead? " + IntToString(GetIsDead(oLastPerceived)) + + " Enemy? " + IntToString(GetIsEnemy(oLastPerceived, oCreature))); + if(ai_Disabled(oCreature)) return; + if(GetIsDead(oLastPerceived) || !GetIsEnemy(oLastPerceived, oCreature)) return; + // All code below assumes the perceived creature is an enemy and is alive! + // **************************** ENEMY HEARD ******************************** + if(GetLastPerceptionHeard()) + { + // Since Heard is run before Seen, but the values are set at the same + // time we can skip heard checks on heard & seen creatures! + if(GetObjectSeen(oLastPerceived, oCreature)) + { + // If the creature we are perceiving was our invisible creature then + // remove that they are invisible. + if(oLastPerceived == GetLocalObject(oCreature, AI_IS_INVISIBLE)) + { + DeleteLocalObject(oCreature, AI_IS_INVISIBLE); + } + ai_AssociateEvaluateNewThreat(oCreature, oLastPerceived, AI_I_SEE_AN_ENEMY); + } + else ai_AssociateEvaluateNewThreat(oCreature, oLastPerceived, AI_I_HEARD_AN_ENEMY); + return; + } + // **************************** ENEMY SEEN ********************************* + if(GetLastPerceptionSeen()) + { + // If the creature we are perceiving was our invisible creature then + // remove that they are invisible. + if(oLastPerceived == GetLocalObject(oCreature, AI_IS_INVISIBLE)) + { + DeleteLocalObject(oCreature, AI_IS_INVISIBLE); + } + ai_AssociateEvaluateNewThreat(oCreature, oLastPerceived, AI_I_SEE_AN_ENEMY); + return; + } + // **************************** ENEMY VANISHED ***************************** + if(GetLastPerceptionVanished()) + { + // Lets keep a mental note of the invisible creature. + SetLocalObject(oCreature, AI_IS_INVISIBLE, oLastPerceived); + if(AI_DEBUG) ai_Debug("nw_ch_ac2", "86", " We saw " + GetName(oLastPerceived) + " disappear!"); + if(ai_GetIsBusy(oCreature)) return; + // If in combat check to see if our target disappeared. + // If they have and we are not in melee with them then reevaluate combat + // since we lost our target. + if(ai_GetIsInCombat(oCreature)) + { + if(AI_DEBUG) ai_Debug("nw_ch_ac2", "93", "Is this our target? " + + IntToString(ai_GetAttackedTarget(oCreature, TRUE, TRUE) == oLastPerceived)); + if(ai_GetAttackedTarget(oCreature, TRUE, TRUE) == oLastPerceived) + { + ai_DoAssociateCombatRound(oCreature); + } + return; + } + // If they are not invisible then that means they left our perception + // range and we need follow them. + if(ai_CanIAttack(oCreature)) ActionMoveToObject(oLastPerceived, TRUE, AI_RANGE_CLOSE); + } + // **************************** ENEMY INAUDIBLE***************************** + // Not used. +} diff --git a/src/module/nss/nw_ch_ac3.nss b/src/module/nss/nw_ch_ac3.nss new file mode 100644 index 0000000..9eb3406 --- /dev/null +++ b/src/module/nss/nw_ch_ac3.nss @@ -0,0 +1,56 @@ +/*////////////////////////////////////////////////////////////////////////////// + Script: nw_ch_ac3 + Programmer: Philos +//////////////////////////////////////////////////////////////////////////////// + Associate (Summons, Familiars, Companions) OnCombatRoundEnd event script; + 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_associates" +void main() +{ + object oCreature = OBJECT_SELF; + if(AI_DEBUG) ai_Debug("nw_ch_ac3", "20", GetName(oCreature) + " ends combat round."); + if(ai_Disabled(oCreature)) return; + // 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); + } + int nAction = GetCurrentAction(oCreature); + if(AI_DEBUG) ai_Debug("nw_ch_ac3", "32", "nAction: " + IntToString(nAction)); + switch(nAction) + { + // These actions are uninteruptable. + case ACTION_MOVETOPOINT : + case ACTION_CASTSPELL : + case ACTION_ITEMCASTSPELL : + case ACTION_COUNTERSPELL : return; + // Might be doing a special action that is not a defined action. + case ACTION_INVALID : + { + int nCombatWait = GetLocalInt(oCreature, AI_COMBAT_WAIT_IN_SECONDS); + if(AI_DEBUG) ai_Debug("nw_ch_ac3", "44", "nCombatWait: " + IntToString(nCombatWait)); + if(nCombatWait) + { + if(ai_IsInCombatRound(oCreature, nCombatWait)) return; + DeleteLocalInt(oCreature, AI_COMBAT_WAIT_IN_SECONDS); + } + } + // We always want to interupt an attack action at the end of a round. + //case ACTION_ATTACKOBJECT : + } + if(ai_GetIsInCombat(oCreature)) ai_DoAssociateCombatRound (oCreature); +} + diff --git a/src/module/nss/nw_ch_ac4.nss b/src/module/nss/nw_ch_ac4.nss index 75c03fe..f6c290d 100644 --- a/src/module/nss/nw_ch_ac4.nss +++ b/src/module/nss/nw_ch_ac4.nss @@ -1,57 +1,44 @@ -//:://///////////////////////////////////////////// -//:: Associate: On Dialogue -//:: NW_CH_AC4 -//:: Copyright (c) 2001 Bioware Corp. -//::////////////////////////////////////////////// -/* - Determines the course of action to be taken - by the generic script after dialogue or a - shout is initiated. -*/ -//::////////////////////////////////////////////// -//:: Created By: Preston Watamaniuk -//:: Created On: Oct 24, 2001 -//::////////////////////////////////////////////// - - -#include "NW_I0_GENERIC" - +/*////////////////////////////////////////////////////////////////////////////// + Script: nw_ch_ac4 + Programmer: Philos +//////////////////////////////////////////////////////////////////////////////// + Associate(Summons, Familiar, Companion) OnDialoge event script; + Fires when oCreature has been clicked on for conversation. + Fires when oCreature hears a shout from another creature. + If SetListening is FALSE then oCreature will not "hear" anything. +*/////////////////////////////////////////////////////////////////////////////// +#include "0i_associates" +#include "nw_inc_gff" void main() { - ExecuteScript("dmfi_voice_exe", OBJECT_SELF); - - if(GetCommandable() || GetCurrentAction() != ACTION_OPENLOCK) + object oCreature = OBJECT_SELF; + int nMatch = GetListenPatternNumber(); + if(AI_DEBUG) ai_Debug("nw_ch_ac4", "16", GetName(oCreature) + " listens " + + IntToString(nMatch) + " to " + GetName(GetLastSpeaker()) + "."); + // Skip ASSOCIATE_COMMAND_MASTERUNDERATTACK(11) since it fires for + // every physical attack made on our master. This fires alot! + if(nMatch == ASSOCIATE_COMMAND_MASTERUNDERATTACK) return; + // If we are disabled then we can't listen or talk, Busy is checked in ai_SelectAssociateCommand(). + if(ai_Disabled(oCreature)) return; + object oLastSpeaker = GetLastSpeaker(); + // Some commands override being busy so we check in ai_SelectAssociateCommand. + if(nMatch != -1) { - int nMatch = GetListenPatternNumber(); - object oShouter = GetLastSpeaker(); - object oIntruder; - if (nMatch == -1) + if(GetFactionEqual(oLastSpeaker, oCreature)) ai_SelectAssociateCommand(oCreature, oLastSpeaker, nMatch); + } + else + { + if (!ai_GetIsBusy(oCreature)) { - if(GetAssociate(ASSOCIATE_TYPE_HENCHMAN, GetMaster()) == OBJECT_SELF) + ai_ClearCreatureActions(); + if(GetAssociateType(oCreature) == ASSOCIATE_TYPE_HENCHMAN) BeginConversation("oc_ai_henchmen", oLastSpeaker); + else { - ClearAllActions(); + json jHenchman = ObjectToJson(oCreature); + string sConversation = JsonGetString(GffGetResRef(jHenchman, "Conversation")); + if(sConversation == "") BeginConversation("oc_ai_henchmen", oLastSpeaker); BeginConversation(); } - else if(!GetIsObjectValid(GetMaster())) - { - ClearAllActions(); - BeginConversation(); - } - else if(GetAssociate(ASSOCIATE_TYPE_FAMILIAR, GetMaster()) == OBJECT_SELF || - GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION, GetMaster()) == OBJECT_SELF) - { - ClearAllActions(); - BeginConversation(); - } - } - else if(GetIsObjectValid(oShouter) && GetMaster() == oShouter) - { - SetCommandable(TRUE); - RespondToShout(oShouter, nMatch, oIntruder); - if(GetSpawnInCondition(NW_FLAG_ON_DIALOGUE_EVENT)) - { - SignalEvent(OBJECT_SELF, EventUserDefined(1004)); - } } } } diff --git a/src/module/nss/nw_ch_ac5.nss b/src/module/nss/nw_ch_ac5.nss new file mode 100644 index 0000000..78f9321 --- /dev/null +++ b/src/module/nss/nw_ch_ac5.nss @@ -0,0 +1,51 @@ +/*////////////////////////////////////////////////////////////////////////////// + Script: nw_ch_ac5 + Programmer: Philos +//////////////////////////////////////////////////////////////////////////////// + Associates (Summons, Familiars, Companions) OnPhysicalAttacked event script; + Fires for all physical attacks, claws, weapons, fists, bow, etc. + Fires for taunt skill, animal empathy skill. +*/////////////////////////////////////////////////////////////////////////////// +#include "0i_associates" +void main() +{ + object oCreature = OBJECT_SELF; + object oAttacker = GetLastAttacker(); + if(AI_DEBUG) ai_Debug("nw_ch_ac5", "14", GetName(oCreature) + " was attacked by " + + GetName(oAttacker) + "."); + SetLocalObject(oAttacker, AI_ATTACKED_PHYSICAL, oCreature); + if(ai_GetIsBusy(oCreature) || ai_Disabled(oCreature)) return; + if(GetSpawnInCondition(NW_FLAG_ATTACK_EVENT)) + { + SignalEvent(OBJECT_SELF, EventUserDefined(1005)); + } + if(ai_GetIsInCombat(oCreature)) return; + // We only inform others if attacked when not busy, not disabled, & not in combat. + SetLocalObject(oCreature, AI_MY_TARGET, oAttacker); + SpeakString(AI_ATKED_BY_WEAPON, TALKVOLUME_SILENT_TALK); + // If they are using a melee weapon then make sure we are using our perception range. + // Don't go running towards them just yet, but if its a ranged weapon then react. + if(ai_GetIsMeleeWeapon(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oAttacker))) + { + float fDistance = GetDistanceBetween(oCreature, oAttacker); + float fPerceptionDistance = GetLocalFloat(oCreature, AI_ASSOC_PERCEPTION_DISTANCE); + if(fDistance > fPerceptionDistance) return; + } + int nAction = GetCurrentAction(oCreature); + float fDistance = GetDistanceBetween(oCreature, oAttacker); + if(!ai_CanIAttack(oCreature)) + { + // We should defend ourselves if we are in Hold mode. + if(!ai_GetAIMode(oCreature, AI_MODE_STAND_GROUND)) return; + // Only defend against melee attacks. + if(fDistance > AI_RANGE_MELEE) return; + } + // The only way to get here is to not be in combat. + if(fDistance < AI_RANGE_CLOSE) + { + ai_StartAssociateCombat(oCreature); + } + else ActionMoveToObject(oAttacker, TRUE, AI_RANGE_CLOSE - 1.0); +} + + diff --git a/src/module/nss/nw_ch_ac6.nss b/src/module/nss/nw_ch_ac6.nss new file mode 100644 index 0000000..f51e937 --- /dev/null +++ b/src/module/nss/nw_ch_ac6.nss @@ -0,0 +1,32 @@ +/*////////////////////////////////////////////////////////////////////////////// + Script: 0e_ch_6_damaged + Programmer: Philos +//////////////////////////////////////////////////////////////////////////////// + Player OnDamaged script for PC AI; + Does not fire if the creature dies from the damage. + Does not fire for plot creatures as they take no damage. + May fire before or after OnPhysicalAttacked event. + Fires when EffectDamage is applied to oCreature even if 0 damage. + Fires when a weapon damages a oCreature, but not if resisted. +*/////////////////////////////////////////////////////////////////////////////// +#include "0i_associates" +void main() +{ + object oCreature = OBJECT_SELF; + if(ai_Disabled(oCreature)) return; + // Make sure to clear wounded shout limit if we take damage. See ai_TryHealing. + DeleteLocalInt(oCreature, "AI_WOUNDED_SHOUT_LIMIT"); + object oDamager = GetLastDamager(oCreature); + if(AI_DEBUG) ai_Debug("nw_ch_ac6", "18", GetName(oCreature) + " has been damaged by " + GetName(oDamager)); + if(GetSpawnInCondition(NW_FLAG_DAMAGED_EVENT)) + { + SignalEvent(OBJECT_SELF, EventUserDefined(1006)); + } + if(GetObjectType(oDamager) == OBJECT_TYPE_AREA_OF_EFFECT && + ai_IsInADangerousAOE(oCreature, AI_RANGE_BATTLEFIELD, TRUE)) return; + if(ai_GetIsBusy(oCreature) || ai_GetIsInCombat(oCreature)) return; + if(!ai_CanIAttack(oCreature)) return; + if(GetDistanceBetween(oCreature, oDamager) < AI_RANGE_CLOSE) ai_DoAssociateCombatRound(oCreature); + else ActionMoveToObject(oDamager, TRUE, AI_RANGE_CLOSE - 1.0); +} + diff --git a/src/module/nss/nw_ch_ac8.nss b/src/module/nss/nw_ch_ac8.nss new file mode 100644 index 0000000..05b7f85 --- /dev/null +++ b/src/module/nss/nw_ch_ac8.nss @@ -0,0 +1,25 @@ +/*////////////////////////////////////////////////////////////////////////////// + Script: nw_ch_ac8 + Programmer: Philos +//////////////////////////////////////////////////////////////////////////////// + Associates (Summons, Familiars, Companions) OnDisturbed event script. + Fires when the inventory of oCreature is changed i.e. added or removed. + Creatures can't have items added or removed from its inventory (it's not a + container), then the only way this fires for creatures if something is stolen. +*/////////////////////////////////////////////////////////////////////////////// +#include "0i_associates" +void main() +{ + if(AI_DEBUG) ai_Debug("nw_ch_ac8", "13", GetName(OBJECT_SELF) + " is been disturbed!"); + if(GetSpawnInCondition(NW_FLAG_DISTURBED_EVENT)) + { + SignalEvent(OBJECT_SELF, EventUserDefined(1008)); + } + // We do nothing at the moment... lets not mess up our factions ok? + // This should be defined by the server admins and is commented out. + //if(ai_GetIsBusy(OBJECT_SELF, FALSE) || ai_Disabled()) return; + //object oTarget = GetLastDisturbed(); + //if (oTarget != OBJECT_INVALID) ai_DoMonsterCombatRound (); +} + + diff --git a/src/module/nss/nw_ch_aca.nss b/src/module/nss/nw_ch_aca.nss new file mode 100644 index 0000000..99b6d5f --- /dev/null +++ b/src/module/nss/nw_ch_aca.nss @@ -0,0 +1,46 @@ +/*////////////////////////////////////////////////////////////////////////////// + Script: nw_ch_aca + Programmer: Philos +//////////////////////////////////////////////////////////////////////////////// + Associate OnRested event script; + Fires when the creature attempts to rest via ActionRest or a PC rests. +*/////////////////////////////////////////////////////////////////////////////// +#include "0i_menus" +void ai_UpdateAssociateWidget(object oMaster, object oAssociate, int nUIToken) +{ + if(nUIToken) NuiDestroy(oMaster, nUIToken); + ai_CreateWidgetNUI(oMaster, oAssociate); + if(oMaster != oAssociate) + { + nUIToken = NuiFindWindow(oMaster, "pc" + AI_WIDGET_NUI); + if(nUIToken) + { + NuiDestroy(oMaster, nUIToken); + ai_CreateWidgetNUI(oMaster, oMaster); + } + } +} +void main() +{ + object oAssociate = OBJECT_SELF; + ai_ClearCreatureActions(); + ai_OnRested(oAssociate); + object oMaster = GetMaster(oAssociate); + if(ai_GetIsCharacter(oMaster) && AI_HENCHMAN_WIDGET) + { + int nLevel = ai_GetCharacterLevels(oAssociate); + float fDelay = StringToFloat(Get2DAString("restduration", "DURATION", nLevel)); + fDelay = (fDelay / 1000.0f) + 6.0f; + // Update widget for spell widget. + string sAssociateType = ai_GetAssociateType(oMaster, oAssociate); + int nUIToken = NuiFindWindow(oMaster, sAssociateType + AI_WIDGET_NUI); + if(nUIToken) DelayCommand(fDelay, ai_UpdateAssociateWidget(oMaster, oAssociate, nUIToken)); + else + { + if(!ai_GetWidgetButton(oMaster, BTN_WIDGET_OFF, oAssociate, sAssociateType)) + { + DelayCommand(fDelay, ai_UpdateAssociateWidget(oMaster, oAssociate, 0)); + } + } + } +} diff --git a/src/module/nss/nw_ch_acb.nss b/src/module/nss/nw_ch_acb.nss new file mode 100644 index 0000000..ec96e77 --- /dev/null +++ b/src/module/nss/nw_ch_acb.nss @@ -0,0 +1,42 @@ +/*////////////////////////////////////////////////////////////////////////////// + Script: nw_ch_acb + Programmer: Philos +//////////////////////////////////////////////////////////////////////////////// + Associates (Summons, Familiars, Companions) OnSpellCastAt event script; + Fires when oCreature becomes the target of a spell via SignalEvent. + Fires when a healing kit is used on a creature. +*/////////////////////////////////////////////////////////////////////////////// +#include "0i_associates" +void main() +{ + object oCreature = OBJECT_SELF; + object oCaster = GetLastSpellCaster(); + SetLocalObject(oCaster, AI_ATTACKED_SPELL, oCreature); + if(ai_Disabled(oCreature)) return; + if(!GetLastSpellHarmful()) return; + // If the spell came from an ally, we don't want to hold it against them. + if(GetFactionEqual(oCaster, oCreature)) + { + ClearPersonalReputation(oCaster, oCreature); + if(GetSpawnInCondition(NW_FLAG_SPELL_CAST_AT_EVENT)) + { + SignalEvent(OBJECT_SELF, EventUserDefined(EVENT_SPELL_CAST_AT)); + } + } + // Lets see what kind of area of effect this is and select an appropriate action. + int nSpell = GetLastSpell(); + if(AI_DEBUG) ai_Debug("nw_ch_acb", "21", GetName(OBJECT_SELF) + " has been hit by a harmful spell(" + + Get2DAString("spells", "Label", nSpell) + ")!"); + if(ai_GetInAOEReaction(oCreature, oCaster, nSpell) && + ai_IsInADangerousAOE(oCreature, AI_RANGE_BATTLEFIELD, TRUE)) return; + if(ai_GetIsBusy(oCreature)) return; + if(ai_CheckForCombat(oCreature, FALSE)) return; + // We were attacked by an enemy out of combat, so let our allies know. + SetLocalObject(oCreature, AI_MY_TARGET, oCaster); + SpeakString(AI_ATKED_BY_SPELL, TALKVOLUME_SILENT_TALK); + if(!ai_CanIAttack(oCreature)) return; + if(GetDistanceBetween(oCreature, oCaster) < AI_RANGE_CLOSE) ai_DoAssociateCombatRound(oCreature); + else ActionMoveToObject(oCaster, TRUE, AI_RANGE_CLOSE - 1.0); +} + + diff --git a/src/module/nss/nw_ch_ace.nss b/src/module/nss/nw_ch_ace.nss new file mode 100644 index 0000000..688ab90 --- /dev/null +++ b/src/module/nss/nw_ch_ace.nss @@ -0,0 +1,60 @@ +/*////////////////////////////////////////////////////////////////////////////// + Script: 0e_ch_e_blocked + Programmer: Philos +//////////////////////////////////////////////////////////////////////////////// + Associates OnBlocked event script; + Can be blocked by a creature or door. +*/////////////////////////////////////////////////////////////////////////////// +#include "0i_associates" +void main() +{ + object oCreature = OBJECT_SELF; + // This actually gets either a Creature or Door that is blocking OBJECT_SELF. + object oObject = GetBlockingDoor(); + if(AI_DEBUG) ai_Debug("nw_ch_ace", "14", GetName(oCreature) + " is being blocked by " + GetName(oObject)); + int nObjectType = GetObjectType(oObject); + if(nObjectType == OBJECT_TYPE_CREATURE) + { + if(GetIsEnemy(oObject, oCreature)) + { + if(ai_CanIAttack(oCreature) && ai_GetIsInCombat(oCreature)) + { + ai_DoAssociateCombatRound(oCreature); + return; + } + if(ai_CheckForCombat(oCreature, FALSE)) return; + } + } + // Anything below blocking us is a door. + if(nObjectType != OBJECT_TYPE_DOOR) return; + if(!ai_GetAIMode(oCreature, AI_MODE_OPEN_DOORS)) return; + //if(GetLockKeyTag(oObject) != "") return; + else if(GetIsDoorActionPossible(oObject, DOOR_ACTION_OPEN) && + GetAbilityScore(oCreature, ABILITY_INTELLIGENCE) >= 5) + { + DoDoorAction(oObject, DOOR_ACTION_OPEN); + return; + } + // Anything below is ignored in combat. + if(ai_GetIsInCombat(oCreature)) return; + if(GetIsDoorActionPossible(oObject, DOOR_ACTION_BASH) && + ai_GetWeaponDamage(oCreature, 3, TRUE) > GetHardness(oObject) && + GetLockKeyTag(oObject) == "") + { + ActionWait(1.0); + ActionAttack(oObject); + // Give them 3 rounds to break through a door. + DelayCommand(18.0, ai_ClearCreatureActions(TRUE)); + return; + } + else if(GetLocked(oObject)) + { + if(AI_DEBUG) ai_Debug("nw_ch_ace", "49", GetName(oObject) + " is locked!"); + ai_AttemptToByPassLock(oCreature, oObject); + } + // Clear our action so we can move on to something else unless the door is open. + else if(!GetIsOpen(oObject)) + { + ai_ClearCreatureActions(); + } +} diff --git a/src/module/nss/nw_ch_summon_9.nss b/src/module/nss/nw_ch_summon_9.nss index 596669a..ca5a87c 100644 --- a/src/module/nss/nw_ch_summon_9.nss +++ b/src/module/nss/nw_ch_summon_9.nss @@ -1,66 +1,40 @@ //:://///////////////////////////////////////////// //:: Associate: On Spawn In -//:: NW_CH_SUMMON_9 +//:: nw_ch_summon_9 //:: Copyright (c) 2001 Bioware Corp. //::////////////////////////////////////////////// +/* + +This must support the OC henchmen and all summoned/companion +creatures. + +*/ //::////////////////////////////////////////////// //:: Created By: Preston Watamaniuk //:: Created On: Nov 19, 2001 //::////////////////////////////////////////////// - -#include "NW_I0_GENERIC" - +//:: Updated By: Georg Zoeller, 2003-08-20: Added variable check for spawn in animation +#include "X0_INC_HENAI" +#include "x2_inc_switches" void main() { - SetAssociateListenPatterns();//Sets up the special henchmen listening patterns - SetListeningPatterns(); // Goes through and sets up which shouts the NPC will listen to. + //Sets up the special henchmen listening patterns + SetAssociateListenPatterns(); - SetAssociateState(NW_ASC_POWER_CASTING); - SetAssociateState(NW_ASC_HEAL_AT_50); - SetAssociateState(NW_ASC_DISTANCE_2_METERS); - - // April 2002: Summoned monsters, associates and familiars need to stay - // further back due to their size. - if (GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION, GetMaster()) == OBJECT_SELF || - GetAssociate(ASSOCIATE_TYPE_DOMINATED, GetMaster()) == OBJECT_SELF || - GetAssociate(ASSOCIATE_TYPE_FAMILIAR, GetMaster()) == OBJECT_SELF || - GetAssociate(ASSOCIATE_TYPE_SUMMONED, GetMaster()) == OBJECT_SELF) + // Set additional henchman listening patterns + //bkSetListeningPatterns(); + // * If Incorporeal, apply changes + if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_IS_INCORPOREAL) == TRUE) { - SetAssociateState(NW_ASC_DISTANCE_4_METERS); + effect eConceal = EffectConcealment(50, MISS_CHANCE_TYPE_NORMAL); + eConceal = ExtraordinaryEffect(eConceal); + effect eGhost = EffectCutsceneGhost(); + eGhost = ExtraordinaryEffect(eGhost); + ApplyEffectToObject(DURATION_TYPE_PERMANENT, eConceal, OBJECT_SELF); + ApplyEffectToObject(DURATION_TYPE_PERMANENT, eGhost, OBJECT_SELF); } - - - SetAssociateState(NW_ASC_RETRY_OPEN_LOCKS, FALSE); - SetAssociateState(NW_ASC_DISARM_TRAPS, FALSE); - SetAssociateState(NW_ASC_MODE_DEFEND_MASTER, FALSE); - SetAssociateState(NW_ASC_USE_RANGED_WEAPON, FALSE); //User ranged weapons by default if true. - - //SetAssociateState(NW_ASC_MODE_DEFEND_MASTER); + // Set starting location SetAssociateStartLocation(); - // SPECIAL CONVERSATION SETTTINGS - //SetSpawnInCondition(NW_FLAG_SPECIAL_CONVERSATION); - //SetSpawnInCondition(NW_FLAG_SPECIAL_COMBAT_CONVERSATION); - // This causes the creature to say a special greeting in their conversation file - // upon Perceiving the player. Attach the [NW_D2_GenCheck.nss] script to the desired - // greeting in order to designate it. As the creature is actually saying this to - // himself, don't attach any player responses to the greeting. - - SetListenPattern(OBJECT_SELF, "**", 20600); //listen to all text - SetLocalInt(OBJECT_SELF, "hls_Listening", 1); //listen to all text - SetListening(OBJECT_SELF, TRUE); //be sure NPC is listening - -// CUSTOM USER DEFINED EVENTS -/* - The following settings will allow the user to fire one of the blank user defined events in the NW_D2_DefaultD. Like the - On Spawn In script this script is meant to be customized by the end user to allow for unique behaviors. The user defined - events user 1000 - 1010 -*/ - //SetSpawnInCondition(NW_FLAG_PERCIEVE_EVENT); //OPTIONAL BEHAVIOR - Fire User Defined Event 1002 - //SetSpawnInCondition(NW_FLAG_ATTACK_EVENT); //OPTIONAL BEHAVIOR - Fire User Defined Event 1005 - //SetSpawnInCondition(NW_FLAG_DAMAGED_EVENT); //OPTIONAL BEHAVIOR - Fire User Defined Event 1006 - //SetSpawnInCondition(NW_FLAG_DISTURBED_EVENT); //OPTIONAL BEHAVIOR - Fire User Defined Event 1008 - //SetSpawnInCondition(NW_FLAG_END_COMBAT_ROUND_EVENT); //OPTIONAL BEHAVIOR - Fire User Defined Event 1003 - //SetSpawnInCondition(NW_FLAG_ON_DIALOGUE_EVENT); //OPTIONAL BEHAVIOR - Fire User Defined Event 1004 - //SetSpawnInCondition(NW_FLAG_DEATH_EVENT); //OPTIONAL BEHAVIOR - Fire User Defined Event 1007 } + diff --git a/src/module/nss/pc_savebuffs.nss b/src/module/nss/pc_savebuffs.nss new file mode 100644 index 0000000..96b42d0 --- /dev/null +++ b/src/module/nss/pc_savebuffs.nss @@ -0,0 +1,182 @@ +/*////////////////////////////////////////////////////////////////////////////// +// Script Name: pc_savebuffs +//////////////////////////////////////////////////////////////////////////////// + Used with pi_buffing to run the buffing plugin for + Philos Single Player Enhancements. + +Note: If a spell saves incorrectly check the spell script to see if the correct +spell is being passed through the SignalEvent correctly. +Known error in Shield of Faith spell as the below code in the shield of faith +script sends Camoflage instead! +"SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, 421, FALSE));" +*/////////////////////////////////////////////////////////////////////////////// +#include "0i_nui" +// sDataField should be one of the data fields for the table. +// Returns a string of the data stored. +string GetBuffDatabaseString(object oPlayer, string sDataField, string sTag = ""); +// sDataField should be one of the data fields for that table. +// sData is the string data to be saved. +void SetBuffDatabaseString(object oPlayer, string sDataField, string sData, string sTag = ""); +// sDataField should be one of the data fields for that table. +// jData is the json data to be saved. +void SetBuffDatabaseJson(object oPlayer, string sDataField, json jData, string sTag = ""); +// sDataField should be one of the data fields for the table. +// Returns a string of the data stored. +json GetBuffDatabaseJson(object oPlayer, string sDataField, string sTag = ""); +// Returns the level if this spell has a domain spell on nLevel, or 0. +int GetHasDomainSpell(object oCaster, int nClass, int nLevel, int nSpell); + +// We do some crazy hack to get all the correct information when casting spells. +// GetLastSpellCastClass() will only give the class if this script is running +// on the actual caster, i.e. our PC. +// GetLastSpellLevel() will only give the level if this script is running on +// the actual caster, i.e. our PC. +// So for this to work we run this scrip in the event OnSpellCastAt of our +// target, then we ExecuteScript this script again with the Caster (oPC) +// as OBJECT_SELF for this script on its second pass. This allows us to get the +// information from the above functions! Neat! +void main() +{ + object oTarget = OBJECT_SELF; + // The first pass we get oCaster via GetLastSpellCaster() fails in ExecuteScript! + // The second pass we get oCaster via the variable "AI_BUFF_CASTER". + object oCaster = GetLocalObject(oTarget, "AI_BUFF_CASTER"); + if(oCaster == OBJECT_INVALID) oCaster = GetLastSpellCaster(); + // We setting up the save spells button we saved the PC to itself. + // Here we get the PC to make sure the caster of this spell is our saving PC. + object oPC = GetLocalObject(oCaster, "AI_BUFF_PC"); + // The first pass we get nspell via GetLastSpell() fails in ExecuteScript! + // The second pass we get nSpell via the variable "AI_BUFF_SPELL". + int nSpell = GetLocalInt(oTarget, "AI_BUFF_SPELL"); + if(nSpell == 0) nSpell = GetLastSpell(); + // If this is a harful spell or The caster does not equal our saving PC then + // we need to fix the targets scripts back and run the correct OnSpellCastAt script. + if(GetLastSpellHarmful() || oPC != oCaster) + { + string sScript = GetLocalString(oTarget, "AI_BUFF_CAST_AT_SCRIPT"); + SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, sScript); + ExecuteScript(sScript, oTarget); + return; + } + // If the oTarget != oCaster then we are casting a spell on one of our + // associates. We must make a second pass to get the correct information. + // We do this by saving the Target, Caster, and Spell so we can get them + // in the second pass as Execute Script makes them impossible to get on a + // second pass. + if(oTarget != oCaster) + { + SetLocalObject(oPC, "AI_BUFF_TARGET", oTarget); + SetLocalObject(oPC, "AI_BUFF_CASTER", oCaster); + SetLocalInt(oPC, "AI_BUFF_SPELL", nSpell); + ExecuteScript("pc_savebuffs", oPC); + return; + } + // If this is the first pass and we get here then oCaster is casting a spell + // on themselves. So oTarget will be invalid and we should use oPC. + // If this is the second pass and we get here then we have saved oTarget + // to oPC and this will get them so we can save the target to the spell! + oTarget = GetLocalObject(oPC, "AI_BUFF_TARGET"); + if(oTarget == OBJECT_INVALID) oTarget = oPC; + // We need to clean up this mess! + DeleteLocalObject(oPC, "AI_BUFF_TARGET"); + DeleteLocalObject(oPC, "AI_BUFF_CASTER"); + DeleteLocalInt(oPC, "AI_BUFF_SPELL"); + // This blocks one spell from saving multiple times due to being an AOE. + if(GetLocalInt(oPC, "AI_ONLY_ONE")) return; + SetLocalInt(oPC, "AI_ONLY_ONE", TRUE); + // We delay this for just less than half a round due to haste. + DelayCommand(2.5, DeleteLocalInt(oPC, "AI_ONLY_ONE")); + // Here is the whole problem and why we must do a second pass if the target + // is not the caster. These only work if this script is run by the caster. + int nClass = GetLastSpellCastClass(); + int nLevel = GetLastSpellLevel(); + // Everything below saves the spell to the database with all our now correct info. + int nDomain = GetHasDomainSpell(oPC, nClass, nLevel, nSpell); + int nMetaMagic = GetMetaMagicFeat(); + string sName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); + if(nDomain) sName += " [Domain]"; + if(nMetaMagic > 0 && StringToInt(Get2DAString("classes", "MemorizesSpells", nClass))) + { + // We must add the level of the metamagic to the spells level to get the spells correct level. + if(nMetaMagic == METAMAGIC_EMPOWER) { sName += " (Empowered)"; nLevel += 2; } + else if(nMetaMagic == METAMAGIC_EXTEND) { sName += " (Extended)"; nLevel += 1; } + else if(nMetaMagic == METAMAGIC_MAXIMIZE) { sName += " (Maximized)"; nLevel += 3; } + else if(nMetaMagic == METAMAGIC_QUICKEN) { sName += " (Quickened)"; nLevel += 4; } + else if(nMetaMagic == METAMAGIC_SILENT) { sName += " (Silent)"; nLevel += 1; } + else if(nMetaMagic == METAMAGIC_STILL) { sName += " (Still)"; nLevel += 1; } + } + json jMenuData = GetBuffDatabaseJson(oPC, "spells", "menudata"); + string sList = JsonGetString(JsonArrayGet(jMenuData, 0)); + json jSpells = GetBuffDatabaseJson(oPC, "spells", sList); + json jSpell = JsonArray(); + jSpell = JsonArrayInsert(jSpell, JsonInt(nSpell)); + jSpell = JsonArrayInsert(jSpell, JsonInt(nClass)); + jSpell = JsonArrayInsert(jSpell, JsonInt(nLevel)); + jSpell = JsonArrayInsert(jSpell, JsonInt(nMetaMagic)); + jSpell = JsonArrayInsert(jSpell, JsonInt(nDomain)); + string sTargetName = ai_RemoveIllegalCharacters(ai_StripColorCodes(GetName(oTarget, TRUE))); + jSpell = JsonArrayInsert(jSpell, JsonString(sTargetName)); + jSpell = JsonArrayInsert(jSpells, jSpell); + SetBuffDatabaseJson(oPC, "spells", jSpells, sList); + SendMessageToPC(oPC, sName + " has been saved for fast buffing on " + sTargetName + "."); + ExecuteScript("pi_buffing", oPC); +} +string GetBuffDatabaseString(object oPlayer, string sDataField, string sTag) +{ + string sName = ai_RemoveIllegalCharacters(ai_StripColorCodes(GetName(oPlayer, TRUE))); + string sQuery = "SELECT " + sDataField + " FROM BUFF_TABLE WHERE name = @name AND tag = @tag;"; + sqlquery sql = SqlPrepareQueryObject(oPlayer, sQuery); + SqlBindString(sql, "@name", sName); + SqlBindString(sql, "@tag", sTag); + if (SqlStep (sql)) return SqlGetString (sql, 0); + else return ""; +} +void SetBuffDatabaseString(object oPlayer, string sDataField, string sData, string sTag) +{ + string sName = ai_RemoveIllegalCharacters(ai_StripColorCodes(GetName(oPlayer, TRUE))); + string sQuery = "UPDATE BUFF_TABLE SET " + sDataField + " = @data WHERE name = @name AND tag = @tag;"; + sqlquery sql = SqlPrepareQueryObject(oPlayer, sQuery); + SqlBindString(sql, "@data", sData); + SqlBindString(sql, "@name", sName); + SqlBindString(sql, "@tag", sTag); + SqlStep (sql); +} +void SetBuffDatabaseJson (object oPlayer, string sDataField, json jData, string sTag) +{ + string sName = ai_RemoveIllegalCharacters(ai_StripColorCodes(GetName(oPlayer, TRUE))); + string sQuery = "UPDATE BUFF_TABLE SET " + sDataField + " = @data WHERE name = @name AND tag = @tag;"; + sqlquery sql = SqlPrepareQueryObject(oPlayer, sQuery); + SqlBindJson (sql, "@data", jData); + SqlBindString (sql, "@name", sName); + SqlBindString (sql, "@tag", sTag); + SqlStep (sql); +} +json GetBuffDatabaseJson (object oPlayer, string sDataField, string sTag) +{ + string sName = ai_RemoveIllegalCharacters(ai_StripColorCodes(GetName(oPlayer, TRUE))); + string sQuery = "SELECT " + sDataField + " FROM BUFF_TABLE WHERE name = @name AND tag = @tag;"; + sqlquery sql = SqlPrepareQueryObject(oPlayer, sQuery); + SqlBindString (sql, "@name", sName); + SqlBindString (sql, "@tag", sTag); + if (SqlStep (sql)) return SqlGetJson (sql, 0); + else return JsonArray (); +} +int GetHasDomainSpell(object oCaster, int nClass, int nLevel, int nSpell) +{ + int nIndex, nMaxIndex, nMSpell, nMmSpell, bDomain, nSubRadSpell, nSubSpell; + string sSubRadSpell; + if(StringToInt(Get2DAString("classes", "MemorizesSpells", nClass))) + { + nMaxIndex = GetMemorizedSpellCountByLevel(oCaster, nClass, nLevel); + while(nIndex < nMaxIndex) + { + nMSpell = GetMemorizedSpellId(oCaster, nClass, nLevel, nIndex); + if(nSpell == nMSpell) + { + if(GetMemorizedSpellIsDomainSpell(oCaster, nClass, nLevel, nIndex)) return nLevel; + } + nIndex ++; + } + } + return 0; +} diff --git a/src/module/nss/pe_buffing.nss b/src/module/nss/pe_buffing.nss new file mode 100644 index 0000000..a6c4050 --- /dev/null +++ b/src/module/nss/pe_buffing.nss @@ -0,0 +1,534 @@ +/*////////////////////////////////////////////////////////////////////////////// +// Script Name: pe_buffing +//////////////////////////////////////////////////////////////////////////////// + Used with pi_buffing to run the buffing plugin for + Philos Single Player Enhancements. +*/////////////////////////////////////////////////////////////////////////////// +#include "0i_nui" + +const int BUFF_MAX_SPELLS = 50; +const string FB_NO_MONSTER_CHECK = "FB_NO_MONSTER_CHECK"; + +// sDataField should be one of the data fields for that table. +// sData is the string data to be saved. +void SetBuffDatabaseString(object oPlayer, string sDataField, string sData, string sTag); +// sDataField should be one of the data fields for the table. +// Returns a string of the data stored. +string GetBuffDatabaseString(object oPlayer, string sDataField, string sTag); +// sDataField should be one of the data fields for that table. +// jData is the json data to be saved. +void SetBuffDatabaseJson(object oPlayer, string sDataField, json jData, string sTag); +// sDataField should be one of the data fields for the table. +// Returns a string of the data stored. +json GetBuffDatabaseJson(object oPlayer, string sDataField, string sTag); +// Casts all buff spells saved to the widget button. +void CastSavedBuffSpells(object oPC); +// Will check and make sure the spell is memorized and/or ready. +// Returns TRUE if memorized and ready, FALSE if memorized but not ready, +// and -1 if not memorized for classes that memorize. +// nSpell is the spell to find. +// nClass that cast the spell. +// nLevel the level of the spell. +// nMetamagic is if it has metamagic on it. +// nDomain is if it is a domain spell. +int GetSpellReady(object oCaster, int nSpell, int nClass, int nLevel, int nMetamagic, int nDomain); +// Creates the Buffing widget. +void PopupWidgetBuffGUIPanel(object oPC); +void main() +{ + object oPC = NuiGetEventPlayer(); + int nToken = NuiGetEventWindow(); + string sEvent = NuiGetEventType(); + string sElem = NuiGetEventElement(); + string sWndId = NuiGetWindowId (oPC, nToken); + //************************************************************************** + // Watch to see if the window moves and save. + if(sElem == "window_geometry" && sEvent == "watch") + { + if(!GetLocalInt (oPC, AI_NO_NUI_SAVE)) + { + // Get the height, width, x, and y of the window. + json jGeom = NuiGetBind(oPC, nToken, "window_geometry"); + // Save on the player using the sWndId. + json jMenuData = GetBuffDatabaseJson(oPC, "spells", "menudata"); + if(sWndId == "plbuffwin") + { + jMenuData = JsonArraySet(jMenuData, 1, JsonObjectGet(jGeom, "x")); + jMenuData = JsonArraySet(jMenuData, 2, JsonObjectGet(jGeom, "y")); + } + else if(sWndId == "widgetbuffwin") + { + jMenuData = JsonArraySet(jMenuData, 5, JsonObjectGet(jGeom, "x")); + jMenuData = JsonArraySet(jMenuData, 6, JsonObjectGet(jGeom, "y")); + } + SetBuffDatabaseJson(oPC, "spells", jMenuData, "menudata"); + } + return; + } + //************************************************************************** + // Spell Buffing. + if(sWndId == "plbuffwin") + { + if(sEvent == "click") + { + string sList; + if(GetStringLeft(sElem, 10) == "btn_spell_") + { + json jMenuData = GetBuffDatabaseJson(oPC, "spells", "menudata"); + sList = JsonGetString(JsonArrayGet(jMenuData, 0)); + json jSpells = GetBuffDatabaseJson(oPC, "spells", sList); + int nIndex = StringToInt(GetStringRight(sElem, GetStringLength(sElem) - 10)); + int nSpell = JsonGetInt(JsonArrayGet(JsonArrayGet(jSpells, nIndex), 0)); + string sName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); + jSpells = JsonArrayDel(jSpells, nIndex); + SetBuffDatabaseJson(oPC, "spells", jSpells, sList); + ai_SendMessages(sName + " has been removed from the list.", AI_COLOR_YELLOW, oPC); + ExecuteScript("pi_buffing", oPC); + } + else if(sElem == "btn_save") + { + string sScript; + object oCreature; + if(JsonGetInt(NuiGetBind (oPC, nToken, "btn_save"))) + { + sScript = GetEventScript(oPC, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT); + SetLocalObject(oPC, "AI_BUFF_PC", oPC); + SetLocalString(oPC, "AI_BUFF_CAST_AT_SCRIPT", sScript); + SetEventScript(oPC, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, "pc_savebuffs"); + // Setup your followers to allow spells to be saved on them as well. + int nAssociateType = 2; + object oAssociate = GetAssociate(nAssociateType, oPC); + while(nAssociateType < 5) + { + if(oAssociate != OBJECT_INVALID) + { + SetLocalString(oAssociate, "AI_BUFF_CAST_AT_SCRIPT", sScript); + SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, "pc_savebuffs"); + } + oAssociate = GetAssociate(++nAssociateType, oPC); + } + int nIndex = 1; + oAssociate = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex); + while(nIndex <= AI_MAX_HENCHMAN) + { + if(oAssociate != OBJECT_INVALID) + { + SetLocalString(oAssociate, "AI_BUFF_CAST_AT_SCRIPT", sScript); + SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, "pc_savebuffs"); + } + oAssociate = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, ++nIndex); + } + ai_SendMessages("Cast spells on yourself or an associate to save them to the widget.", AI_COLOR_YELLOW, oPC); + } + else + { + DeleteLocalObject(oPC, "AI_BUFF_PC"); + sScript = GetLocalString(oPC, "AI_BUFF_CAST_AT_SCRIPT"); + SetEventScript(oPC, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, sScript); + DeleteLocalString(oPC, "AI_BUFF_CAST_AT_SCRIPT"); + // Cleanup your followers to allow spells to be reacted to as normal. + int nAssociateType = 2; + object oAssociate = GetAssociate(nAssociateType, oPC); + while(nAssociateType < 5) + { + if(oAssociate != OBJECT_INVALID) + { + sScript = GetLocalString(oAssociate, "AI_BUFF_CAST_AT_SCRIPT"); + SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, sScript); + DeleteLocalString(oAssociate, "AI_BUFF_CAST_AT_SCRIPT"); + } + oAssociate = GetAssociate(++nAssociateType, oPC); + } + int nIndex = 1; + oAssociate = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex); + while(nIndex <= AI_MAX_HENCHMAN) + { + if(oAssociate != OBJECT_INVALID) + { + sScript = GetLocalString(oAssociate, "AI_BUFF_CAST_AT_SCRIPT"); + SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, sScript); + DeleteLocalString(oAssociate, "AI_BUFF_CAST_AT_SCRIPT"); + } + oAssociate = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, ++nIndex); + } + NuiSetBind(oPC, nToken, "btn_save", JsonBool(FALSE)); + ai_SendMessages("Saving spells to the list has been turned off.", AI_COLOR_YELLOW, oPC); + } + } + else if(sElem == "btn_clear") + { + json jMenuData = GetBuffDatabaseJson(oPC, "spells", "menudata"); + sList = JsonGetString(JsonArrayGet(jMenuData, 0)); + SetBuffDatabaseJson(oPC, "spells", JsonArray(), sList); + ExecuteScript("pi_buffing", oPC); + } + else if(sElem == "btn_buff") CastSavedBuffSpells(oPC); + // Runs all the List 1-4 buttons. + if(GetStringLeft(sElem, 8) == "btn_list") + { + sList = "list" + GetStringRight(sElem, 1); + json jMenuData = GetBuffDatabaseJson(oPC, "spells", "menudata"); + jMenuData = JsonArraySet(jMenuData, 0, JsonString(sList)); + SetBuffDatabaseJson(oPC, "spells", jMenuData, "menudata"); + ExecuteScript("pi_buffing", oPC); + } + } + else if(sEvent == "watch") + { + if(sElem == "buff_widget_check") + { + int bBuffWidget = JsonGetInt(NuiGetBind(oPC, nToken, "buff_widget_check")); + json jMenuData = GetBuffDatabaseJson(oPC, "spells", "menudata"); + jMenuData = JsonArraySet(jMenuData, 3, JsonBool(bBuffWidget)); + SetBuffDatabaseJson(oPC, "spells", jMenuData, "menudata"); + if(bBuffWidget) PopupWidgetBuffGUIPanel(oPC); + else NuiDestroy(oPC, NuiFindWindow(oPC, "widgetbuffwin")); + } + if(sElem == "lock_buff_widget_check") + { + int bBuffLockWidget = JsonGetInt(NuiGetBind(oPC, nToken, "lock_buff_widget_check")); + json jMenuData = GetBuffDatabaseJson(oPC, "spells", "menudata"); + if(bBuffLockWidget) jMenuData = JsonArraySet(jMenuData, 3, JsonBool(TRUE)); + jMenuData = JsonArraySet(jMenuData, 4, JsonBool(bBuffLockWidget)); + SetBuffDatabaseJson(oPC, "spells", jMenuData, "menudata"); + NuiSetBind(oPC, nToken, "buff_widget_check", JsonBool(TRUE)); + PopupWidgetBuffGUIPanel(oPC); + } + if(sElem == "chbx_no_monster_check_check") + { + int bNoCheckMonsters = JsonGetInt(NuiGetBind(oPC, nToken, sElem)); + SetLocalInt(oPC, FB_NO_MONSTER_CHECK, bNoCheckMonsters); + } + } + } + //************************************************************************** + // Spell Buffing. + else if(sWndId == "widgetbuffwin") + { + if(sEvent == "click") + { + string sList; + if(sElem == "btn_one") sList = "list1"; + if(sElem == "btn_two") sList = "list2"; + if(sElem == "btn_three") sList = "list3"; + if(sElem == "btn_four") sList = "list4"; + json jMenuData = GetBuffDatabaseJson(oPC, "spells", "menudata"); + jMenuData = JsonArraySet(jMenuData, 0, JsonString(sList)); + SetBuffDatabaseJson(oPC, "spells", jMenuData, "menudata"); + CastSavedBuffSpells(oPC); + } + } +} +void SetBuffDatabaseString(object oPlayer, string sDataField, string sData, string sTag) +{ + string sName = ai_RemoveIllegalCharacters(ai_StripColorCodes(GetName(oPlayer, TRUE))); + string sQuery = "UPDATE BUFF_TABLE SET " + sDataField + " = @data WHERE name = @name AND tag = @tag;"; + sqlquery sql = SqlPrepareQueryObject(oPlayer, sQuery); + SqlBindString(sql, "@data", sData); + SqlBindString(sql, "@name", sName); + SqlBindString(sql, "@tag", sTag); + SqlStep (sql); +} +string GetBuffDatabaseString(object oPlayer, string sDataField, string sTag) +{ + string sName = ai_RemoveIllegalCharacters(ai_StripColorCodes(GetName(oPlayer, TRUE))); + string sQuery = "SELECT " + sDataField + " FROM BUFF_TABLE WHERE name = @name AND tag = @tag;"; + sqlquery sql = SqlPrepareQueryObject(oPlayer, sQuery); + SqlBindString(sql, "@name", sName); + SqlBindString(sql, "@tag", sTag); + if (SqlStep (sql)) return SqlGetString (sql, 0); + else return ""; +} +void SetBuffDatabaseJson (object oPlayer, string sDataField, json jData, string sTag) +{ + string sName = ai_RemoveIllegalCharacters(ai_StripColorCodes(GetName(oPlayer, TRUE))); + string sQuery = "UPDATE BUFF_TABLE SET " + sDataField + " = @data WHERE name = @name AND tag = @tag;"; + sqlquery sql = SqlPrepareQueryObject(oPlayer, sQuery); + SqlBindJson (sql, "@data", jData); + SqlBindString (sql, "@name", sName); + SqlBindString (sql, "@tag", sTag); + SqlStep (sql); +} +json GetBuffDatabaseJson (object oPlayer, string sDataField, string sTag) +{ + string sName = ai_RemoveIllegalCharacters(ai_StripColorCodes(GetName(oPlayer, TRUE))); + string sQuery = "SELECT " + sDataField + " FROM BUFF_TABLE WHERE name = @name AND tag = @tag;"; + sqlquery sql = SqlPrepareQueryObject(oPlayer, sQuery); + SqlBindString(sql, "@name", sName); + SqlBindString(sql, "@tag", sTag); + if(SqlStep(sql)) return SqlGetJson(sql, 0); + else return JsonArray(); +} +void CastBuffSpell (object oPC, object oTarget, int nSpell, int nClass, int nMetamagic, int nDomain, string sList, string sName) +{ + string sTargetName; + if(oPC == oTarget) sTargetName = "myself."; + else sTargetName = GetName(oTarget); + ai_SendMessages("Quick Buffing: " + sName + " on " + sTargetName, AI_COLOR_GREEN, oPC); + AssignCommand(oPC, ActionCastSpellAtObject(nSpell, oTarget, nMetamagic, FALSE, nDomain, 0, TRUE, nClass)); +} +void CastSavedBuffSpells(object oPC) +{ + // Lets make sure the save button is off! + if(GetEventScript(oPC, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT) == "pc_savebuffs") + { + string sScript = GetLocalString(oPC, "AI_BUFF_CAST_AT_SCRIPT"); + SetEventScript(oPC, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, sScript); + DeleteLocalString(oPC, "AI_BUFF_CAST_AT_SCRIPT"); + // Cleanup your followers to allow spells to be reacted to as normal. + int nAssociateType = 2; + object oAssociate = GetAssociate(nAssociateType, oPC); + while(nAssociateType < 5) + { + if(oAssociate != OBJECT_INVALID) + { + sScript = GetLocalString(oAssociate, "AI_BUFF_CAST_AT_SCRIPT"); + SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, sScript); + DeleteLocalString(oAssociate, "AI_BUFF_CAST_AT_SCRIPT"); + } + oAssociate = GetAssociate(++nAssociateType, oPC); + } + int nIndex = 1; + oAssociate = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex); + while(nIndex <= AI_MAX_HENCHMAN) + { + if(oAssociate != OBJECT_INVALID) + { + sScript = GetLocalString(oAssociate, "AI_BUFF_CAST_AT_SCRIPT"); + SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, sScript); + DeleteLocalString(oAssociate, "AI_BUFF_CAST_AT_SCRIPT"); + } + oAssociate = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, ++nIndex); + } + int nMainWindow = NuiFindWindow(oPC, "plbuffwin"); + if(nMainWindow) NuiSetBind(oPC, nMainWindow, "btn_save", JsonBool(FALSE)); + ai_SendMessages("Saving spells to the list has been turned off.", AI_COLOR_YELLOW, oPC); + } + float fDistance; + if(!GetLocalInt(oPC, FB_NO_MONSTER_CHECK)) + { + // Check for monsters! We cannot let them buff if they are close to the enemy! + object oEnemy = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, oPC); + fDistance = GetDistanceBetween(oPC, oEnemy); + } + if(fDistance > 30.0f || fDistance == 0.0) + { + string sName; + float fDelay = 0.1f; + int nSpell, nClass, nLevel, nMetamagic, nDomain, nSpellReady, nIndex = 0; + json jMenuData = GetBuffDatabaseJson(oPC, "spells", "menudata"); + string sList = JsonGetString(JsonArrayGet(jMenuData, 0)); + json jSpell, jSpells = GetBuffDatabaseJson(oPC, "spells", sList); + while(nIndex <= BUFF_MAX_SPELLS) + { + jSpell = JsonArrayGet(jSpells, nIndex); + if(JsonGetType(jSpell) != JSON_TYPE_NULL) + { + nSpell = JsonGetInt(JsonArrayGet(jSpell, 0)); + nClass = JsonGetInt(JsonArrayGet(jSpell, 1)); + nLevel = JsonGetInt(JsonArrayGet(jSpell, 2)); + nMetamagic = JsonGetInt(JsonArrayGet(jSpell, 3)); + nDomain = JsonGetInt(JsonArrayGet(jSpell, 4)); + // We save the target's name then look them up by it. + string sTargetName = JsonGetString(JsonArrayGet(jSpell, 5)); + object oTarget; + location lLocation = GetLocation(oPC); + if(sTargetName == "" || sTargetName == ai_RemoveIllegalCharacters(ai_StripColorCodes(GetName (oPC)))) oTarget = oPC; + else + { + oTarget = GetFirstObjectInShape(SHAPE_SPHERE, 10.0, lLocation, TRUE); + while(oTarget != OBJECT_INVALID) + { + if(sTargetName == ai_RemoveIllegalCharacters(ai_StripColorCodes(GetName(oTarget)))) break; + oTarget = GetNextObjectInShape(SHAPE_SPHERE, 10.0, lLocation, TRUE); + } + } + sName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); + if(oTarget == OBJECT_INVALID) + { + DelayCommand(fDelay, ai_SendMessages("Cannot quick cast " + sName + " because the " + sTargetName + " is not here!", AI_COLOR_RED, oPC)); + } + else + { + if(nMetamagic > 0) + { + if(nMetamagic == METAMAGIC_EMPOWER) sName += " (Empowered)"; + else if(nMetamagic == METAMAGIC_EXTEND) sName += " (Extended)"; + else if(nMetamagic == METAMAGIC_MAXIMIZE) sName += " (Maximized)"; + else if(nMetamagic == METAMAGIC_QUICKEN) sName += " (Quickened)"; + else if(nMetamagic == METAMAGIC_SILENT) sName += " (Silent)"; + else if(nMetamagic == METAMAGIC_STILL) sName += " (Still)"; + } + nSpellReady = GetSpellReady(oPC, nSpell, nClass, nLevel, nMetamagic, nDomain); + if(nSpellReady == TRUE) + { + DelayCommand(fDelay, CastBuffSpell(oPC, oTarget, nSpell, nClass, nMetamagic, nDomain, sList, sName)); + } + else if(nSpellReady == -1) + { + DelayCommand(fDelay, ai_SendMessages("Cannot quick cast " + sName + " because it is not ready to cast!", AI_COLOR_RED, oPC)); + } + else if(nSpellReady == -2) + { + DelayCommand (fDelay, ai_SendMessages("Cannot quick cast " + sName + " because it is not memorized!", AI_COLOR_RED, oPC)); + } + else if(nSpellReady == -3) + { + DelayCommand (fDelay, ai_SendMessages("Cannot quick cast " + sName + " because there are no spell slots of that level left!", AI_COLOR_RED, oPC)); + } + else if(nSpellReady == -4) + { + DelayCommand (fDelay, ai_SendMessages("Cannot quick cast " + sName + " because that spell is not known.", AI_COLOR_RED, oPC)); + } + fDelay += 0.1f; + } + } + else break; + nIndex ++; + } + if(nIndex == 0 && !NuiFindWindow(oPC, "plbuffwin")) ExecuteScript("pi_buffing", oPC); + } + else ai_SendMessages("Enemies are too close for you to cast all your buff spells!", AI_COLOR_RED, oPC); +} +int GetSpellReady(object oCaster, int nSpell, int nClass, int nLevel, int nMetamagic, int nDomain) +{ + int nIndex, nMaxIndex, nMSpell, nMmSpell, nDSpell, nSubRadSpell, nSubSpell; + string sSubRadSpell; + if(StringToInt(Get2DAString("classes", "MemorizesSpells", nClass))) + { + int nSpellMemorized; + while(nIndex < nMaxIndex) + { + nMSpell = GetMemorizedSpellId(oCaster, nClass, nLevel, nIndex); + if(nSpell == nMSpell) + { + nMmSpell = GetMemorizedSpellMetaMagic(oCaster, nClass, nLevel, nIndex); + nDSpell = GetMemorizedSpellIsDomainSpell(oCaster, nClass, nLevel, nIndex); + //ai_Debug("pe_buffing", "308", "nMmSpell: " + IntToString(nMmSpell) + + // " nMetamagic: " + IntToString(nMetamagic) + + // " nDomain: " + IntToString(nDomain) + + // " nDSpell: " + IntToString(nDSpell)); + // Cannot save the domain status so we just use the first spell ID. + // Then return the domain statusl. + //if(nMmSpell == nMetamagic && + // ((nDomain > 0 && nDSpell == TRUE) || nDomain == 0 && nDSpell == FALSE)) + if(nMmSpell == nMetamagic) + { + nSpellMemorized = TRUE; + if(GetMemorizedSpellReady(oCaster, nClass, nLevel, nIndex)) + { + if(nDSpell == nDomain) return TRUE; + } + } + } + for(nSubRadSpell = 1; nSubRadSpell < 5; nSubRadSpell++) + { + sSubRadSpell = "SubRadSpell" + IntToString(nSubRadSpell); + if(nSpell == StringToInt(Get2DAString("spells", sSubRadSpell, nMSpell))) + nMmSpell = GetMemorizedSpellMetaMagic(oCaster, nClass, nLevel, nIndex); + nDSpell = GetMemorizedSpellIsDomainSpell(oCaster, nClass, nLevel, nIndex); + ai_Debug("pe_buffing", "421", "nMmSpell: " + IntToString(nMmSpell) + + " nMetamagic: " + IntToString(nMetamagic) + + " nDomain: " + IntToString(nDomain) + + " nDSpell: " + IntToString(nDSpell)); + if(nMmSpell == nMetamagic) + { + nSpellMemorized = TRUE; + if(GetMemorizedSpellReady(oCaster, nClass, nLevel, nIndex)) + { + if(nDSpell == nDomain) return TRUE; + } + } + } + nIndex ++; + } + if(nSpellMemorized) return -1; + return -2; + } + else + { + int nSpellKnown; + nMaxIndex = GetKnownSpellCount(oCaster, nClass, nLevel); + while(nIndex < nMaxIndex) + { + nMSpell = GetKnownSpellId(oCaster, nClass, nLevel, nIndex); + if(nSpell == nMSpell) + { + nSpellKnown = TRUE; + if(GetSpellUsesLeft(oCaster, nClass, nSpell)) return TRUE; + } + for(nSubRadSpell = 1; nSubRadSpell < 5; nSubRadSpell++) + { + sSubRadSpell = "SubRadSpell" + IntToString(nSubRadSpell); + if(nSpell == StringToInt(Get2DAString("spells", sSubRadSpell, nMSpell))) + { + nSpellKnown = TRUE; + if(GetSpellUsesLeft(oCaster, nClass, nSpell)) return TRUE; + } + } + nIndex ++; + } + if(nSpellKnown) return -3; + return -4; + } + return -2; +} +void PopupWidgetBuffGUIPanel(object oPC) +{ + // Set window to not save until it has been created. + SetLocalInt(oPC, AI_NO_NUI_SAVE, TRUE); + DelayCommand(0.5f, DeleteLocalInt (oPC, AI_NO_NUI_SAVE)); + // Row 1 (buttons)********************************************************** + + json jRow = CreateButtonImage(JsonArray(), "ir_level1", "btn_one", 35.0f, 35.0f, 0.0); + jRow = CreateButtonImage(jRow, "ir_level2", "btn_two", 35.0f, 35.0f, 0.0); + jRow = CreateButtonImage(jRow, "ir_level3", "btn_three", 35.0f, 35.0f, 0.0); + jRow = CreateButtonImage(jRow, "ir_level4", "btn_four", 35.0f, 35.0f, 0.0); + // Add the row to the column. + json jCol = JsonArrayInsert(JsonArray(), NuiRow(jRow)); + json jMenuData = GetBuffDatabaseJson(oPC, "spells", "menudata"); + int bAIBuffWidgetLock = JsonGetInt(JsonArrayGet(jMenuData, 4)); + // Get the window location to restore it from the database. + float fX = JsonGetFloat(JsonArrayGet(jMenuData, 5)); + float fY = JsonGetFloat(JsonArrayGet(jMenuData, 6)); + if(fX == 0.0f && fY == 0.0f) + { + fX = 10.0f; + fY = 10.0f; + } + float fGUI_Scale = IntToFloat(GetPlayerDeviceProperty(oPC, PLAYER_DEVICE_PROPERTY_GUI_SCALE)) / 100.0; + if(bAIBuffWidgetLock) + { + fX += 4.0f; + // GUI scales are a mess, I just figured them out per scale to keep the widget from moving. + if(fGUI_Scale == 1.0) fY += 37.0; + else if(fGUI_Scale == 1.1) fY += 38.0; + else if(fGUI_Scale == 1.2) fY += 40.0; + else if(fGUI_Scale == 1.3) fY += 42.0; + else if(fGUI_Scale == 1.4) fY += 43.0; + else if(fGUI_Scale == 1.5) fY += 45.0; + else if(fGUI_Scale == 1.6) fY += 47.0; + else if(fGUI_Scale == 1.7) fY += 48.0; + else if(fGUI_Scale == 1.8) fY += 50.0; + else if(fGUI_Scale == 1.9) fY += 52.0; + else if(fGUI_Scale == 2.0) fY += 54.0; + } + // Set the layout of the window. + json jLayout = NuiCol(jCol); + int nToken; + if(bAIBuffWidgetLock) nToken = SetWindow (oPC, jLayout, "widgetbuffwin", "Fast Buff Widget", fX, fY, 160.0, 62.0, FALSE, FALSE, FALSE, TRUE, FALSE, "pe_buffing"); + else nToken = SetWindow (oPC, jLayout, "widgetbuffwin", "Fast Buff Widget", fX, fY, 160.0, 95.0, FALSE, FALSE, FALSE, TRUE, TRUE, "pe_buffing"); + // Set event watches for window inspector and save window location. + NuiSetBindWatch (oPC, nToken, "collapsed", TRUE); + NuiSetBindWatch (oPC, nToken, "window_geometry", TRUE); + // Set the buttons to show events. + //NuiSetBind (oPC, nToken, "btn_one", JsonBool (TRUE)); + NuiSetBind (oPC, nToken, "btn_one_event", JsonBool (TRUE)); + NuiSetBind (oPC, nToken, "btn_two", JsonBool (TRUE)); + NuiSetBind (oPC, nToken, "btn_two_event", JsonBool (TRUE)); + NuiSetBind (oPC, nToken, "btn_three", JsonBool (TRUE)); + NuiSetBind (oPC, nToken, "btn_three_event", JsonBool (TRUE)); + NuiSetBind (oPC, nToken, "btn_four", JsonBool (TRUE)); + NuiSetBind (oPC, nToken, "btn_four_event", JsonBool (TRUE)); +} + diff --git a/src/module/nss/pe_crafting.nss b/src/module/nss/pe_crafting.nss new file mode 100644 index 0000000..388c86a --- /dev/null +++ b/src/module/nss/pe_crafting.nss @@ -0,0 +1,2153 @@ +/*////////////////////////////////////////////////////////////////////////////// +// Script Name: pe_crafting +//////////////////////////////////////////////////////////////////////////////// + Used with pi_crafting to run the crafting plugin events for + Philos Single Player Enhancements. +*/////////////////////////////////////////////////////////////////////////////// +#include "0i_nui" +#include "nw_inc_gff" +#include "0i_main" +#include "0i_items" +// Maximum model number for all items except weapons. +const int CRAFT_MAX_MODEL_NUMBER = 999; + +struct stWeaponAppearance +{ + object oItem; + int nModel; + int nColor; + string sPart; +}; +// Maximum model number for weapons. Note this will be the 100s and 10s places. +// The color number uses the ones place. Thus 25 is actually 250. +const int CRAFT_MAX_WEAPON_MODEL_NUMBER = 99; +const string CRAFT_JSON = "CRAFT_JSON"; +const string CRAFT_ORIGINAL_ITEM = "CRAFT_ORIGINAL_ITEM"; +const string CRAFT_COOL_DOWN = "CRAFT_COOL_DOWN"; +const string CRAFT_ITEM_SELECTION = "CRAFT_ITEM_SELECTION"; +const string CRAFT_MATERIAL_SELECTION = "CRAFT_MATERIAL_SELECTION"; +const string CRAFT_MODEL_SELECTION = "CRAFT_MODEL_SELECTION"; +const string CRAFT_MODEL_SPECIAL = "CRAFT_MODEL_SPECIAL"; +const string CRAFT_ITEM_TYPE = "CRAFT_ITEM_TYPE"; +const string CRAFT_WEAPON_MOD_TOP = "CRAFT_WEAPON_MOD_TOP"; +const string CRAFT_WEAPON_MOD_MID = "CRAFT_WEAPON_MOD_MID"; +const string CRAFT_WEAPON_MOD_BOT = "CRAFT_WEAPON_MOD_BOT"; +const string CRAFT_WEAPON_COL_TOP = "CRAFT_WEAPON_COL_TOP"; +const string CRAFT_WEAPON_COL_MID = "CRAFT_WEAPON_COL_MID"; +const string CRAFT_WEAPON_COL_BOT = "CRAFT_WEAPON_COL_BOT"; +const string CRAFT_COPY_ITEM = "CRAFT_COPY_ITEM"; +const string CRAFT_COPY_ITEM_TYPE = "CRAFT_COPY_ITEM_TYPE"; +const string CRAFT_COPY_MODEL = "CRAFT_COPY_MODEL"; +const string CRAFT_COPY_COLOR = "CRAFT_COPY_COLOR"; +const string CRAFT_COPY_PART_COLOR = "CRAFT_COPY_PART_COLOR"; +const string CRAFT_ARMOR_AC = "CRAFT_ARMOR_AC"; +const string CRAFT_COLOR_PALLET = "CRAFT_COLOR_PALLET"; +const string CRAFT_LEFT_PART_COLOR = "CRAFT_LEFT_PART_COLOR"; +const string CRAFT_ALL_COLOR = "CRAFT_ALL_COLOR"; +const string CRAFT_RIGHT_PART_COLOR = "CRAFT_RIGHT_PART_COLOR"; +const string CRAFT_TARGET = "CRAFT_TARGET"; +// Tag used in lighting effects. +const string CRAFT_HIGHLIGHT = "CRAFT_HIGHLIGHT"; +const string CRAFT_ULTRALIGHT = "CRAFT_ULTRALIGHT"; +// The tags for containers used to do some crafting. +const string CRAFT_TEMPLATE = "x3_plc_basket"; +const string CRAFT_CONTAINER = "CRAFT_CONTAINER"; +// Used in the crafting GUI to copy an item to be pasted to another item later. +void CopyCraftingItem(object oPC, object oItem); +// Used in the crafting GUI to paste a copy of an item to another item. +object PasteCraftingItem(object oPC, object oTarget, object oItem); +int GetItemSelectedEquipSlot(int nItemSelected); +int GetArmorModelSelected(object oPC); +object ChangeItemsAppearance(object oPC, object oTarget, int nToken, object oItem, int nDirection, string sPart); +// Checks to see if the item can be crafted. +// bPasteCheck is a special check when an item is being pasted. +int CanCraftItem(object oPC, object oItem, int nToken, int bPasteCheck = FALSE); +object RandomizeItemsCraftAppearance(object oPlayer, object oTarget, int nToken, object oItem); +// Returns the correct item based on the crafting menu selected item. +object GetSelectedItem(object oTarget, int nItemSelected); +// Cancels the crafted item for the player and restoring the original. +void CancelCraftedItem(object oPlayer, object oTarget); +// Gets the colorId from a image of the color pallet. +// Thanks Zunath for the base code. +int GetColorPalletId(object oPC, int nToken); +// Sets the pointer based on current Item, Part, and Material selected. +void SetColorPalletPointer(object oPC, int nToken, object oItem); +// Locks/Unlocks specific buttons when an item has been changed. +void LockItemInCraftingWindow(object oPC, object oItem, object oTarget, int nToken); +// Locks/Unlocks specific buttons when an item has been cleared. +void ClearItemInCraftingWindow(object oPC, object oItem, int nToken); +// Saves the crafted item for the player removing the original. +void SaveCraftedItem(object oPC, object oTarget, int nToken); +// Remove Effect of type specified from oCreature; +// sEffectTag is the tag of the effect to remove. +// Feat, Class, Racial. +void RemoveTagedEffects(object oCreature, string sEffectTag); +// Returns TRUE/FALSE if item has temporary item property. +int CheckForTemporaryItemProperty(object oItem); +// Updates the model number text in the NUI menu. +void SetModelNumberText(object oPC, object oTarget, int nToken); +// Sets the material buttons for use. +// nMaterial 0,1 Cloth 2,3 Leather 4,5 Metal -1 None. +void SetMaterialButtons(object oPC, int nToken, int nMaterial); +// Creates the item editing menu. +void CreateItemGUIPanel(object oPC, object oTarget); +// Events for ItemGUIPanel +void CraftItemInfoEvents(object oPC, int nToken); +// Creates the save/load menu for items. +//void CreateDresserGUIPanel(object oPC, object oTarget); + +int GetColorIDChange(object oItem, int nType, int nIndex, int nChange) +{ + int nColorId = GetItemAppearance(oItem, nType, nIndex) + nChange; + if(nColorId > 175) return 0; + if(nColorId < 0) return 175; + return nColorId; +} +void main() +{ + // Get the last player to use targeting mode + object oPC = GetLastPlayerToSelectTarget(); + string sTargetMode = GetLocalString(oPC, AI_TARGET_MODE); + if(oPC == OBJECT_SELF && sTargetMode != "") + { + // Get the targeting mode data + object oTarget = GetTargetingModeSelectedObject(); + //vector vTarget = GetTargetingModeSelectedPosition(); + //location lLocation = Location(GetArea(oPC), vTarget, GetFacing(oPC)); + //object oObject = GetLocalObject(oPC, "AI_TARGET_OBJECT"); + // If the user manually exited targeting mode without selecting a target, return + if(!GetIsObjectValid(oTarget))// && vTarget == Vector()) + { + return; + } + // Targeting code here. + if(sTargetMode == "SELECT_TARGET") + { + if(GetAssociateType(oTarget) == ASSOCIATE_TYPE_HENCHMAN || + ai_GetIsCharacter(oTarget)) + { + SetLocalObject(oPC, CRAFT_TARGET, oTarget); + AttachCamera(oPC, oTarget); + ExecuteScript("pi_crafting", oPC); + } + else ai_SendMessages(GetName(oTarget) + " is not the player or a henchmen! Other associates cannot use item crafting.", AI_COLOR_RED, oPC); + } + DeleteLocalString(oPC, AI_TARGET_MODE); + } + else + { + object oPC = NuiGetEventPlayer(); + int nToken = NuiGetEventWindow(); + string sWndId = NuiGetWindowId (oPC, nToken); + if(sWndId == "craft_item_nui") + { + CraftItemInfoEvents(oPC, nToken); + return; + } + string sEvent = NuiGetEventType(); + // We don't use and it causes error windows to go off! Return early! + if(sEvent == "mouseup") return; + string sElem = NuiGetEventElement(); + int nIndex = NuiGetEventArrayIndex(); + json jCraft = GetLocalJson(oPC, CRAFT_JSON); + //SendMessageToPC(oPC, "0e_crafting, 144, sElem: " + sElem + " sEvent: " + sEvent); + //************************************************************************** + // Watch to see if the window moves and save. + if(sElem == "window_geometry" && sEvent == "watch") + { + if(!GetLocalInt (oPC, AI_NO_NUI_SAVE)) + { + json jCraft = GetLocalJson(oPC, CRAFT_JSON); + if(JsonGetType(jCraft) == JSON_TYPE_NULL) jCraft = JsonObject(); + // Get the height, width, x, and y of the window. + json jGeometry = NuiGetBind(oPC, nToken, "window_geometry"); + jCraft = JsonObjectSet(jCraft, "CRAFT_MENU", jGeometry); + SetLocalJson(oPC, CRAFT_JSON, jCraft); + } + return; + } + //************************************************************************** + object oTarget = GetLocalObject(oPC, CRAFT_TARGET); + if(oTarget == OBJECT_INVALID) oTarget = oPC; + // Get the item we are crafting. + int nItemSelected = JsonGetInt(JsonObjectGet(jCraft, CRAFT_ITEM_SELECTION)); + object oItem = GetSelectedItem(oTarget, nItemSelected); + object oOriginalItem = GetLocalObject(oPC, CRAFT_ORIGINAL_ITEM); + if(oItem == OBJECT_INVALID) + { + if(sElem != "btn_cancel") + { + ai_SendMessages("The item we are adjusting is not equiped!", AI_COLOR_RED, oPC); + return; + } + } + else if(oOriginalItem != OBJECT_INVALID && GetTag(oItem) != GetTag(oOriginalItem)) + { + ai_SendMessages(GetName(oItem) + " is not the item you have been adjusting!", AI_COLOR_RED, oPC); + return; + } + // Changing the name needs to be before the cooldown. + if(sElem == "txt_item_name" && sEvent == "watch") + { + string sName = JsonGetString(NuiGetBind(oPC, nToken, "txt_item_name")); + SetName(oItem, sName); + int nToken2 = NuiFindWindow(oPC, "craft_item_nui"); + if(nToken2) NuiSetBind(oPC, nToken2, "txt_item_name", JsonString(sName)); + return; + } + // Delay crafting so it has time to equip and unequip as well as remove. + //if(GetLocalInt(oPC, CRAFT_COOL_DOWN)) return; + //SetLocalInt(oPC, CRAFT_COOL_DOWN, TRUE); + //DelayCommand(0.25f, DeleteLocalInt(oPC, CRAFT_COOL_DOWN)); + // They have selected a color. + if(sElem == "color_pallet") + { + int nColorId, nChange; + object oNewItem; + if(sEvent == "mousedown") + { + // Get the color they selected from the color pallet cell. + nColorId = GetColorPalletId(oPC, nToken); + } + else if(sEvent == "mousescroll") + { + float nMouseScroll = JsonGetFloat(JsonObjectGet(JsonObjectGet(NuiGetEventPayload(), "mouse_scroll"), "y")); + nChange = FloatToInt(nMouseScroll); + } + else return; + if(!CanCraftItem(oPC, oItem, nToken)) return; + int nMaterialSelected = JsonGetInt(JsonObjectGet(jCraft, CRAFT_MATERIAL_SELECTION)); + int nBaseItemType = GetBaseItemType(oItem); + int nAllColor = JsonGetInt(JsonObjectGet(jCraft, CRAFT_ALL_COLOR)); + if(!nAllColor && nBaseItemType == BASE_ITEM_ARMOR) + { + int nIndex; + int nModelSelected = GetArmorModelSelected(oPC); + int nLeftColor = JsonGetInt(JsonObjectGet(jCraft, CRAFT_LEFT_PART_COLOR)); + int nRightColor = JsonGetInt(JsonObjectGet(jCraft, CRAFT_RIGHT_PART_COLOR)); + if(nModelSelected == ITEM_APPR_ARMOR_MODEL_NECK || + nModelSelected == ITEM_APPR_ARMOR_MODEL_TORSO || + nModelSelected == ITEM_APPR_ARMOR_MODEL_BELT || + nModelSelected == ITEM_APPR_ARMOR_MODEL_PELVIS || + nModelSelected == ITEM_APPR_ARMOR_MODEL_ROBE) + { + nIndex = ITEM_APPR_ARMOR_NUM_COLORS + (nModelSelected * ITEM_APPR_ARMOR_NUM_COLORS) + nMaterialSelected; + if(nChange) nColorId = GetColorIDChange(oItem, ITEM_APPR_TYPE_ARMOR_COLOR, nIndex, nChange); + oNewItem = CopyItemAndModify(oItem, ITEM_APPR_TYPE_ARMOR_COLOR, nIndex, nColorId, TRUE); + DestroyObject(oItem); + } + else + { + if(nRightColor) + { + // Color Right side. + nIndex = ITEM_APPR_ARMOR_NUM_COLORS + (nModelSelected * ITEM_APPR_ARMOR_NUM_COLORS) + nMaterialSelected; + if(nChange) nColorId = GetColorIDChange(oItem, ITEM_APPR_TYPE_ARMOR_COLOR, nIndex, nChange); + oNewItem = CopyItemAndModify(oItem, ITEM_APPR_TYPE_ARMOR_COLOR, nIndex, nColorId, TRUE); + DestroyObject(oItem); + // Fix buttons. + NuiSetBind(oPC, nToken, "btn_right_part_reset_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_all_reset_event", JsonBool(TRUE)); + if(nLeftColor) + { + // If we are doing the left side then add one to get the left side. + // Note: Right Thigh and Left Thigh are backwards so this fixes that! + if (nModelSelected == ITEM_APPR_ARMOR_MODEL_RTHIGH) nModelSelected = nModelSelected - 1; + else nModelSelected = nModelSelected + 1; + nIndex = ITEM_APPR_ARMOR_NUM_COLORS + (nModelSelected * ITEM_APPR_ARMOR_NUM_COLORS) + nMaterialSelected; + if(nChange) nColorId = GetColorIDChange(oNewItem, ITEM_APPR_TYPE_ARMOR_COLOR, nIndex, nChange); + oItem = CopyItemAndModify(oNewItem, ITEM_APPR_TYPE_ARMOR_COLOR, nIndex, nColorId, TRUE); + DestroyObject(oNewItem); + oNewItem = oItem; + // Fix buttons. + NuiSetBind(oPC, nToken, "btn_all_reset_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_left_part_reset_event", JsonBool(TRUE)); + } + } + else if(nLeftColor) + { + // If we are doing the left side then add one to get the left side. + // Note: Right Thigh and Left Thigh are backwards so this fixes that! + if (nModelSelected == ITEM_APPR_ARMOR_MODEL_RTHIGH) nModelSelected = nModelSelected - 1; + else nModelSelected = nModelSelected + 1; + nIndex = ITEM_APPR_ARMOR_NUM_COLORS + (nModelSelected * ITEM_APPR_ARMOR_NUM_COLORS) + nMaterialSelected; + if(nChange) nColorId = GetColorIDChange(oItem, ITEM_APPR_TYPE_ARMOR_COLOR, nIndex, nChange); + oNewItem = CopyItemAndModify(oItem, ITEM_APPR_TYPE_ARMOR_COLOR, nIndex, nColorId, TRUE); + DestroyObject(oItem); + // Fix buttons. + NuiSetBind(oPC, nToken, "btn_all_reset_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_left_part_reset_event", JsonBool(TRUE)); + } + } + } + else + { + if(nChange) nColorId = GetColorIDChange(oItem, ITEM_APPR_TYPE_ARMOR_COLOR, nMaterialSelected, nChange); + oNewItem = CopyItemAndModify(oItem, ITEM_APPR_TYPE_ARMOR_COLOR, nMaterialSelected, nColorId, TRUE); + DestroyObject(oItem); + } + // Lock the new item so they can't change it on the character. + LockItemInCraftingWindow(oPC, oNewItem, oTarget, nToken); + // Equip new item. + if(nBaseItemType == BASE_ITEM_CLOAK) AssignCommand (oTarget, ActionEquipItem(oNewItem, INVENTORY_SLOT_CLOAK)); + else if(nBaseItemType == BASE_ITEM_HELMET) AssignCommand(oTarget, ActionEquipItem(oNewItem, INVENTORY_SLOT_HEAD)); + else if(nBaseItemType == BASE_ITEM_ARMOR) AssignCommand(oTarget, ActionEquipItem(oNewItem, INVENTORY_SLOT_CHEST)); + } + else if(sEvent == "watch") + { + // The player is changing the item they are crafting. + if(sElem == "item_combo_selected") + { + int nSelected = JsonGetInt(NuiGetBind (oPC, nToken, sElem)); + oItem = GetSelectedItem(oTarget, nSelected); + if(oItem == OBJECT_INVALID) + { + ai_SendMessages("There is not an item to modify!", AI_COLOR_RED, oPC); + int nItem = JsonGetInt(JsonObjectGet(jCraft, CRAFT_ITEM_SELECTION)); + NuiSetBind(oPC, nToken, "item_combo_selected", JsonInt(nItem)); + return; + } + jCraft = JsonObjectSet(jCraft, CRAFT_ITEM_SELECTION, JsonInt(nSelected)); + // Set button for cloak and helms. + if(nSelected == 1 || nSelected == 2) + { + int nHidden = GetHiddenWhenEquipped(oItem); + if(nHidden) jCraft = JsonObjectSet(jCraft, CRAFT_MODEL_SELECTION, JsonInt(1)); + else jCraft = JsonObjectSet(jCraft, CRAFT_MODEL_SELECTION, JsonInt(0)); + } + else jCraft = JsonObjectSet(jCraft, CRAFT_MODEL_SELECTION, JsonInt(0)); + SetLocalJson(oPC, CRAFT_JSON, jCraft); + NuiDestroy(oPC, nToken); + ExecuteScript("pi_crafting", oPC); + } + // They have selected a part to change. + else if(sElem == "model_combo_selected") + { + int nSelected = JsonGetInt(NuiGetBind(oPC, nToken, sElem)); + jCraft = JsonObjectSet(jCraft, CRAFT_MODEL_SELECTION, JsonInt(nSelected)); + SetLocalJson(oPC, CRAFT_JSON, jCraft); + SetModelNumberText(oPC, oTarget, nToken); + int nItem = JsonGetInt(JsonObjectGet(jCraft, CRAFT_ITEM_SELECTION)); + if(nItem == 1) // Cloak + { + if(!CanCraftItem(oPC, oItem, nToken)) return; + object oItem = GetItemInSlot(INVENTORY_SLOT_CLOAK, oTarget); + if(nSelected == 1) SetHiddenWhenEquipped(oItem, TRUE); + else SetHiddenWhenEquipped(oItem, FALSE); + LockItemInCraftingWindow(oPC, oItem, oTarget, nToken); + } + else if(nItem == 2) // Headgear + { + if(!CanCraftItem(oPC, oItem, nToken)) return; + object oItem = GetItemInSlot(INVENTORY_SLOT_HEAD, oTarget); + if(nSelected == 1) SetHiddenWhenEquipped(oItem, TRUE); + else SetHiddenWhenEquipped(oItem, FALSE); + LockItemInCraftingWindow(oPC, oItem, oTarget, nToken); + } + else if(nItem == 4 && ai_GetIsShield(oItem)) + { + if(!CanCraftItem(oPC, oItem, nToken)) return; + object oItem = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oTarget); + if(nSelected == 1) SetHiddenWhenEquipped(oItem, TRUE); + else SetHiddenWhenEquipped(oItem, FALSE); + LockItemInCraftingWindow(oPC, oItem, oTarget, nToken); + } + if(ai_GetIsWeapon(oItem)) + { + // Clearing sets the module to 0 triggering an extra call. + if(GetLocalInt(oPC, AI_NO_NUI_SAVE)) return; + if(!CanCraftItem(oPC, oItem, nToken)) return; + int nVisual; + itemproperty ipProperty = GetFirstItemProperty(oItem); + while(GetIsItemPropertyValid(ipProperty)) + { + if(GetItemPropertyType(ipProperty) == ITEM_PROPERTY_VISUALEFFECT) + { + RemoveItemProperty(oItem, ipProperty); + } + ipProperty = GetNextItemProperty(oItem); + } + if(nSelected == 1) nVisual = ITEM_VISUAL_ACID; + else if(nSelected == 2) nVisual = ITEM_VISUAL_COLD; + else if(nSelected == 3) nVisual = ITEM_VISUAL_ELECTRICAL; + else if(nSelected == 4) nVisual = ITEM_VISUAL_EVIL; + else if(nSelected == 5) nVisual = ITEM_VISUAL_FIRE; + else if(nSelected == 6) nVisual = ITEM_VISUAL_HOLY; + else if(nSelected == 7) nVisual = ITEM_VISUAL_SONIC; + if(nVisual) + { + ipProperty = ItemPropertyVisualEffect(nVisual); + AddItemProperty(DURATION_TYPE_PERMANENT, ipProperty, oItem); + } + LockItemInCraftingWindow(oPC, oItem, oTarget, nToken); + } + } + } + else if(sEvent == "click") + { + if(sElem == "btn_info") + { + SetLocalObject(oPC, "CRAFT_INFO_ITEM", oItem); + CreateItemGUIPanel(oPC, oItem); + } + //else if(sElem == "btn_wardrobe") CreateDresserGUIPanel(oPC, oTarget); + // Random button to change items looks randomly. + else if(sElem == "btn_randomize") + { + if(CanCraftItem(oPC, oItem, nToken)) + { + oItem = RandomizeItemsCraftAppearance(oPC, oTarget, nToken, oItem); + LockItemInCraftingWindow(oPC, oItem, oTarget, nToken); + } + } + // Save any changes made to the selected item. + else if(sElem == "btn_save") + { + SaveCraftedItem(oPC, oTarget, nToken); + } + // Selecte target to change clothing on. + else if(sElem == "btn_select_target") + { + // Set this variable on the player so PEPS can run the targeting script for this plugin. + SetLocalString(oPC, AI_PLUGIN_TARGET_SCRIPT, "pe_crafting"); + // Set Targeting variables. + SetLocalString(oPC, AI_TARGET_MODE, "SELECT_TARGET"); + NuiDestroy(oPC, nToken); + ai_SendMessages("Select either your charcter or a henchman to craft their equipment.", AI_COLOR_YELLOW, oPC); + DeleteLocalObject(oPC, CRAFT_ORIGINAL_ITEM); + DeleteLocalObject(oPC, CRAFT_TARGET); + DeleteLocalObject(oPC, "CRAFT_INFO_ITEM"); + if(GetLocalInt(oPC, CRAFT_ULTRALIGHT)) + { + RemoveTagedEffects(oTarget, CRAFT_ULTRALIGHT); + DeleteLocalInt(oPC, CRAFT_ULTRALIGHT); + } + if(GetLocalInt(oPC, CRAFT_HIGHLIGHT)) + { + RemoveTagedEffects(oTarget, CRAFT_HIGHLIGHT); + DeleteLocalInt(oPC, CRAFT_HIGHLIGHT); + } + EnterTargetingMode(oPC, OBJECT_TYPE_CREATURE , MOUSECURSOR_EXAMINE, MOUSECURSOR_NOEXAMINE); + } + // Cancel any changes made to the selected item. + else if(sElem == "btn_cancel") + { + // If the button is on cancel then clear the item. + if(JsonGetString(NuiGetBind(oPC, nToken, "btn_cancel_label")) == "Cancel") + { + CancelCraftedItem(oPC, oTarget); + ClearItemInCraftingWindow(oPC, oItem, nToken); + DelayCommand(0.5, NuiDestroy(oPC, nToken)); + DelayCommand(0.5, ExecuteScript("pi_crafting", oPC)); + } + // If the button is on Exit not Cancel then exit. + else + { + AssignCommand(oPC, RestoreCameraFacing()); + AttachCamera(oPC, oPC); + DeleteLocalObject(oPC, CRAFT_ORIGINAL_ITEM); + DeleteLocalObject(oPC, CRAFT_TARGET); + DeleteLocalObject(oPC, "CRAFT_INFO_ITEM"); + NuiDestroy(oPC, nToken); + nToken = NuiFindWindow(oPC, "craft_item_nui"); + if(nToken) NuiDestroy(oPC, nToken); + if(GetLocalInt(oPC, CRAFT_ULTRALIGHT)) + { + RemoveTagedEffects(oTarget, CRAFT_ULTRALIGHT); + DeleteLocalInt(oPC, CRAFT_ULTRALIGHT); + } + if(GetLocalInt(oPC, CRAFT_HIGHLIGHT)) + { + RemoveTagedEffects(oTarget, CRAFT_HIGHLIGHT); + DeleteLocalInt(oPC, CRAFT_HIGHLIGHT); + } + } + } + // Get the previous model of the selected item. + else if(GetStringLeft(sElem, 9) == "btn_prev_") + { + if(CanCraftItem(oPC, oItem, nToken)) + { + oItem = ChangeItemsAppearance(oPC, oTarget, nToken, oItem, -1, GetStringRight(sElem, 1)); + LockItemInCraftingWindow(oPC, oItem, oTarget, nToken); + } + } + // Get the next model of the selected item. + else if(GetStringLeft(sElem, 9) == "btn_next_") + { + if(CanCraftItem(oPC, oItem, nToken)) + { + oItem = ChangeItemsAppearance(oPC, oTarget, nToken, oItem, 1, GetStringRight(sElem, 1)); + LockItemInCraftingWindow(oPC, oItem, oTarget, nToken); + } + } + else if(sElem == "btn_highlight") + { + if(GetLocalInt(oPC, CRAFT_HIGHLIGHT)) + { + RemoveTagedEffects(oTarget, CRAFT_HIGHLIGHT); + DeleteLocalInt(oPC, CRAFT_HIGHLIGHT); + NuiSetBind(oPC, nToken, "btn_highlight", JsonBool(FALSE)); + } + else + { + if(GetLocalInt(oPC, CRAFT_ULTRALIGHT)) + { + RemoveTagedEffects(oTarget, CRAFT_ULTRALIGHT); + DeleteLocalInt(oPC, CRAFT_ULTRALIGHT); + } + SetLocalInt(oPC, CRAFT_HIGHLIGHT, TRUE); + effect eLight = EffectVisualEffect(VFX_DUR_LIGHT_WHITE_20); + eLight = TagEffect(eLight, CRAFT_HIGHLIGHT); + ApplyEffectToObject(DURATION_TYPE_PERMANENT, eLight, oTarget); + NuiSetBind(oPC, nToken, "btn_highlight", JsonBool(TRUE)); + } + } + else if(sElem == "btn_left_part_color") + { + jCraft = JsonObjectSet(jCraft, CRAFT_ALL_COLOR, JsonInt(FALSE)); + NuiSetBind(oPC, nToken, "btn_all_color", JsonBool(FALSE)); + jCraft = JsonObjectSet(jCraft, CRAFT_LEFT_PART_COLOR, JsonInt(TRUE)); + NuiSetBind(oPC, nToken, "btn_left_part_color", JsonBool(TRUE)); + jCraft = JsonObjectSet(jCraft, CRAFT_RIGHT_PART_COLOR, JsonInt(FALSE)); + NuiSetBind(oPC, nToken, "btn_right_part_color", JsonBool(FALSE)); + SetColorPalletPointer(oPC, nToken, oItem); + } + else if(sElem == "btn_all_color") + { + jCraft = JsonObjectSet(jCraft, CRAFT_ALL_COLOR, JsonInt(TRUE)); + NuiSetBind(oPC, nToken, "btn_all_color", JsonBool(TRUE)); + jCraft = JsonObjectSet(jCraft, CRAFT_LEFT_PART_COLOR, JsonInt(FALSE)); + NuiSetBind(oPC, nToken, "btn_left_part_color", JsonBool(FALSE)); + jCraft = JsonObjectSet(jCraft, CRAFT_RIGHT_PART_COLOR, JsonInt(FALSE)); + NuiSetBind(oPC, nToken, "btn_right_part_color", JsonBool(FALSE)); + SetColorPalletPointer(oPC, nToken, oItem); + } + else if(sElem == "btn_right_part_color") + { + jCraft = JsonObjectSet(jCraft, CRAFT_ALL_COLOR, JsonInt(FALSE)); + NuiSetBind(oPC, nToken, "btn_all_color", JsonBool(FALSE)); + jCraft = JsonObjectSet(jCraft, CRAFT_LEFT_PART_COLOR, JsonInt(FALSE)); + NuiSetBind(oPC, nToken, "btn_left_part_color", JsonBool(FALSE)); + jCraft = JsonObjectSet(jCraft, CRAFT_RIGHT_PART_COLOR, JsonInt(TRUE)); + NuiSetBind(oPC, nToken, "btn_right_part_color", JsonBool(TRUE)); + SetColorPalletPointer(oPC, nToken, oItem); + } + else if(sElem == "btn_right_part_reset") + { + if(CanCraftItem(oPC, oItem, nToken)) + { + int nIndex; + int nModelSelected = GetArmorModelSelected(oPC); + int nMaterialSelected = JsonGetInt(JsonObjectGet(jCraft, CRAFT_MATERIAL_SELECTION)); + object oNewItem; + if(nModelSelected == ITEM_APPR_ARMOR_MODEL_NECK || + nModelSelected == ITEM_APPR_ARMOR_MODEL_TORSO || + nModelSelected == ITEM_APPR_ARMOR_MODEL_BELT || + nModelSelected == ITEM_APPR_ARMOR_MODEL_PELVIS || + nModelSelected == ITEM_APPR_ARMOR_MODEL_ROBE) + { + nIndex = ITEM_APPR_ARMOR_NUM_COLORS + (nModelSelected * ITEM_APPR_ARMOR_NUM_COLORS) + nMaterialSelected; + oNewItem = CopyItemAndModify(oItem, ITEM_APPR_TYPE_ARMOR_COLOR, nIndex, 255, TRUE); + DestroyObject(oItem); + } + else + { + nIndex = ITEM_APPR_ARMOR_NUM_COLORS + (nModelSelected * ITEM_APPR_ARMOR_NUM_COLORS) + nMaterialSelected; + oNewItem = CopyItemAndModify(oItem, ITEM_APPR_TYPE_ARMOR_COLOR, nIndex, 255, TRUE); + DestroyObject(oItem); + } + // Lock the new item so they can't change it on the character. + LockItemInCraftingWindow(oPC, oNewItem, oTarget, nToken); + // Equip new item. + AssignCommand(oTarget, ActionEquipItem(oNewItem, INVENTORY_SLOT_CHEST)); + // Fix buttons. + NuiSetBind(oPC, nToken, "btn_right_part_color", JsonBool(FALSE)); + jCraft = JsonObjectSet(jCraft, CRAFT_RIGHT_PART_COLOR, JsonInt(FALSE)); + int nLeft = JsonGetInt(NuiGetBind(oPC, nToken, "btn_left_part_color")); + NuiSetBind(oPC, nToken, "btn_all_color", JsonBool(!nLeft)); + jCraft = JsonObjectSet(jCraft, CRAFT_ALL_COLOR, JsonInt(!nLeft)); + NuiSetBind(oPC, nToken, "btn_right_part_reset_event", JsonBool(FALSE)); + nLeft = JsonGetInt(NuiGetBind(oPC, nToken, "btn_left_part_reset_event")); + NuiSetBind(oPC, nToken, "btn_all_reset_event", JsonBool(nLeft)); + SetColorPalletPointer(oPC, nToken, oNewItem); + } + } + else if(sElem == "btn_all_reset") + { + if(CanCraftItem(oPC, oItem, nToken)) + { + int nIndex, nColor; + json jItem = ObjectToJson(oItem, TRUE); + string sColor, sPartName; + for(nIndex = 0;nIndex < 19;nIndex++) + { + sPartName = "APart_" + IntToString(nIndex) + "_Col_"; + for(nColor = 0;nColor < 6;nColor++) + { + sColor = IntToString(nColor); + if(JsonGetType(GffGetByte(jItem, sPartName + sColor)) != JSON_TYPE_NULL) + { + jItem = GffRemoveByte(jItem, sPartName + sColor); + } + } + } + object oNewItem = JsonToObject(jItem, GetLocation(oTarget), oTarget, TRUE); + AssignCommand(oTarget, ActionEquipItem(oNewItem, INVENTORY_SLOT_CHEST)); + DestroyObject(oItem); + // Lock the new item so they can't change it on the character. + LockItemInCraftingWindow(oPC, oNewItem, oTarget, nToken); + // Fix buttons. + NuiSetBind(oPC, nToken, "btn_right_part_color", JsonBool(FALSE)); + jCraft = JsonObjectSet(jCraft, CRAFT_RIGHT_PART_COLOR, JsonInt(FALSE)); + NuiSetBind(oPC, nToken, "btn_all_color", JsonBool(TRUE)); + jCraft = JsonObjectSet(jCraft, CRAFT_ALL_COLOR, JsonInt(TRUE)); + NuiSetBind(oPC, nToken, "btn_left_part_color", JsonBool(FALSE)); + jCraft = JsonObjectSet(jCraft, CRAFT_RIGHT_PART_COLOR, JsonInt(FALSE)); + NuiSetBind(oPC, nToken, "btn_right_part_reset_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_all_reset_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_left_part_reset_event", JsonBool(FALSE)); + SetColorPalletPointer(oPC, nToken, oNewItem); + } + } + else if(sElem == "btn_left_part_reset") + { + if(CanCraftItem(oPC, oItem, nToken)) + { + int nModelSelected = GetArmorModelSelected(oPC); + if (nModelSelected == ITEM_APPR_ARMOR_MODEL_RTHIGH) nModelSelected = nModelSelected - 1; + else nModelSelected = nModelSelected + 1; + int nMaterialSelected = JsonGetInt(JsonObjectGet(jCraft, CRAFT_MATERIAL_SELECTION)); + int nIndex = ITEM_APPR_ARMOR_NUM_COLORS + (nModelSelected * ITEM_APPR_ARMOR_NUM_COLORS) + nMaterialSelected; + object oNewItem = CopyItemAndModify(oItem, ITEM_APPR_TYPE_ARMOR_COLOR, nIndex, 255, TRUE); + DestroyObject(oItem); + // Lock the new item so they can't change it on the character. + LockItemInCraftingWindow(oPC, oNewItem, oTarget, nToken); + // Equip new item. + AssignCommand(oTarget, ActionEquipItem(oNewItem, INVENTORY_SLOT_CHEST)); + // Fix buttons. + NuiSetBind(oPC, nToken, "btn_left_part_color", JsonBool(FALSE)); + jCraft = JsonObjectSet(jCraft, CRAFT_LEFT_PART_COLOR, JsonInt(FALSE)); + int nRight = JsonGetInt(NuiGetBind(oPC, nToken, "btn_right_part_color")); + NuiSetBind(oPC, nToken, "btn_all_color", JsonBool(!nRight)); + jCraft = JsonObjectSet(jCraft, CRAFT_ALL_COLOR, JsonInt(!nRight)); + NuiSetBind(oPC, nToken, "btn_left_part_reset_event", JsonBool(FALSE)); + nRight = JsonGetInt(NuiGetBind(oPC, nToken, "btn_right_part_reset_event")); + NuiSetBind(oPC, nToken, "btn_all_reset_event", JsonBool(nRight)); + SetColorPalletPointer(oPC, nToken, oNewItem); + } + } + // They have changed the material (color item) for the item. + else if(GetStringLeft(sElem, 13) == "btn_material_") + { + int nSelected = StringToInt(GetStringRight(sElem, 1)); + SetMaterialButtons(oPC, nToken, nSelected); + jCraft = JsonObjectSet(jCraft, CRAFT_MATERIAL_SELECTION, JsonInt(nSelected)); + // Change the pallet for the correct material. + string sColorPallet; + if(nSelected < 4) + { + sColorPallet = "gui_pal_tattoo"; + NuiSetBind(oPC, nToken, "armor_block_1", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "armor_block_2", JsonBool(FALSE)); + } + else + { + sColorPallet = "armor_pallet"; + if(ResManGetAliasFor(sColorPallet, RESTYPE_TGA) == "") + { + sColorPallet = "gui_pal_tattoo"; + NuiSetBind(oPC, nToken, "armor_block_1", JsonBool(TRUE)); + } + } + NuiSetBind(oPC, nToken, "color_pallet_image", JsonString (sColorPallet)); + SetLocalString(oPC, CRAFT_COLOR_PALLET, sColorPallet); + SetColorPalletPointer(oPC, nToken, oItem); + } + SetLocalJson(oPC, CRAFT_JSON, jCraft); + } + else if(sEvent == "mousedown") + { + int nMouseButton = JsonGetInt(JsonObjectGet(NuiGetEventPayload(), "mouse_btn")); + if(nMouseButton == NUI_MOUSE_BUTTON_RIGHT) + { + AssignCommand(oPC, PlaySound("gui_button")); + if(sElem == "btn_highlight") + { + if(GetLocalInt(oPC, CRAFT_ULTRALIGHT)) + { + RemoveTagedEffects(oTarget, CRAFT_ULTRALIGHT); + DeleteLocalInt(oPC, CRAFT_ULTRALIGHT); + NuiSetBind(oPC, nToken, "btn_highlight", JsonBool(FALSE)); + } + else + { + if(GetLocalInt(oPC, CRAFT_HIGHLIGHT)) + { + RemoveTagedEffects(oTarget, CRAFT_HIGHLIGHT); + DeleteLocalInt(oPC, CRAFT_HIGHLIGHT); + } + SetLocalInt(oPC, CRAFT_ULTRALIGHT, TRUE); + effect eLight = EffectVisualEffect(VFX_DUR_ULTRAVISION); + eLight = TagEffect(eLight, CRAFT_ULTRALIGHT); + ApplyEffectToObject(DURATION_TYPE_PERMANENT, eLight, oTarget); + NuiSetBind(oPC, nToken, "btn_highlight", JsonBool(TRUE)); + } + } + } + } + } +} +/*void CopyCraftingItem(object oPC, object oItem) +{ + //ai_Debug("pe_crafting", "295", JsonDump(ObjectToJson(oItem), 2)); + json jItem = ObjectToJson(oItem); + + SetLocalInt(oPC, CRAFT_COPY_ITEM, TRUE); + int nSelected = GetLocalInt(oPC, CRAFT_ITEM_SELECTION); + if (ai_GetIsWeapon(oItem)) + { + // Copy the base item type; + SetLocalInt(oPC, CRAFT_COPY_ITEM_TYPE, GetBaseItemType(oItem)); + // Copy each model/color & save to variables. + int nIndex = 1; + string sIndex; + while(nIndex <= 3) + { + sIndex = IntToString(nIndex); + SetLocalInt(oPC, CRAFT_COPY_MODEL + sIndex, JsonGetInt(GffGetByte(jItem, "ModelPart" + sIndex))); + nIndex++; + } + } + else if (nSelected == 0) + { + // Copy the armors AC so we can check it. + SetLocalInt(oPC, CRAFT_ARMOR_AC, ai_GetArmorBonus(oItem)); + // Copy an per part colors if they exist. + int nPart, nColor, nPartColor; + string sPart, sColor; + while(nPart <= 18) + { + sPart = IntToString(nPart); + nColor = 0; + while(nColor <= 5) + { + sColor = IntToString(nColor); + if(GffGetFieldExists(jItem, "APart_" + sPart + "_Col_" + sColor, GFF_FIELD_TYPE_BYTE)) + { + // Shift the number up by 1 so we can save as a variable and not use 0! + nPartColor = JsonGetInt(GffGetByte(jItem, "APart_" + sPart + "_Col_" + sColor)) + 1; + SetLocalInt(oPC, CRAFT_COPY_PART_COLOR + sPart + sColor, nPartColor); + } + nColor++; + } + nPart++; + } + // Copy each model & save to variables. + SetLocalInt(oPC, "CRAFT_COPY_MODEL0", JsonGetInt(GffGetByte(jItem, "ArmorPart_Belt"))); + SetLocalInt(oPC, "CRAFT_COPY_MODEL1", JsonGetInt(GffGetByte(jItem, "ArmorPart_LBicep"))); + SetLocalInt(oPC, "CRAFT_COPY_MODEL2", JsonGetInt(GffGetByte(jItem, "ArmorPart_LFArm"))); + SetLocalInt(oPC, "CRAFT_COPY_MODEL3", JsonGetInt(GffGetByte(jItem, "ArmorPart_LFoot"))); + SetLocalInt(oPC, "CRAFT_COPY_MODEL4", JsonGetInt(GffGetByte(jItem, "ArmorPart_LHand"))); + SetLocalInt(oPC, "CRAFT_COPY_MODEL5", JsonGetInt(GffGetByte(jItem, "ArmorPart_LShin"))); + SetLocalInt(oPC, "CRAFT_COPY_MODEL6", JsonGetInt(GffGetByte(jItem, "ArmorPart_LShoul"))); + SetLocalInt(oPC, "CRAFT_COPY_MODEL7", JsonGetInt(GffGetByte(jItem, "ArmorPart_LThigh"))); + SetLocalInt(oPC, "CRAFT_COPY_MODEL8", JsonGetInt(GffGetByte(jItem, "ArmorPart_Neck"))); + SetLocalInt(oPC, "CRAFT_COPY_MODEL9", JsonGetInt(GffGetByte(jItem, "ArmorPart_Pelvis"))); + SetLocalInt(oPC, "CRAFT_COPY_MODEL10", JsonGetInt(GffGetByte(jItem, "ArmorPart_RBicep"))); + SetLocalInt(oPC, "CRAFT_COPY_MODEL11", JsonGetInt(GffGetByte(jItem, "ArmorPart_RFArm"))); + SetLocalInt(oPC, "CRAFT_COPY_MODEL12", JsonGetInt(GffGetByte(jItem, "ArmorPart_RFoot"))); + SetLocalInt(oPC, "CRAFT_COPY_MODEL13", JsonGetInt(GffGetByte(jItem, "ArmorPart_RHand"))); + SetLocalInt(oPC, "CRAFT_COPY_MODEL14", JsonGetInt(GffGetByte(jItem, "ArmorPart_RShin"))); + SetLocalInt(oPC, "CRAFT_COPY_MODEL15", JsonGetInt(GffGetByte(jItem, "ArmorPart_RShoul"))); + SetLocalInt(oPC, "CRAFT_COPY_MODEL16", JsonGetInt(GffGetByte(jItem, "ArmorPart_RThigh"))); + SetLocalInt(oPC, "CRAFT_COPY_MODEL17", JsonGetInt(GffGetByte(jItem, "ArmorPart_Robe"))); + SetLocalInt(oPC, "CRAFT_COPY_MODEL18", JsonGetInt(GffGetByte(jItem, "ArmorPart_Torso"))); + // Copy each color and save to variables. + SetLocalInt(oPC, "CRAFT_COPY_COLOR0", JsonGetInt(GffGetByte(jItem, "Cloth1Color"))); + SetLocalInt(oPC, "CRAFT_COPY_COLOR1", JsonGetInt(GffGetByte(jItem, "Cloth2Color"))); + SetLocalInt(oPC, "CRAFT_COPY_COLOR2", JsonGetInt(GffGetByte(jItem, "Leather1Color"))); + SetLocalInt(oPC, "CRAFT_COPY_COLOR3", JsonGetInt(GffGetByte(jItem, "Leather2Color"))); + SetLocalInt(oPC, "CRAFT_COPY_COLOR4", JsonGetInt(GffGetByte(jItem, "Metal1Color"))); + SetLocalInt(oPC, "CRAFT_COPY_COLOR5", JsonGetInt(GffGetByte(jItem, "Metal2Color"))); + } +else + { + // Copy the base item type; + SetLocalInt(oPC, CRAFT_COPY_ITEM_TYPE, GetBaseItemType(oItem)); + // Copy the base item type; + SetLocalInt(oPC, "CRAFT_COPY_MODEL0", JsonGetInt(GffGetByte(jItem, "ModelPart1"))); + // Copy each color and save to variables. + SetLocalInt(oPC, "CRAFT_COPY_COLOR0", JsonGetInt(GffGetByte(jItem, "Cloth1Color"))); + SetLocalInt(oPC, "CRAFT_COPY_COLOR1", JsonGetInt(GffGetByte(jItem, "Cloth2Color"))); + SetLocalInt(oPC, "CRAFT_COPY_COLOR2", JsonGetInt(GffGetByte(jItem, "Leather1Color"))); + SetLocalInt(oPC, "CRAFT_COPY_COLOR3", JsonGetInt(GffGetByte(jItem, "Leather2Color"))); + SetLocalInt(oPC, "CRAFT_COPY_COLOR4", JsonGetInt(GffGetByte(jItem, "Metal1Color"))); + SetLocalInt(oPC, "CRAFT_COPY_COLOR5", JsonGetInt(GffGetByte(jItem, "Metal2Color"))); + } + // Send message that it has been copied. + ai_SendMessages(GetName (oItem) + " appearance has been copied!", AI_COLOR_GREEN, oPC); +} + +// Used in the crafting GUI to paste a copy of an item to another item. +object PasteCraftingItem (object oPC, object oTarget, object oItem) +{ + int nModelPartNum; + object oChestItem; + int nSelected = GetLocalInt(oPC, CRAFT_ITEM_SELECTION); + object oBuildContainer = GetObjectByTag(CRAFT_CONTAINER); + // Move the item to the building container. + oChestItem = CopyItem(oItem, oBuildContainer, TRUE); + DestroyObject(oItem); + json jItem = ObjectToJson(oChestItem, TRUE); + if (ai_GetIsWeapon(oChestItem)) + { + // Copy each model & save to variables. + int nIndex = 1; + string sIndex; + while(nIndex <= 3) + { + sIndex = IntToString(nIndex); + jItem = GffReplaceByte(jItem,"ModelPart" + sIndex, GetLocalInt(oPC, CRAFT_COPY_MODEL + sIndex)); + jItem = GffReplaceWord(jItem,"xModelPart" + sIndex, GetLocalInt(oPC, CRAFT_COPY_MODEL + sIndex)); + DeleteLocalInt(oPC, CRAFT_COPY_MODEL + sIndex); + nIndex++; + } + oItem = JsonToObject(jItem, GetLocation(oTarget), oTarget, TRUE); + // Equip new item. + AssignCommand(oTarget, ActionEquipItem (oItem, INVENTORY_SLOT_RIGHTHAND)); + } + // Armor. + else if (nSelected == 0) + { + // Paste per part colors if they exist. + int nPart, nColor, nPartColor; + string sPart, sColor; + while(nPart <= 18) + { + sPart = IntToString(nPart); + nColor = 0; + while(nColor <= 5) + { + sColor = IntToString(nColor); + nPartColor = GetLocalInt(oPC, CRAFT_COPY_PART_COLOR + sPart + sColor); + if(nPartColor > 0) + { + // Shift the number down by 1 since we can not use 0 in the variable! + nPartColor = nPartColor - 1; + if(GffGetFieldExists(jItem, "APart_" + sPart + "_Col_" + sColor, GFF_FIELD_TYPE_BYTE)) + { + jItem = GffReplaceByte(jItem, "APart_" + sPart + "_Col_" + sColor, nPartColor); + } + else jItem = GffAddByte(jItem, "APart_" + sPart + "_Col_" + sColor, nPartColor); + DeleteLocalInt(oPC, "CRAFT_COPY_PART_COLOR" + sPart + sColor); + } + nColor++; + } + nPart++; + } + jItem = GffReplaceByte(jItem,"ArmorPart_Belt", GetLocalInt(oPC, "CRAFT_COPY_MODEL0")); + jItem = GffReplaceByte(jItem,"ArmorPart_LBicep", GetLocalInt(oPC, "CRAFT_COPY_MODEL1")); + jItem = GffReplaceByte(jItem,"ArmorPart_LFArm", GetLocalInt(oPC, "CRAFT_COPY_MODEL2")); + jItem = GffReplaceByte(jItem,"ArmorPart_LFoot", GetLocalInt(oPC, "CRAFT_COPY_MODEL3")); + jItem = GffReplaceByte(jItem,"ArmorPart_LHand", GetLocalInt(oPC, "CRAFT_COPY_MODEL4")); + jItem = GffReplaceByte(jItem,"ArmorPart_LShin", GetLocalInt(oPC, "CRAFT_COPY_MODEL5")); + jItem = GffReplaceByte(jItem,"ArmorPart_LShoul", GetLocalInt(oPC, "CRAFT_COPY_MODEL6")); + jItem = GffReplaceByte(jItem,"ArmorPart_LThigh", GetLocalInt(oPC, "CRAFT_COPY_MODEL7")); + jItem = GffReplaceByte(jItem,"ArmorPart_Neck", GetLocalInt(oPC, "CRAFT_COPY_MODEL8")); + jItem = GffReplaceByte(jItem,"ArmorPart_Pelvis", GetLocalInt(oPC, "CRAFT_COPY_MODEL9")); + jItem = GffReplaceByte(jItem,"ArmorPart_RBicep", GetLocalInt(oPC, "CRAFT_COPY_MODEL10")); + jItem = GffReplaceByte(jItem,"ArmorPart_RFArm", GetLocalInt(oPC, "CRAFT_COPY_MODEL11")); + jItem = GffReplaceByte(jItem,"ArmorPart_RFoot", GetLocalInt(oPC, "CRAFT_COPY_MODEL12")); + jItem = GffReplaceByte(jItem,"ArmorPart_RHand", GetLocalInt(oPC, "CRAFT_COPY_MODEL13")); + jItem = GffReplaceByte(jItem,"ArmorPart_RShin", GetLocalInt(oPC, "CRAFT_COPY_MODEL14")); + jItem = GffReplaceByte(jItem,"ArmorPart_RShoul", GetLocalInt(oPC, "CRAFT_COPY_MODEL15")); + jItem = GffReplaceByte(jItem,"ArmorPart_RThigh", GetLocalInt(oPC, "CRAFT_COPY_MODEL16")); + jItem = GffReplaceByte(jItem,"ArmorPart_Robe", GetLocalInt(oPC, "CRAFT_COPY_MODEL17")); + jItem = GffReplaceByte(jItem,"ArmorPart_Torso", GetLocalInt(oPC, "CRAFT_COPY_MODEL18")); + jItem = GffReplaceWord(jItem,"xArmorPart_Belt", GetLocalInt(oPC, "CRAFT_COPY_MODEL0")); + jItem = GffReplaceWord(jItem,"xArmorPart_LBice", GetLocalInt(oPC, "CRAFT_COPY_MODEL1")); + jItem = GffReplaceWord(jItem,"xArmorPart_LFArm", GetLocalInt(oPC, "CRAFT_COPY_MODEL2")); + jItem = GffReplaceWord(jItem,"xArmorPart_LFoot", GetLocalInt(oPC, "CRAFT_COPY_MODEL3")); + jItem = GffReplaceWord(jItem,"xArmorPart_LHand", GetLocalInt(oPC, "CRAFT_COPY_MODEL4")); + jItem = GffReplaceWord(jItem,"xArmorPart_LShin", GetLocalInt(oPC, "CRAFT_COPY_MODEL5")); + jItem = GffReplaceWord(jItem,"xArmorPart_LShou", GetLocalInt(oPC, "CRAFT_COPY_MODEL6")); + jItem = GffReplaceWord(jItem,"xArmorPart_LThig", GetLocalInt(oPC, "CRAFT_COPY_MODEL7")); + jItem = GffReplaceWord(jItem,"xArmorPart_Neck", GetLocalInt(oPC, "CRAFT_COPY_MODEL8")); + jItem = GffReplaceWord(jItem,"xArmorPart_Pelvi", GetLocalInt(oPC, "CRAFT_COPY_MODEL9")); + jItem = GffReplaceWord(jItem,"xArmorPart_RBice", GetLocalInt(oPC, "CRAFT_COPY_MODEL10")); + jItem = GffReplaceWord(jItem,"xArmorPart_RFArm", GetLocalInt(oPC, "CRAFT_COPY_MODEL11")); + jItem = GffReplaceWord(jItem,"xArmorPart_RFoot", GetLocalInt(oPC, "CRAFT_COPY_MODEL12")); + jItem = GffReplaceWord(jItem,"xArmorPart_RHand", GetLocalInt(oPC, "CRAFT_COPY_MODEL13")); + jItem = GffReplaceWord(jItem,"xArmorPart_RShin", GetLocalInt(oPC, "CRAFT_COPY_MODEL14")); + jItem = GffReplaceWord(jItem,"xArmorPart_RShou", GetLocalInt(oPC, "CRAFT_COPY_MODEL15")); + jItem = GffReplaceWord(jItem,"xArmorPart_RThig", GetLocalInt(oPC, "CRAFT_COPY_MODEL16")); + jItem = GffReplaceWord(jItem,"xArmorPart_Robe", GetLocalInt(oPC, "CRAFT_COPY_MODEL17")); + jItem = GffReplaceWord(jItem,"xArmorPart_Torso", GetLocalInt(oPC, "CRAFT_COPY_MODEL18")); + jItem = GffReplaceByte(jItem,"Cloth1Color", GetLocalInt(oPC, "CRAFT_COPY_COLOR0")); + jItem = GffReplaceByte(jItem,"Cloth2Color", GetLocalInt(oPC, "CRAFT_COPY_COLOR1")); + jItem = GffReplaceByte(jItem,"Leather1Color", GetLocalInt(oPC, "CRAFT_COPY_COLOR2")); + jItem = GffReplaceByte(jItem,"Leather2Color", GetLocalInt(oPC, "CRAFT_COPY_COLOR3")); + jItem = GffReplaceByte(jItem,"Metal1Color", GetLocalInt(oPC, "CRAFT_COPY_COLOR4")); + jItem = GffReplaceByte(jItem,"Metal2Color", GetLocalInt(oPC, "CRAFT_COPY_COLOR5")); + oItem = JsonToObject(jItem, GetLocation(oTarget), oTarget, TRUE); + int nIndex; + for(nIndex = 0; nIndex <= 18; nIndex++) + { + DeleteLocalInt(oPC, CRAFT_COPY_MODEL + IntToString(nIndex)); + } + for(nIndex = 0; nIndex <= 5; nIndex++) + { + DeleteLocalInt(oPC, CRAFT_COPY_COLOR + IntToString(nIndex)); + } + // Equip new item. + AssignCommand (oTarget, ActionEquipItem (oItem, INVENTORY_SLOT_CHEST)); + } + else if(ai_GetIsShield(oChestItem)) + { + jItem = GffReplaceByte(jItem,"ModelPart1", GetLocalInt(oPC, "CRAFT_COPY_MODEL1")); + jItem = GffReplaceWord(jItem,"xModelPart1", GetLocalInt(oPC, "CRAFT_COPY_MODEL1")); + oItem = JsonToObject(jItem, GetLocation(oTarget), oTarget, TRUE); + // Equip new item. + AssignCommand(oTarget, ActionEquipItem (oItem, INVENTORY_SLOT_LEFTHAND)); + } + else + { + //ai_Debug("pe_crafting", "389", JsonDump(ObjectToJson(oChestItem), 2)); + jItem = GffReplaceByte(jItem,"ModelPart1", GetLocalInt(oPC, "CRAFT_COPY_MODEL0")); + jItem = GffReplaceWord(jItem,"xModelPart1", GetLocalInt(oPC, "CRAFT_COPY_MODEL0")); + jItem = GffReplaceByte(jItem,"Cloth1Color", GetLocalInt(oPC, "CRAFT_COPY_COLOR0")); + jItem = GffReplaceByte(jItem,"Cloth2Color", GetLocalInt(oPC, "CRAFT_COPY_COLOR1")); + jItem = GffReplaceByte(jItem,"Leather1Color", GetLocalInt(oPC, "CRAFT_COPY_COLOR2")); + jItem = GffReplaceByte(jItem,"Leather2Color", GetLocalInt(oPC, "CRAFT_COPY_COLOR3")); + jItem = GffReplaceByte(jItem,"Metal1Color", GetLocalInt(oPC, "CRAFT_COPY_COLOR4")); + jItem = GffReplaceByte(jItem,"Metal2Color", GetLocalInt(oPC, "CRAFT_COPY_COLOR5")); + oItem = JsonToObject(jItem, GetLocation(oTarget), oTarget, TRUE); + DeleteLocalInt(oPC, "CRAFT_COPY_MODEL0"); + int nIndex; + for(nIndex = 0; nIndex <= 5; nIndex++) + { + DeleteLocalInt(oPC, CRAFT_COPY_COLOR + IntToString(nIndex)); + } + // Equip new item. + int nItemType = GetBaseItemType(oChestItem); + if(nItemType == BASE_ITEM_CLOAK) AssignCommand(oTarget, ActionEquipItem (oItem, INVENTORY_SLOT_CLOAK)); + else if(nItemType == BASE_ITEM_HELMET) AssignCommand(oTarget, ActionEquipItem (oItem, INVENTORY_SLOT_HEAD)); + } + // Send message that it has been copied. + AssignCommand(oPC, ai_SendMessages (GetName (oItem) + " appearance has been changed!", AI_COLOR_GREEN, oPC)); + DestroyObject(oChestItem); + return oItem; +} */ +int GetItemSelectedEquipSlot (int nItemSelected) +{ + if (nItemSelected == 0) return INVENTORY_SLOT_CHEST; + if (nItemSelected == 1) return INVENTORY_SLOT_CLOAK; + if (nItemSelected == 2) return INVENTORY_SLOT_HEAD; + if (nItemSelected == 3) return INVENTORY_SLOT_RIGHTHAND; + if (nItemSelected == 4) return INVENTORY_SLOT_LEFTHAND; + return INVENTORY_SLOT_CHEST; +} +int GetArmorModelSelected (object oPC) +{ + json jCraft = GetLocalJson(oPC, CRAFT_JSON); + int nModelSelected = JsonGetInt(JsonObjectGet(jCraft, CRAFT_MODEL_SELECTION)); + if(nModelSelected == 0) return ITEM_APPR_ARMOR_MODEL_NECK; + if(nModelSelected == 1) return ITEM_APPR_ARMOR_MODEL_RSHOULDER; + if(nModelSelected == 2) return ITEM_APPR_ARMOR_MODEL_RBICEP; + if(nModelSelected == 3) return ITEM_APPR_ARMOR_MODEL_RFOREARM; + if(nModelSelected == 4) return ITEM_APPR_ARMOR_MODEL_RHAND; + if(nModelSelected == 5) return ITEM_APPR_ARMOR_MODEL_TORSO; + if(nModelSelected == 6) return ITEM_APPR_ARMOR_MODEL_BELT; + if(nModelSelected == 7) return ITEM_APPR_ARMOR_MODEL_PELVIS; + if(nModelSelected == 8) return ITEM_APPR_ARMOR_MODEL_RTHIGH; + if(nModelSelected == 9) return ITEM_APPR_ARMOR_MODEL_RSHIN; + if(nModelSelected == 10) return ITEM_APPR_ARMOR_MODEL_RFOOT; + return ITEM_APPR_ARMOR_MODEL_ROBE; +} +int GetMaxSimpleItemNumber(object oItem, int nBaseItemType) +{ + int nResType, nMaxNumber, nModelNumber; + string sModelNumber, sModelName = Get2DAString("baseitems", "ItemClass", nBaseItemType) + "_"; + //ai_Debug("pe_crafting", "804", "sModelName: " + sModelName + sModelNumber + + // " nModelNumber: " + IntToString(nModelNumber)); + while(nModelNumber < 999) + { + if(nModelNumber < 10) sModelNumber = "00" + IntToString(nModelNumber); + else if(nModelNumber < 100) sModelNumber = "0" + IntToString(nModelNumber); + else sModelNumber = IntToString(nModelNumber); + if(nBaseItemType == BASE_ITEM_CLOAK) nResType = RESTYPE_PLT; + else nResType = RESTYPE_MDL; + if(ResManGetAliasFor(sModelName + sModelNumber, nResType) != "") nMaxNumber++; + nModelNumber++; + //ai_Debug("pe_crafting", "841", "sModelName: " + sModelName + sModelNumber + + // " nModelNumber: " + IntToString(nModelNumber)); + } + return nMaxNumber; +} +int GetSimpleItemNumber(object oItem, int nModelNumber, int nBaseItemType) +{ + int nResType, nIndex, nCounter; + string sModelNumber, sModelName = Get2DAString("baseitems", "ItemClass", nBaseItemType) + "_"; + //ai_Debug("pe_crafting", "804", "sModelName: " + sModelName + sModelNumber + + // " nModelNumber: " + IntToString(nModelNumber)); + while(nIndex <= 999) + { + if(nIndex < 10) sModelNumber = "00" + IntToString(nIndex); + else if(nIndex < 100) sModelNumber = "0" + IntToString(nIndex); + else sModelNumber = IntToString(nIndex); + if(nBaseItemType == BASE_ITEM_CLOAK) nResType = RESTYPE_PLT; + else nResType = RESTYPE_MDL; + if(ResManGetAliasFor(sModelName + sModelNumber, nResType) != "") nCounter++; + if(nCounter == nModelNumber) return nIndex; + nIndex++; + //ai_Debug("pe_crafting", "841", "sModelName: " + sModelName + sModelNumber + + // " nModelNumber: " + IntToString(nModelNumber)); + } + return nIndex; +} +int GetMaxWeaponModuleNumber(struct stWeaponAppearance stWA) +{ + int nBaseItemType = GetBaseItemType(stWA.oItem); + stWA.nColor = 1; + stWA.nModel = 99; + stWA.sPart = "t"; + string sModelNumber; + string sModelName = Get2DAString("baseitems", "ItemClass", nBaseItemType) + "_" + stWA.sPart + "_"; + int nModelNumber = (stWA.nModel * 10) + stWA.nColor; + if(nModelNumber < 10) sModelNumber = "00" + IntToString(nModelNumber); + else if(nModelNumber < 100) sModelNumber = "0" + IntToString(nModelNumber); + else sModelNumber = IntToString(nModelNumber); + //SendMessageToPC(GetFirstPC(), "pe_crafting, 780, sModel: " + sModelName + sModelNumber + + // " nModel: " + IntToString(stWA.nModel) + " nColor: " + IntToString(stWA.nColor)); + while(ResManGetAliasFor(sModelName + sModelNumber, RESTYPE_MDL) == "") + { + stWA.nModel += -1; + // Create the model name. + nModelNumber = (stWA.nModel * 10) + stWA.nColor; + if(nModelNumber < 100) sModelNumber = "0" + IntToString(nModelNumber); + else sModelNumber = IntToString(nModelNumber); + //SendMessageToPC(GetFirstPC(), "pe_crafting, 789, sModel: " + sModelName + sModelNumber + + // " nModel: " + IntToString(stWA.nModel) + " nColor: " + IntToString(stWA.nColor)); + } + return stWA.nModel; +} +struct stWeaponAppearance GetNextWeaponAppearance(struct stWeaponAppearance stWA, int nDirection) +{ + int nBaseItemType = GetBaseItemType(stWA.oItem); + string sModelNumber; + string sModelName = Get2DAString("baseitems", "ItemClass", nBaseItemType) + "_" + stWA.sPart + "_"; + // Get next/previous color/model. + stWA.nColor += nDirection; + if(stWA.nColor > 9) + { + stWA.nColor = 1; + stWA.nModel += nDirection; + if(stWA.nModel > CRAFT_MAX_WEAPON_MODEL_NUMBER) stWA.nModel = 1; + } + else if(stWA.nColor < 1) + { + stWA.nColor = 9; + stWA.nModel += nDirection; + if(stWA.nModel < 1) stWA.nModel = CRAFT_MAX_WEAPON_MODEL_NUMBER; + } + int nModelNumber = (stWA.nModel * 10) + stWA.nColor; + if(nModelNumber < 10) sModelNumber = "00" + IntToString(nModelNumber); + else if(nModelNumber < 100) sModelNumber = "0" + IntToString(nModelNumber); + else sModelNumber = IntToString(nModelNumber); + //SendMessageToPC(GetFirstPC(), "pe_crafting, 778, sModel: " + sModelName + sModelNumber + + // " nModel: " + IntToString(stWA.nModel) + " nColor: " + IntToString(stWA.nColor)); + while(ResManGetAliasFor(sModelName + sModelNumber, RESTYPE_MDL) == "") + { + // Get next/previous color/model. + stWA.nColor += nDirection; + if(stWA.nColor > 9) + { + stWA.nColor = 1; + stWA.nModel += nDirection; + if(stWA.nModel > CRAFT_MAX_WEAPON_MODEL_NUMBER) stWA.nModel = 1; + } + else if(stWA.nColor < 1) + { + stWA.nColor = 9; + stWA.nModel += nDirection; + if(stWA.nModel < 1) stWA.nModel = CRAFT_MAX_WEAPON_MODEL_NUMBER; + } + // Create the model name. + nModelNumber = (stWA.nModel * 10) + stWA.nColor; + if(nModelNumber < 100) sModelNumber = "0" + IntToString(nModelNumber); + else sModelNumber = IntToString(nModelNumber); + //SendMessageToPC(GetFirstPC(), "pe_crafting, 800, sModel: " + sModelName + sModelNumber + + // " nModel: " + IntToString(stWA.nModel) + " nColor: " + IntToString(stWA.nColor)); + } + return stWA; +} +object ChangeItemsAppearance(object oPC, object oTarget, int nToken, object oItem, int nDirection, string sPart) +{ + json jCraft = GetLocalJson(oPC, CRAFT_JSON); + // Get the item we are changing. + int nModelSelected; + int nItemSelected = JsonGetInt(JsonObjectGet(jCraft, CRAFT_ITEM_SELECTION)); + string sModelName, sModelNumber; + object oNewItem; + // Weapons. + if(ai_GetIsWeapon(oItem)) + { + // Freeze animations - vfx 352? + if(sPart == "t") nModelSelected = 2; + else if(sPart == "m") nModelSelected = 1; + else if(sPart == "b") nModelSelected = 0; + sModelName = Get2DAString("baseitems", "ItemClass", GetBaseItemType(oItem)) + "_" + sPart + "_"; + struct stWeaponAppearance stWA; + stWA.oItem = oItem; + stWA.sPart = sPart; + stWA.nModel = GetItemAppearance(oItem, ITEM_APPR_TYPE_WEAPON_MODEL, nModelSelected); + stWA.nColor = GetItemAppearance(oItem, ITEM_APPR_TYPE_WEAPON_COLOR, nModelSelected); + stWA = GetNextWeaponAppearance(stWA, nDirection); + json jItem = ObjectToJson(oItem, TRUE); + int nModelNumber = stWA.nModel * 10 + stWA.nColor; + jItem = GffReplaceByte(jItem, "ModelPart" + IntToString(nModelSelected + 1), nModelNumber); + jItem = GffReplaceWord(jItem, "xModelPart" + IntToString(nModelSelected + 1), nModelNumber); + oNewItem = JsonToObject(jItem, GetLocation(oTarget), oTarget, TRUE); + AssignCommand(oTarget, ClearAllActions(TRUE)); + DestroyObject(oItem); + // Item selected 3 is the right hand, 4 is the left hand. + //SendMessageToPC(oPC, "nItemSelected: " + IntToString(nItemSelected)); + if(nItemSelected == 3) + { + AssignCommand(oTarget, ActionEquipItem(oNewItem, INVENTORY_SLOT_RIGHTHAND)); + } + else AssignCommand(oTarget, ActionEquipItem(oNewItem, INVENTORY_SLOT_LEFTHAND)); + NuiSetBind(oPC, nToken, "txt_model_number_" + sPart, JsonString(IntToString(nModelNumber))); + } + // Armor. + else if(nItemSelected == 0) + { + // Create the model name. + // Get the ModelType. + int nAppearance = GetAppearanceType(oTarget); + string sModelName = Get2DAString("appearance", "MODELTYPE", nAppearance); + // Get gender. + if(GetGender(oTarget) == GENDER_MALE) sModelName += "m"; + else sModelName += "f"; + // Get race. + sModelName += Get2DAString("appearance", "RACE", nAppearance); + // Get Phenotype. + sModelName += IntToString(GetPhenoType(oTarget)) + "_"; + // Get the selected model. + nModelSelected = GetArmorModelSelected(oPC); + //ai_Debug("pe_crafting", "646", "nModelSide: " + IntToString(nModelSide)); + // If we are doing the left side (bottom menu options) then add one to + // get the left side. + // Note: Right Thigh and Left Thigh are backwards so this fixes that! + if(sPart == "b") + { + if(nModelSelected == ITEM_APPR_ARMOR_MODEL_RTHIGH) nModelSelected--; + else nModelSelected++; + } + int nModelNumber = StringToInt(JsonGetString(NuiGetBind(oPC, nToken, "txt_model_number_" + sPart))); + //int nModelNumber = GetItemAppearance(oItem, ITEM_APPR_TYPE_ARMOR_MODEL, nModelSelected); + //SendMessageToPC(oPC, "pe_crafting, 826, nModelNumber: " + IntToString(nModelNumber) + + // " sPart: " + sPart + " nModelSelected: " + IntToString(nModelSelected)); + int nBaseModelNumber = nModelNumber; + nModelNumber += nDirection; + if(nModelNumber > CRAFT_MAX_MODEL_NUMBER) nModelNumber = 0; + else if(nModelNumber < 0) nModelNumber = CRAFT_MAX_MODEL_NUMBER; + string sModelNumber; + if(nModelNumber < 10) sModelNumber = "00" + IntToString(nModelNumber); + else if(nModelNumber < 100) sModelNumber = "0" + IntToString(nModelNumber); + else sModelNumber = IntToString(nModelNumber); + // Check for changes to the torso (base part of the armor linked to AC). + if(nModelSelected == ITEM_APPR_ARMOR_MODEL_TORSO) + { + string sCurrentACBonus = Get2DAString("parts_chest", "ACBONUS", nBaseModelNumber); + string sACBonus = Get2DAString ("parts_chest", "ACBONUS", nModelNumber); + sModelName += Get2DAString ("capart", "MDLNAME", nModelSelected); + //SendMessageToPC(oPC, "pe_crafting, 842, sModelName: " + sModelName + sModelNumber + + // " nModelNumber: " + IntToString(nModelNumber) + " sCurrentACBonus: " + sCurrentACBonus + + // " sACBonus: " + sACBonus + " nModelSelected: " + IntToString(nModelSelected)); + while(ResManGetAliasFor(sModelName + sModelNumber, RESTYPE_MDL) == "" || + sACBonus != sCurrentACBonus) + { + nModelNumber += nDirection; + if (nModelNumber > CRAFT_MAX_MODEL_NUMBER) nModelNumber = 0; + else if (nModelNumber < 0) nModelNumber = CRAFT_MAX_MODEL_NUMBER; + if(nModelNumber < 10) sModelNumber = "00" + IntToString(nModelNumber); + else if(nModelNumber < 100) sModelNumber = "0" + IntToString(nModelNumber); + else sModelNumber = IntToString(nModelNumber); + sACBonus = Get2DAString ("parts_chest", "ACBONUS", nModelNumber); + //SendMessageToPC(oPC, "pe_crafting, 854, sModelName: " + sModelName + sModelNumber + + // " nModelNumber: " + IntToString(nModelNumber) + " sACBonus: " + sACBonus + + // " nModelSelected: " + IntToString(nModelSelected)); + } + // Change the model. + oNewItem = CopyItemAndModify (oItem, ITEM_APPR_TYPE_ARMOR_MODEL, nModelSelected, nModelNumber, TRUE); + DestroyObject (oItem); + AssignCommand (oTarget, ActionEquipItem (oNewItem, INVENTORY_SLOT_CHEST)); + } + // Change all other parts of armor. + else + { + sModelName += Get2DAString("capart", "MDLNAME", nModelSelected); + //SendMessageToPC(oPC, "pe_crafting, 866, sModelName: " + sModelName + sModelNumber + + // " nModelNumber: " + IntToString(nModelNumber) + " nModelSelected: " + IntToString(nModelSelected)); + while(ResManGetAliasFor(sModelName + sModelNumber, RESTYPE_MDL) == "") + { + nModelNumber += nDirection; + if (nModelNumber > CRAFT_MAX_MODEL_NUMBER) nModelNumber = 0; + else if (nModelNumber < 0) nModelNumber = CRAFT_MAX_MODEL_NUMBER; + if(nModelNumber < 10) sModelNumber = "00" + IntToString(nModelNumber); + else if(nModelNumber < 100) sModelNumber = "0" + IntToString(nModelNumber); + else sModelNumber = IntToString(nModelNumber); + //SendMessageToPC(oPC, "pe_crafting, 705, sModelName: " + sModelName + sModelNumber + + // " nModelNumber: " + IntToString(nModelNumber) + " nModelSelected: " + IntToString(nModelSelected)); + } + oNewItem = CopyItemAndModify (oItem, ITEM_APPR_TYPE_ARMOR_MODEL, nModelSelected, nModelNumber, TRUE); + DestroyObject (oItem); + // If using the linked menu option then change the left side too. + if(sPart == "m" && (nModelSelected != ITEM_APPR_ARMOR_MODEL_NECK && + nModelSelected != ITEM_APPR_ARMOR_MODEL_BELT && + nModelSelected != ITEM_APPR_ARMOR_MODEL_PELVIS && + nModelSelected != ITEM_APPR_ARMOR_MODEL_ROBE)) + { + // Note: Right Thigh and Left Thigh are backwards so this fixes that! + if (nModelSelected == ITEM_APPR_ARMOR_MODEL_RTHIGH) nModelSelected--; + else nModelSelected++; + oItem = CopyItemAndModify(oNewItem, ITEM_APPR_TYPE_ARMOR_MODEL, nModelSelected, nModelNumber, TRUE); + DestroyObject(oNewItem); + AssignCommand(oTarget, ActionEquipItem(oItem, INVENTORY_SLOT_CHEST)); + } + else AssignCommand(oTarget, ActionEquipItem(oNewItem, INVENTORY_SLOT_CHEST)); + } + string sModelSelected; + if (nModelSelected == ITEM_APPR_ARMOR_MODEL_NECK || + nModelSelected == ITEM_APPR_ARMOR_MODEL_TORSO || + nModelSelected == ITEM_APPR_ARMOR_MODEL_BELT || + nModelSelected == ITEM_APPR_ARMOR_MODEL_PELVIS || + nModelSelected == ITEM_APPR_ARMOR_MODEL_ROBE) + { + NuiSetBind(oPC, nToken, "txt_model_number_" + sPart, JsonString(IntToString(nModelNumber))); + } + else + { + if(sPart == "m") + { + // Using labels for Mobile. + //NuiSetBind(oPC, nToken, "txt_model_number_t", JsonString(IntToString(nModelNumber))); + //NuiSetBind(oPC, nToken, "txt_model_number_m", JsonString(IntToString(nModelNumber))); + //NuiSetBind(oPC, nToken, "txt_model_number_b", JsonString(IntToString(nModelNumber))); + NuiSetBind(oPC, nToken, "txt_model_number_t", JsonString(IntToString(nModelNumber))); + NuiSetBind(oPC, nToken, "txt_model_number_m", JsonString(IntToString(nModelNumber))); + NuiSetBind(oPC, nToken, "txt_model_number_b", JsonString(IntToString(nModelNumber))); + } + else + { + NuiSetBind(oPC, nToken, "txt_model_number_" + sPart, JsonString(IntToString(nModelNumber))); + } + } + } + // All other items. + else + { + int nSlot, nResType, nBaseItemType = GetBaseItemType(oItem); + string sModelName = Get2DAString("baseitems", "ItemClass", nBaseItemType) + "_"; + if(nBaseItemType == BASE_ITEM_CLOAK) + { + nSlot = INVENTORY_SLOT_CLOAK; + nResType = RESTYPE_PLT; + } + else if(nBaseItemType == BASE_ITEM_HELMET) + { + nSlot = INVENTORY_SLOT_HEAD; + nResType = RESTYPE_MDL; + } + else if(nBaseItemType == BASE_ITEM_LARGESHIELD || + nBaseItemType == BASE_ITEM_SMALLSHIELD || + nBaseItemType == BASE_ITEM_TOWERSHIELD) + { + nSlot = INVENTORY_SLOT_LEFTHAND; + nResType = RESTYPE_MDL; + } + int nModelNumber = GetItemAppearance(oItem, ITEM_APPR_TYPE_SIMPLE_MODEL, 0); + nModelNumber += nDirection; + if (nModelNumber > CRAFT_MAX_MODEL_NUMBER) nModelNumber = 0; + else if (nModelNumber < 0) nModelNumber = CRAFT_MAX_MODEL_NUMBER; + if(nModelNumber < 10) sModelNumber = "00" + IntToString(nModelNumber); + else if(nModelNumber < 100) sModelNumber = "0" + IntToString(nModelNumber); + else sModelNumber = IntToString(nModelNumber); + //ai_Debug("pe_crafting", "804", "sModelName: " + sModelName + sModelNumber + + // " nModelNumber: " + IntToString(nModelNumber)); + while(ResManGetAliasFor(sModelName + sModelNumber, nResType) == "") + { + nModelNumber += nDirection; + if (nModelNumber > CRAFT_MAX_MODEL_NUMBER) nModelNumber = 0; + else if (nModelNumber < 0) nModelNumber = CRAFT_MAX_MODEL_NUMBER; + if(nModelNumber < 10) sModelNumber = "00" + IntToString(nModelNumber); + else if(nModelNumber < 100) sModelNumber = "0" + IntToString(nModelNumber); + else sModelNumber = IntToString(nModelNumber); + //ai_Debug("pe_crafting", "841", "sModelName: " + sModelName + sModelNumber + + // " nModelNumber: " + IntToString(nModelNumber)); + } + oNewItem = CopyItemAndModify(oItem, ITEM_APPR_TYPE_SIMPLE_MODEL, 0, nModelNumber, TRUE); + DestroyObject(oItem); + AssignCommand(oTarget, ActionEquipItem (oNewItem, nSlot)); + NuiSetBind(oPC, nToken, "txt_model_number_" + sPart, JsonString(IntToString(nModelNumber))); + } + return oNewItem; +} +object RandomizeItemsCraftAppearance(object oPC, object oTarget, int nToken, object oItem) +{ + // Get the item we are changing. + json jCraft = GetLocalJson(oPC, CRAFT_JSON); + int nItemSelected = JsonGetInt(JsonObjectGet(jCraft, CRAFT_ITEM_SELECTION)); + int nBaseItemType = GetBaseItemType(oItem); + object oNewItem; + if(ai_GetIsWeapon(oItem)) + { + int nRollTop, nRollMid, nRollBottom; + int nColorTop, nColorMid, nColorBottom; + struct stWeaponAppearance stWA; + stWA.oItem = oItem; + int nMaxModuleNumber = GetMaxWeaponModuleNumber(stWA); + nRollTop = Random(nMaxModuleNumber) + 1; + // Check bows as they must randomize to the same top, middle, and bottom otherwise they look bad. + if(nBaseItemType == BASE_ITEM_LONGBOW || nBaseItemType == BASE_ITEM_SHORTBOW) + { + nRollMid = nRollTop; + nRollBottom = nRollTop; + } + // Randomize each item individualy for other weapons. + else + { + nRollMid = Random(nMaxModuleNumber) + 1; + nRollBottom = Random(nMaxModuleNumber) + 1; + } + nColorTop = Random(9) + 1; + nColorMid = Random(9) + 1; + nColorBottom = Random(9) + 1; + // Change weapons model. + stWA.sPart = "t"; + stWA.nModel = nRollTop; + stWA.nColor = nColorTop; + stWA = GetNextWeaponAppearance(stWA, -1); + json jItem = ObjectToJson(oItem, TRUE); + //ai_Debug("pe_crafting", "614", "ModelPart" + IntToString(nModelSelected + 1) + + // " nModelNumber: " + IntToString(nModelNumber)); + jItem = GffReplaceByte(jItem, "ModelPart" + IntToString(3), stWA.nModel * 10 + stWA.nColor); + jItem = GffReplaceWord(jItem, "xModelPart" + IntToString(3), stWA.nModel * 10 + stWA.nColor); + NuiSetBind(oPC, nToken, "txt_model_number_" + stWA.sPart, JsonString(IntToString(stWA.nModel * 10 + stWA.nColor))); + stWA.sPart = "m"; + stWA.nModel = nRollMid; + stWA.nColor = nColorMid; + stWA = GetNextWeaponAppearance(stWA, -1); + jItem = GffReplaceByte(jItem, "ModelPart" + IntToString(2), stWA.nModel * 10 + stWA.nColor); + jItem = GffReplaceWord(jItem, "xModelPart" + IntToString(2), stWA.nModel * 10 + stWA.nColor); + NuiSetBind(oPC, nToken, "txt_model_number_" + stWA.sPart, JsonString(IntToString(stWA.nModel * 10 + stWA.nColor))); + stWA.sPart = "b"; + stWA.nModel = nRollBottom; + stWA.nColor = nColorBottom; + stWA = GetNextWeaponAppearance(stWA, -1); + jItem = GffReplaceByte(jItem, "ModelPart" + IntToString(1), stWA.nModel * 10 + stWA.nColor); + jItem = GffReplaceWord(jItem, "xModelPart" + IntToString(1), stWA.nModel * 10 + stWA.nColor); + NuiSetBind(oPC, nToken, "txt_model_number_" + stWA.sPart, JsonString(IntToString(stWA.nModel * 10 + stWA.nColor))); + oNewItem = JsonToObject(jItem, GetLocation(oTarget), oTarget, TRUE); + AssignCommand(oTarget, ClearAllActions(TRUE)); + DestroyObject(oItem); + // Item selected 3 is the right hand, 4 is the left hand. + if (nItemSelected == 3) AssignCommand(oTarget, ActionEquipItem(oNewItem, INVENTORY_SLOT_RIGHTHAND)); + else AssignCommand(oTarget, ActionEquipItem(oNewItem, INVENTORY_SLOT_LEFTHAND)); + } + // Armor. + else if(nItemSelected == 0) + { + int nRoll, nRoll2; + json jItem = ObjectToJson(oItem, TRUE); + // Randomize the models. + // Randomize Torso + //jItem = GffReplaceByte(jItem, "ArmorPart_Torso", ); + //jItem = GffReplaceWord(jItem, "xArmorPart_Torso", ); + // Randomize the colors. + nRoll = Random(175) + 1; + if(d100() < 50) nRoll2 = nRoll + Random(5) - 3; + else nRoll2 = Random(175) + 1; + jItem = GffReplaceByte(jItem, "Cloth1Color", nRoll); + jItem = GffReplaceByte(jItem, "Cloth2Color", nRoll2); + if(d100() < 50) nRoll = nRoll + Random(5) - 3; + else nRoll = Random(175) + 1; + if(d100() < 50) nRoll2 = nRoll + Random(5) - 3; + else nRoll2 = Random(175) + 1; + jItem = GffReplaceByte(jItem, "Leather1Color", nRoll); + jItem = GffReplaceByte(jItem, "Leather2Color", nRoll2); + if(d100() < 50) nRoll = nRoll + Random(5) - 3; + else nRoll = Random(175) + 1; + if(d100() < 50) nRoll2 = nRoll + Random(5) - 3; + else nRoll2 = Random(175) + 1; + jItem = GffReplaceByte(jItem, "Metal1Color", nRoll); + jItem = GffReplaceByte(jItem, "Metal2Color", nRoll2); + DestroyObject(oItem); + oNewItem = JsonToObject(jItem, GetLocation(oTarget), oTarget, TRUE); + AssignCommand(oTarget, ActionEquipItem(oNewItem, INVENTORY_SLOT_CHEST)); + } + // All other items. + else + { + int nSlot; + // Get max models and inventory slot. + int nMaxModel = GetMaxSimpleItemNumber(oItem, nBaseItemType); + if(nBaseItemType == BASE_ITEM_CLOAK) nSlot = INVENTORY_SLOT_CLOAK; + else if(nBaseItemType == BASE_ITEM_HELMET) nSlot = INVENTORY_SLOT_HEAD; + else if(nBaseItemType == BASE_ITEM_LARGESHIELD || nBaseItemType == BASE_ITEM_SMALLSHIELD || + nBaseItemType == BASE_ITEM_TOWERSHIELD) nSlot = INVENTORY_SLOT_LEFTHAND; + int nRoll = Random(nMaxModel) + 1; + int nModel = GetSimpleItemNumber(oItem, nRoll, nBaseItemType); + json jItem = ObjectToJson(oItem, TRUE); + jItem = GffReplaceByte(jItem, "ModelPart1", nModel); + jItem = GffReplaceWord(jItem, "xModelPart1", nModel); + if (nBaseItemType == BASE_ITEM_CLOAK || nBaseItemType == BASE_ITEM_HELMET) + { + jItem = GffReplaceByte(jItem, "Cloth1Color", Random(175) + 1); + jItem = GffReplaceByte(jItem, "Cloth2Color", Random(175) + 1); + jItem = GffReplaceByte(jItem, "Leather1Color", Random(175) + 1); + jItem = GffReplaceByte(jItem, "Leather2Color", Random(175) + 1); + jItem = GffReplaceByte(jItem, "Metal1Color", Random(175) + 1); + jItem = GffReplaceByte(jItem, "Metal2Color", Random(175) + 1); + } + DestroyObject(oItem); + oNewItem = JsonToObject(jItem, GetLocation(oTarget), oTarget, TRUE); + AssignCommand(oTarget, ActionEquipItem(oNewItem, nSlot)); + } + return oNewItem; +} +object GetSelectedItem(object oTarget, int nItemSelected) +{ + if(nItemSelected == 0) return GetItemInSlot(INVENTORY_SLOT_CHEST, oTarget); + else if(nItemSelected == 1) return GetItemInSlot(INVENTORY_SLOT_CLOAK, oTarget); + else if(nItemSelected == 2) return GetItemInSlot(INVENTORY_SLOT_HEAD, oTarget); + else if(nItemSelected == 3) return GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTarget); + else if(nItemSelected == 4) return GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oTarget); + return OBJECT_INVALID; +} +void CancelCraftedItem(object oPC, object oTarget) +{ + json jCraft = GetLocalJson(oPC, CRAFT_JSON); + int nItemSelected = JsonGetInt(JsonObjectGet(jCraft, CRAFT_ITEM_SELECTION)); + object oItem = GetSelectedItem(oTarget, nItemSelected); + object oOriginalItem = GetLocalObject(oPC, CRAFT_ORIGINAL_ITEM); + if(oOriginalItem != OBJECT_INVALID) + { + DestroyObject(oItem); + int nSlot = GetItemSelectedEquipSlot(nItemSelected); + // Give item Backup to Player + oOriginalItem = CopyItem(oOriginalItem, oTarget, TRUE); + DelayCommand(0.2f, AssignCommand (oTarget, ActionEquipItem(oOriginalItem, nSlot))); + DeleteLocalObject(oPC, CRAFT_ORIGINAL_ITEM); + } +} +// Gets the colorId from a image of the color pallet. +// Thanks Zunath for the base code. +int GetColorPalletId(object oPC, int nToken) +{ + float fScale = IntToFloat(GetPlayerDeviceProperty(oPC, PLAYER_DEVICE_PROPERTY_GUI_SCALE)) / 100.0f; + json jPayload = NuiGetEventPayload(); + json jMousePosition = JsonObjectGet(jPayload, "mouse_pos"); + json jX = JsonObjectGet(jMousePosition, "x"); + json jY = JsonObjectGet(jMousePosition, "y"); + float fX = StringToFloat(JsonDump (jX)); + float fY = StringToFloat(JsonDump (jY)); + float fCellSize = 20.0f * fScale; + int nCellX = FloatToInt(fX / fCellSize); + int nCellY = FloatToInt(fY / fCellSize); + if(nCellX < 0) nCellX = 0; + else if (nCellX > 16) nCellX = 16; + if(nCellY < 0) nCellY = 0; + else if(nCellY > 11) nCellY = 11; + NuiSetBind(oPC, nToken, "color_pallet_pointer", NuiRect(IntToFloat(nCellX * 20), IntToFloat(nCellY * 20), 20.0, 20.0)); + return nCellX + nCellY * 16; +} +void SetColorPalletPointer(object oPC, int nToken, object oItem) +{ + json jCraft = GetLocalJson(oPC, CRAFT_JSON); + int nMaterialSelected = JsonGetInt(JsonObjectGet(jCraft, CRAFT_MATERIAL_SELECTION)); + int nColor; + if(!JsonGetInt(NuiGetBind(oPC, nToken, "btn_all_color"))) + { + int nModelSelected = GetArmorModelSelected(oPC); + if(!JsonGetInt(JsonObjectGet(jCraft, CRAFT_RIGHT_PART_COLOR))) + { + // Note: Right Thigh and Left Thigh are backwards so this fixes that! + if (nModelSelected == ITEM_APPR_ARMOR_MODEL_RTHIGH) nModelSelected--; + else nModelSelected++; + } + int nIndex = ITEM_APPR_ARMOR_NUM_COLORS + (nModelSelected * ITEM_APPR_ARMOR_NUM_COLORS) + nMaterialSelected; + nColor = GetItemAppearance(oItem, ITEM_APPR_TYPE_ARMOR_COLOR, nIndex); + } + else nColor = 255; + if(nColor == 255) nColor = GetItemAppearance(oItem, ITEM_APPR_TYPE_ARMOR_COLOR, nMaterialSelected); + float fPointX = IntToFloat((nColor - ((nColor / 16) * 16)) * 20); + float fPointY = IntToFloat((nColor / 16) * 20); + NuiSetBind(oPC, nToken, "color_pallet_pointer", NuiRect(fPointX, fPointY, 20.0, 20.0)); +} +void LockItemInCraftingWindow(object oPC, object oItem, object oTarget, int nToken) +{ + NuiSetBind(oPC, nToken, "item_combo_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_cancel_label", JsonString("Cancel")); + NuiSetBind(oPC, nToken, "btn_cancel_tooltip", JsonString(" Revert back to the original items appearance")); + NuiSetBind(oPC, nToken, "btn_save_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_select_target_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_info_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_wardrobe_event", JsonBool(FALSE)); + // Make sure the item information window is closed. + nToken = NuiFindWindow(oPC, "craft_item_nui"); + if(nToken) NuiDestroy(oPC, nToken); +} +void ClearItemInCraftingWindow(object oPC, object oItem, int nToken) +{ + NuiSetBind(oPC, nToken, "btn_save_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "item_combo_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_select_target_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_info_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_wardrobe_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_cancel_label", JsonString("Exit")); + NuiSetBind(oPC, nToken, "btn_cancel_tooltip", JsonString(" Exit the crafting menu")); + if(ai_GetIsWeapon(oItem)) + { + SetLocalInt(oPC, AI_NO_NUI_SAVE, TRUE); + NuiSetBind(oPC, nToken, "model_combo_selected", JsonInt(0)); + DelayCommand(1.0, DeleteLocalInt(oPC, AI_NO_NUI_SAVE)); + } +} +void SaveCraftedItem(object oPC, object oTarget, int nToken) +{ + json jCraft = GetLocalJson(oPC, CRAFT_JSON); + int nItemSelected = JsonGetInt(JsonObjectGet(jCraft, CRAFT_ITEM_SELECTION)); + object oItem = GetSelectedItem(oTarget, nItemSelected); + ClearItemInCraftingWindow(oPC, oItem, nToken); + DestroyObject(GetLocalObject(oPC, CRAFT_ORIGINAL_ITEM)); + DeleteLocalObject(oPC, CRAFT_ORIGINAL_ITEM); +} +int CanCraftItem(object oPC, object oItem, int nToken, int bPasteCheck = FALSE) +{ + // Plot items cannot be changed. + if(GetPlotFlag(oItem)) + { + ai_SendMessages(GetName(oItem) + "is a plot item and its appearance cannot be changed!", AI_COLOR_RED, oPC); + return FALSE; + } + // Cannot change temorary enchanted items. + if(CheckForTemporaryItemProperty(oItem)) + { + ai_SendMessages(GetName(oItem) + " cannot be altered while it has a temporary enchantment.", AI_COLOR_RED, oPC); + return FALSE; + } + // Do special paste checks. + if (bPasteCheck) + { + int nOldItemType = GetLocalInt (oPC, CRAFT_COPY_ITEM_TYPE); + int nNewItemType = GetBaseItemType(oItem); + if(nNewItemType == BASE_ITEM_ARMOR) + { + if(GetLocalInt (oPC, CRAFT_ARMOR_AC) != ai_GetArmorBonus(oItem)) + { + ai_SendMessages("The armor you are trying to paste to is not the same type as the copy!", AI_COLOR_RED, oPC); + return FALSE; + } + } + else if(nOldItemType != nNewItemType) + { + string sOldBaseItem = GetStringByStrRef(StringToInt(Get2DAString ("baseitems", "Name", nOldItemType))); + string sNewBaseItem = GetStringByStrRef(StringToInt(Get2DAString ("baseitems", "Name", nNewItemType))); + ai_SendMessages("You copied a " + sOldBaseItem + " and are trying to paste to a " + sNewBaseItem + "!", AI_COLOR_RED, oPC); + return FALSE; + } + } + if(GetLocalObject(oPC, CRAFT_ORIGINAL_ITEM) == OBJECT_INVALID) + { + object oBuildContainer = GetObjectByTag(CRAFT_CONTAINER); + if(!GetIsObjectValid(oBuildContainer)) + { + vector vPosition = GetPositionFromLocation(GetLocation(oPC)); + vPosition.z = vPosition.z -2.0; + location lLocation = Location(GetArea(oPC), vPosition, 0.0); + oBuildContainer = CreateObject(OBJECT_TYPE_PLACEABLE, CRAFT_TEMPLATE, lLocation, FALSE, CRAFT_CONTAINER); + //SetObjectVisualTransform(oBuildContainer, OBJECT_VISUAL_TRANSFORM_TRANSLATE_Z, -5.0); + } + object oBackup = CopyItem(oItem, oBuildContainer, TRUE); + // Save the original item to the PC. + SetLocalObject(oPC, CRAFT_ORIGINAL_ITEM, oBackup); + } + return TRUE; +} +void RemoveTagedEffects(object oCreature, string sEffectTag) +{ + //Search for the effect. + //Debug ("0i_effects", "578", "RemoveTagedEffects: " + sEffectTag); + effect eEffect = GetFirstEffect(oCreature); + while (GetIsEffectValid(eEffect)) + { + //Debug ("0i_effects", "582", "Effect Tag: " + GetEffectTag (eEffect)); + if (GetEffectTag(eEffect) == sEffectTag) RemoveEffect(oCreature, eEffect); + eEffect = GetNextEffect(oCreature); + } +} +int CheckForTemporaryItemProperty (object oItem) +{ + itemproperty ipProperty; + ipProperty = GetFirstItemProperty (oItem); + while (GetIsItemPropertyValid (ipProperty)) + { + // Check to see if the item is temporary enchanted. + if (GetItemPropertyDurationType (ipProperty) == DURATION_TYPE_TEMPORARY) return TRUE; + ipProperty = GetNextItemProperty (oItem); + } + return FALSE; +} +int GetHasPartColor(object oItem, int nPart, string sSide) +{ + json jItem = ObjectToJson(oItem); + string sPartName = "APart_"; + if(sSide == "Left") + { + // Note: Right Thigh and Left Thigh are backwards so this fixes that! + if (nPart == ITEM_APPR_ARMOR_MODEL_RTHIGH) nPart--; + else nPart++; + } + sPartName += IntToString(nPart) + "_Col_"; + int nPartColor = JsonGetInt(GffGetByte(jItem, sPartName + "0")); + nPartColor += JsonGetInt(GffGetByte(jItem, sPartName + "1")); + nPartColor += JsonGetInt(GffGetByte(jItem, sPartName + "2")); + nPartColor += JsonGetInt(GffGetByte(jItem, sPartName + "3")); + nPartColor += JsonGetInt(GffGetByte(jItem, sPartName + "4")); + nPartColor += JsonGetInt(GffGetByte(jItem, sPartName + "5")); + //SendMessageToPC(GetFirstPC(), "sPartName: " + sPartName + " nPartColor: " + IntToString(nPartColor)); + return nPartColor; +} +void SetModelNumberText(object oPC, object oTarget, int nToken) +{ + json jCraft = GetLocalJson(oPC, CRAFT_JSON); + int nItem = JsonGetInt(JsonObjectGet(jCraft, CRAFT_ITEM_SELECTION)); + object oItem = GetSelectedItem(oTarget, nItem); + int nSelected = JsonGetInt(JsonObjectGet(jCraft, CRAFT_MODEL_SELECTION)); + string sModelTop, sModelMiddle, sModelBottom; + // Model Group + if (ai_GetIsWeapon (oItem)) + { + int nModel = GetItemAppearance(oItem, ITEM_APPR_TYPE_WEAPON_MODEL, 0); + int nColor = GetItemAppearance(oItem, ITEM_APPR_TYPE_WEAPON_COLOR, 0); + int nModelNumber = (nModel * 10) + nColor; + sModelTop = IntToString(nModelNumber); + nModel = GetItemAppearance(oItem, ITEM_APPR_TYPE_WEAPON_MODEL, 1); + nColor = GetItemAppearance(oItem, ITEM_APPR_TYPE_WEAPON_COLOR, 1); + nModelNumber = (nModel * 10) + nColor; + sModelMiddle = IntToString(nModelNumber); + nModel = GetItemAppearance(oItem, ITEM_APPR_TYPE_WEAPON_MODEL, 2); + nColor = GetItemAppearance(oItem, ITEM_APPR_TYPE_WEAPON_COLOR, 2); + nModelNumber = (nModel * 10) + nColor; + sModelBottom = IntToString(nModelNumber); + NuiSetBind(oPC, nToken, "top_title_label", JsonString("Top")); + //NuiSetBind(oPC, nToken, "txt_model_number_t_enable", JsonBool(TRUE)); + //NuiSetBindWatch(oPC, nToken, "txt_model_number_t", TRUE); + NuiSetBind(oPC, nToken, "txt_model_name_t", JsonString(sModelTop)); + NuiSetBind(oPC, nToken, "btn_prev_t_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_next_t_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "middle_title_label", JsonString("Middle")); + //NuiSetBind(oPC, nToken, "txt_model_number_m_enable", JsonBool(TRUE)); + //NuiSetBindWatch(oPC, nToken, "txt_model_number_m", TRUE); + NuiSetBind(oPC, nToken, "txt_model_number_m", JsonString(sModelMiddle)); + NuiSetBind(oPC, nToken, "btn_prev_m_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_next_m_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "bottom_title_label", JsonString("Bottom")); + //NuiSetBind(oPC, nToken, "txt_model_number_b_enable", JsonBool(TRUE)); + //NuiSetBindWatch(oPC, nToken, "txt_model_number_b", TRUE); + NuiSetBind(oPC, nToken, "txt_model_number_b", JsonString(sModelBottom)); + NuiSetBind(oPC, nToken, "btn_prev_b_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_next_b_event", JsonBool(TRUE)); + } + // Armor and clothing + if(nItem == 0) + { + nSelected = GetArmorModelSelected(oPC); + // These models only have one side so make sure we are not linked. + if (nSelected == ITEM_APPR_ARMOR_MODEL_NECK || + nSelected == ITEM_APPR_ARMOR_MODEL_TORSO || + nSelected == ITEM_APPR_ARMOR_MODEL_BELT || + nSelected == ITEM_APPR_ARMOR_MODEL_PELVIS || + nSelected == ITEM_APPR_ARMOR_MODEL_ROBE) + { + sModelMiddle = IntToString(GetItemAppearance(oItem, ITEM_APPR_TYPE_ARMOR_MODEL, nSelected)); + NuiSetBind(oPC, nToken, "top_title_label", JsonString("")); + //NuiSetBind(oPC, nToken, "txt_model_number_t_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "txt_model_name_t", JsonString("")); + NuiSetBind(oPC, nToken, "btn_prev_t_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_next_t_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "middle_title_label", JsonString("Model")); + //NuiSetBind(oPC, nToken, "txt_model_number_m_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "txt_model_number_m", JsonString(sModelMiddle)); + NuiSetBind(oPC, nToken, "btn_prev_m_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_next_m_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "bottom_title_label", JsonString("")); + //NuiSetBind(oPC, nToken, "txt_model_number_b_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "txt_model_number_b", JsonString("")); + NuiSetBind(oPC, nToken, "btn_prev_b_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_next_b_event", JsonBool(FALSE)); + } + else + { + sModelTop = IntToString(GetItemAppearance(oItem, ITEM_APPR_TYPE_ARMOR_MODEL, nSelected)); + if(nSelected == ITEM_APPR_ARMOR_MODEL_RTHIGH) nSelected--; + else nSelected++; + sModelBottom = IntToString(GetItemAppearance(oItem, ITEM_APPR_TYPE_ARMOR_MODEL, nSelected)); + NuiSetBind(oPC, nToken, "top_title_label", JsonString("Right")); + //NuiSetBind(oPC, nToken, "txt_model_number_t_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "txt_model_number_t", JsonString(sModelTop)); + NuiSetBind(oPC, nToken, "btn_prev_t_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_next_t_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "middle_title_label", JsonString("Right & Left")); + //NuiSetBind(oPC, nToken, "txt_model_number_m_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "txt_model_number_m", JsonString(sModelTop)); + NuiSetBind(oPC, nToken, "btn_prev_m_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_next_m_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "bottom_title_label", JsonString("Left")); + //NuiSetBind(oPC, nToken, "txt_model_number_b_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "txt_model_number_b", JsonString(sModelBottom)); + NuiSetBind(oPC, nToken, "btn_prev_b_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_next_b_event", JsonBool(TRUE)); + } + } + // Cloaks and Helmets. + else + { + sModelMiddle = IntToString(GetItemAppearance(oItem, ITEM_APPR_TYPE_SIMPLE_MODEL, 0)); + NuiSetBind(oPC, nToken, "top_title_label", JsonString("")); + //NuiSetBind(oPC, nToken, "txt_model_number_t_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "txt_model_number_t", JsonString("")); + NuiSetBind(oPC, nToken, "btn_prev_t_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_next_t_event", JsonBool(FALSE)); + //NuiSetBind(oPC, nToken, "txt_model_number_m_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "txt_model_number_m", JsonString(sModelMiddle)); + NuiSetBind(oPC, nToken, "middle_title_label", JsonString("Model")); + NuiSetBind(oPC, nToken, "btn_prev_m_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_next_m_event", JsonBool(TRUE)); + //NuiSetBind(oPC, nToken, "txt_model_number_b_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "txt_model_number_b", JsonString("")); + NuiSetBind(oPC, nToken, "bottom_title_label", JsonString("")); + NuiSetBind(oPC, nToken, "btn_prev_b_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_next_b_event", JsonBool(FALSE)); + } + // Color Group + if(ai_GetIsWeapon(oItem) || ai_GetIsShield(oItem)) + { + // Need to disable the color widgets. + // Row 511 + NuiSetBind(oPC, nToken, "color_pallet_image", JsonString("gui_pal_tattoo")); + NuiSetBind(oPC, nToken, "color_pallet_image_event", JsonBool(FALSE)); + // Row 512 - Label Part to Color + // Row 5l3 + NuiSetBind(oPC, nToken, "btn_right_part_color_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_all_color_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_left_part_color_event", JsonBool(FALSE)); + // Row 514 - Label Part Color to Reset + // Row 515 + NuiSetBind(oPC, nToken, "btn_right_part_reset_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_all_reset_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_left_part_reset_event", JsonBool(FALSE)); + // Row 516 - Label Material to Color + // Row 517 + NuiSetBind(oPC, nToken, "btn_material_0", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_material_2", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_material_4", JsonBool(FALSE)); + // Row 518 + NuiSetBind(oPC, nToken, "btn_material_1", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_material_3", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_material_5", JsonBool(FALSE)); + SetMaterialButtons(oPC, nToken, -1); + } + // Armor and clothing + else if(nItem == 0) + { + // Row 511 + string sColorPallet = GetLocalString(oPC, CRAFT_COLOR_PALLET); + if(sColorPallet == "") sColorPallet = "gui_pal_tattoo"; + NuiSetBind(oPC, nToken, "color_pallet_image", JsonString(sColorPallet)); + NuiSetBind(oPC, nToken, "color_pallet_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "color_pallet_tooltip", JsonString(" Select a color or use the mouse wheel")); + NuiSetBindWatch(oPC, nToken, "txt_color_l", TRUE); + int nSelectedRight, nSelectedAll, nSelectedLeft; + int nModelSelected = GetArmorModelSelected(oPC); + int nMaterialSelected = JsonGetInt(JsonObjectGet(jCraft, CRAFT_MATERIAL_SELECTION)); + string sColorAll = IntToString(GetItemAppearance(oItem, ITEM_APPR_TYPE_ARMOR_COLOR, nMaterialSelected)); + // These models only have one side so make sure we are not linked. + if (nModelSelected == ITEM_APPR_ARMOR_MODEL_NECK || + nModelSelected == ITEM_APPR_ARMOR_MODEL_TORSO || + nModelSelected == ITEM_APPR_ARMOR_MODEL_BELT || + nModelSelected == ITEM_APPR_ARMOR_MODEL_PELVIS || + nModelSelected == ITEM_APPR_ARMOR_MODEL_ROBE) + { + // Row 512 - Label Part to Color + // Row 5l3 + nSelectedRight = JsonGetInt(JsonObjectGet(jCraft, CRAFT_RIGHT_PART_COLOR)); + nSelectedAll = JsonGetInt(JsonObjectGet(jCraft, CRAFT_ALL_COLOR)); + if(!nSelectedRight && !nSelectedAll) + { + nSelectedAll = TRUE; + jCraft = JsonObjectSet(jCraft, CRAFT_ALL_COLOR, JsonBool(TRUE)); + jCraft = JsonObjectSet(jCraft, CRAFT_LEFT_PART_COLOR, JsonBool(FALSE)); + } + NuiSetBind(oPC, nToken, "btn_right_part_color", JsonBool(nSelectedRight)); + NuiSetBind(oPC, nToken, "btn_right_part_color_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_all_color", JsonBool(nSelectedAll)); + NuiSetBind(oPC, nToken, "btn_all_color_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_left_part_color", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_left_part_color_event", JsonBool(FALSE)); + // Row 514 - Label Part Color to Reset + // Row 5l5 + nSelectedRight = GetHasPartColor(oItem, nModelSelected, "Right"); + nSelectedAll = nSelectedRight; + NuiSetBind(oPC, nToken, "btn_right_part_reset_event", JsonBool(nSelectedRight)); + NuiSetBind(oPC, nToken, "btn_all_reset_event", JsonBool(nSelectedAll)); + NuiSetBind(oPC, nToken, "btn_left_part_reset_event", JsonBool(FALSE)); + } + else + { + // Row 511 + string sColorPallet = GetLocalString(oPC, CRAFT_COLOR_PALLET); + if(sColorPallet == "") sColorPallet = "gui_pal_tattoo"; + NuiSetBind(oPC, nToken, "color_pallet_image", JsonString(sColorPallet)); + NuiSetBind(oPC, nToken, "color_pallet_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "color_pallet_tooltip", JsonString(" Select a color or use the mouse wheel")); + // Row 512 - Label Part to Color + // Row 5l3 + nSelectedRight = JsonGetInt(JsonObjectGet(jCraft, CRAFT_RIGHT_PART_COLOR)); + nSelectedAll = JsonGetInt(JsonObjectGet(jCraft, CRAFT_ALL_COLOR)); + nSelectedLeft = JsonGetInt(JsonObjectGet(jCraft, CRAFT_LEFT_PART_COLOR)); + if(!nSelectedRight && !nSelectedAll && !nSelectedLeft) + { + nSelectedAll = TRUE; + jCraft = JsonObjectSet(jCraft, CRAFT_ALL_COLOR, JsonBool(TRUE)); + } + NuiSetBind(oPC, nToken, "btn_right_part_color", JsonBool(nSelectedRight)); + NuiSetBind(oPC, nToken, "btn_right_part_color_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_all_color", JsonBool(nSelectedAll)); + NuiSetBind(oPC, nToken, "btn_all_color_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_left_part_color", JsonBool(nSelectedLeft)); + NuiSetBind(oPC, nToken, "btn_left_part_color_event", JsonBool(TRUE)); + // Row 514 - Label Part Color to Reset + // Row 5l5 + nSelectedRight = GetHasPartColor(oItem, nModelSelected, "Right"); + nSelectedLeft = GetHasPartColor(oItem, nModelSelected, "Left"); + nSelectedAll = nSelectedRight || nSelectedLeft; + //SendMessageToPC(oPC, "nSelectedRight: " + IntToString(nSelectedRight) + + // " nSelectedLeft: " + IntToString(nSelectedLeft)); + NuiSetBind(oPC, nToken, "btn_right_part_reset_event", JsonBool(nSelectedRight)); + NuiSetBind(oPC, nToken, "btn_all_reset_event", JsonBool(nSelectedAll)); + NuiSetBind(oPC, nToken, "btn_left_part_reset_event", JsonBool(nSelectedLeft)); + // Row 516 - Label Material to Color + // Row 517 & 518 + nSelected = JsonGetInt(JsonObjectGet(jCraft, CRAFT_MATERIAL_SELECTION)); + SetMaterialButtons(oPC, nToken, nSelected); + } + SetLocalJson(oPC, CRAFT_JSON, jCraft); + } + // Cloaks and Helmets. + else + { + // Row 512 - Label Part to Color + // Row 5l3 + NuiSetBind(oPC, nToken, "btn_right_part_color", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_right_part_color_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_all_color_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_all_color", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_left_part_color", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_left_part_color_event", JsonBool(FALSE)); + // Row 514 - Label Part Color to Reset + // Row 5l5 + NuiSetBind(oPC, nToken, "btn_right_part_reset_event", JsonBool(FALSE)); + //NuiSetBind(oPC, nToken, "btn_left_part_reset_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_all_reset_event", JsonBool(FALSE)); + // Row 516 - Label Material to Color + // Row 517 & 518 + nSelected = JsonGetInt(JsonObjectGet(jCraft, CRAFT_MATERIAL_SELECTION)); + SetMaterialButtons(oPC, nToken, nSelected); + } +} +void SetMaterialButtons(object oPC, int nToken, int nMaterial) +{ + int nIndex, bBool, bUseable; + string sIndex; + if(nMaterial > -1) bUseable = TRUE; + for(nIndex = 0;nIndex < 6;nIndex++) + { + if(nIndex == nMaterial) bBool = TRUE; + else bBool = FALSE; + sIndex = IntToString(nIndex); + NuiSetBind(oPC, nToken, "btn_material_" + sIndex + "_event", JsonBool(bUseable)); + NuiSetBind(oPC, nToken, "btn_material_" + sIndex, JsonBool(bBool)); + } +} +void CreateItemGUIPanel(object oPC, object oItem) +{ + // Row 1 (Name)************************************************************* 73 + json jRow = CreateLabel(JsonArray(), "Name:", "lbl_name_title", 50.0f, 20.0f, NUI_HALIGN_LEFT); + jRow = CreateTextEditBox (jRow, "name_placeholder", "txt_item_name", 60, FALSE, 325.0f, 20.0f); + // Add row to the column. + json jCol = JsonArrayInsert(JsonArray(), NuiRow(jRow)); + // Row 2 (Tag)************************************************************** 101 + jRow = CreateLabel(JsonArray(), "Tag:", "lbl_tag_title", 50.0f, 20.0f, NUI_HALIGN_LEFT); + jRow = CreateTextEditBox(jRow, "name_placeholder", "txt_item_tag", 60, FALSE, 325.0f, 20.0f); + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 2 (ResRef)*********************************************************** 129 + jRow = CreateLabel(JsonArray(), "ResRef:", "lbl_resref_title", 50.0f, 20.0f, NUI_HALIGN_LEFT); + jRow = CreateTextEditBox(jRow, "name_placeholder", "txt_item_resref", 60, FALSE, 325.0f, 20.0f); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 3 (Base Item/Weight)************************************************* 157 + jRow = CreateLabel(JsonArray(), "Base Item: ", "lbl_baseitem_title", 75.0f, 20.0f, NUI_HALIGN_LEFT); + jRow = CreateLabel(jRow, "", "lbl_baseitem", 145.0f, 20.0f, NUI_HALIGN_LEFT); + jRow = CreateLabel(jRow, "Weight: ", "lbl_weight_title", 55.0f, 20.0f, NUI_HALIGN_LEFT); + jRow = CreateLabel(jRow, "", "lbl_weight", 65.0f, 20.0f, NUI_HALIGN_LEFT); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 4 (Gold Value)******************************************************* 185 + jRow = CreateLabel(JsonArray(), "Gold Value: ", "lbl_gold_title", 85.0f, 20.0f, NUI_HALIGN_LEFT); + jRow = CreateLabel(jRow, "", "lbl_gold_value", 135.0f, 20.0f, NUI_HALIGN_LEFT); + jRow = CreateLabel(jRow, "Minimum Level: ", "lbl_min_lvl_title", 110.0f, 20.0f, NUI_HALIGN_LEFT); + jRow = CreateLabel(jRow, "", "lbl_min_lvl", 20.0f, 20.0f, NUI_HALIGN_LEFT); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 5 (Plot/Stolen)****************************************************** 213 + jRow = CreateCheckBox(JsonArray(), " Plot", "chbx_plot", 110.0, 20.0f, "chbx_plot_tooltip"); + jRow = CreateCheckBox(jRow, " Stolen", "chbx_stolen", 110.0, 20.0f, "chbx_stolen_tooltip"); + jRow = CreateCheckBox(jRow, " Cursed", "chbx_cursed", 110.0, 20.0f, "chbx_cursed_tooltip"); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 6 (Identified/Droppable)********************************************* 269 + jRow = CreateCheckBox(JsonArray(), " Identified", "chbx_identified", 110.0, 25.0f, "chbx_identified_tooltip"); + jRow = CreateCheckBox(jRow, " Droppable", "chbx_droppable", 110.0, 25.0f, "chbx_droppable_tooltip"); + jRow = CreateButton(jRow, "Save as UTI", "btn_save_uti", 110.0, 25.0, -1.0, "btn_save_uti_tooltip"); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 9 (Stack/Variables/Destroy/Charges)********************************** 307 + jRow = CreateTextEditBox(JsonArray(), "name_placeholder", "txt_stack", 4, FALSE, 35.0f, 25.0f); + jRow = CreateLabel(jRow, " Stack", "lbl_stack_title", 72.0f, 20.0f, NUI_HALIGN_LEFT); + jRow = CreateTextEditBox(jRow, "name_placeholder", "txt_charges", 4, FALSE, 40.0f, 25.0f); + jRow = CreateLabel(jRow, " Charges", "lbl_charges_title", 68.0f, 25.0f, NUI_HALIGN_LEFT); + jRow = CreateButtonSelect(jRow, "Destroy", "btn_destroy", 110.0, 25.0, "btn_destroy_tooltip"); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 11 (Description)***************************************************** 558 + jRow = CreateTextEditBox(JsonArray(), "desc_placeholder", "txt_desc", 1000, TRUE, 375.0, 243.0, "txt_desc_tooltip"); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + float fHeight = 566.0; + // Row 12 (Item Base Description)* ***************************************** 158 + int nBaseItemType = GetBaseItemType(oItem); + float fWeight; + string sBaseItemDesc; + if(nBaseItemType == BASE_ITEM_ARMOR) + { + int nArmorAC = ai_GetArmorBonus(oItem); + sBaseItemDesc = GetStringByStrRef(StringToInt(Get2DAString("armor", "BASEITEMSTATREF", nArmorAC))); + fWeight = StringToFloat(Get2DAString("armor", "WEIGHT", nArmorAC)); + } + else + { + sBaseItemDesc = GetStringByStrRef(StringToInt(Get2DAString("baseitems", "BaseItemStatRef", nBaseItemType))); + fWeight = StringToFloat(Get2DAString("baseitems", "TenthLBS", nBaseItemType)); + } + if(sBaseItemDesc == "Bad Strref") sBaseItemDesc = ""; + if(sBaseItemDesc != "") + { + jRow = CreateTextBox(JsonArray(), "txt_base_desc", 375.0, 150.0, FALSE, NUI_SCROLLBARS_NONE, "txt_base_desc_tooltip"); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + fHeight += 158.0; + } + // Set the layout of the window. + json jLayout = NuiCol (jCol); + object oOwner = GetItemPossessor(oItem); + string sName = ai_StripColorCodes (GetName(oOwner)); + int nToken = SetWindow (oPC, jLayout, "craft_item_nui", sName + "'s item menu", + -1.0, -1.0, 400.0, fHeight, FALSE, FALSE, TRUE, FALSE, TRUE, "pe_crafting"); + // Set the buttons to show events to 0e_window. + NuiSetBind(oPC, nToken, "txt_item_name_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "txt_item_name", JsonString(GetName(oItem))); + NuiSetBindWatch(oPC, nToken, "txt_item_name", TRUE); + NuiSetBind(oPC, nToken, "txt_item_tag_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "txt_item_tag", JsonString(GetTag(oItem))); + NuiSetBindWatch(oPC, nToken, "txt_item_tag", TRUE); + NuiSetBind(oPC, nToken, "txt_item_resref_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "txt_item_resref", JsonString(GetResRef(oItem))); + NuiSetBindWatch(oPC, nToken, "txt_item_resref", TRUE); + string sValue = GetStringByStrRef(StringToInt(Get2DAString("baseitems", "Name", nBaseItemType))); + NuiSetBind(oPC, nToken, "lbl_baseitem_label", JsonString(sValue)); + sValue = FloatToString(fWeight * 0.1f, 0, 1); + NuiSetBind(oPC, nToken, "lbl_weight_label", JsonString(sValue)); + int nValue = GetGoldPieceValue(oItem); + NuiSetBind (oPC, nToken, "lbl_gold_value_label", JsonString(IntToString(nValue))); + sValue = IntToString (ai_GetMinimumEquipLevel(oItem)); + NuiSetBind(oPC, nToken, "lbl_min_lvl_label", JsonString (sValue)); + nValue = GetPlotFlag (oItem); + NuiSetBind(oPC, nToken, "chbx_plot_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "chbx_plot_check", JsonBool(nValue)); + NuiSetBindWatch(oPC, nToken, "chbx_plot_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_plot_tooltip", JsonString (" Plot items cannot be sold or destroyed.")); + nValue = GetStolenFlag(oItem); + NuiSetBind(oPC, nToken, "chbx_stolen_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "chbx_stolen_check", JsonBool(nValue)); + NuiSetBindWatch (oPC, nToken, "chbx_stolen_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_stolen_tooltip", JsonString (" Stolen items cannot be sold to some stores.")); + nValue = GetItemCursedFlag(oItem); + NuiSetBind(oPC, nToken, "chbx_cursed_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "chbx_cursed_check", JsonBool(nValue)); + NuiSetBindWatch (oPC, nToken, "chbx_cursed_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_cursed_tooltip", JsonString (" Cursed items cannot be dropped or sold.")); + nValue = GetIdentified (oItem); + NuiSetBind(oPC, nToken, "chbx_identified_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "chbx_identified_check", JsonBool(nValue)); + NuiSetBindWatch(oPC, nToken, "chbx_identified_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_identified_tooltip", JsonString (" Close inventory and open again to refresh identified state.")); + nValue = GetDroppableFlag(oItem); + NuiSetBind(oPC, nToken, "chbx_droppable_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "chbx_droppable_check", JsonBool(nValue)); + NuiSetBindWatch(oPC, nToken, "chbx_droppable_check", TRUE); + NuiSetBind(oPC, nToken, "chbx_droppable_tooltip", JsonString (" Droppable items only work on death of an NPC.")); + NuiSetBind(oPC, nToken, "btn_save_uti_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_save_uti_tooltip", JsonString (" Saves item to a UTI file. Update will be used in the game.")); + nValue = GetItemStackSize (oItem); + NuiSetBind(oPC, nToken, "txt_stack_event", JsonBool(TRUE)); + NuiSetBind (oPC, nToken, "txt_stack", JsonString(IntToString (nValue))); + NuiSetBindWatch (oPC, nToken, "txt_stack", TRUE); + nValue = GetItemCharges (oItem); + NuiSetBind(oPC, nToken, "txt_charges_event", JsonBool(TRUE)); + NuiSetBind (oPC, nToken, "txt_charges", JsonString(IntToString (nValue))); + NuiSetBindWatch (oPC, nToken, "txt_charges", TRUE); + NuiSetBind(oPC, nToken, "btn_destroy_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_destroy_tooltip", JsonString(" Destroys the item permanently! Must click twice to destroy the item.")); + // Description + NuiSetBind(oPC, nToken, "txt_desc_event", JsonBool(TRUE)); + NuiSetBindWatch(oPC, nToken, "txt_desc", TRUE); + NuiSetBind(oPC, nToken, "txt_desc_tooltip", JsonString (" Color codes can be used!")); + NuiSetBind(oPC, nToken, "txt_desc", JsonString(GetDescription(oItem))); + // Base Item Description + NuiSetBind(oPC, nToken, "txt_base_desc_event", JsonBool(TRUE)); + //NuiSetBind(oPC, nToken, "txt_desc_tooltip", JsonString ("Color codes can be used!")); + if(sBaseItemDesc != "") NuiSetBind(oPC, nToken, "txt_base_desc", JsonString(sBaseItemDesc)); +} +void CraftItemInfoEvents(object oPC, int nToken) +{ + string sEvent = NuiGetEventType(); + // We don't use and it causes error windows to go off! Return early! + if(sEvent == "mouseup") return; + string sElem = NuiGetEventElement(); + int nIndex = NuiGetEventArrayIndex(); + json jCraft = GetLocalJson(oPC, CRAFT_JSON); + //SendMessageToPC(oPC, "0e_crafting, 1961, sElem: " + sElem + " sEvent: " + sEvent); + object oTarget = GetLocalObject(oPC, CRAFT_TARGET); + if(oTarget == OBJECT_INVALID) oTarget = oPC; + // Get the item we are crafting. + int nItemSelected = JsonGetInt(JsonObjectGet(jCraft, CRAFT_ITEM_SELECTION)); + object oItem = GetLocalObject(oPC, "CRAFT_INFO_ITEM"); + if(sEvent == "click") + { + if(sElem == "btn_destroy") + { + if(!JsonGetInt(NuiGetBind(oPC, nToken, "btn_destroy"))) + { + if(!GetPlotFlag(oItem)) + { + DestroyObject(oItem); + ai_SendMessages(GetName(oItem) + " has been permanently destroyed!", AI_COLOR_RED, oPC); + NuiDestroy(oPC, nToken); + } + else + { + ai_SendMessages("The plot flag must be removed before you can destroy " + GetName(oItem) + "!", AI_COLOR_YELLOW, oPC); + } + } + else + { + ai_SendMessages("Click Destroy button again to destroy " + GetName(oItem) + "!", AI_COLOR_RED, oPC); + } + } + // Allows saving the item as a UTI! + else if(sElem == "btn_save_uti") + { + json jItem = ObjectToJson(oItem); + string sResRef = JsonGetString(NuiGetBind(oPC, nToken, "txt_item_resref")); + sResRef = ai_RemoveIllegalCharacters(sResRef); + if(sResRef == "") ai_SendMessages(GetName(oItem) + " has not been saved! ResRef does not have a value.", AI_COLOR_RED, oPC); + else + { + JsonToTemplate(jItem, sResRef, RESTYPE_UTI); + ai_SendMessages(GetName(oItem) + " has been saved as " + sResRef + ".uti in your Neverwinter Nights Temp directory.", AI_COLOR_GREEN, oPC); + ai_SendMessages("This temp directory will be removed when the game is left.", AI_COLOR_GREEN, oPC); + } + } + } + if(sEvent == "watch") + { + // Changing the name needs to be before the cooldown. + if(sElem == "txt_item_name") + { + string sName = JsonGetString(NuiGetBind(oPC, nToken, "txt_item_name")); + SetName(oItem, sName); + int nToken2 = NuiFindWindow(oPC, "crafting_nui"); + if(nToken2) NuiSetBind(oPC, nToken2, "txt_item_name", JsonString(sName)); + } + else if(sElem == "txt_item_tag") + { + string sTag = JsonGetString(NuiGetBind(oPC, nToken, "txt_item_tag")); + SetTag(oItem, sTag); + } + else if(sElem == "txt_stack") + { + int nSize = StringToInt(JsonGetString(NuiGetBind(oPC, nToken, "txt_stack"))); + int nBaseItemType = GetBaseItemType(oItem); + string sMaxSize = Get2DAString("baseitems", "Stacking", nBaseItemType); + if(nSize > StringToInt(sMaxSize)) + { + ai_SendMessages("The maximum stack for this item type is " + sMaxSize + ".", AI_COLOR_RED, oPC); + NuiSetBind(oPC, nToken, "txt_stack", JsonString(sMaxSize)); + } + if(nSize != 0) SetItemStackSize(oItem, nSize); + } + else if(sElem == "txt_charges") + { + int nCharges = StringToInt(JsonGetString(NuiGetBind(oPC, nToken, "txt_charges"))); + if(nCharges > 250) + { + ai_SendMessages("The maximum charges for this item type is 250.", AI_COLOR_RED, oPC); + NuiSetBind(oPC, nToken, "txt_charges", JsonString("250")); + } + if(nCharges != 0) SetItemCharges(oItem, nCharges); + } + else if(sElem == "chbx_plot_check") + { + int nValue = JsonGetInt(NuiGetBind(oPC, nToken, sElem)); + SetPlotFlag(oItem, nValue); + } + else if(sElem == "chbx_stolen_check") + { + int nValue = JsonGetInt(NuiGetBind(oPC, nToken, sElem)); + SetStolenFlag(oItem, nValue); + } + else if(sElem == "chbx_cursed_check") + { + int nValue = JsonGetInt(NuiGetBind(oPC, nToken, sElem)); + SetItemCursedFlag(oItem, nValue); + } + else if(sElem == "chbx_identified_check") + { + int nValue = JsonGetInt(NuiGetBind(oPC, nToken, sElem)); + SetIdentified(oItem, nValue); + } + else if(sElem == "chbx_droppable_check") + { + int nValue = JsonGetInt(NuiGetBind(oPC, nToken, sElem)); + SetDroppableFlag(oItem, nValue); + } + } +} +/*void CreateDresserGUIPanel(object oPC, object oTarget) +{ +} + diff --git a/src/module/nss/pe_debug.nss b/src/module/nss/pe_debug.nss new file mode 100644 index 0000000..5b6ad1a --- /dev/null +++ b/src/module/nss/pe_debug.nss @@ -0,0 +1,900 @@ +/*////////////////////////////////////////////////////////////////////////////// + Script Name: pe_debug + Programmer: Philos +//////////////////////////////////////////////////////////////////////////////// + PEPS Plugin to allow use of special Debug scripts +/*////////////////////////////////////////////////////////////////////////////// +#include "0i_main" +#include "0i_module" +#include "0i_menus" +//#include "prc_inc_eventhk" +// Gets a variable from oTarget, if oTarget is OBJECT_INVALID then +// it will get the variable from the Module and Area. +void debug_GetObjectVariable(object oPC, object oTarget, string sDesc = ""); +// Lists the variables from oTarget to the screen. +void debug_ListObjectVariables(object oPC, object oTarget); +// Force event script change to default for oCreature. +void ai_ForceAssociateEventScriptsToDefault(object oPC, object oCreature); +// Reverts event script change from default for oCreature. +void ai_RevertAssociateEventScriptsToDefault(object oPC, object oCreature); +void main() +{ + // Get the last player to use targeting mode + object oPC = GetLastPlayerToSelectTarget(); + string sTargetMode = GetLocalString(oPC, AI_TARGET_MODE); + if(oPC == OBJECT_SELF && sTargetMode != "") + { + // Get the targeting mode data + object oTarget = GetTargetingModeSelectedObject(); + vector vTarget = GetTargetingModeSelectedPosition(); + location lLocation = Location(GetArea(oPC), vTarget, GetFacing(oPC)); + object oObject = GetLocalObject(oPC, "AI_TARGET_OBJECT"); + // If the user manually exited targeting mode without selecting a target, return + if(!GetIsObjectValid(oTarget) && vTarget == Vector()) + { + return; + } + // Targeting code here. + if(sTargetMode == "DEBUG_CREATURE") + { + object oModule = GetModule(); + string sDebugName = GetName(oTarget); + SetLocalString(oModule, AI_RULE_DEBUG_CREATURE, sDebugName); + json jRules = ai_GetCampaignDbJson("rules"); + jRules = JsonObjectSet(jRules, AI_RULE_DEBUG_CREATURE, JsonString(sDebugName)); + ai_SetCampaignDbJson("rules", jRules); + SetLocalObject(oPC, "AI_RULE_DEBUG_CREATURE_OBJECT", oTarget); + ExecuteScript("pi_debug", oPC); + } + else if(sTargetMode == "CLEAR_REPUTATION") + { + int nReputation = GetFactionAverageReputation(oTarget, oPC); + object oPCMember = GetFirstFactionMember(oPC, FALSE); + while(GetIsObjectValid(oPCMember)) + { + ClearPersonalReputation(oPCMember, oTarget); + oPCMember = GetNextFactionMember(oPC, FALSE); + } + ai_SendMessages("Your reputation with " + GetName(oTarget) + " has been set to neutral.", AI_COLOR_YELLOW, oPC); + } + else if(sTargetMode == "SET_REPUTATION") + { + SetStandardFactionReputation(STANDARD_FACTION_COMMONER, 50, oTarget); + SetStandardFactionReputation(STANDARD_FACTION_DEFENDER, 50, oTarget); + SetStandardFactionReputation(STANDARD_FACTION_HOSTILE, 50, oTarget); + SetStandardFactionReputation(STANDARD_FACTION_MERCHANT, 50, oTarget); + ai_SendMessages(GetName(oTarget) + " has been set to a neutral reputation.", AI_COLOR_YELLOW, oPC); + } + else if(sTargetMode == "DEBUG_INFO") + { + ai_SendMessages("Information for " + GetName(oTarget), AI_COLOR_WHITE, oPC); + ai_SendMessages("ResRef: " + GetResRef(oTarget), AI_COLOR_GREEN, oPC); + ai_SendMessages("Tag: " + GetTag(oTarget), AI_COLOR_ORANGE, oPC); + ai_SendMessages("UUID: " + GetObjectUUID(oTarget), AI_COLOR_LIGHT_MAGENTA, oPC); + ai_SendMessages("Faction Commoner: " + IntToString(GetStandardFactionReputation(STANDARD_FACTION_COMMONER, oTarget)), AI_COLOR_GREEN, oPC); + ai_SendMessages("Faction Defender: " + IntToString(GetStandardFactionReputation(STANDARD_FACTION_DEFENDER, oTarget)), AI_COLOR_GREEN, oPC); + ai_SendMessages("Faction Merchant: " + IntToString(GetStandardFactionReputation(STANDARD_FACTION_MERCHANT, oTarget)), AI_COLOR_GREEN, oPC); + ai_SendMessages("Faction Hostile: " + IntToString(GetStandardFactionReputation(STANDARD_FACTION_HOSTILE, oTarget)), AI_COLOR_RED, oPC); + int nObjectType = GetObjectType(oTarget); + if(nObjectType == OBJECT_TYPE_CREATURE) + { + json jObject = ObjectToJson(oTarget); + string sConversation = JsonGetString(GffGetResRef(jObject, "Conversation")); + ai_SendMessages("Conversation: " + sConversation, AI_COLOR_CYAN, oPC); + SendMessageToPC(oPC, "Creature Event Scripts:"); + string sScript = GetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_HEARTBEAT SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_NOTICE); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_NOTICE SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_END_COMBATROUND SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_DIALOGUE); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_DIALOGUE SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_MELEE_ATTACKED SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_DAMAGED); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_DAMAGED SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_DEATH); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_DEATH SCRIPT: " + sScript); + sScript = GetLocalString(oTarget, "AI_ON_DEATH"); + if(sScript != "") + { + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_DEATH SECOND SCRIPT: " + sScript); + } + sScript = GetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_DISTURBED); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_DISTURBED SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_SPAWN_IN); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_SPAWN_IN SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_RESTED); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_RESTED SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_SPELLCASTAT SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_BLOCKED_BY_DOOR SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_USER_DEFINED_EVENT); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_USER_DEFINED_EVENT SCRIPT: " + sScript); + } + else if(nObjectType == OBJECT_TYPE_DOOR) + { + SendMessageToPC(oPC, "Door Event Scripts:"); + string sScript = GetEventScript(oTarget, EVENT_SCRIPT_DOOR_ON_CLICKED); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_CLICKED SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_DOOR_ON_CLOSE); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_CLOSED SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_DOOR_ON_DAMAGE); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_DAMAGE SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_DOOR_ON_DEATH); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_DEATH SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_DOOR_ON_DIALOGUE); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_DIALOGUE SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_DOOR_ON_DISARM); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_DISARM SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_DOOR_ON_FAIL_TO_OPEN); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_FAIL_TO_OPEN SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_DOOR_ON_HEARTBEAT); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_HEARTBEAT SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_DOOR_ON_LOCK); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_LOCK SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_DOOR_ON_MELEE_ATTACKED); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_MELEE_ATTACKED SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_DOOR_ON_OPEN); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_OPEN SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_DOOR_ON_SPELLCASTAT); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_SPELLCASTAT SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_DOOR_ON_TRAPTRIGGERED); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_TRAPTRIGGERED SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_DOOR_ON_UNLOCK); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_UNLOCK SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_DOOR_ON_USERDEFINED); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_USERDEFINED SCRIPT: " + sScript); + } + else if(nObjectType == OBJECT_TYPE_PLACEABLE) + { + SendMessageToPC(oPC, "Placeable Event Scripts:"); + string sScript = GetEventScript(oTarget, EVENT_SCRIPT_PLACEABLE_ON_CLOSED); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_CLOSED SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_PLACEABLE_ON_DAMAGED); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_DAMAGED SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_PLACEABLE_ON_DEATH); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_DEATH SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_PLACEABLE_ON_DIALOGUE); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_DIALOGUE SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_PLACEABLE_ON_DISARM); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_DISARM SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_PLACEABLE_ON_HEARTBEAT); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_HEARTBEAT SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_PLACEABLE_ON_INVENTORYDISTURBED); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_INVENTORYDISTURBED SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_PLACEABLE_ON_LEFT_CLICK); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_LEFT_CLICK SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_PLACEABLE_ON_LOCK); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_LOCK SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_PLACEABLE_ON_MELEEATTACKED); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_MELEEATTACKED SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_PLACEABLE_ON_OPEN); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_OPEN SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_PLACEABLE_ON_SPELLCASTAT); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_SPELLCASTAT SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_PLACEABLE_ON_TRAPTRIGGERED); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_TRAPTRIGGERED SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_PLACEABLE_ON_UNLOCK); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_UNLOCK SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_PLACEABLE_ON_USED); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_USED SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_USER_DEFINED_EVENT); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_USER_DEFINED_EVENT SCRIPT: " + sScript); + } + else if(nObjectType == OBJECT_TYPE_TRIGGER) + { + SendMessageToPC(oPC, "Trigger Event Scripts:"); + string sScript = GetEventScript(oTarget, EVENT_SCRIPT_TRIGGER_ON_CLICKED); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_CLICKED SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_PLACEABLE_ON_DISARM); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_DISARM SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_PLACEABLE_ON_HEARTBEAT); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_HEARTBEAT SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_TRIGGER_ON_OBJECT_ENTER); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_OBJECT_ENTER SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_TRIGGER_ON_OBJECT_EXIT); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_OBJECT_EXIT SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_PLACEABLE_ON_TRAPTRIGGERED); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_TRAPTRIGGERED SCRIPT: " + sScript); + sScript = GetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_USER_DEFINED_EVENT); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_USER_DEFINED_EVENT SCRIPT: " + sScript); + } + else + { + // Area event scripts. + object oArea = GetArea(oPC); + SendMessageToPC(oPC, "Area Event Scripts:"); + string sScript = GetEventScript(oArea, EVENT_SCRIPT_AREA_ON_ENTER); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_ENTER SCRIPT: " + sScript); + sScript = GetEventScript(oArea, EVENT_SCRIPT_AREA_ON_EXIT); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_EXIT SCRIPT: " + sScript); + sScript = GetEventScript(oArea, EVENT_SCRIPT_PLACEABLE_ON_HEARTBEAT); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_HEARTBEAT SCRIPT: " + sScript); + sScript = GetEventScript(oArea, EVENT_SCRIPT_CREATURE_ON_USER_DEFINED_EVENT); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_USER_DEFINED_EVENT SCRIPT: " + sScript); + // Module event scripts. + object oModule = GetModule(); + SendMessageToPC(oPC, GetModuleName() + " Module Event Scripts."); + sScript = GetEventScript(oModule, EVENT_SCRIPT_MODULE_ON_ACQUIRE_ITEM); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_ACQUIRE_ITEM SCRIPT: " + sScript); + sScript = GetEventScript(oModule, EVENT_SCRIPT_MODULE_ON_ACTIVATE_ITEM); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_ACTIVATE_ITEM SCRIPT: " + sScript); + sScript = GetEventScript(oModule, EVENT_SCRIPT_MODULE_ON_CLIENT_ENTER); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_CLIENT_ENTER SCRIPT: " + sScript); + sScript = GetEventScript(oModule, EVENT_SCRIPT_MODULE_ON_CLIENT_EXIT); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_CLIENT_EXIT SCRIPT: " + sScript); + sScript = GetEventScript(oModule, EVENT_SCRIPT_MODULE_ON_EQUIP_ITEM); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_EQUIP_ITEM SCRIPT: " + sScript); + sScript = GetEventScript(oModule, EVENT_SCRIPT_MODULE_ON_HEARTBEAT); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_HEARTBEAT SCRIPT: " + sScript); + sScript = GetEventScript(oModule, EVENT_SCRIPT_MODULE_ON_LOSE_ITEM); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_LOSE_ITEM SCRIPT: " + sScript); + sScript = GetEventScript(oModule, EVENT_SCRIPT_MODULE_ON_MODULE_LOAD); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_MODULE_LOAD SCRIPT: " + sScript); + sScript = GetEventScript(oModule, EVENT_SCRIPT_MODULE_ON_MODULE_START); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_MODULE_START SCRIPT: " + sScript); + sScript = GetEventScript(oModule, EVENT_SCRIPT_MODULE_ON_NUI_EVENT); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_NUI_EVENT SCRIPT: " + sScript); + sScript = GetEventScript(oModule, EVENT_SCRIPT_MODULE_ON_PLAYER_CANCEL_CUTSCENE); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_PLAYER_CANCEL_CUTSCENE SCRIPT: " + sScript); + sScript = GetEventScript(oModule, EVENT_SCRIPT_MODULE_ON_PLAYER_CHAT); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_PLAYER_CHAT SCRIPT: " + sScript); + sScript = GetEventScript(oModule, EVENT_SCRIPT_MODULE_ON_PLAYER_DEATH); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_PLAYER_DEATH SCRIPT: " + sScript); + sScript = GetEventScript(oModule, EVENT_SCRIPT_MODULE_ON_PLAYER_DYING); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_PLAYER_DYING SCRIPT: " + sScript); + sScript = GetEventScript(oModule, EVENT_SCRIPT_MODULE_ON_PLAYER_GUIEVENT); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_PLAYER_GUIEVENT SCRIPT: " + sScript); + sScript = GetEventScript(oModule, EVENT_SCRIPT_MODULE_ON_PLAYER_LEVEL_UP); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_LEVEL_UP SCRIPT: " + sScript); + sScript = GetEventScript(oModule, EVENT_SCRIPT_MODULE_ON_PLAYER_REST); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_PLAYER_REST SCRIPT: " + sScript); + sScript = GetEventScript(oModule, EVENT_SCRIPT_MODULE_ON_PLAYER_TARGET); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_PLAYER_TARGET SCRIPT: " + sScript); + sScript = GetLocalString(oModule, AI_MODULE_TARGET_EVENT); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + if(sScript != "") + { + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_PLAYER_TARGET SECOND SCRIPT: " + sScript); + } + sScript = GetEventScript(oModule, EVENT_SCRIPT_MODULE_ON_PLAYER_TILE_ACTION); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_PLAYER_TILE_ACTION SCRIPT: " + sScript); + sScript = GetEventScript(oModule, EVENT_SCRIPT_MODULE_ON_RESPAWN_BUTTON_PRESSED); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_RESPAWN_BUTTON_PRESSED SCRIPT: " + sScript); + sScript = GetEventScript(oModule, EVENT_SCRIPT_MODULE_ON_UNEQUIP_ITEM); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_UNEQUIP_ITEM SCRIPT: " + sScript); + sScript = GetEventScript(oModule, EVENT_SCRIPT_CREATURE_ON_USER_DEFINED_EVENT); + sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]"; + SendMessageToPC(oPC, "ON_USER_DEFINED_EVENT SCRIPT: " + sScript); + } + /* Checks PRC virtual events. See prc_inc_eventhk + int nIndex = 1; + string sEvent = GetFirstEventScript(oTarget, EVENT_VIRTUAL_ONHEARTBEAT, FALSE); + if(sEvent != "") + { + SendMessageToPC(oPC, "HB event script " + IntToString(nIndex) + ": " + sEvent); + for(nIndex = 2; nIndex < 20; nIndex++) + { + sEvent = GetNextEventScript(oTarget, EVENT_VIRTUAL_ONHEARTBEAT, FALSE); + if(sEvent == "") break; + SendMessageToPC(oPC, "HB event script " + IntToString(nIndex) + ": " + sEvent); + } + }*/ + } + else if(sTargetMode == "SET_NPC_SCRIPTS") + { + if(GetLocalString(oTarget, "AI_ON_HEARTBEAT") == "") + { + ai_ForceAssociateEventScriptsToDefault(oPC, oTarget); + } + else ai_RevertAssociateEventScriptsToDefault(oPC, oTarget); + } + else if(sTargetMode == "CLEAR_CREATURE_EVENTS") + { + ai_SendMessages("Set event scripts for " + GetName(oTarget) + " to default.", AI_COLOR_YELLOW, oPC); + SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "default"); + SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_NOTICE, "default"); + SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND, "default"); + SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_DIALOGUE, "default"); + SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED, "default"); + SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_DAMAGED, "default"); + SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_DEATH, "default"); + SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_DISTURBED, "default"); + SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_SPAWN_IN, "default"); + SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_RESTED, "default"); + SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, "default"); + SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR, "default"); + SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_USER_DEFINED_EVENT, "default"); + DeleteLocalInt(oTarget, "AI_I_AM_BEING_HEALED"); + DeleteLocalString(oTarget, "AIScript"); + ai_ClearCreatureActions(); + } + else if(sTargetMode == "DEBUG_JSON_DUMP") + { + json jObject = ObjectToJson(oTarget, TRUE); + WriteTimestampedLogEntry(GetName(oTarget) + " JsonDump: " + JsonDump(jObject, 1)); + ai_SendMessages(GetName(oTarget) + " has been dumped to the log file!", AI_COLOR_YELLOW, oPC); + } + else if(sTargetMode == "DEBUG_LIST_VAR") + { + debug_ListObjectVariables(oPC, oTarget); + } + else if(sTargetMode == "DEBUG_SET_VARIABLE") + { + string sVarName = GetLocalString(oPC, "Debug_Var_Name"); + int nVarType = GetLocalInt(oPC, "Debug_Var_Type"); + if(nVarType == 0) // Int + { + string sVarValue = GetLocalString(oPC, "Debug_Var_Value"); + int nVarValue = StringToInt(sVarValue); + SetLocalInt(oTarget, sVarName, nVarValue); + ai_SendMessages(sVarName + " [Int] has been set to " + IntToString(nVarValue) + " for " + GetName(oTarget), AI_COLOR_YELLOW, oPC); + } + else if(nVarType == 1) // Float + { + string sVarValue = GetLocalString(oPC, "Debug_Var_Value"); + DeleteLocalString(oPC, "Debug_Var_Name"); + float fVarValue = StringToFloat(sVarValue); + SetLocalFloat(oTarget, sVarName, fVarValue); + ai_SendMessages(sVarName + " [Float] has been set to " + FloatToString(fVarValue, 0, 2) + " for " + GetName(oTarget), AI_COLOR_YELLOW, oPC); + } + else if(nVarType == 2) // String + { + string sVarValue = GetLocalString(oPC, "Debug_Var_Value"); + SetLocalString(oTarget, sVarName, sVarValue); + ai_SendMessages(sVarName + " [String] has been set to " + sVarValue + " for " + GetName(oTarget), AI_COLOR_YELLOW, oPC); + } + else if(nVarType == 3) // Object + { + // Set this variable on the player so PEPS can run the targeting script for this plugin. + SetLocalString(oPC, AI_PLUGIN_TARGET_SCRIPT, "pe_debug"); + // Set Targeting variables. + SetLocalObject(oPC, "AI_TARGET_OBJECT", oTarget); + SetLocalString(oPC, AI_TARGET_MODE, "DEBUG_SET_OBJECT_VARIABLE"); + ai_SendMessages("Select an object to save to " + GetName(oTarget), AI_COLOR_YELLOW, oPC); + EnterTargetingMode(oPC, OBJECT_TYPE_CREATURE | OBJECT_TYPE_DOOR | + OBJECT_TYPE_ITEM | OBJECT_TYPE_PLACEABLE | OBJECT_TYPE_TRIGGER, MOUSECURSOR_EXAMINE, MOUSECURSOR_NOEXAMINE); + } + else if(nVarType == 4) // Location + { + // Set this variable on the player so PEPS can run the targeting script for this plugin. + SetLocalString(oPC, AI_PLUGIN_TARGET_SCRIPT, "pe_debug"); + // Set Targeting variables. + SetLocalObject(oPC, "AI_TARGET_OBJECT", oTarget); + SetLocalString(oPC, AI_TARGET_MODE, "DEBUG_SET_LOCATION_VARIABLE"); + ai_SendMessages("Select a location to save to " + GetName(oTarget), AI_COLOR_YELLOW, oPC); + EnterTargetingMode(oPC, OBJECT_TYPE_TILE, MOUSECURSOR_EXAMINE, MOUSECURSOR_NOEXAMINE); + } + DeleteLocalString(oPC, "Debug_Var_Name"); + DeleteLocalInt(oPC, "Debug_Var_Type"); + DeleteLocalString(oPC, "Debug_Var_Value"); + } + else if(sTargetMode == "DEBUG_SET_OBJECT_VARIABLE") + { + string sVarName = GetLocalString(oPC, "Debug_Var_Name"); + SetLocalObject(oObject, sVarName, oTarget); + DeleteLocalObject(oPC, "AI_TARGET_OBJECT"); + DeleteLocalString(oPC, "Debug_Var_Name"); + ai_SendMessages(sVarName + " [Object] has been set to " + GetName(oObject) + " for " + GetName(oTarget), AI_COLOR_YELLOW, oPC); + } + else if(sTargetMode == "DEBUG_SET_LOCATION_VARIABLE") + { + string sVarName = GetLocalString(oPC, "Debug_Var_Name"); + SetLocalLocation(oObject, sVarName, lLocation); + DeleteLocalObject(oPC, "AI_TARGET_OBJECT"); + DeleteLocalString(oPC, "Debug_Var_Name"); + ai_SendMessages(sVarName + " [Location] has been set to " + LocationToString(lLocation) + " for " + GetName(oTarget), AI_COLOR_YELLOW, oPC); + } + else if(sTargetMode == "DEBUG_DELETE_VARIABLE") + { + string sVarName = GetLocalString(oPC, "Debug_Var_Name"); + int nVarType = GetLocalInt(oPC, "Debug_Var_Type"); + if(nVarType == 0) DeleteLocalInt(oTarget, sVarName); + else if(nVarType == 1) DeleteLocalFloat(oTarget, sVarName); + else if(nVarType == 2) DeleteLocalString(oTarget, sVarName); + else if(nVarType == 4) DeleteLocalObject(oTarget, sVarName); + else if(nVarType == 5) DeleteLocalLocation(oTarget, sVarName); + ai_SendMessages(sVarName + " has been deleted from " + GetName(oTarget), AI_COLOR_YELLOW, oPC); + DeleteLocalString(oPC, "Debug_Var_Name"); + DeleteLocalInt(oPC, "Debug_Var_Type"); + } + else if(sTargetMode == "DEBUG_GET_VARIABLE") + { + debug_GetObjectVariable(oPC, oTarget); + } + } + // Run all non-targeting code here, usually NUI events. + else + { + object oPC = NuiGetEventPlayer(); + int nToken = NuiGetEventWindow(); + string sEvent = NuiGetEventType(); + string sElem = NuiGetEventElement(); + int nIndex = NuiGetEventArrayIndex(); + //string sWndId = NuiGetWindowId(oPC, nToken); + //********************************************************************** + //if(GetLocalInt(oPC, AI_NO_NUI_SAVE)) return; + if(sEvent == "click") + { + if(sElem == "btn_npc_scripts") + { + // Set this variable on the player so PEPS can run the targeting script for this plugin. + SetLocalString(oPC, AI_PLUGIN_TARGET_SCRIPT, "pe_debug"); + // Set Targeting variables. + SetLocalString(oPC, AI_TARGET_MODE, "SET_NPC_SCRIPTS"); + NuiDestroy(oPC, nToken); + ai_SendMessages("Select an npc to change scripts for.", AI_COLOR_YELLOW, oPC); + EnterTargetingMode(oPC, OBJECT_TYPE_CREATURE , MOUSECURSOR_CREATE, MOUSECURSOR_NOCREATE); + } + else if(sElem == "btn_set_reputation") + { + // Set this variable on the player so PEPS can run the targeting script for this plugin. + SetLocalString(oPC, AI_PLUGIN_TARGET_SCRIPT, "pe_debug"); + // Set Targeting variables. + SetLocalString(oPC, AI_TARGET_MODE, "SET_REPUTATION"); + NuiDestroy(oPC, nToken); + ai_SendMessages("Select a creature to set all standard reputations to neutral.", AI_COLOR_YELLOW, oPC); + EnterTargetingMode(oPC, OBJECT_TYPE_CREATURE, MOUSECURSOR_EXAMINE, MOUSECURSOR_NOEXAMINE); + } + else if(sElem == "btn_clear_reputation") + { + // Set this variable on the player so PEPS can run the targeting script for this plugin. + SetLocalString(oPC, AI_PLUGIN_TARGET_SCRIPT, "pe_debug"); + // Set Targeting variables. + SetLocalString(oPC, AI_TARGET_MODE, "CLEAR_REPUTATION"); + NuiDestroy(oPC, nToken); + ai_SendMessages("Select a creature to clear your PC's reputation with that creature's faction.", AI_COLOR_YELLOW, oPC); + EnterTargetingMode(oPC, OBJECT_TYPE_CREATURE, MOUSECURSOR_EXAMINE, MOUSECURSOR_NOEXAMINE); + } + else if(sElem == "btn_info") + { + // Set this variable on the player so PEPS can run the targeting script for this plugin. + SetLocalString(oPC, AI_PLUGIN_TARGET_SCRIPT, "pe_debug"); + // Set Targeting variables. + SetLocalString(oPC, AI_TARGET_MODE, "DEBUG_INFO"); + NuiDestroy(oPC, nToken); + ai_SendMessages("Select an object to send it's information to the players screen.", AI_COLOR_YELLOW, oPC); + EnterTargetingMode(oPC, OBJECT_TYPE_ALL , MOUSECURSOR_EXAMINE, MOUSECURSOR_NOEXAMINE); + } + else if(sElem == "btn_obj_json") + { + // Set this variable on the player so PEPS can run the targeting script for this plugin. + SetLocalString(oPC, AI_PLUGIN_TARGET_SCRIPT, "pe_debug"); + // Set Targeting variables. + SetLocalString(oPC, AI_TARGET_MODE, "DEBUG_JSON_DUMP"); + NuiDestroy(oPC, nToken); + ai_SendMessages("Select an object to dump it's json values to the log.", AI_COLOR_YELLOW, oPC); + EnterTargetingMode(oPC, OBJECT_TYPE_CREATURE | OBJECT_TYPE_DOOR | + OBJECT_TYPE_ITEM | OBJECT_TYPE_PLACEABLE | OBJECT_TYPE_TRIGGER, MOUSECURSOR_EXAMINE, MOUSECURSOR_NOEXAMINE); + } + else if(sElem == "btn_obj_var") + { + // Set this variable on the player so PEPS can run the targeting script for this plugin. + SetLocalString(oPC, AI_PLUGIN_TARGET_SCRIPT, "pe_debug"); + // Set Targeting variables. + SetLocalString(oPC, AI_TARGET_MODE, "DEBUG_LIST_VAR"); + NuiDestroy(oPC, nToken); + ai_SendMessages("Select an object to list it's variables to the player screen.", AI_COLOR_YELLOW, oPC); + EnterTargetingMode(oPC, OBJECT_TYPE_ALL, MOUSECURSOR_EXAMINE, MOUSECURSOR_NOEXAMINE); + } + else if(sElem == "btn_debug_creature") + { + // Set this variable on the player so PEPS can run the targeting script for this plugin. + SetLocalString(oPC, AI_PLUGIN_TARGET_SCRIPT, "pe_debug"); + // Set Targeting variables. + SetLocalObject(oPC, AI_TARGET_ASSOCIATE, OBJECT_SELF); + SetLocalString(oPC, AI_TARGET_MODE, "DEBUG_CREATURE"); + NuiDestroy(oPC, nToken); + ai_SendMessages("Select a creature to start sending debug information to the log for.", AI_COLOR_YELLOW, oPC); + EnterTargetingMode(oPC, OBJECT_TYPE_CREATURE, MOUSECURSOR_EXAMINE, MOUSECURSOR_NOEXAMINE); + } + else if(sElem == "btn_clear_events") + { + // Set this variable on the player so PEPS can run the targeting script for this plugin. + SetLocalString(oPC, AI_PLUGIN_TARGET_SCRIPT, "pe_debug"); + // Set Targeting variables. + SetLocalObject(oPC, AI_TARGET_ASSOCIATE, OBJECT_SELF); + SetLocalString(oPC, AI_TARGET_MODE, "CLEAR_CREATURE_EVENTS"); + NuiDestroy(oPC, nToken); + ai_SendMessages("Select a creature to set event scripts to default.", AI_COLOR_YELLOW, oPC); + EnterTargetingMode(oPC, OBJECT_TYPE_CREATURE, MOUSECURSOR_EXAMINE, MOUSECURSOR_NOEXAMINE); + } + else if(sElem == "btn_clear_debug") + { + object oModule = GetModule(); + SetLocalString(oModule, AI_RULE_DEBUG_CREATURE, ""); + json jRules = ai_GetCampaignDbJson("rules"); + jRules = JsonObjectSet(jRules, AI_RULE_DEBUG_CREATURE, JsonString("")); + ai_SetCampaignDbJson("rules", jRules); + DeleteLocalObject(oPC, "AI_RULE_DEBUG_CREATURE_OBJECT"); + ai_SendMessages("Creature Debug mode has been cleared.", AI_COLOR_YELLOW, oPC); + NuiDestroy(oPC, nToken); + ExecuteScript("pi_debug", oPC); + } + else if(sElem == "btn_delete_var") + { + // Set this variable on the player so PEPS can run the targeting script for this plugin. + SetLocalString(oPC, AI_PLUGIN_TARGET_SCRIPT, "pe_debug"); + // Set Targeting variables. + string sVarName = JsonGetString(NuiGetBind(oPC, nToken, "txt_var_name")); + SetLocalString(oPC, "Debug_Var_Name", sVarName); + SetLocalString(oPC, "Debug_Var_Value", JsonGetString(NuiGetBind(oPC, nToken, "txt_var_value"))); + SetLocalInt(oPC, "Debug_Var_Type", JsonGetInt(NuiGetBind (oPC, nToken, "cmb_var_type_selected"))); + SetLocalString(oPC, AI_TARGET_MODE, "DEBUG_DELETE_VARIABLE"); + NuiDestroy(oPC, nToken); + ai_SendMessages("Select Object to delete (" + sVarName + ") variable from.", AI_COLOR_YELLOW, oPC); + EnterTargetingMode(oPC, OBJECT_TYPE_ALL, MOUSECURSOR_EXAMINE, MOUSECURSOR_NOEXAMINE); + } + else if(sElem == "btn_get_var") + { + // Set this variable on the player so PEPS can run the targeting script for this plugin. + SetLocalString(oPC, AI_PLUGIN_TARGET_SCRIPT, "pe_debug"); + // Set Targeting variables. + string sVarName = JsonGetString(NuiGetBind(oPC, nToken, "txt_var_name")); + SetLocalString(oPC, "Debug_Var_Name", sVarName); + SetLocalString(oPC, "Debug_Var_Value", JsonGetString(NuiGetBind(oPC, nToken, "txt_var_value"))); + SetLocalInt(oPC, "Debug_Var_Type", JsonGetInt(NuiGetBind (oPC, nToken, "cmb_var_type_selected"))); + SetLocalString(oPC, AI_TARGET_MODE, "DEBUG_GET_VARIABLE"); + NuiDestroy(oPC, nToken); + ai_SendMessages("Select Object to get (" + sVarName + ") variable from.", AI_COLOR_YELLOW, oPC); + EnterTargetingMode(oPC, OBJECT_TYPE_ALL, MOUSECURSOR_EXAMINE, MOUSECURSOR_NOEXAMINE); + } + else if(sElem == "btn_set_var") + { + // Set this variable on the player so PEPS can run the targeting script for this plugin. + SetLocalString(oPC, AI_PLUGIN_TARGET_SCRIPT, "pe_debug"); + // Set Targeting variables. + string sVarName = JsonGetString(NuiGetBind(oPC, nToken, "txt_var_name")); + SetLocalString(oPC, "Debug_Var_Name", sVarName); + SetLocalString(oPC, "Debug_Var_Value", JsonGetString(NuiGetBind(oPC, nToken, "txt_var_value"))); + SetLocalInt(oPC, "Debug_Var_Type", JsonGetInt(NuiGetBind (oPC, nToken, "cmb_var_type_selected"))); + SetLocalString(oPC, AI_TARGET_MODE, "DEBUG_SET_VARIABLE"); + NuiDestroy(oPC, nToken); + ai_SendMessages("Select Object to set (" + sVarName + ") variable to.", AI_COLOR_YELLOW, oPC); + EnterTargetingMode(oPC, OBJECT_TYPE_ALL, MOUSECURSOR_EXAMINE, MOUSECURSOR_NOEXAMINE); + } + } + if(sEvent == "watch") + { + if(sElem == "txt_var_name" || sElem == "txt_var_value" || + sElem == "cmb_var_type_selected") + { + if(JsonGetString(NuiGetBind(oPC, nToken, "txt_var_name")) != "") + { + NuiSetBind(oPC, nToken, "btn_get_var_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_delete_var_event", JsonBool(TRUE)); + if(JsonGetInt(NuiGetBind (oPC, nToken, "cmb_var_type_selected")) == 3 || // Objects + JsonGetInt(NuiGetBind (oPC, nToken, "cmb_var_type_selected")) == 4 || // Locations + JsonGetString(NuiGetBind(oPC, nToken, "txt_var_value")) != "") + { + NuiSetBind(oPC, nToken, "btn_set_var_event", JsonBool(TRUE)); + return; + } + } + else + { + NuiSetBind(oPC, nToken, "btn_get_var_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_delete_var_event", JsonBool(FALSE)); + } + NuiSetBind(oPC, nToken, "btn_set_var_event", JsonBool(FALSE)); + } + } + if(sEvent == "mousedown") + { + int nMouseButton = JsonGetInt(JsonObjectGet(NuiGetEventPayload(), "mouse_btn")); + if(nMouseButton == NUI_MOUSE_BUTTON_RIGHT) + { + if(sElem == "btn_delete_var") + { + object oModule = GetModule(); + // Set Targeting variables. + string sVarName = JsonGetString(NuiGetBind(oPC, nToken, "txt_var_name")); + int nVarType = JsonGetInt(NuiGetBind (oPC, nToken, "cmb_var_type_selected")); + if(nVarType == 0) DeleteLocalInt(oModule, sVarName); + else if(nVarType == 1) DeleteLocalFloat(oModule, sVarName); + else if(nVarType == 2) DeleteLocalString(oModule, sVarName); + else if(nVarType == 4) DeleteLocalObject(oModule, sVarName); + else if(nVarType == 5) DeleteLocalLocation(oModule, sVarName); + ai_SendMessages(sVarName + " has been deleted from the Module", AI_COLOR_YELLOW, oPC); + } + else if(sElem == "btn_get_var") + { + // Set Targeting variables. + SetLocalString(oPC, "Debug_Var_Name", JsonGetString(NuiGetBind(oPC, nToken, "txt_var_name"))); + SetLocalInt(oPC, "Debug_Var_Type", JsonGetInt(NuiGetBind (oPC, nToken, "cmb_var_type_selected"))); + debug_GetObjectVariable(oPC, GetModule(), "(Module)"); + } + else if(sElem == "btn_set_var") + { + // Set Targeting variables. + string sVarName = JsonGetString(NuiGetBind(oPC, nToken, "txt_var_name")); + string sVarValue = JsonGetString(NuiGetBind(oPC, nToken, "txt_var_value")); + int nVarType = JsonGetInt(NuiGetBind (oPC, nToken, "cmb_var_type_selected")); + SetLocalString(oPC, AI_TARGET_MODE, "DEBUG_SET_VARIABLE"); + if(nVarType == 0) // Int + { + int nVarValue = StringToInt(sVarValue); + SetLocalInt(GetModule(), sVarName, nVarValue); + ai_SendMessages(sVarName + " [Int] has been set to " + IntToString(nVarValue) + " on the Module.", AI_COLOR_YELLOW, oPC); + } + else if(nVarType == 1) // Float + { + float fVarValue = StringToFloat(sVarValue); + SetLocalFloat(GetModule(), sVarName, fVarValue); + ai_SendMessages(sVarName + " [Float] has been set to " + FloatToString(fVarValue, 0, 2) + " on the Module.", AI_COLOR_YELLOW, oPC); + } + else if(nVarType == 2) // String + { + SetLocalString(GetModule(), sVarName, sVarValue); + ai_SendMessages(sVarName + " [String] has been set to " + sVarValue + " on the Module.", AI_COLOR_YELLOW, oPC); + } + else if(nVarType == 3) // Object + { + object oModule = GetModule(); + // Set this variable on the player so PEPS can run the targeting script for this plugin. + SetLocalString(oPC, AI_PLUGIN_TARGET_SCRIPT, "pe_debug"); + // Set Targeting variables. + SetLocalString(oPC, "Debug_Var_Name", sVarName); + SetLocalObject(oPC, "AI_TARGET_OBJECT", oModule); + SetLocalString(oPC, AI_TARGET_MODE, "DEBUG_SET_OBJECT_VARIABLE"); + ai_SendMessages("Select an object to save to " + GetName(oModule), AI_COLOR_YELLOW, oPC); + EnterTargetingMode(oPC, OBJECT_TYPE_CREATURE | OBJECT_TYPE_DOOR | + OBJECT_TYPE_ITEM | OBJECT_TYPE_PLACEABLE | OBJECT_TYPE_TRIGGER, MOUSECURSOR_EXAMINE, MOUSECURSOR_NOEXAMINE); + } + else if(nVarType == 4) // Location + { + object oModule = GetModule(); + // Set this variable on the player so PEPS can run the targeting script for this plugin. + SetLocalString(oPC, AI_PLUGIN_TARGET_SCRIPT, "pe_debug"); + // Set Targeting variables. + SetLocalString(oPC, "Debug_Var_Name", sVarName); + SetLocalObject(oPC, "AI_TARGET_OBJECT", oModule); + SetLocalString(oPC, AI_TARGET_MODE, "DEBUG_SET_LOCATION_VARIABLE"); + ai_SendMessages("Select a location to save to " + GetName(oModule), AI_COLOR_YELLOW, oPC); + EnterTargetingMode(oPC, OBJECT_TYPE_TILE, MOUSECURSOR_EXAMINE, MOUSECURSOR_NOEXAMINE); + } + } + } + } + } +} +void debug_GetObjectVariable(object oPC, object oTarget, string sDesc = "") +{ + string sVar, sVarName = GetLocalString(oPC, "Debug_Var_Name"); + int nVarType = GetLocalInt(oPC, "Debug_Var_Type"); + if(nVarType == 0) sVar = IntToString(GetLocalInt(oTarget, sVarName)); + else if(nVarType == 1) sVar = FloatToString(GetLocalFloat(oTarget, sVarName), 0, 2); + else if(nVarType == 2) sVar = GetLocalString(oTarget, sVarName); + else if(nVarType == 4) sVar = GetName(GetLocalObject(oTarget, sVarName)); + else if(nVarType == 5) sVar = LocationToString(GetLocalLocation(oTarget, sVarName)); + ai_SendMessages(sVarName + " on " + GetName(oTarget) + sDesc + " is set to " + sVar, AI_COLOR_YELLOW, oPC); +} +void debug_ListObjectVariables(object oPC, object oTarget) +{ + string sName = GetName(oTarget); + if(GetStringRight(sName, 1) == "s") sName = sName + "'"; + else sName = sName + "'s"; + ai_SendMessages(sName + " variables:", AI_COLOR_GREEN, oPC); + json jObject = ObjectToJson(oTarget, TRUE); + json jVarTable = GffGetList(jObject, "VarTable"); + string sVariable; + int nIndex, nVarType; + json jVar = JsonArrayGet(jVarTable, nIndex); + while(JsonGetType(jVar) != JSON_TYPE_NULL) + { + sVariable = JsonGetString(GffGetString(jVar, "Name")); + nVarType = JsonGetInt(GffGetDword(jVar, "Type")); + if(nVarType == 1) + { + sVariable += " [int] "; + sVariable += IntToString(JsonGetInt(GffGetInt(jVar, "Value"))); + } + else if(nVarType == 2) + { + sVariable += " [float] "; + sVariable += FloatToString(JsonGetFloat(GffGetFloat(jVar, "Value")), 0, 2); + } + else if(nVarType == 3) + { + sVariable += " [string] "; + sVariable += JsonGetString(GffGetString(jVar, "Value")); + } + else if(nVarType == 4) + { + sName = GetName(GetLocalObject(oTarget, sVariable)); + sVariable += " [object] " + sName; + } + else if(nVarType == 5) + { + sName = LocationToString(GetLocalLocation(oTarget, sVariable)); + sVariable += " [location] " + sName; + } + else if(nVarType == 7) + { + sVariable += " [struct] "; + sVariable += JsonDump(GffGetStruct(jVar, "Value")); + } + sVariable += JsonGetString(JsonObjectGet(jVar, "Value")); + ai_SendMessages(sVariable, AI_COLOR_YELLOW, oPC); + jVar = JsonArrayGet(jVarTable, ++nIndex); + } + if(!nIndex) ai_SendMessages("No variables to list!", AI_COLOR_YELLOW, oPC); +} +void ai_ForceAssociateEventScriptsToDefault(object oPC, object oCreature) +{ + ai_SendMessages("Changing " + GetName(oCreature) + "'s event scripts to default event scripts!", AI_COLOR_YELLOW, oPC); + ai_SendMessages("Use this tool on them again to revert this creatures event scripts back!", AI_COLOR_YELLOW, oPC); + //********** On Heartbeat ********** + string sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT); + if(sScript == "0e_id_events" || sScript == "0e_prc_id_events") + { + ai_SendMessages("You cannot use this on creatures in Infinite Dungeons!"); + return; + } + SetLocalString(oCreature, "AI_ON_HEARTBEAT", sScript); + SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "nw_ch_ac1"); + //********** On Perception ********** + sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_NOTICE); + SetLocalString(oCreature, "AI_ON_NOTICE", sScript); + SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_NOTICE, "nw_ch_ac2"); + //********** On End Combat Round ********** + sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND); + SetLocalString(oCreature, "AI_ON_END_COMBATROUND", sScript); + SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND, "nw_ch_ac3"); + //********** On Dialogue ********** + sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DIALOGUE); + SetLocalString(oCreature, "AI_ON_DIALOGUE", sScript); + SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DIALOGUE, "nw_ch_ac4"); + //********** On Melee Attacked ********** + sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED); + SetLocalString(oCreature, "AI_ON_MELEE_ATTACKED", sScript); + SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED, "nw_ch_ac5"); + //********** On Damaged ********** + sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DAMAGED); + SetLocalString(oCreature, "AI_ON_DAMAGED", sScript); + SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DAMAGED, "nw_ch_ac6"); + //********** On Disturbed ********** + sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DISTURBED); + SetLocalString(oCreature, "AI_ON_DISTURBED", sScript); + SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DISTURBED, "nw_ch_ac8"); + //SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_SPAWN_IN, ""); + //********** On Rested ********** + sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_RESTED); + SetLocalString(oCreature, "AI_ON_RESTED", sScript); + SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_RESTED, "nw_ch_aca"); + //********** On Spell Cast At ********** + sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT); + SetLocalString(oCreature, "AI_ON_SPELLCASTAT", sScript); + SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, "nw_ch_acb"); + //********** On Blocked ********** + sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR); + SetLocalString(oCreature, "AI_ON_BLOCKED_BY_DOOR", sScript); + SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR, "nw_ch_acb"); + //SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_USER_DEFINED_EVENT, ""); + if(!GetCommandable(oCreature)) SetCommandable(TRUE, oCreature); +} +void ai_RevertAssociateEventScriptsToDefault(object oPC, object oCreature) +{ + ai_SendMessages("Changing " + GetName(oCreature) + "'s event scripts back to original!", AI_COLOR_YELLOW, oPC); + //********** On Heartbeat ********** + string sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT); + if(sScript == "0e_id_events" || sScript == "0e_prc_id_events") + { + ai_SendMessages("You cannot use this on creatures in Infinite Dungeons!", AI_COLOR_RED, oPC); + return; + } + sScript = GetLocalString(oCreature, "AI_ON_HEARTBEAT"); + SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, sScript); + //********** On Perception ********** + sScript = GetLocalString(oCreature, "AI_ON_NOTICE"); + SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_NOTICE, sScript); + //********** On End Combat Round ********** + sScript = GetLocalString(oCreature, "AI_ON_END_COMBATROUND"); + SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND, sScript); + //********** On Dialogue ********** + sScript = GetLocalString(oCreature, "AI_ON_DIALOGUE"); + SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DIALOGUE, sScript); + //********** On Melee Attacked ********** + sScript = GetLocalString(oCreature, "AI_ON_MELEE_ATTACKED"); + SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED, sScript); + //********** On Damaged ********** + sScript = GetLocalString(oCreature, "AI_ON_DAMAGED"); + SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DAMAGED, sScript); + //********** On Disturbed ********** + sScript = GetLocalString(oCreature, "AI_ON_DISTURBED"); + SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DISTURBED, sScript); + //SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_SPAWN_IN, ""); + //********** On Rested ********** + sScript = GetLocalString(oCreature, "AI_ON_RESTED"); + SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_RESTED, sScript); + //********** On Spell Cast At ********** + sScript = GetLocalString(oCreature, "AI_ON_SPELLCASTAT"); + SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, sScript); + //********** On Blocked ********** + sScript = GetLocalString(oCreature, "AI_ON_BLOCKED_BY_DOOR"); + SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR, sScript); + //SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_USER_DEFINED_EVENT, ""); + if(!GetCommandable(oCreature)) SetCommandable(TRUE, oCreature); +} + diff --git a/src/module/nss/pe_henchmen.nss b/src/module/nss/pe_henchmen.nss new file mode 100644 index 0000000..4f6bf42 --- /dev/null +++ b/src/module/nss/pe_henchmen.nss @@ -0,0 +1,589 @@ +/*////////////////////////////////////////////////////////////////////////////// +// Script Name: pe_henchmen +//////////////////////////////////////////////////////////////////////////////// + Used with pe_henchmen to run the npc plugin for + Philos Single Player Enhancements. +*/////////////////////////////////////////////////////////////////////////////// +#include "pinc_henchmen" +#include "x0_i0_henchman" +#include "0i_module" +// Creates the Henchman widget. +void PopupWidgetHenchmanGUIPanel(object oPC); +void ResetHenchmanWindows(object oPC, int nToken, object oHenchman) +{ + DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, "henchman_nui"))); + DelayCommand(0.1, ExecuteScript("pi_henchmen", oPC)); + DelayCommand(0.0, NuiDestroy(oPC, nToken)); + DelayCommand(0.2, CreateCharacterEditGUIPanel(oPC, oHenchman)); +} +void main() +{ + //************************************************************************** + //********************** Henchmen Targeting Execution ********************** + //************************************************************************** + // Get the last player to use targeting mode + object oPC = GetLastPlayerToSelectTarget(); + if(GetLocalInt (oPC, "0_No_Win_Save")) return; + string sTargetMode = GetLocalString(oPC, AI_TARGET_MODE); + if(oPC == OBJECT_SELF && sTargetMode != "") + { + // Get the targeting mode data + object oTarget = GetTargetingModeSelectedObject(); + vector vTarget = GetTargetingModeSelectedPosition(); + location lLocation = Location(GetArea(oPC), vTarget, GetFacing(oPC)); + object oObject = GetLocalObject(oPC, "AI_TARGET_OBJECT"); + // If the user manually exited targeting mode without selecting a target, return + if(!GetIsObjectValid(oTarget) && vTarget == Vector()) + { + return; + } + // Targeting code here. + if(sTargetMode == "MAKE_NPC_HENCHMAN") + { + if(GetAssociateType(oTarget) == ASSOCIATE_TYPE_HENCHMAN) + { + ai_SendMessages(GetName(oTarget) + " is already a henchman!", AI_COLOR_RED, oPC); + return; + } + oTarget = CopyObject(oTarget, GetLocation(oPC), OBJECT_INVALID, "", TRUE); + ai_ClearCombatState(oTarget); + ChangeToStandardFaction(oTarget, STANDARD_FACTION_DEFENDER); + DeleteLocalInt(oTarget, AI_ONSPAWN_EVENT); + ai_ChangeEventScriptsForAssociate(oTarget); + AddHenchman(oPC, oTarget); + // Special check for Infinite Dungeon plot givers to be changed into henchman. + if(GetStringLeft(GetLocalString(oTarget, "sConversation"), 8) == "id1_plot") + { + DeleteLocalString(oTarget, "sConversation"); + } + // Remove this variable so they may get a unique tag associate widget. + DeleteLocalString(oTarget, AI_TAG); + ai_SendMessages(GetName(oTarget) + " has been copied and is now in your party as a henchman.", AI_COLOR_GREEN, oPC); + //ExecuteScript("pi_henchmen", oPC); + } + } + //************************************************************************** + //*********************** Henchmen Elements Execution ********************** + //************************************************************************** + else + { + // Let the inspector handle what it wants. + //HandleWindowInspectorEvent (); + object oPC = NuiGetEventPlayer(); + int nToken = NuiGetEventWindow(); + string sEvent = NuiGetEventType(); + string sElem = NuiGetEventElement(); + int nIndex = NuiGetEventArrayIndex(); + string sWndId = NuiGetWindowId (oPC, nToken); + //SendMessageToPC(oPC, "pe_henchmen , 26 sWndId: " + sWndId + " sEvent: " + sEvent + " sElem: " + sElem + + // " nToken: " + IntToString(nToken) + " nIndex: " + IntToString(nIndex) + + // " oPC: " + GetName(oPC)); + //********************************************************************** + // Watch to see if the window moves and save. + if(sElem == "window_geometry" && sEvent == "watch") + { + if(GetLocalInt(oPC, "AI_NO_NUI_SAVE")) return; + json jGeometry = NuiGetBind(oPC, nToken, "window_geometry"); + json jData = GetHenchmanDbJson(oPC, "henchman", "0"); + if(JsonGetType(jData) == JSON_TYPE_NULL) jData = JsonObject(); + jData = JsonObjectSet(jData, sWndId, jGeometry); + SetHenchmanDbJson(oPC, "henchman", jData, "0"); + } + else if(sWndId == "henchman_nui") + { + //********************************************************************** + // Henchman menu. + if(sEvent == "click") + { + string sParty = GetHenchmanDbString(oPC, "henchname", "0"); + // Change to a different saved party #. + if(GetStringLeft(sElem, 9) == "btn_party") + { + sParty = GetStringRight(sElem, 1); + SetHenchmanDbString(oPC, "henchname", sParty, "0"); + DelayCommand(0.0, NuiDestroy(oPC, nToken)); + DelayCommand(0.1, ExecuteScript("pi_henchmen", oPC)); + } + // Add an NPC in the game as a henchman. + else if(sElem == "btn_npc_henchman") + { + // Set this variable on the player so PEPS can run the targeting script for this plugin. + SetLocalString(oPC, AI_PLUGIN_TARGET_SCRIPT, "pe_henchmen"); + // Set Targeting variables. + SetLocalString(oPC, AI_TARGET_MODE, "MAKE_NPC_HENCHMAN"); + DelayCommand(0.0, NuiDestroy(oPC, nToken)); + ai_SendMessages("Select an NPC to copy and make your henchman.", AI_COLOR_YELLOW, oPC); + EnterTargetingMode(oPC, OBJECT_TYPE_ALL , MOUSECURSOR_CREATE, MOUSECURSOR_NOCREATE); + } + // ******************* Saved Character buttons ********************* + // Show saved party member. + else if(sElem == "btn_saved_char") + { + string sIndex = IntToString(nIndex); + SetHenchmanDbString(oPC, "henchname", sIndex, sParty); + AddSavedCharacterInfo(oPC, nToken, sParty); + } + // Have any saved henchman not in the party join. + else if(sElem == "btn_join_party") + { + SavedPartyJoin(oPC, nToken, sParty); + } + else if(sElem == "btn_saved_join") + { + SavedCharacterJoin(oPC, nToken, sParty); + } + else if(sElem == "btn_saved_remove") + { + string sIndex = GetHenchmanDbString(oPC, "henchname", sParty); + RemoveHenchmanDb(oPC, sParty + sIndex); + if(GetHenchmanDbString(oPC, "henchname", sParty + "0") == "") + { + SetHenchmanDbString(oPC, "henchname", "", sParty); + } + else SetHenchmanDbString(oPC, "henchname", "0", sParty); + DelayCommand(0.0, NuiDestroy(oPC, nToken)); + DelayCommand(0.1, ExecuteScript("pi_henchmen", oPC)); + } + else if(sElem == "btn_clear_party") + { + SavedPartyCleared(oPC, nToken, sParty); + } + // ******************* Current Character buttons ********************* + // Show current party member. + else if(sElem == "btn_cur_char") + { + string sIndex = IntToString(nIndex); + SetHenchmanDbString(oPC, "image", sIndex, sParty); + AddCurrentCharacterInfo(oPC, nToken, sParty); + } + // The edit button, for now we are using it to level up! + else if(sElem == "btn_cur_edit") + { + object oHenchman = GetSelectedHenchman(oPC, sParty); + SetLocalObject(oPC, HENCHMAN_TO_EDIT, oHenchman); + CreateCharacterEditGUIPanel(oPC, oHenchman); + } + else if(sElem == "btn_cur_remove") + { + RemoveYourHenchman(oPC, nToken, sParty); + } + else if(sElem == "btn_remove_party") + { + RemoveWholeParty(oPC, nToken, sParty); + } + else if(sElem == "btn_cur_save") + { + SaveYourHenchman(oPC, nToken, sParty); + SetHenchmanDbString(oPC, "henchname", "0", sParty); + DelayCommand(0.0, NuiDestroy(oPC, nToken)); + DelayCommand(0.1, ExecuteScript("pi_henchmen", oPC)); + } + else if(sElem == "btn_save_party") + { + SaveWholeParty(oPC, nToken, sParty); + } + } + /*else if(sEvent == "watch") + { + if(sElem == "henchman_widget_check") + { + int bWidget = JsonGetInt(NuiGetBind(oPC, nToken, "henchman_widget_check")); + SetLocalInt(oPC, "AI_WIDGET_HENCHMAN", bWidget); + if(bWidget) PopupWidgetHenchmanGUIPanel(oPC); + else DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, "widgethenchmanwin"))); + } + if(sElem == "lock_henchman_widget_check") + { + int bBuffLockWidget = JsonGetInt(NuiGetBind(oPC, nToken, "lock_henchman_widget_check")); + SetLocalInt(oPC, "AI_WIDGET_HENCHMAN_LOCK", bBuffLockWidget); + SetLocalInt(oPC, "AI_WIDGET_HENCHMAN", TRUE); + NuiSetBind(oPC, nToken, "henchman_widget_check", JsonBool(TRUE)); + PopupWidgetHenchmanGUIPanel(oPC); + } + } + //************************************************************************** + // Spell Buffing. + else if (sWndId == "widget_henchman") + { + if (sEvent == "click") + { + string sParty; + if (sElem == "btn_one") sParty = "1"; + if (sElem == "btn_two") sParty = "2"; + if (sElem == "btn_three") sParty = "3"; + if (sElem == "btn_four") sParty = "4"; + SetHenchmanDbString (oPC, "henchname", sParty, "0"); + PopupWidgetHenchmanGUIPanel(oPC); + } + } */ + } + else if(sWndId == "henchman_edit_nui") + { + int nChange = 0; + int nID; + string sResRef, sID, sPlot; + object oHenchman = GetLocalObject(oPC, HENCHMAN_TO_EDIT); + if(sEvent == "watch") + { + if(sElem == "char_name") + { + string sName = JsonGetString(NuiGetBind(oPC, nToken, "char_name")); + SetName(oHenchman, sName); + } + if(sElem == "port_name") + { + if(GetLocalInt(oPC, "AI_PORTRAIT_ID_SET")) + { + DeleteLocalInt(oPC, "AI_PORTRAIT_ID_SET"); + //nID = JsonGetInt(NuiGetUserData(oPC, nToken)); + //SetPortraitId(oHenchman, nID); + } + else NuiSetUserData(oPC, nToken, JsonInt(-1)); + sResRef = JsonGetString (NuiGetBind(oPC, nToken, "port_name")); + if(ResManGetAliasFor(sResRef + "l", RESTYPE_TGA) == "" && + ResManGetAliasFor(sResRef + "l", RESTYPE_DDS) == "") + { + if(GetGender(oHenchman)) sResRef = "po_hu_f_99_"; + else sResRef = "po_hu_m_99_"; + } + NuiSetBind (oPC, nToken, "port_resref_image", JsonString (sResRef + "l")); + } + else if(sElem == "cmb_class_selected") + { + int nPosition = JsonGetInt(NuiGetBind(oPC, nToken, "opt_classes_value")) + 1; + int nSelection = JsonGetInt(NuiGetBind(oPC, nToken, "cmb_class_selected")); + int nClass = GetClassBySelection2DA(nSelection); + SetLocalInt(oHenchman, "CLASS_SELECTED_" + IntToString(nPosition), nClass); + DelayCommand(0.0, NuiDestroy(oPC, nToken)); + DelayCommand(0.1, CreateCharacterEditGUIPanel(oPC, oHenchman)); + } + else if(sElem == "cmb_package_selected") + { + int nPosition = JsonGetInt(NuiGetBind(oPC, nToken, "opt_classes_value")) + 1; + string sClass = IntToString(GetLocalInt(oHenchman, "CLASS_SELECTED_" + IntToString(nPosition))); + int nSelection = JsonGetInt(NuiGetBind(oPC, nToken, "cmb_package_selected")); + int nPackage = GetPackageBySelection2DA(sClass, nSelection); + SetLocalInt(oHenchman, "PACKAGE_SELECTED_" + IntToString(nPosition), nPackage); + } + else if(sElem == "cmb_soundset_selected") + { + int nSelection = JsonGetInt(NuiGetBind(oPC, nToken, "cmb_soundset_selected")); + int nSoundSet = GetSoundSetBySelection2DA(oHenchman, nSelection); + SetSoundset(oHenchman, nSoundSet); + string sResRef = GetStringLowerCase(Get2DAString("soundset", "RESREF", nSoundSet)); + if(GetStringLeft(sResRef, 4) == "vs_f") + { + DelayCommand(0.1, ai_HaveCreatureSpeak(oHenchman, 11, ":1:2:3:22:34:35:41:42:44:45:46:")); + } + else if(GetStringLeft(sResRef, 4) == "vs_n") + { + DelayCommand(0.1, ai_HaveCreatureSpeak(oHenchman, 10, ":1:2:3:34:35:36:40:42:44:45:")); + } + else + { + DelayCommand(0.1, ai_HaveCreatureSpeak(oHenchman, 7, ":1:2:3:11:12:13:33:")); + } + } + } + if(sEvent == "click") + { + if (sElem == "btn_desc_save") + { + string sDescription = JsonGetString(NuiGetBind(oPC, nToken, "desc_value")); + SetDescription(oHenchman, sDescription); + return; + } + else if(sElem == "btn_level_up") + { + int nPosition = JsonGetInt(NuiGetBind(oPC, nToken, "opt_classes_value")) + 1; + int nClass = GetClassByPosition(nPosition, oHenchman); + if(nClass == CLASS_TYPE_INVALID) + { + nClass = GetLocalInt(oHenchman, "CLASS_SELECTED_" + IntToString(nPosition)); + int nIndex = 1; + while(nIndex < 5) + { + if(nClass == GetClassByPosition(nIndex, oHenchman)) + { + ai_SendMessages(GetName(oHenchman) + " already has this class in a different slot! You can only level up this class in its original slot.", AI_COLOR_RED, oPC); + return; + } + nIndex++; + } + } + int nPackage = GetLocalInt(oHenchman, "PACKAGE_SELECTED_" + IntToString(nPosition)); + if(nPackage == 0) nPackage = GetPackageBySelection2DA(IntToString(nClass), 0); + else if(nPackage == -1) + { + ai_SendMessages("There is not a valid package for this class!", AI_COLOR_RED, oPC); + return; + } + string sLevel = IntToString(GetLevelByClass(nClass, oHenchman) + 1); + json jHenchman = ObjectToJson(oHenchman, TRUE); + //WriteTimestampedLogEntry("pe_henchmen, 318, jHenchman: " + JsonDump(jHenchman, 4)); + // Check to see if this character has a LvlStatList that is required to level. + json jLvlStatList = JsonObjectGet(jHenchman, "LvlStatList"); + //WriteTimestampedLogEntry("pe_henchmen, 321, jLvlStatList: " + JsonDump(jLvlStatList, 4)); + if(JsonGetType(jLvlStatList) == JSON_TYPE_NULL) + { + RemoveHenchman(oPC, oHenchman); + // Make sure to get a clean faction version of the henchman here. + jHenchman = ObjectToJson(oHenchman, TRUE); + jHenchman = CreateLevelStatList(jHenchman, oHenchman, oPC); + location lLocation = GetLocation(oHenchman); + int nFamiliar, nCompanion; + object oCompanion = GetAssociate(ASSOCIATE_TYPE_FAMILIAR, oHenchman); + if(oCompanion != OBJECT_INVALID) nFamiliar = TRUE; + oCompanion = GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION, oHenchman); + if(oCompanion != OBJECT_INVALID) nCompanion = TRUE; + AssignCommand(oHenchman, SetIsDestroyable(TRUE, FALSE, FALSE)); + DestroyObject(oHenchman); + oHenchman = ai_AddHenchman(oPC, jHenchman, lLocation, nFamiliar, nCompanion); + SetLocalObject(oPC, HENCHMAN_TO_EDIT, oHenchman); + // We need to move party button list index to the last one since + // the henchman will move to the last henchman slot. + int nIndex = 1; + object oHench = GetHenchman(oPC, nIndex); + while(oHench != OBJECT_INVALID) + { + oHench = GetHenchman(oPC, ++nIndex); + //SendMessageToPC(oPC, "oHench: " + GetName(oHench) + " nIndex: " + IntToString(nIndex)); + } + string sParty = GetHenchmanDbString(oPC, "henchname", "0"); + SetHenchmanDbString(oPC, "image", IntToString(nIndex - 1), sParty); + } + int nLeveled = LevelUpHenchman(oHenchman, nClass, TRUE, nPackage); + //SendMessageToPC(oPC, "pe_henchmen, 282, nClass: " + IntToString(nClass) + + // " nPackage: " + IntToString(nPackage) + " nPosition: " + IntToString(nPosition) + + // " nLeveled: " + IntToString(nLeveled)); + string sClass = GetStringByStrRef(StringToInt(Get2DAString("classes", "Name", nClass))); + if(!nLeveled) + { + //WriteTimestampedLogEntry("pe_henchmen, 306, jLvlStatList: " + JsonDump(jLvlStatList, 1)); + ai_SendMessages(GetName(oHenchman) + " could not level " + sClass + " to level " + sLevel + "!", AI_COLOR_RED, oPC); + } + else + { + ai_SendMessages(GetName(oHenchman) + " has leveled " + sClass + " to " + sLevel + " level!", AI_COLOR_GREEN, oPC); + ResetHenchmanWindows(oPC, nToken, oHenchman); + } + return; + } + else if(sElem == "btn_reset") + { + oHenchman = ResetCharacter(oPC, oHenchman); + SetLocalObject(oPC, HENCHMAN_TO_EDIT, oHenchman); + ai_SendMessages(GetName(oHenchman) + " has been reset to level 1!", AI_COLOR_GREEN, oPC); + // We need to move party button list index to the last one since + // the henchman will move to the last henchman slot. + int nIndex = 1; + object oHench = GetHenchman(oPC, nIndex); + while(oHench != OBJECT_INVALID) + { + oHench = GetHenchman(oPC, ++nIndex); + } + string sParty = GetHenchmanDbString(oPC, "henchname", "0"); + SetHenchmanDbString(oPC, "image", IntToString(nIndex - 1), sParty); + ResetHenchmanWindows(oPC, nToken, oHenchman); + } + else if(sElem == "btn_portrait_next") + { + nID = JsonGetInt(NuiGetUserData(oPC, nToken)) + 1; + nChange = 1; + } + else if(sElem == "btn_portrait_prev") + { + nID = JsonGetInt(NuiGetUserData(oPC, nToken)) - 1; + nChange = -1; + } + else if(sElem == "btn_portrait_ok") + { + nID = JsonGetInt(NuiGetUserData(oPC, nToken)); + if(nID != -1) SetPortraitId(oHenchman, nID); + else + { + sResRef = JsonGetString (NuiGetBind (oPC, nToken, "port_name")); + if(ResManGetAliasFor(sResRef + "l", RESTYPE_TGA) == "" && + ResManGetAliasFor(sResRef + "l", RESTYPE_DDS) == "") + { + if(GetGender(oHenchman)) sResRef = "po_hu_f_99_"; + else sResRef = "po_hu_m_99_"; + SetPortraitResRef(oHenchman, sResRef); + } + } + int nHenchToken = NuiFindWindow(oPC, "henchman_nui"); + if(nHenchToken) + { + string sImage = GetPortraitResRef(oHenchman); + NuiSetBind(oPC, nHenchToken, "img_cur_portrait_image", JsonString(sImage + "l")); + } + } + if (nChange != 0) + { + int nPRace, nPGender; + int nMax2DARow = Get2DARowCount("portraits") - 1; + if(nID > 5000) nID = 1; + if(nID < 0) nID = 5000; + int nGender = GetGender(oHenchman); + int nRace = GetRacialType(oHenchman); + string sPRace = Get2DAString("portraits", "Race", nID); + if(sPRace != "") nPRace = StringToInt(sPRace); + else nPRace = -1; + string sResRef, sPGender = Get2DAString("portraits", "Sex", nID); + if(sPGender != "") nPGender = StringToInt(sPGender); + else nPGender = -1; + //WriteTimestampedLogEntry("pe_henchmen, 367, nGender: " + IntToString(nGender) + + // " nPGender: " + IntToString(nPGender) + + // " nRace: " + IntToString(nRace) + " nPRace: " + IntToString(nPRace) + + // " nID: " + IntToString(nID)); + while((nRace != nPRace && + (nRace != RACIAL_TYPE_HALFELF || + (nPRace != RACIAL_TYPE_ELF || nPRace != RACIAL_TYPE_HUMAN))) || + nGender != nPGender && nPGender != 4) + { + nID += nChange; + //WriteTimestampedLogEntry("pe_henchmen, 382, nCounter: " + IntToString(nCounter) + + // " nMax2DARow: " + IntToString(nMax2DARow)); + if (nID > 5000) nID = 1; + if (nID < 1) nID = 5000; + sPRace = Get2DAString("portraits", "Race", nID); + if(sPRace != "") nPRace = StringToInt(sPRace); + else nPRace = -1; + sPGender = Get2DAString("portraits", "Sex", nID); + if(sPGender != "") nPGender = StringToInt(sPGender); + else nPGender = -1; + //WriteTimestampedLogEntry("pe_henchmen, 385, nGender: " + IntToString(nGender) + + // " nPGender: " + IntToString(nPGender) + " sPGender: " + sPGender + + // " nRace: " + IntToString(nRace) + " nPRace: " + IntToString(nPRace) + + // " sPRace: " + sPRace + " nID: " + IntToString(nID)); + sResRef = "po_" + Get2DAString("portraits", "BaseResRef", nID) + "l"; + if(ResManGetAliasFor(sResRef, RESTYPE_TGA) == "" && + ResManGetAliasFor(sResRef, RESTYPE_DDS) == "") nPRace = 99; + } + sResRef = "po_" + Get2DAString("portraits", "BaseResRef", nID); + NuiSetUserData(oPC, nToken, JsonInt (nID)); + // This is passed to the portrait name txt that actually sets + // the portrait information and tells it we picked an ID. + SetLocalInt(oPC, "AI_PORTRAIT_ID_SET", TRUE); + NuiSetBind(oPC, nToken, "port_name", JsonString (sResRef)); + } + } + if(sEvent == "mousedown") + { + int nMouseButton = JsonGetInt(JsonObjectGet(NuiGetEventPayload(), "mouse_btn")); + if (sElem == "opt_classes" && nMouseButton == NUI_MOUSE_BUTTON_LEFT) + { + int nPosition = JsonGetInt(NuiGetBind(oPC, nToken, "opt_classes_value")); + SetLocalInt(oHenchman, "CLASS_OPTION_POSITION", nPosition); + DelayCommand(0.0, NuiDestroy(oPC, nToken)); + DelayCommand(0.1, CreateCharacterEditGUIPanel(oPC, oHenchman)); + return; + } + if(nMouseButton == NUI_MOUSE_BUTTON_RIGHT) + { + if(sElem == "cmb_class") + { + int nPosition = JsonGetInt(NuiGetBind(oPC, nToken, "opt_classes_value")) + 1; + int nClass = GetLocalInt(oHenchman, "CLASS_SELECTED_" + IntToString(nPosition)); + string sName = GetStringByStrRef(StringToInt(Get2DAString("classes", "Name", nClass))); + string sDescription = GetStringByStrRef(StringToInt(Get2DAString("classes", "Description", nClass))); + string sIcon = Get2DAString("classes", "Icon", nClass); + CreateCharacterDescriptionNUI(oPC, sName, sIcon, sDescription); + } + else if(sElem == "cmb_package") + { + int nPosition = JsonGetInt(NuiGetBind(oPC, nToken, "opt_classes_value")) + 1; + int nClass = GetLocalInt(oHenchman, "CLASS_SELECTED_" + IntToString(nPosition)); + int nPackage = GetLocalInt(oHenchman, "PACKAGE_SELECTED_" + IntToString(nPosition)); + string sName = GetStringByStrRef(StringToInt(Get2DAString("packages", "Name", nPackage))); + string sDescription = GetStringByStrRef(StringToInt(Get2DAString("packages", "Description", nPackage))); + string sIcon = Get2DAString("classes", "Icon", nClass); + CreateCharacterDescriptionNUI(oPC, sName, sIcon, sDescription); + } + else if(sElem == "cmb_soundset") + { + int nSelection = JsonGetInt(NuiGetBind(oPC, nToken, "cmb_soundset_selected")); + int nSoundSet = GetSoundSetBySelection2DA(oHenchman, nSelection); + string sResRef = GetStringLowerCase(Get2DAString("soundset", "RESREF", nSoundSet)); + if(GetStringLeft(sResRef, 4) == "vs_f") + { + DelayCommand(0.1, ai_HaveCreatureSpeak(oHenchman, 11, ":1:2:3:22:34:35:41:42:44:45:46:")); + } + else if(GetStringLeft(sResRef, 4) == "vs_n") + { + DelayCommand(0.1, ai_HaveCreatureSpeak(oHenchman, 10, ":1:2:3:34:35:36:40:42:44:45:")); + } + else + { + DelayCommand(0.1, ai_HaveCreatureSpeak(oHenchman, 7, ":1:2:3:11:12:13:33:")); + } + } + else if(sElem == "opt_classes") + { + int nPosition = JsonGetInt(NuiGetBind(oPC, nToken, "opt_classes_value")) + 1; + int nClass = GetClassByPosition(nPosition, oHenchman); + if(nClass != CLASS_TYPE_INVALID) + { + string sName = GetStringByStrRef(StringToInt(Get2DAString("classes", "Name", nClass))); + string sDescription = GetStringByStrRef(StringToInt(Get2DAString("classes", "Description", nClass))); + int nPackage = GetLocalInt(oHenchman, "PACKAGE_SELECTED_" + IntToString(nPosition)); + string sPackageName = GetStringByStrRef(StringToInt(Get2DAString("packages", "Name", nPackage))); + sDescription += "\n\nPACKAGE: \n" + sPackageName + "\n"; + sDescription += GetStringByStrRef(StringToInt(Get2DAString("packages", "Description", nPackage))); + string sIcon = Get2DAString("classes", "Icon", nClass); + CreateCharacterDescriptionNUI(oPC, sName, sIcon, sDescription); + } + } + } + } + } + else if(sWndId == "char_description_nui") + { + if(sEvent == "click" && sElem == "btn_ok") DelayCommand(0.0, NuiDestroy(oPC, nToken)); + } + } +} +void PopupWidgetHenchmanGUIPanel(object oPC) +{ + // Set window to not save until it has been created. + SetLocalInt (oPC, "AI_NO_NUI_SAVE", TRUE); + DelayCommand (0.5f, DeleteLocalInt (oPC, "AI_NO_NUI_SAVE")); + // Row 1 (buttons)********************************************************** + json jRow = CreateButtonImage(JsonArray(), "ir_level1", "btn_one", 30.0f, 30.0f); + jRow = CreateButtonImage(jRow, "ir_level2", "btn_two", 30.0f, 30.0f); + jRow = CreateButtonImage(jRow, "ir_level3", "btn_three", 30.0f, 30.0f); + jRow = CreateButtonImage(jRow, "ir_level4", "btn_four", 30.0f, 30.0f); + // Add the row to the column. + json jCol = JsonArrayInsert(JsonArray(), NuiRow(jRow)); + int bAINPCWidgetLock = GetLocalInt(oPC, "AI_WIDGET_HENCHMAN_LOCK"); + // Get the window location to restore it from the database. + float fX = GetLocalFloat(oPC, "widget_henchman_X"); + float fY = GetLocalFloat(oPC, "widget_henchman_Y"); + if(fX == 0.0f && fY == 0.0f) + { + fX = 10.0f; + fY = 10.0f; + } + if(bAINPCWidgetLock) + { + fX = fX + 4.0f; + fY = fY + 45.0f; + } + // Set the layout of the window. + json jLayout = NuiCol (jCol); + int nToken; + if(bAINPCWidgetLock) nToken = SetWindow (oPC, jLayout, "widget_henchman", "Henchman Widget", fX, fY, 160.0, 62.0, FALSE, FALSE, FALSE, TRUE, FALSE, "pe_npc"); + else nToken = SetWindow (oPC, jLayout, "widget_henchman", "Henchman Widget", fX, fY, 160.0, 95.0, FALSE, FALSE, FALSE, TRUE, TRUE, "pe_npc"); + // Set event watches for window inspector and save window location. + NuiSetBindWatch (oPC, nToken, "collapsed", TRUE); + NuiSetBindWatch (oPC, nToken, "window_geometry", TRUE); + // Set the buttons to show events. + //NuiSetBind (oPC, nToken, "btn_one", JsonBool (TRUE)); + NuiSetBind (oPC, nToken, "btn_one_event", JsonBool (TRUE)); + NuiSetBind (oPC, nToken, "btn_two", JsonBool (TRUE)); + NuiSetBind (oPC, nToken, "btn_two_event", JsonBool (TRUE)); + NuiSetBind (oPC, nToken, "btn_three", JsonBool (TRUE)); + NuiSetBind (oPC, nToken, "btn_three_event", JsonBool (TRUE)); + NuiSetBind (oPC, nToken, "btn_four", JsonBool (TRUE)); + NuiSetBind (oPC, nToken, "btn_four_event", JsonBool (TRUE)); +} diff --git a/src/module/nss/pe_mod_set.nss b/src/module/nss/pe_mod_set.nss new file mode 100644 index 0000000..9c251b9 --- /dev/null +++ b/src/module/nss/pe_mod_set.nss @@ -0,0 +1,119 @@ +/*////////////////////////////////////////////////////////////////////////////// + Script Name: pe_mod_settings + Programmer: Philos +//////////////////////////////////////////////////////////////////////////////// + PEPS Plugin to set module and area settings. +/*////////////////////////////////////////////////////////////////////////////// +const string AI_MODULE_HEARTBEAT_SCRIPT = "AI_MODULE_HEARTBEAT_SCRIPT"; + +#include "0i_main" +void main() +{ + // Get the last player to use targeting mode + object oPC = GetLastPlayerToSelectTarget(); + string sTargetMode = GetLocalString(oPC, AI_TARGET_MODE); + if(oPC == OBJECT_SELF && sTargetMode != "") + { + // 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); + // If the user manually exited targeting mode without selecting a target, return + if(!GetIsObjectValid(oTarget) && vTarget == Vector()) + { + return; + } + // Targeting code here. + if(sTargetMode == "TEST_LEVEL_TARGET") + { + int nLevel = ai_GetCharacterLevels(oTarget); + int nXPNeeded = StringToInt(Get2DAString("exptable", "XP", nLevel)); + int nXPToGive = nXPNeeded - GetXP(oTarget); + GiveXPToCreature(oTarget, nXPToGive); + ai_SendMessages(GetName(oTarget) + " has gained " + IntToString(nXPToGive) + " experience to gain 1 level.", AI_COLOR_YELLOW, oPC); + } + else if(sTargetMode == "TEST_GOLD_TARGET") + { + GiveGoldToCreature(oTarget, 10000); + ai_SendMessages(GetName(oTarget) + " has gained 10,000 gold.", AI_COLOR_YELLOW, oPC); + } + else if(sTargetMode == "TEST_REST_TARGET") + { + ForceRest(oTarget); + ai_SendMessages(GetName(oTarget) + " has rested.", AI_COLOR_GREEN, oPC); + } + else if(sTargetMode == "TEST_HEAL_TARGET") + { + int nHeal = GetMaxHitPoints(oTarget) - GetCurrentHitPoints(oTarget); + if(nHeal > 0) + { + effect eHeal = EffectHeal(nHeal); + ApplyEffectToObject(DURATION_TYPE_INSTANT, eHeal, oTarget); + ai_SendMessages(GetName(oTarget) + " has been healed.", AI_COLOR_GREEN, oPC); + } + } + else if(sTargetMode == "TEST_ID_TARGET") SetIdentified(oTarget, !GetIdentified(oTarget)); + else if(sTargetMode == "TEST_CLEAR_TARGET") + { + ClearAllActions(TRUE, oTarget); + } + else if(sTargetMode == "TEST_KILL_TARGET") + { + effect eDmg = EffectDamage(10000); + ApplyEffectToObject(DURATION_TYPE_INSTANT, eDmg, oTarget); + ai_SendMessages(GetName(oTarget) + " has been killed.", AI_COLOR_RED, oPC); + } + else if(sTargetMode == "TEST_REMOVE_TARGET") + { + SetIsDestroyable(TRUE, FALSE, FALSE, oTarget); + DestroyObject(oTarget); + ai_SendMessages(GetName(oTarget) + " has been removed!", AI_COLOR_RED, oPC); + } + } + // Run all non-targeting code here, usually NUI events. + else + { + object oPC = NuiGetEventPlayer(); + int nToken = NuiGetEventWindow(); + string sEvent = NuiGetEventType(); + string sElem = NuiGetEventElement(); + int nIndex = NuiGetEventArrayIndex(); + //string sWndId = NuiGetWindowId(oPC, nToken); + //********************************************************************** + //if(GetLocalInt(oPC, AI_NO_NUI_SAVE)) return; + if(sEvent == "click") + { + if(sElem == "btn_combat_music_off") + { + object oArea = GetFirstArea(); + while(GetIsObjectValid(oArea)) + { + MusicBattleChange(oArea, 0); + oArea = GetNextArea(); + } + ai_SendMessages(GetModuleName() + " has had the combat music removed. Save your game or you may loose this change!", AI_COLOR_GREEN, oPC); + } + if(sElem == "btn_night_to_day") + { + object oModule = GetModule(); + string sScript = GetEventScript(oModule, EVENT_SCRIPT_MODULE_ON_HEARTBEAT); + if(sScript == "pc_mod_set") + { + sScript = GetLocalString(oPC, AI_MODULE_HEARTBEAT_SCRIPT); + SetEventScript(oModule, EVENT_SCRIPT_MODULE_ON_HEARTBEAT, sScript); + DeleteLocalString(oPC, AI_MODULE_HEARTBEAT_SCRIPT); + SendMessageToPC(oPC, "Module has been set to use normal time passage!"); + } + else + { + SetLocalString(oPC, AI_MODULE_HEARTBEAT_SCRIPT, sScript); + SetEventScript(oModule, EVENT_SCRIPT_MODULE_ON_HEARTBEAT, "pc_mod_set"); + SendMessageToPC(oPC, "Module has been set to pass through nighttime to make it morning!"); + } + } + } + } +} + + diff --git a/src/module/nss/pe_test.nss b/src/module/nss/pe_test.nss new file mode 100644 index 0000000..7fd799c --- /dev/null +++ b/src/module/nss/pe_test.nss @@ -0,0 +1,227 @@ +/*////////////////////////////////////////////////////////////////////////////// + Script Name: pe_test + Programmer: Philos +//////////////////////////////////////////////////////////////////////////////// + PEPS Plugin to help test errors. + Gives gold, Heals, etc. +/*////////////////////////////////////////////////////////////////////////////// +#include "0i_main" +void main() +{ + // Get the last player to use targeting mode + object oPC = GetLastPlayerToSelectTarget(); + string sTargetMode = GetLocalString(oPC, AI_TARGET_MODE); + if(oPC == OBJECT_SELF && sTargetMode != "") + { + // 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); + // If the user manually exited targeting mode without selecting a target, return + if(!GetIsObjectValid(oTarget) && vTarget == Vector()) + { + return; + } + // Targeting code here. + if(sTargetMode == "TEST_LEVEL_TARGET") + { + int nLevel = ai_GetCharacterLevels(oTarget); + int nXPNeeded = StringToInt(Get2DAString("exptable", "XP", nLevel)); + int nXPToGive = nXPNeeded - GetXP(oTarget); + GiveXPToCreature(oTarget, nXPToGive); + ai_SendMessages(GetName(oTarget) + " has gained " + IntToString(nXPToGive) + " experience to gain 1 level.", AI_COLOR_YELLOW, oPC); + } + else if(sTargetMode == "TEST_GOLD_TARGET") + { + GiveGoldToCreature(oTarget, 10000); + ai_SendMessages(GetName(oTarget) + " has gained 10,000 gold.", AI_COLOR_YELLOW, oPC); + } + else if(sTargetMode == "TEST_REST_TARGET") + { + ForceRest(oTarget); + ai_SendMessages(GetName(oTarget) + " has rested.", AI_COLOR_GREEN, oPC); + } + else if(sTargetMode == "TEST_HEAL_TARGET") + { + int nHeal = GetMaxHitPoints(oTarget) - GetCurrentHitPoints(oTarget); + if(nHeal > 0) + { + effect eHeal = EffectHeal(nHeal); + ApplyEffectToObject(DURATION_TYPE_INSTANT, eHeal, oTarget); + ai_SendMessages(GetName(oTarget) + " has been healed.", AI_COLOR_GREEN, oPC); + } + } + else if(sTargetMode == "TEST_ID_TARGET") SetIdentified(oTarget, !GetIdentified(oTarget)); + else if(sTargetMode == "TEST_CLEAR_TARGET") + { + ClearAllActions(TRUE, oTarget); + } + else if(sTargetMode == "TEST_KILL_TARGET") + { + effect eDmg = EffectDamage(10000); + ApplyEffectToObject(DURATION_TYPE_INSTANT, eDmg, oTarget); + ai_SendMessages(GetName(oTarget) + " has been killed.", AI_COLOR_RED, oPC); + // Set this variable on the player so PEPS can run the targeting script for this plugin. + SetLocalString(oPC, AI_PLUGIN_TARGET_SCRIPT, "pe_test"); + // Set Targeting variables. + SetLocalObject(oPC, AI_TARGET_ASSOCIATE, OBJECT_SELF); + SetLocalString(oPC, AI_TARGET_MODE, "TEST_KILL_TARGET"); + EnterTargetingMode(oPC, OBJECT_TYPE_CREATURE, MOUSECURSOR_KILL, MOUSECURSOR_NOKILL); + } + else if(sTargetMode == "TEST_REMOVE_TARGET") + { + SetIsDestroyable(TRUE, FALSE, FALSE, oTarget); + DestroyObject(oTarget); + ai_SendMessages(GetName(oTarget) + " has been removed!", AI_COLOR_RED, oPC); + } + else if(sTargetMode == "TEST_JUMP") + { + JumpToLocation(lLocation); + int nIndex; + object oAssociate; + for(nIndex = 2; nIndex < 6; nIndex++) + { + oAssociate = GetAssociate(nIndex, oPC); + if(oAssociate != OBJECT_INVALID) AssignCommand(oAssociate, JumpToLocation(lLocation)); + } + for(nIndex = 1; nIndex < AI_MAX_HENCHMAN; nIndex++) + { + oAssociate = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex); + if(oAssociate != OBJECT_INVALID) AssignCommand(oAssociate, JumpToLocation(lLocation)); + } + // Set this variable on the player so PEPS can run the targeting script for this plugin. + SetLocalString(oPC, AI_PLUGIN_TARGET_SCRIPT, "pe_test"); + // Set Targeting variables. + SetLocalObject(oPC, AI_TARGET_ASSOCIATE, OBJECT_SELF); + SetLocalString(oPC, AI_TARGET_MODE, "TEST_JUMP"); + EnterTargetingMode(oPC, OBJECT_TYPE_TILE, MOUSECURSOR_TRANSITION, MOUSECURSOR_NOWALK); + } + else if(sTargetMode == "TEST_KILL_AREA") + { + effect eDmg = EffectDamage(10000); + object oKill = GetFirstObjectInShape(SHAPE_SPHERE, 6.67, lLocation, FALSE); + while(oKill != OBJECT_INVALID) + { + ApplyEffectToObject(DURATION_TYPE_INSTANT, eDmg, oKill); + oKill = GetNextObjectInShape(SHAPE_SPHERE, 6.67, lLocation, FALSE); + } + } + } + // Run all non-targeting code here, usually NUI events. + else + { + object oPC = NuiGetEventPlayer(); + int nToken = NuiGetEventWindow(); + string sEvent = NuiGetEventType(); + string sElem = NuiGetEventElement(); + int nIndex = NuiGetEventArrayIndex(); + //string sWndId = NuiGetWindowId(oPC, nToken); + //********************************************************************** + //if(GetLocalInt(oPC, AI_NO_NUI_SAVE)) return; + if(sEvent == "click") + { + if(sElem == "btn_level") + { + // Set this variable on the player so PEPS can run the targeting script for this plugin. + SetLocalString(oPC, AI_PLUGIN_TARGET_SCRIPT, "pe_test"); + // Set Targeting variables. + SetLocalObject(oPC, AI_TARGET_ASSOCIATE, OBJECT_SELF); + SetLocalString(oPC, AI_TARGET_MODE, "TEST_LEVEL_TARGET"); + EnterTargetingMode(oPC, OBJECT_TYPE_CREATURE , MOUSECURSOR_EXAMINE, MOUSECURSOR_NOEXAMINE); + } + else if(sElem == "btn_gold") + { + // Set this variable on the player so PEPS can run the targeting script for this plugin. + SetLocalString(oPC, AI_PLUGIN_TARGET_SCRIPT, "pe_test"); + // Set Targeting variables. + SetLocalObject(oPC, AI_TARGET_ASSOCIATE, OBJECT_SELF); + SetLocalString(oPC, AI_TARGET_MODE, "TEST_GOLD_TARGET"); + EnterTargetingMode(oPC, OBJECT_TYPE_CREATURE , MOUSECURSOR_CREATE, MOUSECURSOR_NOCREATE); + } + else if(sElem == "btn_rest") + { + // Set this variable on the player so PEPS can run the targeting script for this plugin. + SetLocalString(oPC, AI_PLUGIN_TARGET_SCRIPT, "pe_test"); + // Set Targeting variables. + SetLocalObject(oPC, AI_TARGET_ASSOCIATE, OBJECT_SELF); + SetLocalString(oPC, AI_TARGET_MODE, "TEST_REST_TARGET"); + EnterTargetingMode(oPC, OBJECT_TYPE_CREATURE , MOUSECURSOR_EXAMINE, MOUSECURSOR_NOEXAMINE); + } + else if(sElem == "btn_heal") + { + // Set this variable on the player so PEPS can run the targeting script for this plugin. + SetLocalString(oPC, AI_PLUGIN_TARGET_SCRIPT, "pe_test"); + // Set Targeting variables. + SetLocalObject(oPC, AI_TARGET_ASSOCIATE, OBJECT_SELF); + SetLocalString(oPC, AI_TARGET_MODE, "TEST_HEAL_TARGET"); + EnterTargetingMode(oPC, OBJECT_TYPE_CREATURE, MOUSECURSOR_HEAL, MOUSECURSOR_NOHEAL); + } + else if(sElem == "btn_id_item") + { + // Set this variable on the player so PEPS can run the targeting script for this plugin. + SetLocalString(oPC, AI_PLUGIN_TARGET_SCRIPT, "pe_test"); + // Set Targeting variables. + SetLocalObject(oPC, AI_TARGET_ASSOCIATE, OBJECT_SELF); + SetLocalString(oPC, AI_TARGET_MODE, "TEST_ID_TARGET"); + EnterTargetingMode(oPC, OBJECT_TYPE_ITEM, MOUSECURSOR_HEAL, MOUSECURSOR_NOHEAL); + } + else if(sElem == "btn_clear") + { + // Set this variable on the player so PEPS can run the targeting script for this plugin. + SetLocalString(oPC, AI_PLUGIN_TARGET_SCRIPT, "pe_test"); + // Set Targeting variables. + SetLocalObject(oPC, AI_TARGET_ASSOCIATE, OBJECT_SELF); + SetLocalString(oPC, AI_TARGET_MODE, "TEST_CLEAR_TARGET"); + EnterTargetingMode(oPC, OBJECT_TYPE_CREATURE, MOUSECURSOR_MAGIC, MOUSECURSOR_NOMAGIC); + } + else if(sElem == "btn_kill") + { + // Set this variable on the player so PEPS can run the targeting script for this plugin. + SetLocalString(oPC, AI_PLUGIN_TARGET_SCRIPT, "pe_test"); + // Set Targeting variables. + SetLocalObject(oPC, AI_TARGET_ASSOCIATE, OBJECT_SELF); + SetLocalString(oPC, AI_TARGET_MODE, "TEST_KILL_TARGET"); + EnterTargetingMode(oPC, OBJECT_TYPE_CREATURE, MOUSECURSOR_KILL, MOUSECURSOR_NOKILL); + } + else if(sElem == "btn_remove") + { + // Set this variable on the player so PEPS can run the targeting script for this plugin. + SetLocalString(oPC, AI_PLUGIN_TARGET_SCRIPT, "pe_test"); + // Set Targeting variables. + SetLocalObject(oPC, AI_TARGET_ASSOCIATE, OBJECT_SELF); + SetLocalString(oPC, AI_TARGET_MODE, "TEST_REMOVE_TARGET"); + EnterTargetingMode(oPC, OBJECT_TYPE_CREATURE | + OBJECT_TYPE_DOOR | OBJECT_TYPE_ITEM | + OBJECT_TYPE_PLACEABLE, MOUSECURSOR_KILL, MOUSECURSOR_NOKILL); + } + else if(sElem == "btn_jump") + { + // Set this variable on the player so PEPS can run the targeting script for this plugin. + SetLocalString(oPC, AI_PLUGIN_TARGET_SCRIPT, "pe_test"); + // Set Targeting variables. + SetLocalObject(oPC, AI_TARGET_ASSOCIATE, OBJECT_SELF); + SetLocalString(oPC, AI_TARGET_MODE, "TEST_JUMP"); + EnterTargetingMode(oPC, OBJECT_TYPE_TILE, MOUSECURSOR_TRANSITION, MOUSECURSOR_NOWALK); + } + else if(sElem == "btn_kill_area") + { + // Set this variable on the player so PEPS can run the targeting script for this plugin. + SetLocalString(oPC, AI_PLUGIN_TARGET_SCRIPT, "pe_test"); + // Set Targeting variables. + SetLocalObject(oPC, AI_TARGET_ASSOCIATE, OBJECT_SELF); + SetLocalString(oPC, AI_TARGET_MODE, "TEST_KILL_AREA"); + SetEnterTargetingModeData(oPC, SPELL_TARGETING_SHAPE_SPHERE, 6.67, 0.0, 3); + EnterTargetingMode(oPC, OBJECT_TYPE_ALL, MOUSECURSOR_KILL, MOUSECURSOR_NOKILL); + } + } + else if(sEvent == "watch") + { + if(sElem == "txt_debug_creature") + { + } + } + } +} + + diff --git a/src/module/nss/pi_buffing.nss b/src/module/nss/pi_buffing.nss new file mode 100644 index 0000000..6ce454e --- /dev/null +++ b/src/module/nss/pi_buffing.nss @@ -0,0 +1,338 @@ +/*////////////////////////////////////////////////////////////////////////////// +// Script Name: pi_buffing +//////////////////////////////////////////////////////////////////////////////// + Executable plug in script for Philos Module Extentions. + + Database structure: + Name(string) Tag(String) Spells(Json) + Tag: Widget - 0 = x position, 1 = y position, 2 = On/Off, 3 = Locked + Tag: List (string) set to the list number selected 1,2,3, or 4. + Tag: List# is the list of spells for List number 1,2,3, or 4. + + UI to save a players buff spells to be cast after resting. +*/////////////////////////////////////////////////////////////////////////////// +#include "0i_nui" +const int BUFF_MAX_SPELLS = 50; +const string FB_NO_MONSTER_CHECK = "FB_NO_MONSTER_CHECK"; + +// Does startup check if the game has just been loaded. +int StartingUp(object oPC); +// Creates the table and initializes if it needs to. +void CheckBuffDataAndInitialize(object oPlayer, string sTag); +// sDataField should be one of the data fields for that table. +// sData is the string data to be saved. +void SetBuffDatabaseString(object oPlayer, string sDataField, string sData, string sTag); +// sDataField should be one of the data fields for the table. +// Returns a string of the data stored. +string GetBuffDatabaseString(object oPlayer, string sDataField, string sTag); +// sDataField should be one of the data fields for that table. +// jData is the json data to be saved. +void SetBuffDatabaseJson(object oPlayer, string sDataField, json jData, string sTag); +// sDataField should be one of the data fields for the table. +// Returns a string of the data stored. +json GetBuffDatabaseJson(object oPlayer, string sDataField, string sTag); +// Creates the widget for buffing. +void PopupWidgetBuffGUIPanel(object oPC); + +void main() +{ + object oPC = OBJECT_SELF; + // Check to make sure the database is setup before we do anything. + CheckBuffDataAndInitialize(oPC, "menudata"); + json jMenuData = GetBuffDatabaseJson(oPC, "spells", "menudata"); + if(JsonGetType(JsonArrayGet(jMenuData, 0)) == JSON_TYPE_NULL) + { + jMenuData = JsonArrayInsert(JsonArray(), JsonString("list1")); // 0 Spell List # + jMenuData = JsonArrayInsert(jMenuData, JsonFloat(0.0)); // 1 Main menu X pos. + jMenuData = JsonArrayInsert(jMenuData, JsonFloat(GetGUIHeightMiddle(oPC, 257.0))); // 2 Main menu Y pos. + jMenuData = JsonArrayInsert(jMenuData, JsonBool(FALSE)); // 3 Widget on/off + jMenuData = JsonArrayInsert(jMenuData, JsonBool(FALSE)); // 4 Widget Locked + jMenuData = JsonArrayInsert(jMenuData, JsonFloat(10.0)); // 5 Widget X pos. + jMenuData = JsonArrayInsert(jMenuData, JsonFloat(10.0)); // 6 Widget Y pos. + SetBuffDatabaseJson(oPC, "spells", jMenuData, "menudata"); + } + if(StartingUp(oPC)) return; + // Row 1 (Buttons) ********************************************************* 83 + json jRow = CreateButtonSelect(JsonArray(), "Save", "btn_save", 60.0f, 30.0f, "btn_save_tooltip"); + CreateButton(jRow, "Clear", "btn_clear", 60.0f, 30.0f, -1.0, "btn_clear_tooltip"); + CreateButton(jRow, "Buff", "btn_buff", 60.0f, 30.0f, -1.0, "btn_buff_tooltip"); + CreateButtonSelect(jRow, "List 1", "btn_list1", 60.0f, 30.0f); + CreateButtonSelect(jRow, "List 2", "btn_list2", 60.0f, 30.0f); + CreateButtonSelect(jRow, "List 3", "btn_list3", 60.0f, 30.0f); + CreateButtonSelect(jRow, "List 4", "btn_list4", 60.0f, 30.0f); + // Add the row to the column. + json jCol = JsonArrayInsert(JsonArray(), NuiRow(jRow)); + // Row 2 (Buttons) ********************************************************* 121 + jRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + jRow = CreateCheckBox(jRow, "Buff Widget", "buff_widget", 110.0, 30.0f, "buff_widget_tooltip"); + jRow = CreateCheckBox(jRow, "Lock Widget", "lock_buff_widget", 110.0, 30.0f, "lock_buff_widget_tooltip"); + if(!AI_SERVER) + { + jRow = CreateCheckBox(jRow, "Don't Check for Monsters", "chbx_no_monster_check", 200.0, 30.0f, "chbx_no_monster_check_tooltip"); + } + jRow = JsonArrayInsert(jRow, NuiSpacer()); + // Add the row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 4 (List of Spells) ************************************************** 164 + // Create the button template for the List. + jRow = JsonArray(); + string sList = JsonGetString(JsonArrayGet(jMenuData, 0)); + int nCntr, nIndex; + string sCntr, sIndex; + json jSpell; + CheckBuffDataAndInitialize(oPC, sList); + json jSpells = GetBuffDatabaseJson(oPC, "spells", sList); + while(nCntr <= BUFF_MAX_SPELLS) + { + jSpell = JsonArrayGet(jSpells, nCntr); + if(JsonGetType(jSpell) != JSON_TYPE_NULL) + { + sIndex = IntToString(nIndex++); + jRow = CreateButtonImage(jRow, "", "btn_spell_" + sIndex, 35.0, 35.0, 0.0, "btn_spell_" + sIndex + "_tooltip"); + } + nCntr++; + } + // Add the row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Get the window location to restore it from the database. + float fWidth = IntToFloat(nIndex) * 39; + if(fWidth < 470.0) fWidth = 470.0; + float fX = JsonGetFloat(JsonArrayGet(jMenuData, 1)); + float fY = JsonGetFloat(JsonArrayGet(jMenuData, 2)); + if(fX == 0.0f && fY == 0.0f) + { + fX = 0.0f; + fY = GetGUIHeightMiddle(oPC, 257.0); + } + // Set the layout of the window. + json jLayout = NuiCol(jCol); + int nToken = SetWindow(oPC, jLayout, "plbuffwin", "Fast Buffing Spells", + fX, fY, fWidth, 164.0, FALSE, FALSE, TRUE, FALSE, TRUE, "pe_buffing"); + // Set the elements to show events. + int nSelected = GetEventScript(oPC, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT) == "pc_savebuffs"; + NuiSetBind(oPC, nToken, "btn_save", JsonBool(nSelected)); + NuiSetBind(oPC, nToken, "btn_save_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_save_tooltip", JsonString(" Saves any spells cast on you or your associates.")); + NuiSetBind(oPC, nToken, "btn_clear", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_clear_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "btn_clear_tooltip", JsonString(" Clears the current list of all saved spells.")); + NuiSetBind(oPC, nToken, "btn_buff", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_buff_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_buff_tooltip", JsonString(" Casts the current list of saved spells.")); + if(sList == "list1") NuiSetBind (oPC, nToken, "btn_list1", JsonBool (TRUE)); + else NuiSetBind(oPC, nToken, "btn_list1", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_list1_event", JsonBool(TRUE)); + if(sList == "list2") NuiSetBind (oPC, nToken, "btn_list2", JsonBool (TRUE)); + else NuiSetBind(oPC, nToken, "btn_list2", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_list2_event", JsonBool(TRUE)); + if(sList == "list3") NuiSetBind (oPC, nToken, "btn_list3", JsonBool (TRUE)); + else NuiSetBind(oPC, nToken, "btn_list3", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_list3_event", JsonBool(TRUE)); + if(sList == "list4") NuiSetBind (oPC, nToken, "btn_list4", JsonBool (TRUE)); + else NuiSetBind (oPC, nToken, "btn_list4", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_list4_event", JsonBool(TRUE)); + int nValue = JsonGetInt(JsonArrayGet(jMenuData, 3)); + NuiSetBind(oPC, nToken, "buff_widget_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "buff_widget_check", JsonBool(nValue)); + NuiSetBindWatch(oPC, nToken, "buff_widget_check", TRUE); + string sText = " Creates a set of 4 buttons on the screen for quick buffing."; + NuiSetBind(oPC, nToken, "buff_widget_tooltip", JsonString(sText)); + nValue = JsonGetInt(JsonArrayGet(jMenuData, 4)); + NuiSetBind(oPC, nToken, "lock_buff_widget_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "lock_buff_widget_check", JsonBool(nValue)); + NuiSetBindWatch(oPC, nToken, "lock_buff_widget_check", TRUE); + sText = " Locks the buffing widget in place reducing its size."; + NuiSetBind(oPC, nToken, "lock_buff_widget_tooltip", JsonString(sText)); + if(!AI_SERVER) + { + NuiSetBind(oPC, nToken, "chbx_no_monster_check_event", JsonBool(TRUE)); + nValue = GetLocalInt(oPC, FB_NO_MONSTER_CHECK); + NuiSetBind(oPC, nToken, "chbx_no_monster_check_check", JsonBool(nValue)); + NuiSetBindWatch(oPC, nToken, "chbx_no_monster_check_check", TRUE); + sText = " Turns on/off checks for nearby monsters."; + NuiSetBind(oPC, nToken, "chbx_no_monster_check_tooltip", JsonString(sText)); + } + // Create buttons with spells listed. + int nSpell, nClass, nLevel, nMetamagic, nDomain; + string sName, sTargetName, sResRef; + nCntr = 0; + nIndex = 0; + while(nCntr <= BUFF_MAX_SPELLS) + { + jSpell = JsonArrayGet(jSpells, nCntr); + if(JsonGetType(jSpell) != JSON_TYPE_NULL) + { + nSpell = JsonGetInt(JsonArrayGet(jSpell, 0)); + nClass = JsonGetInt(JsonArrayGet(jSpell, 1)); + nLevel = JsonGetInt(JsonArrayGet(jSpell, 2)); + nMetamagic = JsonGetInt(JsonArrayGet(jSpell, 3)); + nDomain = JsonGetInt(JsonArrayGet(jSpell, 4)); + sTargetName = JsonGetString(JsonArrayGet(jSpell, 5)); + sResRef = Get2DAString("spells", "IconResRef", nSpell); + sName = " " + GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); + sName += " (" + GetStringByStrRef(StringToInt(Get2DAString("classes", "Short", nClass))); + sName += " / " + IntToString (nLevel); + if(nMetamagic > 0) + { + if(nMetamagic == METAMAGIC_EMPOWER) sName += " / Empowered"; + else if(nMetamagic == METAMAGIC_EXTEND) sName += " / Extended"; + else if(nMetamagic == METAMAGIC_MAXIMIZE) sName += " / Maximized"; + else if(nMetamagic == METAMAGIC_QUICKEN) sName += " / Quickened"; + else if(nMetamagic == METAMAGIC_SILENT) sName += " / Silent"; + else if(nMetamagic == METAMAGIC_STILL) sName += " / Still"; + } + if(nDomain > 0) sName += " / Domain"; + sName += ") " + sTargetName; + sIndex = IntToString(nIndex++); + NuiSetBind(oPC, nToken, "btn_spell_" + sIndex + "_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_spell_" + sIndex + "_image", JsonString(sResRef)); + NuiSetBind(oPC, nToken, "btn_spell_" + sIndex + "_tooltip", JsonString(sName)); + } + nCntr++; + } + NuiSetBindWatch(oPC, nToken, "window_geometry", TRUE); +} +int StartingUp(object oPC) +{ + if(GetLocalInt(oPC, AI_ADD_PLUGIN)) + { + json jPlugin = JsonArray(); + jPlugin = JsonArrayInsert(jPlugin, JsonString("pi_buffing")); + jPlugin = JsonArrayInsert(jPlugin, JsonInt(FALSE)); + jPlugin = JsonArrayInsert(jPlugin, JsonString("Quick Buff")); + jPlugin = JsonArrayInsert(jPlugin, JsonString("dm_appear")); + json jPlugins = GetLocalJson(oPC, AI_JSON_PLUGINS); + jPlugins = JsonArrayInsert(jPlugins, jPlugin); + SetLocalJson(oPC, AI_JSON_PLUGINS, jPlugin); + SetLocalInt(oPC, AI_PLUGIN_SET, TRUE); + return TRUE; + } + if(!GetLocalInt(oPC, AI_STARTING_UP)) return FALSE; + json jMenuData = GetBuffDatabaseJson(oPC, "spells", "menudata"); + int bWidgetOn = JsonGetInt(JsonArrayGet(jMenuData, 3)); + if(bWidgetOn) + { + PopupWidgetBuffGUIPanel(oPC); + ai_SendMessages("Buffing widget has been created.", AI_COLOR_YELLOW, oPC); + } + return TRUE; +} +void CreateBuffDataTable(object oPlayer) +{ + sqlquery sql = SqlPrepareQueryObject(oPlayer, + "CREATE TABLE IF NOT EXISTS BUFF_TABLE (" + + "name TEXT, " + + "tag TEXT, " + + "spells TEXT, " + + "PRIMARY KEY(name, tag));"); + SqlStep(sql); +} +void CheckBuffDataAndInitialize(object oPlayer, string sTag) +{ + string sName = ai_RemoveIllegalCharacters(ai_StripColorCodes(GetName(oPlayer, TRUE))); + string sQuery = "SELECT name FROM sqlite_master WHERE type ='table' AND name=@tableName;"; + sqlquery sql = SqlPrepareQueryObject(oPlayer, sQuery); + SqlBindString (sql, "@tableName", "BUFF_TABLE"); + if(!SqlStep (sql)) CreateBuffDataTable(oPlayer); + sQuery = "SELECT name FROM BUFF_TABLE Where name = @name AND tag = @tag;"; + sql = SqlPrepareQueryObject(oPlayer, sQuery); + SqlBindString(sql, "@name", sName); + SqlBindString(sql, "@tag", sTag); + if(!SqlStep(sql)) + { + sQuery = "INSERT INTO BUFF_TABLE(name, tag, spells) " + + "VALUES (@name, @tag, @spells);"; + sql = SqlPrepareQueryObject(oPlayer, sQuery); + SqlBindString(sql, "@name", sName); + SqlBindString(sql, "@tag", sTag); + SqlBindJson(sql, "@spells", JsonArray()); + SqlStep(sql); + } +} +void SetBuffDatabaseString(object oPlayer, string sDataField, string sData, string sTag) +{ + string sName = ai_RemoveIllegalCharacters(ai_StripColorCodes(GetName(oPlayer, TRUE))); + string sQuery = "UPDATE BUFF_TABLE SET " + sDataField + " = @data WHERE name = @name AND tag = @tag;"; + sqlquery sql = SqlPrepareQueryObject(oPlayer, sQuery); + SqlBindString(sql, "@data", sData); + SqlBindString(sql, "@name", sName); + SqlBindString(sql, "@tag", sTag); + SqlStep(sql); +} +string GetBuffDatabaseString(object oPlayer, string sDataField, string sTag) +{ + string sName = ai_RemoveIllegalCharacters(ai_StripColorCodes(GetName(oPlayer, TRUE))); + string sQuery = "SELECT " + sDataField + " FROM BUFF_TABLE WHERE name = @name AND tag = @tag;"; + sqlquery sql = SqlPrepareQueryObject(oPlayer, sQuery); + SqlBindString(sql, "@name", sName); + SqlBindString(sql, "@tag", sTag); + if(SqlStep(sql)) return SqlGetString(sql, 0); + else return ""; +} +void SetBuffDatabaseJson (object oPlayer, string sDataField, json jData, string sTag) +{ + string sName = ai_RemoveIllegalCharacters(ai_StripColorCodes(GetName(oPlayer, TRUE))); + string sQuery = "UPDATE BUFF_TABLE SET " + sDataField + " = @data WHERE name = @name AND tag = @tag;"; + sqlquery sql = SqlPrepareQueryObject(oPlayer, sQuery); + SqlBindJson(sql, "@data", jData); + SqlBindString(sql, "@name", sName); + SqlBindString(sql, "@tag", sTag); + SqlStep(sql); +} +json GetBuffDatabaseJson(object oPlayer, string sDataField, string sTag) +{ + string sName = ai_RemoveIllegalCharacters(ai_StripColorCodes(GetName(oPlayer, TRUE))); + string sQuery = "SELECT " + sDataField + " FROM BUFF_TABLE WHERE name = @name AND tag = @tag;"; + sqlquery sql = SqlPrepareQueryObject(oPlayer, sQuery); + SqlBindString(sql, "@name", sName); + SqlBindString(sql, "@tag", sTag); + if(SqlStep(sql)) return SqlGetJson(sql, 0); + else return JsonArray(); +} +void PopupWidgetBuffGUIPanel(object oPC) +{ + // Set window to not save until it has been created. + SetLocalInt(oPC, AI_NO_NUI_SAVE, TRUE); + DelayCommand(0.5f, DeleteLocalInt (oPC, AI_NO_NUI_SAVE)); + // Row 1 (buttons)********************************************************** + json jRow = JsonArray(); + CreateButtonImage(jRow, "ir_level1", "btn_one", 35.0f, 35.0f, 0.0); + CreateButtonImage(jRow, "ir_level2", "btn_two", 35.0f, 35.0f, 0.0); + CreateButtonImage(jRow, "ir_level3", "btn_three", 35.0f, 35.0f, 0.0); + CreateButtonImage(jRow, "ir_level4", "btn_four", 35.0f, 35.0f, 0.0); + // Add the row to the column. + json jCol = JsonArrayInsert(JsonArray(), NuiRow(jRow)); + json jWidget = GetBuffDatabaseJson(oPC, "spells", "menudata"); + int bAIBuffWidgetLock = JsonGetInt(JsonArrayGet(jWidget, 4)); + // Get the window location to restore it from the database. + float fX = JsonGetFloat(JsonArrayGet(jWidget, 5)); + float fY = JsonGetFloat(JsonArrayGet(jWidget, 6)); + if(fX == 0.0f && fY == 0.0f) + { + fX = 10.0f; + fY = 10.0f; + } + if(bAIBuffWidgetLock) + { + fX = fX + 4.0f; + fY = fY + 45.0f; + } + // Set the layout of the window. + json jLayout = NuiCol (jCol); + int nToken; + if(bAIBuffWidgetLock) nToken = SetWindow(oPC, jLayout, "widgetbuffwin", "Fast Buff Widget", fX, fY, 160.0, 62.0, FALSE, FALSE, FALSE, TRUE, FALSE, "pe_buffing"); + else nToken = SetWindow(oPC, jLayout, "widgetbuffwin", "Fast Buff Widget", fX, fY, 160.0, 95.0, FALSE, FALSE, FALSE, TRUE, TRUE, "pe_buffing"); + // Set event watches for window inspector and save window location. + //NuiSetBindWatch(oPC, nToken, "collapsed", TRUE); + NuiSetBindWatch(oPC, nToken, "window_geometry", TRUE); + // Set the buttons to show events. + //NuiSetBind (oPC, nToken, "btn_one", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "btn_one_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_two", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_two_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_three", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_three_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_four", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_four_event", JsonBool(TRUE)); +} + diff --git a/src/module/nss/pi_crafting.nss b/src/module/nss/pi_crafting.nss new file mode 100644 index 0000000..3fa9775 --- /dev/null +++ b/src/module/nss/pi_crafting.nss @@ -0,0 +1,717 @@ +/*////////////////////////////////////////////////////////////////////////////// +// Script Name: pi_crafting +//////////////////////////////////////////////////////////////////////////////// + Executable plug in script for Philos Module Extentions + + Crafting UI for players items. +*/////////////////////////////////////////////////////////////////////////////// +#include "0i_nui" +#include "0i_items" +#include "nw_inc_gff" +const string CRAFT_JSON = "CRAFT_JSON"; +const string CRAFT_COOL_DOWN = "CRAFT_COOL_DOWN"; +const string CRAFT_ITEM_SELECTION = "CRAFT_ITEM_SELECTION"; +const string CRAFT_MATERIAL_SELECTION = "CRAFT_MATERIAL_SELECTION"; +const string CRAFT_MODEL_SELECTION = "CRAFT_MODEL_SELECTION"; +const string CRAFT_COLOR_PALLET = "CRAFT_COLOR_PALLET"; +const string CRAFT_LEFT_PART_COLOR = "CRAFT_LEFT_PART_COLOR"; +const string CRAFT_ALL_COLOR = "CRAFT_ALL_COLOR"; +const string CRAFT_RIGHT_PART_COLOR = "CRAFT_RIGHT_PART_COLOR"; +const string CRAFT_TARGET = "CRAFT_TARGET"; +// Tag used in lighting effects. +const string CRAFT_HIGHLIGHT = "CRAFT_HIGHLIGHT"; +const string CRAFT_ULTRALIGHT = "CRAFT_ULTRALIGHT"; + +json CreateItemCombo(object oPC, json jRow, string sComboBind); +json CreateModelCombo(object oPC, object oTarget, json jRow, string sComboBind); +json CreateMaterialCombo(object oPC, json jRow, string sComboBind); +// Sets the material buttons for use. +// nMaterial 0,1 Cloth 2,3 Leather 4,5 Metal -1 None. +void SetMaterialButtons(object oPC, int nToken, int nMaterial); +// Returns the correct item based on the crafting menu selected item. +object GetSelectedItem(object oTarget, int nItemSelected); +int GetArmorModelSelected(object oPC); +// Returns True if oItem, nPart has a per part color for sSide. +int GetHasPartColor(object oItem, int nPart, string sSide); +// Does startup check if the game has just been loaded. +int StartingUp(object oPC); +void main() +{ + object oPC = OBJECT_SELF; + object oTarget = GetLocalObject(oPC, CRAFT_TARGET); + if(oTarget == OBJECT_INVALID) oTarget = oPC; + if(StartingUp(oPC)) return; + json jCraft = GetLocalJson(oPC, CRAFT_JSON); + // Row 1 (Object Name)****************************************************** 508 / 83 + json jRow = CreateTextEditBox(JsonArray(), "plc_hold_bind", "txt_item_name", 50, FALSE, 486.0f, 30.0f); // 419 + json jCol = JsonArrayInsert(JsonArray(), NuiRow(jRow)); + // Row 2 (Object Name)****************************************************** 508 / 121 + jRow = JsonArray(); + if(!AI_SERVER) jRow = CreateButton(jRow, "Information", "btn_info", 160.0f, 30.0f, -1.0, "btn_info_tooltip"); + else + { + if(GetIsDM(oTarget)) + { + jRow = CreateButton(jRow, "Information", "btn_info", 160.0f, 30.0f, -1.0, "btn_info_tooltip"); + } + else jRow = JsonArrayInsert(jRow, NuiSpacer()); + } + jRow = CreateButton(jRow, "Wardrobe", "btn_wardrobe", 158.0f, 30.0f, -1.0, "btn_wardrobe_tooltip"); + jRow = CreateButtonSelect(jRow, "Add Light", "btn_highlight", 160.0f, 30.0f, "btn_highlight_tooltip"); + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 3 (Object Name)****************************************************** 508 / 159 + jRow = CreateButton(JsonArray(), "Save", "btn_save", 160.0f, 30.0f, -1.0, "btn_save_tooltip"); + jRow = CreateButton(jRow, "Select Target", "btn_select_target", 158.0f, 30.0f); + jRow = CreateButton(jRow, "", "btn_cancel", 160.0f, 30.0f, -1.0, "btn_cancel_tooltip"); + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 4 (labels)*********************************************************** 508 / 177 + jRow = CreateLabel(JsonArray(), "Model", "module_title", 143.0f, 10.0f); + jRow = CreateLabel(jRow, "Color", "color_title", 339.0f, 10.0f); + jRow = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 5 (groups) + // Row 51 (title)*********************************************************** 508 / 195 / 18 + json jGroupRow = CreateLabel(JsonArray(), "Item", "item__cmb_title", 128.0f, 10.0f); + json jGroupCol = JsonArrayInsert(JsonArray(), NuiRow(jGroupRow)); + // Row 52 (combo)*********************************************************** 508 / 233 / 56 + jGroupRow = CreateItemCombo(oPC, JsonArray(), "item_combo"); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + // Row 53 (title)*********************************************************** 508 / 251 / 74 + jGroupRow = CreateLabel(JsonArray(), "Model", "model_cmb_title",128.0f, 10.0f); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + // Row 54 (combo)*********************************************************** 508 / 289 / 112 + jGroupRow = CreateModelCombo(oPC, oTarget, JsonArray(), "model_combo"); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + // Row 55 (title)*********************************************************** 508 / 307 / 120 + jGroupRow = CreateLabel(JsonArray(), "", "top_title",128.0f, 10.0f); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + // Row 56 (top)************************************************************* 508 / 355 / 168 + jGroupRow = CreateButtonImage(JsonArray(), "nui_shld_left", "btn_prev_t", 40.0f, 40.0f); + // Removed TextEditBox for mobile + jGroupRow = CreateTextEditBox(jGroupRow, "place_holder", "txt_model_number_t", 3, FALSE, 40.0, 40.0); + //CreateLabel(jGroupRow, "", "txt_model_number_t", 40.0, 40.0); + jGroupRow = CreateButtonImage(jGroupRow, "nui_shld_right", "btn_next_t", 40.0f, 40.0f); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + // Row 57 (title)*********************************************************** 508 / 373 / 186 + jGroupRow = CreateLabel(JsonArray(), "", "middle_title",128.0f, 10.0f); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + // Row 58 (middle)********************************************************** 508 / 421 /234 + jGroupRow = CreateButtonImage(JsonArray(), "nui_shld_left", "btn_prev_m", 40.0f, 40.0f); + // Removed TextEditBox for mobile + jGroupRow = CreateTextEditBox(jGroupRow, "place_holder", "txt_model_number_m", 3, FALSE, 40.0, 40.0); + //CreateLabel(jGroupRow, "", "txt_model_number_m", 40.0, 40.0); + jGroupRow = CreateButtonImage(jGroupRow, "nui_shld_right", "btn_next_m", 40.0f, 40.0f); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + // Row 59 (title)*********************************************************** 508 / 439 / 252 + jGroupRow = CreateLabel(JsonArray(), "", "bottom_title",128.0f, 10.0f); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + // Row 510 (bottom)********************************************************* 508 / 487 /300 + jGroupRow = CreateButtonImage(JsonArray(), "nui_shld_left", "btn_prev_b", 40.0f, 40.0f); + // Removed TextEditBox for mobile + jGroupRow = CreateTextEditBox(jGroupRow, "place_holder", "txt_model_number_b", 3, FALSE, 40.0, 40.0); + //CreateLabel(jGroupRow, "", "txt_model_number_b", 40.0, 40.0); + jGroupRow = CreateButtonImage(jGroupRow, "nui_shld_right", "btn_next_b", 40.0f, 40.0f); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + // Row 511 (blank spacer) + jGroupRow = CreateLabel(JsonArray(), "", "blank_space",128.0f, 20.0f); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + // Row 512 (light)********************************************************** 508 / 487 /300 + jGroupRow = CreateButtonSelect(JsonArray(), "Randomize", "btn_randomize", 128.0f, 30.0f); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupCol = JsonArrayInsert(jGroupCol, NuiSpacer()); + jRow = JsonArrayInsert(JsonArray(), NuiHeight(NuiWidth(NuiGroup(NuiCol(jGroupCol)), 143.0), 442.0)); + // Make the Color Group. + // Row 550 (groups)********************************************************* 508 / 361 / 184 + json jImage = NuiEnabled(NuiId(NuiImage(NuiBind("color_pallet_image"), JsonInt(0), JsonInt(0), JsonInt(1)), "color_pallet"), NuiBind("color_pallet_event")); + jImage = NuiWidth(jImage, 320.0); // 256 + 64 + jImage = NuiHeight(jImage, 220.0); // 176 + 44 + jImage = NuiTooltip(jImage, NuiBind("color_pallet_tooltip")); + json jIndicator = JsonArrayInsert(JsonArray(), NuiDrawListRect(JsonBool(TRUE), NuiColor(255,255,255), JsonBool(FALSE), JsonFloat(2.0), NuiBind("color_pallet_pointer"))); + jImage = NuiDrawList(jImage, JsonBool(FALSE), jIndicator); + jGroupRow = JsonArrayInsert(JsonArray(), jImage); + jGroupCol = JsonArrayInsert(JsonArray(), NuiRow(jGroupRow)); + // Row 551 (groups)********************************************************* 508 / 379 /202 + jGroupRow = CreateLabel(JsonArray(), "Part To Color", "lbl_color_parts", 320.0f, 10.0f); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + // Row 552 (groups)********************************************************* 508 / 417 /240 + jGroupRow = CreateButtonSelect(JsonArray(), "Right", "btn_right_part_color", 98.0, 30.0, "btn_right_part_color_tooltip"); + jGroupRow = JsonArrayInsert(jGroupRow, NuiSpacer()); + jGroupRow = CreateButtonSelect(jGroupRow, "All", "btn_all_color", 98.0, 30.0, "btn_all_color_tooltip"); + jGroupRow = JsonArrayInsert(jGroupRow, NuiSpacer()); + jGroupRow = CreateButtonSelect(jGroupRow, "Left", "btn_left_part_color", 98.0, 30.0, "btn_left_part_color_tooltip"); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + // Row 553 (groups)********************************************************* 508 / 435 / 258 + jGroupRow = CreateLabel(JsonArray(), "Part Color To Reset", "lbl_reset_parts", 320.0f, 10.0f); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + // Row 554 (groups)********************************************************* 508 / 473 /296 + jGroupRow = CreateButton(JsonArray(), "Right", "btn_right_part_reset", 98.0, 30.0, -1.0, "btn_right_part_reset_tooltip"); + jGroupRow = JsonArrayInsert(jGroupRow, NuiSpacer()); + jGroupRow = CreateButton(jGroupRow, "All", "btn_all_reset", 50.0, 30.0, -1.0, "btn_all_reset_tooltip"); + jGroupRow = JsonArrayInsert(jGroupRow, NuiSpacer()); + jGroupRow = CreateButton(jGroupRow, "Left", "btn_left_part_reset", 98.0, 30.0, -1.0, "btn_left_part_reset_tooltip"); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + // Row 555 (groups)********************************************************* 508 / 491 / 314 + jGroupRow = CreateLabel(JsonArray(), "Material to Color", "lbl_material_color", 320.0f, 10.0f); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + // Row 556 (groups)********************************************************* 508 / 529 /352 + jGroupRow = CreateButtonSelect(JsonArray(), "Cloth 1", "btn_material_0", 98.0, 30.0); + jGroupRow = JsonArrayInsert(jGroupRow, NuiSpacer()); + jGroupRow = CreateButtonSelect(jGroupRow, "Leather 1", "btn_material_2", 98.0, 30.0); + jGroupRow = JsonArrayInsert(jGroupRow, NuiSpacer()); + jGroupRow = CreateButtonSelect(jGroupRow, "Metal 1", "btn_material_4", 98.0, 30.0); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + // Row 557 (groups)********************************************************* 508 / 567 / 390 + jGroupRow = CreateButtonSelect(JsonArray(), "Cloth 2", "btn_material_1", 98.0, 30.0); + jGroupRow = JsonArrayInsert(jGroupRow, NuiSpacer()); + jGroupRow = CreateButtonSelect(jGroupRow, "Leather 2", "btn_material_3", 98.0, 30.0); + jGroupRow = JsonArrayInsert(jGroupRow, NuiSpacer()); + jGroupRow = CreateButtonSelect(jGroupRow, "Metal 2", "btn_material_5", 98.0, 30.0); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupCol = JsonArrayInsert(jGroupCol, NuiSpacer()); + jRow = JsonArrayInsert(jRow, NuiHeight(NuiWidth(NuiGroup(NuiCol(jGroupCol)), 339.0), 442.0)); // 275 398 + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + json jLayout = NuiCol(jCol); + // Get the window location to restore it from the database. + json jGeometry = JsonObjectGet(jCraft, "CRAFT_MENU"); + float fX = JsonGetFloat(JsonObjectGet(jGeometry, "x")); + float fY = JsonGetFloat(JsonObjectGet(jGeometry, "y")); + string sPCWindow; + int nToken = SetWindow(oPC, jLayout, "crafting_nui", "Crafting", + fX, fY, 508.0, 700.0, FALSE, FALSE, FALSE, FALSE, TRUE, "pe_crafting"); // 444 645 + // Set all binds, events, and watches. + NuiSetBindWatch (oPC, nToken, "window_geometry", TRUE); + int nItem = JsonGetInt(JsonObjectGet(jCraft, CRAFT_ITEM_SELECTION)); + object oItem = GetSelectedItem(oTarget, nItem); + // Row 1 + NuiSetBind(oPC, nToken, "txt_item_name", JsonString(GetName(oItem))); + NuiSetBind(oPC, nToken, "txt_item_name_event", JsonBool(TRUE)); + NuiSetBindWatch(oPC, nToken, "txt_item_name", TRUE); + // Row 2 + NuiSetBind(oPC, nToken, "btn_info_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_info_tooltip", JsonString(" Look at and change item information")); + NuiSetBind(oPC, nToken, "btn_wardrobe_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_wardrobe_tooltip", JsonString(" Use your wardrobe to save/load item appearances")); + int nLight = GetLocalInt(oPC, CRAFT_HIGHLIGHT) + GetLocalInt(oPC, CRAFT_ULTRALIGHT); + NuiSetBind(oPC, nToken, "btn_highlight", JsonBool(nLight)); + NuiSetBind(oPC, nToken, "btn_highlight_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_highlight_tooltip", JsonString(" Left click for White light, Right click for Ultravision")); + // Row 3 + NuiSetBind(oPC, nToken, "btn_save_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_save_tooltip", JsonString(" Save current changes")); + NuiSetBind(oPC, nToken, "btn_select_target_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_cancel_label", JsonString("Exit")); + NuiSetBind(oPC, nToken, "btn_cancel_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_cancel_tooltip", JsonString(" Exit the crafting menu")); + // Row 4 Labels. + // Row 5 Groups. + // Row 51 title. + // Row 52 + NuiSetBind(oPC, nToken, "item_combo_selected", JsonInt(nItem)); + NuiSetBind(oPC, nToken, "item_combo_event", JsonBool(TRUE)); + NuiSetBindWatch(oPC, nToken, "item_combo_selected", TRUE); + // Row 53 title. + // Row 54 + int nSelected = JsonGetInt(JsonObjectGet(jCraft, CRAFT_MODEL_SELECTION)); + if(nItem == 1 || nItem == 2 || nItem == 4) + { + if(GetHiddenWhenEquipped(oItem)) nSelected = 1; + else nSelected = 0; + } + NuiSetBind(oPC, nToken, "model_combo_selected", JsonInt (nSelected)); + NuiSetBind(oPC, nToken, "model_combo_event", JsonBool (TRUE)); + NuiSetBindWatch(oPC, nToken, "model_combo_selected", TRUE); + // Row 55, 56, 57 titles + // Row 58 top, 59 middle, 510 bottom + string sModelTop, sModelMiddle, sModelBottom; + // Model Group + if(ai_GetIsWeapon(oItem)) + { + int nModel = GetItemAppearance(oItem, ITEM_APPR_TYPE_WEAPON_MODEL, 0); + int nColor = GetItemAppearance(oItem, ITEM_APPR_TYPE_WEAPON_COLOR, 0); + int nModelNumber = (nModel * 10) + nColor; + sModelTop = IntToString(nModelNumber); + nModel = GetItemAppearance(oItem, ITEM_APPR_TYPE_WEAPON_MODEL, 1); + nColor = GetItemAppearance(oItem, ITEM_APPR_TYPE_WEAPON_COLOR, 1); + nModelNumber = (nModel * 10) + nColor; + sModelMiddle = IntToString(nModelNumber); + nModel = GetItemAppearance(oItem, ITEM_APPR_TYPE_WEAPON_MODEL, 2); + nColor = GetItemAppearance(oItem, ITEM_APPR_TYPE_WEAPON_COLOR, 2); + nModelNumber = (nModel * 10) + nColor; + sModelBottom = IntToString(nModelNumber); + // Row 55 + NuiSetBind(oPC, nToken, "top_title_label", JsonString("Top")); + // Row 56 + //NuiSetBind(oPC, nToken, "txt_model_number_t_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "txt_model_number_t", JsonString(sModelTop)); + NuiSetBind(oPC, nToken, "btn_prev_t_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_next_t_event", JsonBool(TRUE)); + // Row 57 + NuiSetBind(oPC, nToken, "middle_title_label", JsonString("Middle")); + // Row 58 + //NuiSetBind(oPC, nToken, "txt_model_number_m_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "txt_model_number_m", JsonString(sModelMiddle)); + NuiSetBind(oPC, nToken, "btn_prev_m_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_next_m_event", JsonBool(TRUE)); + // Row 59 + NuiSetBind(oPC, nToken, "bottom_title_label", JsonString("Bottom")); + // Row 510 + //NuiSetBind(oPC, nToken, "txt_model_number_b_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "txt_model_number_b", JsonString(sModelBottom)); + NuiSetBind(oPC, nToken, "btn_prev_b_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_next_b_event", JsonBool(TRUE)); + // Row 511 + NuiSetBind(oPC, nToken, "btn_randomize_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_randomize_tooltip", JsonString(" Randomize the selected weapon")); + } + // Armor and clothing + else if(nItem == 0) + { + nSelected = GetArmorModelSelected(oPC); + // These models only have one side so make sure we are not linked. + if (nSelected == ITEM_APPR_ARMOR_MODEL_NECK || + nSelected == ITEM_APPR_ARMOR_MODEL_TORSO || + nSelected == ITEM_APPR_ARMOR_MODEL_BELT || + nSelected == ITEM_APPR_ARMOR_MODEL_PELVIS || + nSelected == ITEM_APPR_ARMOR_MODEL_ROBE) + { + sModelMiddle = IntToString(GetItemAppearance(oItem, ITEM_APPR_TYPE_ARMOR_MODEL, nSelected)); + // Row 55 + NuiSetBind(oPC, nToken, "top_title_label", JsonString("")); + // Row 56 + //NuiSetBind(oPC, nToken, "txt_model_number_t_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "txt_model_name_t", JsonString("")); + NuiSetBind(oPC, nToken, "btn_prev_t_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_next_t_event", JsonBool(FALSE)); + // Row 57 + NuiSetBind(oPC, nToken, "middle_title_label", JsonString("Model")); + // Row 58 + //NuiSetBind(oPC, nToken, "txt_model_number_m_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "txt_model_number_m", JsonString(sModelMiddle)); + NuiSetBind(oPC, nToken, "btn_prev_m_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_next_m_event", JsonBool(TRUE)); + // Row 59 + NuiSetBind(oPC, nToken, "bottom_title_label", JsonString("")); + // Row 510 + //NuiSetBind(oPC, nToken, "txt_model_number_b_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "txt_model_number_b", JsonString("")); + NuiSetBind(oPC, nToken, "btn_prev_b_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_next_b_event", JsonBool(FALSE)); + } + else + { + sModelTop = IntToString(GetItemAppearance(oItem, ITEM_APPR_TYPE_ARMOR_MODEL, nSelected)); + if(nSelected == ITEM_APPR_ARMOR_MODEL_RTHIGH) nSelected--; + else nSelected++; + sModelBottom = IntToString(GetItemAppearance(oItem, ITEM_APPR_TYPE_ARMOR_MODEL, nSelected)); + // Row 55 + NuiSetBind(oPC, nToken, "top_title_label", JsonString("Right")); + // Row 56 + //NuiSetBind(oPC, nToken, "txt_model_number_t_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "txt_model_number_t", JsonString(sModelTop)); + NuiSetBind(oPC, nToken, "btn_prev_t_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_next_t_event", JsonBool(TRUE)); + // Row 57 + NuiSetBind(oPC, nToken, "middle_title_label", JsonString("Right & Left")); + // Row 58 + //NuiSetBind(oPC, nToken, "txt_model_number_m_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "txt_model_number_m", JsonString(sModelTop)); + NuiSetBind(oPC, nToken, "btn_prev_m_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_next_m_event", JsonBool(TRUE)); + // Row 59 + NuiSetBind(oPC, nToken, "bottom_title_label", JsonString("Left")); + // Row 510 + //NuiSetBind(oPC, nToken, "txt_model_number_b_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "txt_model_number_b", JsonString(sModelBottom)); + NuiSetBind(oPC, nToken, "btn_prev_b_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_next_b_event", JsonBool(TRUE)); + } + // Row 511 + NuiSetBind(oPC, nToken, "btn_randomize_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_randomize_tooltip", JsonString(" Randomize the selected armor")); + } + // Shields, Cloaks, and Helmets. + else + { + sModelMiddle = IntToString(GetItemAppearance(oItem, ITEM_APPR_TYPE_SIMPLE_MODEL, 0)); + // Row 55 + NuiSetBind(oPC, nToken, "top_title_label", JsonString("")); + // Row 56 + //NuiSetBind(oPC, nToken, "txt_model_number_t_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "txt_model_number_t", JsonString("")); + NuiSetBind(oPC, nToken, "btn_prev_t_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_next_t_event", JsonBool(FALSE)); + // Row 57 + NuiSetBind(oPC, nToken, "middle_title_label", JsonString("Model")); + // Row 58 + //NuiSetBind(oPC, nToken, "txt_model_number_m_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "txt_model_number_m", JsonString(sModelMiddle)); + NuiSetBind(oPC, nToken, "btn_prev_m_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_next_m_event", JsonBool(TRUE)); + // Row 59 + NuiSetBind(oPC, nToken, "bottom_title_label", JsonString("")); + // Row 510 + //NuiSetBind(oPC, nToken, "txt_model_number_b_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "txt_model_number_b", JsonString("")); + NuiSetBind(oPC, nToken, "btn_prev_b_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_next_b_event", JsonBool(FALSE)); + // Row 511 + NuiSetBind(oPC, nToken, "btn_randomize_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_randomize_tooltip", JsonString(" Randomize the selected item")); + } + // Color Group + if(ai_GetIsWeapon(oItem) || ai_GetIsShield(oItem)) + { + // Need to disable the color widgets. + // Row 511 + NuiSetBind(oPC, nToken, "color_pallet_image", JsonString("gui_pal_tattoo")); + NuiSetBind(oPC, nToken, "color_pallet_image_event", JsonBool(FALSE)); + // Row 512 - Label Part to Color + // Row 5l3 + NuiSetBind(oPC, nToken, "btn_right_part_color_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_all_color_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_left_part_color_event", JsonBool(FALSE)); + // Row 514 - Label Part Color to Reset + // Row 515 + NuiSetBind(oPC, nToken, "btn_right_part_reset_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_all_reset_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_left_part_reset_event", JsonBool(FALSE)); + // Row 516 - Label Material to Color + // Row 517 + NuiSetBind(oPC, nToken, "btn_material_0", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_material_2", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_material_4", JsonBool(FALSE)); + // Row 518 + NuiSetBind(oPC, nToken, "btn_material_1", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_material_3", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_material_5", JsonBool(FALSE)); + SetMaterialButtons(oPC, nToken, -1); + } + // Armor and clothing + else if(nItem == 0) + { + // Row 511 + string sColorPallet = GetLocalString(oPC, CRAFT_COLOR_PALLET); + if(sColorPallet == "") sColorPallet = "gui_pal_tattoo"; + int nMaterialSelected = JsonGetInt(JsonObjectGet(jCraft, CRAFT_MATERIAL_SELECTION)); + int nModelSelected = GetArmorModelSelected(oPC); + // Row 511 + NuiSetBind(oPC, nToken, "color_pallet_image", JsonString(sColorPallet)); + NuiSetBind(oPC, nToken, "color_pallet_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "color_pallet_tooltip", JsonString(" Select a color or use the mouse wheel")); + int nSelectedRight, nSelectedAll, nSelectedLeft; + string sColorAll = IntToString(GetItemAppearance(oItem, ITEM_APPR_TYPE_ARMOR_COLOR, nMaterialSelected)); + // These models only have one side so make sure we are not linked. + if (nModelSelected == ITEM_APPR_ARMOR_MODEL_NECK || + nModelSelected == ITEM_APPR_ARMOR_MODEL_TORSO || + nModelSelected == ITEM_APPR_ARMOR_MODEL_BELT || + nModelSelected == ITEM_APPR_ARMOR_MODEL_PELVIS || + nModelSelected == ITEM_APPR_ARMOR_MODEL_ROBE) + { + // Row 512 - Label Part to Color + // Row 5l3 + int nPartColor = GetHasPartColor(oItem, nModelSelected, "Right"); + nSelectedRight = JsonGetInt(JsonObjectGet(jCraft, CRAFT_RIGHT_PART_COLOR)); + if(!nSelectedRight && nPartColor) + { + nSelectedRight = TRUE; + nSelectedLeft = FALSE; + } + nSelectedAll = !nSelectedRight; + jCraft = JsonObjectSet(jCraft, CRAFT_ALL_COLOR, JsonBool(nSelectedAll)); + jCraft = JsonObjectSet(jCraft, CRAFT_RIGHT_PART_COLOR, JsonBool(nSelectedRight)); + NuiSetBind(oPC, nToken, "btn_right_part_color", JsonBool(nSelectedRight)); + NuiSetBind(oPC, nToken, "btn_right_part_color_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_all_color", JsonBool(nSelectedAll)); + NuiSetBind(oPC, nToken, "btn_all_color_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_left_part_color", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_left_part_color_event", JsonBool(FALSE)); + // Row 514 - Label Part Color to Reset + // Row 5l5 + nSelectedRight = GetHasPartColor(oItem, nModelSelected, "Right"); + nSelectedAll = nSelectedRight; + NuiSetBind(oPC, nToken, "btn_right_part_reset_event", JsonBool(nSelectedRight)); + NuiSetBind(oPC, nToken, "btn_all_reset_event", JsonBool(nSelectedAll)); + NuiSetBind(oPC, nToken, "btn_left_part_reset_event", JsonBool(FALSE)); + } + else + { + // Row 512 - Label Part to Color + // Row 5l3 + int nPartColor = GetHasPartColor(oItem, nModelSelected, "Right"); + nSelectedRight = JsonGetInt(JsonObjectGet(jCraft, CRAFT_RIGHT_PART_COLOR)); + if(!nSelectedRight && nPartColor) + { + nSelectedRight = TRUE; + nSelectedLeft = FALSE; + } + else + { + nPartColor = GetHasPartColor(oItem, nModelSelected, "Left"); + nSelectedLeft = JsonGetInt(JsonObjectGet(jCraft, CRAFT_LEFT_PART_COLOR)); + if(!nSelectedLeft && nPartColor) + { + nSelectedLeft = TRUE; + nSelectedRight = FALSE; + } + } + nSelectedAll = !nSelectedRight && !nSelectedLeft; + jCraft = JsonObjectSet(jCraft, CRAFT_LEFT_PART_COLOR, JsonBool(nSelectedLeft)); + jCraft = JsonObjectSet(jCraft, CRAFT_ALL_COLOR, JsonBool(nSelectedAll)); + jCraft = JsonObjectSet(jCraft, CRAFT_RIGHT_PART_COLOR, JsonBool(nSelectedRight)); + NuiSetBind(oPC, nToken, "btn_right_part_color", JsonBool(nSelectedRight)); + NuiSetBind(oPC, nToken, "btn_right_part_color_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_all_color", JsonBool(nSelectedAll)); + NuiSetBind(oPC, nToken, "btn_all_color_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_left_part_color", JsonBool(nSelectedLeft)); + NuiSetBind(oPC, nToken, "btn_left_part_color_event", JsonBool(TRUE)); + // Row 514 - Label Part Color to Reset + // Row 5l5 + nSelectedRight = GetHasPartColor(oItem, nModelSelected, "Right"); + nSelectedLeft = GetHasPartColor(oItem, nModelSelected, "Left"); + nSelectedAll = nSelectedRight || nSelectedLeft; + NuiSetBind(oPC, nToken, "btn_right_part_reset_event", JsonBool(nSelectedRight)); + NuiSetBind(oPC, nToken, "btn_all_reset_event", JsonBool(nSelectedAll)); + NuiSetBind(oPC, nToken, "btn_left_part_reset_event", JsonBool(nSelectedLeft)); + } + int nColor; + if(!JsonGetInt(NuiGetBind(oPC, nToken, "btn_all_color"))) + { + int nModelSelected = GetArmorModelSelected(oPC); + if(!JsonGetInt(JsonObjectGet(jCraft, CRAFT_RIGHT_PART_COLOR))) + { + // Note: Right Thigh and Left Thigh are backwards so this fixes that! + if (nModelSelected == ITEM_APPR_ARMOR_MODEL_RTHIGH) nModelSelected--; + else nModelSelected++; + } + int nIndex = ITEM_APPR_ARMOR_NUM_COLORS + (nModelSelected * ITEM_APPR_ARMOR_NUM_COLORS) + nMaterialSelected; + nColor = GetItemAppearance(oItem, ITEM_APPR_TYPE_ARMOR_COLOR, nIndex); + } + else nColor = 255; + if(nColor == 255) nColor = GetItemAppearance(oItem, ITEM_APPR_TYPE_ARMOR_COLOR, nMaterialSelected); + float fPointX = IntToFloat((nColor - ((nColor / 16) * 16)) * 20); + float fPointY = IntToFloat((nColor / 16) * 20); + NuiSetBind(oPC, nToken, "color_pallet_pointer", NuiRect(fPointX, fPointY, 20.0, 20.0)); + // Row 516 - Label Material to Color + // Row 517 & 518 + NuiSetBind(oPC, nToken, "btn_right_part_color_tooltip", JsonString(" Select the right part to be uniquely colored")); + NuiSetBind(oPC, nToken, "btn_all_color_tooltip", JsonString(" Select all parts to be colored")); + NuiSetBind(oPC, nToken, "btn_left_part_color_tooltip", JsonString(" Select the left part to be uniquely colored")); + NuiSetBind(oPC, nToken, "btn_right_part_reset_tooltip", JsonString(" Clears the right part's unique color")); + NuiSetBind(oPC, nToken, "btn_all_reset_tooltip", JsonString(" Clears all parts unique colors")); + NuiSetBind(oPC, nToken, "btn_left_part_reset_tooltip", JsonString(" Clears the left part's unique color")); + nSelected = JsonGetInt(JsonObjectGet(jCraft, CRAFT_MATERIAL_SELECTION)); + SetMaterialButtons(oPC, nToken, nSelected); + SetLocalJson(oPC, CRAFT_JSON, jCraft); + } + // Cloaks and Helmets. + else + { + // Row 511 + string sColorPallet = GetLocalString(oPC, CRAFT_COLOR_PALLET); + if(sColorPallet == "") sColorPallet = "gui_pal_tattoo"; + int nMaterialSelected = JsonGetInt(JsonObjectGet(jCraft, CRAFT_MATERIAL_SELECTION)); + int nModelSelected = JsonGetInt(JsonObjectGet(jCraft, CRAFT_MODEL_SELECTION)); + int nColor = GetItemAppearance(oItem, ITEM_APPR_TYPE_ARMOR_COLOR, nMaterialSelected); + float fPointX = IntToFloat((nColor - ((nColor / 16) * 16)) * 20); + float fPointY = IntToFloat((nColor / 16) * 20); + NuiSetBind(oPC, nToken, "color_pallet_pointer", NuiRect(fPointX, fPointY, 20.0, 20.0)); + NuiSetBind(oPC, nToken, "color_pallet_image", JsonString(sColorPallet)); + NuiSetBind(oPC, nToken, "color_pallet_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "color_pallet_tooltip", JsonString(" Select a color or use the mouse wheel")); + // Row 512 - Label Part to Color + // Row 5l3 + NuiSetBind(oPC, nToken, "btn_right_part_color_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_right_part_color_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_all_color_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_all_color", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_left_part_color_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_left_part_color", JsonBool(FALSE)); + // Row 514 - Label Part Color to Reset + // Row 5l5 + NuiSetBind(oPC, nToken, "btn_right_part_reset_event", JsonBool(FALSE)); + //NuiSetBind(oPC, nToken, "btn_all_reset_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_left_part_reset_event", JsonBool(FALSE)); + // Row 516 - Label Material to Color + // Row 517 & 518 + nSelected = JsonGetInt(JsonObjectGet(jCraft, CRAFT_MATERIAL_SELECTION)); + SetMaterialButtons(oPC, nToken, nSelected); + } + // Lets make sure we clean up any cool down variables. + //DeleteLocalInt(oPC, CRAFT_COOL_DOWN); +} +json CreateItemCombo(object oPC, json jRow, string sComboBind) +{ + int nCnt; + // Create the list. + json jCombo = JsonArrayInsert(JsonArray(), NuiComboEntry("Armor", 0)); + jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Cloak", 1)); + jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Headgear", 2)); + jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Right hand", 3)); + jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Left hand", 4)); + return CreateCombo(jRow, jCombo, sComboBind, 128.0, 40.0); +} +json CreateModelCombo(object oPC, object oTarget, json jRow, string sComboBind) +{ + float fFacing = GetFacing(oTarget); + json jCombo, jCraft = GetLocalJson(oPC, CRAFT_JSON); + int nSelected = JsonGetInt(JsonObjectGet(jCraft, CRAFT_ITEM_SELECTION)); + // Create the list. + // Armor. + if(nSelected == 0) + { + fFacing += 180.0f; + if (fFacing > 359.0) fFacing -=359.0; + AssignCommand(oPC, SetCameraFacing(fFacing, 4.5f, 75.0, CAMERA_TRANSITION_TYPE_VERY_FAST)); + jCombo = JsonArrayInsert(JsonArray(), NuiComboEntry("Neck", 0)); + jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Shoulder", 1)); + jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Bicep", 2)); + jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Forearm", 3)); + jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Hand", 4)); + jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Torso", 5)); + jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Belt", 6)); + jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Pelvis", 7)); + jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Thigh", 8)); + jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Shin", 9)); + jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Foot", 10)); + jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Robe", 11)); + } + // Cloak. + else if(nSelected == 1) + { + if(fFacing > 359.0) fFacing -=359.0; + AssignCommand (oPC, SetCameraFacing(fFacing, 4.5f, 75.0, CAMERA_TRANSITION_TYPE_VERY_FAST)); + jCombo = JsonArrayInsert(JsonArray(), NuiComboEntry("Cloak", 0)); + jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Invisible", 1)); + } + // Headgear. + else if (nSelected == 2) + { + fFacing += 180.0f; + if(fFacing > 359.0) fFacing -=359.0; + AssignCommand(oPC, SetCameraFacing(fFacing, 2.5f, 75.0, CAMERA_TRANSITION_TYPE_VERY_FAST)); + jCombo = JsonArrayInsert(JsonArray(), NuiComboEntry("Headgear", 0)); + jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Invisible", 1)); + } + // Weapon. + else if (nSelected == 3) + { + // If they are changing a bow then face the opposite side. + object oItem = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC); + int nBaseItemType = GetBaseItemType(oItem); + if(nBaseItemType == BASE_ITEM_LONGBOW || nBaseItemType == BASE_ITEM_SHORTBOW) fFacing -= 90.00; + // This will make the camera face a melee weapon. + else fFacing += 90.0; + if(fFacing > 359.0) fFacing -=359.0; + AssignCommand(oPC, SetCameraFacing(fFacing, 3.5f, 75.0, CAMERA_TRANSITION_TYPE_VERY_FAST)); + jCombo = JsonArrayInsert(JsonArray(), NuiComboEntry("Weapon", 0)); + jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Acidic", 1)); + jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Frost", 2)); + jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Electric", 3)); + jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Unholy", 4)); + jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Flaming", 5)); + jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Holy", 6)); + jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Sonic", 7)); +} + // Weapon/Shield. + else if(nSelected == 4) + { + fFacing += 270.0f; + if(fFacing > 359.0) fFacing -=359.0; + AssignCommand(oPC, SetCameraFacing(fFacing, 3.5f, 75.0, CAMERA_TRANSITION_TYPE_VERY_FAST)); + object oItem = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oPC); + if(ai_GetIsShield(oItem)) + { + jCombo = JsonArrayInsert(JsonArray(), NuiComboEntry("Shield", 0)); + jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Invisible", 1)); + } + else + { + jCombo = JsonArrayInsert(JsonArray(), NuiComboEntry("Weapon", 0)); + jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Acidic", 1)); + jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Frost", 2)); + jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Electric", 3)); + jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Unholy", 4)); + jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Flaming", 5)); + jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Holy", 6)); + jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Sonic", 7)); + } + } + return CreateCombo(jRow, jCombo, sComboBind, 128.0, 40.0); +} +void SetMaterialButtons(object oPC, int nToken, int nMaterial) +{ + int nIndex, bBool, bUseable; + string sIndex; + if(nMaterial > -1) bUseable = TRUE; + for(nIndex = 0;nIndex < 6;nIndex++) + { + if(nIndex == nMaterial) bBool = TRUE; + else bBool = FALSE; + sIndex = IntToString(nIndex); + NuiSetBind(oPC, nToken, "btn_material_" + sIndex + "_event", JsonBool(bUseable)); + NuiSetBind(oPC, nToken, "btn_material_" + sIndex, JsonBool(bBool)); + } +} +object GetSelectedItem(object oTarget, int nItemSelected) +{ + if(nItemSelected == 0) return GetItemInSlot(INVENTORY_SLOT_CHEST, oTarget); + else if(nItemSelected == 1) return GetItemInSlot(INVENTORY_SLOT_CLOAK, oTarget); + else if(nItemSelected == 2) return GetItemInSlot(INVENTORY_SLOT_HEAD, oTarget); + else if(nItemSelected == 3) return GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTarget); + else if(nItemSelected == 4) return GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oTarget); + return OBJECT_INVALID; +} +int GetArmorModelSelected(object oPC) +{ + json jCraft = GetLocalJson(oPC, CRAFT_JSON); + int nModelSelected = JsonGetInt(JsonObjectGet(jCraft, CRAFT_MODEL_SELECTION)); + if(nModelSelected == 0) return ITEM_APPR_ARMOR_MODEL_NECK; + if(nModelSelected == 1) return ITEM_APPR_ARMOR_MODEL_RSHOULDER; + if(nModelSelected == 2) return ITEM_APPR_ARMOR_MODEL_RBICEP; + if(nModelSelected == 3) return ITEM_APPR_ARMOR_MODEL_RFOREARM; + if(nModelSelected == 4) return ITEM_APPR_ARMOR_MODEL_RHAND; + if(nModelSelected == 5) return ITEM_APPR_ARMOR_MODEL_TORSO; + if(nModelSelected == 6) return ITEM_APPR_ARMOR_MODEL_BELT; + if(nModelSelected == 7) return ITEM_APPR_ARMOR_MODEL_PELVIS; + if(nModelSelected == 8) return ITEM_APPR_ARMOR_MODEL_RTHIGH; + if(nModelSelected == 9) return ITEM_APPR_ARMOR_MODEL_RSHIN; + if(nModelSelected == 10) return ITEM_APPR_ARMOR_MODEL_RFOOT; + return ITEM_APPR_ARMOR_MODEL_ROBE; +} +int GetHasPartColor(object oItem, int nPart, string sSide) +{ + json jItem = ObjectToJson(oItem); + string sPartName = "APart_"; + if(sSide == "Left") + { + // Note: Right Thigh and Left Thigh are backwards so this fixes that! + if (nPart == ITEM_APPR_ARMOR_MODEL_RTHIGH) nPart--; + else nPart++; + } + sPartName += IntToString(nPart) + "_Col_"; + int nPartColor = JsonGetInt(GffGetByte(jItem, sPartName + "0")); + nPartColor += JsonGetInt(GffGetByte(jItem, sPartName + "1")); + nPartColor += JsonGetInt(GffGetByte(jItem, sPartName + "2")); + nPartColor += JsonGetInt(GffGetByte(jItem, sPartName + "3")); + nPartColor += JsonGetInt(GffGetByte(jItem, sPartName + "4")); + nPartColor += JsonGetInt(GffGetByte(jItem, sPartName + "5")); + return nPartColor; +} +int StartingUp(object oPC) +{ + if(GetLocalInt(oPC, AI_ADD_PLUGIN)) + { + json jPlugin = JsonArray(); + jPlugin = JsonArrayInsert(jPlugin, JsonString("pi_crafting")); + jPlugin = JsonArrayInsert(jPlugin, JsonInt(FALSE)); + jPlugin = JsonArrayInsert(jPlugin, JsonString("Item Crafting")); + jPlugin = JsonArrayInsert(jPlugin, JsonString("isk_x2cweap")); + json jPlugins = GetLocalJson(oPC, AI_JSON_PLUGINS); + jPlugins = JsonArrayInsert(jPlugins, jPlugin); + SetLocalJson(oPC, AI_JSON_PLUGINS, jPlugin); + SetLocalInt(oPC, AI_PLUGIN_SET, TRUE); + return TRUE; + } + if(!GetLocalInt(oPC, AI_STARTING_UP)) return FALSE; + return TRUE; +} + diff --git a/src/module/nss/pi_debug.nss b/src/module/nss/pi_debug.nss new file mode 100644 index 0000000..6555882 --- /dev/null +++ b/src/module/nss/pi_debug.nss @@ -0,0 +1,200 @@ +/*////////////////////////////////////////////////////////////////////////////// + Script: pi_debug + Programmer: Philos +//////////////////////////////////////////////////////////////////////////////// + Plugin for debugging. +*/////////////////////////////////////////////////////////////////////////////// +#include "0i_nui" +#include "0i_player_target" +// Does startup check if the game has just been loaded. +int StartingUp(object oPC); +void main() +{ + object oPC = OBJECT_SELF; + if(StartingUp(oPC)) return; + // Set window to not save until it has been created. + //SetLocalInt (oPC, AI_NO_NUI_SAVE, TRUE); + //DelayCommand (0.5f, DeleteLocalInt (oPC, AI_NO_NUI_SAVE)); + string sText = " [Single player]"; + if(AI_SERVER) sText = " [Server]"; + // ************************************************************************* Width / Height + // Row 1 ******************************************************************* 500 / 73 + json jRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + jRow = CreateLabel(jRow, PHILOS_VERSION + sText, "lbl_version", 470.0f, 20.0f, NUI_HALIGN_CENTER); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + // Add row to the column. + json jCol = JsonArrayInsert(JsonArray(), NuiRow(jRow)); + // Row 2 ******************************************************************* 500 / 129 + sText = "Module: " + GetModuleName() + " [" + GetTag(GetModule()) + "]"; + jRow = CreateLabel(JsonArray(), sText, "lbl_module_name", 470.0f, 20.0f, NUI_HALIGN_CENTER); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 3 ******************************************************************* 500 / 101 + sText = "Monster AI (nw_c2_default1): " + ResManGetAliasFor("nw_c2_default1", RESTYPE_NCS); + jRow = CreateLabel(JsonArray(), sText, "monster_1_ai", 470.0f, 20.0f, NUI_HALIGN_CENTER); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 4 ******************************************************************* 500 / 157 + sText = "Monster AI (j_ai_onheartbeat): " + ResManGetAliasFor("j_ai_onheartbeat", RESTYPE_NCS); + jRow = CreateLabel(JsonArray(), sText, "monster_2_ai", 470.0f, 20.0f, NUI_HALIGN_CENTER); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 5 ******************************************************************* 500 / 213 + sText = "Associate AI (nw_ch_ac1): " + ResManGetAliasFor("nw_ch_ac1", RESTYPE_NCS); + jRow = CreateLabel(JsonArray(), sText, "henchman_ai", 470.0f, 20.0f, NUI_HALIGN_CENTER); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 6 ******************************************************************* 500 / 241 + jRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + jRow = CreateButton(jRow, "Set NPC's scripts", "btn_npc_scripts", 150.0f, 20.0f, -1.0, "btn_npc_scripts_tooltip"); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateButton(jRow, "Set Reputations", "btn_set_reputation", 150.0f, 20.0f, -1.0, "btn_set_reputation_tooltip"); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateButton(jRow, "Clear Party Rep.", "btn_clear_reputation", 150.0f, 20.0f, -1.0, "btn_clear_reputation_tooltip"); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 7 ******************************************************************* 500 / 269 + jRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + jRow = CreateButton(jRow, "Display Target Info", "btn_info", 150.0f, 20.0f, -1.0, "btn_info_tooltip"); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateButton(jRow, "Dump Object to Json", "btn_obj_json", 150.0f, 20.0f, -1.0, "btn_obj_json_tooltip"); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateButton(jRow, "List Object Variables", "btn_obj_var", 150.0f, 20.0f, -1.0, "btn_obj_var_tooltip"); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 8 ******************************************************************* 500 / 297 jRow = JsonArray(); + jRow = CreateButton(JsonArray(), "Delete Variable", "btn_delete_var", 115.0f, 25.0f, -1.0, "btn_delete_var_tooltip"); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateButton(jRow, "Set Variable", "btn_set_var", 115.0f, 25.0f, -1.0, "btn_set_var_tooltip"); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateButton(jRow, "Get Variable", "btn_get_var", 115.0f, 25.0f, -1.0, "btn_get_var_tooltip"); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + json jCombo = JsonArrayInsert(JsonArray(), NuiComboEntry("int", 0)); + jCombo = JsonArrayInsert(jCombo, NuiComboEntry("float", 1)); + jCombo = JsonArrayInsert(jCombo, NuiComboEntry("string", 2)); + jCombo = JsonArrayInsert(jCombo, NuiComboEntry("object", 3)); + jCombo = JsonArrayInsert(jCombo, NuiComboEntry("location", 4)); + jRow = CreateCombo(jRow, jCombo, "cmb_var_type", 115.0, 25.0); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 9 ******************************************************************* 500 / 329 + jRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + jRow = CreateLabel(jRow, "Name:", "lbl_name", 40.0f, 20.0f); + jRow = CreateTextEditBox(jRow, "sPlaceHolder", "txt_var_name", 40, FALSE, 425.0f, 20.0f, "txt_var_name_tooltip"); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 10 ******************************************************************* 500 / 357 + jRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + jRow = CreateLabel(jRow, "Value:", "lbl_value", 40.0f, 20.0f); + jRow = CreateTextEditBox(jRow, "sPlaceHolder", "txt_var_value", 40, FALSE, 425.0f, 20.0f, "txt_var_value_tooltip"); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 11 ******************************************************************* 500 / 385 + // Make the debug creature group. + // Group Row 1 ******************************************************************* 500 / 385 + json jGroupRow = CreateButton(JsonArray(), "Debug Creature", "btn_debug_creature", 120.0f, 20.0f, -1.0, "btn_debug_creature_tooltip"); + jGroupRow = JsonArrayInsert(jGroupRow, NuiSpacer()); + jGroupRow = CreateButton(jGroupRow, "Clear Event Scripts", "btn_clear_events", 150.0f, 20.0f, -1.0, "btn_clear_events_tooltip"); + jGroupRow = JsonArrayInsert(jGroupRow, NuiSpacer()); + jGroupRow = CreateButton(jGroupRow, "Clear Debug", "btn_clear_debug", 120.0f, 20.0f, -1.0, "btn_clear_debug_tooltip"); + // Add group row to the group column. + json jGroupCol = JsonArrayInsert(JsonArray(), NuiRow(jGroupRow)); + float fHeight = 431.0; + // Group Row 2 ******************************************************************* 500 / --- + object oDebugCreature = GetLocalObject(oPC, "AI_RULE_DEBUG_CREATURE_OBJECT"); + if(GetIsObjectValid(oDebugCreature)) + { + string sScript = GetEventScript(oDebugCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT); + if(sScript == "nw_c2_default1") sText = GetName(oDebugCreature) + " is using monster AI scripts (" + sScript + ")."; + else if(sScript == "nw_ch_ac1") sText = GetName(oDebugCreature) + " is using associate AI scripts (" + sScript + ")."; + else if(sScript == "xx_pc_1_hb") sText = GetName(oDebugCreature) + " is using player AI scripts (" + sScript + ")."; + else if(sScript == "0e_id_events") sText = GetName(oDebugCreature) + " is using Infinite Dungeons AI scripts (" + sScript + ")."; + else if(sScript == "0e_prc_id_events") sText = GetName(oDebugCreature) + " is using PRC Infinite Dungeons AI scripts (" + sScript + ")."; + else sText = GetName(oDebugCreature) + " is using unknown AI scripts (" + sScript + ")."; + jGroupRow = CreateLabel(JsonArray(), sText, "debug_info", 455.0f, 20.0f, NUI_HALIGN_CENTER); + // Add group row to the group column. + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + fHeight = fHeight + 28; + } + // Group Row 3 ******************************************************************* 500 / --- + sText = GetLocalString(GetModule(), AI_RULE_DEBUG_CREATURE); + if(sText != "") sText = sText + " is sending AI debug to the log file."; + else sText = "Nothing is sending AI debug to the log file."; + jGroupRow = CreateLabel(JsonArray(), sText, "debug_log", 455.0f, 20.0f, NUI_HALIGN_CENTER); + // Add group row to the group column. + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + fHeight = fHeight + 28; + // Add group to the row. + jRow = JsonArrayInsert(JsonArray(), NuiGroup(NuiCol(jGroupCol))); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Set the Layout of the window. + json jLayout = NuiCol(jCol); + string sName = GetName(oPC); + if(GetStringRight(sName, 1) == "s") sName = sName + "'"; + else sName = sName + "'s"; + int nToken = SetWindow(oPC, jLayout, "pi_debug_nui", sName + " PEPS Debug Menu", + -1.0, -1.0, 500.0f, fHeight + 12.0f, FALSE, FALSE, TRUE, FALSE, TRUE, "pe_debug"); + // Set all binds, events, and watches. + // Row 1 - Version label. + // Row 2 Module Name. + // Row 3 - 5 Script locations. + // Row 6 + NuiSetBind(oPC, nToken, "btn_npc_scripts_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_npc_scripts_tooltip", JsonString(" Forces NPC to use Philos AI scripts!")); + NuiSetBind(oPC, nToken, "btn_set_reputation_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_set_reputation_tooltip", JsonString(" Sets a creatures faction to neutral for all standard factions.")); + NuiSetBind(oPC, nToken, "btn_clear_reputation_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_clear_reputation_tooltip", JsonString(" Clears the party's reputation with creature's faction.")); + // Row 7 + NuiSetBind(oPC, nToken, "btn_info_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_info_tooltip", JsonString(" Displays a target object's information to the log screen.")); + NuiSetBind(oPC, nToken, "btn_obj_json_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_obj_json_tooltip", JsonString(" Sends a Json Dump to the log file for the targeted object.")); + NuiSetBind(oPC, nToken, "btn_obj_var_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_obj_var_tooltip", JsonString(" Sends a list of variables for the targeted object.")); + // Row 8 + NuiSetBind(oPC, nToken, "btn_delete_var_tooltip", JsonString(" Delete the variable for the targeted object or Right click for the Module.")); + NuiSetBind(oPC, nToken, "btn_set_var_tooltip", JsonString(" Set the variable for the targeted object or Right click for the Module.")); + NuiSetBind(oPC, nToken, "btn_get_var_tooltip", JsonString(" Get the variable for the targeted object or Right click for the Module.")); + NuiSetBind(oPC, nToken, "cmb_var_type_event", JsonBool(TRUE)); + NuiSetBindWatch(oPC, nToken, "cmb_var_type_selected", TRUE); + // Row 9 + NuiSetBind(oPC, nToken, "txt_var_name_event", JsonBool(TRUE)); + NuiSetBindWatch (oPC, nToken, "txt_var_name", TRUE); + NuiSetBind(oPC, nToken, "txt_var_name_tooltip", JsonString(" Name of the variable we are setting.")); + // Row 10 + NuiSetBind(oPC, nToken, "txt_var_value_event", JsonBool(TRUE)); + NuiSetBindWatch (oPC, nToken, "txt_var_value", TRUE); + NuiSetBind(oPC, nToken, "txt_var_value_tooltip", JsonString(" The value to set on the variable, Objects/Locations will need to be selected.")); + // Row 11 + NuiSetBind(oPC, nToken, "btn_debug_creature_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_debug_creature_tooltip", JsonString(" Sets target creature to send AI debug to the log file.")); + NuiSetBind(oPC, nToken, "btn_clear_events_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_clear_events_tooltip", JsonString(" Sets a creature's event scripts to default.")); + NuiSetBind(oPC, nToken, "btn_clear_debug_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_clear_debug_tooltip", JsonString(" Clears a creature from sending AI debug to the log file.")); +} +int StartingUp(object oPC) +{ + if(GetLocalInt(oPC, AI_ADD_PLUGIN)) + { + json jPlugin = JsonArray(); + jPlugin = JsonArrayInsert(jPlugin, JsonString("pi_debug")); + jPlugin = JsonArrayInsert(jPlugin, JsonInt(FALSE)); + jPlugin = JsonArrayInsert(jPlugin, JsonString("Debug Menu")); + jPlugin = JsonArrayInsert(jPlugin, JsonString("dm_tagsearch")); + json jPlugins = GetLocalJson(oPC, AI_JSON_PLUGINS); + jPlugins = JsonArrayInsert(jPlugins, jPlugin); + SetLocalJson(oPC, AI_JSON_PLUGINS, jPlugin); + SetLocalInt(oPC, AI_PLUGIN_SET, TRUE); + return TRUE; + } + if(!GetLocalInt(oPC, AI_STARTING_UP)) return FALSE; + return TRUE; +} + diff --git a/src/module/nss/pi_forcerest.nss b/src/module/nss/pi_forcerest.nss new file mode 100644 index 0000000..dfabb34 --- /dev/null +++ b/src/module/nss/pi_forcerest.nss @@ -0,0 +1,70 @@ +#include "0i_menus" +// Does startup check if the game has just been loaded. +int StartingUp(object oPC); +void ai_UpdateAssociateWidget(object oMaster, object oAssociate, int nUIToken) +{ + if(nUIToken) NuiDestroy(oMaster, nUIToken); + ai_CreateWidgetNUI(oMaster, oAssociate); + if(oMaster != oAssociate) + { + nUIToken = NuiFindWindow(oMaster, "pc" + AI_WIDGET_NUI); + if(nUIToken) + { + NuiDestroy(oMaster, nUIToken); + ai_CreateWidgetNUI(oMaster, oMaster); + } + } +} +void main() +{ + object oPC = OBJECT_SELF; + if(StartingUp(oPC)) return; + ForceRest(oPC); + DeleteLocalInt(oPC, "HF_REST_LAST_TIME"); + int nIndex; + int nMaxHenchman = GetMaxHenchmen(); + object oAssociate; + for(nIndex = 1;nIndex <= nMaxHenchman; nIndex++) + { + oAssociate = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex); + ForceRest(oAssociate); + DeleteLocalInt(oAssociate, "HF_REST_LAST_TIME"); + if(ai_GetMagicMode(oAssociate, AI_MAGIC_BUFF_AFTER_REST)) + { + DelayCommand(1.0, ai_HenchmanCastDefensiveSpells(oAssociate, oPC)); + } + if(AI_HENCHMAN_WIDGET) + { + // Update widget for spell widget. + string sAssociateType = ai_GetAssociateType(oPC, oAssociate); + int nUIToken = NuiFindWindow(oPC, sAssociateType + AI_WIDGET_NUI); + if(nUIToken) DelayCommand(6.0, ai_UpdateAssociateWidget(oPC, oAssociate, nUIToken)); + else + { + if(!ai_GetWidgetButton(oPC, BTN_WIDGET_OFF, oAssociate, sAssociateType)) + { + DelayCommand(6.0, ai_UpdateAssociateWidget(oPC, oAssociate, 0)); + } + } + } + } +} +int StartingUp(object oPC) +{ + if(GetLocalInt(oPC, AI_ADD_PLUGIN)) + { + json jPlugin = JsonArray(); + jPlugin = JsonArrayInsert(jPlugin, JsonString("pi_forcerest")); + jPlugin = JsonArrayInsert(jPlugin, JsonInt(FALSE)); + jPlugin = JsonArrayInsert(jPlugin, JsonString("Force Rest")); + jPlugin = JsonArrayInsert(jPlugin, JsonString("ir_rest")); + json jPlugins = GetLocalJson(oPC, AI_JSON_PLUGINS); + jPlugins = JsonArrayInsert(jPlugins, jPlugin); + SetLocalJson(oPC, AI_JSON_PLUGINS, jPlugin); + SetLocalInt(oPC, AI_PLUGIN_SET, TRUE); + return TRUE; + } + if(!GetLocalInt(oPC, AI_STARTING_UP)) return FALSE; + return TRUE; +} + diff --git a/src/module/nss/pi_henchmen.nss b/src/module/nss/pi_henchmen.nss new file mode 100644 index 0000000..5119039 --- /dev/null +++ b/src/module/nss/pi_henchmen.nss @@ -0,0 +1,209 @@ +/*////////////////////////////////////////////////////////////////////////////// +// Script Name: pi_henchmen +//////////////////////////////////////////////////////////////////////////////// + Executable plug in script for Philos Module Extentions. + + UI to save a players as Henchmen. +*/////////////////////////////////////////////////////////////////////////////// +#include "pinc_henchmen" +// Does startup check if the game has just been loaded. +int StartingUp(object oPC); +// Inserts base classes to an array for a combo box. +json JArrayInsertBaseClasses(); +void main() +{ + object oPC = OBJECT_SELF; + if(StartingUp(oPC)) return; + // Set window to not save until it has been created. + SetLocalInt (oPC, "AI_NO_NUI_SAVE", TRUE); + DelayCommand (0.5f, DeleteLocalInt (oPC, "AI_NO_NUI_SAVE")); + // Row 1 (Buttons) ********************************************************* 775 / 73 + json jRow = CreateButtonSelect(JsonArray(), "Party 1", "btn_party1", 90.0f, 20.0f); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateButtonSelect(jRow, "Party 2", "btn_party2", 90.0f, 20.0f); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateButtonSelect(jRow, "Party 3", "btn_party3", 90.0f, 20.0f); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateButtonSelect(jRow, "Party 4", "btn_party4", 90.0f, 20.0f); + jRow = CreateButtonSelect(jRow, "Party 5", "btn_party5", 90.0f, 20.0f); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateButtonSelect(jRow, "Party 6", "btn_party6", 90.0f, 20.0f); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateButtonSelect(jRow, "Party 7", "btn_party7", 90.0f, 20.0f); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateButtonSelect(jRow, "Party 8", "btn_party8", 90.0f, 20.0f); + // Add the row to the column. + json jCol = JsonArrayInsert(JsonArray(), NuiRow(jRow)); + // Row 2 (Options)********************************************************** 775 / 101 + jRow = CreateButton(JsonArray(), "Clear Party", "btn_clear_party", 120.0f, 20.0f, -1.0, "btn_clear_party_tooltip"); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateButton(jRow, "Party Join", "btn_join_party", 120.0f, 20.0f, -1.0, "btn_join_party_tooltip"); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateButtonSelect(jRow, "Create NPC Henchman", "btn_npc_henchman", 200.0f, 20.0f, "btn_npc_henchman_tooltip"); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateButton(jRow, "Save Party", "btn_save_party", 120.0f, 20.0f, -1.0, "btn_save_party_tooltip"); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateButton(jRow, "Remove Party", "btn_remove_party", 120.0f, 20.0f, -1.0, "btn_remove_party_tooltip"); + // Add the row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 3 (Names and List titles) ******************************************* 775 / 124 + jRow = CreateLabel(JsonArray(), "", "lbl_save_char", 150.0, 15.0, 0, 0); + jRow = CreateLabel(jRow, "", "lbl_save_list", 200.0, 15.0, 0, 0); + jRow = CreateLabel(jRow, "In game party", "lbl_game_list", 200.0, 15.0, 0, 0); + jRow = CreateLabel(jRow, "", "lbl_game_char", 150.0, 15.0, 0, 0); + // Add the row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 4 (List Characters) ************************************************* 775 / 488 (364) + // Saved Characters for Party # + // ***** Adding character saved group next to the button list ************** + json jGroupRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + jGroupRow = CreateImage(jGroupRow, "", "img_saved_portrait", NUI_ASPECT_EXACTSCALED, NUI_HALIGN_CENTER, NUI_VALIGN_TOP, 128.0, 200.0, 0.0); + jGroupRow = JsonArrayInsert(jGroupRow, NuiSpacer()); + json jGroupCol = JsonArrayInsert(JsonArray(), NuiRow(jGroupRow)); + jGroupRow = CreateLabel(JsonArray(), "", "lbl_saved_stats", 150.0, 15.0, 0, 0, 0.0); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupRow = CreateLabel(JsonArray(), "", "lbl_saved_classes", 150.0, 15.0, 0, 0, 0.0); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupRow = CreateButton(JsonArray(), "", "btn_saved_join", 75.0, 20.0); + jGroupRow = CreateButton(jGroupRow, "Remove", "btn_saved_remove", 75.0, 20.0); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + //jGroupRow = JsonArray(); + //CreateButton(jGroupRow, "Edit", "btn_saved_edit", 150.0, 20.0); + //jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jRow = JsonArrayInsert(JsonArray(), NuiGroup(NuiCol(jGroupCol))); + // Create the button template for the List. + json jButton = NuiId(NuiButton(NuiBind ("btns_saved_char")), "btn_saved_char"); + json jList = JsonArrayInsert(JsonArray (), NuiListTemplateCell(jButton, 170.0, TRUE)); + // Create the list with the template. + jRow = CreateList(jRow, jList, "btns_saved_char", 25.0, 200.0, 325.0); + // Current Characters. + // Create the button template for the List. + jButton = NuiId(NuiButton(NuiBind ("btns_cur_char")), "btn_cur_char"); + jList = JsonArrayInsert(JsonArray (), NuiListTemplateCell(jButton, 170.0, TRUE)); + // Create the list with the template. + jRow = CreateList(jRow, jList, "btns_cur_char", 25.0, 200.0, 325.0); + // ***** Adding character current group next to the button list ************ + jGroupRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + jGroupRow = CreateImage(jGroupRow, "", "img_cur_portrait", NUI_ASPECT_EXACTSCALED, NUI_HALIGN_CENTER, NUI_VALIGN_TOP, 128.0, 200.0, 0.0); + jGroupRow = JsonArrayInsert(jGroupRow, NuiSpacer()); + jGroupCol = JsonArrayInsert(JsonArray(), NuiRow(jGroupRow)); + jGroupRow = CreateLabel(JsonArray(), "", "lbl_cur_stats", 150.0, 15.0, 0, 0, 0.0); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupRow = CreateLabel(JsonArray(), "", "lbl_cur_classes", 150.0, 15.0, 0, 0, 0.0); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupRow = CreateButton(JsonArray(), "", "btn_cur_save", 75.0, 20.0); + jGroupRow = CreateButton(jGroupRow, "Remove", "btn_cur_remove", 75.0, 20.0); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jGroupRow = CreateButton(JsonArray(), "Edit", "btn_cur_edit", 150.0, 20.0); + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jRow = JsonArrayInsert(jRow, NuiGroup(NuiCol(jGroupCol))); + // Add the row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Set the layout of the window. + json jLayout = NuiCol(jCol); + // Get the window location to restore it from the database. + CheckHenchmanDataAndInitialize(oPC, "0"); + json jData = GetHenchmanDbJson(oPC, "henchman", "0"); + json jGeometry = JsonObjectGet(jData, "henchman_nui"); + float fX = JsonGetFloat(JsonObjectGet(jGeometry, "x")); + float fY = JsonGetFloat(JsonObjectGet(jGeometry, "y")); + if(fX == 0.0 && fY == 0.0) + { + fX = -1.0; + fY = -1.0; + } + string sName = GetName(oPC); + if(GetStringRight(sName, 1) == "s") sName = sName + "'"; + else sName = sName + "'s"; + int nToken = SetWindow (oPC, jLayout, "henchman_nui", sName + " party", + fX, fY, 775.0, 488.0, FALSE, FALSE, TRUE, FALSE, TRUE, "pe_henchmen"); + // Lets set MaxHenchman here. + if(GetMaxHenchmen() < 6) SetMaxHenchmen(6); + // Setup watch for saving location. + NuiSetBindWatch (oPC, nToken, "window_geometry", TRUE); + // Set the elements to show events. + NuiSetBind(oPC, nToken, "btn_save_pc_event", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "btn_current_party_event", JsonBool (TRUE)); + string sParty = GetHenchmanDbString(oPC, "henchname", "0"); + if(sParty == "") + { + SetHenchmanDbString(oPC, "henchname", "1", "0"); + sParty = "1"; + } + // Set the party # buttons. + int nIndex; + string sIndex; + for(nIndex = 1; nIndex < 9; nIndex++) + { + sIndex = IntToString(nIndex); + if(sParty == sIndex) NuiSetBind(oPC, nToken, "btn_party" + sIndex, JsonBool(TRUE)); + else NuiSetBind(oPC, nToken, "btn_party" + sIndex, JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_party" + sIndex + "_event", JsonBool (TRUE)); + } + NuiSetBind(oPC, nToken, "btn_npc_henchman_event", JsonBool(TRUE)); + string sText = " Select a creature to copy and have them join you."; + NuiSetBind(oPC, nToken, "btn_npc_henchman_tooltip", JsonString(sText)); + // ********** Saved Henchman in party # ********* + nIndex = 0; + int nSlot, nMaxHenchman = AI_MAX_HENCHMAN + 1; + json jButtons = JsonArray(); + string sFirstHenchman, sButtonText; + json jNPCs, jNPC; + // Add saved party members from sParty to the button list. + while(nIndex < nMaxHenchman) + { + sIndex = IntToString(nIndex); + sButtonText = GetHenchmanDbString(oPC, "henchname", sParty + sIndex); + if(sButtonText != "") + { + jButtons = JsonArrayInsert(jButtons, JsonString(sButtonText)); + SetHenchmanDbString(oPC, "slot", sParty + IntToString(nSlot++), sParty + sIndex); + } + nIndex++; + } + // Add the buttons to the list. + NuiSetBind(oPC, nToken, "btns_saved_char", jButtons); + // Set up button lables for henchman. + NuiSetBind(oPC, nToken, "lbl_save_list_label", JsonString("Party Save " + sParty)); + AddSavedCharacterInfo(oPC, nToken, sParty); + // ********** Current Party ********* + NuiSetBind(oPC, nToken, "btn_current_party", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_clear_party", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "lbl_save_char", JsonBool(TRUE)); + // Set up button labels for henchman. + NuiSetBind(oPC, nToken, "btn_join_save_label", JsonString("Save")); + nIndex = 0; + jButtons = JsonArray(); + object oPartyMember, oCharacter = OBJECT_INVALID; + // Add current party members to the button list. + while(nIndex < AI_MAX_HENCHMAN) + { + if(nIndex == 0) oPartyMember = oPC; + else oPartyMember = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex); + if(oPartyMember != OBJECT_INVALID) jButtons = JsonArrayInsert(jButtons, JsonString(GetName(oPartyMember))); + else break; + nIndex++; + } + // Add the buttons to the list. + NuiSetBind(oPC, nToken, "btns_cur_char", jButtons); + AddCurrentCharacterInfo(oPC, nToken, sParty); +} +int StartingUp(object oPC) +{ + if(GetLocalInt(oPC, AI_ADD_PLUGIN)) + { + json jPlugin = JsonArray(); + jPlugin = JsonArrayInsert(jPlugin, JsonString("pi_henchmen")); + jPlugin = JsonArrayInsert(jPlugin, JsonInt(FALSE)); + jPlugin = JsonArrayInsert(jPlugin, JsonString("Henchmen Menu")); + jPlugin = JsonArrayInsert(jPlugin, JsonString("dm_creator")); + json jPlugins = GetLocalJson(oPC, AI_JSON_PLUGINS); + jPlugins = JsonArrayInsert(jPlugins, jPlugin); + SetLocalJson(oPC, AI_JSON_PLUGINS, jPlugin); + SetLocalInt(oPC, AI_PLUGIN_SET, TRUE); + return TRUE; + } + if(!GetLocalInt(oPC, AI_STARTING_UP)) return FALSE; + return TRUE; +} + diff --git a/src/module/nss/pi_test.nss b/src/module/nss/pi_test.nss new file mode 100644 index 0000000..818da8c --- /dev/null +++ b/src/module/nss/pi_test.nss @@ -0,0 +1,103 @@ +/*////////////////////////////////////////////////////////////////////////////// + Script: pi_test + Programmer: Philos +//////////////////////////////////////////////////////////////////////////////// + Plugin for debugging. +*/////////////////////////////////////////////////////////////////////////////// +#include "0i_nui" +#include "0i_player_target" +// Does startup check if the game has just been loaded. +int StartingUp(object oPC); +void main() +{ + object oPC = OBJECT_SELF; + if(StartingUp(oPC)) return; + string sText; + // Set window to not save until it has been created. + //SetLocalInt (oPC, AI_NO_NUI_SAVE, TRUE); + //DelayCommand (0.5f, DeleteLocalInt (oPC, AI_NO_NUI_SAVE)); + // ************************************************************************* Width / Height + // Row 1 ******************************************************************* 636 / 73 + json jRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + jRow = CreateButton(jRow, "Level Up Creature", "btn_level", 150.0f, 20.0f, -1.0, "btn_level_tooltip"); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateButton(jRow, "Gold for Creature", "btn_gold", 150.0f, 20.0f, -1.0, "btn_gold_tooltip"); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateButton(jRow, "Force Rest Creature", "btn_rest", 150.0f, 20.0f, -1.0, "btn_rest_tooltip"); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateButton(jRow, "ID/UnID Item", "btn_id_item", 150.0f, 20.0f, -1.0, "btn_id_item_tooltip"); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + // Add row to the column. + json jCol = JsonArrayInsert(JsonArray(), NuiRow(jRow)); + // Row 2 ******************************************************************* 636 / 101 + jRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + jRow = CreateButton(jRow, "Heal Creature", "btn_heal", 150.0f, 20.0f, -1.0, "btn_heal_tooltip"); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateButton(jRow, "Clear Creature Actions", "btn_clear", 150.0f, 20.0f, -1.0, "btn_clear_tooltip"); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateButton(jRow, "Kill Creature", "btn_kill", 150.0f, 20.0f, -1.0, "btn_kill_tooltip"); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateButton(jRow, "Remove Object", "btn_remove", 150.0f, 20.0f, -1.0, "btn_remove_tooltip"); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Row 3 ******************************************************************* 636 / 101 + jRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + jRow = CreateButton(jRow, "Jump To", "btn_jump", 150.0f, 20.0f, -1.0, "btn_jump_tooltip"); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + jRow = CreateButton(jRow, "Kill In Area", "btn_kill_area", 150.0f, 20.0f, -1.0, "btn_kill_area_tooltip"); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + float fHeight = 129.0; + // Set the Layout of the window. + json jLayout = NuiCol(jCol); + string sName = GetName(oPC); + if(GetStringRight(sName, 1) == "s") sName = sName + "'"; + else sName = sName + "'s"; + int nToken = SetWindow(oPC, jLayout, "pi_test_nui", sName + " PEPS Testing Menu", + -1.0, -1.0, 636.0f, fHeight + 12.0f, FALSE, FALSE, TRUE, FALSE, TRUE, "pe_test"); + // Set all binds, events, and watches. + // Row 1 + NuiSetBind(oPC, nToken, "btn_level_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_level_tooltip", JsonString(" Give level to target creature.")); + NuiSetBind(oPC, nToken, "btn_gold_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_gold_tooltip", JsonString(" Give Gold to target creature.")); + NuiSetBind(oPC, nToken, "btn_rest_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_rest_tooltip", JsonString(" Force rest target creature.")); + NuiSetBind(oPC, nToken, "btn_id_item_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_id_item_tooltip", JsonString(" Identify or UnIdentify the target item.")); + // Row 2 + NuiSetBind(oPC, nToken, "btn_heal_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_heal_tooltip", JsonString(" Heal target creature to max hitpoints.")); + NuiSetBind(oPC, nToken, "btn_clear_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_clear_tooltip", JsonString(" Clears a creature's actions including combat.")); + NuiSetBind(oPC, nToken, "btn_kill_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_kill_tooltip", JsonString(" Kill target creature doing 10,000 magic damage.")); + NuiSetBind(oPC, nToken, "btn_remove_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_remove_tooltip", JsonString(" Remove selected object or the nearest object to ground selection.")); + // Row 3 + NuiSetBind(oPC, nToken, "btn_jump_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_jump_tooltip", JsonString(" Jump to target location.")); + NuiSetBind(oPC, nToken, "btn_kill_area_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_kill_area_tooltip", JsonString(" Kills all creatures in target area.")); +} +int StartingUp(object oPC) +{ + if(GetLocalInt(oPC, AI_ADD_PLUGIN)) + { + json jPlugin = JsonArray(); + jPlugin = JsonArrayInsert(jPlugin, JsonString("pi_test")); + jPlugin = JsonArrayInsert(jPlugin, JsonInt(FALSE)); + jPlugin = JsonArrayInsert(jPlugin, JsonString("Testing Menu")); + jPlugin = JsonArrayInsert(jPlugin, JsonString("ir_charsheet")); + json jPlugins = GetLocalJson(oPC, AI_JSON_PLUGINS); + jPlugins = JsonArrayInsert(jPlugins, jPlugin); + SetLocalJson(oPC, AI_JSON_PLUGINS, jPlugin); + SetLocalInt(oPC, AI_PLUGIN_SET, TRUE); + return TRUE; + } + if(!GetLocalInt(oPC, AI_STARTING_UP)) return FALSE; + return TRUE; +} + diff --git a/src/module/nss/pinc_henchmen.nss b/src/module/nss/pinc_henchmen.nss new file mode 100644 index 0000000..a67141a --- /dev/null +++ b/src/module/nss/pinc_henchmen.nss @@ -0,0 +1,1531 @@ +/*////////////////////////////////////////////////////////////////////////////// +// Script Name: pinc_henchmen +//////////////////////////////////////////////////////////////////////////////// + Include file for Henchmen plug in scripts for Philos Module Extentions. + +Database Info: +Slot 0 - henchname = the save slot 1 - 8. +Slots 1 - 8 define the selections: + henchname = Saved character selected. + image = Current character selected. +*/////////////////////////////////////////////////////////////////////////////// +#include "0i_nui" +#include "nw_inc_gff" + +const string HENCHMAN_DATABASE = "philos_henchman_db"; +const string HENCHMAN_TABLE = "HENCHMAN_TABLE"; +const string HENCHMAN_TO_EDIT = "HENCHMAN_TO_EDIT"; + +// Creates the table and initializes if it needs to. +void CheckHenchmanDataAndInitialize(object oPC, string sSlot); +// Removes a henchan from the current slot. +void RemoveHenchmanDb(object oPC, string sSlot); +// sDataField should be one of the data fields for that table. +// sData is the string data to be saved. +void SetHenchmanDbString(object oPC, string sDataField, string sData, string sSlot); +// sDataField should be one of the data fields for the table. +// Returns a string of the data stored. +string GetHenchmanDbString(object oPC, string sDataField, string sSlot); +// sDataField should be one of the data fields for that table. +// jData is the json data to be saved. +void SetHenchmanDbJson(object oPC, string sDataField, json jData, string sSlot); +// sDataField should be one of the data fields for the table. +// Returns a string of the data stored. +json GetHenchmanDbJson(object oPC, string sDataField, string sSlot); +// sSlot is the slot to define this object in the database for this Slot## (# Party button and #1-6). +// oHenchman is the PC/Henchman to be saved. +void SetHenchmanDbObject(object oPC, object oHenchman, string sSlot); +// sSlot is the slot to define this object in the database for this Slot## (# Party button and #1-6). +// lLocationToSpawn will spawn the object at that location. +object GetHenchmanDbObject(object oPC, location lLocationToSpawn, string sSlot); +// Returns TRUE if the henchman with sName can join. +int GetJoinButtonActive(object oPC, string sName); +// Returns a two letter alignment string. +string GetAlignText(object oHenchman); +// Populates the Saved character group. +void AddSavedCharacterInfo(object oPC, int nToken, string sParty); +// Populates the Current character group. +void AddCurrentCharacterInfo(object oPC, int nToken, string sParty); +// Removes a henchman from your party. +void RemoveYourHenchman(object oPC, int nToken, string sParty); +// Removes all henchman from the party. +void RemoveWholeParty(object oPC, int nToken, string sParty); +// Saves a henchman in your party to the saved party #. +void SaveYourHenchman(object oPC, int nToken, string sParty); +// Saves the whole party to the saved party #. +void SaveWholeParty(object oPC, int nToken, string sParty); +// Saves the players current party to party #. +void SavedPartyJoin(object oPC, int nToken, string sParty); +// Saves a character in the players party to party #. +void SavedCharacterJoin(object oPC, int nToken, string sParty); +// Clears the players saved party #. +void SavedPartyCleared(object oPC, int nToken, string sParty); +// Sets oHenchmans scripts to the current AI. +void SetHenchmanScripts(object oHenchman); +// If a henchman does not have a LvlStatList this will create one for them. +// nLevels allows the creation of x levels for LvlStatList using the 1st class. +// 0 on nLevels makes the function build it based on current levels. +json CreateLevelStatList(json jHenchman, object oHenchman, object oPC, int nLevels = 0); +// Resets the character to level one in the first class. +object ResetCharacter(object oPC, object oHenchman); +// Creates a menu to edit a characters information. +void CreateCharacterEditGUIPanel(object oPC, object oAssociate); +// Creates a character description menu. +void CreateCharacterDescriptionNUI(object oPC, string sName, string sIcon, string sDescription); + +void CreateHenchmanDataTable () +{ + sqlquery sql = SqlPrepareQueryCampaign(HENCHMAN_DATABASE, + "CREATE TABLE IF NOT EXISTS " + HENCHMAN_TABLE + " (" + + "name TEXT, " + + "slot TEXT, " + + "henchname TEXT, " + + "image TEXT, " + + "stats TEXT, " + + "classes TEXT, " + + "henchman TEXT, " + + "PRIMARY KEY(slot));"); + SqlStep (sql); +} +void CheckHenchmanDataAndInitialize(object oPC, string sSlot) +{ + string sPCName = ai_RemoveIllegalCharacters(GetPCPlayerName(oPC)); + string sQuery = "SELECT name FROM sqlite_master WHERE type ='table' AND name=@tableName;"; + sqlquery sql = SqlPrepareQueryCampaign(HENCHMAN_DATABASE, sQuery); + SqlBindString(sql, "@tableName", HENCHMAN_TABLE); + if(!SqlStep (sql)) CreateHenchmanDataTable(); + sQuery = "SELECT slot FROM " + HENCHMAN_TABLE + " Where name = @name AND slot = @slot;"; + sql = SqlPrepareQueryCampaign("philos_henchman_db", sQuery); + SqlBindString(sql, "@name", sPCName); + SqlBindString(sql, "@slot", sSlot); + if(!SqlStep(sql)) + { + sQuery = "INSERT INTO " + HENCHMAN_TABLE + "(name, slot, henchname, image, stats, classes " + + ", henchman) VALUES (@name, @slot, @henchname, @image, @stats, @classes, @henchman);"; + sql = SqlPrepareQueryCampaign(HENCHMAN_DATABASE, sQuery); + SqlBindString(sql, "@name", sPCName); + SqlBindString(sql, "@slot", sSlot); + SqlBindString(sql, "@henchname", ""); + SqlBindString(sql, "@image", ""); + SqlBindString(sql, "@stats", ""); + SqlBindString(sql, "@classes", ""); + SqlBindJson(sql, "@henchman", JsonObject()); + SqlStep(sql); + } +} +void RemoveHenchmanDb(object oPC, string sSlot) +{ + string sPCName = ai_RemoveIllegalCharacters(GetPCPlayerName(oPC)); + string sQuery = "DELETE FROM " + HENCHMAN_TABLE + " WHERE " + + "name = @name AND slot = @slot;"; + sqlquery sql = SqlPrepareQueryCampaign(HENCHMAN_DATABASE, sQuery); + SqlBindString(sql, "@name", sPCName); + SqlBindString(sql, "@slot", sSlot); + SqlStep(sql); +} +void SetHenchmanDbString(object oPC, string sDataField, string sData, string sSlot) +{ + string sPCName = ai_RemoveIllegalCharacters(GetPCPlayerName(oPC)); + string sQuery = "UPDATE " + HENCHMAN_TABLE + " SET " + sDataField + " = @data WHERE " + + "name = @name AND slot = @slot;"; + sqlquery sql = SqlPrepareQueryCampaign(HENCHMAN_DATABASE, sQuery); + SqlBindString(sql, "@data", sData); + SqlBindString(sql, "@name", sPCName); + SqlBindString(sql, "@slot", sSlot); + SqlStep(sql); +} +string GetHenchmanDbString(object oPC, string sDataField, string sSlot) +{ + string sPCName = ai_RemoveIllegalCharacters(GetPCPlayerName(oPC)); + string sQuery = "SELECT " + sDataField + " FROM " + HENCHMAN_TABLE + " WHERE " + + "name = @name AND slot = @slot;"; + sqlquery sql = SqlPrepareQueryCampaign(HENCHMAN_DATABASE, sQuery); + SqlBindString(sql, "@name", sPCName); + SqlBindString(sql, "@slot", sSlot); + if(SqlStep (sql)) return SqlGetString(sql, 0); + else return ""; +} +void SetHenchmanDbJson(object oPC, string sDataField, json jData, string sSlot) +{ + string sPCName = ai_RemoveIllegalCharacters(GetPCPlayerName(oPC)); + string sQuery = "UPDATE " + HENCHMAN_TABLE + " SET " + sDataField + + " = @data WHERE name = @name AND slot = @slot;"; + sqlquery sql = SqlPrepareQueryCampaign(HENCHMAN_DATABASE, sQuery); + SqlBindJson (sql, "@data", jData); + SqlBindString(sql, "@name", sPCName); + SqlBindString (sql, "@slot", sSlot); + SqlStep (sql); +} +json GetHenchmanDbJson(object oPC, string sDataField, string sSlot) +{ + string sPCName = ai_RemoveIllegalCharacters(GetPCPlayerName(oPC)); + string sQuery = "SELECT " + sDataField + " FROM " + HENCHMAN_TABLE + " WHERE " + + "name = @name AND slot = @slot;"; + sqlquery sql = SqlPrepareQueryCampaign(HENCHMAN_DATABASE, sQuery); + SqlBindString(sql, "@name", sPCName); + SqlBindString (sql, "@slot", sSlot); + if (SqlStep (sql)) return SqlGetJson (sql, 0); + else return JsonArray (); +} +void SetHenchmanDbObject(object oPC, object oHenchman, string sSlot) +{ + string sPCName = ai_RemoveIllegalCharacters(GetPCPlayerName(oPC)); + string sQuery = "UPDATE " + HENCHMAN_TABLE + " SET henchman = @henchman WHERE " + + "name = @name AND slot = @slot;"; + sqlquery sql = SqlPrepareQueryCampaign(HENCHMAN_DATABASE, sQuery); + SqlBindObject(sql, "@henchman", oHenchman); + SqlBindString(sql, "@name", sPCName); + SqlBindString(sql, "@slot", sSlot); + SqlStep(sql); +} +object GetHenchmanDbObject(object oPC, location lLocationToSpawn, string sSlot) +{ + string sPCName = ai_RemoveIllegalCharacters(GetPCPlayerName(oPC)); + string sQuery = "SELECT henchman FROM " + HENCHMAN_TABLE + " WHERE " + + "name = @name AND slot = @slot;"; + sqlquery sql = SqlPrepareQueryCampaign(HENCHMAN_DATABASE, sQuery); + SqlBindString(sql, "@name", sPCName); + SqlBindString (sql, "@slot", sSlot); + if (SqlStep (sql)) + { + json jHenchman = SqlGetJson(sql, 0); + string sTag = JsonGetString(GffGetString(jHenchman, "Tag")); + if(sTag == "") jHenchman = GffReplaceString(jHenchman, "Tag", "Hench_" + IntToString(Random(100))); + return JsonToObject(jHenchman, lLocationToSpawn, OBJECT_INVALID, TRUE); + } + return OBJECT_INVALID; +} +int GetJoinButtonActive(object oPC, string sName) +{ + if(sName == GetName(oPC)) return FALSE; + // Look for a free henchman slot, and if this henchman is already joined! + int nIndex = 1; + object oHenchman = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex); + while(oHenchman != OBJECT_INVALID) + { + if(GetName(oHenchman) == sName) return FALSE; + oHenchman = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, ++nIndex); + } + return TRUE; +} +string GetAlignText(object oHenchman) +{ + string sAlign1, sAlign2; + switch (GetAlignmentLawChaos(oHenchman)) + { + case ALIGNMENT_LAWFUL : sAlign1 = "L"; break; + case ALIGNMENT_NEUTRAL : sAlign1 = "N"; break; + case ALIGNMENT_CHAOTIC : sAlign1 = "C"; break; + } + switch (GetAlignmentGoodEvil(oHenchman)) + { + case ALIGNMENT_GOOD : sAlign2 = "G"; break; + case ALIGNMENT_NEUTRAL : sAlign2 = "N"; break; + case ALIGNMENT_EVIL : sAlign2 = "E"; break; + } + string sAlign = sAlign1 + sAlign2; + if (sAlign == "NN") sAlign = "TN"; + return sAlign; +} +void AddSavedCharacterInfo(object oPC, int nToken, string sParty) +{ + string sHenchman = GetHenchmanDbString(oPC, "henchname", sParty); + // Add Henchman information. + if(sHenchman != "") + { + NuiSetBind (oPC, nToken, "btn_clear_party_event", JsonBool (TRUE)); + string sText = " Clears all characters from party " + sParty + "'s list!"; + NuiSetBind(oPC, nToken, "btn_clear_party_tooltip", JsonString(sText)); + NuiSetBind(oPC, nToken, "btn_join_party", JsonBool (TRUE)); + NuiSetBind(oPC, nToken, "btn_join_party_event", JsonBool (TRUE)); + sText = " Saved characters from party " + sParty + " enter the game and join you."; + NuiSetBind(oPC, nToken, "btn_join_party_tooltip", JsonString(sText)); + // Setup the henchman window. + string sName = GetHenchmanDbString(oPC, "henchname", sParty + sHenchman); + string sImage = GetHenchmanDbString(oPC, "image", sParty + sHenchman); + string sStats = GetHenchmanDbString(oPC, "stats", sParty + sHenchman); + string sClasses = GetHenchmanDbString(oPC, "classes", sParty + sHenchman); + NuiSetBind(oPC, nToken, "lbl_save_char_label", JsonString(sName)); + NuiSetBind(oPC, nToken, "img_saved_portrait_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "img_saved_portrait_image", JsonString(sImage + "l")); + NuiSetBind(oPC, nToken, "lbl_saved_stats_label", JsonString(sStats)); + NuiSetBind(oPC, nToken, "lbl_saved_classes_label", JsonString(sClasses)); + NuiSetBind(oPC, nToken, "btn_saved_join_label", JsonString("Join")); + NuiSetBind(oPC, nToken, "btn_saved_join_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_saved_remove_event", JsonBool(TRUE)); + //NuiSetBind(oPC, nToken, "btn_saved_edit_event", JsonBool(TRUE)); + } + else + { + NuiSetBind(oPC, nToken, "lbl_save_char_label", JsonString("Empty Party")); + NuiSetBind (oPC, nToken, "btn_clear_party_event", JsonBool (FALSE)); + NuiSetBind (oPC, nToken, "btn_join_party", JsonBool (FALSE)); + NuiSetBind (oPC, nToken, "btn_join_party_event", JsonBool (FALSE)); + // Setup the henchman window. + NuiSetBind(oPC, nToken, "img_saved_portrait_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "img_saved_portrait_image", JsonString("po_hu_m_99_l")); + NuiSetBind(oPC, nToken, "lbl_saved_stats_label", JsonString("")); + NuiSetBind(oPC, nToken, "lbl_saved_classes_label", JsonString("")); + NuiSetBind(oPC, nToken, "btn_saved_join_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_saved_join_label", JsonString("Join")); + NuiSetBind(oPC, nToken, "btn_saved_remove_event", JsonBool(FALSE)); + NuiSetBind(oPC, nToken, "btn_saved_edit_event", JsonBool(FALSE)); + } +} +void AddCurrentCharacterInfo(object oPC, int nToken, string sParty) +{ + string sHenchman = GetHenchmanDbString(oPC, "image", sParty); + if(sHenchman == "") + { + CheckHenchmanDataAndInitialize(oPC, sParty); + SetHenchmanDbString(oPC, "image", "0", sParty); + } + int nHenchman = StringToInt(sHenchman); + int nIndex = 0; + object oCharacter; + while(nIndex < AI_MAX_HENCHMAN) + { + if(nIndex == 0) oCharacter = oPC; + else oCharacter = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex); + if(oCharacter == OBJECT_INVALID) + { + nIndex = 0; + oCharacter = oPC; + break; + } + else if(nHenchman == nIndex) break; + nIndex++; + } + // Adjust the party buttons. + int bParty = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, 1) != OBJECT_INVALID; + //NuiSetBind(oPC, nToken, "btn_save_party", JsonBool (bParty)); + NuiSetBind(oPC, nToken, "btn_save_party_event", JsonBool (bParty)); + //NuiSetBind(oPC, nToken, "btn_remove_party", JsonBool (bParty)); + NuiSetBind(oPC, nToken, "btn_remove_party_event", JsonBool (bParty)); + if(bParty) + { + string sText = " Saves all henchman from your current party to party " + sParty + "."; + NuiSetBind(oPC, nToken, "btn_save_party_tooltip", JsonString(sText)); + sText = " Removes all henchman from your current party!"; + NuiSetBind(oPC, nToken, "btn_remove_party_tooltip", JsonString(sText)); + } + // Setup the henchman window. + string sName = GetName(oCharacter); + string sImage = GetPortraitResRef(oCharacter); + string sStats = GetAlignText(oCharacter) + " "; + if(GetGender(oCharacter) == GENDER_MALE) sStats += "Male "; + else sStats += "Female "; + int nPosition = 1; + sStats += GetStringByStrRef (StringToInt (Get2DAString ("racialtypes", "Name", GetRacialType (oCharacter)))); + string sClasses = GetStringByStrRef (StringToInt (Get2DAString ("classes", "Short", GetClassByPosition (nPosition, oCharacter)))); + sClasses += " " + IntToString (GetLevelByPosition (nPosition, oCharacter)); + int nClass = GetClassByPosition(++nPosition, oCharacter); + while(nClass != CLASS_TYPE_INVALID) + { + sClasses += ", " + GetStringByStrRef (StringToInt (Get2DAString ("classes", "Short", nClass))); + sClasses += " " + IntToString (GetLevelByPosition (nPosition, oCharacter)); + nClass = GetClassByPosition(++nPosition, oCharacter); + } + NuiSetBind(oPC, nToken, "lbl_game_char_label", JsonString(sName)); + NuiSetBind(oPC, nToken, "img_cur_portrait_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "img_cur_portrait_image", JsonString(sImage + "l")); + NuiSetBind(oPC, nToken, "lbl_cur_stats_label", JsonString(sStats)); + NuiSetBind(oPC, nToken, "lbl_cur_classes_label", JsonString(sClasses)); + NuiSetBind(oPC, nToken, "btn_cur_save_label", JsonString("Save")); + NuiSetBind(oPC, nToken, "btn_cur_save_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_cur_edit_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_cur_remove_event", JsonBool(TRUE)); +} +object GetSelectedHenchman(object oPC, string sParty) +{ + string sHenchman = GetHenchmanDbString(oPC, "image", sParty); + if(sHenchman == "") + { + CheckHenchmanDataAndInitialize(oPC, sParty); + SetHenchmanDbString(oPC, "image", "0", sParty); + } + int nHenchman = StringToInt(sHenchman); + int nIndex = 0; + object oCharacter; + while(nIndex < AI_MAX_HENCHMAN) + { + if(nIndex == 0) oCharacter = oPC; + else oCharacter = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex); + if(oCharacter == OBJECT_INVALID) + { + nIndex = 0; + oCharacter = oPC; + break; + } + else if(nHenchman == nIndex) break; + nIndex++; + } + return oCharacter; +} +void RemoveYourHenchman(object oPC, int nToken, string sParty) +{ + object oHenchman = GetSelectedHenchman(oPC, sParty); + if(oHenchman == oPC) ai_SendMessages("You cannot remove the player from the party!", AI_COLOR_RED, oPC); + else + { + RemoveHenchman(oPC, oHenchman); + AssignCommand(oHenchman, SetIsDestroyable(TRUE, FALSE, FALSE)); + NuiDestroy(oPC, NuiFindWindow(oPC, ai_GetAssociateType(oPC, oHenchman) + AI_WIDGET_NUI)); + DestroyObject(oHenchman); + } + ai_SendMessages(GetName(oHenchman) + " has been removed from the party!", AI_COLOR_GREEN, oPC); + NuiDestroy(oPC, nToken); + ExecuteScript("pi_henchmen", oPC); +} +void RemoveWholeParty(object oPC, int nToken, string sParty) +{ + int nIndex = AI_MAX_HENCHMAN; + object oHenchman; + oHenchman = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex); + while(nIndex > 0) + { + if(oHenchman != OBJECT_INVALID) + { + ai_SendMessages(GetName(oHenchman) + " has been remove from your Party.", AI_COLOR_YELLOW, oPC); + RemoveHenchman(oPC, oHenchman); + AssignCommand(oHenchman, SetIsDestroyable(TRUE, FALSE, FALSE)); + NuiDestroy(oPC, NuiFindWindow(oPC, ai_GetAssociateType(oPC, oHenchman) + AI_WIDGET_NUI)); + DestroyObject(oHenchman); + } + oHenchman = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, --nIndex); + } + ai_SendMessages("All of your henchman have been remove from the Party.", AI_COLOR_YELLOW, oPC); + NuiDestroy(oPC, nToken); + ExecuteScript("pi_henchmen", oPC); +} +void SaveYourHenchman(object oPC, int nToken, string sParty) +{ + int bPC, nIndex, nClass, nPosition, nMaxHenchman = AI_MAX_HENCHMAN + 1; + string sName, sIndex, sSlot, sStats, sClasses; + object oHenchman = GetSelectedHenchman(oPC, sParty); + if(oHenchman == oPC) + { + bPC = TRUE; + oHenchman = CopyObject(oPC, GetLocation(oPC), OBJECT_INVALID, "hench_" + IntToString(Random(100)), TRUE); + SetHenchmanScripts(oHenchman); + } + string sHenchmanName = GetName(oHenchman); + while(nIndex < nMaxHenchman) + { + sIndex = IntToString(nIndex); + sName = GetHenchmanDbString(oPC, "henchname", sParty + sIndex); + if(sName == sHenchmanName || sName == "") + { + sSlot = sParty + sIndex; + if(!bPC) RemoveHenchman(oPC, oHenchman); + // Special check for Infinite Dungeon plot givers to be changed into henchman. + if(GetStringLeft(GetLocalString(oHenchman, "sConversation"), 8) == "id1_plot") + { + DeleteLocalString(oHenchman, "sConversation"); + } + ChangeToStandardFaction(oHenchman, STANDARD_FACTION_DEFENDER); + json jHenchman = ObjectToJson(oHenchman, TRUE); + if(!bPC) AddHenchman(oPC, oHenchman); + else DestroyObject(oHenchman); + //string sPatch = "[{\"op\":\"replace\",\"path\":\"/FactionID/value\",\"value\":1}]"; + //json jPatch = JsonParse(sPatch); + //jHenchman = JsonPatch(jHenchman, jPatch); + CheckHenchmanDataAndInitialize(oPC, sSlot); + SetHenchmanDbString(oPC, "image", GetPortraitResRef(oHenchman), sSlot); + SetHenchmanDbString(oPC, "henchname", sHenchmanName, sSlot); + sStats = GetAlignText(oHenchman) + " "; + if(GetGender(oHenchman) == GENDER_MALE) sStats += "Male "; + else sStats += "Female "; + nPosition = 1; + sStats += GetStringByStrRef (StringToInt (Get2DAString ("racialtypes", "Name", GetRacialType (oHenchman)))); + sClasses = GetStringByStrRef (StringToInt (Get2DAString ("classes", "Short", GetClassByPosition (nPosition, oHenchman)))); + sClasses += " " + IntToString (GetLevelByPosition (nPosition, oHenchman)); + nClass = GetClassByPosition(++nPosition, oHenchman); + while(nClass != CLASS_TYPE_INVALID) + { + sClasses += ", " + GetStringByStrRef (StringToInt (Get2DAString ("classes", "Short", GetClassByPosition (nPosition, oHenchman)))); + sClasses += " " + IntToString (GetLevelByPosition (nPosition, oHenchman)); + nClass = GetClassByPosition(++nPosition, oHenchman); + } + SetHenchmanDbString(oPC, "stats", sStats, sSlot); + SetHenchmanDbString(oPC, "classes", sClasses, sSlot); + SetHenchmanDbJson(oPC, "henchman", jHenchman, sSlot); + if(sName == "") ai_SendMessages(sHenchmanName + " has been saved to the party.", AI_COLOR_GREEN, oPC); + else ai_SendMessages(sHenchmanName + " has replaced a copy of themselves in the party.", AI_COLOR_GREEN, oPC); + break; + } + nIndex++; + } +if(nIndex == nMaxHenchman) ai_SendMessages("This party is full!", AI_COLOR_RED, oPC); + NuiDestroy(oPC, nToken); + ExecuteScript("pi_henchmen", oPC); +} +void SaveWholeParty(object oPC, int nToken, string sParty) +{ + int nIndex = AI_MAX_HENCHMAN; + object oHenchman; + while(nIndex > 0) + { + oHenchman = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex); + if(oHenchman != OBJECT_INVALID) + { + SetHenchmanDbString(oPC, "image", IntToString(nIndex), sParty); + SaveYourHenchman(oPC, nToken, sParty); + } + nIndex--; + } + ai_SendMessages("All of your henchman have been saved to Party " + sParty + ".", AI_COLOR_YELLOW, oPC); + SetHenchmanDbString(oPC, "henchname", "0", sParty); + NuiDestroy(oPC, nToken); + ExecuteScript("pi_henchmen", oPC); +} +void SavedPartyJoin(object oPC, int nToken, string sParty) +{ + int bFound, nIndex, nDBHenchman = 0; + json jHenchman; + object oHenchman, oLoadedHenchman; + string sDBHenchman = IntToString(nDBHenchman); + string sName = GetHenchmanDbString(oPC, "henchname", sParty + sDBHenchman); + while(sName != "") + { + bFound = FALSE; + nIndex = 1; + oHenchman = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex); + while(oHenchman != OBJECT_INVALID) + { + if(sName == GetName(oPC) || GetName(oHenchman) == sName) + { + bFound = TRUE; + break; + } + oHenchman = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, ++nIndex); + } + if(!bFound) + { + ai_SendMessages(sName + " has joined your party.", AI_COLOR_GREEN, oPC); + jHenchman = GetHenchmanDbJson(oPC, "henchman", sParty + sDBHenchman); + oLoadedHenchman = JsonToObject(jHenchman, GetLocation(oPC), OBJECT_INVALID, TRUE); + AddHenchman(oPC, oLoadedHenchman); + } + else ai_SendMessages(sName + " is already in your party!", AI_COLOR_RED, oPC); + sDBHenchman = IntToString(++nDBHenchman); + sName = GetHenchmanDbString(oPC, "henchname", sParty + sDBHenchman); + } + NuiDestroy(oPC, nToken); + ExecuteScript("pi_henchmen", oPC); +} +void SavedCharacterJoin(object oPC, int nToken, string sParty) +{ + int nIndex, bFound; + object oHenchman, oLoadedHenchman; + string sHenchman = GetHenchmanDbString(oPC, "henchname", sParty); + string sName = GetHenchmanDbString(oPC, "henchname", sParty + sHenchman); + nIndex = 1; + oHenchman = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex); + while(oHenchman != OBJECT_INVALID) + { + if(sName == GetName(oPC) || GetName(oHenchman) == sName) + { + bFound = TRUE; + break; + } + oHenchman = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, ++nIndex); + } + if(!bFound) + { + ai_SendMessages(sName + " has joined your party!", AI_COLOR_GREEN, oPC); + oLoadedHenchman = GetHenchmanDbObject(oPC, GetLocation(oPC), sParty + sHenchman); + AddHenchman(oPC, oLoadedHenchman); + NuiDestroy(oPC, nToken); + ExecuteScript("pi_henchmen", oPC); + } + else ai_SendMessages(sName + " is already in your party!", AI_COLOR_RED, oPC); +} +void SavedPartyCleared(object oPC, int nToken, string sParty) +{ + int nIndex, nMaxHenchman = AI_MAX_HENCHMAN + 1; + object oHenchman, oLoadedHenchman; + string sIndex = IntToString(nIndex); + string sName = GetHenchmanDbString(oPC, "henchname", sParty + sIndex); + while(nIndex < nMaxHenchman) + { + if(sName != "") + { + RemoveHenchmanDb(oPC, sParty + sIndex); + ai_SendMessages(sName + " has been cleared from the saved party " + sParty + ".", AI_COLOR_YELLOW, oPC); + } + sIndex = IntToString(++nIndex); + sName = GetHenchmanDbString(oPC, "henchname", sParty + sIndex); + } + SetHenchmanDbString(oPC, "henchname", "", sParty); + NuiDestroy(oPC, nToken); + ExecuteScript("pi_henchmen", oPC); +} +json CreateOptionsAlignment(object oHenchman, int nAlignType) +{ + json jAlignNameList = JsonArray(); + if(nAlignType == 0) + { + jAlignNameList = JsonArrayInsert(jAlignNameList, JsonString("Lawful")); + jAlignNameList = JsonArrayInsert(jAlignNameList, JsonString("Neutral")); + jAlignNameList = JsonArrayInsert(jAlignNameList, JsonString("Chaotic")); + } + else + { + jAlignNameList = JsonArrayInsert(jAlignNameList, JsonString("Good")); + jAlignNameList = JsonArrayInsert(jAlignNameList, JsonString("Neutral")); + jAlignNameList = JsonArrayInsert(jAlignNameList, JsonString("Evil")); + } + return jAlignNameList; +} +json CreateOptionsClasses(object oHenchman) +{ + int nIndex = 1, nClass; + string sClassName; + json jClassNameList = JsonArray(); + while(nIndex < 5) + { + nClass = GetClassByPosition(nIndex, oHenchman); + if(nClass == CLASS_TYPE_INVALID) sClassName = "Empty"; + else + { + sClassName = GetStringByStrRef(StringToInt(Get2DAString("classes", "Name", nClass))); + sClassName += " " + IntToString(GetLevelByClass(nClass, oHenchman)); + } + jClassNameList = JsonArrayInsert(jClassNameList, JsonString(sClassName)); + nIndex++; + } + return jClassNameList; +} +json jArrayInsertClasses() +{ + int nIndex, nClass, nMaxClass = Get2DARowCount("classes"); + string sClassName; + json jClassNameCombo = JsonArray(); + while(nIndex < nMaxClass) + { + if(Get2DAString("classes", "PlayerClass", nIndex) == "1") + { + sClassName = GetStringByStrRef(StringToInt(Get2DAString("classes", "Name", nIndex))); + jClassNameCombo = JsonArrayInsert(jClassNameCombo, NuiComboEntry(sClassName, nClass)); + nClass++; + } + nIndex++; + } + return jClassNameCombo; +} +int GetSelectionByClass2DA(int nClass) +{ + int nIndex, nSelection, nMaxClass = Get2DARowCount("classes"); + while(nIndex < nMaxClass) + { + if(Get2DAString("classes", "PlayerClass", nIndex) == "1") + { + if(nClass == nIndex) return nSelection; + nSelection++; + } + nIndex++; + } + return -1; +} +int GetClassBySelection2DA(int nSelection) +{ + int nIndex, nClass, nMaxClass = Get2DARowCount("classes"); + while(nClass < nMaxClass) + { + if(Get2DAString("classes", "PlayerClass", nClass) == "1") + { + if(nSelection == nIndex) return nClass; + nIndex++; + } + nClass++; + } + return -1; +} +json ArrayInsertPackages(string sClass) +{ + int nIndex, nPackage, nMaxPackage = Get2DARowCount("packages"); + string sPackageName; + json jPackageNameCombo = JsonArray(); + while(nIndex < nMaxPackage) + { + if(Get2DAString("packages", "ClassID", nIndex) == sClass) + { + sPackageName = Get2DAString("packages", "Label", nIndex); + //GetStringByStrRef(StringToInt(Get2DAString("packages", "Name", nIndex))); + if(sPackageName != "Bad Strref" && sPackageName != "") + { + jPackageNameCombo = JsonArrayInsert(jPackageNameCombo, NuiComboEntry(sPackageName, nPackage)); + nPackage++; + } + } + nIndex++; + } + return jPackageNameCombo; +} +int GetSelectionByPackage2DA(string sClass, int nPackage) +{ + int nIndex, nSelection, nMaxPackage = Get2DARowCount("packages"); + string sPackageName; + while(nIndex < nMaxPackage) + { + if(Get2DAString("packages", "ClassID", nIndex) == sClass) + { + sPackageName = GetStringByStrRef(StringToInt(Get2DAString("packages", "Name", nIndex))); + if(sPackageName != "Bad Strref" && sPackageName != "") + { + if(nPackage == nIndex) return nSelection; + nSelection++; + } + } + nIndex++; + } + return -1; +} +int GetPackageBySelection2DA(string sClass, int nSelection) +{ + int nIndex, nPackage, nMaxPackage = Get2DARowCount("packages"); + while(nPackage < nMaxPackage) + { + if(Get2DAString("packages", "ClassID", nPackage) == sClass) + { + if(nSelection == nIndex) return nPackage; + nIndex++; + } + nPackage++; + } + return -1; +} +json ArrayInsertSoundSets(object oHenchman) +{ + int nIndex, nSoundSet, nSoundSetType, nMaxSets = Get2DARowCount("soundset"); + string sGender = IntToString(GetGender(oHenchman)); + string sSoundSetName, sResRef; + json jSoundSetNameCombo = JsonArray(); + while(nIndex < nMaxSets) + { + if(Get2DAString("soundset", "GENDER", nIndex) == sGender) + { + nSoundSetType = StringToInt(Get2DAString("soundset", "TYPE", nIndex)); + if(nSoundSetType < 5) + { + sSoundSetName = GetStringByStrRef(StringToInt(Get2DAString("soundset", "STRREF", nIndex))); + sResRef = GetStringLowerCase(Get2DAString("soundset", "RESREF", nIndex)); + if(GetStringLeft(sResRef, 4) == "vs_f") sSoundSetName += " (Full)"; + else if(GetStringLeft(sResRef, 4) == "vs_n") sSoundSetName += " (Part)"; + jSoundSetNameCombo = JsonArrayInsert(jSoundSetNameCombo, NuiComboEntry(sSoundSetName, nSoundSet)); + nSoundSet++; + } + } + nIndex++; + } + return jSoundSetNameCombo; +} +int GetSelectionBySoundSet2DA(object oHenchman, int nSoundSet) +{ + int nIndex, nSelection, nSoundSetType, nMaxSoundSet = Get2DARowCount("soundset"); + string sGender = IntToString(GetGender(oHenchman)); + while(nIndex < nMaxSoundSet) + { + if(Get2DAString("soundset", "GENDER", nIndex) == sGender) + { + nSoundSetType = StringToInt(Get2DAString("soundset", "TYPE", nIndex)); + if(nSoundSetType < 5) + { + if(nSoundSet == nIndex) return nSelection; + nSelection++; + } + } + nIndex++; + } + return -1; +} +int GetSoundSetBySelection2DA(object oHenchman, int nSelection) +{ + int nIndex, nSoundSet, nSoundSetType, nMaxSoundSet = Get2DARowCount("soundset"); + string sGender = IntToString(GetGender(oHenchman)); + while(nSoundSet < nMaxSoundSet) + { + if(Get2DAString("soundset", "GENDER", nSoundSet) == sGender) + { + nSoundSetType = StringToInt(Get2DAString("soundset", "TYPE", nSoundSet)); + if(nSoundSetType < 5) + { + if(nSelection == nIndex) return nSoundSet; + nIndex++; + } + } + nSoundSet++; + } + return -1; +} +void SetHenchmanScripts(object oHenchman) +{ + SetEventScript(oHenchman, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "nw_ch_ac1"); + SetEventScript(oHenchman, EVENT_SCRIPT_CREATURE_ON_NOTICE, "nw_ch_ac2"); + SetEventScript(oHenchman, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND, "nw_ch_ac3"); + SetEventScript(oHenchman, EVENT_SCRIPT_CREATURE_ON_DIALOGUE, "nw_ch_ac4"); + SetEventScript(oHenchman, EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED, "nw_ch_ac5"); + SetEventScript(oHenchman, EVENT_SCRIPT_CREATURE_ON_DAMAGED, "nw_ch_ac6"); + SetEventScript(oHenchman, EVENT_SCRIPT_CREATURE_ON_DEATH, "nw_ch_ac7"); + SetEventScript(oHenchman, EVENT_SCRIPT_CREATURE_ON_DISTURBED, "nw_ch_ac8"); + SetEventScript(oHenchman, EVENT_SCRIPT_CREATURE_ON_SPAWN_IN, "nw_ch_ac9"); + SetEventScript(oHenchman, EVENT_SCRIPT_CREATURE_ON_RESTED, "nw_ch_aca"); + SetEventScript(oHenchman, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, "nw_ch_acb"); + SetEventScript(oHenchman, EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR, "nw_ch_ace"); +} +object ai_AddHenchman(object oPC, json jHenchman, location lLocation, int nFamiliar, int nCompanion) +{ + jHenchman = GffReplaceResRef(jHenchman, "ScriptSpawn", ""); + object oHenchman = JsonToObject(jHenchman, lLocation, OBJECT_INVALID, TRUE); + AddHenchman(oPC, oHenchman); + DeleteLocalInt(oPC, "AI_IGNORE_NO_ASSOCIATE"); + string sAssociateType = ai_GetAssociateType(oPC, oHenchman); + NuiDestroy(oPC, NuiFindWindow(oPC, sAssociateType + AI_WIDGET_NUI)); + if(nFamiliar) SummonFamiliar(oHenchman); + if(nCompanion) SummonAnimalCompanion(oHenchman); + return oHenchman; +} +json CreateLevelStatList(json jHenchman, object oHenchman, object oPC, int nLevels = 0) +{ + int nClass = GetClassByPosition(1, oHenchman); + int nHitDie = StringToInt(Get2DAString("classes", "HitDie", nClass)); + SetLocalInt(oPC, "AI_IGNORE_NO_ASSOCIATE", TRUE); + json jSkill = JsonObject(); + jSkill = GffAddByte(jSkill, "Rank", 0); + jSkill = JsonObjectSet(jSkill, "__struct_id", JsonInt(0)); + json jSkillArray = JsonArray(); + int nNumOfSkills; + for(nNumOfSkills = Get2DARowCount("skills"); nNumOfSkills > 0; nNumOfSkills--) + { + jSkillArray = JsonArrayInsert(jSkillArray, jSkill); + } + json jLevel = JsonObject(); + jLevel = GffAddByte(jLevel, "EpicLevel", 0); + jLevel = GffAddList(jLevel, "FeatList", JsonArray()); + jLevel = GffAddByte(jLevel, "LvlStatClass", nClass); + jLevel = GffAddByte(jLevel, "LvlStatHitDie", nHitDie); + jLevel = GffAddList(jLevel, "SkillList", jSkillArray); + jLevel = GffAddWord(jLevel, "SkillPoints", 0); + jLevel = JsonObjectSet(jLevel, "__struct_id", JsonInt(0)); + json jLevelArray = JsonArray(); + if(nLevels == 0) nLevels = GetLevelByPosition(1, oHenchman); + for(nLevels; nLevels > 0; nLevels--) + { + jLevelArray = JsonArrayInsert(jLevelArray, jLevel); + } + WriteTimestampedLogEntry("pinc_henchmen, 813, Adding LvlStatList to " + GetName(oHenchman)); + return GffAddList(jHenchman, "LvlStatList", jLevelArray); +} +int CanSelectFeat(json jCreature, object oCreature, int nFeat, int nPosition = 1) +{ + // Check if all classes can use. + int n2DAStat = StringToInt(Get2DAString("feat", "ALLCLASSESCANUSE", nFeat)); + if(n2DAStat == 0) + { + int bPass, nClassFeat, nRow, nClass = GetClassByPosition(nPosition, oCreature); + string sClsFeat2DAName = Get2DAString("classes", "FeatsTable", nClass); + int nMaxRow = Get2DARowCount(sClsFeat2DAName); + while(nRow < nMaxRow) + { + nClassFeat = StringToInt(Get2DAString(sClsFeat2DAName, "FeatIndex", nRow)); + if(nClassFeat == nFeat) + { + bPass = TRUE; + break; + } + nRow++; + } + if(!bPass) return FALSE; + } + n2DAStat = StringToInt(Get2DAString("feat", "MINATTACKBONUS", nFeat)); + if(JsonGetInt(GffGetByte(jCreature, "BaseAttackBonus")) < n2DAStat) return FALSE; + n2DAStat = StringToInt(Get2DAString("feat", "MINSTR", nFeat)); + if(JsonGetInt(GffGetByte(jCreature, "Str")) < n2DAStat) return FALSE; + n2DAStat = StringToInt(Get2DAString("feat", "MINDEX", nFeat)); + if(JsonGetInt(GffGetByte(jCreature, "Dex")) < n2DAStat) return FALSE; + n2DAStat = StringToInt(Get2DAString("feat", "MINCON", nFeat)); + if(JsonGetInt(GffGetByte(jCreature, "Con")) < n2DAStat) return FALSE; + n2DAStat = StringToInt(Get2DAString("feat", "MININT", nFeat)); + if(JsonGetInt(GffGetByte(jCreature, "Int")) < n2DAStat) return FALSE; + n2DAStat = StringToInt(Get2DAString("feat", "MINWIS", nFeat)); + if(JsonGetInt(GffGetByte(jCreature, "Wis")) < n2DAStat) return FALSE; + n2DAStat = StringToInt(Get2DAString("feat", "MINCHA", nFeat)); + if(JsonGetInt(GffGetByte(jCreature, "Cha")) < n2DAStat) return FALSE; + n2DAStat = StringToInt(Get2DAString("feat", "MINSPELLLVL", nFeat)); + int nSpellLevel = 0, nClass = GetClassByPosition(nPosition, oCreature); + string s2DAName = Get2DAString("classes", "SpellGainTable", nClass); + int nLevel = GetLevelByPosition(nPosition, oCreature); + if(s2DAName != "") + { + nSpellLevel = StringToInt(Get2DAString(s2DAName, "NumSpellLevels", nLevel - 1)) - 1; + } + if(nSpellLevel < n2DAStat) return FALSE; + n2DAStat = StringToInt(Get2DAString("feat", "PREREQFEAT1", nFeat)); + if(n2DAStat > 0) + { + // ************************************** Add code to search jCreature's feats! + if(!GetHasFeat(n2DAStat, oCreature)) return FALSE; + n2DAStat = StringToInt(Get2DAString("feat", "PREREQFEAT2", nFeat)); + if(!GetHasFeat(n2DAStat, oCreature)) return FALSE; + } + int nIndex; + while(nIndex < 5) + { + n2DAStat = StringToInt(Get2DAString("feat", "OrReqFeat" + IntToString(nIndex), nFeat)); + if(nIndex == 0 && n2DAStat == 0) break; + if(GetHasFeat(n2DAStat, oCreature)) break; + nIndex++; + if(nIndex == 5) return FALSE; + } + string s2DAStat = Get2DAString("feat", "REQSKILL", nFeat); + if(s2DAStat != "") + { + n2DAStat = StringToInt(s2DAStat); + int bCanUse; + if(Get2DAString("skills", "AllClassesCanUse", n2DAStat) == "1") bCanUse = TRUE; + else + { + string sClsSkill2DA = Get2DAString("classes", "SkillsTable", nClass); + int bPass, nClassSkill, nRow, nMaxRow = Get2DARowCount(sClsSkill2DA); + while(nRow < nMaxRow) + { + nClassSkill = StringToInt(Get2DAString(sClsSkill2DA, "SkillIndex", nRow)); + if(nClassSkill == n2DAStat) + { + bCanUse = TRUE; + break; + } + nRow++; + } + } + if(bCanUse) + { + int nSkillReq = StringToInt(Get2DAString("feat", "ReqSkillMinRanks", n2DAStat)); + // ************************** Add code to check jCreatures skills. + if(GetSkillRank(n2DAStat, oCreature, TRUE) < nSkillReq) return FALSE; + } + else return FALSE; + } + s2DAStat = Get2DAString("feat", "REQSKILL2", nFeat); + if(s2DAStat != "") + { + n2DAStat = StringToInt(s2DAStat); + int bCanUse; + if(Get2DAString("skills", "AllClassesCanUse", n2DAStat) == "1") bCanUse = TRUE; + else + { + string sClsSkill2DA = Get2DAString("classes", "SkillsTable", nClass); + int bPass, nClassSkill, nRow, nMaxRow = Get2DARowCount(sClsSkill2DA); + while(nRow < nMaxRow) + { + nClassSkill = StringToInt(Get2DAString(sClsSkill2DA, "SkillIndex", nRow)); + if(nClassSkill == n2DAStat) + { + bCanUse = TRUE; + break; + } + nRow++; + } + } + if(bCanUse) + { + int nSkillReq = StringToInt(Get2DAString("feat", "ReqSkillMinRanks2", n2DAStat)); + if(GetSkillRank(n2DAStat, oCreature, TRUE) < nSkillReq) return FALSE; + } + else return FALSE; + } + n2DAStat = StringToInt(Get2DAString("feat", "MinLevel", nFeat)); + if(n2DAStat > 0) + { + int bPass, nClassPosition, nPositionClass, nPositionLevel; + int nClassRequired = StringToInt(Get2DAString("feat", "MinLevelClass", nFeat)); + while(nClassPosition < AI_MAX_CLASSES_PER_CHARACTER) + { + // ***************************** Rework to check jCreature class list instead. + nPositionClass = GetClassByPosition(nClassPosition, oCreature); + if(nPositionClass == nClassRequired) + { + nPositionLevel = GetLevelByPosition(nClassPosition, oCreature); + if(nPositionLevel < n2DAStat) return FALSE; + else bPass = TRUE; + } + nClassPosition++; + } + if(!bPass) return FALSE; + } + n2DAStat = StringToInt(Get2DAString("feat", "MinFortSave", nFeat)); + if(JsonGetInt(GffGetChar(jCreature, "FortSaveThrow")) < n2DAStat) return FALSE; + s2DAStat = Get2DAString("feat", "PreReqEpic", nFeat); + if(s2DAStat == "1") return FALSE; + return TRUE; +} +json ResetFeats(json jHenchman, object oHenchman) +{ + int nLevel = 0; + // We remake the Feat list if the character doesn't have a level list! + json jFeatList = JsonArray(); + json jFeat; + int nRace = GetRacialType(oHenchman); + string sRace2DAName = Get2DAString("racialtypes", "FeatsTable", nRace); + // Give racial feats. + int nRaceRow, nRaceFeat; + int nRaceMaxRow = Get2DARowCount(sRace2DAName); + while(nRaceRow < nRaceMaxRow) + { + nRaceFeat = StringToInt(Get2DAString(sRace2DAName, "FeatIndex", nRaceRow)); + jFeat = JsonObject(); + jFeat = GffAddWord(jFeat, "Feat", nRaceFeat); + jFeat = JsonObjectSet(jFeat, "__struct_id", JsonInt(1)); + jFeatList = JsonArrayInsert(jFeatList, jFeat); + WriteTimestampedLogEntry("pinc_henchmen, 973, Adding racial feat: " + + Get2DAString("feat", "LABEL", nRaceFeat)); + nRaceRow++; + } + // Give class feats. + int nClass = GetClassByPosition(1, oHenchman); + string sGranted, sList; + string sClsFeat2DAName = Get2DAString("classes", "FeatsTable", nClass); + int nClassRow, nClassFeat, nClassMaxRow = Get2DARowCount(sClsFeat2DAName); + while(nClassRow < nClassMaxRow) + { + sGranted = Get2DAString(sClsFeat2DAName, "GrantedOnLevel", nClassRow); + if(sGranted == "1") + { + sList = Get2DAString(sClsFeat2DAName, "List", nClassRow); + if(sList == "3") + { + nClassFeat = StringToInt(Get2DAString(sClsFeat2DAName, "FeatIndex", nClassRow)); + jFeat = JsonObject(); + jFeat = GffAddWord(jFeat, "Feat", nClassFeat); + jFeat = JsonObjectSet(jFeat, "__struct_id", JsonInt(1)); + jFeatList = JsonArrayInsert(jFeatList, jFeat); + WriteTimestampedLogEntry("pinc_henchmen, 995, Adding class feat: " + + Get2DAString("feat", "LABEL", nClassFeat)); + } + } + nClassRow++; + } + // Give any bonus feats from package. + int nPackageFeat, nPackageRow; + string sBonusFeat2DAName = Get2DAString("classes", "BonusFeatsTable", nClass); + int nNumOfFeats = StringToInt(Get2DAString(sBonusFeat2DAName, "Bonus", nLevel)); + string sPackage2DAName = Get2DAString("packages", "FeatPref2DA", nClass); + int nPackageMaxRow = Get2DARowCount(sPackage2DAName); + // Give bonus feats based on the package. + nPackageRow = 0; + if(nNumOfFeats > 0) + { + while(nPackageRow < nPackageMaxRow) + { + nPackageFeat = StringToInt(Get2DAString(sPackage2DAName, "FeatIndex", nPackageRow)); + nClassRow = 0; + while(nClassRow < nClassMaxRow) + { + nClassFeat = StringToInt(Get2DAString(sClsFeat2DAName, "FeatIndex", nClassRow)); + if(nClassFeat == nPackageFeat) + { + sList = Get2DAString(sClsFeat2DAName, "List", nClassRow); + if((sList == "1" || sList == "2") && CanSelectFeat(jHenchman, oHenchman, nClassFeat)) + { + jFeat = JsonObject(); + jFeat = GffAddWord(jFeat, "Feat", nClassFeat); + jFeat = JsonObjectSet(jFeat, "__struct_id", JsonInt(1)); + jFeatList = JsonArrayInsert(jFeatList, jFeat); + WriteTimestampedLogEntry("pinc_henchmen, 1028, Adding class bonus feat: " + + Get2DAString("feat", "LABEL", nPackageFeat)); + nNumOfFeats--; + } + } + nClassRow++; + } + if(nNumOfFeats < 1) break; + nPackageRow++; + } + } + // Give picked feats from package. + nNumOfFeats = 1; + if(GetHasFeat(FEAT_QUICK_TO_MASTER, oHenchman)) nNumOfFeats++; + nPackageRow = 0; + while(nPackageRow < nPackageMaxRow) + { + nClassRow = 0; + nPackageFeat = StringToInt(Get2DAString(sPackage2DAName, "FeatIndex", nPackageRow)); + if(CanSelectFeat(jHenchman, oHenchman, nPackageFeat)) + { + jFeat = JsonObject(); + jFeat = GffAddWord(jFeat, "Feat", nPackageFeat); + jFeat = JsonObjectSet(jFeat, "__struct_id", JsonInt(1)); + jFeatList = JsonArrayInsert(jFeatList, jFeat); + WriteTimestampedLogEntry("pinc_henchmen, 1053, Adding character bonus feat: " + + Get2DAString("feat", "LABEL", nPackageFeat)); + nNumOfFeats--; + } + if(nNumOfFeats < 1) break; + nPackageRow++; + } + jHenchman = GffReplaceList(jHenchman, "FeatList", jFeatList); + return jHenchman; +} +json ResetSkills(json jHenchman, object oHenchman) +{ + // We remake the Skill List if the character doesn't have a level list! + int nClass = GetClassByPosition(1, oHenchman); + int nSkillPoints, nIntMod = GetAbilityModifier(ABILITY_INTELLIGENCE, oHenchman); + if(nIntMod > 0) nSkillPoints = nIntMod * 4; + if(GetRacialType(oHenchman) == RACIAL_TYPE_HUMAN) nSkillPoints += 4; + nSkillPoints += StringToInt(Get2DAString("classes", "SkillPointBase", nClass)) * 4; + int nMaxRanks = 5; + json jSkillList = JsonArray(); + json jSkill; + // Setup the Skill List. + int nIndex, nSkillMaxRow = Get2DARowCount("skills"); + for(nIndex = 0; nIndex < nSkillMaxRow; nIndex++) + { + jSkill = JsonObject(); + jSkill = GffAddByte(jSkill, "Rank", 0); + jSkill = JsonObjectSet(jSkill, "__struct_id", JsonInt(0)); + jSkillList = JsonArrayInsert(jSkillList, jSkill); + } + // Give skill points based on the package. + int nPackageSkill, nPackageRow, nCurrentRanks, bCrossClass, nClassRow, nNewRanks; + string sPackage2DAName = Get2DAString("packages", "SkillPref2DA", nClass); + int nPackageMaxRow = Get2DARowCount(sPackage2DAName); + string sClass2DAName = Get2DAString("classes", "SkillsTable", nClass); + int nClassMaxRow = Get2DARowCount(sClass2DAName); + nPackageRow = 0; + while(nPackageRow < nPackageMaxRow && nSkillPoints > 0) + { + nPackageSkill = StringToInt(Get2DAString(sPackage2DAName, "SkillIndex", nPackageRow)); + jSkill = JsonArrayGet(jSkillList, nPackageSkill); + nCurrentRanks = JsonGetInt(GffGetByte(jSkill, "Rank")); + nClassRow = 0; + while(nClassRow < nClassMaxRow) + { + if(nPackageSkill == StringToInt(Get2DAString(sClass2DAName, "SkillIndex", nClassRow))) + { + bCrossClass = Get2DAString(sClass2DAName, "ClassSkill", nClassRow) == "0"; + break; + } + nClassRow++; + } + if(bCrossClass) nNewRanks = (nMaxRanks / 2) - nCurrentRanks; + else nNewRanks = nMaxRanks - nCurrentRanks; + if(nNewRanks > nSkillPoints) nNewRanks = nSkillPoints; + if(nNewRanks > 0) + { + jSkill = GffReplaceByte(jSkill, "Rank", nCurrentRanks + nNewRanks); + jSkillList = JsonArraySet(jSkillList, nPackageSkill, jSkill); + WriteTimestampedLogEntry("pinc_henchmen, 1110, Adding " + IntToString(nNewRanks) + + " ranks to " + Get2DAString("skills", "Label", nPackageSkill)); + nSkillPoints -= nNewRanks; + } + nPackageRow++; + } + jHenchman = GffReplaceList(jHenchman, "SkillList", jSkillList); + return jHenchman; +} +json ResetSpellsKnown(json jClass, object oHenchman) +{ + int nClass = GetClassByPosition(1, oHenchman); + if(Get2DAString("classes", "SpellCaster", nClass) == "0") return jClass; + int nLevel = 0; + // We remake the Known spell list if the character doesn't have a level list! + json jKnownList, jMemorizedList; + json jSpell, jSpellsPerDayList; + int bMemorizesSpells = StringToInt(Get2DAString("classes", "MemorizesSpells", nClass)); + int bSpellBookRestricted = StringToInt(Get2DAString("classes", "SpellBookRestricted", nClass)); + string sSpellKnown2DAName = Get2DAString("classes", "SpellKnownTable", nClass); + string sSpellGained2DAName = Get2DAString("classes", "SpellGainTable", nClass); + string sSpellTableColumn = Get2DAString("classes", "SpellTableColumn", nClass); + string sSpellPackage2DAName = Get2DAString("packages", "SpellPref2DA", nClass); + int nPackageSpell, nPackageRow; + int nPackageMaxRow = Get2DARowCount(sSpellPackage2DAName); + int nKnownSpellIndex, nSpellsKnown, nAbility, nSpellLevel = 0; + string sKnownListName, sSpellLevel, sPackageSpellLevel, sAbility; + // Cycle through all spell levels and reset. + while(nSpellLevel < 10) + { + sSpellLevel = IntToString(nSpellLevel); + WriteTimestampedLogEntry("pinc_henchmen, 1143, Checking Spell Level: " + sSpellLevel); + // Recreate the 0th and 1st level based on the package. + if(nSpellLevel < 2 && bSpellBookRestricted) + { + // Spellbook restricted that don't have a SpellsKnown2DAName + // get to keep all 0th level spells so we skip them. Example:Wizard + if(nSpellLevel != 0 || sSpellKnown2DAName != "") + { + // Classes that are spell book restricted but don't have a SpellKnownTable + // get 3 spells + Ability Modifier worth of spells like a wizard. + if(sSpellKnown2DAName == "") + { + sAbility = Get2DAString("classes", "SpellCastingAbil", nClass); + if(sAbility == "INT") nAbility = ABILITY_INTELLIGENCE; + else if(sAbility == "WIS") nAbility = ABILITY_WISDOM; + else if(sAbility == "CHA") nAbility = ABILITY_CHARISMA; + nSpellsKnown = 3 + GetAbilityModifier(nAbility, oHenchman); + } + else + { + nSpellsKnown = StringToInt(Get2DAString(sSpellKnown2DAName, "SpellLevel" + sSpellLevel, nLevel)); + } + WriteTimestampedLogEntry("pinc_henchmen, 1165, nSpellsKnown: " + IntToString(nSpellsKnown)); + jKnownList = JsonArray(); + nPackageRow = 0; + while(nPackageRow < nPackageMaxRow && nSpellsKnown > 0) + { + nPackageSpell = StringToInt(Get2DAString(sSpellPackage2DAName, "SpellIndex", nPackageRow)); + sPackageSpellLevel = Get2DAString("spells", sSpellTableColumn, nPackageSpell); + if(sPackageSpellLevel == sSpellLevel) + { + jSpell = JsonObject(); + jSpell = GffAddWord(jSpell, "Spell", nPackageSpell); + jSpell = JsonObjectSet(jSpell, "__struct_id", JsonInt(3)); + jKnownList = JsonArrayInsert(jKnownList, jSpell); + WriteTimestampedLogEntry("pinc_henchmen, 1178, Adding known spell: " + + Get2DAString("spells", "LABEL", nPackageSpell)); + nSpellsKnown--; + } + nPackageRow++; + } + if(JsonGetLength(jKnownList) == 0) + { + jClass = GffRemoveList(jClass, "KnownList" + sSpellLevel); + WriteTimestampedLogEntry("pinc_henchmen, 1187, Removing KnownList" + sSpellLevel); + } + else if(JsonGetType(GffGetList(jClass, "KnownList" + sSpellLevel)) != JSON_TYPE_NULL) + { + jClass = GffReplaceList(jClass, "KnownList" + sSpellLevel, jKnownList); + } + else jClass = GffAddList(jClass, "KnownList" + sSpellLevel, jKnownList); + } + } + // Remove all other known spell levels and memorized levels. + else + { + jKnownList = GffGetList(jClass, "KnownList" + sSpellLevel); + if(JsonGetType(jKnownList) != JSON_TYPE_NULL) + { + jClass = GffRemoveList(jClass, "KnownList" + sSpellLevel); + WriteTimestampedLogEntry("pinc_henchmen, 1203, Removing KnownList" + sSpellLevel); + } + } + if(bMemorizesSpells) + { + jMemorizedList = GffGetList(jClass, "MemorizedList" + sSpellLevel); + if(JsonGetType(jMemorizedList) != JSON_TYPE_NULL) + { + jClass = GffRemoveList(jClass, "MemorizedList" + sSpellLevel); + WriteTimestampedLogEntry("pinc_henchmen, 1210, Removing MemorizedList" + sSpellLevel); + } + } + else + { + jSpellsPerDayList = GffGetList(jClass, "SpellsPerDayList"); + nSpellsKnown = StringToInt(Get2DAString(sSpellGained2DAName, "SpellLevel"+ sSpellLevel, nLevel)); + jSpell = JsonArrayGet(jSpellsPerDayList, nSpellLevel); + jSpell = GffReplaceByte(jSpell, "NumSpellsLeft", nSpellsKnown); + jSpellsPerDayList = JsonArraySet(jSpellsPerDayList, nSpellLevel, jSpell); + jClass = GffReplaceList(jClass, "SpellsPerDayList", jSpellsPerDayList); + WriteTimestampedLogEntry("pinc_henchmen, 1223, Setting SpellsPerDay to " + + IntToString(nSpellsKnown)); + } + nSpellLevel++; + } + return jClass; +} +object ResetCharacter(object oPC, object oHenchman) +{ + SetLocalInt(oPC, "AI_IGNORE_NO_ASSOCIATE", TRUE); + RemoveHenchman(oPC, oHenchman); + json jHenchman = ObjectToJson(oHenchman, TRUE); + json jClassList = GffGetList(jHenchman, "ClassList"); + json jClass = JsonArrayGet(jClassList, 0); + // Set the Class list to the first class only and put at level 1. + int nClass = JsonGetInt(JsonObjectGet(jClass, "Class")); + jClass = GffReplaceShort(jClass, "ClassLevel", 1); + // Delete extra classes. + int nClassIndex = JsonGetLength(jClassList) - 1; + while(nClassIndex > 0) + { + jClassList = JsonArrayDel(jClassList, nClassIndex--); + } + int nHitPoints = StringToInt(Get2DAString("classes", "HitDie", nClass)); + int nMod = JsonGetInt(GffGetByte(jHenchman, "Con")); + if(nMod > 9) nHitPoints += (nMod - 10) / 2; + else nHitPoints += (nMod - 11) / 2; + jHenchman = GffReplaceShort(jHenchman, "CurrentHitPoints", nHitPoints); + jHenchman = GffReplaceShort(jHenchman, "HitPoints", nHitPoints); + jHenchman = GffReplaceShort(jHenchman, "MaxHitPoints", nHitPoints); + jHenchman = GffReplaceDword(jHenchman, "Experience", 0); + jHenchman = GffReplaceFloat(jHenchman, "ChallengeRating", 1.0); + string s2DA = Get2DAString("classes", "AttackBonusTable", nClass); + int nAtk = StringToInt(Get2DAString(s2DA, "BAB", 0)); + jHenchman = GffReplaceByte(jHenchman, "BaseAttackBonus", nAtk); + s2DA = Get2DAString("classes", "SavingThrowTable", nClass); + int nSave = StringToInt(Get2DAString(s2DA, "FortSave", 0)); + jHenchman = GffReplaceChar(jHenchman, "FortSaveThrow", nSave); + nSave = StringToInt(Get2DAString(s2DA, "RefSave", 0)); + jHenchman = GffReplaceChar(jHenchman, "RefSaveThrow", nSave); + nSave = StringToInt(Get2DAString(s2DA, "WillSave", 0)); + jHenchman = GffReplaceChar(jHenchman, "WillSaveThrow", nSave); + json jLvlStatList = GffGetList(jHenchman, "LvlStatList"); + if(JsonGetType(jLvlStatList) != JSON_TYPE_NULL) + { + WriteTimestampedLogEntry("pinc_henchmen 1275, jLvlStatList: " + JsonDump(jLvlStatList, 4)); + int nLevel = 1, nLevelTrack = 1; + int nAbilityStatIncrease, nAbility; + string sAbility; + json jAbility; + json jLevel = JsonArrayGet(jLvlStatList, nLevel); + while(JsonGetType(jLevel) != JSON_TYPE_NULL) + { + WriteTimestampedLogEntry("inc_henchmen, 1297, Checking level " + IntToString(nLevelTrack)); + // Remove all Ability score increases for each level from ability scores. + jAbility = GffGetByte(jLevel, "LvlStatAbility"); + if(JsonGetType(jAbility) != JSON_TYPE_NULL) + { + nAbilityStatIncrease = JsonGetInt(jAbility); + if(nAbilityStatIncrease == ABILITY_STRENGTH) sAbility = "Str"; + if(nAbilityStatIncrease == ABILITY_DEXTERITY) sAbility = "Dex"; + if(nAbilityStatIncrease == ABILITY_CONSTITUTION) sAbility = "Con"; + if(nAbilityStatIncrease == ABILITY_INTELLIGENCE) sAbility = "Int"; + if(nAbilityStatIncrease == ABILITY_WISDOM) sAbility = "Wis"; + if(nAbilityStatIncrease == ABILITY_CHARISMA) sAbility = "Cha"; + nAbility = JsonGetInt(GffGetByte(jHenchman, sAbility)) - 1; + jHenchman = GffReplaceByte(jHenchman, sAbility, nAbility); + WriteTimestampedLogEntry("pinc_henchmen, 1314, Removing " + sAbility + " level bonus ability score point."); + } + jLvlStatList = JsonArrayDel(jLvlStatList, nLevel); + // Note: nLevel is not incremented since we are removing the previous level. + // there for when we get the same level again its the next level! + jLevel = JsonArrayGet(jLvlStatList, nLevel); + //SendMessageToPC(oPC, "jLvlStatList: " + JsonDump(jLvlStatList, 4)); + nLevelTrack++; + } + jHenchman = GffRemoveList(jHenchman, "LvlStatList"); + } + jHenchman = CreateLevelStatList(jHenchman, oHenchman, oPC, 1); + jHenchman = ResetSkills(jHenchman, oHenchman); + jHenchman = ResetFeats(jHenchman, oHenchman); + jClass = ResetSpellsKnown(jClass, oHenchman); + jClassList = JsonArraySet(jClassList, 0, jClass); + jHenchman = GffReplaceList(jHenchman, "ClassList", jClassList); + //WriteTimestampedLogEntry("pinc_henchmen 1397, jHenchman: " + JsonDump(jHenchman, 4)); + location lLocation = GetLocation(oHenchman); + int nFamiliar, nCompanion; + object oCompanion = GetAssociate(ASSOCIATE_TYPE_FAMILIAR, oHenchman); + if(oCompanion != OBJECT_INVALID) nFamiliar = TRUE; + oCompanion = GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION, oHenchman); + if(oCompanion != OBJECT_INVALID) nCompanion = TRUE; + AssignCommand(oHenchman, SetIsDestroyable(TRUE, FALSE, FALSE)); + DestroyObject(oHenchman); + oHenchman = ai_AddHenchman(oPC, jHenchman, lLocation, nFamiliar, nCompanion); + return oHenchman; +} +// ********* New Henchman windows ********** +void CreateCharacterEditGUIPanel(object oPC, object oHenchman) +{ + // Set window to not save until it has been created. + SetLocalInt(oPC, "0_No_Win_Save", TRUE); + DelayCommand(0.5f, DeleteLocalInt (oPC, "0_No_Win_Save")); + // Group 1 (Portrait)******************************************************* 151 / 73 + // Group 1 Row 1 *********************************************************** 350 / 91 + json jGroupRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + jGroupRow = CreateTextEditBox (jGroupRow, "name_placeholder", "char_name", 15, FALSE, 140.0, 20.0); + jGroupRow = JsonArrayInsert(jGroupRow, NuiSpacer()); + // Add the group row to the group column. + json jGroupCol = JsonArrayInsert(JsonArray(), NuiRow(jGroupRow)); + // Group 1 Row 1 *********************************************************** 350 / 91 + jGroupRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + jGroupRow = CreateTextEditBox (jGroupRow, "port_placeholder", "port_name", 15, FALSE, 140.0, 20.0, "port_tooltip"); + jGroupRow = JsonArrayInsert(jGroupRow, NuiSpacer()); + // Add the group row to the group column. + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + // Group 1 Row 2 *********************************************************** 350 / 259 + jGroupRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + jGroupRow = CreateImage(jGroupRow, "", "port_resref", NUI_ASPECT_EXACTSCALED, NUI_HALIGN_CENTER, NUI_VALIGN_TOP, 140.0f, 160.0f); + jGroupRow = JsonArrayInsert(jGroupRow, NuiSpacer()); + // Add the group row to the group column. + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + // Group 1 Row 3 *********************************************************** 350 / 292 + jGroupRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + jGroupRow = CreateButton (jGroupRow, "<", "btn_portrait_prev", 42.0f, 25.0f); + jGroupRow = CreateButton (jGroupRow, "Set", "btn_portrait_ok", 44.0f, 25.0f); + jGroupRow = CreateButton (jGroupRow, ">", "btn_portrait_next", 42.0f, 25.0f); + jGroupRow = JsonArrayInsert(jGroupRow, NuiSpacer()); + // Add group row to the group column. + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + // Group 1 Row 4 *********************************************************** 350 / 91 + jGroupRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + jGroupRow = CreateLabel(jGroupRow, "Sound Set", "lbl_sound_set", 140.0, 10.0f, NUI_HALIGN_CENTER, NUI_VALIGN_BOTTOM); + jGroupRow = JsonArrayInsert(jGroupRow, NuiSpacer()); + // Add the group row to the group column. + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + // Group 1 Row 5 *********************************************************** 350 / 325 + jGroupRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + jGroupRow = CreateCombo(jGroupRow, ArrayInsertSoundSets(oHenchman), "cmb_soundset", 140.0, 25.0); + jGroupRow = JsonArrayInsert(jGroupRow, NuiSpacer()); + // Add group row to the group column. + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + json jRow = JsonArrayInsert(JsonArray(), NuiGroup(NuiCol(jGroupCol))); + // Group 2 (Stats)********************************************************** 151 / 73 + // Group 2 Row 1 *********************************************************** 350 / 91 + jGroupRow = CreateLabel(JsonArray(), "", "lbl_stats", 150.0, 15.0, 0, NUI_VALIGN_BOTTOM, 0.0); + // Add group row to the group column. + jGroupCol = JsonArrayInsert(JsonArray(), NuiRow(jGroupRow)); + + // Group 2 Row 2 *********************************************************** 350 / 243 + //json jAlign = CreateOptionsAlignment(oHenchman, 0); + //jGroupRow = CreateOptions(JsonArray(), "opt_lawchaos", NUI_DIRECTION_HORIZONTAL, jAlign, 60.0, 35.0); + // Add group row to the group column. + //jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + // Group 2 Row 3 *********************************************************** 350 / 243 + //jAlign = CreateOptionsAlignment(oHenchman, 1); + //jGroupRow = CreateOptions(JsonArray(), "opt_goodevil", NUI_DIRECTION_HORIZONTAL, jAlign, 60.0, 35.0); + //jGroupRow = JsonArrayInsert(jGroupRow, NuiSpacer()); + // Add group row to the group column. + //jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + // Group 2 Row 2 *********************************************************** 350 / 243 + json jClasses = CreateOptionsClasses(oHenchman); + jGroupRow = CreateOptions(JsonArray(), "opt_classes", NUI_DIRECTION_VERTICAL, jClasses, 150.0, 144.0); + // Add group row to the group column. + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + // Group 2 Row 3 *********************************************************** 350 / 276 + jGroupRow = CreateButton(JsonArray(), "Level Up", "btn_level_up", 150.0f, 25.0f, -1.0, "btn_level_up_tooltip"); + // Add group row to the group column. + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + // Group 2 Row 4 *********************************************************** 350 / 309 + jGroupRow = CreateButton (JsonArray(), "Reset Character", "btn_reset", 150.0f, 25.0f, -1.0, "btn_reset_tooltip"); + // Add group row to the group column. + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + // Group 2 Row 5 *********************************************************** 350 / 342 + jGroupRow = CreateCombo(JsonArray(), jArrayInsertClasses(), "cmb_class", 150.0, 25.0); + // Add group row to the group column. + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + // Group 2 Row 6 *********************************************************** 350 / 375 + int nClassOption = GetLocalInt(oHenchman, "CLASS_OPTION_POSITION"); + int nClass = GetClassByPosition(nClassOption + 1, oHenchman); + int bNoClass = FALSE; + if(nClass == CLASS_TYPE_INVALID) + { + nClass = GetLocalInt(oHenchman, "CLASS_SELECTED_" + IntToString(nClassOption + 1)); + bNoClass = TRUE; + } + string sClass = IntToString(nClass); + jGroupRow = CreateCombo(JsonArray(), ArrayInsertPackages(sClass), "cmb_package", 150.0, 25.0); + // Add group row to the group column. + jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow)); + jRow = JsonArrayInsert(jRow, NuiGroup(NuiCol(jGroupCol))); + // Add the row to the column. + json jCol = JsonArrayInsert(JsonArray(), NuiRow(jRow)); + // Row 5 (text edit box)**************************************************** 350 / 518 + jRow = CreateTextEditBox(JsonArray(), "desc_placeholder", "desc_value", 1000, TRUE, 350.0, 150.0, "desc_tooltip"); + // Add the row to the column. + jCol = JsonArrayInsert(jCol, NuiRow (jRow)); + // Row 6 (button)*********************************************************** 350/ 546 + jRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + jRow = CreateButton (jRow, "Save Description", "btn_desc_save", 150.0f, 20.0f); + jRow = JsonArrayInsert(jRow, NuiSpacer()); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow (jRow)); + // Set the Layout of the window. + json jLayout = NuiCol (jCol); + // Get the window location to restore it from the database. + CheckHenchmanDataAndInitialize(oPC, "0"); + json jData = GetHenchmanDbJson(oPC, "henchman", "0"); + json jGeometry = JsonObjectGet(jData, "henchman_edit_nui"); + float fX = JsonGetFloat(JsonObjectGet(jGeometry, "x")); + float fY = JsonGetFloat(JsonObjectGet(jGeometry, "y")); + if(fX == 0.0 && fY == 0.0) + { + fX = -1.0; + fY = -1.0; + } + string sName = GetName(oHenchman); + if(GetStringRight(sName, 1) == "s") sName = sName + "'"; + else sName = sName + "'s"; + int nToken = SetWindow (oPC, jLayout, "henchman_edit_nui", sName + " Character editor", + fX, fY, 380.0, 588.0, FALSE, FALSE, TRUE, FALSE, TRUE, "pe_henchmen"); + // Set all binds, events, and watches. + int nID = GetPortraitId (oPC); + NuiSetUserData(oPC, nToken, JsonInt(nID)); + string sResRef = GetPortraitResRef(oHenchman); + NuiSetBindWatch(oPC, nToken, "window_geometry", TRUE); + NuiSetBind(oPC, nToken, "char_name", JsonString(GetName(oHenchman))); + NuiSetBindWatch(oPC, nToken, "char_name", TRUE); + NuiSetBind(oPC, nToken, "char_name_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "port_name", JsonString(sResRef)); + NuiSetBindWatch(oPC, nToken, "port_name", TRUE); + NuiSetBind(oPC, nToken, "port_name_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "port_resref_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "port_resref_image", JsonString(sResRef + "l")); + NuiSetBind(oPC, nToken, "port_tooltip", JsonString (" You may also type the portrait file name.")); + // Set buttons active. + NuiSetBind(oPC, nToken, "btn_portrait_prev_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_portrait_next_event", JsonBool(TRUE)); + int nSelection = GetSelectionBySoundSet2DA(oHenchman, GetSoundset(oHenchman)); + NuiSetBind(oPC, nToken, "cmb_soundset_selected", JsonInt(nSelection)); + NuiSetBindWatch(oPC, nToken, "cmb_soundset_selected", TRUE); + NuiSetBind(oPC, nToken, "cmb_soundset_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_desc_save_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_portrait_ok_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "desc_tooltip", JsonString(" You can use color codes!")); + string sDescription = GetDescription(oHenchman); + NuiSetBind(oPC, nToken, "desc_value_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "desc_value", JsonString (sDescription)); + // Setup the henchman window. + string sStats = GetAlignText(oHenchman) + " "; + if(GetGender(oHenchman) == GENDER_MALE) sStats += "Male "; + else sStats += "Female "; + sStats += GetStringByStrRef (StringToInt (Get2DAString ("racialtypes", "Name", GetRacialType (oHenchman)))); + NuiSetBind(oPC, nToken, "lbl_stats_label", JsonString(sStats)); + json jHenchman = ObjectToJson(oHenchman); + NuiSetBind(oPC, nToken, "opt_classes_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "opt_classes_value", JsonInt(nClassOption)); + NuiSetBind(oPC, nToken, "btn_level_up_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_level_up_tooltip", JsonString(" Levels the character up by one level in selected class.")); + if(ai_GetIsCharacter(oHenchman)) NuiSetBind(oPC, nToken, "btn_reset_event", JsonBool(FALSE)); + else NuiSetBind(oPC, nToken, "btn_reset_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "btn_reset_tooltip", JsonString(" Resets the character to level 1.")); + nSelection = GetSelectionByClass2DA(nClass); + NuiSetBind(oPC, nToken, "cmb_class_selected", JsonInt(nSelection)); + NuiSetBindWatch(oPC, nToken, "cmb_class_selected", bNoClass); + NuiSetBind(oPC, nToken, "cmb_class_event", JsonBool(bNoClass)); + int nPackage = GetLocalInt(oHenchman, "PACKAGE_SELECTED_" + IntToString(nClassOption + 1)); + if(nPackage == 0) + { + nPackage = GetPackageBySelection2DA(sClass, 0); + SetLocalInt(oHenchman, "PACKAGE_SELECTED_" + IntToString(nClassOption + 1), nPackage); + } + NuiSetBind(oPC, nToken, "cmb_package_selected", JsonInt(GetSelectionByPackage2DA(sClass, nPackage))); + NuiSetBindWatch(oPC, nToken, "cmb_package_selected", bNoClass); + NuiSetBind(oPC, nToken, "cmb_package_event", JsonBool(bNoClass)); +} +void CreateCharacterDescriptionNUI(object oPC, string sName, string sIcon, string sDescription) +{ + // Row 1 ******************************************************************* 500 / 469 + json jRow = CreateImage(JsonArray(), "", "char_icon", NUI_ASPECT_FIT, NUI_HALIGN_CENTER, NUI_VALIGN_MIDDLE, 40.0, 40.0); + jRow = CreateTextBox(jRow, "char_text", 380.0, 400.0); + // Add row to the column. + json jCol = JsonArrayInsert(JsonArray(), NuiRow(jRow)); + // Row 2 ******************************************************************* 500 / 522 + jRow = JsonArrayInsert(JsonArray(), NuiSpacer()); + jRow = CreateButton(jRow, "OK", "btn_ok", 150.0f, 45.0f); + // Add row to the column. + jCol = JsonArrayInsert(jCol, NuiRow(jRow)); + // Set the Layout of the window. + json jLayout = NuiCol(jCol); + int nToken = SetWindow(oPC, jLayout, "char_description_nui", sName, + -1.0, -1.0, 460.0f, 537.0 + 12.0f, FALSE, FALSE, TRUE, FALSE, TRUE, "pe_henchmen"); + json jData = JsonArrayInsert(JsonArray(), JsonString(ObjectToString(oPC))); + NuiSetUserData(oPC, nToken, jData); + // Row 1 + NuiSetBind(oPC, nToken, "char_icon_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "char_icon_image", JsonString(sIcon)); + NuiSetBind(oPC, nToken, "char_text_event", JsonBool(TRUE)); + NuiSetBind(oPC, nToken, "char_text", JsonString(sDescription)); + // Row 2 + NuiSetBind(oPC, nToken, "btn_ok_event", JsonBool(TRUE)); +} + diff --git a/src/module/nss/xx_pc_1_hb.nss b/src/module/nss/xx_pc_1_hb.nss new file mode 100644 index 0000000..7dac876 --- /dev/null +++ b/src/module/nss/xx_pc_1_hb.nss @@ -0,0 +1,79 @@ +/*////////////////////////////////////////////////////////////////////////////// + Script: xx_pc_1_hb + Programmer: Philos +//////////////////////////////////////////////////////////////////////////////// + Player OnHeart beat script for PC AI; + This will usually fire every 6 seconds (1 game round). +*/////////////////////////////////////////////////////////////////////////////// +#include "0i_menus" +void ai_ActionFollow(object oCreature, object oTarget) +{ + if(GetLocalInt(OBJECT_SELF, AI_CURRENT_ACTION_MODE) == AI_LAST_ACTION_MOVE) + { + float fDistance = GetDistanceBetween(oCreature, oTarget); + float fFollowDistance = ai_GetFollowDistance(oCreature); + if(fDistance > fFollowDistance && !ai_GetIsInCombat(oCreature)) + { + if(fDistance > fFollowDistance * 5.0) AssignCommand(oCreature, JumpToObject(oTarget)); + else + { + ClearAllActions(); + ActionMoveToObject(oTarget, TRUE, fFollowDistance); + } + } + DelayCommand(1.0, ai_ActionFollow(oCreature, oTarget)); + } +} +void main() +{ + object oCreature = OBJECT_SELF; + if(AI_DEBUG) ai_Debug("xx_pc_1_hb", "12", GetName(oCreature) + " heartbeat."); + if(ai_GetIsBusy(oCreature) || ai_Disabled(oCreature)) return; + if(ai_GetIsInCombat(oCreature)) + { + ai_DoAssociateCombatRound(oCreature); + return; + } + if(ai_CheckForCombat(oCreature, FALSE)) return; + if(IsInConversation(oCreature)) return; + if(ai_TryHealing(oCreature, oCreature)) return; + if(ai_CheckNearbyObjects(oCreature)) return; + if(ai_GetAIMode(oCreature, AI_MODE_AGGRESSIVE_STEALTH)) + { + if(AI_DEBUG) ai_Debug("xx_ch_1_hb", "47", "Going into stealth mode!"); + int nStealth = GetSkillRank(SKILL_HIDE, oCreature); + nStealth += GetSkillRank(SKILL_MOVE_SILENTLY, oCreature); + if(nStealth / 2 >= ai_GetCharacterLevels(oCreature)) + { + SetActionMode(oCreature, ACTION_MODE_STEALTH, TRUE); + SetActionMode(oCreature, ACTION_MODE_DETECT, FALSE); + } + } + else + { + SetActionMode(oCreature, ACTION_MODE_STEALTH, FALSE); + if(ai_GetAIMode(oCreature, AI_MODE_AGGRESSIVE_SEARCH)) + { + if(AI_DEBUG) ai_Debug("xx_ch_1_hb", "61", "Going into search mode!"); + SetActionMode(oCreature, ACTION_MODE_DETECT, TRUE); + } + else SetActionMode(oCreature, ACTION_MODE_DETECT, FALSE); + } + // Finally we check to make sure we are following. + if(GetCurrentAction(oCreature) != ACTION_FOLLOW) + { + // Follow associate. + object oAssociate = GetLocalObject(oCreature, AI_FOLLOW_TARGET); + if(oAssociate == OBJECT_INVALID || GetMaster(oAssociate) != oCreature) return; + if(GetDistanceBetween(oCreature, oAssociate) > ai_GetFollowDistance(oCreature)) + { + ai_ClearCreatureActions(); + if(AI_DEBUG) ai_Debug("XX_pc_1_hb", "75", "Follow master: " + + " Stealth: " + IntToString(ai_GetAIMode(oCreature, AI_MODE_AGGRESSIVE_STEALTH)) + + " Search: " + IntToString(ai_GetAIMode(oCreature, AI_MODE_AGGRESSIVE_SEARCH))); + SetLocalInt(oCreature, AI_CURRENT_ACTION_MODE, AI_LAST_ACTION_MOVE); + ai_ActionFollow(oCreature, oAssociate); + //ActionMoveToObject(oAssociate, TRUE, ai_GetFollowDistance(oCreature)); + } + } +} diff --git a/src/module/nss/xx_pc_2_percept.nss b/src/module/nss/xx_pc_2_percept.nss new file mode 100644 index 0000000..9731f70 --- /dev/null +++ b/src/module/nss/xx_pc_2_percept.nss @@ -0,0 +1,107 @@ +/*////////////////////////////////////////////////////////////////////////////// + Script: xx_pc_2_percept + Programmer: Philos +//////////////////////////////////////////////////////////////////////////////// + Player OnPerception script for PC AI; + There are 4 types of perception - Heard, Inaudible, Seen, Vanished. + Only one type will ever be true in an event trigger. + The order of trigger is Heard/Seen and Inaudible/Vanished. + There are two states of percepion Heard and Seen. + These states can be set at the same time thus a heard event can see the creature. + Fires when ever one of these states changes from TRUE to FALSE or FALSE to TRUE. +*/////////////////////////////////////////////////////////////////////////////// +#include "0i_associates" +void main() +{ + object oCreature = OBJECT_SELF; + object oLastPerceived = GetLastPerceived(); + if(AI_DEBUG) + { + if(GetLastPerceptionHeard ()) + { + ai_Debug("xx_pc_2_percept", "22", GetName(oCreature) + " heard " + + GetName(GetLastPerceived()) + " Distance: " + + FloatToString(GetDistanceBetween(GetLastPerceived(), oCreature), 0, 2) + + " Seen: " + IntToString(GetObjectSeen(oLastPerceived, oCreature)) + "."); + } + if(GetLastPerceptionSeen ()) + { + ai_Debug("xx_pc_2_percept", "29", GetName(oCreature) + " sees " + + GetName(GetLastPerceived()) + " Distance: " + + FloatToString(GetDistanceBetween(GetLastPerceived(), oCreature), 0, 2) + "."); + } + if(GetLastPerceptionVanished ()) + { + ai_Debug("xx_pc_2_percept", "35", GetName(oCreature) + " lost sight of " + + GetName(GetLastPerceived()) + "."); + } + } + // We do nothing on Inaudibles so drop out early! + if(GetLastPerceptionInaudible()) + { + ai_Debug("xx_pc_2_percept", "42", GetName(oCreature) + " lost sound of " + + GetName(GetLastPerceived()) + "."); + return; + } + if(AI_DEBUG) ai_Debug("xx_pc_2_percept", "46", "Dead? " + IntToString(GetIsDead(oLastPerceived)) + + " Enemy? " + IntToString(GetIsEnemy(oLastPerceived, oCreature))); + if(ai_Disabled(oCreature)) return; + if(GetIsDead(oLastPerceived) || !GetIsEnemy(oLastPerceived, oCreature)) return; + // All code below assumes the perceived creature is an enemy and is alive! + // **************************** ENEMY HEARD ******************************** + if(GetLastPerceptionHeard()) + { + // Since Heard is run before Seen, but the values are set at the same + // time we can skip heard checks on heard & seen creatures! + if(GetObjectSeen(oLastPerceived, oCreature)) + { + // If the creature we are perceiving was our invisible creature then + // remove that they are invisible. + if(oLastPerceived == GetLocalObject(oCreature, AI_IS_INVISIBLE)) + { + DeleteLocalObject(oCreature, AI_IS_INVISIBLE); + } + ai_AssociateEvaluateNewThreat(oCreature, oLastPerceived, AI_I_SEE_AN_ENEMY); + } + else ai_AssociateEvaluateNewThreat(oCreature, oLastPerceived, AI_I_HEARD_AN_ENEMY); + return; + } + // **************************** ENEMY SEEN ********************************* + if(GetLastPerceptionSeen()) + { + // If the creature we are perceiving was our invisible creature then + // remove that they are invisible. + if(oLastPerceived == GetLocalObject(oCreature, AI_IS_INVISIBLE)) + { + DeleteLocalObject(oCreature, AI_IS_INVISIBLE); + } + ai_AssociateEvaluateNewThreat(oCreature, oLastPerceived, AI_I_SEE_AN_ENEMY); + return; + } + // **************************** ENEMY VANISHED ***************************** + if(GetLastPerceptionVanished()) + { + // Lets keep a mental note of the invisible creature. + SetLocalObject(oCreature, AI_IS_INVISIBLE, oLastPerceived); + if(AI_DEBUG) ai_Debug("xx_pc_2_percept", "86", " We saw " + GetName(oLastPerceived) + " disappear!"); + if(ai_GetIsBusy(oCreature)) return; + // If in combat check to see if our target disappeared. + // If they have and we are not in melee with them then reevaluate combat + // since we lost our target. + if(ai_GetIsInCombat(oCreature)) + { + if(AI_DEBUG) ai_Debug("xx_pc_2_percept", "93", "Is this our target? " + + IntToString(ai_GetAttackedTarget(oCreature, TRUE, TRUE) == oLastPerceived)); + if(ai_GetAttackedTarget(oCreature, TRUE, TRUE) == oLastPerceived) + { + ai_DoAssociateCombatRound(oCreature); + } + return; + } + // If they are not invisible then that means they left our perception + // range and we need follow them. + ActionMoveToObject(oLastPerceived, TRUE, AI_RANGE_CLOSE); + } + // **************************** ENEMY INAUDIBLE***************************** + // Not used. +} diff --git a/src/module/nss/xx_pc_3_endround.nss b/src/module/nss/xx_pc_3_endround.nss new file mode 100644 index 0000000..51126e6 --- /dev/null +++ b/src/module/nss/xx_pc_3_endround.nss @@ -0,0 +1,60 @@ +/*////////////////////////////////////////////////////////////////////////////// + Script: xx_pc_3_endround + Programmer: Philos +//////////////////////////////////////////////////////////////////////////////// + Player OnCombatRoundEnd event script for PC AI; + 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_associates" +void main() +{ + object oCreature = OBJECT_SELF; + if(AI_DEBUG) ai_Debug("xx_pc_3_endround", "20", GetName(oCreature) + " ends combat round."); + if(ai_Disabled(oCreature)) return; + // 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); + } + int nAction = GetCurrentAction(oCreature); + if(AI_DEBUG) ai_Debug("xx_pc_3_endround", "32", "nAction: " + IntToString(nAction)); + switch(nAction) + { + // These actions are uninteruptable. + case ACTION_MOVETOPOINT : + case ACTION_CASTSPELL : + case ACTION_ITEMCASTSPELL : + case ACTION_COUNTERSPELL : return; + // Might be doing a special action that is not a defined action. + case ACTION_INVALID : + { + int nCombatWait = GetLocalInt(oCreature, AI_COMBAT_WAIT_IN_SECONDS); + if(AI_DEBUG) ai_Debug("xx_pc_3_endround", "47", "nCombatWait: " + IntToString(nCombatWait)); + if(nCombatWait) + { + if(ai_IsInCombatRound(oCreature, nCombatWait)) return; + DeleteLocalInt(oCreature, AI_COMBAT_WAIT_IN_SECONDS); + } + break; + } + // We always want to interupt an attack action at the end of a round (6 seconds). + case ACTION_ATTACKOBJECT : + { + if(ai_IsInCombatRound(oCreature, AI_COMBAT_ROUND_IN_SECONDS)) return; + } + } + if(ai_GetIsInCombat(oCreature)) ai_DoAssociateCombatRound (oCreature); +} + diff --git a/src/module/nss/xx_pc_4_convers.nss b/src/module/nss/xx_pc_4_convers.nss new file mode 100644 index 0000000..413aef1 --- /dev/null +++ b/src/module/nss/xx_pc_4_convers.nss @@ -0,0 +1,30 @@ +/*////////////////////////////////////////////////////////////////////////////// + Script: xx_pc_4_convers + Programmer: Philos +//////////////////////////////////////////////////////////////////////////////// + Player OnDialoge event script for PC AI; + Fires when oCreature has been clicked on for conversation. + Fires when oCreature hears a shout from another creature. + If SetListening is FALSE then oCreature will not "hear" anything. +*/////////////////////////////////////////////////////////////////////////////// +#include "0i_associates" +void main() +{ + object oCreature = OBJECT_SELF; + int nMatch = GetListenPatternNumber(); + object oLastSpeaker = GetLastSpeaker(); + if(AI_DEBUG) ai_Debug("xx_pc_4_convers", "17", GetName(oCreature) + " listens " + + IntToString(nMatch) + " to " + GetName(oLastSpeaker) + "." + + " Searching: " + IntToString(GetLocalInt(oCreature, AI_AM_I_SEARCHING))); + // If we are disabled then we can't listen or talk, Busy is checked in ai_SelectAssociateCommand(). + // Some modules disable the player then talk to them! So it should be ok + // to keep this remarked out. + // Some commands override being busy so we check in ai_SelectAssociateCommand. + if(nMatch != -1) + { + if(!GetFactionEqual(oLastSpeaker, oCreature)) return; + if(!ai_Disabled(oCreature)) ai_SelectAssociateCommand(oCreature, oLastSpeaker, nMatch); + } + else BeginConversation("", oLastSpeaker); +} + diff --git a/src/module/nss/xx_pc_5_phyatked.nss b/src/module/nss/xx_pc_5_phyatked.nss new file mode 100644 index 0000000..1c6ba79 --- /dev/null +++ b/src/module/nss/xx_pc_5_phyatked.nss @@ -0,0 +1,29 @@ +/*////////////////////////////////////////////////////////////////////////////// + Script: xx_pc_5_phyatked + Programmer: Philos +//////////////////////////////////////////////////////////////////////////////// + Player OnPhysicalAttacked event script for PC AI; + Fires for all physical attacks, claws, weapons, fists, bow, etc. + Fires for taunt skill, animal empathy skill. +/*////////////////////////////////////////////////////////////////////////////// +#include "0i_associates" +void main() +{ + object oCreature = OBJECT_SELF; + object oAttacker = GetLastAttacker(); + if(AI_DEBUG) ai_Debug("xx_pc_5_phyatked", "14", GetName(oCreature) + " was attacked by " + + GetName(oAttacker) + "."); + SetLocalObject(oAttacker, AI_ATTACKED_PHYSICAL, oCreature); + if(ai_GetIsBusy(oCreature) || ai_Disabled(oCreature)) return; + if(ai_GetIsInCombat(oCreature)) return; + // We only inform others if attacked when not busy, not disabled, & not in combat. + SetLocalObject(oCreature, AI_MY_TARGET, oAttacker); + SpeakString(AI_ATKED_BY_WEAPON, TALKVOLUME_SILENT_TALK); + // The only way to get here is to not be in combat thus we have not + // perceived them so lets look for them. + if(!ai_CanIAttack(oCreature)) return; + if(GetDistanceBetween(oCreature, oAttacker) < AI_RANGE_CLOSE) ai_DoAssociateCombatRound(oCreature); + else ActionMoveToObject(oAttacker, TRUE, AI_RANGE_CLOSE - 1.0); +} + + diff --git a/src/module/nss/xx_pc_6_damaged.nss b/src/module/nss/xx_pc_6_damaged.nss new file mode 100644 index 0000000..c3d6aaa --- /dev/null +++ b/src/module/nss/xx_pc_6_damaged.nss @@ -0,0 +1,27 @@ +/*////////////////////////////////////////////////////////////////////////////// + Script: xx_pc_6_damaged + Programmer: Philos +//////////////////////////////////////////////////////////////////////////////// + Associate (Summons, Familiars, Companions) OnDamaged script; + Does not fire if the creature dies from the damage. + Does not fire for plot creatures as they take no damage. + May fire before or after OnPhysicalAttacked event. + Fires when EffectDamage is applied to oCreature even if 0 damage. + Fires when a weapon damages a oCreature, but not if resisted. +*/////////////////////////////////////////////////////////////////////////////// +#include "0i_associates" +void main() +{ + object oCreature = OBJECT_SELF; + if(ai_Disabled(oCreature)) return; + // Make sure to clear wounded shout limit if we take damage. See ai_TryHealing. + DeleteLocalInt(oCreature, "AI_WOUNDED_SHOUT_LIMIT"); + object oDamager = GetLastDamager(oCreature); + if(AI_DEBUG) ai_Debug("xx_pc_6_damaged", "18", GetName(oCreature) + " has been damaged by " + GetName(oDamager)); + if(GetObjectType(oDamager) == OBJECT_TYPE_AREA_OF_EFFECT && + ai_IsInADangerousAOE(oCreature, AI_RANGE_BATTLEFIELD, TRUE)) return; + if(ai_GetIsBusy(oCreature) || ai_GetIsInCombat(oCreature)) return; + if(GetDistanceBetween(oCreature, oDamager) < AI_RANGE_CLOSE) ai_DoAssociateCombatRound(oCreature); + else ActionMoveToObject(oDamager, TRUE, AI_RANGE_CLOSE - 1.0); +} + diff --git a/src/module/nss/xx_pc_8_disturb.nss b/src/module/nss/xx_pc_8_disturb.nss new file mode 100644 index 0000000..6440c03 --- /dev/null +++ b/src/module/nss/xx_pc_8_disturb.nss @@ -0,0 +1,21 @@ +/*////////////////////////////////////////////////////////////////////////////// + Script: xx_pc_8_disturb + Programmer: Philos +//////////////////////////////////////////////////////////////////////////////// + Player OnDisturbed event script for PC AI. + Fires when the inventory of oCreature is changed i.e. added or removed. + Creatures can't have items added or removed from its inventory (it's not a + container), then the only way this fires for creatures if something is stolen. +*/////////////////////////////////////////////////////////////////////////////// +#include "0i_associates" +void main() +{ + if(AI_DEBUG) ai_Debug("xx_pc_8_disturb", "14", GetName(OBJECT_SELF) + " is been disturbed!"); + // We do nothing at the moment... lets not mess up our factions ok? + // This should be defined by the server admins and is commented out. + //if(ai_GetIsBusy(OBJECT_SELF, FALSE) || ai_Disabled()) return; + //object oTarget = GetLastDisturbed(); + //if (oTarget != OBJECT_INVALID) ai_DoMonsterCombatRound (); +} + + diff --git a/src/module/nss/xx_pc_b_castat.nss b/src/module/nss/xx_pc_b_castat.nss new file mode 100644 index 0000000..5d4b85f --- /dev/null +++ b/src/module/nss/xx_pc_b_castat.nss @@ -0,0 +1,35 @@ +/*////////////////////////////////////////////////////////////////////////////// + Script: xx_pc_b_castat + Programmer: Philos +//////////////////////////////////////////////////////////////////////////////// + Player OnSpellCastAt event script for PC AI; + Fires when oCreature becomes the target of a spell via SignalEvent. + Fires when a healing kit is used on a creature. +*/////////////////////////////////////////////////////////////////////////////// +#include "0i_associates" +void main() +{ + object oCreature = OBJECT_SELF; + object oCaster = GetLastSpellCaster(); + SetLocalObject(oCaster, AI_ATTACKED_SPELL, oCreature); + if(ai_Disabled(oCreature)) return; + if(!GetLastSpellHarmful()) return; + // If the spell came from an ally, we don't want to hold it against them. + if(GetFactionEqual(oCaster, oCreature)) ClearPersonalReputation(oCaster, oCreature); + // Lets see what kind of area of effect this is and select an appropriate action. + int nSpell = GetLastSpell(); + if(AI_DEBUG) ai_Debug("xx_pc_b_castat", "21", GetName(OBJECT_SELF) + " has been hit by a harmful spell(" + + Get2DAString("spells", "Label", nSpell) + ")!"); + if(ai_GetInAOEReaction(oCreature, oCaster, nSpell) && + ai_IsInADangerousAOE(oCreature, AI_RANGE_BATTLEFIELD, TRUE)) return; + if(ai_GetIsBusy(oCreature)) return; + if(ai_CheckForCombat(oCreature, FALSE)) return; + // We were attacked by an enemy out of combat, so let our allies know. + SetLocalObject(oCreature, AI_MY_TARGET, oCaster); + SpeakString(AI_ATKED_BY_SPELL, TALKVOLUME_SILENT_TALK); + if(!ai_CanIAttack(oCreature)) return; + if(GetDistanceBetween(oCreature, oCaster) < AI_RANGE_CLOSE) ai_DoAssociateCombatRound(oCreature); + else ActionMoveToObject(oCaster, TRUE, AI_RANGE_CLOSE - 1.0); +} + + diff --git a/src/module/nss/xx_pc_e_blocked.nss b/src/module/nss/xx_pc_e_blocked.nss new file mode 100644 index 0000000..604513e --- /dev/null +++ b/src/module/nss/xx_pc_e_blocked.nss @@ -0,0 +1,68 @@ +/*////////////////////////////////////////////////////////////////////////////// + Script: xx_pc_e_blocked + Programmer: Philos +//////////////////////////////////////////////////////////////////////////////// + Player OnBlocked event script for PC AI; + Can be blocked by a creature or door. +*/////////////////////////////////////////////////////////////////////////////// +#include "0i_associates" +void main() +{ + object oCreature = OBJECT_SELF; + // This actually gets either a Creature or Door that is blocking OBJECT_SELF. + object oObject = GetBlockingDoor(); + if(AI_DEBUG) ai_Debug("xx_pc_e_blocked", "14", GetName(oCreature) + " is being blocked by " + GetName(oObject)); + int nObjectType = GetObjectType(oObject); + if(nObjectType == OBJECT_TYPE_CREATURE) + { + if(GetIsEnemy(oObject, oCreature)) + { + if(ai_CanIAttack(oCreature) && ai_GetIsInCombat(oCreature)) + { + ai_DoAssociateCombatRound(oCreature); + return; + } + if(ai_CheckForCombat(oCreature, FALSE)) return; + } + } + // Anything below blocking us is a door. + if(nObjectType != OBJECT_TYPE_DOOR) return; + //if(GetLockKeyTag(oObject) != "") return; + else if(GetIsDoorActionPossible(oObject, DOOR_ACTION_OPEN) && + GetAbilityScore(oCreature, ABILITY_INTELLIGENCE) >= 5) + { + DoDoorAction(oObject, DOOR_ACTION_OPEN); + return; + } + // Anything below is ignored in combat. + if(ai_GetIsInCombat(oCreature)) return; + // If we are in combat we should ignore doors that do not easily open. + if(GetIsDoorActionPossible(oObject, DOOR_ACTION_BASH) && + ai_GetWeaponDamage(oCreature, 3, TRUE) > GetHardness(oObject) && + GetLockKeyTag(oObject) == "") + { + ActionWait(1.0); + ActionAttack(oObject); + // Give them 3 rounds to break through a door. + DelayCommand(18.0, ai_ClearCreatureActions(TRUE)); + return; + } + else if(GetLocked(oObject)) + { + if(AI_DEBUG) ai_Debug("0e_ch_e_blocked", "49", GetName(oObject) + " is locked!"); + string sID = ObjectToString(oCreature); + if(!GetLocalInt(oObject, "AI_STATED_LOCKED_" + sID) && + !ai_GetAIMode(oCreature, AI_MODE_DO_NOT_SPEAK)) SpeakString("That " + GetName(oObject) + " is locked!"); + SetLocalInt(oObject, "AI_STATED_LOCKED_" + sID, TRUE); + if(ai_GetAIMode(oCreature, AI_MODE_PICK_LOCKS) || + ai_GetAIMode(oCreature, AI_MODE_BASH_LOCKS)) + { + ai_AttemptToByPassLock(oCreature, oObject); + } + } + // Clear our action so we can move on to something else unless the door is open. + else if(!GetIsOpen(oObject)) + { + ai_ClearCreatureActions(); + } +} diff --git a/unpack_haks.cmd b/unpack_haks.cmd new file mode 100644 index 0000000..6ecd98e --- /dev/null +++ b/unpack_haks.cmd @@ -0,0 +1 @@ +nasher unpack pepshak --verbose --removeDeleted:false \ No newline at end of file diff --git a/update_src_from_haks.cmd b/update_src_from_haks.cmd new file mode 100644 index 0000000..72dec37 --- /dev/null +++ b/update_src_from_haks.cmd @@ -0,0 +1 @@ +nasher unpack pepshak --verbose -y \ No newline at end of file