Starting Conditional for GetBaseItemType

Warm winds and hello! I seem to struggling with just a basic starting conditional. I’m wondering if there’s an error in my logic (most likely), or getting BaseItemType in this situation is not recommended. Just a simple check to see if a PC has any shortsword in their inventory (resrefs and tags matter not). Anyway, this one is stumping me, but it’s been a long two weeks…

//toh_has_sh_sword
int StartingConditional()
{

    object oPC = GetPCSpeaker();

    // The PC must possess a shortsword
    if(GetBaseItemType(oPC) == BASE_ITEM_SHORTSWORD)
        return FALSE;

    return TRUE;
}

The problem with this script is that you are identifying your character as a sword, your script will always return TRUE, because your character is not a sword.

I don’t remember if NWN1 has the script, but there is something in NWN2 called GetItemPossessedBy (or something like that, it’s been a while), that use the tag of the item as argument, that function automatically cycles through all items in your inventory and returns true if you have an item with that tag.

In alternative, you can cycle manually

object oITEM = GetFirstItem(oPC) <- (I don't remember the exact function name but it's very similar)
while (oITEM != OBJECT_INVALID)
[
    if(GetBaseItemType(oITEM) == BASE_ITEM_SHORTSWORD) return FALSE;
    oITEM = GetNextItem(oPC);
]

return TRUE;

Damn I can’t even do the proper brackets anymore… =(

1 Like

You want to know if the PC has any short swords or does not have any short swords at all?

@Clangeddin is right that you are checking the PC against being a base item type which won’t work either way.

You can do a loop similar to what was shown in Clangeddin’s reply but you need to reverse the logic and have it only return TRUE when an item is a short sword. Chances are the first item you check will not be a short sword and so it will return FALSE as written and not check anything else.

If you reverse it then it can be used for either case. However, as written it also won’t count the right or left hand equipped slots so you may want to check those first. Returning true if either is a short sword.

1 Like

Hmm, thanks for the kind replies. So, there is an error in my logic, I see now. And also in how I interpret “GetItemPossessedBy,” I think. I assumed it would check both inventory and equipment slots. So, if I structure it differently, perhaps like this?

//toh_has_sh_sword
int StartingConditional()
{

    object oPC = GetPCSpeaker();

    // The PC must possess a shortsword
    object oItem = GetItemPossessedBy(oPC, "Item");
    if(GetBaseItemType(oItem) == BASE_ITEM_SHORTSWORD)
        return FALSE;

    return TRUE;
}

Hmmm, no, that’s not it either, I think. GetItemPossessedBy still looks for a tag, methinks, so I don’t see away around using it that way.

Perhaps this is closer:

//toh_has_sh_sword
int StartingConditional()
{

object oPC = GetPCSpeaker();
object oITEM = GetFirstItemInInventory(oPC);
while (oITEM != OBJECT_INVALID)
{
    if(GetBaseItemType(oITEM) == BASE_ITEM_SHORTSWORD) return FALSE;
    oITEM = GetNextItemInInventory(oPC);
}

return TRUE;
}

Hmmm, no, that’s not it either, blast!

The second one is closer. You really need to reverse the logic and return TRUE if oItem is a SS. And FALSE after checking all of inventory. Otherwise getting FALSE doesn’t mean much. Most of the items in the inventory will not be SSs. You can’t return FALSE (that the PC does not have a SS) until you’ve checked everything

Based on the name of the file (toh_has_sh_sword) it would work (not counting the two relevant inventory slots) if you just switched those words (FALSE and TRUE).

Before the loop starts you can check the inventory slots.

object oITEM = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oPC);
If (GetIsObjectValid(oITEM) && GetBaseItemType(oITEM) == BASE_ITEM_SHORTSWORD) 
        return TRUE;
// Repeat for RIGHTHAND
// then
oITEM = GetFirstItemInInventory(oPC);
...
1 Like

Brilliant! I forgot to reverse the logic, duh. And so a final version would look like so:

//toh_has_sh_sword
int StartingConditional()
{

object oPC = GetPCSpeaker();

object oITEM = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oPC);
    if (GetIsObjectValid(oITEM) && GetBaseItemType(oITEM) == BASE_ITEM_SHORTSWORD)
        return TRUE;

object oITEM2 = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC);
    if (GetIsObjectValid(oITEM2) && GetBaseItemType(oITEM2) == BASE_ITEM_SHORTSWORD)
        return TRUE;

object oITEM3 = GetFirstItemInInventory(oPC);
    while (oITEM3 != OBJECT_INVALID)
{
    if(GetBaseItemType(oITEM3) == BASE_ITEM_SHORTSWORD) return TRUE;
    oITEM3 = GetNextItemInInventory(oPC);
}

return FALSE;
}

Thanks, @meaglyn and @Clangeddin ! You solved my minor riddle and I award you each 500 xp!

#include "x0_i0_partywide"

void main()
{
    object oPCs = GetMeaglynAndClangeddin();
    GiveXPToAll(oPC, 500);
}
1 Like

Great! As an minor nit, you don’t need all the different object oITEM variables. One is sufficient. Just re-use for the second and third check. But it won’t really matter… it’ll work fine as is.

Thanks for the XP! I’ll be able to level up any day now :slight_smile:

1 Like

I thought so, too, but the compiler did not like it so much and complained I was using the same resource over, and then had the nerve not to compile it! As if! Anyway, simply renaming those variables fixed it.

Well, you need to drop the repeated “object” part at the beginning as I did in my snippet. You need to and can only declare oITEM once.

1 Like