Spell Resistance - Working Solution
#1
Posté 25 juin 2015 - 11:29
I was unaware until recently that SR failed to work from items after its first check. So, I looked into the problem and came up with this working solution. (It is probably based on similar lines to others, but this works by implementing a dedicated feat.)
1) Added a dedicated Spell Resistance feat that activates when a creature equips an SR item.
2) A dedicated function is called from ONEQUIP and ONUNEQUIP hooks that check current items equipped.
3) The dedication function in 2 calls a second dedicated item check function to determine best SR item equipped.
4) The dedicated Spell Resistance feat is added or removed (with correct values) as required.
NOTE: The only caveat is that one has to add a variable "SRVALUE" to any items that have SR values. Therefore, I guess I am going to have to update some creature skins.
QUESTION: This part could be automated *IF* anybody knows how to retrieve the SR value of the SR. E.g. Is there a way to differentiate between a SR 12 and SR 16 item for example. At the moment, I have to apply the variable manually. (This is easy enough to do in my crafting system, as I rewrote that anyway, but it would be good to have a means of testing the SR value if anybody knows how?)
If anybody wants more details about this, let me know. The above is basically the system I worked out and works, and I explain for those who also want to implement it. (I can supply my scripts as examples if you prefer.)
Regards, Lance.
#2
Posté 26 juin 2015 - 06:24
here's my version of Reeron's original SR fix. It uses EffectSpellResistanceIncrease() as a SupernaturalEffect()
(and I gotta point out that EffectSpellResistanceIncrease() is *not* an increase - it sets value period.)
Which is better Idk - but you'll find the technique to get SR value of an item in the first dozen lines.
/* Creature SR */
int nSR = 0;
object oCarmour = GetItemInSlot(INVENTORY_SLOT_CARMOUR);
itemproperty iProp = GetFirstItemProperty(oCarmour);
while (GetIsItemPropertyValid(iProp))
{
int nCrap = GetItemPropertyCostTable(iProp);
if (nCrap == 11) // Spell Resistance
{
int nCrap2 = GetItemPropertyCostTableValue(iProp);
string sSRValue = Get2DAString("iprp_srcost", "Value", nCrap2);
if (iDebug) SendMessageToPC(oDebug, ". Creature armor Spell Resistance = " + sSRValue);
nSR = StringToInt(sSRValue);
}
iProp = GetNextItemProperty(oCarmour);
}
int iSR = GetSpellResistance(OBJECT_SELF);
if (iSR > nSR)
{
nSR = iSR;
if (iDebug) SendMessageToPC(oDebug, ". innate SR greater than carapice SR");
}
if (iDebug) SendMessageToPC(oDebug, ". base Spell Resistance = " + IntToString(nSR));
//". fixing SR Bug on items . ."
if (nSR > 0)
{
effect eSR = EffectSpellResistanceIncrease(nSR, -1);
eSR = SupernaturalEffect(eSR);
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eSR, OBJECT_SELF);
if (iDebug)
{
nSR = GetSpellResistance(OBJECT_SELF);
SendMessageToPC(oDebug, ". Spell Resistance of enemy = " + IntToString(nSR));
}
}
/* end Creature SR */
#3
Posté 26 juin 2015 - 12:59
This is very similar to the method I use.
At a quick glance, it looks like the GetItemPropertyCostTableValue function may hold a answer I was looking for then. I am not familiar with this function and so will play around with it a bit to see how it works and what it returns.
EDIT: Well, no wonder I could not find it. This function is exactly the one I was looking for, but I would never have figured it from the function name. This is a useful function to know, as it means we now have a means of determining every potential value of a varying property. In hind sight, this would have been useful to know a few months ago. Oh well.
I think I may write a new function along the lines of: EDITED BELOW I know that not all properties would work with this function, but it may be useful for some.
Interestingly, the script you provide looks like a fix for *creatures only*, as opposed to PCs with SR items ... Is that right, or have I missed something?
The reason I say that is because I believe the way I have done it works for PCs and equipping different SR items too. Let me know if there is more I am missing in your code then, as I do not want to "re-invent the wheel". However, if I can automate the SR value from these new functions you have pointed me towards, then that will solve it completely!
Cheers,
Lance.
This function worked fine with an item with FIVE properties, which is as much as I need. I also intend to mark an item as "DONE" after first collection to stop the function check on every acquisition.
///////////////////////////////////////////////////////////////////////////////////////////////////
// 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)
{
// 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;
}
#4
Posté 26 juin 2015 - 03:58
and, since I'm pretty sure things get Equipped when spawning anyway, all that's likely needed is onEquip/unEquip scripts.
/cheers, don't let cost table value 2da's drive ye nutterz.
#5
Posté 26 juin 2015 - 04:45
hey Lance, yes this is code only for creatures w/ SR-hides. I typically run it onSpawn. Kaedrin's PrC pack has additional code for equipping and unequipping items. I haven't got around to 'conforming' the two and not sure if they need be: things seem to keep up well enough when i'm playing.
and, since I'm pretty sure things get Equipped when spawning anyway, all that's likely needed is onEquip/unEquip scripts.
/cheers, don't let cost table value 2da's drive ye nutterz.
Hi KevL,
I thought I read that you had some concerns about the way Kaedrin's PrC pack handled PC SR. If not, then all's good. ![]()
I must admit that I do like to have a "conforming" system if possible. ![]()
And how could you tell that these cost tables were driving me nuts?
![]()
Cheers,
Lance.
#7
Posté 26 juin 2015 - 06:02
i do. It's just not a pressing concern fo' me atm.
Hi KevL,
Just so I can double check I have covered the same problems in my own code, what did you notice "not working" or "what were your concerns"?
I can at least double check my own to make sure I do not suffer with the same problems ... if you see what I mean?
Also, (I may start a new thread asking this as well), can you think of any other issues/bugs (like this SR one or similar) that would be worth me trying to fix? i.e. Game breaking bugs that affect how the game works.
Cheers,
Lance.
#8
Posté 26 juin 2015 - 08:59
so, DelayCommand(0.1, calcSR(oCreature))
would be the way to go.
Things like that ... here's the kPrC function that fires onEquip/unEquip (from back when the source was available). I haven't looked at this for ages, and will make some notes below:
void ApplySRFix(object oPC)
{
if (GetHasSpellEffect(SR_FIX, oPC))
RemoveSpellEffects(SR_FIX, oPC, oPC);
object oItem;
int nSRMax = 0;
int nSRCurrent = 0;
int nCostTableResRef, nValue;
int nSlotNum;
for (nSlotNum = 0; nSlotNum < NUM_INVENTORY_SLOTS; nSlotNum ++)
{
oItem = GetItemInSlot(nSlotNum, oPC);
if (GetIsObjectValid(oItem))
{
itemproperty iProp = GetFirstItemProperty(oItem);
while (GetIsItemPropertyValid(iProp))
{
nCostTableResRef = GetItemPropertyCostTable(iProp);
if (nCostTableResRef == 11) // iprp_srcost
{
nValue = GetItemPropertyCostTableValue(iProp);
// string nSRValue = Get2DAString("iprp_srcost", "Value", nValue);
// nSRCurrent = StringToInt(nSRValue);
nSRCurrent = GetSRValueBy2DAValue(nValue);
if (nSRMax < nSRCurrent)
{
nSRMax = nSRCurrent;
}
}
iProp = GetNextItemProperty(oItem);
}
}
}
int iSR = GetSpellResistance(oPC); // kL
if (nSRMax > 0 && nSRMax > iSR) // kL
// if (nSRMax > 0)
{
effect eSR = EffectSpellResistanceIncrease(nSRMax);
eSR = SetEffectSpellId(eSR, SR_FIX);
eSR = SupernaturalEffect(eSR);
// DelayCommand(0.3f, DelayedSRFixApplication(oPC, eSR));
DelayCommand(0.1f, DelayedSRFixApplication(oPC, eSR)); // kL
}
}SR_FIX is the SpellID assigned to the supernatural spell resistance effect.I notice that i like to do a fetch of GetSpellResistance() after examining the equipped items. I don't know what the rules are about stacking SR, which is something to keep in mind because when tinkering like this you'd get to choose our own stacking rules. Anyway, fwiw my scripts compare the value of SR returned by the engine w/ GetSpellResistance() and compare that to the max-value that's discovered by the loop-over-equipped-items, and use the higher. The engine-return ought catch Feats and maybe other SR idiosyncracies ... (although it could merely be redundant).
DelayedSRFixApplication() is just:
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC);GetSRValueBy2DAValue() is just a coded lookup table, faster than a .2da lookup but likely with the same values.
#9
Posté 26 juin 2015 - 09:07
/just a thought.
#10
Posté 26 juin 2015 - 09:19
/shrug, donno without testing.
#11
Posté 26 juin 2015 - 10:31
( hm. I wouldn't be surprised if a single, slightly delayed call to GetSpellResistance() in the onEquip/unEquip will return the correct value, and thereby render the for-loop obsolete ...)
/just a thought.
Hi KevL,
I have delays in my EQUIP/UNEQUIP to get around this problem if it is what I think you mean ... I'll EDIT post them in a minute to show ..
EDIT: SR does not stack according to rules ... and good job really.
Cheers,
Lance.
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, oItem));}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, oItem));}FUNCTIONS:///////////////////////////////////////////////////////////////////////////////////////////////////
// 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 = GetSpellResistance(oCreature);
int iCompare = 0;
// ALLOW UP TO 17 TO COVER CREATURE SKIN VALUE 17 (ALTHOUGH NOT NEEDED NOW AS I DO THE CHECK PRIOR NOW)
for(i=0; i<18; i++)
{
object oEquip = GetItemInSlot(i,oCreature);
if(GetIsObjectValid(oEquip))
{
// THIS VAR HOLDER IS SETUP WITH THAT FUNCTION I POSTED ABOVE (WHEN ITEM ACQUIRED)
iCompare = GetLocalInt(oEquip, "PROP39_SUBPROP0");
//SetNoticeTextAll(">>>> " + 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 ACCORDING TO ITEM EQUIPPED/UNEQUIPPED
// FUNTION ONLY CALLED IF A VALID SR ITEM IS EQUIPPED OR UNEQUIPPED
///////////////////////////////////////////////////////////////////////////////////////////////////
void UpdateSRCondition(object oCreature, object oItem);
void UpdateSRCondition(object oCreature, object oItem)
{
SetNoticeText(oCreature, "UPDATING SR STATUS ON " + GetName(oCreature));
// PREPARE NEW SR VALUE
int iNEWSRValue = 0;
// QUICK CREATURE SKIN CHECK (GetMainPC() IS A CUSTOM FUNCTION I USE TO DETERMINE PROPER PLAYER PC)
if(GetMainPC(oCreature) == OBJECT_INVALID)
{
iNEWSRValue = GetSpellResistance(oCreature);
// SAFETY CHECK AGAINST BAD FUNCTION PASS
if(iNEWSRValue == 0){return;}
// PREPARE THE SR EFFECT
effect eSR = EffectSpellResistanceIncrease(iNEWSRValue, -1);
eSR = SupernaturalEffect(eSR);
// APPLY THE EFFECT
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eSR, oCreature);
return;
}
// GET HIGHEST VALID SR EQUIPPED ITEM (CAN BE ZERO)
// IF THIS VALUE IS > 0, THEN THE FEAT "ITEM SR" IS ADDED TO THE CREATURE
else{iNEWSRValue = GetBestEquippedSRValue(oCreature);}
//SetNoticeTextAll("RETURN >>>> " + IntToString(iNEWSRValue), 1);
// HAS THE "ITEM SR" FEAT (AND NEEDS REMOVING)
if(GetHasFeatEffect(2893, oCreature) && iNEWSRValue == 0){FeatRemove(oCreature, 2893);}
// SR ITEM EQUIPPED & REQUIRES FEAT UPDATE
else if(iNEWSRValue > 0)
{
SetLocalInt(oCreature, "SRUPDATE", iNEWSRValue);
FeatAdd(oCreature, 2893, FALSE, TRUE, TRUE);
}
}FEAT CODE 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);
}AND THEN THERE IS A NEWLY ADDED FEAT OF COURSE .... 2893 const int FEAT_ALTHEA_SPELLRESISTANCE = 2893; // SPELL RESISTANCE (VIA ITEM)
Cheers,
Lance
#12
Posté 27 juin 2015 - 06:39
( hm. I wouldn't be surprised if a single, slightly delayed call to GetSpellResistance() in the onEquip/unEquip will return the correct value, and thereby render the for-loop obsolete ...)
/just a thought.
The old spell-resistance fix from the Vault works that way.... I have the impression you guys are trying to re-invent the wheel. ![]()
http://neverwinterva...nd-improvements
http://neverwinterva...-hides-override
#13
Posté 27 juin 2015 - 07:09
It seems to do a different routine depending on whether oCreature is the mainPC or not. Reason? To avoid adding a Feat to mainPC?
i Also notice that no check is done for iNEWSRValue==0 if (GetMainPC(oCreature) == OBJECT_INVALID). I strongly suggest checking for (iNEWSRValue > 0) on both branches. And, if false, use a method for removing any previously applied effect, perhaps w/ a spell-Id after all ....
ideally i'd conform the two branches - although, with some debugText, it's a good way to get feedback on which is the better routine. I guess it comes down to this: is the Feat necessary at all ?
#14
Posté 27 juin 2015 - 07:11
The old spell-resistance fix from the Vault works that way.... I have the impression you guys are trying to re-invent the wheel.
perhaps we are, if there's a better wheel, why not eh
#15
Posté 27 juin 2015 - 09:12
perhaps we are, if there's a better wheel, why not eh
I don't want to discourage you, I'm simply telling you a group of folks already solved the problem. It might make sense to see what they did and how that worked. Or you might end up with a worse wheel, proverbially. ![]()
#16
Posté 27 juin 2015 - 10:39
I don't want to discourage you, I'm simply telling you a group of folks already solved the problem. It might make sense to see what they did and how that worked. Or you might end up with a worse wheel, proverbially.
while i'm not overly familiar with the add feat method that Lance appears fond of - add a feat to trigger a spellscript - I am more than merely familiar with scripting SR; the Personal Impossibility adjustor uses this technique, as adopted from Spell Fixes (Increased Challenge). However, that method is not universal - as is, it only checks creature hides (as far as i'm presently concerned or aware) and doesn't account for equipping and unequipping items, nor perhaps innate SR feats.
And the other method you've mentioned - adding a bunch of custom feats and .Uti's - doesn't appeal to me at all.
ApplySRFix() in Kaedrin's pack strikes me as the most universal and easiest to implement, at present. I think i see some minor things that can be improved in it; firsthand testing is the only way I'll convince myself though ....
http://www.stephenwo...ichard-feynman/
note that the Mayan hieroglyphs had already been decoded but Feynman liked to re-decode them for himself anyway."You should go and talk to him. Or he's going to start working on trying to decode Mayan hieroglyphs again."
few who run the 100m dash break the record
and looking hard at what others have done gives insight, but also introduces bias.
- Tchos et GCoyote aiment ceci
#17
Posté 27 juin 2015 - 04:26
Hi BartjeD and KevL,
Thanks for those link pointers BartjeD! They are most welcome, as I can check to see what has been done ... and why ... hopefully. And of course, as KevL says, this is as much about *understanding* what has gone wrong for me. I often find that whenever I have downloaded stuff to potentially use, I find there is stuff I need to rewrite for my own reasons ... or so I can understand what is happening if something else does go wrong.
EDIT: I just checked that SR hide fix that adds feats to the skins. That is not a method I would like to use, as I do not like the idea of altering blueprints to fix this. (I believe that this approach did not appeal to KevL either ... and I can understand why.)
It seems to do a different routine depending on whether oCreature is the mainPC or not. Reason? To avoid adding a Feat to mainPC?
Actually I just reasoned that creatures/monsters will simply need their SR being made permanent, so they do not need the feat version of the SR application. So, the code just checks their SR value (called from OnSpawn) and makes it permanent to the same value as it finds at time of spawning. If GetMainPC is an INVALID_OBJECT it *MUST* be a creature not played by the player. i.e. A monster or NPC.
I Also notice that no check is done for iNEWSRValue==0 if (GetMainPC(oCreature) == OBJECT_INVALID). I strongly suggest checking for (iNEWSRValue > 0) on both branches. And, if false, use a method for removing any previously applied effect, perhaps w/ a spell-Id after all ....
My explanation above (re GetMainPC) should probably explain this to you now. i.e. I do not need to check for equipping/unequipping of SR items for non-player creatures. i.e. SR equipment (which calls for the feat) is for players only. Of course, I may have to handle NPCs who wear SR equipment, but I will cross that bridge if and when I need to. For example, I may simply just give such a creature the SR on their skin to cover for the equipment they wear. After all, the creature is not going to part with such equipment unless they are dead. ;D
Ieally i'd conform the two branches - although, with some debugText, it's a good way to get feedback on which is the better routine. I guess it comes down to this: is the Feat necessary at all ?
"Is the Feat necessary at all?" ... Possibly not, (I got to the point where I did not want to think about it any more ...
), however, using the feat method has (for me at least) made it easy to distinguish between the SR sources. That was my main goal, which seems to work well. i.e. It is a simple process of removing a feat and leaving natural SR intact if need be .. or SR by any other means.
Now, I may spend a little time looking at those other "fixes" in those links, just to see what was done. ![]()
Cheers,
Lance.
#18
Posté 27 juin 2015 - 04:27
Well, I've learned more about item properties on this thread than I have in a long time. A lot easier than I was making it out to be, for sure. So much for keep it super simple, aye? ![]()
What if instead of adding a feat (and making a character "illegal" on some servers) you make it an iprp feat? Would have the same effect- I use a similar way to make warlocks keep spellcasting abilities if they have a certain feat. It's just Natural Spell in iprpfeats.2da
#19
Posté 27 juin 2015 - 04:43
Well, I've learned more about item properties on this thread than I have in a long time. A lot easier than I was making it out to be, for sure. So much for keep it super simple, aye?
What if instead of adding a feat (and making a character "illegal" on some servers) you make it an iprp feat? Would have the same effect- I use a similar way to make warlocks keep spellcasting abilities if they have a certain feat. It's just Natural Spell in iprpfeats.2da
Hi Saralach,
I may be wrong about this (as I have not had much experience of such), but I made the feat one of those ones that isn't restricted ... "HISTORICAL" I think it is. If I understood this correctly, then this type of feat is not server restricted .. unless the servers do some extra checking of course. There again, if servers adopted the idea, then they would make their own allowances accordingly. ![]()
Actually, this is what I refer to:-
FeatCategory One of *_FT_CAT, of special note are HISTORY_FT_CAT, which are ignored by the Enforce Legal Character game option. Found here:- http://nwn2.wikia.com/wiki/Feat.2da
Cheers,
Lance.
#20
Posté 27 juin 2015 - 05:19
i suggest doing a check for (srValue != 0) before constructing
effect eSR = EffectSpellResistanceIncrease(srValue);when srValue could be 0, on *either* branch
because Skywing's ASC used to/might still compile into machine code that crashes. (debugging that one was a bth) Skywing looked into it and felt that the stock compiler fudges things, like it tends to, but EffectSpellResistance(0) should probably neither be applied nor even constructed. That is, if srValue==0, just remove the previous application and let things ride - that was and is the point of my 'strong suggestion' above.
/your code ofc.
#21
Posté 27 juin 2015 - 05:47
Lance,
i suggest doing a check for (srValue != 0) before constructingeffect eSR = EffectSpellResistanceIncrease(srValue);when srValue could be 0, on *either* branch
because Skywing's ASC used to/might still compile into machine code that crashes. (debugging that one was a bth) Skywing looked into it and felt that the stock compiler fudges things, like it tends to, but EffectSpellResistance(0) should probably neither be applied nor even constructed. That is, if srValue==0, just remove the previous application and let things ride - that was and is the point of my 'strong suggestion' above.
/your code ofc.
Hi KevL,
I think I get you now .... although in the case of creatures that call the UpdateSRCondition (from their onspawn), the function is only called if the creature has SR on them, meaning srValue must be a positive figure in this instance. i.e. There is never a time this function is called for a creature (not played by a player) when they do not have SR on them. That's the idea anyway. I did not see the point of calling the function if the creature did not have some SR value in the first place.
Basically, the creature OnSpawn call is very similar to the OnEquip call for PCs, but checks their "skin" for any SR value and without any delay.
Or did I miss something else?
Cheers,
Lance.
#22
Posté 27 juin 2015 - 06:56
i don't really want to decode the code ....
so I'll just say,
ensure that instead of things like this:
int iSr = calcSr(oObject); effect eSr = EffectSpellResistanceIncrease(iSr); ApplyEffectToObject(DURATION_TYPE_PERMANENT, eSr, oObject);This:
CleanSrEffects(oObject);
int iSr = calcSr(oObject);
if (iSr > 0)
{
effect eSr = EffectSpellResistanceIncrease(iSr);
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eSr, oObject);
}( i might be interested in writing a CleanSrEffects() function ... )
#23
Posté 29 juin 2015 - 12:08
hey Lance
i don't really want to decode the code ....
so I'll just say,
ensure that instead of things like this:int iSr = calcSr(oObject); effect eSr = EffectSpellResistanceIncrease(iSr); ApplyEffectToObject(DURATION_TYPE_PERMANENT, eSr, oObject);This:CleanSrEffects(oObject); int iSr = calcSr(oObject); if (iSr > 0) { effect eSr = EffectSpellResistanceIncrease(iSr); ApplyEffectToObject(DURATION_TYPE_PERMANENT, eSr, oObject); }( i might be interested in writing a CleanSrEffects() function ... )
Hi KevL,
I see what you are getting at now ... Basically, make the function "self-contained" and "self-checking" irrespective of what data is passed to it. Therefore, if somebody pulls out the function to use, they do not have to ensure the correct data is passed in the first place. (Including myself, if I forget how I used the function originally.)
Check!
EDIT: I just added the following ....
// SAFETY CHECK AGAINST BAD FUNCTION PASS
if(iNEWSRValue == 0){return;}
Cheers,
Lance.
#24
Posté 29 juin 2015 - 08:45
else{
run(CTD);
}jk
- 4760 aime ceci
#25
Posté 30 juin 2015 - 08:52
There can indeed be more than one spell resistance Effect applied to a creature-object. That is, multiple applications accrue on target (if not removed / managed by using a spell-Id etc).
Module event "On Player Equip Item Script" is triggered for each equipped-item, including 'hidden slots', when a PC or Companion spawns into the game world. It doesn't seem to run for monsters/NPCs or Familiars though. (... assume "On Player Unequip Item Script" follows the same rules.)
GetSpellResistance() will return the SR of an equipped item, the highest value if two+ items with Spell Resistance are equipped. Or a feat's SR if highest. A scripted SR-effect returns as expected, falling in line with item-SR and feat-SR, if highest. (This implies that iterating over equipped items is merely a complication that could be replaced by using GetSpellResistance(), unless you *want* to check the item-SR values specifically.)
Present conclusion: the item-SR fix in Kaedrin's pack, or any scripts that hook via a module's Player-Equip/Unequip event, works only on PCs and Companions. Monsters & NPCs should hook a script-fix via their OnSpawn events (or some other event that fires in a way that allows iteration over their equipped items, including hides especially and whatnot).
Addenda
I. these are the spells and feats that apply/change SR (the ones I found..)
Spells.2da 124 - Nature's Balance (spell) 'nw_s0_naturebal' - decrease effect, deleted 1041 - Greater Visage of the Deity (spell) 'nx_s0_gvisage' 1124 - Inner Armor (spellability) 'nx_s2_innerarmor' 168 - Spell Resistance (spell) 'nw_s0_splresis' 1105 - Weaken Spirits (spellability) 'nx_s2_weakenspirits' - decrease effect 912 - CounterSong (bard song) 'nw_s2_sngcountr' 84 - Holy Aura (spell) 'nw_s0_holyaura' 187 - Unholy Aura (spell) 'nw_s0_unhaura' 862 - Assay Resistance (spell) 'nw_s0_assayrest' - decrease effect 122 - Mordenkainen's Disjunction (spell) 'nw_s0_morddisj' - decrease effect 98 - Lesser Spell Breach (spell) 'nw_s0_lsspbrch' - decrease effect 72 - Greater Spell Breach (spell) 'nw_s0_grspbrch' - decrease effect Feat.2da (all these appear to be hardcoded, based on having SpellID = "****") 699 - 708 - Epic Improved Spell Resistances 1075 - Drow Resistance 1078 - Svirfneblin Resistance 1085 - Aasimar Resistance 1089 - Tiefling Resistance 1495 - Group Spell Resistance 1833 - Gith Resistance 1868 - 1871 - Genasi Resistances 2091 - Hagspawn Resistance 2118 - Racial Spell Resistance 2171 - Spell Resistance 2189 - Fiendish Resistance 215 - Diamond Soul 36 - Spell Penetration 401 - Greater Spell Penetration 618 - Epic Spell PenetrationII. further reading at NwN2.wiki
Spell Resistance
III. see also Saralach's efforts for warlocks - which I believe addresses special issues re. Invocations





Retour en haut







