Spell Resistance - Working Solution
#51
Posté 04 juillet 2015 - 11:59
done. I had the return from the 2da as iSR when it should be iTest
edit: which leads me to see a hole in all this. If an item has, say, a permanent SR value and somehow gets a higher temporary IP applied to it ... the corresponding effect-SR may or may not be updated (depending on who has it and whether it gets equipped/unequipped).
If it (the item) gets an ip-SpellResistance applied while equipped, which is unlikely since I don't think there's any stock method of doing that, its SR if highest will last only once and then fall back on the previous SR value, if available. (unless it's unequipped and re-equipped etc.)
If a new ip is lower and the original ip is a temporary, then when the temporary wears off the item becomes bugged gain. Anyway ... it's an obscure minutia. /shrug
The only real solution is a fast heartbeat (short of source code), and neither of those is gonna happen i figur.
#52
Posté 06 juillet 2015 - 11:09
I sorta freaked out when i first saw a negative spell-Id also. But i've since concluded that a "spellId" is just a signed integer value (likely four bytes, allowing for values -2147483648 to 2147483647). by making it negative, Kaedrin -- it's the value used in the kPrc Pack -- guarantees there won't be a conflict with any Spells.2da entry.
To take another example of spell-Id usage: another section in my PlayerEquip/Unequip handles a reduction to Reflex Saves based on ACP (Armor Check Penalty). I use an arbitrary spell-Id of "74925" for EffectSavingThrowDecrease() ... long time before Spells.2da gets *that* big.
Ah! So are you saying that you are simply using the *value* BUT NOT adding anything to a 2da file? I get that if that is the case.
am pretty sure the delay is required on only the Unequip phase. Tests: the unequip event fires before the equip event, but since the unequip event is delayed all necessary item changes have occurred and the tests say SR is properly accounted for as is.
That makes sense to me. I think I must have delayed the original OnEquip for something else then. I may have other checks going on that I did not want to affect before the SR took hold or something.
ps. Oh dang, you're getting me in the mood to work on my module again ....
That's a good thing right!
edit: which leads me to see a hole in all this. If an item has, say, a permanent SR value and somehow gets a higher temporary IP applied to it ... the corresponding effect-SR may or may not be updated (depending on who has it and whether it gets equipped/unequipped).
I don't think I will ever have a temporary IP (SR) applied to any item anyway.
Cheers,
Lance.
#53
Posté 06 juillet 2015 - 01:30
Ah! So are you saying that you are simply using the *value* BUT NOT adding anything to a 2da file? I get that if that is the case.
yes, no 2da change req'd. Just slap on a spell-Id when constructing the effect.
That's a good thing right!
it's really a wonderful environment (except when its not..)
I don't think I will ever have a temporary IP (SR) applied to any item anyway.
reminder: if you have Crafting, the caching for IP values may need an extra poke at times ....
#54
Posté 07 juillet 2015 - 02:05
Something to note from my own tests, IP SR overrides any SR from EffectSpellResistanceIncrease. Something that could be done would be setting a local int in the spell and checking that SR int vs the item properties. I haven't messed with any of the feat based SR's yet though. Working through a check could make BG spells like Lower Resistance viable in game. Had some ideas on how to implement my SR code with these checks and remove the need to specify the level. Will try them tomorrow after work.
#55
Posté 07 juillet 2015 - 02:11
Something to note from my own tests, IP SR overrides any SR from EffectSpellResistanceIncrease.
can you be more specific?
Do you mean that when a low-SR item is equipped and a high-SR effect are both active, that GetSpellResistance() -- or perhaps something more internal to the game-engine -- uses the item-SR ?
#56
Posté 07 juillet 2015 - 03:46
Used a test armor with SR 20 and then used a test script that increases the SR to 25, GetSpellResistance() returns 20 instead. Without the armor, the SR updates as it should. It seems like it's looking for an item instead of an effect. Will have to check on feats as well.
#57
Posté 07 juillet 2015 - 05:23
in all my tests, including the one i just did, GetSpellResistance() always returns the highest value of Item, Effect, or Feat.
using MainPC as my test object,
haven't tested ResistSpell() at all tho.
#58
Posté 07 juillet 2015 - 08:55
Still reading with interest ... Have a major bug in my AI code at the moment that I am trying to sort, so cannot test this further just yet. Except to say, I have not experienced the lower SR return when there were any conflicts ... yet.
Major bug now sorted .... Henchman were having a variable added they should not have done and was preventing them from accepting any commands!
Cheers,
Lance.
#59
Posté 07 juillet 2015 - 06:21
Well, this is strange. I'm not able to duplicate the results. Either the game was being wonky or I needed sleep. It's working as it should now... I blame the cat stepping on my keyboard..
#60
Posté 07 juillet 2015 - 10:10
- GCoyote, kamal_ et Saralach aiment ceci
#61
Posté 08 juillet 2015 - 12:01
#62
Posté 23 juillet 2015 - 10:02
you've probably got this covered; what follows is rather for general use
worked a few bugs/ glitches/ anomalies out ...
// 'fixitemsr'
const int ID_EFFECT_srFix = -4000;
// public
void FixItemSR(object oCreature = OBJECT_SELF);
// private
void FixItemSRDelay(object oCreature);
//
void FixItemSR(object oCreature = OBJECT_SELF)
{
if (!GetLocalInt(oCreature, "doSrFix"))
{
SetLocalInt(oCreature, "doSrFix", TRUE);
DelayCommand(0.f, FixItemSRDelay(oCreature));
}
}
//
void FixItemSRDelay(object oCreature)
{
DeleteLocalInt(oCreature, "doSrFix");
effect eSrFix = GetFirstEffect(oCreature);
while (GetIsEffectValid(eSrFix))
{
if (GetEffectSpellId(eSrFix) == ID_EFFECT_srFix)
{
RemoveEffect(oCreature, eSrFix);
eSrFix = GetFirstEffect(oCreature);
}
else
eSrFix = GetNextEffect(oCreature);
}
object oItem;
itemproperty ipProp;
int
iSr = 0,
iSrTest;
int iSlot;
for (iSlot = INVENTORY_SLOT_HEAD; iSlot < NUM_INVENTORY_SLOTS; ++iSlot)
{
oItem = GetItemInSlot(iSlot, oCreature);
if (GetIsObjectValid(oItem))
{
ipProp = GetFirstItemProperty(oItem);
while (GetIsItemPropertyValid(ipProp))
{
if (GetItemPropertyType(ipProp) == ITEM_PROPERTY_SPELL_RESISTANCE)
{
iSrTest = GetItemPropertyCostTableValue(ipProp);
iSrTest = StringToInt(Get2DAString("iprp_srcost", "Value", iSrTest));
if (iSr < iSrTest)
iSr = iSrTest;
}
ipProp = GetNextItemProperty(oItem);
}
}
}
if (iSr > 0)
{
eSrFix = EffectSpellResistanceIncrease(iSr);
eSrFix = SupernaturalEffect(eSrFix);
eSrFix = SetEffectSpellId(eSrFix, ID_EFFECT_srFix);
DelayCommand(0.f, ApplyEffectToObject(DURATION_TYPE_PERMANENT, eSrFix, oCreature));
}
}This method seems to address issues concerning GUI icons not updating correctly, as well as the fact the onEquip event fires off multiple times when starting a game, reloading a save, or simply when a player-like object enters the world (roster-member or PC). No delays are needed in the calls from the onEquip or onUnequip scripts, or when called from anywhere else -- just let the local_int do its trick.NOTE, The idea above ought work for various of the itemproperty-fixes hashed over the past few weeks.
bonus pts for hooking this up to the 'partyselect' Accept btn
// 'gui_refresh_effects'
//
// Refreshes various fixes on all party members when the Accept button is
// clicked in the 'partyselect' scene.
#include "fixitemsr"
void main()
{
object oPC = OBJECT_SELF;
object oFM = GetFirstFactionMember(oPC, FALSE);
while (GetIsObjectValid(oFM))
{
if (GetAssociateType(oFM) == ASSOCIATE_TYPE_NONE)
FixItemSR(oFM);
oFM = GetNextFactionMember(oPC, FALSE);
}
}(note that does not cover roster members joining the party via dialog or alternate scripts)additional: inject into RaiseDead and Resurrect spellscripts
if (GetIsObjectValid(GetFactionLeader(oTarget))
&& GetAssociateType(oTarget) == ASSOCIATE_TYPE_NONE)
{
FixItemSR(oTarget);
}I did fairly extensive testing with PC and companions, and i suspect that a call to FixItemSR() in the onSpawn of NPCs and monsters should work fine also. Associates in a saved game, however, could still be problematic ... idk.
#63
Posté 24 juillet 2015 - 10:15
Lance,
you've probably got this covered; what follows is rather for general use
worked a few bugs/ glitches/ anomalies out ...// 'fixitemsr' const int ID_EFFECT_srFix = -4000; // public void FixItemSR(object oCreature = OBJECT_SELF); // private void FixItemSRDelay(object oCreature); // void FixItemSR(object oCreature = OBJECT_SELF) { if (!GetLocalInt(oCreature, "doSrFix")) { SetLocalInt(oCreature, "doSrFix", TRUE); DelayCommand(0.f, FixItemSRDelay(oCreature)); } } // void FixItemSRDelay(object oCreature) { DeleteLocalInt(oCreature, "doSrFix"); effect eSrFix = GetFirstEffect(oCreature); while (GetIsEffectValid(eSrFix)) { if (GetEffectSpellId(eSrFix) == ID_EFFECT_srFix) { RemoveEffect(oCreature, eSrFix); eSrFix = GetFirstEffect(oCreature); } else eSrFix = GetNextEffect(oCreature); } object oItem; itemproperty ipProp; int iSr = 0, iSrTest; int iSlot; for (iSlot = INVENTORY_SLOT_HEAD; iSlot < NUM_INVENTORY_SLOTS; ++iSlot) { oItem = GetItemInSlot(iSlot, oCreature); if (GetIsObjectValid(oItem)) { ipProp = GetFirstItemProperty(oItem); while (GetIsItemPropertyValid(ipProp)) { if (GetItemPropertyType(ipProp) == ITEM_PROPERTY_SPELL_RESISTANCE) { iSrTest = GetItemPropertyCostTableValue(ipProp); iSrTest = StringToInt(Get2DAString("iprp_srcost", "Value", iSrTest)); if (iSr < iSrTest) iSr = iSrTest; } ipProp = GetNextItemProperty(oItem); } } } if (iSr > 0) { eSrFix = EffectSpellResistanceIncrease(iSr); eSrFix = ExtraordinaryEffect(eSrFix); eSrFix = SetEffectSpellId(eSrFix, ID_EFFECT_srFix); DelayCommand(0.f, ApplyEffectToObject(DURATION_TYPE_PERMANENT, eSrFix, oCreature)); } }This method seems to address issues concerning GUI icons not updating correctly, as well as the fact the onEquip event fires off multiple times when starting a game, reloading a save, or simply when a player-like object enters the world (roster-member or PC). No delays are needed in the calls from the onEquip or onUnequip scripts, or when called from anywhere else -- just let the local_int do its trick.
NOTE, The idea above ought work for various of the itemproperty-fixes hashed over the past few weeks.
bonus pts for hooking this up to the 'partyselect' Accept btn// 'gui_refresh_effects' // // Refreshes various fixes on all party members when the Accept button is // clicked in the 'partyselect' scene. #include "fixitemsr" void main() { object oPC = OBJECT_SELF; object oFM = GetFirstFactionMember(oPC, FALSE); while (GetIsObjectValid(oFM)) { if (GetAssociateType(oFM) == ASSOCIATE_TYPE_NONE) FixItemSR(oFM); oFM = GetNextFactionMember(oPC, FALSE); } }(note that does not cover roster members joining the party via dialog or alternate scripts)
additional: inject into RaiseDead and Resurrect spellscriptsif (GetIsObjectValid(GetFactionLeader(oTarget)) && GetAssociateType(oTarget) == ASSOCIATE_TYPE_NONE) { FixItemSR(oTarget); }I did fairly extensive testing with PC and companions, and i suspect that a call to FixItemSR() in the onSpawn of NPCs and monsters should work fine also. Associates in a saved game, however, could still be problematic ... idk.
Hi KevL,
That seems quite a bit of coding there ... Maybe its because you are applying the fix via "spellID" rather than "feat" application to apply item SR? Can you give me a single specific definitive test to try using my own method that will demonstrate the issues you were having? e.g. You mention "staring a game", but under what circumstances did you notice problems ... and maybe I can double check my own method. (I am always a bit wary regarding application via spells due to the sensitivity of them. I have noticed one or two applications of spell like requirements requiring special attention when a character dies, therefore, it may be that you are referring to. I do not experience that with the "Item feat" method for SR if I recall correctly.)
Cheers,
Lance.
#64
Posté 24 juillet 2015 - 01:11
one was that during entry the onEquip event rapidly fires for each equip. That created as many instances of the fix-effect as there are items equipped. And left them there until an item was slotted or unslotted manually -- then it would fix itself.
The other was that, roughly speaking, when "removing-recalculating-applying" the fix-effect inside the space of one function, the GUI effect icon (at the partybar and on the charactersheet) would appear, then disappear, then appear, then disappear each time items were swapped in/out
Behind the scenes, however, neither of those affected the effectiveness of the fix -- the latter being a cosmetic glitch and the former a multiple-redundancy.
the bite for me was that a simple fix for one caused the other to bork & vice versa.
To test your own: the cosmetic glitch is obvious when swapping in and out two items that both require the fix, on the same equipment slot; just swap them in and out a few times (w/ double-clicks) and watch the icons. And to check for redundant applications of the fix-effect, run my testeffect script right after starting a game, maybe loading a savedgame, or having an NPC join the Roster, etc. (i noticed each of those is slightly different, regarding what events fire) If there are multiple effects of the same type (#52 iirc), the testeffect script will show it (after a bit of interpretation*).
*a guy might be surprised by how many seemingly redundant effects show up after only a few Cleric buffs ... so, uh, don't confuse them.
/cheers
#65
Posté 24 juillet 2015 - 05:12
Hi KevL,
UPDATE: FIXED ... I believe (See below).
Thanks for bringing my attention to this (again). ![]()
I need to clarify some points, but it looks like there may still be a problem with my own method too .... ![]()
First, can you explain to me a little about what I am seeing with your "testeffect" script, as (as you say), the results surprised me a little at first. For instance, I do indeed see a number of "residual" SR (52) effects remaining on the PC ... implying the effect is still in place even after removing said item/feat.
Is that the case?
If so, then I suffer with the same issues due to the effect not being removed properly on an item swap/equip when already equipped.
I am going to take a closer look at your script and my own now.
EDIT: I don't suffer any "visual" problems, as the feat icon adds or removes quite cleanly and without any duplication. However, the SR score on the character sheet does end up being incorrect (due to residual effect on same item swap).
EDIT 2: OK, it appeared to be a relatively simple fix for my own system .... Check out the relevant bit of code ... and the new commented section.
// HAS THE "ITEM SR" FEAT (AND NEEDS REMOVING)
//if(GetHasFeatEffect(2893, oCreature) && iNEWSRValue == 0)
//{
FeatRemove(oCreature, 2893);
//}
Basically, I went back to removing the feat regardless of new state and forcing the new update afresh. I did not notice any significant issue with icons display ... perhaps a momentary flicker, hardly noticeable, and to be expected during the brief moment during the exchange.
(I have updated the main scripts on the previous forum page.)
Cheers,
Lance.
#66
Posté 24 juillet 2015 - 09:13
First, can you explain to me a little about what I am seeing with your "testeffect" script, as (as you say), the results surprised me a little at first. For instance, I do indeed see a number of "residual" SR (52) effects remaining on the PC ... implying the effect is still in place even after removing said item/feat.
re. testeffect + multiple applications
- if all values for two or more effects are identical, it's/ was bugged.
I get a flicker sometimes too ... although DelayCommand(0.f) helps a lot
( it's a way to tell the engine: Don't do this right away but as quick as you can! ie, not during event execution itself but as soon as the core engine-loop gets a return from said event -- if my guess is right, it's a
#67
Posté 24 juillet 2015 - 10:52
re. testeffect + multiple applications
- if all values for two or more effects are identical, it's/ was bugged.
I get a flicker sometimes too ... although DelayCommand(0.f) helps a lot
( it's a way to tell the engine: Don't do this right away but as quick as you can! ie, not during event execution itself but as soon as the core engine-loop gets a return from said event -- if my guess is right, it's alegitimate exploitsolid lever )
Hi KevL,
Well, hopefully, that means the SR is no longer bugged, as I no longer have the duplication, implying it was still in place from a previous application ... so that sounds all good now.
Thanks for pointing this out again.
Cheers,
Lance.
#68
Posté 24 juillet 2015 - 10:59
now i got a bunch of other things to do - like that ipImmunity fix .....
+ urge to finish Fanglewood.
- GCoyote aime ceci
#69
Posté 25 juillet 2015 - 11:22
np Lance,
now i got a bunch of other things to do - like that ipImmunity fix .....
+ urge to finish Fanglewood.
Ah yes ... another campaign I intend to play ... I may just take a break and play some after this module is out before starting module 2. But then again, I always thinks that.
EDIT: Actually, that is one I did start and have a saved game at "Saints Temple". So maybe I can continue that myself at some point.
Cheers,
Lance.





Retour en haut






