diff --git a/nwn/nwnprc/trunk/include/prc_inc_scry.nss b/nwn/nwnprc/trunk/include/prc_inc_scry.nss index 315f2878..f0e74f0e 100644 --- a/nwn/nwnprc/trunk/include/prc_inc_scry.nss +++ b/nwn/nwnprc/trunk/include/prc_inc_scry.nss @@ -232,11 +232,13 @@ void ScryMain(object oPC, object oTarget) // Create the copy oCopy = CopyObject(oPC, lTarget, OBJECT_INVALID, GetName(oPC) + "_" + COPY_LOCAL_NAME); CleanCopy(oCopy); - // Attempted Fix to the Copy get's murdered problem. - int nMaxHenchmen = GetMaxHenchmen(); - SetMaxHenchmen(99); - AddHenchman(oPC, oCopy); - SetMaxHenchmen(nMaxHenchmen); + + // Attempted Fix to the Copy get's murdered problem. + //int nMaxHenchmen = GetMaxHenchmen(); + //SetMaxHenchmen(99); + //AddHenchman(oPC, oCopy); + //SetMaxHenchmen(nMaxHenchmen); + SetIsTemporaryFriend(oPC, oCopy, FALSE); // Set the copy to be undestroyable, so that it won't vanish to the ether // along with the PC's items. @@ -357,7 +359,7 @@ void DoScryEnd(object oPC, object oCopy) PRCRemoveSpellEffects(SPELL_PNP_SCRY_FAMILIAR, oPC, oPC); PRCRemoveSpellEffects(SPELL_CLAIRAUDIENCE_AND_CLAIRVOYANCE, oPC, oPC); PRCRemoveSpellEffects(POWER_CLAIRTANGENT_HAND, oPC, oPC); - + // Remove the local signifying that the PC is a projection DeleteLocalInt(oPC, "Scry_Active"); @@ -400,7 +402,7 @@ void DoScryEnd(object oPC, object oCopy) // VFX ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, eLight, lCopy, 3.0); - DestroyObject(oCopy); + //DestroyObject(oCopy); //Remove duration marker DeleteLocalInt(oPC, "SCRY_EXPIRED"); @@ -409,12 +411,94 @@ void DoScryEnd(object oPC, object oCopy) //Runs tests to see if the projection effect can still continue. //If the PC has reached 1 HP, end projection normally. //If the copy is dead, end projection and kill the PC. -void ScryMonitor(object oPC, object oCopy) +void ScryMonitor(object oPC, object oCopy) +{ + if(DEBUG) DoDebug("prc_inc_scry: ScryMonitor():\n" + + "oPC = '" + GetName(oPC) + "'\n" + + "oCopy = '" + GetName(oCopy) + "'" + ); + + // Abort if the projection is no longer marked as being active + if(!GetLocalInt(oPC, "Scry_Active")) + return; + + // Some paranoia in case something interfered and either PC or copy has been destroyed + if(!(GetIsObjectValid(oPC) && GetIsObjectValid(oCopy))){ + WriteTimestampedLogEntry("Baelnorn Projection hearbeat aborting due to an invalid object. Object status:" + + "\nPC - " + (GetIsObjectValid(oPC) ? "valid":"invalid") + + "\nCopy - " + (GetIsObjectValid(oCopy) ? "valid":"invalid")); + return; + } + + // Start the actual work by checking the copy's status. The death thing should take priority + if(GetIsDead(oCopy)) + { + if (DEBUG) DoDebug("prc_inc_scry: Copy is dead, killing PC"); + DoScryEnd(oPC, oCopy); + effect eKill = EffectDamage(9999, DAMAGE_TYPE_MAGICAL, DAMAGE_POWER_ENERGY); + DelayCommand(3.0, ApplyEffectToObject(DURATION_TYPE_INSTANT, eKill, oPC)); + } + else + { + // Check if the "projection" has been destroyed or if some other event has caused the projection to end + if(GetLocalInt(oPC, "Scry_Abort")) + { + if(DEBUG) DoDebug("prc_inc_scry: ScryMonitor(): The Projection has been terminated, ending projection"); + DoScryEnd(oPC, oCopy); + } + else + { + // This makes sure you are invisible. + //AssignCommand(oPC, ClearAllActions(TRUE)); + ApplyEffectToObject(DURATION_TYPE_TEMPORARY, ExtraordinaryEffect(EffectEthereal()), oPC, SCRY_HB_DELAY + 0.3); + DelayCommand(SCRY_HB_DELAY, ScryMonitor(oPC, oCopy)); + } + + // Skip destructive cleanup triggers for Clairtangent Hand + if(GetLocalInt(oPC, "ScrySpellId") != POWER_CLAIRTANGENT_HAND) + { + //If duration expired, end effect + if(GetLocalInt(oPC, "SCRY_EXPIRED")) + { + DoScryEnd(oPC, oCopy); + } + // End due to being in combat, except for ephemeral image + if(GetIsInCombat(oPC) && GetLocalInt(oPC, "ScrySpellId") != MYST_EPHEMERAL_IMAGE) + { + DoScryEnd(oPC, oCopy); + if(DEBUG) DoDebug("prc_inc_scry: ScryMonitor(): Scryer in combat, ending projection"); + AssignCommand(oPC, ClearAllActions(TRUE)); + } + // In PnP, once you lose line of effect, the spell ends + float fDistance = FeetToMeters(100.0 + GetLocalInt(oPC, "ScryCasterLevel") * 10.0); + if (GetLocalInt(oPC, "ScrySpellId") == MYST_EPHEMERAL_IMAGE && GetDistanceBetween(oPC, oCopy) > fDistance) + { + DoScryEnd(oPC, oCopy); + if(DEBUG) DoDebug("prc_inc_scry: ScryMonitor(): Ephemeral Image distance exceeded, ending projection"); + AssignCommand(oPC, ClearAllActions(TRUE)); + } + } + } +} + + +/* void ScryMonitor(object oPC, object oCopy) { - if(DEBUG) DoDebug("prc_inc_scry: ScryMonitor():\n" + + if(DEBUG) DoDebug("prc_inc_scry: ScryMonitor():\n" + "oPC = '" + GetName(oPC) + "'\n" + "oCopy = '" + GetName(oCopy) + "'" ); + + // Skip automatic cleanup for Clairtangent Hand + if(GetLocalInt(oPC, "ScrySpellId") == POWER_CLAIRTANGENT_HAND) + { + // Only apply ethereal effect and reschedule + ApplyEffectToObject(DURATION_TYPE_TEMPORARY, ExtraordinaryEffect(EffectEthereal()), oPC, SCRY_HB_DELAY + 0.3); + DelayCommand(SCRY_HB_DELAY, ScryMonitor(oPC, oCopy)); + return; + } + // Abort if the projection is no longer marked as being active if(!GetLocalInt(oPC, "Scry_Active")) return; @@ -473,6 +557,7 @@ void ScryMonitor(object oPC, object oCopy) } } } + */ //Undoes changes made in ApplyScryEffects(). void RemoveScryEffects(object oPC) @@ -498,6 +583,14 @@ void RemoveScryEffects(object oPC) IPRemoveMatchingItemProperties(oWeapon, ITEM_PROPERTY_NO_DAMAGE, DURATION_TYPE_PERMANENT); } + effect eEffect = GetFirstEffect(oPC); + while(GetIsEffectValid(eEffect)) + { + if(GetEffectTag(eEffect) == "SCRYING_TAG") + RemoveEffect(oPC, eEffect); + eEffect = GetNextEffect(oPC); + } + array_delete(oPC, "Scry_Nerfed"); } diff --git a/nwn/nwnprc/trunk/newspellbook/shd_myst_bndprs.nss b/nwn/nwnprc/trunk/newspellbook/shd_myst_bndprs.nss index 64b40c6c..e7db899c 100644 --- a/nwn/nwnprc/trunk/newspellbook/shd_myst_bndprs.nss +++ b/nwn/nwnprc/trunk/newspellbook/shd_myst_bndprs.nss @@ -130,7 +130,14 @@ void main() if(myst.bCanMyst) { - //Declare major variables + + // Check if current area blocks scrying + if(GetLocalInt(GetArea(oShadow), "SCRY_FROM_AREA_BLOCKED")) + { + FloatingTextStringOnCreature("This area prevents scrying.", oShadow, FALSE); + return; + } + //Declare major variables myst.fDur = RoundsToSeconds(myst.nShadowcasterLevel); if(myst.bExtend) myst.fDur *= 2; diff --git a/nwn/nwnprc/trunk/newspellbook/shd_myst_ephemrl.nss b/nwn/nwnprc/trunk/newspellbook/shd_myst_ephemrl.nss index 9260008f..ea02e51e 100644 --- a/nwn/nwnprc/trunk/newspellbook/shd_myst_ephemrl.nss +++ b/nwn/nwnprc/trunk/newspellbook/shd_myst_ephemrl.nss @@ -29,7 +29,14 @@ void main() if(myst.bCanMyst) { - myst.fDur = TurnsToSeconds(myst.nShadowcasterLevel); + // Check if current area blocks scrying + if(GetLocalInt(GetArea(oShadow), "SCRY_FROM_AREA_BLOCKED")) + { + FloatingTextStringOnCreature("This area prevents scrying.", oShadow, FALSE); + return; + } + + myst.fDur = TurnsToSeconds(myst.nShadowcasterLevel); if(myst.bExtend) myst.fDur *= 2; SetLocalInt(oShadow, "ScryCasterLevel", myst.nShadowcasterLevel); SetLocalInt(oShadow, "ScrySpellId", myst.nMystId); diff --git a/nwn/nwnprc/trunk/newspellbook/shd_myst_farsght.nss b/nwn/nwnprc/trunk/newspellbook/shd_myst_farsght.nss index 1dc4f98f..19356fb9 100644 --- a/nwn/nwnprc/trunk/newspellbook/shd_myst_farsght.nss +++ b/nwn/nwnprc/trunk/newspellbook/shd_myst_farsght.nss @@ -141,6 +141,13 @@ void main() object oShadow = OBJECT_SELF; object oTarget = PRCGetSpellTargetObject(); struct mystery myst = EvaluateMystery(oShadow, oTarget, METASHADOW_EXTEND); + + // Check if current area blocks scrying + if(GetLocalInt(GetArea(oShadow), "SCRY_FROM_AREA_BLOCKED")) + { + FloatingTextStringOnCreature("This area prevents scrying.", oShadow, FALSE); + return; + } if(myst.bCanMyst) { diff --git a/nwn/nwnprc/trunk/psionics/psi_pow_clrhand.nss b/nwn/nwnprc/trunk/psionics/psi_pow_clrhand.nss index 2f2b66f1..06c1961a 100644 --- a/nwn/nwnprc/trunk/psionics/psi_pow_clrhand.nss +++ b/nwn/nwnprc/trunk/psionics/psi_pow_clrhand.nss @@ -19,139 +19,200 @@ You can see and hear some creature, which may be at any distance. Only Far Hand Valid targets are any monster within the same area as the caster, or any PC. */ -#include "psi_inc_psifunc" -#include "psi_inc_pwresist" -#include "psi_spellhook" -#include "inc_dynconv" - -void ApplyScryEffects(object oManifester) -{ - if(DEBUG) DoDebug("prc_inc_scry: ApplyScryEffects():\n" - + "oManifester = '" + GetName(oManifester) + "'" - ); - // The Scryer is not supposed to be visible, nor can he move or cast - // He also can't take damage from scrying - effect eLink = EffectSpellImmunity(SPELL_ALL_SPELLS); - // Damage immunities - eLink = EffectLinkEffects(eLink, EffectDamageImmunityIncrease(DAMAGE_TYPE_ACID, 100)); - eLink = EffectLinkEffects(eLink, EffectDamageImmunityIncrease(DAMAGE_TYPE_BLUDGEONING, 100)); - eLink = EffectLinkEffects(eLink, EffectDamageImmunityIncrease(DAMAGE_TYPE_COLD, 100)); - eLink = EffectLinkEffects(eLink, EffectDamageImmunityIncrease(DAMAGE_TYPE_DIVINE, 100)); - eLink = EffectLinkEffects(eLink, EffectDamageImmunityIncrease(DAMAGE_TYPE_ELECTRICAL, 100)); - eLink = EffectLinkEffects(eLink, EffectDamageImmunityIncrease(DAMAGE_TYPE_FIRE, 100)); - eLink = EffectLinkEffects(eLink, EffectDamageImmunityIncrease(DAMAGE_TYPE_MAGICAL, 100)); - eLink = EffectLinkEffects(eLink, EffectDamageImmunityIncrease(DAMAGE_TYPE_NEGATIVE, 100)); - eLink = EffectLinkEffects(eLink, EffectDamageImmunityIncrease(DAMAGE_TYPE_PIERCING, 100)); - eLink = EffectLinkEffects(eLink, EffectDamageImmunityIncrease(DAMAGE_TYPE_POSITIVE, 100)); - eLink = EffectLinkEffects(eLink, EffectDamageImmunityIncrease(DAMAGE_TYPE_SLASHING, 100)); - eLink = EffectLinkEffects(eLink, EffectDamageImmunityIncrease(DAMAGE_TYPE_SONIC, 100)); - // Specific immunities - eLink = EffectLinkEffects(eLink, EffectImmunity(IMMUNITY_TYPE_ABILITY_DECREASE)); - eLink = EffectLinkEffects(eLink, EffectImmunity(IMMUNITY_TYPE_BLINDNESS)); - eLink = EffectLinkEffects(eLink, EffectImmunity(IMMUNITY_TYPE_DEAFNESS)); - eLink = EffectLinkEffects(eLink, EffectImmunity(IMMUNITY_TYPE_CRITICAL_HIT)); - eLink = EffectLinkEffects(eLink, EffectImmunity(IMMUNITY_TYPE_DEATH)); - eLink = EffectLinkEffects(eLink, EffectImmunity(IMMUNITY_TYPE_DISEASE)); - eLink = EffectLinkEffects(eLink, EffectImmunity(IMMUNITY_TYPE_ENTANGLE)); - eLink = EffectLinkEffects(eLink, EffectImmunity(IMMUNITY_TYPE_SLOW)); - eLink = EffectLinkEffects(eLink, EffectImmunity(IMMUNITY_TYPE_KNOCKDOWN)); - eLink = EffectLinkEffects(eLink, EffectImmunity(IMMUNITY_TYPE_NEGATIVE_LEVEL)); - eLink = EffectLinkEffects(eLink, EffectImmunity(IMMUNITY_TYPE_PARALYSIS)); - eLink = EffectLinkEffects(eLink, EffectImmunity(IMMUNITY_TYPE_SILENCE)); - eLink = EffectLinkEffects(eLink, EffectImmunity(IMMUNITY_TYPE_SNEAK_ATTACK)); - eLink = EffectLinkEffects(eLink, EffectImmunity(IMMUNITY_TYPE_TRAP)); - eLink = EffectLinkEffects(eLink, EffectImmunity(IMMUNITY_TYPE_MIND_SPELLS)); - // Random stuff - eLink = EffectLinkEffects(eLink, EffectCutsceneGhost()); - eLink = EffectLinkEffects(eLink, EffectCutsceneImmobilize()); - eLink = EffectLinkEffects(eLink, EffectEthereal()); - eLink = EffectLinkEffects(eLink, EffectAttackDecrease(50)); - eLink = EffectLinkEffects(eLink, EffectVisualEffect(VFX_DUR_CUTSCENE_INVISIBILITY)); - // Permanent until Scry ends - ApplyEffectToObject(DURATION_TYPE_TEMPORARY, ExtraordinaryEffect(eLink), oManifester, GetLocalFloat(oManifester, "ScryDuration") + 6.0); - - // Create array for storing a list of the nerfed weapons in - array_create(oManifester, "Scry_Nerfed"); - - object oWeapon; - itemproperty ipNoDam = ItemPropertyNoDamage(); - oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oManifester); - if(IPGetIsMeleeWeapon(oWeapon)){ - if(!GetItemHasItemProperty(oWeapon, ITEM_PROPERTY_NO_DAMAGE)){ - //SetLocalInt(oWeapon, "BaelnornProjection_NoDamage", TRUE); - AddItemProperty(DURATION_TYPE_PERMANENT, ipNoDam, oWeapon); - array_set_object(oManifester, "Scry_Nerfed", array_get_size(oManifester, "Scry_Nerfed"), oWeapon); - } - // Check left hand only if right hand had a weapon - oWeapon = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oManifester); - if(IPGetIsMeleeWeapon(oWeapon)){ - if(!GetItemHasItemProperty(oWeapon, ITEM_PROPERTY_NO_DAMAGE)){ - //SetLocalInt(oWeapon, "BaelnornProjection_NoDamage", TRUE); - AddItemProperty(DURATION_TYPE_PERMANENT, ipNoDam, oWeapon); - array_set_object(oManifester, "Scry_Nerfed", array_get_size(oManifester, "Scry_Nerfed"), oWeapon); - }} - }else if(IPGetIsRangedWeapon(oWeapon)){ - if(!GetItemHasItemProperty(oWeapon, ITEM_PROPERTY_NO_DAMAGE)){ - //SetLocalInt(oWeapon, "BaelnornProjection_NoDamage", TRUE); - AddItemProperty(DURATION_TYPE_PERMANENT, ipNoDam, oWeapon); - array_set_object(oManifester, "Scry_Nerfed", array_get_size(oManifester, "Scry_Nerfed"), oWeapon); - }} - - oWeapon = GetItemInSlot(INVENTORY_SLOT_CWEAPON_B, oManifester); - if(GetIsObjectValid(oWeapon)){ - if(!GetItemHasItemProperty(oWeapon, ITEM_PROPERTY_NO_DAMAGE)){ - //SetLocalInt(oWeapon, "BaelnornProjection_NoDamage", TRUE); - AddItemProperty(DURATION_TYPE_PERMANENT, ipNoDam, oWeapon); - array_set_object(oManifester, "Scry_Nerfed", array_get_size(oManifester, "Scry_Nerfed"), oWeapon); - }} - oWeapon = GetItemInSlot(INVENTORY_SLOT_CWEAPON_L, oManifester); - if(GetIsObjectValid(oWeapon)){ - if(!GetItemHasItemProperty(oWeapon, ITEM_PROPERTY_NO_DAMAGE)){ - //SetLocalInt(oWeapon, "BaelnornProjection_NoDamage", TRUE); - AddItemProperty(DURATION_TYPE_PERMANENT, ipNoDam, oWeapon); - array_set_object(oManifester, "Scry_Nerfed", array_get_size(oManifester, "Scry_Nerfed"), oWeapon); - }} - oWeapon = GetItemInSlot(INVENTORY_SLOT_CWEAPON_R, oManifester); - if(GetIsObjectValid(oWeapon)){ - if(!GetItemHasItemProperty(oWeapon, ITEM_PROPERTY_NO_DAMAGE)){ - //SetLocalInt(oWeapon, "BaelnornProjection_NoDamage", TRUE); - AddItemProperty(DURATION_TYPE_PERMANENT, ipNoDam, oWeapon); - array_set_object(oManifester, "Scry_Nerfed", array_get_size(oManifester, "Scry_Nerfed"), oWeapon); - }} +#include "psi_inc_psifunc" +#include "psi_inc_pwresist" +#include "psi_spellhook" +#include "inc_dynconv" +#include "prc_inc_scry" + +void ApplyScryEffects(object oManifester) +{ + if(DEBUG) DoDebug("prc_inc_scry: ApplyScryEffects():\n" + + "oManifester = '" + GetName(oManifester) + "'" + ); + // The Scryer is not supposed to be visible, nor can he move or cast + // He also can't take damage from scrying + effect eLink = EffectSpellImmunity(SPELL_ALL_SPELLS); + // Damage immunities + eLink = EffectLinkEffects(eLink, EffectDamageImmunityIncrease(DAMAGE_TYPE_ACID, 100)); + eLink = EffectLinkEffects(eLink, EffectDamageImmunityIncrease(DAMAGE_TYPE_BLUDGEONING, 100)); + eLink = EffectLinkEffects(eLink, EffectDamageImmunityIncrease(DAMAGE_TYPE_COLD, 100)); + eLink = EffectLinkEffects(eLink, EffectDamageImmunityIncrease(DAMAGE_TYPE_DIVINE, 100)); + eLink = EffectLinkEffects(eLink, EffectDamageImmunityIncrease(DAMAGE_TYPE_ELECTRICAL, 100)); + eLink = EffectLinkEffects(eLink, EffectDamageImmunityIncrease(DAMAGE_TYPE_FIRE, 100)); + eLink = EffectLinkEffects(eLink, EffectDamageImmunityIncrease(DAMAGE_TYPE_MAGICAL, 100)); + eLink = EffectLinkEffects(eLink, EffectDamageImmunityIncrease(DAMAGE_TYPE_NEGATIVE, 100)); + eLink = EffectLinkEffects(eLink, EffectDamageImmunityIncrease(DAMAGE_TYPE_PIERCING, 100)); + eLink = EffectLinkEffects(eLink, EffectDamageImmunityIncrease(DAMAGE_TYPE_POSITIVE, 100)); + eLink = EffectLinkEffects(eLink, EffectDamageImmunityIncrease(DAMAGE_TYPE_SLASHING, 100)); + eLink = EffectLinkEffects(eLink, EffectDamageImmunityIncrease(DAMAGE_TYPE_SONIC, 100)); + // Specific immunities + eLink = EffectLinkEffects(eLink, EffectImmunity(IMMUNITY_TYPE_ABILITY_DECREASE)); + eLink = EffectLinkEffects(eLink, EffectImmunity(IMMUNITY_TYPE_BLINDNESS)); + eLink = EffectLinkEffects(eLink, EffectImmunity(IMMUNITY_TYPE_DEAFNESS)); + eLink = EffectLinkEffects(eLink, EffectImmunity(IMMUNITY_TYPE_CRITICAL_HIT)); + eLink = EffectLinkEffects(eLink, EffectImmunity(IMMUNITY_TYPE_DEATH)); + eLink = EffectLinkEffects(eLink, EffectImmunity(IMMUNITY_TYPE_DISEASE)); + eLink = EffectLinkEffects(eLink, EffectImmunity(IMMUNITY_TYPE_ENTANGLE)); + eLink = EffectLinkEffects(eLink, EffectImmunity(IMMUNITY_TYPE_SLOW)); + eLink = EffectLinkEffects(eLink, EffectImmunity(IMMUNITY_TYPE_KNOCKDOWN)); + eLink = EffectLinkEffects(eLink, EffectImmunity(IMMUNITY_TYPE_NEGATIVE_LEVEL)); + eLink = EffectLinkEffects(eLink, EffectImmunity(IMMUNITY_TYPE_PARALYSIS)); + eLink = EffectLinkEffects(eLink, EffectImmunity(IMMUNITY_TYPE_SILENCE)); + eLink = EffectLinkEffects(eLink, EffectImmunity(IMMUNITY_TYPE_SNEAK_ATTACK)); + eLink = EffectLinkEffects(eLink, EffectImmunity(IMMUNITY_TYPE_TRAP)); + eLink = EffectLinkEffects(eLink, EffectImmunity(IMMUNITY_TYPE_MIND_SPELLS)); + // Random stuff + eLink = EffectLinkEffects(eLink, EffectCutsceneGhost()); + eLink = EffectLinkEffects(eLink, EffectCutsceneImmobilize()); + eLink = EffectLinkEffects(eLink, EffectEthereal()); + eLink = EffectLinkEffects(eLink, EffectAttackDecrease(50)); + eLink = EffectLinkEffects(eLink, EffectVisualEffect(VFX_DUR_CUTSCENE_INVISIBILITY)); + eLink = TagEffect(eLink, "SCRYING_TAG"); + // Permanent until Scry ends + ApplyEffectToObject(DURATION_TYPE_TEMPORARY, ExtraordinaryEffect(eLink), oManifester, GetLocalFloat(oManifester, "ScryDuration") + 6.0); + + // Create array for storing a list of the nerfed weapons in + array_create(oManifester, "Scry_Nerfed"); + + object oWeapon; + itemproperty ipNoDam = ItemPropertyNoDamage(); + oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oManifester); + if(IPGetIsMeleeWeapon(oWeapon)){ + if(!GetItemHasItemProperty(oWeapon, ITEM_PROPERTY_NO_DAMAGE)){ + //SetLocalInt(oWeapon, "BaelnornProjection_NoDamage", TRUE); + AddItemProperty(DURATION_TYPE_PERMANENT, ipNoDam, oWeapon); + array_set_object(oManifester, "Scry_Nerfed", array_get_size(oManifester, "Scry_Nerfed"), oWeapon); + } + // Check left hand only if right hand had a weapon + oWeapon = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oManifester); + if(IPGetIsMeleeWeapon(oWeapon)){ + if(!GetItemHasItemProperty(oWeapon, ITEM_PROPERTY_NO_DAMAGE)){ + //SetLocalInt(oWeapon, "BaelnornProjection_NoDamage", TRUE); + AddItemProperty(DURATION_TYPE_PERMANENT, ipNoDam, oWeapon); + array_set_object(oManifester, "Scry_Nerfed", array_get_size(oManifester, "Scry_Nerfed"), oWeapon); + }} + }else if(IPGetIsRangedWeapon(oWeapon)){ + if(!GetItemHasItemProperty(oWeapon, ITEM_PROPERTY_NO_DAMAGE)){ + //SetLocalInt(oWeapon, "BaelnornProjection_NoDamage", TRUE); + AddItemProperty(DURATION_TYPE_PERMANENT, ipNoDam, oWeapon); + array_set_object(oManifester, "Scry_Nerfed", array_get_size(oManifester, "Scry_Nerfed"), oWeapon); + }} + + oWeapon = GetItemInSlot(INVENTORY_SLOT_CWEAPON_B, oManifester); + if(GetIsObjectValid(oWeapon)){ + if(!GetItemHasItemProperty(oWeapon, ITEM_PROPERTY_NO_DAMAGE)){ + //SetLocalInt(oWeapon, "BaelnornProjection_NoDamage", TRUE); + AddItemProperty(DURATION_TYPE_PERMANENT, ipNoDam, oWeapon); + array_set_object(oManifester, "Scry_Nerfed", array_get_size(oManifester, "Scry_Nerfed"), oWeapon); + }} + oWeapon = GetItemInSlot(INVENTORY_SLOT_CWEAPON_L, oManifester); + if(GetIsObjectValid(oWeapon)){ + if(!GetItemHasItemProperty(oWeapon, ITEM_PROPERTY_NO_DAMAGE)){ + //SetLocalInt(oWeapon, "BaelnornProjection_NoDamage", TRUE); + AddItemProperty(DURATION_TYPE_PERMANENT, ipNoDam, oWeapon); + array_set_object(oManifester, "Scry_Nerfed", array_get_size(oManifester, "Scry_Nerfed"), oWeapon); + }} + oWeapon = GetItemInSlot(INVENTORY_SLOT_CWEAPON_R, oManifester); + if(GetIsObjectValid(oWeapon)){ + if(!GetItemHasItemProperty(oWeapon, ITEM_PROPERTY_NO_DAMAGE)){ + //SetLocalInt(oWeapon, "BaelnornProjection_NoDamage", TRUE); + AddItemProperty(DURATION_TYPE_PERMANENT, ipNoDam, oWeapon); + array_set_object(oManifester, "Scry_Nerfed", array_get_size(oManifester, "Scry_Nerfed"), oWeapon); + }} +} + +void CheckAndReapplyEffects(object oManifester) +{ + // Only apply effects if we're the real body (not the copy) + if(GetStringLeft(GetTag(oManifester), 5) != "Scry_") + { + ApplyScryEffects(oManifester); + } } - - -void main() -{ - if (!PsiPrePowerCastCode()) + +void main() +{ + if (!PsiPrePowerCastCode()) + { + // If code within the PrePowerCastHook (i.e. UMD) reports FALSE, do not run this spell + return; + } + +// End of Spell Cast Hook + + object oManifester = OBJECT_SELF; + object oTarget = PRCGetSpellTargetObject(); + struct manifestation manif = + EvaluateManifestation(oManifester, oTarget, + PowerAugmentationProfile(), + METAPSIONIC_EXTEND + ); + + if(manif.bCanManifest) { - // If code within the PrePowerCastHook (i.e. UMD) reports FALSE, do not run this spell - return; - } - -// End of Spell Cast Hook - - object oManifester = OBJECT_SELF; - object oTarget = PRCGetSpellTargetObject(); - struct manifestation manif = - EvaluateManifestation(oManifester, oTarget, - PowerAugmentationProfile(), - METAPSIONIC_EXTEND - ); - - if(manif.bCanManifest) - { - float fDur = 60.0 * manif.nManifesterLevel; - if(manif.bExtend) fDur *= 2; - - SetLocalInt(oManifester, "ScryCasterLevel", manif.nManifesterLevel); - SetLocalInt(oManifester, "ScrySpellId", manif.nSpellID); - SetLocalFloat(oManifester, "ScryDuration", fDur); - SetLocalInt(oManifester, "ScrySpellDC", GetManifesterDC(oManifester)); + // Check if current area blocks scrying + if(GetLocalInt(GetArea(oManifester), "SCRY_FROM_AREA_BLOCKED")) + { + FloatingTextStringOnCreature("This area prevents scrying.", oManifester, FALSE); + return; + } + + float fDur = 60.0 * manif.nManifesterLevel; + if(manif.bExtend) fDur *= 2; + + SetLocalInt(oManifester, "ScryCasterLevel", manif.nManifesterLevel); + SetLocalInt(oManifester, "ScrySpellId", manif.nSpellID); + SetLocalFloat(oManifester, "ScryDuration", fDur); + SetLocalInt(oManifester, "ScrySpellDC", GetManifesterDC(oManifester)); + + // Clear any existing Clairtangent Hand effects before copy creation + PRCRemoveSpellEffects(POWER_CLAIRTANGENT_HAND, oManifester, oManifester); + + // Set flag to reapply effects after scry system completes setup + SetLocalInt(oManifester, "ClrHand_ReapplyEffects", TRUE); + + StartDynamicConversation("prc_scry_conv", oManifester, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oManifester); - StartDynamicConversation("prc_scry_conv", oManifester, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oManifester); - - // Apply the immunity effects - ApplyScryEffects(oManifester); - } -} \ No newline at end of file + // Reapply effects after scry system setup + DelayCommand(2.0f, CheckAndReapplyEffects(oManifester)); + + // Apply the immunity effects + //ApplyScryEffects(oManifester); + } +} + +/* void main() +{ + if (!PsiPrePowerCastCode()) + { + // If code within the PrePowerCastHook (i.e. UMD) reports FALSE, do not run this spell + return; + } + +// End of Spell Cast Hook + + object oManifester = OBJECT_SELF; + object oTarget = PRCGetSpellTargetObject(); + struct manifestation manif = + EvaluateManifestation(oManifester, oTarget, + PowerAugmentationProfile(), + METAPSIONIC_EXTEND + ); + + if(manif.bCanManifest) + { + float fDur = 60.0 * manif.nManifesterLevel; + if(manif.bExtend) fDur *= 2; + + SetLocalInt(oManifester, "ScryCasterLevel", manif.nManifesterLevel); + SetLocalInt(oManifester, "ScrySpellId", manif.nSpellID); + SetLocalFloat(oManifester, "ScryDuration", fDur); + SetLocalInt(oManifester, "ScrySpellDC", GetManifesterDC(oManifester)); + + StartDynamicConversation("prc_scry_conv", oManifester, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oManifester); + + // Apply the immunity effects + ApplyScryEffects(oManifester); + } +} */ \ No newline at end of file diff --git a/nwn/nwnprc/trunk/psionics/psi_pow_clrsns.nss b/nwn/nwnprc/trunk/psionics/psi_pow_clrsns.nss index 11b60a83..9185badd 100644 --- a/nwn/nwnprc/trunk/psionics/psi_pow_clrsns.nss +++ b/nwn/nwnprc/trunk/psionics/psi_pow_clrsns.nss @@ -151,7 +151,14 @@ void main() if(manif.bCanManifest) { - float fDur = 60.0 * manif.nManifesterLevel; + // Check if current area blocks scrying + if(GetLocalInt(GetArea(oManifester), "SCRY_FROM_AREA_BLOCKED")) + { + FloatingTextStringOnCreature("This area prevents scrying.", oManifester, FALSE); + return; + } + + float fDur = 60.0 * manif.nManifesterLevel; if(manif.bExtend) fDur *= 2; SetLocalInt(oManifester, "ScryCasterLevel", manif.nManifesterLevel); diff --git a/nwn/nwnprc/trunk/psionics/psi_pow_rmtview.nss b/nwn/nwnprc/trunk/psionics/psi_pow_rmtview.nss index eaa99928..37c690b5 100644 --- a/nwn/nwnprc/trunk/psionics/psi_pow_rmtview.nss +++ b/nwn/nwnprc/trunk/psionics/psi_pow_rmtview.nss @@ -150,7 +150,14 @@ void main() if(manif.bCanManifest) { - float fDur = 60.0 * manif.nManifesterLevel; + // Check if current area blocks scrying + if(GetLocalInt(GetArea(oManifester), "SCRY_FROM_AREA_BLOCKED")) + { + FloatingTextStringOnCreature("This area prevents scrying.", oManifester, FALSE); + return; + } + + float fDur = 60.0 * manif.nManifesterLevel; if(manif.bExtend) fDur *= 2; SetLocalInt(oManifester, "ScryCasterLevel", manif.nManifesterLevel); diff --git a/nwn/nwnprc/trunk/scripts/shadp_shaddoub.nss b/nwn/nwnprc/trunk/scripts/shadp_shaddoub.nss index e27b23f8..db5f39f0 100644 --- a/nwn/nwnprc/trunk/scripts/shadp_shaddoub.nss +++ b/nwn/nwnprc/trunk/scripts/shadp_shaddoub.nss @@ -5,19 +5,20 @@ void main() { DeleteLocalInt(OBJECT_SELF, "X2_L_LAST_SPELLSCHOOL_VAR"); SetLocalInt(OBJECT_SELF, "X2_L_LAST_SPELLSCHOOL_VAR", SPELL_SCHOOL_ILLUSION); -/* - Spellcast Hook Code - Added 2003-06-23 by GeorgZ - If you want to make changes to all spells, - check x2_inc_spellhook.nss to find out more -*/ if (!X2PreSpellCastCode()) { // If code within the PreSpellCastHook (i.e. UMD) reports FALSE, do not run this spell return; } + // Check if current area blocks scrying + if(GetLocalInt(GetArea(OBJECT_SELF), "SCRY_FROM_AREA_BLOCKED")) + { + FloatingTextStringOnCreature("This area prevents scrying.", OBJECT_SELF, FALSE); + return; + } + int nDuration = GetLevelByTypeArcane(); SetLocalInt(OBJECT_SELF, "ScryCasterLevel", nDuration); diff --git a/nwn/nwnprc/trunk/spells/nw_s0_clairadvo.nss b/nwn/nwnprc/trunk/spells/nw_s0_clairadvo.nss index 5eb2ed4d..e1c196e9 100644 --- a/nwn/nwnprc/trunk/spells/nw_s0_clairadvo.nss +++ b/nwn/nwnprc/trunk/spells/nw_s0_clairadvo.nss @@ -114,10 +114,10 @@ void ApplyScryEffects(object oPC) void main() { - object oPC = OBJECT_SELF; + object oPC = OBJECT_SELF; -DeleteLocalInt(oPC, "X2_L_LAST_SPELLSCHOOL_VAR"); -SetLocalInt(oPC, "X2_L_LAST_SPELLSCHOOL_VAR", SPELL_SCHOOL_DIVINATION); + DeleteLocalInt(oPC, "X2_L_LAST_SPELLSCHOOL_VAR"); + SetLocalInt(oPC, "X2_L_LAST_SPELLSCHOOL_VAR", SPELL_SCHOOL_DIVINATION); if (!X2PreSpellCastCode()) { @@ -125,26 +125,33 @@ SetLocalInt(oPC, "X2_L_LAST_SPELLSCHOOL_VAR", SPELL_SCHOOL_DIVINATION); return; } - //Declare major variables - object oTarget; - int nCasterLvl = PRCGetCasterLevel(oPC); - int nSpell = PRCGetSpellId(); - float fDur = 60.0 * nCasterLvl; - int nMetaMagic = PRCGetMetaMagicFeat(); - //Make Metamagic check for extend - if ((nMetaMagic & METAMAGIC_EXTEND)) - { - fDur = fDur * 2; - } - - SetLocalInt(oPC, "ScryCasterLevel", nCasterLvl); - SetLocalInt(oPC, "ScrySpellId", nSpell); - SetLocalFloat(oPC, "ScryDuration", fDur); - - StartDynamicConversation("prc_scry_conv", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC); - - // Apply the immunity effects - ApplyScryEffects(oPC); + // Check if current area blocks scrying + if(GetLocalInt(GetArea(oPC), "SCRY_FROM_AREA_BLOCKED")) + { + FloatingTextStringOnCreature("This area prevents scrying.", oPC, FALSE); + return; + } + + //Declare major variables + object oTarget; + int nCasterLvl = PRCGetCasterLevel(oPC); + int nSpell = PRCGetSpellId(); + float fDur = 60.0 * nCasterLvl; + int nMetaMagic = PRCGetMetaMagicFeat(); + //Make Metamagic check for extend + if ((nMetaMagic & METAMAGIC_EXTEND)) + { + fDur = fDur * 2; + } + + SetLocalInt(oPC, "ScryCasterLevel", nCasterLvl); + SetLocalInt(oPC, "ScrySpellId", nSpell); + SetLocalFloat(oPC, "ScryDuration", fDur); + + StartDynamicConversation("prc_scry_conv", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC); + + // Apply the immunity effects + ApplyScryEffects(oPC); DeleteLocalInt(oPC, "X2_L_LAST_SPELLSCHOOL_VAR"); // Getting rid of the integer used to hold the spells spell school diff --git a/nwn/nwnprc/trunk/spells/prc_scry_conv.nss b/nwn/nwnprc/trunk/spells/prc_scry_conv.nss index 9af1b2fb..431edcb2 100644 --- a/nwn/nwnprc/trunk/spells/prc_scry_conv.nss +++ b/nwn/nwnprc/trunk/spells/prc_scry_conv.nss @@ -26,8 +26,6 @@ const int STAGE_CONFIRMATION = 1; ////////////////////////////////////////////////// /* Aid functions */ ////////////////////////////////////////////////// - - void StorePCForRecovery(object oPC, object oChoice, int nChoice) { SetLocalObject(oPC, "ScryTarget" + IntToString(nChoice), oChoice); @@ -38,7 +36,188 @@ object RetrievePC(object oPC, int nChoice) return GetLocalObject(oPC, "ScryTarget" + IntToString(nChoice)); } -void AddLegalTargets(object oPC) +void AddLegalTargets(object oPC) +{ + // This reads all of the legal choices + int nSpellId = GetLocalInt(oPC, "ScrySpellId"); + int nChoice = 1; + int nDebugCounter = 0; // Add debug counter for frequency limiting + + if (nSpellId == SPELL_LOCATE_OBJECT) + { + // First, get all objects in the area you're in + object oObject = GetFirstObjectInArea(GetArea(oPC)); + while (GetIsObjectValid(oObject) == TRUE) + { + if(DEBUG && (++nDebugCounter % 10 == 0)) + DoDebug("prc_scry_conv: Processed " + IntToString(nDebugCounter) + " objects"); + // Don't target PCs using this + if (GetObjectType(oObject) == OBJECT_TYPE_PLACEABLE || GetObjectType(oObject) == OBJECT_TYPE_ITEM) + { + // Check if object's area blocks scrying + if(!GetLocalInt(GetArea(oObject), "SCRY_AREA_BLOCKED")) + { + // If its a legal object, target it for locating + AddChoice(GetName(oObject), nChoice, oPC); + StorePCForRecovery(oPC, oObject, nChoice); + } + } + nChoice += 1; + oObject = GetNextObjectInArea(GetArea(oPC)); + } + } + else + { + // First, get all creatures in the area you're in + object oCreature = GetFirstObjectInArea(GetArea(oPC)); + while (GetIsObjectValid(oCreature) == TRUE) + { + if(DEBUG && (++nDebugCounter % 10 == 0)) + DoDebug("prc_scry_conv: Processed " + IntToString(nDebugCounter) + " creatures"); + // Don't target PCs using this + if (GetObjectType(oCreature) == OBJECT_TYPE_CREATURE) + { + // Check if creature's area blocks scrying + if(!GetLocalInt(GetArea(oCreature), "SCRY_AREA_BLOCKED")) + { + // This can target PCs in the area, but not in other areas + if ((nSpellId == SPELL_CLAIRAUDIENCE_AND_CLAIRVOYANCE || + nSpellId == SPELL_LOCATE_CREATURE || + nSpellId == MYST_TRAIL_OF_HAZE || + nSpellId == POWER_CLAIRVOYANT_SENSE) && + oPC != oCreature && + !GetIsDM(oCreature)) + { + AddChoice(GetName(oCreature), nChoice, oPC); + StorePCForRecovery(oPC, oCreature, nChoice); + } + // Normally, the second part takes care of all PCs + else if ((!GetIsPC(oCreature) && !GetIsDM(oCreature))) + { + AddChoice(GetName(oCreature), nChoice, oPC); + StorePCForRecovery(oPC, oCreature, nChoice); + } + } + } + nChoice += 1; + oCreature = GetNextObjectInArea(GetArea(oPC)); + } + // These only target in their own areas + if (nSpellId != SPELL_CLAIRAUDIENCE_AND_CLAIRVOYANCE && + nSpellId != SPELL_LOCATE_CREATURE && + nSpellId != MYST_TRAIL_OF_HAZE && + nSpellId != POWER_CLAIRVOYANT_SENSE) + { + // Now, loop through all of the PCs + object oPCTarget = GetFirstPC(); + // Don't target yourself + while (GetIsObjectValid(oPCTarget)) + { + if(oPCTarget != oPC && !GetIsDM(oPCTarget)) + { + if(DEBUG && (++nDebugCounter % 10 == 0)) + DoDebug("prc_scry_conv: Processed " + IntToString(nDebugCounter) + " PC targets"); + + // Check if PC's area blocks scrying + if(!GetLocalInt(GetArea(oPCTarget), "SCRY_AREA_BLOCKED")) + { + AddChoice(GetName(oPCTarget), nChoice, oPC); + StorePCForRecovery(oPC, oPCTarget, nChoice); + } + + nChoice += 1; + } + oPCTarget = GetNextPC(); + } + } + } +} + +/* void AddLegalTargets(object oPC) +{ + // This reads all of the legal choices + int nSpellId = GetLocalInt(oPC, "ScrySpellId"); + int nChoice = 1; + int nDebugCounter = 0; // Add debug counter for frequency limiting + + if (nSpellId == SPELL_LOCATE_OBJECT) + { + // First, get all objects in the area you're in + object oObject = GetFirstObjectInArea(GetArea(oPC)); + while (GetIsObjectValid(oObject) == TRUE) + { + if(DEBUG && (++nDebugCounter % 10 == 0)) + DoDebug("prc_scry_conv: Processed " + IntToString(nDebugCounter) + " objects"); + // Don't target PCs using this + if (GetObjectType(oObject) == OBJECT_TYPE_PLACEABLE || GetObjectType(oObject) == OBJECT_TYPE_ITEM) + { + // If its a legal object, target it for locating + AddChoice(GetName(oObject), nChoice, oPC); + StorePCForRecovery(oPC, oObject, nChoice); + } + nChoice += 1; + oObject = GetNextObjectInArea(GetArea(oPC)); + } + } + else + { + // First, get all creatures in the area you're in + object oCreature = GetFirstObjectInArea(GetArea(oPC)); + while (GetIsObjectValid(oCreature) == TRUE) + { + if(DEBUG && (++nDebugCounter % 10 == 0)) + DoDebug("prc_scry_conv: Processed " + IntToString(nDebugCounter) + " creatures"); + // Don't target PCs using this + if (GetObjectType(oCreature) == OBJECT_TYPE_CREATURE) + { + // This can target PCs in the area, but not in other areas + if ((nSpellId == SPELL_CLAIRAUDIENCE_AND_CLAIRVOYANCE || + nSpellId == SPELL_LOCATE_CREATURE || + nSpellId == MYST_TRAIL_OF_HAZE || + nSpellId == POWER_CLAIRVOYANT_SENSE) && + oPC != oCreature && + !GetIsDM(oCreature)) + { + AddChoice(GetName(oCreature), nChoice, oPC); + StorePCForRecovery(oPC, oCreature, nChoice); + } + // Normally, the second part takes care of all PCs + else if ((!GetIsPC(oCreature) && !GetIsDM(oCreature))) + { + AddChoice(GetName(oCreature), nChoice, oPC); + StorePCForRecovery(oPC, oCreature, nChoice); + } + } + nChoice += 1; + oCreature = GetNextObjectInArea(GetArea(oPC)); + } + // These only target in their own areas + if (nSpellId != SPELL_CLAIRAUDIENCE_AND_CLAIRVOYANCE && + nSpellId != SPELL_LOCATE_CREATURE && + nSpellId != MYST_TRAIL_OF_HAZE && + nSpellId != POWER_CLAIRVOYANT_SENSE) + { + // Now, loop through all of the PCs + object oPCTarget = GetFirstPC(); + // Don't target yourself + while (GetIsObjectValid(oPCTarget)) + { + if(oPCTarget != oPC && !GetIsDM(oPCTarget)) + { + if(DEBUG && (++nDebugCounter % 10 == 0)) + DoDebug("prc_scry_conv: Processed " + IntToString(nDebugCounter) + " PC targets"); + AddChoice(GetName(oPCTarget), nChoice, oPC); + StorePCForRecovery(oPC, oPCTarget, nChoice); + + nChoice += 1; + } + oPCTarget = GetNextPC(); + } + } + } +} + */ +/* void AddLegalTargets(object oPC) { // This reads all of the legal choices int nSpellId = GetLocalInt(oPC, "ScrySpellId"); @@ -116,7 +295,7 @@ void AddLegalTargets(object oPC) } } } - + */ ////////////////////////////////////////////////// /* Main function */ ////////////////////////////////////////////////// @@ -220,6 +399,7 @@ void main() if (GetIsSkillSuccessful(oPC, SKILL_TRUESPEAK, nDC)) { // The function will take it from here ScryMain(oPC, oChoice); + } else // Clean up effects { @@ -230,6 +410,7 @@ void main() { // The function will take it from here ScryMain(oPC, oChoice); + } // And we're all done diff --git a/nwn/nwnprc/trunk/spells/sp_arcaneeye.nss b/nwn/nwnprc/trunk/spells/sp_arcaneeye.nss index 7a98a7c2..69644d5e 100644 --- a/nwn/nwnprc/trunk/spells/sp_arcaneeye.nss +++ b/nwn/nwnprc/trunk/spells/sp_arcaneeye.nss @@ -129,6 +129,13 @@ SetLocalInt(oPC, "X2_L_LAST_SPELLSCHOOL_VAR", SPELL_SCHOOL_DIVINATION); return; } + // Check if current area blocks scrying + if(GetLocalInt(GetArea(oPC), "SCRY_FROM_AREA_BLOCKED")) + { + FloatingTextStringOnCreature("This area prevents scrying.", oPC, FALSE); + return; + } + //Declare major variables object oTarget; int nCasterLvl = PRCGetCasterLevel(oPC); diff --git a/nwn/nwnprc/trunk/spells/sp_discernloc.nss b/nwn/nwnprc/trunk/spells/sp_discernloc.nss index 00c88f9e..2be2e303 100644 --- a/nwn/nwnprc/trunk/spells/sp_discernloc.nss +++ b/nwn/nwnprc/trunk/spells/sp_discernloc.nss @@ -28,6 +28,13 @@ SetLocalInt(oPC, "X2_L_LAST_SPELLSCHOOL_VAR", SPELL_SCHOOL_DIVINATION); return; } + // Check if current area blocks scrying + if(GetLocalInt(GetArea(oPC), "SCRY_FROM_AREA_BLOCKED")) + { + FloatingTextStringOnCreature("This area prevents scrying.", oPC, FALSE); + return; + } + //Declare major variables object oTarget; int nCasterLvl = PRCGetCasterLevel(oPC); diff --git a/nwn/nwnprc/trunk/spells/sp_grscrying.nss b/nwn/nwnprc/trunk/spells/sp_grscrying.nss index cf046938..a2c095f3 100644 --- a/nwn/nwnprc/trunk/spells/sp_grscrying.nss +++ b/nwn/nwnprc/trunk/spells/sp_grscrying.nss @@ -114,41 +114,48 @@ void ApplyScryEffects(object oPC) void main() { - object oPC = OBJECT_SELF; + object oPC = OBJECT_SELF; -DeleteLocalInt(oPC, "X2_L_LAST_SPELLSCHOOL_VAR"); -SetLocalInt(oPC, "X2_L_LAST_SPELLSCHOOL_VAR", SPELL_SCHOOL_DIVINATION); + DeleteLocalInt(oPC, "X2_L_LAST_SPELLSCHOOL_VAR"); + SetLocalInt(oPC, "X2_L_LAST_SPELLSCHOOL_VAR", SPELL_SCHOOL_DIVINATION); if (!X2PreSpellCastCode()) { // If code within the PreSpellCastHook (i.e. UMD) reports FALSE, do not run this spell return; } + + // Check if current area blocks scrying + if(GetLocalInt(GetArea(oPC), "SCRY_FROM_AREA_BLOCKED")) + { + FloatingTextStringOnCreature("This area prevents scrying.", oPC, FALSE); + return; + } - //Declare major variables - object oTarget; - int nCasterLvl = PRCGetCasterLevel(oPC); - int nSpell = PRCGetSpellId(); - int nDC = PRCGetSaveDC(oTarget, oPC); - float fDur = HoursToSeconds(nCasterLvl); - int nMetaMagic = PRCGetMetaMagicFeat(); - //Make Metamagic check for extend - if ((nMetaMagic & METAMAGIC_EXTEND)) - { - fDur = fDur * 2; - } - - SetLocalInt(oPC, "ScryCasterLevel", nCasterLvl); - SetLocalInt(oPC, "ScrySpellId", nSpell); - SetLocalInt(oPC, "ScrySpellDC", nDC); - SetLocalFloat(oPC, "ScryDuration", fDur); - - //AssignCommand(oPC, ClearAllActions(TRUE)); - StartDynamicConversation("prc_scry_conv", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC); - - // Apply the immunity effects - ApplyScryEffects(oPC); + //Declare major variables + object oTarget; + int nCasterLvl = PRCGetCasterLevel(oPC); + int nSpell = PRCGetSpellId(); + int nDC = PRCGetSaveDC(oTarget, oPC); + float fDur = HoursToSeconds(nCasterLvl); + int nMetaMagic = PRCGetMetaMagicFeat(); + //Make Metamagic check for extend + if ((nMetaMagic & METAMAGIC_EXTEND)) + { + fDur = fDur * 2; + } + + SetLocalInt(oPC, "ScryCasterLevel", nCasterLvl); + SetLocalInt(oPC, "ScrySpellId", nSpell); + SetLocalInt(oPC, "ScrySpellDC", nDC); + SetLocalFloat(oPC, "ScryDuration", fDur); + + //AssignCommand(oPC, ClearAllActions(TRUE)); + StartDynamicConversation("prc_scry_conv", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC); + + // Apply the immunity effects + ApplyScryEffects(oPC); -DeleteLocalInt(oPC, "X2_L_LAST_SPELLSCHOOL_VAR"); -// Getting rid of the integer used to hold the spells spell school + DeleteLocalInt(oPC, "X2_L_LAST_SPELLSCHOOL_VAR"); + // Getting rid of the integer used to hold the spells spell school } diff --git a/nwn/nwnprc/trunk/spells/sp_loccreature.nss b/nwn/nwnprc/trunk/spells/sp_loccreature.nss index b31bd201..b5eabac4 100644 --- a/nwn/nwnprc/trunk/spells/sp_loccreature.nss +++ b/nwn/nwnprc/trunk/spells/sp_loccreature.nss @@ -28,6 +28,13 @@ SetLocalInt(oPC, "X2_L_LAST_SPELLSCHOOL_VAR", SPELL_SCHOOL_DIVINATION); return; } + // Check if current area blocks scrying + if(GetLocalInt(GetArea(oPC), "SCRY_FROM_AREA_BLOCKED")) + { + FloatingTextStringOnCreature("This area prevents scrying.", oPC, FALSE); + return; + } + //Declare major variables object oTarget; int nCasterLvl = PRCGetCasterLevel(oPC); diff --git a/nwn/nwnprc/trunk/spells/sp_locobject.nss b/nwn/nwnprc/trunk/spells/sp_locobject.nss index 457fac05..7a2b7bd9 100644 --- a/nwn/nwnprc/trunk/spells/sp_locobject.nss +++ b/nwn/nwnprc/trunk/spells/sp_locobject.nss @@ -28,6 +28,13 @@ SetLocalInt(oPC, "X2_L_LAST_SPELLSCHOOL_VAR", SPELL_SCHOOL_DIVINATION); return; } + // Check if current area blocks scrying + if(GetLocalInt(GetArea(oPC), "SCRY_FROM_AREA_BLOCKED")) + { + FloatingTextStringOnCreature("This area prevents scrying.", oPC, FALSE); + return; + } + //Declare major variables object oTarget; int nCasterLvl = PRCGetCasterLevel(oPC); diff --git a/nwn/nwnprc/trunk/spells/sp_scrying.nss b/nwn/nwnprc/trunk/spells/sp_scrying.nss index 599e3a75..796404d8 100644 --- a/nwn/nwnprc/trunk/spells/sp_scrying.nss +++ b/nwn/nwnprc/trunk/spells/sp_scrying.nss @@ -130,7 +130,14 @@ void main() if(nMetaMagic & METAMAGIC_EXTEND) fDur *= 2; - SetLocalInt(oPC, "ScryCasterLevel", nCasterLvl); + // Check if current area blocks scrying + if(GetLocalInt(GetArea(oPC), "SCRY_FROM_AREA_BLOCKED")) + { + FloatingTextStringOnCreature("This area prevents scrying.", oPC, FALSE); + return; + } + + SetLocalInt(oPC, "ScryCasterLevel", nCasterLvl); SetLocalInt(oPC, "ScrySpellId", nSpell); SetLocalInt(oPC, "ScrySpellDC", nDC); SetLocalFloat(oPC, "ScryDuration", fDur);