Author Topic: Returning Values from Functions (For Spells) Help...  (Read 551 times)

Legacy__Guile

  • Hero Member
  • *****
  • Posts: 1308
  • Karma: +0/-0
Returning Values from Functions (For Spells) Help...
« on: May 16, 2012, 04:52:55 am »


               I need to return 2 values from a spell being cast...

What Level the Spell is...

&

What Spell School the spell being cast is...

Is there a function that will return this?
               
               

               
            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
Returning Values from Functions (For Spells) Help...
« Reply #1 on: May 16, 2012, 12:27:13 pm »


               This is snippet from community patch 1.70, it contains both you need using Get2DAString:

//private function
//1.70 by Shadooow: Is my target immune to last spell cast?
int MyResistSpell_GetIsSpellImmune(object oTarget, int bAOE)
{
object oRight = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND,oTarget);
object oLeft = GetItemInSlot(INVENTORY_SLOT_LEFTHAND,oTarget);
int bNoChange = GetLocalObject(oTarget,"ITEM_IN_RIGHT") == oRight && GetLocalObject(oTarget,"ITEM_IN_LEFT") == oLeft;
int nSpellId = GetEffectSpellId(EffectDazed());//AOE spells workaround
 if(bAOE && bNoChange && !GetIsPC(oTarget) && GetLocalInt(oTarget,"IMMUNE_TO_"+IntToString(nSpellId)) == 1)
 {
 return TRUE;//immunity to AOE is granted via itemproperty, no reason to repeat whole process again
 }
 else if((nSpellId == SPELL_MAGIC_MISSILE || nSpellId == SPELL_SHADOW_CONJURATION_MAGIC_MISSILE) && GetHasSpellEffect(SPELL_SHIELD,oTarget))
 {
 return TRUE;//magic missile on target with Shield spell effect
 }
 else if((nSpellId == SPELL_DROWN || nSpellId == SPELLABILITY_PULSE_DROWN || nSpellId == SPELL_FLESH_TO_STONE) && GetHasSpellEffect(nSpellId,oTarget))
 {
 return TRUE;//drown and flesh to stone immunity workaround
 }
int nSpellLevel = 99;
int nclass = GetLastSpellCastclass();
 if(bAOE)
 {
 nSpellLevel = GetLocalInt(OBJECT_SELF,"AOE_INNATE")-1;
  if(nSpellLevel < 0)
  {
  nSpellLevel = 99;
   if(GetLocalInt(OBJECT_SELF,"AOE_class") > 0)
   {
   nclass = GetLocalInt(OBJECT_SELF,"AOE_class")-1;
   }
  }
 }
 if(nSpellLevel == 99)
 {
 string sCollumn = "Innate";
  switch(nclass)
  {
  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 != "****" && sCollumn != "")
  {
  nSpellLevel = StringToInt(sCollumn);
   if(bAOE) SetLocalInt(OBJECT_SELF,"AOE_INNATE",nSpellLevel+1);
  }
 }
int nMaxLevel;
 if(GetHasSpellEffect(734,oTarget))
 nMaxLevel = 8;
 else if(GetHasSpellEffect(SPELL_GLOBE_OF_INVULNERABILITY,oTarget))
 nMaxLevel = 4;
 else if(GetHasSpellEffect(SPELL_MINOR_GLOBE_OF_INVULNERABILITY,oTarget) || GetHasSpellEffect(SPELL_GREATER_SHADOW_CONJURATION_MINOR_GLOBE,oTarget))
 nMaxLevel = 3;
 else if(GetHasSpellEffect(SPELL_ETHEREAL_VISAGE,oTarget))
 nMaxLevel = 2;                                                                                                                          //shadow ghostly visage
 else if(GetHasSpellEffect(SPELL_GHOSTLY_VISAGE,oTarget) || GetHasSpellEffect(SPELLABILITY_AS_GHOSTLY_VISAGE,oTarget) || GetHasSpellEffect(SPELL_GREATER_SHADOW_CONJURATION_MIRROR_IMAGE,oTarget))
 nMaxLevel = 1;
 if(nSpellLevel <= nMaxLevel)
 {
 return TRUE;//immunity via spell immunity effect like globe of invulnerability
 }
string sSchool = Get2DAString("spells","School",nSpellId);
 if(GetHasSpellEffect(SPELL_SHADOW_SHIELD,oTarget) && sSchool == "N")
 {
 return TRUE;//Necromantic spell cast at target with Shadow Shield
 }
 else if(GetHasSpellEffect(390,oTarget) && sSchool == "E")
 {
 return TRUE;//Enchantment spell cast at target polymorphed into pixie
 }
