Weird while loop behaviour

I’m trying to write script which will smelt armors and place metal ingots on workbench for gold and for that I’ve modified i_smithhammer_ac and put it in override.
Problem is that this while loop seems to get executed in parallel instead of “processing” each item one by one. For example, script will convert all items even if player doesn’t have enough gold for all items.

Do you know what I’ve missed?

Thanks

if (IsSmithWorkbench(oTarget))
	{
        // AssignCommand(oTarget, DoMundaneCrafting(oPC));
	    string sFullPlateResRef = "mwa_hvfp_mth_4";
		string sHalfPlateResRef = "mwa_hvhp_mth_4";
		string sBandedMailResRef = "mwa_hvbm_mth_3";
		string sChainmailResRef = "mwa_mdcm_mth_4";
		string sBreastPlateResRef = "mwa_mdbp_mth_4";
		string sScaleMailResRef = "mwa_mdsm_mth_4";
		string sChainShirtResRef = "mwa_ltcs_mth_4";
		string sTowerShield = "mwa_shtw_mth_4";
        string sIngotResRef = "n2_crft_plkshed";
		string sIngot = "n2_crft_ingmithral";
		string sChainOfFrost = "nx1_chainshirt_frost";
		string sHeavyShield = "mwa_shhv_mth_4";
		string sLightShield = "mwa_shlt_mth_4";
		string sImaskariBattlemage = "nx1_chainmail01";
		
		object oItemOnBench = GetFirstItemInInventory(oTarget);
		
		object oDebug = GetFirstPC(FALSE);
		int counter = 0;
		
        while (GetIsObjectValid(oItemOnBench))
		{
		     if (GetResRef(oItemOnBench) == sFullPlateResRef && GetGold(oPC) >= 16000)
			 {
			    SendMessageToPC(oDebug, "Gold before " + "sFullPlateResRef" + ": " + IntToString(GetGold(oPC)));
			 	AssignCommand(oPC, TakeGoldFromCreature(16000, oPC, TRUE, TRUE));
				DestroyObject(oItemOnBench);
				CreateItemOnObject(sIngotResRef, oTarget, 8);
			 }
			 else if(GetResRef(oItemOnBench) == sHalfPlateResRef && GetGold(oPC) >= 14000)
			 {
			    SendMessageToPC(oDebug, "Gold before " + "sHalfPlateResRef" + ": " + IntToString(GetGold(oPC)));
			 	AssignCommand(oPC, TakeGoldFromCreature(14000, oPC, TRUE, TRUE));
				DestroyObject(oItemOnBench);
				CreateItemOnObject(sIngotResRef, oTarget, 7);
			 }
			 else if(GetResRef(oItemOnBench) == "sBandedMailResRef" && GetGold(oPC) >= 12000)
			 {
			    SendMessageToPC(oDebug, "Gold before " + sBandedMailResRef + ": " + IntToString(GetGold(oPC)));
			 	AssignCommand(oPC, TakeGoldFromCreature(12000, oPC, TRUE, TRUE));
				DestroyObject(oItemOnBench);
				CreateItemOnObject(sIngotResRef, oTarget, 6);
			 }
			 oItemOnBench = GetNextItemInInventory(oTarget);
		}

It’s the AssignCommand() for the TakeGoldFromCreature function - by using that, it will cause the designated object to run the command itself, which will take place after the script has concluded. Good news is, it’s completely unnecessary to use in this case and you can just use the TakeGoldFromCreature function without it.

5 Likes

Unfortunately, without AssignCommand it doesn’t work.

TakeGoldFromCreature(16000, oPC, TRUE, TRUE)

Gold is not removed from PC inventory?

1 Like

@Examon

You need to approach this a bit differently … :slightly_smiling_face:

Trying to GetGold and TakeGold in this manner will not work as far as I am aware. Instead, you need to first check gold available, then run a loop that “accounts” for gold that will be removed, and “stop” when that limit is reached.

So, track GOLDREQUIRED as a variable and add to that variable until the limit is reached and then TAKE that gold at the end (outside) of the loop.

1 Like

Okay that’s my bad, I’d run a quick test and it worked, but there might be something else there causing it to not work. As Lance says you can just keep track of the gold required in separate variables though, something like this:

	int nGoldRemaining = GetGold(oPC);
	int nGoldToTake;
	
	while (GetIsObjectValid(oItemOnBench))
	{
	     if (GetResRef(oItemOnBench) == sFullPlateResRef && nGoldRemaining >= 16000)
		 {
		    SendMessageToPC(oDebug, "Gold before " + "sFullPlateResRef" + ": " + IntToString(GetGold(oPC)));
			nGoldRemaining -= 16000;
			nGoldToTake += 16000;
			DestroyObject(oItemOnBench);
			CreateItemOnObject(sIngotResRef, oTarget, 8);
		 }
		 else if(GetResRef(oItemOnBench) == sHalfPlateResRef && nGoldRemaining >= 14000)
		 {
		    SendMessageToPC(oDebug, "Gold before " + "sHalfPlateResRef" + ": " + IntToString(GetGold(oPC)));
			nGoldRemaining -= 14000;
			nGoldToTake += 14000;
			DestroyObject(oItemOnBench);
			CreateItemOnObject(sIngotResRef, oTarget, 7);
		 }
		 else if(GetResRef(oItemOnBench) == "sBandedMailResRef" && nGoldRemaining >= 12000)
		 {
		    SendMessageToPC(oDebug, "Gold before " + sBandedMailResRef + ": " + IntToString(GetGold(oPC)));
			nGoldRemaining -= 12000;
			nGoldToTake += 12000;
			DestroyObject(oItemOnBench);
			CreateItemOnObject(sIngotResRef, oTarget, 6);
		 }
		 oItemOnBench = GetNextItemInInventory(oTarget);
	}
	
	AssignCommand(oPC, TakeGoldFromCreature(nGoldToTake, oPC, TRUE, TRUE));
3 Likes

Works good in testing - edit as you see fit:

// i_smithhammer_ac

#include "ginc_crafting"

void Smelt(object oItemOnBench, object oPC, object oTarget, int nTally, int nCost, int nIngots)
{
	int nNewTally = nTally - nCost;

	SendMessageToPC(oPC, GetName(oItemOnBench) + " smelted for " + IntToString(nCost) + " gold.");
	SendMessageToPC(oPC, "Remaining gold: " + IntToString(nNewTally));	
	SetLocalInt(oTarget, "tally", nNewTally);
	DestroyObject(oItemOnBench);
	CreateItemOnObject("n2_crft_ingmithral", oPC, nIngots);
	SendMessageToPC(oPC, " ");	
}

void main()
{
	object oPC = GetItemActivator();
	object oItem = GetItemActivated();
	object oTarget = GetItemActivatedTarget();
	location lTarget = GetItemActivatedTargetLocation();
	string sTargetTag = GetTag(oItem);
	int bSmithHammerRenameItem = GetGlobalInt(CAMPAIGN_SWITCH_SMITH_HAMMER_RENAME_ITEM);

	if (IsSmithWorkbench(oTarget))
	{
		int nStartGold = GetGold(oPC);
		int n;
		string s;
		object oItemOnBench = GetFirstItemInInventory(oTarget);

		SetLocalInt(oTarget, "tally", nStartGold);
		SendMessageToPC(oPC, "Starting gold: " + IntToString(nStartGold));
					
		while (GetIsObjectValid(oItemOnBench))
		{
			n = GetLocalInt(oTarget, "tally");	
			s = GetResRef(oItemOnBench);
						 
			if (s == "mwa_hvfp_mth_4" && n >= 16000)			//full plate
			{
				Smelt(oItemOnBench, oPC, oTarget, n, 16000, 8);
			}
			
			else if (s == "mwa_hvhp_mth_4" && n >= 14000)		//half plate
			{
				Smelt(oItemOnBench, oPC, oTarget, n, 14000, 7);
			}
			
			else if (s == "mwa_hvbm_mth_3" && n >= 12000)		//banded mail
			{
				Smelt(oItemOnBench, oPC, oTarget, n, 12000, 6);
			}
			
			else if (s == "mwa_mdcm_mth_4" && n >= 10000)		//chain mail
			{
				Smelt(oItemOnBench, oPC, oTarget, n, 10000, 5);
			}
			
			else if (s == "mwa_mdbp_mth_4" && n >= 10000)		//breast plate
			{
				Smelt(oItemOnBench, oPC, oTarget, n, 10000, 5);
			}

			else if (s == "mwa_mdsm_mth_4" && n >= 8000)		//scale mail
			{
				Smelt(oItemOnBench, oPC, oTarget, n, 8000, 4);
			}
			
			else if (s == "mwa_ltcs_mth_4" && n >= 8000)		//chain shirt
			{
				Smelt(oItemOnBench, oPC, oTarget, n, 8000, 4);
			}
			
			else if (s == "mwa_shtw_mth_4" && n >= 8000)		//tower shield
			{
				Smelt(oItemOnBench, oPC, oTarget, n, 8000, 4);
			}
			
			else if (s == "nx1_chainshirt_frost" && n >= 8000)	//chain of frost
			{
				Smelt(oItemOnBench, oPC, oTarget, n, 8000, 4);
			}

			else if (s == "mwa_shhv_mth_4" && n >= 2000)		//heavy shield
			{
				Smelt(oItemOnBench, oPC, oTarget, n, 2000, 2);
			}
			
			else if (s == "mwa_shlt_mth_4" && n >= 1000)		//light shield
			{
				Smelt(oItemOnBench, oPC, oTarget, n, 1000, 1);
			}
			
			else if (s == "nx1_chainmail01" && n >= 10000)		//imaskari battlemage armor
			{
				Smelt(oItemOnBench, oPC, oTarget, n, 10000, 5);
			}									
		
			oItemOnBench = GetNextItemInInventory(oTarget);
		}
		
		n = GetLocalInt(oTarget, "tally");
		
		if (n < nStartGold)
		{
			AssignCommand(oTarget, TakeGoldFromCreature(nStartGold - n, oPC, TRUE, FALSE));
		}
		
		// no change in gold so lets do normal crafting
		else AssignCommand(oTarget, DoMundaneCrafting(oPC));
	}
		
	else if (bSmithHammerRenameItem && (GetObjectType(oTarget) == OBJECT_TYPE_ITEM))
	{
		SetEnchantedItemName(oPC, oTarget);
	}
	
	else ErrorNotify(oPC, ERROR_UNRECOGNIZED_HAMMER_USAGE);
}
4 Likes

Using additional variables GoldSpent and GoldRemaining in if statements resolved issue. Thank you very much.

3 Likes