PRC8/nwn/nwnprc/trunk/spells/x0_s3_rodwonder.nss
Jaysyn904 6ec137a24e Updated AMS marker feats
Updated AMS marker feats.  Removed arcane & divine marker feats.  Updated Dread Necromancer for epic progression. Updated weapon baseitem models.  Updated new weapons for crafting & npc equip.
 Updated prefix.  Updated release archive.
2024-02-11 14:01:05 -05:00

539 lines
20 KiB
Plaintext

//:://////////////////////////////////////////////////
//:: X0_S2_RODWONDER
/*
Spell script for Rod of Wonder spell.
This spell produces a random spell effect.
*/
//:://////////////////////////////////////////////////
//:: Copyright (c) 2002 Floodgate Entertainment
//:: Created By: Naomi Novik
//:: Created On: 11/25/2002
//:://////////////////////////////////////////////////
#include "x0_i0_petrify"
#include "x0_i0_spells"
#include "x0_i0_common"
#include "x0_i0_position"
#include "prc_class_const"
/**********************************************************************
* TEMPORARY CONSTANTS
**********************************************************************/
const int SPELL_GEM_SPRAY = 504;
const int SPELL_BUTTERFLY_SPRAY = 505;
/**********************************************************************
* FUNCTION PROTOTYPES
* These are generally custom variations on various spells.
**********************************************************************/
// Nothing happens message
void DoNothing(object oCaster);
// Windstorm-force gust of wind effect -- knocks down everyone in the area
void DoWindstorm(location lTarget);
// Give short-term premonition (d4 rounds & up to d4*5 hp damage absorbed)
void DoDetectThoughts(object oCaster);
// Summon a penguin, cow, or rat
void DoSillySummon(object oTarget);
// Do a blindness spell on all in the given radius of a cone for the given
// number of rounds in duration.
void DoBlindnessEffect(object oCaster, location lTarget, float fRadius, int nDuration);
/**********************************************************************
* MAIN FUNCTION DEFINITION
**********************************************************************/
void main()
{
object oCaster = OBJECT_SELF;
object oTarget = GetAttemptedSpellTarget();
location lTargetLoc = GetSpellTargetLocation();
// Create a placeable object to act as the caster
object oCastingObject = CreateObject(OBJECT_TYPE_PLACEABLE, "x0_rodwonder", GetLocation(oCaster));
int nRoll = d100();
// Roll twice, take the better result
if(GetLevelByClass(CLASS_TYPE_WILD_MAGE, oTarget) >= 3)
{
int nRoll2 = d100();
if (nRoll2 > nRoll)
nRoll = nRoll2;
}
// All the random effects
// 1 - 5
if (nRoll < 6) {
// slow target for 10 rounds
effect eSlow = EffectSlow();
ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
eSlow, oTarget, RoundsToSeconds(10));
// 6 - 10
} else if (nRoll < 11) {
// faerie fire on target, DC 11
// replace with polymorph target into chicken
effect ePoly = EffectPolymorph(POLYMORPH_TYPE_CHICKEN);
effect eImp = EffectVisualEffect(VFX_IMP_POLYMORPH);
ApplyEffectToObject(DURATION_TYPE_INSTANT, eImp, oTarget);
ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
ePoly,
oTarget,
RoundsToSeconds(d4()));
// 11 - 15
} else if (nRoll < 16) {
// delude wielder into thinking it's another effect
int nFakeSpell;
effect eFakeEffect;
if (Random(2) == 0) {
nFakeSpell = SPELL_FIREBALL;
eFakeEffect = EffectVisualEffect(VFX_FNF_FIREBALL);
} else {
nFakeSpell = SPELL_LIGHTNING_BOLT;
eFakeEffect = EffectVisualEffect(VFX_IMP_LIGHTNING_S);
}
AssignCommand(oCastingObject,
ActionCastFakeSpellAtObject(nFakeSpell, oTarget));
if (nFakeSpell == SPELL_LIGHTNING_BOLT) {
effect eLightning = EffectBeam(VFX_BEAM_LIGHTNING,
OBJECT_SELF,
BODY_NODE_HAND);
AssignCommand(oCastingObject,
ActionDoCommand(
ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
eLightning,
oTarget,
1.0)));
}
AssignCommand(oCastingObject,
ActionDoCommand(
ApplyEffectToObject(DURATION_TYPE_INSTANT,
eFakeEffect,
oTarget)));
// 16 - 20
} else if (nRoll < 21) {
// windstorm-force gust of wind
// knock down everyone in the area and play a wind sound
DoWindstorm(lTargetLoc);
// 21 - 25
} else if (nRoll < 26) {
// detect thoughts -- give short-term premonition
DoDetectThoughts(oCaster);
// 26 - 30
} else if (nRoll < 31) {
// stinking cloud, 30 ft range
effect eAOE = EffectAreaOfEffect(AOE_PER_FOGSTINK);
effect eImpact = EffectVisualEffect(259);
ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eImpact, lTargetLoc);
ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY,
eAOE,
lTargetLoc,
RoundsToSeconds(d4()));
// 31 - 33
} else if (nRoll < 34) {
// heavy rain falls briefly
PlaySound("as_wt_thundercl3");
object oArea = GetArea(oCaster);
SetWeather(oArea, WEATHER_RAIN);
DelayCommand(RoundsToSeconds(5),
SetWeather(oArea, WEATHER_USE_AREA_SETTINGS));
// 34 - 36
} else if (nRoll < 37) {
// summon penguin, rat, or cow
DoSillySummon(oTarget);
// 37 - 43
} else if (nRoll < 44) {
// lightning bolt
int nDamage = d6(6);
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF,
SPELLABILITY_BOLT_LIGHTNING));
nDamage = GetReflexAdjustedDamage(nDamage,
oTarget,
13,
SAVING_THROW_TYPE_ELECTRICITY);
//Make a ranged touch attack
if (nDamage > 0 && TouchAttackRanged(oTarget) > 0) {
effect eLightning = EffectBeam(VFX_BEAM_LIGHTNING,
oCaster,
BODY_NODE_HAND);
effect eVis = EffectVisualEffect(VFX_IMP_LIGHTNING_S);
effect eBolt = EffectDamage(nDamage, DAMAGE_TYPE_ELECTRICAL);
//Apply the VFX impact and effects
ApplyEffectToObject(DURATION_TYPE_INSTANT, eBolt, oTarget);
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget);
ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
eLightning,
oTarget,
1.7);
}
// 44 - 46
} else if (nRoll < 47) {
// polymorph caster into a penguin
effect ePoly = EffectPolymorph(POLYMORPH_TYPE_PENGUIN);
effect eImp = EffectVisualEffect(VFX_IMP_POLYMORPH);
ApplyEffectToObject(DURATION_TYPE_INSTANT, eImp, oCaster);
ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
ePoly,
oCaster,
RoundsToSeconds(d4()));
SetCustomToken(0, GetName(oCaster));
FloatingTextStrRefOnCreature( 9266, oCaster);
// 47 - 49 Butterflies
} else if (nRoll < 50) {
ActionCastSpellAtObject(505,
oTarget,
METAMAGIC_ANY, TRUE);
ActionDoCommand(SetCommandable(TRUE));
SetCommandable(FALSE);
// 50 - 53
} else if (nRoll < 54) {
// enlarge target -- replaced by giving the target
// Bull's Strength
effect eStr = EffectAbilityIncrease(ABILITY_STRENGTH, d4());
effect eVis = EffectVisualEffect(VFX_IMP_IMPROVE_ABILITY_SCORE);
effect eDur = EffectVisualEffect(VFX_DUR_CESSATE_POSITIVE);
effect eLink = EffectLinkEffects(eStr, eDur);
ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
eLink,
oTarget,
RoundsToSeconds(d6()));
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget);
// 54 - 58
} else if (nRoll < 59) {
// darkness around target
effect eAOE = EffectAreaOfEffect(AOE_PER_DARKNESS);
ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY,
eAOE,
lTargetLoc,
RoundsToSeconds(d4()));
// 59 - 62
} else if (nRoll < 63) {
// grass grows around caster
effect eAOE = EffectAreaOfEffect(AOE_PER_ENTANGLE);
ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY,
eAOE,
GetLocation(oCaster),
RoundsToSeconds(d6()));
// 63 - 65
} else if (nRoll < 66) {
// turn target ethereal
effect eVis = EffectVisualEffect(VFX_DUR_ETHEREAL_VISAGE);
effect eDam = EffectDamageReduction(20, DAMAGE_POWER_PLUS_THREE);
effect eSpell = EffectSpellLevelAbsorption(2);
effect eConceal = EffectConcealment(25);
effect eDur = EffectVisualEffect(VFX_DUR_CESSATE_POSITIVE);
effect eLink = EffectLinkEffects(eDam, eVis);
eLink = EffectLinkEffects(eLink, eSpell);
eLink = EffectLinkEffects(eLink, eDur);
eLink = EffectLinkEffects(eLink, eConceal);
ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
eLink,
oTarget,
RoundsToSeconds(d4()));
// 66 - 69
} else if (nRoll < 70) {
// reduce wielder -- replaced by making the
// target invisible
effect eInvis = EffectInvisibility(INVISIBILITY_TYPE_NORMAL);
ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
eInvis,
oTarget,
RoundsToSeconds(d6()));
// 70 - 76
} else if (nRoll < 77) {
// fireball
AssignCommand(oCastingObject,
ActionCastSpellAtObject(SPELL_FIREBALL,
oTarget,
METAMAGIC_NONE,
TRUE,0,
PROJECTILE_PATH_TYPE_DEFAULT,
TRUE));
// 77 - 79
} else if (nRoll < 80) {
// polymorph target into a chicken
effect ePoly = EffectPolymorph(POLYMORPH_TYPE_CHICKEN);
effect eImp = EffectVisualEffect(VFX_IMP_POLYMORPH);
ApplyEffectToObject(DURATION_TYPE_INSTANT, eImp, oTarget);
ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
ePoly,
oTarget,
RoundsToSeconds(d4()));
SetCustomToken(0, GetName(oTarget));
FloatingTextStrRefOnCreature( 9265, oTarget);
// 80 - 84
} else if (nRoll < 85) {
// wielder goes invisible
effect eInvis = EffectInvisibility(INVISIBILITY_TYPE_NORMAL);
effect eDur = EffectVisualEffect(VFX_DUR_CESSATE_POSITIVE);
effect eLink = EffectLinkEffects(eInvis, eDur);
ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
eLink,
oCaster,
RoundsToSeconds(d6()));
// 85 - 87
} else if (nRoll < 88) {
// leaves grow from target
// - long-term pixie dust visual effect on caster
int nEffectPixieDust = 321;
effect eDust = EffectVisualEffect(nEffectPixieDust);
ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
eDust,
oCaster,
RoundsToSeconds(d10(3) + 10));
// 88 - 90
} else if (nRoll < 91) {
// SpawnScriptDebugger();
// 10-40 gems fly out
ActionCastSpellAtObject(SPELL_GEM_SPRAY,
oTarget,
METAMAGIC_ANY, TRUE);
// ActionCastSpellAtObject(504,
// oTarget, METAMAGIC_ANY, TRUE);
ActionDoCommand(SetCommandable(TRUE));
SetCommandable(FALSE);
//DoFlyingGems(oCaster, lTargetLoc);
// 91 - 95
} else if (nRoll < 96) {
// shimmering colors blind
ActionCastFakeSpellAtObject(SPELL_PRISMATIC_SPRAY,
oTarget,
PROJECTILE_PATH_TYPE_DEFAULT);
DoBlindnessEffect(oCaster, lTargetLoc, 20.0, d4());
// 96 - 97
} else if (nRoll < 98) {
// wielder turns blue or purple
effect eVis;
SetCustomToken(0, GetName(oCaster));
if (Random(2) == 0) {
eVis = EffectVisualEffect(VFX_DUR_GHOSTLY_VISAGE);
FloatingTextStrRefOnCreature(8861,
oCaster);
} else {
eVis = EffectVisualEffect(VFX_DUR_ETHEREAL_VISAGE);
FloatingTextStrRefOnCreature(8860,
oCaster);
}
ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
eVis, oCaster,
TurnsToSeconds(3));
// 98 - 100
} else {
// flesh to stone or stone to flesh
int nSpell = SPELL_FLESH_TO_STONE;
effect eEff = GetFirstEffect(oTarget);
while (GetIsEffectValid(eEff) && GetEffectType(eEff) != EFFECT_TYPE_PETRIFY)
eEff = GetNextEffect(oTarget);
if (GetIsEffectValid(eEff) && GetEffectType(eEff) == EFFECT_TYPE_PETRIFY)
nSpell = SPELL_STONE_TO_FLESH;
AssignCommand(oCastingObject,
ActionCastSpellAtObject(nSpell,
oTarget,
METAMAGIC_NONE,
TRUE,0,
PROJECTILE_PATH_TYPE_DEFAULT,
TRUE));
}
DestroyObject(oCastingObject, 6.0);
}
/**********************************************************************
* FUNCTION DEFINITIONS
* All the individual effect functions are below.
***********************************************************/
// Nothing happens message
void DoNothing(object oCaster)
{
FloatingTextStrRefOnCreature(8848, oCaster);
}
// Windstorm-force gust of wind effect
void DoWindstorm(location lTarget)
{
// Play a low thundering sound
PlaySound("as_wt_thunderds4");
// Capture the first target object in the shape.
object oTarget = GetFirstObjectInShape(SHAPE_SPHERE,
RADIUS_SIZE_HUGE,
lTarget, TRUE,
OBJECT_TYPE_CREATURE |
OBJECT_TYPE_DOOR |
OBJECT_TYPE_AREA_OF_EFFECT);
// Cycle through the targets within the spell shape
while (GetIsObjectValid(oTarget)) {
// Play a random sound
switch (Random(5)) {
case 0: AssignCommand(oTarget, PlaySound("as_wt_gustchasm1")); break;
case 1: AssignCommand(oTarget, PlaySound("as_wt_gustcavrn1")); break;
case 2: AssignCommand(oTarget, PlaySound("as_wt_gustgrass1")); break;
case 3: AssignCommand(oTarget, PlaySound("as_wt_guststrng1")); break;
case 4: AssignCommand(oTarget, PlaySound("fs_floatair")); break;
}
// Area-of-effect spells get blown away
if (GetObjectType(oTarget) == OBJECT_TYPE_AREA_OF_EFFECT) {
DestroyObject(oTarget);
}
// * unlocked doors will reverse their open state
else if (GetObjectType(oTarget) == OBJECT_TYPE_DOOR) {
if (!GetLocked(oTarget)) {
if (GetIsOpen(oTarget) == FALSE)
AssignCommand(oTarget, ActionOpenDoor(oTarget));
else
AssignCommand(oTarget, ActionCloseDoor(oTarget));
}
}
// creatures will get knocked down, tough fort saving throw
// to resist.
else if (GetObjectType(oTarget) == OBJECT_TYPE_CREATURE) {
if( !FortitudeSave(oTarget, 15) ) {
effect eKnockdown = EffectKnockdown();
ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
eKnockdown,
oTarget,
RoundsToSeconds(1));
}
}
// Get the next target within the spell shape.
oTarget = GetNextObjectInShape(SHAPE_SPHERE,
RADIUS_SIZE_HUGE,
lTarget, TRUE,
OBJECT_TYPE_CREATURE |
OBJECT_TYPE_DOOR |
OBJECT_TYPE_AREA_OF_EFFECT);
}
}
// Give premonition for a few rounds, up to d4*5 hp
void DoDetectThoughts(object oCaster)
{
int nRounds = d4();
int nLimit = nRounds * 5;
effect ePrem = EffectDamageReduction(30, DAMAGE_POWER_PLUS_FIVE, nLimit);
effect eVis = EffectVisualEffect(VFX_DUR_PROT_PREMONITION);
//Link the visual and the damage reduction effect
effect eLink = EffectLinkEffects(ePrem, eVis);
//Fire cast spell at event for the specified target
SignalEvent(oCaster, EventSpellCastAt(oCaster, SPELL_PREMONITION, FALSE));
//Apply the linked effect
ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
eLink, oCaster, RoundsToSeconds(nRounds));
}
// Summon something extremely silly (rats will be hostile to caster!)
void DoSillySummon(object oTarget)
{
location lTargetLoc = GetOppositeLocation(oTarget);
int nSummon = d100();
string sSummon = "";
if (nSummon < 26) {
sSummon = "x0_penguin001";
} else if (nSummon < 51) {
sSummon = "nw_cow";
} else {
sSummon = "nw_rat001";
}
ApplyEffectAtLocation(DURATION_TYPE_INSTANT,
EffectVisualEffect(VFX_FNF_SUMMON_MONSTER_1),
lTargetLoc);
CreateObject(OBJECT_TYPE_CREATURE, sSummon, lTargetLoc, TRUE);
}
// Do a blindness spell on all in the given radius of a cone for the given
// number of rounds in duration.
void DoBlindnessEffect(object oCaster, location lTarget, float fRadius, int nDuration)
{
vector vOrigin = GetPosition(oCaster);
effect eVis = EffectVisualEffect(VFX_IMP_BLIND_DEAF_M);
effect eDur = EffectVisualEffect(VFX_DUR_CESSATE_NEGATIVE);
effect eLink = EffectBlindness();
eLink = EffectLinkEffects(eLink, eDur);
object oTarget = GetFirstObjectInShape(SHAPE_CONE,
fRadius,
lTarget,
TRUE,
OBJECT_TYPE_CREATURE,
vOrigin);
while (GetIsObjectValid(oTarget)) {
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF,
SPELL_BLINDNESS_AND_DEAFNESS));
//Do SR check
if ( !MyResistSpell(OBJECT_SELF, oTarget)) {
// Make Fortitude save to negate
if (! MySavingThrow(SAVING_THROW_FORT, oTarget, 13)) {
//Apply visual and effects
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oTarget,
RoundsToSeconds(nDuration));
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget);
}
}
oTarget = GetNextObjectInShape(SHAPE_CONE,
fRadius,
lTarget,
TRUE,
OBJECT_TYPE_CREATURE,
vOrigin);
}
}