//::////////////////////////////////////////////////// //:: jw_nun_wild_eff /* 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_inc_spells" /********************************************************************** * 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 deer void DoSillySummon(object oTarget); // Do WyrmBreath void DoWyrmBreath(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() { // DEBUG //SpeakString("DEBUG - running wild magic"); object oCaster = OBJECT_SELF; object oTarget = GetAttemptedSpellTarget(); if(oTarget == OBJECT_INVALID) oTarget = oCaster; location lTargetLoc = PRCGetSpellTargetLocation(); // Get rid of the casting object int nRoll = d100(); // All the random effects DBG_msg("Rod nRoll: " + IntToString(nRoll)); // 1 - 5 if (nRoll < 6) { // stone hold target for 2 rounds effect eHold = EffectMovementSpeedDecrease(99); effect eVis = EffectVisualEffect(VFX_DUR_STONEHOLD); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eHold, oTarget, RoundsToSeconds(2)); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eVis, oTarget, RoundsToSeconds(2)); // 6 - 10 } else if (nRoll < 11 ) { // faerie fire on target, DC 11 // replace with polymorph target into chicken if(GetMaster(oTarget) != OBJECT_INVALID) return; // should not affect henchmen 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) { // create rats ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectVisualEffect(469),oTarget); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,EffectSwarm(FALSE,"jw_ratty","jw_ratty","jw_ratty","jw_ratty"),oTarget,300.0); // 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 - 22 } else if (nRoll < 23) { // fireworks... int nRand = Random(4) + 2; int i; float fDelay; effect eVis = EffectVisualEffect(VFX_FNF_MYSTICAL_EXPLOSION); for(i = 1; i <= nRand; i++) { DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget)); fDelay += 3.0; } // 26 - 30 } else if (nRoll < 29) { // chains sprout from caster to any nearby creature for a few rounds int i = 1; object oCreature = GetNearestCreature(CREATURE_TYPE_IS_ALIVE, TRUE, oCaster, i); float fDistance; effect eChain = EffectBeam(VFX_BEAM_CHAIN, oCaster, BODY_NODE_CHEST); effect eImp = EffectVisualEffect(VFX_COM_HIT_SONIC); while(oCreature != OBJECT_INVALID) { fDistance = GetDistanceBetween(oCaster, oCreature); if(fDistance >= 20.0) return; ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eChain, oCreature, 18.0); ApplyEffectToObject(DURATION_TYPE_INSTANT, eImp, oCreature); i++; oCreature = GetNearestCreature(CREATURE_TYPE_IS_ALIVE, TRUE, oCaster, i); } // 31 - 33 } else if (nRoll < 34) { //Declare major variables including Area of Effect Object effect eAOE = EffectAreaOfEffect(AOE_PER_STORM); effect eVis = EffectVisualEffect(VFX_FNF_STORM); ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eVis, lTargetLoc); //Create an instance of the AOE Object using the Apply Effect function ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, eAOE, lTargetLoc, RoundsToSeconds(10)); // 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 = PRCGetReflexAdjustedDamage(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 if(GetMaster(oCaster) != OBJECT_INVALID) return; // should not affect henchmen 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)); // 47 - 49 Butterflies } else if (nRoll < 50) { ActionCastSpellAtObject(505, oTarget, METAMAGIC_ANY, TRUE); ActionDoCommand(SetCommandable(TRUE)); SetCommandable(FALSE); // 50 - 53 } else if (nRoll < 54) { // switch caster and target's places (if casting a spell on self then strike with holy strike) location lLoc1 = GetLocation(oTarget); location lLoc2 = GetLocation(oCaster); if(oCaster == oTarget) { oTarget=GetNearestCreature(CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY); } if (GetIsObjectValid(oTarget)) { AssignCommand(oTarget, JumpToLocation(lLoc2)); AssignCommand(oCaster, JumpToLocation(lLoc1)); } else { ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectVisualEffect(VFX_FNF_GREATER_RUIN),oCaster); } // 54 - 58 } else if (nRoll < 59) { ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectVisualEffect(VFX_FNF_MYSTICAL_EXPLOSION),oCaster); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,EffectVisualEffect(VFX_DUR_GLOW_LIGHT_PURPLE),oCaster,60.0); // 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 - 69 } else if (nRoll < 70) { effect eVis = EffectVisualEffect(VFX_DUR_FLIES); int nRand = Random(4) + 2; ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eVis, oTarget, RoundsToSeconds(nRand)); // 70 - 76 } else if (nRoll < 77) { // Wyrmbreath DoWyrmBreath(oTarget); // 77 - 79 } else if (nRoll < 80 ) { if(GetMaster(oTarget) != OBJECT_INVALID) return; // should not affect henchmen // 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)); // 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) { if(GetMaster(oTarget) != OBJECT_INVALID) return; // should not affect henchmen // polymorph target into a chicken effect ePoly = EffectPolymorph(POLYMORPH_TYPE_HARPY); effect eImp = EffectVisualEffect(VFX_IMP_POLYMORPH); ApplyEffectToObject(DURATION_TYPE_INSTANT, eImp, oTarget); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, ePoly, oTarget, RoundsToSeconds(d4())); SetCustomToken(0, GetName(oTarget)); // 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 { // target changes colors every round for 4-9 rounds int nDur = Random(6) + 4; int i; float fDelay; int nRand; int nEffect; effect eVis; for(i = 1; i <= nDur; i++) { nRand = Random(7) + 1; if(nRand == 1) nEffect = VFX_DUR_GLOW_PURPLE; else if(nRand == 2) nEffect = VFX_DUR_GLOW_RED; else if(nRand == 3) nEffect = VFX_DUR_GLOW_YELLOW; else if(nRand == 4) nEffect = VFX_DUR_GLOW_GREEN; else if(nRand == 5) nEffect = VFX_DUR_GLOW_ORANGE; else if(nRand == 6) nEffect = VFX_DUR_GLOW_BROWN; else if(nRand == 7) nEffect = VFX_DUR_GLOW_GREY; eVis = EffectVisualEffect(nEffect); DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eVis, oTarget, 6.0)); fDelay += 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 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_deer"; } 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 ( !PRCDoResistSpell(OBJECT_SELF, oTarget)) { // Make Fortitude save to negate if (! PRCMySavingThrow(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); } } // Do WyrmBreath void DoWyrmBreath(object oTarget) { object oCaster=OBJECT_SELF; if(oCaster == oTarget) { oTarget=GetNearestCreature(CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY); } if (GetIsObjectValid(oTarget)) { location lLoc=GetLocation(oTarget); int nDamageDie = 4; int nDamageType = DAMAGE_TYPE_COLD; int nVfx = VFX_IMP_FROST_S; int nSave = SAVING_THROW_TYPE_COLD; int nSpell = SPELLABILITY_DRAGON_BREATH_COLD; int nDice = 3; int nDamage = (Random(nDamageDie)+1)* nDice; int nDC=20; int nDamStrike; float fDelay; object oTarget; effect eVis, eBreath; oTarget = GetFirstObjectInShape(SHAPE_SPELLCONE, 14.0, lLoc, TRUE); while(GetIsObjectValid(oTarget)) { if(oTarget != OBJECT_SELF ) { SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, nSpell)); fDelay = GetDistanceBetween(OBJECT_SELF, oTarget)/20; nDamStrike = PRCGetReflexAdjustedDamage(nDamage, oTarget, nDC); if (nDamStrike > 0) { eBreath = EffectDamage(nDamStrike, nDamageType); eVis = EffectVisualEffect(nVfx); DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget)); DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eBreath, oTarget)); } } oTarget = GetNextObjectInShape(SHAPE_SPELLCONE, 14.0, lLoc, TRUE); } } else { ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectVisualEffect(VFX_FNF_GREATER_RUIN),oCaster); } }