Author Topic: Language Clerk Conversation  (Read 601 times)

Legacy_Evelath

  • Full Member
  • ***
  • Posts: 108
  • Karma: +0/-0
Language Clerk Conversation
« on: April 16, 2011, 05:10:50 am »


               Hello Everyone,

I am working on a set of scripts that involve an NPC that gives out Languages, however there are certain parameters to getting those languages.  

Here is an example of the script that is called when a player chooses the "Drow" language to learn:

void main()
{

    object oPC = GetPCSpeaker();
    object oLang = GetItemPossessedBy(oPC, "lang_token");

    if (GetIsObjectValid(GetItemPossessedBy(oPC, "hlslang_13"))==TRUE)
        {
            SendMessageToPC(oPC, "You have already learned this language.");
            return;
        }

    if (GetIsObjectValid(GetItemPossessedBy(oPC, "lang_token"))==FALSE)
        {
            SendMessageToPC(oPC, "You can not learn anymore languages right now.");
            return;
        }

    if (GetIsObjectValid(GetItemPossessedBy(oPC, "hlslang_13"))==FALSE)
        {
            DestroyObject(oLang);
            CreateItemOnObject("hlslang_13", GetPCSpeaker(), 1);
        }

}


Now, what I need to do is set-up a function that checks several things:

1) It needs to group together 16 different items, with different tags.
2) It needs to check to see how many of those items the player has.
3) It needs to check the INT bonus that a character has.
4) If a player has enough INT (for example, 12 INT, giving an additional language), then he/she can select the appropriate conversation option to bring up the full list of languages available on the server.

Also, if anyone sees area for improvement in my script above, please let me know.  My scripting knowledge is a work in progress, and if there are easier solutions, I would love to hear them.

Thanks!
               
               

               


                     Modifié par Evelath, 16 avril 2011 - 04:11 .
                     
                  


            

Legacy__Guile

  • Hero Member
  • *****
  • Posts: 1308
  • Karma: +0/-0
Language Clerk Conversation
« Reply #1 on: April 18, 2011, 02:52:56 am »


               Let me improve the first script:

void main()
{
  //Declare all variables....
     object oPC = GetPCSpeaker();
     object oLang = GetItemPossessedBy(oPC, "lang_token");
     object oLang_2 = GetItemPossessedBy(oPC, "hlslang_13");

  if (oLang_2 == OBJECT_INVALID) //If the PC does NOT have the item
  {   DestroyObject(oLang);
             CreateItemOnObject("hlslang_13", GetPCSpeaker(), 1);       }
  else  //Otherwise they have the item!
         {        SendMessageToPC(oPC, "You have already learned this language.");        }
 
  if (oLang != OBJECT_INVALID) //If the PC does have the item...
         {            SendMessageToPC(oPC, "You can not learn anymore languages right now.");        }
}

if oLang does not equal (not there) kind of backwards language huh? it means they have it...or it's true...
               
               

               


                     Modifié par _Guile, 18 avril 2011 - 02:07 .
                     
                  


            

Legacy_Evelath

  • Full Member
  • ***
  • Posts: 108
  • Karma: +0/-0
Language Clerk Conversation
« Reply #2 on: April 18, 2011, 03:03:50 am »


               Thank you for that.  I am attempting to get the earlier function to work (Where I simply identify how many of a set of items a player has):

