Author Topic: Spell Data Retrieval  (Read 364 times)

Legacy_Failed.Bard

  • Hero Member
  • *****
  • Posts: 1409
  • Karma: +0/-0
Spell Data Retrieval
« on: June 13, 2012, 04:00:12 pm »


                 I've been bouncing around between projects on my mod lately, fleshing out the rumour system I use being one project on the go, the other being a change in the spell data collection routine I use, switching to a struct based retrieval system.



  Obviously, I'm not the first to go about this method for it, but after setting it up and starting to switch over the spell scripts to take advantage of it, I really can't see why Bioware didn't impliment spell data and combat data structs for easy retrieval to begin with.  It's so much easier coding spells when you have everything you need handy in one function call, and saves having to assign the same few common variables each and every time.

  The bitwize GetMetaMagic(); with item level override routine I'd posted before became part of it, as did a wrapper routine for item caster level override allowance.

  The spell script changes are taking a bit, but it lets me clean up the code more as I convert them to use this system.

  These are the components to it:  (Spell school is the only part I added that I'm still not entirely sure was necessary, but a cached 2da read is near instant anyways so it's not really an issue efficiency wise.)

//// MetaMagic check that filters out the item exploit.
int FB_GetMetaMagicFeat();
 
int FB_GetMetaMagicFeat()
{
object oItem = GetSpellCastItem();

if (GetIsObjectValid (oItem))
     {
       return GetLocalInt (oItem, "FB_ITEM_METAMAGIC_FEAT");
     }

int nMetaMagic = GetMetaMagicFeat();

// add only if not already present.
if (GetHasFeat (FEAT_DEITY_AUTOMATIC_EMPOWER))  nMetaMagic |= METAMAGIC_EMPOWER;
if (GetHasFeat (FEAT_DEITY_AUTOMATIC_EXTEND))   nMetaMagic |= METAMAGIC_EXTEND;
if (GetHasFeat (FEAT_DEITY_AUTOMATIC_MAXIMIZE)) nMetaMagic |= METAMAGIC_MAXIMIZE;

  return nMetaMagic;
}


//// Spell caster level check to allow spell level to be set on items.
int FB_GetCasterLevel (object oCaster = OBJECT_SELF);

int FB_GetCasterLevel (object oCaster = OBJECT_SELF)
{
object oItem = GetSpellCastItem();
int    nLevel;

if (GetIsObjectValid (oItem))
   {
    nLevel = GetLocalInt (oItem, "FB_ITEM_SPELL_LEVEL");
   }
if (nLevel) return nLevel;
else return GetCasterLevel (oCaster);
}


And the main routine:

//// Spell stats
struct FB_SpellData {int Spell;
                    int Casterclass;
                    int CasterLevel;
                    int SpellLevel;
                    int MetaMagic;
                    int DC;
                    string SpellSchool;
                    object oTarget;
                    location lTarget;};


//// Based on: struct SpellData {int Spell;
////                             int Casterclass;
////                             int CasterLevel;
////                             int SpellLevel;
////                             int MetaMagic;
////                             int DC
////                             string SpellSchool;};
////                             object oTarget;
////                             location lTarget;};
struct FB_SpellData FB_GetSpellData (object oCaster = OBJECT_SELF);
//// (6/10/2012) Failed Bard.
struct FB_SpellData FB_GetSpellData (object oCaster = OBJECT_SELF)
{
struct FB_SpellData SpellData;
object oItem = GetSpellCastItem();

// Spell ID - The row number in spells.2da
SpellData.Spell = GetSpellId();

// Caster class, used internally for determining spell cast level.
SpellData.Casterclass = GetLastSpellCastclass();

// Caster level with item level override check.
SpellData.CasterLevel = FB_GetCasterLevel (OBJECT_SELF);

// Spell Saving Throw DC
SpellData.DC = GetSpellSaveDC();

// Spell level, determined based on caster class and a 2da read.
string sclass;
switch (SpellData.Casterclass)
   {
    case class_TYPE_BARD:    sclass = "Bard"; break;
    case class_TYPE_CLERIC:  sclass = "Cleric"; break;
    case class_TYPE_DRUID:   sclass = "Druid"; break;
    case class_TYPE_PALADIN: sclass = "Paladin"; break;
    case class_TYPE_RANGER:  sclass = "Ranger"; break;
    // these two share one.
    case class_TYPE_SORCERER:
    case class_TYPE_WIZARD:  sclass = "Wiz_Sorc"; break;
    default: sclass = "Innate";
   }
SpellData.SpellLevel = StringToInt (Get2DAString ("spells", sclass, SpellData.Spell));


// Expanded metamagic check with item exploit fix and allowance for automatic
// versions of maximized, empowered, and extended feats.
SpellData.MetaMagic   = FB_GetMetaMagicFeat();

// Spell school, determined based on 2da read
SpellData.SpellSchool = Get2DAString ("spells", "School", SpellData.Spell);

// Standard target object and location.
SpellData.oTarget = GetSpellTargetObject();
SpellData.lTarget = GetSpellTargetLocation();

return SpellData;
}


  It's unfortunate that all the "class" mentions are messed up by the formatting here.


  Anyways, is there any commonly accessed spell information that I missed?  It's easy enough to add into a struct (though much harder to remove parts once they're being used in scripts), if I need to.  If anyone notices anything that could be done more efficiently that'd be a help as well.  I'm getting better, but I still have a ways to go with some of my code.
               
               

               


                     Modifié par Failed.Bard, 13 juin 2012 - 03:00 .
                     
                  


            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
