Author Topic: Help understanding a script.  (Read 1853 times)

Legacy_Fester Pot

  • Hero Member
  • *****
  • Posts: 1698
  • Karma: +0/-0
Help understanding a script.
« on: November 05, 2011, 10:18:27 pm »


               The below script is from Witches Wake, used in conversations to cast spells.

Two test characters are used and are generating different results and I don't understand why or where the difference in value is coming from.

Character 1

Level 6 Dwarf Pure Wizard with 16 Intelligence

Character 2

Level 6 Dwarf Pure Wizard with 19 Intelligence

When casting the same spell, Acid Splash - or any spell for that matter using these scripts - the value that is added to the d20 roll is different, which I expect based on the +3 difference in the intelligence between the two characters.

The problem, or perhaps it's not a problem, I just can't figure out how the value is being determined, is that Character 1 has a higher value added to the d20 roll vs. Character 2, even though the latter has the higher intelligence.

Character 1 always receives a 9 (sSkill) bonus when casting spells, added to the d20 roll.

Character 2 always receives a 5 (sSkill) bonus when casting spells, added to the d20 roll.

I can't figure out why.

All test characters were naked when casting these spells and all intelligence stats posted above are their stock INT scores with no modifiers.

Here's the script.

//::///////////////////////////////////////////////
//:: Witchwork Conversation System: Cast Acid Splash Check
//:: WW_Abil_AcidSp.nss
//:: Copyright © 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
     Does a Cast Acid Splash check and broadcasts a
     feedback string.
*/
//:://////////////////////////////////////////////
//:: Created By: Rob Bartel
//:: Created On: August 30, 2002
//:://////////////////////////////////////////////

void main()
{
    object oPC = GetPCSpeaker();
    int bHasSpell1 = GetHasSpell(SPELL_ACID_SPLASH, oPC);

    //If PC is unable to cast Acid Splash, do nothing...
    if (bHasSpell1 == FALSE)
    {
        return;
    }

    object oNPC = OBJECT_SELF;
    int iAbilityType;
    int iSpell;

    //Get the PC's individual class levels for calculating their total
    //character level.
    int iclass1Level = GetLevelByPosition(1, oPC);
    int iclass2Level = GetLevelByPosition(2, oPC);
    int iclass3Level = GetLevelByPosition(3, oPC);

    //Determine what those three classes are.
    int iclass1 = GetclassByPosition(1, oPC);
    int iclass2 = GetclassByPosition(2, oPC);
    int iclass3 = GetclassByPosition(3, oPC);

    //Make an educated guess as to whether they used Acid Splash
    if (GetHasSpell(SPELL_ACID_SPLASH, oPC))
        iSpell = SPELL_ACID_SPLASH;

    //Otherwise start doing some educated guessing as to what class they might
    //be casting from so you can use the appropriate ability score modifier.
    //class 1:
    else if (iclass1 == class_TYPE_WIZARD)
        iAbilityType = ABILITY_INTELLIGENCE;
    else if (iclass1 == class_TYPE_SORCERER ||
             (iclass1 == class_TYPE_BARD &&
              iclass1Level >= 2))
        iAbilityType = ABILITY_CHARISMA;
    //class 2:
    else if (iclass2 == class_TYPE_WIZARD)
        iAbilityType = ABILITY_INTELLIGENCE;
    else if (iclass2 == class_TYPE_SORCERER ||
             (iclass2 == class_TYPE_BARD &&
              iclass1Level >= 2))
        iAbilityType = ABILITY_CHARISMA;
    //class 3:
    else if (iclass3 == class_TYPE_WIZARD)
        iAbilityType = ABILITY_INTELLIGENCE;
    else if (iclass3 == class_TYPE_SORCERER ||
             (iclass3 == class_TYPE_BARD &&
              iclass1Level >= 2))
        iAbilityType = ABILITY_CHARISMA;
    //For Special Abilities, use intelligence:
    else
        iAbilityType = ABILITY_INTELLIGENCE;

    //Decrement the spell & cast a fake one
    AssignCommand(oPC, ActionPauseConversation());
    DecrementRemainingSpellUses(oPC, iSpell);
    AssignCommand(oPC, ActionCastFakeSpellAtObject(iSpell, oNPC));
    AssignCommand(oPC, ActionResumeConversation());

    //Declare the values used in the Ability Check
    int iDC = GetLocalInt(OBJECT_SELF, "iWW_AbilityDC");
    int iD20 = Random(20)+1;
    int iAbilMod = GetAbilityModifier(iAbilityType, oPC);
    int iCharLevel = iclass1Level + iclass2Level + iclass3Level;

    //Create the final Check calculation.
    int iCheck = iD20 + iAbilMod + iCharLevel;
    int iSkill = iAbilMod + iCharLevel;

    //Convert the above Ints to Strings in preparation for broadcast.
    // DEBUG
    string sDC = IntToString(iDC); // DONE
    string sRoll = IntToString(iD20); // DONE
    string sSkill = IntToString(iSkill); // DONE
    string sCheck = IntToString(iCheck);  // DONE
    // DEBUG

    //If the PC's Check >= DC, they succeed.
    if (iCheck >= iDC)
    {
        SetLocalString(OBJECT_SELF, "sWW_AbilityResult", "Success");
        // PASS ROLL
        string sBroadcast = "<c þþ>Acid Splash</c> <cþþ >:</c> <cþþþ>"+sRoll+"</c> <cþþ >+</c> <cþþþ>"+sSkill+"</c> <cþþ >=</c> <c þ >"+sCheck+"</c> <cþþ >vs.</c> <cþþþ>DC</c> <c þþ>"+sDC+".</c>";
    SendMessageToPC(oPC, sBroadcast);
    }
    //If not, they fail.
    else
    {
        SetLocalString(OBJECT_SELF, "sWW_AbilityResult", "Failure");
        // FAIL ROLL
    string sBroadcast = "<c þþ>Acid Splash</c> <cþþ >:</c> <cþþþ>"+sRoll+"</c> <cþþ >+</c> <cþþþ>"+sSkill+"</c> <cþþ >=</c> <cþ  >"+sCheck+"</c> <cþþ >vs.</c> <cþþþ>DC</c> <c þþ>"+sDC+".</c>";
    SendMessageToPC(oPC, sBroadcast);
    }
}


