20250530 Late Update

Added @Rakiov's brilliant NUI spellcast system & power attack GUI.
Fixed incorrect constants for Charming the Arrow and Investigator.
Updated loadhints.2da.
This commit is contained in:
Jaysyn904 2025-05-30 23:23:08 -04:00
parent a85b0de327
commit 1fa8b68d5d
23 changed files with 2718 additions and 7818 deletions

View File

@ -0,0 +1,18 @@
hp_pa_events -> prc_nui_pa_event*
hp_pa_script -> prc_nui_pa_trggr
hp_pa_view -> prc_nui_pa_view
hp_sb_events -> prc_nui_sb_event
hp_sb_otscript -> prc_nui_sb_trggr
hp_sb_view -> prc_nui_sb_view
//:: INCLUDES
hp_nui_consts -> prc_nui_consts
hp_sb_script -> prc_nui_sb_inc
hp_string_util -> prc_string_inc
hp_sb_desc_view -> prc_nui_sbd_inc
//:: Events
hp_chatscript -> prc_onplayerchat
hp_nui_events -> prc_onplayernui
hp_otevent -> prc_onplaytarget

View File

@ -1,103 +1,106 @@
2DA V2.0
LABEL HINT CAMPAIGNONLY
0 Hint1 67053 0
1 Hint2 67054 1
2 Hint3 67055 0
3 Hint3 67653 0
4 Hint3 67655 1
5 Hint3 67656 1
6 Hint3 67657 0
7 Hint3 67658 0
8 Hint3 67659 0
9 Hint3 67660 0
10 Hint3 67661 0
11 Hint3 67662 1
12 Hint3 67663 0
13 Hint3 67664 0
14 Hint3 67665 1
15 Hint3 67666 1
16 Hint3 67667 1
17 Hint3 67668 0
18 Hint3 67669 1
19 Hint3 67670 1
20 Hint3 67671 0
21 Hint3 67672 0
22 Hint3 67673 1
23 Hint3 67707 1
24 Hint 68481 0
25 Hint 68486 0
26 Qbar2Wp 45 0
27 DeadHen 68700 1
28 Hint 40109 0
29 Hint 40112 0
30 Hint 40113 2
31 Hint 40114 1
32 Hint 40115 2
33 Hint 40116 2
34 Hint 40117 2
35 Hint 40118 2
36 Hint 40119 2
37 Hint 40120 2
38 Hint 40121 2
39 Hint 40122 2
40 Hint 40123 2
41 Hint 40124 2
42 Hint 40125 2
43 Hint 40126 2
44 Hint 40127 2
45 Hint 40128 2
46 Hint 40129 2
47 Hint 40130 2
48 Hint 40131 2
49 Hint 40132 2
50 Hint 40133 2
51 Hint 40134 2
52 Hint 40135 2
53 Hint 40136 2
54 Hint 40137 2
55 Hint 40545 2
56 RestHint 40552 2
57 HealingHint 40575 2
58 DeathHint 40576 2
59 WeaponHint 40580 2
60 HenchEquipHint 76393 2
61 RaiseDead 83458 3
62 CraftFeatHint 83613 1
63 ContinualLight 83786 0
64 UseHenches 85567 3
65 RestHint2 85569 3
66 PowerAttack 85575 3
67 PaleMaster1 85703 3
68 PaleMaster2 85704 3
69 Wounding 85765 0
70 Geography101 86778 3
71 spellcasting 86871 3
72 lowac 86872 3
73 shapeshift 86873 3
74 lightgems 86874 3
75 useRelic 86881 3
76 PoolOfsouls 86882 3
77 Rest 86883 3
78 AC30 86884 3
79 Armor 86885 3
80 SpellMantle 86886 0
81 InvisiblityCounter 86887 3
82 UseProperWeapons 86888 3
83 IllithidBrainSuck 86889 3
84 AlchemistsFire 100938 0
85 WeaponFinesse 110100 3
86 StoresAndShifter 110118 0
87 PRC8_LETO 16852017 0
88 PRC8_SPONTANEOUS 16852018 0
89 PRC8_SPELLSLOTS 16852019 0
90 PRC8_TWOHANDED 16852020 0
91 PRC8_DELEVEL 16852021 0
92 PRC8_EXALTED_VILE 16852022 0
93 PRC8_OPTIONS 16852023 0
94 PRC8_INVALID_FEATS_SKILLS 16852024 0
95 PRC8_MARKER_FEATS 16852025 0
96 PRC8_INVOKING 16852026 0
97 PRC8_SPELLCRAFT 16852027 0
98 PRC8_TUMBLE 16852028 0
99 PRC8_MASTERFEATS 16852029 0
LABEL HINT CAMPAIGNONLY
0 Hint1 67053 0
1 Hint2 67054 1
2 Hint3 67055 0
3 Hint3 67653 0
4 Hint3 67655 1
5 Hint3 67656 1
6 Hint3 67657 0
7 Hint3 67658 0
8 Hint3 67659 0
9 Hint3 67660 0
10 Hint3 67661 0
11 Hint3 67662 1
12 Hint3 67663 0
13 Hint3 67664 0
14 Hint3 67665 1
15 Hint3 67666 1
16 Hint3 67667 1
17 Hint3 67668 0
18 Hint3 67669 1
19 Hint3 67670 1
20 Hint3 67671 0
21 Hint3 67672 0
22 Hint3 67673 1
23 Hint3 67707 1
24 Hint 68481 0
25 Hint 68486 0
26 Qbar2Wp 45 0
27 DeadHen 68700 1
28 Hint 40109 0
29 Hint 40112 0
30 Hint 40113 2
31 Hint 40114 1
32 Hint 40115 2
33 Hint 40116 2
34 Hint 40117 2
35 Hint 40118 2
36 Hint 40119 2
37 Hint 40120 2
38 Hint 40121 2
39 Hint 40122 2
40 Hint 40123 2
41 Hint 40124 2
42 Hint 40125 2
43 Hint 40126 2
44 Hint 40127 2
45 Hint 40128 2
46 Hint 40129 2
47 Hint 40130 2
48 Hint 40131 2
49 Hint 40132 2
50 Hint 40133 2
51 Hint 40134 2
52 Hint 40135 2
53 Hint 40136 2
54 Hint 40137 2
55 Hint 40545 2
56 RestHint 40552 2
57 HealingHint 40575 2
58 DeathHint 40576 2
59 WeaponHint 40580 2
60 HenchEquipHint 76393 2
61 RaiseDead 83458 3
62 CraftFeatHint 83613 1
63 ContinualLight 83786 0
64 UseHenches 85567 3
65 RestHint2 85569 3
66 PowerAttack 85575 3
67 PaleMaster1 85703 3
68 PaleMaster2 85704 3
69 Wounding 85765 0
70 Geography101 86778 3
71 spellcasting 86871 3
72 lowac 86872 3
73 shapeshift 86873 3
74 lightgems 86874 3
75 useRelic 86881 3
76 PoolOfsouls 86882 3
77 Rest 86883 3
78 AC30 86884 3
79 Armor 86885 3
80 SpellMantle 86886 0
81 InvisiblityCounter 86887 3
82 UseProperWeapons 86888 3
83 IllithidBrainSuck 86889 3
84 AlchemistsFire 100938 0
85 WeaponFinesse 110100 3
86 StoresAndShifter 110118 0
87 PRC8_LETO 16852017 0
88 PRC8_SPONTANEOUS 16852018 0
89 PRC8_SPELLSLOTS 16852019 0
90 PRC8_TWOHANDED 16852020 0
91 PRC8_DELEVEL 16852021 0
92 PRC8_EXALTED_VILE 16852022 0
93 PRC8_OPTIONS 16852023 0
94 PRC8_INVALID_FEATS_SKILLS 16852024 0
95 PRC8_MARKER_FEATS 16852025 0
96 PRC8_INVOKING 16852026 0
97 PRC8_SPELLCRAFT 16852027 0
98 PRC8_TUMBLE 16852028 0
99 PRC8_MASTERFEATS 16852029 0
100 PRC_NUI_SPELLBOOK 16852030 0
101 PRC_NUI_POWERATTACK 16852031 0
102 **** **** ****

View File

@ -187,7 +187,7 @@ const int FEAT_SANCTIFY_MARTIAL_ELVEN_THINBLADE = 24864;
const int FEAT_SANCTIFY_MARTIAL_ELVEN_COURTBLADE = 24865;
//:: Web Enhancement Feats
const int FEAT_CHARMING_THE_ARROW = 25997;
const int FEAT_CHARMING_THE_ARROW = 25998;
//:: Skill Based Feats
const int FEAT_JUMP = 2884;
@ -3906,7 +3906,7 @@ const int FEAT_IMPROVED_TRIP = 2807;
const int FEAT_PRC_IMP_DISARM = 5196;
const int FEAT_AWESOME_BLOW = 5370;
const int FEAT_IMPROVED_SHIELD_BASH = 3250;
const int FEAT_INVESTIGATOR = 25997;
const int FEAT_INVESTIGATOR = 25998;
// Player's Handbook II Feats
const int FEAT_STEADFAST_DETERMINATION = 3267;

View File

@ -0,0 +1,113 @@
//::///////////////////////////////////////////////
//:: NUI Constants
//:: prc_nui_consts
//:://////////////////////////////////////////////
/*
This file holds all the constants used by the various PRC NUI scripts.
*/
//:://////////////////////////////////////////////
//:: Created By: Rakiov
//:: Created On: 24.05.2005
//:://////////////////////////////////////////////
const int NUI_PAYLOAD_BUTTON_LEFT_CLICK = 0;
const int NUI_PAYLOAD_BUTTON_MIDDLE_CLICK = 1;
const int NUI_PAYLOAD_BUTTON_RIGHT_CLICK = 2;
//////////////////////////////////////////////////
// //
// NUI Spellbook //
// //
//////////////////////////////////////////////////
// This is the NUI Spellbook window ID
const string PRC_SPELLBOOK_NUI_WINDOW_ID = "prcSpellbookNui";
// This is the base Id for the Class buttons in the NUI Spellbook, the ID will
// have the ClassID attached to it (i.e. spellbookClassButton_123)
const string PRC_SPELLBOOK_NUI_CLASS_BUTTON_BASEID = "spellbookClassButton_";
// This is the base Id for the Spell Circle buttons in the NUI Spellbook, the ID will
// have the Circle attached to it (i.e. spellbookCircleButton__6)
const string PRC_SPELLBOOK_NUI_CIRCLE_BUTTON_BASEID = "spellbookCircleButton_";
// This is the base Id for the Spell Buttons in the NUI Spellbook, the ID will
// have the SpellbookId (the row of the class's spell's 2da or equivalent)
// attached to it (i.e. spellbookSpellButton_6)
const string PRC_SPELLBOOK_NUI_SPELL_BUTTON_BASEID = "spellbookSpellButton_";
// This is the base Id for the Meta Feat buttons in the NUI Spellbook, the ID will
// have the FeatID attached to it (i.e. spellbookMetaButton_12345)
const string PRC_SPELLBOOK_NUI_META_BUTTON_BASEID = "spellbookMetaButton_";
// This is the selected ClassID var used to store what class was selected to the Player
// locally
const string PRC_SPELLBOOK_SELECTED_CLASSID_VAR = "prcSpellbookSelectedClassID";
// This is the selected Circle var used to store what spell circle was selected
// to the Player locally
const string PRC_SPELLBOOK_SELECTED_CIRCLE_VAR = "prcSpellbookSelectedCircle";
// This is the Spellbook NUI geomeotry var, used to allow the location and sizing
// of the NUI to be remembered if it is ever rerendered.
const string PRC_SPELLBOOK_NUI_GEOMETRY_VAR = "sbNuiGeometry";
// This is the Selected SpellID Var, used to tell the OnTarget script what spell
// we are using after manual targetting
const string NUI_SPELLBOOK_SELECTED_SPELLID_VAR = "NUI_Spellbook_SpellId";
// This is the Selected FeatID Var, used to tell the OnTarget script what feat
// we are using after manual targetting
const string NUI_SPELLBOOK_SELECTED_FEATID_VAR = "NUI_Spellbook_FeatID";
// This is the Selected SubSpellID Var, used in conjuncture with the Selected FeatID
// to allow radial spells to work (it needs the master spell's featID and the sub spell's
// SpellID for it to work.
const string NUI_SPELLBOOK_SELECTED_SUBSPELL_SPELLID_VAR = "NUI_Spellbook_SubSpellID";
// This is the OnTarget action var saved to the player locally to say if we are
// using the NUI Spellbook spell or not.
const string NUI_SPELLBOOK_ON_TARGET_ACTION_VAR = "ONPLAYERTARGET_ACTION";
// This is a Boolean to tell the target script if the selected feat is a persoanl feat
// and can only be used on the executing object.
const string NUI_SPELLBOOK_ON_TARGET_IS_PERSONAL_FEAT = "NUI_Spellbook_IsPersonalFeat";
const string NUI_SPELL_DESCRIPTION_WINDOW_ID = "NUI_Spell_Description";
const string NUI_SPELL_DESCRIPTION_OK_BUTTON = "NUIDescriptionOKButton";
// This is the limit of how many spell buttons we can have in a row before we
// need to start a new row on the NUI Spellbook.
const int NUI_SPELLBOOK_SPELL_BUTTON_LENGTH = 9;
const string NUI_SPELLBOOK_BINDER_DICTIONARY_CACHE_VAR = "NUI_Spellbook_GetBinderSpellToFeatDictionaryCache";
const string NUI_SPELLBOOK_CLASS_STANCES_CACHE_BASE_VAR = "NUI_Spellbook_GetToBStanceSpellListCache_";
const string NUI_SPELLBOOK_CLASS_SHAPES_CACHE_BASE_VAR = "NUI_Spellbook_GetInvokerShapeSpellListCache_";
const string NUI_SPELLBOOK_CLASS_ESSENCE_CACHE_BASE_VAR = "NUISpellbookClassEssence_";
//////////////////////////////////////////////////
// //
// NUI Power Attack //
// //
//////////////////////////////////////////////////
// The Window ID for the Power Attack NUI
const string NUI_PRC_POWER_ATTACK_WINDOW = "nui_prc_power_attack_window";
// LocalVar for the geometry of the Power Attack NUI window
const string NUI_PRC_PA_GEOMETRY_VAR = "paNuiGeometry";
// Event For Left "-" button of the Power Attack NUI
const string NUI_PRC_PA_LEFT_BUTTON_EVENT = "nui_prc_pa_left_button_event";
// Event For Right "+" Button of the Power Attack NUI
const string NUI_PRC_PA_RIGHT_BUTTON_EVENT = "nui_prc_pa_right_button_event";
// Bind for Text of the Power Attack NUI saying what the current Power Attack level is
const string NUI_PRC_PA_TEXT_BIND = "nui_prc_pa_text_bind";
// Left Button Enabled Bind for Power Attack NUI
const string NUI_PRC_PA_LEFT_BUTTON_ENABLED_BIND = "leftButtonEnabled";
// Right Button Enabled Bind for Power Attack NUI
const string NUI_PRC_PA_RIGHT_BUTTON_ENABLED_BIND = "rightButtonEnabled";

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,98 @@
//::///////////////////////////////////////////////
//:: PRC Spellbook Description NUI
//:: prc_nui_sbd_inc
//:://////////////////////////////////////////////
/*
This is the view for the Spell Description NUI
*/
//:://////////////////////////////////////////////
//:: Created By: Rakiov
//:: Created On: 29.05.2005
//:://////////////////////////////////////////////
#include "nw_inc_nui"
#include "prc_nui_consts"
#include "inc_2dacache"
//
// CreateSpellDescriptionNUI
// Creates a Spell Description NUI mimicing the description GUI of NWN
//
// Arguments:
// oPlayer:Object the player object
// featID:int the FeatID
// spellId:int the SpellID
// realSpellId:int the RealSpellID
//
void CreateSpellDescriptionNUI(object oPlayer, int featID, int spellId=0, int realSpellId=0);
void CreateSpellDescriptionNUI(object oPlayer, int featID, int spellId=0, int realSpellId=0)
{
// look for existing window and destroy
int nPreviousToken = NuiFindWindow(OBJECT_SELF, NUI_SPELL_DESCRIPTION_WINDOW_ID);
if(nPreviousToken != 0)
{
NuiDestroy(OBJECT_SELF, nPreviousToken);
}
// in order of accuracy for names it goes RealSpellID > SpellID > FeatID
string spellName;
if (realSpellId)
spellName = GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", realSpellId)));
else if (spellId)
spellName = GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", spellId)));
else
spellName = GetStringByStrRef(StringToInt(Get2DACache("feat", "FEAT", featID)));
// Descriptions and Icons are accuratly stored on the feat
string spellDesc = GetStringByStrRef(StringToInt(Get2DACache("feat", "DESCRIPTION", featID)));
string spellIcon = Get2DACache("feat", "ICON", featID);
json jRoot = JsonArray();
json jGroup = JsonArray();
json jRow = JsonArray();
json jImage = NuiImage(JsonString(spellIcon), JsonInt(NUI_ASPECT_EXACT), JsonInt(NUI_HALIGN_LEFT), JsonInt(NUI_VALIGN_TOP));
jImage = NuiWidth(jImage, 32.0f);
jRow = JsonArrayInsert(jRow, jImage);
jRow = NuiCol(jRow);
jGroup = JsonArrayInsert(jGroup, jRow);
jRow = JsonArray();
json jText = NuiText(JsonString(spellDesc), FALSE, NUI_SCROLLBARS_AUTO);
jRow = JsonArrayInsert(jRow, jText);
jRow = NuiCol(jRow);
jGroup = JsonArrayInsert(jGroup, jRow);
jGroup = NuiRow(jGroup);
jGroup = NuiGroup(jGroup, TRUE, NUI_SCROLLBARS_NONE);
jRoot = JsonArrayInsert(jRoot, jGroup);
jRow = JsonArray();
jRow = JsonArrayInsert(jRow, NuiSpacer());
json jButton = NuiId(NuiButton(JsonString("OK")), NUI_SPELL_DESCRIPTION_OK_BUTTON);
jButton = NuiWidth(jButton, 175.0f);
jButton = NuiHeight(jButton, 48.0f);
jRow = JsonArrayInsert(jRow, jButton);
jRow = NuiRow(jRow);
jRoot = JsonArrayInsert(jRoot, jRow);
jRoot = NuiCol(jRoot);
// This is the main window with jRoot as the main pane. It includes titles and parameters (more on those later)
json nui = NuiWindow(jRoot, JsonString(spellName), NuiBind("geometry"), NuiBind("resizable"), JsonBool(FALSE), NuiBind("closable"), NuiBind("transparent"), NuiBind("border"));
// finally create it and it'll return us a non-zero token.
int nToken = NuiCreate(oPlayer, nui, NUI_SPELL_DESCRIPTION_WINDOW_ID);
// get the geometry of the window in case we opened this before and have a
// preference for location
json geometry = NuiRect(893.0f,346.0f, 426.0f, 446.0f);
// Set the binds to their default values
NuiSetBind(oPlayer, nToken, "geometry", geometry);
NuiSetBind(oPlayer, nToken, "resizable", JsonBool(FALSE));
NuiSetBind(oPlayer, nToken, "closable", JsonBool(FALSE));
NuiSetBind(oPlayer, nToken, "transparent", JsonBool(FALSE));
NuiSetBind(oPlayer, nToken, "border", JsonBool(TRUE));
}

