Edit: Why array size not increased on adding items? C++

Hello, I need some help to identify why my for loop is infinite in this function?

void AMyGameMode::RandomItemID(EItemType ItemType, FST_ItemTypeAndID& Item)
{
	TStructArray<FST_ItemTypeAndID> StructArr; //this struct contains two variables (FName ID) and (EItemType Type)
	FST_ItemTypeAndID TempItemTypeAndID_var;
	TStructArray<FName> OutRowNames{};
	FST_ItemTypeAndID GetByRef;

	switch (ItemType)
	{
	case EItemType::E_None:
		{
			print100s("Invalid Type: Default Type Selected::None");
		}break;
	case EItemType::E_Weapon:
		{
			if (const UDataTable* Rows = LoadObject<UDataTable>(GetWorld(), TEXT("/Game/DataTables/DT_ItamWeapon")))
				OutRowNames = Rows->GetRowNames();
			{
				for (auto& StructArrElem : OutRowNames)
				{
					if (const UDataTable* DT_ItamWeapon{ LoadObject<UDataTable>(GetWorld(), TEXT("/Game/DataTables/DT_ItamWeapon")) })
					{
						if (const FST_ItemWeapon * OutRow{ DT_ItamWeapon->FindRow<FST_ItemWeapon>(FName(StructArrElem), "") })
						{
							if (OutRow)
							{
								FST_ItemWeapon WeaponItemDatas = *OutRow;
//this loop is infinite for some reason, help me to figure it out, thanks
								for (int32 i = 1; i <= WeaponItemDatas.ProbabilityPercent; i++)
								{
									TempItemTypeAndID_var.ID = StructArrElem;
									TempItemTypeAndID_var.Type = EItemType::E_Weapon;
									StructArr.Add(TempItemTypeAndID_var);
								}
							}
							else {
								print100s("Cast of Weapon Item Datas Failed: Line 240 :: Class MyGameMode");
							}
							
						}
					}
				}
			}
		}
		break;
		default:
		{
			TempItemTypeAndID_var.Type = EItemType::E_None;
		}break;
	}
	GetByRef = StructArr[FMath::RandRange(0, StructArr.Num() - 1)];
	FCustomThunkTemplates::StructArray_Shuffle(StructArr);
	Item = GetByRef;
}

UPDATE, working blueprint version

The loop is infinite only in “C++”

ku, can you please share the error message?

Sir the engine crashed on this page

its mean array index out of limit and it can cause assertion failed on beginplay.
how many rows in your weapon data table?

currently I have 20 rows

increase the array size or decrease the row size
just experimental try it

hope it helps
cheers!

1 Like

will try for sure and will update here about the result :slight_smile: , thank you for helping me in my studies , really appreciated

this is what I found in the logs

Assertion failed: (Index >= 0) & (Index < ArrayNum)
----------------------------------------------------
[\Engine\Source\Runtime\Core\Public\Containers/Array.h] [Line: 674] 
Array index out of bounds: 0 from an array of size 0
UE4Editor.exe has triggered a breakpoint.

The program '[13792] UE4Editor.exe' has exited with code 0 (0x0).

Sir, i tried your experimental solution but the problem remain the same, don’t you think my cast the struct is even not created or not availabe to make the correct row size to be randomized?

i think thats why GetByRef = StructArr[FMath::RandRange(0, StructArr.Num() - 1)]; is complaining about Array index out of bounds: 0 from an array of size 0

how can I increase the size of the struct array if this the reason for
Assertion failed: (Index >= 0) & (Index < ArrayNum) ?
currently I have the struct of size 16 and I am randomizing it like

 StructArr[FMath::RandRange(0, StructArr.Num() - 1)];

it has 2 variables

UENum ItemType;
FName ID;

Thank you for assisting :slight_smile:

try adding this line right before randomizing

Arr.SetNum(32);

hope it helps
cheers!

1 Like

adding this is fixing the for loop

StructArr.SetNum(32);

but why the array size is not increasing by itself when I add I tems to struct dynamically?

