Author Topic: Item Property Craziness - What Gives?  (Read 1478 times)

Legacy_JediMindTrix

  • Sr. Member
  • ****
  • Posts: 383
  • Karma: +0/-0
Item Property Craziness - What Gives?
« on: May 24, 2016, 04:36:31 pm »


               

I have this block of code in my OnUnEquip module event:



if (GetBaseItemType(oItem) == BASE_ITEM_ARROW  || BASE_ITEM_BOLT || BASE_ITEM_BULLET || BASE_ITEM_SHURIKEN || BASE_ITEM_THROWINGAXE) //Check if the last unequipped is a projectile weapon of any kind.

        {

        //Get Item Properties and declare them as ints to be called by IPGetItemHasProperty later in the equip script. ignore temporaries because they add too many variables.
        itemproperty iProperty = GetFirstItemProperty(oItem)
         while(GetIsItemPropertyValid(iProperty))
         {
         int iPropertyType1 = GetItemPropertyType(iProperty);                       //The general idea here is that every loop through, this codeblock will declare individual ints for every
         int iPropertySubType1 = GetItemPropertySubType(iProperty);                 //item property and it's subtype, checking against the last declared one to make sure they are not the same.
         int iPropertyParam1 = GetItemPropertyParam1(iProperty);
         int iPropertyParam1Value = GetItemPropertyParam1Value(iProperty);
         SendMessageToPC(oPC, IntToString(iPropertyType1));
         SendMessageToPC(oPC, IntToString(iPropertySubType1));
         SendMessageToPC(oPC, IntToString(iPropertyParam1));
         SendMessageToPC(oPC, IntToString(iPropertyParam1Value));
         if(iPropertyType1)

         {
          int iPropertyType2 = GetItemPropertyType(iProperty);
          int iPropertySubType2 = GetItemPropertyType(iProperty);
          int iPropertyParam2 = GetItemPropertyParam1(iProperty);
          int iPropertyParam2Value = GetItemPropertyParam1Value(iProperty);
          SendMessageToPC(oPC, IntToString(iPropertyType2));
          SendMessageToPC(oPC, IntToString(iPropertySubType2));
          SendMessageToPC(oPC, IntToString(iPropertyParam2));
          SendMessageToPC(oPC, IntToString(iPropertyParam2Value));
          if(iPropertyType2)

           {

           int iPropertyType3 = GetItemPropertyType(iProperty);
           int iPropertySubType3 = GetItemPropertyType(iProperty);
           int iPropertyParam3 = GetItemPropertyParam1(iProperty);
           int iPropertyParam3Value = GetItemPropertyParam1Value(iProperty);
           SendMessageToPC(oPC, IntToString(iPropertyType3));
           SendMessageToPC(oPC, IntToString(iPropertySubType3));
           SendMessageToPC(oPC, IntToString(iPropertyParam3));
           SendMessageToPC(oPC, IntToString(iPropertyParam3Value));
           if(iPropertyType3)

            {
            int iPropertyType4 = GetItemPropertyType(iProperty);
            int iPropertySubType4 = GetItemPropertyType(iProperty);
            int iPropertyParam4 = GetItemPropertyParam1(iProperty);
            int iPropertyParam4Value = GetItemPropertyParam1Value(iProperty);
            SendMessageToPC(oPC, IntToString(iPropertyType4));
            SendMessageToPC(oPC, IntToString(iPropertySubType4));
            SendMessageToPC(oPC, IntToString(iPropertyParam4));
            SendMessageToPC(oPC, IntToString(iPropertyParam4Value));
             if(iPropertyType4)

             {
             int iPropertyType5 = GetItemPropertyType(iProperty);
             int iPropertySubType5 = GetItemPropertyType(iProperty);
             int iPropertyParam5 = GetItemPropertyParam1(iProperty);
             int iPropertyParam5Value = GetItemPropertyParam1Value(iProperty);
             SendMessageToPC(oPC, IntToString(iPropertyType5));
             SendMessageToPC(oPC, IntToString(iPropertySubType5));
             SendMessageToPC(oPC, IntToString(iPropertyParam5));
             SendMessageToPC(oPC, IntToString(iPropertyParam5Value));
             }
            }
           }
         }
         iProperty = GetNextItemProperty(oItem);  //Loop over.
        }
        }
}

The goal for this code is to prevent the loop from overwriting any of the declared ints, so that each integer matches an individual property (And property subtype, and param1 and param1value). However in testing I noticed this:


 


