Aller au contenu

Photo

GetItemStackSize & Projectile Ammunition


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

#1
JediMindTrix

JediMindTrix
  • Members
  • 283 messages

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);
        }
       }
     }
}

 



#2
Shadooow

Shadooow
  • Members
  • 4 465 messages

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



#3
JediMindTrix

JediMindTrix
  • Members
  • 283 messages

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.



#4
Shadooow

Shadooow
  • Members
  • 4 465 messages

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



#5
JediMindTrix

JediMindTrix
  • Members
  • 283 messages

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



#6
KMdS!

KMdS!
  • Members
  • 189 messages

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.



#7
meaglyn

meaglyn
  • Members
  • 804 messages

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...



#8
KMdS!

KMdS!
  • Members
  • 189 messages

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.



#9
KMdS!

KMdS!
  • Members
  • 189 messages

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.



#10
JediMindTrix

JediMindTrix
  • Members
  • 283 messages

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



#11
ShadowM

ShadowM
  • Members
  • 768 messages

GetModuleItemLost()



#12
JediMindTrix

JediMindTrix
  • Members
  • 283 messages

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)



#13
KMdS!

KMdS!
  • Members
  • 189 messages

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



#14
JediMindTrix

JediMindTrix
  • Members
  • 283 messages

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.



#15
Shadooow

Shadooow
  • Members
  • 4 465 messages

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



#16
JediMindTrix

JediMindTrix
  • Members
  • 283 messages

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

I was also able to reproduce that behavior with throwing weapons, darts specifically. Thanks for digging that code up btw.