Updated AMS marker feats. Removed arcane & divine marker feats. Updated Dread Necromancer for epic progression. Updated weapon baseitem models. Updated new weapons for crafting & npc equip. Updated prefix. Updated release archive.
222 lines
7.6 KiB
Plaintext
222 lines
7.6 KiB
Plaintext
//::///////////////////////////////////////////////
|
||
//:: Mirror Image
|
||
//:: sp_mirror.nss
|
||
//:://////////////////////////////////////////////
|
||
/*
|
||
Caster Level(s): Bard 2, Wizard 2, Sorcerer 2
|
||
Innate Level: 2
|
||
School: Illusion
|
||
Component(s): Verbal, Somatic
|
||
Range: Personal
|
||
Area of Effect / Target: Self
|
||
Duration: 1 min/level
|
||
Save: harmless
|
||
Spell Resistance: harmless
|
||
|
||
Several illusory duplicates of you pop into being, making it
|
||
difficult for enemies to know which target to attack. The
|
||
figments stay near you and disappear when struck.
|
||
|
||
Mirror image creates 1d4 images plus one image per three
|
||
caster levels (maximum eight images total). These figments
|
||
separate from you and remain in a cluster, each within 5 feet
|
||
of at least one other figment or you. You can move into and
|
||
through a mirror image. When you and the mirror image separate,
|
||
observers can’t use vision or hearing to tell which one is you
|
||
and which the image. The figments may also move through each
|
||
other. The figments mimic your actions, pretending to cast spells
|
||
when you cast a spell, drink potions when you drink a potion,
|
||
levitate when you levitate, and so on.
|
||
|
||
Enemies attempting to attack you or cast spells at you must
|
||
select from among indistinguishable targets. Any successful
|
||
attack against an image destroys it. An image’s AC is 10 +
|
||
your size modifier + your Dex modifier. Figments seem to react
|
||
normally to area spells (such as looking like they’re burned or
|
||
dead after being hit by a fireball).
|
||
|
||
*/
|
||
//:://////////////////////////////////////////////
|
||
//:: Created By: Stratovarius
|
||
//:: Created On: August 20, 2004
|
||
//:://////////////////////////////////////////////
|
||
|
||
#include "prc_inc_spells"
|
||
|
||
|
||
void CleanCopy(object oImage)
|
||
{
|
||
SetLootable(oImage, FALSE);
|
||
// remove inventory contents
|
||
object oItem = GetFirstItemInInventory(oImage);
|
||
while(GetIsObjectValid(oItem))
|
||
{
|
||
SetPlotFlag(oItem,FALSE);
|
||
if(GetHasInventory(oItem))
|
||
{
|
||
object oItem2 = GetFirstItemInInventory(oItem);
|
||
while(GetIsObjectValid(oItem2))
|
||
{
|
||
object oItem3 = GetFirstItemInInventory(oItem2);
|
||
while(GetIsObjectValid(oItem3))
|
||
{
|
||
SetPlotFlag(oItem3,FALSE);
|
||
DestroyObject(oItem3);
|
||
oItem3 = GetNextItemInInventory(oItem2);
|
||
}
|
||
SetPlotFlag(oItem2,FALSE);
|
||
DestroyObject(oItem2);
|
||
oItem2 = GetNextItemInInventory(oItem);
|
||
}
|
||
}
|
||
DestroyObject(oItem);
|
||
oItem = GetNextItemInInventory(oImage);
|
||
}
|
||
// remove non-visible equipped items
|
||
int i;
|
||
for(i=0;i<NUM_INVENTORY_SLOTS;i++)//equipment
|
||
{
|
||
oItem = GetItemInSlot(i, oImage);
|
||
if(GetIsObjectValid(oItem))
|
||
{
|
||
if(i == INVENTORY_SLOT_HEAD || i == INVENTORY_SLOT_CHEST ||
|
||
i == INVENTORY_SLOT_RIGHTHAND || i == INVENTORY_SLOT_LEFTHAND ||
|
||
i == INVENTORY_SLOT_CLOAK) // visible equipped items
|
||
{
|
||
SetDroppableFlag(oItem, FALSE);
|
||
SetItemCursedFlag(oItem, TRUE);
|
||
// remove all item properties
|
||
itemproperty ipLoop=GetFirstItemProperty(oItem);
|
||
while (GetIsItemPropertyValid(ipLoop))
|
||
{
|
||
RemoveItemProperty(oItem, ipLoop);
|
||
ipLoop=GetNextItemProperty(oItem);
|
||
}
|
||
}
|
||
else // can't see it so destroy
|
||
{
|
||
SetPlotFlag(oItem,FALSE);
|
||
DestroyObject(oItem);
|
||
}
|
||
}
|
||
|
||
}
|
||
TakeGoldFromCreature(GetGold(oImage), oImage, TRUE);
|
||
}
|
||
|
||
void MakeMoreImages(object oImage, int iImages, int nDuration)
|
||
{
|
||
string sImage = "PC_IMAGE"+ObjectToString(OBJECT_SELF)+"mirror";
|
||
|
||
effect eImage = EffectCutsceneParalyze();
|
||
eImage = SupernaturalEffect(eImage);
|
||
effect eGhost = EffectCutsceneGhost();
|
||
eGhost = SupernaturalEffect(eGhost);
|
||
effect eNoSpell = EffectSpellFailure(100);
|
||
eNoSpell = SupernaturalEffect(eNoSpell);
|
||
int iPlus;
|
||
for (iPlus = 0; iPlus < iImages; iPlus++)
|
||
{
|
||
object oImage2 = CopyObject(oImage, GetLocation(OBJECT_SELF), OBJECT_INVALID, sImage);
|
||
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eImage, oImage2);
|
||
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eNoSpell, oImage2);
|
||
ChangeFaction(oImage2, oImage);
|
||
SetIsTemporaryFriend(OBJECT_SELF, oImage2, FALSE);
|
||
DelayCommand(3.0f, ApplyEffectToObject(DURATION_TYPE_PERMANENT, eGhost, oImage2));
|
||
DestroyObject(oImage2, TurnsToSeconds(nDuration)); // they dissapear after a minute per level
|
||
}
|
||
}
|
||
|
||
void RemoveExtraImages()
|
||
{
|
||
string sImage1 = "PC_IMAGE"+ObjectToString(OBJECT_SELF)+"mirror";
|
||
string sImage2 = "PC_IMAGE"+ObjectToString(OBJECT_SELF)+"flurry";
|
||
|
||
object oCreature = GetFirstObjectInArea(GetArea(OBJECT_SELF));
|
||
while (GetIsObjectValid(oCreature))
|
||
{
|
||
if(GetTag(oCreature) == sImage1 || GetTag(oCreature) == sImage2)
|
||
{
|
||
DestroyObject(oCreature, 0.0);
|
||
}
|
||
oCreature = GetNextObjectInArea(GetArea(OBJECT_SELF));;
|
||
}
|
||
}
|
||
|
||
void main2()
|
||
{
|
||
int iLevel = PRCGetCasterLevel(OBJECT_SELF);
|
||
int iAdd = iLevel/3;
|
||
int iImages = d4(1) + iAdd;
|
||
if(iImages >8)
|
||
iImages = 8;
|
||
int nDuration = iLevel;
|
||
//Enter Metamagic conditions
|
||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||
if (CheckMetaMagic(nMetaMagic, METAMAGIC_EXTEND))
|
||
{
|
||
nDuration = nDuration *2; //Duration is +100%
|
||
}
|
||
|
||
|
||
string sImage = "PC_IMAGE"+ObjectToString(OBJECT_SELF)+"mirror";
|
||
|
||
effect eImage = EffectCutsceneParalyze();
|
||
eImage = SupernaturalEffect(eImage);
|
||
effect eGhost = EffectCutsceneGhost();
|
||
eGhost = SupernaturalEffect(eGhost);
|
||
effect eNoSpell = EffectSpellFailure(100);
|
||
eNoSpell = SupernaturalEffect(eNoSpell);
|
||
|
||
// make, then clean up, first image and copy it, not the PC for subsequent images
|
||
object oImage = CopyObject(OBJECT_SELF, GetLocation(OBJECT_SELF), OBJECT_INVALID, sImage);
|
||
CleanCopy(oImage);
|
||
|
||
// images will have only 1 HP
|
||
int iHP = GetCurrentHitPoints(oImage);
|
||
--iHP;
|
||
effect eDamage = PRCEffectDamage(oImage, iHP); // reduces image to 1 hp
|
||
|
||
// these need to be applied to every image
|
||
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eImage, oImage);
|
||
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eNoSpell, oImage);
|
||
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eDamage, oImage);
|
||
if(!GetIsPC(OBJECT_SELF))
|
||
ChangeFaction(oImage, OBJECT_SELF);
|
||
else
|
||
ChangeToStandardFaction(oImage, STANDARD_FACTION_DEFENDER);
|
||
SetIsTemporaryFriend(OBJECT_SELF, oImage, FALSE);
|
||
DelayCommand(3.0f, ApplyEffectToObject(DURATION_TYPE_PERMANENT, eGhost, oImage));
|
||
DestroyObject(oImage, TurnsToSeconds(nDuration)); // they dissapear after a minute per level
|
||
|
||
--iImages; // made one already
|
||
DelayCommand(0.2, MakeMoreImages(oImage, iImages, nDuration));
|
||
}
|
||
|
||
void main()
|
||
{
|
||
DeleteLocalInt(OBJECT_SELF, "X2_L_LAST_SPELLSCHOOL_VAR");
|
||
SetLocalInt(OBJECT_SELF, "X2_L_LAST_SPELLSCHOOL_VAR", SPELL_SCHOOL_ILLUSION);
|
||
/*
|
||
Spellcast Hook Code
|
||
Added 2003-06-23 by GeorgZ
|
||
If you want to make changes to all spells,
|
||
check x2_inc_spellhook.nss to find out more
|
||
|
||
*/
|
||
|
||
if (!X2PreSpellCastCode())
|
||
{
|
||
// If code within the PreSpellCastHook (i.e. UMD) reports FALSE, do not run this spell
|
||
return;
|
||
}
|
||
|
||
// End of Spell Cast Hook
|
||
|
||
DelayCommand(0.0, RemoveExtraImages());
|
||
DelayCommand(0.1, main2());
|
||
|
||
DeleteLocalInt(OBJECT_SELF, "X2_L_LAST_SPELLSCHOOL_VAR");
|
||
// Getting rid of the local integer storing the spellschool name
|
||
}
|