PRC8/nwn/nwnprc/trunk/include/prc_inc_scry.nss
Jaysyn904 6ec137a24e Updated AMS marker feats
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.
2024-02-11 14:01:05 -05:00

596 lines
23 KiB
Plaintext

//::///////////////////////////////////////////////
//:: Scrying include
//:: prc_inc_scry
//::///////////////////////////////////////////////
/** @file
This include contains all of the code that is used
to scry. At the moment, this is the basic scrying
and will be expanded with the additional material
as coding goes along. This is based on the code
of the Baelnorn Project written by Ornedan.
All the operations work only on PCs, as there is no
AI that could have NPCs take any advantage of the
system.
*/
//:://////////////////////////////////////////////
//:: Created By: Stratovarius
//:: Created On: 30.04.2007
//:://////////////////////////////////////////////
#include "psi_inc_psifunc"
#include "inc_utility"
#include "true_utter_const"
#include "shd_myst_const"
///////////////////////
/* Public Constants */
///////////////////////
const string COPY_LOCAL_NAME = "Scry_Copy";
const string ALREADY_IMMORTAL_LOCAL_NAME = "Scry_ImmortalAlready";
const float SCRY_HB_DELAY = 1.0f;
//////////////////////////////////////////////////
/* Function prototypes */
//////////////////////////////////////////////////
/**
* ONLY CALL THIS FUNCTION
* Does all of the necessary set up for scrying
* Also checks for all of the anti-scrying features
* if oPC == oTarget, will use PRCGetSpellLocation
* as the location for the effects to begin
*
* @param oPC The PC on whom to operate.
* @param oTarget The object to target
*/
void ScryMain(object oPC, object oTarget);
/**
* Moves all of the PC's items to the copy creature
* Switches locations of the two creatures
*
* @param oPC The PC on whom to operate.
* @param oCopy The copy of the PC
*/
void DoScryBegin(object oPC, object oCopy);
/**
* Undoes all the effects of DoScryBegin
*
* @param oPC The PC on whom to operate.
* @param oCopy The copy of the PC
*/
void DoScryEnd(object oPC, object oCopy);
/**
* Runs tests to see if the Scry effect can still continue.
* If the copy is dead, end Scry and kill the PC.
*
* @param oPC The PC on whom to operate.
* @param oCopy The copy of the PC
*/
void ScryMonitor(object oPC, object oCopy);
/**
* Reverses ApplyScryEffects
*
* @param oPC The PC on whom to operate.
*/
void RemoveScryEffects(object oPC);
/**
* Checks whether the PC is scrying or not
*
* @param oPC The PC on whom to operate.
*/
int GetIsScrying(object oPC);
/**
* Does the Discern Location content
*
* @param oPC The PC on whom to operate.
* @param oTarget The spell Target
*/
void DiscernLocation(object oPC, object oTarget);
/**
* Does the Locate Creature and Object content
*
* @param oPC The PC on whom to operate.
* @param oTarget The spell Target
*/
void LocateCreatureOrObject(object oPC, object oTarget);
/**
* Prevents the copy from dropping goods when dead.
*
* @param oImage The PC's copy.
*/
void CleanCopy(object oImage);
//////////////////////////////////////////////////
/* Function definitions */
//////////////////////////////////////////////////
void ScryMain(object oPC, object oTarget)
{
// Get the main variables used.
object oCopy = GetLocalObject(oPC, COPY_LOCAL_NAME);
effect eLight = EffectVisualEffect(VFX_IMP_HEALING_X , FALSE);
effect eGlow = EffectVisualEffect(VFX_DUR_ETHEREAL_VISAGE, FALSE);
// Use prestored variables because of time delay
int nCasterLevel = GetLocalInt(oPC, "ScryCasterLevel");
int nSpell = PRCGetSpellId(); //GetLocalInt(oPC, "ScrySpellId");
int nDC = GetLocalInt(oPC, "ScrySpellDC");
float fDur = GetLocalFloat(oPC, "ScryDuration");
if(DEBUG) DoDebug("prc_inc_scry: Beginning ScryMain. nSpell: " + IntToString(nSpell));
if (oPC != oTarget) // No hitting yourself with defenses
{
if(GetHasSpellEffect(POWER_REMOTE_VIEW_TRAP, oTarget))
{
effect eVis = EffectVisualEffect(VFX_IMP_LIGHTNING_S);
// Failed Save
if(!PRCMySavingThrow(SAVING_THROW_WILL, oTarget, nDC, SAVING_THROW_TYPE_NONE))
{
FloatingTextStringOnCreature("You have been caught in a Remote View Trap", oPC, FALSE);
eVis = EffectLinkEffects(eVis, EffectDamage(d6(8), DAMAGE_TYPE_ELECTRICAL));
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget);
return;
}
else
{
FloatingTextStringOnCreature("You have saved against a Remote View Trap", oPC, FALSE);
eVis = EffectLinkEffects(eVis, EffectDamage(d6(4), DAMAGE_TYPE_ELECTRICAL));
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget);
}
}
if(GetHasSpellEffect(SPELL_SEQUESTER, oTarget) || GetHasSpellEffect(POWER_SEQUESTER, oTarget))
{
// Spell auto-fails if this is the case
FloatingTextStringOnCreature(GetName(oTarget) + " has been Sequestered.", oPC, FALSE);
return;
}
if(GetHasSpellEffect(SPELL_OBSCURE_OBJECT, oTarget))
{
// Spell auto-fails if this is the case
FloatingTextStringOnCreature(GetName(oTarget) + " has been Obscured.", oPC, FALSE);
return;
}
if(GetHasSpellEffect(SPELL_NONDETECTION, oTarget) || GetLevelByClass(CLASS_TYPE_WILD_MAGE, oTarget) >= 6 || GetLevelByClass(CLASS_TYPE_UNSEEN_SEER, oTarget) >= 5 || GetHasSpellEffect(MELD_ENIGMA_HELM, oTarget) || GetRacialType(oTarget) == RACIAL_TYPE_SKULK)
{
// Caster level check or the Divination fails.
int nTarget = PRCGetCasterLevel(oTarget) + 11;
if (GetRacialType(oTarget) == RACIAL_TYPE_SKULK && 20 > nTarget) nTarget = 20;
if(nTarget > nCasterLevel + d20())
{
FloatingTextStringOnCreature(GetName(oTarget) + " has Nondetection active.", oPC, FALSE);
return;
}
}
if(GetHasSpellEffect(POWER_ESCAPE_DETECTION, oTarget))
{
// Caster level check or the Divination fails.
// Max of 10
if(max(10, GetManifesterLevel(oTarget)) + 13 > nCasterLevel + d20())
{
FloatingTextStringOnCreature(GetName(oTarget) + " has Escape Detection active.", oPC, FALSE);
return;
}
}
if(GetHasSpellEffect(POWER_DETECT_REMOTE_VIEWING, oTarget))
{
// Caster level check for the target to learn where the caster is
if(GetManifesterLevel(oTarget) + d20() >= nCasterLevel + d20())
{
FloatingTextStringOnCreature(GetName(oPC) + " is viewing you from " + GetName(GetArea(oPC)), oTarget, FALSE);
}
}
}
// Discern Location skips all of this
if(nSpell == SPELL_DISCERN_LOCATION)
{
DiscernLocation(oPC, oTarget);
return;
}
// So do the Locate Twins
if(nSpell == SPELL_LOCATE_CREATURE || nSpell == SPELL_LOCATE_OBJECT || nSpell == MYST_TRAIL_OF_HAZE)
{
LocateCreatureOrObject(oPC, oTarget);
return;
}
if(nSpell != SPELL_CLAIRAUDIENCE_AND_CLAIRVOYANCE && nSpell != POWER_CLAIRTANGENT_HAND && nSpell != SPELL_PNP_SCRY_FAMILIAR
&& nSpell != POWER_CLAIRVOYANT_SENSE && nSpell != TRUE_SEE_THE_NAMED && oPC != oTarget) // No save if you target yourself.
{
//Make SR Check
if(PRCDoResistSpell(oPC, oTarget, nCasterLevel))
{
FloatingTextStringOnCreature(GetName(oTarget) + " made Spell Resistance check vs Scrying", oPC, FALSE);
DoScryEnd(oPC, oCopy);
return;
}
//Save
if(PRCMySavingThrow(SAVING_THROW_WILL, oTarget, nDC, SAVING_THROW_TYPE_MIND_SPELLS))
{
FloatingTextStringOnCreature(GetName(oTarget) + " saved vs Scrying", oPC, FALSE);
DoScryEnd(oPC, oCopy);
return;
}
}
if(DEBUG) DoDebug("prc_inc_scry running.\n"
+ "oPC = '" + GetName(oPC) + "' - '" + GetTag(oPC) + "' - " + ObjectToString(oPC)
+ "Copy exists: " + DebugBool2String(GetIsObjectValid(oCopy))
);
location lTarget = GetLocation(oTarget);
if (oTarget == oPC || !GetIsObjectValid(oTarget)) // Some spells just target ground for this
lTarget = PRCGetSpellTargetLocation();
// Create the copy
oCopy = CopyObject(oPC, lTarget, OBJECT_INVALID, GetName(oPC) + "_" + COPY_LOCAL_NAME);
CleanCopy(oCopy);
// Attempted Fix to the Copy get's murdered problem.
int nMaxHenchmen = GetMaxHenchmen();
SetMaxHenchmen(99);
AddHenchman(oPC, oCopy);
SetMaxHenchmen(nMaxHenchmen);
SetIsTemporaryFriend(oPC, oCopy, FALSE);
// Set the copy to be undestroyable, so that it won't vanish to the ether
// along with the PC's items.
AssignCommand(oCopy, SetIsDestroyable(FALSE, FALSE, FALSE));
// Make the copy immobile and minimize the AI on it
ApplyEffectToObject(DURATION_TYPE_PERMANENT, ExtraordinaryEffect(EffectCutsceneImmobilize()), oCopy);
SetAILevel(oCopy, AI_LEVEL_VERY_LOW);
// Store a referece to the copy on the PC
SetLocalObject(oPC, COPY_LOCAL_NAME, oCopy);
//Set Immortal flag on the PC or if they were already immortal,
//leave a note about it on them.
if(GetImmortal(oPC))
{
if(DEBUG) DoDebug("prc_inc_scry: The PC was already immortal");
SetLocalInt(oPC, ALREADY_IMMORTAL_LOCAL_NAME, TRUE);
}
else
{
if(DEBUG) DoDebug("prc_inc_scry: Setting PC immortal");
SetImmortal(oPC, TRUE);
DeleteLocalInt(oPC, ALREADY_IMMORTAL_LOCAL_NAME); // Paranoia
}
// Do VFX on PC and copy
SPApplyEffectToObject(DURATION_TYPE_INSTANT, eLight, oCopy);
SPApplyEffectToObject(DURATION_TYPE_INSTANT, eLight, oPC);
// Do the switching around
DoScryBegin(oPC, oCopy);
//Set up duration marker for ending effect
DelayCommand(fDur, SetLocalInt(oPC, "SCRY_EXPIRED", 1));
}
// Moves the PC's items to the copy and switches their locations around
void DoScryBegin(object oPC, object oCopy)
{
if(DEBUG) DoDebug("prc_inc_scry: DoScryBegin():\n"
+ "oPC = '" + GetName(oPC) + "'\n"
+ "oCopy = '" + GetName(oCopy) + "'"
);
// Make sure both objects are valid
if(!GetIsObjectValid(oCopy) || !GetIsObjectValid(oPC)){
if(DEBUG) DoDebug("DoScryBegin called, but one of the parameters wasn't a valid object. Object status:" +
"\nPC - " + (GetIsObjectValid(oPC) ? "valid":"invalid") +
"\nCopy - " + (GetIsObjectValid(oCopy) ? "valid":"invalid")
);
// Some cleanup before aborting
if(!GetLocalInt(oPC, ALREADY_IMMORTAL_LOCAL_NAME))
{
SetImmortal(oPC, FALSE);
DeleteLocalInt(oPC, ALREADY_IMMORTAL_LOCAL_NAME);
}
MyDestroyObject(oCopy);
DeleteLocalInt(oPC, "Scry_Active");
RemoveScryEffects(oPC);
return;
}
// Set a local on the PC telling that it's a scry. This is used
// to keep the PC from picking up or losing objects.
// Also stops it from casting spells
SetLocalInt(oPC, "Scry_Active", TRUE);
// Start a pseudo-hb to monitor the status of both PC and copy
DelayCommand(SCRY_HB_DELAY, ScryMonitor(oPC, oCopy));
// Add eventhooks
if(DEBUG) DoDebug("AddEventScripts");
AddEventScript(oPC, EVENT_ONPLAYEREQUIPITEM, "prc_scry_event", TRUE, FALSE); // OnEquip
AddEventScript(oPC, EVENT_ONACQUIREITEM, "prc_scry_event", TRUE, FALSE); // OnAcquire
AddEventScript(oPC, EVENT_ONPLAYERREST_STARTED, "prc_scry_event", FALSE, FALSE); // OnRest
AddEventScript(oPC, EVENT_ONCLIENTENTER, "prc_scry_event", TRUE, FALSE); //OnClientEnter
// Adjust reputation so the target monster doesn't attack you
//ApplyEffectToObject(DURATION_TYPE_TEMPORARY, ExtraordinaryEffect(EffectCharmed()), oTarget, GetLocalFloat(oPC, "ScryDuration"));
// Swap the copy and PC
location lPC = GetLocation(oPC);
location lCopy = GetLocation(oCopy);
DelayCommand(1.5f,AssignCommand(oPC, JumpToLocation(lCopy)));
DelayCommand(1.5f,AssignCommand(oCopy, JumpToLocation(lPC)));
}
// Switches the PC's inventory back from the copy and returns the PC to the copy's location.
void DoScryEnd(object oPC, object oCopy)
{
if(DEBUG) DoDebug("prc_inc_scry: DoScryEnd():\n"
+ "oPC = '" + GetName(oPC) + "'\n"
+ "oCopy = '" + GetName(oCopy) + "'"
);
//effect eGlow = EffectVisualEffect(VFX_DUR_ETHEREAL_VISAGE, FALSE);
effect eLight = EffectVisualEffect(VFX_IMP_HEALING_X , FALSE);
// Remove Immortality from the PC if necessary
if(!GetLocalInt(oPC, ALREADY_IMMORTAL_LOCAL_NAME))
SetImmortal(oPC, FALSE);
// Remove the VFX and the attack penalty from all spells.
PRCRemoveSpellEffects(SPELL_SCRY , oPC, oPC);
PRCRemoveSpellEffects(SPELL_GREATER_SCRYING , oPC, oPC);
PRCRemoveSpellEffects(SPELL_DISCERN_LOCATION , oPC, oPC);
PRCRemoveSpellEffects(SPELL_LOCATE_CREATURE , oPC, oPC);
PRCRemoveSpellEffects(SPELL_LOCATE_OBJECT , oPC, oPC);
PRCRemoveSpellEffects(SPELL_ARCANE_EYE , oPC, oPC);
PRCRemoveSpellEffects(MYST_BEND_PERSPECTIVE , oPC, oPC);
PRCRemoveSpellEffects(MYST_FAR_SIGHT , oPC, oPC);
PRCRemoveSpellEffects(MYST_EPHEMERAL_IMAGE , oPC, oPC);
PRCRemoveSpellEffects(SPELL_SHADOWDOUBLE , oPC, oPC);
PRCRemoveSpellEffects(SPELL_OBSCURE_OBJECT , oPC, oPC);
PRCRemoveSpellEffects(SPELL_SEQUESTER , oPC, oPC);
PRCRemoveSpellEffects(SPELL_PNP_SCRY_FAMILIAR, oPC, oPC);
PRCRemoveSpellEffects(SPELL_CLAIRAUDIENCE_AND_CLAIRVOYANCE, oPC, oPC);
// Remove the local signifying that the PC is a projection
DeleteLocalInt(oPC, "Scry_Active");
// Remove the local signifying projection being terminated by an external cause
DeleteLocalInt(oPC, "Scry_Abort");
// Remove the heartbeat HP tracking local
DeleteLocalInt(oPC, "Scry_HB_HP");
// Delete all of the marker ints for the spell
DeleteLocalInt(oPC, "ScryCasterLevel");
DeleteLocalInt(oPC, "ScrySpellId");
DeleteLocalInt(oPC, "ScrySpellDC");
DeleteLocalFloat(oPC, "ScryDuration");
// Remove weapons nerfing
RemoveScryEffects(oPC);
// Remove eventhooks
RemoveEventScript(oPC, EVENT_ONPLAYEREQUIPITEM, "prc_scry_event", TRUE, FALSE); // OnEquip
RemoveEventScript(oPC, EVENT_ONACQUIREITEM, "prc_scry_event", TRUE, FALSE); // OnAcquire
RemoveEventScript(oPC, EVENT_ONPLAYERREST_STARTED, "prc_scry_event", FALSE, FALSE); // OnRest
RemoveEventScript(oPC, EVENT_ONCLIENTENTER, "prc_scry_event", TRUE, FALSE); //OnClientEnter
// Move PC and inventory
location lCopy = GetLocation(oCopy);
DelayCommand(1.5f, AssignCommand(oPC, JumpToLocation(lCopy)));
// Set the PC's hitpoints to be whatever the copy has
int nOffset = GetCurrentHitPoints(oCopy) - GetCurrentHitPoints(oPC);
if(nOffset > 0)
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectHeal(nOffset), oPC);
else if (nOffset < 0)
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(-nOffset, DAMAGE_TYPE_MAGICAL, DAMAGE_POWER_ENERGY), oPC);
// Schedule deletion of the copy
DelayCommand(0.3f, MyDestroyObject(oCopy));
//Delete the object reference
DeleteLocalObject(oPC, COPY_LOCAL_NAME);
// VFX
ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, eLight, lCopy, 3.0);
DestroyObject(oCopy);
//Remove duration marker
DeleteLocalInt(oPC, "SCRY_EXPIRED");
}
//Runs tests to see if the projection effect can still continue.
//If the PC has reached 1 HP, end projection normally.
//If the copy is dead, end projection and kill the PC.
void ScryMonitor(object oPC, object oCopy)
{
if(DEBUG) DoDebug("prc_inc_scry: ScryMonitor():\n"
+ "oPC = '" + GetName(oPC) + "'\n"
+ "oCopy = '" + GetName(oCopy) + "'"
);
// Abort if the projection is no longer marked as being active
if(!GetLocalInt(oPC, "Scry_Active"))
return;
// Some paranoia in case something interfered and either PC or copy has been destroyed
if(!(GetIsObjectValid(oPC) && GetIsObjectValid(oCopy))){
WriteTimestampedLogEntry("Baelnorn Projection hearbeat aborting due to an invalid object. Object status:" +
"\nPC - " + (GetIsObjectValid(oPC) ? "valid":"invalid") +
"\nCopy - " + (GetIsObjectValid(oCopy) ? "valid":"invalid"));
return;
}
// Start the actual work by checking the copy's status. The death thing should take priority
if(GetIsDead(oCopy))
{
if (DEBUG) DoDebug("prc_inc_scry: Copy is dead, killing PC");
DoScryEnd(oPC, oCopy);
effect eKill = EffectDamage(9999, DAMAGE_TYPE_MAGICAL, DAMAGE_POWER_ENERGY);
DelayCommand(3.0, ApplyEffectToObject(DURATION_TYPE_INSTANT, eKill, oPC));
}
else
{
// Check if the "projection" has been destroyed or if some other event has caused the projection to end
if(GetLocalInt(oPC, "Scry_Abort"))
{
if(DEBUG) DoDebug("prc_inc_scry: ScryMonitor(): The Projection has been terminated, ending projection");
DoScryEnd(oPC, oCopy);
}
else
{
// This makes sure you are invisible.
//AssignCommand(oPC, ClearAllActions(TRUE));
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, ExtraordinaryEffect(EffectEthereal()), oPC, SCRY_HB_DELAY + 0.3);
DelayCommand(SCRY_HB_DELAY, ScryMonitor(oPC, oCopy));
}
//If duration expired, end effect
if(GetLocalInt(oPC, "SCRY_EXPIRED"))
{
DoScryEnd(oPC, oCopy);
}
// End due to being in combat, except when ephemeral image
if(GetIsInCombat(oPC) && GetLocalInt(oPC, "ScrySpellId") != MYST_EPHEMERAL_IMAGE)
{
DoScryEnd(oPC, oCopy);
if(DEBUG) DoDebug("prc_inc_scry: ScryMonitor(): Scryer in combat, ending projection");
AssignCommand(oPC, ClearAllActions(TRUE));
}
// In PnP, once you lose line of effect, the spell ends
float fDistance = FeetToMeters(100.0 + GetLocalInt(oPC, "ScryCasterLevel") * 10.0);
if (GetLocalInt(oPC, "ScrySpellId") == MYST_EPHEMERAL_IMAGE && GetDistanceBetween(oPC, oCopy) > fDistance)
{
DoScryEnd(oPC, oCopy);
if(DEBUG) DoDebug("prc_inc_scry: ScryMonitor(): Ephemeral Image distance exceeded, ending projection");
AssignCommand(oPC, ClearAllActions(TRUE));
}
}
}
//Undoes changes made in ApplyScryEffects().
void RemoveScryEffects(object oPC)
{
if(DEBUG) DoDebug("prc_inc_scry: RemoveScryEffects():\n"
+ "oPC = '" + GetName(oPC) + "'"
);
effect eCheck = GetFirstEffect(oPC);
while(GetIsEffectValid(eCheck)){
if(GetEffectSpellId(eCheck) == GetLocalInt(oPC, "ScrySpellId"))
{
RemoveEffect(oPC, eCheck);
}
eCheck = GetNextEffect(oPC);
}
// Remove the no-damage property from all weapons it was added to
int i;
object oWeapon;
for(i = 0; i < array_get_size(oPC, "Scry_Nerfed"); i++)
{
oWeapon = array_get_object(oPC, "Scry_Nerfed", i);
IPRemoveMatchingItemProperties(oWeapon, ITEM_PROPERTY_NO_DAMAGE, DURATION_TYPE_PERMANENT);
}
array_delete(oPC, "Scry_Nerfed");
}
int GetIsScrying(object oPC)
{
return GetLocalInt(oPC, "Scry_Active");
}
void DiscernLocation(object oPC, object oTarget)
{
// Tells the name of the area the target is in
// Yes, this is a little crappy for an 8th level spell.
FloatingTextStringOnCreature(GetName(oTarget) + " is in " + GetName(GetArea(oTarget)), oPC, FALSE);
// Delete all of the marker ints for the spell
DeleteLocalInt(oPC, "ScryCasterLevel");
DeleteLocalInt(oPC, "ScrySpellId");
DeleteLocalInt(oPC, "ScrySpellDC");
DeleteLocalFloat(oPC, "ScryDuration");
}
void LocateCreatureOrObject(object oPC, object oTarget)
{
location lPC = GetLocation(oPC);
location lTarget = GetLocation(oTarget);
// Cause the caller to face the target
SetFacingPoint(GetPosition(oTarget));
// Now spit out the distance
float fDist = GetDistanceBetweenLocations(lPC, lTarget);
FloatingTextStringOnCreature(GetName(oTarget) + " is " + FloatToString(MetersToFeet(fDist)) + " feet away from you.", oPC, FALSE);
// Delete all of the marker ints for the spell
DeleteLocalInt(oPC, "ScryCasterLevel");
DeleteLocalInt(oPC, "ScrySpellId");
DeleteLocalInt(oPC, "ScrySpellDC");
DeleteLocalFloat(oPC, "ScryDuration");
}
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);
}