void main()
{

    object oPC          = GetPCSpeaker();
    int    nLanguage    = 0;

    if (GetIsObjectValid(GetItemPossessedBy(oPC, "hlslang_1"))==TRUE)
       (GetIsObjectValid(GetItemPossessedBy(oPC, "hlslang_2"))==TRUE);
       (GetIsObjectValid(GetItemPossessedBy(oPC, "hlslang_3"))==TRUE);
       (GetIsObjectValid(GetItemPossessedBy(oPC, "hlslang_4"))==TRUE);
       (GetIsObjectValid(GetItemPossessedBy(oPC, "hlslang_5"))==TRUE);
       (GetIsObjectValid(GetItemPossessedBy(oPC, "hlslang_6"))==TRUE);
       (GetIsObjectValid(GetItemPossessedBy(oPC, "hlslang_7"))==TRUE);
       (GetIsObjectValid(GetItemPossessedBy(oPC, "hlslang_10"))==TRUE);
       (GetIsObjectValid(GetItemPossessedBy(oPC, "hlslang_11"))==TRUE);
       (GetIsObjectValid(GetItemPossessedBy(oPC, "hlslang_12"))==TRUE);
       (GetIsObjectValid(GetItemPossessedBy(oPC, "hlslang_13"))==TRUE);
       (GetIsObjectValid(GetItemPossessedBy(oPC, "hlslang_14"))==TRUE);
       (GetIsObjectValid(GetItemPossessedBy(oPC, "hlslang_15"))==TRUE);
       (GetIsObjectValid(GetItemPossessedBy(oPC, "hlslang_16"))==TRUE);
        {
        nLanguage ++;

     string sResponse    = "You currently know " + IntToString(nLanguage) + " languages.";
        SendMessageToPC(oPC, sResponse);

        }


Obviously this isn't working as intended (tested it...)  My intention is to confine the number of languages known to a single number, that way I can later use IF statements to determine if the integer matches the appropriate INT bonus.

Any help would be appreciated '<img'>
               
               

               
            

Legacy__Guile

  • Hero Member
  • *****
  • Posts: 1308
  • Karma: +0/-0
Language Clerk Conversation
« Reply #3 on: April 18, 2011, 03:14:14 am »


               void main()
{

    object oPC = GetPCSpeaker();

    int  i;
    int nInt = 0;
    string sName = "hlslang_";
    string sConvert;
    object oItem;

    //Loop
    for(i=0; i<17; i++)
    {
      nInt += 1;
      sConvert = sName + IntToString(i);  //add "hlslang_" & the int i (which will change from 1 to 2 etc)
      
      oItem = GetItemPossessedBy(oPC, sConvert);

      if(oItem != OBJECT_INVALID)
      {  
        sResponse    = "You currently know " + IntToString(nInt) + " languages.";
        SendMessageToPC(oPC, sResponse);
      }

    }
 
//End Main Script
}

Loops are powerful, they shorten scripts tremendously, including Switch / Case Statements as well, but these subjects are best left to study in the Lexicon as they are subjects that are rather difficult to talk about on a forum for they are well beyond the scope of forums post... 

Hope that helped   :innocent:
               
               

               


                     Modifié par _Guile, 18 avril 2011 - 02:18 .
                     
                  


            

Legacy_Evelath

  • Full Member
  • ***
  • Posts: 108
  • Karma: +0/-0
Language Clerk Conversation
« Reply #4 on: April 18, 2011, 03:19:17 am »


               Thank you so much '<img'>

I'm working my way through learning everything, and loops and case/break situations are what I am attempting to get through now, so it looks really good '<img'>  I'll test it out and see how it goes.  Thanks again!
               
               

               
            

Legacy_Evelath

  • Full Member
  • ***
  • Posts: 108
  • Karma: +0/-0
Language Clerk Conversation
« Reply #5 on: April 18, 2011, 04:05:10 am »


               Minor bug.  The script compiles ( after declaring String sResponse '<img'> ), however when I added "hlslang_1" to my inventory, it states I have 2 languages.  "hlslang_11" to my inventory, it states I have 12.

All I can tell is that it seems to be setting a particular number (1), then adding the variable at the end of "hlslang_" to the amount of languages learned.  I'll take a whack at it later this evening, however if you beat me to it I appreciate it '<img'>
               
               

               
            

Legacy_GhostOfGod

  • Hero Member
  • *****
  • Posts: 1490
  • Karma: +0/-0
Language Clerk Conversation
« Reply #6 on: April 18, 2011, 06:14:34 am »


               I noticed in your script attempt Evelath that you skipped "hlslang_8" and "hlslang_9". Are you not using those two language items? If not then you can't do the loop the same way that _Guile suggested.

Could try it more like this perhaps?


void main()
{
    object oPC = GetPCSpeaker();
    int i;
    int nInt = 0;
    object oItem;
    string sResponse;
   
    for(i=0; i<17; i++)
    {
          oItem = GetItemPossessedBy(oPC, "hlslang_" + IntToString(i));
          if (oItem != OBJECT_INVALID)
          nInt++;
    }

    if (nInt == 1)
    sResponse = "You currently know 1 language.";
    else
    sResponse = "You currently know " + IntToString(nInt) + " languages.";
    SendMessageToPC(oPC, sResponse);
}


Hope that works for ya. Good luck.
               
               

               


                     Modifié par GhostOfGod, 18 avril 2011 - 05:24 .
                     
                  


            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Language Clerk Conversation
« Reply #7 on: April 18, 2011, 06:29:24 am »


               The problem with the   GetItemPossessedBy function is that it loops through the players inventory every time you use it. I am not saying the method you are trying to use will not work, just that it is ineffecient.  It would be better if you just made a custom loop or function to go through the inventory only one time.  I made it into a function.  This way you can place it into an include to use it where ever you want.

int  GetNumLanguages(object oPC)
{
     int nCount;

     object oInv = GetFirstItemInInventory(oPC);
     while (GetIsObjectValid(oInv))
     {
        if(GetStringLeft(GetTag(oInv), 8) == "hlslang_") nCount++;
        GetNextItemInInventory(oInv);
        oInv = GetNextItemInInventory(oPC);
     }
     return nCount;


               
               

               


                     Modifié par Lightfoot8, 22 avril 2011 - 08:31 .
                     
                  


            

Legacy_GhostOfGod

  • Hero Member
  • *****
  • Posts: 1490
  • Karma: +0/-0
Language Clerk Conversation
« Reply #8 on: April 18, 2011, 06:58:17 am »


               Another excellent suggestion by Lightfoot.

So you could save his function to your library or by itself in its own scirpt. For examples sake we'll say you leave it by itself and name the script "num_lang_inc". Then you could make a script like so:

#include "num_lang_inc"
void main()
{
    object oPC = GetPCSpeaker();
    int nLangs = GetNumLanguages(oPC);
    string sResponse;
   
    if (nLangs == 1)
    sResponse = "You currently know 1 language.";
    else
    sResponse = "You currently know " + IntToString(nLangs) + " languages.";
    SendMessageToPC(oPC, sResponse);
}
               
               

               
            

Legacy_Evelath

  • Full Member
  • ***
  • Posts: 108
  • Karma: +0/-0
Language Clerk Conversation
« Reply #9 on: April 18, 2011, 08:26:07 pm »


               Thanks for the comments/suggestions.

I implemented the two scripts (include + main script), and it works appropriately when there are no languages present on the PC.  (It will state that I have 0 languages).  However when I add the language, I get the "Too Many Instructions" line.

I essentially did a copy of the script to identify how many language tokens a player has as well, and it's turning up the same error.

Any help is appreciated '<img'>
               
               

               
            

Legacy_Evelath

  • Full Member
  • ***
  • Posts: 108
  • Karma: +0/-0
Language Clerk Conversation
« Reply #10 on: April 18, 2011, 09:02:10 pm »


               Also, another question.

Rather than using language tokens, would it be easier and/or more efficient to use Player Skins (this will be used on a PW.)?  I've read a bit about PC skins, however I am not sure whether it would be most feasible to utilize them in this case.
               
               

               
            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Language Clerk Conversation
« Reply #11 on: April 18, 2011, 09:11:59 pm »


               Can you post your script. I do not see any error in what I posted. The only problem I can currently see happening is if you are nesting that function inside of another Inventory looping function.


EDIT:  *Cringes*    On the other hand.   Sorry my fault . 

Change the line: 

 

GetNextItemInInventory(oInv);

To

oInv = GetNextItemInInventory(oPC);
               
               

               


                     Modifié par Lightfoot8, 18 avril 2011 - 08:17 .
                     
                  


            

Legacy_Evelath

  • Full Member
  • ***
  • Posts: 108
  • Karma: +0/-0
Language Clerk Conversation
« Reply #12 on: April 22, 2011, 08:17:23 pm »


               A late 'thank you' to everyone assisting.  I am now attempting to link the current code(s) that you provided, with another script that sets the Int Bonus for a character (base, w/o items) to a single number that can then be matched against the current number of languages that a character knows.

#include "nw_i0_plot"

int GetIntBonus(object oPC)

{
    int    nInt     = GetIntelligence(oPC);
    int    nBonus;

    if (nInt = 12)
    {
    nBonus + 1;
    }


    return nBonus;



}

I started working on a separate function to call; however I am thinking that it may be easier to run a Loop?  It would simply need to check nInt to determine if it is an even value (12, 14, 16, 18, 20, etc. stopping at likely 30), and then setting nBonus to the appropriate amount (if nInt = 12, then nBonus = 1).  The above however, has a number of parameters that I am not sure would be able to work in a Loop situation.  A little lost with this being a bit more complex than my previous scripts (or I am atleast making it that way.)
               
               

               
            

Legacy_GhostOfGod

  • Hero Member
  • *****
  • Posts: 1490
  • Karma: +0/-0
Language Clerk Conversation
« Reply #13 on: April 22, 2011, 09:23:15 pm »


               If my scripting hat is on right this morning something like this perhaps?


int GetIntBonus(object oPC)
{
    int iIntelligence = GetAbilityScore(oPC, ABILITY_INTELLIGENCE, TRUE);
    int iIntBonus;

    if (iIntelligence < 12)
    {
        return iIntBonus;
    }

    else if (iIntelligence > 30)
    {
        iIntBonus = 10;
        return iIntBonus;
    }

    else
    {
        while (iIntelligence > 11)
        {
            if (iIntelligence % 2 == 0) iIntBonus++;
            iIntelligence--;
        }
        return iIntBonus;
    }
}


Hope it helps. Good luck.
               
               

               
            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Language Clerk Conversation
« Reply #14 on: April 22, 2011, 09:51:30 pm »


               Why not just use the built in function.  

Function - GetAbilityModifier


If you still wanted to script it. You can reduce your function down to one line. 

int GetIntBonus(object oPC)
{
 return  (GetAbilityScore(oPC,ABILITY_INTELLIGENCE,TRUE)-10)/2;
}  



If you wanted adjusted ability scores to effect how many languages they can learn, just change the TRUE to a FALSE.
               
               

               


                     Modifié par Lightfoot8, 22 avril 2011 - 08:58 .