View File

@ -1,6 +1,6 @@
//::///////////////////////////////////////////////
//:: String Util
//:: hp_string_util
//:: prc_string_inc
//:://////////////////////////////////////////////
/*
A util class for providing useful string functions.
@ -10,6 +10,8 @@
//:: Created On: 22.05.2005
//:://////////////////////////////////////////////
#include "inc_utility"
//
// StringSplit
// Takes a string and splits it by " " into a json list of strings
@ -29,27 +31,13 @@
//
json StringSplit(string input);
//
// TrimString
// Takes a string and trims any leading whitespace characters
// i.e. " this is a test" returns
// "this is a test"
//
// Parameters:
// input string the input string to trim
//
// Returns:
// string the trimmed string
//
string TrimString(string input);
json StringSplit(string input)
{
json retValue = JsonArray();
string subString = "";
//trim any whitespace characters first
string currString = TrimString(input);
string currString = PRCTrimString(input);
// loop until we process the whole string
while(currString != "")
@ -84,16 +72,3 @@ json StringSplit(string input)
return retValue;
}
string TrimString(string input)
{
string retValue = input;
// while the string is not empty and we are looking at a whitespace, pop it.
while(retValue != "" && GetStringLeft(retValue, 1) == " ")
{
retValue = GetStringRight(retValue, GetStringLength(retValue)-1);
}
return retValue;
}

View File

@ -115,6 +115,7 @@ void PRCFeat_Equip(object oPC, object oSkin, int iEquip)
SetCompositeAttackBonus(oPC, "BrutalThrow", 0);
}
}
//:: Charming the Arrow - Apply bonus if Charisma > Dexterity for bows & crossbows
if (GetHasFeat(FEAT_CHARMING_THE_ARROW, oPC))
{
@ -134,6 +135,11 @@ void PRCFeat_Equip(object oPC, object oSkin, int iEquip)
SetCompositeAttackBonus(oPC, "CharmingTheArrow", 0);
}
}
else
{
// Remove the bonus if Charisma is not greater
SetCompositeAttackBonus(oPC, "CharmingTheArrow", 0);
}
}
}
}

View File

@ -1,27 +1,18 @@
//::///////////////////////////////////////////////
//:: Power Attack Events
//:: hp_pa_events
//:: Power Attack NUI Events
//:: prc_nui_pa_event
//:://////////////////////////////////////////////
/*
The NUI events for the Power Attack NUI Window
A class that handles the event firings from
the Power Attack NUI
*/
//:://////////////////////////////////////////////
//:: Created By: Rakiov
//:: Created On: 22.05.2005
//:: Created On: 24.05.2005
//:://////////////////////////////////////////////
#include "nw_inc_nui"
#include "hp_pa_view"
#include "prc_nui_consts"
//
// SetWindowGeometry
// Sets the window geometry for the Power Attack NUI to the player
// so it can be remembered when opened next time
//
// Arguments:
// oPlayer object the player that owns the window
// nToken int the windowId
//
void SetWindowGeometry(object oPlayer, int nToken);
void main()
@ -31,14 +22,7 @@ void main()
string sEvent = NuiGetEventType();
string sElement = NuiGetEventElement();
int nIndex = NuiGetEventArrayIndex();
string sWindowId = NuiGetWindowId(oPlayer, nToken);
//HandleWindowInspectorEvent(); // used to debug
if(sWindowId != NUI_PRC_POWER_ATTACK_WINDOW)
{
return;
}
// Get the current Power Attack value for player
int currentPAAmount = GetLocalInt(oPlayer, "PRC_PowerAttack_Level");
@ -56,6 +40,9 @@ void main()
return;
}
// set the geometry to the player since we only get mouseup events on button presses :(
SetWindowGeometry(oPlayer, nToken);
int currentBAB = GetBaseAttackBonus(oPlayer);
if (sElement == NUI_PRC_PA_LEFT_BUTTON_EVENT)
@ -64,7 +51,7 @@ void main()
if(currentPAAmount-1 >= 0)
{
SetLocalInt(oPlayer, "PRC_PowerAttack_Level", currentPAAmount-1);
ExecuteScript("hp_pa_script", oPlayer);
ExecuteScript("prc_nui_pa_trggr", oPlayer);
// if decreased pwoer attack is lower than the current BAB then allow
// the incrase button
if(currentPAAmount-1 <= currentBAB)
@ -86,7 +73,7 @@ void main()
if(currentPAAmount+1 <= currentBAB)
{
SetLocalInt(oPlayer, "PRC_PowerAttack_Level", currentPAAmount+1);
ExecuteScript("hp_pa_script", oPlayer);
ExecuteScript("prc_nui_pa_trggr", oPlayer);
// if the increased power attack amount is greater than 0 then enable
// the decrease button
if (currentPAAmount+1 > 0)
@ -103,13 +90,11 @@ void main()
currentPAAmount = GetLocalInt(oPlayer, "PRC_PowerAttack_Level");
// set the geometry to the player since we only get mouseup events on button presses :(
NuiSetBind(oPlayer, nToken, NUI_PRC_PA_TEXT_BIND, JsonString(IntToString(currentPAAmount)));
SetWindowGeometry(oPlayer, nToken);
}
void SetWindowGeometry(object oPlayer, int nToken)
{
json dimensions = NuiGetBind(oPlayer, nToken, "geometry");
SetLocalJson(oPlayer, NUI_PRC_PA_GEOMETRY_VAR, dimensions);
}
}

View File

@ -1,6 +1,6 @@
//::///////////////////////////////////////////////
//:: Power Attack Script
//:: hp_pa_script
//:: prc_nui_pa_trggr
//:://////////////////////////////////////////////
/*
A script that sets the power attack on a player based on the amount
@ -12,8 +12,18 @@
//:://////////////////////////////////////////////
#include "prc_spell_const"
#include "inc_2dacache"
void SetPowerAttack();
//
// ExecutePowerAttackChange
// Takes a Power Attack SpellID and checks to see what it's spell2da Master is.
// it then takes the Master's FeatID and the spell's spellId and does UseActionFeat
// to execute the power attack change.
//
// Arguments:
// spellId:int the Power attack spell Id this is being executed for
//
void ExecutePowerAttackChange(int spellId);
//
// Sets the power attack for a player, if the player has power attack and the
@ -27,43 +37,25 @@ void SetPowerAttack();
//
void main()
{
ExecuteScript("prc_nui_pwrattk");
/* int amount = GetLocalInt(OBJECT_SELF, "PRC_PowerAttack_Level");
int amount = GetLocalInt(OBJECT_SELF, "PRC_PowerAttack_Level");
int prevPowerAttack5 = GetLocalInt(OBJECT_SELF, "prevPowerAttack5");
int prevPowerAttack1 = GetLocalInt(OBJECT_SELF, "prevPowerAttack1");
int powerAttack5Amount = amount / 5;
int powerAttack1Amount = amount % 5;
// Current actions can cause this to not run right away, so clear the queue
// and force this to happen.
ClearAllActions();
//sets the 5 values for Power attack ranging from 0,5,10,15,20 respectivly
if (prevPowerAttack5 != powerAttack5Amount)
{
if (powerAttack5Amount == 0) // Power Attack 0
{
ActionDoCommand(ActionCastSpellAtObject(SPELL_POWER_ATTACK6, OBJECT_SELF, METAMAGIC_ANY, TRUE, 0, PROJECTILE_PATH_TYPE_DEFAULT, TRUE));
}
ExecutePowerAttackChange(SPELL_POWER_ATTACK6);
if (powerAttack5Amount == 1) // Power Attack 5
{
ActionDoCommand(ActionCastSpellAtObject(SPELL_POWER_ATTACK7, OBJECT_SELF, METAMAGIC_ANY, TRUE, 0, PROJECTILE_PATH_TYPE_DEFAULT, TRUE));
}
ExecutePowerAttackChange(SPELL_POWER_ATTACK7);
if (powerAttack5Amount == 2) // Power Attack 10
{
ActionCastSpellAtObject(SPELL_POWER_ATTACK8, OBJECT_SELF, METAMAGIC_ANY, TRUE, 0, PROJECTILE_PATH_TYPE_DEFAULT, TRUE);
}
ExecutePowerAttackChange(SPELL_POWER_ATTACK8);
if (powerAttack5Amount == 3) // Power Attack 15
{
ActionCastSpellAtObject(SPELL_POWER_ATTACK9, OBJECT_SELF, METAMAGIC_ANY, TRUE, 0, PROJECTILE_PATH_TYPE_DEFAULT, TRUE);
}
ExecutePowerAttackChange(SPELL_POWER_ATTACK9);
if (powerAttack5Amount == 4) // Power Attack 20
{
ActionCastSpellAtObject(SPELL_POWER_ATTACK10, OBJECT_SELF, METAMAGIC_ANY, TRUE, 0, PROJECTILE_PATH_TYPE_DEFAULT, TRUE);
}
ExecutePowerAttackChange(SPELL_POWER_ATTACK10);
SetLocalInt(OBJECT_SELF, "prevPowerAttack5", powerAttack5Amount);
}
@ -71,26 +63,32 @@ void main()
{
//sets the 1 values for Power attack ranging from 0,1,2,3,4 respectivly
if (powerAttack1Amount == 0) // Power Attack 0
{
ActionDoCommand(ActionCastSpellAtObject(SPELL_POWER_ATTACK1, OBJECT_SELF, METAMAGIC_ANY, TRUE, 0, PROJECTILE_PATH_TYPE_DEFAULT, TRUE));
}
ExecutePowerAttackChange(SPELL_POWER_ATTACK1);
if (powerAttack1Amount == 1) // Power Attack 1
{
ActionDoCommand(ActionCastSpellAtObject(SPELL_POWER_ATTACK2, OBJECT_SELF, METAMAGIC_ANY, TRUE, 0, PROJECTILE_PATH_TYPE_DEFAULT, TRUE));
}
ExecutePowerAttackChange(SPELL_POWER_ATTACK2);
if (powerAttack1Amount == 2) // Power Attack 2
{
ActionCastSpellAtObject(SPELL_POWER_ATTACK3, OBJECT_SELF, METAMAGIC_ANY, TRUE, 0, PROJECTILE_PATH_TYPE_DEFAULT, TRUE);
}
ExecutePowerAttackChange(SPELL_POWER_ATTACK3);
if (powerAttack1Amount == 3) // Power Attack 3
{
ActionCastSpellAtObject(SPELL_POWER_ATTACK4, OBJECT_SELF, METAMAGIC_ANY, TRUE, 0, PROJECTILE_PATH_TYPE_DEFAULT, TRUE);
}
ExecutePowerAttackChange(SPELL_POWER_ATTACK4);
if (powerAttack1Amount == 4) // Power Attack 4
{
ActionCastSpellAtObject(SPELL_POWER_ATTACK5, OBJECT_SELF, METAMAGIC_ANY, TRUE, 0, PROJECTILE_PATH_TYPE_DEFAULT, TRUE);
}
ExecutePowerAttackChange(SPELL_POWER_ATTACK5);
SetLocalInt(OBJECT_SELF, "prevPowerAttack1", powerAttack1Amount);
}
*/
}
}
void ExecutePowerAttackChange(int spellId)
{
int masterSpellId = StringToInt(Get2DACache("spells", "Master", spellId));
int featID;
int subSpellId = 0;
if (masterSpellId)
{
featID = StringToInt(Get2DACache("spells", "FeatID", masterSpellId));
subSpellId = spellId;
}
else
featID = StringToInt(Get2DACache("spells", "FeatID", spellId));
ActionUseFeat(featID, OBJECT_SELF, subSpellId);
}

