speedweasel

Improved loot spawner for v1.0.3

28 posts in this topic

Improved loot spawner for Exile v1.0.3.  Makes the size of loot spawns less predictable and occasionally spawns a large crate full of gear.  Fully configurable.

Instructions:

1. Overwrite the CfgExileLootSettings class in your mission config.cpp file with the code below.  Just overwrite the class - including the class name and the opening and closing braces {} - Do not overwrite the whole config.cpp file.  

class CfgExileLootSettings
{
	/**
	 * Lifetime of loot in minutes. Synchronize this with
	 * the garbage collector settings of your server
	 * CfgSettings!
	 */
	lifeTime = 30;

	/**
	 * Interval in seconds when the client searches for
	 * new buildings to spawn loot in
	 */
	spawnInterval = 12;

	/**
	 * This is a percentage value to determine how many loot
	 * positions should contain loot when the system spawns loot.
	 *
	 * If a building has 20 positions defined, Exile will 
	 * spawn loot in 10 random positions of them.
	 * 
	 * This means smaller buildings spawn less loot and larger
	 * ones spawn more loot.
	 *
	 * You can also cap it at a maximum value. See below.
	 */
	maximumPositionCoverage = 30;

 	/**
 	 * Limit the number of loot positions per building. If the 
 	 * above percentage value exceeds this value, it will be capped.
 	 *
 	 * Example: Coverage is 50%. Building has 60 loot positions defined.
 	 * This results in 30 loot positions and that is too much. So we
 	 * cap this at 10
 	 */
	maximumNumberOfLootSpotsPerBuilding = 3;

	/**
	 * Exile spawns a random number of items per loot spot. This 
	 * is the upper cap for that. So 3 means it will never spawn more than 3 items in one spot.
	 */
	maximumNumberOfItemsPerLootSpot = 7;
	
	/**
	 * This is the mid range for the number of loot items per spot. Exile is most likely to spawn this number of items. https://community.bistudio.com/wiki/random
	 */
	midNumberOfItemsPerLootSpot = 3;
	
	/**
	 * This is the minimum number of loot items per spot.
	 */
	minimumNumberOfItemsPerLootSpot = 1;
	
	/**
	 * This is the chance (as a percentage) of spawning a crate full of items.
	 */
	percentageChanceToSpawnCrate = 1; // 2 = 2% chance to spawn a crate.  Keep it low.
	
	/**
	 * The number of items to spawn in a crate.
	 */
	numberOfItemsPerCrate = 50;
		

	/**
	 * Radius in meter to spawn loot AROUND each player.
	 * Do NOT touch this value if you dont know what you do.
	 * The higher the number, the higher the drop rates, the
	 * easier your server will lag.
	 *
	 * 50m  = Minimum
	 * 200m = Maximum
	 */
	spawnRadius = 60;

	/**
	 * Defines the radius around trader cities where the system should
	 * not spawn loot. Set this to 0 if you want to have loot spawning
	 * in trader citites, ugh.
	 */
	minimumDistanceToTraderZones = 500;

	/**
	 * Defines the radius around territories where no loot spawns.
	 * This does not regard the actual size of a territory. So do not
	 * set this to a lower value than the maximum radius of a territory,
	 * which is 150m by default.
	 */
	minimumDistanceToTerritories = 150;
};

2. Tune the settings in CfgExileLootSettings to your liking.

3. Overwrite the ExileServer_system_lootManager_spawnLootInBuilding function with the code below, using the regular Exile CustomCode overwrite method.

/**
 * ExileServer_system_lootManager_spawnLootInBuilding
 *
 * Exile Mod
 * www.exilemod.com
 * © 2015 Exile Mod Team
 *
 * This work is licensed under the Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License. 
 * To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-nd/4.0/.
 */
 