int nSchool = -1;
 if     (sSchool == "A")     nSchool = 0;
 else if(sSchool == "C")     nSchool = 1;
 else if(sSchool == "D")     nSchool = 2;
 else if(sSchool == "E")     nSchool = 3;
 else if(sSchool == "V")     nSchool = 4;
 else if(sSchool == "I")     nSchool = 5;
 else if(sSchool == "N")     nSchool = 6;
 else if(sSchool == "T")     nSchool = 7;
 if(bAOE && !GetIsPC(oTarget))
 {
  if(bNoChange && GetLocalInt(oTarget,"IMMUNE_TO_"+IntToString(nSpellId)) == -1)
  {
  return FALSE;//immunity to AOE is not granted via itemproperty, no reason to repeat whole process again
  }
  else
  {
  SetLocalObject(oTarget,"ITEM_IN_RIGHT",oRight);
  SetLocalObject(oTarget,"ITEM_IN_LEFT",oLeft);
  }
 }
//still nothing, lets check target items to handle creatures like demilich
int nSlot;
object oItem;
itemproperty ip;
 for(;nSlot < NUM_INVENTORY_SLOTS;nSlot++)
 {
 oItem = GetItemInSlot(nSlot,oTarget);
  if(GetIsObjectValid(oItem))
  {
  itemproperty ip = GetFirstItemProperty(oItem);
   while(GetIsItemPropertyValid(ip))
   {
    switch(GetItemPropertyType(ip))
    {
    case ITEM_PROPERTY_IMMUNITY_SPECIFIC_SPELL:
     if(StringToInt(Get2DAString("iprp_spellcost","SpellIndex",GetItemPropertyCostTableValue(ip))) == nSpellId)
     {
      if(bAOE) SetLocalInt(oTarget,"IMMUNE_TO_"+IntToString(nSpellId),1);
     return TRUE;//immunity specifically on our spell from itemproperty
     }
    break;
    case ITEM_PROPERTY_IMMUNITY_SPELLS_BY_LEVEL:
     if(nSpellLevel <= GetItemPropertyCostTableValue(ip))
     {
      if(bAOE) SetLocalInt(oTarget,"IMMUNE_TO_"+IntToString(nSpellId),1);
     return TRUE;//immunity to spell by level from itemproperty
     }
    break;
    case ITEM_PROPERTY_IMMUNITY_SPELL_SCHOOL:
     if(GetItemPropertySubType(ip) == nSchool)
     {
      if(bAOE) SetLocalInt(oTarget,"IMMUNE_TO_"+IntToString(nSpellId),1);
     return TRUE;//immunity to spell school from itemproperty
     }
    break;
    }
   ip = GetNextItemProperty(oItem);
   }
  }
 }
 if(bAOE) SetLocalInt(oTarget,"IMMUNE_TO_"+IntToString(nSpellId),-1);
return FALSE;
}


               
               

               
            

Legacy__Guile

  • Hero Member
  • *****
  • Posts: 1308
  • Karma: +0/-0
Returning Values from Functions (For Spells) Help...
« Reply #2 on: May 16, 2012, 01:17:04 pm »


               So Basically...

This..

 if(nSpellLevel == 99)
 {
 string sCollumn = "Innate";
  switch(nclass)
  {
  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 != "****" && sCollumn != "")
  {
  nSpellLevel = StringToInt(sCollumn);
   if(bAOE) SetLocalInt(OBJECT_SELF,"AOE_INNATE",nSpellLevel+1);
  }
 }
int nMaxLevel;
 if(GetHasSpellEffect(734,oTarget))
 nMaxLevel = 8;
 else if(GetHasSpellEffect(SPELL_GLOBE_OF_INVULNERABILITY,oTarget))
 nMaxLevel = 4;
 else
if(GetHasSpellEffect(SPELL_MINOR_GLOBE_OF_INVULNERABILITY,oTarget) ||
GetHasSpellEffect(SPELL_GREATER_SHADOW_CONJURATION_MINOR_GLOBE,oTarget))
 nMaxLevel = 3;
 else if(GetHasSpellEffect(SPELL_ETHEREAL_VISAGE,oTarget))
 nMaxLevel
=
2;                                                                                                                         
//shadow ghostly visage
 else
if(GetHasSpellEffect(SPELL_GHOSTLY_VISAGE,oTarget) ||
GetHasSpellEffect(SPELLABILITY_AS_GHOSTLY_VISAGE,oTarget) ||
GetHasSpellEffect(SPELL_GREATER_SHADOW_CONJURATION_MIRROR_IMAGE,oTarget))
 nMaxLevel = 1;
 if(nSpellLevel <= nMaxLevel)
 {
 return TRUE;//immunity via spell immunity effect like globe of invulnerability
 }
string sSchool = Get2DAString("spells","School",nSpellId);
 if(GetHasSpellEffect(SPELL_SHADOW_SHIELD,oTarget) && sSchool == "N")
 {
 return TRUE;//Necromantic spell cast at target with Shadow Shield
 }
 else if(GetHasSpellEffect(390,oTarget) && sSchool == "E")
 {
 return TRUE;//Enchantment spell cast at target polymorphed into pixie
 }