View File

@ -12,44 +12,16 @@
//:://////////////////////////////////////////////
#include "nw_inc_nui"
#include "prc_nui_consts"
// #include "nw_inc_nui_insp" // used to debug
//
// NuiPRCPowerAttackView
// The NUI window for the Power Attack interface, running this function
// creates the window itself
//
// Arguments:
// oPlayer object the player referenced for the NUI
//
void NuiPRCPowerAttackView(object oPlayer);
// The Window ID
const string NUI_PRC_POWER_ATTACK_WINDOW = "nui_prc_power_attack_window";
// LocalVar for the geometry of the window
const string NUI_PRC_PA_GEOMETRY_VAR = "paNuiGeometry";
// Event For Left Button
const string NUI_PRC_PA_LEFT_BUTTON_EVENT = "nui_prc_pa_left_button_event";
// Event For Right Button
const string NUI_PRC_PA_RIGHT_BUTTON_EVENT = "nui_prc_pa_right_button_event";
// Bind for Text
const string NUI_PRC_PA_TEXT_BIND = "nui_prc_pa_text_bind";
// Left Button Enabled Bind
const string NUI_PRC_PA_LEFT_BUTTON_ENABLED_BIND = "leftButtonEnabled";
// Right Button Enabled Bind
const string NUI_PRC_PA_RIGHT_BUTTON_ENABLED_BIND = "rightButtonEnabled";
void NuiPRCPowerAttackView(object oPlayer)
void main()
{
// First we look for any previous windows, if found (ie, non-zero) we destory them so we can start fresh.
int nPreviousToken = NuiFindWindow(oPlayer, NUI_PRC_POWER_ATTACK_WINDOW);
int nPreviousToken = NuiFindWindow(OBJECT_SELF, NUI_PRC_POWER_ATTACK_WINDOW);
if (nPreviousToken != 0)
{
NuiDestroy(oPlayer, nPreviousToken);
NuiDestroy(OBJECT_SELF, nPreviousToken);
}
// base element for NUI
@ -88,11 +60,11 @@ void NuiPRCPowerAttackView(object oPlayer)
// Create the window and set binds for parameters in case we want to change them later
json nui = NuiWindow(jRoot, JsonString("Power Attack"), NuiBind("geometry"), NuiBind("resizable"), NuiBind("collapsed"), NuiBind("closable"), NuiBind("transparent"), NuiBind("border"));
int nToken = NuiCreate(oPlayer, nui, NUI_PRC_POWER_ATTACK_WINDOW);
int nToken = NuiCreate(OBJECT_SELF, nui, NUI_PRC_POWER_ATTACK_WINDOW);
// get the geometry of the window in case we opened this before and have a
// preference for location
json geometry = GetLocalJson(oPlayer, NUI_PRC_PA_GEOMETRY_VAR);
json geometry = GetLocalJson(OBJECT_SELF, NUI_PRC_PA_GEOMETRY_VAR);
// Default to put this near the middle and let the person adjust its location
if (geometry == JsonNull())
@ -101,15 +73,15 @@ void NuiPRCPowerAttackView(object oPlayer)
}
// Set the binds to their default values
NuiSetBind(oPlayer, nToken, "geometry", geometry);
NuiSetBind(oPlayer, nToken, "collapsed", JsonBool(FALSE));
NuiSetBind(oPlayer, nToken, "resizable", JsonBool(FALSE));
NuiSetBind(oPlayer, nToken, "closable", JsonBool(TRUE));
NuiSetBind(oPlayer, nToken, "transparent", JsonBool(TRUE));
NuiSetBind(oPlayer, nToken, "border", JsonBool(FALSE));
NuiSetBind(OBJECT_SELF, nToken, "geometry", geometry);
NuiSetBind(OBJECT_SELF, nToken, "collapsed", JsonBool(FALSE));
NuiSetBind(OBJECT_SELF, nToken, "resizable", JsonBool(FALSE));
NuiSetBind(OBJECT_SELF, nToken, "closable", JsonBool(TRUE));
NuiSetBind(OBJECT_SELF, nToken, "transparent", JsonBool(TRUE));
NuiSetBind(OBJECT_SELF, nToken, "border", JsonBool(FALSE));
int paAmount = GetLocalInt(oPlayer, "PRC_PowerAttack_Level");
int currentBAB = GetBaseAttackBonus(oPlayer);
int paAmount = GetLocalInt(OBJECT_SELF, "PRC_PowerAttack_Level");
int currentBAB = GetBaseAttackBonus(OBJECT_SELF);
// if we reach the left or right limits of the power attack, then disable the buttons
json leftButtonEnabled = (paAmount == 0) ? JsonBool(FALSE) : JsonBool(TRUE);
@ -117,10 +89,10 @@ void NuiPRCPowerAttackView(object oPlayer)
// set the current PA amount to the window
NuiSetBind(oPlayer, nToken, NUI_PRC_PA_TEXT_BIND, JsonString(IntToString(paAmount)));
NuiSetBind(OBJECT_SELF, nToken, NUI_PRC_PA_TEXT_BIND, JsonString(IntToString(paAmount)));
NuiSetBind(oPlayer, nToken, NUI_PRC_PA_LEFT_BUTTON_ENABLED_BIND, leftButtonEnabled);
NuiSetBind(oPlayer, nToken, NUI_PRC_PA_RIGHT_BUTTON_ENABLED_BIND, rightButtonEnabled);
}
NuiSetBind(OBJECT_SELF, nToken, NUI_PRC_PA_LEFT_BUTTON_ENABLED_BIND, leftButtonEnabled);
NuiSetBind(OBJECT_SELF, nToken, NUI_PRC_PA_RIGHT_BUTTON_ENABLED_BIND, rightButtonEnabled);
}

View File

@ -0,0 +1,372 @@
//::///////////////////////////////////////////////
//:: PRC Spellbook NUI Events
//:: prc_nui_sb_event
//:://////////////////////////////////////////////
/*
This is the event script for the PRC Spellbook NUI that handles button presses
and the like
*/
//:://////////////////////////////////////////////
//:: Created By: Rakiov
//:: Created On: 24.05.2005
//:://////////////////////////////////////////////
#include "prc_nui_consts"
#include "prc_nui_sb_inc"
#include "prc_nui_sbd_inc"
//
// SetWindowGeometry
// Saves the window geometry of the NUI Spellbook to the player so next time it
// renders it remembers where it was
//
// Arguments:
// oPlayer:object player tied to NUI
// nToken:int the NUI Spellbook window
//
void SetWindowGeometry(object oPlayer, int nToken);
//
// DetermineRangeForSpell
// Takes the string range from the spells.2da of a spell and converts it to
// the appropriate float range for the manual targetting mode
//
// Arguments:
// sRange:string the string range of the spell (P,T,S,M,L)
//
// Returns:
// float The flaot representation of the sRange provided
//
float DetermineRangeForSpell(string sRange);
//
// DetermineShapeForSpell
// Takes the string shape from the spells.2da of a spell and converts it to
// the int representation of the spell's shape. This is case sensitive and
// has to be in all UpperCase
//
// Arguments:
// shape:string the string shape of the spell (SPHERE,CONE, etc.)
//
// Returns:
// int the int representation of the shape provided
//
int DetermineShapeForSpell(string shape);
//
// DetermineTargetType
// Takes the string (actually hex) target type from the spells.2da of a spell and convers it to
// the int representation of the spell's target type. How this works is a bit unintuitive but
// it converts the string hex to a int, then subtracts it by the powers of 2. Each power represents
// the target the spell is allowed to be used on as all the ints are bitwise added together
//
// Arguments:
// targetType:string the hex value of the target type as a string.
//
// Returns:
// int the bitwise int representation of the targetType
int DetermineTargetType(string targetType);
void main()
{
object oPlayer = NuiGetEventPlayer();
int nToken = NuiGetEventWindow();
string sEvent = NuiGetEventType();
string sElement = NuiGetEventElement();
string sWindowId = NuiGetWindowId(oPlayer, nToken);
// if this was the Spell Description NUI and the OK button was clicked
// then we close the window.
if (sWindowId == NUI_SPELL_DESCRIPTION_WINDOW_ID)
{
if (sElement == NUI_SPELL_DESCRIPTION_OK_BUTTON)
NuiDestroy(oPlayer, nToken);
return;
}
// if the window is closed, save the geometry
if (sEvent == "close")
{
SetWindowGeometry(oPlayer, nToken);
return;
}
// Not a mouseup event, nothing to do.
if (sEvent != "mouseup")
{
return;
}
// Save the geometry first
SetWindowGeometry(oPlayer, nToken);
int spellId;
int featId;
int realSpellId;
// Checks to see if the event button has the class button baseId
// Then replaces the baseId with nothing and converts the end of the string to a int
// representing the ClassID gathered. (i.e. "test_123" gets converted to 123)
if (FindSubString(sElement, PRC_SPELLBOOK_NUI_CLASS_BUTTON_BASEID) >= 0)
{
int classId = StringToInt(RegExpReplace(PRC_SPELLBOOK_NUI_CLASS_BUTTON_BASEID, sElement, ""));
SetLocalInt(oPlayer, PRC_SPELLBOOK_SELECTED_CLASSID_VAR, classId);
ExecuteScript("prc_nui_sb_view", oPlayer);
return;
}
// Checks to see if the event button has the circle button baseId
// Then replaces the baseId with nothing and converts the end of the string to a int
// representing the circle number gathered. (i.e. "test_5" gets converted to 5)
if (FindSubString(sElement, PRC_SPELLBOOK_NUI_CIRCLE_BUTTON_BASEID) >= 0)
{
int circle = StringToInt(RegExpReplace(PRC_SPELLBOOK_NUI_CIRCLE_BUTTON_BASEID, sElement, ""));
SetLocalInt(oPlayer, PRC_SPELLBOOK_SELECTED_CIRCLE_VAR, circle);
ExecuteScript("prc_nui_sb_view", oPlayer);
return;
}
// Checks to see if the event button has the meta button baseId
// Then replaces the baseId with nothing and converts the end of the string to a int
// representing the SpellID gathered. (i.e. "test_123" gets converted to 123)
if (FindSubString(sElement, PRC_SPELLBOOK_NUI_META_BUTTON_BASEID) >= 0)
{
spellId = StringToInt(RegExpReplace(PRC_SPELLBOOK_NUI_META_BUTTON_BASEID, sElement, ""));
int masterSpellId = StringToInt(Get2DACache("spells", "Master", spellId));
if (masterSpellId)
{
SetLocalInt(oPlayer, NUI_SPELLBOOK_SELECTED_SUBSPELL_SPELLID_VAR, spellId);
featId = StringToInt(Get2DACache("spells", "FeatID", masterSpellId));
}
else
featId = StringToInt(Get2DACache("spells", "FeatID", spellId));
}
// Checks to see if the event button has the class button baseId
// Then replaces the baseId with nothing and converts the end of the string to a int
// representing the SpellbookID gathered. (i.e. "test_123" gets converted to 123)
if (FindSubString(sElement, PRC_SPELLBOOK_NUI_SPELL_BUTTON_BASEID) >= 0)
{
int spellbookId = StringToInt(RegExpReplace(PRC_SPELLBOOK_NUI_SPELL_BUTTON_BASEID, sElement, ""));
int classId = GetLocalInt(oPlayer, PRC_SPELLBOOK_SELECTED_CLASSID_VAR);
// special case for binders, since they don't have a spell 2da of their own.
if (classId == CLASS_TYPE_BINDER)
{
json binderDict = GetBinderSpellToFeatDictionary(oPlayer);
spellId = spellbookId;
featId = JsonGetInt(JsonObjectGet(binderDict, IntToString(spellId)));
int masterSpellId = StringToInt(Get2DACache("spells", "Master", spellId));
if (masterSpellId)
{
SetLocalInt(oPlayer, NUI_SPELLBOOK_SELECTED_SUBSPELL_SPELLID_VAR, spellId);
featId = StringToInt(Get2DACache("spells", "FeatID", masterSpellId));
}
else
featId = StringToInt(Get2DACache("spells", "FeatID", spellId));
}
else
{
string sFile = GetClassSpellbookFile(classId);
spellId = StringToInt(Get2DACache(sFile, "SpellID", spellbookId));
realSpellId = StringToInt(Get2DACache(sFile, "RealSpellID", spellbookId));
int masterSpellId = StringToInt(Get2DACache("spells", "Master", spellId));
// If this spell is part of a radial we need to send the master featID
// to be used along with the radial spellId
if (masterSpellId)
{
SetLocalInt(oPlayer, NUI_SPELLBOOK_SELECTED_SUBSPELL_SPELLID_VAR, spellId);
spellId = masterSpellId;
}
featId = StringToInt(Get2DACache("spells", "FeatID", spellId));
}
}
json jPayload = NuiGetEventPayload();
int nButton = JsonGetInt(JsonObjectGet(jPayload, "mouse_btn"));
// If right click, open the Spell Description NUI
if (nButton == NUI_PAYLOAD_BUTTON_RIGHT_CLICK)
{
CreateSpellDescriptionNUI(oPlayer, featId, spellId, realSpellId);
return;
}
// If left click, operate normally
if (nButton == NUI_PAYLOAD_BUTTON_LEFT_CLICK)
{
// We use the spell's FeatID to do actions, and we set the OnTarget action
// to PRC_NUI_SPELLBOOK so the handler knows what the action is being done
SetLocalInt(oPlayer, NUI_SPELLBOOK_SELECTED_FEATID_VAR, featId);
string sRange = GetStringUpperCase(Get2DACache("spells", "Range", spellId));
// If its a personal spell/feat than use it directly on the player.
if (sRange == "P")
{
SetLocalInt(oPlayer, NUI_SPELLBOOK_ON_TARGET_IS_PERSONAL_FEAT, 1);
ExecuteScript("prc_nui_sb_trggr", oPlayer);
}
// otherwise enter targetting mode
else
{
SetLocalString(oPlayer, NUI_SPELLBOOK_ON_TARGET_ACTION_VAR, "PRC_NUI_SPELLBOOK");
// These gather the targetting information for the TargetingMode functions
float fRange = DetermineRangeForSpell(sRange);
string sShape = GetStringUpperCase(Get2DACache("spells", "TargetShape", spellId));
int iShape = DetermineShapeForSpell(sShape);
float fSizeX = StringToFloat(Get2DACache("spells", "TargetSizeX", spellId));
float fSizeY = StringToFloat(Get2DACache("spells", "TargetSizeY", spellId));
int nFlags = StringToInt(Get2DACache("spells", "TargetFlags", spellId));
string sTargetType = Get2DACache("spells", "TargetType", spellId);
int iTargetType = DetermineTargetType(sTargetType);
SetEnterTargetingModeData(oPlayer, iShape, fSizeX, fSizeY, nFlags, fRange);
EnterTargetingMode(oPlayer, iTargetType);
}
}
}
void SetWindowGeometry(object oPlayer, int nToken)
{
json dimensions = NuiGetBind(oPlayer, nToken, "geometry");
SetLocalJson(oPlayer, PRC_SPELLBOOK_NUI_GEOMETRY_VAR, dimensions);
}
int DetermineShapeForSpell(string shape)
{
if (shape == "CONE")
{
return SPELL_TARGETING_SHAPE_CONE;
}
if (shape == "SPHERE")
{
return SPELL_TARGETING_SHAPE_SPHERE;
}
if (shape == "RECTANGLE")
{
return SPELL_TARGETING_SHAPE_RECT;
}
if (shape == "HSPHERE")
{
return SPELL_TARGETING_SHAPE_HSPHERE;
}
return SPELL_TARGETING_SHAPE_NONE;
}
float DetermineRangeForSpell(string sRange)
{
//Personal
if (sRange == "P")
{
return StringToFloat(Get2DACache("ranges", "PrimaryRange", 0));
}
//Touch
if(sRange == "T")
{
return StringToFloat(Get2DACache("ranges", "PrimaryRange", 1));
}
//Short
if(sRange == "S")
{
return StringToFloat(Get2DACache("ranges", "PrimaryRange", 2));
}
//Medium
if(sRange == "M")
{
return StringToFloat(Get2DACache("ranges", "PrimaryRange", 3));
}
//Long
if(sRange == "L")
{
return StringToFloat(Get2DACache("ranges", "PrimaryRange", 4));
}
return 0.0;
}
int DetermineTargetType(string targetType)
{
int retValue = -1;
int iTargetType = HexToInt(targetType);
if (iTargetType - 64 >= 0)
{
if (retValue == -1)
{
retValue = OBJECT_TYPE_TRIGGER;
}
else
{
retValue = retValue | OBJECT_TYPE_TRIGGER;
}
iTargetType -= 64;
}
if (iTargetType - 32 >= 0)
{
if (retValue == -1)
{
retValue = OBJECT_TYPE_PLACEABLE;
}
else
{
retValue = retValue | OBJECT_TYPE_PLACEABLE;
}
iTargetType -= 32;
}
if (iTargetType - 16 >= 0)
{
if (retValue == -1)
{
retValue = OBJECT_TYPE_DOOR;
}
else
{
retValue = retValue | OBJECT_TYPE_DOOR;
}
iTargetType -= 16;
}
if (iTargetType - 8 >= 0)
{
if (retValue == -1)
{
retValue = OBJECT_TYPE_ITEM;
}
else
{
retValue = retValue | OBJECT_TYPE_ITEM;
}
iTargetType -= 8;
}
if (iTargetType - 4 >= 0)
{
if (retValue == -1)
{
retValue = OBJECT_TYPE_TILE;
}
else
{
retValue = retValue | OBJECT_TYPE_TILE;
}
iTargetType -= 4;
}
if (iTargetType - 2 >= 0 || iTargetType - 1 >= 0)
{
if (retValue == -1)
{
retValue = OBJECT_TYPE_CREATURE;
}
else
{
retValue = retValue | OBJECT_TYPE_CREATURE;
}
iTargetType = 0;
}
return retValue;
}