private["_numberOfItemsPerCrate","_percentageChanceToSpawnCrate","_midNumberOfItemsPerLootSpot","_minimumNumberOfItemsPerLootSpot","_crate","_building", "_buildingConfig", "_lootTableName", "_localPositions", "_lootConfig", "_maximumNumberOfLootPositions", "_maximumPositionCoverage", "_maximumNumberOfItemsPerLootSpot", "_numberOfPositionsToUse", "_lootPositions", "_spawnedItemClassNames", "_lootWeaponHolderNetIDs", "_lootPosition", "_lootHolder", "_numberOfItemsToSpawn", "_n", "_itemClassName", "_cargoType", "_magazineClassNames", "_magazineClassName", "_numberOfMagazines"];
_building = _this;
_building setVariable ["ExileLootSpawnedAt", time];
_building setVariable ["ExileHasLoot", true];
_buildingConfig = configFile >> "CfgBuildings" >> typeOf _building;
_lootTableName = getText (_buildingConfig >> "table");
_localPositions = getArray (_buildingConfig >> "positions");
if ((getPosATL _building) call ExileClient_util_world_isInRadiatedZone) then 
{
	_lootTableName = "Radiation";
};
_lootConfig = missionConfigFile >> "CfgExileLootSettings";
_maximumNumberOfLootPositions = getNumber (_lootConfig >> "maximumNumberOfLootSpotsPerBuilding");
_maximumPositionCoverage = getNumber (_lootConfig >> "maximumPositionCoverage");
_maximumNumberOfItemsPerLootSpot = getNumber (_lootConfig >> "maximumNumberOfItemsPerLootSpot");
_minimumNumberOfItemsPerLootSpot = getNumber (_lootConfig >> "minimumNumberOfItemsPerLootSpot");
_midNumberOfItemsPerLootSpot = getNumber (_lootConfig >> "midNumberOfItemsPerLootSpot");
_numberOfPositionsToUse = 1 max (((count _localPositions) * _maximumPositionCoverage / 100) min _maximumNumberOfLootPositions);
_localPositions = _localPositions call ExileClient_util_array_shuffle;
_lootPositions = _localPositions select [0, _numberOfPositionsToUse];
_spawnedItemClassNames = [];
_lootWeaponHolderNetIDs = [];
_percentageChanceToSpawnCrate = getNumber (_lootConfig >> "percentageChanceToSpawnCrate");
_numberOfItemsPerCrate = getNumber (_lootConfig >> "numberOfItemsPerCrate");

