// HCR v3.2.0 - Small change to fix double XP message.
//::////////////////////////////////////////////////////////////////////////////
//:: FileName:  HC_NPCCorpse
//::////////////////////////////////////////////////////////////////////////////
/*
     By Keron Blackfeld on 07/13/2002. E-Mail Questions and Comments to:
    keron@broadswordgaming.com or catch me in Bioware's NWN Community -
    Builder's NWN Scripting Forum.

    updated 07/27/2002 -
    updated 12/29/2002 - by Ragnar69 - Use GetResRef() and safe plot items.
    updated 01/03/2003 - by   ???    - Included toggle nDropOnlyDroppable.
*/
//::////////////////////////////////////////////////////////////////////////////
#include "HC_Inc_NPCCorpse"
//::////////////////////////////////////////////////////////////////////////////
void main()
{
    object oDeadNPC = OBJECT_SELF;
    string sBaseTag = GetTag(oDeadNPC);

    // Bypass if Tagged as a no corpse, has a local set, used by ATS
    // or used by CNR.
    if (GetLocalInt(oDeadNPC, "NORMALCORPSE") ||
        FindSubString(sBaseTag, "NC_") > -1 ||
        GetStringLeft(sBaseTag, 4) == "ATS_" ||
        GetStringLeft(sBaseTag, 4) == "cnra")
        return;

    // Bypass the droppable flag for Bioware creatures (selected as the tag
    // beginning with "NW_").
    if (GetStringLeft(sBaseTag, 3) == "NW_" && nDropBWitems)
        nDropOnlyDroppable = FALSE;
    else
        nDropOnlyDroppable = nDropDroppableOnly;

    // If False, do nothing.
    if (nUseLootable == TRUE)
    {
        vector vHere        = GetPosition(oDeadNPC);
        vector vUnder       = Vector(vHere.x, vHere.y, vHere.z - 0.1);
        location lCorpseLoc = Location(GetArea(oDeadNPC), vUnder, 0.0);
        location lBloodLoc  = GetLocation(oDeadNPC);

        // Do 'spawned corpse' if desired.
        if (GetStringLeft(sBaseTag, 4) == "Dead")
        {
            if (nOverrideForPlacedCorpses)
            {
                nKeepEmpties = TRUE;// Set 'Spawned Dead' corpses to Keep Empties.
                nCorpseFade = 0;// Disable Corpse Fade for 'Spawned Dead' corpses.
            }
        }

        // Protect our corpse from decaying.
        SetIsDestroyable(FALSE);

        // Spawn some blood for effect. If nUseBlood is TRUE and if our NPC is
        // not an Undead, Construct or Elemental.
        object oCorpseBlood = OBJECT_INVALID;
        int nRace = GetRacialType(oDeadNPC);
        if (nUseBlood == TRUE &&
            nRace != RACIAL_TYPE_CONSTRUCT &&
            nRace != RACIAL_TYPE_ELEMENTAL &&
            nRace != RACIAL_TYPE_UNDEAD)
            oCorpseBlood = CreateObject(OBJECT_TYPE_PLACEABLE, "plc_bloodstain", lBloodLoc);

        // Spawn the lootable object and set the locals.
        object oLootCorpse = CreateObject(OBJECT_TYPE_PLACEABLE, "invis_corpse_obj", lCorpseLoc);
        if (GetIsObjectValid(oLootCorpse))
        {
            // Set the pointers for the lootable corpse.
            SetLocalObject(oLootCorpse, "oHostBody", oDeadNPC);
            SetLocalObject(oLootCorpse, "oBloodSpot", oCorpseBlood);
            SetLocalInt(oLootCorpse, "KeepEmptyCorpse", nKeepEmpties);

            // Transfer Gold.
            int nAmtGold = GetGold(oDeadNPC);
            if (nAmtGold > 0)
            {
                object oGold = CreateItemOnObject("nw_it_gold001", oLootCorpse, nAmtGold);
                if (oGold != OBJECT_INVALID)
                    AssignCommand(oLootCorpse, TakeGoldFromCreature(nAmtGold, oDeadNPC, TRUE));
            }

            // Transfer Weapons/Shield.
            if (nDropWeapons == 1)
            {
                // Drop Weapons/Shield on the ground.
                DropLeftWeapon(oDeadNPC);
                object oCLWpn = GetLocalObject(oDeadNPC, "oLeftWpn");
                SetLocalObject(oLootCorpse, "oLeftWpn", oCLWpn);
                DropRightWeapon(oDeadNPC);
                object oCRWpn = GetLocalObject(oDeadNPC, "oRightWpn");
                SetLocalObject(oLootCorpse, "oRightWpn", oCRWpn);
            }
            else if (nDropWeapons == 2)
            {
                // Move Weapons/Shield to the corpse.
                DropEquipment(oDeadNPC, oLootCorpse, GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oDeadNPC));
                DropEquipment(oDeadNPC, oLootCorpse, GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oDeadNPC));
            }

            // Transfer Armour.
            if (nDropArmour)
            {
                object oArmour = GetItemInSlot(INVENTORY_SLOT_CHEST, oDeadNPC);
                if (GetDroppableFlag(oArmour) ||
                   !nDestroyNoDrop ||
                   !GetIsItemNoDrop(oArmour))
                {
                    if (!nDropOnlyDroppable || GetDroppableFlag(oArmour))
                    {
                        object oLootArmour = CopyItem(oArmour, oLootCorpse, TRUE);
                        SetLocalObject(oLootCorpse, "oOrigArmour", oArmour);
                        SetLocalObject(oLootCorpse, "oLootArmour", oLootArmour);

                        if (GetIsObjectValid(oArmour))
                            SetLocalInt(oDeadNPC, "iLoot", 1);
                    }
                }
            }

            // Transfer Equipment.
            object oItem;
            object oNew;
            if (nDropEquip)
            {
                int nSlot;
                for (nSlot = 0; nSlot < 14; nSlot++)
                {
                    if (nSlot != INVENTORY_SLOT_CHEST &&
                        nSlot != INVENTORY_SLOT_LEFTHAND &&
                        nSlot != INVENTORY_SLOT_RIGHTHAND)
                    {
                        oItem = GetItemInSlot(nSlot, oDeadNPC);
                        if (oItem != OBJECT_INVALID)
                            DropEquipment(oDeadNPC, oLootCorpse, oItem);
                    }
                }
            }

            // Transfer Inventory.
            oItem = GetFirstItemInInventory(oDeadNPC);
            while (GetIsObjectValid(oItem))
            {
                DropEquipment(oDeadNPC, oLootCorpse, oItem);
                oItem = GetNextItemInInventory(oDeadNPC);
            }

            // Do Corpse Fade out after specified delay. (Unless flagged 0)
            if (nCorpseFade > 0)
            {
                float fDelay = IntToFloat(nCorpseFade);
                ClearAllActions(TRUE);
                ActionWait(fDelay);
                DelayCommand(fDelay, ClearInventory(oLootCorpse));
                DelayCommand(fDelay, DestroyObject(oCorpseBlood));
                DelayCommand(fDelay, DestroyObject(oLootCorpse));
                DelayCommand(fDelay, ClearInventory(oDeadNPC));
                DelayCommand(fDelay, DestroyWeapons(oDeadNPC));
                DelayCommand(fDelay, SetIsDestroyable(TRUE));
                DelayCommand(fDelay + 0.1, DeleteLocalInt(oDeadNPC, "iLoot"));
                DelayCommand(fDelay + 0.1, DeleteLocalInt(oDeadNPC, "KeepEmptyCorpse"));
                DelayCommand(fDelay + 0.1, DeleteLocalObject(oDeadNPC, "oHostBody"));
                DelayCommand(fDelay + 0.1, DeleteLocalObject(oDeadNPC, "oBloodSpot"));
                DelayCommand(fDelay + 0.1, DeleteLocalObject(oDeadNPC, "oOrigArmour"));
                DelayCommand(fDelay + 0.1, DeleteLocalObject(oDeadNPC, "oLootArmour"));
                DelayCommand(fDelay + 0.1, DeleteLocalObject(oDeadNPC, "oRightWpn"));
                DelayCommand(fDelay + 0.1, DeleteLocalObject(oDeadNPC, "oLeftWpn"));
                DelayCommand(fDelay + 0.2, DestroyObject(oDeadNPC));
            }
        }

        //
        if (!GetLocalInt(oDeadNPC, "iLoot") && !nKeepEmpties)
        {
            SetIsDestroyable(TRUE);
            DestroyObject(oDeadNPC);
            DestroyObject(oLootCorpse);
            DestroyObject(oCorpseBlood);
        }
    }

    DelayCommand(4.0, DeleteLocalInt(oDeadNPC, "DropDroppable"));
}
//::////////////////////////////////////////////////////////////////////////////
