Author Topic: Use a variable value instead?  (Read 583 times)

Legacy_Fester Pot

  • Hero Member
  • *****
  • Posts: 1698
  • Karma: +0/-0
Use a variable value instead?
« on: June 17, 2011, 02:25:42 am »


               Hey folks! I'm not familiar with using variables stored on NPCs but would like to change how I use skill checks in conversations. Currently, I'm using predetermined scripts with a numeric value check against a skill roll. The problem is for each different value, there are different scripts. This amounts to a growing number as values change based on the NPC in question.

What I'd like to do is set a variable on the NPC and have this variable get picked up by the script.

This is an example of the current script I'm using for a persuade skill check.

#include "nw_i0_tool"
/////////////////////
int StartingConditional()
{
object oPC=GetPCSpeaker();
int iSkill=GetSkillRank(SKILL_PERSUADE, oPC);
int iRoll=d20(1);
int iTotal=iSkill+iRoll;
    // Perform silent skill checks
    if(!(iTotal>=15))
        return FALSE;
    RewardPartyXP(15, oPC, FALSE);
    DelayCommand(3.0, FloatingTextStringOnCreature("You use a skill. . .", oPC));
    return TRUE;
}


So where the number "15" is on if(!(iTotal>=15)) replace that with the variable name from the NPC, which would have the number stored for such checks. An example -

BLUFF int 15
PERSUADE int 17
INTIMIDATE int 12

So this is what I came up with but I receive an error - COMPARISON TEST HAS INVALID OPERANDS on the following line -

if(!(iTotal>=sPersuade))

#include "nw_i0_tool"

/////////////////////

int StartingConditional()

{

object oPC=GetPCSpeaker();

string sBluff = GetLocalString(OBJECT_SELF, "skillBluff");
string sPersuade = GetLocalString(OBJECT_SELF, "skillPersuade");
string sIntimidate = GetLocalString(OBJECT_SELF, "skillIntimidate");

int iSkill=GetSkillRank(SKILL_PERSUADE, oPC);

int iRoll=d20(1);

int iTotal=iSkill+iRoll;
// Perform silent skill checks

if(!(iTotal>=sPersuade))

        return FALSE;

RewardPartyXP(15, oPC, FALSE);

    DelayCommand(3.0, FloatingTextStringOnCreature("You use a skill. . .", oPC));

    return TRUE;

}


I'm guessing that I have to get the INT rather than the STRING?

So ...

string sPersuade = GetLocalString(OBJECT_SELF, "skillPersuade");

would become ...

int iPersuade = GetLocalInt(OBJECT_SELF, "skillPersuade");

and change ...

if(!(iTotal>=sPersuade))

to ...

if(!(iTotal>=iPersuade))

??

FP!
               
               

               


                     Modifié par Fester Pot, 17 juin 2011 - 01:35 .
                     
                  


            

Legacy_Failed.Bard

  • Hero Member
  • *****
  • Posts: 1409
  • Karma: +0/-0
Use a variable value instead?
« Reply #1 on: June 17, 2011, 02:41:00 am »


               You would use GetLocalInt, yes.  I'm not sure in that script why you're retrieving all three numbers if you're only checking one of them, though, unless you're planning to have a system that determines which skill the PC will check against built into the script.
               
               

               
            

Legacy_FunkySwerve

  • Hero Member
  • *****
  • Posts: 2325
  • Karma: +0/-0
Use a variable value instead?
« Reply #2 on: June 17, 2011, 02:51:30 am »


               Your original, modified to use a local int:


