Updated Release Archive. Fixed Mage-killer prereqs. Removed old LETO & ConvoCC related files. Added organized spell scroll store. Fixed Gloura spellbook. Various TLK fixes. Reorganized Repo. Removed invalid user folders. Added DocGen back in.
539 lines
20 KiB
Plaintext
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);
|
|
}
|
|
}
|
|
|
|
|
|
|