Skip to content

Commit

Permalink
Added civilian casualtie simulation system (#1074)
Browse files Browse the repository at this point in the history
* Added simple civilian zone detection

* Fixed spelling

* Updated logging

* Minor adjustments and fixes

* Update fn_civ_damage.sqf

* Fixed spelling on variable and diary records

* fixed spelling for density variable

* added check for density

* Fixed formating and added continue instead of exitWith

* Update fn_civ_damage.sqf

* Fixed documents

* Update and rename fn_civ_zone.sqf to fn_civ_checkProjectile.sqf

* Update fn_civ_checkProjectile.sqf

* Fixed zone > checkProjectile

* Fixed name for function

* Fixed typo

* Added documentation

* Fixed format

* Check now done once each check instead of each success

* Added meme none

* Added extream

* Update fn_civ_init.sqf

* Show warning if invalid

* Updated with script and agent and unit handler

* Removed debugging

* Cleaned
  • Loading branch information
AndreasBrostrom authored Jan 9, 2024
1 parent 3161c89 commit da05cf9
Show file tree
Hide file tree
Showing 6 changed files with 259 additions and 0 deletions.
8 changes: 8 additions & 0 deletions cScripts/CfgFunctions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ class cScripts {

class doStarterCrate {};
class doSupplyCrate {};

class makeAgent {};
};
class systems {
file = "cScripts\functions\systems";
Expand Down Expand Up @@ -190,6 +192,12 @@ class cScripts {
class vehicle_reset {};
class vehicle_addFlagAction {};
};
class civ {
file = "cScripts\functions\civ";
class civ_init {};
class civ_checkProjectile {};
class civ_damage {};
};
class modules {
file = "cScripts\functions\modules";
class zenModule_EnableUnitSimulation {};
Expand Down
2 changes: 2 additions & 0 deletions cScripts/cScripts_postInit.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ if (EGVAR(Settings,showDiaryRecords)) then {
call EFUNC(init,diary);
};

call EFUNC(civ,init);

onPlayerConnected {
[QEGVAR(log,player), [name player]] call CBA_fnc_serverEvent;
};
Expand Down
42 changes: 42 additions & 0 deletions cScripts/functions/civ/fn_civ_checkProjectile.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#include "..\script_component.hpp";
/*
* Author: SGT.Brostrom.A
* This function checks a given projectile and se if it can damage a target.
*
* Arguments:
* 1: Not used <NIL>
* 2: Not used <NIL>
* 3: Not used <NIL>
* 4: Not used <NIL>
* 5: Not used <NIL>
* 6: Not used <NIL>
* 7: Projectile <OBJECT>
*
* Return Value:
* Nothing
*
* Example:
* call cScripts_fnc_civ_checkProjectile
*
* Public: No
*/

params ["", "", "", "", "", "", "_projectile"];

if (!GVAR(isPlayer)) exitWith {};
if (typeOf _projectile isKindOf "Chemlight_base") exitWith {};
if (typeOf _projectile isKindOf "SmokeShell") exitWith {};
if (typeOf _projectile isKindOf "rhs_ammo_m84") exitWith {};

_projectile addEventHandler ["HitExplosion", {
params ["_projectile", "_hitEntity", "_projectileOwner", "_hitSelections"];
_hitSelections params ["_hitSelections"];
private _pos = _hitSelections#0;
{
_x params ["_marker", "", "", "", "_dencity"];
private _inArea = _pos inArea _marker;
if (_inArea) then {
[_marker, _dencity, _projectile, player] call EFUNC(civ,damage);
};
} forEach GETMVAR(EGVAR(Civ,Zones), []);
}];
49 changes: 49 additions & 0 deletions cScripts/functions/civ/fn_civ_damage.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#include "..\script_component.hpp";
/*
* Author: SGT.Brostrom.A
* This function handle the casualties and send the information to all curators.
*
* Arguments:
* 0: Marker <STRING>
* 1: Density <STRING>
* 2: Projectile <OBJECT>
* 4: Unit <OBJECT>
*
* Return Value:
* Nothing
*
* Example:
* call cScripts_fnc_civ_damage
*
* Public: No
*/

params ["_marker", "_density", "_projectile", "_unit"];

if (!GVAR(ALLOW_CIV_ZONE_DAMAGE)) exitWith {};
GVAR(ALLOW_CIV_ZONE_DAMAGE) = false;

INFO_1("Civ", "Checking for possible civilian casualties at %1.", _marker);

private _damageChance = switch (_density) do {
case "extream": {0.65};
case "high": {0.4};
case "medium": {0.25};
case "low": {0.1};
case "none": {0};
default {0};
};

if (random 1 < _damageChance) then {
INFO_1("Civ", "Civilian casualties at %1.", _marker);
private _location = text nearestLocation [markerPos _marker, ""];
{
private _curator = getAssignedCuratorUnit _x;
[QEGVAR(Civilian,Casualties), [_location, _unit], _curator] call CBA_fnc_targetEvent;
} forEach allCurators;
} else {
INFO_1("Civ", "No civilian casualties at %1 detected.", _marker);
};

// Allow additional check again
[{GVAR(ALLOW_CIV_ZONE_DAMAGE) = true;}, [], 5] call CBA_fnc_waitAndExecute;
97 changes: 97 additions & 0 deletions cScripts/functions/civ/fn_civ_init.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
#include "..\script_component.hpp";
/*
* Author: SGT.Brostrom.A
* This function checks and enables eventhandlers for the the civ population simulation system.
*
* Arguments:
* None
*
* Return Value:
* Nothing
*
* Example:
* call cScripts_fnc_civ_init
*
* Public: No
*/

INFO("Civ", "Checking for population zones...");

GVAR(ALLOW_CIV_ZONE_DAMAGE) = true;
private _civZones = [];
{
private _markerName = [_x, 0, 21] call BIS_fnc_trimString;
_markerName = toLower _markerName;
if (_markerName == "cscripts_civilan_zone_") then {
private _density = [_x, 21] call BIS_fnc_trimString;
_density = (_density splitString "_")#0;
if !(_density in ["extream", "high", "medium", "low", "none"]) then {
SHOW_CHAT_WARNING_2("Civ", "Zone %1 have invalid density '%2'.", _x, _density);
continue;
};
private _pos = getMarkerPos _x;
private _dir = markerDir _x;
private _size = markerSize _x;
_civZones append [[_x, _pos, _dir, _size, _density]];
_x setMarkerAlpha 0;
INFO_5("Civ", "Population zone added [%1, %2, %3, %4, %5]", _x, _pos, _dir, _size, _density);
};
} forEach allMapMarkers;

if (_civZones isEqualTo []) exitWith {INFO("Civ", "No population zones detected");};
SETMVAR(EGVAR(Civ,Zones), _civZones);


// Create diary records for the zones
if !(player diarySubjectExists "CivCenter") then {
{
_x params ["_marker", "_pos", "", "", "_density"];
player createDiarySubject ["CivCenter","Population Centers"];

private _location = text nearestLocation [_pos, ""];
private _textLocation = formatText["<font color='#ffc61a'>%1</font> is a population center located at <font color='#ffc61a'>%2</font>.", _location, mapGridPosition _pos];
private _textDensity = if (_density != "none") then { formatText["<br/><br/>The location have <font color='#ffc61a'>%1</font> density.", _density]; } else {""};
private _record = player createDiaryRecord ["CivCenter", [_location, format [
"%1%2", _textLocation, _textDensity
]]];
} forEach GETMVAR(EGVAR(Civ,Zones), []);
};


// Event Handlers
[player, "fired", {_this call EFUNC(civ,checkProjectile)}] call CBA_fnc_addBISEventHandler;
["ace_firedPlayer", {_this call EFUNC(civ,checkProjectile)}] call CBA_fnc_addEventHandler;
["ace_firedPlayerVehicle", {_this call EFUNC(civ,checkProjectile)}] call CBA_fnc_addEventHandler;


// Physical civilian units
["CAManBase", "init", {
params ["_unit"];
if (isPlayer _unit) exitWith {};
if (side _unit == civilian) then {
INFO_2("Civ", "Civilian unit detected %1 (%2) applying eventhandler.", _unit, typeOf _unit);
[_unit, "killed", {
params ["_unit", "_source", "_damage", "_instigator"];
private _location = text nearestLocation [getPosASLVisual _unit, ""];
INFO_1("Civ", "Civilian casualties at %1.", _location);
{
private _curator = getAssignedCuratorUnit _x;
[QEGVAR(Civilian,Casualties), [_location, _source], _curator] call CBA_fnc_targetEvent;
} forEach allCurators;
}] call CBA_fnc_addBISEventHandler;
};
}, true, [], true] call CBA_fnc_addClassEventHandler;

[QEGVAR(Civilian,Casualties), {
params ["_location", "_unit"];
[
[],
["Civilian Casualties", 1.2, [1, 0.776, 0.102, 1]],
[format ["Casualties repoted in %1.", _location]],
[format ["Caused by %1.", name _unit]],
[""],
[""]
] call CBA_fnc_notify;
systemChat format ["Civilian casualties caused by %1 repoted near %2.", name _unit, _location];
playSound "hint";
}] call CBA_fnc_addEventHandler;
61 changes: 61 additions & 0 deletions cScripts/functions/mission/fn_makeAgent.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#include "..\script_component.hpp";
/*
* Author: SGT.Brostrom.A
* This function removes and recreates a given unit as a agent when in proximity.
* Run this function in the object or unit init.
*
* Arguments:
* 0: Unit <OBJECT>
*
* Example:
* [this] call cScripts_fnc_makeAgent
*
*/

params [["_unit", objNull, [objNull]]];

private _classname = typeOf _unit;
private _postion = getPosASL _unit;
private _vectorUp = vectorUp _unit;
private _vectorDir = vectorDir _unit;
private _side = side _unit;

deleteVehicle _unit;

_agent = createAgent [_classname, _postion, [], 0, 'CAN_COLLIDE'];
_agent setPosASL _postion;
_agent setVectorDirAndUp [_vectorDir, _vectorUp];

INFO_3("Agent", "Converted %1 (%2) to agent %3 (%2).", _unit, _classname, _agent);

if (_side == civilian) then {
[{
params ["_agent"];
_agent unassignItem "ItemMap";
_agent removeItem "ItemMap";
_agent unassignItem "ItemCompass";
_agent removeItem "ItemCompass";

private _watch = selectRandom ["ItemWatch", "", ""];
if (_watch == "") then {
_agent unassignItem "ItemWatch";
_agent removeItem "ItemWatch";
};

private _money = selectRandom ["Money_roll", "Money_bunch", "Money_bunch", "Money_bunch", "Money_bunch", "", ""];
if (_money != "") then {
[_agent, _money] call CBA_fnc_addItem;
};

private _wallet = selectRandom ["Wallet_ID", "Wallet_ID", ""];
if (_wallet != "") then {
[_agent, _wallet] call CBA_fnc_addItem;
};

private _phone = selectRandom ["MobilePhone", "MobilePhone", "MobilePhone", "SmartPhone", "", "", "", ""];
if (_phone != "") then {
[_agent, _phone] call CBA_fnc_addItem;
};
}, [_agent]] call CBA_fnc_execNextFrame;
};

0 comments on commit da05cf9

Please sign in to comment.