Skip to content

Commit

Permalink
Fully localize all user visible actions, messages, notifications and …
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
3Mydlo3 authored Apr 15, 2024
1 parent cbc2700 commit 4004b52
Show file tree
Hide file tree
Showing 55 changed files with 638 additions and 229 deletions.
1 change: 1 addition & 0 deletions addons/civilian/XEH_PREP.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ PREP(initCity);
PREP(initCivilians);
PREP(initConfig);
PREP(initCivilian);
PREP(isPositionInCity);
PREP(unassignCivilianFromCity);
5 changes: 5 additions & 0 deletions addons/civilian/XEH_postInit.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -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;
11 changes: 5 additions & 6 deletions addons/civilian/functions/fnc_civilianKilled.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
8 changes: 4 additions & 4 deletions addons/civilian/functions/fnc_civilianKilledMarker.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
26 changes: 10 additions & 16 deletions addons/civilian/functions/fnc_civilianKilledMsg.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
*
* Arguments:
* 0: Dead civilian <OBJECT>
* 1: Civilian's time of death <STRING>
* 2: Nearest location <LOCATION>
* 1: Unit which killed civilian <OBJECT>
* 2: Civilian's time of death <STRING>
* 3: Nearest location <LOCATION>
*
* Return Value:
* 0: Civilian killed message <STRING>
Expand All @@ -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
32 changes: 32 additions & 0 deletions addons/civilian/functions/fnc_isPositionInCity.sqf
Original file line number Diff line number Diff line change
@@ -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 <OBJECT/POSITION>
* 1: Particular city location to check <LOCATION> (Optional)
*
* Return Value:
* 0: Result <BOOL>
*
* 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
28 changes: 26 additions & 2 deletions addons/civilian/stringtable.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,30 @@
<English>SerialKillers - Civilian</English>
<Polish>SerialKillers - Cywile</Polish>
</Key>
<Key ID="STR_AFSK_Civilian_Civilian_Killed_In_City">
<Key ID="STR_AFSK_Civilian_EmptyVehiclesLimit">
<English>Civilian vehicles limit</English>
<Polish>Limit pojazdów cywilnych</Polish>
</Key>
<Key ID="STR_AFSK_Civilian_EmptyVehiclesLimit_Description">
<English>Controls how much civilian vehicles will be created on the whole map.</English>
<Polish>Ustala jak dużo pojazdów cywilnych będzie utworzonych na całej mapie.</Polish>
</Key>
<Key ID="STR_AFSK_Civilian_Killed_In_City">
<English>Civilian was killed at %1 in %2!</English>
<Polish>Cywil został zabity o godzinie %1 w %2!</Polish>
</Key>
<Key ID="STR_AFSK_Civilian_Civilian_Killed_Near_City">
<Key ID="STR_AFSK_Civilian_Killed_Near_City">
<English>Civilian was killed at %1 near %2!</English>
<Polish>Cywil został zabity o godzinie %1 w pobliżu %2!</Polish>
</Key>
<Key ID="STR_AFSK_Civilian_KilledByCop_In_City">
<English>Civilian was killed by cop %3 at %1 in %2!</English>
<Polish>Cywil został zabity przez policjanta %3 o godzinie %1 w %2!</Polish>
</Key>
<Key ID="STR_AFSK_Civilian_KilledByCop_Near_City">
<English>Civilian was killed by cop %3 at %1 near %2!</English>
<Polish>Cywil został zabity przez policjanta %3 o godzinie %1 w pobliżu %2!</Polish>
</Key>
<Key ID="STR_AFSK_Civilian_InitialCiviliansCount">
<English>Civilians count</English>
<Polish>Liczba cywili</Polish>
Expand Down Expand Up @@ -89,6 +105,14 @@
<English>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.</English>
<Polish>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.</Polish>
</Key>
<Key ID="STR_AFSK_Civilian_Killed">
<English>Civilian was killed</English>
<Polish>Cywil został zabity</Polish>
</Key>
<Key ID="STR_AFSK_Civilian_KilledByCop">
<English>Civilian was killed by cop</English>
<Polish>Cywil został zabity przez policjanta</Polish>
</Key>
<Key ID="STR_AFSK_Civilian_Low">
<English>Low</English>
<Polish>Mało</Polish>
Expand Down
1 change: 1 addition & 0 deletions addons/common/XEH_PREP.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ PREP(createArsenal);
PREP(deleteAtRandom);
PREP(getAllMapCities);
PREP(getLocationName);
PREP(getLocationNameRaw);
PREP(getLocationType);
PREP(getNearestCityLocation);
PREP(getNearestLocation);
Expand Down
8 changes: 6 additions & 2 deletions addons/common/XEH_postInit.sqf
Original file line number Diff line number Diff line change
@@ -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.");
Expand All @@ -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;
};

Expand Down Expand Up @@ -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;
};
3 changes: 2 additions & 1 deletion addons/common/XEH_preInit.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions addons/common/functions/fnc_getLocationName.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -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
38 changes: 38 additions & 0 deletions addons/common/functions/fnc_getLocationNameRaw.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#include "script_component.hpp"
/*
* Author: 3Mydlo3
* Function returns location name from config.
*
* Arguments:
* 0: Location <LOCATION>
*
* Return Value:
* 0: Location name <STRING>
*
* 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
2 changes: 1 addition & 1 deletion addons/killers/XEH_postInit.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion addons/killers/functions/fnc_createTeleport.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
5 changes: 3 additions & 2 deletions addons/killers/functions/fnc_initStartPositions.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -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 {};
Expand All @@ -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];
Expand Down
4 changes: 4 additions & 0 deletions addons/killers/stringtable.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,9 @@
<English>How many positions will be available to killers for teleportation on the beginning. 0 or -1 to random [10, 20].</English>
<Polish>Ile pozycji do teleportacji na starcie będzie dostępnych dla zabójców. 0 lub -1 by wylosować z przedziału [10, 20]</Polish>
</Key>
<Key ID="STR_AFSK_Killers_TeleportBack">
<English>Teleport back</English>
<Polish>Teleport z powrotem</Polish>
</Key>
</Package>
</Project>
2 changes: 1 addition & 1 deletion addons/main/script_mod.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
6 changes: 3 additions & 3 deletions addons/missions/SK_test.Malden/mission.sqm
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ class Mission
"STRING"
};
};
value="Chapoi";
value="";
};
};
};
Expand Down Expand Up @@ -255,7 +255,7 @@ class Mission
"STRING"
};
};
value="Le Port";
value="";
};
};
};
Expand Down Expand Up @@ -552,7 +552,7 @@ class Mission
"STRING"
};
};
value="Kankon";
value="";
};
};
};
Expand Down
Loading

0 comments on commit 4004b52

Please sign in to comment.