View File

@ -0,0 +1,50 @@
//::///////////////////////////////////////////////
//:: PRC Spellbook OnTrigger Script
//:: prc_nui_sb_trggr
//:://////////////////////////////////////////////
/*
This is the OnTarget action script used to make spell attacks with the
selected spell from the PRC Spellbook NUI
*/
//:://////////////////////////////////////////////
//:: Created By: Rakiov
//:: Created On: 24.05.2005
//:://////////////////////////////////////////////
#include "prc_nui_consts"
#include "inc_newspellbook"
void main()
{
// Get the selected PRC spell we are going to cast
int featId = GetLocalInt(OBJECT_SELF, NUI_SPELLBOOK_SELECTED_FEATID_VAR);
int isPersonalFeat = GetLocalInt(OBJECT_SELF, NUI_SPELLBOOK_ON_TARGET_IS_PERSONAL_FEAT);
// if this is a personal feat then this was called directly since we never entered
// targetting and this should be applied immediatly to the executing player.
if (isPersonalFeat)
{
ActionUseFeat(featId);
// we want to remove this just in case of weird cases.
DeleteLocalInt(OBJECT_SELF, NUI_SPELLBOOK_ON_TARGET_IS_PERSONAL_FEAT);
}
else
{
// if the spell has a master feat this is it. This will return 0 if not set.
int subSpellID = GetLocalInt(OBJECT_SELF, NUI_SPELLBOOK_SELECTED_SUBSPELL_SPELLID_VAR);
// Get the target and location data we are casting at
object oTarget = GetLocalObject(OBJECT_SELF, "TARGETING_OBJECT");
location spellLocation = GetLocalLocation(OBJECT_SELF, "TARGETING_POSITION");
// if the object is valid and isn't empty then cast spell at target
if (GetIsObjectValid(oTarget) && GetObjectType(oTarget))
spellLocation = LOCATION_INVALID;
// otherwise if the area is a valid location to cast at, cast at location
else if (GetIsObjectValid(GetAreaFromLocation(spellLocation)))
oTarget = OBJECT_INVALID;
ActionUseFeat(featId, oTarget, subSpellID, spellLocation);
}
}

View File

