Author Topic: GetItemStackSize & Projectile Ammunition  (Read 1683 times)

Legacy_JediMindTrix

  • Sr. Member
  • ****
  • Posts: 383
  • Karma: +0/-0
GetItemStackSize & Projectile Ammunition
« on: May 29, 2016, 08:16:49 pm »


               

Hi all!


 


Is there a way to get via NWScript if the last projectile of a stack has been fired?


 


I.E: *Last arrow is fired.*


*Script returns that it no longer exists, or better yet, returns the name or tag of the last projectile fired.*


 


Using GetItemStackSize only seems to work if there is only one projectile left. I assume this is ironically, because the projectile no longer exists, and thus the stacksize can't be 'got'.


 


Methods I've tried:


int bIsAmmoOrThrowing = GetBaseItemType(oItem) == BASE_ITEM_ARROW    ||
                        GetBaseItemType(oItem) == BASE_ITEM_BOLT     ||
                        GetBaseItemType(oItem) == BASE_ITEM_BULLET   ||
                        GetBaseItemType(oItem) == BASE_ITEM_DART     ||
                        GetBaseItemType(oItem) == BASE_ITEM_SHURIKEN ||
                        GetBaseItemType(oItem) == BASE_ITEM_THROWINGAXE;
if (!bIsAmmoOrThrowing) return; //Check nBaseItemType to see if it's a projectile
    {
      if(oItem == OBJECT_INVALID)
       {
        SendMessageToPC(oPC, "Arrows no longer exist");
        if(jmtFindMatchingNameTypeAndEquip(oPC, oItem) != TRUE)
        {
         SendMessageToPC(oPC, "Same Item/Name Not Found!");
         jmtFindMatchingTypeAndEquip(oPC, oItem);
        }
       }
     }
}

 


if (!bIsAmmoOrThrowing) return; //Check nBaseItemType to see if it's a projectile
    {
      if(GetItemStackSize(oItem) > 1)
       {
        SendMessageToPC(oPC, "Arrows no longer exist");
        if(jmtFindMatchingNameTypeAndEquip(oPC, oItem) != TRUE)
        {
         SendMessageToPC(oPC, "Same Item/Name Not Found!");
         jmtFindMatchingTypeAndEquip(oPC, oItem);
        }
       }
     }
}

 



               
               

               
            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
GetItemStackSize & Projectile Ammunition
« Reply #1 on: May 29, 2016, 08:45:59 pm »


               

I see what you are trying to do.


 


Here is how to accomplish this.


 


1) when item is equipped, set local variable with this format SetLocalString(oPC,ObjectToString(oItem),GetResRef(oItem));


2) when item is unequipped therefore ran out of, check for this variable GetLocalString(oPC,ObjectToString(oItem)); to determine a new item to equip


 


However, there are few issues:


 


1) arrow/bolts/bullets are equipped automatically, I dont know whether you will be able to override this, ie. whether OnUnAcquire runs before this happens


2) in case of throwing weapons, you need the code from community patch that performs action cancel in case player thrown last dart/shuriken/throwing axe as without it, player character tends to initiate unarmed melee attack



               
               

               
            

Legacy_JediMindTrix

  • Sr. Member
  • ****
  • Posts: 383
  • Karma: +0/-0
GetItemStackSize & Projectile Ammunition
« Reply #2 on: May 29, 2016, 09:00:31 pm »


               


I see what you are trying to do.


 


Here is how to accomplish this.


 


1) when item is equipped, set local variable with this format SetLocalString(oPC,ObjectToString(oItem),GetResRef(oItem));


2) when item is unequipped therefore ran out of, check for this variable GetLocalString(oPC,ObjectToString(oItem)); to determine a new item to equip


 


However, there are few issues:


 


1) arrow/bolts/bullets are equipped automatically, I dont know whether you will be able to override this, ie. whether OnUnAcquire runs before this happens


2) in case of throwing weapons, you need the code from community patch that performs action cancel in case player thrown last dart/shuriken/throwing axe as without it, player character tends to initiate unarmed melee attack




 


An issue I see here: There is no way that I can see to differentiate between a player intentionally unequipping the last projectile in a stack and when it actually runs out. The UnEquip script triggers when you hit the last projectile, and not when it actually runs out.


 


EDIT: OH! I was worried about #1 as well, but since the game only auto-equips a projectile when you next attempt to fire and you have none in your projectile slot, the script actually "beats" it to the punch, equipping the next projectile before the vanilla game's auto-equip is triggered.


For #2 this has definitely proved to be a problem in testing. I am unable to install the patch and can't retrieve this code, unfortunately.



               
               

               
            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
GetItemStackSize & Projectile Ammunition
« Reply #3 on: May 29, 2016, 10:16:04 pm »


               


An issue I see here: There is no way that I can see to differentiate between a player intentionally unequipping the last projectile in a stack and when it actually runs out. The UnEquip script triggers when you hit the last projectile, and not when it actually runs out.




iirc, the loss of the last ammo/thrown weapon fires only OnUnAcquire and the item is not valid there (GetIsObjectValid == false) but not invalid (oItem != OBJECT_INVALID) whereas manually dropping the item on floor will run OnUnEquip first then OnUnAcquire and item will be valid in both events and its stacksize will also be retriveable


               
               

               
            

Legacy_JediMindTrix

  • Sr. Member
  • ****
  • Posts: 383
  • Karma: +0/-0
GetItemStackSize & Projectile Ammunition
« Reply #4 on: May 29, 2016, 10:43:37 pm »


               

