/////////////////////////////////////////////////////////////////////////////// // Spells out the Wazoo - Custom Spell Director // By Deva Bryson Winblood. 12/19/2003 //----------------------------------------------------------------------------- // This script will handle multiple spells by reviewing their spell ID. /////////////////////////////////////////////////////////////////////////////// #include "x2_inc_spellhook" // Georg Zoellers new include //#include "x2_inc_itemprop" // Georg Zoellers item property addon #include "prc_x2_itemprop" #include "prc_inc_spells" #include "x0_i0_henchman" #include "wazoo_h" /////////////////////////////// // SPELL CONSTANTS /////////////////////////////// /////////////////////////////// // PROTOTYPES /////////////////////////////// void fnSpellAstralProjection(object oTarget); void fnSpellShadowWalk(object oTarget); void fnSpellCommand(object oTarget); void fnSpellPolymorphOther(object oTarget); void fnSpellMageHand(object oTarget); void fnSpellContingency(object oTarget); void fnSpellRopeTrick(); void fnSpellWaterBreathing(object oTarget,object oCaster); void fnSpellFaerieFire(object oTarget,object oCaster); void fnSpellDancingLights(object oCaster); void fnSpellErase(location lLoc,object oCaster); void fnSpellRepelVermin(object oCaster); void fnSpellCreateWater(object oCaster); void fnSpellPurify(object oTarget,object oCaster); void fnSpellObscuringMist(object oCaster); void fnSpellHeatMetal(object oTarget,object oCaster); void fnSpellHoldPortal(location lLoc,object oCaster); void fnSpellWarpWood(object oTarget,object oCaster); void fnSpellWoodShape(object oCaster); void fnSpellFireSeeds(object oCaster); void fnSpellHaltUndead(object oTarget, object oCaster); void fnSpellGaseousForm(object oTarget, object oCaster); void fnSpellLSC(object oTarget,object oCaster,location lLoc); void fnSpellMFH(location lLoc,object oCaster); void fnSpellMaze(object oTarget,object oCaster); void fnSpellMislead(object oCaster); void fnSpellClone(object oCaster); void fnSpellCollectPersonalItem(object oTarget,object oCaster); void fnSpellScry(object oCaster); void fnSpellGoodberries(object oCaster); void fnSpellDisguiseUndead(object oTarget, object oCaster); void fnSpellRegenerateWounds(object oTarget, object oCaster,int nSpeed); void fnSpellMightOfOak(object oTarget, object oCaster); void fnSpellEpidemic(object oTarget,object oCaster); void fnSpellAnimateTree(object oCaster); void fnSpellGreaterCallLightning(object oTarget, object oCaster); void fnSpellThunderswarm(location lTarget,object oCaster); ///////////////////////////////////////////////////////// [ MAIN ] ///////////// #include "prc_inc_spells" void main() { // Georg Zoeller's SpellHook test if (!X2PreSpellCastCode()) { //SendMessageToPC(GetLastSpellCaster(),"You could not cast that spell for some reason."); // If code within the PreSpellCastHook (i.e. UMD) reports FALSE, do not run this spell return; } int nID=PRCGetSpellId(); object oTarget=PRCGetSpellTargetObject(); object oCaster=OBJECT_SELF; location lLoc=PRCGetSpellTargetLocation(); SetLocalInt(oCaster,"nSpellID",nID); if (GetLocalInt(GetModule(),"bDisableSpell"+IntToString(nID))!=TRUE) {// spell not disabled if (GetLocalInt(oCaster,"bDisableSpell"+IntToString(nID))!=TRUE) { // spell not disabled on caster switch(nID) { // spell chooser case SPELL_ASTRAL_PROJECTION : { fnSpellAstralProjection(oTarget); break; } case SPELL_SHADOW_WALK : { fnSpellShadowWalk(oTarget); break; } case SPELL_COMMAND : { fnSpellCommand(oTarget); break; } case SPELL_POLYMORPH_OTHER: { fnSpellPolymorphOther(oTarget); break; } case SPELL_WZ_MAGE_HAND: { oTarget=GetNearestObjectToLocation(OBJECT_TYPE_ITEM,lLoc); fnSpellMageHand(oTarget); break; } case SPELL_CONTINGENCY: { fnSpellContingency(oTarget); break; } case SPELL_ROPE_TRICK: { fnSpellRopeTrick(); break; } case SPELL_WZ_WATER_BREATHING: { fnSpellWaterBreathing(oTarget,oCaster); break; } case SPELL_WZ_FAERIE_FIRE: { fnSpellFaerieFire(oTarget,oCaster); break ; } case SPELL_WZ_DANCING_LIGHTS: { fnSpellDancingLights(oCaster); break; } case SPELL_ERASE: { fnSpellErase(lLoc,oCaster); break; } case SPELL_WZ_REPEL_VERMIN: { fnSpellRepelVermin(oCaster); break; } case SPELL_CREATE_WATER: { fnSpellCreateWater(oCaster); break; } case SPELL_PURIFY_FOOD_AND_DRINK: { fnSpellPurify(oTarget,oCaster); break; } case SPELL_WZ_OBSCURING_MIST: { fnSpellObscuringMist(oCaster); break; } case SPELL_HEAT_METAL: { fnSpellHeatMetal(oTarget,oCaster); break; } case SPELL_HOLD_PORTAL: { fnSpellHoldPortal(lLoc,oCaster); break; } case SPELL_WARP_WOOD: { fnSpellWarpWood(oTarget,oCaster); break; } case SPELL_WOOD_SHAPE: { fnSpellWoodShape(oCaster); break; } case SPELL_WZ_FIRE_SEEDS: { fnSpellFireSeeds(oCaster); break; } case SPELL_WZ_HALT_UNDEAD: { fnSpellHaltUndead(oTarget,oCaster); break; } case SPELL_WZ_GASEOUS_FORM: { fnSpellGaseousForm(oTarget,oCaster); break; } case SPELL_LEOMUNDS_SECRET_CHEST: { fnSpellLSC(oTarget,oCaster,lLoc); break; } case SPELL_MORDENKAINENS_HOUND: { fnSpellMFH(lLoc,oCaster); break; } case SPELL_WZ_MAZE: { fnSpellMaze(oTarget,oCaster); break; } case SPELL_WZ_MISLEAD: { fnSpellMislead(oCaster); break; } case SPELL_CLONE: { fnSpellClone(oCaster); break; } case SPELL_COLLECT_PERSONAL_ITEM: { fnSpellCollectPersonalItem(oTarget,oCaster); break; } case SPELL_WZ_SCRY: { fnSpellScry(oCaster); break; } case SPELL_WZ_GOODBERRY: { fnSpellGoodberries(oCaster); break; } case SPELL_DISGUISE_UNDEAD: { fnSpellDisguiseUndead(oTarget,oCaster); break; } case SPELL_WZ_REGEN_LIGHT_WOUNDS: { fnSpellRegenerateWounds(oTarget,oCaster,1); break; } case SPELL_WZ_REGEN_MODERATE_WOUNDS: { fnSpellRegenerateWounds(oTarget,oCaster,2); break; } case SPELL_WZ_REGEN_SERIOUS_WOUNDS: { fnSpellRegenerateWounds(oTarget,oCaster,3); break; } case SPELL_WZ_REGEN_CRITICAL_WOUNDS: { fnSpellRegenerateWounds(oTarget,oCaster,4); break; } case SPELL_MIGHT_OF_THE_OAK: { fnSpellMightOfOak(oTarget,oCaster); break; } case SPELL_EPIDEMIC: { fnSpellEpidemic(oTarget,oCaster); break; } case SPELL_ANIMATE_TREE: { fnSpellAnimateTree(oCaster); break; } case SPELL_GREATER_CALL_LIGHTNING: { fnSpellGreaterCallLightning(oTarget,oCaster); break; } case SPELL_THUNDERSWARM: { fnSpellThunderswarm(lLoc,oCaster); break; } } // spell chooser } // spell not disabled on caster else { SendMessageToPC(oCaster,"Some outside force prevents you from using that spell."); } } // spell not disabled else { SendMessageToPC(oCaster,"ERROR: The module or PW maker chose to disable that spell in this module."); } } ////////////////////////////////////////////////////////// [ MAIN ] //////////// ////////////////////// // FUNCTIONS ////////////////////// void fnWatch(object oMaster) { // PURPOSE: For summone critter to know when to despawn effect eUnsum=EffectVisualEffect(VFX_FNF_SUMMON_MONSTER_1); object oMe=OBJECT_SELF; SetLocalInt(oMe,"bWatcher",TRUE); //SendMessageToPC(oMaster,"DEBUG: '"+GetName(oMe)+"' Watching"); if (GetIsObjectValid(oMaster)==TRUE) { // valid master if (GetIsDead(oMaster)||GetCurrentAction(oMaster)==ACTION_REST||GetLocalInt(oMe,"bUnsummon")) { // despawn ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY,eUnsum,GetLocation(oMe),4.0); RemoveHenchman(oMaster,oMe); SetIsDestroyable(TRUE,FALSE,FALSE); DelayCommand(1.0,DestroyObject(oMe)); } // despawn DelayCommand(6.0,fnWatch(oMaster)); } // valid master else { // destroy self ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY,eUnsum,GetLocation(oMe),4.0); RemoveHenchman(oMaster,oMe); SetIsDestroyable(TRUE,FALSE,FALSE); DelayCommand(1.0,DestroyObject(oMe)); DelayCommand(6.0,fnWatch(oMaster)); } // destroy self } // fnWatch() void fnSetWatchers(object oMaster,float fDur) { // PURPOSE: Fire the watcher routines int nN=1; object oSum; oSum=GetAssociate(ASSOCIATE_TYPE_SUMMONED,oMaster,nN); while(GetIsObjectValid(oSum)) { // check for watch //SendMessageToPC(oMaster,"DEBUG: Summoned '"+GetName(oSum)+"'"); if (GetLocalInt(oSum,"bWatcher")!=TRUE) { // fire watch AssignCommand(oSum,fnWatch(oMaster)); DelayCommand(fDur,SetLocalInt(oSum,"bUnsummon",TRUE)); } // fire watch nN++; oSum=GetAssociate(ASSOCIATE_TYPE_SUMMONED,oMaster,nN); } // check for watch } // fnSetWatchers() void fnSpellMFH(location lLoc,object oCaster) { // PURPOSE: Mordenkainen's Faithful Hound effect eS=EffectSummonCreature("wazoo_cr_mordhou",VFX_FNF_SUMMON_MONSTER_2,1.0,FALSE); int nLevel=PRCGetCasterLevel(oCaster); int nDuration=nLevel*30; if (PRCGetMetaMagicFeat()==METAMAGIC_EXTEND) nDuration=nDuration*2; SendMessageToPC(oCaster,"Mordenkainen's Hound will last "+IntToString(nDuration)+" seconds."); AssignCommand(oCaster,ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY,eS,lLoc,IntToFloat(nDuration))); DelayCommand(2.0,fnSetWatchers(oCaster,IntToFloat(nDuration))); } // fnSpellMFH() void fnThunderBallControl(location lTarget,object oCaster) { // PURPOSE: Move the ball object oMe=OBJECT_SELF; object oCreature=GetNearestCreature(CREATURE_TYPE_IS_ALIVE,TRUE,oMe,1); if (GetIsObjectValid(oCreature)&&!GetIsFriend(oCreature,oCaster)&&GetDistanceBetween(oCreature,oMe)<0.8) { // damage the creature and despawn effect eStrike=EffectVisualEffect(VFX_IMP_LIGHTNING_S); effect eDamage=EffectDamage(d6(16),DAMAGE_TYPE_ELECTRICAL); AssignCommand(oCaster,ApplyEffectToObject(DURATION_TYPE_INSTANT,eStrike,oCreature)); AssignCommand(oCaster,ApplyEffectToObject(DURATION_TYPE_INSTANT,eDamage,oCreature)); DelayCommand(0.8,DestroyObject(oMe)); SendMessageToPC(oCaster,GetName(oCreature)+" was near and was hit by one of the thunder balls."); } // damage the creature and despawn else if (GetDistanceBetweenLocations(lTarget,GetLocation(oMe))<0.5) { // reached destination - explode effect eExplode=EffectVisualEffect(VFX_FNF_ELECTRIC_EXPLOSION); effect eDamage; effect eStrike=EffectVisualEffect(VFX_IMP_LIGHTNING_S); int nN=1; object oTarg; ApplyEffectToObject(DURATION_TYPE_INSTANT,eExplode,oMe); int nDiff=GetGameDifficulty(); oTarg=GetNearestCreature(CREATURE_TYPE_IS_ALIVE,TRUE,oMe,nN); while(GetIsObjectValid(oTarg)&&GetDistanceBetween(oMe,oTarg)<5.2) { // explosion victims eDamage=EffectDamage(d8(4),DAMAGE_TYPE_ELECTRICAL); if (nDiff==GAME_DIFFICULTY_CORE_RULES||nDiff==GAME_DIFFICULTY_DIFFICULT) { // all targets effected AssignCommand(oCaster,ApplyEffectToObject(DURATION_TYPE_INSTANT,eStrike,oTarg)); AssignCommand(oCaster,ApplyEffectToObject(DURATION_TYPE_INSTANT,eDamage,oTarg)); } // all targets effected else if (!GetIsFriend(oTarg,oCaster)) { // only non-friend's effected AssignCommand(oCaster,ApplyEffectToObject(DURATION_TYPE_INSTANT,eStrike,oTarg)); AssignCommand(oCaster,ApplyEffectToObject(DURATION_TYPE_INSTANT,eDamage,oTarg)); } // only non-friend's effected nN++; oTarg=GetNearestCreature(CREATURE_TYPE_IS_ALIVE,TRUE,oMe,nN); } // explosion victims DelayCommand(1.0,DestroyObject(oMe)); } // reached destination - explode else { // move int nCount=GetLocalInt(oMe,"nCount"); nCount=nCount+1; SetLocalInt(oMe,"nCount",nCount); if (nCount>400) DestroyObject(oMe); if (GetCurrentAction(oMe)!=ACTION_MOVETOPOINT) { // move AssignCommand(oMe,ClearAllActions(TRUE)); AssignCommand(oMe,ActionMoveToLocation(lTarget,TRUE)); } // move DelayCommand(0.02,fnThunderBallControl(lTarget,oCaster)); } // move } // fnThunderBallControl() void fnCreateThunder(location lTarget,object oCaster) { // PURPOSE: Create thunderswarm bolt object oThunder=CreateObject(OBJECT_TYPE_CREATURE,"wazoo_thunder",GetLocation(oCaster)); effect eBeam=EffectBeam(VFX_BEAM_LIGHTNING,oCaster,BODY_NODE_HAND); AssignCommand(oCaster,ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eBeam,oThunder,13.0)); AssignCommand(oThunder,fnThunderBallControl(lTarget,oCaster)); } // fnCreateThunder() void fnSpellThunderswarm(location lTarget,object oCaster) { // PURPOSE: Thunderswarm int nCount=1; float fDelay=0.01; while(nCount<5) { // spawn and fire DelayCommand(fDelay,fnCreateThunder(lTarget,oCaster)); nCount++; fDelay=fDelay+0.8; } // spawn and fire } // fnSpellThunderswarm() void fnCLBolt(object oTarget,object oArea,object oCaster,int nBolts) { // PURPOSE: Handle additional bolts from Greater Call Lightning effect eDmg=EffectDamage(d10(5),DAMAGE_TYPE_ELECTRICAL); effect eVFX=EffectVisualEffect(VFX_IMP_LIGHTNING_M); object oHit=oTarget; if (!GetIsObjectValid(oHit)||GetCurrentHitPoints(oHit)<1||GetIsDead(oHit)||GetArea(oTarget)!=oArea) { // pick different target oHit=OBJECT_INVALID; if (GetArea(oCaster)==oArea) { // still in area oHit=GetNearestCreature(CREATURE_TYPE_IS_ALIVE,TRUE,oCaster,1,CREATURE_TYPE_PERCEPTION,PERCEPTION_SEEN,CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY); if (!GetIsObjectValid(oHit)) { // keep looking int nDiff=GetGameDifficulty(); if (nDiff==GAME_DIFFICULTY_CORE_RULES||nDiff==GAME_DIFFICULTY_DIFFICULT) { // look for nearby neutral oHit=GetNearestCreature(CREATURE_TYPE_IS_ALIVE,TRUE,oCaster,1,CREATURE_TYPE_PERCEPTION,PERCEPTION_SEEN,CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_NEUTRAL); } // look for nearby neutra if (!GetIsObjectValid(oHit)&&nDiff==GAME_DIFFICULTY_VERY_EASY) { // very easy - target invisible oHit=GetNearestCreature(CREATURE_TYPE_IS_ALIVE,TRUE,oCaster,1,CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY); } // very easy - target invisible } // keep looking } // still in area } // pick different target if (GetIsObjectValid(oHit)) { // strike ApplyEffectToObject(DURATION_TYPE_INSTANT,eVFX,oHit); ApplyEffectToObject(DURATION_TYPE_INSTANT,eDmg,oHit); if (nBolts>1) DelayCommand(6.0,fnCLBolt(oHit,oArea,oCaster,nBolts-1)); } // strike } // fnCLBolt() void fnSpellGreaterCallLightning(object oTarget, object oCaster) { // PURPOSE: Greater Call Lightning object oArea=GetArea(oCaster); int bMultipleBolts=FALSE; if (GetIsAreaAboveGround(oArea)==AREA_ABOVEGROUND&&GetWeather(oArea)==WEATHER_RAIN) bMultipleBolts=TRUE; effect eVFX=EffectVisualEffect(VFX_IMP_LIGHTNING_M); effect eDmg; if (bMultipleBolts) eDmg=EffectDamage(d10(5),DAMAGE_TYPE_ELECTRICAL); else { eDmg=EffectDamage(d6(5),DAMAGE_TYPE_ELECTRICAL); } ApplyEffectToObject(DURATION_TYPE_INSTANT,eVFX,oTarget); ApplyEffectToObject(DURATION_TYPE_INSTANT,eDmg,oTarget); if (bMultipleBolts) { // multiple bolts int nBolts=GetLevelByClass(CLASS_TYPE_DRUID,oCaster); nBolts=nBolts/3; nBolts=nBolts-1; if (nBolts>1) { // bolts DelayCommand(6.0,fnCLBolt(oTarget,oArea,oCaster,nBolts)); } // bolts } // multiple bolts } // fnSpellGreaterCallLightning() void fnSpellAnimateTree(object oCaster) { // PURPOSE: Animate Tree object oArea=GetArea(oCaster); int nTree=GetLocalInt(oArea,"nWazooTree"); if (nTree>0) { // trees exist to animate effect eS=EffectSummonCreature("wazoo_tree"+IntToString(nTree),VFX_FNF_SUMMON_MONSTER_2,1.0,FALSE); int nLevel=GetLevelByClass(CLASS_TYPE_DRUID,oCaster); location lLoc=GetLocation(oCaster); int nDuration=nLevel*60; if (PRCGetMetaMagicFeat()==METAMAGIC_EXTEND) nDuration=nDuration*2; SendMessageToPC(oCaster,"Animate tree will last "+IntToString(nDuration)+" seconds."); AssignCommand(oCaster,ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY,eS,lLoc,IntToFloat(nDuration))); DelayCommand(2.0,fnSetWatchers(oCaster,IntToFloat(nDuration))); } // trees exist to animate else { // no valid trees FloatingTextStringOnCreature("No valid trees exist in this area to animate. The spell fizzles.",oCaster,FALSE); } // no valid trees } // fnSpellAnimateTree() void fnUnderEpidemic(object oTarget,int nID,int nDuration,object oCaster,int nDC) { // PURPOSE: Spread this epidemic effect eVFX=EffectVisualEffect(VFX_DUR_FLIES); effect eStrengthDecrease=EffectAbilityDecrease(ABILITY_STRENGTH,5); effect eConstDecrease=EffectAbilityDecrease(ABILITY_CONSTITUTION,5); object oOb; int nN; int nSpread=nDC-1; if (nSpread<12) nSpread=12; if (!GetLocalInt(oTarget,"bWZE"+IntToString(nID))) { // see if epidemic set SetLocalInt(oTarget,"bWZE"+IntToString(nID),TRUE); nN=FortitudeSave(oTarget,nDC,SAVING_THROW_TYPE_DISEASE); if (nN==0) { // save failed - infected if (GetIsPC(oTarget)) SendMessageToPC(oTarget,"[INFECTED] - You have been infected by an epidemic spell and will be contagious for "+IntToString(nDuration*6)+" seconds."); SetLocalInt(oTarget,"nWZED"+IntToString(nID),nDuration); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eVFX,oTarget,IntToFloat(nDuration*6)); int nStr=GetAbilityScore(oTarget,ABILITY_STRENGTH); int nCon=GetAbilityScore(oTarget,ABILITY_CONSTITUTION); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eStrengthDecrease,oTarget,IntToFloat(nDuration*6)); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eConstDecrease,oTarget,IntToFloat(nDuration*6)); if (nStr-5<3) { // knock down effect eKnockdown=EffectKnockdown(); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eKnockdown,oTarget,IntToFloat(nDuration*6)); if (nStr-5<1) { // death effect eKill=EffectDamage(GetMaxHitPoints(oTarget)); DelayCommand(3.0,AssignCommand(oCaster,ApplyEffectToObject(DURATION_TYPE_INSTANT,eKill,oTarget))); } // death } // knock down else { // pause drunk AssignCommand(oTarget,ClearAllActions()); AssignCommand(oTarget,ActionPlayAnimation(ANIMATION_LOOPING_PAUSE_DRUNK,1.0,5.0)); } // pause drunk if (nCon-5<3) { // negative con effect eDiseaseSusceptibility=EffectSavingThrowDecrease(SAVING_THROW_FORT,5,SAVING_THROW_TYPE_DISEASE); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eDiseaseSusceptibility,oTarget,IntToFloat(nDuration*6)); if (nCon-5<1) { // death effect eKill=EffectDamage(GetMaxHitPoints(oTarget)); DelayCommand(3.0,AssignCommand(oCaster,ApplyEffectToObject(DURATION_TYPE_INSTANT,eKill,oTarget))); } // death } // negative con DelayCommand(6.0,fnUnderEpidemic(oTarget,nID,nDuration,oCaster,nSpread)); } // save failed - infected } // see if epidemic set else if (GetLocalInt(oTarget,"nWZED"+IntToString(nID))>0) { // epidemic active nN=GetLocalInt(oTarget,"nWZED"+IntToString(nID)); nN=nN-1; SetLocalInt(oTarget,"nWZED"+IntToString(nID),nN); DelayCommand(6.0,fnUnderEpidemic(oTarget,nID,nN,oCaster,nDC)); nN=1; oOb=GetNearestCreature(CREATURE_TYPE_IS_ALIVE,TRUE,oTarget,nN); while(GetIsObjectValid(oOb)&&GetDistanceBetween(oOb,oTarget)<15.01) { // infection spread possible int nRT=MyPRCGetRacialType(oOb); if (oOb!=oCaster&&GetMaster(oOb)!=oCaster&&!GetLocalInt(oOb,"bWZE"+IntToString(nID))&&nRT!=RACIAL_TYPE_CONSTRUCT&&nRT!=RACIAL_TYPE_ELEMENTAL&&nRT!=RACIAL_TYPE_UNDEAD) { // possible to infect fnUnderEpidemic(oOb,nID,nDuration,oCaster,nSpread); } // possible to infect nN++; oOb=GetNearestCreature(CREATURE_TYPE_IS_ALIVE,TRUE,oTarget,nN); } // infection spread possible } // epidemic active else { // no epidemic DeleteLocalInt(oTarget,"nWZED"+IntToString(nID)); DeleteLocalInt(oTarget,"bWZE"+IntToString(nID)); } // no epidemic } // fnUnderEpidemic() void fnSpellEpidemic(object oTarget,object oCaster) { // PURPOSE: Epidemic handling int nEpidemicID=GetTimeMillisecond()+(GetTimeSecond()*100)+(GetTimeMinute()*100*60); int nDuration=GetLevelByClass(CLASS_TYPE_DRUID,oCaster)*10; int nStartingDC=GetLevelByClass(CLASS_TYPE_DRUID,oCaster); fnUnderEpidemic(oTarget,nEpidemicID,nDuration,oCaster,nStartingDC); } // fnSpellEpidemic() void fnSpellMightOfOak(object oTarget, object oCaster) { // PURPOSE: Might of oak +4 Str, -2 Dex 10 min/level float fHour=HoursToSeconds(1); float fPerLevel=fHour/6.0; int nLevel=GetLevelByClass(CLASS_TYPE_DRUID,oCaster); float fDuration=fPerLevel*IntToFloat(nLevel); ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectVisualEffect(VFX_IMP_HEAD_NATURE),oTarget); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,EffectAbilityIncrease(ABILITY_STRENGTH,4),oTarget,fDuration); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,EffectAbilityDecrease(ABILITY_DEXTERITY,2),oTarget,fDuration); } // fnSpellMightOfOak() void fnRegenerate(object oTarget,int nDuration,int nSpeed) { // PURPOSE: Regenerate effect eVFX=EffectVisualEffect(VFX_DUR_AURA_PULSE_CYAN_GREEN); int nMax=GetMaxHitPoints(oTarget); int nCurr=GetCurrentHitPoints(oTarget); int nHeal=nMax-nCurr; if (nHeal>nSpeed) nHeal=nSpeed; effect eHeal=EffectHeal(nHeal); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eVFX,oTarget,6.1); if (nHeal>0) ApplyEffectToObject(DURATION_TYPE_INSTANT,eHeal,oTarget); if (nDuration>1) DelayCommand(6.0,fnRegenerate(oTarget,nDuration-1,nSpeed)); } // fnRegenerate() void fnSpellRegenerateWounds(object oTarget, object oCaster,int nSpeed) { // PURPOSE: Handle Regenerate wounds spells int nDuration=10+GetLevelByClass(CLASS_TYPE_DRUID,oCaster); fnRegenerate(oTarget,nDuration,nSpeed); } // fnSpellRegenerateWounds() void fnMonitorFaerieFire(object oTarget,int nDuration) { // PURPOSE: keep the faerie effect going during duration int nDur=nDuration; int nExtend=GetLocalInt(oTarget,"nExtendFaerieFire"); int bDispel=GetLocalInt(oTarget,"bDispelMagic"); effect eE; int nET; nDur=nDur-6; if (nExtend>0) { nDur=nExtend; DeleteLocalInt(oTarget,"nExtendFaerieFire"); } if (bDispel) nDur=0; if (nDur>0) { // continue faerie fire SetLocalInt(oTarget,"bFaerieFire",TRUE); eE=GetFirstEffect(oTarget); while(GetEffectType(eE)!=EFFECT_TYPE_INVALIDEFFECT) { // traverse effects nET=GetEffectType(eE); if (nET==EFFECT_TYPE_CONCEALMENT||nET==EFFECT_TYPE_DARKNESS||nET==EFFECT_TYPE_INVISIBILITY) { // negate DelayCommand(0.2,RemoveEffect(oTarget,eE)); } // negate eE=GetNextEffect(oTarget); } // traverse effects DelayCommand(6.0,fnMonitorFaerieFire(oTarget,nDur)); } // continue faerie fire else { // end spell DeleteLocalInt(oTarget,"bFaerieFire"); } // end spell } // fnMonitorFaerieFire() void fnSpellFaerieFire(object oTarget,object oCaster) { // Faerie Fire Spell int nDuration; object oOb; int nN; effect eE; int nLevel=PRCGetCasterLevel(oCaster); nDuration=nLevel*60; if (PRCGetMetaMagicFeat()==METAMAGIC_EXTEND) nDuration=nDuration+60; eE=EffectVisualEffect(VFX_DUR_GLOW_LIGHT_PURPLE); if (oTarget!=OBJECT_INVALID) { // valid target ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eE,oTarget,IntToFloat(nDuration)); if (GetLocalInt(oTarget,"bFaerieFire")==FALSE) fnMonitorFaerieFire(oTarget,nDuration+6); else { SetLocalInt(oTarget,"nExtendFaerieFire",nDuration); } if (GetIsPC(oTarget)) SendMessageToPC(oTarget,GetName(oCaster)+" cast faerie fire upon you."); nN=1; oOb=GetNearestCreature(CREATURE_TYPE_IS_ALIVE,TRUE,oTarget,nN,CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_FRIEND); while(oOb!=OBJECT_INVALID&&GetDistanceBetween(oOb,oTarget)<=3.0) { // do in a 3 meter radius instead of 5 feet it says in PHB ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eE,oTarget,IntToFloat(nDuration)); if (GetLocalInt(oOb,"bFaerieFire")==FALSE) fnMonitorFaerieFire(oOb,nDuration+6); else { SetLocalInt(oOb,"nExtendFaerieFire",nDuration); } if (GetIsPC(oOb)) SendMessageToPC(oTarget,GetName(oOb)+" cast faerie fire upon you."); nN++; oOb=GetNearestCreature(CREATURE_TYPE_IS_ALIVE,TRUE,oTarget,nN,CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_FRIEND); } // do in a 3 meter radius instead of 5 feet it says in PHB } // valid target } // fnSpellFaerieFire() void fnSpellAstralProjection(object oTarget) { // astral projection spell object oMe=OBJECT_SELF; if (oTarget!=OBJECT_INVALID&&GetWaypointByTag("PLANESHIFT_ASTRAL")!=OBJECT_INVALID&&GetLocalInt(oMe,"nWAZOOASTRAL")!=TRUE) { // valid target SetLocalObject(oMe,"oSpellTarget",oTarget); ExecuteScript("wazoo_s0_astproj",oMe); } // valid target } // fnSpellAstralProjection() void fnSpellShadowWalk(object oTarget) { // shadow walk object oMe=OBJECT_SELF; if (oTarget!=OBJECT_INVALID&&GetWaypointByTag("PLANESHIFT_SHADOW")!=OBJECT_INVALID) { // valid target SetLocalObject(oMe,"oSpellTarget",oTarget); AssignCommand(oMe,ClearAllActions()); AssignCommand(oMe,ActionStartConversation(oMe,"wazoo_cv_shadowwlk",TRUE,FALSE)); } // valid target } // fnSpellShadowWalk() void fnSpellCommand(object oTarget) { // Command/Suggestion spell object oMe=OBJECT_SELF; if (oTarget!=oMe&&oTarget!=OBJECT_INVALID) { // valid target SetLocalObject(oMe,"oSpellTarget",oTarget); SetLocalInt(oMe,"nCasterLevel",PRCGetCasterLevel(OBJECT_SELF)); AssignCommand(oMe,ClearAllActions(TRUE)); AssignCommand(oMe,ActionStartConversation(oMe,"wazoo_cv_command",TRUE,FALSE)); } // valid target } // fnSpellCommand() void fnSpellPolymorphOther(object oTarget) { object oMe=OBJECT_SELF; if (oTarget!=oMe&&oTarget!=OBJECT_INVALID) { // valid target SetLocalObject(oMe,"oSpellTarget",oTarget); SetLocalInt(oMe,"nCasterLevel",PRCGetCasterLevel(oMe)); AssignCommand(oMe,ClearAllActions(TRUE)); AssignCommand(oMe,ActionStartConversation(oMe,"wazoo_cv_polyoth",TRUE,FALSE)); } // valid target } // fnSpellPolymorphOther() void fnSpellMageHand(object oTarget) { object oMe=OBJECT_SELF; effect eBeam=EffectBeam(VFX_BEAM_SILENT_MIND,oMe,BODY_NODE_HAND); float fRange; int nCasterLevel=PRCGetCasterLevel(oMe); fRange=IntToFloat(25+((nCasterLevel/2)*5))*0.3; if (GetObjectType(oTarget)==OBJECT_TYPE_ITEM) { // item if (GetDistanceBetween(oMe,oTarget)<=fRange) { // in range ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY,eBeam,GetLocation(oTarget),2.0); if (GetWeight(oTarget)<=5) { // valid weight CreateItemOnObject(GetResRef(oTarget),oMe,GetItemStackSize(oTarget)); DestroyObject(oTarget); } // valid weight else { // too heavy SendMessageToPC(oMe,"That item is too heavy for this simple cantrip."); } // too heavy } // in range else { nCasterLevel=FloatToInt(fRange); SendMessageToPC(oMe,"That object is out of range. Your maximum range for mage hand is "+IntToString(nCasterLevel)+" meters."); } } // item else { SendMessageToPC(oMe,"This spell only works on single items of 5 pounds or less. This may mean the item was not within range."); } } // mage hand void fnSpellContingency(object oTarget) { object oCaster=OBJECT_SELF; AssignCommand(oCaster,ClearAllActions(TRUE)); AssignCommand(oCaster,ActionStartConversation(oCaster,"wazoo_cv_conting",TRUE,FALSE)); } // fnSpellContingency() void fnSpellRopeTrick() { object oMod=GetModule(); object oOb1; object oOb2; if (GetLocalInt(oMod,"bWazooMaterialComponents")) { // requires material components oOb1=GetItemPossessedBy(OBJECT_SELF,"wazoo_sc_pcorn"); oOb2=GetItemPossessedBy(OBJECT_SELF,"wazoo_sc_tparc"); if (GetIsObjectValid(oOb1)&&GetIsObjectValid(oOb2)) { // have material components DestroyObject(oOb1); DestroyObject(oOb2); ExecuteScript("wazoo_s0_ropetri",OBJECT_SELF); } // have material components else { // SendMessageToPC(OBJECT_SELF,"The Rope Trick spell fails. You do not have the Powdered Corn, and Twisted Parchment material components."); } // } // requires material components else { // no components ExecuteScript("wazoo_s0_ropetric",OBJECT_SELF); } // no components } // fnSpellRopeTrick(); void fnWaterBreathing(int nDuration) { // PURPOSE: To keep water breathing effect going. Also, to disable water breathing if the // player decides to rest object oMe=OBJECT_SELF; int nDur=nDuration; int bWB=GetLocalInt(oMe,"bWaterBreathing"); int nIncreaseDuration=GetLocalInt(oMe,"nWBIncreaseDuration"); effect eE; nDur=nDur-1; if (nIncreaseDuration>0) { // add to duration nDur=nIncreaseDuration; DeleteLocalInt(oMe,"nWBIncreaseDuration"); } // add to duration if (GetLocalInt(oMe,"bDispelMagic")) nDur=0; if (nDur==7) SendMessageToPC(oMe,"You have less than a minute of water breathing remaining."); else if (nDur==3) SendMessageToPC(oMe,"You have 24 seconds of water breathing remaining."); if (GetCurrentAction(oMe)!=ACTION_REST&&bWB&&nDuration!=0) { // keep effect going eE=EffectVisualEffect(VFX_DUR_IOUNSTONE_BLUE); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eE,oMe,10.0); DelayCommand(8.0,fnWaterBreathing(nDuration-1)); } // keep effect going else { // done with water breathing DeleteLocalInt(oMe,"bWaterBreathing"); SendMessageToPC(oMe,"Water breathing has worn off and is no longer active."); } // done with water breathing } // fnWaterBreathing() void fnSpellWaterBreathing(object oTarget,object oCaster) { int nLevel=PRCGetCasterLevel(oCaster); int nDuration=nLevel*(240); // level * 240 seconds (2 hours / level) nDuration=nDuration/8; // it will be monitored every 8 seconds if (PRCGetMetaMagicFeat()==METAMAGIC_EXTEND) nDuration=nDuration*2; if ((GetObjectType(oTarget)==OBJECT_TYPE_CREATURE||GetIsPC(oTarget))&&GetLocalInt(oTarget,"bWaterBreathing")!=TRUE) { // valid targets SetLocalInt(oTarget,"bWaterBreathing",TRUE); AssignCommand(oTarget,fnWaterBreathing(nDuration+1)); SendMessageToPC(oTarget,"Water Breathing has been cast upon you and will last "+IntToString((nDuration*8)/60)+" minutes."); } // valid targets else if (GetLocalInt(oTarget,"bWaterBreathing")) { // already under spell SendMessageToPC(oCaster,"The target already had water breathing so, the duration has been reset."); SetLocalInt(oTarget,"nWBIncreaseDuration",nDuration); SendMessageToPC(oTarget,"The duration of your water breathing has been reset to "+IntToString((nDuration*8)/60)+" minutes"); } // already under spell } // fnSpellWaterBreathing() void fnDLMovement(int nDuration) { // PURPOSE: handle the movement of the dancing light object oMe=OBJECT_SELF; object oLead=GetLocalObject(oMe,"oMaster"); int nDur=nDuration; float fAheadDist=3.0; float fDX; float fDY; float fDZ; float fMX=0.0; float fMY=0.0; location lRecon; float fFacing=GetFacing(oLead); vector vVecPC=GetPosition(oLead); float fLX=vVecPC.x; float fLY=vVecPC.y; float fLZ=vVecPC.z; vector vNewVec; if (fFacing>335.0||fFacing<25.0) { // east fMX=1.0; } // east else if (fFacing>291.0&&fFacing<335.1) { // south east fMX=0.75; fMY=-0.75; } // south east else if (fFacing>250.0&&fFacing<291.1) { // south fMY=-1.0; } // south else if (fFacing>200.0&&fFacing<250.1) { // south west fMX=-0.75; fMY=-0.75; } // south west else if (fFacing>160.0&&fFacing<200.1) { // west fMX=-1.0; } // west else if (fFacing>110.0&&fFacing<160.1) { // north west fMX=-0.75; fMY=0.75; } // north west else if (fFacing>70.0&&fFacing<110.1) { // north fMY=1.0; } // north else { // north east fMY=0.75; fMX=0.75; } // north east if (oLead==OBJECT_INVALID) { // instant despawn DestroyObject(oMe); return; } // instant despawn fDX=fLX+(fMX*fAheadDist); fDY=fLY+(fMY*fAheadDist); fDZ=fLZ; if (fDX<0.0) fDX=0.0; if (fDY<0.0) fDY=0.0; vNewVec=Vector(fDX,fDY,fDZ); lRecon=Location(GetArea(oLead),vNewVec,fFacing); AssignCommand(oMe,ClearAllActions(TRUE)); AssignCommand(oMe,ActionMoveToLocation(lRecon,TRUE)); nDur=nDur-2; if (nDur>0&&GetCurrentAction(oLead)!=ACTION_REST) DelayCommand(2.0,fnDLMovement(nDur)); else { // despawn DeleteLocalObject(oLead,"oWZDancing"); DestroyObject(oMe); } // despawn } // fnDLMovement() void fnSpellDancingLights(object oCaster) { // Dancing Lights Spell string sRes="wazoodancel"; int nLevel=PRCGetCasterLevel(oCaster); int nDuration=60; object oDL; if (PRCGetMetaMagicFeat()==METAMAGIC_EXTEND) nDuration=90; if (GetLocalObject(oCaster,"oWZDancing")==OBJECT_INVALID) { // create dancing light oDL=CreateObject(OBJECT_TYPE_CREATURE,sRes,GetLocation(oCaster)); SetLocalObject(oCaster,"oWZDancing",oDL); SetLocalObject(oDL,"oMaster",oCaster); AssignCommand(oDL,fnDLMovement(nDuration+2)); } // create dancing light else { // already exists SendMessageToPC(oCaster,"Dancing light already exists"); } // already exists } // fnSpellDancingLights() void fnSpellErase(location lLoc,object oCaster) { // PURPOSE: Spell Erase object oOb; int nN; nN=1; oOb=GetNearestObjectToLocation(OBJECT_TYPE_PLACEABLE,lLoc,nN); while(oOb!=OBJECT_INVALID&&GetDistanceBetweenLocations(lLoc,GetLocation(oOb))<=3.0) { // erase if (GetLocalInt(oOb,"bEraseable")) DelayCommand(0.5,DestroyObject(oOb)); nN++; oOb=GetNearestObjectToLocation(OBJECT_TYPE_PLACEABLE,lLoc,nN); } // erase } // fnSpellErase() void fnVerminRepellantForce(int nDuration,int nDmg,int nResist,int bMaximize) { // PURPOSE: Handle actual repelling object oMe=OBJECT_SELF; int nN; object oOb; effect eE; int nR; int nDur=nDuration; int nExtend=GetLocalInt(oMe,"nWZRepelVerminExtend"); nDur=nDur-1; if (nExtend>0) { // reset duration nDur=nExtend; DeleteLocalInt(oMe,"nWZRepelVerminExtend"); } // reset duration if (GetLocalInt(oMe,"bDispelMagic")) nDur=0; if (nDur>0&&GetCurrentAction(oMe)!=ACTION_REST) { // duration remains eE=EffectVisualEffect(VFX_DUR_IOUNSTONE_GREEN); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eE,oMe,2.0); SetLocalInt(oMe,"bRepelVermin",TRUE); nN=1; oOb=GetNearestCreature(CREATURE_TYPE_IS_ALIVE,TRUE,oMe,nN); while(oOb!=OBJECT_INVALID&&GetDistanceBetween(oMe,oOb)<=7.5) { // repel if (GetRacialType(oOb)==RACIAL_TYPE_VERMIN) { // vermin nR=GetHitDice(oOb); if (nR<=nResist) { // valid eE=EffectBeam(VFX_BEAM_SILENT_MIND,oMe,BODY_NODE_HAND,FALSE); AssignCommand(oOb,ClearAllActions(TRUE)); AssignCommand(oOb,ActionMoveAwayFromObject(oMe,TRUE,9.0)); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eE,oOb,2.0); } // valid else { // bigger nR=d6(nDmg); if (bMaximize) nR=6*nDmg; if (GetLocalInt(oOb,"bDamagedByRepel")==FALSE) { // okay to damage SetLocalInt(oOb,"bDamagedByRepel",TRUE); eE=EffectBeam(VFX_BEAM_SILENT_MIND,oMe,BODY_NODE_HAND,FALSE); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eE,oOb,2.0); eE=EffectDamage(nR); ApplyEffectToObject(DURATION_TYPE_INSTANT,eE,oOb,1.0); } // okay to damage } // bigger } // vermin nN++; oOb=GetNearestCreature(CREATURE_TYPE_IS_ALIVE,TRUE,oMe,nN); } // repel DelayCommand(1.0,fnVerminRepellantForce(nDur,nDmg,nResist,bMaximize)); } // duration remains else { // done DeleteLocalInt(oMe,"bRepelVermin"); } // done } // fnVerminRepellantForce() void fnSpellRepelVermin(object oCaster) { // PURPOSE: Repel Vermin int nLevel=PRCGetCasterLevel(oCaster); int nDur; int nDmg=2; int nDLevel=nLevel; // effective duration level; int bMaximize=FALSE; int nHD=nLevel/3; if (nHD<1) nHD=1; if (PRCGetMetaMagicFeat()==METAMAGIC_EXTEND) nDLevel++; else if (PRCGetMetaMagicFeat()==METAMAGIC_MAXIMIZE) bMaximize=TRUE; else if (PRCGetMetaMagicFeat()==METAMAGIC_EMPOWER) { nDmg=3; nHD=nHD+1; } nDur=30*nDLevel; if (GetLocalInt(oCaster,"bRepelVermin")!=TRUE) { // cast spell AssignCommand(oCaster,fnVerminRepellantForce(nDur+1,nDmg,nHD,bMaximize)); SendMessageToPC(oCaster,"You cast Repel Vermin which should last "+IntToString(nDur)+" seconds and repel vermin with HD up to "+IntToString(nHD)+"."); } // cast spell else { // reset duration SetLocalInt(oCaster,"nWZRepelVerminExtend",nDur); SendMessageToPC(oCaster,"The duration of Repel Vermin has been reset to "+IntToString(nDur)+" seconds."); } // reset duration } // fnSpellRepelVermin() void fnSpellCreateWater(object oCaster) { // PURPOSE: Fill empty water bottles carried by caster int nN; int nLevel=PRCGetCasterLevel(oCaster); string sBaseTag="DH2_EWBOT"; string sNewRes="dh2_waterbot"; object oBase; object oNew; int nDif; oBase=GetItemPossessedBy(oCaster,sBaseTag); if (oBase!=OBJECT_INVALID) { // have water bottles while(oBase!=OBJECT_INVALID&&nLevel>0) { // create water nN=GetItemStackSize(oBase); if (nN==1) { // 1 DestroyObject(oBase); oNew=CreateItemOnObject(sNewRes,oCaster); oBase=GetItemPossessedBy(oCaster,sBaseTag); nLevel=nLevel-1; } // 1 else { // multiple if (nN>nLevel) { // more than can handle nDif=nN-nLevel; SetItemStackSize(oBase,nDif); oNew=CreateItemOnObject(sNewRes,oCaster,nLevel); nLevel=0; } // more than can handle else { // less or equal DestroyObject(oBase); oNew=CreateItemOnObject(sNewRes,oCaster,nN); oBase=GetItemPossessedBy(oCaster,sBaseTag); nLevel=nLevel-nN; } // less or equal } // multiple } // create water } // have water bottles else { // message SendMessageToPC(oCaster,"You must be carrying empty water bottles for this spell to have any effect."); } // message } // fnSpellCreateWater() void fnSpellPurify(object oTarget,object oCaster) { // PURPOSE: To make any water bottles carried by the target into purified water string sBaseTag="DH2_WATERSPEC"; string sNewRes="dh2_waterbot"; object oBase; object oNew; int nN; int nDif; int nLevel=PRCGetCasterLevel(oCaster); oBase=GetItemPossessedBy(oTarget,sBaseTag); if (oBase!=OBJECT_INVALID) { // has items to be purified while(oBase!=OBJECT_INVALID&&nLevel>0) { // look for tainted water bottles nN=GetItemStackSize(oBase); if (nN>nLevel) { // more than can purify nDif=nN-nLevel; SetItemStackSize(oBase,nDif); oNew=CreateItemOnObject(sNewRes,oTarget,nLevel); nLevel=0; } // more than can purify else { // can purify all DestroyObject(oBase); oNew=CreateItemOnObject(sNewRes,oTarget,nN); nLevel=nLevel-nN; } // can purify all oBase=GetItemPossessedBy(oTarget,sBaseTag); } // look for tainted water bottles SendMessageToPC(oCaster,"Items that could be purified at your level have been."); } // has items to be purified else { // pure SendMessageToPC(oCaster,"All water sources carried by "+GetName(oTarget)+" appear to be purified."); } // pure } // fnSpellPurify() void fnObscure(int nDuration) { // PURPOSE: handle obscuring mist int nDur=nDuration; object oMe=OBJECT_SELF; effect eE; int nExtend=GetLocalInt(oMe,"nWZObscuringExtend"); if (GetLocalInt(oMe,"bDispelMagic")==FALSE) { // not dispelled nDur=nDur-6; if (nExtend>0) { nDur=nExtend; DeleteLocalInt(oMe,"nWZObscuringExtend"); } if (nDur>0&&GetCurrentAction(oMe)!=ACTION_REST) { // spell still active SetLocalInt(oMe,"bWZObscuring",TRUE); eE=EffectVisualEffect(VFX_DUR_GHOST_SMOKE); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eE,oMe,6.1); eE=EffectConcealment(50,MISS_CHANCE_TYPE_NORMAL); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eE,oMe,6.1); DelayCommand(6.0,fnObscure(nDur)); } // spell still active else { // spell expired DeleteLocalInt(oMe,"bWZObscuring"); } // spell expired } // not dispelled else { // dispelled DeleteLocalInt(oMe,"bWZObscuring"); DeleteLocalInt(oMe,"nWZObscuringExtend"); } // dispelled } // fnObscure() void fnSpellObscuringMist(object oCaster) { // PURPOSE: int nLevel=PRCGetCasterLevel(oCaster); int nDur=nLevel; if (PRCGetMetaMagicFeat()==METAMAGIC_EXTEND) nDur=nDur+1; nDur=nDur*60; if (GetLocalInt(oCaster,"bWZObscuring")==FALSE) { // not active SendMessageToPC(oCaster,"Obscuring mist has been activated and will last "+IntToString(nDur)+" seconds."); AssignCommand(oCaster,fnObscure(nDur+6)); } // not active else { // active reset duration SetLocalInt(oCaster,"nWZObscuringExtend",nDur); SendMessageToPC(oCaster,"Obscuring mist was already active so reset the duration to "+IntToString(nDur)+" seconds."); } // active reset duration } // fnSpellObscuringMist() int fnGetArmorMagicBonus(object oItem) { // returns the AC bonus of the item int nRet=0; itemproperty ip; int nN=1; while(nN<=20) { // check for each AC bonus level ip=ItemPropertyACBonus(nN); if (IPGetItemHasProperty(oItem,ip,-1)) return nN; nN++; } // check for each AC bonus level return nRet; } // fnGetArmorMagicBonus() int fnGetItemMaterial(object oItem) { // PURPOSE: returns 0 for unknown, 1 = metal, 2 = wood int nBT=GetBaseItemType(oItem); int nRet=0; int nACUnmodified; int nACMagical=0; int nACModified; if (nBT==BASE_ITEM_ARMOR) { // depends on non-magical AC value nACUnmodified=GetItemACValue(oItem); nACMagical=fnGetArmorMagicBonus(oItem); nACModified=nACUnmodified-nACMagical; if (nACModified>3) nRet=1; } // depends on non-magical AC value else if (nBT==BASE_ITEM_ARROW) nRet=2; else if (nBT==BASE_ITEM_BASTARDSWORD) nRet=1; else if (nBT==BASE_ITEM_BATTLEAXE) nRet=1; else if (nBT==BASE_ITEM_BOLT) nRet=2; else if (nBT==BASE_ITEM_BRACER) nRet=1; else if (nBT==BASE_ITEM_CLUB) nRet=2; else if (nBT==BASE_ITEM_DAGGER) nRet=1; else if (nBT==BASE_ITEM_DART) nRet=2; else if (nBT==BASE_ITEM_DIREMACE) nRet=1; else if (nBT==BASE_ITEM_DOUBLEAXE) nRet=1; else if (nBT==BASE_ITEM_DWARVENWARAXE) nRet=1; else if (nBT==BASE_ITEM_GREATAXE) nRet=1; else if (nBT==BASE_ITEM_GREATSWORD) nRet=1; else if (nBT==BASE_ITEM_HALBERD) nRet=2; else if (nBT==BASE_ITEM_HANDAXE) nRet=2; else if (nBT==BASE_ITEM_HEAVYCROSSBOW) nRet=2; else if (nBT==BASE_ITEM_HEAVYFLAIL) nRet=1; else if (nBT==BASE_ITEM_HELMET) nRet=1; else if (nBT==BASE_ITEM_KAMA) nRet=2; else if (nBT==BASE_ITEM_KATANA) nRet=1; else if (nBT==BASE_ITEM_KUKRI) nRet=1; else if (nBT==BASE_ITEM_LIGHTCROSSBOW) nRet=2; else if (nBT==BASE_ITEM_LIGHTFLAIL) nRet=1; else if (nBT==BASE_ITEM_LIGHTHAMMER) nRet=2; else if (nBT==BASE_ITEM_LIGHTMACE) nRet=1; else if (nBT==BASE_ITEM_LONGBOW) nRet=2; else if (nBT==BASE_ITEM_LONGSWORD) nRet=1; else if (nBT==BASE_ITEM_MORNINGSTAR) nRet=1; else if (nBT==BASE_ITEM_QUARTERSTAFF) nRet=2; else if (nBT==BASE_ITEM_RAPIER) nRet=1; else if (nBT==BASE_ITEM_RING) nRet=1; else if (nBT==BASE_ITEM_SCIMITAR) nRet=1; else if (nBT==BASE_ITEM_SCYTHE) nRet=2; else if (nBT==BASE_ITEM_SHORTBOW) nRet=1; else if (nBT==BASE_ITEM_SHORTSPEAR) nRet=2; else if (nBT==BASE_ITEM_SHORTSWORD) nRet=1; else if (nBT==BASE_ITEM_SHURIKEN) nRet=1; else if (nBT==BASE_ITEM_SICKLE) nRet=2; else if (nBT==BASE_ITEM_THROWINGAXE) nRet=2; else if (nBT==BASE_ITEM_TOWERSHIELD) nRet=1; else if (nBT==BASE_ITEM_TWOBLADEDSWORD) nRet=1; else if (nBT==BASE_ITEM_WARHAMMER) nRet=1; else if (nBT==BASE_ITEM_LARGESHIELD||nBT==BASE_ITEM_SMALLSHIELD) nRet=2; return nRet; } // fnGetItemMaterial() void fnCheckFumbleItem(object oOwner,object oItem,int nDC) { // PURPOSE: To a reflex save versus DC to see if oOwner drops oItem int nRS=GetReflexSavingThrow(oOwner); int nRoll=d20(); object oCopy; int nN; int bFumble=FALSE; if (GetDroppableFlag(oItem)==TRUE&&oItem!=OBJECT_INVALID) { // okay to drop if (nRS+nRoll0) { // extend nDur=(nExtend*4); DeleteLocalInt(oDoor,"nWZExtendHoldPortal"); } // extend if (nDur>0&&!bDispelMagic&&oCaster!=OBJECT_INVALID&&GetCurrentAction(oCaster)!=ACTION_REST) { // hold portal active SetLocalInt(oDoor,"bHoldPortal",TRUE); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eGlow,oDoor,2.0); oTrans=GetTransitionTarget(oDoor); if (GetObjectType(oTrans)==OBJECT_TYPE_DOOR) { // lock ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eGlow,oTrans,2.0); SetLocked(oTrans,TRUE); } // lock SetLocked(oDoor,TRUE); if (GetIsOpen(oDoor)) { // the door is open AssignCommand(oDoor,ActionCloseDoor(oDoor)); AssignCommand(oDoor,SpeakString("** HOLD PORTAL **")); AssignCommand(oDoor,SetLocked(oDoor,TRUE)); } // the door is open DelayCommand(0.25,fnHoldPortal(oCaster,nDur)); } // hold portal active else { // end hold portal DeleteLocalInt(oDoor,"bHoldPortal"); nDur=GetLocalInt(oDoor,"bHPLockedState"); SetLocked(oDoor,nDur); oTrans=GetTransitionTarget(oDoor); if (GetObjectType(oTrans)==OBJECT_TYPE_DOOR) SetLocked(oTrans,nDur); DeleteLocalInt(oDoor,"bHPLockedState"); } // end hold portal } // fnHoldPortal() void fnSpellHoldPortal(location lLoc,object oCaster) { // PURPOSE: handle hold portal spell on a door int nLevel=PRCGetCasterLevel(oCaster); int nDur=30*nLevel; object oDoor=GetNearestObjectToLocation(OBJECT_TYPE_DOOR,lLoc); int bLocked; if (PRCGetMetaMagicFeat()==METAMAGIC_EXTEND) nDur=30*(nLevel+1); if (oDoor!=OBJECT_INVALID&&GetDistanceBetween(oCaster,oDoor)<5.0) { // door found if (GetLocalInt(oDoor,"bHoldPortal")==FALSE) { // hold portal not already on door SendMessageToPC(oCaster,"You cast hold portal on the door which will last "+IntToString(nDur)+" seconds."); bLocked=GetLocked(oDoor); SetLocalInt(oDoor,"bHPLockedState",bLocked); AssignCommand(oDoor,fnHoldPortal(oCaster,(nDur*4)+1)); } // hold portal not already on door else { // hold portal on door SendMessageToPC(oCaster,"The door was already held. This will simply reset the duration."); SetLocalInt(oDoor,"nWZExtendHoldPortal",nDur); } // hold portal on door } // door found else { // not found SendMessageToPC(oCaster,"A door near that location could not be found."); } // not found } // fnSpellHoldPortal() void fnWarpItem(object oItem) { // PURPOSE: The item is warped itemproperty ip; object oOwner=GetItemPossessor(oItem); int nBT=GetBaseItemType(oItem); if (nBT==BASE_ITEM_ARROW||nBT==BASE_ITEM_BOLT||nBT==BASE_ITEM_LONGBOW||nBT==BASE_ITEM_LIGHTCROSSBOW||nBT==BASE_ITEM_HEAVYCROSSBOW||nBT==BASE_ITEM_SHORTBOW) DestroyObject(oItem); else if (nBT==BASE_ITEM_SMALLSHIELD||nBT==BASE_ITEM_LARGESHIELD) { // warp shields ip=ItemPropertyDecreaseAC(IP_CONST_ACMODIFIERTYPE_SHIELD,1); if (IPGetItemHasProperty(oItem,ip,-1)==FALSE) { // apply property IPSafeAddItemProperty(oItem,ip); if (GetIsPC(oOwner)) SendMessageToPC(oOwner,"Your item '"+GetName(oItem)+"' has been warped and has -1 to its AC value."); } // apply property } // warp shields else { // individual item ip=ItemPropertyAttackPenalty(4); if (IPGetItemHasProperty(oItem,ip,-1)==FALSE) { // apply property IPSafeAddItemProperty(oItem,ip); if (GetIsPC(oOwner)) SendMessageToPC(oOwner,"Your item '"+GetName(oItem)+"' has been warped and has -4 to hit."); } // apply property } // individual item } // fnWarpItem() void fnSpellWarpWood(object oTarget,object oCaster) { // PURPOSE: To warp wooden items object oItem; int nLevel=PRCGetCasterLevel(oCaster); itemproperty ip; int nDC=10+nLevel; int nResist; int nRoll; SendMessageToPC(oTarget,GetName(oCaster)+" casts warp wood at you."); SendMessageToPC(oCaster,"You cast warp wood at "+GetName(oTarget)+"."); SetIsTemporaryEnemy(oCaster,oTarget,TRUE); oItem=GetItemInSlot(INVENTORY_SLOT_RIGHTHAND,oTarget); if (oItem!=OBJECT_INVALID) { // valid item nRoll=fnGetItemMaterial(oItem); if (nRoll==2) { // it is wooden nResist=1; if (GetPlotFlag(oItem)) nResist=nResist+5; if (GetStringLeft(GetResRef(oItem),3)=="rts") nResist=nResist+5; ip=GetFirstItemProperty(oItem); while(GetIsItemPropertyValid(ip)) { // check all properties nResist++; ip=GetNextItemProperty(oItem); } // check all properties nRoll=d20()+nResist; if (nRoll=nDC) { // saved SendMessageToPC(oCaster," "+GetName(oTarget)+" made their saving throw or is immune to paralysis."); } // saved else { // failed SendMessageToPC(oCaster," "+GetName(oTarget)+" failed the save and is held for "+IntToString(nDuration)+" rounds."); nC++; eHold=EffectCutsceneParalyze(); AssignCommand(oCaster,ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eHold,oTarget,RoundsToSeconds(nDuration))); } // failed } // first target was valid nN=1; oOb=GetNearestCreature(CREATURE_TYPE_IS_ALIVE,TRUE,oTarget,nN); while(oOb!=OBJECT_INVALID&&nC<3&&GetDistanceBetween(oTarget,oOb)<=10.0) { // in range nRT=MyPRCGetRacialType(oOb); if (nRT==RACIAL_TYPE_UNDEAD||GetLocalInt(oOb,"nIsVampire")) { // first target was valid nSave=GetWillSavingThrow(oOb); nRoll=d20(); if (GetIsPC(oOb)) { // message SendMessageToPC(oOb,GetName(oCaster)+" cast halt undead at you."); SendMessageToPC(oOb," Save check: Roll("+IntToString(nRoll)+")+Save("+IntToString(nSave)+")="+IntToString(nRoll+nSave)+" versus DC "+IntToString(nDC)); } // message SetIsTemporaryEnemy(oCaster,oOb,TRUE); if ((nRoll+nSave)>=nDC) { // saved SendMessageToPC(oCaster," "+GetName(oTarget)+" made their saving throw or is immune to paralysis."); } // saved else { // failed SendMessageToPC(oCaster," "+GetName(oOb)+" failed the save and is held for "+IntToString(nDuration)+" rounds."); nC++; eHold=EffectCutsceneParalyze(); AssignCommand(oCaster,ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eHold,oOb,RoundsToSeconds(nDuration))); } // failed } // first target was valid nN++; oOb=GetNearestCreature(CREATURE_TYPE_IS_ALIVE,TRUE,oTarget,nN); } // in range } // fnSpellHaltUndead() void fnWZGFEquip(object oItem,int nSlot) { // PURPOSE: Keep trying to equip object oMe=OBJECT_SELF; if (GetItemInSlot(nSlot,oMe)!=oItem) { // keep trying AssignCommand(oMe,ActionEquipItem(oItem,nSlot)); DelayCommand(0.5,fnWZGFEquip(oItem,nSlot)); } // keep trying } // fnWZGFEquip() void fnGaseous(object oCaster,int nDuration) { // PURPOSE: Handle the gaseous state object oMe=OBJECT_SELF; int nDur=nDuration; int nExtend=GetLocalInt(oMe,"nWZExtendGaseous"); effect eE; object oItem; nDur=nDur-5; if (nExtend>0) { // reset duration DeleteLocalInt(oMe,"nWZExtendGaseous"); nDur=nExtend; } // reset duration if (nDur>0&&GetCurrentAction(oCaster)!=ACTION_REST&&GetLocalInt(oMe,"bDispelMagic")==FALSE&&GetIsDead(oMe)!=TRUE) { // gaseous SetLocalInt(oMe,"bWZGaseous",TRUE); eE=EffectVisualEffect(VFX_DUR_GHOST_SMOKE_2); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eE,oMe,5.1); eE=EffectEthereal(); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eE,oMe,5.1); eE=EffectMovementSpeedIncrease(99); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eE,oMe,5.1); eE=EffectCutsceneGhost(); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eE,oMe,5.1); eE=EffectAttackDecrease(20); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eE,oMe,5.1); eE=EffectImmunity(IMMUNITY_TYPE_CRITICAL_HIT); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eE,oMe,5.1); eE=EffectImmunity(IMMUNITY_TYPE_KNOCKDOWN); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eE,oMe,5.1); eE=EffectImmunity(IMMUNITY_TYPE_SNEAK_ATTACK); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eE,oMe,5.1); eE=EffectImmunity(IMMUNITY_TYPE_TRAP); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eE,oMe,5.1); eE=EffectDamageImmunityIncrease(DAMAGE_TYPE_BASE_WEAPON,100); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eE,oMe,5.1); eE=EffectDamageImmunityIncrease(DAMAGE_TYPE_BLUDGEONING,100); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eE,oMe,5.1); eE=EffectDamageImmunityIncrease(DAMAGE_TYPE_PIERCING,100); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eE,oMe,5.1); eE=EffectDamageImmunityIncrease(DAMAGE_TYPE_SLASHING,100); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eE,oMe,5.1); eE=EffectSkillDecrease(SKILL_CONCENTRATION,40); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eE,oMe,5.1); eE=EffectSkillDecrease(SKILL_PERFORM,40); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eE,oMe,5.1); eE=EffectSkillDecrease(SKILL_SPELLCRAFT,40); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eE,oMe,5.1); eE=EffectSkillDecrease(SKILL_SET_TRAP,40); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eE,oMe,5.1); eE=EffectSkillDecrease(SKILL_DISABLE_TRAP,40); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eE,oMe,5.1); eE=EffectSkillDecrease(SKILL_CRAFT_ARMOR,40); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eE,oMe,5.1); eE=EffectSkillDecrease(SKILL_CRAFT_TRAP,40); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eE,oMe,5.1); eE=EffectSkillDecrease(SKILL_CRAFT_WEAPON,40); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eE,oMe,5.1); eE=EffectSkillDecrease(SKILL_OPEN_LOCK,40); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eE,oMe,5.1); eE=EffectSkillDecrease(SKILL_PARRY,40); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eE,oMe,5.1); eE=EffectSkillDecrease(SKILL_PICK_POCKET,40); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eE,oMe,5.1); eE=EffectSkillDecrease(SKILL_TAUNT,40); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eE,oMe,5.1); eE=EffectSkillDecrease(SKILL_PERSUADE,40); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eE,oMe,5.1); eE=EffectSkillDecrease(SKILL_BLUFF,40); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eE,oMe,5.1); eE=EffectSkillDecrease(SKILL_USE_MAGIC_DEVICE,40); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eE,oMe,5.1); eE=EffectDamageDecrease(100); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eE,oMe,5.1); DelayCommand(5.0,fnGaseous(oCaster,nDur)); //SendMessageToPC(oMe,"Gaseous Countdown:"+IntToString(nDur)+" seconds."); } // gaseous else { // end gaseous form nDur=GetLocalInt(oMe,"nWZAppearanceSaveGF"); DeleteLocalInt(oMe,"nWZAppearanceSaveGF"); SetCreatureAppearanceType(oMe,nDur); DeleteLocalInt(oMe,"bWZGaseous"); oItem=GetLocalObject(oMe,"oWZSaveGFRH"); if (oItem!=OBJECT_INVALID) { DeleteLocalObject(oMe,"oWZSaveGFRH"); AssignCommand(oMe,fnWZGFEquip(oItem,INVENTORY_SLOT_RIGHTHAND)); } oItem=GetLocalObject(oMe,"oWZSaveGFLH"); if (oItem!=OBJECT_INVALID) { DeleteLocalObject(oMe,"oWZSaveGFLH"); AssignCommand(oMe,fnWZGFEquip(oItem,INVENTORY_SLOT_LEFTHAND)); } } // end gaseous form } // fnGaseous() void fnSpellGaseousForm(object oTarget, object oCaster) { // PURPOSE: Handle gaseous form int nLevel=PRCGetCasterLevel(oCaster); int nDur=nLevel; object oListener; int nGF; object oItem; object oDo=OBJECT_INVALID; if (PRCGetMetaMagicFeat()==METAMAGIC_EXTEND) nDur=nDur*2; if (oTarget!=oCaster) { // caster cast spell upon other target if (GetIsFriend(oTarget,oCaster)) { // valid target SendMessageToPC(oCaster,"You cast gaseous form upon "+GetName(oTarget)+" which should last "+IntToString(nDur*20)+" seconds."); SendMessageToPC(oTarget,GetName(oCaster)+" cast gaseous forum upon you which should last "+IntToString(nDur*20)+" seconds."); oDo=oTarget; } // valid target else { // must be willing SendMessageToPC(oCaster,"You may only cast gaseous form upon willing targets!"); } // must be willing } // caster cast spell upon other target else { // caster cast the spell upon themselves SendMessageToPC(oCaster,"You cast gaseous form upon yourself which should last "+IntToString(nDur*20)+" seconds."); oDo=oTarget; } // caster cast the spell upon themselves if (oDo!=OBJECT_INVALID) { // target is valid if (GetLocalInt(oDo,"bWZGaseous")) { // already gaseous SendMessageToPC(oDo,"Since the spell was already active its duration has been reset."); SetLocalInt(oDo,"nWZExtendGaseous",nDur); } // already gaseous else { // new spell nLevel=GetAppearanceType(oDo); SetLocalInt(oDo,"nWZAppearanceSaveGF",nLevel); SetCreatureAppearanceType(oDo,298); oItem=GetItemInSlot(INVENTORY_SLOT_RIGHTHAND,oDo); SetLocalObject(oDo,"oWZSaveGFRH",oItem); AssignCommand(oDo,ActionUnequipItem(oItem)); oItem=GetItemInSlot(INVENTORY_SLOT_LEFTHAND,oDo); SetLocalObject(oDo,"oWZSaveGFLH",oItem); AssignCommand(oDo,ActionUnequipItem(oItem)); AssignCommand(oDo,fnGaseous(oCaster,(nDur*20)+5)); } // new spell } // target is valid } // fnSpellGaseousForm() void fnSpellLSC(object oTarget,object oCaster,location lLoc) { // PURPOSE: Leomund's Secret Chest SetLocalObject(oCaster,"oTarget",oTarget); SetLocalLocation(oCaster,"lLoc",lLoc); ExecuteScript("wazoo_leochest",oCaster); } // fnSpellLSC() void fnEscapeMaze(object oT) { // bring NPC back out of maze object oReturn; if (GetTag(GetArea(oT))=="Maze"&&oT!=OBJECT_INVALID) { // bring back oReturn=GetLocalObject(oT,"oMazeReturn"); AssignCommand(oT,ClearAllActions(TRUE)); AssignCommand(oT,JumpToObject(oReturn)); DelayCommand(10.0,AssignCommand(oT,DestroyObject(oReturn))); } // bring back } // fnEscapeMaze() void IsTAlive(object oT) { // make sure target exists if (GetIsDead(oT)!=TRUE&&oT!=OBJECT_INVALID) DelayCommand(10.0,IsTAlive(oT)); else { DestroyObject(oT); } } // IsTAlive() void fnMakeSureFollowersDontFollow(object oT) { // make sure followers within 30 meters do not follow int nC=1; object oCr=GetNearestCreature(CREATURE_TYPE_IS_ALIVE,TRUE,oT,nC,CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_FRIEND); float fDist=GetDistanceBetween(oT,oCr); int nS; object oF; object oMod=GetModule(); string sID; while(oCr!=OBJECT_INVALID&&fDist<30.1) { // test nS=GetLocalInt(oCr,"nMState"); if (nS==5||nS==4||nS==14) { // check to see if following target oF=GetLocalObject(oCr,"oDestWP"); if (oF==oT) { // make return to base SetLocalInt(oCr,"nMState",2); SetLocalInt(oCr,"nSState",0); sID=GetLocalString(oCr,"sTeamID"); oF=GetLocalObject(oMod,"oGUARD5"+sID); SetLocalObject(oCr,"oDestWP",oF); } // make return to base } // check to see if following target nC++; oCr=GetNearestCreature(CREATURE_TYPE_IS_ALIVE,TRUE,oT,nC,CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_FRIEND); fDist=GetDistanceBetween(oT,oCr); } // test } // fnMakeSureFollowersDontFollow() void fnSpellMaze(object oTarget,object oCaster) { // PURPOSE: Maze object oWP=GetWaypointByTag("MAZE_SPAWN"+IntToString(d4())); int bValid=TRUE; object oRet; if (GetIsPC(oTarget)==FALSE) { // make sure valid NPC if (GetPlotFlag(oTarget)==TRUE) bValid=FALSE; if (GetLocalString(oTarget,"sTeamID")==GetLocalString(oCaster,"sTeamID")) bValid=FALSE; } // make sure valid NPC if (oTarget==oCaster) bValid=FALSE; // can't send yourself else if (GetPlotFlag(oTarget)==TRUE) bValid=FALSE; // can't send plot characters else if (GetLocalInt(oTarget,"nMazeImmune")==1) bValid=FALSE; // way to disable the horn for some creatures if (bValid) { // target is legal if (GetIsPC(oTarget)) SendMessageToPC(oTarget,GetName(oCaster)+" has sent you into the maze."); SendMessageToPC(oCaster,"You have sent "+GetName(oTarget)+" to the maze."); oRet=CreateObject(OBJECT_TYPE_PLACEABLE,"rts_marker",GetLocation(oTarget)); AssignCommand(oRet,IsTAlive(oTarget)); SetLocalObject(oTarget,"oMazeReturn",oRet); fnMakeSureFollowersDontFollow(oTarget); AssignCommand(oTarget,ClearAllActions(TRUE)); AssignCommand(oTarget,JumpToObject(oWP)); if (!GetIsPC(oTarget)) DelayCommand(HoursToSeconds(d6()),fnEscapeMaze(oTarget)); } // target is legal else if (GetPlotFlag(oTarget)==TRUE) { SendMessageToPC(oCaster,"You may not send plot characters to the maze."); } else if (GetLocalInt(oTarget,"nMazeImmune")==1) { SendMessageToPC(oCaster,"That target has some type of magic resistance that prevents you from sending them to the maze."); } else { SendMessageToPC(oCaster,"That is an invalid target for this spell. Is it on the same team?"); } } // fnSpellMaze() void fnMislead_IllusionAI(object oCaster,object oIllusion) { // PURPOSE: Handle running the illusion away from enemies, and the PC object oOb; if (GetLocalInt(oIllusion,"bActive")) { // spell is active if (GetIsInCombat(oIllusion)) { // combat AssignCommand(oIllusion,ClearAllActions(TRUE)); oOb=GetNearestCreature(CREATURE_TYPE_IS_ALIVE,TRUE,oIllusion,1,CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY); if (GetIsObjectValid(oOb)) { // run away from the enemy if (GetCurrentAction(oIllusion)!=ACTION_MOVETOPOINT) { // move AssignCommand(oIllusion,ActionMoveAwayFromObject(oOb,TRUE,200.0)); } // move } // run away from the enemy } // combat else { // run away if (GetArea(oIllusion)==GetArea(oCaster)) { // run away if (GetCurrentAction(oIllusion)!=ACTION_MOVETOPOINT) { // move AssignCommand(oIllusion,ClearAllActions(TRUE)); AssignCommand(oIllusion,ActionMoveAwayFromObject(oCaster,TRUE,200.0)); } // move } // run away else { // run away from enemies oOb=GetNearestCreature(CREATURE_TYPE_IS_ALIVE,TRUE,oIllusion,1,CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY); if (GetIsObjectValid(oOb)) { // run away from the enemy if (GetCurrentAction(oIllusion)!=ACTION_MOVETOPOINT) { // move AssignCommand(oIllusion,ClearAllActions(TRUE)); AssignCommand(oIllusion,ActionMoveAwayFromObject(oOb,TRUE,200.0)); } // move } // run away from the enemy } // run away from enemies } // run away DelayCommand(1.0,fnMislead_IllusionAI(oCaster,oIllusion)); } // spell is active else { // clean up DestroyObject(oIllusion); } // clean up } // fnMislead_IllusionAI() void fnSpellMislead(object oCaster) { // PURPOSE: Mislead spell int nLevel=PRCGetCasterLevel(oCaster); float fDuration=6.0*IntToFloat(nLevel); effect eVFX=EffectCutsceneGhost(); object oIllusion; string sID=GetLocalString(oCaster,"sTeamID"); object oProxy=GetObjectByTag(sID+"_PROXY"); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eVFX,oCaster,3.0); oIllusion=CopyObject(oCaster,GetLocation(oCaster),OBJECT_INVALID,"PC_ILLUSION"); SetPlotFlag(oIllusion,TRUE); SetLocalInt(oIllusion,"bActive",TRUE); DelayCommand(0.3,AssignCommand(oIllusion,fnMislead_IllusionAI(oCaster,oIllusion))); eVFX=EffectInvisibility(INVISIBILITY_TYPE_IMPROVED); ChangeFaction(oIllusion,oProxy); DelayCommand(0.2,ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eVFX,oCaster,fDuration)); DelayCommand(fDuration,DeleteLocalInt(oIllusion,"bActive")); } // fnSpellMislead() void fnSpellClone(object oCaster) { // PURPOSE: Create a clone of the caster at the location they currently stand object oClone; object oInv; int bHasComponents=TRUE; effect eGhost=EffectCutsceneGhost(); string sID=GetLocalString(oCaster,"sTeamID"); object oProxy=GetObjectByTag(sID+"_PROXY"); oClone=GetLocalObject(oCaster,"oClone"); oInv=GetItemPossessedBy(oCaster,"NW_IT_MSMLMISC06"); if (!GetIsObjectValid(oInv)) bHasComponents=FALSE; oInv=GetItemPossessedBy(oCaster,"NW_IT_MSMLMISC10"); if (!GetIsObjectValid(oInv)) bHasComponents=FALSE; oInv=GetItemPossessedBy(oCaster,"NW_IT_MSMLMISC08"); if (!GetIsObjectValid(oInv)) bHasComponents=FALSE; oInv=GetItemPossessedBy(oCaster,"NW_IT_MSMLMISC19"); if (!GetIsObjectValid(oInv)) bHasComponents=FALSE; if (!bHasComponents) { // lacks spell components SendMessageToPC(oCaster,"The clone spell requires that you be carrying a bodak tooth, slaad tongue, fire beetle's belly, and fairy dust as spell components!"); return; } // lacks spell components if(!GetIsObjectValid(oClone)) { // clone ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eGhost,oCaster,3.0); oClone=CopyObject(oCaster,GetLocation(oCaster),OBJECT_INVALID,"PC_CLONE"); if (!GetIsObjectValid(oClone)) oClone=CopyObject(oCaster,GetLocation(oCaster),OBJECT_INVALID,"PC_CLONE"); if (!GetIsObjectValid(oClone)) oClone=CopyObject(oCaster,GetLocation(oCaster),OBJECT_INVALID,"PC_CLONE"); if (!GetIsObjectValid(oClone)) oClone=CopyObject(oCaster,GetLocation(oCaster),OBJECT_INVALID,"PC_CLONE"); if (!GetIsObjectValid(oClone)) { // failed SendMessageToPC(oCaster,"Clone script failed to produce clone. Components not consumed."); return; } // failed DelayCommand(5.0,SetCreatureAppearanceType(oClone,GetAppearanceType(oCaster))); eGhost=EffectCutsceneParalyze(); SetLocalObject(oCaster,"oClone",oClone); //AssignCommand(oClone,ClearAllActions(TRUE)); //DelayCommand(2.0,AssignCommand(oClone,ActionPlayAnimation(ANIMATION_LOOPING_DEAD_BACK,1.0,9999.0))); ChangeFaction(oClone,oProxy); DelayCommand(3.0,ApplyEffectToObject(DURATION_TYPE_PERMANENT,eGhost,oClone,9999.0)); oInv=GetFirstItemInInventory(oClone); while(GetIsObjectValid(oInv)) { // check inventory DelayCommand(0.03,DestroyObject(oClone)); oInv=GetNextItemInInventory(oClone); } // check inventory oInv=GetItemInSlot(INVENTORY_SLOT_ARMS,oClone); if (GetIsObjectValid(oInv)) DestroyObject(oInv); oInv=GetItemInSlot(INVENTORY_SLOT_ARROWS,oClone); if (GetIsObjectValid(oInv)) DestroyObject(oInv); oInv=GetItemInSlot(INVENTORY_SLOT_BELT,oClone); if (GetIsObjectValid(oInv)) DestroyObject(oInv); oInv=GetItemInSlot(INVENTORY_SLOT_BOLTS,oClone); if (GetIsObjectValid(oInv)) DestroyObject(oInv); oInv=GetItemInSlot(INVENTORY_SLOT_BOOTS,oClone); if (GetIsObjectValid(oInv)) DestroyObject(oInv); oInv=GetItemInSlot(INVENTORY_SLOT_BULLETS,oClone); if (GetIsObjectValid(oInv)) DestroyObject(oInv); oInv=GetItemInSlot(INVENTORY_SLOT_CHEST,oClone); if (GetIsObjectValid(oInv)) DestroyObject(oInv); oInv=GetItemInSlot(INVENTORY_SLOT_CLOAK,oClone); if (GetIsObjectValid(oInv)) DestroyObject(oInv); oInv=GetItemInSlot(INVENTORY_SLOT_HEAD,oClone); if (GetIsObjectValid(oInv)) DestroyObject(oInv); oInv=GetItemInSlot(INVENTORY_SLOT_LEFTRING,oClone); if (GetIsObjectValid(oInv)) DestroyObject(oInv); oInv=GetItemInSlot(INVENTORY_SLOT_LEFTHAND,oClone); if (GetIsObjectValid(oInv)) DestroyObject(oInv); oInv=GetItemInSlot(INVENTORY_SLOT_NECK,oClone); if (GetIsObjectValid(oInv)) DestroyObject(oInv); oInv=GetItemInSlot(INVENTORY_SLOT_RIGHTHAND,oClone); if (GetIsObjectValid(oInv)) DestroyObject(oInv); oInv=GetItemInSlot(INVENTORY_SLOT_RIGHTRING,oClone); if (GetIsObjectValid(oInv)) DestroyObject(oInv); SetName(oClone,"Clone of "+GetName(oCaster)); oInv=GetItemPossessedBy(oCaster,"NW_IT_MSMLMISC06"); if (GetIsObjectValid(oInv)) DestroyObject(oInv); oInv=GetItemPossessedBy(oCaster,"NW_IT_MSMLMISC10"); if (GetIsObjectValid(oInv)) DestroyObject(oInv); oInv=GetItemPossessedBy(oCaster,"NW_IT_MSMLMISC08"); if (GetIsObjectValid(oInv)) DestroyObject(oInv); oInv=GetItemPossessedBy(oCaster,"NW_IT_MSMLMISC19"); if (GetIsObjectValid(oInv)) DestroyObject(oInv); SendMessageToPC(oCaster,"You create a clone!"); } // clone else { // already have one SendMessageToPC(oCaster,"You already have a clone!"); } // already have one } // fnSpellClone() void fnSpellCollectPersonalItem(object oTarget,object oCaster) { // PURPOSE: Create personal item if (GetIsObjectValid(oTarget)&&GetObjectType(oTarget)==OBJECT_TYPE_CREATURE) { // parameters okay object oItem=CreateItemOnObject("wazoo_it_person",oCaster); SetName(oItem,GetName(oTarget)+" hair"); SetLocalString(oItem,"sOwnerName",GetName(oTarget)); SetLocalObject(oItem,"oOwner",oTarget); SendMessageToPC(oCaster,"You collect some of the hair of "+GetName(oTarget)+"."); } // parameters okay } // fnSpellCollectPersonalItem() void fnSpellScry(object oCaster) { // PURPOSE: Activate the scry dialog AssignCommand(oCaster,ClearAllActions(TRUE)); AssignCommand(oCaster,ActionStartConversation(oCaster,"wazoo_scry",TRUE,FALSE)); } // fnSpellScry() void fnSpellGoodberries(object oCaster) { // PURPOSE: Create 2 to 8 good berries int nAmount=d4()+d4(); object oItem; while(nAmount>0) { // create goodberries oItem=CreateItemOnObject("wazoo_it_berry",oCaster); nAmount=nAmount-1; } // create goodberries } // fnSpellGoodberries() void fnDisguised(int nEndTime) { // PURPOSE: Handle disguised undead int nABS=GetTimeHour()+(GetCalendarDay()*24)+(GetCalendarMonth()*24*30)+(GetCalendarYear()*24*30*12); object oMe=OBJECT_SELF; if (nABS>=nEndTime||GetIsInCombat(oMe)||!GetLocalInt(oMe,"bDisguised")) { // spell end string sTeamID=GetLocalString(oMe,"sTeamID"); DeleteLocalInt(oMe,"bDisguised"); object oProxy=GetObjectByTag(sTeamID+"_PROXY"); ChangeFaction(oMe,oProxy); SetName(oMe,GetLocalString(oMe,"sWazooPDName")); SetCreatureAppearanceType(oMe,GetLocalInt(oMe,"nWazooPDAppearance")); DeleteLocalString(oMe,"sWazooPDName"); DeleteLocalInt(oMe,"nWazooPDAppearance"); } // spell end else { // continue DelayCommand(10.0,fnDisguised(nEndTime)); } // continue } // fnDisguised() void fnSpellDisguiseUndead(object oTarget, object oCaster) { // PURPOSE: Make an undead creature not appear as enemy or undead for 1 game // hour per caster level or until in combat if (GetIsObjectValid(oTarget)&&GetObjectType(oTarget)==OBJECT_TYPE_CREATURE&&GetRacialType(oTarget)==RACIAL_TYPE_UNDEAD&&GetLocalString(oTarget,"sTeamID")==GetLocalString(oCaster,"sTeamID")) { // valid target if (!GetLocalInt(oTarget,"bDisguised")) { // not already disguised if (!GetIsInCombat(oTarget)) { // not in combat SetLocalString(oTarget,"sWazooPDName",GetName(oTarget)); SetLocalInt(oTarget,"nWazooPDAppearance",GetAppearanceType(oTarget)); SetLocalInt(oTarget,"bDisguised",TRUE); object oProxy=GetObjectByTag("ABS_PROXY"); int nDuration=PRCGetCasterLevel(oTarget); int nABS=GetTimeHour()+(GetCalendarDay()*24)+(GetCalendarMonth()*24*30)+(GetCalendarYear()*24*30*12); int nEndTime=nABS+nDuration; ChangeFaction(oTarget,oProxy); int nR=d4(); if (nR==1) { // Man SetName(oTarget,"Man"); SetCreatureAppearanceType(oTarget,APPEARANCE_TYPE_HUMAN_NPC_MALE_01); } // Man else if (nR==2) { // Woman SetName(oTarget,"Woman"); SetCreatureAppearanceType(oTarget,APPEARANCE_TYPE_HUMAN_NPC_FEMALE_01); } // Woman else if (nR==3) { // Child Female SetName(oTarget,"Girl"); SetCreatureAppearanceType(oTarget,APPEARANCE_TYPE_KID_FEMALE); } // Child Female else if (nR==4) { // Child Male SetName(oTarget,"Boy"); SetCreatureAppearanceType(oTarget,APPEARANCE_TYPE_KID_MALE); } // Child Male AssignCommand(oTarget,fnDisguised(nEndTime)); } // not in combat else { // cannot use on creatures in combat FloatingTextStringOnCreature("** Cannot use on creatures in combat **",oCaster,FALSE); } // cannot use on creatures in combat } // not already disguised else { // already disguised FloatingTextStringOnCreature("** That creature s already disguised **",oCaster,FALSE); } // already disguised } // valid target else { // invalid target FloatingTextStringOnCreature("** Invalid target **",oCaster,FALSE); } // invalid target } // fnSpellDisguiseUndead()