If I had to guess it’s because all your ProbabilityPercent values are greater than 1 and you’re failing the `i <= WeaponItemDatas.ProbabilityPercent’ check.

You should get more familiar with your debugger, set a breakpoint and step through the code and watch the variables as they change and are checked.

1 Like

I am already making the space for them from 1 to 99 and the addition of all ProbabilityPercent values = 100 , so I should have an array of size 99 automatically logically but I don’t know where I miss something and the array is not populating by itself to the correct size.

void AMyGameMode::RandomItemNumber(nt32& Number)
{
	TArray<int32> Arr{};
	TArray<FName> OutRowNames{};
	int32 GetByCopy{};
	(OutRowNames).Reset();

	if (const UDataTable* DT_ItemNumberProbability = LoadObject<UDataTable>(NULL, TEXT("/Game/DataTables/DT_ItemNumbarProbability")))
	{
		OutRowNames = DT_ItemNumberProbability->GetRowNames();
		for (auto& Array : OutRowNames)
		{
			if (const UDataTable* DT_ItemNumberProbability{ LoadObject<UDataTable>(GetWorld(), TEXT("/Game/DataTables/DT_ItemNumbarProbability")) })
			{
				if (const FST_ItemNumberProbability * OutRow{ DT_ItemNumberProbability->FindRow<FST_ItemNumberProbability>(FName(Array), "") })
				{
					if (OutRow)
					{
						NumberProbabilityDatas = *OutRow;
						for ( int32 i = 1; i <= NumberProbabilityDatas.Percent; i++)
						{
							Arr.Add(NumberProbabilityDatas.Number);
						}
					}
				}
			}
		}
		GetByCopy = Arr[FMath::RandRange(1, 99)]; //Set Random Array Length
		FCustomThunkTemplates::Array_Shuffle(Arr);
		Number = GetByCopy;
	}
}

Really, you need to re-think this entire operation. There is no reason whatsoever to build an array of 100 items to calculate a percentile. It’s just a simple math and an if comparison.

You are doing this in probably the most complex way imaginable, and that’s why you are having trouble with every single operation.

1 Like

this is the goal , I can’t imagine any other simple way achieve this, ex: every weapon will know which accessories it should use, ex: sniper know that big range scopes are intended to use by snipers, actually every weapon know what accessories and other types it should use by type and ID.
look a to this accessories data table, every accessory has its own ID of weapon to be used.
image_2022-08-08_000225363

ID 1 and 2 are DMR/AR and 3 is SR
if accessory don’t have a weapon ID, its mean it can be used with all weapons

I finally managed to test if the arrays are actually generated with random groups of random item arrays in range of [0, 99] and in the result every thing works fine, the minimum number of items/rows is 3 and the maximum is 5, every item is generated and not duplicated in the group.

So RandomItemNumbers(); and RandomItemType(); working fine.

The problem is in the RandomItemID(); Function, returning error…

Assertion failed: (Index >= 0) & (Index < ArrayNum)

The for loop is actually infinite for some reason I don’t Know.

void AMyGameMode::RandomItemID(EItemType ItemType, FST_ItemTypeAndID & Item) {
  ItemType = TempItemTypeAndID_var.Type = EItemType::E_Weapon;

  switch (ItemTypes) {
  case EItemType::E_Weapon: {
    if (const UDataTable * DT_ItamWeaponRows = LoadObject < UDataTable > (GetWorld(), TEXT("/Game/DataTables/Items/Weapon/DT_ItamWeapon"))) {
      OutRowNamesWeapons = DT_ItamWeaponRows -> GetRowNames();
      for (auto & WeaponArrayElem: OutRowNamesWeapons) {
        if (const UDataTable * DT_ItamWeapon {
            LoadObject < UDataTable > (GetWorld(), TEXT("/Game/DataTables/Items/Weapon/DT_ItamWeapon"))
          }) {
          if (const FST_ItemWeapon * OutRow {
              DT_ItamWeapon -> FindRow < FST_ItemWeapon > (FName(WeaponArrayElem), "")
            }) {
            if (OutRow) {
             //Why this loop is Infinite?
              for (int32 i = 1; i <= 10; i++) {
                print100s("Loop Executed!");
              }
            }
          }
        }
      }
    }
  }
  break;
  default: {
    print100s("Default State--");
  }
  break;
  }
}

according to your blueprint you are totally doing different things in your C++ code, reconsider re doing the whole logic.

hope it helps
cheers!

1 Like

already trying from 2 days and i am lost, I can make a request to edit my code to match my bp if you don’t mind :tired_face: