Author Topic: Have a NPC check for multiple items?  (Read 2339 times)

Legacy_Apeleutheros

  • Newbie
  • *
  • Posts: 22
  • Karma: +0/-0
Have a NPC check for multiple items?
« on: May 07, 2016, 12:50:47 am »


               

Please bear with me, I'm trying to learn the basics.


 


I'm making a "Go kill and fetch" quest.


 


Sorry, for being cliche, but a tavern keeper wants rats killed in the cellar (I know, I know... I'm a sucker for cliche's as long as its done well, and done with some humor.)


 


I want the Tavern keeper to demand 10 rat tails, but I do not know how to script (I'm trying to learn). I'm testing the script only using 3 tails. The script I placed into the "Text Appears When" looks like this:


 



 


int StartingConditional()

{


    // Make sure the PC speaker has these items in their inventory

    if(!HasItem(GetPCSpeaker(), "RatsTail01"))

    if(!HasItem(GetPCSpeaker(), "RatsTail02"))

    if(!HasItem(GetPCSpeaker(), "RatsTail03"))

        return FALSE;


    return TRUE;

}



Obviously I didn't do it right. The inn keeper only checks for 1 of the tails, not all 3, and the completion dialog fires. My question is, how do I make him check for all 3 tails? I assume it would by placing a + in an appropriate place?


 


Honestly, I would prefer it if there is a way I can just have the inn keeper check for a quantity of x10 "RatsTail01" so I don't clutter up my plot items list with 10 rat's tails with separate tags.


 


Sorry, I haven't really gotten familiar with the scripting language yet. Sifting through the lexicon is like reading gibberish sometimes. I think once I get it, it should make sense to me.



               
               

               
            

Legacy_Apeleutheros

  • Newbie
  • *
  • Posts: 22
  • Karma: +0/-0
Have a NPC check for multiple items?
« Reply #1 on: May 07, 2016, 12:59:00 am »


               

Would this work?


 



 



 


int StartingConditional()

{


    // Make sure the PC speaker has these items in their inventory

    if(!HasItem(GetPCSpeaker(), "RatsTail01", 10))

        return FALSE;


    return TRUE;

}




Just add a value of 10 after the "item tag"?


 


EDIT: NVM, it didn't work.



               
               

               
            

Legacy_Tarot Redhand

  • Hero Member
  • *****
  • Posts: 4165
  • Karma: +0/-0
Have a NPC check for multiple items?
« Reply #2 on: May 07, 2016, 01:34:20 am »


               

A quick check with the lexicon reveals -



 


GetNumItems(object, string)


Gets the number of the item that the target carries.

 

int GetNumItems(

    object oTarget,

    string sItem

);

 

Parameters

 

oTarget

 

The creature to check the inventory.

 

sItem

 

The tag of the item to search for.

 

Description

 

Returns the number of items of sItem that oTarget has in inventory, to include all stacked items.

 

Remarks

 

Function can be found in nw_i0_plot.nss line 780. 

 

This will count each individual item in a stack, as well as items that are not in a stack. 

 

Does not count items equipped by oTarget.

 

Requirements

 

#include "nw_i0_plot"


 


In other words you need to put the line


 


#include "nw_i0_plot"


 


at the top of your script before GetNumItems is called.


 


TR



               
               

               
            

Legacy_KMdS!

  • Sr. Member
  • ****
  • Posts: 364
  • Karma: +0/-0
Have a NPC check for multiple items?
« Reply #3 on: May 07, 2016, 03:52:23 am »


               

Let me give you a few things to think about. You might not understand what I am saying, but take the time to try to figure it out. 

When you get it, you will have a much better understanding of what you want to do. I don't want to give it to you w/o your taking a moment to think, and learn. It's the best way.


  • Are the rat tails "stackable". like potions or arrows?

  • Or are they unique, have different tags or resrefs for each tail?

This will affect how you go about finding them in the PC's inventory.


 


If the rat tail is stackable , you can find if they have the item in their inventory by using the GetItemPossessedBy method. Then use the GetItemStackSize method to see if they have the requisite quantity.


 


If they are unique items with different tags, you can use the same method, but will have to run the check multiple times, one for each tag/item.


 


The most likely situation is they are the same item (same tag and resref), and are not stsckable, In this case you mus set up a loop using the "while" loop to search the pc's inventory, setting up a counting variable to track each instance found, set each one as a local object on the pc so that if they have the requisite quantity, you can remove them from the players inventory when you dole out the reward.


 


Sounds like a daunting task? if you are new to nwscripting, it should be. Never fear, this is about as complicated as most scripting gets. Get a feel; for this and you will be ok. It's actually not that hard. Use the lexicon. Give it a try and whatever happens I will get you a working script in a couple of days that will get you close, if someone else doesn't do it first.


 


Keep trying and post your questions in the mean time.



               
               

               
            

Legacy_Tarot Redhand

  • Hero Member
  • *****
  • Posts: 4165
  • Karma: +0/-0
Have a NPC check for multiple items?
« Reply #4 on: May 07, 2016, 11:09:13 am »


               

@KMdS! Why go to all that bother when the function I found doesn't care if the items are stackable or not? It does the counting for you. The only caveat is that they must all have the same tag which from the description the op gave, the rat's tails should in all probability have. If they don't the question is why don't they? is there some compelling reason to have a different tag for each one? It cleans up and shortens the script considerably. like so -



#include "nw_i0_plot"

int StartingConditional()
{
    object oPC = GetPCSpeaker();

    if(!(GetIsPC(oPC)))
        return FALSE;

    int ReturnValue = TRUE;

    // Make sure the PC speaker has these items in their inventory

    if(GetNumItems(oPC, "RatsTail")  < 10))
        ReturnValue = FALSE;

    return ReturnValue;
}