#include "nw_i0_tool"
/////////////////////
int StartingConditional()
{
int iCheckType = GetLocalInt(OBJECT_SELF, "SkillType");//set to SKILL_ const value
int iCheckDC = GetLocalInt(OBJECT_SELF, "SkillDC";//set to skill difficulty check
object oPC=GetPCSpeaker();
int iSkill=GetSkillRank(iCheckType, oPC);
int iRoll=d20(1);
int iTotal=iSkill+iRoll;
    // Perform silent skill checks
    if(!(iTotal>=iCheckDC))
        return FALSE;
    RewardPartyXP(15, oPC, FALSE);
    DelayCommand(3.0, FloatingTextStringOnCreature("You use a skill. . .", oPC));
    return TRUE;
}

Your problem was that you were trying to compare and int and a string. This uses two Int-type local vars set on the NPC, SkillType, set to SKILL_PERSUADE's const value of 12, and SkillDC, set to the dc value of 15. I didn't bother compiling this, but, absent typos, it will compile.

Funky
               
               

               


                     Modifié par FunkySwerve, 17 juin 2011 - 01:52 .
                     
                  


            

Legacy_AndarianTD

  • Hero Member
  • *****
  • Posts: 725
  • Karma: +0/-0
Use a variable value instead?
« Reply #3 on: June 17, 2011, 03:59:19 am »


               

Fester Pot wrote...

Hey folks! I'm not familiar with using variables stored on NPCs but would like to change how I use skill checks in conversations... What I'd like to do is set a variable on the NPC and have this variable get picked up by the script...


I use this approach extensively in Sanctum of the Archmage, for exactly the reason you cite -- to avoid having to write a horde of individual scripts that all do the same thing with different parameters. This form of kludging is unfortunately necessary to gett around the inability in NWN1 to pass parameters to scripts.

Here's an example of one that I wrote for The Sight


//:://////////////////////////////////////////////
//:: Created By: Tony Donadio
//:: Created On: 6/10/2006 10:34:08 AM
//:://////////////////////////////////////////////
#include "nw_i0_tool"
int StartingConditional()
{
  // Script assumes that "PC" or a henchman tag is set on the PCSpeaker in the
  //  variable "sa_skillck_tag", and that the skill enumeration and DC for
  //  the check are set on the checker in sa_skillck_skill and sa_skillck_DC.
  // The NPC conversation speaker is used if "sa_skillck_tag" is blank or invalid.
 
  object oChecker = GetPCSpeaker();
  string sChecker = GetLocalString(oChecker,"sa_skillck_tag");
  DeleteLocalString(oChecker,"sa_skillck_tag");
  if (sChecker != "PC") oChecker = GetObjectByTag(sChecker);
  if (!GetIsObjectValid(oChecker)) oChecker = OBJECT_SELF;
 
  int iSkill = GetLocalInt(oChecker,"sa_skillck_skill");
  int iDC = GetLocalInt(oChecker,"sa_skillck_DC");
  DeleteLocalInt(oChecker,"sa_skillck_skill");
  DeleteLocalInt(oChecker,"sa_skillck_DC");

  //SendMessageToPC(GetFirstPC(),"Skill Check by "+GetName(oChecker)+
  //  " on Skill "+IntToString(iSkill)+" : "+
  //  IntToString(GetSkillRank(iSkill,oChecker))+" vs. "+IntToString(iDC));

  // Perform skill check
  if(!(AutoDC(iDC, iSkill, oChecker))) return FALSE;
  return TRUE;
}

This lets me to set up various NPCs with the INT enumeration values for the skill and DC to be checked, associate them with conversation nodes that'll check them, and do it all with one script.

Regarding the question in your post, FP: yes, I think your analysis is exactly right. For what you're looking to do, you have to use GetLocalInt to get an integer value from the NPC to test in your script. On the other hand if there's a reason why you want to use a string instead, you could always just convert it:


if(!(iTotal>=StringToInt(sPersuade)))...

               
               

               


                     Modifié par AndarianTD, 17 juin 2011 - 03:04 .
                     
                  


            

Legacy__Knightmare_

  • Full Member
  • ***
  • Posts: 191
  • Karma: +0/-0
Use a variable value instead?
« Reply #4 on: June 17, 2011, 01:05:49 pm »


               This may be a difference between this game and NWN2, been so long since I opened the NWN toolset I forget, but can't you pass things in the int StartingConditional() line and forget the variables all together? Such as:

int StartingConditional (int nSkill, int nDC)
{
object oPC=GetPCSpeaker();
int iSkill=GetSkillRank(nSkill, oPC);
int iRoll=d20(1);
int iTotal=iSkill+iRoll;
// Perform silent skill checks
if(iTotal > nDC) return FALSE;
RewardPartyXP(15, oPC, FALSE);
 DelayCommand(3.0, FloatingTextStringOnCreature("You use a skill. . .", oPC));
 return TRUE;
}

That would make it so that this one script would work for any skill and any DC number.
               
               

               


                     Modifié par _Knightmare_, 17 juin 2011 - 12:06 .
                     
                  


            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Use a variable value instead?
« Reply #5 on: June 17, 2011, 09:16:43 pm »


               

_Knightmare_ wrote...

This may be a difference between this game and NWN2, been so long since I opened the NWN toolset I forget, but can't you pass things in the int StartingConditional() line and forget the variables all together? Such as:

int StartingConditional (int nSkill, int nDC)
{
object oPC=GetPCSpeaker();
int iSkill=GetSkillRank(nSkill, oPC);
int iRoll=d20(1);
int iTotal=iSkill+iRoll;
// Perform silent skill checks
if(iTotal > nDC) return FALSE;
RewardPartyXP(15, oPC, FALSE);
 DelayCommand(3.0, FloatingTextStringOnCreature("You use a skill. . .", oPC));
 return TRUE;
}

That would make it so that this one script would work for any skill and any DC number.


Can not be done.   We have to no way to redefine the arguments that StartingConditional() can take.  
               
               

               
            

Legacy_Mudeye

  • Full Member
  • ***
  • Posts: 238
  • Karma: +0/-0
Use a variable value instead?
« Reply #6 on: June 17, 2011, 10:53:46 pm »


               Here's an untested stab at a solution to making conversation check conditionals where you don't need to make one for every possible DC and every possible skill.

In conversations there are 3 primary skills that get used.
They are Bluff, Intimidate, Persuade

This system uses the skills on the NPCs.  The persuade, bluff and intimidate skills on NPCs are not used by the game engine since an NPC cannot bluff, persuade or intimidate the PC.  The skills are still part of the NPC and can be used to store the difficulty checks for them instead of creating local variables.  When an NPC is created that you want to use one of these skills in a conversation you set the base difficulty for checks on that NPC.

So for a stupid guard, you might set the PERSUADE skill to 7, but for a clever magistrate you might set it to 15. 

Also, sometimes the DCs for these might change in a conversation depending upon what is being said.
For example, convincing the guard that you are lost might be easier than convincing the guard that you are really the King in disguise.  To allow this kind of modification a modifier is added to adjust for easy, average or difficult checks.

=================================================
#include "nw_i0_tool"

//These are the modifiers for relative difficulty of checks
int SKILLCHECK_EASY = -5;
int SKILLCHECK_AVERAGE = 0;
int SKILCHECK_HARD = 5;

//This is a utility function for using skills stored on an NPC for checks

int passedSkillCheck( int whichSkill, int easyHard )
{
    int pcRoll = d20(1);
    object oPC=GetPCSpeaker();
   
    int pcSkill=GetSkillRank(whichSkill, oPC);
    int npcSkill = GetSkillRank( whichSkill, OBJECT_SELF );
    int pcTotal = (pcSkill + pcRoll) - (npcSkill + easyHard);
    return pcTotal > 0 ? 1 : 0;
}
==============================================================================
Now make 9 conditional functions, 1 for each of the skills at each of the 3 difficulty levels.


//Example:  Easy Persuade

int StartingConditional()
{
    return passedSkillCheck( SKILL_PERSUADE, SKILLCHECK_EASY );
}

//Example:  Difficult Persuade

int StartingConditional()
{
    return passedSkillCheck( SKILL_PERSUADE, SKILLCHECK_HARD );
}

Now for any NPC that needs to make an easy persuade check. You would set the default persuade skill check in the NPC's persuade skill and use the conditional for the Easy Persuade shown above.
               
               

               


                     Modifié par Mudeye, 17 juin 2011 - 09:56 .
                     
                  


            

Legacy_Failed.Bard

  • Hero Member
  • *****
  • Posts: 1409
  • Karma: +0/-0
Use a variable value instead?
« Reply #7 on: June 17, 2011, 11:01:28 pm »


               ^^  I like that idea, using the existing skills to bypass the need for variables is certainly faster than having to manually enter the variables.
 If I hadn't already added the sense motive skill to my mod I'd have likely grabbed that script to use myself.
               
               

               
            

Legacy_Fester Pot

  • Hero Member
  • *****
  • Posts: 1698
  • Karma: +0/-0
Use a variable value instead?
« Reply #8 on: June 18, 2011, 12:33:47 am »


               Wow! That's more than I could have asked for. Thanks everyone! Now it's just a matter of finding one that works best with how I build and it'll be a difficult choice for sure.

FP!
               
               

               
            

Legacy_AndarianTD

  • Hero Member
  • *****
  • Posts: 725
  • Karma: +0/-0
Use a variable value instead?
« Reply #9 on: June 18, 2011, 02:10:58 am »


               

_Knightmare_ wrote...

This may be a difference between this game and NWN2, been so long since I opened the NWN toolset I forget, but can't you pass things in the int StartingConditional() line and forget the variables all together?


Nope. That's one of the major differences between NWN and NWN2 -- that NWN2 implemented parameter passing on conversation nodes to scripts. The extent to which that simplifies scripting and dialogue writing cannot be overstated.

The fact that Bioware didn't implement this feature in the Dragon Age toolset either made for some interesting discussion with the devs when I attended their Builder's event a couple of years ago. I still remember the somewhat wide-eyed looks I got when I said, "What do you mean I can't pass parameters to scripts? NWN2 lets you do that." '<img'>
               
               

               


                     Modifié par AndarianTD, 18 juin 2011 - 01:13 .
                     
                  


            

Legacy_henesua

  • Hero Member
  • *****
  • Posts: 6519
  • Karma: +0/-0
Use a variable value instead?
« Reply #10 on: June 18, 2011, 04:25:01 am »


                A simple solution to this is to create a few scripts that are very similar in all ways except for the name of the local variable they grab off the NPC.

Example:


int StartingConditional()
{
    string sDestAreaName = GetLocalString(OBJECT_SELF, "teleport_sDestAreaName_3");
    if (sDestAreaName == "") return FALSE;
    return TRUE;
}

This script was called
    ck_destiantion_3
and called upon local string
    teleport_sDestAreaName_3

to use different local vars, we simply changed the value of the last digit and so it worked somewhat like an index in an array.

This is still kludgey but it makes it very easy for builders to set the local variables on the NPC, and set up the conversation. It also greatly reduced the number of scripts we had to create. And a single NPC could hold several different locations to travel to. (this was part of a travel system)

In your case you could enable each NPC conversation to have a number of different skill checks to check against.
               
               

               


                     Modifié par henesua, 18 juin 2011 - 03:34 .
                     
                  


            

Legacy_CID-78

  • Sr. Member
  • ****
  • Posts: 261
  • Karma: +0/-0
Use a variable value instead?
« Reply #11 on: June 18, 2011, 07:30:14 am »


               I would have go for mudeye solution and use the NPC skills directly. that script will be usefull for any skill not only the three needed in this topic. and ther i no risk that you forget to set the variable on a NPC, ie it will be skill value 0, which isn't modified automatically by gear and spells like the real skill value would be, it's allways there and it got a value even if it's low by default. and if you want you can change the default values a new NPC get in the skill by changing a few toolset ini files.