From ebf28e6dae3a52ead5d2e13d9384e94b5756e37f Mon Sep 17 00:00:00 2001
From: vbawol <vbawol@veteranbastards.com>
Date: Tue, 10 Oct 2017 10:49:00 -0500
Subject: [PATCH] optimize EPOCH_fnc_weightedArray and usage

added isClass check to make sure item exists before adding to loottable.
updated for use with single array syntax of selectRandomWeighted
---
 .../compile/both/EPOCH_weightedArray.sqf      | 52 +++++++++++++++----
 .../epoch_server/EPOCH_serverLootObject.sqf   | 17 +++---
 2 files changed, 49 insertions(+), 20 deletions(-)

diff --git a/Sources/epoch_code/compile/both/EPOCH_weightedArray.sqf b/Sources/epoch_code/compile/both/EPOCH_weightedArray.sqf
index 832d01ca..d659de4f 100644
--- a/Sources/epoch_code/compile/both/EPOCH_weightedArray.sqf
+++ b/Sources/epoch_code/compile/both/EPOCH_weightedArray.sqf
@@ -11,9 +11,13 @@
 
 	Github:
 	https://github.com/EpochModTeam/Epoch/tree/release/Sources/epoch_code/compile/both/EPOCH_weightedArray.sqf
+
+	Usage:
+	_lootTable = ["CfgMainTable", _type, "tables"] call EPOCH_fnc_weightedArray;
+	_loot = selectRandomWeighted _lootTable;
 */
 //[[[cog import generate_private_arrays ]]]
-private ["_allow","_lootIndex","_lootTableArray","_lootTableName","_return","_value","_weightedArray"];
+private ["_allow","_itemType","_lootTableArray","_lootTableName","_newChances","_return","_selectedloot","_totalChances","_value","_weightedArray"];
 //[[[end]]]
 params ["_configName","_keyName","_arrayName"];
 
@@ -25,10 +29,11 @@ if(_return isEqualTo[]) then {
 	// Since no cached version is found, make one.
 	_lootTableArray = [];
 	_weightedArray  = [];
-	_lootIndex = 0;
 	{
 		if(_x isEqualType []) then {
 			_x params ["_tname","_tqty",["_extraLogicRaw", [] ]];
+			_tname params ["_item",["_itemType","NA"]];
+			if (_configName isEqualTo "CfgMainTable") then {_itemType = "CfgLootTable"};
 			_allow = true;
 			if !(_extraLogicRaw isEqualTo[]) then {
 				_extraLogicRaw params [["_extraLogicType",""],["_extraLogicName",""],["_extraLogicCond",""],["_extraLogicData",""]];
@@ -50,22 +55,51 @@ if(_return isEqualTo[]) then {
 				};
 				_allow = [_value,_extraLogicCond,_extraLogicData] call EPOCH_fnc_arrayToLogic;
 			};
+			// Check if config item actually exists
+			if (_allow) then {
+				switch _itemType do {
+					case "magazine": {
+						_allow = isClass (configFile >> "CfgMagazines" >> _item);
+					};
+					case "backpack": {
+						_allow = isClass (configFile >> "CfgVehicles" >> _item);
+					};
+					case "item";
+					case "weapon": {
+						_allow = isClass (configFile >> "CfgWeapons" >> _item);
+					};
+					case "CfgLootTable": {
+						_allow = isClass (missionConfigFile >> "CfgLootTable" >> _item);
+					};
+				};
+			};
+			// add to loot table
 			if (_allow) then {
 				_lootTableArray pushBack _tname;
-				for "_i" from 1 to _tqty do {
-					_weightedArray pushBack _lootIndex;
-				};
-				_lootIndex = _lootIndex + 1;
+				_weightedArray pushBack _tqty;
 			};
 		} else {
 			_lootTableArray pushBack _x;
-			_weightedArray pushBack _lootIndex;
-			_lootIndex = _lootIndex + 1;
+			_weightedArray pushBack 1;
 		};
 	}forEach getArray((_configName call EPOCH_returnConfig) >> _keyName >> _arrayName);
-	_return = [_lootTableArray,_weightedArray];
+
+	// compile to selectRandomWeighted <ARRAY> format.
+	private _totalChances = 0;
+	{_totalChances = _totalChances + _x} count _weightedArray;
+	_return = [];
+	{
+		_selectedloot = _lootTableArray select _forEachIndex;
+		_return append [_selectedloot,linearConversion [0,_totalChances,_x,0,1]];
+	} forEach _weightedArray;
+
 	// cache loot final loot table
 	missionNamespace setVariable[_lootTableName,_return];
+
+	// debug
+	if (["CfgEpochClient", "debug", false] call EPOCH_fnc_returnConfigEntryV2) then {
+		diag_log format["DEBUG: LootTable: %1 DATA: %2",_lootTableName,_return];
+	};
 };
 
 _return