int nSchool = -1;
 if     (sSchool == "A")     nSchool = 0;
 else if(sSchool == "C")     nSchool = 1;
 else if(sSchool == "D")     nSchool = 2;
 else if(sSchool == "E")     nSchool = 3;
 else if(sSchool == "V")     nSchool = 4;
 else if(sSchool == "I")     nSchool = 5;
 else if(sSchool == "N")     nSchool = 6;
 else if(sSchool == "T")     nSchool = 7;
 if(bAOE && !GetIsPC(oTarget))
 {
  if(bNoChange && GetLocalInt(oTarget,"IMMUNE_TO_"+IntToString(nSpellId)) == -1)
  {
  return FALSE;//immunity to AOE is not granted via itemproperty, no reason to repeat whole process again
  }
  else
  {
  SetLocalObject(oTarget,"ITEM_IN_RIGHT",oRight);
  SetLocalObject(oTarget,"ITEM_IN_LEFT",oLeft);
  }
 }


& This

string sSchool = Get2DAString("spells","School",nSpellId);


Correct?

I was really looking for exact help (as in complete function), if you would be willing to do that ShadoOow?

One other question, would 2da String Lookup be slow????

I'm thinking it would be better to just like use a switch/case statement with all of the spells listed in each case, for speed, or would this be slow too?
               
               

               


                     Modifié par _Guile, 16 mai 2012 - 12:27 .
                     
                  


            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
Returning Values from Functions (For Spells) Help...
« Reply #3 on: May 16, 2012, 02:07:02 pm »


               2DA lookups were slow before 1.69 but now this is automatically cached in engine. But even if it would be slow - how often you want to do it and where you want to do it?

You and not only you, are probably too obsessed with efficiency while you don't care about default AI scripts that run every second. General PW module with hundred areas will run thousands scripts each second, in this manner one script that runs one time when player rest or equip item doesn't really matter.

Anyway, Im not in toolset now so I can't really make the function for you and im too lazy to compile it from snippet above in textpad, maybe later if noone else does. But yes for the spellshool you only need single 2DAlookup with only one required parameter -> spellId. The spell level is a bit complicated as it depends on last spell cast class.
               
               

               


                     Modifié par ShaDoOoW, 16 mai 2012 - 01:11 .
                     
                  


            

Legacy_The Amethyst Dragon

  • Hero Member
  • *****
  • Posts: 2981
  • Karma: +0/-0
Returning Values from Functions (For Spells) Help...
« Reply #4 on: May 16, 2012, 04:53:08 pm »


               


// functions for getting spell school and level


int GetSpellLevel(int nSpellID, int nCasterType)
{
int nReturn;
string sType = "Innate";
switch (nCasterType)
   {
   case 1: sType = "Bard"; break;
   case 2: sType = "Cleric"; break;
   case 3: sType = "Druid"; break;
   case 6: sType = "Paladin"; break;
   case 7: sType = "Ranger"; break;
   case 9:
   case 10: sType = "Wiz_Sorc"; break;
   }
nReturn = StringToInt(Get2DAString("spells", sType, nSpellID));
return nReturn;
}

void main()
{
int nSpellID = GetSpellId();

int nSpellLevel = GetSpellLevel(nSpellID, GetLastSpellCastclass());
string sSpellSchool = Get2DAString("spells", "School", nSpellID);
}


For formating any type of text, this forum sucks.  You'll have to manually capitalize the last "c" in GetLastSpellCastclass().

The string sSpellSchool will return a single character representing the spell's school:
A = abjuration
C = conjuration
D = divination
E = enchantment
I = illusion
N = necromancy
T = transmutation
V = evocation
               
               

               


                     Modifié par The Amethyst Dragon, 16 mai 2012 - 04:05 .
                     
                  


            

Legacy__Guile

  • Hero Member
  • *****
  • Posts: 1308
  • Karma: +0/-0
Returning Values from Functions (For Spells) Help...
« Reply #5 on: May 16, 2012, 05:49:55 pm »


               Unfortunately I'm already better than 1/2 through the revisions of my spell system...

I just simply used nwn wiki and looked up each spell to ensure that the proper level & school were checked in the spell vs a private function, that way there is as little lag as possible...

Thanks for the help guys anyway. '<img'>
               
               

               


                     Modifié par _Guile, 16 mai 2012 - 04:50 .
                     
                  


            

Legacy_henesua

  • Hero Member
  • *****
  • Posts: 6519
  • Karma: +0/-0
Returning Values from Functions (For Spells) Help...
« Reply #6 on: May 16, 2012, 06:27:59 pm »


               Great stuff, TAD and Shadow. I can make use of this information. Thanks.