Just a clean crop of the colour codes regarding the broadcast message of the variables.

Acid Splash : "+sRoll+" + "+sSkill+" = "+sCheck+" vs. DC "+sDC+".

FP!
               
               

               


                     Modifié par Fester Pot, 05 novembre 2011 - 10:22 .
                     
                  


            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
Help understanding a script.
« Reply #1 on: November 05, 2011, 10:33:15 pm »


               That probably because the second char has Acid splash spell memorised and thus the ability part is errorneusly skipped and ability remains at value of 0 which is strenght. If your strenght is 8-9 it will match then.
               
               

               
            

Legacy_Fester Pot

  • Hero Member
  • *****
  • Posts: 1698
  • Karma: +0/-0
Help understanding a script.
« Reply #2 on: November 05, 2011, 11:37:45 pm »


               They both have it memorized, otherwise the option to cast it via a conversation is not available.

The script does not check strength at all.

FP!
               
               

               
            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Help understanding a script.
« Reply #3 on: November 06, 2011, 12:02:40 am »


               lol,   Shadow nailed it.     Where it is true that the script as written will only work if they have Acid Splash.  The ability being checked is Strength.  

else
       iAbilityType = ABILITY_INTELLIGENCE;

is never excuted being in an else clause theat can never fire.   Since iAbilityType is never set it is 0.  hence the strenght is being checked.
               
               

               
            

Legacy_WhiZard

  • Hero Member
  • *****
  • Posts: 2149
  • Karma: +0/-0
Help understanding a script.
« Reply #4 on: November 06, 2011, 12:14:20 am »


               

Fester Pot wrote...

They both have it memorized, otherwise the option to cast it via a conversation is not available.

The script does not check strength at all.

FP!


Are the two builds of the same character level?  It seems iCheck adds in the character level + ability modifier + d20. However, I am not seeing which value you are broadcasting that you are trying to refer to as the "before the d20". iDC uses a local variable and is possibly isolated from this system.
               
               

               


                     Modifié par WhiZard, 06 novembre 2011 - 12:17 .
                     
                  


            

Legacy_WhiZard

  • Hero Member
  • *****
  • Posts: 2149
  • Karma: +0/-0
Help understanding a script.
« Reply #5 on: November 06, 2011, 12:32:39 am »


               

Lightfoot8 wrote...

lol,   Shadow nailed it.     Where it is true that the script as written will only work if they have Acid Splash.  The ability being checked is Strength.  

else
       iAbilityType = ABILITY_INTELLIGENCE;

is never excuted being in an else clause theat can never fire.   Since iAbilityType is never set it is 0.  hence the strenght is being checked.


Yep, looks right.  You might wish to get rid of the GetHasSpell() check, and instead work by GetLastSpellCastclass(), instead.

EDIT: Doesn't look like this forum likes the multiple capitalizations in GetLastSpellCastclass().
               
               

               


                     Modifié par WhiZard, 06 novembre 2011 - 12:37 .
                     
                  


            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Help understanding a script.
