MMD_PRC8/_module/nss/_kb_raise_res.nss
Jaysyn904 adeff59f82 Initial commit
Initial commit.
2024-08-02 23:18:00 -04:00

313 lines
16 KiB
Plaintext

////////////////////////////////////////////////////////////////////////////////
// // //
// _kb_raise_res // VERSION 1.0 //
// // //
// Scrotok's Raise Dead/Resurrection Plugin ////////////////////////////
// by Scrotok on 18 Dec 02 //
// Thanks to Lord Niah and Bored Bistander for help on the Raise/Res idea //
// email Questions and Comments to: jnbplatte@intellisys.net //
// //
////////////////////////////////////////////////////////////////////////////////
// //
// This is an optional plugin for Scrotok's Lootable Corpses. It requires //
// modified versions of "nw_s0_raisdead" and "nw_s0_resserec" (included in //
// the ERF for this plugin). This script enables lootable corpses to be //
// brought back to life with either the Resurrection or Raise Dead spells. //
// This script can be called by lootable corpse placeables or bones. //
// //
// NEWBIES: You don't need to place this script anywhere -- it gets called //
// (using the ExecuteScript function) by another script ("_kb_plugins").
// //
// KNOWN BUG: If Raise Dead or Resurrection is cast, but the spell //
// won't work (based on racial type, or the fact that Raise Dead won't work //
// on bones), the spell or scroll is still wasted in the attempt. //
// //
////////////////////////////////////////////////////////////////////////////////
/*******************************************************************************
** Used for debugging to determine where the oEquip items are (or if the **
** items are invalid objects). **
*******************************************************************************/
void DetermineEquipOwner(object oLootCorpse)
{
int x;
string sEquip;
for (x = 1; x < 15; x++)
{
sEquip = "oEquip"+IntToString(x);
// oEquip12 & 13 == OBJECT_INVALID if nDropWeapons is TRUE
// oEquip8 & 14 are destroyed (OBJECT_INVALID) during inventory move to oHostBody (if nCopyArmour is TRUE)
if (GetIsObjectValid(GetLocalObject(oLootCorpse, sEquip)))
{
SendMessageToPC(GetFirstPC(), sEquip+" is possessed by "+GetTag(GetItemPossessor(GetLocalObject(oLootCorpse, sEquip))));
}
else
{
SendMessageToPC(GetFirstPC(), sEquip+" is an invalid object.");
}
}
}
/*******************************************************************************
** Used for debugging to ensure returned items get re-equipped by oHostBody. **
** You can also verify some items are equipped in-game by right-clicking on **
** the creature and selecting Examine; for example, you'll see "Increased **
** Strength" if the creature is wearing Gauntlets of Ogre Power. **
*******************************************************************************/
void VerifyEquipped(object oHostBody)
{
object oItem; int x;
for (x = 0; x < 14; x++)
{
oItem = GetItemInSlot(x, oHostBody);
if (GetIsObjectValid(oItem))
{
SendMessageToPC(GetFirstPC(), GetName(oItem)+" is equipped");
}
}
}
/*******************************************************************************
** This script removes ALL gold and inventory items (even non-Droppable and **
** Plot) from a newly-created oHostBody (as part of Resurrection spell). **
** Creature Slot items are not affected. **
*******************************************************************************/
void RemoveInventory(object oHostBody)
{
// Delete gold
TakeGoldFromCreature(GetGold(oHostBody), oHostBody, TRUE);
// Destroy equipped items
// 0=head, 1=chest, 2=boot, 3=arms, 4=rhand, 5=lhand, 6=cloak,
// 7=lring, 8=rring, 9=neck, 10=belt, 11=arrow, 12=bullet, 13=bolt
object oItem; int x;
for (x = 0; x < 14; x++)
{
oItem = GetItemInSlot(x, oHostBody);
if (GetIsObjectValid(oItem))
{
if (GetPlotFlag(oItem)) SetPlotFlag(oItem, FALSE);
DestroyObject(oItem);
}
}
// Delete items (including non-Droppable and Plot items)
oItem = GetFirstItemInInventory(oHostBody);
while (GetIsObjectValid(oItem))
{
if (GetPlotFlag(oItem)) SetPlotFlag(oItem, FALSE);
DestroyObject(oItem);
oItem = GetNextItemInInventory(oHostBody);
}
}
/*******************************************************************************
** Re-equip previously-equipped items on oHostBody if items were passed back **
** to oHostBody from oLootCorpse (assumes the items weren't looted from **
** oLootCorpse). This script only applies to oLootCorpse; bones don't have **
** local "oEquip" objects, so if bones are resurrected, the items don't get **
** re-equipped (NPCs with "naked" models will appear naked, which is as it **
** should be, since their corpse was too damaged to wear equipment anyway). **
*******************************************************************************/
void ReEquip(object oHostBody, object oLootCorpse)
{
if (GetItemPossessor(GetLocalObject(oLootCorpse, "oEquip1")) == oHostBody)
AssignCommand(oHostBody, ActionEquipItem(GetLocalObject(oLootCorpse, "oEquip1"), INVENTORY_SLOT_ARMS));
if (GetItemPossessor(GetLocalObject(oLootCorpse, "oEquip2")) == oHostBody)
AssignCommand(oHostBody, ActionEquipItem(GetLocalObject(oLootCorpse, "oEquip2"), INVENTORY_SLOT_ARROWS));
if (GetItemPossessor(GetLocalObject(oLootCorpse, "oEquip3")) == oHostBody)
AssignCommand(oHostBody, ActionEquipItem(GetLocalObject(oLootCorpse, "oEquip3"), INVENTORY_SLOT_BELT));
if (GetItemPossessor(GetLocalObject(oLootCorpse, "oEquip4")) == oHostBody)
AssignCommand(oHostBody, ActionEquipItem(GetLocalObject(oLootCorpse, "oEquip4"), INVENTORY_SLOT_BOLTS));
if (GetItemPossessor(GetLocalObject(oLootCorpse, "oEquip5")) == oHostBody)
AssignCommand(oHostBody, ActionEquipItem(GetLocalObject(oLootCorpse, "oEquip5"), INVENTORY_SLOT_BOOTS));
if (GetItemPossessor(GetLocalObject(oLootCorpse, "oEquip6")) == oHostBody)
AssignCommand(oHostBody, ActionEquipItem(GetLocalObject(oLootCorpse, "oEquip6"), INVENTORY_SLOT_BULLETS));
if (GetItemPossessor(GetLocalObject(oLootCorpse, "oEquip7")) == oHostBody)
AssignCommand(oHostBody, ActionEquipItem(GetLocalObject(oLootCorpse, "oEquip7"), INVENTORY_SLOT_CLOAK));
/*
Helmet (oEquip8) gets handled by "oOrigHelmet" code in ReturnInventory
(if nCopyArmour is TRUE), or gets re-equipped (if nMoveArmour is TRUE and
nCopyArmour is FALSE)
*/
if (GetItemPossessor(GetLocalObject(oLootCorpse, "oEquip8")) == oHostBody)
AssignCommand(oHostBody, ActionEquipItem(GetLocalObject(oLootCorpse, "oEquip8"), INVENTORY_SLOT_HEAD));
if (GetItemPossessor(GetLocalObject(oLootCorpse, "oEquip9")) == oHostBody)
AssignCommand(oHostBody, ActionEquipItem(GetLocalObject(oLootCorpse, "oEquip9"), INVENTORY_SLOT_LEFTRING));
if (GetItemPossessor(GetLocalObject(oLootCorpse, "oEquip10")) == oHostBody)
AssignCommand(oHostBody, ActionEquipItem(GetLocalObject(oLootCorpse, "oEquip10"), INVENTORY_SLOT_NECK));
if (GetItemPossessor(GetLocalObject(oLootCorpse, "oEquip11")) == oHostBody)
AssignCommand(oHostBody, ActionEquipItem(GetLocalObject(oLootCorpse, "oEquip11"), INVENTORY_SLOT_RIGHTRING));
/*
Weapons (oEquip12 & 13) stay dropped on the ground (if nDropWeapons is
TRUE, oEquip12 & 13 == OBJECT_INVALID), or get re-equipped (if
nMoveWeapons is TRUE and nDropWeapons is FALSE)
*/
if (GetItemPossessor(GetLocalObject(oLootCorpse, "oEquip12")) == oHostBody)
AssignCommand(oHostBody, ActionEquipItem(GetLocalObject(oLootCorpse, "oEquip12"), INVENTORY_SLOT_RIGHTHAND));
if (GetItemPossessor(GetLocalObject(oLootCorpse, "oEquip13")) == oHostBody)
AssignCommand(oHostBody, ActionEquipItem(GetLocalObject(oLootCorpse, "oEquip13"), INVENTORY_SLOT_LEFTHAND));
/*
Armour (oEquip14) gets handled by "oOrigArmour" code in ReturnInventory
(if nCopyArmour is TRUE), or gets re-equipped (if nMoveArmour is TRUE and
nCopyArmour is FALSE)
*/
if (GetItemPossessor(GetLocalObject(oLootCorpse, "oEquip14")) == oHostBody)
AssignCommand(oHostBody, ActionEquipItem(GetLocalObject(oLootCorpse, "oEquip14"), INVENTORY_SLOT_CHEST));
}
/*******************************************************************************
** This script returns gold and inventory items from oLootCorpse (or bones) **
** to oHostBody. Dropped, unclaimed weapons remain where they fell. **
** **
** NOTE: Even though one of the parameters is "oLootCorpse = OBJECT_SELF", **
** this script can also be called by bones! **
*******************************************************************************/
void ReturnInventory(object oHostBody, object oLootCorpse = OBJECT_SELF)
{
// Remember dropped weapon info
/*
Store oLeftWpn/oRightWpn on oHostBody, so that if the oHostBody is killed
again, dropped weapons info will be saved (see "_kb_loot_corpse").
*/
SetLocalObject(oHostBody, "oLeftWpn", GetLocalObject(OBJECT_SELF, "oLeftWpn"));
SetLocalObject(oHostBody, "oRightWpn", GetLocalObject(OBJECT_SELF, "oRightWpn"));
// Move gold to oHostBody
// (This was commented out because gold is moved as an inventory item below)
// (if you don't comment out this line, the creature's gold will double)
// AssignCommand(oLootCorpse, GiveGoldToCreature(oHostBody, GetGold(oLootCorpse)));
// Move inventory items to oHostBody
object oEquip = GetFirstItemInInventory(oLootCorpse);
while (GetIsObjectValid(oEquip))
{
// If oHostBody is still wearing oOrigArmor, and no one has removed
// oLootArmor from oLootCorpse, destroy oLootArmor/oEquip14 (no need to
// transfer it back to oHostBody, since oOrigArmor is still there)
// NOTE: This never applies to bones, since if bones exist, oHostBody
// and oOrigArmour were already destroyed, and oLootArmour was already
// transferred to the bones (oLootArmour/oOrigArmour == OBJECT_INVALID)
if ((oEquip == GetLocalObject(OBJECT_SELF, "oLootArmour")) &&
(GetIsObjectValid(GetLocalObject(OBJECT_SELF, "oOrigArmour"))))
DestroyObject(oEquip); // destroys oLootArmour/oEquip14
// Make a similar check for oLootHelmet/oEquip8 and oOrigHelmet
// (doesn't apply to bones either)
else if ((oEquip == GetLocalObject(OBJECT_SELF, "oLootHelmet")) &&
(GetIsObjectValid(GetLocalObject(OBJECT_SELF, "oOrigHelmet"))))
DestroyObject(oEquip); // destroys oLootHelmet/oEquip8
else
{
// This following line doesn't work
// (maybe because combat leads to ClearAllActions on oHostBody?)
// AssignCommand(oHostBody, ActionTakeItem(oEquip, oLootCorpse));
AssignCommand(oLootCorpse, ActionGiveItem(oEquip, oHostBody));
}
oEquip = GetNextItemInInventory(oLootCorpse);
}
/*
// Used for debugging
SendMessageToPC(GetFirstPC(), "MOVING INVENTORY...");
DetermineEquipOwner(oLootCorpse);
DelayCommand(0.5, SendMessageToPC(GetFirstPC(), "MOVE COMPLETE (hopefully)..."));
DelayCommand(0.5, DetermineEquipOwner(oLootCorpse));
*/
// Delay time might need to be increased for slower PC's or large inventories
DelayCommand(0.5, ReEquip(oHostBody, oLootCorpse));
// Used for debugging
// DelayCommand(0.7, VerifyEquipped(oHostBody));
DelayCommand(1.0, DestroyObject(OBJECT_SELF));
}
void main()
{
/* register with other scripts */
int bModDebug = GetLocalInt(GetModule(),"bModDebug");
if (!GetLocalInt(GetModule(),"kb_raise_res"))
{
if (bModDebug) SendMessageToPC(GetFirstPC(),"Registering _kb_raise_res ...");
SetLocalInt(GetModule(),"kb_raise_res",1);
}
/* exit if null object calling - probably registration */
if (OBJECT_SELF == OBJECT_INVALID) return;
/* run plugin code */
int nSpellCast = GetLastSpell();
//Get all of our required information
object oHostBody = GetLocalObject(OBJECT_SELF, "oHostBody"); // returns OBJECT_INVALID if script called by bones
string sHostBodyResRef = GetLocalString(OBJECT_SELF, "sHostBodyResRef");
object oCorpseBlood = GetLocalObject(OBJECT_SELF, "oBloodSpot"); // returns OBJECT_INVALID if script called by bones
// Spell failure effect (for later use)
effect eSpellFail = EffectVisualEffect(VFX_IMP_MAGIC_RESISTANCE_USE);
// Raise Dead and Resurrection won't work on Outsiders, Elementals,
// Constructs, Undead, or RACIAL_TYPE_INVALID
int nRacialType = GetLocalInt(OBJECT_SELF, "nRacialType");
if ((nRacialType == RACIAL_TYPE_OUTSIDER) ||
(nRacialType == RACIAL_TYPE_ELEMENTAL) ||
(nRacialType == RACIAL_TYPE_CONSTRUCT) ||
(nRacialType == RACIAL_TYPE_UNDEAD) ||
(nRacialType == RACIAL_TYPE_INVALID))
{
// Spell failure effect
ApplyEffectToObject(DURATION_TYPE_INSTANT, eSpellFail, OBJECT_SELF);
// Spell failure message
if (nSpellCast == SPELL_RAISE_DEAD)
{
SendMessageToPC(GetLastSpellCaster(), "This type of creature cannot be raised from the dead.");
}
if (nSpellCast == SPELL_RESURRECTION)
{
SendMessageToPC(GetLastSpellCaster(), "This type of creature cannot be resurrected.");
}
// KNOWN BUG: Spell or scroll is wasted in the attempt
return;
}
if (nSpellCast == SPELL_RAISE_DEAD)
{
// Raise Dead won't work on bones
if (GetTag(OBJECT_SELF) == "loot_bones_obj")
{
// Spell failure effect
ApplyEffectToObject(DURATION_TYPE_INSTANT, eSpellFail, OBJECT_SELF);
// Spell failure message
SendMessageToPC(GetLastSpellCaster(), "This corpse is too badly damaged to be raised from the dead.");
// KNOWN BUG: Spell or scroll is wasted in the attempt
return;
}
ActionCastSpellAtObject(nSpellCast, oHostBody, METAMAGIC_ANY, TRUE, 0, PROJECTILE_PATH_TYPE_DEFAULT, TRUE);
if (GetIsObjectValid(oCorpseBlood)) DestroyObject(oCorpseBlood);
ReturnInventory(oHostBody);
}
else if (nSpellCast == SPELL_RESURRECTION)
{
// Works on lootable corpse placeable or bones
if (!GetIsObjectValid(oHostBody))
{
// Resurrect oBones ("transforms" oBones into oHostBody by
// re-creating the creature using sHostBodyResRef)
oHostBody = CreateObject(OBJECT_TYPE_CREATURE, sHostBodyResRef, GetLocation(OBJECT_SELF), FALSE);
// delete all default gold/items from oHostBody
RemoveInventory(oHostBody);
// Resurrection visual and sound effect
effect eResVis = EffectVisualEffect(VFX_IMP_RAISE_DEAD);
ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eResVis, GetLocation(oHostBody));
PlaySound("sim_healdead");
}
else
{
// Resurrect oHostBody (lootable corpse placeable is OBJECT_SELF)
ActionCastSpellAtObject(nSpellCast, oHostBody, METAMAGIC_ANY, TRUE, 0, PROJECTILE_PATH_TYPE_DEFAULT, TRUE);
if (GetIsObjectValid(oCorpseBlood)) DestroyObject(oCorpseBlood);
}
ReturnInventory(oHostBody);
}
else return;
}