diff --git a/README.md b/README.md index 83f762e8..d0f40026 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Mordenkainen's Magnificent Dungeon [PRC8] +# Mordenkainen's Magnificent Dungeon [PRC8-PEPS-CEP3] Repository for development of the PRC8 version of the rogue-like multiplayer module, Mordenkainen's Magnificent Dungeon. diff --git a/_module/PackModule.cmd b/_module/PackModule.cmd index 3cee7cdf..fe606b48 100644 --- a/_module/PackModule.cmd +++ b/_module/PackModule.cmd @@ -1 +1 @@ -Module.Packer.exe "Mordenkainen's Magnificent Dungeon [PRC8-CEP3].mod" p \ No newline at end of file +Module.Packer.exe "Mordenkainen's Magnificent Dungeon [PRC8-PEPS-CEP3].mod" p \ No newline at end of file diff --git a/_module/UnpackModule.cmd b/_module/UnpackModule.cmd index 81165457..d5a7acf5 100644 --- a/_module/UnpackModule.cmd +++ b/_module/UnpackModule.cmd @@ -1 +1 @@ -Module.Packer.exe "Mordenkainen's Magnificent Dungeon [PRC8-CEP3].mod" u \ No newline at end of file +Module.Packer.exe "Mordenkainen's Magnificent Dungeon [PRC8-PEPS-CEP3].mod" u \ No newline at end of file diff --git a/_module/are/forge001.are.json b/_module/are/forge001.are.json index 71c40723..67cecdaa 100644 --- a/_module/are/forge001.are.json +++ b/_module/are/forge001.are.json @@ -1713,7 +1713,7 @@ }, "Version": { "type": "dword", - "value": 13 + "value": 14 }, "Width": { "type": "int", diff --git a/_module/are/valeford.are.json b/_module/are/valeford.are.json index e75e9cb5..3b91f7b9 100644 --- a/_module/are/valeford.are.json +++ b/_module/are/valeford.are.json @@ -11173,7 +11173,7 @@ }, "Version": { "type": "dword", - "value": 80 + "value": 83 }, "Width": { "type": "int", diff --git a/_module/are/valefordblacksmi.are.json b/_module/are/valefordblacksmi.are.json index dfa5f71c..62b551ea 100644 --- a/_module/are/valefordblacksmi.are.json +++ b/_module/are/valefordblacksmi.are.json @@ -853,7 +853,7 @@ }, "Version": { "type": "dword", - "value": 8 + "value": 9 }, "Width": { "type": "int", diff --git a/_module/are/valefordgenerals.are.json b/_module/are/valefordgenerals.are.json index b8cc81f3..3d784365 100644 --- a/_module/are/valefordgenerals.are.json +++ b/_module/are/valefordgenerals.are.json @@ -1713,7 +1713,7 @@ }, "Version": { "type": "dword", - "value": 11 + "value": 12 }, "Width": { "type": "int", diff --git a/_module/are/valefordtavernan.are.json b/_module/are/valefordtavernan.are.json index 4e2913f1..4e0fedfa 100644 --- a/_module/are/valefordtavernan.are.json +++ b/_module/are/valefordtavernan.are.json @@ -1197,7 +1197,7 @@ }, "Version": { "type": "dword", - "value": 7 + "value": 8 }, "Width": { "type": "int", diff --git a/_module/are/valefordtemple.are.json b/_module/are/valefordtemple.are.json index d1771cbc..09eca0a0 100644 --- a/_module/are/valefordtemple.are.json +++ b/_module/are/valefordtemple.are.json @@ -1713,7 +1713,7 @@ }, "Version": { "type": "dword", - "value": 15 + "value": 16 }, "Width": { "type": "int", diff --git a/_module/dlg/nw_g_animal.dlg.json b/_module/dlg/nw_g_animal.dlg.json new file mode 100644 index 00000000..a65a225c --- /dev/null +++ b/_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/_module/dlg/nw_g_fam.dlg.json b/_module/dlg/nw_g_fam.dlg.json new file mode 100644 index 00000000..5be0aaee --- /dev/null +++ b/_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/_module/dlg/oc_ai_henchmen.dlg.json b/_module/dlg/oc_ai_henchmen.dlg.json new file mode 100644 index 00000000..d9ca1b69 --- /dev/null +++ b/_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/_module/git/forge001.git.json b/_module/git/forge001.git.json index 2637ed61..cd9c3caa 100644 --- a/_module/git/forge001.git.json +++ b/_module/git/forge001.git.json @@ -138,7 +138,7 @@ }, "ChallengeRating": { "type": "float", - "value": 11.0 + "value": 12.0 }, "ClassList": { "type": "list", @@ -1318,6 +1318,56 @@ "type": "resref", "value": "bulin" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "MMD_KEEPHEAD" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "MMD_KEEPSKIN" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "MMD_KEEPPHENO" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -2129,6 +2179,21 @@ "type": "cexostring", "value": "002d004p000" } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } } ] }, @@ -2943,6 +3008,21 @@ "type": "cexostring", "value": "002d004p000" } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } } ] }, @@ -4686,6 +4766,41 @@ "type": "resref", "value": "ander001" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "RND_FIGHTER" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -6079,6 +6194,41 @@ "type": "resref", "value": "bognar001" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "RND_BARBARIAN" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -7489,6 +7639,41 @@ "type": "resref", "value": "sander001" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "RND_ROGUE" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -8833,6 +9018,41 @@ "type": "resref", "value": "vrurk001" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "RND_BARBARIAN" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -10911,6 +11131,41 @@ "type": "resref", "value": "dori001" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "RND_MAGE" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -12494,6 +12749,41 @@ "type": "resref", "value": "kathela001" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "RND_CLERIC" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -14031,6 +14321,41 @@ "type": "resref", "value": "walio001" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "RND_CLERIC" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -16595,6 +16920,51 @@ "type": "int", "value": 1 } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "MMD_KEEPHEAD" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "MMD_KEEPSKIN" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "MMD_KEEPPHENO" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } } ] }, @@ -18246,6 +18616,41 @@ "type": "resref", "value": "drudo001" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "RND_FIGHTER" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -20326,6 +20731,41 @@ "type": "resref", "value": "loric001" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "RND_MAGE" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -22424,6 +22864,41 @@ "type": "resref", "value": "perin001" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "RND_ROGUE" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 diff --git a/_module/git/valeford.git.json b/_module/git/valeford.git.json index af216d44..eb47b669 100644 --- a/_module/git/valeford.git.json +++ b/_module/git/valeford.git.json @@ -1673,6 +1673,41 @@ "type": "resref", "value": "ander" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "RND_FIGHTER" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -3066,6 +3101,41 @@ "type": "resref", "value": "bognar" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "RND_BARBARIAN" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -4602,6 +4672,41 @@ "type": "resref", "value": "buppi" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "RND_MAGE" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -7145,6 +7250,41 @@ "type": "resref", "value": "celurion" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "RND_MONK" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -8900,6 +9040,41 @@ "type": "resref", "value": "elolaldor" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "RND_RANGER" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -10545,6 +10720,41 @@ "type": "resref", "value": "hagma" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "RND_FIGHTER" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -10750,7 +10960,7 @@ }, "ChallengeRating": { "type": "float", - "value": 0.5 + "value": 1.0 }, "ClassList": { "type": "list", @@ -12786,6 +12996,41 @@ "type": "resref", "value": "hediel" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "RND_MAGE" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -14230,6 +14475,41 @@ "type": "resref", "value": "lagnar" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "RND_CLERIC" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -16364,6 +16644,41 @@ "type": "resref", "value": "legebril" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "RND_BARD" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -18455,6 +18770,41 @@ "type": "resref", "value": "perin" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "RNG_ROGUE" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -19766,6 +20116,41 @@ "type": "resref", "value": "peta" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "RND_DRUID" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -21573,6 +21958,41 @@ "type": "resref", "value": "tagnar" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "RND_FIGHTER" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 0 + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -22896,6 +23316,41 @@ "type": "resref", "value": "vilmar" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "RND_FIGHTER" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -24240,6 +24695,41 @@ "type": "resref", "value": "vrurk" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "RND_BARBARIAN" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -25888,6 +26378,41 @@ "type": "resref", "value": "drudo" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "RND_FIGHTER" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -27311,6 +27836,41 @@ "type": "resref", "value": "gustin" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "RND_CLERIC" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -30533,6 +31093,41 @@ "type": "resref", "value": "elenne" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "RND_MAGE" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -32321,6 +32916,41 @@ "type": "resref", "value": "bink" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "RND_FIGHTER" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -33992,6 +34622,41 @@ "type": "resref", "value": "frum" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "RND_BARD" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -36114,6 +36779,41 @@ "type": "resref", "value": "tonan" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "RND_BARD" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -37651,6 +38351,41 @@ "type": "resref", "value": "walio" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "RND_CLERIC" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -38835,6 +39570,41 @@ "type": "resref", "value": "bran" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "RND_MONK" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -40137,6 +40907,41 @@ "type": "resref", "value": "kell" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "RND_PALADIN" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -41582,6 +42387,41 @@ "type": "resref", "value": "sander" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "RND_ROGUE" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -43444,6 +44284,41 @@ "type": "resref", "value": "jong" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "RND_MAGE" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -45533,6 +46408,41 @@ "type": "resref", "value": "loric" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "RND_MAGE" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -47611,6 +48521,41 @@ "type": "resref", "value": "dori" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "RND_MAGE" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -49300,6 +50245,41 @@ "type": "resref", "value": "merago" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "RND_FIGHTER" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -51058,6 +52038,41 @@ "type": "resref", "value": "ramin" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "RND_FIGHTER" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -52676,6 +53691,41 @@ "type": "resref", "value": "kathela" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "RND_CLERIC" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -53487,6 +54537,21 @@ "type": "cexostring", "value": "002d004p000" } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } } ] }, @@ -54301,6 +55366,21 @@ "type": "cexostring", "value": "002d004p000" } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } } ] }, @@ -55115,6 +56195,21 @@ "type": "cexostring", "value": "002d004p000" } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } } ] }, @@ -55929,6 +57024,21 @@ "type": "cexostring", "value": "002d004p000" } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } } ] }, @@ -56743,6 +57853,21 @@ "type": "cexostring", "value": "002d004p000" } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } } ] }, @@ -58371,6 +59496,21 @@ "type": "cexostring", "value": "002d004p000" } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } } ] }, @@ -59185,6 +60325,21 @@ "type": "cexostring", "value": "002d004p000" } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } } ] }, @@ -59999,6 +61154,21 @@ "type": "cexostring", "value": "002d004p000" } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } } ] }, @@ -67806,6 +68976,41 @@ "type": "resref", "value": "gnomeairshipc001" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "TITLE" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "Skycaptain" + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 diff --git a/_module/git/valefordblacksmi.git.json b/_module/git/valefordblacksmi.git.json index c8be2454..567a5116 100644 --- a/_module/git/valefordblacksmi.git.json +++ b/_module/git/valefordblacksmi.git.json @@ -1273,6 +1273,51 @@ "type": "int", "value": 1 } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "MMD_KEEPHEAD" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "MMD_KEEPSKIN" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "MMD_KEEPPHENO" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } } ] }, @@ -2087,6 +2132,21 @@ "type": "cexostring", "value": "002d004p000" } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } } ] }, diff --git a/_module/git/valefordgenerals.git.json b/_module/git/valefordgenerals.git.json index 04c061af..02fbf253 100644 --- a/_module/git/valefordgenerals.git.json +++ b/_module/git/valefordgenerals.git.json @@ -1200,6 +1200,56 @@ "type": "resref", "value": "tomantheprovisio" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "MMD_KEEPHEAD" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "MMD_KEEPSKIN" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "MMD_KEEPPHENO" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -2011,6 +2061,21 @@ "type": "cexostring", "value": "002d004p000" } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } } ] }, diff --git a/_module/git/valefordtavernan.git.json b/_module/git/valefordtavernan.git.json index 4f18c089..7c18b451 100644 --- a/_module/git/valefordtavernan.git.json +++ b/_module/git/valefordtavernan.git.json @@ -983,6 +983,51 @@ "type": "cexostring", "value": "006d006p025" } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "MMD_KEEPHEAD" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "MMD_KEEPSKIN" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "MMD_KEEPPHENO" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } } ] }, @@ -1797,6 +1842,21 @@ "type": "cexostring", "value": "002d004p000" } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } } ] }, @@ -2611,6 +2671,21 @@ "type": "cexostring", "value": "002d004p000" } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } } ] }, diff --git a/_module/git/valefordtemple.git.json b/_module/git/valefordtemple.git.json index 65185357..ed7617bc 100644 --- a/_module/git/valefordtemple.git.json +++ b/_module/git/valefordtemple.git.json @@ -50,7 +50,7 @@ "__struct_id": 4, "Appearance_Head": { "type": "byte", - "value": 2 + "value": 22 }, "Appearance_Type": { "type": "word", @@ -1973,6 +1973,56 @@ "type": "resref", "value": "fathernathal" }, + "VarTable": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "MMD_KEEPHEAD" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "MMD_KEEPSKIN" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "MMD_KEEPPHENO" + }, + "Type": { + "type": "dword", + "value": 1 + }, + "Value": { + "type": "int", + "value": 1 + } + } + ] + }, "WalkRate": { "type": "int", "value": 4 @@ -1991,7 +2041,7 @@ }, "xAppearance_Head": { "type": "word", - "value": 2 + "value": 22 }, "xArmorPart_RFoot": { "type": "word", @@ -3016,6 +3066,36 @@ "type": "cexostring", "value": "002d004p000" } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "TITLE" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "Brother" + } } ] }, @@ -4062,6 +4142,36 @@ "type": "cexostring", "value": "002d004p000" } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "SET_NAME" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "RANDOM" + } + }, + { + "__struct_id": 0, + "Name": { + "type": "cexostring", + "value": "TITLE" + }, + "Type": { + "type": "dword", + "value": 3 + }, + "Value": { + "type": "cexostring", + "value": "Sister" + } } ] }, diff --git a/_module/ifo/module.ifo.json b/_module/ifo/module.ifo.json index 5507a72b..f53119e5 100644 --- a/_module/ifo/module.ifo.json +++ b/_module/ifo/module.ifo.json @@ -543,7 +543,7 @@ "Mod_Description": { "type": "cexolocstring", "value": { - "0": "Mordenkainen's Magnificent Dungeon [PRC8-CEP3]\n\nBy: Mordenkainen / PRC'd By: Jaysyn\n\nThe most comprehensive random dungeon generator ever.\n\n" + "0": "Mordenkainen's Magnificent Dungeon [PRC8-PEPS-CEP3]\n\nBy: Mordenkainen / PRC'd By: Jaysyn\n\nThe most comprehensive random dungeon generator ever.\n\n" } }, "Mod_DuskHour": { @@ -585,6 +585,13 @@ "Mod_HakList": { "type": "list", "value": [ + { + "__struct_id": 8, + "Mod_Hak": { + "type": "cexostring", + "value": "peps_prc8" + } + }, { "__struct_id": 8, "Mod_Hak": { @@ -809,7 +816,7 @@ "Mod_Name": { "type": "cexolocstring", "value": { - "0": "Mordenkainen's Magnificent Dungeon [PRC8-CEP3]" + "0": "Mordenkainen's Magnificent Dungeon [PRC8-PEPS-CEP3]" } }, "Mod_OnAcquirItem": { diff --git a/_module/jrl/module.jrl.json b/_module/jrl/module.jrl.json index 94fa7183..79f280ad 100644 --- a/_module/jrl/module.jrl.json +++ b/_module/jrl/module.jrl.json @@ -34,7 +34,7 @@ "Name": { "type": "cexolocstring", "value": { - "0": "D&D XP Chart" + "0": "| D&D XP Chart |" } }, "Picture": { @@ -56,6 +56,57 @@ }, { "__struct_id": 1, + "Comment": { + "type": "cexostring", + "value": "" + }, + "EntryList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "End": { + "type": "word", + "value": 0 + }, + "ID": { + "type": "dword", + "value": 1 + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Make sure to drink and eat before each rest.\n\nDon't forget to fill your canteens and water bottles." + } + } + } + ] + }, + "Name": { + "type": "cexolocstring", + "value": { + "0": "| Food & Water |" + } + }, + "Picture": { + "type": "word", + "value": 65535 + }, + "Priority": { + "type": "dword", + "value": 4 + }, + "Tag": { + "type": "cexostring", + "value": "JRNL_FOODWTR" + }, + "XP": { + "type": "dword", + "value": 0 + } + }, + { + "__struct_id": 2, "Comment": { "type": "cexostring", "value": "Level Adjustment Buy-off Table" @@ -85,7 +136,7 @@ "Name": { "type": "cexolocstring", "value": { - "0": "LA Buy-off Table" + "0": "| LA Buy-off Table |" } }, "Picture": { @@ -104,6 +155,57 @@ "type": "dword", "value": 0 } + }, + { + "__struct_id": 3, + "Comment": { + "type": "cexostring", + "value": "" + }, + "EntryList": { + "type": "list", + "value": [ + { + "__struct_id": 0, + "End": { + "type": "word", + "value": 0 + }, + "ID": { + "type": "dword", + "value": 1 + }, + "Text": { + "type": "cexolocstring", + "value": { + "0": "Visit the PRC8 Discord for ruleset information, as well as other PW servers & dozens of single player PRC8 modules.\n\nhttps://discord.gg/FW9V9RKy5U" + } + } + } + ] + }, + "Name": { + "type": "cexolocstring", + "value": { + "0": "| PRC8 Discord |" + } + }, + "Picture": { + "type": "word", + "value": 65535 + }, + "Priority": { + "type": "dword", + "value": 4 + }, + "Tag": { + "type": "cexostring", + "value": "JRNL_PRC8" + }, + "XP": { + "type": "dword", + "value": 0 + } } ] } diff --git a/_module/ncs/0c_assoc_actions.ncs b/_module/ncs/0c_assoc_actions.ncs new file mode 100644 index 00000000..38d5507c Binary files /dev/null and b/_module/ncs/0c_assoc_actions.ncs differ diff --git a/_module/ncs/0c_cast_polymorp.ncs b/_module/ncs/0c_cast_polymorp.ncs new file mode 100644 index 00000000..9f1916e4 Binary files /dev/null and b/_module/ncs/0c_cast_polymorp.ncs differ diff --git a/_module/ncs/0c_fire_henchmen.ncs b/_module/ncs/0c_fire_henchmen.ncs new file mode 100644 index 00000000..64c87e44 Binary files /dev/null and b/_module/ncs/0c_fire_henchmen.ncs differ diff --git a/_module/ncs/0c_get_convo.ncs b/_module/ncs/0c_get_convo.ncs new file mode 100644 index 00000000..718e80f5 Binary files /dev/null and b/_module/ncs/0c_get_convo.ncs differ diff --git a/_module/ncs/0c_get_henchman.ncs b/_module/ncs/0c_get_henchman.ncs new file mode 100644 index 00000000..40709b75 Binary files /dev/null and b/_module/ncs/0c_get_henchman.ncs differ diff --git a/_module/ncs/0c_h_cast_spell.ncs b/_module/ncs/0c_h_cast_spell.ncs new file mode 100644 index 00000000..4a5f698c Binary files /dev/null and b/_module/ncs/0c_h_cast_spell.ncs differ diff --git a/_module/ncs/0c_henchmenspell.ncs b/_module/ncs/0c_henchmenspell.ncs new file mode 100644 index 00000000..3e0cb165 Binary files /dev/null and b/_module/ncs/0c_henchmenspell.ncs differ diff --git a/_module/ncs/0c_if_a_magic_m.ncs b/_module/ncs/0c_if_a_magic_m.ncs new file mode 100644 index 00000000..c6db42b4 Binary files /dev/null and b/_module/ncs/0c_if_a_magic_m.ncs differ diff --git a/_module/ncs/0c_if_ass_convo.ncs b/_module/ncs/0c_if_ass_convo.ncs new file mode 100644 index 00000000..80221db5 Binary files /dev/null and b/_module/ncs/0c_if_ass_convo.ncs differ diff --git a/_module/ncs/0c_if_assoc_mode.ncs b/_module/ncs/0c_if_assoc_mode.ncs new file mode 100644 index 00000000..3a539b8c Binary files /dev/null and b/_module/ncs/0c_if_assoc_mode.ncs differ diff --git a/_module/ncs/0c_if_cntrspell.ncs b/_module/ncs/0c_if_cntrspell.ncs new file mode 100644 index 00000000..0a489079 Binary files /dev/null and b/_module/ncs/0c_if_cntrspell.ncs differ diff --git a/_module/ncs/0c_if_com_script.ncs b/_module/ncs/0c_if_com_script.ncs new file mode 100644 index 00000000..1772a7ef Binary files /dev/null and b/_module/ncs/0c_if_com_script.ncs differ diff --git a/_module/ncs/0c_if_convo.ncs b/_module/ncs/0c_if_convo.ncs new file mode 100644 index 00000000..13b85f09 Binary files /dev/null and b/_module/ncs/0c_if_convo.ncs differ diff --git a/_module/ncs/0c_if_has_assoc.ncs b/_module/ncs/0c_if_has_assoc.ncs new file mode 100644 index 00000000..ffdfb4f3 Binary files /dev/null and b/_module/ncs/0c_if_has_assoc.ncs differ diff --git a/_module/ncs/0c_if_has_class.ncs b/_module/ncs/0c_if_has_class.ncs new file mode 100644 index 00000000..ccacecff Binary files /dev/null and b/_module/ncs/0c_if_has_class.ncs differ diff --git a/_module/ncs/0c_if_has_feat.ncs b/_module/ncs/0c_if_has_feat.ncs new file mode 100644 index 00000000..1db2eecd Binary files /dev/null and b/_module/ncs/0c_if_has_feat.ncs differ diff --git a/_module/ncs/0c_if_has_spell.ncs b/_module/ncs/0c_if_has_spell.ncs new file mode 100644 index 00000000..d98b2012 Binary files /dev/null and b/_module/ncs/0c_if_has_spell.ncs differ diff --git a/_module/ncs/0c_if_hen_leave.ncs b/_module/ncs/0c_if_hen_leave.ncs new file mode 100644 index 00000000..58b270f4 Binary files /dev/null and b/_module/ncs/0c_if_hen_leave.ncs differ diff --git a/_module/ncs/0c_if_identify.ncs b/_module/ncs/0c_if_identify.ncs new file mode 100644 index 00000000..f1e13f6e Binary files /dev/null and b/_module/ncs/0c_if_identify.ncs differ diff --git a/_module/ncs/0c_if_not_master.ncs b/_module/ncs/0c_if_not_master.ncs new file mode 100644 index 00000000..4af03a6f Binary files /dev/null and b/_module/ncs/0c_if_not_master.ncs differ diff --git a/_module/ncs/0c_if_open_inven.ncs b/_module/ncs/0c_if_open_inven.ncs new file mode 100644 index 00000000..89a2fb55 Binary files /dev/null and b/_module/ncs/0c_if_open_inven.ncs differ diff --git a/_module/ncs/0c_if_pickuploot.ncs b/_module/ncs/0c_if_pickuploot.ncs new file mode 100644 index 00000000..b7265983 Binary files /dev/null and b/_module/ncs/0c_if_pickuploot.ncs differ diff --git a/_module/ncs/0c_if_polymorph.ncs b/_module/ncs/0c_if_polymorph.ncs new file mode 100644 index 00000000..2abec1d9 Binary files /dev/null and b/_module/ncs/0c_if_polymorph.ncs differ diff --git a/_module/ncs/0c_if_scout.ncs b/_module/ncs/0c_if_scout.ncs new file mode 100644 index 00000000..b7265983 Binary files /dev/null and b/_module/ncs/0c_if_scout.ncs differ diff --git a/_module/ncs/0c_if_skillrank.ncs b/_module/ncs/0c_if_skillrank.ncs new file mode 100644 index 00000000..0116caa1 Binary files /dev/null and b/_module/ncs/0c_if_skillrank.ncs differ diff --git a/_module/ncs/0c_if_taunt.ncs b/_module/ncs/0c_if_taunt.ncs new file mode 100644 index 00000000..c715cd97 Binary files /dev/null and b/_module/ncs/0c_if_taunt.ncs differ diff --git a/_module/ncs/0c_listhenchman.ncs b/_module/ncs/0c_listhenchman.ncs new file mode 100644 index 00000000..de1e30e0 Binary files /dev/null and b/_module/ncs/0c_listhenchman.ncs differ diff --git a/_module/ncs/0c_no_com_script.ncs b/_module/ncs/0c_no_com_script.ncs new file mode 100644 index 00000000..e2a6ab19 Binary files /dev/null and b/_module/ncs/0c_no_com_script.ncs differ diff --git a/_module/ncs/0c_remove_effect.ncs b/_module/ncs/0c_remove_effect.ncs new file mode 100644 index 00000000..f525d1a8 Binary files /dev/null and b/_module/ncs/0c_remove_effect.ncs differ diff --git a/_module/ncs/0c_summon_assoc.ncs b/_module/ncs/0c_summon_assoc.ncs new file mode 100644 index 00000000..8072f01b Binary files /dev/null and b/_module/ncs/0c_summon_assoc.ncs differ diff --git a/_module/ncs/0c_use_feat.ncs b/_module/ncs/0c_use_feat.ncs new file mode 100644 index 00000000..5f0da84e Binary files /dev/null and b/_module/ncs/0c_use_feat.ncs differ diff --git a/_module/ncs/0e_c2_1_hb.ncs b/_module/ncs/0e_c2_1_hb.ncs new file mode 100644 index 00000000..2e0448d1 Binary files /dev/null and b/_module/ncs/0e_c2_1_hb.ncs differ diff --git a/_module/ncs/0e_c2_7_ondeath.ncs b/_module/ncs/0e_c2_7_ondeath.ncs new file mode 100644 index 00000000..1fc2a893 Binary files /dev/null and b/_module/ncs/0e_c2_7_ondeath.ncs differ diff --git a/_module/ncs/0e_ch_1_hb.ncs b/_module/ncs/0e_ch_1_hb.ncs new file mode 100644 index 00000000..dbe91f37 Binary files /dev/null and b/_module/ncs/0e_ch_1_hb.ncs differ diff --git a/_module/ncs/0e_ch_7_ondeath.ncs b/_module/ncs/0e_ch_7_ondeath.ncs new file mode 100644 index 00000000..911eb7a3 Binary files /dev/null and b/_module/ncs/0e_ch_7_ondeath.ncs differ diff --git a/_module/ncs/0e_do_combat_rnd.ncs b/_module/ncs/0e_do_combat_rnd.ncs new file mode 100644 index 00000000..aea68d3e Binary files /dev/null and b/_module/ncs/0e_do_combat_rnd.ncs differ diff --git a/_module/ncs/0e_gui_events.ncs b/_module/ncs/0e_gui_events.ncs new file mode 100644 index 00000000..2064ddc2 Binary files /dev/null and b/_module/ncs/0e_gui_events.ncs differ diff --git a/_module/ncs/0e_m1_3_endround.ncs b/_module/ncs/0e_m1_3_endround.ncs new file mode 100644 index 00000000..13dfe43a Binary files /dev/null and b/_module/ncs/0e_m1_3_endround.ncs differ diff --git a/_module/ncs/0e_nui.ncs b/_module/ncs/0e_nui.ncs new file mode 100644 index 00000000..69733f01 Binary files /dev/null and b/_module/ncs/0e_nui.ncs differ diff --git a/_module/ncs/0e_nui_dm.ncs b/_module/ncs/0e_nui_dm.ncs new file mode 100644 index 00000000..af7cbfb0 Binary files /dev/null and b/_module/ncs/0e_nui_dm.ncs differ diff --git a/_module/ncs/0e_onclientload.ncs b/_module/ncs/0e_onclientload.ncs new file mode 100644 index 00000000..2244bcd8 Binary files /dev/null and b/_module/ncs/0e_onclientload.ncs differ diff --git a/_module/ncs/0e_player_target.ncs b/_module/ncs/0e_player_target.ncs new file mode 100644 index 00000000..55d2976b Binary files /dev/null and b/_module/ncs/0e_player_target.ncs differ diff --git a/_module/ncs/0e_prc_ch_events.ncs b/_module/ncs/0e_prc_ch_events.ncs new file mode 100644 index 00000000..7aa1cca2 Binary files /dev/null and b/_module/ncs/0e_prc_ch_events.ncs differ diff --git a/_module/ncs/69_hench_pickup.ncs b/_module/ncs/69_hench_pickup.ncs index 0e841f06..5a62985a 100644 Binary files a/_module/ncs/69_hench_pickup.ncs and b/_module/ncs/69_hench_pickup.ncs differ diff --git a/_module/ncs/69_hench_scout1.ncs b/_module/ncs/69_hench_scout1.ncs index ec27b38a..394c342c 100644 Binary files a/_module/ncs/69_hench_scout1.ncs and b/_module/ncs/69_hench_scout1.ncs differ diff --git a/_module/ncs/69_henchscoutno.ncs b/_module/ncs/69_henchscoutno.ncs index 9d7da327..96cec1fd 100644 Binary files a/_module/ncs/69_henchscoutno.ncs and b/_module/ncs/69_henchscoutno.ncs differ diff --git a/_module/ncs/BookOfTownPortal.ncs b/_module/ncs/BookOfTownPortal.ncs index df864b58..a42be706 100644 Binary files a/_module/ncs/BookOfTownPortal.ncs and b/_module/ncs/BookOfTownPortal.ncs differ diff --git a/_module/ncs/_kb_corpse_damg.ncs b/_module/ncs/_kb_corpse_damg.ncs index 6fee11e3..b480f4b9 100644 Binary files a/_module/ncs/_kb_corpse_damg.ncs and b/_module/ncs/_kb_corpse_damg.ncs differ diff --git a/_module/ncs/_kb_corpse_death.ncs b/_module/ncs/_kb_corpse_death.ncs index 5a27f4d2..dce6dddf 100644 Binary files a/_module/ncs/_kb_corpse_death.ncs and b/_module/ncs/_kb_corpse_death.ncs differ diff --git a/_module/ncs/_kb_corpse_distb.ncs b/_module/ncs/_kb_corpse_distb.ncs index 874e891d..2b30eb52 100644 Binary files a/_module/ncs/_kb_corpse_distb.ncs and b/_module/ncs/_kb_corpse_distb.ncs differ diff --git a/_module/ncs/_kb_corpse_phatk.ncs b/_module/ncs/_kb_corpse_phatk.ncs index 6fee11e3..b480f4b9 100644 Binary files a/_module/ncs/_kb_corpse_phatk.ncs and b/_module/ncs/_kb_corpse_phatk.ncs differ diff --git a/_module/ncs/_kb_corpse_spell.ncs b/_module/ncs/_kb_corpse_spell.ncs index 4395074b..aafcd3fe 100644 Binary files a/_module/ncs/_kb_corpse_spell.ncs and b/_module/ncs/_kb_corpse_spell.ncs differ diff --git a/_module/ncs/_kb_corpse_used.ncs b/_module/ncs/_kb_corpse_used.ncs index 1f890717..3f580058 100644 Binary files a/_module/ncs/_kb_corpse_used.ncs and b/_module/ncs/_kb_corpse_used.ncs differ diff --git a/_module/ncs/_kb_corpse_user.ncs b/_module/ncs/_kb_corpse_user.ncs index 66619e81..6d138987 100644 Binary files a/_module/ncs/_kb_corpse_user.ncs and b/_module/ncs/_kb_corpse_user.ncs differ diff --git a/_module/ncs/_kb_plc_corpse.ncs b/_module/ncs/_kb_plc_corpse.ncs index f088e53b..69e1bd8e 100644 Binary files a/_module/ncs/_kb_plc_corpse.ncs and b/_module/ncs/_kb_plc_corpse.ncs differ diff --git a/_module/ncs/_kb_plugins.ncs b/_module/ncs/_kb_plugins.ncs index f8afb170..6da4be16 100644 Binary files a/_module/ncs/_kb_plugins.ncs and b/_module/ncs/_kb_plugins.ncs differ diff --git a/_module/ncs/_kb_raise_res.ncs b/_module/ncs/_kb_raise_res.ncs index f3996106..46e60963 100644 Binary files a/_module/ncs/_kb_raise_res.ncs and b/_module/ncs/_kb_raise_res.ncs differ diff --git a/_module/ncs/addkeen.ncs b/_module/ncs/addkeen.ncs index d0cec49a..24db944d 100644 Binary files a/_module/ncs/addkeen.ncs and b/_module/ncs/addkeen.ncs differ diff --git a/_module/ncs/ai_a_ambusher.ncs b/_module/ncs/ai_a_ambusher.ncs new file mode 100644 index 00000000..a3807bd2 Binary files /dev/null and b/_module/ncs/ai_a_ambusher.ncs differ diff --git a/_module/ncs/ai_a_atk_casters.ncs b/_module/ncs/ai_a_atk_casters.ncs new file mode 100644 index 00000000..5aafe7f1 Binary files /dev/null and b/_module/ncs/ai_a_atk_casters.ncs differ diff --git a/_module/ncs/ai_a_atk_nearest.ncs b/_module/ncs/ai_a_atk_nearest.ncs new file mode 100644 index 00000000..51b5bab9 Binary files /dev/null and b/_module/ncs/ai_a_atk_nearest.ncs differ diff --git a/_module/ncs/ai_a_atk_warrior.ncs b/_module/ncs/ai_a_atk_warrior.ncs new file mode 100644 index 00000000..cdd1fccf Binary files /dev/null and b/_module/ncs/ai_a_atk_warrior.ncs differ diff --git a/_module/ncs/ai_a_barbarian.ncs b/_module/ncs/ai_a_barbarian.ncs new file mode 100644 index 00000000..bafeedbf Binary files /dev/null and b/_module/ncs/ai_a_barbarian.ncs differ diff --git a/_module/ncs/ai_a_bard.ncs b/_module/ncs/ai_a_bard.ncs new file mode 100644 index 00000000..d0e85e33 Binary files /dev/null and b/_module/ncs/ai_a_bard.ncs differ diff --git a/_module/ncs/ai_a_cleric.ncs b/_module/ncs/ai_a_cleric.ncs new file mode 100644 index 00000000..00cd7bbd Binary files /dev/null and b/_module/ncs/ai_a_cleric.ncs differ diff --git a/_module/ncs/ai_a_cntrspell.ncs b/_module/ncs/ai_a_cntrspell.ncs new file mode 100644 index 00000000..0502ceb9 Binary files /dev/null and b/_module/ncs/ai_a_cntrspell.ncs differ diff --git a/_module/ncs/ai_a_default.ncs b/_module/ncs/ai_a_default.ncs new file mode 100644 index 00000000..62dd563a Binary files /dev/null and b/_module/ncs/ai_a_default.ncs differ diff --git a/_module/ncs/ai_a_defensive.ncs b/_module/ncs/ai_a_defensive.ncs new file mode 100644 index 00000000..0703aed0 Binary files /dev/null and b/_module/ncs/ai_a_defensive.ncs differ diff --git a/_module/ncs/ai_a_druid.ncs b/_module/ncs/ai_a_druid.ncs new file mode 100644 index 00000000..8b0099a7 Binary files /dev/null and b/_module/ncs/ai_a_druid.ncs differ diff --git a/_module/ncs/ai_a_fighter.ncs b/_module/ncs/ai_a_fighter.ncs new file mode 100644 index 00000000..65ba6d89 Binary files /dev/null and b/_module/ncs/ai_a_fighter.ncs differ diff --git a/_module/ncs/ai_a_flanker.ncs b/_module/ncs/ai_a_flanker.ncs new file mode 100644 index 00000000..c021687e Binary files /dev/null and b/_module/ncs/ai_a_flanker.ncs differ diff --git a/_module/ncs/ai_a_invisible.ncs b/_module/ncs/ai_a_invisible.ncs new file mode 100644 index 00000000..67a9a811 Binary files /dev/null and b/_module/ncs/ai_a_invisible.ncs differ diff --git a/_module/ncs/ai_a_monk.ncs b/_module/ncs/ai_a_monk.ncs new file mode 100644 index 00000000..7eb5970b Binary files /dev/null and b/_module/ncs/ai_a_monk.ncs differ diff --git a/_module/ncs/ai_a_no_cmb_mode.ncs b/_module/ncs/ai_a_no_cmb_mode.ncs new file mode 100644 index 00000000..2aef820e Binary files /dev/null and b/_module/ncs/ai_a_no_cmb_mode.ncs differ diff --git a/_module/ncs/ai_a_paladin.ncs b/_module/ncs/ai_a_paladin.ncs new file mode 100644 index 00000000..d854d63d Binary files /dev/null and b/_module/ncs/ai_a_paladin.ncs differ diff --git a/_module/ncs/ai_a_peaceful.ncs b/_module/ncs/ai_a_peaceful.ncs new file mode 100644 index 00000000..02a00540 Binary files /dev/null and b/_module/ncs/ai_a_peaceful.ncs differ diff --git a/_module/ncs/ai_a_polymorphed.ncs b/_module/ncs/ai_a_polymorphed.ncs new file mode 100644 index 00000000..c513c3ff Binary files /dev/null and b/_module/ncs/ai_a_polymorphed.ncs differ diff --git a/_module/ncs/ai_a_ranged.ncs b/_module/ncs/ai_a_ranged.ncs new file mode 100644 index 00000000..19c592d8 Binary files /dev/null and b/_module/ncs/ai_a_ranged.ncs differ diff --git a/_module/ncs/ai_a_ranger.ncs b/_module/ncs/ai_a_ranger.ncs new file mode 100644 index 00000000..be76ad10 Binary files /dev/null and b/_module/ncs/ai_a_ranger.ncs differ diff --git a/_module/ncs/ai_a_rogue.ncs b/_module/ncs/ai_a_rogue.ncs new file mode 100644 index 00000000..a652083a Binary files /dev/null and b/_module/ncs/ai_a_rogue.ncs differ diff --git a/_module/ncs/ai_a_sorcerer.ncs b/_module/ncs/ai_a_sorcerer.ncs new file mode 100644 index 00000000..9d3fd6e4 Binary files /dev/null and b/_module/ncs/ai_a_sorcerer.ncs differ diff --git a/_module/ncs/ai_a_taunter.ncs b/_module/ncs/ai_a_taunter.ncs new file mode 100644 index 00000000..6686a00d Binary files /dev/null and b/_module/ncs/ai_a_taunter.ncs differ diff --git a/_module/ncs/ai_a_wizard.ncs b/_module/ncs/ai_a_wizard.ncs new file mode 100644 index 00000000..af215ee0 Binary files /dev/null and b/_module/ncs/ai_a_wizard.ncs differ diff --git a/_module/ncs/ai_ambusher.ncs b/_module/ncs/ai_ambusher.ncs new file mode 100644 index 00000000..d6387dca Binary files /dev/null and b/_module/ncs/ai_ambusher.ncs differ diff --git a/_module/ncs/ai_barbarian.ncs b/_module/ncs/ai_barbarian.ncs new file mode 100644 index 00000000..29eb43db Binary files /dev/null and b/_module/ncs/ai_barbarian.ncs differ diff --git a/_module/ncs/ai_bard.ncs b/_module/ncs/ai_bard.ncs new file mode 100644 index 00000000..f1d6c70f Binary files /dev/null and b/_module/ncs/ai_bard.ncs differ diff --git a/_module/ncs/ai_cleric.ncs b/_module/ncs/ai_cleric.ncs new file mode 100644 index 00000000..1c0d242d Binary files /dev/null and b/_module/ncs/ai_cleric.ncs differ diff --git a/_module/ncs/ai_cntrspell.ncs b/_module/ncs/ai_cntrspell.ncs new file mode 100644 index 00000000..e8150cb2 Binary files /dev/null and b/_module/ncs/ai_cntrspell.ncs differ diff --git a/_module/ncs/ai_coward.ncs b/_module/ncs/ai_coward.ncs new file mode 100644 index 00000000..56d92784 Binary files /dev/null and b/_module/ncs/ai_coward.ncs differ diff --git a/_module/ncs/ai_default.ncs b/_module/ncs/ai_default.ncs new file mode 100644 index 00000000..c95d2d38 Binary files /dev/null and b/_module/ncs/ai_default.ncs differ diff --git a/_module/ncs/ai_defensive.ncs b/_module/ncs/ai_defensive.ncs new file mode 100644 index 00000000..777e2f92 Binary files /dev/null and b/_module/ncs/ai_defensive.ncs differ diff --git a/_module/ncs/ai_dragon.ncs b/_module/ncs/ai_dragon.ncs new file mode 100644 index 00000000..5de5e345 Binary files /dev/null and b/_module/ncs/ai_dragon.ncs differ diff --git a/_module/ncs/ai_druid.ncs b/_module/ncs/ai_druid.ncs new file mode 100644 index 00000000..de40f51a Binary files /dev/null and b/_module/ncs/ai_druid.ncs differ diff --git a/_module/ncs/ai_fighter.ncs b/_module/ncs/ai_fighter.ncs new file mode 100644 index 00000000..8d39b573 Binary files /dev/null and b/_module/ncs/ai_fighter.ncs differ diff --git a/_module/ncs/ai_flanker.ncs b/_module/ncs/ai_flanker.ncs new file mode 100644 index 00000000..d03ab5f0 Binary files /dev/null and b/_module/ncs/ai_flanker.ncs differ diff --git a/_module/ncs/ai_incorporeal.ncs b/_module/ncs/ai_incorporeal.ncs new file mode 100644 index 00000000..79505183 Binary files /dev/null and b/_module/ncs/ai_incorporeal.ncs differ diff --git a/_module/ncs/ai_invisible.ncs b/_module/ncs/ai_invisible.ncs new file mode 100644 index 00000000..c1c4a310 Binary files /dev/null and b/_module/ncs/ai_invisible.ncs differ diff --git a/_module/ncs/ai_monk.ncs b/_module/ncs/ai_monk.ncs new file mode 100644 index 00000000..69db5d8c Binary files /dev/null and b/_module/ncs/ai_monk.ncs differ diff --git a/_module/ncs/ai_paladin.ncs b/_module/ncs/ai_paladin.ncs new file mode 100644 index 00000000..593113ac Binary files /dev/null and b/_module/ncs/ai_paladin.ncs differ diff --git a/_module/ncs/ai_polymorphed.ncs b/_module/ncs/ai_polymorphed.ncs new file mode 100644 index 00000000..9d259292 Binary files /dev/null and b/_module/ncs/ai_polymorphed.ncs differ diff --git a/_module/ncs/ai_ranged.ncs b/_module/ncs/ai_ranged.ncs new file mode 100644 index 00000000..9a9524e2 Binary files /dev/null and b/_module/ncs/ai_ranged.ncs differ diff --git a/_module/ncs/ai_ranger.ncs b/_module/ncs/ai_ranger.ncs new file mode 100644 index 00000000..d35ffce1 Binary files /dev/null and b/_module/ncs/ai_ranger.ncs differ diff --git a/_module/ncs/ai_rogue.ncs b/_module/ncs/ai_rogue.ncs new file mode 100644 index 00000000..a7da6ff8 Binary files /dev/null and b/_module/ncs/ai_rogue.ncs differ diff --git a/_module/ncs/ai_shadow.ncs b/_module/ncs/ai_shadow.ncs new file mode 100644 index 00000000..5bbe01a4 Binary files /dev/null and b/_module/ncs/ai_shadow.ncs differ diff --git a/_module/ncs/ai_sorcerer.ncs b/_module/ncs/ai_sorcerer.ncs new file mode 100644 index 00000000..1346087d Binary files /dev/null and b/_module/ncs/ai_sorcerer.ncs differ diff --git a/_module/ncs/ai_taunter.ncs b/_module/ncs/ai_taunter.ncs new file mode 100644 index 00000000..c8f5b71a Binary files /dev/null and b/_module/ncs/ai_taunter.ncs differ diff --git a/_module/ncs/ai_wizard.ncs b/_module/ncs/ai_wizard.ncs new file mode 100644 index 00000000..404c2f88 Binary files /dev/null and b/_module/ncs/ai_wizard.ncs differ diff --git a/_module/ncs/at_enter_pc_room.ncs b/_module/ncs/at_enter_pc_room.ncs index fa6dfe40..0f783782 100644 Binary files a/_module/ncs/at_enter_pc_room.ncs and b/_module/ncs/at_enter_pc_room.ncs differ diff --git a/_module/ncs/bleeding_ondying.ncs b/_module/ncs/bleeding_ondying.ncs index d11be2ee..74c94948 100644 Binary files a/_module/ncs/bleeding_ondying.ncs and b/_module/ncs/bleeding_ondying.ncs differ diff --git a/_module/ncs/c_con_riddler.ncs b/_module/ncs/c_con_riddler.ncs index 5c18a336..13bf2bb3 100644 Binary files a/_module/ncs/c_con_riddler.ncs and b/_module/ncs/c_con_riddler.ncs differ diff --git a/_module/ncs/calcmodvalue1.ncs b/_module/ncs/calcmodvalue1.ncs index 54181ba0..c321292d 100644 Binary files a/_module/ncs/calcmodvalue1.ncs and b/_module/ncs/calcmodvalue1.ncs differ diff --git a/_module/ncs/calcmodvalue1a.ncs b/_module/ncs/calcmodvalue1a.ncs index 4437a0fa..eedc0bba 100644 Binary files a/_module/ncs/calcmodvalue1a.ncs and b/_module/ncs/calcmodvalue1a.ncs differ diff --git a/_module/ncs/calcmodvalue2.ncs b/_module/ncs/calcmodvalue2.ncs index 221b46c9..398b0a2d 100644 Binary files a/_module/ncs/calcmodvalue2.ncs and b/_module/ncs/calcmodvalue2.ncs differ diff --git a/_module/ncs/cannotafford.ncs b/_module/ncs/cannotafford.ncs index 7000cbdd..51b8097a 100644 Binary files a/_module/ncs/cannotafford.ncs and b/_module/ncs/cannotafford.ncs differ diff --git a/_module/ncs/cast_heal_circle.ncs b/_module/ncs/cast_heal_circle.ncs index 3c2cc4f8..cd1ed057 100644 Binary files a/_module/ncs/cast_heal_circle.ncs and b/_module/ncs/cast_heal_circle.ncs differ diff --git a/_module/ncs/chk_has10gp.ncs b/_module/ncs/chk_has10gp.ncs index 532b0611..96c15401 100644 Binary files a/_module/ncs/chk_has10gp.ncs and b/_module/ncs/chk_has10gp.ncs differ diff --git a/_module/ncs/chk_has500gp.ncs b/_module/ncs/chk_has500gp.ncs index ec54f135..12a8c93d 100644 Binary files a/_module/ncs/chk_has500gp.ncs and b/_module/ncs/chk_has500gp.ncs differ diff --git a/_module/ncs/chk_has5gp.ncs b/_module/ncs/chk_has5gp.ncs index a8220e16..16577804 100644 Binary files a/_module/ncs/chk_has5gp.ncs and b/_module/ncs/chk_has5gp.ncs differ diff --git a/_module/ncs/chk_has_bluff.ncs b/_module/ncs/chk_has_bluff.ncs index faa36600..caf52f2c 100644 Binary files a/_module/ncs/chk_has_bluff.ncs and b/_module/ncs/chk_has_bluff.ncs differ diff --git a/_module/ncs/chk_has_intimida.ncs b/_module/ncs/chk_has_intimida.ncs index ff6a9624..44708150 100644 Binary files a/_module/ncs/chk_has_intimida.ncs and b/_module/ncs/chk_has_intimida.ncs differ diff --git a/_module/ncs/chk_has_persuade.ncs b/_module/ncs/chk_has_persuade.ncs index bfb11cc5..0e64ba32 100644 Binary files a/_module/ncs/chk_has_persuade.ncs and b/_module/ncs/chk_has_persuade.ncs differ diff --git a/_module/ncs/chk_hascowhelm.ncs b/_module/ncs/chk_hascowhelm.ncs index 944f41f4..4be9f0ce 100644 Binary files a/_module/ncs/chk_hascowhelm.ncs and b/_module/ncs/chk_hascowhelm.ncs differ diff --git a/_module/ncs/chk_high_cha.ncs b/_module/ncs/chk_high_cha.ncs index a3375e9b..4860aae4 100644 Binary files a/_module/ncs/chk_high_cha.ncs and b/_module/ncs/chk_high_cha.ncs differ diff --git a/_module/ncs/chk_is_chaotic.ncs b/_module/ncs/chk_is_chaotic.ncs index 183e3487..83c0523b 100644 Binary files a/_module/ncs/chk_is_chaotic.ncs and b/_module/ncs/chk_is_chaotic.ncs differ diff --git a/_module/ncs/chk_is_evil.ncs b/_module/ncs/chk_is_evil.ncs index 9b815d63..1e3be7f2 100644 Binary files a/_module/ncs/chk_is_evil.ncs and b/_module/ncs/chk_is_evil.ncs differ diff --git a/_module/ncs/chk_is_orc.ncs b/_module/ncs/chk_is_orc.ncs index 69916548..26279056 100644 Binary files a/_module/ncs/chk_is_orc.ncs and b/_module/ncs/chk_is_orc.ncs differ diff --git a/_module/ncs/chk_isgoodor_nue.ncs b/_module/ncs/chk_isgoodor_nue.ncs index b21e2f78..5a6e2028 100644 Binary files a/_module/ncs/chk_isgoodor_nue.ncs and b/_module/ncs/chk_isgoodor_nue.ncs differ diff --git a/_module/ncs/chk_manroot.ncs b/_module/ncs/chk_manroot.ncs index a36225cf..591f90f4 100644 Binary files a/_module/ncs/chk_manroot.ncs and b/_module/ncs/chk_manroot.ncs differ diff --git a/_module/ncs/chk_niceorc.ncs b/_module/ncs/chk_niceorc.ncs index 5b3613d7..aff583ac 100644 Binary files a/_module/ncs/chk_niceorc.ncs and b/_module/ncs/chk_niceorc.ncs differ diff --git a/_module/ncs/chk_percy.ncs b/_module/ncs/chk_percy.ncs index 405aecfe..441cbe0e 100644 Binary files a/_module/ncs/chk_percy.ncs and b/_module/ncs/chk_percy.ncs differ diff --git a/_module/ncs/chk_pointyears.ncs b/_module/ncs/chk_pointyears.ncs index 4a4e6c27..3a219d50 100644 Binary files a/_module/ncs/chk_pointyears.ncs and b/_module/ncs/chk_pointyears.ncs differ diff --git a/_module/ncs/chk_sm_rc_cls.ncs b/_module/ncs/chk_sm_rc_cls.ncs index a06753e7..d2585da1 100644 Binary files a/_module/ncs/chk_sm_rc_cls.ncs and b/_module/ncs/chk_sm_rc_cls.ncs differ diff --git a/_module/ncs/con_a_townportal.ncs b/_module/ncs/con_a_townportal.ncs index 740adb34..d426cf47 100644 Binary files a/_module/ncs/con_a_townportal.ncs and b/_module/ncs/con_a_townportal.ncs differ diff --git a/_module/ncs/con_c_townport0.ncs b/_module/ncs/con_c_townport0.ncs index 833e42d0..30a6cdd4 100644 Binary files a/_module/ncs/con_c_townport0.ncs and b/_module/ncs/con_c_townport0.ncs differ diff --git a/_module/ncs/con_c_townport1.ncs b/_module/ncs/con_c_townport1.ncs index 877d512a..d72d2d84 100644 Binary files a/_module/ncs/con_c_townport1.ncs and b/_module/ncs/con_c_townport1.ncs differ diff --git a/_module/ncs/cook_meat.ncs b/_module/ncs/cook_meat.ncs index abd196f7..688d8ca5 100644 Binary files a/_module/ncs/cook_meat.ncs and b/_module/ncs/cook_meat.ncs differ diff --git a/_module/ncs/create_gemstore.ncs b/_module/ncs/create_gemstore.ncs index b8cea63d..dea4c14d 100644 Binary files a/_module/ncs/create_gemstore.ncs and b/_module/ncs/create_gemstore.ncs differ diff --git a/_module/ncs/create_wmstore.ncs b/_module/ncs/create_wmstore.ncs index 19c19440..efeb49df 100644 Binary files a/_module/ncs/create_wmstore.ncs and b/_module/ncs/create_wmstore.ncs differ diff --git a/_module/ncs/cv_inn_door.ncs b/_module/ncs/cv_inn_door.ncs index b81e0391..06b157b0 100644 Binary files a/_module/ncs/cv_inn_door.ncs and b/_module/ncs/cv_inn_door.ncs differ diff --git a/_module/ncs/death_dummy.ncs b/_module/ncs/death_dummy.ncs index b8f07b4f..5b7167da 100644 Binary files a/_module/ncs/death_dummy.ncs and b/_module/ncs/death_dummy.ncs differ diff --git a/_module/ncs/death_save.ncs b/_module/ncs/death_save.ncs index 3a65bfcc..c0deeb80 100644 Binary files a/_module/ncs/death_save.ncs and b/_module/ncs/death_save.ncs differ diff --git a/_module/ncs/disarm_trap.ncs b/_module/ncs/disarm_trap.ncs index 020fc9cd..912d497e 100644 Binary files a/_module/ncs/disarm_trap.ncs and b/_module/ncs/disarm_trap.ncs differ diff --git a/_module/ncs/door_bash.ncs b/_module/ncs/door_bash.ncs index 451f7b94..938aa4b9 100644 Binary files a/_module/ncs/door_bash.ncs and b/_module/ncs/door_bash.ncs differ diff --git a/_module/ncs/door_click.ncs b/_module/ncs/door_click.ncs index cb21144a..60032623 100644 Binary files a/_module/ncs/door_click.ncs and b/_module/ncs/door_click.ncs differ diff --git a/_module/ncs/drink.ncs b/_module/ncs/drink.ncs index 3a6a3f92..c7044d15 100644 Binary files a/_module/ncs/drink.ncs and b/_module/ncs/drink.ncs differ diff --git a/_module/ncs/empty_destroy.ncs b/_module/ncs/empty_destroy.ncs index b133139d..5becf9d0 100644 Binary files a/_module/ncs/empty_destroy.ncs and b/_module/ncs/empty_destroy.ncs differ diff --git a/_module/ncs/flavortext.ncs b/_module/ncs/flavortext.ncs index c938f8cb..dec6f25f 100644 Binary files a/_module/ncs/flavortext.ncs and b/_module/ncs/flavortext.ncs differ diff --git a/_module/ncs/flintandtinder.ncs b/_module/ncs/flintandtinder.ncs index 2fd2a4e7..7f72a6ca 100644 Binary files a/_module/ncs/flintandtinder.ncs and b/_module/ncs/flintandtinder.ncs differ diff --git a/_module/ncs/food.ncs b/_module/ncs/food.ncs index ec060434..fde17a01 100644 Binary files a/_module/ncs/food.ncs and b/_module/ncs/food.ncs differ diff --git a/_module/ncs/food_disease.ncs b/_module/ncs/food_disease.ncs index db3cdea9..6a6e8db9 100644 Binary files a/_module/ncs/food_disease.ncs and b/_module/ncs/food_disease.ncs differ diff --git a/_module/ncs/food_poison.ncs b/_module/ncs/food_poison.ncs index e5bebed5..72ba3423 100644 Binary files a/_module/ncs/food_poison.ncs and b/_module/ncs/food_poison.ncs differ diff --git a/_module/ncs/get_is_not_hired.ncs b/_module/ncs/get_is_not_hired.ncs index 2a74aab7..34a8e40f 100644 Binary files a/_module/ncs/get_is_not_hired.ncs and b/_module/ncs/get_is_not_hired.ncs differ diff --git a/_module/ncs/give_root.ncs b/_module/ncs/give_root.ncs index 0e1adf54..64f5b46a 100644 Binary files a/_module/ncs/give_root.ncs and b/_module/ncs/give_root.ncs differ diff --git a/_module/ncs/heal_grtr_restor.ncs b/_module/ncs/heal_grtr_restor.ncs index 27f3f045..9ad98c4b 100644 Binary files a/_module/ncs/heal_grtr_restor.ncs and b/_module/ncs/heal_grtr_restor.ncs differ diff --git a/_module/ncs/hench_level.ncs b/_module/ncs/hench_level.ncs index 9112c463..0c67cb69 100644 Binary files a/_module/ncs/hench_level.ncs and b/_module/ncs/hench_level.ncs differ diff --git a/_module/ncs/hire_henchman.ncs b/_module/ncs/hire_henchman.ncs index aa2c3d54..b5589782 100644 Binary files a/_module/ncs/hire_henchman.ncs and b/_module/ncs/hire_henchman.ncs differ diff --git a/_module/ncs/isamtrefund.ncs b/_module/ncs/isamtrefund.ncs index b50a78db..beb641c8 100644 Binary files a/_module/ncs/isamtrefund.ncs and b/_module/ncs/isamtrefund.ncs differ diff --git a/_module/ncs/isamttopay.ncs b/_module/ncs/isamttopay.ncs index 4981e3ce..5e2d2204 100644 Binary files a/_module/ncs/isamttopay.ncs and b/_module/ncs/isamttopay.ncs differ diff --git a/_module/ncs/isitemonanvil.ncs b/_module/ncs/isitemonanvil.ncs index ccd95a31..da97638e 100644 Binary files a/_module/ncs/isitemonanvil.ncs and b/_module/ncs/isitemonanvil.ncs differ diff --git a/_module/ncs/kill_undead.ncs b/_module/ncs/kill_undead.ncs index 02bde4bc..84deeac2 100644 Binary files a/_module/ncs/kill_undead.ncs and b/_module/ncs/kill_undead.ncs differ diff --git a/_module/ncs/map_reveal_trig.ncs b/_module/ncs/map_reveal_trig.ncs index 7b519a8e..f947684c 100644 Binary files a/_module/ncs/map_reveal_trig.ncs and b/_module/ncs/map_reveal_trig.ncs differ diff --git a/_module/ncs/mm_prc_spells.ncs b/_module/ncs/mm_prc_spells.ncs new file mode 100644 index 00000000..eff60291 Binary files /dev/null and b/_module/ncs/mm_prc_spells.ncs differ diff --git a/_module/ncs/mmd_onnui.ncs b/_module/ncs/mmd_onnui.ncs index c2415dea..09714b55 100644 Binary files a/_module/ncs/mmd_onnui.ncs and b/_module/ncs/mmd_onnui.ncs differ diff --git a/_module/ncs/mmd_onplaytarget.ncs b/_module/ncs/mmd_onplaytarget.ncs index 099f3587..4650599e 100644 Binary files a/_module/ncs/mmd_onplaytarget.ncs and b/_module/ncs/mmd_onplaytarget.ncs differ diff --git a/_module/ncs/mod_nui.ncs b/_module/ncs/mod_nui.ncs index c6d75ebb..b0caa98a 100644 Binary files a/_module/ncs/mod_nui.ncs and b/_module/ncs/mod_nui.ncs differ diff --git a/_module/ncs/mod_target.ncs b/_module/ncs/mod_target.ncs index b635b0a8..0f78656d 100644 Binary files a/_module/ncs/mod_target.ncs and b/_module/ncs/mod_target.ncs differ diff --git a/_module/ncs/modifyitem.ncs b/_module/ncs/modifyitem.ncs index 1a3d870c..b794feff 100644 Binary files a/_module/ncs/modifyitem.ncs and b/_module/ncs/modifyitem.ncs differ diff --git a/_module/ncs/modifyitema.ncs b/_module/ncs/modifyitema.ncs index 2d64f109..a8d83851 100644 Binary files a/_module/ncs/modifyitema.ncs and b/_module/ncs/modifyitema.ncs differ diff --git a/_module/ncs/mp_hen_spawn.ncs b/_module/ncs/mp_hen_spawn.ncs index eb34792f..603aef59 100644 Binary files a/_module/ncs/mp_hen_spawn.ncs and b/_module/ncs/mp_hen_spawn.ncs differ diff --git a/_module/ncs/nui_f_storage.ncs b/_module/ncs/nui_f_storage.ncs index 3e3dcaf1..065e4c90 100644 Binary files a/_module/ncs/nui_f_storage.ncs and b/_module/ncs/nui_f_storage.ncs differ diff --git a/_module/ncs/nw_c2_default1.ncs b/_module/ncs/nw_c2_default1.ncs index 5aebc39b..8a75e8f2 100644 Binary files a/_module/ncs/nw_c2_default1.ncs and b/_module/ncs/nw_c2_default1.ncs differ diff --git a/_module/ncs/nw_c2_default2.ncs b/_module/ncs/nw_c2_default2.ncs index 68f702aa..603f806d 100644 Binary files a/_module/ncs/nw_c2_default2.ncs and b/_module/ncs/nw_c2_default2.ncs differ diff --git a/_module/ncs/nw_c2_default3.ncs b/_module/ncs/nw_c2_default3.ncs index c54384cc..3c27f360 100644 Binary files a/_module/ncs/nw_c2_default3.ncs and b/_module/ncs/nw_c2_default3.ncs differ diff --git a/_module/ncs/nw_c2_default4.ncs b/_module/ncs/nw_c2_default4.ncs index b8de03c1..ddb3945e 100644 Binary files a/_module/ncs/nw_c2_default4.ncs and b/_module/ncs/nw_c2_default4.ncs differ diff --git a/_module/ncs/nw_c2_default5.ncs b/_module/ncs/nw_c2_default5.ncs index 1502fbc3..3c848e63 100644 Binary files a/_module/ncs/nw_c2_default5.ncs and b/_module/ncs/nw_c2_default5.ncs differ diff --git a/_module/ncs/nw_c2_default6.ncs b/_module/ncs/nw_c2_default6.ncs index 1727698b..b71e606a 100644 Binary files a/_module/ncs/nw_c2_default6.ncs and b/_module/ncs/nw_c2_default6.ncs differ diff --git a/_module/ncs/nw_c2_default8.ncs b/_module/ncs/nw_c2_default8.ncs index 2df2091a..631a5226 100644 Binary files a/_module/ncs/nw_c2_default8.ncs and b/_module/ncs/nw_c2_default8.ncs differ diff --git a/_module/ncs/nw_c2_defaultb.ncs b/_module/ncs/nw_c2_defaultb.ncs index 146034f3..1afa53b7 100644 Binary files a/_module/ncs/nw_c2_defaultb.ncs and b/_module/ncs/nw_c2_defaultb.ncs differ diff --git a/_module/ncs/nw_c2_defaulte.ncs b/_module/ncs/nw_c2_defaulte.ncs index 1eb98734..db0e0b52 100644 Binary files a/_module/ncs/nw_c2_defaulte.ncs and b/_module/ncs/nw_c2_defaulte.ncs differ diff --git a/_module/ncs/nw_ch_ac1.ncs b/_module/ncs/nw_ch_ac1.ncs new file mode 100644 index 00000000..aab4daea Binary files /dev/null and b/_module/ncs/nw_ch_ac1.ncs differ diff --git a/_module/ncs/nw_ch_ac2.ncs b/_module/ncs/nw_ch_ac2.ncs index f0369fb5..b5e70e2a 100644 Binary files a/_module/ncs/nw_ch_ac2.ncs and b/_module/ncs/nw_ch_ac2.ncs differ diff --git a/_module/ncs/nw_ch_ac3.ncs b/_module/ncs/nw_ch_ac3.ncs new file mode 100644 index 00000000..9125c619 Binary files /dev/null and b/_module/ncs/nw_ch_ac3.ncs differ diff --git a/_module/ncs/nw_ch_ac4.ncs b/_module/ncs/nw_ch_ac4.ncs new file mode 100644 index 00000000..86308081 Binary files /dev/null and b/_module/ncs/nw_ch_ac4.ncs differ diff --git a/_module/ncs/nw_ch_ac5.ncs b/_module/ncs/nw_ch_ac5.ncs new file mode 100644 index 00000000..4e6b5a8c Binary files /dev/null and b/_module/ncs/nw_ch_ac5.ncs differ diff --git a/_module/ncs/nw_ch_ac6.ncs b/_module/ncs/nw_ch_ac6.ncs new file mode 100644 index 00000000..10f3f1ff Binary files /dev/null and b/_module/ncs/nw_ch_ac6.ncs differ diff --git a/_module/ncs/nw_ch_ac8.ncs b/_module/ncs/nw_ch_ac8.ncs new file mode 100644 index 00000000..44db5e50 Binary files /dev/null and b/_module/ncs/nw_ch_ac8.ncs differ diff --git a/_module/ncs/nw_ch_aca.ncs b/_module/ncs/nw_ch_aca.ncs new file mode 100644 index 00000000..d5ad0b42 Binary files /dev/null and b/_module/ncs/nw_ch_aca.ncs differ diff --git a/_module/ncs/nw_ch_acb.ncs b/_module/ncs/nw_ch_acb.ncs new file mode 100644 index 00000000..d2a2d61a Binary files /dev/null and b/_module/ncs/nw_ch_acb.ncs differ diff --git a/_module/ncs/nw_ch_ace.ncs b/_module/ncs/nw_ch_ace.ncs new file mode 100644 index 00000000..7ed9d641 Binary files /dev/null and b/_module/ncs/nw_ch_ace.ncs differ diff --git a/_module/ncs/nw_ch_summon_9.ncs b/_module/ncs/nw_ch_summon_9.ncs new file mode 100644 index 00000000..43fdf733 Binary files /dev/null and b/_module/ncs/nw_ch_summon_9.ncs differ diff --git a/_module/ncs/nw_o2_boss.ncs b/_module/ncs/nw_o2_boss.ncs index 57cdce63..cbfe2929 100644 Binary files a/_module/ncs/nw_o2_boss.ncs and b/_module/ncs/nw_o2_boss.ncs differ diff --git a/_module/ncs/nw_o2_classweap.ncs b/_module/ncs/nw_o2_classweap.ncs index 354ca56c..100d8c1f 100644 Binary files a/_module/ncs/nw_o2_classweap.ncs and b/_module/ncs/nw_o2_classweap.ncs differ diff --git a/_module/ncs/nw_o2_generalhig.ncs b/_module/ncs/nw_o2_generalhig.ncs index 35297075..4088ba7e 100644 Binary files a/_module/ncs/nw_o2_generalhig.ncs and b/_module/ncs/nw_o2_generalhig.ncs differ diff --git a/_module/ncs/nw_o2_generallow.ncs b/_module/ncs/nw_o2_generallow.ncs index 55674bc1..db902117 100644 Binary files a/_module/ncs/nw_o2_generallow.ncs and b/_module/ncs/nw_o2_generallow.ncs differ diff --git a/_module/ncs/nw_o2_generalmed.ncs b/_module/ncs/nw_o2_generalmed.ncs index 169bf904..918b0a04 100644 Binary files a/_module/ncs/nw_o2_generalmed.ncs and b/_module/ncs/nw_o2_generalmed.ncs differ diff --git a/_module/ncs/obj_us_chest.ncs b/_module/ncs/obj_us_chest.ncs index a52c2c7f..288720cf 100644 Binary files a/_module/ncs/obj_us_chest.ncs and b/_module/ncs/obj_us_chest.ncs differ diff --git a/_module/ncs/on_mod_enter.ncs b/_module/ncs/on_mod_enter.ncs index 1707a89d..df6183d0 100644 Binary files a/_module/ncs/on_mod_enter.ncs and b/_module/ncs/on_mod_enter.ncs differ diff --git a/_module/ncs/on_pc_respawn.ncs b/_module/ncs/on_pc_respawn.ncs index 4975dbf7..e0f6ed31 100644 Binary files a/_module/ncs/on_pc_respawn.ncs and b/_module/ncs/on_pc_respawn.ncs differ diff --git a/_module/ncs/on_pcdie.ncs b/_module/ncs/on_pcdie.ncs index 556d12fe..b753e745 100644 Binary files a/_module/ncs/on_pcdie.ncs and b/_module/ncs/on_pcdie.ncs differ diff --git a/_module/ncs/onrest.ncs b/_module/ncs/onrest.ncs index 00c36a19..c65e05b0 100644 Binary files a/_module/ncs/onrest.ncs and b/_module/ncs/onrest.ncs differ diff --git a/_module/ncs/open_gemstore.ncs b/_module/ncs/open_gemstore.ncs index cba0012c..456fae7d 100644 Binary files a/_module/ncs/open_gemstore.ncs and b/_module/ncs/open_gemstore.ncs differ diff --git a/_module/ncs/open_shop.ncs b/_module/ncs/open_shop.ncs index cbbb3a2b..7706c344 100644 Binary files a/_module/ncs/open_shop.ncs and b/_module/ncs/open_shop.ncs differ diff --git a/_module/ncs/pc_ondeath.ncs b/_module/ncs/pc_ondeath.ncs index d4131b30..363c5db3 100644 Binary files a/_module/ncs/pc_ondeath.ncs and b/_module/ncs/pc_ondeath.ncs differ diff --git a/_module/ncs/pc_room_onexit.ncs b/_module/ncs/pc_room_onexit.ncs index c567d0c2..26adf172 100644 Binary files a/_module/ncs/pc_room_onexit.ncs and b/_module/ncs/pc_room_onexit.ncs differ diff --git a/_module/ncs/pc_savebuffs.ncs b/_module/ncs/pc_savebuffs.ncs new file mode 100644 index 00000000..cb415d49 Binary files /dev/null and b/_module/ncs/pc_savebuffs.ncs differ diff --git a/_module/ncs/pe_buffing.ncs b/_module/ncs/pe_buffing.ncs new file mode 100644 index 00000000..f1564d41 Binary files /dev/null and b/_module/ncs/pe_buffing.ncs differ diff --git a/_module/ncs/pe_crafting.ncs b/_module/ncs/pe_crafting.ncs new file mode 100644 index 00000000..5d741a0d Binary files /dev/null and b/_module/ncs/pe_crafting.ncs differ diff --git a/_module/ncs/pe_debug.ncs b/_module/ncs/pe_debug.ncs new file mode 100644 index 00000000..04366bf6 Binary files /dev/null and b/_module/ncs/pe_debug.ncs differ diff --git a/_module/ncs/pe_henchmen.ncs b/_module/ncs/pe_henchmen.ncs new file mode 100644 index 00000000..7275c699 Binary files /dev/null and b/_module/ncs/pe_henchmen.ncs differ diff --git a/_module/ncs/pe_mod_set.ncs b/_module/ncs/pe_mod_set.ncs new file mode 100644 index 00000000..ccab4daf Binary files /dev/null and b/_module/ncs/pe_mod_set.ncs differ diff --git a/_module/ncs/pe_test.ncs b/_module/ncs/pe_test.ncs new file mode 100644 index 00000000..3fb5d405 Binary files /dev/null and b/_module/ncs/pe_test.ncs differ diff --git a/_module/ncs/pi_buffing.ncs b/_module/ncs/pi_buffing.ncs new file mode 100644 index 00000000..c1a93e9a Binary files /dev/null and b/_module/ncs/pi_buffing.ncs differ diff --git a/_module/ncs/pi_crafting.ncs b/_module/ncs/pi_crafting.ncs new file mode 100644 index 00000000..dc5627fe Binary files /dev/null and b/_module/ncs/pi_crafting.ncs differ diff --git a/_module/ncs/pi_debug.ncs b/_module/ncs/pi_debug.ncs new file mode 100644 index 00000000..1d9a0ea8 Binary files /dev/null and b/_module/ncs/pi_debug.ncs differ diff --git a/_module/ncs/pi_forcerest.ncs b/_module/ncs/pi_forcerest.ncs new file mode 100644 index 00000000..3beda059 Binary files /dev/null and b/_module/ncs/pi_forcerest.ncs differ diff --git a/_module/ncs/pi_henchmen.ncs b/_module/ncs/pi_henchmen.ncs new file mode 100644 index 00000000..ccaa01b1 Binary files /dev/null and b/_module/ncs/pi_henchmen.ncs differ diff --git a/_module/ncs/pi_test.ncs b/_module/ncs/pi_test.ncs new file mode 100644 index 00000000..7d3ae063 Binary files /dev/null and b/_module/ncs/pi_test.ncs differ diff --git a/_module/ncs/picklock.ncs b/_module/ncs/picklock.ncs index 74f6d708..9099fc0a 100644 Binary files a/_module/ncs/picklock.ncs and b/_module/ncs/picklock.ncs differ diff --git a/_module/ncs/plo_townport_use.ncs b/_module/ncs/plo_townport_use.ncs index 9f0735f9..a38b5606 100644 Binary files a/_module/ncs/plo_townport_use.ncs and b/_module/ncs/plo_townport_use.ncs differ diff --git a/_module/ncs/plo_townport_usr.ncs b/_module/ncs/plo_townport_usr.ncs index 91e3277e..43775d13 100644 Binary files a/_module/ncs/plo_townport_usr.ncs and b/_module/ncs/plo_townport_usr.ncs differ diff --git a/_module/ncs/port_archspire.ncs b/_module/ncs/port_archspire.ncs index 910ea290..6515d5be 100644 Binary files a/_module/ncs/port_archspire.ncs and b/_module/ncs/port_archspire.ncs differ diff --git a/_module/ncs/port_valeford.ncs b/_module/ncs/port_valeford.ncs index d66609b3..1325c3bc 100644 Binary files a/_module/ncs/port_valeford.ncs and b/_module/ncs/port_valeford.ncs differ diff --git a/_module/ncs/prc_pw_raisedead.ncs b/_module/ncs/prc_pw_raisedead.ncs index 4f3283f9..275626d0 100644 Binary files a/_module/ncs/prc_pw_raisedead.ncs and b/_module/ncs/prc_pw_raisedead.ncs differ diff --git a/_module/ncs/prc_pw_res.ncs b/_module/ncs/prc_pw_res.ncs index dc015b10..584e9829 100644 Binary files a/_module/ncs/prc_pw_res.ncs and b/_module/ncs/prc_pw_res.ncs differ diff --git a/_module/ncs/prc_pwonspawn.ncs b/_module/ncs/prc_pwonspawn.ncs index 79012fd5..301064af 100644 Binary files a/_module/ncs/prc_pwonspawn.ncs and b/_module/ncs/prc_pwonspawn.ncs differ diff --git a/_module/ncs/rest_inn.ncs b/_module/ncs/rest_inn.ncs index 3ffda967..d7062ebb 100644 Binary files a/_module/ncs/rest_inn.ncs and b/_module/ncs/rest_inn.ncs differ diff --git a/_module/ncs/riddler_a.ncs b/_module/ncs/riddler_a.ncs index 2b95a565..ed878502 100644 Binary files a/_module/ncs/riddler_a.ncs and b/_module/ncs/riddler_a.ncs differ diff --git a/_module/ncs/riddler_g.ncs b/_module/ncs/riddler_g.ncs index 1ed6ffd7..d1bcdca5 100644 Binary files a/_module/ncs/riddler_g.ncs and b/_module/ncs/riddler_g.ncs differ diff --git a/_module/ncs/riddler_q.ncs b/_module/ncs/riddler_q.ncs index 765e9305..e536be60 100644 Binary files a/_module/ncs/riddler_q.ncs and b/_module/ncs/riddler_q.ncs differ diff --git a/_module/ncs/rnd_addcsc.ncs b/_module/ncs/rnd_addcsc.ncs index 5f7412da..732383f6 100644 Binary files a/_module/ncs/rnd_addcsc.ncs and b/_module/ncs/rnd_addcsc.ncs differ diff --git a/_module/ncs/rnd_addcsd.ncs b/_module/ncs/rnd_addcsd.ncs index f570ba9f..08d1a3b9 100644 Binary files a/_module/ncs/rnd_addcsd.ncs and b/_module/ncs/rnd_addcsd.ncs differ diff --git a/_module/ncs/rnd_addwand.ncs b/_module/ncs/rnd_addwand.ncs index f7c9a3b1..4d7b9e03 100644 Binary files a/_module/ncs/rnd_addwand.ncs and b/_module/ncs/rnd_addwand.ncs differ diff --git a/_module/ncs/rnd_amlt.ncs b/_module/ncs/rnd_amlt.ncs index ef6ca349..f71a1c9c 100644 Binary files a/_module/ncs/rnd_amlt.ncs and b/_module/ncs/rnd_amlt.ncs differ diff --git a/_module/ncs/rnd_arrow.ncs b/_module/ncs/rnd_arrow.ncs index 804339c8..ecf7c800 100644 Binary files a/_module/ncs/rnd_arrow.ncs and b/_module/ncs/rnd_arrow.ncs differ diff --git a/_module/ncs/rnd_belt.ncs b/_module/ncs/rnd_belt.ncs index 76384cbe..3b7c3b9b 100644 Binary files a/_module/ncs/rnd_belt.ncs and b/_module/ncs/rnd_belt.ncs differ diff --git a/_module/ncs/rnd_blnt.ncs b/_module/ncs/rnd_blnt.ncs index 4fa388bb..0845a6b3 100644 Binary files a/_module/ncs/rnd_blnt.ncs and b/_module/ncs/rnd_blnt.ncs differ diff --git a/_module/ncs/rnd_boot.ncs b/_module/ncs/rnd_boot.ncs index 4f89d11f..6930a4a4 100644 Binary files a/_module/ncs/rnd_boot.ncs and b/_module/ncs/rnd_boot.ncs differ diff --git a/_module/ncs/rnd_clok.ncs b/_module/ncs/rnd_clok.ncs index 66c81226..f6dd8ab0 100644 Binary files a/_module/ncs/rnd_clok.ncs and b/_module/ncs/rnd_clok.ncs differ diff --git a/_module/ncs/rnd_exot.ncs b/_module/ncs/rnd_exot.ncs index 51ac2a1d..d227eebb 100644 Binary files a/_module/ncs/rnd_exot.ncs and b/_module/ncs/rnd_exot.ncs differ diff --git a/_module/ncs/rnd_gaun.ncs b/_module/ncs/rnd_gaun.ncs index a51b599a..b760a18d 100644 Binary files a/_module/ncs/rnd_gaun.ncs and b/_module/ncs/rnd_gaun.ncs differ diff --git a/_module/ncs/rnd_gossip.ncs b/_module/ncs/rnd_gossip.ncs index ad48a29f..c414f8b4 100644 Binary files a/_module/ncs/rnd_gossip.ncs and b/_module/ncs/rnd_gossip.ncs differ diff --git a/_module/ncs/rnd_harm.ncs b/_module/ncs/rnd_harm.ncs index 31d0b001..fe636548 100644 Binary files a/_module/ncs/rnd_harm.ncs and b/_module/ncs/rnd_harm.ncs differ diff --git a/_module/ncs/rnd_helm.ncs b/_module/ncs/rnd_helm.ncs index 31d0b001..fe636548 100644 Binary files a/_module/ncs/rnd_helm.ncs and b/_module/ncs/rnd_helm.ncs differ diff --git a/_module/ncs/rnd_larm.ncs b/_module/ncs/rnd_larm.ncs index 31d0b001..fe636548 100644 Binary files a/_module/ncs/rnd_larm.ncs and b/_module/ncs/rnd_larm.ncs differ diff --git a/_module/ncs/rnd_long.ncs b/_module/ncs/rnd_long.ncs index 4fa388bb..0845a6b3 100644 Binary files a/_module/ncs/rnd_long.ncs and b/_module/ncs/rnd_long.ncs differ diff --git a/_module/ncs/rnd_magicitem.ncs b/_module/ncs/rnd_magicitem.ncs index 528599be..35b720b5 100644 Binary files a/_module/ncs/rnd_magicitem.ncs and b/_module/ncs/rnd_magicitem.ncs differ diff --git a/_module/ncs/rnd_marm.ncs b/_module/ncs/rnd_marm.ncs index 31d0b001..fe636548 100644 Binary files a/_module/ncs/rnd_marm.ncs and b/_module/ncs/rnd_marm.ncs differ diff --git a/_module/ncs/rnd_ring.ncs b/_module/ncs/rnd_ring.ncs index 0f76bb93..15bffbf4 100644 Binary files a/_module/ncs/rnd_ring.ncs and b/_module/ncs/rnd_ring.ncs differ diff --git a/_module/ncs/rnd_robe.ncs b/_module/ncs/rnd_robe.ncs index 4288e2bc..2a4cafbd 100644 Binary files a/_module/ncs/rnd_robe.ncs and b/_module/ncs/rnd_robe.ncs differ diff --git a/_module/ncs/rnd_rwep.ncs b/_module/ncs/rnd_rwep.ncs index 525d94ed..935fb984 100644 Binary files a/_module/ncs/rnd_rwep.ncs and b/_module/ncs/rnd_rwep.ncs differ diff --git a/_module/ncs/rnd_shld.ncs b/_module/ncs/rnd_shld.ncs index 3e880f93..2915b8ce 100644 Binary files a/_module/ncs/rnd_shld.ncs and b/_module/ncs/rnd_shld.ncs differ diff --git a/_module/ncs/rnd_stff.ncs b/_module/ncs/rnd_stff.ncs index a420d472..56f02ba9 100644 Binary files a/_module/ncs/rnd_stff.ncs and b/_module/ncs/rnd_stff.ncs differ diff --git a/_module/ncs/rnd_swrd.ncs b/_module/ncs/rnd_swrd.ncs index 4fa388bb..0845a6b3 100644 Binary files a/_module/ncs/rnd_swrd.ncs and b/_module/ncs/rnd_swrd.ncs differ diff --git a/_module/ncs/scrolloftownport.ncs b/_module/ncs/scrolloftownport.ncs index 0bbb3224..23a3a06f 100644 Binary files a/_module/ncs/scrolloftownport.ncs and b/_module/ncs/scrolloftownport.ncs differ diff --git a/_module/ncs/se_door_death.ncs b/_module/ncs/se_door_death.ncs index 12091647..a71b2a20 100644 Binary files a/_module/ncs/se_door_death.ncs and b/_module/ncs/se_door_death.ncs differ diff --git a/_module/ncs/sei_sit.ncs b/_module/ncs/sei_sit.ncs index de30a5f7..794e5f14 100644 Binary files a/_module/ncs/sei_sit.ncs and b/_module/ncs/sei_sit.ncs differ diff --git a/_module/ncs/sell_root.ncs b/_module/ncs/sell_root.ncs index 54355079..72ef5a35 100644 Binary files a/_module/ncs/sell_root.ncs and b/_module/ncs/sell_root.ncs differ diff --git a/_module/ncs/sob_examine002.ncs b/_module/ncs/sob_examine002.ncs index 7098ab3d..26d4486a 100644 Binary files a/_module/ncs/sob_examine002.ncs and b/_module/ncs/sob_examine002.ncs differ diff --git a/_module/ncs/spawn.ncs b/_module/ncs/spawn.ncs index 4149fb59..e4c29229 100644 Binary files a/_module/ncs/spawn.ncs and b/_module/ncs/spawn.ncs differ diff --git a/_module/ncs/spawn_mummy_onds.ncs b/_module/ncs/spawn_mummy_onds.ncs index 9183af82..f17145c1 100644 Binary files a/_module/ncs/spawn_mummy_onds.ncs and b/_module/ncs/spawn_mummy_onds.ncs differ diff --git a/_module/ncs/spawn_percy.ncs b/_module/ncs/spawn_percy.ncs index 9da1fbb0..68ffac68 100644 Binary files a/_module/ncs/spawn_percy.ncs and b/_module/ncs/spawn_percy.ncs differ diff --git a/_module/ncs/spawn_towners.ncs b/_module/ncs/spawn_towners.ncs index 46266e95..f2604520 100644 Binary files a/_module/ncs/spawn_towners.ncs and b/_module/ncs/spawn_towners.ncs differ diff --git a/_module/ncs/ss_treas_auto_on.ncs b/_module/ncs/ss_treas_auto_on.ncs index 64796903..6032cd16 100644 Binary files a/_module/ncs/ss_treas_auto_on.ncs and b/_module/ncs/ss_treas_auto_on.ncs differ diff --git a/_module/ncs/ss_treas_chest.ncs b/_module/ncs/ss_treas_chest.ncs index f2d0f061..bc681b02 100644 Binary files a/_module/ncs/ss_treas_chest.ncs and b/_module/ncs/ss_treas_chest.ncs differ diff --git a/_module/ncs/ss_treasure.ncs b/_module/ncs/ss_treasure.ncs index 1f06c1f2..e4c7f940 100644 Binary files a/_module/ncs/ss_treasure.ncs and b/_module/ncs/ss_treasure.ncs differ diff --git a/_module/ncs/ss_treasure_spwn.ncs b/_module/ncs/ss_treasure_spwn.ncs index d51738d2..a276d4c4 100644 Binary files a/_module/ncs/ss_treasure_spwn.ncs and b/_module/ncs/ss_treasure_spwn.ncs differ diff --git a/_module/ncs/store_cleaner.ncs b/_module/ncs/store_cleaner.ncs index 394d0301..98674062 100644 Binary files a/_module/ncs/store_cleaner.ncs and b/_module/ncs/store_cleaner.ncs differ diff --git a/_module/ncs/townportal.ncs b/_module/ncs/townportal.ncs index 8f588273..b28c4799 100644 Binary files a/_module/ncs/townportal.ncs and b/_module/ncs/townportal.ncs differ diff --git a/_module/ncs/trig_can_refill.ncs b/_module/ncs/trig_can_refill.ncs index 38437d19..d1681069 100644 Binary files a/_module/ncs/trig_can_refill.ncs and b/_module/ncs/trig_can_refill.ncs differ diff --git a/_module/ncs/trig_cant_refill.ncs b/_module/ncs/trig_cant_refill.ncs index 1c3c0ab5..eca5d6f2 100644 Binary files a/_module/ncs/trig_cant_refill.ncs and b/_module/ncs/trig_cant_refill.ncs differ diff --git a/_module/ncs/trig_sleep.ncs b/_module/ncs/trig_sleep.ncs index f2e47eae..8eea2745 100644 Binary files a/_module/ncs/trig_sleep.ncs and b/_module/ncs/trig_sleep.ncs differ diff --git a/_module/ncs/ucd_xpawardtraps.ncs b/_module/ncs/ucd_xpawardtraps.ncs index 55499259..a3911877 100644 Binary files a/_module/ncs/ucd_xpawardtraps.ncs and b/_module/ncs/ucd_xpawardtraps.ncs differ diff --git a/_module/ncs/use_altar_evil.ncs b/_module/ncs/use_altar_evil.ncs index d847128b..b388d6f7 100644 Binary files a/_module/ncs/use_altar_evil.ncs and b/_module/ncs/use_altar_evil.ncs differ diff --git a/_module/ncs/use_altar_good.ncs b/_module/ncs/use_altar_good.ncs index f8ba8c85..4f1f2bc1 100644 Binary files a/_module/ncs/use_altar_good.ncs and b/_module/ncs/use_altar_good.ncs differ diff --git a/_module/ncs/use_archery_targ.ncs b/_module/ncs/use_archery_targ.ncs index d95ce095..8756628f 100644 Binary files a/_module/ncs/use_archery_targ.ncs and b/_module/ncs/use_archery_targ.ncs differ diff --git a/_module/ncs/use_contraption.ncs b/_module/ncs/use_contraption.ncs index 49469cdf..4b3054b2 100644 Binary files a/_module/ncs/use_contraption.ncs and b/_module/ncs/use_contraption.ncs differ diff --git a/_module/ncs/use_controlpanel.ncs b/_module/ncs/use_controlpanel.ncs index 480ffca3..9725735a 100644 Binary files a/_module/ncs/use_controlpanel.ncs and b/_module/ncs/use_controlpanel.ncs differ diff --git a/_module/ncs/use_crystalball.ncs b/_module/ncs/use_crystalball.ncs index e2ff7c8a..e7215e89 100644 Binary files a/_module/ncs/use_crystalball.ncs and b/_module/ncs/use_crystalball.ncs differ diff --git a/_module/ncs/use_drink_d.ncs b/_module/ncs/use_drink_d.ncs index 1e4f3cde..2e674ddf 100644 Binary files a/_module/ncs/use_drink_d.ncs and b/_module/ncs/use_drink_d.ncs differ diff --git a/_module/ncs/use_drink_p.ncs b/_module/ncs/use_drink_p.ncs index f02b00c3..2cd32322 100644 Binary files a/_module/ncs/use_drink_p.ncs and b/_module/ncs/use_drink_p.ncs differ diff --git a/_module/ncs/use_gong.ncs b/_module/ncs/use_gong.ncs index 780cf69f..8fe6506a 100644 Binary files a/_module/ncs/use_gong.ncs and b/_module/ncs/use_gong.ncs differ diff --git a/_module/ncs/use_healfount.ncs b/_module/ncs/use_healfount.ncs index 6a0b87b4..ab5d7039 100644 Binary files a/_module/ncs/use_healfount.ncs and b/_module/ncs/use_healfount.ncs differ diff --git a/_module/ncs/use_mirror.ncs b/_module/ncs/use_mirror.ncs index 609f016e..a972c7ba 100644 Binary files a/_module/ncs/use_mirror.ncs and b/_module/ncs/use_mirror.ncs differ diff --git a/_module/ncs/use_obelisk.ncs b/_module/ncs/use_obelisk.ncs index c78c675b..de040d37 100644 Binary files a/_module/ncs/use_obelisk.ncs and b/_module/ncs/use_obelisk.ncs differ diff --git a/_module/ncs/vat_setcharges.ncs b/_module/ncs/vat_setcharges.ncs index 3d10e23c..f098f1f7 100644 Binary files a/_module/ncs/vat_setcharges.ncs and b/_module/ncs/vat_setcharges.ncs differ diff --git a/_module/ncs/vtw_chargecost.ncs b/_module/ncs/vtw_chargecost.ncs index 095dc102..93c61cf4 100644 Binary files a/_module/ncs/vtw_chargecost.ncs and b/_module/ncs/vtw_chargecost.ncs differ diff --git a/_module/ncs/vtw_false.ncs b/_module/ncs/vtw_false.ncs index a6d4bab9..16175694 100644 Binary files a/_module/ncs/vtw_false.ncs and b/_module/ncs/vtw_false.ncs differ diff --git a/_module/ncs/vtw_gmrt.ncs b/_module/ncs/vtw_gmrt.ncs index 4d30e5ec..0e82a162 100644 Binary files a/_module/ncs/vtw_gmrt.ncs and b/_module/ncs/vtw_gmrt.ncs differ diff --git a/_module/ncs/vtw_gmta.ncs b/_module/ncs/vtw_gmta.ncs index 2fd43983..73945c18 100644 Binary files a/_module/ncs/vtw_gmta.ncs and b/_module/ncs/vtw_gmta.ncs differ diff --git a/_module/ncs/vtw_hasgold.ncs b/_module/ncs/vtw_hasgold.ncs index 0d2fcfab..67fb7089 100644 Binary files a/_module/ncs/vtw_hasgold.ncs and b/_module/ncs/vtw_hasgold.ncs differ diff --git a/_module/ncs/vtw_m.ncs b/_module/ncs/vtw_m.ncs index 046f723b..790e0b6b 100644 Binary files a/_module/ncs/vtw_m.ncs and b/_module/ncs/vtw_m.ncs differ diff --git a/_module/ncs/vtw_mrt.ncs b/_module/ncs/vtw_mrt.ncs index 0b1cda03..ecfedfd6 100644 Binary files a/_module/ncs/vtw_mrt.ncs and b/_module/ncs/vtw_mrt.ncs differ diff --git a/_module/ncs/vtw_mt.ncs b/_module/ncs/vtw_mt.ncs index 68430a80..e9ecd9e6 100644 Binary files a/_module/ncs/vtw_mt.ncs and b/_module/ncs/vtw_mt.ncs differ diff --git a/_module/ncs/vtw_mta.ncs b/_module/ncs/vtw_mta.ncs index 2c372340..5589c8ec 100644 Binary files a/_module/ncs/vtw_mta.ncs and b/_module/ncs/vtw_mta.ncs differ diff --git a/_module/ncs/vtw_nonsupported.ncs b/_module/ncs/vtw_nonsupported.ncs index 5c7738da..1dd75957 100644 Binary files a/_module/ncs/vtw_nonsupported.ncs and b/_module/ncs/vtw_nonsupported.ncs differ diff --git a/_module/ncs/vtw_notgold.ncs b/_module/ncs/vtw_notgold.ncs index ba538057..a4b26aa2 100644 Binary files a/_module/ncs/vtw_notgold.ncs and b/_module/ncs/vtw_notgold.ncs differ diff --git a/_module/ncs/vtw_r.ncs b/_module/ncs/vtw_r.ncs index 7667ad36..12b761a0 100644 Binary files a/_module/ncs/vtw_r.ncs and b/_module/ncs/vtw_r.ncs differ diff --git a/_module/ncs/vtw_rt.ncs b/_module/ncs/vtw_rt.ncs index d1d301c3..3dd34225 100644 Binary files a/_module/ncs/vtw_rt.ncs and b/_module/ncs/vtw_rt.ncs differ diff --git a/_module/ncs/vtw_s.ncs b/_module/ncs/vtw_s.ncs index e614306e..92b6b929 100644 Binary files a/_module/ncs/vtw_s.ncs and b/_module/ncs/vtw_s.ncs differ diff --git a/_module/ncs/vtw_shgmr.ncs b/_module/ncs/vtw_shgmr.ncs index fc4606be..48b261e9 100644 Binary files a/_module/ncs/vtw_shgmr.ncs and b/_module/ncs/vtw_shgmr.ncs differ diff --git a/_module/ncs/vtw_shgmrt.ncs b/_module/ncs/vtw_shgmrt.ncs index e1fd92dd..e3abe061 100644 Binary files a/_module/ncs/vtw_shgmrt.ncs and b/_module/ncs/vtw_shgmrt.ncs differ diff --git a/_module/ncs/vtw_shgmrw.ncs b/_module/ncs/vtw_shgmrw.ncs index b0cb3b11..6327b27d 100644 Binary files a/_module/ncs/vtw_shgmrw.ncs and b/_module/ncs/vtw_shgmrw.ncs differ diff --git a/_module/ncs/x0_ch_hen_conv.ncs b/_module/ncs/x0_ch_hen_conv.ncs index fa13b9bc..af2224e3 100644 Binary files a/_module/ncs/x0_ch_hen_conv.ncs and b/_module/ncs/x0_ch_hen_conv.ncs differ diff --git a/_module/ncs/x0_ch_hen_heart.ncs b/_module/ncs/x0_ch_hen_heart.ncs index 4a10674e..1959eecb 100644 Binary files a/_module/ncs/x0_ch_hen_heart.ncs and b/_module/ncs/x0_ch_hen_heart.ncs differ diff --git a/_module/ncs/x0_ch_hen_percep.ncs b/_module/ncs/x0_ch_hen_percep.ncs index 6e7a992f..0a4c19dd 100644 Binary files a/_module/ncs/x0_ch_hen_percep.ncs and b/_module/ncs/x0_ch_hen_percep.ncs differ diff --git a/_module/ncs/x2_def_spawn.ncs b/_module/ncs/x2_def_spawn.ncs new file mode 100644 index 00000000..1d3dbe1b Binary files /dev/null and b/_module/ncs/x2_def_spawn.ncs differ diff --git a/_module/ncs/x2_mod_def_equ.ncs b/_module/ncs/x2_mod_def_equ.ncs index e9c72400..93e1e4ae 100644 Binary files a/_module/ncs/x2_mod_def_equ.ncs and b/_module/ncs/x2_mod_def_equ.ncs differ diff --git a/_module/ncs/x2_mod_def_load.ncs b/_module/ncs/x2_mod_def_load.ncs index 9723f968..695141f1 100644 Binary files a/_module/ncs/x2_mod_def_load.ncs and b/_module/ncs/x2_mod_def_load.ncs differ diff --git a/_module/ncs/xx_pc_1_hb.ncs b/_module/ncs/xx_pc_1_hb.ncs new file mode 100644 index 00000000..21caec30 Binary files /dev/null and b/_module/ncs/xx_pc_1_hb.ncs differ diff --git a/_module/ncs/xx_pc_2_percept.ncs b/_module/ncs/xx_pc_2_percept.ncs new file mode 100644 index 00000000..908ca7e1 Binary files /dev/null and b/_module/ncs/xx_pc_2_percept.ncs differ diff --git a/_module/ncs/xx_pc_3_endround.ncs b/_module/ncs/xx_pc_3_endround.ncs new file mode 100644 index 00000000..2acc6c03 Binary files /dev/null and b/_module/ncs/xx_pc_3_endround.ncs differ diff --git a/_module/ncs/xx_pc_4_convers.ncs b/_module/ncs/xx_pc_4_convers.ncs new file mode 100644 index 00000000..c63ea387 Binary files /dev/null and b/_module/ncs/xx_pc_4_convers.ncs differ diff --git a/_module/ncs/xx_pc_5_phyatked.ncs b/_module/ncs/xx_pc_5_phyatked.ncs new file mode 100644 index 00000000..9136c2be Binary files /dev/null and b/_module/ncs/xx_pc_5_phyatked.ncs differ diff --git a/_module/ncs/xx_pc_6_damaged.ncs b/_module/ncs/xx_pc_6_damaged.ncs new file mode 100644 index 00000000..0ee05115 Binary files /dev/null and b/_module/ncs/xx_pc_6_damaged.ncs differ diff --git a/_module/ncs/xx_pc_8_disturb.ncs b/_module/ncs/xx_pc_8_disturb.ncs new file mode 100644 index 00000000..6ef01265 Binary files /dev/null and b/_module/ncs/xx_pc_8_disturb.ncs differ diff --git a/_module/ncs/xx_pc_b_castat.ncs b/_module/ncs/xx_pc_b_castat.ncs new file mode 100644 index 00000000..b9b51082 Binary files /dev/null and b/_module/ncs/xx_pc_b_castat.ncs differ diff --git a/_module/ncs/xx_pc_e_blocked.ncs b/_module/ncs/xx_pc_e_blocked.ncs new file mode 100644 index 00000000..009f816b Binary files /dev/null and b/_module/ncs/xx_pc_e_blocked.ncs differ diff --git a/_module/ncs/zep_onoff_cruel.ncs b/_module/ncs/zep_onoff_cruel.ncs index 2b5b57bf..065055c7 100644 Binary files a/_module/ncs/zep_onoff_cruel.ncs and b/_module/ncs/zep_onoff_cruel.ncs differ diff --git a/_module/nss/0c_assoc_actions.nss b/_module/nss/0c_assoc_actions.nss new file mode 100644 index 00000000..74975d45 --- /dev/null +++ b/_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/_module/nss/0c_cast_polymorp.nss b/_module/nss/0c_cast_polymorp.nss new file mode 100644 index 00000000..b06f1834 --- /dev/null +++ b/_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/_module/nss/0c_fire_henchmen.nss b/_module/nss/0c_fire_henchmen.nss new file mode 100644 index 00000000..5505be97 --- /dev/null +++ b/_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/_module/nss/0c_get_convo.nss b/_module/nss/0c_get_convo.nss new file mode 100644 index 00000000..7cdfd409 --- /dev/null +++ b/_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/_module/nss/0c_get_henchman.nss b/_module/nss/0c_get_henchman.nss new file mode 100644 index 00000000..e0952d57 --- /dev/null +++ b/_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/_module/nss/0c_h_cast_spell.nss b/_module/nss/0c_h_cast_spell.nss new file mode 100644 index 00000000..40868d87 --- /dev/null +++ b/_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/_module/nss/0c_henchmenspell.nss b/_module/nss/0c_henchmenspell.nss new file mode 100644 index 00000000..5e64cbac --- /dev/null +++ b/_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/_module/nss/0c_if_a_magic_m.nss b/_module/nss/0c_if_a_magic_m.nss new file mode 100644 index 00000000..7ef48321 --- /dev/null +++ b/_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/_module/nss/0c_if_ass_convo.nss b/_module/nss/0c_if_ass_convo.nss new file mode 100644 index 00000000..190a0f73 --- /dev/null +++ b/_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/_module/nss/0c_if_assoc_mode.nss b/_module/nss/0c_if_assoc_mode.nss new file mode 100644 index 00000000..342bfff3 --- /dev/null +++ b/_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/_module/nss/0c_if_cntrspell.nss b/_module/nss/0c_if_cntrspell.nss new file mode 100644 index 00000000..a0a5c878 --- /dev/null +++ b/_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/_module/nss/0c_if_com_script.nss b/_module/nss/0c_if_com_script.nss new file mode 100644 index 00000000..34d8370e --- /dev/null +++ b/_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/_module/nss/0c_if_convo.nss b/_module/nss/0c_if_convo.nss new file mode 100644 index 00000000..83e1db43 --- /dev/null +++ b/_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/_module/nss/0c_if_has_assoc.nss b/_module/nss/0c_if_has_assoc.nss new file mode 100644 index 00000000..cd16680b --- /dev/null +++ b/_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/_module/nss/0c_if_has_class.nss b/_module/nss/0c_if_has_class.nss new file mode 100644 index 00000000..1251c0a5 --- /dev/null +++ b/_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/_module/nss/0c_if_has_feat.nss b/_module/nss/0c_if_has_feat.nss new file mode 100644 index 00000000..fc111d84 --- /dev/null +++ b/_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/_module/nss/0c_if_has_spell.nss b/_module/nss/0c_if_has_spell.nss new file mode 100644 index 00000000..02004ff1 --- /dev/null +++ b/_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/_module/nss/0c_if_hen_leave.nss b/_module/nss/0c_if_hen_leave.nss new file mode 100644 index 00000000..e2b2bbdc --- /dev/null +++ b/_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/_module/nss/0c_if_identify.nss b/_module/nss/0c_if_identify.nss new file mode 100644 index 00000000..b593bafd --- /dev/null +++ b/_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/_module/nss/0c_if_not_master.nss b/_module/nss/0c_if_not_master.nss new file mode 100644 index 00000000..73cb84e6 --- /dev/null +++ b/_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/_module/nss/0c_if_open_inven.nss b/_module/nss/0c_if_open_inven.nss new file mode 100644 index 00000000..2755c990 --- /dev/null +++ b/_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/_module/nss/0c_if_pickuploot.nss b/_module/nss/0c_if_pickuploot.nss new file mode 100644 index 00000000..f4edfdb3 --- /dev/null +++ b/_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/_module/nss/0c_if_polymorph.nss b/_module/nss/0c_if_polymorph.nss new file mode 100644 index 00000000..e2317f6f --- /dev/null +++ b/_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/_module/nss/0c_if_scout.nss b/_module/nss/0c_if_scout.nss new file mode 100644 index 00000000..9f7b0a3b --- /dev/null +++ b/_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/_module/nss/0c_if_skillrank.nss b/_module/nss/0c_if_skillrank.nss new file mode 100644 index 00000000..e0d77294 --- /dev/null +++ b/_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/_module/nss/0c_if_taunt.nss b/_module/nss/0c_if_taunt.nss new file mode 100644 index 00000000..3e0fde64 --- /dev/null +++ b/_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/_module/nss/0c_listhenchman.nss b/_module/nss/0c_listhenchman.nss new file mode 100644 index 00000000..802f1003 --- /dev/null +++ b/_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/_module/nss/0c_no_com_script.nss b/_module/nss/0c_no_com_script.nss new file mode 100644 index 00000000..ca5c3863 --- /dev/null +++ b/_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/_module/nss/0c_remove_effect.nss b/_module/nss/0c_remove_effect.nss new file mode 100644 index 00000000..aa95a0ce --- /dev/null +++ b/_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/_module/nss/0c_summon_assoc.nss b/_module/nss/0c_summon_assoc.nss new file mode 100644 index 00000000..19544de2 --- /dev/null +++ b/_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/_module/nss/0c_use_feat.nss b/_module/nss/0c_use_feat.nss new file mode 100644 index 00000000..ec3ddcca --- /dev/null +++ b/_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/_module/nss/0e_c2_1_hb.nss b/_module/nss/0e_c2_1_hb.nss new file mode 100644 index 00000000..05fbfc2c --- /dev/null +++ b/_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/_module/nss/0e_c2_7_ondeath.nss b/_module/nss/0e_c2_7_ondeath.nss new file mode 100644 index 00000000..129e81ec --- /dev/null +++ b/_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/_module/nss/0e_ch_1_hb.nss b/_module/nss/0e_ch_1_hb.nss new file mode 100644 index 00000000..d04eeb8a --- /dev/null +++ b/_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/_module/nss/0e_ch_7_ondeath.nss b/_module/nss/0e_ch_7_ondeath.nss new file mode 100644 index 00000000..76d955df --- /dev/null +++ b/_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/_module/nss/0e_do_combat_rnd.nss b/_module/nss/0e_do_combat_rnd.nss new file mode 100644 index 00000000..f1cb9c00 --- /dev/null +++ b/_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/_module/nss/0e_gui_events.nss b/_module/nss/0e_gui_events.nss new file mode 100644 index 00000000..401c8254 --- /dev/null +++ b/_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/_module/nss/0e_m1_3_endround.nss b/_module/nss/0e_m1_3_endround.nss new file mode 100644 index 00000000..e8a0125e --- /dev/null +++ b/_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/_module/nss/0e_nui.nss b/_module/nss/0e_nui.nss new file mode 100644 index 00000000..7d18c65e --- /dev/null +++ b/_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/_module/nss/0e_nui_dm.nss b/_module/nss/0e_nui_dm.nss new file mode 100644 index 00000000..4ffd8515 --- /dev/null +++ b/_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/_module/nss/0e_onclientload.nss b/_module/nss/0e_onclientload.nss new file mode 100644 index 00000000..041d49ff --- /dev/null +++ b/_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/_module/nss/0e_player_target.nss b/_module/nss/0e_player_target.nss new file mode 100644 index 00000000..16b83fb6 --- /dev/null +++ b/_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/_module/nss/0e_prc_ch_events.nss b/_module/nss/0e_prc_ch_events.nss new file mode 100644 index 00000000..3028e9c8 --- /dev/null +++ b/_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/_module/nss/0i_actions.nss b/_module/nss/0i_actions.nss new file mode 100644 index 00000000..7d7d2d75 --- /dev/null +++ b/_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/_module/nss/0i_associates.nss b/_module/nss/0i_associates.nss new file mode 100644 index 00000000..23091603 --- /dev/null +++ b/_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/_module/nss/0i_color.nss b/_module/nss/0i_color.nss new file mode 100644 index 00000000..b18fe7ac --- /dev/null +++ b/_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/_module/nss/0i_combat.nss b/_module/nss/0i_combat.nss new file mode 100644 index 00000000..6c40eb1c --- /dev/null +++ b/_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/_module/nss/0i_constants.nss b/_module/nss/0i_constants.nss new file mode 100644 index 00000000..5413ac4d --- /dev/null +++ b/_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/_module/nss/0i_gui_events.nss b/_module/nss/0i_gui_events.nss new file mode 100644 index 00000000..4628cf3d --- /dev/null +++ b/_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/_module/nss/0i_items.nss b/_module/nss/0i_items.nss new file mode 100644 index 00000000..87d3ce7e --- /dev/null +++ b/_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/_module/nss/0i_main.nss b/_module/nss/0i_main.nss new file mode 100644 index 00000000..a0a46741 --- /dev/null +++ b/_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/_module/nss/0i_menus.nss b/_module/nss/0i_menus.nss new file mode 100644 index 00000000..8d6834ce --- /dev/null +++ b/_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/_module/nss/0i_menus_dm.nss b/_module/nss/0i_menus_dm.nss new file mode 100644 index 00000000..a2a2cfc8 --- /dev/null +++ b/_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/_module/nss/0i_messages.nss b/_module/nss/0i_messages.nss new file mode 100644 index 00000000..ff01269a --- /dev/null +++ b/_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/_module/nss/0i_module.nss b/_module/nss/0i_module.nss new file mode 100644 index 00000000..6d501824 --- /dev/null +++ b/_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/_module/nss/0i_nui.nss b/_module/nss/0i_nui.nss new file mode 100644 index 00000000..eab5ee7c --- /dev/null +++ b/_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/_module/nss/0i_player_target.nss b/_module/nss/0i_player_target.nss new file mode 100644 index 00000000..bed48348 --- /dev/null +++ b/_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/_module/nss/0i_spells.nss b/_module/nss/0i_spells.nss new file mode 100644 index 00000000..b7b75e2e --- /dev/null +++ b/_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/_module/nss/0i_states_cond.nss b/_module/nss/0i_states_cond.nss new file mode 100644 index 00000000..4c77ccf0 --- /dev/null +++ b/_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/_module/nss/0i_talents.nss b/_module/nss/0i_talents.nss new file mode 100644 index 00000000..fa773b9f --- /dev/null +++ b/_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/_module/nss/0i_time.nss b/_module/nss/0i_time.nss new file mode 100644 index 00000000..3052ea67 --- /dev/null +++ b/_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/_module/nss/ai_a_ambusher.nss b/_module/nss/ai_a_ambusher.nss new file mode 100644 index 00000000..f3f424b6 --- /dev/null +++ b/_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/_module/nss/ai_a_atk_casters.nss b/_module/nss/ai_a_atk_casters.nss new file mode 100644 index 00000000..362ba4b2 --- /dev/null +++ b/_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/_module/nss/ai_a_atk_nearest.nss b/_module/nss/ai_a_atk_nearest.nss new file mode 100644 index 00000000..1261dc7a --- /dev/null +++ b/_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/_module/nss/ai_a_atk_warrior.nss b/_module/nss/ai_a_atk_warrior.nss new file mode 100644 index 00000000..4821e53e --- /dev/null +++ b/_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/_module/nss/ai_a_barbarian.nss b/_module/nss/ai_a_barbarian.nss new file mode 100644 index 00000000..12521c93 --- /dev/null +++ b/_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/_module/nss/ai_a_bard.nss b/_module/nss/ai_a_bard.nss new file mode 100644 index 00000000..975bac2e --- /dev/null +++ b/_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/_module/nss/ai_a_cleric.nss b/_module/nss/ai_a_cleric.nss new file mode 100644 index 00000000..5de1cc26 --- /dev/null +++ b/_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/_module/nss/ai_a_cntrspell.nss b/_module/nss/ai_a_cntrspell.nss new file mode 100644 index 00000000..a1bc9ec0 --- /dev/null +++ b/_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/_module/nss/ai_a_default.nss b/_module/nss/ai_a_default.nss new file mode 100644 index 00000000..7540340c --- /dev/null +++ b/_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/_module/nss/ai_a_defensive.nss b/_module/nss/ai_a_defensive.nss new file mode 100644 index 00000000..f19523c4 --- /dev/null +++ b/_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/_module/nss/ai_a_druid.nss b/_module/nss/ai_a_druid.nss new file mode 100644 index 00000000..6b82c260 --- /dev/null +++ b/_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/_module/nss/ai_a_fighter.nss b/_module/nss/ai_a_fighter.nss new file mode 100644 index 00000000..a5f3720c --- /dev/null +++ b/_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/_module/nss/ai_a_flanker.nss b/_module/nss/ai_a_flanker.nss new file mode 100644 index 00000000..fb6845a5 --- /dev/null +++ b/_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/_module/nss/ai_a_invisible.nss b/_module/nss/ai_a_invisible.nss new file mode 100644 index 00000000..9772b322 --- /dev/null +++ b/_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/_module/nss/ai_a_monk.nss b/_module/nss/ai_a_monk.nss new file mode 100644 index 00000000..607ce4cd --- /dev/null +++ b/_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/_module/nss/ai_a_no_cmb_mode.nss b/_module/nss/ai_a_no_cmb_mode.nss new file mode 100644 index 00000000..1ffedb4d --- /dev/null +++ b/_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/_module/nss/ai_a_paladin.nss b/_module/nss/ai_a_paladin.nss new file mode 100644 index 00000000..24520a76 --- /dev/null +++ b/_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/_module/nss/ai_a_peaceful.nss b/_module/nss/ai_a_peaceful.nss new file mode 100644 index 00000000..b9bd3103 --- /dev/null +++ b/_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/_module/nss/ai_a_polymorphed.nss b/_module/nss/ai_a_polymorphed.nss new file mode 100644 index 00000000..107e6e92 --- /dev/null +++ b/_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/_module/nss/ai_a_ranged.nss b/_module/nss/ai_a_ranged.nss new file mode 100644 index 00000000..477937de --- /dev/null +++ b/_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/_module/nss/ai_a_ranger.nss b/_module/nss/ai_a_ranger.nss new file mode 100644 index 00000000..179298f0 --- /dev/null +++ b/_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/_module/nss/ai_a_rogue.nss b/_module/nss/ai_a_rogue.nss new file mode 100644 index 00000000..10e1ae05 --- /dev/null +++ b/_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/_module/nss/ai_a_sorcerer.nss b/_module/nss/ai_a_sorcerer.nss new file mode 100644 index 00000000..5e4a3b74 --- /dev/null +++ b/_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/_module/nss/ai_a_taunter.nss b/_module/nss/ai_a_taunter.nss new file mode 100644 index 00000000..b06fed80 --- /dev/null +++ b/_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/_module/nss/ai_a_wizard.nss b/_module/nss/ai_a_wizard.nss new file mode 100644 index 00000000..dfad8c30 --- /dev/null +++ b/_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/_module/nss/ai_ambusher.nss b/_module/nss/ai_ambusher.nss new file mode 100644 index 00000000..829a3dae --- /dev/null +++ b/_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/_module/nss/ai_barbarian.nss b/_module/nss/ai_barbarian.nss new file mode 100644 index 00000000..69efcb42 --- /dev/null +++ b/_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/_module/nss/ai_bard.nss b/_module/nss/ai_bard.nss new file mode 100644 index 00000000..9dde198f --- /dev/null +++ b/_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/_module/nss/ai_cleric.nss b/_module/nss/ai_cleric.nss new file mode 100644 index 00000000..34bd1e67 --- /dev/null +++ b/_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/_module/nss/ai_cntrspell.nss b/_module/nss/ai_cntrspell.nss new file mode 100644 index 00000000..04939c9f --- /dev/null +++ b/_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/_module/nss/ai_coward.nss b/_module/nss/ai_coward.nss new file mode 100644 index 00000000..b88e4243 --- /dev/null +++ b/_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/_module/nss/ai_default.nss b/_module/nss/ai_default.nss new file mode 100644 index 00000000..cfe8e8f9 --- /dev/null +++ b/_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/_module/nss/ai_defensive.nss b/_module/nss/ai_defensive.nss new file mode 100644 index 00000000..15f52751 --- /dev/null +++ b/_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/_module/nss/ai_dragon.nss b/_module/nss/ai_dragon.nss new file mode 100644 index 00000000..a82362ce --- /dev/null +++ b/_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/_module/nss/ai_druid.nss b/_module/nss/ai_druid.nss new file mode 100644 index 00000000..95cb82b5 --- /dev/null +++ b/_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/_module/nss/ai_fighter.nss b/_module/nss/ai_fighter.nss new file mode 100644 index 00000000..04f4ce06 --- /dev/null +++ b/_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/_module/nss/ai_flanker.nss b/_module/nss/ai_flanker.nss new file mode 100644 index 00000000..20a65389 --- /dev/null +++ b/_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/_module/nss/ai_incorporeal.nss b/_module/nss/ai_incorporeal.nss new file mode 100644 index 00000000..cdd20bdd --- /dev/null +++ b/_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/_module/nss/ai_invisible.nss b/_module/nss/ai_invisible.nss new file mode 100644 index 00000000..7d42b21b --- /dev/null +++ b/_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/_module/nss/ai_monk.nss b/_module/nss/ai_monk.nss new file mode 100644 index 00000000..d6ff1b65 --- /dev/null +++ b/_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/_module/nss/ai_paladin.nss b/_module/nss/ai_paladin.nss new file mode 100644 index 00000000..d45d2231 --- /dev/null +++ b/_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/_module/nss/ai_polymorphed.nss b/_module/nss/ai_polymorphed.nss new file mode 100644 index 00000000..9a7630a6 --- /dev/null +++ b/_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/_module/nss/ai_ranged.nss b/_module/nss/ai_ranged.nss new file mode 100644 index 00000000..3a46228c --- /dev/null +++ b/_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/_module/nss/ai_ranger.nss b/_module/nss/ai_ranger.nss new file mode 100644 index 00000000..5878cfb5 --- /dev/null +++ b/_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/_module/nss/ai_rogue.nss b/_module/nss/ai_rogue.nss new file mode 100644 index 00000000..81c4500b --- /dev/null +++ b/_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/_module/nss/ai_shadow.nss b/_module/nss/ai_shadow.nss new file mode 100644 index 00000000..3d6419fa --- /dev/null +++ b/_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/_module/nss/ai_sorcerer.nss b/_module/nss/ai_sorcerer.nss new file mode 100644 index 00000000..f1fdcc3f --- /dev/null +++ b/_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/_module/nss/ai_taunter.nss b/_module/nss/ai_taunter.nss new file mode 100644 index 00000000..825d0259 --- /dev/null +++ b/_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/_module/nss/ai_wizard.nss b/_module/nss/ai_wizard.nss new file mode 100644 index 00000000..6baa4c8c --- /dev/null +++ b/_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/_module/nss/food.nss b/_module/nss/food.nss index 3ef457d0..4c4b1ac9 100644 --- a/_module/nss/food.nss +++ b/_module/nss/food.nss @@ -13,5 +13,4 @@ else if (iHungry == 1) { FloatingTextStringOnCreature("You aren't hungry, but you eat the "+ sName +" anyway.",oPC,TRUE); } - -} +} \ No newline at end of file diff --git a/_module/nss/mm_prc_spells.nss b/_module/nss/mm_prc_spells.nss new file mode 100644 index 00000000..4aeb8e03 --- /dev/null +++ b/_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/_module/nss/mmd_inc_random.nss b/_module/nss/mmd_inc_random.nss new file mode 100644 index 00000000..2b2541ab --- /dev/null +++ b/_module/nss/mmd_inc_random.nss @@ -0,0 +1,91 @@ +//::////////////////////////////////////////////// +//;: +//:: mmd_inc_random.nss +//:: +/* + Handles random NPC appearances. +*/ +//:: +//::////////////////////////////////////////////// +//:: Created By: Jaysyn +//:: Created On: 2025-07-15 16:49:54 +//::////////////////////////////////////////////// + +void rnd_height(object oPC) +{ + int nPercent = 90 + Random(21); // 90% to 110% + float fScale = IntToFloat(nPercent) / 100.0f; + + SetObjectVisualTransform(OBJECT_SELF, OBJECT_VISUAL_TRANSFORM_SCALE, fScale); +} + + +void rnd_skin(object oPC) +{ +//:: Randomize skin color + int nKeepskin = GetLocalInt(OBJECT_SELF,"MMD_KEEPSKIN"); + int nSkinColor; + nSkinColor = Random(15); + + if (nKeepskin != 1) + { + SetColor(OBJECT_SELF, COLOR_CHANNEL_SKIN, nSkinColor); + } +} + +void rnd_pheno(object oPC) +{ +//: Randomize body size (3:1 ratio) + int nKeepPheno = GetLocalInt(OBJECT_SELF, "MMD_KEEPPHENO"); + int nRandom = d4(); + + if (nKeepPheno != 1 && nRandom == 1) + { + SetPhenoType(PHENOTYPE_BIG , OBJECT_SELF); + } + +} + +void rnd_head(object oPC) +{ + // Randomize head + int nKeephead = GetLocalInt(OBJECT_SELF,"MMD_KEEPHEAD"); + int nKeephair = GetLocalInt(OBJECT_SELF,"MMD_KEEPHAIR"); + int nHeadNumber; + nHeadNumber = Random(12)+1; + + if (nKeephead != 1) + { + SetCreatureBodyPart(CREATURE_PART_HEAD, nHeadNumber, OBJECT_SELF); + } + + // Randomize hair color + int nHairColor; + nHairColor = Random(15); + if (nKeephair != 1) + { + SetColor(OBJECT_SELF, COLOR_CHANNEL_HAIR, nHairColor); + } +} + +void rnd_tattoo(object oPC) +{ + // Randomize Tattoos + int nKeeptats = GetLocalInt(OBJECT_SELF,"MMD_KEEPTATS"); + int nTattoo1; + nTattoo1 = Random(60); + + if (nKeeptats != 1) + { + SetColor(OBJECT_SELF, COLOR_CHANNEL_TATTOO_1, nTattoo1); + } + + int nTattoo2; + nTattoo2 = Random(60); + + if (nKeeptats != 1) + { + SetColor(OBJECT_SELF, COLOR_CHANNEL_TATTOO_2, nTattoo2); + } + +} diff --git a/_module/nss/mp_hen_spawn.nss b/_module/nss/mp_hen_spawn.nss index 8ab1a968..1fd848e5 100644 --- a/_module/nss/mp_hen_spawn.nss +++ b/_module/nss/mp_hen_spawn.nss @@ -12,16 +12,42 @@ Henchman-specific OnSpawn handler for XP1. Based on NW_CH_AC9 by Bioware. #include "x0_i0_anims" #include "x0_inc_henai" #include "x2_inc_switches" +#include "ms_name_inc" +#include "mmd_inc_random" void main() { -string sTag = GetTag(OBJECT_SELF); -object oReset = GetWaypointByTag(sTag); -object oRespawn = GetObjectByTag("NW_DEATH_TEMPLE"); -location lRespawn = GetLocation(oRespawn); -location lReset = GetLocation(oReset); -//SetLocalInt(OBJECT_SELF,"X2_L_SPAWN_USE_AMBIENT",1); + object oNPC = OBJECT_SELF; + string sTag = GetTag(oNPC); + object oReset = GetWaypointByTag(sTag); + object oRespawn = GetObjectByTag("NW_DEATH_TEMPLE"); + location lRespawn = GetLocation(oRespawn); + location lReset = GetLocation(oReset); + //SetLocalInt(oNPC,"X2_L_SPAWN_USE_AMBIENT",1); + + + //:: Don't want all the Henchmen to have a title. + if (d2(1) == 2) + { + DeleteLocalInt(oNPC, "RND_BARD"); + DeleteLocalInt(oNPC, "RND_BARBARIAN"); + DeleteLocalInt(oNPC, "RND_CLERIC"); + DeleteLocalInt(oNPC, "RND_DRUID"); + DeleteLocalInt(oNPC, "RND_FIGHTER"); + DeleteLocalInt(oNPC, "RND_MAGE"); + DeleteLocalInt(oNPC, "RND_MONK"); + DeleteLocalInt(oNPC, "RND_PALADIN"); + DeleteLocalInt(oNPC, "RND_RANGER"); + DeleteLocalInt(oNPC, "RND_ROGUE"); + } + ms_Nomenclature(oNPC); + + DelayCommand(0.0f, rnd_skin(oNPC)); + DelayCommand(0.0f, rnd_head(oNPC)); + DelayCommand(0.0f, rnd_pheno(oNPC)); + DelayCommand(0.0f, rnd_tattoo(oNPC)); + DelayCommand(0.0f, rnd_height(oNPC)); //Sets up the special henchmen listening patterns SetAssociateListenPatterns(); @@ -40,25 +66,26 @@ location lReset = GetLocation(oReset); //Use melee weapons by default SetAssociateState(NW_ASC_USE_RANGED_WEAPON, FALSE); - // Set starting location - //SetAssociateStartLocation(); - - // Set respawn location - // SetRespawnLocationSpecific(OBJECT_SELF, lRespawn); - // For some general behavior while we don't have a master, // let's do some immobile animations //SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS); SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS); //JumpToLocation(lReset); -int iRoll = Random(60)+1; -string sTag2 = "henchwp"; -object oWP = GetObjectByTag(sTag2+IntToString(iRoll)); -//ExecuteScript("nw_c2_default9",OBJECT_SELF); -//ActionForceMoveToObject(oWP,FALSE,3.0f); -JumpToObject(oWP); -//DelayCommand(6.0f,ActionRandomWalk()); -if (GetIsHired(OBJECT_SELF)!=TRUE) SetAnimationCondition(NW_ANIM_FLAG_IS_ACTIVE); -} + int iRoll = Random(60)+1; + string sTag2 = "henchwp"; + object oWP = GetObjectByTag(sTag2+IntToString(iRoll)); + //ExecuteScript("nw_c2_default9",OBJECT_SELF); + //ActionForceMoveToObject(oWP,FALSE,3.0f); + JumpToObject(oWP); + // Set starting location + //SetAssociateStartLocation(); + + // Set respawn location + //SetRespawnLocationSpecific(oNPC, lRespawn); + + //DelayCommand(6.0f,ActionRandomWalk()); + if (GetIsHired(oNPC)!=TRUE) SetAnimationCondition(NW_ANIM_FLAG_IS_ACTIVE); + +} \ No newline at end of file diff --git a/_module/nss/ms_name_inc.nss b/_module/nss/ms_name_inc.nss index 90de1df5..2b5e0115 100644 --- a/_module/nss/ms_name_inc.nss +++ b/_module/nss/ms_name_inc.nss @@ -27,7 +27,7 @@ // the NPC then is given a random name generated by RACE and GENDER using // the RandomName function. // -// eg. Male Dwarven Villager in the creator becomes Gloigan on spawn +// eg. Male Dwarven Villager in the Aurora Toolset becomes Gloigan on spawn // this time and perhaps Rufus on the next spawned Villager. // // "NAME_TYPE": Setting this int variable to "1" will cause a Full Name @@ -60,12 +60,11 @@ #include "prc_inc_racial" -//void main (){} ///// FUNCTION DECLARATIONS //////////////////////////////////////////////////// -string GetClassLevelTitle(int nClassType); +string GetClassLevelTitle(int nClassType, object oNPC = OBJECT_SELF); int GetHighestClassLevel(object oCreature = OBJECT_SELF); @@ -96,969 +95,869 @@ void ms_Nomenclature(object oNPC = OBJECT_SELF) string sTitle = GetLocalString(oNPC, "TITLE"); string sPostfix = GetLocalString(oNPC, "POSTFIX"); string sBaseRace = GetLocalString(oNPC, "BASE_RACE"); + string sClassTitle; - int nGender = GetGender(oNPC); int bClassTitle = GetLocalInt(oNPC,"CLASS_TITLE"); - int nHighClass = GetHighestClassLevel(oNPC); - int nLevel = GetLevelByClass(nHighClass, oNPC); + //:: Handles class level based NPC titles if (bClassTitle) { - string sTitle; - - switch (nHighClass) - { - case CLASS_TYPE_BARBARIAN: - switch(nLevel) - { - case 1: case 2: case 3: - sTitle = "Brute" ; - break; - - case 4: case 5: - sTitle = "Vandal"; break; - - case 6: - if (nGender == 1) - {sTitle = "Plunderess"; break;} - else - {sTitle = "Plunderer"; break;} - - case 7: - sTitle = "Pillager"; break; - - case 8: - sTitle = "Marauder"; break; - - case 9: - sTitle = "Reaver"; break; - - case 10: - sTitle = "Barbarian"; break; - - case 11: - sTitle = "Mauler"; break; - - case 12: - sTitle = "Ravager"; break; - - case 13: - sTitle = "Slaughterer"; break; - - case 14: - sTitle = "Destroyer"; break; - - case 15: - if (nGender == 1) - {sTitle = "Chieftainess"; break;} - else - {sTitle = "Chieftain"; break;} - - case 16: - sTitle = "Bloodletter"; break; - - case 17: - sTitle = "Rampager"; break; - - case 18: - sTitle = "Slayer"; break; - - case 19: - sTitle = "Warmonger"; break; - - case 20: - if (nGender == 1) - {sTitle = "High Chieftainess"; break;} - else - {sTitle = "High Chieftain"; break;} - - default: - if (nGender == 1) - {sTitle = "Conqueress"; break;} - else - {sTitle = "Conqueror"; break;} - - } - - case CLASS_TYPE_ROGUE: - switch(nLevel) - { - case 1: case 2: case 3: - sTitle = "Lookout" ; - break; - - case 4: case 5: - sTitle = "Outlaw"; break; - - case 6: - sTitle = "Scalawag"; break; - - case 7: - sTitle = "Creeper"; break; - - case 8: - sTitle = "Larker"; break; - - case 9: - sTitle = "Footpad"; break; - - case 10: - sTitle = "Rogue"; break; - - case 11: - sTitle = "Cutpurse"; break; - - case 12: - sTitle = "Thief"; break; - - case 13: - sTitle = "Pilferer"; break; - - case 14: - sTitle = "Robber"; break; - - case 15: - sTitle = "Sharper"; break; - - case 16: - sTitle = "Burglar"; break; - - case 17: - sTitle = "Filcher"; break; - - case 18: - sTitle = "Scoundrel"; break; - - case 19: - sTitle = "Knave"; break; - - case 20: - sTitle = "Prowler"; break; - - default: - sTitle = "Master Rogue"; break; - - } - - case CLASS_TYPE_BARD: - switch(nLevel) - { - case 1: case 2: case 3: - sTitle = "Crier" ; - break; - - case 4: case 5: - if (nGender == 1) - {sTitle = "Chantress"; break;} - else - {sTitle = "Chanter"; break;} - - case 6: - sTitle = "Skop"; break; - - case 7: - sTitle = "Accompanist"; break; - - case 8: - sTitle = "Rhymer"; break; - - case 9: - sTitle = "Singer"; break; - - case 10: - sTitle = "Balladeer"; break; - - case 11: - if (nGender == 1) - {sTitle = "Cantoress"; break;} - else - {sTitle = "Cantor"; break;} - - case 12: - sTitle = "Lutenist"; break; - - case 13: - sTitle = "Melodist"; break; - - case 14: - sTitle = "Lyrist"; break; - - case 15: - sTitle = "Jongleur"; break; - - case 16: - sTitle = "Loreweaver"; break; - - case 17: - sTitle = "Chronicler"; break; - - case 18: - sTitle = "Muse"; break; - - case 19: - if (nGender == 1) - {sTitle = "Rhapsode"; break;} - else - {sTitle = "Rhapsodist"; break;} - - case 20: - sTitle = "Bard"; break; - - case 21: - sTitle = "Raconteur"; break; - - case 22: - sTitle = "Siren"; break; - - case 23: - sTitle = "Songsmith"; break; - - case 24: - sTitle = "Versifer"; break; - - case 25: - sTitle = "Minstrel"; break; - - case 26: - sTitle = "Sonneteer"; break; - - case 27: - if (nGender == 1) - {sTitle = "Trobairitz"; break;} - else - {sTitle = "Troubadour"; break;} - - case 28: - sTitle = "Citharist"; break; - - case 29: - sTitle = "High Minstrel"; break; - - default: - sTitle = "Master Bard"; break; - - } - - case CLASS_TYPE_SORCERER: - case CLASS_TYPE_WIZARD: - switch(nLevel) - { - case 1: case 2: case 3: - sTitle = "Apprentice" ; - break; - - case 4: case 5: - sTitle = "Adept"; break; - - case 6: - sTitle = "Journeymage"; break; - - case 7: - sTitle = "Hedge Mage"; break; - - case 8: - sTitle = "Magician"; break; - - case 9: - sTitle = "Prestidigitator"; break; - - case 10: - sTitle = "Wizard"; break; - - case 11: - sTitle = "Sage"; break; - - case 12: - sTitle = "Visionary"; break; - - case 13: - sTitle = "Loremaster"; break; - - case 14: - sTitle = "Mage"; break; - - case 15: - sTitle = "Fatespinner"; break; - - case 16: - sTitle = "Cabalist"; break; - - case 17: - sTitle = "Thaumaturge"; break; - - case 18: - sTitle = "Theurgist"; break; - - case 19: - sTitle = "Augur"; break; - - case 20: - sTitle = "Spellbinder"; break; - - default: - sTitle = "Archmage"; break; - - } - - case CLASS_TYPE_CLERIC: - switch(nLevel) - { - case 1: case 2: case 3: - sTitle = "Candidate" ; - break; - - case 4: case 5: - sTitle = "Aspirant"; break; - - case 6: - sTitle = "Novice"; break; - - case 7: - sTitle = "Acolyte"; break; - - case 8: - sTitle = "Initiate"; break; - - case 9: - if (nGender == 1) - {sTitle = "Priestess"; break;} - else - {sTitle = "Priest"; break;} - - case 10: - sTitle = "Cleric"; break; - - case 11: - sTitle = "Curate"; break; - - case 12: - sTitle = "Apostle"; break; - - case 13: - sTitle = "Ovate"; break; - - case 14: - sTitle = "Missionary"; break; - - case 15: - if (nGender == 1) - {sTitle = "Canoness"; break;} - else - {sTitle = "Canon"; break;} - - case 16: - if (nGender == 1) - {sTitle = "Abbotess"; break;} - else - {sTitle = "Abbot"; break;} - - case 17: - sTitle = "Bishop"; break; - - case 18: - if (nGender == 1) - {sTitle = "Matriarch"; break;} - else - {sTitle = "Patriarch"; break;} - - case 19: - sTitle = "Preacher"; break; - - default: - if (nGender == 1) - {sTitle = "High Priestess"; break;} - else - {sTitle = "High Priest"; break;} - - } - - case CLASS_TYPE_DRUID: - switch(nLevel) - { - case 1: case 2: case 3: - sTitle = "Initiate" ; - break; - - case 4: case 5: - sTitle = "Devotee"; break; - - case 6: - sTitle = "Beastling"; break; - - case 7: - sTitle = "Grovelurker"; break; - - case 8: - sTitle = "Shaper"; break; - - case 9: - sTitle = "Springwalker"; break; - - case 10: - sTitle = "Druid"; break; - - case 11: - sTitle = "Naturekin"; break; - - case 12: - sTitle = "Treewarden"; break; - - case 13: - sTitle = "Auspex"; break; - - case 14: - sTitle = "Haruspex"; break; - - case 15: - sTitle = "Student of Stones"; break; - - case 16: - sTitle = "Student of Waters"; break; - - case 17: - sTitle = "Student of Forests"; break; - - case 18: - sTitle = "Student of Winds"; break; - - case 19: - sTitle = "Student of Changes"; break; - - case 20: - sTitle = "Pathwarden"; break; - - default: - sTitle = "Archdruid"; break; - - } - - case CLASS_TYPE_FIGHTER: - switch(nLevel) - { - case 1: case 2: case 3: - sTitle = "Guard"; - break; - - case 4: - sTitle = "Elite Guard"; break; - - case 5: case 6: - sTitle = "Warrior"; break; - - case 7: - sTitle = "Elite Warrior"; break; - - case 8: - sTitle = "Soldier"; break; - - case 9: - sTitle = "Enforcer"; break; - - case 10: - sTitle = "Fighter"; break; - - case 11: - sTitle = "Skirmisher"; break; - - case 12: - sTitle = "Veteran"; break; - - case 13: - sTitle = "Armiger"; break; - - case 14: - sTitle = "Myrmidon"; break; - - case 15: - sTitle = "Hero"; break; - - case 16: - sTitle = "Vanguard"; break; - - case 17: - sTitle = "Sentinel"; break; - - case 18: - sTitle = "Dominator"; break; - - case 19: - sTitle = "Warmonger"; break; - - case 20: - sTitle = "Champion"; break; - - default: - sTitle = "Grandmaster"; break; - - } - - case CLASS_TYPE_MONK: - switch(nLevel) - { - case 1: - sTitle = "Trainee"; break; - - case 2: - sTitle = "Initiate"; break; - - case 3: - sTitle = "Novice"; break; - - case 4: - sTitle = "Neophyte"; break; - - case 5: - sTitle = "Aspirant"; break; - - case 6: - sTitle = "Acolyte"; break; - - case 7: - sTitle = "Devotee"; break; - - case 8: - sTitle = "Disciple"; break; - - case 9: - sTitle = "Adept"; break; - - case 10: - sTitle = "Ascetic"; break; - - case 11: - sTitle = "Pilgrim"; break; - - case 12: - sTitle = "Master"; break; - - case 13: - sTitle = "Anchorite"; break; - - case 14: - sTitle = "Mystic"; break; - - case 15: - sTitle = "Meditator"; break; - - case 16: - sTitle = "Seeker"; break; - - case 17: - sTitle = "Guru"; break; - - case 18: - sTitle = "Sensei"; break; - - case 19: - sTitle = "Sannyasi"; break; - - case 20: - sTitle = "Exemplar"; break; - - case 21: - sTitle = "Transcendent"; break; - - default: - sTitle = "High Master"; break; - - } - - case CLASS_TYPE_PALADIN: - switch(nLevel) - { - case 1: - sTitle = "Advocate"; break; - - case 2: - sTitle = "Initiate"; break; - - case 3: - sTitle = "Squire"; break; - - case 4: - sTitle = "Gallant"; break; - - case 5: - sTitle = "Emissary"; break; - - case 6: - sTitle = "Guardian"; break; - - case 7: - sTitle = "Devotee"; break; - - case 8: - sTitle = "Disciple"; break; - - case 9: - sTitle = "Adept"; break; - - case 10: - sTitle = "Ascetic"; break; - - case 11: - sTitle = "Pilgrim"; break; - - case 12: - sTitle = "Master"; break; - - case 13: - sTitle = "Anchorite"; break; - - case 14: - sTitle = "Mystic"; break; - - case 15: - sTitle = "Meditator"; break; - - case 16: - sTitle = "Seeker"; break; - - case 17: - sTitle = "Guru"; break; - - case 18: - sTitle = "Sensei"; break; - - case 19: - sTitle = "Sannyasi"; break; - - case 20: - sTitle = "Exemplar"; break; - - case 21: - sTitle = "Transcendent"; break; - - default: - sTitle = "High Master"; break; - - } - - case CLASS_TYPE_RANGER: - switch(nLevel) - { - case 1: case 2: case 3: - sTitle = "Greenhorn" ; - break; - - case 4: case 5: - sTitle = "Tenderfoot"; break; - - case 6: - sTitle = "Vagrant"; break; - - case 7: - sTitle = "Tramp"; break; - - case 8: - sTitle = "Nomad"; break; - - case 9: - sTitle = "Wanderer"; break; - - case 10: - sTitle = "Ranger"; break; - - case 11: - sTitle = "Rambler"; break; - - case 12: - sTitle = "Traveler"; break; - - case 13: - sTitle = "Sojourner"; break; - - case 14: - sTitle = "Outrider"; break; - - case 15: - sTitle = "Wayfarer"; break; - - case 16: - sTitle = "Excursionist"; break; - - case 17: - sTitle = "Trekker"; break; - - case 18: - sTitle = "Trailblazer"; break; - - case 19: - sTitle = "Woodsman"; break; - - case 20: - sTitle = "High Ranger"; break; - - case 21: - sTitle = "Ranger"; break; - - case 22: - sTitle = "Rambler"; break; - - case 23: - sTitle = "Traveler"; break; - - case 24: - sTitle = "Sojourner"; break; - - case 25: - sTitle = "Outrider"; break; - - case 26: - sTitle = "Wayfarer"; break; - - case 27: - sTitle = "Excursionist"; break; - - case 28: - sTitle = "Trekker"; break; - - case 29: - sTitle = "Trailblazer"; break; - - default: - sTitle = "Ranger Lord"; break; - - } - - } - - //return sTitle; + sClassTitle = GetClassLevelTitle(GetHighestClassLevel(oNPC), oNPC); } //:: Handles class based Henchman titles - int nRndRogue = GetLocalInt(OBJECT_SELF,"RND_ROGUE"); - if (nRndRogue == 1) - { - int nResult = d6(1); - if (nResult == 1) - { - sPostfix = "the Quick"; - } - else if(nResult == 2) - { - sPostfix = "the Quiet"; - } - else if(nResult == 3) - { - sPostfix = "the Sharp"; - } - else if(nResult ==4) - { - sPostfix = "the Sneak"; - } - else if(nResult == 5) - { - sPostfix = "the Rogue"; - } - else - sPostfix = "the Footpad"; + int nRndPaladin = GetLocalInt(OBJECT_SELF, "RND_PALADIN"); + if (nRndPaladin == 1) + { + int nResult = Random(30) + 1; // Generate a random number between 1 and 30 + switch (nResult) + { + case 1: sPostfix = "the Righteous"; break; + case 2: sPostfix = "the Just"; break; + case 3: sPostfix = "the Defender"; break; + case 4: sPostfix = "the Virtuous"; break; + case 5: sPostfix = "the Crusader"; break; + case 6: sPostfix = "the Lightbringer"; break; + case 7: sPostfix = "the Faithful"; break; + case 8: sPostfix = "the Zealous"; break; + case 9: sPostfix = "the Beacon"; break; + case 10: sPostfix = "the Redeemer"; break; + case 11: sPostfix = "the Shield of Faith"; break; + case 12: sPostfix = "of the Sacred Flame"; break; + case 13: sPostfix = "the Lawful"; break; + case 14: sPostfix = "the Blessed"; break; + case 15: sPostfix = "the Chosen"; break; + case 16: sPostfix = "of the Holy Vow"; break; + case 17: sPostfix = "the Avenger"; break; + case 18: sPostfix = "the Purifier"; break; + case 19: sPostfix = "the Divine Hand"; break; + case 20: sPostfix = "the Sacred Blade"; break; + case 21: sPostfix = "the Lightforged"; break; + case 22: sPostfix = "the Protector"; break; + case 23: sPostfix = "the Illuminated"; break; + case 24: sPostfix = "of the Silver Oath"; break; + case 25: sPostfix = "the Guardian"; break; + case 26: sPostfix = "the Oathbound"; break; + case 27: sPostfix = "the Valiant"; break; + case 28: sPostfix = "the Seraphic"; break; + case 29: sPostfix = "the Golden Knight"; break; + case 30: sPostfix = "the True"; break; + } + } - } + int nRndMonk = GetLocalInt(OBJECT_SELF, "RND_MONK"); + if (nRndMonk == 1) + { + int nResult = Random(30) + 1; + switch (nResult) + { + case 1: sPostfix = "the Disciplined"; break; + case 2: sPostfix = "the Enlightened"; break; + case 3: sPostfix = "of the Open Palm"; break; + case 4: sPostfix = "of the Empty Hand"; break; + case 5: sPostfix = "the Ascetic"; break; + case 6: sPostfix = "the Calm"; break; + case 7: sPostfix = "the Wayfarer"; break; + case 8: sPostfix = "the Iron Fist"; break; + case 9: sPostfix = "the Centered"; break; + case 10: sPostfix = "of the Quiet Mind"; break; + case 11: sPostfix = "the Humble"; break; + case 12: sPostfix = "the Swift Palm"; break; + case 13: sPostfix = "the Inner Flame"; break; + case 14: sPostfix = "the Master"; break; + case 15: sPostfix = "of the Lotus Path"; break; + case 16: sPostfix = "the Patient"; break; + case 17: sPostfix = "the Balanced"; break; + case 18: sPostfix = "the Serene"; break; + case 19: sPostfix = "the Watchful"; break; + case 20: sPostfix = "the Disciple"; break; + case 21: sPostfix = "the Harmonious"; break; + case 22: sPostfix = "the Seeker"; break; + case 23: sPostfix = "the Breathless"; break; + case 24: sPostfix = "the Stilled Hand"; break; + case 25: sPostfix = "of Perfect Form"; break; + case 26: sPostfix = "the Tranquil"; break; + case 27: sPostfix = "the Unbound"; break; + case 28: sPostfix = "the Silent Step"; break; + case 29: sPostfix = "the Mindful"; break; + case 30: sPostfix = "the Flowing One"; break; + } + } + + int nRndRogue = GetLocalInt(OBJECT_SELF,"RND_ROGUE"); + if (nRndRogue == 1) + { + int nResult = Random(30) + 1; // Generate a random number between 1 and 30 + switch (nResult) + { + case 1: + sPostfix = "the Quick"; + break; + case 2: + sPostfix = "the Quiet"; + break; + case 3: + sPostfix = "the Sharp"; + break; + case 4: + sPostfix = "the Sneak"; + break; + case 5: + sPostfix = "the Rogue"; + break; + case 6: + sPostfix = "the Footpad"; + break; + case 7: + sPostfix = "the Shadow"; + break; + case 8: + sPostfix = "the Nimble"; + break; + case 9: + sPostfix = "the Swift"; + break; + case 10: + sPostfix = "the Silent"; + break; + case 11: + sPostfix = "the Sly"; + break; + case 12: + sPostfix = "the Crafty"; + break; + case 13: + sPostfix = "the Cunning"; + break; + case 14: + sPostfix = "the Elusive"; + break; + case 15: + sPostfix = "the Deft"; + break; + case 16: + sPostfix = "the Guileful"; + break; + case 17: + sPostfix = "the Lurker"; + break; + case 18: + sPostfix = "the Trickster"; + break; + case 19: + sPostfix = "the Prowler"; + break; + case 20: + sPostfix = "the Skulker"; + break; + case 21: + sPostfix = "the Phantom"; + break; + case 22: + sPostfix = "the Wily"; + break; + case 23: + sPostfix = "the Mysterious"; + break; + case 24: + sPostfix = "the Furtive"; + break; + case 25: + sPostfix = "the Discreet"; + break; + case 26: + sPostfix = "the Spy"; + break; + case 27: + sPostfix = "the Veiled"; + break; + case 28: + sPostfix = "the Artful"; + break; + case 29: + sPostfix = "the Sleuth"; + break; + case 30: + sPostfix = "the Masked"; + break; + } + } - int nRndBarb = GetLocalInt(OBJECT_SELF,"RND_BARBARIAN"); - if (nRndBarb == 1) - { - int nResult = d6(1); - if (nResult == 1) - { - sPostfix = "the Barbarian"; - } - else if(nResult == 2) - { - sPostfix = "the Destroyer"; - } - else if(nResult == 3) - { - sPostfix = "of the Plains"; - } - else if(nResult ==4) - { - sPostfix = "of Klar Clan"; - } - else if(nResult == 5) - { - sPostfix = "the Rampager"; - } - else - sPostfix = "the Reaver"; + int nRndBarb = GetLocalInt(OBJECT_SELF,"RND_BARBARIAN"); + if (nRndBarb == 1) + { + int nResult = Random(30) + 1; // Generate a random number between 1 and 30 + switch (nResult) + { + case 1: + sPostfix = "the Barbarian"; + break; + case 2: + sPostfix = "the Destroyer"; + break; + case 3: + sPostfix = "of the Plains"; + break; + case 4: + sPostfix = "of Bear Clan"; + break; + case 5: + sPostfix = "the Rampager"; + break; + case 6: + sPostfix = "the Reaver"; + break; + case 7: + sPostfix = "the Savage"; + break; + case 8: + sPostfix = "the Berserker"; + break; + case 9: + sPostfix = "the Untamed"; + break; + case 10: + sPostfix = "the Fierce"; + break; + case 11: + sPostfix = "the Warbringer"; + break; + case 12: + sPostfix = "the Wild"; + break; + case 13: + sPostfix = "the Raider"; + break; + case 14: + sPostfix = "the Vicious"; + break; + case 15: + sPostfix = "the Ruthless"; + break; + case 16: + sPostfix = "the Savage"; + break; + case 17: + sPostfix = "the Bloodthirsty"; + break; + case 18: + sPostfix = "the Warlord"; + break; + case 19: + sPostfix = "the Brute"; + break; + case 20: + sPostfix = "the Fierce"; + break; + case 21: + sPostfix = "the Marauder"; + break; + case 22: + sPostfix = "the Howler"; + break; + case 23: + sPostfix = "the Ravager"; + break; + case 24: + sPostfix = "the Crusher"; + break; + case 25: + sPostfix = "the Frenzied"; + break; + case 26: + sPostfix = "the Beast"; + break; + case 27: + sPostfix = "the Juggernaut"; + break; + case 28: + sPostfix = "the Slayer"; + break; + case 29: + sPostfix = "the Rager"; + break; + case 30: + sPostfix = "the Conqueror"; + break; + } + } - } + int nRndFight = GetLocalInt(OBJECT_SELF,"RND_FIGHTER"); + if (nRndFight == 1) + { + int nResult = Random(30) + 1; // Generate a random number between 1 and 30 + switch (nResult) + { + case 1: + sPostfix = "the Strong"; + break; + case 2: + sPostfix = "the Stout"; + break; + case 3: + sPostfix = "of Harrowdale"; + break; + case 4: + sPostfix = "of Tyr"; + break; + case 5: + sPostfix = "of Neverwinter"; + break; + case 6: + sPostfix = "the Swordhand"; + break; + case 7: + sPostfix = "the Valiant"; + break; + case 8: + sPostfix = "the Brave"; + break; + case 9: + sPostfix = "the Defender"; + break; + case 10: + sPostfix = "the Just"; + break; + case 11: + sPostfix = "the Noble"; + break; + case 12: + sPostfix = "the Gallant"; + break; + case 13: + sPostfix = "the Protector"; + break; + case 14: + sPostfix = "the Shield"; + break; + case 15: + sPostfix = "the Champion"; + break; + case 16: + sPostfix = "the Guardian"; + break; + case 17: + sPostfix = "the Sentinel"; + break; + case 18: + sPostfix = "the Warrior"; + break; + case 19: + sPostfix = "the Stalwart"; + break; + case 20: + sPostfix = "the Ironclad"; + break; + case 21: + sPostfix = "the Blade"; + break; + case 22: + sPostfix = "the Swordsman"; + break; + case 23: + sPostfix = "the Vanguard"; + break; + case 24: + sPostfix = "the Lancer"; + break; + case 25: + sPostfix = "the Spearhead"; + break; + case 26: + sPostfix = "the Battlemaster"; + break; + case 27: + sPostfix = "the Blademaster"; + break; + case 28: + sPostfix = "the Warlord"; + break; + case 29: + sPostfix = "the Vanquisher"; + break; + case 30: + sPostfix = "the Swordmaster"; + break; + } + } - int nRndFight = GetLocalInt(OBJECT_SELF,"RND_FIGHTER"); - if (nRndFight == 1) - { - int nResult = d6(1); - if (nResult == 1) - { - sPostfix = "the Strong"; - } - else if(nResult == 2) - { - sPostfix = "the Stout"; - } - else if(nResult == 3) - { - sPostfix = "of the Blade"; - } - else if(nResult ==4) - { - sPostfix = "of Tyr"; - } - else if(nResult == 5) - { - sPostfix = "of Urik"; - } - else - sPostfix = "the Swordhand"; + int nRndCleric = GetLocalInt(OBJECT_SELF,"RND_CLERIC"); + if (nRndCleric == 1) + { + int nResult = Random(30) + 1; // Generate a random number between 1 and 30 + if (nResult == 1) + { + sPostfix = "the Pious"; + } + else if (nResult == 2) + { + sPostfix = "the Holy"; + } + else if (nResult == 3) + { + sPostfix = "the Priest"; + } + else if (nResult == 4) + { + sPostfix = "the Zealous"; + } + else if (nResult == 5) + { + sPostfix = "of Phlan"; + } + else if (nResult == 6) + { + sPostfix = "the Wise"; + } + else if (nResult == 7) + { + sPostfix = "the Devout"; + } + else if (nResult == 8) + { + sPostfix = "the Faithful"; + } + else if (nResult == 9) + { + sPostfix = "the Righteous"; + } + else if (nResult == 10) + { + sPostfix = "the Blessed"; + } + else if (nResult == 11) + { + sPostfix = "the Pure"; + } + else if (nResult == 12) + { + sPostfix = "the Sacred"; + } + else if (nResult == 13) + { + sPostfix = "the Benevolent"; + } + else if (nResult == 14) + { + sPostfix = "the Virtuous"; + } + else if (nResult == 15) + { + sPostfix = "the Saintly"; + } + else if (nResult == 16) + { + sPostfix = "the Healer"; + } + else if (nResult == 17) + { + sPostfix = "the Anointed"; + } + else if (nResult == 18) + { + sPostfix = "the Protector"; + } + else if (nResult == 19) + { + sPostfix = "the Merciful"; + } + else if (nResult == 20) + { + sPostfix = "the Revered"; + } + else if (nResult == 21) + { + sPostfix = "the Graceful"; + } + else if (nResult == 22) + { + sPostfix = "the Watchful"; + } + else if (nResult == 23) + { + sPostfix = "the Forgiving"; + } + else if (nResult == 24) + { + sPostfix = "the Humble"; + } + else if (nResult == 25) + { + sPostfix = "the Divine"; + } + else if (nResult == 26) + { + sPostfix = "the Preacher"; + } + else if (nResult == 27) + { + sPostfix = "the Illuminated"; + } + else if (nResult == 28) + { + sPostfix = "the Mystic"; + } + else if (nResult == 29) + { + sPostfix = "the Herald"; + } + else // nResult == 30 + { + sPostfix = "the Exalted"; + } + } - } + int nRndMage = GetLocalInt(OBJECT_SELF,"RND_MAGE"); + if (nRndMage == 1) + { + int nResult = Random(30) + 1; // Generate a random number between 1 and 30 + switch (nResult) + { + case 1: + sPostfix = "the Mad"; + break; + case 2: + sPostfix = "the Arcane"; + break; + case 3: + sPostfix = "the Black"; + break; + case 4: + sPostfix = "the Wizard"; + break; + case 5: + sPostfix = "of Waterdeep"; + break; + case 6: + sPostfix = "the Mage"; + break; + case 7: + sPostfix = "the Enigmatic"; + break; + case 8: + sPostfix = "the Mystical"; + break; + case 9: + sPostfix = "the Eldritch"; + break; + case 10: + sPostfix = "the Runeweaver"; + break; + case 11: + sPostfix = "the Sorcerous"; + break; + case 12: + sPostfix = "the Seer"; + break; + case 13: + sPostfix = "the Arcanist"; + break; + case 14: + sPostfix = "the Illustrious"; + break; + case 15: + sPostfix = "the Sage"; + break; + case 16: + sPostfix = "the Sorcerous"; + break; + case 17: + sPostfix = "the Occult"; + break; + case 18: + sPostfix = "the Arcane Adept"; + break; + case 19: + sPostfix = "the Spellbinder"; + break; + case 20: + sPostfix = "the Occultist"; + break; + case 21: + sPostfix = "the Conjurer"; + break; + case 22: + sPostfix = "the Seer"; + break; + case 23: + sPostfix = "the Invoker"; + break; + case 24: + sPostfix = "the Mysterious"; + break; + case 25: + sPostfix = "the Shrouded"; + break; + case 26: + sPostfix = "the Visionary"; + break; + case 27: + sPostfix = "the Spellweaver"; + break; + case 28: + sPostfix = "the Willbreaker"; + break; + case 29: + sPostfix = "the Charmer"; + break; + case 30: + sPostfix = "the Elementalist"; + break; + } + } - int nRndCleric = GetLocalInt(OBJECT_SELF,"RND_CLERIC"); - if (nRndCleric == 1) - { - int nResult = d6(1); - if (nResult == 1) - { - sPostfix = "the Pious"; - } - else if(nResult == 2) - { - sPostfix = "the Holy"; - } - else if(nResult == 3) - { - sPostfix = "the Priest"; - } - else if(nResult ==4) - { - sPostfix = "the Zealous"; - } - else if(nResult == 5) - { - sPostfix = "of Phlan"; - } - else - sPostfix = "the Wise"; + int nRndBard = GetLocalInt(OBJECT_SELF,"RND_BARD"); + if (nRndBard == 1) + { + int nResult = Random(25) + 1; // Generate a random number between 1 and 25 + switch (nResult) + { + case 1: + sPostfix = "the Subtle"; + break; + case 2: + sPostfix = "the Veiled"; + break; + case 3: + sPostfix = "the Shadowed"; + break; + case 4: + sPostfix = "the Intriguer"; + break; + case 5: + sPostfix = "of Altaruk"; + break; + case 6: + sPostfix = "the Elusive"; + break; + case 7: + sPostfix = "the Mysterious"; + break; + case 8: + sPostfix = "the Cryptic"; + break; + case 9: + sPostfix = "the Insidious"; + break; + case 10: + sPostfix = "the Quiet"; + break; + case 11: + sPostfix = "the Sly"; + break; + case 12: + sPostfix = "the Covert"; + break; + case 13: + sPostfix = "the Furtive"; + break; + case 14: + sPostfix = "the Discreet"; + break; + case 15: + sPostfix = "the Subversive"; + break; + case 16: + sPostfix = "the Shrouded"; + break; + case 17: + sPostfix = "the Obscured"; + break; + case 18: + sPostfix = "the Clever"; + break; + case 19: + sPostfix = "the Enigmatic"; + break; + case 20: + sPostfix = "of Elventree"; + break; + case 21: + sPostfix = "of Melvaunt"; + break; + case 22: + sPostfix = "of Deepingdale"; + break; + case 23: + sPostfix = "of Skullport"; + break; + case 24: + sPostfix = "the Crafty"; + break; + case 25: + sPostfix = "of Amn"; + break; + } + } - } + int nRndDruid = GetLocalInt(OBJECT_SELF,"RND_DRUID"); + if (nRndDruid == 1) + { + int nResult = Random(25) + 1; // Generate a random number between 1 and 25 + switch (nResult) + { + case 1: + sPostfix = "the Druid"; + break; + case 2: + sPostfix = "of the Forest"; + break; + case 3: + sPostfix = "of the Wild"; + break; + case 4: + sPostfix = "the Wolflord"; + break; + case 5: + sPostfix = "the Treelord"; + break; + case 6: + sPostfix = "the Verdant"; + break; + case 7: + sPostfix = "the Earthshaker"; + break; + case 8: + sPostfix = "the Feral"; + break; + case 9: + sPostfix = "of the Glade"; + break; + case 10: + sPostfix = "of the Crystal Forest"; + break; + case 11: + sPostfix = "the Thorned"; + break; + case 12: + sPostfix = "the Greenwarden"; + break; + case 13: + sPostfix = "the Naturebound"; + break; + case 14: + sPostfix = "the Forestborn"; + break; + case 15: + sPostfix = "the Spiritcaller"; + break; + case 16: + sPostfix = "the Leafblade"; + break; + case 17: + sPostfix = "the Mossy"; + break; + case 18: + sPostfix = "the Grovekeeper"; + break; + case 19: + sPostfix = "the Stormbringer"; + break; + case 20: + sPostfix = "the Earthshaper"; + break; + case 21: + sPostfix = "the Bramble"; + break; + case 22: + sPostfix = "of the Black Sands"; + break; + case 23: + sPostfix = "of the Silt Sea"; + break; + case 24: + sPostfix = "the Spiritbinder"; + break; + case 25: + sPostfix = "the Wildheart"; + break; + } + } - int nRndMage = GetLocalInt(OBJECT_SELF,"RND_MAGE"); - if (nRndMage == 1) - { - int nResult = d6(1); - if (nResult == 1) - { - sPostfix = "the Mad"; - } - else if(nResult == 2) - { - sPostfix = "the Arcane"; - } - else if(nResult == 3) - { - sPostfix = "the Black"; - } - else if(nResult ==4) - { - sPostfix = "the Wizard"; - } - else if(nResult == 5) - { - sPostfix = "of Ur-Draxa"; - } - else - sPostfix = "the Mage"; - - } - - int nRndBard = GetLocalInt(OBJECT_SELF,"RND_BARD"); - if (nRndMage == 1) - { - int nResult = d6(1); - if (nResult == 1) - { - sPostfix = "the Dancer"; - } - else if(nResult == 2) - { - sPostfix = "the Troubador"; - } - else if(nResult == 3) - { - sPostfix = "of the Song"; - } - else if(nResult ==4) - { - sPostfix = "the Bard"; - } - else if(nResult == 5) - { - sPostfix = "the Raconteur"; - } - else - sPostfix = "the Minstrel"; - - } - - int nRndDruid = GetLocalInt(OBJECT_SELF,"RND_DRUID"); - if (nRndDruid == 1) - { - int nResult = d6(1); - if (nResult == 1) - { - sPostfix = "the Druid"; - } - else if(nResult == 2) - { - sPostfix = "of the Forest"; - } - else if(nResult == 3) - { - sPostfix = "of the Wild"; - } - else if(nResult ==4) - { - sPostfix = "the Wolflord"; - } - else if(nResult == 5) - { - sPostfix = "the Treelord"; - } - else - sPostfix = "the Warden"; - - } - - int nRndRanger = GetLocalInt(OBJECT_SELF,"RND_RANGER"); - if (nRndRanger == 1) - { - int nResult = d6(1); - if (nResult == 1) - { - sPostfix = "the Ranger"; - } - else if(nResult == 2) - { - sPostfix = "of the Forest"; - } - else if(nResult == 3) - { - sPostfix = "of the Wild"; - } - else if(nResult ==4) - { - sPostfix = "the Strider"; - } - else if(nResult == 5) - { - sPostfix = "the Venger"; - } - else - sPostfix = "the Warden"; - - } + int nRndRanger = GetLocalInt(OBJECT_SELF,"RND_RANGER"); + if (nRndRanger == 1) + { + int nResult = Random(25) + 1; // Generate a random number between 1 and 25 + switch (nResult) + { + case 1: + sPostfix = "the Ranger"; + break; + case 2: + sPostfix = "of the Forest"; + break; + case 3: + sPostfix = "of the Wild"; + break; + case 4: + sPostfix = "the Strider"; + break; + case 5: + sPostfix = "the Venger"; + break; + case 6: + sPostfix = "the Pathfinder"; + break; + case 7: + sPostfix = "the Woodsman"; + break; + case 8: + sPostfix = "the Trailblazer"; + break; + case 9: + sPostfix = "the Hunter"; + break; + case 10: + sPostfix = "the Scout"; + break; + case 11: + sPostfix = "the Wayfarer"; + break; + case 12: + sPostfix = "the Outrider"; + break; + case 13: + sPostfix = "the Seeker"; + break; + case 14: + sPostfix = "the Sentinel"; + break; + case 15: + sPostfix = "the Forestborn"; + break; + case 16: + sPostfix = "the Survivalist"; + break; + case 17: + sPostfix = "the Tracker"; + break; + case 18: + sPostfix = "the Forager"; + break; + case 19: + sPostfix = "the Warder"; + break; + case 20: + sPostfix = "the Greenblade"; + break; + case 21: + sPostfix = "the Beastmaster"; + break; + case 22: + sPostfix = "the Thornhunter"; + break; + case 23: + sPostfix = "of the Deepwood"; + break; + case 24: + sPostfix = "of the Roughlands"; + break; + case 25: + sPostfix = "the Wilderness Guide"; + break; + } + } if (sRandomName != "") { @@ -1149,20 +1048,64 @@ string ms_RandomLastName(object oNPC = OBJECT_SELF) return Name; } - -// Function to get the class-based level title based on the class type -string GetClassLevelTitle(int nClassType) +//:: Function to get the highest class level of an object, excluding racialtype classes +int GetHighestClassLevel(object oCreature) { - object oCreature = OBJECT_SELF; // Assuming this function is called on a creature object - - int nLevel = GetLevelByClass(nClassType, oCreature); - int nGender = GetGender(oCreature); - - string sTitle; + int nHighestLevel = -1; + int nClassTypes = 254; // Maximum number of class types + int i; - switch (nClassType) + for (i = 0; i <= nClassTypes; i++) { - case CLASS_TYPE_BARBARIAN: + // Check if the class type is excluded + if (i == CLASS_TYPE_ABERRATION || + i == CLASS_TYPE_ANIMAL || + i == CLASS_TYPE_BEAST || + i == CLASS_TYPE_CONSTRUCT || + i == CLASS_TYPE_DRAGON || + i == CLASS_TYPE_ELEMENTAL || + i == CLASS_TYPE_FEY || + i == CLASS_TYPE_GIANT || + i == CLASS_TYPE_HUMANOID || + i == CLASS_TYPE_MAGICAL_BEAST || + i == CLASS_TYPE_MONSTROUS || + i == CLASS_TYPE_OOZE || + i == CLASS_TYPE_OUTSIDER || + i == CLASS_TYPE_PLANT || + i == CLASS_TYPE_SHAPECHANGER || + i == CLASS_TYPE_UNDEAD || + i == CLASS_TYPE_VERMIN) + continue; + + int nLevel = GetLevelByClass(i, oCreature); + if (nLevel > 0) + { + if (nLevel > nHighestLevel) + { + nHighestLevel = nLevel; + } + } + else + { + break; // Reached an invalid class level, exit the loop + } + } + + return nHighestLevel; +} + + +//:: Handles class level based NPC titles +string GetClassLevelTitle(int nClassType, object oNPC = OBJECT_SELF) +{ + string sTitle; + int nHighClass = GetHighestClassLevel(oNPC); + int nLevel = GetLevelByClass(nHighClass, oNPC); + int nGender = GetGender(oNPC); + + switch (nHighClass) + { + case CLASS_TYPE_BARBARIAN: switch(nLevel) { case 1: case 2: case 3: @@ -1234,7 +1177,7 @@ string GetClassLevelTitle(int nClassType) } - case CLASS_TYPE_ROGUE: + case CLASS_TYPE_ROGUE: switch(nLevel) { case 1: case 2: case 3: @@ -1294,7 +1237,7 @@ string GetClassLevelTitle(int nClassType) } - case CLASS_TYPE_BARD: + case CLASS_TYPE_BARD: switch(nLevel) { case 1: case 2: case 3: @@ -1393,7 +1336,7 @@ string GetClassLevelTitle(int nClassType) } - case CLASS_TYPE_SORCERER: + case CLASS_TYPE_SORCERER: case CLASS_TYPE_WIZARD: switch(nLevel) { @@ -1454,7 +1397,7 @@ string GetClassLevelTitle(int nClassType) } - case CLASS_TYPE_CLERIC: + case CLASS_TYPE_CLERIC: switch(nLevel) { case 1: case 2: case 3: @@ -1526,7 +1469,7 @@ string GetClassLevelTitle(int nClassType) } - case CLASS_TYPE_DRUID: + case CLASS_TYPE_DRUID: switch(nLevel) { case 1: case 2: case 3: @@ -1586,7 +1529,7 @@ string GetClassLevelTitle(int nClassType) } - case CLASS_TYPE_FIGHTER: + case CLASS_TYPE_FIGHTER: switch(nLevel) { case 1: case 2: case 3: @@ -1646,7 +1589,7 @@ string GetClassLevelTitle(int nClassType) } - case CLASS_TYPE_MONK: + case CLASS_TYPE_MONK: switch(nLevel) { case 1: @@ -1875,55 +1818,9 @@ string GetClassLevelTitle(int nClassType) } - } + } - return sTitle; + return sTitle; } -//:: Function to get the highest class level of an object, excluding racial classes types -int GetHighestClassLevel(object oCreature) -{ - int nHighestLevel = -1; - int nClassTypes = 254; // Maximum number of class types - int i; - - for (i = 0; i <= nClassTypes; i++) - { - // Check if the class type is excluded - if (i == CLASS_TYPE_ABERRATION || - i == CLASS_TYPE_ANIMAL || - i == CLASS_TYPE_BEAST || - i == CLASS_TYPE_CONSTRUCT || - i == CLASS_TYPE_DRAGON || - i == CLASS_TYPE_ELEMENTAL || - i == CLASS_TYPE_FEY || - i == CLASS_TYPE_GIANT || - i == CLASS_TYPE_HUMANOID || - i == CLASS_TYPE_MAGICAL_BEAST || - i == CLASS_TYPE_MONSTROUS || - i == CLASS_TYPE_OOZE || - i == CLASS_TYPE_OUTSIDER || - i == CLASS_TYPE_PLANT || - i == CLASS_TYPE_SHAPECHANGER || - i == CLASS_TYPE_UNDEAD || - i == CLASS_TYPE_VERMIN) - continue; - - int nLevel = GetLevelByClass(i, oCreature); - if (nLevel > 0) - { - if (nLevel > nHighestLevel) - { - nHighestLevel = nLevel; - } - } - else - { - break; // Reached an invalid class level, exit the loop - } - } - - return nHighestLevel; -} - - +//::void main (){} diff --git a/_module/nss/nui_i_library.nss b/_module/nss/nui_i_library.nss new file mode 100644 index 00000000..a6fb4f56 --- /dev/null +++ b/_module/nss/nui_i_library.nss @@ -0,0 +1,44 @@ +/// ---------------------------------------------------------------------------- +/// @file nui_i_library.nss +/// @author Ed Burke (tinygiant98) +/// @brief Boilerplate code for creating a library dispatcher. Should only be +/// included in library scripts as it implements main(). +/// ---------------------------------------------------------------------------- + +#include "nui_i_main" + +// ----------------------------------------------------------------------------- +// Function Protoypes +// ----------------------------------------------------------------------------- + +void DefineForm(); +void BindForm(); +void HandleNUIEvents(); +void HandleModuleEvents(); + +// ----------------------------------------------------------------------------- +// Function Implementations +// ----------------------------------------------------------------------------- + +// These are dummy implementations to prevent nwnsc from complaining that they +// do not exist. If you want to compile in the toolset rather than using nwnsc, +// comment these lines out. +//#pragma default_function(DefineForm) +//#pragma default_function(BindForm) +//#pragma default_function(HandleNUIEvents) +//#pragma default_function(HandleModuleEvents) + +// ----------------------------------------------------------------------------- +// Library Dispatch +// ----------------------------------------------------------------------------- + +void main() +{ + string sOperation = GetScriptParam(NUI_FUNCTION); + + if (sOperation == NUI_DEFINE) DefineForm(); + else if (sOperation == NUI_BIND) BindForm(); + else if (sOperation == NUI_EVENT_NUI) HandleNUIEvents(); + else if (sOperation == NUI_EVENT_MOD) HandleModuleEvents(); + else NUI(); +} diff --git a/_module/nss/nui_i_main.nss b/_module/nss/nui_i_main.nss index 2b47a6aa..f28ab6b9 100644 --- a/_module/nss/nui_i_main.nss +++ b/_module/nss/nui_i_main.nss @@ -7,12 +7,13 @@ #include "util_i_csvlists" #include "util_i_color" #include "nui_c_config" +#include "nw_inc_nui" // ----------------------------------------------------------------------------- // Constants // ----------------------------------------------------------------------------- -const string NUI_VERSION = "0.4.7"; +const string NUI_VERSION = "0.5.0"; const string NUI_DATABASE = "nui_form_data"; const int NUI_ORIENTATION_ROW = 0; @@ -28,42 +29,23 @@ const int NUI_DRAW_MOUSELEFT = 3; const int NUI_DRAW_MOUSERIGHT = 4; const int NUI_DRAW_MOUSEMIDDLE = 5; -const int NUI_SCROLLBARS_NONE = 0; -const int NUI_SCROLLBARS_X = 1; -const int NUI_SCROLLBARS_Y = 2; -const int NUI_SCROLLBARS_BOTH = 3; -const int NUI_SCROLLBARS_AUTO = 4; - const int NUI_CHART_LINE = 0; const int NUI_CHART_BAR = 1; -const int NUI_ASPECT_FIT = 0; -const int NUI_ASPECT_FILL = 1; -const int NUI_ASPECT_FIT100 = 2; -const int NUI_ASPECT_EXACT = 3; -const int NUI_ASPECT_EXACTSCALED = 4; -const int NUI_ASPECT_STRETCH = 5; - -const int NUI_HALIGN_CENTER = 0; -const int NUI_HALIGN_LEFT = 1; -const int NUI_HALIGN_RIGHT = 2; - -const int NUI_VALIGN_MIDDLE = 0; -const int NUI_VALIGN_TOP = 1; -const int NUI_VALIGN_BOTTOM = 2; - const string NUI_DEFINE = "DefineForm"; const string NUI_BIND = "BindForm"; const string NUI_EVENT_NUI = "HandleNUIEvents"; const string NUI_EVENT_MOD = "HandleModuleEvents"; const string NUI_OBJECT = "NUI_OBJECT"; +const string NUI_FUNCTION = "NUI_FUNCTION"; +const string NUI_ARGS = "NUI_ARGS"; const int NUI_FI_EVENT_UPDATE_FORMS = 100001; const int NUI_FI_EVENT_UPDATE_EVENTS = 100002; -json jTrue = JsonBool(TRUE); -json jFalse = JsonBool(FALSE); +json jTrue = JSON_TRUE; +json jFalse = JSON_FALSE; const int NUI_USE_CAMPAIGN_DATABASE = FALSE; const string NUI_FORMFILE_PREFIX = "nui_f_"; @@ -976,8 +958,10 @@ void NUI_DefineForms(string sFormfile = ""); /// @param oPC Client to display the form on. /// @param sFormID ID of the form to display. /// @param sProfile Optional form profile. +/// @param bSelfManage If TRUE, call the formfile directly instead of the +/// game's NUI event handler. /// @returns Form's token as assigned by the game engine. -int NUI_DisplayForm(object oPC, string sFormID, string sProfile = "default"); +int NUI_DisplayForm(object oPC, string sFormID, string sProfile = "", int bSelfManage = FALSE); /// @brief Close an open form. /// @param oPC Client on which to close the form. @@ -1301,7 +1285,7 @@ int nui_InitializeDatabase() "timestamp INTEGER);"; SqlStep(nui_PrepareQuery(sQuery)); - sQuery = "SELECT * FROM nui_forms;"; + sQuery = "SELECT COUNT(*) FROM nui_forms;"; return SqlStep(nui_PrepareQuery(sQuery)); } @@ -1332,9 +1316,9 @@ void nui_CopyDefinitions(string sTable = "nui_forms") string sQuery = "WITH forms AS (SELECT json_object('form', form, 'definition', definition) AS f " + "FROM " + sTable + ") SELECT json_group_array(json(f)) FROM forms;"; sqlquery sql = nui_PrepareQuery(sQuery, TRUE); - json jForms = SqlStep(sql) ? SqlGetJson(sql, 0) : JsonNull(); + json jForms = SqlStep(sql) ? SqlGetJson(sql, 0) : JSON_NULL; - if (jForms == JsonNull()) + if (jForms == JSON_NULL) return; sQuery = "INSERT OR REPLACE INTO " + sTable + " (form, definition) " + @@ -1554,7 +1538,7 @@ void NUI_SaveBindState(object oPC, string sFormID) void NUI_RestoreBindState(object oPC, string sFormID) { json jState = GetLocalJson(oPC, "NUI_STATE:" + sFormID); - if (jState == JsonNull()) + if (jState == JSON_NULL) return; json jKeys = JsonObjectKeys(jState); @@ -1732,6 +1716,11 @@ void NUI_CloseRow() {nui_DecrementPath();} void NUI_CloseLayout() {nui_DecrementPath();} +void NUI_AddLayout(json jLayout) +{ + nui_SetProperty("root", JsonDump(jLayout)); +} + // Controls -------------------------------------------------------------------- void NUI_AddCheckbox(string sID = "") {nui_CreateControl("check", sID);} @@ -2269,7 +2258,7 @@ json nui_GetForm(string sFormID, int bForceModule = FALSE) sqlquery sql = nui_PrepareQuery("SELECT definition FROM nui_forms WHERE form = @form;", bForceModule); SqlBindString(sql, "@form", sFormID); - return SqlStep(sql) ? SqlGetJson(sql, 0) : JsonNull(); + return SqlStep(sql) ? SqlGetJson(sql, 0) : JSON_NULL; } string nui_GetFormsByPrefix(string sForms, string sPrefix, int nResType) @@ -2294,8 +2283,8 @@ int nui_ExecuteFunction(string sFile, string sFunction, object oTarget = OBJECT_ if (ResManFindPrefix(sFile, RESTYPE_NCS) == sFile) { - SetScriptParam("NUI_FUNCTION", sFunction); - SetScriptParam("NUI_ARGS", sArguments); + SetScriptParam(NUI_FUNCTION, sFunction); + SetScriptParam(NUI_ARGS, sArguments); ExecuteScript(sFile, oTarget); return TRUE; } @@ -2314,7 +2303,7 @@ json nui_GetWatchedBinds(string sFormID) "nui_forms.definition, path || '.watch') = true AND form = @form);"; sqlquery sql = nui_PrepareQuery(sQuery); SqlBindString(sql, "@form", sFormID); - return SqlStep(sql) ? SqlGetJson(sql, 0) : JsonArray(); + return SqlStep(sql) ? SqlGetJson(sql, 0) : JSON_ARRAY; } json NUI_GetOrphanBinds(string sFormID) @@ -2325,7 +2314,7 @@ json NUI_GetOrphanBinds(string sFormID) "'$.profiles.default') AS value WHERE form = @form));"; sqlquery sql = nui_PrepareQuery(sQuery); SqlBindString(sql, "@form", sFormID); - return SqlStep(sql) ? SqlGetJson(sql, 0) : JsonArray(); + return SqlStep(sql) ? SqlGetJson(sql, 0) : JSON_ARRAY; } // ----------------------------------------------------------------------------- @@ -2377,7 +2366,7 @@ json nui_GetProfileBinds(string sFormID, string sProfile = "") sqlquery sql = nui_PrepareQuery(sQuery); SqlBindString(sql, "@form", sFormID); SqlBindString(sql, "@profile", sProfile); - return SqlStep(sql) ? SqlGetJson(sql, 0) : JsonObject(); + return SqlStep(sql) ? SqlGetJson(sql, 0) : JSON_OBJECT; } /// @private Called during form opening, sets the initial values for all default binds. @@ -2426,7 +2415,7 @@ void NUI_DefineForms(string sFormfile = "") int n; for (n; n < CountList(NUI_FORMFILE_PREFIX); n++) { string sFormfiles = nui_GetForms(GetListItem(NUI_FORMFILE_PREFIX, n)); - if (sFormfiles == "") return; + if (sFormfiles == "") break; int f; for (f; f < CountList(sFormfiles); f++) { @@ -2443,14 +2432,16 @@ void NUI_DefineForms(string sFormfile = "") nui_CommitTransaction(); } -int NUI_DisplayForm(object oPC, string sFormID, string sProfile = "default") +int NUI_DisplayForm(object oPC, string sFormID, string sProfile = "", int bSelfManage = FALSE) { json jForm = nui_GetForm(sFormID); - if (jForm != JsonNull()) + if (jForm != JSON_NULL) { - int nToken = NuiCreate(oPC, jForm, sFormID); - json jData = JsonObjectSet(JsonObject(), "profile", JsonString(sProfile)); - jData = JsonObjectSet(jData, "formfile", JsonString(nui_GetDefinitionValue(sFormID, "formfile"))); + string sFormfile = nui_GetDefinitionValue(sFormID, "formfile"); + + int nToken = NuiCreate(oPC, jForm, sFormID, (bSelfManage ? sFormfile : "")); + json jData = JsonObjectSet(JSON_OBJECT, "profile", JsonString(sProfile == "" ? "default" : sProfile)); + jData = JsonObjectSet(jData, "formfile", JsonString(sFormfile)); NuiSetUserData(oPC, NuiFindWindow(oPC, sFormID), jData); return nToken; @@ -2490,7 +2481,7 @@ void NUI_CreateProfile(string sProfile, string sBase = "") void NUI_SetProfileBind(string sBind, string sJson) { - if (sBind == "" || sJson == "" || JsonParse(sJson) == JsonNull()) + if (sBind == "" || sJson == "" || JsonParse(sJson) == JSON_NULL) return; nui_SetProfileBind(sBind, sJson); @@ -2503,7 +2494,7 @@ void NUI_SetProfileBindJ(string sBind, json jValue) void NUI_SetProfileBinds(string sBinds, string sJson) { - if (sBinds == "" || sJson == "" || JsonParse(sJson) == JsonNull()) + if (sBinds == "" || sJson == "" || JsonParse(sJson) == JSON_NULL) return; int n; for (n; n < CountList(sBinds); n++) diff --git a/_module/nss/nw_c2_default1.nss b/_module/nss/nw_c2_default1.nss index 62ac86b0..4801a4d8 100644 --- a/_module/nss/nw_c2_default1.nss +++ b/_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/_module/nss/nw_c2_default2.nss b/_module/nss/nw_c2_default2.nss index 34499fdb..b7d5e074 100644 --- a/_module/nss/nw_c2_default2.nss +++ b/_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/_module/nss/nw_c2_default3.nss b/_module/nss/nw_c2_default3.nss index 572e1239..567b327f 100644 --- a/_module/nss/nw_c2_default3.nss +++ b/_module/nss/nw_c2_default3.nss @@ -1,56 +1,68 @@ -//:://///////////////////////////////////////////// -//:: Default: End of Combat Round -//:: NW_C2_DEFAULT3 -//:: Copyright (c) 2008 Bioware Corp. -//::////////////////////////////////////////////// -/* - Calls the end of combat script every round -*/ -//::////////////////////////////////////////////// -//:: Created By: Preston Watamaniuk -//:: Created On: Oct 16, 2001 -//::////////////////////////////////////////////// -//::////////////////////////////////////////////// -//:: Modified By: Deva Winblood -//:: Modified On: Feb 16th, 2008 -//:: Added Support for Mounted Combat Feat Support -//::////////////////////////////////////////////// - -#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); - - if (!GetLocalInt(GetModule(),"X3_NO_MOUNTED_COMBAT_FEAT")) - { // set variables on target for mounted combat - DeleteLocalInt(OBJECT_SELF,"bX3_LAST_ATTACK_PHYSICAL"); - DeleteLocalInt(OBJECT_SELF,"nX3_HP_BEFORE"); - DeleteLocalInt(OBJECT_SELF,"bX3_ALREADY_MOUNTED_COMBAT"); - if (GetHasFeat(FEAT_MOUNTED_COMBAT,OBJECT_SELF)) - { // check for AC increase - int nRoll=d20()+GetSkillRank(SKILL_RIDE); - nRoll=nRoll-10; - if (nRoll>4) - { // ac increase - nRoll=nRoll/5; - ApplyEffectToObject(DURATION_TYPE_TEMPORARY,EffectACIncrease(nRoll),OBJECT_SELF,8.5); - } // ac increase - } // check for AC increase - } // set variables on target for mounted combat - - if(GetBehaviorState(NW_FLAG_BEHAVIOR_SPECIAL)) - { - DetermineSpecialBehavior(); - } - else if(!GetSpawnInCondition(NW_FLAG_SET_WARNINGS)) - { - DetermineCombatRound(); - } + 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)) { 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/_module/nss/nw_c2_default4.nss b/_module/nss/nw_c2_default4.nss index de904593..cd1f6160 100644 --- a/_module/nss/nw_c2_default4.nss +++ b/_module/nss/nw_c2_default4.nss @@ -1,93 +1,70 @@ -//::////////////////////////////////////////////////// -//:: NW_C2_DEFAULT4 -/* - Default OnConversation event handler for NPCs. - - */ -//::////////////////////////////////////////////////// -//:: Copyright (c) 2002 Floodgate Entertainment -//:: Created By: Naomi Novik -//:: Created On: 12/22/2002 -//::////////////////////////////////////////////////// - -#include "nw_i0_generic" -#include "prc_inc_spells" - +/*////////////////////////////////////////////////////////////////////////////// + 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() { - // * if petrified, jump out - if (PRCGetHasEffect(EFFECT_TYPE_PETRIFY, OBJECT_SELF) == TRUE) - { - return; - } - - // * If dead, exit directly. - if (GetIsDead(OBJECT_SELF) == TRUE) - { - return; - } - + object oCreature = OBJECT_SELF; ExecuteScript("prc_npc_conv", OBJECT_SELF); - - // See if what we just 'heard' matches any of our - // predefined patterns + 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)) + { + ai_DoMonsterCombatRound(oCreature); + return; + } + object oLastSpeaker = GetLastSpeaker(); int nMatch = GetListenPatternNumber(); - object oShouter = GetLastSpeaker(); - - if (nMatch == -1) + if(nMatch != -1) { - // Not a match -- start an ordinary conversation - if (GetCommandable(OBJECT_SELF)) - { - ClearActions(CLEAR_NW_C2_DEFAULT4_29); - BeginConversation(); - } - else - // * July 31 2004 - // * If only charmed then allow conversation - // * so you can have a better chance of convincing - // * people of lowering prices - if (PRCGetHasEffect(EFFECT_TYPE_CHARMED) == TRUE) - { - ClearActions(CLEAR_NW_C2_DEFAULT4_29); - BeginConversation(); - } + if(GetFactionEqual(oLastSpeaker, oCreature)) ai_MonsterCommands(oCreature, oLastSpeaker, nMatch); } - // Respond to shouts from friendly non-PCs only - else if (GetIsObjectValid(oShouter) - && !GetIsPC(oShouter) - && GetIsFriend(oShouter)) + else { - object oIntruder = OBJECT_INVALID; - // Determine the intruder if any - 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; - } - } - } - } - - // Actually respond to the shout - RespondToShout(oShouter, nMatch, oIntruder); + ai_ClearCreatureActions(); + BeginConversation(); } - // Send the user-defined event if appropriate if(GetSpawnInCondition(NW_FLAG_ON_DIALOGUE_EVENT)) { 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/_module/nss/nw_c2_default5.nss b/_module/nss/nw_c2_default5.nss index d6e2e631..acc3b3ed 100644 --- a/_module/nss/nw_c2_default5.nss +++ b/_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/_module/nss/nw_c2_default6.nss b/_module/nss/nw_c2_default6.nss index d362ecf1..53478420 100644 --- a/_module/nss/nw_c2_default6.nss +++ b/_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/_module/nss/nw_c2_default8.nss b/_module/nss/nw_c2_default8.nss index 3e494283..fa7ef11b 100644 --- a/_module/nss/nw_c2_default8.nss +++ b/_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/_module/nss/nw_c2_defaultb.nss b/_module/nss/nw_c2_defaultb.nss index 13385446..31500267 100644 --- a/_module/nss/nw_c2_defaultb.nss +++ b/_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/_module/nss/nw_c2_defaulte.nss b/_module/nss/nw_c2_defaulte.nss index 3d8ab2c9..76f62db6 100644 --- a/_module/nss/nw_c2_defaulte.nss +++ b/_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/_module/nss/nw_ch_ac1.nss b/_module/nss/nw_ch_ac1.nss new file mode 100644 index 00000000..6ed2fea5 --- /dev/null +++ b/_module/nss/nw_ch_ac1.nss @@ -0,0 +1,158 @@ +/*////////////////////////////////////////////////////////////////////////////// + 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() +{ + 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) + { + if(ai_GetIsInCombat(oCreature)) + { + ai_DoAssociateCombatRound(oCreature); + return; + } + 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) + { + // 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 + { + SetActionMode(oCreature, ACTION_MODE_STEALTH, FALSE); + if(ai_GetAIMode(oCreature, AI_MODE_AGGRESSIVE_SEARCH)) + { + 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); + } + } + } + if(AI_DEBUG) ai_Counter_End(GetName(oCreature) + ": Heartbeat, end"); + if(GetSpawnInCondition(NW_FLAG_HEARTBEAT_EVENT)) + { + SignalEvent(OBJECT_SELF, EventUserDefined(1001)); + } +} diff --git a/_module/nss/nw_ch_ac2.nss b/_module/nss/nw_ch_ac2.nss index 908594c9..04a56f98 100644 --- a/_module/nss/nw_ch_ac2.nss +++ b/_module/nss/nw_ch_ac2.nss @@ -1,57 +1,107 @@ -`//:://///////////////////////////////////////////// -//:: Associate: On Percieve -//:: NW_CH_AC2 -//:: Copyright (c) 2001 Bioware Corp. -//::////////////////////////////////////////////// -//::////////////////////////////////////////////// -//:: Created By: Preston Watamaniuk -//:: Created On: Nov 19, 2001 -//::////////////////////////////////////////////// - -#include "X0_INC_HENAI" - +/*////////////////////////////////////////////////////////////////////////////// + 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() { - //This is the equivalent of a force conversation bubble, should only be used if you want an NPC - //to say something while he is already engaged in combat. - if(GetSpawnInCondition(NW_FLAG_SPECIAL_COMBAT_CONVERSATION)) + object oCreature = OBJECT_SELF; + object oLastPerceived = GetLastPerceived(); + if(AI_DEBUG) { - ActionStartConversation(OBJECT_SELF); - } - - // * July 2003 - // * If in Stealth mode, don't attack enemies. Wait for player to attack or - // * for you to be attacked. (No point hiding anymore if you've been detected) - if(!GetAssociateState(NW_ASC_MODE_STAND_GROUND) && GetActionMode(OBJECT_SELF, ACTION_MODE_STEALTH)== FALSE) - { - //Do not bother checking the last target seen if already fighting - if(!GetIsObjectValid(GetAttemptedAttackTarget()) && - !GetIsObjectValid(GetAttackTarget()) && - !GetIsObjectValid(GetAttemptedSpellTarget())) + if(GetLastPerceptionHeard ()) { - //Check if the last percieved creature was actually seen - if(GetLastPerceptionSeen()) - { - if(GetIsEnemy(GetLastPerceived())) - { - SetFacingPoint(GetPosition(GetLastPerceived())); - HenchmenCombatRound(OBJECT_INVALID); - } - //Linked up to the special conversation check to initiate a special one-off conversation - //to get the PCs attention - else if(GetSpawnInCondition(NW_FLAG_SPECIAL_CONVERSATION) && GetIsPC(GetLastPerceived())) - { - ActionStartConversation(OBJECT_SELF); - } - } + 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()) + "."); } } - if(GetSpawnInCondition(NW_FLAG_PERCIEVE_EVENT)) + // We do nothing on Inaudibles so drop out early! + if(GetLastPerceptionInaudible()) { - SignalEvent(OBJECT_SELF, EventUserDefined(1002)); + ai_Debug("nw_ch_ac2", "42", GetName(oCreature) + " lost sound of " + + GetName(GetLastPerceived()) + "."); + return; } - - if (GetIsHired(OBJECT_SELF)!=TRUE) ExecuteScript("nw_c2_default2",OBJECT_SELF); - //SetAnimationCondition(NW_ANIM_FLAG_IS_ACTIVE); + 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/_module/nss/nw_ch_ac3.nss b/_module/nss/nw_ch_ac3.nss new file mode 100644 index 00000000..9eb34065 --- /dev/null +++ b/_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/_module/nss/nw_ch_ac4.nss b/_module/nss/nw_ch_ac4.nss new file mode 100644 index 00000000..f6c290d6 --- /dev/null +++ b/_module/nss/nw_ch_ac4.nss @@ -0,0 +1,45 @@ +/*////////////////////////////////////////////////////////////////////////////// + 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() +{ + 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) + { + if(GetFactionEqual(oLastSpeaker, oCreature)) ai_SelectAssociateCommand(oCreature, oLastSpeaker, nMatch); + } + else + { + if (!ai_GetIsBusy(oCreature)) + { + ai_ClearCreatureActions(); + if(GetAssociateType(oCreature) == ASSOCIATE_TYPE_HENCHMAN) BeginConversation("oc_ai_henchmen", oLastSpeaker); + else + { + json jHenchman = ObjectToJson(oCreature); + string sConversation = JsonGetString(GffGetResRef(jHenchman, "Conversation")); + if(sConversation == "") BeginConversation("oc_ai_henchmen", oLastSpeaker); + BeginConversation(); + } + } + } +} + diff --git a/_module/nss/nw_ch_ac5.nss b/_module/nss/nw_ch_ac5.nss new file mode 100644 index 00000000..78f93214 --- /dev/null +++ b/_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/_module/nss/nw_ch_ac6.nss b/_module/nss/nw_ch_ac6.nss new file mode 100644 index 00000000..f51e9374 --- /dev/null +++ b/_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/_module/nss/nw_ch_ac8.nss b/_module/nss/nw_ch_ac8.nss new file mode 100644 index 00000000..05b7f856 --- /dev/null +++ b/_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/_module/nss/nw_ch_aca.nss b/_module/nss/nw_ch_aca.nss new file mode 100644 index 00000000..99b6d5fa --- /dev/null +++ b/_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/_module/nss/nw_ch_acb.nss b/_module/nss/nw_ch_acb.nss new file mode 100644 index 00000000..ec96e77f --- /dev/null +++ b/_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/_module/nss/nw_ch_ace.nss b/_module/nss/nw_ch_ace.nss new file mode 100644 index 00000000..688ab902 --- /dev/null +++ b/_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/_module/nss/nw_ch_summon_9.nss b/_module/nss/nw_ch_summon_9.nss new file mode 100644 index 00000000..ca5a87c4 --- /dev/null +++ b/_module/nss/nw_ch_summon_9.nss @@ -0,0 +1,40 @@ +//:://///////////////////////////////////////////// +//:: Associate: On Spawn In +//:: 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 +//::////////////////////////////////////////////// +//:: Updated By: Georg Zoeller, 2003-08-20: Added variable check for spawn in animation +#include "X0_INC_HENAI" +#include "x2_inc_switches" +void main() +{ + //Sets up the special henchmen listening patterns + SetAssociateListenPatterns(); + + // Set additional henchman listening patterns + //bkSetListeningPatterns(); + // * If Incorporeal, apply changes + if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_IS_INCORPOREAL) == TRUE) + { + 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); + } + // Set starting location + SetAssociateStartLocation(); +} + + diff --git a/_module/nss/on_mod_enter.nss b/_module/nss/on_mod_enter.nss index f6e67b85..c1c990d5 100644 --- a/_module/nss/on_mod_enter.nss +++ b/_module/nss/on_mod_enter.nss @@ -27,4 +27,6 @@ void main() //:: Add system journal entries 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); + AddJournalQuestEntry("JRNL_FOODWTR", 1, oPC, FALSE, FALSE, FALSE); } diff --git a/_module/nss/onrest.nss b/_module/nss/onrest.nss index abf11448..cf9ef5b4 100644 --- a/_module/nss/onrest.nss +++ b/_module/nss/onrest.nss @@ -1,170 +1,184 @@ +#include "prc_inc_racial" + void main() { -object oPC = GetLastPCRested(); - -if (GetLastRestEventType()==REST_EVENTTYPE_REST_STARTED) - { - int nWM = d100(1); - string sLevel = IntToString(GetHitDice(oPC)); - string sResref = "wm_" + sLevel; - object oWP = GetNearestObjectByTag("wmwp"); - location lWP = GetLocation(oWP); - if (nWM<=10) - { - object oSpawn = CreateObject(OBJECT_TYPE_CREATURE,sResref,lWP); - AssignCommand(oSpawn,ActionAttack(oPC)); - } - } -else if (GetLastRestEventType()==REST_EVENTTYPE_REST_FINISHED||REST_EVENTTYPE_REST_CANCELLED) - { - int nHour = GetTimeHour(); - int nMinute = GetTimeMinute(); - int nSecond = GetTimeSecond(); - int nMillisecond = GetTimeMillisecond(); - // Advance the time 8 hours. - nHour += 8; - - // Set the new time - int iPW = GetLocalInt(GetModule(), "PW_MODE"); + object oPC = GetLastPCRested(); - //:: Skip if running as a Persistant World MP module - if (!iPW) + int nRace = MyPRCGetRacialType(oPC); + + if (GetLastRestEventType()==REST_EVENTTYPE_REST_STARTED) { - SetTime(nHour, nMinute, nSecond, nMillisecond); + int nWM = d100(1); + string sLevel = IntToString(GetHitDice(oPC)); + string sResref = "wm_" + sLevel; + object oWP = GetNearestObjectByTag("wmwp"); + location lWP = GetLocation(oWP); + if (nWM<=10) + { + object oSpawn = CreateObject(OBJECT_TYPE_CREATURE,sResref,lWP); + AssignCommand(oSpawn,ActionAttack(oPC)); + } } + else if (GetLastRestEventType()==REST_EVENTTYPE_REST_FINISHED||REST_EVENTTYPE_REST_CANCELLED) + { + int nHour = GetTimeHour(); + int nMinute = GetTimeMinute(); + int nSecond = GetTimeSecond(); + int nMillisecond = GetTimeMillisecond(); + // Advance the time 8 hours. + nHour += 8; - // See how hungry and thirsty PC is - int ibHungry = GetLocalInt(oPC,"ate"); - int ibThirsty = GetLocalInt(oPC,"drank"); + // Set the new time + int iPW = GetLocalInt(GetModule(), "PW_MODE"); - // Make them wake up hungrier and thirstier - SetLocalInt(oPC,"ate",ibHungry-1); - SetLocalInt(oPC,"drank",ibThirsty-1); + //:: Skip if running as a Persistant World MP module + if (!iPW) + { + SetTime(nHour, nMinute, nSecond, nMillisecond); + } + // See how hungry and thirsty PC is + int ibHungry = GetLocalInt(oPC,"ate"); + int ibThirsty = GetLocalInt(oPC,"drank"); - //get new values - int iHungry = GetLocalInt(oPC,"ate"); - int iThirsty = GetLocalInt(oPC,"drank"); - //apply hunger and thirst penalties - switch (iHungry) - { - case -1: - { - effect eEffect = EffectAbilityDecrease(ABILITY_CONSTITUTION, 2); - eEffect = ExtraordinaryEffect(eEffect); - ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC); - SendMessageToPC(oPC,"You rest well, but you awaken hungry."); - break; - } - case -2: - { - effect eEffect = EffectAbilityDecrease(ABILITY_CONSTITUTION, 4); - eEffect = ExtraordinaryEffect(eEffect); - ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC); - SendMessageToPC(oPC,"You rest well, but you awaken quite hungry."); - break; - } - case -3: - { - effect eEffect = EffectAbilityDecrease(ABILITY_CONSTITUTION, 5); - eEffect = ExtraordinaryEffect(eEffect); - ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC); - SendMessageToPC(oPC,"You rest well, but you awaken really hungry."); - break; - } - case -4: - { - effect eEffect = EffectAbilityDecrease(ABILITY_CONSTITUTION, 6); - eEffect = ExtraordinaryEffect(eEffect); - ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC); - SendMessageToPC(oPC,"You rest well, but you awaken very hungry."); - break; - } - case -5: - { - effect eEffect = EffectAbilityDecrease(ABILITY_CONSTITUTION, 7); - eEffect = ExtraordinaryEffect(eEffect); - ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC); - SendMessageToPC(oPC,"You rest well, but you awaken painfully hungry."); - break; - } - case -6: - { - effect eEffect = EffectAbilityDecrease(ABILITY_CONSTITUTION, 8); - eEffect = ExtraordinaryEffect(eEffect); - ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC); - SendMessageToPC(oPC,"You rest well, but you awaken extremely hungry."); - break; - } - case -7: - { - effect eEffect = EffectAbilityDecrease(ABILITY_CONSTITUTION, 10); - eEffect = ExtraordinaryEffect(eEffect); - ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC); - SendMessageToPC(oPC,"You rest well, but you are starving to death."); - break; - } - case -8: - { - effect eEffect = EffectAbilityDecrease(ABILITY_CONSTITUTION, 12); - eEffect = ExtraordinaryEffect(eEffect); - ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC); - SendMessageToPC(oPC,"You will die soon if you don't eat."); - break; - } - case -9: - { - effect eEffect = EffectDeath(); - ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC); - SendMessageToPC(oPC,"You have starved to death."); - break; - } - } - switch (iThirsty) - { - case -1: - { - effect eEffect = EffectNegativeLevel(1,FALSE); - eEffect = ExtraordinaryEffect(eEffect); - ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC); - SendMessageToPC(oPC,"You awaken and are quite thirsty."); - break; - } - case -2: - { - effect eEffect = EffectNegativeLevel(2,FALSE); - eEffect = ExtraordinaryEffect(eEffect); - ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC); - SendMessageToPC(oPC,"You awaken and are extremely thirsty."); - break; - } - case -3: - { - effect eEffect = EffectNegativeLevel(3,FALSE); - eEffect = ExtraordinaryEffect(eEffect); - ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC); - SendMessageToPC(oPC,"You awaken and are dreadfully thirsty."); - break; - } - case -4: - { - effect eEffect = EffectNegativeLevel(4,FALSE); - eEffect = ExtraordinaryEffect(eEffect); - ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC); - SendMessageToPC(oPC,"You are dying of thirst, you need to find something to drink."); - break; - } - case -5: - { - effect eEffect = EffectDeath(); - ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC); - SendMessageToPC(oPC,"You have died of thirst."); - break; - } - } + // Make them wake up hungrier and thirstier + SetLocalInt(oPC,"ate",ibHungry-1); + SetLocalInt(oPC,"drank",ibThirsty-1); + + if ( + nRace == RACIAL_TYPE_CONSTRUCT || + nRace == RACIAL_TYPE_UNDEAD || + nRace == RACIAL_TYPE_ELEMENTAL || + nRace == RACIAL_TYPE_OUTSIDER + ) + { + SetLocalInt(oPC, "ate", 99); + SetLocalInt(oPC, "drank", 99); + } + + //get new values + int iHungry = GetLocalInt(oPC,"ate"); + int iThirsty = GetLocalInt(oPC,"drank"); + //apply hunger and thirst penalties + switch (iHungry) + { + case -1: + { + effect eEffect = EffectAbilityDecrease(ABILITY_CONSTITUTION, 2); + eEffect = ExtraordinaryEffect(eEffect); + ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC); + SendMessageToPC(oPC,"You rest well, but you awaken hungry."); + break; + } + case -2: + { + effect eEffect = EffectAbilityDecrease(ABILITY_CONSTITUTION, 4); + eEffect = ExtraordinaryEffect(eEffect); + ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC); + SendMessageToPC(oPC,"You rest well, but you awaken quite hungry."); + break; + } + case -3: + { + effect eEffect = EffectAbilityDecrease(ABILITY_CONSTITUTION, 5); + eEffect = ExtraordinaryEffect(eEffect); + ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC); + SendMessageToPC(oPC,"You rest well, but you awaken really hungry."); + break; + } + case -4: + { + effect eEffect = EffectAbilityDecrease(ABILITY_CONSTITUTION, 6); + eEffect = ExtraordinaryEffect(eEffect); + ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC); + SendMessageToPC(oPC,"You rest well, but you awaken very hungry."); + break; + } + case -5: + { + effect eEffect = EffectAbilityDecrease(ABILITY_CONSTITUTION, 7); + eEffect = ExtraordinaryEffect(eEffect); + ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC); + SendMessageToPC(oPC,"You rest well, but you awaken painfully hungry."); + break; + } + case -6: + { + effect eEffect = EffectAbilityDecrease(ABILITY_CONSTITUTION, 8); + eEffect = ExtraordinaryEffect(eEffect); + ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC); + SendMessageToPC(oPC,"You rest well, but you awaken extremely hungry."); + break; + } + case -7: + { + effect eEffect = EffectAbilityDecrease(ABILITY_CONSTITUTION, 10); + eEffect = ExtraordinaryEffect(eEffect); + ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC); + SendMessageToPC(oPC,"You rest well, but you are starving to death."); + break; + } + case -8: + { + effect eEffect = EffectAbilityDecrease(ABILITY_CONSTITUTION, 12); + eEffect = ExtraordinaryEffect(eEffect); + ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC); + SendMessageToPC(oPC,"You will die soon if you don't eat."); + break; + } + case -9: + { + effect eEffect = EffectDeath(); + ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC); + SendMessageToPC(oPC,"You have starved to death."); + break; + } + } + switch (iThirsty) + { + case -1: + { + effect eEffect = EffectNegativeLevel(1,FALSE); + eEffect = ExtraordinaryEffect(eEffect); + ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC); + SendMessageToPC(oPC,"You awaken and are quite thirsty."); + break; + } + case -2: + { + effect eEffect = EffectNegativeLevel(2,FALSE); + eEffect = ExtraordinaryEffect(eEffect); + ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC); + SendMessageToPC(oPC,"You awaken and are extremely thirsty."); + break; + } + case -3: + { + effect eEffect = EffectNegativeLevel(3,FALSE); + eEffect = ExtraordinaryEffect(eEffect); + ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC); + SendMessageToPC(oPC,"You awaken and are dreadfully thirsty."); + break; + } + case -4: + { + effect eEffect = EffectNegativeLevel(4,FALSE); + eEffect = ExtraordinaryEffect(eEffect); + ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC); + SendMessageToPC(oPC,"You are dying of thirst, you need to find something to drink."); + break; + } + case -5: + { + effect eEffect = EffectDeath(); + ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC); + SendMessageToPC(oPC,"You have died of thirst."); + break; + } + } - } + } } diff --git a/_module/nss/pc_savebuffs.nss b/_module/nss/pc_savebuffs.nss new file mode 100644 index 00000000..96b42d00 --- /dev/null +++ b/_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/_module/nss/pe_buffing.nss b/_module/nss/pe_buffing.nss new file mode 100644 index 00000000..a6c40500 --- /dev/null +++ b/_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/_module/nss/pe_crafting.nss b/_module/nss/pe_crafting.nss new file mode 100644 index 00000000..388c86a4 --- /dev/null +++ b/_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/_module/nss/pe_debug.nss b/_module/nss/pe_debug.nss new file mode 100644 index 00000000..5b6ad1a4 --- /dev/null +++ b/_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/_module/nss/pe_henchmen.nss b/_module/nss/pe_henchmen.nss new file mode 100644 index 00000000..4f6bf42f --- /dev/null +++ b/_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/_module/nss/pe_mod_set.nss b/_module/nss/pe_mod_set.nss new file mode 100644 index 00000000..9c251b98 --- /dev/null +++ b/_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/_module/nss/pe_test.nss b/_module/nss/pe_test.nss new file mode 100644 index 00000000..7fd799c8 --- /dev/null +++ b/_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/_module/nss/pi_buffing.nss b/_module/nss/pi_buffing.nss new file mode 100644 index 00000000..6ce454ea --- /dev/null +++ b/_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/_module/nss/pi_crafting.nss b/_module/nss/pi_crafting.nss new file mode 100644 index 00000000..3fa9775d --- /dev/null +++ b/_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/_module/nss/pi_debug.nss b/_module/nss/pi_debug.nss new file mode 100644 index 00000000..6555882a --- /dev/null +++ b/_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/_module/nss/pi_forcerest.nss b/_module/nss/pi_forcerest.nss new file mode 100644 index 00000000..dfabb342 --- /dev/null +++ b/_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/_module/nss/pi_henchmen.nss b/_module/nss/pi_henchmen.nss new file mode 100644 index 00000000..51190399 --- /dev/null +++ b/_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/_module/nss/pi_test.nss b/_module/nss/pi_test.nss new file mode 100644 index 00000000..818da8c1 --- /dev/null +++ b/_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/_module/nss/pinc_henchmen.nss b/_module/nss/pinc_henchmen.nss new file mode 100644 index 00000000..a67141a3 --- /dev/null +++ b/_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/_module/nss/spawn_towners.nss b/_module/nss/spawn_towners.nss index 3e0fd9fb..da739356 100644 --- a/_module/nss/spawn_towners.nss +++ b/_module/nss/spawn_towners.nss @@ -28,33 +28,46 @@ const int EVENT_USER_DEFINED_POSTSPAWN = 1511; #include "x0_i0_anims" #include "x2_inc_switches" +#include "ms_name_inc" +#include "mmd_inc_random" + void main() { - // User defined OnSpawn event requested? - int nSpecEvent = GetLocalInt(OBJECT_SELF,"X2_USERDEFINED_ONSPAWN_EVENTS"); + object oNPC = OBJECT_SELF; + + // User defined OnSpawn event requested? + int nSpecEvent = GetLocalInt(oNPC,"X2_USERDEFINED_ONSPAWN_EVENTS"); // Pre Spawn Event requested if (nSpecEvent == 1 || nSpecEvent == 3 ) { - SignalEvent(OBJECT_SELF,EventUserDefined(EVENT_USER_DEFINED_PRESPAWN )); + SignalEvent(oNPC,EventUserDefined(EVENT_USER_DEFINED_PRESPAWN )); } + ms_Nomenclature(oNPC); + + DelayCommand(0.0f, rnd_skin(oNPC)); + DelayCommand(0.0f, rnd_head(oNPC)); + DelayCommand(0.0f, rnd_pheno(oNPC)); + DelayCommand(0.0f, rnd_tattoo(oNPC)); + DelayCommand(0.0f, rnd_height(oNPC)); + /* Fix for the new golems to reduce their number of attacks */ - int nNumber = GetLocalInt(OBJECT_SELF,CREATURE_VAR_NUMBER_OF_ATTACKS); + int nNumber = GetLocalInt(oNPC,CREATURE_VAR_NUMBER_OF_ATTACKS); if (nNumber >0 ) { SetBaseAttackBonus(nNumber); } // Execute default OnSpawn script. - ExecuteScript("nw_c2_default9", OBJECT_SELF); + ExecuteScript("nw_c2_default9", oNPC); //Post Spawn event requeste if (nSpecEvent == 2 || nSpecEvent == 3) { - SignalEvent(OBJECT_SELF,EventUserDefined(EVENT_USER_DEFINED_POSTSPAWN)); + SignalEvent(oNPC,EventUserDefined(EVENT_USER_DEFINED_POSTSPAWN)); } SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS); } diff --git a/_module/nss/x2_def_spawn.nss b/_module/nss/x2_def_spawn.nss new file mode 100644 index 00000000..f562dc24 --- /dev/null +++ b/_module/nss/x2_def_spawn.nss @@ -0,0 +1,101 @@ +//:://///////////////////////////////////////////// +//:: Name x2_def_spawn +//:: Copyright (c) 2001 Bioware Corp. +//::////////////////////////////////////////////// +/* + Default On Spawn script + + + 2003-07-28: Georg Zoeller: + + If you set a ninteger on the creature named + "X2_USERDEFINED_ONSPAWN_EVENTS" + The creature will fire a pre and a post-spawn + event on itself, depending on the value of that + variable + 1 - Fire Userdefined Event 1510 (pre spawn) + 2 - Fire Userdefined Event 1511 (post spawn) + 3 - Fire both events + + 2007-12-31: Deva Winblood + Modified to look for X3_HORSE_OWNER_TAG and if + it is defined look for an NPC with that tag + nearby or in the module (checks near first). + It will make that NPC this horse's master. + +*/ +//::////////////////////////////////////////////// +//:: Created By: Keith Warner, Georg Zoeller +//:: Created On: June 11/03 +//::////////////////////////////////////////////// + +const int EVENT_USER_DEFINED_PRESPAWN = 1510; +const int EVENT_USER_DEFINED_POSTSPAWN = 1511; + +#include "ms_name_inc" +#include "x2_inc_switches" +#include "mmd_inc_random" + +void main() +{ + string sTag; + object oNPC; + // User defined OnSpawn event requested? + int nSpecEvent = GetLocalInt(OBJECT_SELF,"X2_USERDEFINED_ONSPAWN_EVENTS"); + + + // Pre Spawn Event requested + if (nSpecEvent == 1 || nSpecEvent == 3 ) + { + SignalEvent(OBJECT_SELF,EventUserDefined(EVENT_USER_DEFINED_PRESPAWN )); + } + + ms_Nomenclature(OBJECT_SELF); + + DelayCommand(0.0f, rnd_skin(oNPC)); + DelayCommand(0.0f, rnd_head(oNPC)); + DelayCommand(0.0f, rnd_pheno(oNPC)); + DelayCommand(0.0f, rnd_tattoo(oNPC)); + DelayCommand(0.0f, rnd_height(oNPC)); + + sTag=GetLocalString(OBJECT_SELF,"X3_HORSE_OWNER_TAG"); + if (GetStringLength(sTag)>0) + { // look for master + oNPC=GetNearestObjectByTag(sTag); + if (GetIsObjectValid(oNPC)&&GetObjectType(oNPC)==OBJECT_TYPE_CREATURE) + { // master found + AddHenchman(oNPC); + } // master found + else + { // look in module + oNPC=GetObjectByTag(sTag); + if (GetIsObjectValid(oNPC)&&GetObjectType(oNPC)==OBJECT_TYPE_CREATURE) + { // master found + AddHenchman(oNPC); + } // master found + else + { // master does not exist - remove X3_HORSE_OWNER_TAG + DeleteLocalString(OBJECT_SELF,"X3_HORSE_OWNER_TAG"); + } // master does not exist - remove X3_HORSE_OWNER_TAG + } // look in module + } // look for master + + /* Fix for the new golems to reduce their number of attacks */ + + int nNumber = GetLocalInt(OBJECT_SELF,CREATURE_VAR_NUMBER_OF_ATTACKS); + if (nNumber >0 ) + { + SetBaseAttackBonus(nNumber); + } + + // Execute default OnSpawn script. + ExecuteScript("nw_c2_default9", OBJECT_SELF); + + + //Post Spawn event requeste + if (nSpecEvent == 2 || nSpecEvent == 3) + { + SignalEvent(OBJECT_SELF,EventUserDefined(EVENT_USER_DEFINED_POSTSPAWN)); + } + +} diff --git a/_module/nss/xx_pc_1_hb.nss b/_module/nss/xx_pc_1_hb.nss new file mode 100644 index 00000000..7dac8764 --- /dev/null +++ b/_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/_module/nss/xx_pc_2_percept.nss b/_module/nss/xx_pc_2_percept.nss new file mode 100644 index 00000000..9731f702 --- /dev/null +++ b/_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/_module/nss/xx_pc_3_endround.nss b/_module/nss/xx_pc_3_endround.nss new file mode 100644 index 00000000..51126e6d --- /dev/null +++ b/_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/_module/nss/xx_pc_4_convers.nss b/_module/nss/xx_pc_4_convers.nss new file mode 100644 index 00000000..413aef15 --- /dev/null +++ b/_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/_module/nss/xx_pc_5_phyatked.nss b/_module/nss/xx_pc_5_phyatked.nss new file mode 100644 index 00000000..1c6ba790 --- /dev/null +++ b/_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/_module/nss/xx_pc_6_damaged.nss b/_module/nss/xx_pc_6_damaged.nss new file mode 100644 index 00000000..c3d6aaa3 --- /dev/null +++ b/_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/_module/nss/xx_pc_8_disturb.nss b/_module/nss/xx_pc_8_disturb.nss new file mode 100644 index 00000000..6440c038 --- /dev/null +++ b/_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/_module/nss/xx_pc_b_castat.nss b/_module/nss/xx_pc_b_castat.nss new file mode 100644 index 00000000..5d4b85f5 --- /dev/null +++ b/_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/_module/nss/xx_pc_e_blocked.nss b/_module/nss/xx_pc_e_blocked.nss new file mode 100644 index 00000000..604513e8 --- /dev/null +++ b/_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(); + } +}