Author Topic: Need to Hook into Spell Resistance  (Read 1718 times)

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
Need to Hook into Spell Resistance
« Reply #30 on: August 27, 2011, 06:54:57 am »


               

WhiZard wrote...

ShaDoOoW wrote...

I cant use new lines in TLK for reasons I already explained. Also you cannot set custom token 0 and 1.


Looked into this and you can "set" both manually simply by replacing that part of the string.  (E.g. "<....0>" can be replaced with a name and "<...1>" can be replaced with the string resrefs above, and this works for any language.

Seriously? You tried that?

If you manually replace <CUSTOM0> for name then whole text will be in the server's language and not multilanguaged. In order to send to PC text from his own talk table you ust use one of the "ByStrRef" functions.

Also that still doesnt solve second feedback. Which my solution does.

EDIT The occurrence of the double line may also be mitigated if the
underwent a temporary decrease by its current magnitude (i.e. all but
monks would have an SR of 0 and thus the non-monks would never have the
double line).

Already suggesting this and you thought its a bad solution.
               
               

               


                     Modifié par ShaDoOoW, 27 août 2011 - 06:35 .
                     
                  


            

Legacy_FunkySwerve

  • Hero Member
  • *****
  • Posts: 2325
  • Karma: +0/-0
Need to Hook into Spell Resistance
« Reply #31 on: August 27, 2011, 10:02:16 am »


               

WhiZard wrote...

Does SR and specific spell immunity before mantles, but spell immunity by level and/or school after mantles.  Also does a double line for not making the custom SR roll but making the ResistSpell() roll. 

Is this supposed to be a critique? A question?

Are its messages straight TLK lines?


No, they're custom. They're sorted according to chat-command-toggleable 'pc option' settings, allowing our casters to filter out all combat info save spell pen (and other things, like saves), and to select terse/verbose output:


struct SubString GetSpellResistanceMessage (object oCaster, object oTarget, int nRoll, int nSP, int nSR) {
    struct SubString ss;
    int bCasterBrief = GetPCFilter(oCaster, PCFILTER_BRIEF);
    int bTargetBrief = GetPCFilter(oTarget, PCFILTER_BRIEF);

    string sCaster = (bCasterBrief ? "SP" : "Spell Penetration");
    string sTarget = (bTargetBrief ? "SR" : "Spell Resistance");


    if (nSR == -2) {
        ss.first = C_TEAL + GetName(oTarget) + " : " + sCaster + " : *immune*" + C_END;
        ss.rest  = C_TEAL + GetName(oCaster) + " : " + sTarget + " : *immune*" + C_END;
    } else if (nSR == -3) {
        ss.first = C_TEAL + GetName(oTarget) + " : " + sCaster + ": *absorbed*" + C_END;
        ss.rest  = C_TEAL + GetName(oCaster) + " : " + sTarget + ": *absorbed*" + C_END;
    } else {
        string sCasterRoll = "(" + IntToString(nRoll) + " + " + IntToString(nSP) +
            " = " + IntToString(nRoll + nSP) + (bCasterBrief ? " / " : " vs. SR: " ) +
            IntToString(nSR) + ")";
        string sTargetRoll = "(" + IntToString(nRoll) + " + " + IntToString(nSP) +
            " = " + IntToString(nRoll + nSP) + (bTargetBrief ? " / " : " vs. SR: " ) +
            IntToString(nSR) + ")";

        if (nSP + nRoll >= nSR) {
            ss.first = C_TEAL + GetName(oTarget) + " : " + sCaster + " : *success* : "  + sCasterRoll + C_END;
            ss.rest  = C_TEAL + GetName(oCaster) + " : " + sTarget + " : *defeated* : " + sTargetRoll + C_END;
        } else {
            ss.first = C_TEAL + GetName(oTarget) + " : " + sCaster + " : *failure* : "  + sCasterRoll + C_END;
            ss.rest  = C_TEAL + GetName(oCaster) + " : " + sTarget + " : *resisted* : " + sTargetRoll + C_END;
        }
    }

    return ss;
}

void SendSpellResistanceMessage (object oCaster, object oTarget, int nRoll, int nSP, int nSR, float fDelay=0.0) {
    struct SubString ss = GetSpellResistanceMessage(oCaster, oTarget, nRoll, nSP, nSR);

    switch (GetPCFilter(oCaster, PCFILTER_SPELLPEN)) {
        case 0: DelayCommand(fDelay, SendMessageToPC(oCaster, ss.first));                     break;
        case 1: DelayCommand(fDelay, SendSystemMessage(oCaster, ss.first));                   break;
        case 2: DelayCommand(fDelay, FloatingTextStringOnCreature(ss.first, oCaster, FALSE)); break;
    }

    switch (GetPCFilter(oTarget, PCFILTER_SPELLPEN)) {
        case 0: DelayCommand(fDelay, SendMessageToPC(oTarget, ss.rest));                      break;
        case 1: DelayCommand(fDelay, SendSystemMessage(oTarget, ss.rest));                    break;
        case 2: DelayCommand(fDelay, FloatingTextStringOnCreature(ss.rest, oTarget, FALSE));  break;
    }
}

Funky
               
               

               


                     Modifié par FunkySwerve, 27 août 2011 - 09:02 .
                     
                  


            

Legacy_WhiZard

  • Hero Member
  • *****
  • Posts: 2149
  • Karma: +0/-0
Need to Hook into Spell Resistance
« Reply #32 on: August 27, 2011, 10:10:02 am »


               
Quote
ShaDoOoW wrote...

Quote
WhiZard wrote...

Quote
ShaDoOoW wrote...

I cant use new lines in TLK for reasons I already explained. Also you cannot set custom token 0 and 1.


Looked into this and you can "set" both manually simply by replacing that part of the string.  (E.g. "<....0>" can be replaced with a name and "<...1>" can be replaced with the string resrefs above, and this works for any language.

Seriously? You tried that?

If you manually replace <CUSTOM0> for name then whole text will be in the server's language and not multilanguaged. In order to send to PC text from his own talk table you ust use one of the "ByStrRef" functions.

Also that still doesnt solve second feedback. Which my solution does.

The name of the character would not change from one language to another.  Regardless of the language there are two custom tokens within TLK line 8342.  The token "<....0>" is replaced with the character name, the token "<...1>" is replaced with one of the TLK lines 8343, 8344, 8345, or 5353.

Quote
EDIT The occurrence of the double line may also be mitigated if the
underwent a temporary decrease by its current magnitude (i.e. all but
monks would have an SR of 0 and thus the non-monks would never have the
double line).
Already suggesting this and you thought its a bad solution.

[/quote]
Never said good or bad to that specific one.
               
               

               


                     Modifié par WhiZard, 27 août 2011 - 09:11 .
                     
                  


            

Legacy_WhiZard

  • Hero Member
  • *****
  • Posts: 2149
  • Karma: +0/-0
Need to Hook into Spell Resistance
« Reply #33 on: August 27, 2011, 10:15:30 am »


               

FunkySwerve wrote...

WhiZard wrote...

Does SR and specific spell immunity before mantles, but spell immunity by level and/or school after mantles.  Also does a double line for not making the custom SR roll but making the ResistSpell() roll. 

Is this supposed to be a critique? A question?


More of an observation, that this is pretty much what is being discussed.  No distinct special changes that give further significant insight into functionality.
               
               

               
            

Legacy_the.gray.fox

  • Full Member
  • ***
  • Posts: 214
  • Karma: +0/-0
Need to Hook into Spell Resistance
« Reply #34 on: August 27, 2011, 10:47:59 am »


               _Guile

SpellResistance checks, SpellImmunity checks and SpellAbsorption checks can all be scripted to do what-ever you want. You can replicate the NWN hardcoded counterparts down to their last detail, and transfer full control of them to the script layer -- as I did.
You can even do it so well that a Player may not tell the difference between your scripts and the NWN engine doings, unless you want it to show off.

The question is: how much time and fatigue are you willing to slave on it?
As it has been said: it is no simple, nor quick thing.

If you are still into it, take a look at my [Fox Spells] scripts to see how I did.


-fox
               
               

               
            

Legacy__Guile

  • Hero Member
  • *****
  • Posts: 1308
  • Karma: +0/-0
Need to Hook into Spell Resistance
« Reply #35 on: August 27, 2011, 01:57:02 pm »


               

the.gray.fox wrote...

_Guile

SpellResistance checks, SpellImmunity checks and SpellAbsorption checks can all be scripted to do what-ever you want. You can replicate the NWN hardcoded counterparts down to their last detail, and transfer full control of them to the script layer -- as I did.
You can even do it so well that a Player may not tell the difference between your scripts and the NWN engine doings, unless you want it to show off.

The question is: how much time and fatigue are you willing to slave on it?
As it has been said: it is no simple, nor quick thing.

If you are still into it, take a look at my [Fox Spells] scripts to see how I did.


-fox


TY Fox, I like how you talk to people, directly, furthermore your question is a most excellent answer as well, as the truth to be told is, I already had a good idea I could do it, but I didn't know just how nausious it was going to make me to try to do it, so now that I have smelled the coffee, I will gracefully decline. '<img'>

Thanks again..
               
               

               
            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
Need to Hook into Spell Resistance
« Reply #36 on: August 28, 2011, 07:32:29 pm »


               

WhiZard wrote...

The name of the character would not change from one language to another.  Regardless of the language there are two custom tokens within TLK line 8342.  The token "<....0>" is replaced with the character name, the token "<...1>" is replaced with one of the TLK lines 8343, 8344, 8345, or 5353.

Please try things you are suggesting before you suggest them. This wont work of course.
               
               

               


                     Modifié par ShaDoOoW, 28 août 2011 - 06:32 .
                     
                  


            

Legacy_WhiZard

  • Hero Member
  • *****
  • Posts: 2149
  • Karma: +0/-0
Need to Hook into Spell Resistance
« Reply #37 on: August 28, 2011, 09:04:21 pm »


               

ShaDoOoW wrote...

WhiZard wrote...

The name of the character would not change from one language to another.  Regardless of the language there are two custom tokens within TLK line 8342.  The token "<....0>" is replaced with the character name, the token "<...1>" is replaced with one of the TLK lines 8343, 8344, 8345, or 5353.

Please try things you are suggesting before you suggest them. This wont work of course.


It does and has.
               
               

               
            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
Need to Hook into Spell Resistance
« Reply #38 on: August 29, 2011, 11:33:29 am »


               No it doesnt. You probably didnt tried it properly in the multilanguage environment. If you tried it at all which I doubt. You just throwing out ideas there but It seems you didnt take any work to tried and proof them.

So again.

The only way how to send the player multilanguaged text is to use ByStrRef function. This is the only way how to force client to use text from his TLK.

If you do something like this:

string sFeedback = GetStringByStrRef(8342);

You get this text in the language installed on server. If you then do any modification you want, its already in the server language and you cannot send it to the client by the function SendMessageToPCByStrRef anymore. This means that if the client has german language and server has english, client will see text in the the server's language.

Even if you would change the default text in TLK to the <CUSTOM532> and then set the CUSTOM token to something before you send it to the client you still cant set multilanguaged string to the custom token.
               
               

               
            

Legacy_WhiZard

  • Hero Member
  • *****
  • Posts: 2149
  • Karma: +0/-0
Need to Hook into Spell Resistance
« Reply #39 on: August 29, 2011, 09:31:37 pm »


               

ShaDoOoW wrote...

No it doesnt. You probably didnt tried it properly in the multilanguage environment.


That was it.  Had a friend upload my scripts unfortunately I later found out he was using English TLK.
               
               

               
            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
Need to Hook into Spell Resistance
« Reply #40 on: September 02, 2011, 10:20:20 am »


               

WhiZard wrote...

This might be a helpful function to use for custom SR checks.  The spell resistance part comes before the spell level absorption.


int DoResistSpell(object oCaster, object oTarget, int nCaster = -100)
{
if(nCaster == -100) nCaster = GetCasterLevel(oCaster);  //Allows preset caster level
int nRoll = nCaster + d20();
int nSR = GetSpellResistance(oTarget);
if(GetHasFeat(FEAT_EPIC_SPELL_PENETRATION, oCaster)) nRoll += 6;
else if(GetHasFeat(FEAT_GREATER_SPELL_PENETRATION, oCaster)) nRoll += 4;
else if(GetHasFeat(FEAT_SPELL_PENETRATION, oCaster)) nRoll +=2;
if(nRoll >= nSR || !nSR)  //0 SR opponents get hit
  {
  FloatingTextStringOnCreature("Spell resistance: spell resisted", oCaster, FALSE);
  FloatingTextStringOnCreature("Spell resistance: spell resisted", oTarget, FALSE);
  return 1;
  }
int nResist = ResistSpell(oCaster, oTarget);
if(nResist == 1)
  {
  FloatingTextStringOnCreature("Spell bypassed resistance", oCaster, FALSE);
  FloatingTextStringOnCreature("Spell bypassed resistance", oTarget, FALSE);
  nResist = 0;
  }
return nResist;
}

So Im working on my patch again and I reconsidered yours suggestions. Since I already use the same fake feedback as you suggested for spell immunity I guess it wouldnt be problem however, two feedback are problem for me.

Also I especially need this order of the SpellResist function: spell immunity, spell absorbtion, spell resistance, not spell resistance first. (default is spell absorption, spell immunity, spell resistance I made a workaround for this like yours above).

So any other ideas how to do it? Or how to make the message Name: immune to magic message multilanguaged?

Total rewrite isnt probably possible as I dont want alter every spell in way that it become impossible to understand by unexperienced scripter, and I doubt it can be done truly invisible.

So if anyone have idea now is good time, now I ask so you may throw ideas and I wont be mad.
               
               

               
            

Legacy_WhiZard

  • Hero Member
  • *****
  • Posts: 2149
  • Karma: +0/-0
Need to Hook into Spell Resistance
« Reply #41 on: September 02, 2011, 02:46:18 pm »


               

ShaDoOoW wrote...
Also I especially need this order of the SpellResist function: spell immunity, spell absorbtion, spell resistance, not spell resistance first. (default is spell absorption, spell immunity, spell resistance I made a workaround for this like yours above).


Immunity first is a bear as the standard functions won't get spell immunity from EffectSpellLevelAbsorption()  (i.e. the immunity to spells of a school, and/or a level or less).  These pop up in a host of spells (shadow shield, globes, ghostly visage, ethereal visage), and polymorphs can often have associated item properties (e.g. polymorph self: fey, outsider shape: rakshasa).  If you manage to solve the immunity part, then you would likely also have a system for the absorption part.

As for multilanguaged there aren't too many line options given <custom token> replacements are not viable except in single player.  If you are okay with it you could use 8343-8345 all by themselves; they wouldn't tell who cast what spell on whom, but would tell how the spell failed to effect the target.  Given your intended ordering, you wouldn't use ResistSpell() anyways, so there would not be a problem with a double line.
               
               

               
            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
Need to Hook into Spell Resistance
« Reply #42 on: September 02, 2011, 03:07:42 pm »


               Well the immunity part is already covered in my half a year old version at vault. Yes its not multilanguaged and if someone thought about way how to make it multilanguaged it would be great but well its a minor issue. I guess I havent expressed myself very well so:

What I want to help with is the caster level increase issue. My solution decreases SR of the creature before using ResistSpell function which doenst work on monks as you said. So im looking for better option. I can fake a feedback like I did for immunity but I dont want to have two feedbacks and I also need this order: immunity - absorption - spell resist.

I see no other way so I take any idea, there is current code:


int MyResistSpell(object oCaster, object oTarget, float fDelay = 0.0)
{
 if(fDelay > 0.5)
 {
 fDelay -= 0.1;
 }                        //aoe spells workaround
int bImmunity, nSpellId = GetEffectSpellId(EffectDazed());
//Shadoow for 1.70: spell immunity goes before spell absorption
 if((GetHasSpellEffect(SPELL_LESSER_SPELL_MANTLE,oTarget) ||
     GetHasSpellEffect(SPELL_SPELL_MANTLE,oTarget) ||
     GetHasSpellEffect(SPELL_GREATER_SPELL_MANTLE,oTarget)) && (
     GetHasSpellEffect(SPELL_MINOR_GLOBE_OF_INVULNERABILITY,oTarget) ||
     GetHasSpellEffect(SPELL_GREATER_SHADOW_CONJURATION_MINOR_GLOBE,oTarget) ||
     GetHasSpellEffect(SPELL_GLOBE_OF_INVULNERABILITY,oTarget) ||
     GetHasSpellEffect(SPELL_GHOSTLY_VISAGE,oTarget) ||
     GetHasSpellEffect(SPELLABILITY_AS_GHOSTLY_VISAGE,oTarget) ||
     GetHasSpellEffect(SPELL_GREATER_SHADOW_CONJURATION_MIRROR_IMAGE,oTarget) || //shadow ghostly visage
     GetHasSpellEffect(SPELL_ETHEREAL_VISAGE,oTarget)))
 {
 int nMaxLevel = 1;
  if(GetHasSpellEffect(SPELL_ETHEREAL_VISAGE,oTarget))
  {
  nMaxLevel = 2;
  }
  if(GetHasSpellEffect(SPELL_MINOR_GLOBE_OF_INVULNERABILITY,oTarget) || GetHasSpellEffect(SPELL_GREATER_SHADOW_CONJURATION_MINOR_GLOBE,oTarget))
  {
  nMaxLevel = 3;
  }
  if(GetHasSpellEffect(SPELL_GLOBE_OF_INVULNERABILITY,oTarget))
  {
  nMaxLevel = 4;
  }
 string sCollumn = "Innate";
  switch(GetLastSpellCastclass())
  {
  case class_TYPE_WIZARD:
  case class_TYPE_SORCERER:
  sCollumn = "Wiz_Sorc";
  break;
  case class_TYPE_CLERIC:
  sCollumn = "Cleric";
  break;
  case class_TYPE_DRUID:
  sCollumn = "Druid";
  break;
  case class_TYPE_BARD:
  sCollumn = "Bard";
  break;
  case class_TYPE_RANGER:
  sCollumn = "Ranger";
  break;
  case class_TYPE_PALADIN:
  sCollumn = "Paladin";
  break;
  }
 sCollumn = Get2DAString("spells",sCollumn,nSpellId);
  if(sCollumn != "")
  {
  bImmunity = StringToInt(sCollumn) <= nMaxLevel;
  }
 }
 if(!bImmunity && nSpellId == SPELL_MAGIC_MISSILE && GetHasSpellEffect(SPELL_SHIELD,oTarget))
 {
 bImmunity = TRUE;//magic missile on target with Shield spell effect
 }                                                                                   //polymorph - pixie
 if(!bImmunity && (GetHasSpellEffect(SPELL_SHADOW_SHIELD,oTarget) || GetHasSpellEffect(390,oTarget)))
 {
 string sSchool = Get2DAString("spells","School",nSpellId);
  if(GetHasSpellEffect(SPELL_SHADOW_SHIELD,oTarget))
  {
  bImmunity = sSchool == "N";//Necromantic spell cast at target with Shadow Shield
  }
  if(!bImmunity && GetHasSpellEffect(390,oTarget))
  {
  bImmunity = sSchool == "E";//Enchantment spell cast at target polymorphed into pixie
  }
 }
 //spell should be resisted via various spell immunity!
 if(bImmunity)
 {
 //engine workaround to print "immunity feedback"
 string sFeedback = GetStringByStrRef(8342);//this will work pretty well for singleplayer
 sFeedback = GetStringLeft(sFeedback,GetStringLength(sFeedback)-10);//but if would someone with non-english language
 sFeedback = GetStringRight(sFeedback,GetStringLength(sFeedback)-10);//played english server, then this immunity
 sFeedback = "<c›ţţ>"+GetName(oTarget)+"</c> <cÍÅ£>"+sFeedback+" "+GetStringByStrRef(8344)+"</c>";//feedback will be
 SendMessageToPC(oTarget,sFeedback);//in english, while normally it would be in his language...
 SendMessageToPC(oCaster,sFeedback);
 DelayCommand(fDelay,ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectVisualEffect(VFX_IMP_GLOBE_USE),oTarget));
 return 2;
 }
//Shadooow for 1.70: caster level override workaround, since ResistSpell function uses its own values
//and its hardcoded I apply a spell resistance decrease in the appropriate ammount in order to cheat
//this hardcoded function. This works pretty well for non-monks. 12+ lvl monks are immune to this solution.
int clOverride = GetLocalInt(oCaster,"SPECIAL_ABILITY_CASTER_LEVEL_OVERRIDE")+GetLocalInt(GetSpellCastItem(),"ITEM_CASTER_LEVEL_OVERRIDE");
 if(GetObjectType(OBJECT_SELF) == OBJECT_TYPE_AREA_OF_EFFECT)
 {
 clOverride = GetLocalInt(OBJECT_SELF,"AOE_LEVEL");
 }
 if(clOverride > 0)
 {//if overriden above default caster level we must alter spell resistance of our target...
 int clDefault = GetCasterLevel(oCaster);
 int SR = GetSpellResistance(oTarget);
  if(clOverride > clDefault && clDefault < SR && clOverride >= SR)
  {//do nothing if default caster level is higher, or if even overriden level is lower than current SR
  ApplyEffectToObject(DURATION_TYPE_TEMPORARY,EffectSpellResistanceDecrease(clOverride-clDefault),oTarget,0.01);//should not affect anything else
  }
 }//end of caster level workaround
int nResist = ResistSpell(oCaster,oTarget);
 if(nResist == 1) //Spell Resistance
 {
 effect eSR = EffectVisualEffect(VFX_IMP_MAGIC_RESISTANCE_USE);
 DelayCommand(fDelay,ApplyEffectToObject(DURATION_TYPE_INSTANT,eSR,oTarget));
 }
 else if(nResist == 2) //Globe
 {
 effect eGlobe = EffectVisualEffect(VFX_IMP_GLOBE_USE);
 DelayCommand(fDelay,ApplyEffectToObject(DURATION_TYPE_INSTANT,eGlobe,oTarget));
 }
 else if(nResist == 3) //Spell Mantle
 {
  if(fDelay > 0.5)
  {
  fDelay -= 0.1;
  }
 effect eMantle = EffectVisualEffect(VFX_IMP_SPELL_MANTLE_USE);
 DelayCommand(fDelay,ApplyEffectToObject(DURATION_TYPE_INSTANT,eMantle,oTarget));
 }
return nResist;
}
The code in the public version of my patch does check only for globes, I added check for ghostly visage, ethereal visage, shadow shield, shield and pixie's polymorph otherwise its the same.
               
               

               
            

Legacy__Guile

  • Hero Member
  • *****
  • Posts: 1308
  • Karma: +0/-0
Need to Hook into Spell Resistance
« Reply #43 on: May 15, 2012, 07:26:56 pm »


               OK, after rereading the post I think I understand more of what you guys have been saying...

However, someone has figured out how to turn off the message for the SR Check...
(...Attempts to resist spell: Spell Resisted etc..)

I don't know how they did it, but I seen it on a server that only the Custom SR Roll is displayed...

Maybe I'm missing something here, how would one go about removing that message?
               
               

               


                     Modifié par _Guile, 15 mai 2012 - 11:05 .
                     
                  


            

Legacy_Xardex

  • Sr. Member
  • ****
  • Posts: 414
  • Karma: +0/-0
Need to Hook into Spell Resistance
« Reply #44 on: May 17, 2012, 09:20:23 pm »


               Off the top of my head... Either by emulating the SR check, changing the regular SR check function or by hooking the thing with nwnx.