Amon_PRC8/_module/nss/hench_i0_henutil.nss

345 lines
11 KiB
Plaintext
Raw Permalink Normal View History

2025-04-03 19:00:46 -04:00
//::///////////////////////////////////////////////
//:: hench_i0_henutil (parts from the original NW_I0_HENCHMAN)
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
//void main() { } int GetIsHumanoid(int nRacial) { return 0; }
/*
This is the include file for the
henchmen who can join the player.
ASSUMPTION: All these functions
are meant to be ran by the henchman.
OBJECT_SELF is assumed to be the henchman.
RULES: Henchman are dialog controlled only!
No locals/globals should be set outside of the
henchman's own dialog file!
*/
//:://////////////////////////////////////////////
//:: Created By: Brent
//:: Created On: February 2002
//:://////////////////////////////////////////////
// * ---------
// * CONSTANTS
// * ---------
#include "hench_i0_ident"
#include "hench_i0_strings"
int GetIsHumanoid(int nRacial);
// Check to see if the item was successfully equipped.
void CheckIsEquipped(object oItem, int iSlot, string sDescr)
{
object oWorn = GetItemInSlot(iSlot);
if (oWorn != oItem) {
if (oWorn == OBJECT_INVALID ||
GetGoldPieceValue(oWorn) / GetNumStackedItems(oWorn) < GetGoldPieceValue(oItem)/GetNumStackedItems(oItem))
SpeakString(sHenchUnableToEquip1 + sDescr + sHenchUnableToEquip2);
else
SpeakString(sHenchUnableToEquip3 + sDescr + sHenchUnableToEquip4);
} else
SpeakString(sHenchAbleToEquip + sDescr + ".");
}
// Equip an item in iSlot, or optionally in iOtherSlot if iSlot is full.
void EquipIfWorthIt(object oItem, int iMaxGPIdentify, int iSlot, string sDescr,
int iOtherSlot=500)
{
string sName;
// These variables store the value of the most valuable
// object in the NPC's inventory examined thus far. They are set
// to -1 at the beginning of inventory control.
string sSlotVar = "Invent"+IntToString(iSlot);
string sSlotVarName = "InventName"+IntToString(iSlot);
string sOtherVar = "Invent"+IntToString(iOtherSlot);
int iStoredValue = GetLocalInt(OBJECT_SELF,sSlotVar);
int iOtherValue = GetLocalInt(OBJECT_SELF,sOtherVar);
int iNewValue = 0;
// Don't want to reveal the object's name unless it's already
// identified. Again, assign unidentified items a nominal value of 1.
if (GetIdentified(oItem)) {
sName = GetName(oItem);
iNewValue = GetGoldPieceValue(oItem) / GetNumStackedItems(oItem);
}
else {
sName = "unidentified "+sDescr;
iNewValue = 1;
}
// If we are already equipping something in the given slot, get its value.
// Unidentified items have a nominal value of 1. Note: this only works with
// items equipped before inventory control.
if (iStoredValue == -1) {
object oOld = GetItemInSlot(iSlot);
if (GetIsObjectValid(oOld) && !GetLocalInt(oOld,"DestroyItem") &&
oOld != GetLocalObject(OBJECT_SELF,"Decency")) {
HenchIdentifyItem(oOld, iMaxGPIdentify);
//SpeakString(GetName(oOld)+GetName(oItem)+IntToString(GetGoldPieceValue(oOld)/GetNumStackedItems(oOld))+
// " "+IntToString(GetGoldPieceValue(oItem)/GetNumStackedItems(oItem)));
if (GetIdentified(oOld)) {
iStoredValue = GetGoldPieceValue(oOld) / GetNumStackedItems(oOld);
SetLocalString(OBJECT_SELF,sSlotVarName,GetName(oOld));
}
else {
iStoredValue = 1;
SetLocalString(OBJECT_SELF,sSlotVarName,"unidentifed "+GetName(oOld));
}
SetLocalInt(OBJECT_SELF,sSlotVar,iStoredValue);
}
}
// If we already have considered an item of this type, we need to
// juggle the inventory.
if (iStoredValue >= 0) {
// If we have another slot in which we can equip this item,
// and if the item in the other slot is not better than the item in
// the current iSlot, then run the function on that other slot.
if (iNewValue > iOtherValue && iOtherSlot != 500)
if (iOtherValue < iStoredValue) {
EquipIfWorthIt(oItem, iMaxGPIdentify, iOtherSlot, sDescr);
return;
}
// If the item is better than what we had before, tell the player so and
// store its value. Otherwise, tell the player and do nothing else.
if (iNewValue > iStoredValue)
SpeakString(sHenchSelectItem1 + sName + ".");
else if (iNewValue < iStoredValue) {
SpeakString(sHenchSelectItem2 + GetLocalString(OBJECT_SELF, sSlotVarName) +
sHenchSelectItem3 + sName+ ".");
return;
}
else if (iStoredValue > 0)
SpeakString(sHenchDecisions);
}
// Now attempt to equip the items, and after a suitable time, check
// to see if the the attempt succeeds.
SetLocalInt(OBJECT_SELF,sSlotVar,iNewValue);
SetLocalString(OBJECT_SELF,sSlotVarName,sName);
ActionDoCommand(ActionEquipItem(oItem,iSlot));
DelayCommand(2.,CheckIsEquipped(oItem,iSlot,sName));
}
// Try to figure out what to do with an item.
void EquipItems(object oSource)
{
int i;
object oItem;
DestroyObject(oSource,0.0);
for (i = 0; i < NUM_INVENTORY_SLOTS; ++i)
SetLocalInt(OBJECT_SELF,"Invent"+IntToString(i),-1);
SetLocalInt(OBJECT_SELF,"GotAWeapon",FALSE);
int iMaxGPIdentify = HenchGetMaxGPToIdentify();
oItem = GetFirstItemInInventory();
while (GetIsObjectValid(oItem)) {
if (!GetLocalInt(oItem,"DestroyItem")) {
HenchIdentifyItem(oItem, iMaxGPIdentify);
switch (GetBaseItemType(oItem)) {
case BASE_ITEM_ARMOR:
EquipIfWorthIt(oItem, iMaxGPIdentify, INVENTORY_SLOT_CHEST, sHenchEquipArmor);
break;
case BASE_ITEM_LARGESHIELD:
case BASE_ITEM_SMALLSHIELD:
case BASE_ITEM_TOWERSHIELD:
SpeakString(sHenchEquipShield);
break;
case BASE_ITEM_CLOAK:
EquipIfWorthIt(oItem, iMaxGPIdentify, INVENTORY_SLOT_CLOAK, sHenchEquipCloak);
break;
case BASE_ITEM_BOOTS:
EquipIfWorthIt(oItem, iMaxGPIdentify, INVENTORY_SLOT_BOOTS, sHenchEquipBoots);
break;
case BASE_ITEM_BRACER:
case BASE_ITEM_GLOVES:
EquipIfWorthIt(oItem, iMaxGPIdentify, INVENTORY_SLOT_ARMS, sHenchEquipHandwear);
break;
case BASE_ITEM_HELMET:
EquipIfWorthIt(oItem, iMaxGPIdentify, INVENTORY_SLOT_HEAD, sHenchEquipHelmet);
break;
case BASE_ITEM_BELT:
EquipIfWorthIt(oItem, iMaxGPIdentify, INVENTORY_SLOT_BELT, sHenchEquipBelt);
break;
case BASE_ITEM_RING:
EquipIfWorthIt(oItem, iMaxGPIdentify, INVENTORY_SLOT_LEFTRING, sHenchEquipRing, INVENTORY_SLOT_RIGHTRING);
break;
case BASE_ITEM_AMULET:
EquipIfWorthIt(oItem, iMaxGPIdentify, INVENTORY_SLOT_NECK, sHenchEquipAmulet);
break;
// These items are auto-equipped by the ActionEquipMostDamagingRanged() command
case BASE_ITEM_ARROW:
case BASE_ITEM_BULLET:
case BASE_ITEM_BOLT:
// THESE SHOULD BE EDITED SO THAT THE HENCHMAN DEALS WITH THEM
// PROPERLY. FOR NOW THEY ARE IGNORED
case BASE_ITEM_CREATUREITEM:
case BASE_ITEM_GEM:
case BASE_ITEM_KEY:
case BASE_ITEM_MAGICROD:
case BASE_ITEM_MAGICSTAFF:
case BASE_ITEM_MAGICWAND:
case BASE_ITEM_POTIONS:
case BASE_ITEM_SPELLSCROLL:
case BASE_ITEM_THIEVESTOOLS:
case BASE_ITEM_TRAPKIT:
case BASE_ITEM_TORCH: // done by equip shield
break;
default:
if (!GetLocalInt(OBJECT_SELF,"GotAWeapon"))
{
SpeakString(sHenchEquipWeapon);
SetLocalInt(OBJECT_SELF,"GotAWeapon",TRUE);
}
break;
}
}
oItem = GetNextItemInInventory();
}
SpeakString(sHenchEquipWait);
}
void DestroyDecency(int bIndicateNoClothes)
{
object oDecency = GetLocalObject(OBJECT_SELF,"Decency");
if (GetItemInSlot(INVENTORY_SLOT_CHEST) != oDecency)
{
DestroyObject(oDecency);
DeleteLocalObject(OBJECT_SELF,"Decency");
}
else if (bIndicateNoClothes && GetIsHumanoid(GetRacialType(OBJECT_SELF)))
{
SpeakString(sHenchEquipDecency);
}
}
// Copy associate's inventory.
void CopyAssociateItems(object oPC, object oAssociate)
{
object oItem;
int i;
for(i = 0; i < NUM_INVENTORY_SLOTS; ++i)
{
oItem = GetItemInSlot(i, oAssociate);
if (oItem != OBJECT_INVALID)
{
switch (GetBaseItemType(oItem))
{
case BASE_ITEM_CREATUREITEM:
case BASE_ITEM_CBLUDGWEAPON:
case BASE_ITEM_CSLASHWEAPON:
case BASE_ITEM_CSLSHPRCWEAP:
case BASE_ITEM_CPIERCWEAPON:
break;
case BASE_ITEM_DAGGER:
// prevent pixie dagger from being given up
if (!GetDroppableFlag(oItem))
{
break;
}
default:
CopyItem(oItem, oPC);
break;
}
}
}
// Now go through the backpack.
oItem = GetFirstItemInInventory(oAssociate);
while (oItem != OBJECT_INVALID)
{
CopyItem(oItem, oPC);
oItem = GetNextItemInInventory(oAssociate);
}
}
// Copy familiar/animal companion's inventory.
void CopyFamiliarAnimalCompanionItems(object oPC)
{
if (!GetIsObjectValid(oPC))
{
return;
}
object oAssociate;
oAssociate = GetAssociate(ASSOCIATE_TYPE_FAMILIAR, oPC);
if (GetIsObjectValid(oAssociate))
{
CopyAssociateItems(oPC, oAssociate);
}
oAssociate = GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION, oPC);
if (GetIsObjectValid(oAssociate))
{
CopyAssociateItems(oPC, oAssociate);
}
}
void DestroyAssociates(object oCreature)
{
// Checking for henchman summons/familiars/animal companions/dominated
// and destroying them to prevent them going hostile.
if (GetIsObjectValid(GetAssociate(ASSOCIATE_TYPE_FAMILIAR, oCreature)))
{
effect eUnSum = EffectVisualEffect(VFX_FNF_SMOKE_PUFF);
location lUnSum = GetLocation(GetAssociate(ASSOCIATE_TYPE_FAMILIAR, oCreature));
ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eUnSum, lUnSum, 5.0);
DestroyObject(GetAssociate(ASSOCIATE_TYPE_FAMILIAR, oCreature));
}
if (GetIsObjectValid(GetAssociate(ASSOCIATE_TYPE_SUMMONED, oCreature)))
{
effect eUnSum = EffectVisualEffect(VFX_FNF_SMOKE_PUFF);
location lUnSum = GetLocation(GetAssociate(ASSOCIATE_TYPE_SUMMONED, oCreature));
ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eUnSum, lUnSum, 5.0);
DestroyObject(GetAssociate(ASSOCIATE_TYPE_SUMMONED, oCreature));
}
if (GetIsObjectValid(GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION, oCreature)))
{
effect eUnSum = EffectVisualEffect(VFX_FNF_SMOKE_PUFF);
location lUnSum = GetLocation(GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION, oCreature));
ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eUnSum, lUnSum, 5.0);
DestroyObject(GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION, oCreature));
}
if (GetIsObjectValid(GetAssociate(ASSOCIATE_TYPE_DOMINATED, oCreature)))
{
effect eUnSum = EffectVisualEffect(VFX_FNF_SMOKE_PUFF);
location lUnSum = GetLocation(GetAssociate(ASSOCIATE_TYPE_DOMINATED, oCreature));
ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eUnSum, lUnSum, 5.0);
DestroyObject(GetAssociate(ASSOCIATE_TYPE_DOMINATED, oCreature));
}
}