Rydygier 1309 Posted November 1, 2015 Not to mention that mod authors sometimes misconfigure things. (For example, the CUP MP5s were put into "Rifles" and not "SMGs" due to a wrong attribute in their configs.) IMHO I wouldn't worry about this. Enough to make clear, who is responsible/guilty of misplaced stuff, plus, at most, some info to the modder, to let him know, he screwed up. :) I mean, proper configuration is important part of the modder's job, yet sometimes perhaps neglected by some of them. I think, better for all would be to make "educational pressure" on the modellers/mapmakers etc. to motivate them toward more attentive configuration instead of taking all errors, odd ideas and mistakes of the others on the own shoulders and self-limit yourself because of the possibility of them. Then all would benefit - modellers who so far neglected config may pay more attention in the future and fix current erros in their work, usually trivial to do, scripters/mission makers can focus on features rather than patching the others possible mistakes, players would enjoy even better result. For example, pricing algorithm from Pilgrimage shamelessly takes values from the config and uses them to calculate the price procedurally, so it's perfectly vulnerable on misconfiguration, and I'm OK with that - when doing my job I'm just assuming, the others did their, and if not - shame on them. From the other hand so far had no any reports on the odd prices, so it's not that bad. Can't wait, till I get enough free time to try this mission without haste, but with adequate solemnity... :) 2 Share this post Link to post Share on other sites
IndeedPete 1038 Posted November 1, 2015 Yes, it's not that bad. And I'm still rather strict when it comes to auto-indexing. There's a whitelist of allowed weapon types and if a weapon is not configured by that standard used by BI, it does not show up: _weaponCategories = "((if (isNumber(_x >> 'show')) then {(getNumber(_x >> 'show'))} else {1}) == 1) && {count _x > 0}" configClasses (missionConfigFile >> "ShopWeapons"); IP_WeaponCategories = _weaponCategories call _getClasses; IP_WeaponFilters = ["All"] + IP_WeaponCategories; IP_AvailableWeapons = []; { private "_weapons"; _weapons = []; _weaponClasspaths = "((isNumber(_x >> 'price')) && {(if (isNumber(_x >> 'show')) then {(getNumber(_x >> 'show'))} else {1}) == 1})" configClasses (missionConfigFile >> "ShopWeapons" >> _x); _weaponClasses = _weaponClasspaths call _getClasses; { if ((isNumber(configFile >> "CfgWeapons" >> _x >> "scope")) && {getNumber(configFile >> "CfgWeapons" >> _x >> "scope") == 2}) then { _weapons pushBack _x; }; } forEach _weaponClasses; IP_AvailableWeapons pushBack _weapons; } forEach IP_WeaponCategories; if (_autoIndexing) then { _weaponClasspaths = "((getText(_x >> 'simulation') == 'weapon') && {isNumber(_x >> 'scope')} && {getNumber(_x >> 'scope') == 2})" configClasses (configFile >> "CfgWeapons"); _weaponClasses = _weaponClasspaths call _getClasses; { if ((([_x] call BIS_fnc_baseWeapon) == _x) && {([(missionConfigFile >> "ShopWeapons"), _x] call IP_fnc_getConfigCategory) == ""}) then { private "_category"; _category = switch (getText(configFile >> "CfgWeapons" >> _x >> "cursor")) do { case "hgun": {"Pistols"}; case "smg": {"SMG"}; case "sgun": {"Carbines"}; case "arifle": {"Rifles"}; case "mg": {"LMG"}; case "srifle": {"Marksman"}; case "rocket": {"Launchers"}; default {""}; }; _muzzles = (getArray(configFile >> "CfgWeapons" >> _x >> "muzzles")) - ["this"]; if (count _muzzles > 0) then { _weapon = _x; { if (((getText(configFile >> "CfgWeapons" >> _weapon >> _x >> "cursor")) == "EmptyCursor") && {(getText(configFile >> "CfgWeapons" >> _weapon >> _x >> "cursorAim")) == "gl"}) exitWith { _category = "RiflesGL"; }; } forEach _muzzles; }; _index = IP_WeaponCategories find _category; if (_index >= 0) then { (IP_AvailableWeapons select _index) pushBack _x; }; }; } forEach _weaponClasses; }; I've also thought about automated pricing. I'd rather keep auto-pricing optional, so that configured values override generic values determined by an alrorithm. At the moment, I use a hard-coded base price based on category. It's okay with weapons, ammo's the real bitch. I was able to split explosives (grenades, rockets, etc.) from bullets already, but I still need to go deeper to determine the size / caliber of a projectile. A grenade from a mod pack shouldn't be as expensive as a rocket for example. Would you mind if I take a look at Pilgrimage's pricing algorithm? Share this post Link to post Share on other sites
Rydygier 1309 Posted November 1, 2015 Would you mind if I take a look at Pilgrimage's pricing algorithm? Sure, feel free to do so. It's 1080-1966 lines of JR_fnc.sqf, a function caller RYD_JR_SellCargo, containing algorithm to obtain all the stuff, then pricing, then selling it. RYD_JR_SellCargo = { _holder = _this select 0; _removeH = _this select 3; if (_removeH) then { _holder removeAction (_this select 2); }; _val = 0; _wps = []; _ammo = []; _items = []; if not (_holder in allDeadMen) then { _holders = [_holder]; { _holders pushBack (_x select 1) } foreach (everyContainer _holder); { _items pushBack (typeOf _x) } foreach (everyBackpack _holder); { _hldr = _x; _itemC = getItemCargo _hldr; { for "_i" from 1 to ((_itemC select 1) select _foreachIndex) do { _items pushBack _x } } foreach (_itemC select 0); { _wpnArr = _x; _wpn = _wpnArr select 0; if not (_wpn in _items) then { _wps pushBack (_wpnArr select 0); }; for "_i" from 1 to ((count _wpnArr) - 1) do { _item = _wpnArr select _i; if ((typeName _item) in [typeName []]) then { _ammo pushBack _item } else { if not (_item isEqualTo "") then { _items pushBack _item } } } } foreach (weaponsItemsCargo _hldr); { _ammo pushBack _x } foreach (magazinesAmmoCargo _hldr) } foreach _holders; } else { { _itemC = getItemCargo _x; { for "_i" from 1 to ((_itemC select 1) select _foreachIndex) do { _items pushBack _x } } foreach (_itemC select 0); } foreach [uniformContainer _holder,vestContainer _holder,backPackContainer _holder]; { if not (_x isEqualTo "") then { _items pushBack _x } } foreach ((assignedItems _holder) + [headGear _holder,goggles _holder,uniform _holder,vest _holder, backPack _holder]); { _wpnArr = _x; _wpn = _wpnArr select 0; if not (_wpn in _items) then { _wps pushBack (_wpnArr select 0); }; for "_i" from 1 to ((count _wpnArr) - 1) do { _item = _wpnArr select _i; if ((typeName _item) in [typeName []]) then { _ammo pushBack _item } else { if not (_item isEqualTo "") then { _items pushBack _item } } } } foreach (weaponsItems _holder); { _ammo pushBack _x } foreach (magazinesAmmo _holder); }; _weapons = []; _weaponsA = []; { _wpn = _x; if not (_wpn in _weapons) then { _weapons pushBack _wpn; _cnt = {_wpn isEqualTo _x} count _wps; _weaponsA pushBack _cnt } } foreach _wps; _ammunition = []; _ammunitionA = []; _ammunitionC = []; { if ((typeName _x) in [typeName []]) then { if ((count _x) > 1) then { _mag = _x select 0; if not (_mag in _ammunition) then { _ammunition pushBack _mag; _cnt = {_mag isEqualTo (_x select 0)} count _ammo; _ammunitionA pushBack _cnt; _bCnt = 0; { if ((_x select 0) isEqualTo _mag) then { _bCnt = _bCnt + (_x select 1) } } foreach _ammo; _ammunitionC pushBack _bCnt } } /*else { hint format ["mag wrong content: %1",_x]; diag_log format ["mag wrong content: %1",_x]; }*/ } /*else { hint format ["mag wrong content: %1",_x]; diag_log format ["mag wrong type: %1",_x]; }*/ } foreach _ammo; _other = []; _otherA = []; { _itm = _x; if not (_itm in _other) then { _other pushBack _itm; _cnt = {_itm isEqualTo _x} count _items; _otherA pushBack _cnt } } foreach _items; _desc = ""; _fx = ""; _vehClass = configFile >> "CfgVehicles"; _weapClass = configFile >> "CfgWeapons"; _ammoClass = configFile >> "CfgMagazines"; _bulletClass = configFile >> "CfgAmmo"; { _amt = _weaponsA select _foreachIndex; if (_foreachIndex > 0) then {_fx = "_"}; _type = [_x] call BIS_fnc_itemType; switch (true) do { case ("MissileLauncher" in _type) : {_val = _val + (2400 * _amt)}; case ("RocketLauncher" in _type) : {_val = _val + (2000 * _amt)}; case ("Launcher" in _type) : {_val = _val + (2000 * _amt)}; case ("SniperRifle" in _type) : {_val = _val + (1500 * _amt)}; case ("MachineGun" in _type) : {_val = _val + (1000 * _amt)}; case ("AssaultRifle" in _type) : {_val = _val + (700 * _amt)}; case ("Rifle" in _type) : {_val = _val + (600 * _amt)}; case ("SubmachineGun" in _type) : {_val = _val + (400 * _amt)}; case ("Handgun" in _type) : {_val = _val + (100 * _amt)}; case ("Binocular" in _type) : { _addVal = 10; _vModes = _weapClass >> _x >> "visionMode"; if (isArray _vModes) then { _vModes = getArray _vModes; _vModesLow = []; { _vModesLow pushBack (tolower _x) } foreach _vModes; _vModes = _vModesLow; if ("nvg" in _vModes) then {_addVal = _addVal + 500}; if ("ti" in _vModes) then {_addVal = _addVal + 800}; }; _zoom = _weapClass >> _x >> "opticsZoomMin"; if (isNumber _zoom) then { _zoom = getNumber _zoom; _addVal = _addVal + 10/(0.0001 + _zoom) }; _val = _val + (_addVal * _amt) }; case ("LaserDesignator" in _type) : { _val = _val + (2000 * _amt) }; default {_val = _val + (100 * _amt)} }; _addVal = 0; if (isArray (_weapClass >> _x >> "muzzles")) then { _mVal = 80 * (((count (getArray (_weapClass >> _x >> "muzzles"))) - 1)); _addVal = _addVal + _mVal }; if (isArray (_weapClass >> _x >> "magazines")) then { _mags = getArray (_weapClass >> _x >> "magazines"); if ((count _mags) > 0) then { _mag = _mags select 0; _magC = _ammoClass >> _mag; _iSpeed = 0; _count = 0; if (isClass _magC) then { if (isNumber (_magC >> "initSpeed")) then { _iSpeed = getNumber (_magC >> "initSpeed") }; if (isNumber (_magC >> "count")) then { _count = getNumber (_magC >> "count") } }; if (isText (_ammoClass >> _mag >> "ammo")) then { _bullet = getText (_ammoClass >> _mag >> "ammo"); _bulletC = _bulletClass >> _bullet; if (isClass _bulletC) then { _hit = 0; if (isNumber (_bulletC >> "hit")) then { _hit = getNumber (_bulletC >> "hit") }; _iHit = 0; if (isNumber (_bulletC >> "indirectHit")) then { _iHit = getNumber (_bulletC >> "indirectHit") }; _iHitR = 0; if (isNumber (_bulletC >> "indirectHitRange")) then { _iHitR = getNumber (_bulletC >> "indirectHitRange") }; _cal = 0; if (isNumber (_bulletC >> "caliber")) then { _cal = getNumber (_bulletC >> "caliber") }; if (_type in ["MissileLauncher","RocketLauncher","Launcher"]) then { _addVal = _addVal + (round ((_hit + (_iHit * _iHitR)) * _amt)) } else { _addVal = _addVal + (round (((_cal * 100) + (_iSpeed/8) + (_count min 100)) * _amt)); } }; }; }; }; _val = _val + _addVal; _name = "Various"; if (isText (_weapClass >> _x >> "DisplayName")) then { _name = getText (_weapClass >> _x >> "DisplayName"); }; if (_name in [""]) then {_name = "Various"}; _desc = _desc + _fx + _name + "_" + (str _amt); } foreach _weapons; _fx = ""; { _mCnt = _ammunitionA select _foreachIndex; _bCnt = _ammunitionC select _foreachIndex; if (_foreachIndex > 0) then {_fx = "_"} else { if not (_desc in [""]) then {_desc = _desc + "_"} }; _count = 0; if (isNumber (_ammoClass >> _x >> "Count")) then { _count = getNumber (_ammoClass >> _x >> "Count") }; _cnt = _bCnt/_count; _mass = 0; if (isNumber (_ammoClass >> _x >> "mass")) then { _mass = getNumber (_ammoClass >> _x >> "mass") }; _ammoName = ""; if (isText (_ammoClass >> _x >> "ammo")) then { _ammoName = getText (_ammoClass >> _x >> "ammo") }; if (_count in [1,3]) then { _mpl = 1; if ((toLower _ammoName) isEqualTo "g_40mm_he") then {_mpl = 10}; _vl = getNumber (_ammoClass >> _x >> "value"); _val = _val + ((_mass * _vl * _count) * _mpl * _cnt) } else { _hit = 0; if (isNumber (_bulletClass >> _ammoName >> "hit")) then { _hit = getNumber (_bulletClass >> _ammoName >> "hit") }; _iHit = 0; if (isNumber (_bulletClass >> _ammoName >> "indirectHit")) then { _iHit = getNumber (_bulletClass >> _ammoName >> "indirectHit") }; _iHitR = 0; if (isNumber (_bulletClass >> _ammoName >> "indirectHitRange")) then { _iHitR = getNumber (_bulletClass >> _ammoName >> "indirectHitRange") }; _tSpeed = 0; if (isNumber (_bulletClass >> _ammoName >> "typicalSpeed")) then { _tSpeed = getNumber (_bulletClass >> _ammoName >> "typicalSpeed") }; _cal = 0; if (isNumber (_bulletClass >> _ammoName >> "caliber")) then { _cal = getNumber (_bulletClass >> _ammoName >> "caliber") }; _val = _val + (((_mass ^ 0.85) * _count * ((1 + _hit + _iHitR + _iHit)/100)) * ((1 + _tSpeed)/1000) * (sqrt (1 + _cal)) * _cnt * 0.5) }; _name = "Various"; if (isText (_ammoClass >> _x >> "DisplayName")) then { _name = getText (_ammoClass >> _x >> "DisplayName"); }; if (_name in [""]) then {_name = "Various"}; _desc = _desc + _fx + _name + "_" + (str _mCnt); } foreach _ammunition; _fx = ""; { _amt = _otherA select _foreachIndex; if (_foreachIndex > 0) then {_fx = "_"} else { if not (_desc in [""]) then {_desc = _desc + "_"} }; _type = [_x] call BIS_fnc_itemType; switch (true) do { case ("AccessoryMuzzle" in _type) : { _addVal = 92; _iInfo = _weapClass >> _x >> "ItemInfo" >> "AmmoCoef"; if (isClass _iInfo) then { _aF = _iInfo >> "audibleFire"; _aFT = _iInfo >> "audibleFireTime"; _vF = _iInfo >> "visibleFire"; _vFT = _iInfo >> "visibleFireTime"; if (({isNumber _x} count [_aF,_aFT,_vF,_vFT]) == 4) then { _aF = getNumber _aF; _aFT = getNumber _aFT; _vF = getNumber _vF; _vFT = getNumber _vFT; _addVal = _addVal + (1/((0.00001 + (_aF * _aFT * _vF * _vFT))^0.65)) } }; _val = _val + (_addVal * _amt) }; case ("AccessoryPointer" in _type) : { _val = _val + (60 * _amt) }; case ("AccessorySights" in _type) : { _addVal = 75; _oModes = _weapClass >> _x >> "ItemInfo" >> "OpticsModes"; if (isClass _oModes) then { _cntOM = count _oModes; _addVal = _addVal + (25 * _cntOM); for "_i" from 0 to (_cntOM - 1) do { _om = _oModes select _i; if (isClass _om) then { _om = configName _om; _minZero = _oModes >> _om >> "distanceZoomMin"; _maxZero = _oModes >> _om >> "distanceZoomMax"; if ((isNumber _minZero) and {isNumber _maxZero}) then { _minZero = getNumber _minZero; _maxZero = getNumber _maxZero; _addVal = _addVal + (((2 * _maxZero) - _minZero)/10) }; _discreteFov = _oModes >> _om >> "discretefov"; if (isArray _discreteFov) then { _discreteFov = getArray _discreteFov; _addVal = _addVal + (25 * (count _discreteFov)); }; _discreteDst = _oModes >> _om >> "discreteDistance"; if (isArray _discreteDst) then { _discreteDst = getArray _discreteDst; _addVal = _addVal + (10 * (count _discreteDst)); }; _zoom = _oModes >> _om >> "opticsZoomMin"; if (isNumber _zoom) then { _zoom = getNumber _zoom; _addVal = _addVal + (7.5/_zoom) }; _vModes = _oModes >> _om >> "visionMode"; if (isArray _vModes) then { _vModes = getArray _vModes; _vModesLow = []; { _vModesLow pushBack (tolower _x) } foreach _vModes; _vModes = _vModesLow; if ("normal" in _vModes) then {_addVal = _addVal + 100}; if ("nvg" in _vModes) then {_addVal = _addVal + 500}; if ("ti" in _vModes) then {_addVal = _addVal + 800}; }; } } }; _val = _val + ((_addVal/1.5) * _amt) }; case ("AccessoryBipod" in _type) : { _val = _val + (200 * _amt) }; case ("Binocular" in _type) : { _addVal = 10; _vModes = _weapClass >> _x >> "visionMode"; if (isArray _vModes) then { _vModes = getArray _vModes; _vModesLow = []; { _vModesLow pushBack (tolower _x) } foreach _vModes; _vModes = _vModesLow; if ("nvg" in _vModes) then {_addVal = _addVal + 500}; if ("ti" in _vModes) then {_addVal = _addVal + 800}; }; _zoom = _weapClass >> _x >> "opticsZoomMin"; if (isNumber _zoom) then { _zoom = getNumber _zoom; _addVal = _addVal + 10/(0.0001 + _zoom) }; _val = _val + (_addVal * _amt) }; case ("FirstAidKit" in _type) : { _val = _val + (30 * _amt) }; case ("GPS" in _type) : { _val = _val + (100 * _amt) }; case ("LaserDesignator" in _type) : { _val = _val + (2000 * _amt) }; case ("Map" in _type) : { _val = _val + (20 * _amt) }; case ("Medikit" in _type) : { _val = _val + (400 * _amt) }; case ("MineDetector" in _type) : { _val = _val + (400 * _amt) }; case ("NVGoggles" in _type) : { _val = _val + (500 * _amt) }; case ("Radio" in _type) : { _val = _val + (100 * _amt) }; case ("Toolkit" in _type) : { _val = _val + (400 * _amt) }; case ("UAVTerminal" in _type) : { _val = _val + (800 * _amt) }; case ("Watch" in _type) : { _val = _val + (40 * _amt) }; case ("Glasses" in _type) : { _addVal = 20; if (_x in ["G_Tactical_Clear","G_Tactical_Black"]) then { _addVal = 200 }; _val = _val + (_addVal * _amt) }; case ("Headgear" in _type) : { _addVal = 10; _pT = _weapClass >> _x >> "ItemInfo" >> "passThrough"; if (isNumber _pT) then { _pT = getNumber _pT; _addVal = _addVal/((_pT max 0.25)^3) }; _val = _val + (_addVal * _amt) }; case ("Vest" in _type) : { _addVal = 90; _pT = _weapClass >> _x >> "ItemInfo" >> "passThrough"; if (isNumber _pT) then { _pT = getNumber _pT; _addVal = _addVal + 10/((_pT max 0.25)^3) }; _armor = _weapClass >> _x >> "ItemInfo" >> "armor"; if (isNumber _armor) then { _armor = getNumber _armor; _addVal = _addVal + (_armor * 40) }; _cap = _weapClass >> _x >> "ItemInfo" >> "containerClass"; if (isText _cap) then { _cap = getText _cap; _cap = _vehClass >> _cap >> "maximumLoad"; if (isNumber _cap) then { _cap = getNumber _cap; _addVal = _addVal + _cap }; }; _val = _val + ((_addVal/6) * _amt) }; case ("Uniform" in _type) : { _addVal = 110; _cap = _weapClass >> _x >> "ItemInfo" >> "containerClass"; if (isText _cap) then { _cap = getText _cap; _cap = _vehClass >> _cap >> "maximumLoad"; if (isNumber _cap) then { _cap = getNumber _cap; _addVal = _addVal + _cap }; }; _val = _val + (_addVal * _amt) }; case ("Backpack" in _type) : { _addVal = 140; _cap = _vehClass >> _x >> "maximumLoad"; if (isNumber _cap) then { _cap = getNumber _cap; _addVal = _addVal + (_cap * 2) }; _val = _val + (_addVal * _amt) }; default { _val = _val + (10 * _amt) } }; _name = "Various"; if (isText (_weapClass >> _x >> "DisplayName")) then { _name = getText (_weapClass >> _x >> "DisplayName"); } else { if (isText (_vehClass >> _x >> "DisplayName")) then { _name = getText (_vehClass >> _x >> "DisplayName"); } }; if (_name in [""]) then {_name = "Various"}; _desc = _desc + _fx + _name + "_" + (str (_otherA select _foreachIndex)); } foreach _other; if not (_holder in allDeadMen) then { clearItemCargo _holder; clearWeaponCargo _holder; clearMagazineCargo _holder; clearBackpackCargo _holder } else { removeHeadgear _holder; removeGoggles _holder; removeAllContainers _holder; removeAllWeapons _holder; removeAllAssignedItems _holder; }; if (_removeH) then { _posTaken = missionnameSpace getVariable ["PosTaken",[]]; _lootSpot = _holder getVariable ["RYD_JR_MyPlace",[0,0,0]]; { if (_lootSpot isEqualTo _x) exitWith {_posTaken set [_foreachIndex,0]} } foreach _posTaken; _posTaken = _posTaken - [0]; missionnameSpace setVariable ["PosTaken",_posTaken]; deleteVehicle _holder; }; RYD_JR_DM_Count = RYD_JR_DM_Count + 1; sleep 0.5; playSound "FD_CP_Clear_F"; sleep 0.02; //diag_log format ["ADMclient - auctioneer: Item '%1' on auction Gattamelata#%2_rapid. Waiting for bidders...",_desc,RYD_JR_DM_Count]; RYD_JR_Caller globalChat format ["ADMclient - auctioneer: Item '%1' on auction Gattamelata#%2_rapid. Waiting for bidders...",_desc,RYD_JR_DM_Count]; [_val,_desc] spawn { _val = _this select 0; _desc = _this select 1; _val = round (_val * (0.85 + (random 0.3))); _val = _val * RYD_JR_CargoValueM; _val = (ceil (_val/10)) * 10; sleep (5 + (random 55)); waitUntil { sleep 2; (((time - RYD_JR_LastComm) > 10) or {RYD_JR_Outro}) }; if (RYD_JR_Outro) exitWith {}; RYD_JR_LastComm = time; RYD_JR_FuelFund = RYD_JR_FuelFund + _val; RYD_JR_FuelFundGain = RYD_JR_FuelFundGain + _val; playSound "FD_CP_Clear_F"; sleep 0.02; RYD_JR_Caller globalChat format ["ADMclient - auctioneer: Item '%4' sold for %1 ff. Auction Gattamelata#%3_rapid closed. Your current account: %2 ff.",_val,RYD_JR_FuelFund,RYD_JR_DM_Count,_desc]; }; }; Share this post Link to post Share on other sites
IndeedPete 1038 Posted November 2, 2015 Sure, feel free to do so. It's 1080-1966 lines of JR_fnc.sqf, a function caller RYD_JR_SellCargo, containing algorithm to obtain all the stuff, then pricing, then selling it. RYD_JR_SellCargo = { _holder = _this select 0; _removeH = _this select 3; if (_removeH) then { _holder removeAction (_this select 2); }; _val = 0; _wps = []; _ammo = []; _items = []; if not (_holder in allDeadMen) then { _holders = [_holder]; { _holders pushBack (_x select 1) } foreach (everyContainer _holder); { _items pushBack (typeOf _x) } foreach (everyBackpack _holder); { _hldr = _x; _itemC = getItemCargo _hldr; { for "_i" from 1 to ((_itemC select 1) select _foreachIndex) do { _items pushBack _x } } foreach (_itemC select 0); { _wpnArr = _x; _wpn = _wpnArr select 0; if not (_wpn in _items) then { _wps pushBack (_wpnArr select 0); }; for "_i" from 1 to ((count _wpnArr) - 1) do { _item = _wpnArr select _i; if ((typeName _item) in [typeName []]) then { _ammo pushBack _item } else { if not (_item isEqualTo "") then { _items pushBack _item } } } } foreach (weaponsItemsCargo _hldr); { _ammo pushBack _x } foreach (magazinesAmmoCargo _hldr) } foreach _holders; } else { { _itemC = getItemCargo _x; { for "_i" from 1 to ((_itemC select 1) select _foreachIndex) do { _items pushBack _x } } foreach (_itemC select 0); } foreach [uniformContainer _holder,vestContainer _holder,backPackContainer _holder]; { if not (_x isEqualTo "") then { _items pushBack _x } } foreach ((assignedItems _holder) + [headGear _holder,goggles _holder,uniform _holder,vest _holder, backPack _holder]); { _wpnArr = _x; _wpn = _wpnArr select 0; if not (_wpn in _items) then { _wps pushBack (_wpnArr select 0); }; for "_i" from 1 to ((count _wpnArr) - 1) do { _item = _wpnArr select _i; if ((typeName _item) in [typeName []]) then { _ammo pushBack _item } else { if not (_item isEqualTo "") then { _items pushBack _item } } } } foreach (weaponsItems _holder); { _ammo pushBack _x } foreach (magazinesAmmo _holder); }; _weapons = []; _weaponsA = []; { _wpn = _x; if not (_wpn in _weapons) then { _weapons pushBack _wpn; _cnt = {_wpn isEqualTo _x} count _wps; _weaponsA pushBack _cnt } } foreach _wps; _ammunition = []; _ammunitionA = []; _ammunitionC = []; { if ((typeName _x) in [typeName []]) then { if ((count _x) > 1) then { _mag = _x select 0; if not (_mag in _ammunition) then { _ammunition pushBack _mag; _cnt = {_mag isEqualTo (_x select 0)} count _ammo; _ammunitionA pushBack _cnt; _bCnt = 0; { if ((_x select 0) isEqualTo _mag) then { _bCnt = _bCnt + (_x select 1) } } foreach _ammo; _ammunitionC pushBack _bCnt } } /*else { hint format ["mag wrong content: %1",_x]; diag_log format ["mag wrong content: %1",_x]; }*/ } /*else { hint format ["mag wrong content: %1",_x]; diag_log format ["mag wrong type: %1",_x]; }*/ } foreach _ammo; _other = []; _otherA = []; { _itm = _x; if not (_itm in _other) then { _other pushBack _itm; _cnt = {_itm isEqualTo _x} count _items; _otherA pushBack _cnt } } foreach _items; _desc = ""; _fx = ""; _vehClass = configFile >> "CfgVehicles"; _weapClass = configFile >> "CfgWeapons"; _ammoClass = configFile >> "CfgMagazines"; _bulletClass = configFile >> "CfgAmmo"; { _amt = _weaponsA select _foreachIndex; if (_foreachIndex > 0) then {_fx = "_"}; _type = [_x] call BIS_fnc_itemType; switch (true) do { case ("MissileLauncher" in _type) : {_val = _val + (2400 * _amt)}; case ("RocketLauncher" in _type) : {_val = _val + (2000 * _amt)}; case ("Launcher" in _type) : {_val = _val + (2000 * _amt)}; case ("SniperRifle" in _type) : {_val = _val + (1500 * _amt)}; case ("MachineGun" in _type) : {_val = _val + (1000 * _amt)}; case ("AssaultRifle" in _type) : {_val = _val + (700 * _amt)}; case ("Rifle" in _type) : {_val = _val + (600 * _amt)}; case ("SubmachineGun" in _type) : {_val = _val + (400 * _amt)}; case ("Handgun" in _type) : {_val = _val + (100 * _amt)}; case ("Binocular" in _type) : { _addVal = 10; _vModes = _weapClass >> _x >> "visionMode"; if (isArray _vModes) then { _vModes = getArray _vModes; _vModesLow = []; { _vModesLow pushBack (tolower _x) } foreach _vModes; _vModes = _vModesLow; if ("nvg" in _vModes) then {_addVal = _addVal + 500}; if ("ti" in _vModes) then {_addVal = _addVal + 800}; }; _zoom = _weapClass >> _x >> "opticsZoomMin"; if (isNumber _zoom) then { _zoom = getNumber _zoom; _addVal = _addVal + 10/(0.0001 + _zoom) }; _val = _val + (_addVal * _amt) }; case ("LaserDesignator" in _type) : { _val = _val + (2000 * _amt) }; default {_val = _val + (100 * _amt)} }; _addVal = 0; if (isArray (_weapClass >> _x >> "muzzles")) then { _mVal = 80 * (((count (getArray (_weapClass >> _x >> "muzzles"))) - 1)); _addVal = _addVal + _mVal }; if (isArray (_weapClass >> _x >> "magazines")) then { _mags = getArray (_weapClass >> _x >> "magazines"); if ((count _mags) > 0) then { _mag = _mags select 0; _magC = _ammoClass >> _mag; _iSpeed = 0; _count = 0; if (isClass _magC) then { if (isNumber (_magC >> "initSpeed")) then { _iSpeed = getNumber (_magC >> "initSpeed") }; if (isNumber (_magC >> "count")) then { _count = getNumber (_magC >> "count") } }; if (isText (_ammoClass >> _mag >> "ammo")) then { _bullet = getText (_ammoClass >> _mag >> "ammo"); _bulletC = _bulletClass >> _bullet; if (isClass _bulletC) then { _hit = 0; if (isNumber (_bulletC >> "hit")) then { _hit = getNumber (_bulletC >> "hit") }; _iHit = 0; if (isNumber (_bulletC >> "indirectHit")) then { _iHit = getNumber (_bulletC >> "indirectHit") }; _iHitR = 0; if (isNumber (_bulletC >> "indirectHitRange")) then { _iHitR = getNumber (_bulletC >> "indirectHitRange") }; _cal = 0; if (isNumber (_bulletC >> "caliber")) then { _cal = getNumber (_bulletC >> "caliber") }; if (_type in ["MissileLauncher","RocketLauncher","Launcher"]) then { _addVal = _addVal + (round ((_hit + (_iHit * _iHitR)) * _amt)) } else { _addVal = _addVal + (round (((_cal * 100) + (_iSpeed/8) + (_count min 100)) * _amt)); } }; }; }; }; _val = _val + _addVal; _name = "Various"; if (isText (_weapClass >> _x >> "DisplayName")) then { _name = getText (_weapClass >> _x >> "DisplayName"); }; if (_name in [""]) then {_name = "Various"}; _desc = _desc + _fx + _name + "_" + (str _amt); } foreach _weapons; _fx = ""; { _mCnt = _ammunitionA select _foreachIndex; _bCnt = _ammunitionC select _foreachIndex; if (_foreachIndex > 0) then {_fx = "_"} else { if not (_desc in [""]) then {_desc = _desc + "_"} }; _count = 0; if (isNumber (_ammoClass >> _x >> "Count")) then { _count = getNumber (_ammoClass >> _x >> "Count") }; _cnt = _bCnt/_count; _mass = 0; if (isNumber (_ammoClass >> _x >> "mass")) then { _mass = getNumber (_ammoClass >> _x >> "mass") }; _ammoName = ""; if (isText (_ammoClass >> _x >> "ammo")) then { _ammoName = getText (_ammoClass >> _x >> "ammo") }; if (_count in [1,3]) then { _mpl = 1; if ((toLower _ammoName) isEqualTo "g_40mm_he") then {_mpl = 10}; _vl = getNumber (_ammoClass >> _x >> "value"); _val = _val + ((_mass * _vl * _count) * _mpl * _cnt) } else { _hit = 0; if (isNumber (_bulletClass >> _ammoName >> "hit")) then { _hit = getNumber (_bulletClass >> _ammoName >> "hit") }; _iHit = 0; if (isNumber (_bulletClass >> _ammoName >> "indirectHit")) then { _iHit = getNumber (_bulletClass >> _ammoName >> "indirectHit") }; _iHitR = 0; if (isNumber (_bulletClass >> _ammoName >> "indirectHitRange")) then { _iHitR = getNumber (_bulletClass >> _ammoName >> "indirectHitRange") }; _tSpeed = 0; if (isNumber (_bulletClass >> _ammoName >> "typicalSpeed")) then { _tSpeed = getNumber (_bulletClass >> _ammoName >> "typicalSpeed") }; _cal = 0; if (isNumber (_bulletClass >> _ammoName >> "caliber")) then { _cal = getNumber (_bulletClass >> _ammoName >> "caliber") }; _val = _val + (((_mass ^ 0.85) * _count * ((1 + _hit + _iHitR + _iHit)/100)) * ((1 + _tSpeed)/1000) * (sqrt (1 + _cal)) * _cnt * 0.5) }; _name = "Various"; if (isText (_ammoClass >> _x >> "DisplayName")) then { _name = getText (_ammoClass >> _x >> "DisplayName"); }; if (_name in [""]) then {_name = "Various"}; _desc = _desc + _fx + _name + "_" + (str _mCnt); } foreach _ammunition; _fx = ""; { _amt = _otherA select _foreachIndex; if (_foreachIndex > 0) then {_fx = "_"} else { if not (_desc in [""]) then {_desc = _desc + "_"} }; _type = [_x] call BIS_fnc_itemType; switch (true) do { case ("AccessoryMuzzle" in _type) : { _addVal = 92; _iInfo = _weapClass >> _x >> "ItemInfo" >> "AmmoCoef"; if (isClass _iInfo) then { _aF = _iInfo >> "audibleFire"; _aFT = _iInfo >> "audibleFireTime"; _vF = _iInfo >> "visibleFire"; _vFT = _iInfo >> "visibleFireTime"; if (({isNumber _x} count [_aF,_aFT,_vF,_vFT]) == 4) then { _aF = getNumber _aF; _aFT = getNumber _aFT; _vF = getNumber _vF; _vFT = getNumber _vFT; _addVal = _addVal + (1/((0.00001 + (_aF * _aFT * _vF * _vFT))^0.65)) } }; _val = _val + (_addVal * _amt) }; case ("AccessoryPointer" in _type) : { _val = _val + (60 * _amt) }; case ("AccessorySights" in _type) : { _addVal = 75; _oModes = _weapClass >> _x >> "ItemInfo" >> "OpticsModes"; if (isClass _oModes) then { _cntOM = count _oModes; _addVal = _addVal + (25 * _cntOM); for "_i" from 0 to (_cntOM - 1) do { _om = _oModes select _i; if (isClass _om) then { _om = configName _om; _minZero = _oModes >> _om >> "distanceZoomMin"; _maxZero = _oModes >> _om >> "distanceZoomMax"; if ((isNumber _minZero) and {isNumber _maxZero}) then { _minZero = getNumber _minZero; _maxZero = getNumber _maxZero; _addVal = _addVal + (((2 * _maxZero) - _minZero)/10) }; _discreteFov = _oModes >> _om >> "discretefov"; if (isArray _discreteFov) then { _discreteFov = getArray _discreteFov; _addVal = _addVal + (25 * (count _discreteFov)); }; _discreteDst = _oModes >> _om >> "discreteDistance"; if (isArray _discreteDst) then { _discreteDst = getArray _discreteDst; _addVal = _addVal + (10 * (count _discreteDst)); }; _zoom = _oModes >> _om >> "opticsZoomMin"; if (isNumber _zoom) then { _zoom = getNumber _zoom; _addVal = _addVal + (7.5/_zoom) }; _vModes = _oModes >> _om >> "visionMode"; if (isArray _vModes) then { _vModes = getArray _vModes; _vModesLow = []; { _vModesLow pushBack (tolower _x) } foreach _vModes; _vModes = _vModesLow; if ("normal" in _vModes) then {_addVal = _addVal + 100}; if ("nvg" in _vModes) then {_addVal = _addVal + 500}; if ("ti" in _vModes) then {_addVal = _addVal + 800}; }; } } }; _val = _val + ((_addVal/1.5) * _amt) }; case ("AccessoryBipod" in _type) : { _val = _val + (200 * _amt) }; case ("Binocular" in _type) : { _addVal = 10; _vModes = _weapClass >> _x >> "visionMode"; if (isArray _vModes) then { _vModes = getArray _vModes; _vModesLow = []; { _vModesLow pushBack (tolower _x) } foreach _vModes; _vModes = _vModesLow; if ("nvg" in _vModes) then {_addVal = _addVal + 500}; if ("ti" in _vModes) then {_addVal = _addVal + 800}; }; _zoom = _weapClass >> _x >> "opticsZoomMin"; if (isNumber _zoom) then { _zoom = getNumber _zoom; _addVal = _addVal + 10/(0.0001 + _zoom) }; _val = _val + (_addVal * _amt) }; case ("FirstAidKit" in _type) : { _val = _val + (30 * _amt) }; case ("GPS" in _type) : { _val = _val + (100 * _amt) }; case ("LaserDesignator" in _type) : { _val = _val + (2000 * _amt) }; case ("Map" in _type) : { _val = _val + (20 * _amt) }; case ("Medikit" in _type) : { _val = _val + (400 * _amt) }; case ("MineDetector" in _type) : { _val = _val + (400 * _amt) }; case ("NVGoggles" in _type) : { _val = _val + (500 * _amt) }; case ("Radio" in _type) : { _val = _val + (100 * _amt) }; case ("Toolkit" in _type) : { _val = _val + (400 * _amt) }; case ("UAVTerminal" in _type) : { _val = _val + (800 * _amt) }; case ("Watch" in _type) : { _val = _val + (40 * _amt) }; case ("Glasses" in _type) : { _addVal = 20; if (_x in ["G_Tactical_Clear","G_Tactical_Black"]) then { _addVal = 200 }; _val = _val + (_addVal * _amt) }; case ("Headgear" in _type) : { _addVal = 10; _pT = _weapClass >> _x >> "ItemInfo" >> "passThrough"; if (isNumber _pT) then { _pT = getNumber _pT; _addVal = _addVal/((_pT max 0.25)^3) }; _val = _val + (_addVal * _amt) }; case ("Vest" in _type) : { _addVal = 90; _pT = _weapClass >> _x >> "ItemInfo" >> "passThrough"; if (isNumber _pT) then { _pT = getNumber _pT; _addVal = _addVal + 10/((_pT max 0.25)^3) }; _armor = _weapClass >> _x >> "ItemInfo" >> "armor"; if (isNumber _armor) then { _armor = getNumber _armor; _addVal = _addVal + (_armor * 40) }; _cap = _weapClass >> _x >> "ItemInfo" >> "containerClass"; if (isText _cap) then { _cap = getText _cap; _cap = _vehClass >> _cap >> "maximumLoad"; if (isNumber _cap) then { _cap = getNumber _cap; _addVal = _addVal + _cap }; }; _val = _val + ((_addVal/6) * _amt) }; case ("Uniform" in _type) : { _addVal = 110; _cap = _weapClass >> _x >> "ItemInfo" >> "containerClass"; if (isText _cap) then { _cap = getText _cap; _cap = _vehClass >> _cap >> "maximumLoad"; if (isNumber _cap) then { _cap = getNumber _cap; _addVal = _addVal + _cap }; }; _val = _val + (_addVal * _amt) }; case ("Backpack" in _type) : { _addVal = 140; _cap = _vehClass >> _x >> "maximumLoad"; if (isNumber _cap) then { _cap = getNumber _cap; _addVal = _addVal + (_cap * 2) }; _val = _val + (_addVal * _amt) }; default { _val = _val + (10 * _amt) } }; _name = "Various"; if (isText (_weapClass >> _x >> "DisplayName")) then { _name = getText (_weapClass >> _x >> "DisplayName"); } else { if (isText (_vehClass >> _x >> "DisplayName")) then { _name = getText (_vehClass >> _x >> "DisplayName"); } }; if (_name in [""]) then {_name = "Various"}; _desc = _desc + _fx + _name + "_" + (str (_otherA select _foreachIndex)); } foreach _other; if not (_holder in allDeadMen) then { clearItemCargo _holder; clearWeaponCargo _holder; clearMagazineCargo _holder; clearBackpackCargo _holder } else { removeHeadgear _holder; removeGoggles _holder; removeAllContainers _holder; removeAllWeapons _holder; removeAllAssignedItems _holder; }; if (_removeH) then { _posTaken = missionnameSpace getVariable ["PosTaken",[]]; _lootSpot = _holder getVariable ["RYD_JR_MyPlace",[0,0,0]]; { if (_lootSpot isEqualTo _x) exitWith {_posTaken set [_foreachIndex,0]} } foreach _posTaken; _posTaken = _posTaken - [0]; missionnameSpace setVariable ["PosTaken",_posTaken]; deleteVehicle _holder; }; RYD_JR_DM_Count = RYD_JR_DM_Count + 1; sleep 0.5; playSound "FD_CP_Clear_F"; sleep 0.02; //diag_log format ["ADMclient - auctioneer: Item '%1' on auction Gattamelata#%2_rapid. Waiting for bidders...",_desc,RYD_JR_DM_Count]; RYD_JR_Caller globalChat format ["ADMclient - auctioneer: Item '%1' on auction Gattamelata#%2_rapid. Waiting for bidders...",_desc,RYD_JR_DM_Count]; [_val,_desc] spawn { _val = _this select 0; _desc = _this select 1; _val = round (_val * (0.85 + (random 0.3))); _val = _val * RYD_JR_CargoValueM; _val = (ceil (_val/10)) * 10; sleep (5 + (random 55)); waitUntil { sleep 2; (((time - RYD_JR_LastComm) > 10) or {RYD_JR_Outro}) }; if (RYD_JR_Outro) exitWith {}; RYD_JR_LastComm = time; RYD_JR_FuelFund = RYD_JR_FuelFund + _val; RYD_JR_FuelFundGain = RYD_JR_FuelFundGain + _val; playSound "FD_CP_Clear_F"; sleep 0.02; RYD_JR_Caller globalChat format ["ADMclient - auctioneer: Item '%4' sold for %1 ff. Auction Gattamelata#%3_rapid closed. Your current account: %2 ff.",_val,RYD_JR_FuelFund,RYD_JR_DM_Count,_desc]; }; }; Thanks for that valuable input! I've managed to come up with my own automated categorisation and pricing, using a defined base price per category plus calculated values. It's still pretty rough but works more or less accurate for the packs I've tested (CUP, RH Packs, TRYK's uniforms, Niko's uniforms): params [ ["_shopConfig", "ShopWeapons", [""]], ["_class", "", [""]], "_category", "_price" ]; _category = [(missionConfigFile >> _shopConfig), _class] call IP_fnc_getConfigCategory; _price = switch (_shopConfig) do { case "ShopWeapons": { _res = if (_category != "") then { (getNumber(missionConfigFile >> _shopConfig >> _category >> _class >> "price")) } else { private "_index"; { _category = _x; if ({_x == _class} count _category > 0) exitWith { _index = _forEachIndex; }; } forEach IP_AvailableWeapons; if (isNil "_index") exitWith {0}; private "_add"; _category = IP_WeaponCategories select _index; _basePrice = getNumber(missionConfigFile >> _shopConfig >> _category >> "basePrice"); _magazines = getArray(configFile >> "CfgWeapons" >> _class >> "magazines"); _add = 0; if (_category != "Optics") then { private "_caliberHitPairs"; _caliberHitSets = []; { _ammo = getText(configFile >> "CfgMagazines" >> _x >> "ammo"); _count = getNumber(configFile >> "CfgMagazines" >> _x >> "count"); _caliber = getNumber(configFile >> "CfgAmmo" >> _ammo >> "caliber"); _hit = getNumber(configFile >> "CfgAmmo" >> _ammo >> "hit"); _hitIndirect = getNumber(configFile >> "CfgAmmo" >> _ammo >> "indirectHit"); _hitIndirectRange = getNumber(configFile >> "CfgAmmo" >> _ammo >> "indirectHitRange"); _set = [_count, _caliber, _hit, _hitIndirect, _hitIndirectRange]; if !(_set in _caliberHitSets) then { _caliberHitSets pushBack _set; _add = _add + (_count * _caliber) + (_hit * 10) + (_hitIndirect * _hitIndirectRange); }; } forEach _magazines; } else { if (isArray(configFile >> "CfgWeapons" >> _class >> "visionMode")) then { { if (_x == "NVG") then { _add = _add + 250; }; if (_x == "TI") then { _add = _add + 500; }; } forEach (getArray(configFile >> "CfgWeapons" >> _class >> "visionMode")); }; }; (_basePrice + _add) }; _res }; case "ShopMagazines": { _res = if (isNumber(missionConfigFile >> "ShopMagazines" >> _class >> "price")) then { (getNumber(missionConfigFile >> "ShopMagazines" >> _class >> "price")) } else { _ammo = getText(configFile >> "CfgMagazines" >> _class >> "ammo"); _basePrice = if (getNumber(configFile >> "CfgAmmo" >> _ammo >> "explosive") == 1) then {(getNumber(missionConfigFile >> "ShopMagazines" >> "basePriceExplosive"))} else {(getNumber(missionConfigFile >> "ShopMagazines" >> "basePrice"))}; _count = getNumber(configFile >> "CfgMagazines" >> _class >> "count"); _caliber = getNumber(configFile >> "CfgAmmo" >> _ammo >> "caliber"); _hit = getNumber(configFile >> "CfgAmmo" >> _ammo >> "hit"); _hitIndirect = getNumber(configFile >> "CfgAmmo" >> _ammo >> "indirectHit"); _hitIndirectRange = getNumber(configFile >> "CfgAmmo" >> _ammo >> "indirectHitRange"); (_basePrice + (_count * _caliber) + _hit + (_hitIndirect * _hitIndirectRange)) }; _res }; case "ShopItems": { _res = if (isNumber(missionConfigFile >> _shopConfig >> _category >> _class >> "price")) then { (getNumber(missionConfigFile >> _shopConfig >> _category >> _class >> "price")) } else { _cfg = missionConfigFile >> "ShopItems"; _typeArr = [_class] call BIS_fnc_itemType; _cat = _typeArr select 0; _type = _typeArr select 1; _res = switch (_cat) do { case "Item": { _res = switch (_type) do { case "AccessoryMuzzle": {(getNumber(_cfg >> "AttachmentsMuzzle" >> "basePrice"))}; case "AccessoryPointer": {(getNumber(_cfg >> "AttachmentsRail" >> "basePrice"))}; case "AccessorySights": { private "_add"; _add = 0; _basePrice = getNumber(_cfg >> "AttachmentsOptics" >> "basePrice"); _sightsCfg = (configFile >> "CfgWeapons" >> _class >> "ItemInfo" >> "OpticsModes"); if (isArray _sightsCfg) then { { _add = _add + (getNumber(_sightsCfg >> _x >> "distanceZoomMax")); { if (_x == "NVG") then { _add = _add + 250; }; if (_x == "TI") then { _add = _add + 500; }; } forEach (getArray(_sightsCfg >> _x >> "visionMode")); } forEach (getArray _sightsCfg); }; (_basePrice + _add) }; case "AccessoryBipod": {(getNumber(_cfg >> "AttachmentsUnderBarrel" >> "basePrice"))}; case "Compass": {(getNumber(_cfg >> "Misc" >> "ItemCompass" >> "price"))}; case "FirstAidKit": {(getNumber(_cfg >> "Misc" >> "FirstAidKit" >> "price"))}; case "GPS": {(getNumber(_cfg >> "Misc" >> "ItemGPS" >> "price"))}; case "Map": {(getNumber(_cfg >> "Misc" >> "ItemMap" >> "price"))}; case "Medikit": {(getNumber(_cfg >> "Misc" >> "Medikit" >> "price"))}; case "MineDetector": {(getNumber(_cfg >> "Misc" >> "MineDetector" >> "price"))}; case "NVGoggles": {(getNumber(_cfg >> "Misc" >> "NVGoggles" >> "price"))}; case "Radio": {(getNumber(_cfg >> "Misc" >> "ItemRadio" >> "price"))}; case "Toolkit": {(getNumber(_cfg >> "Misc" >> "Toolkit" >> "price"))}; case "UAVTerminal": {(getNumber(_cfg >> "Misc" >> "B_UavTerminal" >> "price"))}; case "Watch": {(getNumber(_cfg >> "Misc" >> "ItemWatch" >> "price"))}; default {0}; }; _res }; case "Equipment": { _res = switch (_type) do { case "Glasses": {(getNumber(_cfg >> "Goggles" >> "basePrice"))}; case "Headgear": { _armour = getNumber(configFile >> "CfgWeapons" >> _class >> "ItemInfo" >> "HitpointsProtectionInfo" >> "Head" >> "armor"); _pass = getNumber(configFile >> "CfgWeapons" >> _class >> "ItemInfo" >> "HitpointsProtectionInfo" >> "Head" >> "passThrough"); _res = if ((_armour == 0) OR (_pass == 1)) then { (getNumber(_cfg >> "HeadgearSoft" >> "basePrice")) } else { _basePrice = getNumber(_cfg >> "HeadgearCombat" >> "basePrice"); _add = if (_armour > 4) then { ((_armour - 4) * 250) } else { 0 }; (_basePrice + _add) }; _res }; case "Vest": { _bodyArmour = if (isNumber(configFile >> "CfgWeapons" >> _class >> "ItemInfo" >> "HitpointsProtectionInfo" >> "Body" >> "armor")) then { (getNumber(configFile >> "CfgWeapons" >> _class >> "ItemInfo" >> "HitpointsProtectionInfo" >> "Body" >> "armor")) } else { 1 }; _bodyPass = getNumber(configFile >> "CfgWeapons" >> _class >> "ItemInfo" >> "HitpointsProtectionInfo" >> "Body" >> "passThrough"); _capacity = getNumber(configFile >> "CfgVehicles" >> (getText(configFile >> "CfgWeapons" >> _class >> "ItemInfo" >> "containerClass")) >> "maximumLoad"); _capacityAdd = _capacity * 5; _res = if (((_bodyArmour == 0) OR (_bodyPass == 1)) && {_capacity <= 140}) then { _basePrice = getNumber(_cfg >> "VestsLight" >> "basePrice"); (_basePrice + _capacityAdd) } else { private "_cumulated"; _cumulated = 0; _hitParts = "isNumber(_x >> 'armor')" configClasses (configFile >> "CfgWeapons" >> _class >> "ItemInfo" >> "HitpointsProtectionInfo"); { _cumulated = _cumulated + (getNumber(_x >> "armor")); } forEach _hitParts; _cumulatedAdd = _cumulated * 5; _res = if (_cumulated < 80) then { _basePrice = getNumber(_cfg >> "VestsMedium" >> "basePrice"); (_basePrice + _capacityAdd + _cumulatedAdd) } else { _basePrice = getNumber(_cfg >> "VestsHeavy" >> "basePrice"); (_basePrice + _capacityAdd + _cumulatedAdd) }; _res }; _res }; case "Backpack": { _capacity = getNumber(configFile >> "CfgVehicles" >> _class >> "maximumLoad"); _res = if ((isText(configFile >> "CfgVehicles" >> _class >> "backpackSimulation")) && {(getText(configFile >> "CfgVehicles" >> _class >> "backpackSimulation")) == "ParachuteSteerable"}) then { (getNumber(_cfg >> "BackpacksParachutes" >> "basePrice")) } else { _res = if (_capacity <= 0) then { (getNumber(_cfg >> "BackpacksStatics" >> "basePrice")) } else { _basePrice = getNumber(_cfg >> "Backpacks" >> "basePrice"); _capacityAdd = _capacity * 5; (_basePrice + _capacityAdd) }; _res }; _res }; default {0}; }; _res }; default {0}; }; _res }; _res }; case "ShopUniforms": { _res = if (_category != "") then { (getNumber(missionConfigFile >> _shopConfig >> _category >> _class >> "price")) } else { _basePrice = getNumber(missionConfigFile >> _shopConfig >> "basePrice"); _capacity = getNumber(configFile >> "CfgVehicles" >> (getText(configFile >> "CfgWeapons" >> _class >> "ItemInfo" >> "containerClass")) >> "maximumLoad"); _capacityAdd = _capacity * 5; (_basePrice + _capacityAdd) }; _res }; default {0}; }; _price Automatically indexed content seamlessly integrates with manually listed items which in return override the alrogrithmic pricing. Prices for weapons and ammo seem more or less accurate considering that a manually listed 5.56mm assault rifle like the TRG-21 comes at 3.500€ with 1€ per 5.56mm bullet (respectively 30 per magazine), whereas an automatically indexed G36 from CUP comes at ~3.400€ with 29€ per magazine. Even the as rifle misconfigured six-round grenade launcher from CUP is priced with more than 6.000€ due to its large caliber explosive ammo. I'm still having trouble to price protective gear as the new DevBranch armour system seems to function a bit differently. (You'd have to update your algorithm as well when Nexus hits stable as the config structure with regards to protection values changed.) And the zoom levels of weapon optics seem to be overriden by CBA, I can't access the ItemInfo sub-class when it's running, so they stay at base price. Anyway, that's small stuff. 1 Share this post Link to post Share on other sites
Rydygier 1309 Posted November 3, 2015 You'd have to update your algorithm as well when Nexus hits stable as the config structure with regards to protection values changed. Thanks for the tip. One must always be vigilant because of continual game development... Share this post Link to post Share on other sites
rell 13 Posted November 8, 2015 - Ah and please share your favorite screenshots or videos (in spoiler tags or PM). Thanks! Hello. I want to share the results of their games, and to say a few ideas for the gameplay. It all started so .. T-shirt and trousers. Even maps of the area were not. Now, I finally bought a good weapon. And I can even arrange an ambush and something explode. B) Imagine how much easier with such weapons, earn in the game. Personally, my opinion, a good weapon, and especially ammunition and other supplies must "be ten times" more expensive. Maybe I'm wrong because it's only an alpha version of ... In the release version, I'll probably spend thousands on first aid kit. :) The second sentence of artifacts. If you add them, it is likely they will be located in the anomalies. I propose to make an artifact. Which will spawn in the anomaly "Chem" (for example). But this artifact will neutralize explosions anomaly "Blaster". Just let it be a "big secret." ) Good luck to you in development. It would be cool, performing some task, meet a group of people ... I dream about the multiplayer in this mission. sorry for my english... Share this post Link to post Share on other sites
IndeedPete 1038 Posted November 8, 2015 Lovely, judging by the videos and replies to this thread CZ seems to be quite popular with the Russian-speaking part of the Arma community. :) Thanks for the screenshots and the video! If I get all of your points, you vote for a raise of shop prices and real artifacts, right? The balancing and the prices are not fixed yet, so expect some changes in this area. That artifact thing, I don't know yet. It's a good idea, I've already thought of positive anomalies granting temporary buffs to players. We'll see.^^ Share this post Link to post Share on other sites
IndeedPete 1038 Posted November 8, 2015 In other news I've just yesterday finished a working version of the parameters dialog, allowing SP'ers to set the same parameters as MP'ers can do in the lobby of an MP game. Not all of them are having actual functionality yet, but it's a start. The most important changes are the possibility to skip the intro mission, the mission start and daytime options, and the selection of start loadout as Naked (hardcore mode!), Freezoner (as it is now, no weapons), or Mercenary (random gear from the shop for more action). As you can see, there's room for more options. I'm all open for suggestions. And since it seems to be best practice (as we know from Pilgrimage and WLA), I've added small cutscenes showing various places of the Zone in the background during the parameter selection. A few scripts were also tweaked to have less impact on performance. I'm still looking for an effective random loot script suite. Next on my list aside from playable content is AI caching and dedicated servers. Anyone knows good scripts out of the box for that? The changes are currently at Surfer's for testing who added even more splendid places to the map. I'm certain we can release an update in the near future. 5 Share this post Link to post Share on other sites
giorgygr 61 Posted November 9, 2015 @Next on my list aside from playable content is AI caching and dedicated servers. Anyone knows good scripts out of the box for that? I haven't compared more solutions ..but if ZBE caching working on HETMAN..it works for anything imHo :D Share this post Link to post Share on other sites
IndeedPete 1038 Posted November 9, 2015 @Next on my list aside from playable content is AI caching and dedicated servers. Anyone knows good scripts out of the box for that? I haven't compared more solutions ..but if ZBE caching working on HETMAN..it works for anything imHo :D Thanks, I'll look into that. 1 Share this post Link to post Share on other sites
rell 13 Posted November 15, 2015 Hello. Another screenshot. Blowouts. And I found another bug. Bug on a mission "Mechanic In Need"He refused to take the tools. After that, I decided to check out the job "Doctor In Need",Medikit bought and brought to the doctor. This has led to some interesting consequences. Video sorry for my english... 1 Share this post Link to post Share on other sites
IndeedPete 1038 Posted November 15, 2015 Huh, funny. I fixed that bug like three times already. Nasty one. Thanks again for your report! Share this post Link to post Share on other sites
surfer 42 Posted November 26, 2015 Dear Friend, I'm sending you this selfie of me in front of the Unforgiving Church Of The Apocalypse, here on Altis or "Contention Zone" as the locals call it. Unfortunately the camera focused on the background and I didn't have the time to do another image. Had to run from a pack of mutated freaks, haha =) Groud Zero, where one of the nukes hit is even more impressive than it looks on the sat images. My little excursion is nearly over but it was definitely worth it. I tell you all the stories once I'm back. Cheers, S. 4 Share this post Link to post Share on other sites
inlesco 233 Posted November 29, 2015 Great work, guys! Ever thought of porting STALKER models over or using other mods that have them ported already? This 'd make the mission even more impressive! 1 Share this post Link to post Share on other sites
IndeedPete 1038 Posted November 29, 2015 This would also require it to be an addon or at least have addon requirements. I would love to create zone-specific gear, maybe even using free third party models. But as it is, this would increase the file size and it wouldn't run on vanilla anymore. Share this post Link to post Share on other sites
surfer 42 Posted November 30, 2015 Sorry for teasing this to you. We decided to keep it vanilla right from the beginning to have it as accessible as possible. Some day in the future BIS will give us gas masks and haz suits and this will probably be the same day we have all the features inside that we wished for. Share this post Link to post Share on other sites
IndeedPete 1038 Posted December 6, 2015 Small status update. Aside from even more splendid locations and a few story quests, we have finished the param dialog functionality. In SP, you will be able to save and load a preset of your favourite parameter settings for the zone using your profile namespace. Then we think we have nailed down one of the major performance issues. It turns out that spamming setDate every X seconds to keep the time at level causes heavy stuttering after some time. Replacing it with a skipTime -X seems to cause no issues so far. Then the shop got a small update, and icons in quest actions were added. But the biggest improvement is that we were able to fully complete the story quests on a dedicated server. It took a lot of work and hairpulling but there we go, the Zone seems to run comparably stable on dedis. As usual, there are still minor issues. We should really update the Alpha soon, probably in the next few days. Keep in mind that it still won't be complete, it's rather to see if the performance improved and some bugs are gone for you. Until then, a few screenshots from one of the new quests: And some random Zoner on his travels: 7 Share this post Link to post Share on other sites
IndeedPete 1038 Posted December 16, 2015 Update time! As promised, version 0.51 found its way onto Dropbox, introducing a ton of fixes and features and a bit more (generic) content. Aside from splendid new map locations, the most remarkable additions are (hopefully) full dedicated server support (tested on local dedi), a major performance fix, a lot of new parameters for both SP and MP leaving room for a completely individual experience, automated indexing of mod content for the shop system (might take up to a few minutes on mission start if you run a lot of mods), a new lightweight and dynamic loot framework, much more dangerous zombies, and optional random enemy patrols. Version: 0.51 ALPHA Actively Supported Mods (All Mods Are Completely OPTIONAL)The following mods are officially supported by the shop system, use is completely optional. Do not start an MP session where clients run different weapon pack mods than the server. Any mod use at your own risk. Toadie's SmallArms and Animations for Arma3 EUROFORCE by IndeedPete CSAT Snow Tigers by IndeedPete Black Star Movement by IndeedPete SP Campaign Ice by IndeedPete Hidden Identity Pack V.2 by Cunico How to InstallCopy the "CONTENTION_ZONE.Altis.pbo" to your Arma 3 Missions and/or MPMissions dir ("...\steam\steamApps\common\Arma 3\Missions").Changelog 0.51 Alpha - 16.12.2015 FIXED: Improved dedicated server support. FIXED: Major performance killer caused by spamming setDate. FIXED: Detecting ZOMBIE anomalies caused the generation of unexpected map markers. FIXED: Generic FIND mission task would show the wrong grid location. FIXED: Mistakes and errors in various dialogues. CHANGED: Improved shop system. CHANGED: Implemented new, custom loot framework. CHANGED: Improved zombie script framework. CHANGED: Tweaked UI feedback for main missions. ADDED: New parameters for SP and MP. ADDED: Parameterised random infantry, ground vehicle, and air vehicle patrols. ADDED: Parameters dialog for SP. ADDED: Two new main missions. ADDED: Two new generic SECURE and ELIMINATE missions. ADDED: Whitelisted gas masks from Hidden Identity Pack V.2 for the shop and hazard systems. ADDED: Automated indexing of items for the shop system. ADDED: New map locations. ADDED: New custom music tracks. LicenseContent created by IndeedPete and Surfer is published under the "Arma Public License Share Alike (APL-SA)". You are free to take or change anything you can use, just give us a mention in the credits.Release Dropbox v0.51 ALPHACredits & Thanks Bohemia Interactive Studios for this great game! MrCrazyDude115 for his splendid voice acting! Shuko for his SHKPos script! And all the great people on the BI-Forums who helped out with answers and feedback to so many questions! Enjoy, and don't forget to report bugs and feedback us with your experiences! :) 5 Share this post Link to post Share on other sites
Not_Oliver 16 Posted December 17, 2015 Yo, haven't tested it yet (not home), but what save functionality does it have right now on a dedi? Share this post Link to post Share on other sites
IndeedPete 1038 Posted December 17, 2015 None so far, if I got you corretly. Saving might be enabled but it hasn't been tested on a dedi. Also, JIP is not supported (yet), it might be in a future state. For now, it is intended for small groups to play it in one take. Share this post Link to post Share on other sites
rell 13 Posted December 27, 2015 Hello.Missing the sound of rain in the mission. The sound does not exist in any "CONTENTION ZONE Version: 0.51", Version: 0.5. Perhaps the problem is due to the recent upgrade of the game ... In other modes (at the end of the video clip) there is the sound of rainVideo:. sorry for my english... Share this post Link to post Share on other sites
IndeedPete 1038 Posted December 27, 2015 Hey, thanks for your comment. We are aware of the missing sounds. That is due to the environment (butterflies, cricket noises, etc.) being disabled as it does not really fit the overall atmosphere. Unfortunately, this disables the rain and wind sounds as well, hence we play our own ones which you can also hear in your video. Share this post Link to post Share on other sites
rell 13 Posted December 28, 2015 Hey, thanks for your comment. We are aware of the missing sounds. That is due to the environment (butterflies, cricket noises, etc.) being disabled as it does not really fit the overall atmosphere. Unfortunately, this disables the rain and wind sounds as well, hence we play our own ones which you can also hear in your video. It's a pity... Previously, another sound was ... IMHO It was better. https://youtu.be/Rcs9k4YqjB4?t=1m16s Share this post Link to post Share on other sites
IndeedPete 1038 Posted December 28, 2015 Yes, but if you allow the environment to be on, you will not only get the good rain sounds but also butterflies, crickets, etc. Sadly, BI did not separate the environmental sounds (wind, rain) from the animal sounds. I believe there is a ticket on the FT already but I don't expect them to change that anytime soon. Share this post Link to post Share on other sites
froggyluv 2136 Posted January 11, 2016 This mission looks great but everytime I start its just pitch black...I read something about a 'Blowout' but I opted out of that and am not hearing any noises or anything at all. No mods either. Edit: NM it started in MP Share this post Link to post Share on other sites