Aller au contenu

Photo

Create Stack of Darts, Bolts, or Arrows ** ok **


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

#1
Supreme_Pizza

Supreme_Pizza
  • Members
  • 45 messages
I know for a fact that I am not the first person to have issues with stacked items.

I've tried this script and it didn't work. So I installed NWNX_Fixes and still no luck.

FYI the script works for non stackable items.

I will post the relevant functions in the following posts.

Modifié par Supreme_Pizza, 03 février 2013 - 08:53 .


#2
Supreme_Pizza

Supreme_Pizza
  • Members
  • 45 messages
/////////////////////////////////////////////////////
// ATS_GetResRefFromTag //
// Converts a tag into a resref assuming tag //
// has the same name as resref. //
// Returns: string - ResRef //
/////////////////////////////////////////////////////
string ATS_GetResRefFromTag(string sTag)
{
return GetStringLowerCase(GetStringLeft(sTag, 16));
}

/////////////////////////////////////////////////////
// ATS_CreateItemOnPlayer //
// Wrapper for CreateItemOnObject() so it can //
// be used with DelayCommand() //
// Returns: None //
// Check local object variable: //
// "ats_returnvalue_created_item" for the //
// created object //
// Fix courtesy of Helimar on the ATS Forums //
/////////////////////////////////////////////////////
void ATS_CreateItemOnPlayer
(
string sItemTag, // Tag of the item
object oPlayer, // Player to create item on
int iStackSize = 1, // Size of the item stack
int iDropToFloor = FALSE, // Creates the item on the floor if inventory is full
)
{
string sItemResRef = ATS_GetResRefFromTag(sItemTag);
if ((GetStringRight(sItemTag,3)== "DAR") || (GetStringRight(sItemTag,3)== "dar"))
{iStackSize = 20;}
else if ((GetStringRight(sItemTag,3)== "BOL") || (GetStringRight(sItemTag,3)== "bol"))
{iStackSize = 10;}
else if ((GetStringRight(sItemTag,3)== "ARR") || (GetStringRight(sItemTag,3)== "arr"))
{iStackSize = 10;}
else
{
object oCreatedItem = CreateItemOnObject(sItemResRef, oPlayer, iStackSize);
if(GetItemPossessor(oCreatedItem) == OBJECT_INVALID && iDropToFloor == TRUE)
{ // stacked items do not have the possessor set correctly even if they were
// created correctly if the new items were added to an existing partial stack
object chk = GetObjectByTag(GetStringUpperCase(sItemTag));
if(iStackSize==1) // if it's not we assume it's a stackable
{
if(GetNumStackedItems(chk)<=1)
// check the size of the first object found by GetObjectByTag,
// which should have more than 1 if stackable, especially since
// 1 was just added to a partial stack in the previous create.
// If not, assume it's a non-stackable and create it on the ground
oCreatedItem = CreateObject(OBJECT_TYPE_ITEM, sItemResRef, GetLocation(oPlayer));
}
}
SetLocalObject(oPlayer, "ats_returnvalue_created_item", oCreatedItem);
SetLocalObject(oCreatedItem, "ats_obj_possessor", GetItemPossessor(oCreatedItem));
if(GetItemHasItemProperty(oCreatedItem, ITEM_PROPERTY_CAST_SPELL) == TRUE)
SetLocalInt(oCreatedItem, "ats_charges_fix", TRUE);
}
}

#3
Supreme_Pizza

Supreme_Pizza
  • Members
  • 45 messages
/////////////////////////////////////////////////////
// ATS_CreateObject //
// Wrapper for CreateObject() so it can //
// be used with DelayCommand() //
// Returns: None //
/////////////////////////////////////////////////////
void ATS_CreateObject
(
int iObjectType, // object type constant
string sTemplate, // object resref
location lLocation, // location of new object
int bUseAppearAnimation = FALSE // use animation
)
{
object oObjectCreated = CreateObject(iObjectType, sTemplate, lLocation, bUseAppearAnimation);
if(GetItemHasItemProperty(oObjectCreated, ITEM_PROPERTY_CAST_SPELL) == TRUE)
SetLocalInt(oObjectCreated, "ats_charges_fix", TRUE);
SetLocalObject(oObjectCreated, "ats_obj_possessor", GetItemPossessor(oObjectCreated));

}

string ATS_GetUniquePlayerID(object oPlayer)
{
return ("ATS_PID_" + GetPCPlayerName(oPlayer) + GetName(oPlayer));

}

