2025/11/30 Update
Moved PRC8 notes into DevNotes. Updated Eternal Blade TLK to explain abilities better. Updated Werewolf to use "monk" gloves when they exist. Added PRC switch to allow Wildshapes to always merge the arms slot. Clicking on a spell effect now opens the spell effect NUI. (@Rakiov)) Added prc_onplayergui event script for spell effect handling. (@Rakiov) Added prc_nui_sd_event and prc_nui_dur_view to handle displaying spell durations. (@Rakiov) Corrected typo in switch name for PRC_CRAFT_POISON_USE_INGREDIENTS Allowed mindblade to work with Vow of Poverty. Eternal Blade - Island in TIme now has a VFX, looks slightly better. Eternal Blade - Guided Strike now functions. Time Stands Still now has an impact VFX. Added optional PRC_ALLOWED_TO_REMOVE_FRIENDLY_SPELLS and PRC_ALLOWED_TO_SEE_HOSTILE_SPELLS switches for the spell effect view window.
This commit is contained in:
@@ -157,7 +157,12 @@ void main()
|
||||
for (nSlot=0; nSlot < 13; nSlot++) //All but creatures slots
|
||||
{
|
||||
oItem=GetItemInSlot(nSlot, oPC);
|
||||
if (!(GetTag(oItem) == "xp1_mystrashand") && !(GetTag(oItem) == "H2_SenseiAmulet"))
|
||||
if (!(GetTag(oItem) == "xp1_mystrashand")
|
||||
&& !(GetTag(oItem) == "H2_SenseiAmulet")
|
||||
&& !(GetResRef(oItem) == "prc_sk_mblade_bs")
|
||||
&& !(GetResRef(oItem) == "prc_sk_mblade_th")
|
||||
&& !(GetResRef(oItem) == "prc_sk_mblade_ss")
|
||||
&& !(GetResRef(oItem) == "prc_sk_mblade_ls"))
|
||||
{
|
||||
if((GetIsItemPropertyValid(GetFirstItemProperty(oItem)) && !(GetItemPropertyTag(GetFirstItemProperty(oItem)) == "Tag_PRC_OnHitKeeper")
|
||||
&& !(nSlot == 4 || nSlot == 5)) //Check if it is magical (all items but on the hands)
|
||||
@@ -210,7 +215,12 @@ void main()
|
||||
&& !(GetItemPropertyTag(eCheckIP) == "Sanctify4")) iMagic = 1;
|
||||
eCheckIP = GetNextItemProperty(oItem);
|
||||
}
|
||||
if (!(GetTag(oItem) == "xp1_mystrashand") && !(GetTag(oItem) == "H2_SenseiAmulet"))
|
||||
if (!(GetTag(oItem) == "xp1_mystrashand")
|
||||
&& !(GetTag(oItem) == "H2_SenseiAmulet")
|
||||
&& !(GetResRef(oItem) == "prc_sk_mblade_bs")
|
||||
&& !(GetResRef(oItem) == "prc_sk_mblade_th")
|
||||
&& !(GetResRef(oItem) == "prc_sk_mblade_ss")
|
||||
&& !(GetResRef(oItem) == "prc_sk_mblade_ls"))
|
||||
{
|
||||
if((IPGetIsMeleeWeapon(oItem) || GetWeaponRanged(oItem)) && (iMagic || !iWeaponAllowed)) //Check if weapon is magical or not on allowed list
|
||||
{
|
||||
|
||||
@@ -1429,7 +1429,7 @@ void main()
|
||||
}
|
||||
case STAGE_CONFIRM_POISON:
|
||||
{
|
||||
int bIngredients = GetPRCSwitch(PRC_CRAFT_POISON_USE_INGREDIENST);
|
||||
int bIngredients = GetPRCSwitch(PRC_CRAFT_POISON_USE_INGREDIENTS);
|
||||
string sIngr1Name = Get2DACache("prc_craft_poison", "Ingr1Name", nLine);
|
||||
string sIngr2Name = Get2DACache("prc_craft_poison", "Ingr2Name", nLine);
|
||||
string sCost = Get2DACache("prc_craft_poison", "GoldCost", nLine);
|
||||
@@ -2046,7 +2046,7 @@ void main()
|
||||
}
|
||||
else if(nChoice == CHOICE_CONFIRM)
|
||||
{
|
||||
int bIngredients = GetPRCSwitch(PRC_CRAFT_POISON_USE_INGREDIENST);
|
||||
int bIngredients = GetPRCSwitch(PRC_CRAFT_POISON_USE_INGREDIENTS);
|
||||
int nCost = StringToInt(Get2DACache("prc_craft_poison", "GoldCost", nLine));
|
||||
int nPCGold = GetGold(oPC);
|
||||
object oIngr1, oIngr2;
|
||||
|
||||
296
nwn/nwnprc/trunk/scripts/prc_nui_dur_view.nss
Normal file
296
nwn/nwnprc/trunk/scripts/prc_nui_dur_view.nss
Normal file
@@ -0,0 +1,296 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: PRC Spell Duration NUI View
|
||||
//:: prc_nui_dur_view
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
This is the logic for the Spell Duration NUI
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Rakiov
|
||||
//:: Created On: 28.11.2025
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "nw_inc_nui"
|
||||
#include "prc_nui_consts"
|
||||
#include "prc_nui_com_inc"
|
||||
|
||||
int IsAllowedToRemoveSpell(effect selectedEffect)
|
||||
{
|
||||
object creator = GetEffectCreator(selectedEffect);
|
||||
if (GetPRCSwitch(PRC_ALLOWED_TO_REMOVE_FRIENDLY_SPELLS))
|
||||
{
|
||||
int spellId = GetEffectSpellId(selectedEffect);
|
||||
int hostileSetting = StringToInt(Get2DACache("spells", "HostileSetting", spellId));
|
||||
if (!hostileSetting && !GetIsEnemy(creator))
|
||||
return TRUE;
|
||||
}
|
||||
else if (creator == OBJECT_SELF)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
string ConvertDurationToString(int duration)
|
||||
{
|
||||
if (duration == -1)
|
||||
{
|
||||
return "--:--:--";
|
||||
}
|
||||
int seconds = duration % 60;
|
||||
int minutes = duration / 60;
|
||||
int hours = minutes / 60;
|
||||
minutes = (minutes % 60);
|
||||
|
||||
string totalTime;
|
||||
if ((hours / 10) == 0)
|
||||
{
|
||||
totalTime += "0";
|
||||
}
|
||||
totalTime += IntToString(hours);
|
||||
totalTime += ":";
|
||||
if ((minutes / 10) == 0)
|
||||
{
|
||||
totalTime += "0";
|
||||
}
|
||||
totalTime += IntToString(minutes);
|
||||
totalTime += ":";
|
||||
if ((seconds / 10) == 0)
|
||||
{
|
||||
totalTime += "0";
|
||||
}
|
||||
totalTime += IntToString(seconds);
|
||||
|
||||
return totalTime;
|
||||
}
|
||||
|
||||
int UpdateBindsAndCheckRefresh(int nuiToken)
|
||||
{
|
||||
json spellList = GetLocalJson(OBJECT_SELF, NUI_DURATION_TRACKED_SPELLS);
|
||||
int totalEffects = JsonGetLength(spellList);
|
||||
effect selectedEffect = GetFirstEffect(OBJECT_SELF);
|
||||
json updatedSpells = JsonObject();
|
||||
|
||||
while (GetIsEffectValid(selectedEffect))
|
||||
{
|
||||
int spellId = GetEffectSpellId(selectedEffect);
|
||||
json spellFound = JsonObjectGet(spellList, IntToString(spellId));
|
||||
if (spellFound != JsonNull())
|
||||
{
|
||||
json hasBeenUpdated = JsonObjectGet(updatedSpells, IntToString(spellId));
|
||||
if (hasBeenUpdated == JsonNull())
|
||||
{
|
||||
int durationRem = GetEffectDurationRemaining(selectedEffect);
|
||||
int durationType = GetEffectDurationType(selectedEffect);
|
||||
string duration;
|
||||
if (durationType == DURATION_TYPE_PERMANENT)
|
||||
durationRem = -1;
|
||||
duration = ConvertDurationToString(durationRem);
|
||||
|
||||
NuiSetBind(OBJECT_SELF, nuiToken, NUI_SPELL_DURATION_BASE_BIND + IntToString(spellId), JsonString(duration));
|
||||
spellList = JsonObjectSet(spellList, IntToString(spellId), JsonInt(durationRem));
|
||||
updatedSpells = JsonObjectSet(updatedSpells, IntToString(spellId), JsonInt(TRUE));
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
string effectCreator = GetName(GetEffectCreator(selectedEffect));
|
||||
if (effectCreator != "prc_2da_cache" && effectCreator != "base_prc_skin")
|
||||
{
|
||||
updatedSpells = JsonObjectSet(updatedSpells, IntToString(spellId), JsonInt(TRUE));
|
||||
}
|
||||
}
|
||||
selectedEffect = GetNextEffect(OBJECT_SELF);
|
||||
}
|
||||
if (JsonGetLength(updatedSpells) == totalEffects)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
json CreateEffectEntry(effect selectedEffect)
|
||||
{
|
||||
json jRow = JsonArray();
|
||||
json jTitle;
|
||||
|
||||
int spellId;
|
||||
int remainingDur;
|
||||
|
||||
// Spell Icon
|
||||
json spellIcon = JsonNull();
|
||||
if (GetIsEffectValid(selectedEffect))
|
||||
{
|
||||
spellId = GetEffectSpellId(selectedEffect);
|
||||
int featId = StringToInt(Get2DACache("spells", "FeatID", spellId));
|
||||
spellIcon = GetSpellIcon(spellId, featId);
|
||||
}
|
||||
if (spellIcon == JsonNull())
|
||||
{
|
||||
jTitle = NuiText(JsonString(""), FALSE, NUI_SCROLLBARS_NONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
jTitle = NuiImage(spellIcon, JsonInt(NUI_ASPECT_FIT), JsonInt(NUI_HALIGN_LEFT), JsonInt(NUI_VALIGN_TOP));
|
||||
}
|
||||
jTitle = NuiWidth(jTitle, 32.0f);
|
||||
jTitle = NuiHeight(jTitle, 32.0f);
|
||||
jRow = JsonArrayInsert(jRow, jTitle);
|
||||
|
||||
// Get Name of Spell
|
||||
string spellName;
|
||||
if (GetIsEffectValid(selectedEffect))
|
||||
{
|
||||
spellId = GetEffectSpellId(selectedEffect);
|
||||
spellName = GetSpellName(spellId);
|
||||
json spellList = GetLocalJson(OBJECT_SELF, NUI_DURATION_TRACKED_SPELLS);
|
||||
if (spellList == JsonNull())
|
||||
spellList = JsonObject();
|
||||
|
||||
remainingDur = GetEffectDurationRemaining(selectedEffect);
|
||||
spellList = JsonObjectSet(spellList, IntToString(spellId), JsonInt(remainingDur));
|
||||
SetLocalJson(OBJECT_SELF, NUI_DURATION_TRACKED_SPELLS, spellList);
|
||||
|
||||
if (DEBUG) DoDebug("Tracked spellIds for duration NUI");
|
||||
if (DEBUG) DoDebug(JsonDump(spellList, 2));
|
||||
}
|
||||
else
|
||||
{
|
||||
spellName = "Name";
|
||||
}
|
||||
jTitle = NuiText(JsonString(spellName), FALSE, NUI_SCROLLBARS_NONE);
|
||||
jRow = JsonArrayInsert(jRow, jTitle);
|
||||
|
||||
// Get Creator of Spell
|
||||
string creator;
|
||||
if (GetIsEffectValid(selectedEffect))
|
||||
{
|
||||
creator = GetName(GetEffectCreator(selectedEffect));
|
||||
}
|
||||
else
|
||||
{
|
||||
creator = "Creator";
|
||||
}
|
||||
jTitle = NuiText(JsonString(creator), FALSE, NUI_SCROLLBARS_NONE);
|
||||
jRow = JsonArrayInsert(jRow, jTitle);
|
||||
|
||||
// Get Duration
|
||||
if (GetIsEffectValid(selectedEffect))
|
||||
{
|
||||
jTitle = NuiText(NuiBind(NUI_SPELL_DURATION_BASE_BIND + IntToString(spellId)), FALSE, NUI_SCROLLBARS_NONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
jTitle = NuiText(JsonString("Duration"), FALSE, NUI_SCROLLBARS_NONE);
|
||||
}
|
||||
|
||||
|
||||
jRow = JsonArrayInsert(jRow, jTitle);
|
||||
|
||||
if (GetIsEffectValid(selectedEffect))
|
||||
{
|
||||
jTitle = NuiId(NuiButtonImage(JsonString("nui_close")), NUI_SPELL_DURATION_SPELLID_BASE_CANCEL_BUTTON + IntToString(spellId));
|
||||
jTitle = NuiEnabled(jTitle, JsonInt(IsAllowedToRemoveSpell(selectedEffect)));
|
||||
jTitle = NuiWidth(jTitle, 32.0f);
|
||||
jTitle = NuiHeight(jTitle, 32.0f);
|
||||
jRow = JsonArrayInsert(jRow, jTitle);
|
||||
}
|
||||
|
||||
return NuiRow(jRow);
|
||||
}
|
||||
|
||||
int ShouldCreateEffectEntry(effect selectedEffect)
|
||||
{
|
||||
string effectCreator = GetName(GetEffectCreator(selectedEffect));
|
||||
if (effectCreator == "prc_2da_cache" || effectCreator == "base_prc_skin")
|
||||
return FALSE;
|
||||
|
||||
json spellList = GetLocalJson(OBJECT_SELF, NUI_DURATION_TRACKED_SPELLS);
|
||||
if (spellList == JsonNull())
|
||||
return TRUE;
|
||||
int spellId = GetEffectSpellId(selectedEffect);
|
||||
|
||||
if (!GetPRCSwitch(PRC_ALLOWED_TO_SEE_HOSTILE_SPELLS))
|
||||
{
|
||||
int hostileSpell = StringToInt(Get2DACache("spells", "HostileSetting", spellId));
|
||||
if (hostileSpell)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
json spellExists = JsonObjectGet(spellList, IntToString(spellId));
|
||||
|
||||
if (spellExists != JsonNull())
|
||||
return FALSE;
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
int recreate = FALSE;
|
||||
int windowId = NuiFindWindow(OBJECT_SELF, DURATION_NUI_WINDOW_ID);
|
||||
if (windowId)
|
||||
{
|
||||
if (UpdateBindsAndCheckRefresh(windowId))
|
||||
{
|
||||
if (DEBUG) DoDebug("Spell added/removed, updating duration NUI.");
|
||||
DeleteLocalJson(OBJECT_SELF, NUI_DURATION_TRACKED_SPELLS);
|
||||
NuiDestroy(OBJECT_SELF, windowId);
|
||||
recreate = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int manualOpen = StringToInt(GetScriptParam(NUI_DURATION_MANUALLY_OPENED_PARAM));
|
||||
if (!manualOpen)
|
||||
{
|
||||
DeleteLocalJson(OBJECT_SELF, NUI_DURATION_TRACKED_SPELLS);
|
||||
return;
|
||||
}
|
||||
else
|
||||
recreate = TRUE;
|
||||
}
|
||||
|
||||
if (recreate)
|
||||
{
|
||||
json jRoot = JsonArray();
|
||||
effect eNull;
|
||||
jRoot = JsonArrayInsert(jRoot, CreateEffectEntry(eNull));
|
||||
|
||||
effect selectedEffect = GetFirstEffect(OBJECT_SELF);
|
||||
while (GetIsEffectValid(selectedEffect))
|
||||
{
|
||||
if (ShouldCreateEffectEntry(selectedEffect))
|
||||
jRoot = JsonArrayInsert(jRoot, CreateEffectEntry(selectedEffect));
|
||||
selectedEffect = GetNextEffect(OBJECT_SELF);
|
||||
}
|
||||
|
||||
jRoot = NuiCol(jRoot);
|
||||
string title = "Spell Duration";
|
||||
|
||||
// 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"), JsonBool(FALSE), NuiBind("closable"), NuiBind("transparent"), NuiBind("border"));
|
||||
|
||||
// finally create it and it'll return us a non-zero token.
|
||||
int nToken = NuiCreate(OBJECT_SELF, nui, DURATION_NUI_WINDOW_ID);
|
||||
UpdateBindsAndCheckRefresh(nToken);
|
||||
|
||||
// get the geometry of the window in case we opened this before and have a
|
||||
// preference for location
|
||||
json geometry = NuiRect(-1.0f,-1.0f, 748.0f, 535.0f);
|
||||
|
||||
// Set the binds to their default values
|
||||
NuiSetBind(OBJECT_SELF, nToken, "geometry", geometry);
|
||||
NuiSetBind(OBJECT_SELF, nToken, "resizable", JsonBool(TRUE));
|
||||
NuiSetBind(OBJECT_SELF, nToken, "closable", JsonBool(TRUE));
|
||||
NuiSetBind(OBJECT_SELF, nToken, "transparent", JsonBool(FALSE));
|
||||
NuiSetBind(OBJECT_SELF, nToken, "border", JsonBool(TRUE));
|
||||
}
|
||||
|
||||
int dontLoop = StringToInt(GetScriptParam(NUI_DURATION_NO_LOOP_PARAM));
|
||||
if (!dontLoop)
|
||||
DelayCommand(1.0f, ExecuteScript("prc_nui_dur_view"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
51
nwn/nwnprc/trunk/scripts/prc_nui_sd_event.nss
Normal file
51
nwn/nwnprc/trunk/scripts/prc_nui_sd_event.nss
Normal file
@@ -0,0 +1,51 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: PRC Spell Duration NUI Events
|
||||
//:: prc_nui_sd_event
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
This is the logic that handles the events for the Spell Duration NUI
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Rakiov
|
||||
//:: Created On: 29.11.2025
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_nui_lv_inc"
|
||||
|
||||
void RemoveSpellEffectBySpellID(int spellId, object oPC)
|
||||
{
|
||||
effect selectedEffect = GetFirstEffect(oPC);
|
||||
while (GetIsEffectValid(selectedEffect))
|
||||
{
|
||||
int selectedSpellId = GetEffectSpellId(selectedEffect);
|
||||
if (selectedSpellId == spellId)
|
||||
RemoveEffect(oPC, selectedEffect);
|
||||
selectedEffect = GetNextEffect(oPC);
|
||||
}
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
object oPlayer = NuiGetEventPlayer();
|
||||
int nToken = NuiGetEventWindow();
|
||||
string sEvent = NuiGetEventType();
|
||||
string sElement = NuiGetEventElement();
|
||||
string sWindowId = NuiGetWindowId(oPlayer, nToken);
|
||||
|
||||
// Not a mouseup event, nothing to do.
|
||||
if (sEvent != "mouseup")
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// we clicked a spell circle, set the selected circle to the new one and refresh the window
|
||||
if (FindSubString(sElement, NUI_SPELL_DURATION_SPELLID_BASE_CANCEL_BUTTON) >= 0)
|
||||
{
|
||||
int spellId = StringToInt(RegExpReplace(NUI_SPELL_DURATION_SPELLID_BASE_CANCEL_BUTTON, sElement, ""));
|
||||
RemoveSpellEffectBySpellID(spellId, oPlayer);
|
||||
SetScriptParam(NUI_DURATION_NO_LOOP_PARAM, "1");
|
||||
ExecuteScript("prc_nui_dur_view", oPlayer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
33
nwn/nwnprc/trunk/scripts/prc_onplayergui.nss
Normal file
33
nwn/nwnprc/trunk/scripts/prc_onplayergui.nss
Normal file
@@ -0,0 +1,33 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: PRC On Player GUI
|
||||
//:: prc_onplayergui
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
This is the logic for the On Player GUI event script
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Rakiov
|
||||
//:: Created On: 28.11.2025
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "nw_inc_nui"
|
||||
#include "prc_nui_consts"
|
||||
|
||||
void main()
|
||||
{
|
||||
// Event variables
|
||||
object oPlayer = GetLastGuiEventPlayer();
|
||||
int nEventType = GetLastGuiEventType();
|
||||
int nEventInteger = GetLastGuiEventInteger();
|
||||
object oEventObject = GetLastGuiEventObject();
|
||||
|
||||
if (nEventType == GUIEVENT_EFFECTICON_CLICK)
|
||||
{
|
||||
int windowId = NuiFindWindow(oPlayer, DURATION_NUI_WINDOW_ID);
|
||||
if (!windowId)
|
||||
{
|
||||
SetScriptParam(NUI_DURATION_MANUALLY_OPENED_PARAM, "1");
|
||||
ExecuteScript("prc_nui_dur_view", oPlayer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,6 +34,9 @@ void main()
|
||||
if (sWindowId == NUI_LEVEL_UP_WINDOW_ID)
|
||||
ExecuteScript("prc_nui_lv_event");
|
||||
|
||||
if (sWindowId == DURATION_NUI_WINDOW_ID)
|
||||
ExecuteScript("prc_nui_sd_event");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user