Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into feature/more-config…
Browse files Browse the repository at this point in the history
…urability
  • Loading branch information
3Mydlo3 committed Mar 21, 2024
2 parents c81e35b + adc5496 commit e1e88bb
Show file tree
Hide file tree
Showing 66 changed files with 29,016 additions and 355 deletions.
25 changes: 25 additions & 0 deletions .hemtt/project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,28 @@ path = "addons/main/script_version.hpp"
exclude = [
".inc.sqf"
]

[hemtt.launch]
workshop = [
"450814997", # CBA_A3
"2369477168", # ADT
]
parameters = [
"-name=dev_sk",
"-window",
]

[hemtt.launch.cup]
workshop = [
"450814997", # CBA_A3
"2369477168", # ADT
"583496184", # CUP Terrains - Core
"583544987", # CUP Terrains - Maps
"497660133", # CUP Weapons
"497661914", # CUP Units
"541888371", # CUP Vehicles
]
parameters = [
"-name=dev_sk",
"-window",
]
28 changes: 20 additions & 8 deletions addons/civilian/XEH_preInit.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,27 @@ if (isServer) then {
};
publicVariable QGVAR(initialCiviliansCount);

// Weights for civilians creation
GVAR(weightCapital) = ceil (random (10));
GVAR(weightCity) = ceil (random (8));
GVAR(weightVillage) = ceil (random (6));
GVAR(weightRural) = ceil (random (10));

// Initialize all cities found on the map
{
GVAR(cities) pushBack ([_x] call FUNC(initCity));
private _city = [_x] call FUNC(initCity);
GVAR(cities) pushBack _city;

#ifdef DEV_DEBUG
private _cityArea = _city getVariable QGVAR(cityArea);
_cityArea params ["_position", "_radiusA", "_radiusB", "_angle"];

private _marker = createMarkerLocal [configName _x, _position];
_marker setMarkerShapeLocal "ELLIPSE";
_marker setMarkerAlphaLocal 0.5;
_marker setMarkerColorLocal "ColorCIVILIAN";
_marker setMarkerSizeLocal [_radiusA, _radiusB];
_marker setMarkerDir _angle;

private _centerMarker = createMarkerLocal [format["center_%1", configName _x], _position];
_centerMarker setMarkerColorLocal "ColorCIVILIAN";
_centerMarker setMarkerSizeLocal [0.25, 0.25];
_centerMarker setMarkerType "mil_dot";
#endif
} forEach EGVAR(common,cities);
publicVariable QGVAR(cities);