{
	_lootPosition = ASLToATL (AGLToASL (_building modelToWorld _x));
	if (_lootPosition select 2 < 0.05) then
	{
		_lootPosition set [2, 0.05];
	};
	_lootHolder = objNull;
	_numberOfItemsToSpawn = round random [_minimumNumberOfItemsPerLootSpot,_midNumberOfItemsPerLootSpot,_maximumNumberOfItemsPerLootSpot]; // [min,mid,max]
	if (random 100 <= _percentageChanceToSpawnCrate) then {_numberOfItemsToSpawn = _numberOfItemsPerCrate}; // occasionally have a big loot cache
	for "_n" from 1 to _numberOfItemsToSpawn do
	{
		_itemClassName = _lootTableName call ExileServer_system_lootManager_dropItem;
		if !(_itemClassName in _spawnedItemClassNames) then
		{
			if (isNull _lootHolder) then 
			{
				if (_numberOfItemsToSpawn == _numberOfItemsPerCrate) then  //if you have a big loot cache, put it in a random crate
				{
					_crate = selectRandom [	
					"Box_IND_Ammo_F",
					"Box_T_East_Ammo_F",
					"Box_East_Ammo_F",
					"Box_NATO_Ammo_F",
					"Box_Syndicate_Ammo_F",
					"Box_IND_Wps_F",
					"Box_T_East_Wps_F",
					"Box_East_Wps_F",
					"Box_T_NATO_Wps_F",
					"Box_Syndicate_Wps_F",
					"Box_Syndicate_WpsLaunch_F",
					"Box_IND_WpsSpecial_F",
					"Box_East_WpsSpecial_F",
					"Box_T_NATO_WpsSpecial_F",
					"Box_NATO_WpsSpecial_F",
					"Box_IND_Support_F",
					"Box_East_Support_F",
					"Box_NATO_Support_F"];
					_lootHolder = createVehicle [_crate, _lootPosition, [], 0, "CAN_COLLIDE"];
					clearWeaponCargoGlobal _lootHolder; // empty crate
					clearMagazineCargoGlobal _lootHolder; // empty crate
					clearItemCargoGlobal _lootHolder; // empty crate
					clearBackpackCargoGlobal _lootHolder; // empty crate
				}
				else
				{
					_lootHolder = createVehicle ["LootWeaponHolder", _lootPosition, [], 0, "CAN_COLLIDE"];
				};
			_lootHolder setDir (random 360);
			_lootHolder setPosATL _lootPosition;
			_lootHolder setVariable ["ExileSpawnedAt", time];
			_lootWeaponHolderNetIDs pushBack (netId _lootHolder);
			};
			_cargoType = _itemClassName call ExileClient_util_cargo_getType;
			switch (_cargoType) do
			{
				case 1: 	
				{ 
					if (_itemClassName isEqualTo "Exile_Item_MountainDupe") then
					{
						_lootHolder addMagazineCargoGlobal [_itemClassName, 2]; 
					}
					else 
					{
						_lootHolder addMagazineCargoGlobal [_itemClassName, 1]; 
					};
				};
				case 3: 	
				{ 
					_lootHolder addBackpackCargoGlobal [_itemClassName, 1]; 
				};
				case 2: 	
				{ 
					_lootHolder addWeaponCargoGlobal [_itemClassName, 1]; 
					if !(_itemClassName isKindOf ["Exile_Melee_Abstract", configFile >> "CfgWeapons"]) then
					{
						_magazineClassNames = getArray(configFile >> "CfgWeapons" >> _itemClassName >> "magazines");
						if (count(_magazineClassNames) > 0) then
						{
							_magazineClassName = selectRandom _magazineClassNames;
							_numberOfMagazines = 2 + floor(random 3); 
							_lootHolder addMagazineCargoGlobal [_magazineClassName, _numberOfMagazines];
							_spawnedItemClassNames pushBack _magazineClassName;
						};
					};
					_numberOfItemsToSpawn = -1;
				};
				default
				{ 
					_lootHolder addItemCargoGlobal [_itemClassName, 1]; 
				};
			};
			_spawnedItemClassNames pushBack _itemClassName;
		};
	};
}
forEach _lootPositions;
_building setVariable ["ExileLootWeaponHolderNetIDs", _lootWeaponHolderNetIDs];
ExileServerBuildingNetIdsWithLoot pushBack (netId _building);

Enjoy!

  • Like 7

Share this post


Link to post
Share on other sites

Hey this is really cool. Tested it out and it works well. It can be annoying when a box spawns in front of a door, so just make sure to add the crate to R3F so players can move or load them. Thanks a bunch man! :]

Share this post


Link to post
Share on other sites
Advertisement
5 hours ago, gfourth said:

Very cool! Can the loot crate chance be set to a decimal like 0.1? To make it REALLY rare...

Sure.  Any number between 0 and 100 should work.  Be aware that 0.1 would mean an average of 1 crate in 1000 loot spawns.  That's pretty rare.  Many players will never find a crate.

  • Like 1

Share this post


Link to post
Share on other sites

I did exactly as described above, and got this

ErrorMessage: File mpmissions\__cur_mp.Altis\config.cpp, line 3155: Config: /CfgExileCustomCode.private: '"' encountered instead of ']'

 

Share this post


Link to post
Share on other sites
3 hours ago, Darksoul47 said:

I did exactly as described above, and got this


ErrorMessage: File mpmissions\__cur_mp.Altis\config.cpp, line 3155: Config: /CfgExileCustomCode.private: '"' encountered instead of ']'

 

just as the error says, somewhere around line 3155 in the config.cpp file in your mpmission folder, it encountered " instead of ]. simple typo fix. since you didnt post the line in that file i cant tell you exactly what the error is, so youll have to go off of what the error says.

Share this post


Link to post
Share on other sites
23 minutes ago, JayPaypers said:

