From 4004b524a44b2b1da060b7cd099a8886b8321116 Mon Sep 17 00:00:00 2001 From: 3Mydlo3 Date: Mon, 15 Apr 2024 22:16:20 +0200 Subject: [PATCH] Fully localize all user visible actions, messages, notifications and fix related bugs (#96) * Replace placeholders * Variable location size so kill messages better reflect in/around for large cities * Adjust for cityArea * Fix Civilian killed stringtable * Optimize killed marker creation * Prevent 'cop killed by cop' when civilian kills cop * Fix localization of kill notifications * Show localized car alarm notification * Localize cannot create vehicle message * Fix some settings should not require restart * Fix alarm not working in nearby civilians mode * Add TODO * Localize killers start positions names * Fix incorrect PREP * Change locationNames(Raw) namespaces to hashMaps * Fix default LocationName for module not being localized * Fix for generated positions * Optimize policeStationMarker creation * Localize "Teleport back" * Add FUNC(isCop) * Fix logging player or AI * Fix again * Fix side check in isCop * Try workaround for vehicle suicide detection * Add name of the cop that killed other cop * Fix variable name * Fix cop check in kill messages * Fix killer name being null on suicide * Resolve TODO * Localized police station name * Fix no empty spawner message appearing when empty vehicle can be removed * Increase 2nd spawn attempt delay * Remove forced police station names from missions * Add a note to module "LocationName" that it's optional * Fix killers start module missing property name * Drop forced killers start name in Malden scenario * Log module LocationNames and fix automatic name selection * Fix killers don't see police station markers * Try localize 'maximum idle time reached' * Localize teleport name * Use isNotEqualTo * PublicVariable LocationName of police station module * Pass unlocalized string to changeScore for timeout message * Fix localizable message template and args ignored in showScore flow * Still doesn't work * Fix format array creation * Add postInit warning message that debug mode is enabled * Actually implement time limit * Change killers score change stacking duration the more score changes * Time limit & extra time improvements * Shorten main game time limit to 30 minutes (+15 extra) * Increase extra time timeouts limit --- addons/civilian/XEH_PREP.hpp | 1 + addons/civilian/XEH_postInit.sqf | 5 ++ .../civilian/functions/fnc_civilianKilled.sqf | 11 ++- .../functions/fnc_civilianKilledMarker.sqf | 8 +- .../functions/fnc_civilianKilledMsg.sqf | 26 +++--- .../functions/fnc_isPositionInCity.sqf | 32 +++++++ addons/civilian/stringtable.xml | 28 +++++- addons/common/XEH_PREP.hpp | 1 + addons/common/XEH_postInit.sqf | 8 +- addons/common/XEH_preInit.sqf | 3 +- .../common/functions/fnc_getLocationName.sqf | 4 +- .../functions/fnc_getLocationNameRaw.sqf | 38 ++++++++ addons/killers/XEH_postInit.sqf | 2 +- .../killers/functions/fnc_createTeleport.sqf | 2 +- .../functions/fnc_initStartPositions.sqf | 5 +- addons/killers/stringtable.xml | 4 + addons/main/script_mod.hpp | 2 +- addons/missions/SK_test.Malden/mission.sqm | 6 +- .../mission.sqm | 12 +-- .../mission.sqm | 12 +-- .../mission.sqm | 12 +-- addons/modules/CfgVehicles.hpp | 8 +- .../functions/fnc_moduleKillersStart.sqf | 8 +- .../functions/fnc_modulePoliceStation.sqf | 8 +- addons/modules/stringtable.xml | 36 ++++---- addons/police/XEH_PREP.hpp | 2 + addons/police/XEH_postInit.sqf | 16 ++++ addons/police/functions/fnc_copKilled.sqf | 24 ++++-- .../police/functions/fnc_copKilledMarker.sqf | 8 +- addons/police/functions/fnc_copKilledMsg.sqf | 22 ++--- .../police/functions/fnc_createTeleport.sqf | 4 +- .../functions/fnc_initPoliceStation.sqf | 5 +- addons/police/functions/fnc_isCop.sqf | 22 +++++ addons/police/functions/fnc_isKilledByCop.sqf | 27 ++++++ .../functions/fnc_policeStationMarker.sqf | 12 +-- addons/police/functions/fnc_spawnVehicle.sqf | 54 ++++++------ addons/police/stringtable.xml | 24 +++++- addons/score/CfgDebriefing.hpp | 3 + addons/score/XEH_PREP.hpp | 2 + addons/score/XEH_postInit.sqf | 29 +++++-- addons/score/XEH_preInit.sqf | 1 + .../score/functions/fnc_addKillersScore.sqf | 5 +- addons/score/functions/fnc_changeScore.sqf | 17 +++- .../score/functions/fnc_endMissionClient.sqf | 2 +- .../functions/fnc_extraTimeAdjustRules.sqf | 21 +++++ .../functions/fnc_getIdleTimeRulesMessage.sqf | 32 +++++++ .../score/functions/fnc_monitorTimeLimit.sqf | 39 +++++++-- .../score/functions/fnc_monitorTimeouts.sqf | 13 +-- addons/score/functions/fnc_showScore.sqf | 8 +- addons/score/initSettings.inc.sqf | 80 ++++++++++------- addons/score/stringtable.xml | 86 +++++++++++++++---- addons/vehicles/XEH_postInit.sqf | 5 ++ .../functions/fnc_carAlarmNotification.sqf | 4 +- .../functions/fnc_vehicleStolenMsg.sqf | 14 +-- addons/vehicles/initSettings.inc.sqf | 4 +- 55 files changed, 638 insertions(+), 229 deletions(-) create mode 100644 addons/civilian/functions/fnc_isPositionInCity.sqf create mode 100644 addons/common/functions/fnc_getLocationNameRaw.sqf create mode 100644 addons/police/functions/fnc_isCop.sqf create mode 100644 addons/police/functions/fnc_isKilledByCop.sqf create mode 100644 addons/score/functions/fnc_extraTimeAdjustRules.sqf create mode 100644 addons/score/functions/fnc_getIdleTimeRulesMessage.sqf diff --git a/addons/civilian/XEH_PREP.hpp b/addons/civilian/XEH_PREP.hpp index 279b6c5a..1676523a 100644 --- a/addons/civilian/XEH_PREP.hpp +++ b/addons/civilian/XEH_PREP.hpp @@ -12,4 +12,5 @@ PREP(initCity); PREP(initCivilians); PREP(initConfig); PREP(initCivilian); +PREP(isPositionInCity); PREP(unassignCivilianFromCity); diff --git a/addons/civilian/XEH_postInit.sqf b/addons/civilian/XEH_postInit.sqf index 38e3b877..60ac6907 100644 --- a/addons/civilian/XEH_postInit.sqf +++ b/addons/civilian/XEH_postInit.sqf @@ -16,3 +16,8 @@ if (isServer) then { _this call FUNC(civilianKilled); }] call CBA_fnc_addEventHandler; }; + +[QGVAR(showCivilianKilledNotification), { + private _msg = _this call FUNC(civilianKilledMsg); + [QEGVAR(common,showSideChatMsg), [WEST, _msg]] call CBA_fnc_localEvent; +}] call CBA_fnc_addEventHandler; diff --git a/addons/civilian/functions/fnc_civilianKilled.sqf b/addons/civilian/functions/fnc_civilianKilled.sqf index 1d36d6fb..e78acade 100644 --- a/addons/civilian/functions/fnc_civilianKilled.sqf +++ b/addons/civilian/functions/fnc_civilianKilled.sqf @@ -35,16 +35,15 @@ private _time = [daytime] call BIS_fnc_timeToString; // Call function to create marker at killed unit's position. [_civilian, _time] call FUNC(civilianKilledMarker); // Show message for all cops that cop has been killed near some location with timestamp -private _msg = [_civilian, _time] call FUNC(civilianKilledMsg); -[QEGVAR(common,showSideChatMsg), [WEST, _msg]] call CBA_fnc_globalEvent; +[QGVAR(showCivilianKilledNotification), [_civilian, _killer, _time]] call CBA_fnc_globalEvent; // Killer can be vehicle sometimes so get driver _killer = driver _killer; // If killer was police, we need to change score accordingly if (side _killer isEqualTo WEST) then { - [QEGVAR(score,changeScore), [EAST, EGVAR(score,policekilledCivilianKillersScore), "CIVILIAN KILLED BY COP PLACEHOLDER"]] call CBA_fnc_serverEvent; - [QEGVAR(score,changeScore), [WEST, EGVAR(score,policeKilledCivilianPoliceScore), "CIVILIAN KILLED BY COP PLACEHOLDER"]] call CBA_fnc_serverEvent; + [QEGVAR(score,changeScore), [EAST, EGVAR(score,policekilledCivilianKillersScore), LSTRING(KilledByCop)]] call CBA_fnc_serverEvent; + [QEGVAR(score,changeScore), [WEST, EGVAR(score,policeKilledCivilianPoliceScore), LSTRING(KilledByCop)]] call CBA_fnc_serverEvent; } else { - [QEGVAR(score,changeScore), [EAST, EGVAR(score,killedCivilianKillersScore), "CIVILIAN KILLED PLACEHOLDER"]] call CBA_fnc_serverEvent; - [QEGVAR(score,changeScore), [WEST, EGVAR(score,killedCivilianPoliceScore), "CIVILIAN KILLED PLACEHOLDER"]] call CBA_fnc_serverEvent; + [QEGVAR(score,changeScore), [EAST, EGVAR(score,killedCivilianKillersScore), LSTRING(Killed)]] call CBA_fnc_serverEvent; + [QEGVAR(score,changeScore), [WEST, EGVAR(score,killedCivilianPoliceScore), LSTRING(Killed)]] call CBA_fnc_serverEvent; }; diff --git a/addons/civilian/functions/fnc_civilianKilledMarker.sqf b/addons/civilian/functions/fnc_civilianKilledMarker.sqf index 278b996f..ce47606b 100644 --- a/addons/civilian/functions/fnc_civilianKilledMarker.sqf +++ b/addons/civilian/functions/fnc_civilianKilledMarker.sqf @@ -20,10 +20,10 @@ params ["_unit", "_time"]; private _markerName = format ["killed_civilian_%1_%2", _unit]; private _markerText = format ["%1", _time]; -private _marker = createMarker [_markerName, getPosATL _unit]; -_marker setMarkerType "mil_objective"; -_marker setMarkerColor "ColorEAST"; -_marker setMarkerSize [0.4, 0.4]; +private _marker = createMarkerLocal [_markerName, getPosATL _unit]; +_marker setMarkerTypeLocal "mil_objective"; +_marker setMarkerColorLocal "ColorEAST"; +_marker setMarkerSizeLocal [0.4, 0.4]; _marker setMarkerText _markerText; [_marker] call EFUNC(markers,markerDecay); diff --git a/addons/civilian/functions/fnc_civilianKilledMsg.sqf b/addons/civilian/functions/fnc_civilianKilledMsg.sqf index 0440b88d..fe1190ed 100644 --- a/addons/civilian/functions/fnc_civilianKilledMsg.sqf +++ b/addons/civilian/functions/fnc_civilianKilledMsg.sqf @@ -5,8 +5,9 @@ * * Arguments: * 0: Dead civilian - * 1: Civilian's time of death - * 2: Nearest location + * 1: Unit which killed civilian + * 2: Civilian's time of death + * 3: Nearest location * * Return Value: * 0: Civilian killed message @@ -17,27 +18,20 @@ * Public: No */ -params ["_deadCivilian", ["_timeOfDeath", daytime], ["_nearestTown", locationNull]]; +params ["_unit", ["_killer", objNull], ["_timeOfDeath", daytime], ["_nearestTown", locationNull]]; if (_timeOfDeath isEqualType 0) then { _timeOfDeath = [_timeOfDeath] call BIS_fnc_timeToString; }; -private _nearestCity = if (isNull _nearestTown) then { - [_deadCivilian] call FUNC(getNearestCity) +// Check if civilian died in city. If so then change output a bit to represent that. +private _template = if ([_unit, _nearestTown] call FUNC(isPositionInCity)) then { + if ([_killer] call EFUNC(police,isCop)) then { LLSTRING(KilledByCop_In_City) } else { LLSTRING(Killed_In_City) }; } else { - [_nearestTown] call FUNC(getCityByLocation) + if ([_killer] call EFUNC(police,isCop)) then { LLSTRING(KilledByCop_Near_City) } else { LLSTRING(Killed_Near_City) }; }; -private _msg = ""; -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 (_isInCity) then { - _msg = format [LLSTRING(Civilian_Killed_In_City), _timeOfDeath, text _nearestTown]; -} else { - _msg = format [LLSTRING(Civilian_Killed_Near_City), _timeOfDeath, text _nearestTown]; -}; +// Supplying killer name to format, but only killed by cop should reveal name for lynch +private _msg = format [_template, _timeOfDeath, text _nearestTown, name _killer]; _msg diff --git a/addons/civilian/functions/fnc_isPositionInCity.sqf b/addons/civilian/functions/fnc_isPositionInCity.sqf new file mode 100644 index 00000000..6f50f002 --- /dev/null +++ b/addons/civilian/functions/fnc_isPositionInCity.sqf @@ -0,0 +1,32 @@ +#include "script_component.hpp" +/* + * Author: 3Mydlo3 + * Function checks if a unit/position is in a city. + * + * Arguments: + * 0: Unit/Position to check + * 1: Particular city location to check (Optional) + * + * Return Value: + * 0: Result + * + * Example: + * [position player] call afsk_civilian_fnc_isPositionInCity + * + * Public: No + */ + +params ["_position", ["_location", locationNull]]; + +if (_position isEqualType objNull) then { + _position = getPosATL _position; +}; + +private _nearestCity = if (_location isEqualTo locationNull) then { + [_position] call FUNC(getNearestCity) +} else { + [_location] call FUNC(getCityByLocation) +}; + +private _nearestCityArea = _nearestCity getVariable QGVAR(cityArea); +_position inArea _nearestCityArea diff --git a/addons/civilian/stringtable.xml b/addons/civilian/stringtable.xml index e7fe608f..7a922de1 100644 --- a/addons/civilian/stringtable.xml +++ b/addons/civilian/stringtable.xml @@ -5,14 +5,30 @@ SerialKillers - Civilian SerialKillers - Cywile - + + Civilian vehicles limit + Limit pojazdów cywilnych + + + Controls how much civilian vehicles will be created on the whole map. + Ustala jak dużo pojazdów cywilnych będzie utworzonych na całej mapie. + + Civilian was killed at %1 in %2! Cywil został zabity o godzinie %1 w %2! - + Civilian was killed at %1 near %2! Cywil został zabity o godzinie %1 w pobliżu %2! + + Civilian was killed by cop %3 at %1 in %2! + Cywil został zabity przez policjanta %3 o godzinie %1 w %2! + + + Civilian was killed by cop %3 at %1 near %2! + Cywil został zabity przez policjanta %3 o godzinie %1 w pobliżu %2! + Civilians count Liczba cywili @@ -89,6 +105,14 @@ When map locations are badly defined, this can be used to control how large capital(s) are on a given map. This is used for spawning civilians, waypoints and some other things. Gdy lokacje na mapie są słabo zdefiniowane, można ustawić ręcznie jak duże są stolice na danej mapie. Jest to używane do spawnownia cywili, waypointów i wielu innych rzeczy. + + Civilian was killed + Cywil został zabity + + + Civilian was killed by cop + Cywil został zabity przez policjanta + Low Mało diff --git a/addons/common/XEH_PREP.hpp b/addons/common/XEH_PREP.hpp index df0ca2e9..55bf0d2d 100644 --- a/addons/common/XEH_PREP.hpp +++ b/addons/common/XEH_PREP.hpp @@ -5,6 +5,7 @@ PREP(createArsenal); PREP(deleteAtRandom); PREP(getAllMapCities); PREP(getLocationName); +PREP(getLocationNameRaw); PREP(getLocationType); PREP(getNearestCityLocation); PREP(getNearestLocation); diff --git a/addons/common/XEH_postInit.sqf b/addons/common/XEH_postInit.sqf index d9394fbb..0dbe45aa 100644 --- a/addons/common/XEH_postInit.sqf +++ b/addons/common/XEH_postInit.sqf @@ -1,5 +1,9 @@ #include "script_component.hpp" +#ifdef DEBUG_MODE_FULL + WARNING("Debug mode is enabled. It might reveal information, don't use it for normal gameplay!"); +#endif + // Killswitch if (!EGVAR(common,enabled)) exitWith { WARNING("Mission is missing 'SK' gameType Header. SerialKillers framework will be disabled."); @@ -19,7 +23,7 @@ if (isServer) then { params [["_side", sideEmpty], ["_msg", ""]]; if (_msg isEqualTo "") exitWith {}; private _sideText = if (_side isEqualTo sideEmpty) then { "ALL" } else { _side }; - INFO_2("(Side Chat) %1: %2",_sideText,_msg); + INFO_2("(Side Chat) %1: %2",_sideText,_msg call BIS_fnc_localize); }] call CBA_fnc_addEventHandler; }; @@ -60,7 +64,7 @@ if (hasInterface) then { if (_msg isEqualTo "") exitWith {}; // If side is empty we want to show message to everyone if (_side isEqualTo sideEmpty || {playerSide isEqualTo _side}) then { - [playerSide, "HQ"] sideChat _msg; + [playerSide, "HQ"] sideChat (_msg call BIS_fnc_localize); }; }] call CBA_fnc_addEventHandler; }; diff --git a/addons/common/XEH_preInit.sqf b/addons/common/XEH_preInit.sqf index 68729b87..23165495 100644 --- a/addons/common/XEH_preInit.sqf +++ b/addons/common/XEH_preInit.sqf @@ -26,7 +26,8 @@ if (!GVAR(enabled)) exitWith {}; GVAR(allLocationTypes) = ("true" configClasses (configFile >> "CfgLocationTypes")) apply {configName _x}; // Location names cache namespace (to prevent reading from config every time) -GVAR(locationNames) = call CBA_fnc_createNamespace; +GVAR(locationNames) = createHashMap; +GVAR(locationNamesRaw) = createHashMap; if (isServer) then { GVAR(musicEH) = -1; diff --git a/addons/common/functions/fnc_getLocationName.sqf b/addons/common/functions/fnc_getLocationName.sqf index fdcb7dea..b304d62c 100644 --- a/addons/common/functions/fnc_getLocationName.sqf +++ b/addons/common/functions/fnc_getLocationName.sqf @@ -27,12 +27,12 @@ private _locationClassname = if (_location isEqualType locationNull) then { if (_locationClassname isEqualTo "") exitWith {""}; // Try to get name from cache -private _name = GVAR(locationNames) getVariable [_locationClassname, ""]; +private _name = GVAR(locationNames) getOrDefault [_locationClassname, ""]; if (_name isEqualTo "") then { _name = getText (configFile >> "CfgWorlds" >> worldName >> "Names" >> _locationClassname >> "name"); // Fill cache - GVAR(locationNames) setVariable [_locationClassname, _name]; + GVAR(locationNames) set [_locationClassname, _name]; }; _name diff --git a/addons/common/functions/fnc_getLocationNameRaw.sqf b/addons/common/functions/fnc_getLocationNameRaw.sqf new file mode 100644 index 00000000..acbd8e31 --- /dev/null +++ b/addons/common/functions/fnc_getLocationNameRaw.sqf @@ -0,0 +1,38 @@ +#include "script_component.hpp" +/* + * Author: 3Mydlo3 + * Function returns location name from config. + * + * Arguments: + * 0: Location + * + * Return Value: + * 0: Location name + * + * Example: + * [[player] call afsk_common_fnc_getNearestLocation] call afsk_common_fnc_getLocationName + * + * Public: No + */ + +params ["_location"]; + +private _locationClassname = if (_location isEqualType locationNull) then { + className _location; +} else { + _location +}; + +// Location does not have classname so no name also +if (_locationClassname isEqualTo "") exitWith {""}; + +// Try to get name from cache +private _name = GVAR(locationNamesRaw) getOrDefault [_locationClassname, ""]; + +if (_name isEqualTo "") then { + _name = getTextRaw (configFile >> "CfgWorlds" >> worldName >> "Names" >> _locationClassname >> "name"); + // Fill cache + GVAR(locationNamesRaw) set [_locationClassname, _name]; +}; + +_name diff --git a/addons/killers/XEH_postInit.sqf b/addons/killers/XEH_postInit.sqf index ad20005a..a9227b80 100644 --- a/addons/killers/XEH_postInit.sqf +++ b/addons/killers/XEH_postInit.sqf @@ -69,7 +69,7 @@ if (hasInterface) then { [QGVAR(teleportedToStart), { params ["_flag"]; - private _actionID = player addAction ["Teleport back", { + private _actionID = player addAction [LLSTRING(TeleportBack), { player setPos getPosATL (_this select 3) }, _flag, 10, true]; // Wait until player teleports back or times out diff --git a/addons/killers/functions/fnc_createTeleport.sqf b/addons/killers/functions/fnc_createTeleport.sqf index 3a597f14..94271b76 100644 --- a/addons/killers/functions/fnc_createTeleport.sqf +++ b/addons/killers/functions/fnc_createTeleport.sqf @@ -21,7 +21,7 @@ private _teleportActionsIDs = []; private _positionID = 0; { // _x is location name and value is position assigned - private _destinationName = format ["%1 - %2", _positionID, _x]; + private _destinationName = format ["%1 - %2", _positionID, localize _x]; private _destinationPos = GVAR(startPositions) getVariable _x; private _teleportActionID = _flag addAction [_destinationName, { [QEGVAR(killers,teleport), [_this select 1, _this select 3 select 0]] call CBA_fnc_localEvent; diff --git a/addons/killers/functions/fnc_initStartPositions.sqf b/addons/killers/functions/fnc_initStartPositions.sqf index 7c5536be..8b5378e7 100644 --- a/addons/killers/functions/fnc_initStartPositions.sqf +++ b/addons/killers/functions/fnc_initStartPositions.sqf @@ -31,7 +31,7 @@ while {_i > 0} do { private _nearestLocation = [_pos, 1500] call EFUNC(common,getNearestLocationWithAvailableName); //diag_log format ["[AFSK] [KILLERS] [initStartPositions] Location: %1", _nearestLocation]; if (_nearestLocation isEqualTo locationNull) exitWith {}; - private _locationName = [_nearestLocation] call EFUNC(common,getLocationName); + private _locationName = [_nearestLocation] call EFUNC(common,getLocationNameRaw); if (_locationName isEqualTo "") exitWith {}; //diag_log format ["[AFSK] [KILLERS] [initStartPositions] Location Name: %1", _locationName]; if (!(_positions getVariable [_locationName, []] isEqualTo [])) exitWith {}; @@ -45,12 +45,13 @@ while {_i > 0} do { { private _pos = getPos _x; private _locationName = _x getVariable ["LocationName", ""]; + // TODO: Localize location name (move it to local rather than server) if (_locationName isEqualTo "") then { private _nearestLocation = [_pos] call EFUNC(common,getNearestLocationWithAvailableName); _locationName = if (_nearestLocation isEqualTo locationNull) then { random (999) toFixed 1 } else { - [_nearestLocation] call EFUNC(common,getLocationName); + [_nearestLocation] call EFUNC(common,getLocationNameRaw); }; }; _positions setVariable [_locationName, _pos, true]; diff --git a/addons/killers/stringtable.xml b/addons/killers/stringtable.xml index eed50747..523097ee 100644 --- a/addons/killers/stringtable.xml +++ b/addons/killers/stringtable.xml @@ -17,5 +17,9 @@ How many positions will be available to killers for teleportation on the beginning. 0 or -1 to random [10, 20]. Ile pozycji do teleportacji na starcie będzie dostępnych dla zabójców. 0 lub -1 by wylosować z przedziału [10, 20] + + Teleport back + Teleport z powrotem + diff --git a/addons/main/script_mod.hpp b/addons/main/script_mod.hpp index eb4232df..02171ccf 100644 --- a/addons/main/script_mod.hpp +++ b/addons/main/script_mod.hpp @@ -7,7 +7,7 @@ #define VERSION_STR MAJOR.MINOR.PATCH.BUILD #define VERSION_AR MAJOR,MINOR,PATCH,BUILD -#define REQUIRED_VERSION 1.94 +#define REQUIRED_VERSION 2.08 #ifdef COMPONENT_BEAUTIFIED #define COMPONENT_NAME QUOTE(AFSK - COMPONENT_BEAUTIFIED) diff --git a/addons/missions/SK_test.Malden/mission.sqm b/addons/missions/SK_test.Malden/mission.sqm index af50eea5..50883c4f 100644 --- a/addons/missions/SK_test.Malden/mission.sqm +++ b/addons/missions/SK_test.Malden/mission.sqm @@ -182,7 +182,7 @@ class Mission "STRING" }; }; - value="Chapoi"; + value=""; }; }; }; @@ -255,7 +255,7 @@ class Mission "STRING" }; }; - value="Le Port"; + value=""; }; }; }; @@ -552,7 +552,7 @@ class Mission "STRING" }; }; - value="Kankon"; + value=""; }; }; }; diff --git a/addons/missions/SerialKillers_CUP_RHS.Chernarus/mission.sqm b/addons/missions/SerialKillers_CUP_RHS.Chernarus/mission.sqm index d4112577..de8073dd 100644 --- a/addons/missions/SerialKillers_CUP_RHS.Chernarus/mission.sqm +++ b/addons/missions/SerialKillers_CUP_RHS.Chernarus/mission.sqm @@ -6016,7 +6016,7 @@ class Mission class data { singleType="STRING"; - value="Chernogorsk"; + value=""; }; }; }; @@ -6060,7 +6060,7 @@ class Mission class data { singleType="STRING"; - value="Zelenogorsk"; + value=""; }; }; }; @@ -6105,7 +6105,7 @@ class Mission class data { singleType="STRING"; - value="Elektrozavodsk"; + value=""; }; }; }; @@ -6149,7 +6149,7 @@ class Mission class data { singleType="STRING"; - value="Solnichny"; + value=""; }; }; }; @@ -6193,7 +6193,7 @@ class Mission class data { singleType="STRING"; - value="Vybor"; + value=""; }; }; }; @@ -6237,7 +6237,7 @@ class Mission class data { singleType="STRING"; - value="Gorka"; + value=""; }; }; }; diff --git a/addons/missions/SerialKillers_CUP_RHS.Chernarus_Summer/mission.sqm b/addons/missions/SerialKillers_CUP_RHS.Chernarus_Summer/mission.sqm index d4112577..de8073dd 100644 --- a/addons/missions/SerialKillers_CUP_RHS.Chernarus_Summer/mission.sqm +++ b/addons/missions/SerialKillers_CUP_RHS.Chernarus_Summer/mission.sqm @@ -6016,7 +6016,7 @@ class Mission class data { singleType="STRING"; - value="Chernogorsk"; + value=""; }; }; }; @@ -6060,7 +6060,7 @@ class Mission class data { singleType="STRING"; - value="Zelenogorsk"; + value=""; }; }; }; @@ -6105,7 +6105,7 @@ class Mission class data { singleType="STRING"; - value="Elektrozavodsk"; + value=""; }; }; }; @@ -6149,7 +6149,7 @@ class Mission class data { singleType="STRING"; - value="Solnichny"; + value=""; }; }; }; @@ -6193,7 +6193,7 @@ class Mission class data { singleType="STRING"; - value="Vybor"; + value=""; }; }; }; @@ -6237,7 +6237,7 @@ class Mission class data { singleType="STRING"; - value="Gorka"; + value=""; }; }; }; diff --git a/addons/missions/SerialKillers_CUP_RHS.Chernarus_Winter/mission.sqm b/addons/missions/SerialKillers_CUP_RHS.Chernarus_Winter/mission.sqm index d4112577..de8073dd 100644 --- a/addons/missions/SerialKillers_CUP_RHS.Chernarus_Winter/mission.sqm +++ b/addons/missions/SerialKillers_CUP_RHS.Chernarus_Winter/mission.sqm @@ -6016,7 +6016,7 @@ class Mission class data { singleType="STRING"; - value="Chernogorsk"; + value=""; }; }; }; @@ -6060,7 +6060,7 @@ class Mission class data { singleType="STRING"; - value="Zelenogorsk"; + value=""; }; }; }; @@ -6105,7 +6105,7 @@ class Mission class data { singleType="STRING"; - value="Elektrozavodsk"; + value=""; }; }; }; @@ -6149,7 +6149,7 @@ class Mission class data { singleType="STRING"; - value="Solnichny"; + value=""; }; }; }; @@ -6193,7 +6193,7 @@ class Mission class data { singleType="STRING"; - value="Vybor"; + value=""; }; }; }; @@ -6237,7 +6237,7 @@ class Mission class data { singleType="STRING"; - value="Gorka"; + value=""; }; }; }; diff --git a/addons/modules/CfgVehicles.hpp b/addons/modules/CfgVehicles.hpp index cc5c103f..0c72d354 100644 --- a/addons/modules/CfgVehicles.hpp +++ b/addons/modules/CfgVehicles.hpp @@ -60,8 +60,8 @@ class CfgVehicles { class Attributes: AttributesBase { // Allows police station identification class LocationName: Edit { - displayName = CSTRING(PoliceStation_LocationName); - tooltip = CSTRING(PoliceStation_LocationName_Description); + displayName = CSTRING(LocationName); + tooltip = CSTRING(LocationName_Description); property = "LocationName"; }; // Determine if helicopters can be spawned here @@ -105,8 +105,8 @@ class CfgVehicles { class Attributes: AttributesBase { // Allows killers start positions identification class LocationName: Edit { - displayName = CSTRING(Location_Name); - tooltip = CSTRING(Location_Name_Description); + displayName = CSTRING(LocationName); + tooltip = CSTRING(LocationName_Description); property = "LocationName"; }; class ModuleDescription: ModuleDescription {}; diff --git a/addons/modules/functions/fnc_moduleKillersStart.sqf b/addons/modules/functions/fnc_moduleKillersStart.sqf index 16e64324..ac2bceaa 100644 --- a/addons/modules/functions/fnc_moduleKillersStart.sqf +++ b/addons/modules/functions/fnc_moduleKillersStart.sqf @@ -19,5 +19,11 @@ params ["_module"]; private _locationName = _module getVariable ["LocationName", ""]; if (_locationName isEqualTo "") then { - _module setVariable ["LocationName", [_module] call EFUNC(common,getNearestLocationName)]; + private _nearestLocation = [_module] call EFUNC(common,getNearestLocationWithAvailableName); + _locationName = [_nearestLocation] call EFUNC(common,getLocationNameRaw); + _module setVariable ["LocationName", _locationName]; + + LOG_1("Killers start named automatically: '%1'",_locationName); +} else { + LOG_1("Killers start has forced name: '%1'",_locationName); }; diff --git a/addons/modules/functions/fnc_modulePoliceStation.sqf b/addons/modules/functions/fnc_modulePoliceStation.sqf index 9de1d235..a8b1c1d7 100644 --- a/addons/modules/functions/fnc_modulePoliceStation.sqf +++ b/addons/modules/functions/fnc_modulePoliceStation.sqf @@ -19,5 +19,11 @@ params ["_module"]; private _locationName = _module getVariable ["LocationName", ""]; if (_locationName isEqualTo "") then { - _module setVariable ["LocationName", [_module] call EFUNC(common,getNearestLocationName), true]; + private _nearestLocation = [_module] call EFUNC(common,getNearestLocationWithAvailableName); + _locationName = [_nearestLocation] call EFUNC(common,getLocationNameRaw); + _module setVariable ["LocationName", _locationName, true]; + + LOG_1("Police station named automatically: '%1'",_locationName); +} else { + LOG_1("Police station has forced name: '%1'",_locationName); }; diff --git a/addons/modules/stringtable.xml b/addons/modules/stringtable.xml index 2e9cca24..c2b530ce 100644 --- a/addons/modules/stringtable.xml +++ b/addons/modules/stringtable.xml @@ -1,21 +1,9 @@ - - Police Station - Posterunek Policji - - - Location Name - Nazwa lokacji - - - Location Name. If empty will use nearest map location name. - Nazwa lokacji. Jeżeli puste to użyta zostanie nazwa najbliższej lokacji na mapie. - - - Has helipad - Posiada lądowisko dla helikoptera + + Jail + Więzienie Killers Base @@ -29,9 +17,21 @@ Killers Weapon Stash Skład broni zabójców - - Jail - Więzienie + + Location Name (Optional) + Nazwa lokacji (Opcjonalne) + + + Location Name. If empty will use nearest map location name according to player language. If not empty, the same name will be used for all languages (unless it's stringtable empty starting with $). + Nazwa lokacji. Jeżeli puste to użyta zostanie nazwa najbliższej lokacji na mapie zgodnie z językiem gracza. Jeżeli nie będzie puste, ta sama nazwa pokaże się we wszystkich językach (chyba że będzie zawierać wpis lokalizowalny rozpoczynający się od $). + + + Police Station + Posterunek Policji + + + Has helipad + Posiada lądowisko dla helikoptera diff --git a/addons/police/XEH_PREP.hpp b/addons/police/XEH_PREP.hpp index e47497d4..4c7c7878 100644 --- a/addons/police/XEH_PREP.hpp +++ b/addons/police/XEH_PREP.hpp @@ -9,6 +9,8 @@ PREP(initPoliceStation); PREP(initSpawner); PREP(initPoliceStationClient); PREP(initSaveEquipmentAction); +PREP(isCop); +PREP(isKilledByCop); PREP(policeStationAlarm); PREP(policeStationMarker); PREP(removeVehiclesFromSpawner); diff --git a/addons/police/XEH_postInit.sqf b/addons/police/XEH_postInit.sqf index 71121b90..19125f0e 100644 --- a/addons/police/XEH_postInit.sqf +++ b/addons/police/XEH_postInit.sqf @@ -63,6 +63,11 @@ if (isServer) then { }] call CBA_fnc_addEventHandler; if (hasInterface) then { + + [QGVAR(createPoliceStationMarkerLocal), { + _this call FUNC(policeStationMarker); + }] call CBA_fnc_addEventHandler; + if !(playerSide isEqualTo WEST) exitWith {}; // Fill arsenal with starting items @@ -78,3 +83,14 @@ if (hasInterface) then { [QGVAR(copRespawned), _this] call CBA_fnc_serverEvent; }]; }; + +[QGVAR(showCopKilledNotification), { + private _msg = _this call FUNC(copKilledMsg); + [QEGVAR(common,showSideChatMsg), [WEST, _msg]] call CBA_fnc_localEvent; +}] call CBA_fnc_addEventHandler; + +[QGVAR(showFailedCreatingVehicleNotification), { + params ["_vehicleName", "_baseName"]; + private _msg = format [LLSTRING(FailedCreatingVehicle), _vehicleName call BIS_fnc_localize, _baseName call BIS_fnc_localize]; + [QEGVAR(common,showSideChatMsg), [WEST, _msg]] call CBA_fnc_localEvent; +}] call CBA_fnc_addEventHandler; diff --git a/addons/police/functions/fnc_copKilled.sqf b/addons/police/functions/fnc_copKilled.sqf index e3b8be08..612c0463 100644 --- a/addons/police/functions/fnc_copKilled.sqf +++ b/addons/police/functions/fnc_copKilled.sqf @@ -21,16 +21,26 @@ params ["_unit", "_killer"]; if !(isServer) exitWith {}; private _time = [daytime] call BIS_fnc_timeToString; + +private _isPlayerOrAi = ["AI", "PLAYER"] select isPlayer _killer; +LOG_4("Cop %1 was killed by %2 %3 at %4",name _unit,_isPlayerOrAi,name _killer,_time); + // Call function to create marker at killed unit's position. [_unit, _time] call FUNC(copKilledMarker); // Show message for all cops that cop has been killed near some location with timestamp -private _msg = [_unit, _time] call FUNC(copKilledMsg); -[QEGVAR(common,showSideChatMsg), [WEST, _msg]] call CBA_fnc_globalEvent; +[QGVAR(showcopKilledNotification), [_unit, _killer, _time]] call CBA_fnc_globalEvent; + +// Killer will be null if unit was driving a vehicle and smashed into something, killing itself. +// Killer might also be null when vehicle explodes after unit got out of it, but that's why vehicle check is done. +// It might cause false-positives when a killer rams cops, but cops smashing other cops or trees are much more likely. +// TODO: Confirm that if someone doesn't get out of red hull vehicle in time, but it was damaged by killers beforehand, killer won't be null when vehicle finally explodes. +private _isSuicideInVehicle = isNull _killer && {vehicle _unit isNotEqualTo _unit}; + // Check why unit died and call funcion to change score. -if (side _killer == EAST || {_unit == _killer}) then { - [QEGVAR(score,changeScore), [EAST, EGVAR(score,killedCopKillersScore), "COP KILLED PLACEHOLDER"]] call CBA_fnc_serverEvent; - [QEGVAR(score,changeScore), [WEST, EGVAR(score,killedCopPoliceScore), "COP KILLED PLACEHOLDER"]] call CBA_fnc_serverEvent; +if ([_unit, _killer] call FUNC(isKilledByCop)) then { + [QEGVAR(score,changeScore), [EAST, EGVAR(score,copKilledCopKillersScore), LSTRING(KilledByCop)]] call CBA_fnc_serverEvent; + [QEGVAR(score,changeScore), [WEST, EGVAR(score,copKilledCopPoliceScore), LSTRING(KilledByCop)]] call CBA_fnc_serverEvent; } else { - [QEGVAR(score,changeScore), [EAST, EGVAR(score,copKilledCopKillersScore), "COP KILLED BY COP PLACEHOLDER"]] call CBA_fnc_serverEvent; - [QEGVAR(score,changeScore), [WEST, EGVAR(score,copKilledCopPoliceScore), "COP KILLED BY COP PLACEHOLDER"]] call CBA_fnc_serverEvent; + [QEGVAR(score,changeScore), [EAST, EGVAR(score,killedCopKillersScore), LSTRING(Killed)]] call CBA_fnc_serverEvent; + [QEGVAR(score,changeScore), [WEST, EGVAR(score,killedCopPoliceScore), LSTRING(Killed)]] call CBA_fnc_serverEvent; }; diff --git a/addons/police/functions/fnc_copKilledMarker.sqf b/addons/police/functions/fnc_copKilledMarker.sqf index ae15f444..303806c4 100644 --- a/addons/police/functions/fnc_copKilledMarker.sqf +++ b/addons/police/functions/fnc_copKilledMarker.sqf @@ -20,10 +20,10 @@ params ["_unit", "_time"]; private _markerName = format ["killed_cop_%1_%2", _unit, serverTime]; private _markerText = format ["%1", _time]; -private _marker = createMarker [_markerName, getPosATL _unit]; -_marker setMarkerType "mil_objective"; -_marker setMarkerColor "ColorWEST"; -_marker setMarkerSize [0.4, 0.4]; +private _marker = createMarkerLocal [_markerName, getPosATL _unit]; +_marker setMarkerTypeLocal "mil_objective"; +_marker setMarkerColorLocal "ColorWEST"; +_marker setMarkerSizeLocal [0.4, 0.4]; _marker setMarkerText _markerText; [_marker] call EFUNC(markers,markerDecay); diff --git a/addons/police/functions/fnc_copKilledMsg.sqf b/addons/police/functions/fnc_copKilledMsg.sqf index c3736ae9..181c0528 100644 --- a/addons/police/functions/fnc_copKilledMsg.sqf +++ b/addons/police/functions/fnc_copKilledMsg.sqf @@ -17,27 +17,21 @@ * Public: No */ -params ["_deadCop", ["_timeOfDeath", daytime], ["_nearestTown", locationNull]]; +params ["_unit", "_killer", ["_timeOfDeath", daytime], ["_nearestTown", locationNull]]; if (_timeOfDeath isEqualType 0) then { _timeOfDeath = [_timeOfDeath] call BIS_fnc_timeToString; }; -private _nearestCity = if (isNull _nearestTown) then { - [_deadCop] call EFUNC(civilian,getNearestCity) +// Check if civilian died in city. If so then change output a bit to represent that. +private _template = if ([_unit, _nearestTown] call EFUNC(civilian,isPositionInCity)) then { + if ([_unit, _killer] call FUNC(isKilledByCop)) then { LLSTRING(KilledByCop_In_City) } else { LLSTRING(Killed_In_City) }; } else { - [_nearestTown] call EFUNC(civilian,getCityByLocation) + if ([_unit, _killer] call FUNC(isKilledByCop)) then { LLSTRING(KilledByCop_Near_City) } else { LLSTRING(Killed_Near_City) }; }; -private _msg = ""; -private _nearestCityArea = _nearestCity getVariable QEGVAR(civilian,cityArea); -private _isInCity = (position _deadCop) inArea _nearestCityArea; - -// Check if distance is greater than 250 m. If so then change output a bit to represent that. -if (_isInCity) then { - _msg = format [LLSTRING(Cop_Killed_In_City), _timeOfDeath, text _nearestTown]; -} else { - _msg = format [LLSTRING(Cop_Killed_Near_City), _timeOfDeath, text _nearestTown]; -}; +// Supplying killer name to format, but only killed by cop should reveal name for lynch +private _killerName = if (isNull _killer) then { name _unit } else { name _killer }; +private _msg = format [_template, _timeOfDeath, text _nearestTown, _killerName]; _msg diff --git a/addons/police/functions/fnc_createTeleport.sqf b/addons/police/functions/fnc_createTeleport.sqf index 0009bdaf..b3b2f067 100644 --- a/addons/police/functions/fnc_createTeleport.sqf +++ b/addons/police/functions/fnc_createTeleport.sqf @@ -19,9 +19,9 @@ params ["_flag"]; private _logic = _flag getVariable ["policeStation", objNull]; { - if !(_logic isEqualTo _x) then { + if (_logic isNotEqualTo _x) then { private _destinationName = _x getVariable ["LocationName", "Teleport"]; - _flag addAction [_destinationName, { + _flag addAction [_destinationName call BIS_fnc_localize, { [QGVAR(teleport), [_this select 0, _this select 1, _this select 3 select 0]] call CBA_fnc_serverEvent; }, [_x]]; }; diff --git a/addons/police/functions/fnc_initPoliceStation.sqf b/addons/police/functions/fnc_initPoliceStation.sqf index 8dafd2d9..eb50df66 100644 --- a/addons/police/functions/fnc_initPoliceStation.sqf +++ b/addons/police/functions/fnc_initPoliceStation.sqf @@ -39,9 +39,10 @@ GVAR(arsenals) pushBack _box; [_box] call FUNC(initSpawner); // Create marker -private _marker = [_baseName, _basePos] call FUNC(policeStationMarker); -_logic setVariable ["Marker", _marker]; +[QGVAR(createPoliceStationMarkerLocal), [_baseName, _basePos]] call CBA_fnc_globalEventJIP; // Create teleporter _logic setVariable ["Teleporter", _flag, true]; [QGVAR(createTeleport), [_flag]] call CBA_fnc_globalEventJIP; + +LOG_1("Initialized police station %1",_baseName); diff --git a/addons/police/functions/fnc_isCop.sqf b/addons/police/functions/fnc_isCop.sqf new file mode 100644 index 00000000..3439aaeb --- /dev/null +++ b/addons/police/functions/fnc_isCop.sqf @@ -0,0 +1,22 @@ +#include "script_component.hpp" +/* + * Author: 3Mydlo3 + * Function checks whether given unit is a cop. + * + * Arguments: + * 0: Unit + * + * Return Value: + * True if unit is a cop + * + * Example: + * [player] call afsk_police_fnc_isCop + * + * Public: No + */ + +params ["_unit"]; + +if (isNull _unit) exitWith { false }; + +_unit getVariable [QEGVAR(common,side), CIVILIAN] isEqualTo WEST diff --git a/addons/police/functions/fnc_isKilledByCop.sqf b/addons/police/functions/fnc_isKilledByCop.sqf new file mode 100644 index 00000000..46d8b3b9 --- /dev/null +++ b/addons/police/functions/fnc_isKilledByCop.sqf @@ -0,0 +1,27 @@ +#include "script_component.hpp" +/* + * Author: 3Mydlo3 + * Function checks whether given unit died due to cop actions. + * + * Arguments: + * 0: Unit + * 1: Killer + * + * Return Value: + * True if unit was killed by cop. + * + * Example: + * [player] call afsk_police_fnc_isKilledByCop + * + * Public: No + */ + +params ["_unit", "_killer"]; + +// Killer will be null if unit was driving a vehicle and smashed into something, killing itself. +// Killer might also be null when vehicle explodes after unit got out of it, but that's why vehicle check is done. +// If a vehicle has a red hull and explodes, it will be a killer, that's fine that it won't be counted as a suicide. +// It might cause false-positives when a killer rams cops, but cops smashing other cops or trees are much more likely. +private _isSuicideInVehicle = isNull _killer && {vehicle _unit isNotEqualTo _unit}; + +_isSuicideInVehicle || {[_killer] call FUNC(isCop)} diff --git a/addons/police/functions/fnc_policeStationMarker.sqf b/addons/police/functions/fnc_policeStationMarker.sqf index 5114f83e..e90dc9a2 100644 --- a/addons/police/functions/fnc_policeStationMarker.sqf +++ b/addons/police/functions/fnc_policeStationMarker.sqf @@ -19,10 +19,12 @@ params ["_baseName", "_basePos"]; private _markerName = format ["policeStation_%1", _baseName]; -private _markerText = format ["%1", _baseName]; -private _marker = createMarker [_markerName, _basePos]; -_marker setMarkerType "mil_flag"; -_marker setMarkerColor "ColorWEST"; -_marker setMarkerText _markerText; +private _markerText = format ["%1", _baseName call BIS_fnc_localize]; +private _marker = createMarkerLocal [_markerName, _basePos]; +_marker setMarkerTypeLocal "mil_flag"; +_marker setMarkerColorLocal "ColorWEST"; +_marker setMarkerTextLocal _markerText; + +LOG_2("Created local police station marker %1 with text %2",_markerName,_markerText); _marker diff --git a/addons/police/functions/fnc_spawnVehicle.sqf b/addons/police/functions/fnc_spawnVehicle.sqf index b9e41432..9689337f 100644 --- a/addons/police/functions/fnc_spawnVehicle.sqf +++ b/addons/police/functions/fnc_spawnVehicle.sqf @@ -27,17 +27,19 @@ private _spawnPoints = if (_vehicleType isEqualTo "Helicopter" || {_vehicleType +(_spawner getVariable QGVAR(spawnPoints)) }; +private _fnc_noEmptyPositionMsg = { + params ["_vehicleClassname", "_spawner"]; + private _baseName = (_spawner getVariable "policeStation") getVariable "LocationName"; + private _vehicleName = getTextRaw (configFile >> "CfgVehicles" >> _vehicleClassname >> "displayName"); + [QGVAR(showFailedCreatingVehicleNotification), [_vehicleName, _baseName]] call CBA_fnc_globalEvent; +}; + // Find spawn position private _position = []; private _direction = 0; private _emptySpawnPointIndex = _spawnPoints findIf {getPosATL _x nearEntities SPAWNPOINT_SAFEZONE isEqualTo []}; -if (_emptySpawnPointIndex isNotEqualTo -1) then { - LOG("Found empty spawnpoint"); - private _spawnPoint = _spawnPoints select _emptySpawnPointIndex; - _position = getPosATL _spawnPoint; - _direction = getDir _spawnPoint; -} else { +if (_emptySpawnPointIndex isEqualTo -1) exitWith { // Maybe there is a position that has unoccupied vehicle LOG("Looking for unoccupied vehicles"); private _fullSpawnPointsWithoutCrew = _spawnPoints select { @@ -46,33 +48,33 @@ if (_emptySpawnPointIndex isNotEqualTo -1) then { _nearEntities findIf {crew _x isEqualTo []} isNotEqualTo -1 }; - if (_fullSpawnPointsWithoutCrew isNotEqualTo []) exitWith { - LOG("Found unoccupied vehicles"); - private _spawnPoint = [_fullSpawnPointsWithoutCrew] call EFUNC(common,deleteAtRandom); + if (_fullSpawnPointsWithoutCrew isEqualTo []) exitWith { + [_vehicleClassname, _spawner] call _fnc_noEmptyPositionMsg; + }; - // Clear the area - LOG("Deleting vehicles"); - _spawnPoint nearEntities SPAWNPOINT_SAFEZONE - apply { - TRACE_1("Deleting vehicle %1",typeOf _x); - deleteVehicle _x; - }; + LOG("Found unoccupied vehicles"); + private _spawnPoint = [_fullSpawnPointsWithoutCrew] call EFUNC(common,deleteAtRandom); - _position = getPosATL _spawnPoint; - _direction = getDir _spawnPoint; - }; -}; + // Clear the area + LOG("Deleting vehicles"); + _spawnPoint nearEntities SPAWNPOINT_SAFEZONE + apply { + TRACE_1("Deleting vehicle %1",typeOf _x); + deleteVehicle _x; + }; -if (_position isNotEqualTo []) then { - _position = _position findEmptyPosition [0, SPAWNPOINT_SAFEZONE, _vehicleClassname]; + // execNextFrame is too low delay for findEmptyPosition to recognize that a vehicle was deleted + [FUNC(spawnVehicle), _this, 0.1] call CBA_fnc_waitAndExecute; }; +LOG("Found empty spawnpoint"); +private _spawnPoint = _spawnPoints select _emptySpawnPointIndex; +private _position = getPosATL _spawnPoint findEmptyPosition [0, SPAWNPOINT_SAFEZONE, _vehicleClassname]; +_direction = getDir _spawnPoint; + // Show message if no empty spawn position if (_position isEqualTo []) exitWith { - private _baseName = (_spawner getVariable "policeStation") getVariable "LocationName"; - private _vehicleName = getText (configFile >> "CfgVehicles" >> _vehicleClassname >> "displayName"); - private _msg = format ["Cannot create %1 at %2.", _vehicleName, _baseName]; - [QEGVAR(common,showSideChatMsg), [WEST, _msg]] call CBA_fnc_globalEvent; + [_vehicleClassname, _spawner] call _fnc_noEmptyPositionMsg; }; // Spawn vehicle diff --git a/addons/police/stringtable.xml b/addons/police/stringtable.xml index d36a4ca1..509a8474 100644 --- a/addons/police/stringtable.xml +++ b/addons/police/stringtable.xml @@ -17,14 +17,34 @@ It was a bad idea... To był zły pomysł... - + Cop was killed at %1 in %2! Policjant został zabity o godzinie %1 w %2! - + Cop was killed at %1 near %2! Policjant został zabity o godzinie %1 w pobliżu %2! + + Cop was killed by cop %3 at %1 in %2! + Policjant został zabity przez policjanta %3 o godzinie %1 w %2! + + + Cop was killed by cop %3 at %1 near %2! + Policjant został zabity przez policjanta %3 o godzinie %1 w pobliżu %2! + + + Cop was killed + Policjant został zabity + + + Cop was killed by cop + Policjant został zabity przez policjanta + + + Cannot create %1 at %2. + Nie można utworzyć %1 w %2. + Save equipment for respawn Zapisz ekwipunek do odrodzenia diff --git a/addons/score/CfgDebriefing.hpp b/addons/score/CfgDebriefing.hpp index 8987ade7..e470c22f 100644 --- a/addons/score/CfgDebriefing.hpp +++ b/addons/score/CfgDebriefing.hpp @@ -15,6 +15,9 @@ class CfgDebriefing { title = CSTRING(Police_Win); subtitle = CSTRING(Killers_Dead); }; + class GVAR(timeLimit): GVAR(killersDead) { + subtitle = CSTRING(TimeLimit_Reached); + }; class GVAR(timeoutLimit): GVAR(killersDead) { subtitle = CSTRING(Timeout_Limit); }; diff --git a/addons/score/XEH_PREP.hpp b/addons/score/XEH_PREP.hpp index 07d4c422..8e684c45 100644 --- a/addons/score/XEH_PREP.hpp +++ b/addons/score/XEH_PREP.hpp @@ -3,6 +3,8 @@ PREP(addPoliceScore); PREP(changeScore); PREP(endMissionClient); PREP(endMissionServer); +PREP(extraTimeAdjustRules); +PREP(getIdleTimeRulesMessage); PREP(monitorTimeLimit); PREP(monitorTimeouts); PREP(showScore); diff --git a/addons/score/XEH_postInit.sqf b/addons/score/XEH_postInit.sqf index 61c2eda4..80acc2a3 100644 --- a/addons/score/XEH_postInit.sqf +++ b/addons/score/XEH_postInit.sqf @@ -36,15 +36,20 @@ if (isServer) then { // Initialize score display UI [WEST, 0] call BIS_fnc_respawnTickets; [EAST, 0] call BIS_fnc_respawnTickets; + + call FUNC(monitorTimeLimit); }; [QGVAR(scoreChanged), { - params ["_side", "_change", ["_reason", ""]]; + params ["_side", "_change", ["_reason", "", ["", []]]]; [QGVAR(showScore), [_reason]] call CBA_fnc_localEvent; }] call CBA_fnc_addEventHandler; if (hasInterface) then { + // Disable vanilla ratings + player addEventHandler ["HandleRating", { 0 }]; + /* Clientside events */ [QGVAR(endMission), { _this call FUNC(endMissionClient); @@ -56,17 +61,25 @@ if (hasInterface) then { [QGVAR(showTimeoutInitialMessage), { private _msg = composeText [ - text format [LLSTRING(IdleTime_Inital_Message), (GVAR(IdleTimeMax) / 60)], + text format [LLSTRING(IdleTime_InitalMessage), (GVAR(IdleTimeMax) / 60)], lineBreak, + call FUNC(getIdleTimeRulesMessage) + ]; + _msg setAttributes ["valign", "middle"]; + _msg setAttributes ["align", "center"]; + [QEGVAR(common,showMessage), [_msg, [6]]] call CBA_fnc_localEvent; + }] call CBA_fnc_addEventHandler; + + [QGVAR(showExtraTimeInitialMessage), { + private _msg = composeText [ + text LLSTRING(ExtraTime_StartedMessageHeader), lineBreak, - text format ["%1: %2", LELSTRING(killers,Killers), GVAR(idleTimeKillersScoreChange)], + text format [LLSTRING(TimeRemaining), GVAR(timeLimitExtraTime)], lineBreak, - text format ["%1: %2", LELSTRING(police,Police), GVAR(idleTimePoliceScoreChange)] + call FUNC(getIdleTimeRulesMessage) ]; _msg setAttributes ["valign", "middle"]; - [QEGVAR(common,showMessage), [_msg, [3]]] call CBA_fnc_localEvent; + _msg setAttributes ["align", "center"]; + [QEGVAR(common,showMessage), [_msg, [6]]] call CBA_fnc_localEvent; }] call CBA_fnc_addEventHandler; - - // Disable vanilla ratings - player addEventHandler ["HandleRating", { 0 }]; }; diff --git a/addons/score/XEH_preInit.sqf b/addons/score/XEH_preInit.sqf index 1cc34f41..aedde0cd 100644 --- a/addons/score/XEH_preInit.sqf +++ b/addons/score/XEH_preInit.sqf @@ -20,6 +20,7 @@ GVAR(policeScoreLastChangeTime) = CBA_missionTime; GVAR(killersScoreLastChangeTime) = CBA_missionTime; // Idle timeouts counter GVAR(idleTimeouts) = 0; +GVAR(isExtraTime) = false; // Mission end flag GVAR(missionEnd) = -1; diff --git a/addons/score/functions/fnc_addKillersScore.sqf b/addons/score/functions/fnc_addKillersScore.sqf index 476ed4f0..2dda71f2 100644 --- a/addons/score/functions/fnc_addKillersScore.sqf +++ b/addons/score/functions/fnc_addKillersScore.sqf @@ -33,13 +33,14 @@ publicVariable QGVAR(killersScoreChange); // Save change time GVAR(killersScoreLastChangeTime) = CBA_missionTime; -// Keep last score change for 5 seconds to "stack it" visually if many events occur in short succession. +// Keep last score change for some time to "stack it" visually if many events occur in short succession. +// Using (5 + score change) seconds so that the more score changed, the longer it's stacked. [{ if (GVAR(killersScoreChange) isEqualTo (_this select 0)) then { GVAR(killersScoreChange) = 0; publicVariable QGVAR(killersScoreChange); }; -}, [GVAR(killersScoreChange)], 5] call CBA_fnc_waitAndExecute; +}, [GVAR(killersScoreChange)], 5 + GVAR(killersScoreChange)] call CBA_fnc_waitAndExecute; // Check if killers have reached their goal if (GVAR(killersScore) >= GVAR(killersScoreMax)) then { diff --git a/addons/score/functions/fnc_changeScore.sqf b/addons/score/functions/fnc_changeScore.sqf index e5e71a3b..ccf594ea 100644 --- a/addons/score/functions/fnc_changeScore.sqf +++ b/addons/score/functions/fnc_changeScore.sqf @@ -17,7 +17,7 @@ * Public: No */ -params ["_side", "_change", ["_reason", ""]]; +params ["_side", "_change", ["_reason", "", ["", []]]]; private _previousScore = [_side] call FUNC(getSideScore); @@ -29,12 +29,23 @@ if (_side isEqualTo WEST) then { private _newScore = [_side] call FUNC(getSideScore); +private _finalReason = ""; + if (_reason isEqualTo "") then { INFO_4("Changed score for %1: %2 + %3 = %4",_side,_previousScore,_change,_newScore); } else { - INFO_5("Changed score for %1: %2 + %3 = %4, caused by %5",_side,_previousScore,_change,_newScore,_reason); + if (_reason isEqualType []) then { + // BUG: This doesn't work + private _formatArray = [_reason select 0 call BIS_fnc_localize]; + _formatArray append (_reason select [1, count _reason - 1]); + _finalReason = format _formatArray; + } else { + _finalReason = _reason; + }; + + INFO_5("Changed score for %1: %2 + %3 = %4, caused by %5",_side,_previousScore,_change,_newScore,_finalReason); }; -[QGVAR(scoreChanged), [_side, _change, _newScore, _reason]] call CBA_fnc_globalEvent; +[QGVAR(scoreChanged), [_side, _change, _newScore, _finalReason]] call CBA_fnc_globalEvent; _newScore diff --git a/addons/score/functions/fnc_endMissionClient.sqf b/addons/score/functions/fnc_endMissionClient.sqf index dcf9bb62..41d0d9d6 100644 --- a/addons/score/functions/fnc_endMissionClient.sqf +++ b/addons/score/functions/fnc_endMissionClient.sqf @@ -40,7 +40,7 @@ switch (_endType) do { // 3 case TIME_LIMIT_REACHED: { private _win = if (playerSide isEqualTo WEST) then {true} else {false}; - [QGVAR(timeoutLimit), _win, nil, false] call BIS_fnc_endMission; + [QGVAR(timeLimit), _win, nil, false] call BIS_fnc_endMission; }; // 4 case ALL_CIVILIANS_DEAD: { diff --git a/addons/score/functions/fnc_extraTimeAdjustRules.sqf b/addons/score/functions/fnc_extraTimeAdjustRules.sqf new file mode 100644 index 00000000..2e79205a --- /dev/null +++ b/addons/score/functions/fnc_extraTimeAdjustRules.sqf @@ -0,0 +1,21 @@ +#include "script_component.hpp" +/* + * Author: 3Mydlo3 + * Function adjusts settings for extra time. + * + * Arguments: + * + * Return Value: + * None + * + * Example: + * None + * + * Public: No + */ + +GVAR(idleTimeMax) = GVAR(extraTimeIdleTime); +GVAR(idleTimeouts) = 0; +GVAR(idleTimeoutsMax) = GVAR(extraTimeIdleTimeoutsMax); +GVAR(idleTimeKillersScoreChange) = GVAR(extraTimeKillersScoreChange); +GVAR(idleTimePoliceScoreChange) = GVAR(extraTimePoliceScoreChange); diff --git a/addons/score/functions/fnc_getIdleTimeRulesMessage.sqf b/addons/score/functions/fnc_getIdleTimeRulesMessage.sqf new file mode 100644 index 00000000..6f111b82 --- /dev/null +++ b/addons/score/functions/fnc_getIdleTimeRulesMessage.sqf @@ -0,0 +1,32 @@ +#include "script_component.hpp" +/* + * Author: 3Mydlo3 + * Function prepares message with idle time settings + * + * Arguments: + * None + * + * Return Value: + * Structured text message + * + * Example: + * None + * + * Public: No + */ + +private _idleTimeMaxAllowedMsg = [ + composeText [lineBreak, text format [LLSTRING(IdleTimeMaxAllowed), GVAR(idleTimeoutsMax)]], + "" +] select (GVAR(idleTimeoutsMax) isEqualTo -1); + +composeText [ + text format [LLSTRING(IdleTimeAllowed), GVAR(idleTimeMax)], + _idleTimeMaxAllowedMsg, + lineBreak, + text LLSTRING(IdleTimeScoreChanges), + lineBreak, + text format ["%1: %2", LELSTRING(police,Police), GVAR(idleTimePoliceScoreChange)], + lineBreak, + text format ["%1: %2", LELSTRING(killers,Killers), GVAR(idleTimeKillersScoreChange)] +] diff --git a/addons/score/functions/fnc_monitorTimeLimit.sqf b/addons/score/functions/fnc_monitorTimeLimit.sqf index cb5d00c1..6161f0ba 100644 --- a/addons/score/functions/fnc_monitorTimeLimit.sqf +++ b/addons/score/functions/fnc_monitorTimeLimit.sqf @@ -14,15 +14,42 @@ * Public: No */ +if (GVAR(timeLimit) isEqualTo -1) exitWith { + INFO("Time limit is disabled"); +}; + [{ + // Check if mission didn't end yet + if (GVAR(missionEnd) isNotEqualTo -1) exitWith {}; + + // Instant end if (GVAR(timeLimitInstantEnd)) exitWith { + INFO("Time limit reached, extra time is disabled, ending mission"); [QGVAR(endMission), [TIME_LIMIT_REACHED]] call CBA_fnc_globalEvent; }; + + GVAR(isExtraTime) = true; + // Adjust rules - GVAR(idleTimeMax) = GVAR(timeLimitIdleTime); - GVAR(idleTimeouts) = 0; - GVAR(idleTimeoutsMax) = GVAR(timeLimitIdleTimeoutsMax); - [{ - [QGVAR(endMission), [TIME_LIMIT_REACHED]] call CBA_fnc_globalEvent; - }, [], (GVAR(timeLimitExtraTime) * 60)] call CBA_fnc_waitAndExecute; + call FUNC(extraTimeAdjustRules); + + // Extra time countdown if enabled + if (GVAR(timeLimitExtraTime) isNotEqualTo -1) exitWith { + private _extraTimeDurationInMinutes = GVAR(timeLimitExtraTime) * 60; + + [{ + INFO("Extra time limit reached"); + [QGVAR(endMission), [TIME_LIMIT_REACHED]] call CBA_fnc_globalEvent; + }, [], _extraTimeDurationInMinutes] call CBA_fnc_waitAndExecute; + + INFO_1("Extra time limit of %1 minutes has started",_extraTimeDurationInMinutes); + + [QGVAR(showExtraTimeInitialMessage)] call CBA_fnc_globalEvent; + }; + + INFO("No extra time limit, changed rules apply"); + + [QGVAR(showTimeoutInitialMessage)] call CBA_fnc_globalEvent; }, [], (GVAR(timeLimit) * 60)] call CBA_fnc_waitAndExecute; + +INFO_1("Enabled time limit of %1 minutes",GVAR(timeLimit) * 60); diff --git a/addons/score/functions/fnc_monitorTimeouts.sqf b/addons/score/functions/fnc_monitorTimeouts.sqf index 9c7c47b4..6bbb9800 100644 --- a/addons/score/functions/fnc_monitorTimeouts.sqf +++ b/addons/score/functions/fnc_monitorTimeouts.sqf @@ -23,15 +23,18 @@ if (GVAR(idleTimeouts) >= GVAR(idleTimeoutsMax)) exitWith { }; if (GVAR(killersScoreChange) isEqualTo 0) then { - [{GVAR(killersScoreChange) > 0}, { + private _isExtraTime = GVAR(isExtraTime); + + [{GVAR(killersScoreChange) > 0 || {(_this select 0) isNotEqualTo GVAR(isExtraTime)}}, { // Killers managed to increase their score within time limit + // Or extra time has started and we need to restart to adjust for new rules. call FUNC(monitorTimeouts); - }, [], GVAR(idleTimeMax), { + }, [_isExtraTime], GVAR(idleTimeMax), { // Killers failed to increase their score within time limit GVAR(idleTimeouts) = GVAR(idleTimeouts) + 1; - private _msg = format [LLSTRING(IdleTime_TimeoutReached), GVAR(idleTimeouts), GVAR(idleTimeoutsMax)]; - [QGVAR(changeScore), [EAST, 0, _msg]] call CBA_fnc_serverEvent; - [QGVAR(changeScore), [WEST, 5, _msg]] call CBA_fnc_serverEvent; + private _msg = [LSTRING(IdleTime_TimeoutReached), GVAR(idleTimeouts), GVAR(idleTimeoutsMax)]; + [QGVAR(changeScore), [EAST, GVAR(idleTimeKillersScoreChange), _msg]] call CBA_fnc_serverEvent; + [QGVAR(changeScore), [WEST, GVAR(idleTimePoliceScoreChange), _msg]] call CBA_fnc_serverEvent; call FUNC(monitorTimeouts); }] call CBA_fnc_waitUntilAndExecute; } else { diff --git a/addons/score/functions/fnc_showScore.sqf b/addons/score/functions/fnc_showScore.sqf index e211b1a1..74c362c9 100644 --- a/addons/score/functions/fnc_showScore.sqf +++ b/addons/score/functions/fnc_showScore.sqf @@ -16,7 +16,7 @@ * Public: No */ -params [["_extraText", ""]]; +params [["_extraText", "", ["", []]]]; private _fnc_determineSign = { params ["_value"]; @@ -45,6 +45,10 @@ _msgPolice setAttributes ["align", "center"]; private _msgPoliceScore = text format ["%1/%2 (%4%3)", GVAR(policeScore), GVAR(policeScoreMax), GVAR(policeScoreChange), [GVAR(policeScoreChange)] call _fnc_determineSign]; _msgPoliceScore setAttributes ["align", "center"]; +if (_extraText isEqualType []) then { + _extraText = format ([_extraText select 0 call BIS_fnc_localize] append _extraText select [1, count _extraText - 1]); +}; + private _msg = composeText [ _msgHour, _separator, @@ -57,7 +61,7 @@ private _msg = composeText [ lineBreak, _msgPoliceScore, lineBreak, - _extraText + _extraText call BIS_fnc_localize ]; _msg setAttributes ["valign", "middle"]; diff --git a/addons/score/initSettings.inc.sqf b/addons/score/initSettings.inc.sqf index 63e5ade0..8e85e6b2 100644 --- a/addons/score/initSettings.inc.sqf +++ b/addons/score/initSettings.inc.sqf @@ -90,7 +90,7 @@ "SLIDER", [LSTRING(TimeLimit), LSTRING(TimeLimit_Description)], [LSTRING(DisplayName), LSTRING(TimeLimit)], - [-1, 120, 45, 0], + [-1, 120, 30, 0], true, {}, true @@ -105,35 +105,7 @@ true ] call CBA_fnc_addSetting; -[ - QGVAR(timeLimitExtraTime), - "SLIDER", - [LSTRING(TimeLimit_ExtraTime), LSTRING(TimeLimit_ExtraTime_Description)], - [LSTRING(DisplayName), LSTRING(TimeLimit)], - [-1, 120, 15, 0], - true -] call CBA_fnc_addSetting; - // Idle Time - -[ - QGVAR(timeLimitIdleTime), - "SLIDER", - [LSTRING(IdleTimeMax), LSTRING(TimeLimit_IdleTime_Description)], - [LSTRING(DisplayName), LSTRING(TimeLimit)], - [-1, 900, 150, 0], - true -] call CBA_fnc_addSetting; - -[ - QGVAR(timeLimitIdleTimeoutsMax), - "SLIDER", - [LSTRING(IdleTimeoutsMax), LSTRING(TimeLimit_IdleTimeoutsMax_Description)], - [LSTRING(DisplayName), LSTRING(TimeLimit)], - [-1, 10, 1, 0], - true -] call CBA_fnc_addSetting; - [ QGVAR(idleTimeMax), "SLIDER", @@ -178,3 +150,53 @@ true ] call CBA_fnc_addSetting; + +// Extra time +[ + QGVAR(timeLimitExtraTime), + "SLIDER", + [LSTRING(ExtraTime_Duration), LSTRING(ExtraTime_Duration_Description)], + [LSTRING(DisplayName), LSTRING(ExtraTime)], + [-1, 120, 15, 0], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(extraTimeIdleTime), + "SLIDER", + [LSTRING(IdleTimeMax), LSTRING(ExtraTime_IdleTime_Description)], + [LSTRING(DisplayName), LSTRING(ExtraTime)], + [-1, 900, 150, 0], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(extraTimeIdleTimeoutsMax), + "SLIDER", + [LSTRING(IdleTimeoutsMax), LSTRING(ExtraTime_IdleTimeoutsMax_Description)], + [LSTRING(DisplayName), LSTRING(ExtraTime)], + [-1, 10, 5, 0], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(extraTimePoliceScoreChange), + "SLIDER", + [LSTRING(ExtraTime_IdleTimePoliceScoreChange), LSTRING(ExtraTime_IdleTimePoliceScoreChange_Description)], + [LSTRING(DisplayName), LSTRING(ExtraTime)], + [-10, 10, 2, 0], + true, + {}, + true +] call CBA_fnc_addSetting; + +[ + QGVAR(extraTimeKillersScoreChange), + "SLIDER", + [LSTRING(ExtraTime_IdleTimeKillersScoreChange), LSTRING(ExtraTime_IdleTimeKillersScoreChange_Description)], + [LSTRING(DisplayName), LSTRING(ExtraTime)], + [-10, 10, 0, 0], + true, + {}, + true +] call CBA_fnc_addSetting; diff --git a/addons/score/stringtable.xml b/addons/score/stringtable.xml index e41225c4..a0cb28db 100644 --- a/addons/score/stringtable.xml +++ b/addons/score/stringtable.xml @@ -94,14 +94,6 @@ Timeout between kills Odstęp czasu pomiędzy zabójstwami - - From now on killers must keep killing within %1 minutes since last kill or they will face penalty. - Od tego momentu zabójcy muszą zabić w ciągu %1 minut od ostatniego zabójstwa albo otrzymają karę. - - - Maximum idle time reached %1/%2 - Maksymalny odstęp czasu pomiędzy zabójstwami przekroczony %1/%2 - Maximum number of timeouts Maksymalna liczba przekroczeń limitu czasu @@ -153,6 +145,10 @@ All killers are either dead or in custody. Wszyscy zabójcy są martwi albo w więzieniu. + + Mission time limit reached + Osiągnięty limit czasu misji + Timeouts limit reached Osiągnięty limit przekroczeń limitu czasu @@ -169,32 +165,86 @@ Limit czasu misji - After this time (in minutes) rules change accordingly to other settings in this category. - Po tym czasie (w minutach) zasady zmieniają się zgodnie z innymi ustawieniami w tej kategorii. + After this time (in minutes) rules change accordingly to other settings in this category. Set to -1 to disable. + Po tym czasie (w minutach) zasady zmieniają się zgodnie z innymi ustawieniami w tej kategorii. Ustaw na -1 by wyłączyć. Instant lose Natychmiastowa przegrana - Police instantly wins scenario. Overrides everything in this category. - Natychmiast kończy scenariusz zwycięstwem policji. Pozostałe ustawienia nie mają żadnego wpływu. + Police instantly wins scenario. Overrides extra time settings. + Natychmiast kończy scenariusz zwycięstwem policji. Nadpisuje ustawienia dogrywki. - + + + Extra time + Dogrywka + + Maximum extra time duration Maksymalna długość dogrywki - - After this additional time mission instantly ends with police victory. - Po tym dodatkowym czasie misja kończy się Natychmiastowym zwycięstwem policji. + + After this additional time mission instantly ends with police victory. Set to -1 to disable. + Po tym dodatkowym czasie misja kończy się Natychmiastowym zwycięstwem policji. Ustaw na -1 by wyłączyć. - + Maximum timeout is adjusted to this value. Maksymalny odstęp czasu między zabójstwami zostaje zmieniony do tej wartości. - + Maximum number of timeouts is adjusted to this value. Maksymalna liczba przekroczeń limitu czasu zostaje zmieniona do tej wartości. + + Police score change during extra time + Zmiana wyniku policji po przekroczeniu limitu czasu w dogrywce + + + Police gets this many points on timeout during extra time. + Po upłynięciu maksymalnego czasu pomiędzy zabójstwami podczas dogrywki policja dostanie tyle punktów. + + + Killers score change during extra time + Zmiana wyniku zabójców po przekroczeniu limitu czasu w dogrywce + + + Killers get this many points on timeout during extra time. + Po upłynięciu maksymalnego czasu pomiędzy zabójstwami podczas dogrywki policja dostanie tyle punktów. + + + + From now on killers must keep killing within %1 minutes since last kill or they will face penalty. + Od tego momentu zabójcy muszą zabić w ciągu %1 minut od ostatniego zabójstwa albo otrzymają karę. + + + Maximum idle time reached %1/%2 + Maksymalny odstęp czasu pomiędzy zabójstwami przekroczony %1/%2 + + + Extra time has started + Rozpoczęła się dogrywka + + + Remaining time left: %1 min + Pozostały czas: %1 min + + + Allowed idle time: %1 s + Dozwolony czas bezczynności: %1 s + + + Maximum idle times: %1 + Maksymalnie %1 razy bezczynności + + + Score changes on idle time + Zmiany wyniku po bezczynności + diff --git a/addons/vehicles/XEH_postInit.sqf b/addons/vehicles/XEH_postInit.sqf index dbdca032..837ffb16 100644 --- a/addons/vehicles/XEH_postInit.sqf +++ b/addons/vehicles/XEH_postInit.sqf @@ -27,3 +27,8 @@ if (hasInterface) then { [_vehicle, true, GVAR(alarmDuration)] call FUNC(carAlarmLoop); }] call CBA_fnc_addEventHandler; }; + +[QGVAR(showCarAlarmNotification), { + private _msg = _this call FUNC(vehicleStolenMsg); + [QEGVAR(common,showSideChatMsg), [WEST, _msg]] call CBA_fnc_localEvent; +}] call CBA_fnc_addEventHandler; diff --git a/addons/vehicles/functions/fnc_carAlarmNotification.sqf b/addons/vehicles/functions/fnc_carAlarmNotification.sqf index 0d2bac97..3a2e06ad 100644 --- a/addons/vehicles/functions/fnc_carAlarmNotification.sqf +++ b/addons/vehicles/functions/fnc_carAlarmNotification.sqf @@ -29,7 +29,7 @@ private _notify = if (GVAR(alarmCopsNotification) isEqualTo 1) then { // Notify only if civilians nearby (alarmAudibleDistance/2 as no one would really care about an alarm far from him) private _nearbyUnits = _vehicle nearEntities ["Man", GVAR(alarmAudibleDistance)/2]; private _anyNearbyUnrestrainedCivilians = _nearbyUnits - findIf {alive _x && {side _x isEqualTo CIVILIAN_SIDE && {!([_x] call EFUNC(jail,isHandcuffed))}}} != -1; + findIf {alive _x && {side _x isEqualTo CIVILIAN && {!([_x] call EFUNC(jail,isHandcuffed))}}} != -1; if (_anyNearbyUnrestrainedCivilians) then { true } else { false }; }; @@ -37,7 +37,7 @@ private _notify = if (GVAR(alarmCopsNotification) isEqualTo 1) then { if (_notify) exitWith { LOG("Cops are notified about a car alarm."); - [QEGVAR(common,showSideChatMsg), [WEST, _this call FUNC(vehicleStolenMsg)]] call CBA_fnc_globalEvent; + [QGVAR(showCarAlarmNotification), [_vehicle]] call CBA_fnc_globalEvent; true }; diff --git a/addons/vehicles/functions/fnc_vehicleStolenMsg.sqf b/addons/vehicles/functions/fnc_vehicleStolenMsg.sqf index 8a0134f3..221b5fba 100644 --- a/addons/vehicles/functions/fnc_vehicleStolenMsg.sqf +++ b/addons/vehicles/functions/fnc_vehicleStolenMsg.sqf @@ -23,19 +23,21 @@ if (_timeOfTheft isEqualType 0) then { _timeOfTheft = [_timeOfTheft] call BIS_fnc_timeToString; }; -if (isNull _nearestTown) then { - _nearestTown = [_stolenVehicle] call EFUNC(common,getNearestCityLocation); +private _nearestCity = if (isNull _nearestTown) then { + [_stolenVehicle] call EFUNC(civilian,getNearestCity) +} else { + [_nearestTown] call EFUNC(civilian,getCityByLocation) }; private _msg = ""; -private _nearestCityArea = _nearestTown getVariable QGVAR(cityArea); +private _nearestCityName = _nearestCity getVariable [QEGVAR(civilian,name), ""]; +private _nearestCityArea = _nearestCity getVariable QEGVAR(civilian,cityArea); private _isInCity = (position _stolenVehicle) inArea _nearestCityArea; -// Check if distance is greater than 250 m. If so then change output a bit to represent that. if (_isInCity) then { - _msg = format [LLSTRING(Vehicle_Stolen_In_City), _timeOfTheft, text _nearestTown]; + _msg = format [LLSTRING(Vehicle_Stolen_In_City), _timeOfTheft, _nearestCityName]; } else { - _msg = format [LLSTRING(Vehicle_Stolen_Near_City), _timeOfTheft, text _nearestTown]; + _msg = format [LLSTRING(Vehicle_Stolen_Near_City), _timeOfTheft, _nearestCityName]; }; _msg diff --git a/addons/vehicles/initSettings.inc.sqf b/addons/vehicles/initSettings.inc.sqf index c2dd2b4d..41ea838d 100644 --- a/addons/vehicles/initSettings.inc.sqf +++ b/addons/vehicles/initSettings.inc.sqf @@ -105,7 +105,7 @@ [[1, 2, 3], [LSTRING(Always), LSTRING(IfCiviliansNearby), LSTRING(Never)], 1], true, {}, - true + false ] call CBA_fnc_addSetting; [ @@ -116,5 +116,5 @@ [0, 300, 30, 1], true, {}, - true + false ] call CBA_fnc_addSetting;