TR



               
               

               
            

Legacy_Apeleutheros

  • Newbie
  • *
  • Posts: 22
  • Karma: +0/-0
Have a NPC check for multiple items?
« Reply #5 on: May 07, 2016, 12:04:02 pm »


               

Thanks for the responses you guys.


 


I realized last night that I just need to sit down this weekend and get a good primer on scripting so I start to grasp the language. After I get the rat quest finished from your help, I am going to go through Celowin's scripting tutorial and do a bunch of exercises so scripts start to make some sense to me.


 


So far, I have been taking the things that you guys give me, using the variable wizard, or just finding existing scripts to frankenstein together. It seems to work but when I look at the scripts, they just looks like greek to me (At least in ancient greek I can form some sentences and sort of understand the function of certain case endings). When I start to grasp the commands, functions, and their structure, the lexicon will be much more helpful to me than it currently is.


               
               

               
            

Legacy_KMdS!

  • Sr. Member
  • ****
  • Posts: 364
  • Karma: +0/-0
Have a NPC check for multiple items?
« Reply #6 on: May 07, 2016, 04:52:54 pm »


               


@KMdS! Why go to all that bother when the function I found doesn't care if the items are stackable or not? It does the counting for you. The only caveat is that they must all have the same tag which from the description the op gave, the rat's tails should in all probability have. If they don't the question is why don't they? is there some compelling reason to have a different tag for each one? It cleans up and shortens the script considerably. like so -



#include "nw_i0_plot"

int StartingConditional()
{
    object oPC = GetPCSpeaker();

    if(!(GetIsPC(oPC)))
        return FALSE;

    int ReturnValue = TRUE;

    // Make sure the PC speaker has these items in their inventory

    if(GetNumItems(oPC, "RatsTail")  < 10))
        ReturnValue = FALSE;

    return ReturnValue;
}

TR




W/O knowledge of what he did I just thought to include as many contingencies as possible. His listing of "RatsTail01", "RatsTail02", "RatsTail03" left me unsure whether a mistake in logic or actually unique items.


 


I had forgotten the particular method you used and had difficulty reading your earlier post.  '<img'>


 


@Apeleutheros


That's a good idea. Here's looking to your future success!


               
               

               
            

Legacy_KMdS!

  • Sr. Member
  • ****
  • Posts: 364
  • Karma: +0/-0
Have a NPC check for multiple items?
« Reply #7 on: May 07, 2016, 06:10:12 pm »


               

Did a little research and found why I didn't remember the method. Here is the actual code for the method


 


int GetNumItems(object oTarget,string sItem)
{
    int nNumItems = 0;
    object oItem = GetFirstItemInInventory(oTarget);
 
    while (GetIsObjectValid(oItem) == TRUE)
    {
        if (GetTag(oItem) == sItem)
        {
            nNumItems = nNumItems + GetNumStackedItems(oItem);
        }
        oItem = GetNextItemInInventory(oTarget);
    }
 
   return nNumItems;
}

               
               

               
            

Legacy_KMdS!

  • Sr. Member
  • ****
  • Posts: 364
  • Karma: +0/-0
Have a NPC check for multiple items?
« Reply #8 on: May 07, 2016, 06:21:15 pm »


               

Phoooey, I don't like the way the board processes posts, lost the actuaql info I wanted to convey because I entered it after the code....Here goes a second time.... ':wacko:'


 


Anyway, The method actually performs the loop I described above but performs no work. Without the required processing of the item searched for, another loop must be run through the PC's inventory to remove or otherwise process the item. That can be a very bad thing as players can have an incredible amount of inventory on hand and running multiple loops through it will many times get you the unwanted TMI (Too Many Instructions) error. Also, the method does not check any of the PC's container items either...more loops and loops. For this reason I never consider it, BUT!!!!!, it is an excellent starting template for the loop required.



               
               

               
            

Legacy_KMdS!

  • Sr. Member
  • ****
  • Posts: 364
  • Karma: +0/-0
Have a NPC check for multiple items?
« Reply #9 on: May 07, 2016, 07:38:23 pm »


               

Here would be a better template.


 


*Edited to take into account new info referenced below



// Return the number of items with the tag provided.