« Reply #6 on: November 06, 2011, 12:38:02 am »


               The local Look to be the DC of casting.  It is never modified or used in calculations, just checked against for the pass/ fail. 

As far as fixing it goes just remove the else in red below.  

//Make an educated guess as to whether they used Acid Splash
    if (GetHasSpell(SPELL_ACID_SPLASH, oPC))
        iSpell = SPELL_ACID_SPLASH;


    //Otherwise start doing some educated guessing as to what class they might
    //be casting from so you can use the appropriate ability score modifier.
    //class 1:
    else if (iclass1 == class_TYPE_WIZARD)
        iAbilityType = ABILITY_INTELLIGENCE;
    else if (iclass1 == class_TYPE_SORCERER ||......
               
               

               
            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Help understanding a script.
« Reply #7 on: November 06, 2011, 12:40:27 am »


               

WhiZard wrote...

EDIT: Doesn't look like this forum likes the multiple capitalizations in GetLastSpellCastclass().


It is the word 'class'  that it does not like.   This forum will always change it to lower case reguardless of where it is found.  
               
               

               
            

Legacy_Fester Pot

  • Hero Member
  • *****
  • Posts: 1698
  • Karma: +0/-0
Help understanding a script.
« Reply #8 on: November 06, 2011, 01:38:19 pm »


               Got it now. In the end, I removed the entire iclass checks as it's a base Wizard/Sorcerer module anyhow and added in an additional check for SpellCraft to the roll to add to the iAbilityType. It's working fine now for both test characters but wow, that strength comment really confused me at first. '<img'>

Thanks all for the direction.

Final and modified script below for reference,

//::///////////////////////////////////////////////
//:: Witchwork Conversation System: Cast Acid Splash Check
//:: WW_Abil_AcidSp.nss
//:: Copyright © 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
     Does a Cast Acid Splash check and broadcasts a
     feedback string.
*/
//:://////////////////////////////////////////////
//:: Created By: Rob Bartel
//:: Created On: August 30, 2002
//:://////////////////////////////////////////////

void main()
{
    object oPC = GetPCSpeaker();
    int bHasSpell1 = GetHasSpell(SPELL_ACID_SPLASH, oPC);


    //If PC is unable to cast Acid Splash, do nothing...
    if (bHasSpell1 == FALSE)
    {
        return;
    }

    object oNPC = OBJECT_SELF;
    int iAbilityType;
    int iSpell;
    int iSpellCraft;


   if (GetHasSpell(SPELL_ACID_SPLASH, oPC))

        iSpell = SPELL_ACID_SPLASH;
        iSpellCraft = GetSkillRank(SKILL_SPELLCRAFT, oPC, FALSE);

    if (GetLevelByclass(class_TYPE_WIZARD, oPC) == TRUE)

    {
     iAbilityType = ABILITY_INTELLIGENCE;
    }

    if (GetLevelByclass(class_TYPE_SORCERER, oPC) == TRUE)

    {
     iAbilityType = ABILITY_CHARISMA;
    }

    //Decrement the spell & cast a fake one
    AssignCommand(oPC, ActionPauseConversation());
    DecrementRemainingSpellUses(oPC, iSpell);
    AssignCommand(oPC, ActionCastFakeSpellAtObject(iSpell, oNPC));
    AssignCommand(oPC, ActionResumeConversation());

    //Declare the values used in the Ability Check
    int iDC = GetLocalInt(OBJECT_SELF, "iWW_AbilityDC");
    int iD20 = Random(20)+1;
    int iAbilMod = GetAbilityModifier(iAbilityType, oPC);

    //Create the final Check calculation.
    int iCheck = iD20 + iAbilMod + iSpellCraft;
    int iSkill = iAbilMod + iSpellCraft;

    //Convert the above Ints to Strings in preparation for broadcast.
    string sDC = IntToString(iDC); // DONE
    string sRoll = IntToString(iD20); // DONE
    string sSkill = IntToString(iSkill); // DONE
    string sCheck = IntToString(iCheck);  // DONE

    //If the PC's Check >= DC, they succeed.
    if (iCheck >= iDC)
    {
        SetLocalString(OBJECT_SELF, "sWW_AbilityResult", "Success");
        // PASS ROLL
        string sBroadcast = "<c þþ>Acid Splash</c> <cþþ >:</c> <cþþþ>"+sRoll+"</c> <cþþ >+</c> <cþþþ>"+sSkill+"</c> <cþþ >=</c> <c þ >"+sCheck+"</c> <cþþ >vs.</c> <cþþþ>DC</c> <c þþ>"+sDC+".</c>";
    SendMessageToPC(oPC, sBroadcast);
    }
    //If not, they fail.
    else
    {
        SetLocalString(OBJECT_SELF, "sWW_AbilityResult", "Failure");
        // FAIL ROLL
    string sBroadcast = "<c þþ>Acid Splash</c> <cþþ >:</c> <cþþþ>"+sRoll+"</c> <cþþ >+</c> <cþþþ>"+sSkill+"</c> <cþþ >=</c> <cþ  >"+sCheck+"</c> <cþþ >vs.</c> <cþþþ>DC</c> <c þþ>"+sDC+".</c>";
    SendMessageToPC(oPC, sBroadcast);
    }
}


FP!
               
               

               


                     Modifié par Fester Pot, 06 novembre 2011 - 01:45 .
                     
                  


            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Help understanding a script.
« Reply #9 on: November 06, 2011, 02:16:33 pm »


               

Fester wrote....

... object oNPC = OBJECT_SELF;
    int iAbilityType;
    int iSpell;
    int iSpellCraft;


   if (GetHasSpell(SPELL_ACID_SPLASH, oPC))

        iSpell = SPELL_ACID_SPLASH;
        iSpellCraft = GetSkillRank(SKILL_SPELLCRAFT, oPC, FALSE);

    if (GetLevelByclass(class_TYPE_WIZARD, oPC) == TRUE)

    {
     iAbilityType = ABILITY_INTELLIGENCE;
    }

    if (GetLevelByclass(class_TYPE_SORCERER, oPC) == TRUE)

    {
     iAbilityType = ABILITY_CHARISMA;
    }...

 


Note; with the way it is written, If the PC is nither a Wizard or a Sorcerer you will still end up checking strength.  Also if the PC has one level of bard and 20 levels of wizard you wuold end up using Charaisma not intelegence.  
               
               

               
            

Legacy_Fester Pot

  • Hero Member
  • *****
  • Posts: 1698
  • Karma: +0/-0
Help understanding a script.
« Reply #10 on: November 06, 2011, 03:59:02 pm »


               If the player is not a Wizard or a Sorcerer, then they should not be playing any of my modules, which are Wizard and Sorcerer only. I will not cater to players who can't read module requirements. '<img'>

FP!
               
               

               


                     Modifié par Fester Pot, 06 novembre 2011 - 03:59 .
                     
                  


            

Legacy_WhiZard

  • Hero Member
  • *****
  • Posts: 2149
  • Karma: +0/-0
Help understanding a script.
« Reply #11 on: November 06, 2011, 06:11:17 pm »


               

Fester Pot wrote...

    if (GetLevelByclass(class_TYPE_SORCERER, oPC) == TRUE)


No, this will only work if the player has exactly one level in sorcerer (same can be said for the wizard class check).
TRUE == 1.  "==" in this case would be returning FALSE if GetLevelByclass != 1 (1 being the value of TRUE).

What this should be is:

if(GetLevelByclass(class_TYPE_SORCERER, oPC))  as the if clause will report any non-zero value as satisfying the "if" requirements.
               
               

               
            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Help understanding a script.
« Reply #12 on: November 06, 2011, 07:52:02 pm »


               Good catch WhiZard.  

So,
   ...
   iAbilityType = ABILITY_INTELLIGENCE;
   if (GetLevelByclass(class_TYPE_SORCERER, oPC)) iAbilityType = ABILITY_CHARISMA;
  ...

would cover all of your bases.
               
               

               
            

Legacy_Fester Pot

  • Hero Member
  • *****
  • Posts: 1698
  • Karma: +0/-0
Help understanding a script.
« Reply #13 on: November 06, 2011, 10:23:06 pm »


               Great! Thanks for catching that! Will modify and go with that then.

FP!
               
               

               
            

Legacy_Rolo Kipp

  • Hero Member
  • *****
  • Posts: 4349
  • Karma: +0/-0
Help understanding a script.
« Reply #14 on: November 07, 2011, 01:31:38 am »


               <holding a large lens...>

Lightfoot8 wrote...
...
   iAbilityType = ABILITY_INTELLIGENCE;
   if (GetLevelByclass(class_TYPE_SORCERER, oPC)) iAbilityType = ABILITY_CHARISMA;
  ...
would cover all of your bases.

Unless the PC had 1 level in sorcerer and 19 levels in wizard? *Any* level in Sorc will change iAbilityType to CHA, regardless of major class.

Wouldn't a compare levels check be good in there so the weak ability isn't chosen over the strong? Is that what you were getting at with:

Note; with the way it is written, If the PC is nither a Wizard or a Sorcerer you will still end up checking strength.  Also if the PC has one level of bard and 20 levels of wizard you wuold end up using Charaisma not intelegence.  

<...to his eye>
               
               

               


                     Modifié par Rolo Kipp, 07 novembre 2011 - 01:33 .