#4
Supreme_Pizza

Supreme_Pizza
  • Members
  • 45 messages
/////////////////////////////////////////////////////
// ATS_CreateItemInContainer //
// Wrapper for CreateItemOnObject() so it can //
// be used with DelayCommand() //
// Returns: None //
// Check local object variable: //
// "ats_returnvalue_created_item" for the //
// created object //
// Fix courtesy of Helimar on the ATS Forums //
/////////////////////////////////////////////////////
void ATS_CreateItemInContainer
(
string sItemTag, // Tag of the item
object oContainer, // Container to create the item in
int iStackSize = 1, // Size of the item stack
int iForceCreation = TRUE, // If container is full, the object is created on the owner
)
{
string sItemResRef = ATS_GetResRefFromTag(sItemTag);

object oCreatedItem = CreateItemOnObject(sItemResRef, oContainer, iStackSize);
if(GetItemPossessor(oCreatedItem) == OBJECT_INVALID && iForceCreation == TRUE)
{
// stacked items do not have the possessor set correctly even if they were
// created correctly if the new items were added to an existing partial stack
object chk = GetObjectByTag(GetStringUpperCase(sItemTag));
if(iStackSize==1) // if it's not we assume it's a stackable
{
if(GetNumStackedItems(chk)<=1)
{ // check the size of the first object found by GetObjectByTag,
// which should have more than 1 if stackable, especially since
// 1 was just added to a partial stack in the previous create.
// If not, assume it's a non-stackable and create it on the player
object oPlayer = GetItemPossessor(oContainer);
ATS_CreateItemOnPlayer(sItemTag, oPlayer, iStackSize);
oCreatedItem = GetLocalObject(oPlayer, "ats_returnvalue_created_item");
}
}
}
SetLocalObject(oContainer, "ats_returnvalue_created_item", oCreatedItem);
SetLocalObject(oCreatedItem, "ats_obj_possessor", GetItemPossessor(oCreatedItem));
if(GetItemHasItemProperty(oCreatedItem, ITEM_PROPERTY_CAST_SPELL) == TRUE)
SetLocalInt(oCreatedItem, "ats_charges_fix", TRUE);
}

#5
FunkySwerve

FunkySwerve
  • Members
  • 1 308 messages
Why would you use GetObjectByTag at all? Doing that with anything with a nonunique tag is asking for trouble, and you already have an easy way of getting it - Create. I'll post what I think is what you're trying to do with the first function, though it'd be easier if you were a little more specific than 'it doesn't work'.

Funky

Modifié par FunkySwerve, 29 janvier 2013 - 04:40 .


#6
FunkySwerve

FunkySwerve
  • Members
  • 1 308 messages
Here's a cleaned-up version of the first function, with some comments indicating potential problem spots that might explain dysfunction:

/////////////////////////////////////////////////////
// ATS_CreateItemOnPlayer //
// Wrapper for CreateItemOnObject() so it can //
// be used with DelayCommand() //
// Returns: None //
// Check local object variable: //
// "ats_returnvalue_created_item" for the //
// created object //
// Fix courtesy of Helimar on the ATS Forums //
/////////////////////////////////////////////////////
void ATS_CreateItemOnPlayer(string sItemTag,object oPlayer, int iStackSize = 1, int iDropToFloor = FALSE) {

    string sItemResRef = GetStringLowerCase(GetStringLeft(sTag, 16));
    string sCheck = GetStringLowercase(GetStringRight(sItemTag, 3));
    if (sCheck == "dar")
        iStackSzie = 20;
    else if (sCheck == "bol")
        iStackSize = 10;
    else if (sCheck == "arr")
        iStackSize = 10;
    else {

        object oCreatedItem = CreateItemOnObject(sItemResRef, oPlayer, iStackSize);
        if (iDropToFloor && GetItemPossessor(oCreatedItem) == OBJECT_INVALID) {/* FKY: reordered and cleaned up - put booleans first to cut runtimes*/
            // stacked items do not have the possessor set correctly even if they were
            // created correctly if the new items were added to an existing partial stack

            /*FKY: I assume the above is what you're trying to address? I'm not familiar with ths issue, but...*/
            object chk = GetObjectByTag(GetStringUpperCase(sItemTag)); /*FKY: This is a bad idea, since tags are case-sensitive, and since, if memory serves, GOBT goes by most recently added AREA, not item */
            /*if(iStackSize==1) // if it's not we assume it's a stackable - FKY: removed bc redundant - it must be 1 here as written*/

            if(GetNumStackedItems(chk)<=1)
            /*FKY: What's the purpose of this? Will return 0 for invalid items, so you might as well just check if
            GetIsObjectValid(chk). Dropped items already head to the ground, unless you have other scripts to prevent it*/
            // check the size of the first object found by GetObjectByTag,
            // which should have more than 1 if stackable, especially since
            // 1 was just added to a partial stack in the previous create.
            // If not, assume it's a non-stackable and create it on the ground
                oCreatedItem = CreateObject(OBJECT_TYPE_ITEM, sItemResRef, GetLocation(oPlayer));
        }
        SetLocalObject(oPlayer, "ats_returnvalue_created_item", oCreatedItem);/*FKY: did you intend for the remainder only to fire if stacksize = 1? At present, this is what it does, so if so, move this stuff outside this bracket, down.*/
        SetLocalObject(oCreatedItem, "ats_obj_possessor", GetItemPossessor(oCreatedItem));
        if (GetItemHasItemProperty(oCreatedItem, ITEM_PROPERTY_CAST_SPELL))
            SetLocalInt(oCreatedItem, "ats_charges_fix", TRUE);
    }
}