Expand All @@ -48,7 +60,7 @@ if (isServer) then {
publicVariable QGVAR(vests);
publicVariable QGVAR(headgear);
// Initialize civilians
call FUNC(initCivilians);
[GVAR(cities)] call FUNC(initCivilians);
publicVariable QGVAR(civilians);
{
private _civiliansCount = count (_x getVariable [QGVAR(CiviliansList), []]);
Expand Down
12 changes: 8 additions & 4 deletions addons/civilian/functions/fnc_civilianKilledMsg.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,18 @@ if (_timeOfDeath isEqualType 0) then {
_timeOfDeath = [_timeOfDeath] call BIS_fnc_timeToString;
};

if (isNull _nearestTown) then {
_nearestTown = [_deadCivilian] call EFUNC(common,getNearestCityLocation);
private _nearestCity = if (isNull _nearestTown) then {
[_deadCivilian] call FUNC(getNearestCity)
} else {
[_nearestTown] call FUNC(getCityByLocation)
};

private _msg = "";
private _distance = (position _deadCivilian) distance _nearestTown;
private _nearestCityArea = _nearestCity getVariable QGVAR(cityArea);
private _isInCity = (position _deadCivilian) inArea _nearestCityArea;

// Check if distance is greater than 250 m. If so then change output a bit to represent that.
if (_distance <= 250) then {
if (_isInCity) then {
_msg = format [LLSTRING(Civilian_Killed_In_City), _timeOfDeath, text _nearestTown];
} else {
_msg = format [LLSTRING(Civilian_Killed_Near_City), _timeOfDeath, text _nearestTown];
Expand Down
10 changes: 6 additions & 4 deletions addons/civilian/functions/fnc_getCityName.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,14 @@ if (_city isEqualType locationNull) exitWith {
private _name = _city getVariable [QGVAR(Name), ""];
if !(_name isEqualTo "") exitWith {_name};

// Get logic assigned location
private _location = _city getVariable [QGVAR(Location), [_city] call EFUNC(common,getNearestCityLocation)];
if (_location isEqualTo locationNull) exitWith {""};
// Get logic assigned location class name
private _locationClassName = _city getVariable [QGVAR(locationClassName),
className ([_city] call EFUNC(common,getNearestCityLocation))];

if (_locationClassName isEqualTo "") exitWith {""};

// Get location name from config and save as logic variable for future calls
_name = getText (configFile >> "CfgWorlds" >> worldName >> "Names" >> className _location >> "name");
_name = getText (configFile >> "CfgWorlds" >> worldName >> "Names" >> _locationClassName >> "name");
_city setVariable [QGVAR(Name), _name];

_name
9 changes: 4 additions & 5 deletions addons/civilian/functions/fnc_getCityRandomPos.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

params ["_cityNamespace", ["_objectType", ""], ["_nearRoad", false], ["_allowOnRoad", true], ["_nearHouse", false], ["_emptyPosSearchRadius", 25]];

private _cityArea = _cityNamespace getVariable QGVAR(cityArea);
private _cityArea = _cityNamespace getVariable QGVAR(cityAreaForRandomPos);

// Function returns position random position in area
private _fnc_randomPos = {
Expand Down Expand Up @@ -54,17 +54,16 @@ if (!(_objectType isEqualType "")) then {

// If no object is given, just random position is enough
if (_objectType isEqualTo "") exitWith {[_cityArea, _nearRoad, _allowOnRoad, _nearHouse, _emptyPosSearchRadius] call _fnc_randomPos};

private _location = _cityNamespace getVariable QGVAR(Location);
private _cityArea = _cityNamespace getVariable QGVAR(cityArea);
private _randomPos = [];
private _loopLimit = 250;
// Loop until acquired random empty pos is within location area (or loop limit reached)
while {(_loopLimit >= 0) && {(_randomPos isEqualTo []) || {!(_randomPos inArea _location)}}} do {
while {(_loopLimit >= 0) && {(_randomPos isEqualTo []) || {!(_randomPos inArea _cityArea)}}} do {
_randomPos = [_cityArea, _nearRoad, _allowOnRoad, _nearHouse, _emptyPosSearchRadius] call _fnc_randomPos;
_randomPos = _randomPos findEmptyPosition [0, _emptyPosSearchRadius, _objectType];
_loopLimit = _loopLimit - 1;
};

if (_loopLimit isEqualTo 0) exitWith {[]};

_randomPos;
_randomPos
7 changes: 5 additions & 2 deletions addons/civilian/functions/fnc_getNearestVehicle.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
*
* Arguments:
* 0: Position <POSITION/OBJECT>
* 1: Search radius <NUMBER> (Optional)
* 2: Filter function returning true for valid vehicles <FUNC> (Optional)
*
* Return Value:
* None
Expand All @@ -15,13 +17,14 @@
* Public: No
*/

params ["_pos", ["_radius", 500]];
params ["_pos", ["_radius", 500], ["_filterFunction", {true}]];

if (_pos isEqualType objNull) then {
_pos = getPos _pos;
};

private _nearbyVehicles = _pos nearEntities [["Air", "Car", "Motorcycle", "Tank"], _radius];
private _nearbyVehicles = _pos nearEntities [["Air", "Car", "Motorcycle", "Tank"], _radius]
select {[_x] call _filterFunction};

private _nearestVehicle = [_nearbyVehicles, _pos] call BIS_fnc_nearestPosition;

Expand Down
38 changes: 33 additions & 5 deletions addons/civilian/functions/fnc_initCity.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -15,28 +15,56 @@
* Public: No
*/

#define IS_CITY_RECTANGLE false

params ["_cityLocation"];

if (_cityLocation isEqualType configNull) then {
_cityLocation = [getArray (_cityLocation >> 'position'), 10] call EFUNC(common,getNearestCityLocation);
};

private _cityLocationConfig = (configFile >> "CfgWorlds" >> worldName >> "Names" >> className _cityLocation);
private _cityLocationClassName = className _cityLocation;
private _cityLocationConfig = (configFile >> "CfgWorlds" >> worldName >> "Names" >> _cityLocationClassName);

// Create city namespace
private _cityNamespace = true call CBA_fnc_createNamespace;
GVAR(citiesLocations) setVariable [className _cityLocation, _cityNamespace, true];
_cityNamespace setVariable [QGVAR(Location), _cityLocation, true];
GVAR(citiesLocations) setVariable [_cityLocationClassName, _cityNamespace, true];
_cityNamespace setVariable [QGVAR(locationClassName), _cityLocationClassName, true];
_cityNamespace setVariable [QGVAR(Name), [_cityLocation] call FUNC(getCityName), true];
private _cityType = [_cityLocation] call EFUNC(common,getLocationType);
_cityNamespace setVariable [QGVAR(cityType), _cityType, true];

// Set city position and area variables
private _cityPosition = (position _cityLocation);
_cityPosition set [2, 0]; // Location position has negative third coordinate
private _positionOffset = getArray (_cityLocationConfig >> 'positionOffset');
if (_positionOffset isNotEqualTo []) then {
_cityPosition = _cityPosition vectorAdd _positionOffset;
};

_cityNamespace setVariable [QGVAR(Position), _cityPosition, true];
private _cityArea = [_cityPosition, [getNumber (_cityLocationConfig >> 'radiusA'), getNumber (_cityLocationConfig >> 'radiusB'), 0, false]];
_cityNamespace setVariable [QGVAR(cityArea), _cityArea];

private _area = if (GVAR(respectCityArea)) then {
private _radiusA = getNumber (_cityLocationConfig >> 'radiusA');
private _radiusB = getNumber (_cityLocationConfig >> 'radiusB');
private _angle = getNumber (_cityLocationConfig >> 'angle');

[_radiusA, _radiusB, _angle, IS_CITY_RECTANGLE]
} else {
switch (_cityType) do {
case "NameVillage": { [GVAR(customVillageAreaRadius), GVAR(customVillageAreaRadius), 0, IS_CITY_RECTANGLE] };
case "NameCity": { [GVAR(customCityAreaRadius), GVAR(customCityAreaRadius), 0, IS_CITY_RECTANGLE] };
case "NameCityCapital": { [GVAR(customCityCapitalAreaRadius), GVAR(customCityCapitalAreaRadius), 0, IS_CITY_RECTANGLE] };
default { [GVAR(customVillageAreaRadius), GVAR(customVillageAreaRadius), 0, IS_CITY_RECTANGLE] };
}
};

private _cityArea = [_cityPosition];
_cityArea append _area;
private _cityAreaForRandomPos = [_cityPosition, _area];

_cityNamespace setVariable [QGVAR(cityArea), _cityArea, true]; // [_pos, _radiusA, _radiusB, _angle, _rectangle]
_cityNamespace setVariable [QGVAR(cityAreaForRandomPos), _cityAreaForRandomPos, true]; // [_pos, [_radiusA, _radiusB, _angle, _rectangle]]

// Create city civilians variables
_cityNamespace setVariable [QGVAR(CiviliansList), []];
Expand Down
75 changes: 68 additions & 7 deletions addons/civilian/functions/fnc_initCivilians.sqf
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#include "script_component.hpp"
/*
* Author: 3Mydlo3
* Function initializes civilians on whole map.
* Function initializes civilians in cities only.
*
* Arguments:
* None
* 0: Cities that should contain civilians <ARRAY>
*
* Return Value:
* None
Expand All @@ -15,14 +15,75 @@
* Public: No
*/

#define NEAR_ROAD true
#define ALLOW_ON_ROAD true
#define NEAR_BUILDINGS true
#define MAX_DISTANCE_TO_VILLAGE 500
#define MAX_DISTANCE_TO_NEAREST_CITY 1000

params ["_cities"];

// Determine initial weights for cities
private _cityWeightsArray = _cities apply {
private _cityArea = _x getVariable QGVAR(cityArea);
_cityArea params ["_center", "_radiusA", "_radiusB"];
private _area = _radiusA * _radiusB; // We can omit the PI as it's a const and we'll just compare all the values

private _cityType = _x getVariable [QGVAR(cityType), "NameVillage"];
private _cityTypeMultiplier = switch (_cityType) do {
case "NameVillage": { GVAR(villageCiviliansWeightMultiplier) };
case "NameCity": { GVAR(cityCiviliansWeightMultiplier) };
case "NameCityCapital": { GVAR(cityCapitalCiviliansWeightMultiplier) };
default { 0 };
};

private _weight = _area * _cityTypeMultiplier;
[_x getVariable QGVAR(Name), [_x, _weight]]
};

private _cityWeights = createHashMapFromArray _cityWeightsArray;

// Spawn civilians
private _i = GVAR(initialCiviliansCount);

while {_i > 0} do {
private _pos = [nil, false, true, true] call EFUNC(common,getRandomPos);
if (!(_pos isEqualTo [])) then {
private _nearestCity = [_pos, 1500] call FUNC(getNearestCity);
if (_nearestCity isEqualTo objNull) exitWith {};
if (GVAR(guaranteedCivilianInEveryLocation)) then {
private _cityIndex = 0;
private _citiesCount = count _cities;

while {_cityIndex < _citiesCount && {_i > 0}} do {
private _city = _cities select _cityIndex;
private _pos = [_city, nil, NEAR_ROAD, ALLOW_ON_ROAD, NEAR_BUILDINGS] call FUNC(getCityRandomPos);

_cityIndex = _cityIndex + 1;

if (_pos isEqualTo []) then { continue };

[_pos] call FUNC(createCivilian);
_i = _i - 1;
};
};

while {_i > 0} do {
private _citiesNames = keys _cityWeights;
private _citiesWeights = values _cityWeights apply {_x select 1};

private _randomCityName = _citiesNames selectRandomWeighted _citiesWeights;
private _randomCityAndWeight = _cityWeights get _randomCityName;
private _randomCity = _randomCityAndWeight select 0;

private _pos = [_randomCity, nil, NEAR_ROAD, ALLOW_ON_ROAD, NEAR_BUILDINGS] call FUNC(getCityRandomPos);

if (_pos isEqualTo []) then { continue };

private _nearbyCivilians = _pos nearEntities ["Man", 100];
private _nearbyCiviliansCount = count _nearbyCivilians;
if (_nearbyCiviliansCount >= 2 && {(random 1) - _nearbyCiviliansCount * 0.05 > 0.1}) then { continue };

// Update weight as civilian will be created here
private _newCityWeight = (_randomCityAndWeight select 1) / 2;
_cityWeights set [_randomCityName, [_randomCity, _newCityWeight]];

// Create civilian
[_pos] call FUNC(createCivilian);
_i = _i - 1;
};
Loading

0 comments on commit e1e88bb

Please sign in to comment.