strangeness1.jpg


 


The item tested has the following properties:

strangeness2.jpg


Unfortunately, this presents a roadblock in what I intended to do with this script: compare the values obtained from each individual property to compare against the properties on other items later.


Can anyone tell me if I am implementing this code wrong, if I've run into an engine bug of some kind, or if there are workarounds to dodge this '225'??


 


Cheers!


 


-JediMindTrix


EDIT: I realized shortly after posting this that the SendMessageToPC's should've all been in the final if statement, so I moved them and added a break; It appears that as I had hoped, nothing was being overwritten.



               
               

               
            

Legacy_meaglyn

  • Hero Member
  • *****
  • Posts: 1451
  • Karma: +0/-0
Item Property Craziness - What Gives?
« Reply #1 on: May 24, 2016, 05:24:13 pm »


               

That's not what your code is doing. It's doing all 5 code blocks for each item property.  In that last one, what you show on the screen, you are setting iPropertyType1  to 16 from GetItemPropertyType(iProperty);  then checking if that value is non-zero (if(iPropertyType1)) which is true since it's 16, then doing the code for iPropertyType2 based on the same iProperty.  And so on... so you get the same item property printed over again.    The 255s are there because those itemproperties do not have settings for param and value.


(also you're getting the type twice for 2 -5, rather than the subtype which is why the first one is "16 6 255 255" and the other 4 are "16 16 ...").


 


I think the thing to do would be to operate on each itemproperty in the loop. Such as saving them as locals, which you can do with incrementing names.  i.e. SetLocalInt(oSomeObject, "itemproptype" + IntToString(i), GetItemPropertyType(iProperty));   Presumably you are planning to do something with those variables to which you have assigned values.


 


Also, it will do this code no matter what the baseitemtype is.  If (foo == x || y)  does not do what you think it does. It will be true if foo == x  and true if y is non-zero regardless of the value of foo. 



int nType = GetBaseItemType(oItem);
if (nType == BASE_ITEM_ARROW  || nType == BASE_ITEM_BOLT || nType == BASE_ITEM_BULLET || nType == BASE_ITEM_SHURIKEN || nType == BASE_ITEM_THROWINGAXE) {

               
               

               
            

Legacy_JediMindTrix

  • Sr. Member
  • ****
  • Posts: 383
  • Karma: +0/-0
Item Property Craziness - What Gives?
« Reply #2 on: May 24, 2016, 06:36:07 pm »


               

Wow, I was way off the mark! But this is part of the learning experience '<img'>


 


I am confused by this, though:


"The 255s are there because those itemproperties do not have settings for param and value." -Meaglyn


Inside the .2da that the function calls, there is a DamageType (it's line 0). Which is what I thought I was calling. What are param1 and param1value for, if not for that?


How would I go about retrieving the damage type? GetItemPropertyCostx?



               
               

               
            

Legacy_meaglyn

  • Hero Member
  • *****
  • Posts: 1451
  • Karma: +0/-0
Item Property Craziness - What Gives?
« Reply #3 on: May 24, 2016, 06:56:30 pm »


               

The itemproperty in the example (16)  is created with ItemPropertyDamageBonus(int, int)  -- or equivalent when built in the toolset.  The first argument is the subtype and is one of IP_CONST_DAMAGETYPE_*. The second is the costTableValue  and is one of IP_CONST_DAMAGEBONUS_*.  You get the costTableValue with GetItemPropertCostTableValue.  You're not calling this routine.  The subtype is right and this item property has no Param1 or Param1Value settings, so you get 255 when you ask for those on this particular itemproperty. 


 


The damage type is the subtype.  The bonus damage amount is the CostTableValue.


 


Also the function is not calling into a 2da...   It's pulling numbers out of the itemproperty structure. The 2das define the possible values and meanings for those numbers (with some hand-waving for the hardcoded itemproperty constructors...) but not what numbers this particular itemproperty has in it.  



               
               

               
            

Legacy_KMdS!

  • Sr. Member
  • ****
  • Posts: 364
  • Karma: +0/-0
Item Property Craziness - What Gives?
« Reply #4 on: May 25, 2016, 02:56:00 am »


               

Item properties are difficult to get a handle on. I remember trying to figure it out back when.... What worked for me was to use the toolset and open the various items and see what the various properties were and reference the Lexicon while studying the 2da's. There are times I still need to lookup my notes. hehe.



               
               

               
            

Legacy_JediMindTrix

  • Sr. Member
  • ****
  • Posts: 383
  • Karma: +0/-0
Item Property Craziness - What Gives?
« Reply #5 on: May 26, 2016, 10:45:33 am »


               

Ultimately, I chose to rethink my strategy and approach it from a different angle. However, I now have another question:


 


Is there a way to loop through an inventory and check to see if the PC has an item with a certain name, and if they do not possess any of a certain name, then do something?


GetItemPossessedBy is too narrow in focus to be of assistance here.



               
               

               
            

Legacy_JediMindTrix

  • Sr. Member
  • ****
  • Posts: 383
  • Karma: +0/-0
Item Property Craziness - What Gives?
« Reply #6 on: May 26, 2016, 03:33:34 pm »


               

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
    {
     SendMessageToPC(oPC, "Test");
      string sName = GetName(oItem);   //Get the name of the depleted ammunition.
      int nDepletedProjectileType = GetBaseItemType(oItem);
      object oNewProjectile = GetFirstItemInInventory(oPC); //The start of finding a similar item.

      while(oNewProjectile != OBJECT_INVALID)
       {
        if(!bIsAmmoOrThrowing) return; //Same as above, making sure we've found a projectile before proceeding.
        {
         int nNewProjectileType = GetBaseItemType(oNewProjectile); //Declare new projectile type for comparison against depleted projectile type.

         if(nNewProjectileType == nDepletedProjectileType) //If projectile types match
          {
           string sNextItemName = GetName(oNewProjectile); //Get the name of projectile stack.
           SendMessageToPC(oPC, "Base Item Types Match.");

           if(TestStringAgainstPattern(sName, sNextItemName) != FALSE) //Compare names, if match:
            {
             switch(nNewProjectileType) //Switch/case statement to determine what slot to equip the projectile match.
             {
              case 20:               //Arrows
              {
               SendMessageToPC(oPC, "Equip new arrows.");
               AssignCommand(oPC, ActionEquipItem(oNewProjectile, INVENTORY_SLOT_ARROWS));
               break;
              }
              case 25:               //Bolts
              {
               SendMessageToPC(oPC, "Equip new bolts.");
               AssignCommand(oPC, ActionEquipItem(oNewProjectile, INVENTORY_SLOT_BOLTS));
               break;
              }
              case 27:               //Bullets
              {
               SendMessageToPC(oPC, "Equip new bullets.");
               AssignCommand(oPC, ActionEquipItem(oNewProjectile, INVENTORY_SLOT_BULLETS));
               break;
              }
              case 31:               //Darts
              case 59:               //Shuriken
              case 63:               //Throwing Axe
              {
               SendMessageToPC(oPC, "Equip new throwing weapon.");
               AssignCommand(oPC, ActionEquipItem(oNewProjectile, INVENTORY_SLOT_RIGHTHAND));
               break;
              }
              default: SendMessageToPC(oPC, "You have found a bug in the projectile auto-equip script! Please report to the devs.");
              break; //If for some reason nNewProjectileType is not one of the projectiles, we'll find out about it.
             }
            }
          }
         }

        oNewProjectile = GetNextItemInInventory(oPC); //Otherwise, continue the search. This function will also search "nested" inventory for Bags of Holding/Magic Bags/Boxes automatically.
       }

    }

How would you go about implementing a check to see if the PC does NOT have a projectile with a matching name to his.

Like, it loops through the inventory looking for a name match, and if it can't find one, then it equips any projectile of the same type it can find?



               
               

               
            

Legacy_KMdS!

  • Sr. Member
  • ****
  • Posts: 364
  • Karma: +0/-0
Item Property Craziness - What Gives?
« Reply #7 on: May 26, 2016, 03:55:18 pm »


               

There isn't enough info with the clip provided........like who owns the script, what is it being processed on, the oPC object? or mopsst likely from an event, ei the module. If the latter, you must assign the "ActionEquipItem" command  to the oPC object, otherwise you are telling the module to equip the item.



    AssignCommand(oPC, ActionEquipItem(oNewProjectile, INVENTORY_SLOT_RIGHTHAND));

If that dosen't work I need more of the code to evaluate....


 


I am headed to work, don't have time right now for any more than that. If no one else gets this for you, I will in about 12 hours. Though i imagine someone else will. '<img'>



               
               

               
            

Legacy_JediMindTrix

  • Sr. Member
  • ****
  • Posts: 383
  • Karma: +0/-0
Item Property Craziness - What Gives?
« Reply #8 on: May 26, 2016, 04:44:33 pm »


               

int jmtFindMatchingNameType(object oPC, object oItem)
{
string sName = GetName(oItem);   //Get the name of the depleted ammunition.
int nItemToMatch = GetBaseItemType(oItem);
object oMatchToThis = GetFirstItemInInventory(oPC); //The start of finding a similar item.
      while(oMatchToThis != OBJECT_INVALID)
       {
        string sNextItemName = GetName(oMatchToThis); //Get the name of the item being cycled.
        int nMatchToThisType = GetBaseItemType(oMatchToThis); //Get base type of item being cycled.
         if(nItemToMatch == nMatchToThisType) //If the items base types match.
         {
          if(TestStringAgainstPattern(sName, sNextItemName) != FALSE) //Compare names, if match:
          {
           return TRUE; //Return true if find item with name match
          }
         oMatchToThis = GetNextItemInInventory(oPC); //Otherwise, continue the search. This function will also search "nested" inventory for Bags of Holding/Magic Bags/Boxes automatically.
         }
       }
  return FALSE; //Return FALSE if can't find a match
}

This, when called on in the OnModuleUnEquip event (See below), causes a tmi error, EDIT: But only when the function can't find a matching name/type. However, I was under the assumption that coming across an invalid object (i.e. no more items in inventory to check) would break the loop.



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(jmtFindMatchingNameTypeAndEquip(oPC, oItem) != FALSE)
     {
     }
    }
}

The TMI error only occurs when the code from the custom int function is inside the void main() of the OnModuleUnEquip event.


 


The general idea was to use the custom function to do something like this:



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(jmtFindMatchingNameTypeAndEquip(oPC, oItem) != FALSE)
     {
      //Equip projectile of matching name and base type
     }
    else if(jmtFindMatchingNameTypeAndEquip(oPC, oItem) == FALSE)
     {
     //Equip projectile of matching base type
     }
    }
}


               
               

               
            