Funky

Modifié par FunkySwerve, 29 janvier 2013 - 05:18 .


#7
Lightfoot8

Lightfoot8
  • Members
  • 2 535 messages
The other big bug in the mix is that you are only creating the item if  it does not have arr, bol or dar in the tag.  If it is one of them you are simply setting the stack size and then skiping the creation.   Simply get rid of the last else in the code.  From funky's corrected post. 

...string sItemResRef = GetStringLowerCase(GetStringLeft(sTag, 16));
    string sCheck = GetStringLowercase(GetStringRight(sItemTag, 3));
    if (sCheck == "dar")
        iStackSzie = 20;
    else if (sCheck == "bol")
        iStackSize = 10;
    else if (sCheck == "arr")
        iStackSize = 10;
    else {...

#8
FunkySwerve

FunkySwerve
  • Members
  • 1 308 messages
Psst. See the comment at the end:
/*FKY: did you intend for the remainder only to fire if stacksize = 1? At present, this is what it does, so if so, move this stuff outside this bracket, down.*/

Though I meant to say 'so if not' :P Moving it down a bracket puts it outside that else, but leaves the rest in, which is I THINK what he intended - though it's a bit hard to be sure.

Funky

#9
Supreme_Pizza

Supreme_Pizza
  • Members
  • 45 messages
Thanks guys!

This is the reson NWN will never die.

OK...

So this is what I have now thanks to your help.

void ATS_CreateItemOnPlayer(string sItemTag, object oPlayer, int iStackSize = 1)
{
    string sItemResRef = ATS_GetResRefFromTag(sItemTag);
    string sCheck = GetStringLowerCase(GetStringRight(sItemTag, 3));
    if (sCheck == "dar")
        iStackSize = 20;
    else if (sCheck == "bol")
        iStackSize = 10;
    else if (sCheck == "arr")
        iStackSize = 10;
    object oCreatedItem = CreateItemOnObject(sItemResRef, oPlayer, iStackSize);
    SetLocalObject(oPlayer, "ats_returnvalue_created_item", oCreatedItem);
    SetLocalObject(oCreatedItem, "ats_obj_possessor", GetItemPossessor(oCreatedItem));
    if(GetItemHasItemProperty(oCreatedItem, ITEM_PROPERTY_CAST_SPELL) == TRUE)
        SetLocalInt(oCreatedItem, "ats_charges_fix", TRUE);
}


It's clear, concise and makes total sense.

However, darts bolts and arrows still are not created.

I am starting to wonder if it is broken elsewhere.

Modifié par Supreme_Pizza, 03 février 2013 - 01:37 .


#10
Lightfoot8

Lightfoot8
  • Members
  • 2 535 messages
What sItemTag are you feeding into the function?

#11
Supreme_Pizza

Supreme_Pizza
  • Members
  • 45 messages

Lightfoot8 wrote...

What sItemTag are you feeding into the function?


Thanks!

I thought the script was good but I didn't  trust it.

Your question puhed me to check the constants where I found another error.

Thanks for all the help. :wizard: