DMS_Exile/@ExileServer/addons/a3_dms/scripts/fn_FindSafePos.sqf
eraser1 78aa0f8667 Say bye-bye to the pre-packed PBO ;)
#### November 14, 2015 (8:30 PM CST-America):
* **NEW CONFIG VALUES:**

DMS_AllowStaticReinforcements
DMS_MarkerText_ShowAICount_Static
DMS_PredefinedMissionLocations_WEIGHTED
DMS_AIKill_DistanceBonusMinDistance
DMS_AIKill_DistanceBonusCoefficient
* You can now manually disable Static Mission AI reinforcements using
"DMS_AllowStaticReinforcements"
* You can now choose whether or not to show AI count for map markers for
both Static and Dynamic missions separately.
* DMS will now check to see if the config.sqf didn't load properly, and
for the presence of RyanZombies.
* You can now make predefined locations weighted.
* Some optimization + code clarity.
* Added ```taviana_config.sqf``` (identical to ```tavi_config.sqf```)
for the latest version of Taviana.
* **saltflats mission**:
* The AI will now initially spawn randomly across the compound. This
should help with the issue of some AI spawning outside of the compound.
* Added more static guns: 4 around the flagpole (5 meters north, south,
east, and west). One on top of the tower in each corner, and another on
the top of the concrete water tower.
* When an AI group is offloaded to a client and he gets out of range AND
no other viable client is found, the AI locality should now revert to
the server (it used to just stay with the original client).
* Added extra measures to prevent the creation of 2 markers with the
same name.
* fn_FillCrate.sqf:
* Fixed the issue where DMS would complain about incorrect parameters
when using custom code to generate loot.
* DMS now has debug logging to tell you exactly what it spawns in the
crate when using a crate case or custom code.
* "DMS_PredefinedMissionLocations" itself will now be shuffled when
finding a position. This should make the generated positions even more
random.
* Added new Group Reinforcement Types: "armed_vehicle_replace" and
"static_gunner"
* Potentially resolved the issue with launchers not being deleted from
AI bodies when they're killed sometimes.
* **fn_PlayerAwardOnAIKill.sqf**: Created a separate function to handle
poptabs/respect of a player when he/she kills an AI.
* Added a "distance bonus" for respect when killing AI.
* Added logging for player rewards on AI kills.
* DMS now lets Exile's body cleanup handle dead AIs.
* Fixed the issue where DMS would spawn static missions even when
"DMS_StaticMission" is set to false.
* fn_SetAILocality.sqf now returns true/false if it does/doesn't find an
owner.
* New function "fn_SpawnAIGroup_MultiPos.sqf". Almost identical to
SpawnAIGroup, except it spawns each AI along a list of locations.
* **Removed the pre-packed PBO. Too many people were having issues with
their PBO tool removing the prefix and repacking it would result in DMS
not working.**
2015-11-14 20:08:41 -06:00

107 lines
4.4 KiB
Plaintext

