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.
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);
|
|
}
|
|
}
|
|
|
|
|
|
|