Item Property Quandary

So, with the discovery that Clangeddin’s Level Cap mod has an adverse effect on the Extra Slot feats, I have been trying to script around this issue, with kevL_s’ help. I am able to get one Extra Feat added to the character, but for some reason, unable to get the second one added. Right now, just trying to get Extra Slot 0 and Extra Slot 1 to work for the Wizard. Whichever one is selected first is the only one that gets added. Even though the location that the Item Properties are being added to can hold a total of 8 slots. The latest attempt, which shows what is happening via debug lines has shown that, as suspected, only one Item Property is being added. So, we are asking for anyone to throw in their ideas, please. If anyone out there is using Clangeddin’s Level Cap mod, please have a look and see if those feats work. One caveat here - I am only using the parts of the Level Cap mod that allow for advancement to level 40, which Clangeddin instructed me how to do. I am providing the script we are trying to implement, and a screenshot of the results.

#include "x2_inc_itemprop"

void printIps(object oArmor)
{
	SendMessageToPC(GetFirstPC(FALSE), "printIps()");

	if (GetIsObjectValid(oArmor))
	{
		itemproperty ip = GetFirstItemProperty(oArmor);
		while (GetIsItemPropertyValid(ip))
		{
			int iProp = GetItemPropertyType(ip);			// ref to ItemPropDef.2da
			int iSubtype = GetItemPropertySubType(ip);		// ref to Classes.2da
			int iValue = GetItemPropertyCostTableValue(ip);	// ref to IprpSpellLvCost.2da

			SendMessageToPC(GetFirstPC(FALSE), "ip= " + IntToString(iProp)
											+ " subtype= " + IntToString(iSubtype)
											+ " value= " + IntToString(iValue));
			ip = GetNextItemProperty(oArmor);
		}
	}
	else
		SendMessageToPC(GetFirstPC(FALSE), "armor invalid");
}

void CheckForExtraSlotFeats(object oCaster)
{
	if (GetLevelByClass(CLASS_TYPE_WIZARD, oCaster) > 0)
	{
		SendMessageToPC(GetFirstPC(FALSE), "Wizard");

		itemproperty ipBonus;

		int bArmorCreated = FALSE;
		int bIpAdded = FALSE;

		object oArmor = GetItemInSlot(INVENTORY_SLOT_CARMOUR);
		if (!GetIsObjectValid(oArmor))
		{
			SendMessageToPC(GetFirstPC(FALSE), "created armor");

			bArmorCreated = TRUE;
			oArmor = CreateItemOnObject("x2_it_emptyskin", OBJECT_SELF, 1, "", FALSE);
		}


		if (GetHasFeat(FEAT_EXTRA_SLOT_WIZARD_LEVEL0))
		{
			SendMessageToPC(GetFirstPC(FALSE), "Has Extra Slot 0");

			bIpAdded = TRUE;
			ipBonus = ItemPropertyBonusLevelSpell(IP_CONST_CLASS_WIZARD, 0);
			IPSafeAddItemProperty(oArmor, ipBonus, 0.0f, X2_IP_ADDPROP_POLICY_KEEP_EXISTING);
		}

		if (GetHasFeat(FEAT_EXTRA_SLOT_WIZARD_LEVEL1))
		{
			SendMessageToPC(GetFirstPC(FALSE), "Has Extra Slot 1");

			bIpAdded = TRUE;
			ipBonus = ItemPropertyBonusLevelSpell(IP_CONST_CLASS_WIZARD, 1);
			IPSafeAddItemProperty(oArmor, ipBonus, 0.0f, X2_IP_ADDPROP_POLICY_KEEP_EXISTING);
		}


		if (bArmorCreated)
		{
			if (bIpAdded)
			{
				SendMessageToPC(GetFirstPC(FALSE), "equip armor");
				ActionEquipItem(oArmor, INVENTORY_SLOT_CARMOUR);
			}
			else
			{
				SendMessageToPC(GetFirstPC(FALSE), "destroy armor");
				DestroyObject(oArmor, 0.1f, FALSE);
			}
		}

		DelayCommand(0.3f, printIps(oArmor));
	}
}