just as the error says, somewhere around line 3155 in the config.cpp file in your mpmission folder, it encountered " instead of ]. simple typo fix. since you didnt post the line in that file i cant tell you exactly what the error is, so youll have to go off of what the error says.

Here is line 3150 to 3160

	class Exile_Car_Van_Guerilla06 						{ quality = 2; price = 12000; };
	class Exile_Car_Van_Guerilla07 						{ quality = 2; price = 12000; };
	class Exile_Car_Van_Guerilla08 						{ quality = 2; price = 12000; };

	///////////////////////////////////////////////////////////////////////////////
	// Van (Box)
	///////////////////////////////////////////////////////////////////////////////
	class Exile_Car_Van_Box_Black 						{ quality = 3; price = 17000; };
	class Exile_Car_Van_Box_White 						{ quality = 3; price = 17000; };
	class Exile_Car_Van_Box_Red 						{ quality = 3; price = 17000; };
	class Exile_Car_Van_Box_Guerilla01 					{ quality = 3; price = 17000; };

After commenting out the loot spawner code I used from here, it resolved the issue, but the code starts at line 3238 to 3369, inside ExileCustomCode

/*
	private["_numberOfItemsPerCrate","_percentageChanceToSpawnCrate","_midNumberOfItemsPerLootSpot","_minimumNumberOfItemsPerLootSpot","_crate","_building", "_buildingConfig", "_lootTableName", "_localPositions", "_lootConfig", "_maximumNumberOfLootPositions", "_maximumPositionCoverage", "_maximumNumberOfItemsPerLootSpot", "_numberOfPositionsToUse", "_lootPositions", "_spawnedItemClassNames", "_lootWeaponHolderNetIDs", "_lootPosition", "_lootHolder", "_numberOfItemsToSpawn", "_n", "_itemClassName", "_cargoType", "_magazineClassNames", "_magazineClassName", "_numberOfMagazines"];
	_building = _this;
	_building setVariable ["ExileLootSpawnedAt", time];
	_building setVariable ["ExileHasLoot", true];
	_buildingConfig = configFile >> "CfgBuildings" >> typeOf _building;
	_lootTableName = getText (_buildingConfig >> "table");
	_localPositions = getArray (_buildingConfig >> "positions");
	if ((getPosATL _building) call ExileClient_util_world_isInRadiatedZone) then 
	{
		_lootTableName = "Radiation";
	};
	_lootConfig = missionConfigFile >> "CfgExileLootSettings";
	_maximumNumberOfLootPositions = getNumber (_lootConfig >> "maximumNumberOfLootSpotsPerBuilding");
	_maximumPositionCoverage = getNumber (_lootConfig >> "maximumPositionCoverage");
	_maximumNumberOfItemsPerLootSpot = getNumber (_lootConfig >> "maximumNumberOfItemsPerLootSpot");
	_minimumNumberOfItemsPerLootSpot = getNumber (_lootConfig >> "minimumNumberOfItemsPerLootSpot");
	_midNumberOfItemsPerLootSpot = getNumber (_lootConfig >> "midNumberOfItemsPerLootSpot");
	_numberOfPositionsToUse = 1 max (((count _localPositions) * _maximumPositionCoverage / 100) min _maximumNumberOfLootPositions);
	_localPositions = _localPositions call ExileClient_util_array_shuffle;
	_lootPositions = _localPositions select [0, _numberOfPositionsToUse];
	_spawnedItemClassNames = [];
	_lootWeaponHolderNetIDs = [];
	_percentageChanceToSpawnCrate = getNumber (_lootConfig >> "percentageChanceToSpawnCrate");
	_numberOfItemsPerCrate = getNumber (_lootConfig >> "numberOfItemsPerCrate");

	{
		_lootPosition = ASLToATL (AGLToASL (_building modelToWorld _x));
		if (_lootPosition select 2 < 0.05) then
		{
			_lootPosition set [2, 0.05];
		};
		_lootHolder = objNull;
		_numberOfItemsToSpawn = round random [_minimumNumberOfItemsPerLootSpot,_midNumberOfItemsPerLootSpot,_maximumNumberOfItemsPerLootSpot]; // [min,mid,max]
		if (random 30 <= _percentageChanceToSpawnCrate) then {_numberOfItemsToSpawn = _numberOfItemsPerCrate}; // occasionally have a big loot cache
		for "_n" from 1 to _numberOfItemsToSpawn do
		{
			_itemClassName = _lootTableName call ExileServer_system_lootManager_dropItem;
			if !(_itemClassName in _spawnedItemClassNames) then
			{
				if (isNull _lootHolder) then 
				{
					if (_numberOfItemsToSpawn == _numberOfItemsPerCrate) then  //if you have a big loot cache, put it in a random crate
					{
						_crate = selectRandom [	
						"Box_IND_Ammo_F",
						"Box_T_East_Ammo_F",
						"Box_East_Ammo_F",
						"Box_NATO_Ammo_F",
						"Box_Syndicate_Ammo_F",
						"Box_IND_Wps_F",
						"Box_T_East_Wps_F",
						"Box_East_Wps_F",
						"Box_T_NATO_Wps_F",
						"Box_Syndicate_Wps_F",
						"Box_Syndicate_WpsLaunch_F",
						"Box_IND_WpsSpecial_F",
						"Box_East_WpsSpecial_F",
						"Box_T_NATO_WpsSpecial_F",
						"Box_NATO_WpsSpecial_F",
						"Box_IND_Support_F",
						"Box_East_Support_F",
						"Box_NATO_Support_F"];
						_lootHolder = createVehicle [_crate, _lootPosition, [], 0, "CAN_COLLIDE"];
						clearWeaponCargoGlobal _lootHolder; // empty crate
						clearMagazineCargoGlobal _lootHolder; // empty crate
						clearItemCargoGlobal _lootHolder; // empty crate
						clearBackpackCargoGlobal _lootHolder; // empty crate
					}
					else
					{
						_lootHolder = createVehicle ["LootWeaponHolder", _lootPosition, [], 0, "CAN_COLLIDE"];
					};
				_lootHolder setDir (random 360);
				_lootHolder setPosATL _lootPosition;
				_lootHolder setVariable ["ExileSpawnedAt", time];
				_lootWeaponHolderNetIDs pushBack (netId _lootHolder);
				};
				_cargoType = _itemClassName call ExileClient_util_cargo_getType;
				switch (_cargoType) do
				{
					case 1: 	
					{ 
						if (_itemClassName isEqualTo "Exile_Item_MountainDupe") then
						{
							_lootHolder addMagazineCargoGlobal [_itemClassName, 2]; 
						}
						else 
						{
							_lootHolder addMagazineCargoGlobal [_itemClassName, 1]; 
						};
					};
					case 3: 	
					{ 
						_lootHolder addBackpackCargoGlobal [_itemClassName, 1]; 
					};
					case 2: 	
					{ 
						_lootHolder addWeaponCargoGlobal [_itemClassName, 1]; 
						if !(_itemClassName isKindOf ["Exile_Melee_Abstract", configFile >> "CfgWeapons"]) then
						{
							_magazineClassNames = getArray(configFile >> "CfgWeapons" >> _itemClassName >> "magazines");
							if (count(_magazineClassNames) > 0) then
							{
								_magazineClassName = selectRandom _magazineClassNames;
								_numberOfMagazines = 2 + floor(random 3); 
								_lootHolder addMagazineCargoGlobal [_magazineClassName, _numberOfMagazines];
								_spawnedItemClassNames pushBack _magazineClassName;
							};
						};
						_numberOfItemsToSpawn = -1;
					};
					default
					{ 
						_lootHolder addItemCargoGlobal [_itemClassName, 1]; 
					};
				};
				_spawnedItemClassNames pushBack _itemClassName;
			};
		};
	}
	forEach _lootPositions;
	_building setVariable ["ExileLootWeaponHolderNetIDs", _lootWeaponHolderNetIDs];
	ExileServerBuildingNetIdsWithLoot pushBack (netId _building);
	*/

somewhere in this code is the typo. Appreciate any help.

Edited by Darksoul47

Share this post


Link to post
Share on other sites
Advertisement

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.