That's a little confusing. Because the object is neither valid or invalid, then OnUnAcquire can't be used?



               
               

               
            

Legacy_KMdS!

  • Sr. Member
  • ****
  • Posts: 364
  • Karma: +0/-0
GetItemStackSize & Projectile Ammunition
« Reply #5 on: May 30, 2016, 01:46:47 am »


               

Shadoow,


 


Are you certain the missile item isn't invalid after the last is fired? I haven't tested for that to date, just wondering.


 


Sorry Jedi I didn't get beck to you, been unexpectedly busy the last couple of days.



               
               

               
            

Legacy_meaglyn

  • Hero Member
  • *****
  • Posts: 1451
  • Karma: +0/-0
GetItemStackSize & Projectile Ammunition
« Reply #6 on: May 30, 2016, 02:07:39 am »


               

As Shadooow more or less said, this item _is_ invalid in the unacquire event it's just not equal to OBJECT_INVALID.  That is, GetIsObjectValid will return FALSE, but the item object does not have the specific value OBJECT_INVALID.  Objects can be invalid without being equal to OBJECT_INVALID.  He sort of clouded the issue with his wording, saying "... is not valid ... but not invalid".  Not valid _is_ invalid, it's just not OBJECT_INVALID.  The validity of an object is boolean. There are only two states...



               
               

               
            

Legacy_KMdS!

  • Sr. Member
  • ****
  • Posts: 364
  • Karma: +0/-0
GetItemStackSize & Projectile Ammunition
« Reply #7 on: May 30, 2016, 02:12:25 am »


               

Ok, finally had a moment to look at your situation Jedi....you need to script hook to get this done.


 


Instead of having the script directly equip the replacement missile on last missile firing, have the script only determine that the missiles equiped were unaquired and have the script run a delayed method, maybe 1.5 seconds, to equip the new missiles with a check for a local variable before performing the equip.


 


Next, create an unequip method to check if the creature unequiped the missile wep, if so, set a variable that the delayed script will look for before equipping the fresh missiles. Otherwise, if the variable is not found by the equiping method, it will equip the missiles.


 


From what I saw of your script, you seem capable of creating this.



               
               

               
            

Legacy_KMdS!

  • Sr. Member
  • ****
  • Posts: 364
  • Karma: +0/-0
GetItemStackSize & Projectile Ammunition
« Reply #8 on: May 30, 2016, 02:44:25 am »


               

Thanks Meaglyn, that I knew, just didn't quite get how he said it. If I remember right, you actually can't to the oObject == OBJECT_INVALID check unless that value is specifically set on oObject by the method used.



               
               

               
            

Legacy_JediMindTrix

  • Sr. Member
  • ****
  • Posts: 383
  • Karma: +0/-0
GetItemStackSize & Projectile Ammunition
« Reply #9 on: May 30, 2016, 09:57:00 pm »


               

There is no GetModuleItemUnAcquired function. I'm uncertain how to proceed.



               
               

               
            

Legacy_ShadowM

  • Hero Member
  • *****
  • Posts: 1373
  • Karma: +0/-0
GetItemStackSize & Projectile Ammunition
« Reply #10 on: May 30, 2016, 10:00:31 pm »


               

GetModuleItemLost()



               
               

               
            

Legacy_JediMindTrix

  • Sr. Member
  • ****
  • Posts: 383
  • Karma: +0/-0
GetItemStackSize & Projectile Ammunition
« Reply #11 on: May 30, 2016, 10:26:46 pm »


               

Some issues I see:

When you 'drop' something, which will fire the script as well using GetModuleItemLost(), does it not unequip the item first into inventory before dropping it, just as when you try to equip something from the ground, it first goes into your inventory before being equipped?


Thus, would setting a variable on UnEquip happen regardless of whether or not it was dropped or merely unequipped? Or am I missing something here? (Totally likely it's late)



               
               

               
            

Legacy_KMdS!

  • Sr. Member
  • ****
  • Posts: 364
  • Karma: +0/-0
GetItemStackSize & Projectile Ammunition
« Reply #12 on: May 30, 2016, 10:52:59 pm »


               

Should be unequip first, then unacquire for droping an equipped item. The reverse for equiping...Acquire first, then equip.



               
               

               
            

Legacy_JediMindTrix

  • Sr. Member
  • ****
  • Posts: 383
  • Karma: +0/-0
GetItemStackSize & Projectile Ammunition
« Reply #13 on: June 01, 2016, 10:18:20 pm »


               

Testing has shown me that: OnUnAcquireItem does not seem to be triggered when the last of a projectile is shot, but it does when you just plain drop it from your inventory. Anymore ideas? For I am all out.



               
               

               
            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
GetItemStackSize & Projectile Ammunition
« Reply #14 on: June 01, 2016, 10:58:24 pm »


               


Testing has shown me that: OnUnAcquireItem does not seem to be triggered when the last of a projectile is shot, but it does when you just plain drop it from your inventory. Anymore ideas? For I am all out.




Thats weird, I know for a fact it does run for throwing weapons. I wasn't dealing with ammo, but it should work as well.


 


Here the code from CPP to fix the automatic unarmed attack:



     //1.71: fix for automatic unarmed attack when stack of throwing weapons gets destroyed
     if(!GetIsObjectValid(oItem) && oItem != OBJECT_INVALID && GetAttackTarget(oPC) != OBJECT_INVALID && GetItemInSlot(INVENTORY_SLOT_RIGHTHAND,oPC) == OBJECT_INVALID)
     {
         AssignCommand(oPC,ClearAllActions());
     }

this is in unacquire