@ -0,0 +1,519 @@
//::///////////////////////////////////////////////
//:: PRC Spellbook NUI View
//:: prc_nui_sb_view
//:://////////////////////////////////////////////
/*
This is the NUI view for the PRC Spellbook
*/
//:://////////////////////////////////////////////
//:: Created By: Rakiov
//:: Created On: 24.05.2005
//:://////////////////////////////////////////////
#include "nw_inc_nui"
//#include "nw_inc_nui_insp"
#include "prc_nui_sb_inc"
#include "prc_nui_consts"
//
// CreateSpellBookClassButtons
// Gets the list of classes that have Spells, "Spells" and /Spells/ the player has
// that are allowed to use the NUI Spellbook.
//
// Returns:
// json NuiRow the list of class buttons allowed to use the NUI Spellbook
//
json CreateSpellBookClassButtons();
//
// CreateSpellbookSpellButtons
// Creates the NUI buttons for the spells a player knows in the specified class
// and circle provided.
//
// Arguments:
// nClass int the class currently being checked for spells
// circle int the circle level of the spells we want to check for
//
// Returns:
// json:Array<NuiRow> the list of NuiRows of spells we have memorized
//
json CreateSpellbookSpellButtons(int nClass, int circle);
//
// CreateSpellbookSpellButtons
// Creates the buttons for what circles the class is allowed to cast in
// ranging from Cantrips to 9th circle or equivalent for classes that don't have
// a concept of spell circles, like ToB and Psionics
//
// Arguments:
// nClass int the class id this is being constructed for.
//
// Returns:
// json NuiRow the level at which the caster can or does know as buttons
//
json CreateSpellbookCircleButtons(int nClass);
//
// CreateMetaMagicFeatButtons
// Takes a class and creates the appropriate meta feat buttons it can use or
// possibly use.
//
// Arguments:
// nClass:int the ClassID we are checking
//
// Returns:
// json:Array<NuiRow> the list of meta feats the class can use. Can return an
// empty JsonArray if no meta feats are allowed for the class.
//
json CreateMetaMagicFeatButtons(int nClass);
//
// CreateMetaFeatButtonRow
// a helper function for CreateMetaMagicFeatButtons that takes a list of featIds
// and creates buttons for them.
//
// Arguments:
// featList:json:Array<int> the list of featIDs to render
//
// Returns:
// json:Array<NuiButtons> the row of buttons rendered for the FeatIDs.
//
json CreateMetaFeatButtonRow(json spellList);
//
// GetSpellLevelIcon
// Takes the spell circle int and gets the icon appropriate for it (i.e. 0 turns
// into "ir_cantrips"
//
// Arguments:
// spellLevel:int the spell level we want the icon for
//
// Returns:
// string the spell level icon
//
string GetSpellLevelIcon(int spellLevel);
//
// GetSpellLevelToolTip
// Gets the spell level tool tip text based on the int spell level provided (i.e.
// 0 turns into "Cantrips")
//
// Arguments:
// spellLevel:int the spell level we want the tooltip for
//
// Returns:
// string the spell level toop tip
//
string GetSpellLevelToolTip(int spellLevel);
//
// GetSpellIcon
// Gets the spell icon based off the spellId by using the FeatID instead
//
// Arguments:
// nClass:int the class Id
// spellId:int the spell Id we want the icon for
//
// Returns:
// json:String the string of the icon we want.
//
json GetSpellIcon(int spellId, int nClass=0);
void main()
{
// look for existing window and destroy
int nPreviousToken = NuiFindWindow(OBJECT_SELF, PRC_SPELLBOOK_NUI_WINDOW_ID);
if(nPreviousToken != 0)
{
NuiDestroy(OBJECT_SELF, nPreviousToken);
}
json jRoot = JsonArray();
json jRow = CreateSpellBookClassButtons();
jRoot = JsonArrayInsert(jRoot, jRow);
int selectedClassId = GetLocalInt(OBJECT_SELF, PRC_SPELLBOOK_SELECTED_CLASSID_VAR);
// GetLocalInt returns 0 if not set, which is Barb class which conveniently doesn't have spells :)
// if there was no selected class then there is nothing to render
if (selectedClassId != CLASS_TYPE_BARBARIAN)
{
// create the metamagic/metapsionic/metamystery/sudden buttons if applicable
// suddens are on their own row so its possible we can have 2 NuiRows in the list
jRow = CreateMetaMagicFeatButtons(selectedClassId);
int i;
for(i = 0; i < JsonGetLength(jRow); i++)
{
jRoot = JsonArrayInsert(jRoot, JsonArrayGet(jRow, i));
}
// create the spell/feat circle buttons for the class (most use 0-9, but
// ToB uses something similar that ranges from 1-9 and Invokers essentially
// go 1-4 as examples
jRow = CreateSpellbookCircleButtons(selectedClassId);
jRoot = JsonArrayInsert(jRoot, jRow);
// Get the currently selected circle's spell buttons
int currentCircle = GetLocalInt(OBJECT_SELF, PRC_SPELLBOOK_SELECTED_CIRCLE_VAR);
jRow = CreateSpellbookSpellButtons(selectedClassId, currentCircle);
// since we limit how many buttons a row can have here we need to add
// multiple NuiRows if they exist
for(i = 0; i < JsonGetLength(jRow); i++)
{
jRoot = JsonArrayInsert(jRoot, JsonArrayGet(jRow, i));
}
}
jRoot = NuiCol(jRoot);
string title = "PRC Spellbook";
if (selectedClassId != CLASS_TYPE_BARBARIAN)
title = title + ": " + GetStringByStrRef(StringToInt(Get2DACache("classes", "Name", selectedClassId)));
// This is the main window with jRoot as the main pane. It includes titles and parameters (more on those later)
json nui = NuiWindow(jRoot, JsonString(title), NuiBind("geometry"), NuiBind("resizable"), NuiBind("collapsed"), NuiBind("closable"), NuiBind("transparent"), NuiBind("border"));
// finally create it and it'll return us a non-zero token.
int nToken = NuiCreate(OBJECT_SELF, nui, PRC_SPELLBOOK_NUI_WINDOW_ID);
// get the geometry of the window in case we opened this before and have a
// preference for location
json geometry = GetLocalJson(OBJECT_SELF, PRC_SPELLBOOK_NUI_GEOMETRY_VAR);
// Default to put this near the middle and let the person adjust its location
if (geometry == JsonNull())
{
geometry = NuiRect(893.0f,346.0f, 489.0f, 351.0f);
}
// Set the binds to their default values
NuiSetBind(OBJECT_SELF, nToken, "geometry", geometry);
NuiSetBind(OBJECT_SELF, nToken, "collapsed", JsonBool(FALSE));
NuiSetBind(OBJECT_SELF, nToken, "resizable", JsonBool(FALSE));
NuiSetBind(OBJECT_SELF, nToken, "closable", JsonBool(TRUE));
NuiSetBind(OBJECT_SELF, nToken, "transparent", JsonBool(TRUE));
NuiSetBind(OBJECT_SELF, nToken, "border", JsonBool(FALSE));
}
json CreateSpellBookClassButtons()
{
json jRow = JsonArray();
// Get all the Classes that can use the NUI Spellbook
json classList = GetSupportedNUISpellbookClasses(OBJECT_SELF);
// if we have selected a class already due to re-rendering, we need to disable
// the button for it.
int selectedClassId = GetLocalInt(OBJECT_SELF, PRC_SPELLBOOK_SELECTED_CLASSID_VAR);
int i;
for (i = 0; i < JsonGetLength(classList); i++)
{
int classId = JsonGetInt(JsonArrayGet(classList, i));
// if the selected class doen't exist, automatically use the first class allowed
if (selectedClassId == 0)
{
selectedClassId = classId;
SetLocalInt(OBJECT_SELF, PRC_SPELLBOOK_SELECTED_CLASSID_VAR, selectedClassId);
}
// Get the class icon from the classes.2da
json jClassButton = NuiId(NuiButtonImage(JsonString(Get2DACache("classes", "Icon", classId))), PRC_SPELLBOOK_NUI_CLASS_BUTTON_BASEID + IntToString(classId));
jClassButton = NuiWidth(jClassButton, 32.0f);
jClassButton = NuiHeight(jClassButton, 32.0f);
// Get the class name from the classes.2da and set it to the tooltip
jClassButton = NuiTooltip(jClassButton, JsonString(GetStringByStrRef(StringToInt(Get2DACache("classes", "Name", classId)))));
jRow = JsonArrayInsert(jRow, jClassButton);
}
jRow = NuiRow(jRow);
return jRow;
}
json CreateSpellbookCircleButtons(int nClass)
{
json jRow = JsonArray();
int i;
// Get the current selected circle and the class caster level.
int currentCircle = GetLocalInt(OBJECT_SELF, PRC_SPELLBOOK_SELECTED_CIRCLE_VAR);
int casterLevel = GetPrCAdjustedCasterLevel(nClass, OBJECT_SELF);
// Get what the lowest level of a circle is for the class (some start at 1,
// some start higher, some start at cantrips)
int minSpellLevel = GetMinSpellLevel(nClass);
if (minSpellLevel >= 0)
{
// get what is the highest circle the class can cast at
int currentMaxSpellLevel = GetCurrentSpellLevel(nClass, casterLevel);
// Get what the max circle the class can reach at is
int totalMaxSpellLevel = GetMaxSpellLevel(nClass);
// if the current circle is less than the minimum level (possibly due to
// switching classes) then set it to that.
if (currentCircle < minSpellLevel)
{
currentCircle = minSpellLevel;
SetLocalInt(OBJECT_SELF, PRC_SPELLBOOK_SELECTED_CIRCLE_VAR, currentCircle);
}
// conversily if it is higher than the max the class has (possibly due to
// switching classes) then set it to that.
if (currentCircle > currentMaxSpellLevel)
{
currentCircle = currentMaxSpellLevel;
SetLocalInt(OBJECT_SELF, PRC_SPELLBOOK_SELECTED_CIRCLE_VAR, currentCircle);
}
for (i = minSpellLevel; i <= totalMaxSpellLevel; i++)
{
json enabled;
json jButton = NuiId(NuiButtonImage(JsonString(GetSpellLevelIcon(i))), PRC_SPELLBOOK_NUI_CIRCLE_BUTTON_BASEID + IntToString(i));
jButton = NuiWidth(jButton, 42.0f);
jButton = NuiHeight(jButton, 42.0f);
jButton = NuiTooltip(jButton, JsonString(GetSpellLevelToolTip(i)));
// if the current circle is selected or if the person can't cast at
// that circle yet then disable the button.
if (currentCircle == i || i > currentMaxSpellLevel)
{
enabled = JsonBool(FALSE);
}
else
{
enabled = JsonBool(TRUE);
}
jButton = NuiEnabled(jButton, enabled);
jRow = JsonArrayInsert(jRow, jButton);
}
}
jRow = NuiRow(jRow);
return jRow;
}
json CreateSpellbookSpellButtons(int nClass, int circle)
{
json jRows = JsonArray();
// we only want to get spells at the currently selected circle.
int currentCircle = GetLocalInt(OBJECT_SELF, PRC_SPELLBOOK_SELECTED_CIRCLE_VAR);
json spellListAtCircle = GetSpellListForCircle(OBJECT_SELF, nClass, currentCircle);
string sFile = GetClassSpellbookFile(nClass);
// how many buttons a row can have before we have to make a new row.
int rowLimit = NUI_SPELLBOOK_SPELL_BUTTON_LENGTH;
json tempRow = JsonArray();
int i;
for (i = 0; i < JsonGetLength(spellListAtCircle); i++)
{
int spellbookId = JsonGetInt(JsonArrayGet(spellListAtCircle, i));
int spellId;
// Binders don't have a spellbook, so spellbookId is actually SpellID
if (nClass == CLASS_TYPE_BINDER)
spellId = spellbookId;
else
spellId = StringToInt(Get2DACache(sFile, "SpellID", spellbookId));
json jSpellButton = NuiId(NuiButtonImage(GetSpellIcon(spellId, nClass)), PRC_SPELLBOOK_NUI_SPELL_BUTTON_BASEID + IntToString(spellbookId));
jSpellButton = NuiWidth(jSpellButton, 38.0f);
jSpellButton = NuiHeight(jSpellButton, 38.0f);
// the RealSpellID has the accurate descriptions for the spells/abilities
int realSpellId = StringToInt(Get2DACache(sFile, "RealSpellID", spellbookId));
if (!realSpellId)
realSpellId = spellId;
jSpellButton = NuiTooltip(jSpellButton, JsonString(GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", realSpellId)))));
// if the row limit has been reached, make a new row
tempRow = JsonArrayInsert(tempRow, jSpellButton);
if (JsonGetLength(tempRow) >= rowLimit)
{
tempRow = NuiRow(tempRow);
jRows = JsonArrayInsert(jRows, tempRow);
tempRow = JsonArray();
}
}
// if the row was cut short (a remainder) then we finish the row and add it
// to the list
if (JsonGetLength(tempRow) > 0)
{
tempRow = NuiRow(tempRow);
jRows = JsonArrayInsert(jRows, tempRow);
}
return jRows;
}
json CreateMetaMagicFeatButtons(int nClass)
{
json jRows = JsonArray();
json currentRow = JsonArray();
// if an invoker, add the invoker shapes and essences as its own row of buttons
if (nClass == CLASS_TYPE_WARLOCK
|| nClass == CLASS_TYPE_DRAGONFIRE_ADEPT
|| nClass == CLASS_TYPE_DRAGON_SHAMAN)
{
currentRow = CreateMetaFeatButtonRow(GetInvokerShapeSpellList(nClass));
if (JsonGetLength(currentRow) > 0)
{
currentRow = NuiRow(currentRow);
jRows = JsonArrayInsert(jRows, currentRow);
}
currentRow = CreateMetaFeatButtonRow(GetInvokerEssenceSpellList(nClass));
if (JsonGetLength(currentRow) > 0)
{
currentRow = NuiRow(currentRow);
jRows = JsonArrayInsert(jRows, currentRow);
}
}
// if a ToB class, add its stances as its own row of buttons
if (nClass == CLASS_TYPE_WARBLADE
|| nClass == CLASS_TYPE_CRUSADER
|| nClass == CLASS_TYPE_SWORDSAGE)
{
currentRow = CreateMetaFeatButtonRow(GetToBStanceSpellList(nClass));
if (JsonGetLength(currentRow) > 0)
{
currentRow = NuiRow(currentRow);
jRows = JsonArrayInsert(jRows, currentRow);
}
}
currentRow = JsonArray();
// check to see if the class can use any particular meta feats
if (CanClassUseMetamagicFeats(nClass))
currentRow = CreateMetaFeatButtonRow(GetMetaMagicFeatList());
else if (CanClassUseMetaPsionicFeats(nClass))
currentRow = CreateMetaFeatButtonRow(GetMetaPsionicFeatList());
else if (CanClassUseMetaMysteryFeats(nClass))
currentRow = CreateMetaFeatButtonRow(GetMetaMysteryFeatList());
if (JsonGetLength(currentRow) > 0)
{
currentRow = NuiRow(currentRow);
jRows = JsonArrayInsert(jRows, currentRow);
}
// and check to see if the class can use sudden meta feats
currentRow = JsonArray();
if (CanClassUseSuddenMetamagicFeats(nClass))
currentRow = CreateMetaFeatButtonRow(GetSuddenMetaMagicFeatList());
if (JsonGetLength(currentRow) > 0)
{
currentRow = NuiRow(currentRow);
jRows = JsonArrayInsert(jRows, currentRow);
}
return jRows;
}
json CreateMetaFeatButtonRow(json spellList)
{
json jRow = JsonArray();
int i;
for (i = 0; i < JsonGetLength(spellList); i++)
{
int spellId = JsonGetInt(JsonArrayGet(spellList, i));
int featId;
int masterSpell = StringToInt(Get2DACache("spells", "Master", spellId));
if (masterSpell)
featId = StringToInt(Get2DACache("spells", "FeatID", masterSpell));
else
featId = StringToInt(Get2DACache("spells", "FeatID", spellId));
if (GetHasFeat(featId, OBJECT_SELF, TRUE))
{
string featName = GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", spellId)));
json jMetaButton = NuiId(NuiButtonImage(GetSpellIcon(spellId)), PRC_SPELLBOOK_NUI_META_BUTTON_BASEID + IntToString(spellId));
jMetaButton = NuiWidth(jMetaButton, 32.0f);
jMetaButton = NuiHeight(jMetaButton, 32.0f);
jMetaButton = NuiTooltip(jMetaButton, JsonString(featName));
jRow = JsonArrayInsert(jRow, jMetaButton);
}
}
return jRow;
}
json GetSpellIcon(int spellId,int nClass=0)
{
// Binder's spells don't have the FeatID on the spells.2da, so we have to use
// the mapping we constructed to get it.
if (nClass == CLASS_TYPE_BINDER)
{
json binderDict = GetBinderSpellToFeatDictionary();
int featId = JsonGetInt(JsonObjectGet(binderDict, IntToString(spellId)));
return JsonString(Get2DACache("feat", "Icon", featId));
}
int masterSpellID = StringToInt(Get2DACache("spells", "Master", spellId));
// if this is a sub radial spell, then we use spell's icon instead
if (masterSpellID)
return JsonString(Get2DACache("spells", "IconResRef", spellId));
// the FeatID holds the accurate spell icon, not the SpellID
int featId = StringToInt(Get2DACache("spells", "FeatID", spellId));
return JsonString(Get2DACache("feat", "Icon", featId));
}
string GetSpellLevelIcon(int spellLevel)
{
switch (spellLevel)
{
case 0: return "ir_cantrips";
case 1: return "ir_level1";
case 2: return "ir_level2";
case 3: return "ir_level3";
case 4: return "ir_level4";
case 5: return "ir_level5";
case 6: return "ir_level6";
case 7: return "ir_level789";
case 8: return "ir_level789";
case 9: return "ir_level789";
}
return "";
}
string GetSpellLevelToolTip(int spellLevel)
{
switch (spellLevel)
{
case 0: return "Cantrips";
case 1: return "Level 1";
case 2: return "Level 2";
case 3: return "Level 3";
case 4: return "Level 4";
case 5: return "Level 5";
case 6: return "Level 6";
case 7: return "Level 7";
case 8: return "Level 8";
case 9: return "Level 9";
}
return "";
}

View File

@ -2,6 +2,15 @@
//:: OnPlayerChat eventscript
//:: prc_onplayerchat
//:://////////////////////////////////////////////
/*
A OnChat script that parses what is said and
uses any commands or NUI associated with
commands.
*/
//:://////////////////////////////////////////////
//:: Updated By: Rakiov
//:: Created On: 22.05.2005
//:://////////////////////////////////////////////
/*
PRC Chat Command Format:
@ -15,6 +24,10 @@ OR:
#include "prc_inc_chat_dm"
#include "prc_inc_chat_pow"
#include "prc_inc_chat_shf"
#include "nw_inc_nui"
#include "prc_string_inc"
#include "prc_nui_sb_inc"
#include "prc_nui_consts"
const string CHAT_COMMAND_INDICATOR_1 = "~~";
const string CHAT_COMMAND_INDICATOR_2 = "..";
@ -87,8 +100,54 @@ void main()
ExecuteScript(GetLocalString(oPC, PRC_CHAT_HOOK_SCRIPT), oPC);
_clear_chat_vars(oPC);
}
ExecuteScript("hp_pa_chatscript", oPC);
// get current player message and split it up into a list
string sCommand = GetPCChatMessage();
json sCommandSplit = StringSplit(sChat);
if(JsonGetLength(sCommandSplit) > 0)
{
string firstWord = JsonGetString(JsonArrayGet(sCommandSplit, 0));
// if first word is /pa we are using the power attack interface
if(firstWord == "/pa")
{
if(JsonGetLength(sCommandSplit) >= 2)
{
//if a parameter is given then run the power attack command directly.
string param1 = JsonGetString(JsonArrayGet(sCommandSplit, 1));
int paAmount = StringToInt(param1);
SetLocalInt(oPC, "PRC_PowerAttack_Level", paAmount);
ExecuteScript("prc_nui_pa_trggr", oPC);
// update the NUI so it is in sync
int nToken = NuiFindWindow(oPC, NUI_PRC_POWER_ATTACK_WINDOW);
if (nToken != 0)
{
NuiSetBind(oPC, nToken, NUI_PRC_PA_TEXT_BIND, JsonString(IntToString(paAmount)));
}
}
else
{
// if no param is given then open the NUI
ExecuteScript("prc_nui_pa_view", oPC);
}
// clear message from chat
SetPCChatMessage();
}
// If the first word is /sb then we open the Spellbook NUI
if(firstWord == "/sb")
{
ExecuteScript("prc_nui_sb_view", oPC);
// clear message from chat
SetPCChatMessage();
}
}
// Execute scripts hooked to this event for the player triggering it
ExecuteAllScriptsHookedToEvent(oPC, EVENT_ONPLAYERCHAT);
}

View File

@ -0,0 +1,37 @@
//::///////////////////////////////////////////////
//:: NUI Events
//:: prc_onplayernui (hp_nui_events)
//:://////////////////////////////////////////////
/*
This handles any NUI events and sends them to
appropriate NUI Event handler depending on the
window Id
*/
//:://////////////////////////////////////////////
//:: Created By: Rakiov
//:: Created On: 22.05.2005
//:://////////////////////////////////////////////
#include "prc_nui_consts"
void main()
{
object oPlayer = NuiGetEventPlayer();
int nToken = NuiGetEventWindow();
string sWindowId = NuiGetWindowId(oPlayer, nToken);
// Open the Power Attack NUI
if(sWindowId == NUI_PRC_POWER_ATTACK_WINDOW)
{
ExecuteScript("prc_nui_pa_event");
}
// Open the Spellbook NUI
if(sWindowId == PRC_SPELLBOOK_NUI_WINDOW_ID
|| sWindowId == NUI_SPELL_DESCRIPTION_WINDOW_ID)
{
ExecuteScript("prc_nui_sb_event");
}
return;
}

View File

@ -1,43 +1,101 @@
//::
//:: prc_onplaytarget.nss
//::
//::
//::///////////////////////////////////////////////
//:: PRC Spellbook OnTrigger Event
//:: prc_onplaytarget
//:://////////////////////////////////////////////
/*
This is the OnTarget event used set up spell
attacks with the selected spell from the PRC
Spellbook NUI
*/
//:://////////////////////////////////////////////
//:: Updated By: Rakiov
//:: Created On: 24.05.2005
//:://////////////////////////////////////////////
#include "prc_inc_skills"
#include "prc_nui_consts"
void DoJump(object oPC, location lTarget, int bDoKnockdown);
//
// DoSpellbookAction
// This is a OnTarget event action handling the use of the NUI Spellbook's spell.
// All this should do is take the manual targeting information and send it to the
// prc_nui_sb_trggr to handle the use of the spell.
//
// Arguments:
// oPC:object the player executing the action
// oTarget:object the object target of the spell
// lTarget:location the location the spell is being cast at.
//
void DoSpellbookAction(object oPC, object oTarget, location lTarget);
//
// ClearEventVariables
// Clears all the event variables used by the NUI Spellbook that coordinates with
// the OnTarget script to make sure it doesn't leave weird behavior for the next run.
//
// Arguments:
// oPC:object the player we are removing the info from.
//
void ClearEventVariables(object oPC);
void DoJump(object oPC, location lTarget, int bDoKnockdown)
{
object oTarget;
location lSource = GetLocation(oPC);
vector vSource = GetPositionFromLocation(lSource);
float fDistance = GetDistanceBetweenLocations(lTarget, lSource);
string sMessage = "You cannot jump through a closed door.";
oTarget = GetFirstObjectInShape(SHAPE_SPELLCYLINDER, fDistance, lTarget, TRUE, OBJECT_TYPE_DOOR, vSource);
object oTarget;
//:: Check if the first object found is a door.
while (oTarget != OBJECT_INVALID)
{
//:: Check if the door is closed.
if (!GetIsOpen(oTarget))
{
FloatingTextStringOnCreature(sMessage, oPC, FALSE);
DeleteLocalLocation(oPC, "TARGETING_POSITION");
return;
}
location lSource = GetLocation(oPC);
vector vSource = GetPositionFromLocation(lSource);
float fDistance = GetDistanceBetweenLocations(lTarget, lSource);
//:: Select the next target within the spell shape.
oTarget = GetNextObjectInShape(SHAPE_SPELLCYLINDER, fDistance, lTarget, TRUE, OBJECT_TYPE_DOOR,vSource);
}
PerformJump(oPC, lTarget, TRUE);
DeleteLocalLocation(oPC, "TARGETING_POSITION");
string sMessage = "You cannot jump through a closed door.";
oTarget = GetFirstObjectInShape(SHAPE_SPELLCYLINDER, fDistance, lTarget, TRUE, OBJECT_TYPE_DOOR, vSource);
//:: Check if the first object found is a door.
while (oTarget != OBJECT_INVALID)
{
//:: Check if the door is closed.
if (!GetIsOpen(oTarget))
{
FloatingTextStringOnCreature(sMessage, oPC, FALSE);
DeleteLocalLocation(oPC, "TARGETING_POSITION");
return;
}
//:: Select the next target within the spell shape.
oTarget = GetNextObjectInShape(SHAPE_SPELLCYLINDER, fDistance, lTarget, TRUE, OBJECT_TYPE_DOOR,vSource);
}
PerformJump(oPC, lTarget, TRUE);
DeleteLocalLocation(oPC, "TARGETING_POSITION");
}
void DoSpellbookAction(object oPC, object oTarget, location lTarget)
{
object currentTarget = oTarget;
if (GetIsObjectValid(currentTarget))
{
SetLocalObject(oPC, "TARGETING_OBJECT", currentTarget);
}
else
{
SetLocalLocation(oPC, "TARGETING_POSITION", lTarget);
}
ExecuteScript("prc_nui_sb_trggr", oPC);
ClearEventVariables(oPC);
}
void ClearEventVariables(object oPC)
{
DeleteLocalObject(oPC, "TARGETING_OBJECT");
DeleteLocalLocation(oPC, "TARGETING_POSITION");
DeleteLocalString(oPC, "ONPLAYERTARGET_ACTION");
DeleteLocalInt(oPC, NUI_SPELLBOOK_ON_TARGET_IS_PERSONAL_FEAT);
DeleteLocalInt(oPC, NUI_SPELLBOOK_SELECTED_SUBSPELL_SPELLID_VAR);
}
void main()
@ -45,57 +103,69 @@ void main()
// Get the last player to use targeting mode
object oPC = GetLastPlayerToSelectTarget();
string sAction = GetLocalString(oPC, "ONPLAYERTARGET_ACTION");
string sAction = GetLocalString(oPC, "ONPLAYERTARGET_ACTION");
// Get the targeting mode data
object oTarget = GetTargetingModeSelectedObject();
vector vTarget = GetTargetingModeSelectedPosition();
float fOrientation = GetFacing(oPC);
object oTarget = GetTargetingModeSelectedObject();
vector vTarget = GetTargetingModeSelectedPosition();
float fOrientation = GetFacing(oPC);
// If the user manually exited targeting mode without selecting a target, return
// we also want to clear any existing targeting information we are sending to the script
// so clear all event variables.
if (!GetIsObjectValid(oTarget) && vTarget == Vector())
{
ClearEventVariables(oPC);
return;
}
// Save the targeting data to the PC object for later use
location lTarget = Location(GetArea(oTarget), vTarget, fOrientation);
SetLocalObject(oPC, "TARGETING_OBJECT", oTarget);
SetLocalLocation(oPC, "TARGETING_POSITION", lTarget);
if (sAction == "PRC_JUMP")
{
AssignCommand(oPC, SetFacingPoint(vTarget));
DelayCommand(0.0f, DoJump(oPC, lTarget, TRUE));
}
if (sAction == "PRC_JUMP")
{
AssignCommand(oPC, SetFacingPoint(vTarget));
DelayCommand(0.0f, DoJump(oPC, lTarget, TRUE));
}
// this is being called by the NUI Spellbook, perform the spell action
if (sAction == "PRC_NUI_SPELLBOOK")
{
DoSpellbookAction(oPC, oTarget, lTarget);
}
}
/* object oTarget;
location lTarget = GetLocalLocation(oPC, "TARGETING_POSITION");
location lSource = GetLocation(oPC);
float fDistance = GetDistanceBetweenLocations(lTarget, lSource);
/* object oTarget;
string sMessage = "You cannot jump through a closed door.";
oTarget = GetFirstObjectInShape(SHAPE_SPELLCYLINDER, fDistance, lTarget, TRUE, OBJECT_TYPE_DOOR);
location lTarget = GetLocalLocation(oPC, "TARGETING_POSITION");
location lSource = GetLocation(oPC);
float fDistance = GetDistanceBetweenLocations(lTarget, lSource);
// Check if the first object found is a door.
while (GetIsObjectValid(oTarget))
{
// Check if the door is closed.
if (!GetIsOpen(oTarget))
{
SpeakString(sMessage);
break;
}
string sMessage = "You cannot jump through a closed door.";
oTarget = GetFirstObjectInShape(SHAPE_SPELLCYLINDER, fDistance, lTarget, TRUE, OBJECT_TYPE_DOOR);
// Check if the first object found is a door.
while (GetIsObjectValid(oTarget))
{
// Check if the door is closed.
if (!GetIsOpen(oTarget))
{
SpeakString(sMessage);
break;
}
//Select the next target within the spell shape.
oTarget = GetNextObjectInShape(SHAPE_SPELLCYLINDER, fDistance, lTarget, TRUE, OBJECT_TYPE_DOOR);
}
//location lTarget = PRCGetSpellTargetLocation();
}
//location lTarget = PRCGetSpellTargetLocation();
//PerformJump(oPC, lLoc, TRUE));
DelayCommand(0.0f, DoJump(oPC, lTarget, TRUE)); */
DelayCommand(0.0f, DoJump(oPC, lTarget, TRUE)); */

View File

@ -71357,6 +71357,8 @@ When within your own black labyrinth, you are immune to the last two effects (mo
<entry id="74811" lang="en" sex="m">Spellcraft doesn't provide a bonus to your save vs. spells in 3e Dungeons &amp; Dragons. This is reflected in the PRC8.</entry>
<entry id="74812" lang="en" sex="m">Tumble doesn't provide a bonus to your Armor Class in 3e Dungeons &amp; Dragons. This is reflected in the PRC8.</entry>
<entry id="74813" lang="en" sex="m">Feats for Alternate Magic Systems (Psionics, Incarnum, etc) are all organized under a Masterfeat. Psionic Feats, ToB Feats, etc...</entry>
<entry id="74814" lang="en" sex="m">Typing "/sb" in chat will bring up the NUI spellcasting menu.</entry>
<entry id="74815" lang="en" sex="m">Typing "/pa" in chat will bring up the NUI Power Attack menu.</entry>
<entry id="75001" lang="en" sex="m">Favored Mystery - Black Labyrinth</entry>
<entry id="75002" lang="en" sex="m">Holy Warrior</entry>
<entry id="75003" lang="en" sex="m">Type of Feat: Reserve

View File

@ -1,676 +0,0 @@
//:://////////////////////////////////////////////
//:: Alternate magic system gain evaluation script
//:: prc_amagsys_gain
//:://////////////////////////////////////////////
/** @file
This file determines if the given character
has gained new spells / powers / utterances /
whathaveyou since the last time it was run.
If so, it starts the relevant selection
conversations.
Add new classes to their respective magic
user type block, or if such doesn't exist
yet for the system the class belongs to,
make a new block for them at the end of main().
@author Ornedan
@date Created - 2006.12.14
*/
//:://////////////////////////////////////////////
//:: Updated for .35 by Jaysyn 2023/03/11
//:://////////////////////////////////////////////
#include "inc_dynconv"
#include "psi_inc_psifunc"
#include "inc_newspellbook"
#include "true_inc_trufunc"
#include "tob_inc_tobfunc"
#include "shd_inc_shdfunc"
#include "inv_inc_invfunc"
//////////////////////////////////////////////////
/* Function prototypes */
//////////////////////////////////////////////////
void CheckSpellbooks(object oPC);
void CheckPsionics(object oPC);
void CheckInvocations(object oPC);
void CheckToB(object oPC);
void CheckShadow(object oPC);
void CheckTruenaming(object oPC);
int CheckMissingPowers(object oPC, int nClass);
int CheckMissingSpells(object oPC, int nClass, int nMinLevel, int nMaxLevel);
int CheckMissingUtterances(object oPC, int nClass, int nLexicon);
int CheckMissingManeuvers(object oPC, int nClass);
int CheckMissingMysteries(object oPC, int nClass);
int CheckMissingInvocations(object oPC, int nClass);
void AMSCompatibilityCheck(object oPC);
//////////////////////////////////////////////////
/* Function definitions */
//////////////////////////////////////////////////
void main()
{
object oPC = OBJECT_SELF;
// Sanity checks - Shifted or polymorphed characters may have their hide fucked up, and might be missing access to their hide-feats
// @todo Shifting probably doesn't do this anymore, could be ditchable - Ornedan, 20061214
if(GetLocalInt(oPC, "nPCShifted"))
return;
effect eTest = GetFirstEffect(oPC);
while(GetIsEffectValid(eTest))
{
if(GetEffectType(eTest) == EFFECT_TYPE_POLYMORPH)
return;
eTest = GetNextEffect(oPC);
}
DelayCommand(0.0f, CheckSpellbooks(oPC));
}
// Handle new spellbooks
void CheckSpellbooks(object oPC)
{
if(GetLevelByClass(CLASS_TYPE_SUBLIME_CHORD, oPC) > 0)
{
CheckMissingSpells(oPC, CLASS_TYPE_SUBLIME_CHORD, 4, 9);
if(GetHasFeat(FEAT_SUBLIME_CHORD_SPELLCASTING_BARD, oPC))
{
CheckMissingSpells(oPC, CLASS_TYPE_BARD, 0, 3);
}
if(GetHasFeat(FEAT_SUBLIME_CHORD_SPELLCASTING_SORCERER))
{
CheckMissingSpells(oPC, CLASS_TYPE_SORCERER, 0, 3);
}
if(GetHasFeat(FEAT_SUBLIME_CHORD_SPELLCASTING_WARMAGE, oPC))
{
CheckMissingSpells(oPC, CLASS_TYPE_WARMAGE, 0, 3);
}
if(GetHasFeat(FEAT_SUBLIME_CHORD_SPELLCASTING_DUSKBLADE, oPC))
{
CheckMissingSpells(oPC, CLASS_TYPE_DUSKBLADE, 0, 3);
}
if(GetHasFeat(FEAT_SUBLIME_CHORD_SPELLCASTING_BEGUILER, oPC))
{
CheckMissingSpells(oPC, CLASS_TYPE_BEGUILER, 0, 3);
}
}
// Check all classes that might need a spellbook update
if(GetIsRHDSorcerer(oPC)) CheckMissingSpells(oPC, CLASS_TYPE_SORCERER, 0, 9);
if(GetIsRHDBard(oPC)) CheckMissingSpells(oPC, CLASS_TYPE_BARD, 0, 6);
if(!GetPRCSwitch(PRC_BARD_DISALLOW_NEWSPELLBOOK))
CheckMissingSpells(oPC, CLASS_TYPE_BARD, 0, 6);
if(!GetPRCSwitch(PRC_SORC_DISALLOW_NEWSPELLBOOK))
CheckMissingSpells(oPC, CLASS_TYPE_SORCERER, 0, 9);
CheckMissingSpells(oPC, CLASS_TYPE_SUEL_ARCHANAMACH, 1, 5);
CheckMissingSpells(oPC, CLASS_TYPE_FAVOURED_SOUL, 0, 9);
CheckMissingSpells(oPC, CLASS_TYPE_WARMAGE, 0, 9);
CheckMissingSpells(oPC, CLASS_TYPE_DREAD_NECROMANCER, 1, 9);
CheckMissingSpells(oPC, CLASS_TYPE_HEXBLADE, 1, 4);
CheckMissingSpells(oPC, CLASS_TYPE_DUSKBLADE, 0, 5);
CheckMissingSpells(oPC, CLASS_TYPE_JUSTICEWW, 1, 4);
CheckMissingSpells(oPC, CLASS_TYPE_KNIGHT_WEAVE, 1, 6);
CheckMissingSpells(oPC, CLASS_TYPE_ARCHIVIST, 0, 9);
CheckMissingSpells(oPC, CLASS_TYPE_BEGUILER, 0, 9);
CheckMissingSpells(oPC, CLASS_TYPE_HARPER, 1, 3);
CheckMissingSpells(oPC, CLASS_TYPE_ASSASSIN, 1, 4);
CheckMissingSpells(oPC, CLASS_TYPE_CELEBRANT_SHARESS, 1, 4);
// Check psionics
DelayCommand(0.0f, CheckPsionics(oPC));
}
/* void CheckSpellbooks(object oPC)
{
if(GetLevelByClass(CLASS_TYPE_SUBLIME_CHORD, oPC) > 0)
{
// Manually check Sublime Chord spells (levels 49)
CheckMissingSpells(oPC, CLASS_TYPE_SUBLIME_CHORD, 4, 9);
// Get the character's *base* arcane class (Sublime Chord isn't returned)
int nPrimaryArcane = GetPrimaryArcaneClass(oPC);
// Carveout: Allow known spells from Bard/Sorc/Warmage etc. up to level 3
if(nPrimaryArcane == CLASS_TYPE_BARD)
{
CheckMissingSpells(oPC, CLASS_TYPE_BARD, 0, 3);
}
else if(nPrimaryArcane == CLASS_TYPE_SORCERER)
{
CheckMissingSpells(oPC, CLASS_TYPE_SORCERER, 0, 3);
}
else if(nPrimaryArcane == CLASS_TYPE_WARMAGE)
{
CheckMissingSpells(oPC, CLASS_TYPE_WARMAGE, 0, 3);
}
else if(nPrimaryArcane == CLASS_TYPE_DUSKBLADE)
{
CheckMissingSpells(oPC, CLASS_TYPE_DUSKBLADE, 0, 3);
}
else if(nPrimaryArcane == CLASS_TYPE_BEGUILER)
{
CheckMissingSpells(oPC, CLASS_TYPE_BEGUILER, 0, 3);
}
// Stop here; Sublime Chord handled separately
return;
}
if(GetIsRHDSorcerer(oPC) && CheckMissingSpells(oPC, CLASS_TYPE_SORCERER, 0, 9))
return;
if(GetIsRHDBard(oPC) && CheckMissingSpells(oPC, CLASS_TYPE_BARD, 0, 6))
return;
if(!GetPRCSwitch(PRC_BARD_DISALLOW_NEWSPELLBOOK) && CheckMissingSpells(oPC, CLASS_TYPE_BARD, 0, 6))
return;
if(!GetPRCSwitch(PRC_SORC_DISALLOW_NEWSPELLBOOK) && CheckMissingSpells(oPC, CLASS_TYPE_SORCERER, 0, 9))
return;
if(CheckMissingSpells(oPC, CLASS_TYPE_SUEL_ARCHANAMACH, 1, 5))
return;
if(CheckMissingSpells(oPC, CLASS_TYPE_FAVOURED_SOUL, 0, 9))
return;
if(CheckMissingSpells(oPC, CLASS_TYPE_WARMAGE, 0, 9))
return;
if(CheckMissingSpells(oPC, CLASS_TYPE_DREAD_NECROMANCER, 1, 9))
return;
if(CheckMissingSpells(oPC, CLASS_TYPE_HEXBLADE, 1, 4))
return;
if(CheckMissingSpells(oPC, CLASS_TYPE_DUSKBLADE, 0, 5))
return;
if(CheckMissingSpells(oPC, CLASS_TYPE_JUSTICEWW, 1, 4))
return;
if(CheckMissingSpells(oPC, CLASS_TYPE_KNIGHT_WEAVE, 1, 6))
return;
// if(CheckMissingSpells(oPC, CLASS_TYPE_SUBLIME_CHORD, 4, 9))
// return;
if(CheckMissingSpells(oPC, CLASS_TYPE_ARCHIVIST, 0, 9))
return;
if(CheckMissingSpells(oPC, CLASS_TYPE_BEGUILER, 0, 9))
return;
if(CheckMissingSpells(oPC, CLASS_TYPE_HARPER, 1, 3))
return;
if(CheckMissingSpells(oPC, CLASS_TYPE_ASSASSIN, 1, 4))
return;
if(CheckMissingSpells(oPC, CLASS_TYPE_CELEBRANT_SHARESS, 1, 4))
return;
DelayCommand(0.0f, CheckPsionics(oPC));
}
*/
// Handle psionics
void CheckPsionics(object oPC)
{
if(CheckMissingPowers(oPC, CLASS_TYPE_PSION))
return;
if(CheckMissingPowers(oPC, CLASS_TYPE_WILDER))
return;
if(CheckMissingPowers(oPC, CLASS_TYPE_PSYWAR))
return;
if(CheckMissingPowers(oPC, CLASS_TYPE_PSYCHIC_ROGUE))
return;
if(CheckMissingPowers(oPC, CLASS_TYPE_FIST_OF_ZUOKEN))
return;
if(CheckMissingPowers(oPC, CLASS_TYPE_WARMIND))
return;
//expanded knowledge
if(CheckMissingPowers(oPC, -1))
return;
//epic expanded knowledge
if(CheckMissingPowers(oPC, -2))
return;
DelayCommand(0.0f, CheckInvocations(oPC));
}
// Handle Invocations
void CheckInvocations(object oPC)
{
if(CheckMissingInvocations(oPC, CLASS_TYPE_DRAGONFIRE_ADEPT))
return;
if(CheckMissingInvocations(oPC, CLASS_TYPE_WARLOCK))
return;
if(CheckMissingInvocations(oPC, CLASS_TYPE_DRAGON_SHAMAN))
return;
//extra invocations
if(CheckMissingInvocations(oPC, CLASS_TYPE_INVALID))
return;
//epic extra invocations
if(CheckMissingInvocations(oPC, -2))
return;
DelayCommand(0.0f, CheckToB(oPC));
}
// Handle Tome of Battle
void CheckToB(object oPC)
{
if(CheckMissingManeuvers(oPC, CLASS_TYPE_CRUSADER))
return;
if(CheckMissingManeuvers(oPC, CLASS_TYPE_SWORDSAGE))
return;
if(CheckMissingManeuvers(oPC, CLASS_TYPE_WARBLADE))
return;
DelayCommand(0.0f, CheckShadow(oPC));
}
// Handle Shadowcasting
void CheckShadow(object oPC)
{
if(CheckMissingMysteries(oPC, CLASS_TYPE_SHADOWCASTER))
return;
if(CheckMissingMysteries(oPC, CLASS_TYPE_SHADOWSMITH))
return;
DelayCommand(0.0f, CheckTruenaming(oPC));
}
// Handle Truenaming - Three different Lexicons to check
void CheckTruenaming(object oPC)
{
if(CheckMissingUtterances(oPC, CLASS_TYPE_TRUENAMER, LEXICON_EVOLVING_MIND))
return;
if(CheckMissingUtterances(oPC, CLASS_TYPE_TRUENAMER, LEXICON_CRAFTED_TOOL))
return;
if(CheckMissingUtterances(oPC, CLASS_TYPE_TRUENAMER, LEXICON_PERFECTED_MAP))
return;
if(!GetIsDM(oPC))
DelayCommand(0.0f, AMSCompatibilityCheck(oPC));
}
int CheckMissingPowers(object oPC, int nClass)
{
int nLevel = GetLevelByClass(nClass, oPC);
if(!nLevel && nClass != -1 && nClass != -2)
return FALSE;
else if(nClass == -1 && !GetHasFeat(FEAT_EXPANDED_KNOWLEDGE_1))
return FALSE;
else if(nClass == -2 && !GetHasFeat(FEAT_EPIC_EXPANDED_KNOWLEDGE_1))
return FALSE;
int nCurrentPowers = GetPowerCount(oPC, nClass);
int nMaxPowers = GetMaxPowerCount(oPC, nClass);
if(nCurrentPowers < nMaxPowers)
{
// Mark the class for which the PC is to gain powers and start the conversation
SetLocalInt(oPC, "nClass", nClass);
StartDynamicConversation("psi_powconv", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
return TRUE;
}
return FALSE;
}
int CheckMissingInvocations(object oPC, int nClass)
{
int nLevel = GetLevelByClass(nClass, oPC);
if(!nLevel && (nClass == CLASS_TYPE_DRAGONFIRE_ADEPT || nClass == CLASS_TYPE_WARLOCK || nClass == CLASS_TYPE_DRAGON_SHAMAN))
return FALSE;
else if(nClass == CLASS_TYPE_INVALID && !GetHasFeat(FEAT_EXTRA_INVOCATION_I))
return FALSE;
else if(nClass == -2 && !GetHasFeat(FEAT_EPIC_EXTRA_INVOCATION_I))
return FALSE;
int nCurrentInvocations = GetInvocationCount(oPC, nClass);
if(DEBUG) DoDebug("Current Invocations: " + IntToString(nCurrentInvocations));
int nMaxInvocations = GetMaxInvocationCount(oPC, nClass);
if(DEBUG) DoDebug("Max Invocations: " + IntToString(nMaxInvocations));
if(nCurrentInvocations < nMaxInvocations)
{
// Mark the class for which the PC is to gain invocations and start the conversation
SetLocalInt(oPC, "nClass", nClass);
StartDynamicConversation("inv_invokeconv", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
return TRUE;
}
return FALSE;
}
void AddSpellsForLevel(int nClass, int nLevel)
{
object oPC = OBJECT_SELF;
object oSkin = GetPCSkin(oPC);
//object oToken = GetHideToken(oPC);
string sFile = GetFileForClass(nClass);
string sSpellbook;
int nSpellbookType = GetSpellbookTypeForClass(nClass);
if(nSpellbookType == SPELLBOOK_TYPE_SPONTANEOUS)
sSpellbook = "Spellbook"+IntToString(nClass);
else
sSpellbook = "Spellbook_Known_"+IntToString(nClass)+"_"+IntToString(nLevel);
// Create spells known persistant array if it is missing
int nSize = persistant_array_get_size(oPC, sSpellbook);
if (nSize < 0)
{
persistant_array_create(oPC, sSpellbook);
nSize = 0;
}
//check for learnable spells
object oToken_Class = GetObjectByTag("SpellLvl_" + IntToString(nClass) + "_Level_" + IntToString(nLevel));
int nSpells_Total = persistant_array_get_size(oToken_Class, "Lkup");
int i;
for(i = 0; i < nSpells_Total; i++)
{
int nSpellbookID = persistant_array_get_int(oToken_Class, "Lkup", i);
if(Get2DAString(sFile, "AL", nSpellbookID) != "1")
{
persistant_array_set_int(oPC, sSpellbook, nSize, nSpellbookID);
nSize++;
if(nSpellbookType == SPELLBOOK_TYPE_SPONTANEOUS)
{
int nIPFeatID = StringToInt(Get2DACache(sFile, "IPFeatID", nSpellbookID));
int nFeatID = StringToInt(Get2DACache(sFile, "FeatID", nSpellbookID));
AddSpellUse(oPC, nSpellbookID, nClass, sFile, "NewSpellbookMem_" + IntToString(nClass), nSpellbookType, oSkin, nFeatID, nIPFeatID);
}
}
}
}
int CheckMissingSpells(object oPC, int nClass, int nMinLevel, int nMaxLevel)
{
int nLevel;
//:: Rakshasa cast as sorcerers
if(nClass == CLASS_TYPE_SORCERER && !GetLevelByClass(CLASS_TYPE_SORCERER, oPC) && GetRacialType(oPC) == RACIAL_TYPE_RAKSHASA)
nLevel = GetSpellslotLevel(nClass, oPC); //GetLevelByClass(CLASS_TYPE_OUTSIDER, oPC);
//:: Aranea cast as sorcerers
else if(nClass == CLASS_TYPE_SORCERER && !GetLevelByClass(CLASS_TYPE_SORCERER, oPC) && GetRacialType(oPC) == RACIAL_TYPE_ARANEA)
nLevel = GetSpellslotLevel(nClass, oPC); //GetLevelByClass(CLASS_TYPE_SHAPECHANGER, oPC);
//::Arkamoi cast as sorcerers
else if(nClass == CLASS_TYPE_SORCERER && !GetLevelByClass(CLASS_TYPE_SORCERER, oPC) && GetRacialType(oPC) == RACIAL_TYPE_ARKAMOI)
nLevel = GetSpellslotLevel(nClass, oPC); //GetLevelByClass(CLASS_TYPE_MONSTROUS, oPC);
//::Hobgoblin Warsouls cast as sorcerers
else if(nClass == CLASS_TYPE_SORCERER && !GetLevelByClass(CLASS_TYPE_SORCERER, oPC) && GetRacialType(oPC) == RACIAL_TYPE_HOBGOBLIN_WARSOUL)
nLevel = GetSpellslotLevel(nClass, oPC); //GetLevelByClass(CLASS_TYPE_MONSTROUS, oPC);
//:: Driders cast as sorcerers
else if(nClass == CLASS_TYPE_SORCERER && !GetLevelByClass(CLASS_TYPE_SORCERER, oPC) && GetRacialType(oPC) == RACIAL_TYPE_DRIDER)
nLevel = GetSpellslotLevel(nClass, oPC); //GetLevelByClass(CLASS_TYPE_ABERRATION, oPC);
//:: Marrutact cast as 6/7 sorcerers
else if(nClass == CLASS_TYPE_SORCERER && !GetLevelByClass(CLASS_TYPE_SORCERER, oPC) && GetRacialType(oPC) == RACIAL_TYPE_MARRUTACT)
nLevel = GetSpellslotLevel(nClass, oPC); //GetLevelByClass(CLASS_TYPE_MONSTROUS, oPC);
//:: Redspawn Arcaniss cast as 3/4 sorcerers
else if(nClass == CLASS_TYPE_SORCERER && !GetLevelByClass(CLASS_TYPE_SORCERER, oPC) && GetRacialType(oPC) == RACIAL_TYPE_REDSPAWN_ARCANISS)
nLevel = GetSpellslotLevel(nClass, oPC); //GetLevelByClass(CLASS_TYPE_MONSTROUS, oPC);
//:: Gloura cast as bards
else if(nClass == CLASS_TYPE_BARD && !GetLevelByClass(CLASS_TYPE_BARD, oPC) && GetRacialType(oPC) == RACIAL_TYPE_GLOURA)
nLevel = GetSpellslotLevel(nClass, oPC); //GetLevelByClass(CLASS_TYPE_MONSTROUS, oPC);
else
nLevel = nClass == CLASS_TYPE_SUBLIME_CHORD ? GetLevelByClass(nClass, oPC) : GetSpellslotLevel(nClass, oPC);
if (DEBUG) DoDebug("CheckMissingSpells 1 Class: " + IntToString(nClass));
if (DEBUG) DoDebug("CheckMissingSpells 1 Level: " + IntToString(nLevel));
if(!nLevel)
return FALSE;
if(nClass == CLASS_TYPE_BARD || nClass == CLASS_TYPE_SORCERER)
{
if((GetLevelByClass(nClass, oPC) == nLevel) //no PrC
&& !(GetHasFeat(FEAT_DRACONIC_GRACE, oPC) || GetHasFeat(FEAT_DRACONIC_BREATH, oPC))) //no Draconic feats that apply
return FALSE;
}
else if(nClass == CLASS_TYPE_ARCHIVIST)
{
int nLastGainLevel = GetPersistantLocalInt(oPC, "LastSpellGainLevel");
nLevel = GetLevelByClass(CLASS_TYPE_ARCHIVIST, oPC);
if(nLastGainLevel < nLevel)
{
if(nLevel == 1)
{
//count the number of available at 1st level spells
int nSpellsAvailable = 3 + GetAbilityModifier(ABILITY_INTELLIGENCE, oPC);
SetLocalInt(oPC, "LrnLvlUp", nSpellsAvailable);
}
else if(nLevel > 1)
//add additional 2 spells form cleric list
SetLocalInt(oPC, "LrnLvlUp", 2);
SetLocalInt(oPC, "SpellGainClass", CLASS_TYPE_ARCHIVIST);
SetLocalInt(oPC, "SpellbookMinSpelllevel", nMinLevel);
StartDynamicConversation("prc_s_spellgain", oPC, DYNCONV_EXIT_NOT_ALLOWED, TRUE, FALSE, oPC);
return TRUE;
}
//add cleric spells known for level 0
else if(persistant_array_get_size(oPC, "Spellbook_Known_"+IntToString(CLASS_TYPE_ARCHIVIST)+"_0") < 5) // TODO: replace with GetSpellKnownCurrentCount
{
ActionDoCommand(AddSpellsForLevel(CLASS_TYPE_ARCHIVIST, 0));
}
else
return FALSE;
}
if (DEBUG) DoDebug("CheckMissingSpells 2 Class: " + IntToString(nClass));
if (DEBUG) DoDebug("CheckMissingSpells 2 Level: " + IntToString(nLevel));
int i;
for(i = nMinLevel; i <= nMaxLevel; i++)
{
int nMaxSpells = GetSpellKnownMaxCount(nLevel, i, nClass, oPC);
if(nMaxSpells > 0)
{
int nCurrentSpells = GetSpellKnownCurrentCount(oPC, i, nClass);
int nSpellsAvailable = GetSpellUnknownCurrentCount(oPC, i, nClass);
if(nCurrentSpells < nMaxSpells && nSpellsAvailable > 0)
{
if(GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS && bKnowsAllClassSpells(nClass))
{
ActionDoCommand(AddSpellsForLevel(nClass, i));
}
else
{
// Mark the class for which the PC is to gain powers and start the conversation
SetLocalInt(oPC, "SpellGainClass", nClass);
SetLocalInt(oPC, "SpellbookMinSpelllevel", nMinLevel);
SetLocalInt(oPC, "SpellbookMaxSpelllevel", nMaxLevel);
StartDynamicConversation("prc_s_spellgain", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
return TRUE;
}
}
}
}
//Advanced Learning check
nLevel = GetLevelByClass(nClass, oPC);
int nALSpells = GetPersistantLocalInt(oPC, "AdvancedLearning_"+IntToString(nClass));
if(nClass == CLASS_TYPE_BEGUILER && nALSpells < (nLevel+1)/4)//one every 4 levels starting at 3.
{
// Mark the class for which the PC is to gain powers and start the conversation
SetLocalInt(oPC, "SpellGainClass", CLASS_TYPE_BEGUILER);
SetLocalInt(oPC, "SpellbookMinSpelllevel", nMinLevel);
SetLocalInt(oPC, "AdvancedLearning", 1);
StartDynamicConversation("prc_s_spellgain", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
return TRUE;
}
else if(nClass == CLASS_TYPE_DREAD_NECROMANCER && nALSpells < nLevel/4)//one every 4 levels
{
// Mark the class for which the PC is to gain powers and start the conversation
SetLocalInt(oPC, "SpellGainClass", CLASS_TYPE_DREAD_NECROMANCER);
SetLocalInt(oPC, "SpellbookMinSpelllevel", nMinLevel);
SetLocalInt(oPC, "AdvancedLearning", 1);
StartDynamicConversation("prc_s_spellgain", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
return TRUE;
}
else if(nClass == CLASS_TYPE_WARMAGE)
{
if((nLevel >= 40 && nALSpells < 9) ||// :/
(nLevel >= 36 && nLevel < 40 && nALSpells < 8) ||
(nLevel >= 32 && nLevel < 36 && nALSpells < 7) ||
(nLevel >= 28 && nLevel < 32 && nALSpells < 6) ||
(nLevel >= 24 && nLevel < 28 && nALSpells < 5) ||
(nLevel >= 16 && nLevel < 24 && nALSpells < 4) ||
(nLevel >= 11 && nLevel < 16 && nALSpells < 3) ||
(nLevel >= 6 && nLevel < 11 && nALSpells < 2) ||
(nLevel >= 3 && nLevel < 6 && nALSpells < 1))
{
// Mark the class for which the PC is to gain powers and start the conversation
SetLocalInt(oPC, "SpellGainClass", CLASS_TYPE_WARMAGE);
SetLocalInt(oPC, "SpellbookMinSpelllevel", nMinLevel);
SetLocalInt(oPC, "AdvancedLearning", 1);
StartDynamicConversation("prc_s_spellgain", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
return TRUE;
}
}
else if(nClass == CLASS_TYPE_NIGHTSTALKER && nALSpells < (nLevel+1)/6)//one every 6 levels starting at 5th
{
// Mark the class for which the PC is to gain powers and start the conversation
SetLocalInt(oPC, "SpellGainClass", CLASS_TYPE_NIGHTSTALKER);
SetLocalInt(oPC, "SpellbookMinSpelllevel", nMinLevel);
SetLocalInt(oPC, "AdvancedLearning", 1);
StartDynamicConversation("prc_s_spellgain", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
return TRUE;
}
return FALSE;
}
int CheckMissingUtterances(object oPC, int nClass, int nLexicon)
{
int nLevel = GetLevelByClass(nClass, oPC);
if(!nLevel)
return FALSE;
int nCurrentUtterances = GetUtteranceCount(oPC, nClass, nLexicon);
int nMaxUtterances = GetMaxUtteranceCount(oPC, nClass, nLexicon);
if(DEBUG) DoDebug("CheckMissingUtterances(" + IntToString(nClass) + ", " + IntToString(nLexicon) + ", " + GetName(oPC) + ") = " + IntToString(nCurrentUtterances) + ", " + IntToString(nMaxUtterances));
if(nCurrentUtterances < nMaxUtterances)
{
// Mark the class for which the PC is to gain Utterances and start the conversation
SetLocalInt(oPC, "nClass", nClass);
StartDynamicConversation("true_utterconv", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
return TRUE;
}
return FALSE;
}
int CheckMissingManeuvers(object oPC, int nClass)
{
int nLevel = GetLevelByClass(nClass, oPC);
if(!nLevel)
return FALSE;
int nCurrentManeuvers = GetManeuverCount(oPC, nClass, MANEUVER_TYPE_MANEUVER);
int nMaxManeuvers = GetMaxManeuverCount(oPC, nClass, MANEUVER_TYPE_MANEUVER);
int nCurrentStances = GetManeuverCount(oPC, nClass, MANEUVER_TYPE_STANCE);
int nMaxStances = GetMaxManeuverCount(oPC, nClass, MANEUVER_TYPE_STANCE);
if(nCurrentManeuvers < nMaxManeuvers || nCurrentStances < nMaxStances)
{
// Mark the class for which the PC is to gain powers and start the conversation
SetLocalInt(oPC, "nClass", nClass);
StartDynamicConversation("tob_moveconv", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
return TRUE;
}
return FALSE;
}
int CheckMissingMysteries(object oPC, int nClass)
{
int nLevel = GetLevelByClass(nClass, oPC);
if(!nLevel)
return FALSE;
int nCurrentMysteries = GetMysteryCount(oPC, nClass);
int nMaxMysteries = GetMaxMysteryCount(oPC, nClass);
if(nCurrentMysteries < nMaxMysteries)
{
// Mark the class for which the PC is to gain powers and start the conversation
SetLocalInt(oPC, "nClass", nClass);
StartDynamicConversation("shd_mystconv", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
return TRUE;
}
return FALSE;
}
//AMS Compatibility functions - xwarren:
void CopyAMSArray(object oPC, object oAMSToken, int nClass, string sArray, int nMin, int nMax, int nLoopSize = 100)
{
string sFile = GetFileForClass(nClass);
int i = nMin;
while(i < nMin + nLoopSize && i < nMax)
{
int nSpellbookID = persistant_array_get_int(oPC, sArray, i);
int nSpell = StringToInt(Get2DACache(sFile, "RealSpellID", nSpellbookID));
if(DEBUG) DoDebug("Copying spell "+IntToString(nSpell));
array_set_int(oAMSToken, sArray, i, nSpell);
i++;
}
if(i < nMax)
DelayCommand(0.0, CopyAMSArray(oPC, oAMSToken, nClass, sArray, i, nMax));
}
void DoBuckUpAMS(object oPC, int nClass, string sSpellbook, object oHideToken, object oAMSToken)
{
if(DEBUG) DoDebug("Creating buck-up copy of "+sSpellbook);
if(array_exists(oAMSToken, sSpellbook))
array_delete(oAMSToken, sSpellbook);
array_create(oAMSToken, sSpellbook);
int nSize = persistant_array_get_size(oPC, sSpellbook);
DelayCommand(0.0, CopyAMSArray(oPC, oAMSToken, nClass, sSpellbook, 0, nSize));
}
void AMSCompatibilityCheck(object oPC)
{
//Get an extra hide token with amagsys info
object oAMSToken = GetHideToken(oPC, TRUE);
object oHideToken = GetHideToken(oPC); //ebonfowl: no longer used but I'm leaving it to not have to edit other functions
int i;
for(i = 1; i <= 8; i++)
{
int nClass = GetClassByPosition(i, oPC);
string sSpellbook;
int nSpellbookType = GetSpellbookTypeForClass(nClass);
if(nSpellbookType == SPELLBOOK_TYPE_SPONTANEOUS)
{
sSpellbook = "Spellbook"+IntToString(nClass);
int nSize1 = persistant_array_get_size(oPC, sSpellbook);
int nSize2 = array_get_size(oAMSToken, sSpellbook);
if(nSize1 > nSize2)
DelayCommand(0.1f, DoBuckUpAMS(oPC, nClass, sSpellbook, oHideToken, oAMSToken));
}
else if(nSpellbookType == SPELLBOOK_TYPE_PREPARED)
{
int j;
for(j = 0; j <= 9; j++)
{
sSpellbook = "Spellbook_Known_"+IntToString(nClass)+"_"+IntToString(j);
int nSize1 = persistant_array_get_size(oPC, sSpellbook);
int nSize2 = array_get_size(oAMSToken, sSpellbook);
if(nSize1 > nSize2)
DelayCommand(0.1f, DoBuckUpAMS(oPC, nClass, sSpellbook, oHideToken, oAMSToken));
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,63 +0,0 @@
//::///////////////////////////////////////////////
//:: Power Attack NUI
//:: hp_pa_chatscript
//:://////////////////////////////////////////////
/*
A OnChat script that parses what is said and opens the power attack NUI
if provided /pa. Otherwise if /pa x is provided run the command directly
*/
//:://////////////////////////////////////////////
//:: Created By: Rakiov
//:: Created On: 22.05.2005
//:://////////////////////////////////////////////
#include "nw_inc_nui"
#include "hp_pa_view"
#include "hp_string_util"
void main()
{
// Get current player
object oPlayer = GetPCChatSpeaker();
if (!GetIsPC(oPlayer))
{
return;
}
// get current player message and split it up into a list
string sCommand = GetPCChatMessage();
json sCommandSplit = StringSplit(sCommand);
if(JsonGetLength(sCommandSplit) > 0)
{
string firstWord = JsonGetString(JsonArrayGet(sCommandSplit, 0));
// if first word is /pa we are using the power attack interface
if(firstWord == "/pa")
{
if(JsonGetLength(sCommandSplit) >= 2)
{
//if a parameter is given then run the power attack command directly.
string param1 = JsonGetString(JsonArrayGet(sCommandSplit, 1));
int paAmount = StringToInt(param1);
SetLocalInt(oPlayer, "PRC_PowerAttack_Level", paAmount);
ExecuteScript("hp_pa_script", oPlayer);
// update the NUI so it is in sync
int nToken = NuiFindWindow(oPlayer, NUI_PRC_POWER_ATTACK_WINDOW);
if (nToken != 0)
{
NuiSetBind(oPlayer, nToken, NUI_PRC_PA_TEXT_BIND, JsonString(IntToString(paAmount)));
}
}
else
{
// if no param is given then open the NUI
NuiPRCPowerAttackView(oPlayer);
}
// clear message from chat
SetPCChatMessage();
}
}
}