Aller au contenu

Photo

How do you make an NPC take only ONE potion?


  • Veuillez vous connecter pour répondre
9 réponses à ce sujet

#1
LostChangeling

LostChangeling
  • Members
  • 25 messages

Hi, everyone. New here. Been working on a module for Neverwinter Nights (absolutely wonderful game). :) There's just a problem I've run into.

 

I'm trying to make an NPC take a certain potion from my player at a certain point in the game. Now as you know potions are stackable items, meaning you can have a batch of say up to 10 of the same potion grouped together in the same space in your inventory. This seems to lead to an interesting problem: during the game the NPC grabs all of the potions I have in the same batch, as if treating the entire batch as one single thing, rather than just deduct 1 from the batch. So if I have 3 bottles of ale at first -- all grouped together in one batch -- I'm not left with 2 but 0. This sort of thing didn't happen with non-stackable items.

 

Question: how do you script the thing so that the NPC will take only one potion, leaving you with still 2? Tried searching online for some tutorial or hints; no luck. Any help will be greatly appreciated, thanks!



#2
kalbaern

kalbaern
  • Members
  • 824 messages

Post your current script and one of us can easily modify it for you.


  • LostChangeling aime ceci

#3
LostChangeling

LostChangeling
  • Members
  • 25 messages

Thanks. Here's the script. Basically I'm just trying to make an NPC take a bottle of ale from the player and give him/her a healing potion in return.

 

I usually watch my spelling very carefully, by the way.  ;)

 

void main()
{
    // Give the speaker the items
    CreateItemOnObject("nw_it_mpotion003", GetPCSpeaker(), 1);
 
 
    // Remove items from the player's inventory
    object oItemToTake;
    oItemToTake = GetItemPossessedBy(GetPCSpeaker(), "NW_IT_MPOTION021");
    if(GetIsObjectValid(oItemToTake) != 0)
        DestroyObject(oItemToTake);
}


#4
MagicalMaster

MagicalMaster
  • Members
  • 2 003 messages

You can't destroy the object since that includes every item in the stack.  You'll need to adjust the stack size instead (unless, say, the stack size was 1 to start...).  See if you can figure it out from there -- if not, we can help fix it.


  • Squatting Monk et LostChangeling aiment ceci

#5
LostChangeling

LostChangeling
  • Members
  • 25 messages

Ah, HA!  :D

 

I believe then that what I need to do is: (1) get the current stack size; (2) subtract 1 from it; and (3) make the result the new stack size. Presumably the code would be something like this:

 

SetItemStackSize(object oItemToTake, ((GetItemStackSize(object oItemToTake)) - 1));

 

Substituted the last line in my script above (the one in blue) with this line (the one in red) and then tried compiling it; the toolset returned 'Error: Unknown state in compiler'. What gives? I've very little grasp of the syntax of the language actually; the script in blue was created with the script wizard. Help, please? Thanks!



#6
Fester Pot

Fester Pot
  • Members
  • 1 394 messages

Well, you've already defined oItemToTake as an object, so it's just in name that's required.

 

SetItemStackSize(oItemToTake, (GetItemStackSize(oItemToTake)) - 1);

 

FP!


  • Squatting Monk et LostChangeling aiment ceci

#7
Kato -

Kato -
  • Members
  • 392 messages
void TakeNumItemsFromPC(object oPC, string sRef, int nNmb)
{
   int nDeleted, nItemStack;
   object oItem = GetFirstItemInInventory(oPC);
   while(GetIsObjectValid(oItem) && nDeleted < nNmb)
   {
      if(GetResRef(oItem) == sRef)
      {
         nItemStack = GetItemStackSize(oItem);
         if(nItemStack <= (nNmb-nDeleted))
         {
            nDeleted += nItemStack;
            DestroyObject(oItem);
         }
         else
         {
            SetItemStackSize(oItem, nItemStack-(nNmb-nDeleted));
            nDeleted += (nNmb-nDeleted);
         }
      }
      oItem = GetNextItemInInventory(oPC);
   }
}
 
 
Modify the function accordingly if you prefer using the tag instead of the resref.
 
 
Kato


#8
LostChangeling

LostChangeling
  • Members
  • 25 messages

Thanks, Kato! This may well prove helpful!

 

I actually tried Fester Pot's correction of my piece of script. This time it compiled properly. And guess what: in the game the stack does get reduced in size as I wanted it to, but if my player has only one bottle of ale, the number stops getting reduced! Apparently any stack must have at least a value of 1, so if you want to simulate the last bottle of ale being taken away you can no longer use SetItemStackSize, but must use DestroyObject. (I initially thought that when the stack size is reduced to 0, then the item is automatically 'destroyed'.) Ah, well, more correction work for me...

 

Well, at least progress is now being made. Thanks so much, you fellas rock!  :D



#9
MagicalMaster

MagicalMaster
  • Members
  • 2 003 messages

Apparently any stack must have at least a value of 1, so if you want to simulate the last bottle of ale being taken away you can no longer use SetItemStackSize, but must use DestroyObject.

 

Correct, hence my earlier hint of

 

(unless, say, the stack size was 1 to start...)

 

Kato's script is designed to work across multiple stacks of items if needed, hence the loop and some of the other stuff.  I'm assuming it works correctly as it looks about right.


  • Squatting Monk aime ceci

#10
Kato -

Kato -
  • Members
  • 392 messages

All true you guys, sorry that I misread the exact concept sought after...