Spell update
Added the following spells: Regenerate Light Wounds, Regenerate Moderate Wounds, Regenerate Serious Wounds, Regenerate Critical Wounds, Spirit Worm, Tortoise Shell, Speed of the Wind & Spiritual Weapon. Updated Force Missiles & Chasing Perfection. Updated Acid Fog to be more like pen & paper. Updated release archive.
This commit is contained in:
225
nwn/nwnprc/trunk/scripts/prc_evnt_spirwep.nss
Normal file
225
nwn/nwnprc/trunk/scripts/prc_evnt_spirwep.nss
Normal file
@@ -0,0 +1,225 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: [Spiritual Weapon]
|
||||
//:: [prc_evnt_spirwep.nss]
|
||||
//:: [Jaysyn 2024-08-23 07:58:14]
|
||||
//::
|
||||
//:: OnHit event script for the Spiritual
|
||||
//:: Weapon spell.
|
||||
//::
|
||||
//::///////////////////////////////////////////////
|
||||
/**@ Spiritual Weapon
|
||||
(Player's Handbook v.3.5, p. 283)
|
||||
|
||||
Evocation [Force]
|
||||
Level: Cleric 2, Knight of the Chalice 2, War 2, Mysticism 2,
|
||||
Components: V, S, DF,
|
||||
Casting Time: 1 standard action
|
||||
Range: Medium (100 ft. + 10 ft./level)
|
||||
Effect: Magic weapon of force
|
||||
Duration: 1 round/level (D)
|
||||
Saving Throw: None
|
||||
Spell Resistance: Yes
|
||||
|
||||
A weapon made of pure force springs into existence and attacks
|
||||
opponents at a distance, as you direct it, dealing 1d8 force
|
||||
damage per hit, +1 point per three caster levels (maximum +5
|
||||
at 15th level). The weapon takes the shape of a weapon
|
||||
favored by your deity or a weapon with some spiritual
|
||||
significance or symbolism to you (see below) and has the
|
||||
same threat range and critical multipliers as a real weapon
|
||||
of its form. It strikes the opponent you designate, starting
|
||||
with one attack in the round the spell is cast and continuing
|
||||
each round thereafter on your turn. It uses your base attack
|
||||
bonus (possibly allowing it multiple attacks per round in
|
||||
subsequent rounds) plus your Wisdom modifier as its attack
|
||||
bonus. It strikes as a spell, not as a weapon, so, for
|
||||
example, it can damage creatures that have damage
|
||||
reduction. As a force effect, it can strike incorporeal
|
||||
creatures without the normal miss chance associated with
|
||||
incorporeality. The weapon always strikes from your
|
||||
direction. It does not get a flanking bonus or help a
|
||||
combatant get one. Your feats (such as Weapon Focus)
|
||||
or combat actions (such as charge) do not affect the
|
||||
weapon. If the weapon goes beyond the spell range, if
|
||||
it goes out of your sight, or if you are not directing
|
||||
it, the weapon returns to you and hovers.
|
||||
|
||||
Each round after the first, you can use a move action to
|
||||
redirect the weapon to a new target. If you do not,
|
||||
the weapon continues to attack the previous round's
|
||||
target. On any round that the weapon switches targets,
|
||||
it gets one attack. Subsequent rounds of attacking that
|
||||
target allow the weapon to make multiple attacks if your
|
||||
base attack bonus would allow it to. Even if the spiritual
|
||||
weapon is a ranged weapon, use the spell's range, not the
|
||||
weapon's normal range increment, and switching targets
|
||||
still is a move action.
|
||||
|
||||
A spiritual weapon cannot be attacked or harmed by
|
||||
physical attacks, but dispel magic, disintegrate, a
|
||||
sphere of annihilation, or a rod of cancellation affects it.
|
||||
A spiritual weapon's AC against touch attacks is 12 (10 +
|
||||
size bonus for Tiny object).
|
||||
|
||||
If an attacked creature has spell resistance, you make a
|
||||
caster level check (1d20 + caster level) against that
|
||||
spell resistance the first time the spiritual weapon
|
||||
strikes it. If the weapon is successfully resisted, the
|
||||
spell is dispelled. If not, the weapon has its normal
|
||||
full effect on that creature for the duration of the spell.
|
||||
*///////////////////////////////////////////////////////////
|
||||
#include "prc_inc_spells"
|
||||
#include "inc_spirit_weapn"
|
||||
|
||||
void main()
|
||||
{
|
||||
object oWeapon = PRCGetSpellCastItem(); // The weapon itself
|
||||
object oSummon = GetItemPossessor(oWeapon); // The wielder of the weapon
|
||||
object oTarget = PRCGetSpellTargetObject(); // The creature being attacked
|
||||
object oCaster = GetLocalObject(oSummon, "MY_CASTER"); // Retrieve the stored caster
|
||||
object oPC = GetFirstPC(); // First player character for debug messages
|
||||
|
||||
int nRunEvent = GetRunningEvent();
|
||||
|
||||
if (nRunEvent == EVENT_ONUNAQUIREITEM || nRunEvent == EVENT_ITEM_ONPLAYERUNEQUIPITEM)
|
||||
{
|
||||
oSummon = GetPCItemLastUnequippedBy();
|
||||
oWeapon = GetPCItemLastUnequipped();
|
||||
SendMessageToPC(GetFirstPC(), "prc_evnt_spirwep: Item OnUnEquip / OnUnAcquire Event running.");
|
||||
HandleSpiritualWeaponUnequipEvent();
|
||||
return;
|
||||
}
|
||||
|
||||
if(DEBUG) DoDebug("prc_evnt_spirwep: Script started. Weapon hit detected.");
|
||||
|
||||
if(DEBUG) DoDebug("prc_evnt_spirwep: Caster found: " + GetName(oCaster));
|
||||
|
||||
int nCasterLevel = PRCGetCasterLevel(oCaster);
|
||||
int nPenetr = nCasterLevel + SPGetPenetr();
|
||||
|
||||
if(DEBUG) DoDebug("prc_evnt_spirwep: Caster Level: " + IntToString(nCasterLevel));
|
||||
if(DEBUG) DoDebug("prc_evnt_spirwep: Spell Penetration: " + IntToString(SPGetPenetr()));
|
||||
if(DEBUG) DoDebug("prc_evnt_spirwep: Total Penetration: " + IntToString(nPenetr));
|
||||
|
||||
string sRunKey = ObjectToString(oWeapon)+"SR_CHECKED_" + ObjectToString(oTarget);
|
||||
if (!GetLocalInt(oWeapon, sRunKey))
|
||||
{
|
||||
if(DEBUG) DoDebug("prc_evnt_spirwep: SR check has not been performed yet. Proceeding with the check.");
|
||||
SetLocalInt(oWeapon, sRunKey, TRUE);
|
||||
|
||||
if(PRCDoResistSpell(oCaster, oTarget, nPenetr))
|
||||
{
|
||||
if(DEBUG) DoDebug("prc_evnt_spirwep: Target's spell resistance check succeeded. Destroying Spiritual Weapon.");
|
||||
|
||||
SetPlotFlag(oWeapon, FALSE);
|
||||
SetPlotFlag(oSummon, FALSE);
|
||||
SetImmortal(oSummon, FALSE);
|
||||
|
||||
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_FNF_DISPEL), oSummon);
|
||||
if(DEBUG) DoDebug("prc_evnt_spirwep: VFX applied to wielder.");
|
||||
|
||||
DelayCommand(0.5f, DestroyObject(oWeapon));
|
||||
if(DEBUG) DoDebug("prc_evnt_spirwep: Spiritual Weapon destruction scheduled.");
|
||||
|
||||
DelayCommand(1.0f, DestroyObject(oSummon));
|
||||
if(DEBUG) DoDebug("prc_evnt_spirwep: Spiritual Weapon Summon destruction scheduled.");
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(DEBUG) DoDebug("prc_evnt_spirwep: Spell resistance check passed. Spiritual Weapon remains intact.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(DEBUG) DoDebug("prc_evnt_spirwep: SR check already performed for this target. Skipping SR check.");
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
/* void main()
|
||||
{
|
||||
object oWeapon = PRCGetSpellCastItem(); // The weapon itself
|
||||
object oSummon = GetItemPossessor(oWeapon); // The wielder of the weapon
|
||||
object oTarget = PRCGetSpellTargetObject(); // The creature being attacked
|
||||
object oCaster = GetLocalObject(oSummon, "MY_CASTER"); // Retrieve the stored caster
|
||||
object oPC = GetFirstPC(); // First player character for debug messages
|
||||
|
||||
if(DEBUG) DoDebug("prc_evnt_spirwep: Script started. Weapon hit detected.");
|
||||
|
||||
if (GetUserDefinedItemEventNumber() == X2_ITEM_EVENT_UNEQUIP)
|
||||
{
|
||||
oSummon = GetPCItemLastUnequippedBy();
|
||||
oWeapon = GetPCItemLastUnequipped();
|
||||
SendMessageToPC(GetFirstPC(), "prc_evnt_spirwep: Item OnUnEquip Event running.");
|
||||
HandleSpiritualWeaponUnequipEvent();
|
||||
return;
|
||||
}
|
||||
|
||||
else if (GetUserDefinedItemEventNumber() != X2_ITEM_EVENT_ONHITCAST)
|
||||
{
|
||||
if(DEBUG) DoDebug("prc_evnt_spirwep: onHit Event not detected.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (oCaster == OBJECT_INVALID)
|
||||
{
|
||||
if(DEBUG) DoDebug("prc_evnt_spirwep: Error: Caster not found on summon. Exiting script.");
|
||||
return;
|
||||
}
|
||||
|
||||
if(DEBUG) DoDebug("prc_evnt_spirwep: Caster found: " + GetName(oCaster));
|
||||
|
||||
int nCasterLevel = PRCGetCasterLevel(oCaster);
|
||||
int nPenetr = nCasterLevel + SPGetPenetr();
|
||||
|
||||
if(DEBUG) DoDebug("prc_evnt_spirwep: Caster Level: " + IntToString(nCasterLevel));
|
||||
if(DEBUG) DoDebug("prc_evnt_spirwep: Spell Penetration: " + IntToString(SPGetPenetr()));
|
||||
if(DEBUG) DoDebug("prc_evnt_spirwep: Total Penetration: " + IntToString(nPenetr));
|
||||
|
||||
string sRunKey = ObjectToString(oWeapon)+"SR_CHECKED_" + ObjectToString(oTarget);
|
||||
if (!GetLocalInt(oWeapon, sRunKey))
|
||||
{
|
||||
if(DEBUG) DoDebug("prc_evnt_spirwep: SR check has not been performed yet. Proceeding with the check.");
|
||||
SetLocalInt(oWeapon, sRunKey, TRUE);
|
||||
|
||||
if(PRCDoResistSpell(oCaster, oTarget, nPenetr))
|
||||
{
|
||||
if(DEBUG) DoDebug("prc_evnt_spirwep: Target's spell resistance check succeeded. Destroying Spiritual Weapon.");
|
||||
|
||||
SetPlotFlag(oWeapon, FALSE);
|
||||
SetPlotFlag(oSummon, FALSE);
|
||||
SetImmortal(oSummon, FALSE);
|
||||
|
||||
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_FNF_DISPEL), oSummon);
|
||||
if(DEBUG) DoDebug("prc_evnt_spirwep: VFX applied to wielder.");
|
||||
|
||||
DelayCommand(0.5f, DestroyObject(oWeapon));
|
||||
if(DEBUG) DoDebug("prc_evnt_spirwep: Spiritual Weapon destruction scheduled.");
|
||||
|
||||
DelayCommand(1.0f, DestroyObject(oSummon));
|
||||
if(DEBUG) DoDebug("prc_evnt_spirwep: Spiritual Weapon Summon destruction scheduled.");
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(DEBUG) DoDebug("prc_evnt_spirwep: Spell resistance check passed. Spiritual Weapon remains intact.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(DEBUG) DoDebug("prc_evnt_spirwep: SR check already performed for this target. Skipping SR check.");
|
||||
}
|
||||
|
||||
int nDamBonus = min(5, nCasterLevel / 3);
|
||||
effect eDamage = EffectDamage(nDamBonus, DAMAGE_TYPE_DIVINE);
|
||||
ApplyEffectToObject(DURATION_TYPE_INSTANT, eDamage, oTarget);
|
||||
if(DEBUG) DoDebug("prc_evnt_spirwep: "+IntToString(nDamBonus)+" magical damage applied to the target.");
|
||||
} */
|
98
nwn/nwnprc/trunk/scripts/rs_regen_wounds.nss
Normal file
98
nwn/nwnprc/trunk/scripts/rs_regen_wounds.nss
Normal file
@@ -0,0 +1,98 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: [Regenerate X Wounds]
|
||||
//:: [rs_regen_wounds.nss]
|
||||
//:: [Jaysyn - PRC8 2024-08-29 12:26:40]
|
||||
//::
|
||||
//:: RunScript for Regeneration effect
|
||||
//::
|
||||
//::///////////////////////////////////////////////
|
||||
/**@file Regenerate X Wounds
|
||||
(Masters of the Wild: A Guidebook to Barbarians,
|
||||
Druids, and Rangers)
|
||||
|
||||
Conjuration (Healing)
|
||||
Level: Cleric 1-4, Druid 1-4,
|
||||
Components: V, S,
|
||||
Casting Time: 1 action
|
||||
Range: Touch
|
||||
Target: Living creature touched
|
||||
Duration: 10 rounds + 1 round/level
|
||||
Saving Throw: Will negates (harmless)
|
||||
Spell Resistance: Yes (harmless)
|
||||
|
||||
With a touch of your hand, you boost the subject's
|
||||
life energy, granting him or her the fast healing
|
||||
ability for the duration of the spell.
|
||||
|
||||
This healing applies only to damage sustained during
|
||||
the spell's duration, not to that from previous injuries.
|
||||
|
||||
The subject heals 1 hit point per round of such
|
||||
damage until the spell ends and is automatically stabilized
|
||||
if he or she begins dying from hit point loss during that time.
|
||||
|
||||
Regenerate light wounds does not restore hit points lost from
|
||||
starvation, thirst, or suffocation, nor does it allow a creature
|
||||
to regrow or attach lost body parts.
|
||||
|
||||
The effects of multiple regenerate spells do not stack, only
|
||||
the highest-level effect applies.
|
||||
|
||||
Applying a second regenerate spell of equal level extends the
|
||||
first spell's duration by the full duration of the second spell.
|
||||
|
||||
*//////////////////////////////////////////////////
|
||||
#include "prc_inc_spells"
|
||||
|
||||
void ControlledRegeneration(object oTarget, int nRegenRate)
|
||||
{
|
||||
int nCurrentHP = GetCurrentHitPoints(oTarget);
|
||||
int nInitialHP = GetLocalInt(oTarget, "INITIAL_HIT_POINTS");
|
||||
|
||||
if(DEBUG) DoDebug("rs_regen_wounds > ControlledRegeneration: Initial HP = " + IntToString(nInitialHP) + ".");
|
||||
if(DEBUG) DoDebug("rs_regen_wounds > ControlledRegeneration: Current HP = " + IntToString(nCurrentHP) + ".");
|
||||
|
||||
if (nCurrentHP < nInitialHP)
|
||||
{
|
||||
int nHealAmount = min(nRegenRate, nInitialHP - nCurrentHP); // Ensure not to heal beyond the initial hit points
|
||||
if(DEBUG) DoDebug( "rs_regen_wounds > ControlledRegeneration: Healing " + IntToString(nHealAmount) + " HP.");
|
||||
effect eFakeRegen = EffectHeal(nHealAmount);
|
||||
ApplyEffectToObject(DURATION_TYPE_INSTANT, eFakeRegen, oTarget);
|
||||
|
||||
effect eVis = EffectVisualEffect(VFX_DUR_GLOW_LIGHT_GREEN);
|
||||
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eVis, oTarget, 6.0f); // Temporary visual effect
|
||||
}
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
// Get the event type
|
||||
int nEvent = GetLastRunScriptEffectScriptType();
|
||||
// Get original effect
|
||||
effect eOriginal = GetLastRunScriptEffect();
|
||||
// Get creator
|
||||
object oCaster = GetEffectCreator(eOriginal);
|
||||
// Get healing amount from sData
|
||||
int nHealing = StringToInt(GetEffectString(eOriginal, 0));
|
||||
// Target is OBJECT_SELF, needed for AssignCommand later
|
||||
object oTarget = OBJECT_SELF;
|
||||
|
||||
// We apply healing on the start and interval scripts
|
||||
switch(nEvent)
|
||||
{
|
||||
case RUNSCRIPT_EFFECT_SCRIPT_TYPE_ON_APPLIED:
|
||||
case RUNSCRIPT_EFFECT_SCRIPT_TYPE_ON_INTERVAL:
|
||||
{
|
||||
// Apply Healing
|
||||
ControlledRegeneration(oTarget, nHealing);
|
||||
}
|
||||
break;
|
||||
case RUNSCRIPT_EFFECT_SCRIPT_TYPE_ON_REMOVED:
|
||||
{
|
||||
// Cessate
|
||||
effect eCessate = EffectVisualEffect(VFX_DUR_CESSATE_NEGATIVE);
|
||||
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eCessate, oTarget, 0.1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user