Hi KevL,
I had to rewrite the scripts because of a few points that needed addressing when it came to how SR was applied to either an NPC that could become a companion (and could be raised, equip/un-equip SR items), or an NPC that simply needed the SR fixed. These scripts should address the following points:-
1) Applies a permanent "natural" SR fix to NPCs that are simply monsters via SKIN SR value. E.g. Succubus with SR attached to "SKIN" item.
2) Applies a permanent "natural" SR fix to NPCs that can become companions via a variable SR value. i.e. Companions MUST NOT use "SKINS". (See
http://worldofalthea...n-problems.html)
3A) Reapplies a permanent "natural" SR fix to companions raised from the dead. (Because SR fix is removed upon "death".)
3B) The function UpdateSRCondition that fixes SR can be delayed to double check any automatically re-equipped equipment after a resurrection if need be. (E.g. Used in my own campaign with the Tombstone system. See
http://worldofalthea...h-recovery.html )
4) A dedicated ITEM SR FEAT is applied to a any player controlled PC who equips an item that has a higher SR than any "natural" SR they may have. If the item is removed, any "natural" SR is returned and made permanent in its place.
Below is a list of the functions, followed by which scripts to call them from, and the feat spell script. The FEAT should be added as a persistent feat, so that it activates immediately and stays active all the while the conditions are met (the creature wears the SR ITEM).
**** IMPORTANT **** The function GetMainPC() is a homebrew function that checks if the object returned is one that a player can control, whether they currently possess that creature or not. i.e. You will need to use your own appropriate function to determine this within the function.I hope this all makes sense ... and that *should* be it ... unless I have missed something?
Cheers,
Lance.
THE FUNCTIONS ///////////////////////////////////////////////////////////////////////////////////////////////////
// RETURN (& STORE) THE SUB VALUE OF AN ITEM PROPERTY ON AN ITEM (E.g. SR Value of an SR property.)
// DEFAULT: STORES/CACHES ALL PROPERTY SUB-VALUES ON ITEM WHEN CALLED FOR ITEM. UNTESTED WITH MANY PROPS.
// E.g. IF iPROPERTY = ITEM_PROPERTY_SPELL_RESISTANCE (or 39), then this function will cycle through
// an item's properties looking to see if it had Spell Resistance. If it does, then this
// function will return the sub value of the SR property on the oItem.
// It will also STORE the SUB VALUE on the item in a variable "PROP39_SUBPROP0" (39 is int for SR)
// BEST USAGE: Use this function when acquiring an item for the first time, and then refer to the
// stored integer values recorded at the time of acquisition, rather than risk looping if possible.
///////////////////////////////////////////////////////////////////////////////////////////////////
int LBGetItemPropertySubValue(object oItem, int iPROPERTY = -1);
int LBGetItemPropertySubValue(object oItem, int iPROPERTY = -1)
{
// ONCE IS ENOUGH (DELETE TO UPDATE)
SetLocalInt(oItem, "SUBPROPSDONE", 1);
// PREPARE A NEGATIVE RETURN
int iSubValue = -1;
// LOOK FOR THE PROPERTY ON THE ITEM
itemproperty iProp = GetFirstItemProperty(oItem);
while (GetIsItemPropertyValid(iProp))
{
int iPROPFOUND = GetItemPropertyType(iProp);
// FOUND THE PROPERTY WE ARE LOOKING FOR
if(iPROPFOUND == iPROPERTY || iPROPERTY == -1)
{
// FIND THE ROW INDICATING THE SUB-VALUE 2DA TO USE (E.g. SR returns 11)
// AS A NOTE: THIS FUNCTION MAY GET ITS REFERENCE FROM THE itempropdef.2da
int iPROPERTY_COSTTABLE_ROW = GetItemPropertyCostTable(iProp);
// NOW WE CAN DETERMINE THE SUB VALUE FOR THIS PROPERTY ATTACHED TO THIS ITEM
// IF A VALID SUB-VALUE COST 2DA IS RETURNED (WHICH SHOULD BE > 0)
if(iPROPERTY_COSTTABLE_ROW > 0)
{
// DETERMINE THE NAME OF THE SUB PROPERTY 2DA TO USE
string sSubTable2da = Get2DAString("iprp_costtable", "Name", iPROPERTY_COSTTABLE_ROW);
// THIS FUNCTION DETERMINES THE SUB-VALUE 2DA ROW NUMBER FOR THE PROPERTY
int iROW_SUBVAL = GetItemPropertyCostTableValue(iProp);
// RETRIEVE THE SUB-VALUE FROM THE SUB-VALUE 2da
string sSUBValue = Get2DAString(sSubTable2da, "Value", iROW_SUBVAL);
// RETURN AS AN INT
iSubValue = StringToInt(sSUBValue);
// A FURTHER DISTINGUISHER IF REQUIRED (E.g. DIFFERENT ABILITIES ON SAME ITEM, EACH DIFFERING VALUE)
int iSubType = GetItemPropertySubType(iProp);
string sSUBVALUE = "PROP" + IntToString(iPROPFOUND) + "_SUBPROP" + IntToString(iSubType);
// STORE VALUE ON ITEM
SetLocalInt(oItem, sSUBVALUE, iSubValue);
// DEBUG
//SetNoticeTextAll("ITEM SUB PROPERTY VALUES >>>> " + sSUBValue + " STORED WITHIN " + sSUBVALUE, 1);
}
}
iProp = GetNextItemProperty(oItem);
}
// RETURN THE SUB VALUE WHETHER USED OR NOT (RETURN NEGATIVE IF JUST FINDING ALL)
if(iPROPERTY == -1){iSubValue = -1;}
return iSubValue;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// CYCLE THROUGH ALL EQUIPPED ITEMS FOR HIGHEST SR ITEM (STORE AS AN INT ON SR ITEM)
///////////////////////////////////////////////////////////////////////////////////////////////////
int GetBestEquippedSRValue(object oCreature);
int GetBestEquippedSRValue(object oCreature)
{
int i;
int iCurrentSRItem = 0;
int iNaturalSRValue = GetLocalInt(oCreature, "NATURALSRVALUE");
int iCompare = 0;
// ALLOW UP TO 10 ONLY AS THEY ARE THE ONLY VALID SR EQUIP TO CHECK
for(i=0; i<11; i++)
{
object oEquip = GetItemInSlot(i,oCreature);
if(GetIsObjectValid(oEquip))
{
iCompare = GetLocalInt(oEquip, "PROP39_SUBPROP0");
SetNoticeTextAll("ITEM NUM " + IntToString(i) + " >>>> " + IntToString(iCurrentSRItem), 1);
// ONLY STORE ITEM SR VALUE IF BETTER THAN ALREADY RECORDED AND NATURAL SR ABILITY
if(iCompare >= iCurrentSRItem && iCompare >= iNaturalSRValue){iCurrentSRItem = iCompare;}
}
}
// CAN RETURN ZERO
return iCurrentSRItem;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// UPDATE CURRENT Spell Resistance (SR) FOR CREATURE
// FUNCTION FIRST CALLED AT SPAWN TO SETUP ANY NATURAL SR FOR THE CREATURE
// LATER CALLED IF A VALID SR ITEM IS EQUIPPED OR UNEQUIPPED FOR A PLAYER CONTROLLED CREATURE
// ALSO CALLED IF A PLAYER CONTROLLED COMPANION IS RAISED FROM THE DEAD (REFRESHES SR VALUES)
///////////////////////////////////////////////////////////////////////////////////////////////////
void UpdateSRCondition(object oCreature, int iRAISED = 0);
void UpdateSRCondition(object oCreature, int iRAISED = 0)
{
SetNoticeText(oCreature, "UPDATING SR STATUS ON " + GetName(oCreature));
// PREPARE NEW SR VALUE
int iNEWSRValue = 0;
// RETRIEVE ANY NATURAL SR VALUES - SET AT SPAWN VIA VAR (FOR COMPS) OR SKIN (FOR NPCS)
int iNATURALSRValue = GetLocalInt(oCreature, "NATURALSRVALUE");
///////////////////////////////////////////////////////////////////////////////
// COMP/NPC SPAWNED WITH SR IN SOME WAY: SR INITIAL PERMANENT FIX
///////////////////////////////////////////////////////////////////////////////
if(GetMainPC(oCreature) == OBJECT_INVALID && iRAISED == 0)
{
// UPDATE NATURALVALUE FOR ALL CREATURES SPAWNED WITH SR SKIN
if(GetLocalInt(oCreature, "NATURALSRVALUE") == 0)
{
iNATURALSRValue = GetSpellResistance(oCreature);
}
// SAFETY CHECK AGAINST BAD FUNCTION PASS
if(iNATURALSRValue == 0){return;}
// PREPARE THE SR EFFECT
effect eSR = EffectSpellResistanceIncrease(iNATURALSRValue, -1);
eSR = SupernaturalEffect(eSR);
// APPLY THE EFFECT
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eSR, oCreature);
return;
}
/////////////////////////////////////////////////////////////////////////
// CALLED ONEQUIP OR UNEQUIP - GET HIGHEST VALID SR EQUIPPED ITEM (CAN BE ZERO)
// IF THIS VALUE IS > 0 & NAT SR, THEN THE FEAT "ITEM SR" IS ADDED TO THE CREATURE
/////////////////////////////////////////////////////////////////////////
else{iNEWSRValue = GetBestEquippedSRValue(oCreature);}
// REMOVE THE ITEM SR FEAT REGARDLESS TO PREVENT "REDUNDANCY" EFFECT
FeatRemove(oCreature, 2893);
// SR ITEM EQUIPPED & REQUIRES FEAT UPDATE (ITEM SR MADE PERMANENT THROUGH THE FEAT)
if(iNEWSRValue > 0)
{
SetLocalInt(oCreature, "SRUPDATE", iNEWSRValue);
FeatAdd(oCreature, 2893, FALSE, TRUE, TRUE);
}
// RESTORE ANY NATURAL SR IF REQUIRED (NATURAL SR MADE PERMANENT HERE)
// CALLED WHEN CREATURE RAISED FROM DEAD OR REMOVES SR ITEM
else if(iNATURALSRValue > 0)
{
// PREPARE THE SR EFFECT
effect eSR = EffectSpellResistanceIncrease(iNATURALSRValue, -1);
eSR = SupernaturalEffect(eSR);
// APPLY THE EFFECT
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eSR, oCreature);
}
} SET UP VARIABLE VALUES ON ITEM ACQUIRED // LETS TRY ADDING PROPERTY SUB-VALUES AS VARIABLES HERE
if(GetLocalInt(oItem, "SUBPROPSDONE") == 0){LBGetItemPropertySubValue(oItem);} POTENTIAL COMPANION ONSPAWN (MUST NOT USE SKINS AS THESE CAUSE ISSUES) // ADD "NATURALSRVALUE" AT TIME OF BUILD
int iSRValue = GetLocalInt(OBJECT_SELF, "NATURALSRVALUE");
if(iSRValue> 0){UpdateSRCondition(OBJECT_SELF);}MONSTER ONSPAWN (USES NORMAL SKINS THAT HAVE AN SR VALUE ON THEM)// SR - SIMPLY CHECK FOR AND MAKE ANY SR FOUND PERMANENT
object oSKIN = GetItemInSlot(17);
if(GetItemHasItemProperty(oSKIN, ITEM_PROPERTY_SPELL_RESISTANCE)){UpdateSRCondition(OBJECT_SELF);}FUNCTION MUST ALSO BE ADDED AND CALLED FROM THE RAISE DEAD OR RESURRECTION SPELLS// RESTORE ANY NATURAL SR
UpdateSRCondition(oTarget, 1);
FUNCTION CALLED FROM ON EQUIP///////////////////////////////////////////////////////////////////////////////////////////////////
// UPDATE SPELL RESISTANCE FOR PC ACCORDING TO EQUIPMENT - ONLY SR ITEMS FIRE FUNCTION
// DELAY ALLOWS TIME FOR ANY UNEQUIPPING IF OTHER SR ITEMS AT SAME TIME
///////////////////////////////////////////////////////////////////////////////////////////////////
if(GetItemHasItemProperty(oItem, ITEM_PROPERTY_SPELL_RESISTANCE)){DelayCommand(0.11, UpdateSRCondition(oPC));}
FUNCTION CALLED FROM ON UNEQUIP///////////////////////////////////////////////////////////////////////////////////////////////////
// UPDATE SPELL RESISTANCE FOR PC ACCORDING TO EQUIPMENT - ONLY SR ITEMS FIRE FUNCTION
// NEED DELAY TO ALLOW ITEM TO UNEQUIP BEFORE THE CHECK FOR REMAINING SR ITEMS IS MADE
///////////////////////////////////////////////////////////////////////////////////////////////////
if(GetItemHasItemProperty(oItem, ITEM_PROPERTY_SPELL_RESISTANCE)){DelayCommand(0.1, UpdateSRCondition(oPC));}THE ITEM SR FEAT SPELL SCRIPT// SPELL RESISTANCE FIX FOR ITEMS (BY GIVING A FEAT)
// ADD SPELL RESISTANCE VALUE ACCORDING TO THE ITEM EQUIPPED
void main()
{
// THE OBJECT WITH SR
object oCreature = OBJECT_SELF;
// RETRIEVE THE SR VALUE TO ASSIGN
int iSRValue = GetLocalInt(oCreature, "SRUPDATE");
DeleteLocalInt(oCreature, "SRUPDATE");
// PREPARE THE SR EFFECT
effect eSR = EffectSpellResistanceIncrease(iSRValue, -1);
eSR = SupernaturalEffect(eSR);
// APPLY THE EFFECT
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eSR, oCreature);
}