/*
DMS_fnc_FindSafePos
Created by eraser1
ALL PARAMETERS ARE OPTIONAL (as long as configs are properly defined).
Excluding parameters will create some RPT spam, but it's not too much of an issue.
Usage:
[
_nearestObjectMinDistance, // NUMBER (distance): Minimum distance from the nearest object.
_waterNearLimit, // NUMBER (distance): Minimum distance from water.
_minSurfaceNormal, // NUMBER (between 0-1): Maximum "surfaceNormal"; Basically determines how steep a position is. Check the comment for config value "DMS_MinSurfaceNormal" in config.sqf for more info
_spawnZoneNearLimit, // NUMBER (distance): Minimum distance from a spawn point.
_traderZoneNearLimit, // NUMBER (distance): Minimum distance from a trader zone.
_missionNearLimit, // NUMBER (distance): Minimum distance from another mission.
_playerNearLimit, // NUMBER (distance): Minimum distance from a player.
_throttleParams // BOOLEAN: Whether or not some of the distance values should be throttled on repeated attempts.
_waterSpawn // (OPTIONAL) BOOLEAN: Whether or not the mission is supposed to spawn on water. Default: false
] call DMS_fnc_findSafePos;
*/
private ["_nearestObjectMinDistance", "_waterNearLimit", "_minSurfaceNormal", "_spawnZoneNearLimit", "_traderZoneNearLimit", "_missionNearLimit", "_playerNearLimit", "_territoryNearLimit", "_throttleParams", "_waterSpawn", "_isValidSpot", "_attempts", "_pos", "_restriction", "_generatePos", "_presetLocs", "_presetLocsLength"];
params
[
["_nearestObjectMinDistance", 25, [0] ],
["_waterNearLimit", DMS_WaterNearBlacklist, [0] ],
["_minSurfaceNormal", DMS_MinSurfaceNormal, [0] ],
["_spawnZoneNearLimit", DMS_SpawnZoneNearBlacklist, [0] ],
["_traderZoneNearLimit", DMS_TraderZoneNearBlacklist,[0] ],
["_missionNearLimit", DMS_MissionNearBlacklist, [0] ],
["_playerNearLimit", DMS_PlayerNearBlacklist, [0] ],
["_territoryNearLimit", DMS_TerritoryNearBlacklist, [0] ],
["_throttleParams", DMS_ThrottleBlacklists, [true]]
];
_waterSpawn = if ((count _this)>9) then {_this select 9} else {false};
_isValidSpot = false;
_attempts = 0;
_restriction = if (_waterSpawn) then {2} else {0};
_presetLocsLength = 0;
if (DMS_UsePredefinedMissionLocations) then
{
// Shuffle the array so that the positions are selected in random order
_presetLocs = DMS_PredefinedMissionLocations call ExileClient_util_array_shuffle;
_presetLocsLength = count _presetLocs;
};
_generatePos =
{
if (DMS_UsePredefinedMissionLocations && {_attempts<=_presetLocsLength}) then
{
_presetLocs select (_attempts - 1)
}
else
{
[DMS_MinMax_X_Coords call DMS_fnc_SelectRandomVal,DMS_MinMax_Y_Coords call DMS_fnc_SelectRandomVal] isFlatEmpty [_nearestObjectMinDistance, 0, 9999, 1, _restriction, _waterSpawn, objNull]
};
};
while{!_isValidSpot} do
{
_attempts = _attempts+1;
_pos = [];
while {_pos isEqualTo []} do
{
_pos = call _generatePos;
};
// It will only throttle the missionNear blacklist and playerNear limits because those are the most likely to throw an exception.
// The throttling works by decreasing the parameters by 10% every 15 attempts, until it reaches 100 meters (by default).
if (_throttleParams && {(_attempts>=DMS_AttemptsUntilThrottle) && {(_attempts%DMS_AttemptsUntilThrottle)==0}}) then
{
_missionNearLimit = (DMS_ThrottleCoefficient * _missionNearLimit) max DMS_MinThrottledDistance;
_playerNearLimit = (DMS_ThrottleCoefficient * _playerNearLimit) max DMS_MinThrottledDistance;
// SurfaceNormal is a bit more tricky than distances, so it's throttled differently. To convert from degrees to surfaceNormal, you take the cosine of the degrees from horizontal. Take the arc-cosine to convert surfaceNormal to degrees: arccos(0.8) in degrees ~= 37
_minSurfaceNormal = (_minSurfaceNormal - 0.005) max 0.8;
if (DMS_DEBUG) then
{
(format ["FindSafePos :: Throttling _missionNearLimit to %1 and _playerNearLimit to %2 and _minSurfaceNormal to %4 after %3 failed attempts to find a safe position!",_missionNearLimit,_playerNearLimit,_attempts,_minSurfaceNormal]) call DMS_fnc_DebugLog;
};
};
_isValidSpot = [_pos, _waterNearLimit, _minSurfaceNormal, _spawnZoneNearLimit, _traderZoneNearLimit, _missionNearLimit, _playerNearLimit, _territoryNearLimit, _waterSpawn] call DMS_fnc_IsValidPosition;
};
_pos set [2,0];
if (DMS_DEBUG) then
{
(format["FindSafePos :: Found mission position %1 in %2 attempts. _this: %3",_pos,_attempts,_this]) call DMS_fnc_DebugLog;
};
_pos;