@temyankee

What is this item you are creating and equipping?

If it is the equivalent of an older NWN1 “skin” that you could alter properties on, then that may be the problem. I tried using a “skin” for various projects in the early days and they simply failed to work.

  1. If the “skin” is a proper armour item, does the code still fail?

  2. Also, try adding a slight delay between when adding the properties (if more than one)…

  3. I had an issue once where I needed to delay using GetHasFeat if I was checking more than one feat in one time. Therefore, you may also need to consider putting in a wrapper to add a 0.1 delay for the check of each further feat.

“Skin” References …

1 Like

This is actuallt an item within the content added by Kaedrin. It is basically an item that can be equipped to the Creature Armour equipment slot - weighs nothing, does nothing, grants no boons or banes - in order to be able to add such things. For example, the Spirit of the Rat spell, and similar spells, will create this item to add the necessary feats that the spells grant and then equip it. The spell does this if there is nothing in the Creature Armour slot. Unless you can think of a way to add ItempropertyBonusLevelSpell more than once for a different level. Each Extra Slot can only be taken once for each spell level available to the character. Literally, a maximum of 9 of these can be taken, from Level 0 to Level 8. But, since the LevelCap mod disables these feats, Scripting seems to be the only way around it.

Also, the DelayCommand didn’t work. Since only one of these Item Properties is added at a time, unless you get bonus feats that allow for the selection of more than one, I had my doubts that would make a difference. I am selecting one at 6th-level, then again at 9th-level. While the Extra Slot 1 debug line does fire, for some reason then PRoperty is not actually being added. I even tried to add both at the same time, but that failed as well.

@temyankee

Can you try just adding a standard piece of armour and try the code?

I may not be back until Monday now, but if I think of anything else, I’ll try and post tonight.

Tried adding the two Extra Slots to an existing armor that the character was wearing. Same result. The first one I selected got added. The second one did not. Even unequipped and re-equipped and rested. Still only the first one showed up.

On a lark I figured I would try enchanting one item with 2 of the Extra Slot feats. I have The Complete Craftsman incorporated into my game , most updated version. I was able to successfully add Extra Slot 1 and Extra Slot 2 to a Wizard’s Robe. So, it’s not a matter of being able to only add 1 Extra Slot feat to an item. Since all of the settings for a piece of armor are the same as the settings for the CARMOUR or Creature Item, that’s not the issue. It must have something to do with how the Item Properties are being added. Just don’t understand it. If I can enchant the item in the game with 2 Extra Slot feats, why can’t I add them using a script?

1 Like

@temyankee

I am a little bit confused at what you are saying here… (Some clarification please.)

First you say…

How? Are you saying through crafting? If so, crafting uses script. So when you then say…

This makes no sense, as I say above, crafting uses script.

However, I also note that you have success with level 1 and 2, but in your previous tests you are using 0 and 1. So, what happens if you change your own scripts to test with 1 and 2?

Okay. First - Adding the Extra Slot 1 and Extra Slot 2 was by way of enchanting the Wizard’s Robe the normal way, using the Magician’s Worktable and the Craft Magic Arms and Armor feat. That way works fine. The way that is not working is when the character selects the Extra Slot feat. The first one selected, regardless of level, gets added normally when the character selects it on level up. When the character chooses another one on level up, nothing happens. But, I will try your idea of using Level 1 and 2 instead of Level 0 and 1.

UPDATE: Tried using levels 1 and 2 instead and still got the same result. Only the first feat selected at level up was added correctly to the character. Whatever method is being used to enchant an item is different than what I am trying to do. I am trying to find a way to add the feat to the character by way of scripting the ItemPropertyBonusLevelSpell so it works like the Extra Slot # feat. Again, since the Level Cap mod of Clangeddin’s broke that line of feats, I am trying to script a workaround, but just can’t figure out why I can’t get it to work.

1 Like

Have you checked the way this script adds it then, as I would have thought it used the same function?

Also, try making a “test lever” or two that adds the property one at a time as it is used. i.e. A lever that when pulled adds the property to item worn in the armour slot.

(I can only advise for now, as I am working on my own module in the time I have.)

Already tried adding the feats to an existing item on the character. Same issue. Also, what script(s) would I be looking for to find the item enchantments?

I guess this … else the OC crafting system.

I am changing the “delivery system”, not the item with this test.

i.e. Add the property at the switch of a lever and not feat detection.

Forgive me, but are you talking about a switch/case loop?

@temyankee

Sorry, now you also have me confused here … :grin:

I am simply asking you to run a script that adds these two properties a different way to the way you are currently trying to do it.

Rather than you use your script above, write one that attaches the property when you pull a lever object instead. (One at a time.) This is just part of the testing procedure, not how it will end up. :slight_smile:

hey Lance,
there might have been a problem in IPSafeAddItemProperty() since Tem said he was starting to get it to work by changing the type-param from X2_IP_ADDPROP_POLICY_KEEP_EXISTING to X2_IP_ADDPROP_POLICY_IGNORE_EXISTING. So i subverted the whole thing and did the checks in-script :

void AddBonusSpellSlots(object oCaster)
{
	if (GetLevelByClass(CLASS_TYPE_WIZARD, oCaster) > 0)
	{
		SendMessageToPC(GetFirstPC(FALSE), "Wizard");

		int bArmorCreated = FALSE;
		int bIpAdded = FALSE;

		object oArmor = GetItemInSlot(INVENTORY_SLOT_CARMOUR);
		if (!GetIsObjectValid(oArmor))
		{
			SendMessageToPC(GetFirstPC(FALSE), "created armor");

			bArmorCreated = TRUE;
			oArmor = CreateItemOnObject("x2_it_emptyskin", OBJECT_SELF, 1, "", FALSE);
		}

		int bLevel0 = FALSE;
		int bLevel1 = FALSE;
		int bLevel2 = FALSE;
		int bLevel3 = FALSE;
		int bLevel4 = FALSE;
		int bLevel5 = FALSE;
		int bLevel6 = FALSE;
		int bLevel7 = FALSE;
		int bLevel8 = FALSE;
//		int bLevel9 = FALSE;

		itemproperty ip = GetFirstItemProperty(oArmor);
		while (GetIsItemPropertyValid(ip))
		{
			if (GetItemPropertyType(ip) == ITEM_PROPERTY_BONUS_SPELL_SLOT_OF_LEVEL_N
				&& GetItemPropertySubType(ip) == CLASS_TYPE_WIZARD
				&& GetItemPropertyDurationType(ip) == DURATION_TYPE_PERMANENT)
			{
				switch (GetItemPropertyCostTableValue(ip))
				{
					case IP_CONST_SPELLLEVEL_0: bLevel0 = TRUE;
						SendMessageToPC(GetFirstPC(FALSE), "Has Level 0");
						break;

					case IP_CONST_SPELLLEVEL_1: bLevel1 = TRUE;
						SendMessageToPC(GetFirstPC(FALSE), "Has Level 1");
						break;

					case IP_CONST_SPELLLEVEL_2: bLevel2 = TRUE;
						SendMessageToPC(GetFirstPC(FALSE), "Has Level 2");
						break;

					case IP_CONST_SPELLLEVEL_3: bLevel3 = TRUE;
						SendMessageToPC(GetFirstPC(FALSE), "Has Level 3");
						break;

					case IP_CONST_SPELLLEVEL_4: bLevel4 = TRUE;
						SendMessageToPC(GetFirstPC(FALSE), "Has Level 4");
						break;

					case IP_CONST_SPELLLEVEL_5: bLevel5 = TRUE;
						SendMessageToPC(GetFirstPC(FALSE), "Has Level 5");
						break;

					case IP_CONST_SPELLLEVEL_6: bLevel6 = TRUE;
						SendMessageToPC(GetFirstPC(FALSE), "Has Level 6");
						break;

					case IP_CONST_SPELLLEVEL_7: bLevel7 = TRUE;
						SendMessageToPC(GetFirstPC(FALSE), "Has Level 7");
						break;

					case IP_CONST_SPELLLEVEL_8: bLevel8 = TRUE;
						SendMessageToPC(GetFirstPC(FALSE), "Has Level 8");
						break;

//					case IP_CONST_SPELLLEVEL_9: bLevel9 = TRUE;
//						SendMessageToPC(GetFirstPC(FALSE), "Has Level 9");
//						break;

				}
			}
			ip = GetNextItemProperty(oArmor);
		}


		itemproperty ipBonus;

		if (!bLevel0 && GetHasFeat(FEAT_EXTRA_SLOT_WIZARD_LEVEL0))
		{
			SendMessageToPC(GetFirstPC(FALSE), "Adding Extra Slot 0");

			bIpAdded = TRUE;
			ipBonus = ItemPropertyBonusLevelSpell(IP_CONST_CLASS_WIZARD, 0);
			DelayCommand(0.2f, AddItemProperty(DURATION_TYPE_PERMANENT, ipBonus, oArmor));
		}

		if (!bLevel1 && GetHasFeat(FEAT_EXTRA_SLOT_WIZARD_LEVEL1))
		{
			SendMessageToPC(GetFirstPC(FALSE), "Adding Extra Slot 1");

			bIpAdded = TRUE;
			ipBonus = ItemPropertyBonusLevelSpell(IP_CONST_CLASS_WIZARD, 1);
			DelayCommand(0.2f, AddItemProperty(DURATION_TYPE_PERMANENT, ipBonus, oArmor));
		}

		if (!bLevel2 && GetHasFeat(FEAT_EXTRA_SLOT_WIZARD_LEVEL2))
		{
			SendMessageToPC(GetFirstPC(FALSE), "Adding Extra Slot 2");

			bIpAdded = TRUE;
			ipBonus = ItemPropertyBonusLevelSpell(IP_CONST_CLASS_WIZARD, 2);
			DelayCommand(0.2f, AddItemProperty(DURATION_TYPE_PERMANENT, ipBonus, oArmor));
		}

		if (!bLevel3 && GetHasFeat(FEAT_EXTRA_SLOT_WIZARD_LEVEL3))
		{
			SendMessageToPC(GetFirstPC(FALSE), "Adding Extra Slot 3");

			bIpAdded = TRUE;
			ipBonus = ItemPropertyBonusLevelSpell(IP_CONST_CLASS_WIZARD, 3);
			DelayCommand(0.2f, AddItemProperty(DURATION_TYPE_PERMANENT, ipBonus, oArmor));
		}

		if (!bLevel4 && GetHasFeat(FEAT_EXTRA_SLOT_WIZARD_LEVEL4))
		{
			SendMessageToPC(GetFirstPC(FALSE), "Adding Extra Slot 4");

			bIpAdded = TRUE;
			ipBonus = ItemPropertyBonusLevelSpell(IP_CONST_CLASS_WIZARD, 4);
			DelayCommand(0.2f, AddItemProperty(DURATION_TYPE_PERMANENT, ipBonus, oArmor));
		}

		if (!bLevel5 && GetHasFeat(FEAT_EXTRA_SLOT_WIZARD_LEVEL5))
		{
			SendMessageToPC(GetFirstPC(FALSE), "Adding Extra Slot 5");

			bIpAdded = TRUE;
			ipBonus = ItemPropertyBonusLevelSpell(IP_CONST_CLASS_WIZARD, 5);
			DelayCommand(0.2f, AddItemProperty(DURATION_TYPE_PERMANENT, ipBonus, oArmor));
		}

		if (!bLevel6 && GetHasFeat(FEAT_EXTRA_SLOT_WIZARD_LEVEL6))
		{
			SendMessageToPC(GetFirstPC(FALSE), "Adding Extra Slot 6");

			bIpAdded = TRUE;
			ipBonus = ItemPropertyBonusLevelSpell(IP_CONST_CLASS_WIZARD, 6);
			DelayCommand(0.2f, AddItemProperty(DURATION_TYPE_PERMANENT, ipBonus, oArmor));
		}

		if (!bLevel7 && GetHasFeat(FEAT_EXTRA_SLOT_WIZARD_LEVEL7))
		{
			SendMessageToPC(GetFirstPC(FALSE), "Adding Extra Slot 7");

			bIpAdded = TRUE;
			ipBonus = ItemPropertyBonusLevelSpell(IP_CONST_CLASS_WIZARD, 7);
			DelayCommand(0.2f, AddItemProperty(DURATION_TYPE_PERMANENT, ipBonus, oArmor));
		}

		if (!bLevel8 && GetHasFeat(FEAT_EXTRA_SLOT_WIZARD_LEVEL8))
		{
			SendMessageToPC(GetFirstPC(FALSE), "Adding Extra Slot 8");

			bIpAdded = TRUE;
			ipBonus = ItemPropertyBonusLevelSpell(IP_CONST_CLASS_WIZARD, 8);
			DelayCommand(0.2f, AddItemProperty(DURATION_TYPE_PERMANENT, ipBonus, oArmor));
		}

//		if (!bLevel9 && GetHasFeat(FEAT_EXTRA_SLOT_WIZARD_LEVEL9))
//		{
//			SendMessageToPC(GetFirstPC(FALSE), "Adding Extra Slot 9");
//
//			bIpAdded = TRUE;
//			ipBonus = ItemPropertyBonusLevelSpell(IP_CONST_CLASS_WIZARD, 9);
//			DelayCommand(0.2f, AddItemProperty(DURATION_TYPE_PERMANENT, ipBonus, oArmor));
//		}


		if (bArmorCreated)
		{
			if (bIpAdded)
			{
				SendMessageToPC(GetFirstPC(FALSE), "equip armor");
				ActionEquipItem(oArmor, INVENTORY_SLOT_CARMOUR);
			}
			else
			{
				SendMessageToPC(GetFirstPC(FALSE), "destroy armor");
				DestroyObject(oArmor, 0.1f, FALSE);
			}
		}
	}
}

 
he says it’s working, and he has to expand it for the other spellcasting classes …

