2042 lines
82 KiB
Plaintext
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()
|