diff --git a/Sources/epoch_server/compile/epoch_server/EPOCH_serverLootObject.sqf b/Sources/epoch_server/compile/epoch_server/EPOCH_serverLootObject.sqf
index b9ec5949..021df6bc 100644
--- a/Sources/epoch_server/compile/epoch_server/EPOCH_serverLootObject.sqf
+++ b/Sources/epoch_server/compile/epoch_server/EPOCH_serverLootObject.sqf
@@ -30,22 +30,19 @@ if (isnull _object && !(_pos isequalto [])) then {
 };
 if !(isNull _object) then{
 	_lootTable = ["CfgMainTable", _type, "tables"] call EPOCH_fnc_weightedArray;
-	_lootTable params ["_lootTableArray","_weightedArray"];
-	if !(_lootTableArray isEqualTo []) then {
+	if !(_lootTable isEqualTo []) then {
 		_loots = [];
 		_config = configFile >> "CfgMainTable" >> _type;
 		_minLoot = getNumber(_config >> "lootMin");
 		_maxLoot = getNumber(_config >> "lootMax");
 		_maxPayout = ((random(_maxLoot) * EPOCH_lootMultiplier) min _maxLoot) max _minLoot;
 		for "_k" from 1 to _maxPayout do {
-			_loots pushBack (_lootTableArray select(selectRandom _weightedArray));
+			_loots pushBack (selectRandomWeighted _lootTable);
 		};
 		{
 			_lootItemWeightedArray = [_lootTableClass, _x, "items"] call EPOCH_fnc_weightedArray;
-			_lootItemArray = _lootItemWeightedArray select 0;
-			if !(_lootItemArray isEqualTo[]) then {
-				_weightedItemArray = _lootItemWeightedArray select 1;
-				_randomItemArray = _lootItemArray select (selectRandom _weightedItemArray);
+			if !(_lootItemWeightedArray isEqualTo[]) then {
+				_randomItemArray = selectRandomWeighted _lootItemWeightedArray;
 				_randomItem = _randomItemArray select 0;
 				_type = _randomItemArray select 1;
 				_quan = 1;
@@ -107,10 +104,8 @@ if !(isNull _object) then{
 						case "CfgLootTable": {
 							// go down the rabit hole
 							_lootItemWeightedArray = [_lootTableClass, _randomItem, "items"] call EPOCH_fnc_weightedArray;
-							_lootItemArray = _lootItemWeightedArray select 0;
-							if !(_lootItemArray isEqualTo[]) then {
-								_weightedItemArray = _lootItemWeightedArray select 1;
-								_randomItemArray = _lootItemArray select(selectRandom _weightedItemArray);
+							if !(_lootItemWeightedArray isEqualTo[]) then {
+								_randomItemArray = selectRandomWeighted _lootItemWeightedArray;
 								_randomItem = _randomItemArray select 0;
 								_type = _randomItemArray select 1;
 							} else {