TOO_MANY_INSTRUCTIONS
4BOLTMAIN
Member Posts: 90
I have been experimenting with some code for a few hours now and I cant figure out why I am getting the TMI error in game. Maybe someone can see something that I am missing?
This code goes in the on closed slot of a chest and without the item property section it works fine. It renames all the items as intended without errors but when I add the item property section It caused the TMI error in game.
This code goes in the on closed slot of a chest and without the item property section it works fine. It renames all the items as intended without errors but when I add the item property section It caused the TMI error in game.
#include "x2_inc_itemprop"
#include "x3_inc_string"
void main()
{
string sNewName, sName;
int iCount, iLength, nAbility, nBonus, nDamage, nResist, nSaves;
itemproperty ipProperty;
object oChest = OBJECT_SELF;
nAbility = 12;
nSaves = 12;
nBonus = 16;
nResist = IP_CONST_DAMAGERESIST_30;
//nResist = IP_CONST_DAMAGERESIST_50;
nDamage = 26; //amount is 16 This is the same for Mass Crit
//nElement = 30; //amount is 20 This is the same for Mass Crit
object oItem = (GetFirstItemInInventory(oChest));
while (GetIsObjectValid(oItem))
{
sNewName = ""; //clear string for next item
iCount = 0; //clear count for new item
sName = GetName(oItem, FALSE);
iLength = GetStringLength(sName);
while (iCount < iLength)
{
if (GetSubString(sName,iCount,1) == "<") iCount = iCount + 4;
if (GetSubString(sName,iCount,1) == "A" || GetSubString(sName,iCount,1) == "a"
|| GetSubString(sName,iCount,1) == "B" || GetSubString(sName,iCount,1) == "b"
|| GetSubString(sName,iCount,1) == "C" || GetSubString(sName,iCount,1) == "c"
|| GetSubString(sName,iCount,1) == "D" || GetSubString(sName,iCount,1) == "d"
|| GetSubString(sName,iCount,1) == "E" || GetSubString(sName,iCount,1) == "e"
|| GetSubString(sName,iCount,1) == "F" || GetSubString(sName,iCount,1) == "f"
|| GetSubString(sName,iCount,1) == "G" || GetSubString(sName,iCount,1) == "g"
|| GetSubString(sName,iCount,1) == "H" || GetSubString(sName,iCount,1) == "h"
|| GetSubString(sName,iCount,1) == "I" || GetSubString(sName,iCount,1) == "i"
|| GetSubString(sName,iCount,1) == "J" || GetSubString(sName,iCount,1) == "j"
|| GetSubString(sName,iCount,1) == "K" || GetSubString(sName,iCount,1) == "k"
|| GetSubString(sName,iCount,1) == "L" || GetSubString(sName,iCount,1) == "l"
|| GetSubString(sName,iCount,1) == "M" || GetSubString(sName,iCount,1) == "m"
|| GetSubString(sName,iCount,1) == "N" || GetSubString(sName,iCount,1) == "n"
|| GetSubString(sName,iCount,1) == "O" || GetSubString(sName,iCount,1) == "o"
|| GetSubString(sName,iCount,1) == "P" || GetSubString(sName,iCount,1) == "p"
|| GetSubString(sName,iCount,1) == "Q" || GetSubString(sName,iCount,1) == "q"
|| GetSubString(sName,iCount,1) == "R" || GetSubString(sName,iCount,1) == "r"
|| GetSubString(sName,iCount,1) == "S" || GetSubString(sName,iCount,1) == "s"
|| GetSubString(sName,iCount,1) == "T" || GetSubString(sName,iCount,1) == "t"
|| GetSubString(sName,iCount,1) == "U" || GetSubString(sName,iCount,1) == "u"
|| GetSubString(sName,iCount,1) == "V" || GetSubString(sName,iCount,1) == "v"
|| GetSubString(sName,iCount,1) == "W" || GetSubString(sName,iCount,1) == "w"
|| GetSubString(sName,iCount,1) == "X" || GetSubString(sName,iCount,1) == "x"
|| GetSubString(sName,iCount,1) == "Y" || GetSubString(sName,iCount,1) == "y"
|| GetSubString(sName,iCount,1) == "Z" || GetSubString(sName,iCount,1) == "z"
|| GetSubString(sName,iCount,1) == " ")
{
sNewName = sNewName + GetSubString(sName,iCount,1);
}
iCount++;
}
while (GetStringLeft(sNewName, 1) == " ")
{
sNewName = GetStringRight(sNewName, GetStringLength(sNewName) - 1);//remove left spaces
}
while (GetStringRight(sNewName, 1) == " ")
{
sNewName = GetStringLeft(sNewName, GetStringLength(sNewName) - 1);//remove right spaces
}
//---------------------------------------------------------------------------------
// This section here compiles but it gives me a TOO_MANY_INSTRUCTIONS error in game
ipProperty = GetFirstItemProperty(oItem);
while (GetIsItemPropertyValid(ipProperty))
{
if (GetItemPropertyType(ipProperty) == ITEM_PROPERTY_AC_BONUS)
{
RemoveItemProperty(oItem, ipProperty);
AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyACBonus(nBonus), oItem, 0.0);
}
ipProperty = GetNextItemProperty(oItem);
}
//---------------------------------------------------------------------------------
SetName(oItem, StringToRGBString(sNewName, "627"));
oItem = GetNextItemInInventory(oChest);
}
}
0
Comments
In general, when looping through a list, adding or removing list items is bad news unless the changes are delayed.
I changed the if to a case and used item property type.
I checked to see if the item property bonus was at the maximum and if it was the item property was not added, no new properties would get added if the bonuses were higher than x amount.
What this does is renames items in a chest removing the + # on the end and it increases the properties to the values called out at the beginning of the script. This also removes color tags from the names if there are any.
Here is the working code...
#include "x2_inc_itemprop" #include "x3_inc_string" void main() { string sNewName, sName; int iCount, iLength, nAbility, nBonus, nDamage, nResist, nSaves; itemproperty ipProperty; object oChest = OBJECT_SELF; nAbility = 12; nSaves = 12; nBonus = 16; nResist = IP_CONST_DAMAGERESIST_30; //nResist = IP_CONST_DAMAGERESIST_50; nDamage = 26; //amount is 16 This is the same for Mass Crit //nDamage = 30; //amount is 20 This is the same for Mass Crit object oItem = (GetFirstItemInInventory(oChest)); while (GetIsObjectValid(oItem)) { sNewName = ""; //reset string for next item iCount = 0; //reset count for next item sName = GetName(oItem, FALSE); iLength = GetStringLength(sName); while (iCount < iLength) { if (GetSubString(sName,iCount,1) == "<") iCount = iCount + 4; if (GetSubString(sName,iCount,1) == "A" || GetSubString(sName,iCount,1) == "a" || GetSubString(sName,iCount,1) == "B" || GetSubString(sName,iCount,1) == "b" || GetSubString(sName,iCount,1) == "C" || GetSubString(sName,iCount,1) == "c" || GetSubString(sName,iCount,1) == "D" || GetSubString(sName,iCount,1) == "d" || GetSubString(sName,iCount,1) == "E" || GetSubString(sName,iCount,1) == "e" || GetSubString(sName,iCount,1) == "F" || GetSubString(sName,iCount,1) == "f" || GetSubString(sName,iCount,1) == "G" || GetSubString(sName,iCount,1) == "g" || GetSubString(sName,iCount,1) == "H" || GetSubString(sName,iCount,1) == "h" || GetSubString(sName,iCount,1) == "I" || GetSubString(sName,iCount,1) == "i" || GetSubString(sName,iCount,1) == "J" || GetSubString(sName,iCount,1) == "j" || GetSubString(sName,iCount,1) == "K" || GetSubString(sName,iCount,1) == "k" || GetSubString(sName,iCount,1) == "L" || GetSubString(sName,iCount,1) == "l" || GetSubString(sName,iCount,1) == "M" || GetSubString(sName,iCount,1) == "m" || GetSubString(sName,iCount,1) == "N" || GetSubString(sName,iCount,1) == "n" || GetSubString(sName,iCount,1) == "O" || GetSubString(sName,iCount,1) == "o" || GetSubString(sName,iCount,1) == "P" || GetSubString(sName,iCount,1) == "p" || GetSubString(sName,iCount,1) == "Q" || GetSubString(sName,iCount,1) == "q" || GetSubString(sName,iCount,1) == "R" || GetSubString(sName,iCount,1) == "r" || GetSubString(sName,iCount,1) == "S" || GetSubString(sName,iCount,1) == "s" || GetSubString(sName,iCount,1) == "T" || GetSubString(sName,iCount,1) == "t" || GetSubString(sName,iCount,1) == "U" || GetSubString(sName,iCount,1) == "u" || GetSubString(sName,iCount,1) == "V" || GetSubString(sName,iCount,1) == "v" || GetSubString(sName,iCount,1) == "W" || GetSubString(sName,iCount,1) == "w" || GetSubString(sName,iCount,1) == "X" || GetSubString(sName,iCount,1) == "x" || GetSubString(sName,iCount,1) == "Y" || GetSubString(sName,iCount,1) == "y" || GetSubString(sName,iCount,1) == "Z" || GetSubString(sName,iCount,1) == "z" || GetSubString(sName,iCount,1) == " ") { sNewName = sNewName + GetSubString(sName,iCount,1); } iCount++; } while (GetStringLeft(sNewName, 1) == " ") { sNewName = GetStringRight(sNewName, GetStringLength(sNewName) - 1);//remove left spaces } while (GetStringRight(sNewName, 1) == " ") { sNewName = GetStringLeft(sNewName, GetStringLength(sNewName) - 1);//remove right spaces } if (GetStringLeft(sNewName, 1) == "f") { sNewName = GetStringRight(sNewName, GetStringLength(sNewName) - 2);//remove "f" } SetName(oItem, StringToRGBString(sNewName, "127")); ipProperty = GetFirstItemProperty(oItem); while (GetIsItemPropertyValid(ipProperty)) { switch (GetItemPropertyType(ipProperty)) { case ITEM_PROPERTY_AC_BONUS: if (GetItemPropertyCostTableValue(ipProperty) < nBonus) { RemoveItemProperty(oItem, ipProperty); AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyACBonus(nBonus), oItem); } break; case ITEM_PROPERTY_ENHANCEMENT_BONUS: if (GetItemPropertyCostTableValue(ipProperty) < nBonus) { RemoveItemProperty(oItem, ipProperty); AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyEnhancementBonus(nBonus), oItem); } break; case ITEM_PROPERTY_ATTACK_BONUS: if (GetItemPropertyCostTableValue(ipProperty) < nBonus) { RemoveItemProperty(oItem, ipProperty); AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyAttackBonus(nBonus), oItem); } break; case ITEM_PROPERTY_REGENERATION: if (GetItemPropertyCostTableValue(ipProperty) < nBonus) { RemoveItemProperty(oItem, ipProperty); AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyRegeneration(nBonus), oItem); } break; case ITEM_PROPERTY_REGENERATION_VAMPIRIC: if (GetItemPropertyCostTableValue(ipProperty) < nBonus) { RemoveItemProperty(oItem, ipProperty); AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyVampiricRegeneration(nBonus), oItem); } break; case ITEM_PROPERTY_MIGHTY: if (GetItemPropertyCostTableValue(ipProperty) < nBonus) { RemoveItemProperty(oItem, ipProperty); AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyMaxRangeStrengthMod(nBonus), oItem); } break; case ITEM_PROPERTY_SAVING_THROW_BONUS: if (GetItemPropertyCostTableValue(ipProperty) < nSaves) { RemoveItemProperty(oItem, ipProperty); AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyBonusSavingThrowVsX(IP_CONST_SAVEVS_UNIVERSAL,nSaves) , oItem); } break; case ITEM_PROPERTY_MASSIVE_CRITICALS: if (GetItemPropertyCostTableValue(ipProperty) < nDamage) { RemoveItemProperty(oItem, ipProperty); AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyMassiveCritical(nDamage), oItem); } break; case ITEM_PROPERTY_DAMAGE_RESISTANCE: if (GetItemPropertyCostTableValue(ipProperty) < nResist) { RemoveItemProperty(oItem, ipProperty); AddItemProperty(DURATION_TYPE_PERMANENT,ItemPropertyDamageResistance(GetItemPropertySubType(ipProperty),nResist), oItem); } break; case ITEM_PROPERTY_DAMAGE_BONUS: if (GetItemPropertyCostTableValue(ipProperty) < nDamage) { RemoveItemProperty(oItem, ipProperty); AddItemProperty(DURATION_TYPE_PERMANENT,ItemPropertyDamageBonus(GetItemPropertySubType(ipProperty),nDamage), oItem); } break; case ITEM_PROPERTY_ABILITY_BONUS: if (GetItemPropertyCostTableValue(ipProperty) < nAbility) { RemoveItemProperty(oItem, ipProperty); AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyAbilityBonus(GetItemPropertySubType(ipProperty), nAbility), oItem); } break; default: break; } ipProperty = GetNextItemProperty(oItem); } oItem = GetNextItemInInventory(oChest); } }while (iCount < iLength) { if (GetSubString(sName,iCount,1) == "<") iCount = iCount + 4; if (GetSubString(sName,iCount,1) == "A" || GetSubString(sName,iCount,1) == "a" || GetSubString(sName,iCount,1) == "B" || GetSubString(sName,iCount,1) == "b" || GetSubString(sName,iCount,1) == "C" || GetSubString(sName,iCount,1) == "c" || GetSubString(sName,iCount,1) == "D" || GetSubString(sName,iCount,1) == "d" || GetSubString(sName,iCount,1) == "E" || GetSubString(sName,iCount,1) == "e" || GetSubString(sName,iCount,1) == "F" || GetSubString(sName,iCount,1) == "f" || GetSubString(sName,iCount,1) == "G" || GetSubString(sName,iCount,1) == "g" || GetSubString(sName,iCount,1) == "H" || GetSubString(sName,iCount,1) == "h" || GetSubString(sName,iCount,1) == "I" || GetSubString(sName,iCount,1) == "i" || GetSubString(sName,iCount,1) == "J" || GetSubString(sName,iCount,1) == "j" || GetSubString(sName,iCount,1) == "K" || GetSubString(sName,iCount,1) == "k" || GetSubString(sName,iCount,1) == "L" || GetSubString(sName,iCount,1) == "l" || GetSubString(sName,iCount,1) == "M" || GetSubString(sName,iCount,1) == "m" || GetSubString(sName,iCount,1) == "N" || GetSubString(sName,iCount,1) == "n" || GetSubString(sName,iCount,1) == "O" || GetSubString(sName,iCount,1) == "o" || GetSubString(sName,iCount,1) == "P" || GetSubString(sName,iCount,1) == "p" || GetSubString(sName,iCount,1) == "Q" || GetSubString(sName,iCount,1) == "q" || GetSubString(sName,iCount,1) == "R" || GetSubString(sName,iCount,1) == "r" || GetSubString(sName,iCount,1) == "S" || GetSubString(sName,iCount,1) == "s" || GetSubString(sName,iCount,1) == "T" || GetSubString(sName,iCount,1) == "t" || GetSubString(sName,iCount,1) == "U" || GetSubString(sName,iCount,1) == "u" || GetSubString(sName,iCount,1) == "V" || GetSubString(sName,iCount,1) == "v" || GetSubString(sName,iCount,1) == "W" || GetSubString(sName,iCount,1) == "w" || GetSubString(sName,iCount,1) == "X" || GetSubString(sName,iCount,1) == "x" || GetSubString(sName,iCount,1) == "Y" || GetSubString(sName,iCount,1) == "y" || GetSubString(sName,iCount,1) == "Z" || GetSubString(sName,iCount,1) == "z" || GetSubString(sName,iCount,1) == " ") { sNewName = sNewName + GetSubString(sName,iCount,1); } iCount++; }If the character you are testing does not match any of the letters you are testing for, the function GetSubString() is called 54 times. Even if the character is one of those you are testing for GetSubString() will be called between 2 and 54 times depending on the actual character. Remember this will be for each pass through the While() that the above code is embedded in. If you use a string constant and the function FindSubString() you can reduce that number of calls to GetSubString() down to just one or two instead. So I rewrote that section and did a little tidying up of your code to produce this -#include "x2_inc_itemprop" #include "x3_inc_string" const string csInTheseChars = " ABCDEFGHIJKLMNOPQRSTUVWXabcdefghijklmnopqrstuvwxyz"; void main() { string sNewName, sName, sTestMe; int iCount, iLength, nAbility, nBonus, nDamage, nResist, nSaves; itemproperty ipProperty; object oChest = OBJECT_SELF; nAbility = 12; nSaves = 12; nBonus = 16; nResist = IP_CONST_DAMAGERESIST_30; //nResist = IP_CONST_DAMAGERESIST_50; nDamage = 26; //amount is 16 This is the same for Mass Crit //nDamage = 30; //amount is 20 This is the same for Mass Crit object oItem = (GetFirstItemInInventory(oChest)); while(GetIsObjectValid(oItem)) { sNewName = ""; //reset string for next item iCount = 0; //reset count for next item sName = GetName(oItem, FALSE); iLength = GetStringLength(sName); while(iCount < iLength) { sTestMe = GetSubString(sName, iCount, 1); if(sTestMe == "<") { iCount += 4; sTestMe = GetSubString(sName, iCount, 1); } if(FindSubString(csInTheseChars, sTestMe) > -1) sNewName = sNewName + GetSubString(sName, iCount, 1); iCount++; } while(GetStringLeft(sNewName, 1) == " ") sNewName = GetStringRight(sNewName, GetStringLength(sNewName) - 1);//remove left spaces while(GetStringRight(sNewName, 1) == " ") sNewName = GetStringLeft(sNewName, GetStringLength(sNewName) - 1);//remove right spaces if(GetStringLeft(sNewName, 1) == "f") sNewName = GetStringRight(sNewName, GetStringLength(sNewName) - 2);//remove "f" SetName(oItem, StringToRGBString(sNewName, "127")); ipProperty = GetFirstItemProperty(oItem); while(GetIsItemPropertyValid(ipProperty)) { switch (GetItemPropertyType(ipProperty)) { case ITEM_PROPERTY_AC_BONUS: if(GetItemPropertyCostTableValue(ipProperty) < nBonus) { RemoveItemProperty(oItem, ipProperty); AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyACBonus(nBonus), oItem); } break; case ITEM_PROPERTY_ENHANCEMENT_BONUS: if(GetItemPropertyCostTableValue(ipProperty) < nBonus) { RemoveItemProperty(oItem, ipProperty); AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyEnhancementBonus(nBonus), oItem); } break; case ITEM_PROPERTY_ATTACK_BONUS: if(GetItemPropertyCostTableValue(ipProperty) < nBonus) { RemoveItemProperty(oItem, ipProperty); AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyAttackBonus(nBonus), oItem); } break; case ITEM_PROPERTY_REGENERATION: if(GetItemPropertyCostTableValue(ipProperty) < nBonus) { RemoveItemProperty(oItem, ipProperty); AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyRegeneration(nBonus), oItem); } break; case ITEM_PROPERTY_REGENERATION_VAMPIRIC: if(GetItemPropertyCostTableValue(ipProperty) < nBonus) { RemoveItemProperty(oItem, ipProperty); AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyVampiricRegeneration(nBonus), oItem); } break; case ITEM_PROPERTY_MIGHTY: if(GetItemPropertyCostTableValue(ipProperty) < nBonus) { RemoveItemProperty(oItem, ipProperty); AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyMaxRangeStrengthMod(nBonus), oItem); } break; case ITEM_PROPERTY_SAVING_THROW_BONUS: if(GetItemPropertyCostTableValue(ipProperty) < nSaves) { RemoveItemProperty(oItem, ipProperty); AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyBonusSavingThrowVsX(IP_CONST_SAVEVS_UNIVERSAL,nSaves) , oItem); } break; case ITEM_PROPERTY_MASSIVE_CRITICALS: if(GetItemPropertyCostTableValue(ipProperty) < nDamage) { RemoveItemProperty(oItem, ipProperty); AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyMassiveCritical(nDamage), oItem); } break; case ITEM_PROPERTY_DAMAGE_RESISTANCE: if(GetItemPropertyCostTableValue(ipProperty) < nResist) { RemoveItemProperty(oItem, ipProperty); AddItemProperty(DURATION_TYPE_PERMANENT,ItemPropertyDamageResistance(GetItemPropertySubType(ipProperty),nResist), oItem); } break; case ITEM_PROPERTY_DAMAGE_BONUS: if(GetItemPropertyCostTableValue(ipProperty) < nDamage) { RemoveItemProperty(oItem, ipProperty); AddItemProperty(DURATION_TYPE_PERMANENT,ItemPropertyDamageBonus(GetItemPropertySubType(ipProperty),nDamage), oItem); } break; case ITEM_PROPERTY_ABILITY_BONUS: if(GetItemPropertyCostTableValue(ipProperty) < nAbility) { RemoveItemProperty(oItem, ipProperty); AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyAbilityBonus(GetItemPropertySubType(ipProperty), nAbility), oItem); } break; } ipProperty = GetNextItemProperty(oItem); } oItem = GetNextItemInInventory(oChest); } }Hope you find this of use.TR
That aside, you may find the tutorials on scripting that I wrote to be of use in understanding the changes I made to your code -
TR's Basics - Variables, Types and Functions (TBC)
TR's Basics - Boolean Algebra
TR's Basics - Decisions
TR's Basics - Mostly Operators
TR
With the release of NWNEE I am a firm believer that writing code is not like riding a bike. I often look at code I wrote years ago and struggle understanding it. It is coming back to me but slowly.
Thank you for taking the time to point out the efficiency in the naming section. I don't do a whole lot of work with strings so this is something I definitely need to work on.
Hope that is of use.
TR