Legacy_JediMindTrix

  • Sr. Member
  • ****
  • Posts: 383
  • Karma: +0/-0
Item Property Craziness - What Gives?
« Reply #9 on: May 26, 2016, 05:22:00 pm »


               

The cause of the TMI error was:


while(oMatchToThis != OBJECT_INVALID)
       {
        string sNextItemName = GetName(oMatchToThis); //Get the name of the item being cycled.
        int nMatchToThisType = GetBaseItemType(oMatchToThis); //Get base type of item being cycled.
         if(nItemToMatch == nMatchToThisType) //If the items base types match.
         {
          if(TestStringAgainstPattern(sName, sNextItemName) != FALSE) //Compare names, if match:
          {
           return TRUE; //Return true if find item with name match
          }
         oMatchToThis = GetNextItemInInventory(oPC); //Otherwise, continue the search. This function will also search "nested" inventory for Bags of Holding/Magic Bags/Boxes automatically.
         }
       }

 


Should have been:


 


while(oMatchToThis != OBJECT_INVALID)
       {
        string sNextItemName = GetName(oMatchToThis); //Get the name of the item being cycled.
        int nMatchToThisType = GetBaseItemType(oMatchToThis); //Get base type of item being cycled.
         if(nItemToMatch == nMatchToThisType) //If the items base types match.
         {
          if(TestStringAgainstPattern(sName, sNextItemName) != FALSE) //Compare names, if match:
          {
           return TRUE; //Return true if find item with name match
          }
         }
oMatchToThis = GetNextItemInInventory(oPC); //Otherwise, continue the search. This function will also search "nested" inventory for Bags of Holding/Magic Bags/Boxes automatically.
       }


               
               

               
            

Legacy_KMdS!

  • Sr. Member
  • ****
  • Posts: 364
  • Karma: +0/-0
Item Property Craziness - What Gives?
« Reply #10 on: May 27, 2016, 03:17:33 am »


               

Have you figured out what you needed or is there still something you need help on with this?



               
               

               
            

Legacy_JediMindTrix

  • Sr. Member
  • ****
  • Posts: 383
  • Karma: +0/-0
Item Property Craziness - What Gives?
« Reply #11 on: May 27, 2016, 10:53:16 am »


               

I figured out what I needed, mostly, thank you!