Jaysyn904 04165202c0 Initial upload
Initial upload
2024-11-25 19:36:07 -05:00

2042 lines
82 KiB
Plaintext

///////////////////////////////////////////////////////////////////////////////
// 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+nRoll<nDC) bFumble=TRUE;
if (GetIsPC(oOwner))
{ // send message
if (bFumble) SendMessageToPC(oOwner,"Reflex save to avoid fumbling item: roll:"+IntToString(nRoll)+"+Reflex:"+IntToString(nRS)+"="+IntToString(nRS+nRoll)+" which fails versus DC "+IntToString(nDC));
else { SendMessageToPC(oOwner,"Reflex save to avoid fumbling item: roll:"+IntToString(nRoll)+"+Reflex:"+IntToString(nRS)+"="+IntToString(nRS+nRoll)+" which succeeds versus DC "+IntToString(nDC));}
} // send message
if (bFumble)
{ // drop item
oCopy=CreateObject(OBJECT_TYPE_ITEM,GetResRef(oItem),GetLocation(oOwner),FALSE,GetTag(oItem));
nN=GetItemCharges(oItem);
SetItemCharges(oItem,nN);
DestroyObject(oItem);
} // drop item
} // okay to drop
} // fnCheckFumbleItem()
void fnSpellHeatMetal(object oTarget,object oCaster)
{
int nLevel=PRCGetCasterLevel(oCaster);
int bImmune=FALSE;
object oItem;
object oNew;
int nN;
int nDmgA=2;
int nDmgW=nLevel/3;
int bMaximize=FALSE;
int bWeaponDamage=FALSE;
int bArmorDamage=FALSE;
effect eE;
SendMessageToPC(oCaster,"You cast heat metal upon "+GetName(oTarget)+".");
if (nDmgW<1) nDmgW=1;
if (PRCGetMetaMagicFeat()==METAMAGIC_EMPOWER) { nDmgA=3; nDmgW++; }
else if (PRCGetMetaMagicFeat()==METAMAGIC_MAXIMIZE) bMaximize=TRUE;
if (GetHasSpellEffect(SPELL_ELEMENTAL_SHIELD,oTarget)==TRUE) bImmune=TRUE;
else if (GetHasSpellEffect(SPELL_ENDURE_ELEMENTS,oTarget)==TRUE) bImmune=TRUE;
else if (GetHasSpellEffect(SPELL_ENERGY_BUFFER,oTarget)==TRUE) bImmune=TRUE;
else if (GetHasSpellEffect(SPELL_PROTECTION_FROM_ELEMENTS,oTarget)==TRUE) bImmune=TRUE;
else if (GetHasSpellEffect(SPELL_RESIST_ELEMENTS,oTarget)==TRUE) bImmune=TRUE;
if (bImmune) SendMessageToPC(oCaster," The target is currently immune to heat metal.");
if (!bImmune&&oTarget!=OBJECT_INVALID)
{ // valid target
eE=EffectVisualEffect(VFX_IMP_FLAME_S);
ApplyEffectToObject(DURATION_TYPE_INSTANT,eE,oTarget,1.0);
if (GetIsPC(oTarget)) SendMessageToPC(oTarget,GetName(oCaster)+" has cast heat metal upon you.");
else if (GetIsPC(GetMaster(oTarget))) SendMessageToPC(GetMaster(oTarget),GetName(oCaster)+" has cast heat metal upon "+GetName(oTarget)+".");
oItem=GetItemInSlot(INVENTORY_SLOT_CHEST,oTarget);
if (fnGetItemMaterial(oItem)==1) bArmorDamage=TRUE;
oItem=GetItemInSlot(INVENTORY_SLOT_RIGHTHAND,oTarget);
if (fnGetItemMaterial(oItem)==1) { bWeaponDamage=TRUE; fnCheckFumbleItem(oTarget,oItem,10); }
oItem=GetItemInSlot(INVENTORY_SLOT_LEFTHAND,oTarget);
if (fnGetItemMaterial(oItem)==1) { bWeaponDamage=TRUE; fnCheckFumbleItem(oTarget,oItem,10); }
if (bArmorDamage)
{ // armor damage
SendMessageToPC(oCaster," The target has taken damage due to wearing metal armor.");
eE=EffectDamage(d6(nDmgA));
if (bMaximize) eE=EffectDamage(6*nDmgA);
AssignCommand(oCaster,ApplyEffectToObject(DURATION_TYPE_INSTANT,eE,oTarget,1.0));
} // armor damage
if (bWeaponDamage)
{ // weapon damage
SendMessageToPC(oCaster," The target has taken damage due to holding a metal weapon.");
eE=EffectDamage(nDmgW);
AssignCommand(oCaster,ApplyEffectToObject(DURATION_TYPE_INSTANT,eE,oTarget,1.0));
} // weapon damage
} // valid target
else if (oTarget!=OBJECT_INVALID)
{ // message
if (GetIsPC(oTarget)) SendMessageToPC(oTarget,GetName(oCaster)+" cast heat metal upon you but, it had no effect.");
else if (GetIsPC(GetMaster(oTarget))) SendMessageToPC(GetMaster(oTarget),GetName(oCaster)+" cast heat metal at "+GetName(oTarget)+" but, it had no effect.");
} // message
} // fnSpellHeatMetal()
void fnHoldPortal(object oCaster,int nDuration)
{ // PURPOSE: Keep the door closed
object oDoor=OBJECT_SELF;
object oTrans;
int nDur=nDuration;
int nExtend=GetLocalInt(oDoor,"nWZExtendHoldPortal");
int bDispelMagic=GetLocalInt(oDoor,"bDispelMagic");
effect eGlow=EffectVisualEffect(VFX_DUR_GLOW_LIGHT_ORANGE);
nDur=nDur-1;
if (nExtend>0)
{ // 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)
{ // warp it
SendMessageToPC(oCaster," "+GetName(oItem)+" failed its save and was warped.");
fnWarpItem(oItem);
} // warp it
else
{ // saved
SendMessageToPC(oCaster," "+GetName(oItem)+" saved against the warp.");
} // saved
} // it is wooden
} // valid item
oItem=GetItemInSlot(INVENTORY_SLOT_ARROWS,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)
{ // warp it
SendMessageToPC(oCaster," "+GetName(oItem)+" failed its save and was warped.");
fnWarpItem(oItem);
} // warp it
else
{ // saved
SendMessageToPC(oCaster," "+GetName(oItem)+" saved against the warp.");
} // saved
} // it is wooden
} // valid item
oItem=GetItemInSlot(INVENTORY_SLOT_BOLTS,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)
{ // warp it
SendMessageToPC(oCaster," "+GetName(oItem)+" failed its save and was warped.");
fnWarpItem(oItem);
} // warp it
else
{ // saved
SendMessageToPC(oCaster," "+GetName(oItem)+" saved against the warp.");
} // saved
} // it is wooden
} // valid item
oItem=GetItemInSlot(INVENTORY_SLOT_LEFTHAND,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)
{ // warp it
SendMessageToPC(oCaster," "+GetName(oItem)+" failed its save and was warped.");
fnWarpItem(oItem);
} // warp it
else
{ // saved
SendMessageToPC(oCaster," "+GetName(oItem)+" saved against the warp.");
} // saved
} // it is wooden
} // valid item
oItem=GetFirstItemInInventory(oTarget);
while(oItem!=OBJECT_INVALID)
{ // traverse inventory
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)
{ // warp it
SendMessageToPC(oCaster," "+GetName(oItem)+" failed its save and was warped.");
fnWarpItem(oItem);
} // warp it
else
{ // saved
SendMessageToPC(oCaster," "+GetName(oItem)+" saved against the warp.");
} // saved
} // it is wooden
} // valid item
oItem=GetNextItemInInventory(oTarget);
} // traverse inventory
} // fnWarpWood()
void fnSpellWoodShape(object oCaster)
{ // PURPOSE: Wood Shape
AssignCommand(oCaster,ClearAllActions(TRUE));
AssignCommand(oCaster,ActionStartConversation(oCaster,"wazoo_woodshape",TRUE,FALSE));
} // fnSpellWoodShape
void fnSpellFireSeeds(object oCaster)
{ // PURPOSE: Fire seeds
AssignCommand(oCaster,ClearAllActions(TRUE));
AssignCommand(oCaster,ActionStartConversation(oCaster,"wazoo_fireseed",TRUE,FALSE));
} // fnSpellFireSeeds()
void fnSpellHaltUndead(object oTarget, object oCaster)
{ // PURPOSE: Halt Undead
int nLevel=PRCGetCasterLevel(oCaster);
int nDC=10+GetSkillRank(SKILL_SPELLCRAFT,oCaster);
int nDuration=nLevel;
int nSave;
int nRoll;
int nN;
int nC;
int nRT;
object oOb;
effect eHold;
SendMessageToPC(oCaster,"You cast halt undead at "+GetName(oTarget)+".");
if (PRCGetMetaMagicFeat()==METAMAGIC_EXTEND) nDuration=nDuration*2;
else if (PRCGetMetaMagicFeat()==METAMAGIC_EMPOWER) nDC=nDC+2;
nC=0;
nRT=MyPRCGetRacialType(oTarget);
if (nRT==RACIAL_TYPE_UNDEAD||GetLocalInt(oTarget,"nIsVampire"))
{ // first target was valid
nSave=GetWillSavingThrow(oTarget);
nRoll=d20();
if (GetIsPC(oTarget))
{ // message
SendMessageToPC(oTarget,GetName(oCaster)+" cast halt undead at you.");
SendMessageToPC(oTarget," Save check: Roll("+IntToString(nRoll)+")+Save("+IntToString(nSave)+")="+IntToString(nRoll+nSave)+" versus DC "+IntToString(nDC));
} // message
SetIsTemporaryEnemy(oCaster,oTarget,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(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()