1 Like

In fact it works perfectly. All that is needed beyond this is to add for each of the other spellcasting classes, an include line for the script name in the “player_levelup” script (cmi_player_levelup is the one I am using in conjunction with Kaedrin’s content), and the appropriate calling line:

#include "extra_slot_check"

DoExtraSlotCheck();

UPDATE: If using this script, you would also need to take into account for the Favored Soul and the Spirit Shaman in a separate Includes file with the following:

const int IP_CONST_CLASS_SPIRIT_SHAMAN = 55;
const int IP_CONST_CLASS_FAVORED_SOUL = 58;

These are the lines in the Classes.2da that need to be added for this script to work for those classes.

Also, if an Extra Slot feat is not defined, you just need to add it into the Includes file as well. Ex:

const int FEAT_EXTRA_SLOT_FAVORED_SOUL_LEVEL0 = 2069;

@kevL_s

Glad you managed to sort it … time to experiment myself was not on my side. :slightly_smiling_face:

However, changing this parameter was where I was going to go next, after any feedback … although, I am surprised it needed it. :thinking:

EDIT: Although, I see you use the AddItemProperty property directly in your new script.

1 Like

I really have to thank kevL_s for all that I have learned thanx to his generosity and patience. It has given me the ability to add so much to the game, as well as allowing me to merge different mods together almost seamlessly, so that they all work together without any clashing. At least so far.

Again, I thank kevL_s for everything.

@temyankee

:face_with_raised_eyebrow:

Sorry I was no help at all. Time restraints do not afford me the luxury to work full time on any fix, and I have to rely on the feedback I get from the person doing the testing. The quicker and more detailed the responses from my requests, the better I am able to help in the time I have spare.

This would have eventually led to your answer as well as we pursued the test path, but … :face_with_diagonal_mouth:

No worries. I undertand how time constraints can affect things. Besides, you still pushed me in a different direction, which eventually with kevL_s help got us the rest of the way.

Well, maybe this (below) could have been better worded… and I was not without patience myself. :dizzy_face: But, hey, I’m probably just tired from trying to help … never mind.