// Set bProcess = TRUE to store the item instance for processing outside of this method
// and the total count of instances found.
// Retrieve an instance of an object by retrieving the local object "ITEM_NUMBER_*") stored
// on the target object, the * must be a number between 1 and the total count of instances stored in
/// the local variable int "ITEM_COUNT".
// Retrieve the total number of item instances by retrieving the local variable int "ITEM_COUNT"
// stored on the target object.
int GetNumberOfItemsInInventory(object oTarget,string sItemTag, int bProcess = FALSE);
int GetNumberOfItemsInInventory(object oTarget,string sItemTag, int bProcess = FALSE)
{
    int nNumItems = 0;
    int iIteration = 0;
 
    object oItem = GetFirstItemInInventory(oTarget);
    while (oItem != OBJECT_INVALID)
    {
        if (GetTag(oItem) == sItemTag)
        {
            nNumItems += GetNumStackedItems(oItem);
            if(bProcess)
            {
                // Store the item for retrieval outside this method
                SetLocalObject(oTarget, "ITEM_NUMBER_"+IntToString(++iIteration), oItem);
                /***Place whatever additional processing you want one here**/
            }
        }
        oItem = GetNextItemInInventory(oTarget);
    }
    if(bProcess)
    {
        // Store the number of instances found for retrieval outside this method
        SetLocalInt(oTarget, "ITEM_COUNT", iIteration);
        /***Place whatever additional processing you want one here**/
    }
 
   return nNumItems;
}


               
               

               
            

Legacy_meaglyn

  • Hero Member
  • *****
  • Posts: 1451
  • Karma: +0/-0
Have a NPC check for multiple items?
« Reply #10 on: May 07, 2016, 08:44:45 pm »


               

You don't need the loop with the containers. Things in the PC's inventory which are in containers will still show up in the main loop. You can count things twice the way you have it.  TR already pointed to the GetNumItems routine so it should not have been too hard to find '<img'>



               
               

               
            

Legacy_KMdS!

  • Sr. Member
  • ****
  • Posts: 364
  • Karma: +0/-0
Have a NPC check for multiple items?
« Reply #11 on: May 08, 2016, 02:16:23 am »


               

Wonderful, it's fun top learn something new. Thanks..


 


Anyway, there is still the issue of having to run multiple loops to actually do anything with the items found.  I edited the post above to reflect the new information. and be able to do something to minimize the need to loop through inventory more than once should you need to do something with the items found.



               
               

               
            

Legacy_meaglyn

  • Hero Member
  • *****
  • Posts: 1451
  • Karma: +0/-0
Have a NPC check for multiple items?
« Reply #12 on: May 08, 2016, 02:52:55 am »


               

Yeah, I like your approach of saving them to temp local object vars so you can get at them later.  That can be useful.



               
               

               
            

Legacy_Apeleutheros

  • Newbie
  • *
  • Posts: 22
  • Karma: +0/-0
Have a NPC check for multiple items?
« Reply #13 on: May 09, 2016, 09:57:28 pm »


               

I ended up using this script from the wiki for now.



 


#include "nw_i0_plot"

int StartingConditional()

{

    //check inventory of oPC for oQuestItem and get iNumItems

    string sMark = "RatsTail01";

    int nMarkCount = 10;

    object oMark = GetObjectByTag(sMark);

    if(GetNumItems(GetPCSpeaker(),sMark) >= nMarkCount)

        return TRUE;

    return FALSE;

}



It was easy to set up and it does what I want. I don't know if it will work if the rat tails are in a bag. At this point the PC is level 1, and doesn't have an opportunity to purchase a bag (It's late at night and the stores are all closed).


 


He then takes the tails,



 


#include "nw_i0_plot"

void main()

{

    string sMark = "RatsTail01"; // Enter tag of your Item

    object oMark = GetObjectByTag(sMark);

    int nMarkCount = 10; // Change to num Items you want

    if(GetNumItems(GetPCSpeaker(),sMark) >= nMarkCount)

        {

        TakeNumItems(GetPCSpeaker(),sMark,nMarkCount);

        // Uncomment the following line to Give the PC an Item Also

        // CreateItemOnObject("item_ResRef",GetPCSpeaker(),1);

        }

}



I still have to set it up so the Inn Keeper rewards the player with exp/gold and set a variable to open up the next part of the plot.


 


The dialogs are getting a little overwhelming for me. I'm trying to offer opportunity for the PC to role play a bit and it opens up a lot of trees. I'm getting it figured out, but all the dialog branches, copying, pasting, looping in the dialog, and all the variables and scripts are overloading my meager, one task brain, lol.



               
               

               
            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Have a NPC check for multiple items?
« Reply #14 on: May 10, 2016, 02:36:31 am »


               


Wonderful, it's fun top learn something new. Thanks..


 


Anyway, there is still the issue of having to run multiple loops to actually do anything with the items found.  I edited the post above to reflect the new information. and be able to do something to minimize the need to loop through inventory more than once should you need to do something with the items found.




 


in a conversation it is better to run multiple loops then to store the number of items as a local,  due to players exploits.