Spell Data Retrieval
« Reply #1 on: June 13, 2012, 04:03:51 pm »


               Why are you doing (again) exactly the same I have done in community patch? You can save hours using my struct spell engine that is already implemented in every spell.
               
               

               
            

Legacy_Failed.Bard

  • Hero Member
  • *****
  • Posts: 1409
  • Karma: +0/-0
Spell Data Retrieval
« Reply #2 on: June 13, 2012, 04:43:15 pm »


               

ShaDoOoW wrote...

Why are you doing (again) exactly the same I have done in community patch? You can save hours using my struct spell engine that is already implemented in every spell.


  Because most of the standard spells aren't of any use for my mod, which has the ravenloft version of all of them put in place.  If I installed the community patch I'd have to turn around and rewrite all of the spells I'd changed.  Plus, you'd already said in the thread I made on GetMetaMagicFeat() that you didn't include the bitwise support that I need for some of the creatures I have in.
  You've done quite a few good things in the community patch, but in my specific case it'd be a step backwards using it.  This method does what I need it to, yours, by your own words, wouldn't.
               
               

               
            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
Spell Data Retrieval
« Reply #3 on: June 13, 2012, 04:53:32 pm »


               

Failed.Bard wrote...

ShaDoOoW wrote...

Why are you doing (again) exactly the same I have done in community patch? You can save hours using my struct spell engine that is already implemented in every spell.


  Because most of the standard spells aren't of any use for my mod, which has the ravenloft version of all of them put in place.  If I installed the community patch I'd have to turn around and rewrite all of the spells I'd changed.  Plus, you'd already said in the thread I made on GetMetaMagicFeat() that you didn't include the bitwise support that I need for some of the creatures I have in.
  You've done quite a few good things in the community patch, but in my specific case it'd be a step backwards using it.  This method does what I need it to, yours, by your own words, wouldn't.

Yes, thats correct. But if you want to rewrite all spells to using struct engine then you have to do that anyway whether with already existing struct-based engine or your own. I haven't implemented metamagic bitwise but it can be easy added since the difference between your newly setup engine and mine is that mine engine doesn't use spell related functions (GetCasterLevel, GetSpellSaveDC, GetMetaMagic) inside spellscripts thus you can easily change it in spell engine include no need for new functions for each of this. The only one GetMetaMagicFeat call is inside the struct spell spell spellsDeclareMajorvariables(); function so to implement bitwise, you dont have to change all GetMetaMagic calls into FB_GetMetaMagic calls.

But its your time. Its funny though. RP servers says: community patch server content is for action/pvp servers not for us. Action servers says the opposite. And most folks here says: our servers are too advanced to use any advantage of it. And then I read something like this. '<img'>
               
               

               


                     Modifié par ShaDoOoW, 13 juin 2012 - 03:55 .
                     
                  


            

Legacy_Failed.Bard

  • Hero Member
  • *****
  • Posts: 1409
  • Karma: +0/-0
Spell Data Retrieval
« Reply #4 on: June 13, 2012, 05:12:26 pm »


               

ShaDoOoW wrote...

But its your time. Its funny though. RP servers says: community patch server content is for action/pvp servers not for us. Action servers says the opposite. And most folks here says: our servers are too advanced to use any advantage of it. And then I read something like this. '<img'>


  It takes less time to convert them to struct based, than to rewrite them to ravenloft standards, and get the powers and horror checks hooked in again.  I didn't say my scripts were more advanced, but it would still be a step backwards because I'd have to do more work if I started using the spells in the community patch.

 Anyways, looking through how you did it for the patch, I forgot spell ID, and about the bug that misreported spell DCs.
               
               

               
            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
Spell Data Retrieval
« Reply #5 on: June 13, 2012, 05:32:50 pm »


               I had also many functions hooked in my own mod, but then found out its better and easier for me to use the spell engine I created for community patch as I can remove the hooks.

All whats left was direct changes into spells like shield 4 shield ac, mage armor 4 armor ac etc. and that wasnt much. I dont know what are these powers you talk about - perhaps item-tag based extra powers so it makes sense it would be harder to rewrite them from scratch then apply struct based engine to them.

At any rate, you should consider my approach of not using spells-funcs at all thus you dont need to hook caster level or anything as you can do it in your main struct function like I did it.

To allow cap/radius size hook (I considered it before but abadoned for global use which community patch is) you could add the paramteres into struct function like this:

struct FB_SpellData FB_GetSpellData (object oCaster = OBJECT_SELF, int nCap=-1, int nRadiusSize=-1)
{
FB_SpellData.Cap = nCap+adjust_override;
FB_SpellData.Size = nRadiusSize+adjust_override;
}

this way you will be able to icnrease spell shape and spell cap without hooking GetFirst/NextInShape or creating a new function for calculating caps.

Last note: I've noticed it in The Krit's scripts, why everyone names all functions by their initials? I understand that you need to make custom casterlevel function so you add initials into function, but why to add it into a unique new function or (in case of Krit) even constants and variable names? Looks lame really.