diff --git a/PRC8_ChangeLog.txt b/PRC8_ChangeLog.txt
index 9cebbdcc..8188fa1f 100644
--- a/PRC8_ChangeLog.txt
+++ b/PRC8_ChangeLog.txt
@@ -1,3 +1,47 @@
+Commit: Jaysyn904
+Date: Sun May 24
+
+Warforged Scouts can take Warforged Juggernaut.
+FEAT_EXTRA_GRANTED_MANEUVER is for Crusaders, not Swordsages.
+FEAT_EXTRA_GRANTED_MANEUVER now shows all 5 granted maneuvers after 19th lvl.
+Mirror Image onCastAt script now uses PRCGetCasterLevel()
+Summon Hamatula now uses PRCGetCasterLevel()
+Spiritual Weapon now uses PRCGetCasterLevel()
+Heal & Harm now SignalEvent on placeables. DEITY$ only knows how many modules this broke.
+Hospitaler had incorrect epic bonus feat progression
+Hospitaler had incorrect bonus feat list.
+Hospitaler was missing Ride from its skill list.
+Runecaster had incorrect epic bonus feat progression
+Runecaster had incorrect bonus feat list.
+Warmage Edge should work with magic staves.
+Added PRC_RETH_DEKALA_AURA_HOSTILE_ONLY switch and modified Vilefire aura to use it.
+Spells that use DoCone() should now respect Mastery of Shaping.
+Removed Hospitaler from list of classes that use the Fighter Bonus Feat list.
+ExtraordinarySpellAim() now handles persistent AoEs
+Acid Fog, Blade Barrier, Creeping Doom, Grease, Incindiary Cloud, Wall of Fire, Wall of Frost, Prismatic Wall, Prismatic Sphere, Sleet Storm and Spike Growth now respect Extraordinary Spell Aim.
+Archivist wasn't specifically set as a divine class in classes.2da.
+Added Create Infusion & Craft Scepter to the Archvist's feat 2da.
+The Lich class is now getting the correct level based stat updates.
+Fixed Create Infusion and Craft Scepter to use character level instead of caster level in feat.2da.
+Added default level up package for Scout.
+Added default level up package for Swashbuckler.
+Fixed the prc cache creature to be cutscene invisible, regardless of which function is creating it.
+Added special handling in PRCGetLastSpellCastClass() for Bard/Sublime Chord to fix the DC issue.
+Added more CEP2 wings to PRCIsFlying()
+Added X2_CI_CRAFTSCEPTER_FEAT_ID to CIGetIsSpellRestrictedFromCraftFeat()
+Fixed Small Shield handling in ArcaneSpellFailure()
+Fixed Troglodyte's racial Stench ability.
+Vow of Poverty dialog no longer shows up when you rest & chose to skil the feat for the previous level.
+Swashbuckler Grace now supports 60 levels.
+Swashbuckler Dodge now respects Daring Outlaw and supports 60 levels.
+Blinding Glory isn't a Glory Domain spell in the PRC8.
+Fixed TLK typo in Knight (Cavalier) package description.
+Fixed Contingent Resurrection from stealing epic spell slots.
+Fixed bonus spell slot itemprops for newspellbook casters. (@lightbeard)
+Fixed taking Ability Focus: Eldritch Blast from bricking a first level character.
+Archivist should use INT for epic spell DCs, not WIS.
+Fixed Sublime Chord epic spell DCs.
+
Commit: Jaysyn904
Date: Sat May 2 12:46:30 2026
diff --git a/nwn/nwnprc/trunk/2das/feat.2da b/nwn/nwnprc/trunk/2das/feat.2da
index 6ddb57c6..15f271f3 100644
--- a/nwn/nwnprc/trunk/2das/feat.2da
+++ b/nwn/nwnprc/trunk/2das/feat.2da
@@ -2473,7 +2473,7 @@
2469 TribalFrenzy 16825723 16825718 ife_cfrenzy **** **** **** **** **** **** **** **** **** **** 0 0 0 **** **** 1597 **** 1 -1 **** 1 **** **** **** **** **** **** **** **** **** **** 4 **** **** **** **** **** 0 0
2470 AbilityBoost 16825719 16825720 ife_X2GrCha1 **** **** **** **** **** **** **** **** **** **** 0 0 0 **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** FEAT_ALERTNESS 5 **** **** **** **** **** 0 1
2471 DevotedBodyguards 16825721 16825722 ife_epAlliedMa **** **** **** **** **** **** **** **** **** **** 0 0 0 **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** FEAT_ALERTNESS 5 **** **** **** **** **** 0 1
-2472 AttuneGem 16822665 16822666 ife_X2PlnrTurn **** **** **** 13 **** **** **** **** **** **** 0 0 1 **** **** 1781 **** 1 -1 **** 0 **** **** **** **** **** **** **** **** **** **** 4 **** **** **** **** **** 0 0
+2472 AttuneGem 16822665 16822666 ife_X2PlnrTurn **** **** **** 13 **** **** **** **** **** **** 0 0 1 **** **** 1781 **** 1 -1 **** 0 **** **** **** **** **** **** **** **** **** **** 4 **** 5 **** **** **** 0 0
2473 WidenSpell 16822648 16822649 ife_X2PlnrTurn **** **** **** **** **** **** **** **** **** **** 0 0 0 **** **** 1637 **** 1 35 **** 1 **** **** **** **** **** **** **** **** **** **** 4 **** **** **** **** **** 0 0
2474 EnlargeSpellArea 16822650 16822651 ife_legendaryart **** **** **** **** **** **** **** **** **** **** 0 0 0 **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** FEAT_ALERTNESS 5 **** **** **** **** **** 0 1
2475 StunningStrike 16827037 16827038 ife_X2SpTghBne **** **** **** **** **** **** **** **** **** **** 0 0 0 **** **** 2470 **** 1 5 **** **** **** **** **** **** **** **** **** **** **** **** 4 **** **** **** **** **** 0 1
diff --git a/nwn/nwnprc/trunk/2das/spells.2da b/nwn/nwnprc/trunk/2das/spells.2da
index 619b5730..e797b9fb 100644
--- a/nwn/nwnprc/trunk/2das/spells.2da
+++ b/nwn/nwnprc/trunk/2das/spells.2da
@@ -1783,7 +1783,7 @@
1779 ShieldAlly 16827626 ife_mastelem T M 0 **** 0x03 prc_knght_shally **** **** **** **** **** **** 9 0 head **** vco_smhanevil01 **** sco_mehannatr01 vs_chant_ench_lm vs_chant_ench_lf self 0 **** **** **** **** 0 **** **** **** **** **** **** 0 **** **** **** **** **** 10 **** 3 **** 0 0 **** 0 2843 **** **** 0 **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
1780 ImprovedShieldAlly 16827628 ife_mastelem T M 0 **** 0x03 prc_knght_ishlly **** **** **** **** **** **** 9 0 head **** vco_smhanevil01 **** sco_mehannatr01 vs_chant_ench_lm vs_chant_ench_lf self 0 **** **** **** **** 0 **** **** **** **** **** **** 0 **** **** **** **** **** 10 **** 3 **** 0 0 **** 0 2844 **** **** 0 **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
1781 AttuneGem 16822665 is_divprot G L v **** 0x09 prc_radialbug **** **** **** **** **** **** 1 1500 hand **** vco_mehanodd02 vco_lgrinodd01 sco_lgrinodd01 vs_chant_conj_hm vs_chant_conj_hf out 1000 **** **** **** **** 0 **** **** **** **** **** **** 0 1782 1783 **** **** **** 15 **** 1 16828494 1 0 **** 0 2472 **** **** 0 **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
-1782 AttuneGemCraft 16822665 is_divprot G L v **** 0x09 prc_ft_attunegem **** **** **** **** **** **** 1 1500 hand **** vco_mehanelec02 vco_lgrinelec01 sco_lgrinelec01 vs_chant_conj_hm vs_chant_conj_hf out 1000 **** **** **** **** 0 **** **** **** **** **** **** 0 **** **** **** **** **** 15 1781 1 16828494 1 0 **** 0 392694184 **** **** 0 **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
+1782 AttuneGemCraft 16822665 is_divprot G L v **** 0x01 prc_ft_attunegem **** **** **** **** **** **** 1 1500 hand **** vco_mehanelec02 vco_lgrinelec01 sco_lgrinelec01 vs_chant_conj_hm vs_chant_conj_hf out 1000 **** **** **** **** 0 **** **** **** **** **** **** 0 **** **** **** **** **** 15 1781 1 16828494 1 0 **** 0 392694184 **** **** 0 **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
1783 AttuneGemCheckGem 16822665 is_curpfail G L v **** 0x09 prc_ft_attngemsl **** **** **** **** **** **** 1 1500 hand **** vco_mehanacid02 vco_lgrinacid01 sco_lgrinelec01 vs_chant_conj_hm vs_chant_conj_hf out 1000 **** **** **** **** 0 **** **** **** **** **** **** 0 **** **** **** **** **** 15 1781 1 16828494 1 0 **** 0 392759720 **** **** 0 **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
1784 SummonUndeadI 16847420 is_SumUndead1 C S vs 0x3a 0x2c sp_sum_undead **** 1 **** **** **** 1 1 1500 hand **** vco_mebalsonc01 **** sco_mebalsonc01 vs_chant_necr_lm vs_chant_necr_lf touch 1000 **** **** **** **** 0 **** **** **** **** **** **** 0 **** **** **** **** **** 15 **** 1 16847421 1 0 **** 0 **** **** **** 0 **** **** **** **** **** **** **** **** **** **** 1 **** **** **** **** **** **** ****
1785 SummonUndeadII 16847422 is_SumUndead2 C S vs 0x3a 0x2c sp_sum_undead **** 2 **** **** **** 2 2 1500 hand **** vco_mebalsonc01 **** sco_mebalsonc01 vs_chant_necr_lm vs_chant_necr_lf touch 1000 **** **** **** **** 0 **** **** **** **** **** **** 0 **** **** **** **** **** 15 **** 1 16847423 1 0 **** 0 **** **** **** 0 **** **** **** **** **** **** **** **** **** **** 2 **** **** **** **** **** **** ****
diff --git a/nwn/nwnprc/trunk/2das/vfx_persistent.2da b/nwn/nwnprc/trunk/2das/vfx_persistent.2da
index fa32c314..fe5906d6 100644
--- a/nwn/nwnprc/trunk/2das/vfx_persistent.2da
+++ b/nwn/nwnprc/trunk/2das/vfx_persistent.2da
@@ -204,7 +204,7 @@
200 VFX_PER_FOGFREEZE C 5 **** **** **** **** **** 0 **** vps_fogfreeze vps_fogfreeze vps_fogfreeze 5 10 5 3400 1100 1900 0 0.25 0.25 **** sps_fog_loop **** sps_fog 0.3 vps_fogfreeze_L vps_fogfreeze_L vps_fogfreeze_L
201 VFX_PER_FOGYELLOW C 5 **** **** **** **** **** 0 **** vps_fogyell vps_fogyell vps_fogyell 5 10 5 3400 1100 1900 0 0.25 0.25 **** sps_fog_loop **** sps_fog 0.3 vps_fogyell_L vps_fogyell_L vps_fogyell_L
202 VFX_PER_FOGPURPLE C 5 **** **** **** **** **** 0 **** vps_fogpurp vps_fogpurp vps_fogpurp 5 10 5 3400 1100 1900 0 0.25 0.25 **** sps_fog_loop **** sps_fog 0.3 vps_fogpurp_L vps_fogpurp_L vps_fogpurp_L
-203 AOE_PER_DAMNDARK C 6.7 **** **** sp_damn_darkA sp_damn_darkB **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
+203 AOE_PER_DAMNDARK C 6.7 **** **** sp_damng_darka sp_damng_darkb **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
204 VFX_MOB_BRILLIANT_EMANATION C 30.48 **** **** sp_brill_emanA sp_brill_emanB **** 0 **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
205 VFX_PER_UTTERDARK C 50 **** **** sp_utterdarkA sp_utterdarkB **** 0 844 **** **** **** **** **** **** **** **** **** **** **** **** sps_darkness **** **** **** **** **** **** ****
206 VFX_PER_ACHAIERAI C 3.048 **** **** sp_cloud_achai sp_cloud_achaiB **** 0 845 **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
diff --git a/nwn/nwnprc/trunk/include/prc_add_spell_dc.nss b/nwn/nwnprc/trunk/include/prc_add_spell_dc.nss
index b8ecd637..f138edee 100644
--- a/nwn/nwnprc/trunk/include/prc_add_spell_dc.nss
+++ b/nwn/nwnprc/trunk/include/prc_add_spell_dc.nss
@@ -690,7 +690,7 @@ int PRCGetSpellSaveDC(int nSpellID = -1, int nSchool = -1, object oCaster = OBJE
int PRCGetSaveDC(object oTarget, object oCaster, int nSpellID = -1)
{
- object oItem = GetSpellCastItem();
+ object oItem = PRCGetSpellCastItem();
if(nSpellID == -1)
nSpellID = PRCGetSpellId();
int nSchool = GetSpellSchool(nSpellID);
diff --git a/nwn/nwnprc/trunk/include/prc_x2_craft.nss b/nwn/nwnprc/trunk/include/prc_x2_craft.nss
index 46c24e81..887b65a0 100644
--- a/nwn/nwnprc/trunk/include/prc_x2_craft.nss
+++ b/nwn/nwnprc/trunk/include/prc_x2_craft.nss
@@ -1968,16 +1968,24 @@ int AttuneGem(object oTarget = OBJECT_INVALID, object oCaster = OBJECT_INVALID,
return TRUE; // tried item creation but do not know how to do it
}
- // No point scribing Gems from items, and its not allowed.
- if (oItem != OBJECT_INVALID)
- {
- FloatingTextStringOnCreature("You cannot attune a Gem from an item.", oCaster, FALSE);
- return TRUE;
- }
+ // Only allow arcane spellcasters
+ int nClass = PRCGetLastSpellCastClass();
+ if (!GetIsArcaneClass(nClass, oCaster))
+ {
+ FloatingTextStringOnCreature("Only arcane casters can attune gems.", oCaster, FALSE);
+ return TRUE;
+ }
+
+ // No point scribing Gems from items, and its not allowed.
+ if (oItem != OBJECT_INVALID)
+ {
+ FloatingTextStringOnCreature("You cannot attune a Gem from an item.", oCaster, FALSE);
+ return TRUE;
+ }
// oTarget here should be the gem. If it's not, fail.
if(!GetIsObjectValid(oTarget)) oTarget = PRCGetSpellTargetObject();
// Only accepts bioware gems & Craftable Natural Resources gems, but not gem dust.
- int bIsBioGem = (GetStringLeft(GetResRef(oTarget), 5) == "it_gem");
+ int bIsBioGem = (GetStringLeft(GetResRef(oTarget), 9) == "nw_it_gem");
int bIsCNRGem = (GetStringLeft(GetResRef(oTarget), 6) == "cnrgem");
int bIsDust = (GetStringLeft(GetResRef(oTarget), 10) == "cnrgemdust");
@@ -1987,21 +1995,12 @@ int AttuneGem(object oTarget = OBJECT_INVALID, object oCaster = OBJECT_INVALID,
return TRUE;
}
-/* if ((GetStringLeft(GetResRef(oTarget), 5) == "it_gem") || (GetStringLeft(GetResRef(oTarget), 6) == "cnrgem") && (GetStringLeft(GetResRef(oTarget), 10) != "cnrgemdust"))
- {
- FloatingTextStringOnCreature("Spell target is not a valid gem.", oCaster, FALSE);
- // And out we go
- return TRUE;
- } */
-
int nCaster = GetAlternativeCasterLevel(oCaster, PRCGetCasterLevel(oCaster));
int nDC = PRCGetSaveDC(oTarget, oCaster);
if(!nSpell) nSpell = PRCGetSpellId();
int nSpellLevel;
- if (PRCGetLastSpellCastClass() == CLASS_TYPE_CLERIC || PRCGetLastSpellCastClass() == CLASS_TYPE_UR_PRIEST) nSpellLevel = StringToInt(lookup_spell_cleric_level(nSpell));
- else if (PRCGetLastSpellCastClass() == CLASS_TYPE_DRUID) nSpellLevel = StringToInt(lookup_spell_druid_level(nSpell));
- else if (PRCGetLastSpellCastClass() == CLASS_TYPE_WIZARD || PRCGetLastSpellCastClass() == CLASS_TYPE_SORCERER) nSpellLevel = StringToInt(lookup_spell_level(nSpell));
+ if (PRCGetLastSpellCastClass() == CLASS_TYPE_WIZARD || PRCGetLastSpellCastClass() == CLASS_TYPE_SORCERER) nSpellLevel = StringToInt(lookup_spell_level(nSpell));
// If none of these work, check the innate level of the spell
if (nSpellLevel == 0) nSpellLevel = StringToInt(lookup_spell_innate(nSpell));
// Minimum level.
@@ -2034,13 +2033,13 @@ int AttuneGem(object oTarget = OBJECT_INVALID, object oCaster = OBJECT_INVALID,
if (!GetHasGPToSpend(oCaster, costs.nGoldCost))
{
- FloatingTextStringOnCreature("You do not have enough gold to scribe this Gem.", oCaster, FALSE);
+ FloatingTextStringOnCreature("You do not have enough gold to attue this Gem.", oCaster, FALSE);
// Since they don't have enough, the spell casts normally
return TRUE;
}
if (!GetHasXPToSpend(oCaster, costs.nXPCost) )
{
- FloatingTextStringOnCreature("You do not have enough experience to scribe this Gem.", oCaster, FALSE);
+ FloatingTextStringOnCreature("You do not have enough experience to attune this Gem.", oCaster, FALSE);
// Since they don't have enough, the spell casts normally
return TRUE;
}
@@ -2057,7 +2056,24 @@ int AttuneGem(object oTarget = OBJECT_INVALID, object oCaster = OBJECT_INVALID,
}
// Steal all the code from craft wand.
- int nPropID = IPGetIPConstCastSpellFromSpellID(nSpell);
+ //int nPropID = IPGetIPConstCastSpellFromSpellID(nSpell);
+
+ // Handle subradial spells - keep original for radial menu
+ int nSpellOriginal = nSpell;
+ int nSpellMaster = nSpellOriginal;
+ if (GetIsSubradialSpell(nSpellOriginal))
+ {
+ nSpellMaster = GetMasterSpellFromSubradial(nSpellOriginal);
+ }
+
+ // Prefer iprp mapping for original subradial, fallback to master
+ int nPropID = IPGetIPConstCastSpellFromSpellID(nSpellOriginal);
+ int nSpellUsedForIP = nSpellOriginal;
+ if (nPropID < 0)
+ {
+ nPropID = IPGetIPConstCastSpellFromSpellID(nSpellMaster);
+ nSpellUsedForIP = nSpellMaster;
+ }
// * GZ 2003-09-11: If the current spell cast is not acid fog, and
// * returned property ID is 0, bail out to prevent
@@ -2075,22 +2091,71 @@ int AttuneGem(object oTarget = OBJECT_INVALID, object oCaster = OBJECT_INVALID,
return TRUE;
}
- if (nPropID != -1)
+ if (nPropID != -1)
+ {
+ // Handle stack - reduce original stack by 1
+ int nOriginalStack = GetItemStackSize(oTarget);
+ if (nOriginalStack > 1)
+ SetItemStackSize(oTarget, nOriginalStack - 1);
+
+ // Create a NEW single gem in a work container to prevent auto-stacking
+ string sResRef = GetResRef(oTarget);
+ object oWorkContainer = IPGetIPWorkContainer(oCaster);
+ object oWorkGem = CreateItemOnObject(sResRef, oWorkContainer, 1);
+
+ // Add properties to the NEW gem only
+ itemproperty ipLevel = ItemPropertyCastSpellCasterLevel(nSpellUsedForIP, PRCGetCasterLevel());
+ AddItemProperty(DURATION_TYPE_PERMANENT,ipLevel, oWorkGem);
+ itemproperty ipMeta = ItemPropertyCastSpellMetamagic(nSpellUsedForIP, PRCGetMetaMagicFeat());
+ AddItemProperty(DURATION_TYPE_PERMANENT,ipMeta, oWorkGem);
+ itemproperty ipDC = ItemPropertyCastSpellDC(nSpellUsedForIP, PRCGetSaveDC(PRCGetSpellTargetObject(), OBJECT_SELF));
+ AddItemProperty(DURATION_TYPE_PERMANENT,ipDC, oWorkGem);
+
+ int nUseType = IP_CONST_CASTSPELL_NUMUSES_1_CHARGE_PER_USE;
+ if (nCharges == 1)
+ {
+ nUseType = IP_CONST_CASTSPELL_NUMUSES_2_CHARGES_PER_USE;
+ nCharges = 3;
+ }
+ itemproperty ipProp = ItemPropertyCastSpell(nPropID, nUseType);
+ AddItemProperty(DURATION_TYPE_PERMANENT, ipProp, oWorkGem);
+
+ SetItemCharges(oWorkGem, nCharges);
+ SetXP(oCaster, nNewXP);
+ TakeGoldFromCreature(costs.nGoldCost, oCaster, TRUE);
+
+ string sName;
+ sName = Get2DACache("spells", "Name", nSpellUsedForIP);
+ sName = "Gem of "+GetStringByStrRef(StringToInt(sName));
+ SetName(oWorkGem, sName);
+
+ // Copy the work gem to create the final attuned gem in caster's inventory
+ object oNewGem = CopyObject(oWorkGem, GetLocation(oCaster), oCaster, "prc_attunegem");
+
+ // Destroy the work gem
+ DestroyObject(oWorkGem, 0.1);
+
+ // If original stack was 1, destroy it too
+ if (nOriginalStack == 1)
+ DestroyObject(oTarget, 0.1);
+ }
+
+/* if (nPropID != -1)
{
- itemproperty ipLevel = ItemPropertyCastSpellCasterLevel(nSpell, PRCGetCasterLevel());
+ // Handle stack splitting - reduce original stack and create single gem to work with
+ int nOriginalStack = GetItemStackSize(oTarget);
+ if (nOriginalStack > 1)
+ {
+ SetItemStackSize(oTarget, nOriginalStack - 1);
+ oTarget = CreateItemOnObject(GetResRef(oTarget), oCaster, 1);
+ }
+
+ itemproperty ipLevel = ItemPropertyCastSpellCasterLevel(nSpell, PRCGetCasterLevel());
AddItemProperty(DURATION_TYPE_PERMANENT,ipLevel, oTarget);
itemproperty ipMeta = ItemPropertyCastSpellMetamagic(nSpell, PRCGetMetaMagicFeat());
AddItemProperty(DURATION_TYPE_PERMANENT,ipMeta, oTarget);
itemproperty ipDC = ItemPropertyCastSpellDC(nSpell, PRCGetSaveDC(PRCGetSpellTargetObject(), OBJECT_SELF));
AddItemProperty(DURATION_TYPE_PERMANENT,ipDC, oTarget);
-
-/* if (nCharges == 1) // This is to handle one use Gems so the spellhooking works
- {
- itemproperty ipProp = ItemPropertyCastSpell(nPropID,IP_CONST_CASTSPELL_NUMUSES_2_CHARGES_PER_USE);
- AddItemProperty(DURATION_TYPE_PERMANENT,ipProp, oTarget);
- // This is done so the item exists when it is used for the game to read data off of
- nCharges = 3;
- } */
int nUseType = IP_CONST_CASTSPELL_NUMUSES_1_CHARGE_PER_USE;
if (nCharges == 1)
@@ -2139,7 +2204,7 @@ int AttuneGem(object oTarget = OBJECT_INVALID, object oCaster = OBJECT_INVALID,
object oNewGem = CopyObject(oTarget, GetLocation(oCaster), oCaster, "prc_attunegem");
DestroyObject(oTarget, 0.1);
}
-
+ */
// If we have made it this far, they have crafted the Gem and the spell has been used up, so it returns false.
return FALSE;
}
diff --git a/nwn/nwnprc/trunk/include/x2_inc_spellhook.nss b/nwn/nwnprc/trunk/include/x2_inc_spellhook.nss
index 0ea543e5..5bac81dd 100644
--- a/nwn/nwnprc/trunk/include/x2_inc_spellhook.nss
+++ b/nwn/nwnprc/trunk/include/x2_inc_spellhook.nss
@@ -3503,6 +3503,21 @@ int X2PreSpellCastCode2()
nContinue = FALSE;
}
}
+
+ //---------------------------------------------------------------------------
+ // Attuned Gem Use check
+ //---------------------------------------------------------------------------
+ if(nContinue && (GetBaseItemType(oSpellCastItem) == BASE_ITEM_GEM) && (GetTag(oSpellCastItem) == "prc_attunegem"))
+ {
+ int bIsSubradial = GetIsSubradialSpell(nSpellID);
+
+ if(bIsSubradial)
+ {
+ nSpellID = GetMasterSpellFromSubradial(nSpellID);
+ }
+ int nItemCL = GetCastSpellCasterLevelFromItem(oSpellCastItem, nSpellID);
+ if(DEBUG) DoDebug("x2_inc_spellhook >> X2PreSpellCastCode2: Attuned Gem Found");
+ }
//---------------------------------------------------------------------------
// No casting while using expertise
diff --git a/nwn/nwnprc/trunk/newspellbook/inv_dra_darkness.nss b/nwn/nwnprc/trunk/newspellbook/inv_dra_darkness.nss
index 68c4a79f..4bdc56c0 100644
--- a/nwn/nwnprc/trunk/newspellbook/inv_dra_darkness.nss
+++ b/nwn/nwnprc/trunk/newspellbook/inv_dra_darkness.nss
@@ -39,14 +39,14 @@ void main()
if(iAttackRoll > 0)
{
oItemTarget = GetItemInSlot(INVENTORY_SLOT_CHEST, oTarget);
- if(!GetIsObjectValid(oTarget))
+ if(!GetIsObjectValid(oItemTarget))
{
//no armor, check other slots
int i;
for(i=0;i<14;i++)
{
oItemTarget = GetItemInSlot(i, oTarget);
- if(GetIsObjectValid(oTarget))
+ if(GetIsObjectValid(oItemTarget))
break;//end for loop
}
}
diff --git a/nwn/nwnprc/trunk/newspellbook/tob_dpst_drgtth.nss b/nwn/nwnprc/trunk/newspellbook/tob_dpst_drgtth.nss
index ad3603a1..94939f4d 100644
--- a/nwn/nwnprc/trunk/newspellbook/tob_dpst_drgtth.nss
+++ b/nwn/nwnprc/trunk/newspellbook/tob_dpst_drgtth.nss
@@ -6,6 +6,10 @@
----------------
27/01/08 by Stratovarius
+
+ Fixed by: Jaysyn
+ On: 2026-05-25 19:11:53
+
*/ /** @file
Dragon's Tooth
@@ -23,7 +27,7 @@ void main()
{
object oInitiator = OBJECT_SELF;
object oCreature = CreateObject(OBJECT_TYPE_PLACEABLE, "tob_dpst_pillar", PRCGetSpellTargetLocation());
- object oProneTarget = MyFirstObjectInShape(SHAPE_SPHERE, FeetToMeters(10.0), GetLocation(oInitiator));
+ object oProneTarget = MyFirstObjectInShape(SHAPE_SPHERE, FeetToMeters(60.0), PRCGetSpellTargetLocation());
while(GetIsObjectValid(oProneTarget))
{
int nDC = 10 + GetHitDice(oInitiator)/2 + GetAbilityModifier(ABILITY_STRENGTH, oInitiator);
@@ -34,11 +38,11 @@ void main()
nDC += 1;
}
// Save check
- if (!PRCMySavingThrow(SAVING_THROW_WILL, oProneTarget, nDC))
+ if (!PRCMySavingThrow(SAVING_THROW_REFLEX, oProneTarget, nDC))
{
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, ExtraordinaryEffect(EffectKnockdown()), oProneTarget, 6.0);
}
- oProneTarget = MyNextObjectInShape(SHAPE_SPHERE, FeetToMeters(10.0), GetLocation(oInitiator));
+ oProneTarget = MyNextObjectInShape(SHAPE_SPHERE, FeetToMeters(60.0), PRCGetSpellTargetLocation());
}
}
diff --git a/nwn/nwnprc/trunk/newspellbook/true_utr_sezitem.nss b/nwn/nwnprc/trunk/newspellbook/true_utr_sezitem.nss
index fa75e712..5a20a6f6 100644
--- a/nwn/nwnprc/trunk/newspellbook/true_utr_sezitem.nss
+++ b/nwn/nwnprc/trunk/newspellbook/true_utr_sezitem.nss
@@ -76,7 +76,6 @@ void main()
}
// Impact Effects
- //ApplyEffectAtLocation(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_DUR_FLOATING_DISK), GetLocation(oTarget));
- ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, EffectVisualEffect(VFX_DUR_FLOATING_DISK), GetLocation(oTarget), 3.0f);
+ ApplyEffectAtLocation(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_BIGBYS_FORCEFUL_HAND), GetLocation(oTarget));
}// end if - Successful utterance
}
diff --git a/nwn/nwnprc/trunk/scripts/prc_acolyte.nss b/nwn/nwnprc/trunk/scripts/prc_acolyte.nss
index c45aac8d..6ebb0809 100644
--- a/nwn/nwnprc/trunk/scripts/prc_acolyte.nss
+++ b/nwn/nwnprc/trunk/scripts/prc_acolyte.nss
@@ -26,8 +26,10 @@ void AcolyteSymbiosis(object oPC, object oSkin, int iLevel)
{
if(GetLocalInt(oSkin, "AcolyteSymbBonus") == iLevel) return;
- RemoveSpecificProperty(oSkin, ITEM_PROPERTY_DAMAGE_REDUCTION, GetLocalInt(oSkin, "AcolyteSymbBonus"), IP_CONST_DAMAGESOAK_20_HP, 1, "AcolyteSymbBonus");
- AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyDamageReduction(iLevel, IP_CONST_DAMAGESOAK_20_HP), oSkin);
+ //RemoveSpecificProperty(oSkin, ITEM_PROPERTY_DAMAGE_REDUCTION, GetLocalInt(oSkin, "AcolyteSymbBonus"), IP_CONST_DAMAGESOAK_20_HP, 1, "AcolyteSymbBonus");
+ RemoveSpecificProperty(oSkin, ITEM_PROPERTY_DAMAGE_REDUCTION, IP_CONST_DAMAGESOAK_20_HP, GetLocalInt(oSkin, "AcolyteSymbBonus"), 1, "AcolyteSymbBonus");
+ //AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyDamageReduction(iLevel, IP_CONST_DAMAGESOAK_20_HP), oSkin);
+ AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyDamageReduction(IP_CONST_DAMAGESOAK_20_HP, iLevel), oSkin);
SetLocalInt(oSkin, "AcolyteSymbBonus", iLevel);
}
diff --git a/nwn/nwnprc/trunk/spells/nw_s0_darkness.nss b/nwn/nwnprc/trunk/spells/nw_s0_darkness.nss
index af496ea5..76e6ea46 100644
--- a/nwn/nwnprc/trunk/spells/nw_s0_darkness.nss
+++ b/nwn/nwnprc/trunk/spells/nw_s0_darkness.nss
@@ -65,14 +65,14 @@ int DoSpell(object oCaster, object oTarget, int nCasterLevel)
if(iAttackRoll > 0)
{
oItemTarget = GetItemInSlot(INVENTORY_SLOT_CHEST, oTarget);
- if(!GetIsObjectValid(oTarget))
+ if(!GetIsObjectValid(oItemTarget))
{
//no armor, check other slots
int i;
for(i=0;i<14;i++)
{
oItemTarget = GetItemInSlot(i, oTarget);
- if(GetIsObjectValid(oTarget))
+ if(GetIsObjectValid(oItemTarget))
break;//end for loop
}
}
diff --git a/nwn/nwnprc/trunk/spells/sp_damng_dark.nss b/nwn/nwnprc/trunk/spells/sp_damng_dark.nss
index 1824b2c0..90b42980 100644
--- a/nwn/nwnprc/trunk/spells/sp_damng_dark.nss
+++ b/nwn/nwnprc/trunk/spells/sp_damng_dark.nss
@@ -82,14 +82,14 @@ int DoSpell(object oCaster, object oTarget, int nCasterLevel)
if(iAttackRoll > 0)
{
oItemTarget = GetItemInSlot(INVENTORY_SLOT_CHEST, oTarget);
- if(!GetIsObjectValid(oTarget))
+ if(!GetIsObjectValid(oItemTarget))
{
//no armor, check other slots
int i;
for(i=0;i<14;i++)
{
oItemTarget = GetItemInSlot(i, oTarget);
- if(GetIsObjectValid(oTarget))
+ if(GetIsObjectValid(oItemTarget))
break;//end for loop
}
}
diff --git a/nwn/nwnprc/trunk/spells/sp_deepdarkness.nss b/nwn/nwnprc/trunk/spells/sp_deepdarkness.nss
index 2379ded4..7c38d4aa 100644
--- a/nwn/nwnprc/trunk/spells/sp_deepdarkness.nss
+++ b/nwn/nwnprc/trunk/spells/sp_deepdarkness.nss
@@ -53,14 +53,14 @@ int DoSpell(object oCaster, object oTarget, int nCasterLevel)
if(iAttackRoll > 0)
{
oItemTarget = GetItemInSlot(INVENTORY_SLOT_CHEST, oTarget);
- if(!GetIsObjectValid(oTarget))
+ if(!GetIsObjectValid(oItemTarget))
{
//no armor, check other slots
int i;
for(i=0;i<14;i++)
{
oItemTarget = GetItemInSlot(i, oTarget);
- if(GetIsObjectValid(oTarget))
+ if(GetIsObjectValid(oItemTarget))
break;//end for loop
}
}
diff --git a/nwn/nwnprc/trunk/tlk/prc8_consortium.tlk b/nwn/nwnprc/trunk/tlk/prc8_consortium.tlk
index bbcb9ce9..558b979f 100644
Binary files a/nwn/nwnprc/trunk/tlk/prc8_consortium.tlk and b/nwn/nwnprc/trunk/tlk/prc8_consortium.tlk differ
diff --git a/nwn/nwnprc/trunk/tlk/prc8_consortium.tlk.xml b/nwn/nwnprc/trunk/tlk/prc8_consortium.tlk.xml
index bdfe6442..db3adb1b 100644
--- a/nwn/nwnprc/trunk/tlk/prc8_consortium.tlk.xml
+++ b/nwn/nwnprc/trunk/tlk/prc8_consortium.tlk.xml
@@ -7347,7 +7347,7 @@ You make yourself - including clothing, armor, weapons and equipment - look diff
Disguise Self, Normal Form
Attune Gem
Type of Feat: Item Creation
-Prerequisite: Intelligence 13, Arcane Spells level 2.
+Prerequisite: Intelligence 13, Arcane Spells level 3.
Specifics: You can cast any arcane spell you have prepared as a gem. The caster must have the spell memorized to be able to create the gem. Crafting a gem costs Spell level * Caster level * 50 in gold pieces for a normal caster (half base cost). It also takes XP equal to 1/25th of the base cost. If you cannot pay the casting cost or the XP loss would drop you a level, the crafting will fail, and the spell will be lost. Crafting the gem requires a gem with a value of 50gp * spell level. A gem is permanent until used. Gems target those who activate them.
Use: Selected.
Epic Scout
diff --git a/nwn/nwnprc/trunk/tlk/prc_consortium.tlk b/nwn/nwnprc/trunk/tlk/prc_consortium.tlk
index bbcb9ce9..4f61d108 100644
Binary files a/nwn/nwnprc/trunk/tlk/prc_consortium.tlk and b/nwn/nwnprc/trunk/tlk/prc_consortium.tlk differ