PWE_PRC8/_module/nss/el_loot_include.nss
Jaysyn904 ee1dc35889 Initial Commit
Initial Commit
2025-04-03 10:29:41 -04:00

764 lines
24 KiB
Plaintext

//::///////////////////////////////////////////////
//:: el_loot_include
//:: main library for Looting Script ver 5.4
//:: By: Emmanuel Lusinchi (Sentur Signe)
//:: Last modified: 11/21/2002
//
//:: New from 5.2
//:: a) Corpse placeable is deleted after a random time
//:: (between 1 and 3 seconds) if the corresponding creature possessed
//:: no lootable items
//:: b) Corpse moving due to the 'animal empathy ceasing' solved (I think)
//:: c) Corrected one bug in which destroying a corpse placeable would not cause
//:: the real creature to decay if EL_CORPSE_CLEANING_DELAY was set to 0.0f
//::
//:: New from 5.3
//:: a) Solved problem with double-click destroying the corpse placeable
//:: b) Took some steps to prevent endless looting animation. Animation *will*
//:: stop when closing the placeable. Note that if you open & close a
//:: placeable (any placeable with an associated onopen script) fast enough
//:: and long enough, you *will* eventually confuse NWN on the state of the
//:: placeable (ie: it won't know whether it's open or closed)
//::
//:://////////////////////////////////////////////
int bUSEDELAYINLOOTING = FALSE;
float fDELAYCHEST = 6.0f;
float fDELAYITEMS = 2.0f;
int GetDropeableFlag(object oInv) {return GetDroppableFlag(oInv);}
// el_SetCorpseCondition(int EL_FLAG_NO_CHEST_LOOT, int EL_FLAG_2X_CHEST_LOOT,float EL_CORPSE_TIMEOUT_NOLOOT,float EL_CORPSE_TIMEOUT_IFLOOT,float EL_CORPSE_CLEANING_DELAY, EL_ONDESTRUCTION_MESSY_EFFECT)
//
// - EL_FLAG_NO_CHEST_LOOT: if set to TRUE, the chest item can never be looted
// - EL_FLAG_2X_CHEST_LOOT: obsolete
// - EL_CORPSE_TIMEOUT_IFLOOT, EL_CORPSE_TIMEOUT_NOLOOT: delay for decay to happen
// - EL_CORPSE_CLEANING_DELAY: setting to 0.0f disable clean-up. Clean-up also only
// works if some form of decay is happening.
// - EL_ONDESTRUCTION_MESSY_EFFECT : A value of -1 will use the default blood&bone animation, 0 will disable the animation, and any VFX_ instant animation constant can be used (eg: VFX_COM_CHUNK_GREEN_MEDIUM )
void el_SetCorpseCondition(int EL_FLAG_NO_CHEST_LOOT, int EL_FLAG_2X_CHEST_LOOT,float EL_CORPSE_TIMEOUT_NOLOOT,float EL_CORPSE_TIMEOUT_IFLOOT,float EL_CORPSE_CLEANING_DELAY, int EL_ONDESTRUCTION_MESSY_EFFECT);
void destroyObjectIfNotPlot(object oItem);
int getNextSlot(int iSlot);
void lootInventory(object oOwner, object oLooter, object oCleaner);
void lootSlot(object oOwner, object oLooter, object oCleaner, int iSlot);
void lootChest(object oOwner, object oLooter, object oCleaner, int iCounter);
void lootOnOpen();
void lootOnClose();
void lootCleanUp();
void lootCleanUpPart2();
void lootTakeNote(object oOwner);
void lootGold(object oOwner, object oPlaceable, object oCleaner);
void lootQuickly();
void lootQuicklyOnClose();
int lootIsEmpty(object oOwner);
void el_LootMobOnUserDef();
void el_LootPlaceableOnOpen(int iLootedByPC);
void el_LootPlaceableOnClose();
void el_LootPlaceableOnUserDef();
void el_LootPlaceableOnDeath();
///////////////////////////////////////////////
///////////////////////////////////////////////
void el_SetCorpseCondition(int EL_FLAG_NO_CHEST_LOOT, int EL_FLAG_2X_CHEST_LOOT,float EL_CORPSE_TIMEOUT_NOLOOT,float EL_CORPSE_TIMEOUT_IFLOOT,float EL_CORPSE_CLEANING_DELAY, int EL_ONDESTRUCTION_MESSY_EFFECT)
{
SetIsDestroyable(FALSE, TRUE, FALSE);
SetLocalInt(OBJECT_SELF, "EL_FLAG_LEAVE_CORPSE", TRUE);
SetLocalInt(OBJECT_SELF, "EL_FLAG_NO_CHEST_LOOT", EL_FLAG_NO_CHEST_LOOT);
SetLocalInt(OBJECT_SELF, "EL_FLAG_2X_CHEST_LOOT", EL_FLAG_2X_CHEST_LOOT);
// The Chest item is where clothes are located for player-like creature
// If you set "EL_FLAG_NO_CHEST_LOOT" to:
// TRUE = will not loot the chest area (Clothes will stay on!)
// FALSE = will loot the chest area but if the chest item Dropeable flag is not set,
// the item will be removed from the mob but NOT given to the players (ie: it will
// be destroyed).
// If the Dropeable property is set on the item and EL_FLAG_NO_CHEST_LOOT is TRUE,
// the chest item WILL be available upon destruction of the corpse, which is the normal
// expected behavior.
// If EL_FLAG_2X_CHEST_LOOT is TRUE and EL_FLAG_NO_CHEST_LOOT is FALSE, first looting
// of the corpse will remove everything except the chest item and a *second* looting will
// remove the chest item.
// In NO CASE, flag or no flag, tag or not tag, will players have access to an item
// if the 'Dropeable' property wasn't checked on the item itself. So, the use of the
// Corpse Lootable feature is always 100% safe regardless
// of EL_FLAG_NO_CHEST_LOOT and EL_FLAG_2X_CHEST_LOOT
// EL_CORPSE_CLEANING_DELAY is the time before the dead creature's objects
// get cleaned-up and destroyed.
// Only those objects that are close enough to the location of death & not
// in a player's inventory will be cleaned out.
SetLocalFloat(OBJECT_SELF, "EL_CORPSE_TIMEOUT_IFLOOT", EL_CORPSE_TIMEOUT_IFLOOT);
SetLocalFloat(OBJECT_SELF, "EL_CORPSE_TIMEOUT_NOLOOT", EL_CORPSE_TIMEOUT_NOLOOT);
if ( ( EL_CORPSE_TIMEOUT_IFLOOT == 0.0f) && ( EL_CORPSE_TIMEOUT_NOLOOT == 0.0f ) )
SetLocalFloat(OBJECT_SELF, "EL_CORPSE_CLEANING_DELAY", 0.0f);
else
SetLocalFloat(OBJECT_SELF, "EL_CORPSE_CLEANING_DELAY", EL_CORPSE_CLEANING_DELAY);
if (EL_ONDESTRUCTION_MESSY_EFFECT != 0)
{
SetLocalInt(OBJECT_SELF, "EL_FLAG_MESSY_DEATH",TRUE);
if (EL_ONDESTRUCTION_MESSY_EFFECT == -1)
{
SetLocalInt(OBJECT_SELF, "EL_ONDESTRUCTION_MESSY_EFFECT",VFX_COM_CHUNK_RED_SMALL);
}
else
{
SetLocalInt(OBJECT_SELF, "EL_ONDESTRUCTION_MESSY_EFFECT",EL_ONDESTRUCTION_MESSY_EFFECT);
}
}
}
void el_LootMobOnUserDef()
{
int nUser = GetUserDefinedEventNumber();
// ON DEATH
if ( nUser == 1007 )
{
ActionPlayAnimation(ANIMATION_FIREFORGET_HEAD_TURN_LEFT, 1.0f);
vector vHere = GetPosition(OBJECT_SELF);
vector vUnder = Vector(vHere.x, vHere.y,vHere.z-0.1f);
location lUnder = Location(GetArea(OBJECT_SELF), vUnder, 0.0f);
object oPlaceable = CreateObject(OBJECT_TYPE_PLACEABLE, "el_corpsetoloot", lUnder, FALSE);
object oCleaner = CreateObject(OBJECT_TYPE_PLACEABLE, "el_cleaner", lUnder, FALSE);
SetLocalObject(oPlaceable, "oOwner", OBJECT_SELF);
SetLocalObject(oCleaner, "oOwner", OBJECT_SELF);
SetLocalObject(oPlaceable, "oCleaner", oCleaner);
SetLocalObject(oCleaner, "oPlaceable", oPlaceable);
DelayCommand(1.0f+d20()*0.1f, SignalEvent(oCleaner, EventUserDefined(2003))); // Check if inventory is empty
float fDelayNoLoot = GetLocalFloat(OBJECT_SELF, "EL_CORPSE_TIMEOUT_NOLOOT");
if (fDelayNoLoot != 0.0f)
DelayCommand(fDelayNoLoot, SignalEvent(oCleaner, EventUserDefined(2001)));
// remove sleep resistance...
object oTemp;
oTemp = GetItemInSlot(INVENTORY_SLOT_CARMOUR, OBJECT_SELF);
SetPlotFlag(oTemp, FALSE);
DestroyObject(oTemp);
oTemp = GetItemInSlot(INVENTORY_SLOT_CWEAPON_B, OBJECT_SELF);
SetPlotFlag(oTemp, FALSE);
DestroyObject(oTemp);
oTemp = GetItemInSlot(INVENTORY_SLOT_CWEAPON_L, OBJECT_SELF);
SetPlotFlag(oTemp, FALSE);
DestroyObject(oTemp);
oTemp = GetItemInSlot(INVENTORY_SLOT_CWEAPON_R, OBJECT_SELF);
SetPlotFlag(oTemp, FALSE);
DestroyObject(oTemp);
ApplyEffectToObject(DURATION_TYPE_INSTANT, SupernaturalEffect(EffectDispelMagicAll(20)),OBJECT_SELF);
ApplyEffectToObject(DURATION_TYPE_INSTANT, ExtraordinaryEffect(EffectDispelMagicAll(20)),OBJECT_SELF);
}
}
void el_LootPlaceableOnOpen(int iLootedByPC)
{
if (bUSEDELAYINLOOTING) lootOnOpen();
else lootQuickly();
return;
}
void el_LootPlaceableOnClose()
{
if (bUSEDELAYINLOOTING) lootOnClose();
else lootQuicklyOnClose();
return;
}
void el_LootPlaceableOnDeath()
{
object oCleaner = GetLocalObject(OBJECT_SELF,"oCleaner");
SetLocalInt(oCleaner, "bForceDecay", TRUE);
object oOwner = GetLocalObject(OBJECT_SELF,"oOwner");
if ( GetLocalInt(oOwner, "EL_FLAG_MESSY_DEATH") )
ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectVisualEffect(GetLocalInt(oOwner, "EL_ONDESTRUCTION_MESSY_EFFECT")),oOwner);
DestroyObject(GetLocalObject(oCleaner, "oWait"));
SignalEvent(oCleaner, EventUserDefined(2001));
return;
}
void el_LootPlaceableOnUserDef()
{
int nUser = GetUserDefinedEventNumber();
// Decay if never touched. Part I
if ( ( nUser == 2001 ) || ( nUser == 2002) )
{
lootCleanUp();
return;
}
if (nUser == 2003)
{
object oOwner = GetLocalObject(OBJECT_SELF,"oOwner");
// New in ver 5.3 ///////////// !!!!!!!!!!!!
// We put it here rather than on the owner's ondeath to prevent
// spurious 'coup de grace' messages :)
object oTemp;
oTemp = GetItemInSlot(INVENTORY_SLOT_CARMOUR, oOwner);
SetPlotFlag(oTemp, FALSE);
DestroyObject(oTemp);
oTemp = GetItemInSlot(INVENTORY_SLOT_CWEAPON_B, oOwner);
SetPlotFlag(oTemp, FALSE);
DestroyObject(oTemp);
oTemp = GetItemInSlot(INVENTORY_SLOT_CWEAPON_L, oOwner);
SetPlotFlag(oTemp, FALSE);
DestroyObject(oTemp);
oTemp = GetItemInSlot(INVENTORY_SLOT_CWEAPON_R, oOwner);
SetPlotFlag(oTemp, FALSE);
DestroyObject(oTemp);
ApplyEffectToObject(DURATION_TYPE_PERMANENT, SupernaturalEffect(EffectSleep()),oOwner);
ApplyEffectToObject(DURATION_TYPE_PERMANENT, ExtraordinaryEffect(EffectSleep()),oOwner);
if (lootIsEmpty(oOwner))
DestroyObject(GetLocalObject(OBJECT_SELF,"oPlaceable"));
return;
}
}
void destroyObjectIfNotPlot(object oItem)
{
if (!GetPlotFlag(oItem)) DestroyObject(oItem);
}
int getNextSlot(int iSlot)
{
if (iSlot == INVENTORY_SLOT_RIGHTHAND ) return INVENTORY_SLOT_LEFTHAND;
if (iSlot == INVENTORY_SLOT_LEFTHAND ) return INVENTORY_SLOT_HEAD;
if (iSlot == INVENTORY_SLOT_HEAD ) return INVENTORY_SLOT_ARMS;
if (iSlot == INVENTORY_SLOT_ARMS ) return INVENTORY_SLOT_CLOAK;
if (iSlot == INVENTORY_SLOT_CLOAK ) return INVENTORY_SLOT_RIGHTRING;
if (iSlot == INVENTORY_SLOT_RIGHTRING ) return INVENTORY_SLOT_LEFTRING;
if (iSlot == INVENTORY_SLOT_LEFTRING ) return INVENTORY_SLOT_NECK;
if (iSlot == INVENTORY_SLOT_NECK ) return INVENTORY_SLOT_BOOTS;
if (iSlot == INVENTORY_SLOT_BOOTS ) return INVENTORY_SLOT_ARROWS;
if (iSlot == INVENTORY_SLOT_ARROWS ) return INVENTORY_SLOT_BOLTS;
if (iSlot == INVENTORY_SLOT_BOLTS ) return INVENTORY_SLOT_BULLETS;
if (iSlot == INVENTORY_SLOT_BULLETS ) return INVENTORY_SLOT_BELT;
if (iSlot == INVENTORY_SLOT_BELT ) return INVENTORY_SLOT_CHEST;
return -1;
}
void lootInventory(object oOwner, object oLooter, object oCleaner)
{
if (GetLocalInt(OBJECT_SELF, "bAbortLooting")) return;
object oItem = GetFirstItemInInventory(oOwner);
int bFound = FALSE;
while (bFound == FALSE)
{
// nothing in inventory. We move on to slots.
if (oItem == OBJECT_INVALID)
{
DelayCommand(0.1f, lootSlot(oOwner, oLooter, oCleaner, INVENTORY_SLOT_RIGHTHAND));
AssignCommand(oLooter, ActionPlayAnimation(ANIMATION_LOOPING_GET_LOW, 1.0f, 1.0f));
return;
}
if (GetDropeableFlag(oItem)) bFound = TRUE;
else
{
DestroyObject(oItem);
oItem = GetNextItemInInventory(oOwner);
}
}
// setup for the loot of the next object
ActionTakeItem(oItem, oOwner);
int iIndex = GetLocalInt(oCleaner, "iIndex");
SetLocalObject(oCleaner, "oToClean_"+IntToString(iIndex), oItem);
SetLocalInt(oCleaner, "iIndex", iIndex+1);
DelayCommand(fDELAYITEMS,lootInventory(oOwner, oLooter, oCleaner));
AssignCommand(oLooter, ActionPlayAnimation(ANIMATION_LOOPING_GET_LOW, 1.0f, fDELAYITEMS));
return;
}
void lootSlot(object oOwner, object oLooter, object oCleaner, int iSlot)
{
if (GetLocalInt(OBJECT_SELF, "bAbortLooting")) return;
int iCurrentSlot = iSlot;
object oItem = GetItemInSlot(iCurrentSlot, oOwner);
int bFound = FALSE;
while (bFound == FALSE)
{
if (oItem != OBJECT_INVALID)
{
if (GetDropeableFlag(oItem))
{
bFound = TRUE;
}
else
{
if ( (iCurrentSlot != INVENTORY_SLOT_CHEST) && (iCurrentSlot != INVENTORY_SLOT_RIGHTHAND) && (iCurrentSlot !=INVENTORY_SLOT_LEFTHAND ) )
DestroyObject(oItem);
iCurrentSlot = getNextSlot(iCurrentSlot);
oItem = GetItemInSlot(iCurrentSlot, oOwner);
}
}
else
{
iCurrentSlot = getNextSlot(iCurrentSlot);
if (iCurrentSlot != -1) oItem = GetItemInSlot(iCurrentSlot, oOwner);
else
{
FloatingTextStringOnCreature("Nothing Left To Loot", oLooter, TRUE);
SetLocalInt(OBJECT_SELF, "bNothingLeftToLoot", TRUE);
return;
}
}
}
if (iCurrentSlot == INVENTORY_SLOT_CHEST)
{
if (GetLocalInt(oOwner, "EL_FLAG_NO_CHEST_LOOT")) return;
FloatingTextStringOnCreature("Looting Armor / Cloth", oLooter, TRUE);
DelayCommand(fDELAYCHEST, lootChest(oOwner, oLooter,oCleaner, 0));
if (GetItemPossessedBy(OBJECT_SELF, "LootingArmororClothPleaseWait") == OBJECT_INVALID)
{
object oWait = CreateItemOnObject("lootingarmororcl", OBJECT_SELF);
SetLocalObject(oCleaner, "oWait", oWait);
}
AssignCommand(oLooter, ActionPlayAnimation(ANIMATION_LOOPING_GET_LOW, 1.0f, fDELAYCHEST));
return;
}
else
{
ActionTakeItem(oItem, oOwner);
int iIndex = GetLocalInt(oCleaner, "iIndex");
SetLocalObject(oCleaner, "oToClean_"+IntToString(iIndex), oItem);
SetLocalInt(oCleaner, "iIndex", iIndex+1);
iCurrentSlot = getNextSlot(iCurrentSlot);
DelayCommand(fDELAYITEMS, lootSlot(oOwner, oLooter, oCleaner, iCurrentSlot));
AssignCommand(oLooter, ActionPlayAnimation(ANIMATION_LOOPING_GET_LOW, 1.0f, fDELAYITEMS));
return;
}
}
void lootChest(object oOwner, object oLooter, object oCleaner, int iCounter)
{
DestroyObject(GetLocalObject(oCleaner, "oWait"));
if (GetLocalInt(OBJECT_SELF, "bAbortLooting")) return;
object oItem = GetItemInSlot(INVENTORY_SLOT_CHEST, oOwner);
if (oItem == OBJECT_INVALID)
{
FloatingTextStringOnCreature("Nothing Left To Loot", oLooter, TRUE);
SetLocalInt(OBJECT_SELF, "bNothingLeftToLoot", TRUE);
return;
}
else
{
if (iCounter == 10) return; // some problem... we give up
ActionTakeItem(oItem, oOwner);
int iIndex = GetLocalInt(oCleaner, "iIndex");
SetLocalObject(oCleaner, "oToClean_"+IntToString(iIndex), oItem);
// take the item and check periodically that it succeeded. Yes I am a bit on the paranoid side nowadays
DelayCommand(1.0f, lootChest(oOwner, oLooter, oCleaner, iCounter+1));
return;
}
}
void lootOnOpen()
{
SetLocalInt(OBJECT_SELF, "bAbortLooting", FALSE);
if (GetLocalInt(OBJECT_SELF, "bNothingLeftToLoot")) return;
object oOwner = GetLocalObject(OBJECT_SELF,"oOwner");
object oCleaner = GetLocalObject(OBJECT_SELF,"oCleaner");
int bAlreadyUsed = GetLocalInt(OBJECT_SELF, "bAlreadyUsed");
if (bAlreadyUsed == FALSE)
{
SetLocalInt(OBJECT_SELF, "bAlreadyUsed", TRUE);
lootGold(oOwner, OBJECT_SELF, oCleaner);
float fDelayIfLoot = GetLocalFloat(oOwner, "EL_CORPSE_TIMEOUT_IFLOOT");
if (fDelayIfLoot!=0.0f)
DelayCommand(fDelayIfLoot, SignalEvent(oCleaner, EventUserDefined(2002)));
}
lootInventory(oOwner, GetLastOpenedBy(), oCleaner);
return;
}
void lootOnClose()
{
DestroyObject(GetLocalObject(GetLocalObject(OBJECT_SELF, "oCleaner"), "oWait"));
SetLocalInt(OBJECT_SELF, "bAbortLooting", TRUE);
AssignCommand(GetLastClosedBy(),ActionPlayAnimation(ANIMATION_FIREFORGET_HEAD_TURN_LEFT, 1.0f));
if (GetLocalInt(OBJECT_SELF, "bNothingLeftToLoot"))
{
object oItem = GetFirstItemInInventory();
if (oItem == OBJECT_INVALID) DestroyObject(OBJECT_SELF);
}
}
void lootCleanUp()
{
object oOwner = GetLocalObject(OBJECT_SELF,"oOwner");
object oPlaceable = GetLocalObject(OBJECT_SELF,"oPlaceable");
lootGold(oOwner, oPlaceable, OBJECT_SELF); // if never looted, we need to get the gold now
float fCleaningDelay = GetLocalFloat(oOwner, "EL_CORPSE_CLEANING_DELAY");
if ( GetLocalInt(OBJECT_SELF, "bForceDecay") == FALSE )
{
if (fCleaningDelay == 0.0f) return;
ApplyEffectToObject(DURATION_TYPE_PERMANENT, EffectVisualEffect(VFX_DUR_INVISIBILITY), oOwner);
}
lootTakeNote(oOwner);
// AssignCommand(oOwner, SetIsDestroyable(TRUE)); // done in lootTakeNote
DestroyObject(oPlaceable);
if (fCleaningDelay != 0.0f) DelayCommand (fCleaningDelay, lootCleanUpPart2());
}
void lootCleanUpPart2()
{
object oGold = GetLocalObject(OBJECT_SELF, "oGold");
SetPlotFlag(oGold, FALSE);
DestroyObject(oGold);
int iMaxIndex = GetLocalInt(OBJECT_SELF, "iIndex");
// if no item have been indexed, nothing to clean-up... just allow dead mob to decay
if (iMaxIndex == 0)
{
DestroyObject(OBJECT_SELF, 1.0f);
return;
}
object oToClean;
object oPossessor;
int iIndex = 0;
while (iIndex <= iMaxIndex)
{
oToClean = GetLocalObject(OBJECT_SELF, "oToClean_"+IntToString(iIndex));
oPossessor = GetItemPossessor(oToClean);
if ( (GetObjectType(oPossessor) != OBJECT_TYPE_CREATURE) || (GetIsDead(oPossessor) == TRUE) )
if (GetDistanceBetween(OBJECT_SELF, oToClean) < 500.0f)
{
destroyObjectIfNotPlot(oToClean);
}
iIndex++;
}
DestroyObject(OBJECT_SELF, 1.0f);
return;
}
void lootTakeNote(object oOwner)
{
int iIndex = GetLocalInt(OBJECT_SELF, "iIndex");
object oItem = GetFirstItemInInventory(oOwner);
while (oItem != OBJECT_INVALID)
{
SetLocalObject(OBJECT_SELF, "oToClean_"+IntToString(iIndex), oItem);
iIndex++;
oItem = GetNextItemInInventory(oOwner);
}
int iSlot = INVENTORY_SLOT_RIGHTHAND;
oItem = GetItemInSlot(iSlot, oOwner);
while (iSlot != -1)
{
if (oItem != OBJECT_INVALID)
{
SetLocalObject(OBJECT_SELF, "oToClean_"+IntToString(iIndex), oItem);
iIndex++;
}
iSlot = getNextSlot(iSlot);
if (iSlot != -1) oItem = GetItemInSlot(iSlot, oOwner);
}
SetLocalInt(OBJECT_SELF, "iIndex", iIndex);
AssignCommand(oOwner, SetIsDestroyable(TRUE));
}
void lootGold(object oOwner, object oPlaceable, object oCleaner)
{
int iGold = GetGold(oOwner);
if (iGold == 0) return;
TakeGoldFromCreature(iGold, oOwner, TRUE);
object oGold = CreateItemOnObject("nw_it_gold001", oPlaceable, iGold);
SetLocalObject(oCleaner, "oGold", oGold);
return;
}
void lootQuickly()
{
int bAlreadyUsed = GetLocalInt(OBJECT_SELF, "bAlreadyUsed");
if (bAlreadyUsed == TRUE) return;
object oOwner = GetLocalObject(OBJECT_SELF,"oOwner");
object oCleaner = GetLocalObject(OBJECT_SELF,"oCleaner");
object oLooter = GetLastOpenedBy();
SetLocalInt(OBJECT_SELF, "bAlreadyUsed", TRUE);
lootGold(oOwner, OBJECT_SELF, oCleaner);
float fDelayIfLoot = GetLocalFloat(oOwner, "EL_CORPSE_TIMEOUT_IFLOOT");
if (fDelayIfLoot!=0.0f)
DelayCommand(fDelayIfLoot, SignalEvent(oCleaner, EventUserDefined(2002)));
AssignCommand(oLooter, ActionPlayAnimation(ANIMATION_LOOPING_GET_LOW, 3.0f, 1.0f));
int iIndex = GetLocalInt(oCleaner, "iIndex");
object oItem = GetFirstItemInInventory(oOwner);
while (oItem != OBJECT_INVALID)
{
if ( GetDropeableFlag(oItem) )
{
SetLocalObject(oCleaner, "oToClean_"+IntToString(iIndex), oItem);
iIndex++;
ActionTakeItem(oItem, oOwner);
}
else
{
DestroyObject(oItem); // save resources and noone will notice
}
oItem = GetNextItemInInventory(oOwner);
}
int iSlot = INVENTORY_SLOT_RIGHTHAND;
oItem = GetItemInSlot(iSlot, oOwner);
while (iSlot != -1)
{
if (oItem != OBJECT_INVALID)
{
if ( GetDropeableFlag(oItem) )
{
ActionTakeItem(oItem, oOwner);
SetLocalObject(oCleaner, "oToClean_"+IntToString(iIndex), oItem);
iIndex++;
}
else
{
if ( (iSlot != INVENTORY_SLOT_CHEST) && (iSlot != INVENTORY_SLOT_RIGHTHAND) && (iSlot != INVENTORY_SLOT_LEFTHAND) ) DestroyObject(oItem); // save resources and noone will noticeINVENTORY_SLOT_RIGHTRING
}
}
iSlot = getNextSlot(iSlot);
if (iSlot != -1) oItem = GetItemInSlot(iSlot, oOwner);
}
SetLocalInt(oCleaner, "iIndex", iIndex);
// SetLocalInt(OBJECT_SELF, "bNothingLeftToLoot", TRUE);
}
void checkAgain()
{
object oOwner = GetLocalObject(OBJECT_SELF,"oOwner");
if (oOwner == OBJECT_INVALID) return;
if (lootIsEmpty(oOwner))
{
if (GetFirstItemInInventory() == OBJECT_INVALID)
{
DestroyObject(OBJECT_SELF, 1.0f);
}
}
}
void lootQuicklyOnClose()
{
// if (GetLocalInt(OBJECT_SELF, "bNothingLeftToLoot"))
// {
// object oItem = GetFirstItemInInventory();
// if (oItem == OBJECT_INVALID) DestroyObject(OBJECT_SELF);
// }
AssignCommand(GetLastClosedBy(), ActionPlayAnimation(ANIMATION_FIREFORGET_HEAD_TURN_LEFT));
if (GetFirstItemInInventory() == OBJECT_INVALID)
{
DelayCommand(10.0f, checkAgain());
}
}
// Index the loot & check if empty
int lootIsEmpty(object oOwner)
{
// ChangeToStandardFaction(oOwner, STANDARD_FACTION_COMMONER);
// int iIndex = GetLocalInt(OBJECT_SELF, "iIndex");
object oItem = GetFirstItemInInventory(oOwner);
int bEmpty = TRUE;
while (oItem != OBJECT_INVALID)
{
if (GetDropeableFlag(oItem))
{
bEmpty = FALSE;
// SetLocalObject( OBJECT_SELF, "oToClean_"+IntToString(iIndex), oItem);
// iIndex++;
}
else
{
DestroyObject(oItem);
}
oItem = GetNextItemInInventory(oOwner);
}
int iSlot = INVENTORY_SLOT_RIGHTHAND;
oItem = GetItemInSlot(iSlot, oOwner);
while (iSlot != -1)
{
if (oItem != OBJECT_INVALID)
{
if (GetDropeableFlag(oItem))
{
bEmpty = FALSE;
// SetLocalObject(OBJECT_SELF, "oToClean_"+IntToString(iIndex), oItem);
// iIndex++;
}
else
{
if ( (iSlot != INVENTORY_SLOT_CHEST) && (iSlot != INVENTORY_SLOT_RIGHTHAND) && (iSlot !=INVENTORY_SLOT_LEFTHAND ) )
DestroyObject(oItem);
}
}
iSlot = getNextSlot(iSlot);
if (iSlot != -1) oItem = GetItemInSlot(iSlot, oOwner);
}
// SetLocalInt(OBJECT_SELF, "iIndex", iIndex);
return bEmpty;
}