Pfh! Don’t apologize for not being all-knowing. Very very secretly, we’re all in the same boat, there.
Very nearly. OK, custom functions lesson:
You can write new functions for pretty much anything you want. The function does not have to be in the script where it’s being called, per se; you could save it into a library which you #include at the top of the script where you’re using the function.
That way, you can access the function from different scripts, and can spare yourself a lot of bloat from repeat code. Plus, if it turns out there’s a bug with the code or you want to expand it somehow, you only have to edit one instance of it.
So, anytime you’ve got a bit of code that you’ll be using repeatedly in different scripts, it’d make a lot of sense to write it into a custom function library.
Make a new script. Delete void main from it, and copypaste these two functions into it:
// Removes nAmount stackable items tagged with sTag from oPC's inventory,
// by destroying them. Should be used in conjunction with CollectableAmountCheck().
void TakeCollectables(string sTag, int nAmount, object oPC);
void TakeCollectables(string sTag, int nAmount, object oPC)
{
if (nAmount <= 0)
return;
object oCollectable = GetItemPossessedBy(oPC, sTag);
int nStackSize = GetItemStackSize(oCollectable);
if (nStackSize <= nAmount)
{
DestroyObject(oCollectable);
nAmount -= nStackSize;
}
else
{
SetItemStackSize(oCollectable, nStackSize-nAmount);
nAmount = 0;
}
DelayCommand(0.01, TakeCollectables(sTag, nAmount, oPC));
}
// Goes through all items in oPC's inventory, counting stack sizes of all
// items tagged sCollectableTag. Returns TRUE if the total amount is equal or
// greater than nAmount. Otherwise, returns FALSE.
int CollectableAmountCheck(string sCollectableTag, int nAmount=1, object oPC=OBJECT_SELF);
int CollectableAmountCheck(string sCollectableTag, int nAmount=1, object oPC=OBJECT_SELF)
{
int nCollectables;
// Count the total collectables in the player's inventory.
object oCollectable = GetFirstItemInInventory(oPC);
while (GetIsObjectValid(oCollectable))
{
if (GetTag(oCollectable) == sCollectableTag)
nCollectables += GetItemStackSize(oCollectable);
oCollectable = GetNextItemInInventory(oPC);
}
return (nCollectables >= nAmount);
}
Save it as, for instance, “inc_collect”, and then go to your conversation node script.
Include inc_collect in it, at the very top.
#include "inc_collect"
void main()
{
object oPC = GetPCSpeaker();
string sCollectableName = "diamonds";
string sCollectableTag = "diamond";
int nAmount = 25;
// Not enough, so abort.
if (!CollectableAmountCheck(sCollectableTag, nAmount))
{
FloatingTextStringOnCreature("You don't have enough "+sCollectableName+" for that.", oPC);
return;
}
// Destroy the collectables:
TakeCollectables(sCollectableTag, nAmount, oPC);
}
Fingers crossed I didn’t write any bugs into that while moving stuff around.
Mind, I don’t know about best method. I think it’s very possible if not altogether likely that doing it in one go-through the inventory would be less performance-heavy. It’s relatively small stuff, but… in the long run, efficiency pays off in that it doesn’t cause the same lagginess problems inefficiency does.
Also, note: You can have a function implementation below void main as long as the prototype is above it.
Example:
// Function prototype.
void HelloIamAFunction(int i=1);
void main()
{
// Calling the function from void main here.
HelloIamAFunction();
}
// Function implementation.
void HelloIamAFunction(int i=1)
{
SpeakString(IntToString(i));
}