diff --git a/addons/mapfx/XEH_postClientInit.sqf b/addons/mapfx/XEH_postClientInit.sqf index 1836083993..111bcbb171 100644 --- a/addons/mapfx/XEH_postClientInit.sqf +++ b/addons/mapfx/XEH_postClientInit.sqf @@ -3,9 +3,9 @@ ADDON = false; LOG(MSG_INIT); +// Calculate the maximum zoom allowed for this map call FUNC(determineZoom); -//Probably need this spawn, because CBA_fnc_addPerFrameHandler doesn't work durring briefing. [] spawn { // Wait until the map display is detected waitUntil {(!isNull findDisplay 12)}; diff --git a/addons/mapfx/config.cpp b/addons/mapfx/config.cpp index ff20c33499..1cdb1e93c1 100644 --- a/addons/mapfx/config.cpp +++ b/addons/mapfx/config.cpp @@ -13,7 +13,15 @@ class CfgPatches { #include "CfgEventHandlers.hpp" class ACE_Settings { - class GVAR(limitZoom) { + class GVAR(mapIllumination) { + value = 1; + typeName = "BOOL"; + }; + class GVAR(mapShake) { + value = 1; + typeName = "BOOL"; + }; + class GVAR(mapLimitZoom) { value = 0; typeName = "BOOL"; }; diff --git a/addons/mapfx/functions/fnc_determineMapLight.sqf b/addons/mapfx/functions/fnc_determineMapLight.sqf index c5267689d5..370bcdb167 100644 --- a/addons/mapfx/functions/fnc_determineMapLight.sqf +++ b/addons/mapfx/functions/fnc_determineMapLight.sqf @@ -1,10 +1,23 @@ +/* +* Author: Rocko and CAA-Picard +* Calculates the current map illumination for a given unit +* +* Arguments: +* 0: Unit +* +* Return Value: +* 0: Does the map needs shading? +* 1: Color of the overlay +* +* Public: No +*/ #include "script_component.hpp" -private ["_darkenMap","_darkenColor","_createLight","_gunlight","_nearObjects","_light"]; +EXPLODE_1_PVT(_this,_unit); -// @todo: Update the way to check for flashlights -_gunlight = isArray(configFile>> "CfgWeapons" >> currentWeapon player >>"ace_gunlight_classes") || {"ACE_MugLite" in weapons player}; +private ["_isEnclosed","_nearObjects","_light","_ll","_flashlight"]; +// Blend two colors _fnc_blendColor = { EXPLODE_3_PVT(_this,_c1,_c2,_alpha); [(_c1 select 0) * (1 - _alpha) + (_c2 select 0) * _alpha, @@ -13,27 +26,26 @@ _fnc_blendColor = { (_c1 select 3) * (1 - _alpha) + (_c2 select 3) * _alpha] }; - +// Ambient light tint depending on time of day _lightTint = switch (true) do { - case (sunOrMoon == 1.0) : { [1,1,1,1] }; + case (sunOrMoon == 1.0) : { [0.5,0.5,0.5,1] }; case (sunOrMoon > 0.80) : {[[1.0 - overcast,0.2,0,1], [1,1,1,1], (sunOrMoon - 0.8)/0.2] call _fnc_blendColor}; case (sunOrMoon > 0.50) : {[[0,0,0.1,1], [1.0 - overcast,0.2,0,1], (sunOrMoon - 0.5)/0.3] call _fnc_blendColor}; case (sunOrMoon <= 0.5) : { [0,0,0.1,1] }; }; -_lightLevel = 0.04 + (0.96 * call EFUNC(common,ambientBrightness)); - +// Calculates overlay color from tint and light level _fnc_calcColor = { EXPLODE_2_PVT(_this,_c1,_lightLevel); - _l = abs(_lightLevel - 0.5) / 0.5; - if (_lightLevel < 0.5) then { - [(_c1 select 0) * _l * _l * _l, - (_c1 select 1) * _l * _l * _l, - (_c1 select 2) * _l * _l * _l, + _l = _lightLevel / 0.5; + [(_c1 select 0) * _l, + (_c1 select 1) * _l, + (_c1 select 2) * _l, (_c1 select 3) * (1 - _lightLevel)] } else { + _l = (_lightLevel - 0.5) / 0.5; [(_c1 select 0) * (1 - _l) + _l, (_c1 select 1) * (1 - _l) + _l, (_c1 select 2) * (1 - _l) + _l, @@ -41,107 +53,92 @@ _fnc_calcColor = { }; }; -_darkenMap = true; -_createLight = false; +_lightLevel = 0.04 + (0.96 * call EFUNC(common,ambientBrightness)); // check if player has NVG enabled -if (currentVisionMode ACE_player == 1) exitWith { +if (currentVisionMode _unit == 1) exitWith { // stick to nvg color - _darkenMap = true; - _darkenColor = [154/255,253/255,177/255,0.5]; - _createLight = false; - - [_darkenMap,_darkenColor,_createLight] + [true, [154/255,253/255,177/255,0.5]] }; +// Do not obscure the map if the ambient light level is above 0.95 if (_lightLevel > 0.95) exitWith { - [false, [1,1,1,0], false] + [false, [0.5,0.5,0.5,0]] }; +// Do not obscure the map if the player is on a enclosed vehicle (assume internal illumination) +if (vehicle _unit != _unit) then { + // Player is in a vehicle + if ((vehicle _unit) isKindOf "Tank") then { + _isEnclosed = true; + }; +}; +if (_isEnclosed) exitWith { + TRACE_1("Player in a enclosed vehicle",""); + [false, [1,1,1,0]] +}; -// Check if player is not in a vehicle -if (vehicle ACE_player == ACE_player) then { - // Player is not in a vehicle - TRACE_1("NOT in vehicle",""); +// Player is not in a vehicle +TRACE_1("Player is on foot or in an open vehicle",""); - // darken map, unless following cases are fulfilled - // Priorities: Weapons flashlight, lamppost, fire, chemlight, flares +// Check if player is near a campfires, lights or vehicles with lights on - 15m +_nearObjects = [nearestObjects [_unit, ["All"], 15], {(inflamed _this) || (isLightOn _this)}] call EFUNC(common,filter); +if (count (_nearObjects) > 0) then { + _light = _nearObjects select 0; - // Check if player is near a campfires, lights or vehicles with lights on - 15m - _nearObjects = [nearestObjects [ACE_player, ["All"], 15], {(inflamed _this) || (isLightOn _this)}] call EFUNC(common,filter); - if (count (_nearObjects) > 0) then { - _light = _nearObjects select 0; - _lightLevel = _lightLevel max (1 - (((((ACE_player distance _light) - 5)/10) max 0) min 1)); + _ll = (1 - (((((_unit distance _light) - 5)/10) max 0) min 1)); + if (_ll > _lightLevel) then { + _lightLevel = _ll; TRACE_1("player near campfire",""); }; - - // TODO: Illumination flares (timed) - - // Using chemlights - _fnc_chemLight = { - EXPLODE_2_PVT(_this,_no,_lc); - if (count (_no) == 0) exitWith {}; - - _light = _no select 0; - _ll = (1 - ((((ACE_player distance _light) - 2)/2) max 0)) * 0.4; - if (_ll > _lightLevel) then { - _lightLevel = _ll; - _lightTint = +_lc; - hint format ["%1 %2",ACE_player distance _light,_ll]; - }; - TRACE_1("player near chemlight",""); - }; - - _nearObjects = [ACE_player nearObjects ["Chemlight_red", 4], {alive _this}] call EFUNC(common,filter); - [_nearObjects, [1,0,0,1]] call _fnc_chemLight; - - _nearObjects = [ACE_player nearObjects ["Chemlight_green", 4], {alive _this}] call EFUNC(common,filter); - [_nearObjects, [0,1,0,1]] call _fnc_chemLight; - - _nearObjects = [ACE_player nearObjects ["Chemlight_blue", 4], {alive _this}] call EFUNC(common,filter); - [_nearObjects, [0,0,1,1]] call _fnc_chemLight; - - _nearObjects = [ACE_player nearObjects ["Chemlight_yellow", 4], {alive _this}] call EFUNC(common,filter); - [_nearObjects, [1,1,0,1]] call _fnc_chemLight; - - // Gun with light - if (_gunlight) then { - _darkenMap = false; - _createLight = true; - TRACE_1("using gun light",""); - }; - -} else { - // Player is in a vehicle - if ((vehicle ACE_player) isKindOf "Tank") exitWith { - _darkenMap = false; - _createLight = false; - }; - - // check if vehicle is not of following type: parachute - TRACE_1("in vehicle",""); - - // darken map if vehicle is kind of bicycle or motorbike or ATV or parachute or PBX boat - if (vehicle ACE_player isKindOf "Bicycle" || {vehicle ACE_player isKindOf "Motorcycle"}) then { - if (_gunlight) then { - _darkenMap = false; - _createLight = true; - TRACE_1("bright map - gun lights",""); - } else { - _darkenColor = [0,0,0,(_alpha*1.1)]; - TRACE_1("darken map - no lights",""); - }; - } else { - // do not darken map, but create a lightpoint at players eye pos to simulate dash light / flashlight usage to view map - // do nothing if in a tank or apc - _darkenMap = false; - _createLight = true; - TRACE_1("using vehicle light",""); - }; - }; -_darkenColor = [_lightTint, _lightLevel] call _fnc_calcColor; -TRACE_4("",_darkenMap,_darkenColor,_createLight); -[_darkenMap,_darkenColor,_createLight] +// Gun with light +_nearObjects = [nearestObjects [_unit, ["CAManBase"], 10], { _this isFlashlightOn (currentWeapon _this)}] call EFUNC(common,filter); +if (count (_nearObjects) > 0) then { + _light = (_nearObjects select 0); + _flashlight = (_light weaponAccessories currentMuzzle _light) select 1; + + // Check if it's a day laser + if (_flashlight == "ACE_acc_pointer_red") exitWith {}; + if (_flashlight == "ACE_acc_pointer_green") exitWith {}; + + _lightLevel = _lightLevel max (1 - (((((_unit distance _light) - 2)/8) max 0) min 1)); + TRACE_1("Using gun light",""); +}; + + +// @todo: Illumination flares (timed) + + +// Using chemlights +_nearObjects = [_unit nearObjects ["SmokeShell", 4], { + alive _this && {(typeOf _this == "Chemlight_red") || { + (typeOf _this == "Chemlight_green") || { + (typeOf _this == "Chemlight_blue") || { + (typeOf _this == "Chemlight_yellow")}}}}}] call EFUNC(common,filter); +if (count (_nearObjects) > 0) then { + _light = _nearObjects select 0; + + _ll = (1 - ((((_unit distance _light) - 2)/2) max 0)) * 0.4; + if (_ll > _lightLevel) then { + _flareTint = switch (typeOf _light) do { + case "Chemlight_red" : {[1,0,0,1]}; + case "Chemlight_green" : {[0,1,0,1]}; + case "Chemlight_blue" : {[0,0,1,1]}; + case "Chemlight_yellow" : {[1,1,0,1]}; + }; + _lightTint = [_lightTint, _flareTint, (_ll - _lightLevel)/(1 - _lightLevel)] call _fnc_blendColor; + _lightLevel = _ll; + TRACE_1("player near chemlight",""); + }; +}; + +// Do not obscure the map if the ambient light level is above 0.95 +if (_lightLevel > 0.95) exitWith { + [false, [0.5,0.5,0.5,0]] +}; + +// Calculate resulting map color +[true, [_lightTint, _lightLevel] call _fnc_calcColor] diff --git a/addons/mapfx/functions/fnc_determineZoom.sqf b/addons/mapfx/functions/fnc_determineZoom.sqf index 5893967a4f..fdc620b417 100644 --- a/addons/mapfx/functions/fnc_determineZoom.sqf +++ b/addons/mapfx/functions/fnc_determineZoom.sqf @@ -1,7 +1,17 @@ +/* +* Author: Rocko +* Calculate the maximum zoom level allowed for the current map +* +* Arguments: +* None +* +* Return Value: +* None +* +* Public: No +*/ #include "script_component.hpp" -// TODO: Perhaps change to return values instead of setting GVAR's directly - private ["_grids", "_fourSize", "_sixSize", "_continue", "_size"]; _grids = configFile >> "CfgWorlds" >> worldName >> "Grid"; _fourSize = -1; diff --git a/addons/mapfx/functions/fnc_updateMapFx.sqf b/addons/mapfx/functions/fnc_updateMapFx.sqf index 93c42b4749..ad32a02632 100644 --- a/addons/mapfx/functions/fnc_updateMapFx.sqf +++ b/addons/mapfx/functions/fnc_updateMapFx.sqf @@ -1,69 +1,78 @@ +/* +* Author: Rocko and CAA-Picard +* On map draw, updates the effects +* +* Arguments: +* None +* +* Return Value: +* None +* +* Public: No +*/ #include "script_component.hpp" -// Calculate the light -_data = [[], FUNC(determineMapLight), missionNamespace, QGVAR(mapLight), 0.1] call EFUNC(common,cachedCall); +private ["_mapCtrl","_mapScale"]; -EXPLODE_3_PVT(_data,_darkenMap,_darkenColor,_externalLight); -//systemChat format ["%1 %2 %3", _darkenMap, _darkenColor, _createLight]; +_mapCtrl = ((findDisplay 12) displayCtrl 51); +_mapScale = ctrlMapScale _mapCtrl; -if (_darkenMap) then { - _darkenFill = format["#(rgb,1,1,1)color(%1,%2,%3,%4)",_darkenColor select 0, _darkenColor select 1, _darkenColor select 2, _darkenColor select 3]; - ((findDisplay 12) displayCtrl 51) drawRectangle [(getArray(configFile >> 'CfgWorlds' >> worldName >> 'centerPosition')),80000,80000,0,_darkenColor,_darkenFill]; -} else { - /*if (_externalLight) then { - [] spawn { - _light = ACE_player getVariable ['ace_map_light',objNull]; - if (isNull _light) then { - _type = if (ACE_player == vehicle ACE_player) then { 'ACE_Flashlight' } else { 'ACE_Dashlight' }; - _light = _type createVehicle (getPos ACE_player); - _light attachTo [(vehicle ACE_player), if (_type == 'ACE_Flashlight') then { [0,0.4,1] } else { [0,0,-1]}]; - ACE_player setVariable ['ace_map_light',_light]; - waitUntil {sleep 0.1; !visibleMap; }; - deleteVehicle _light; - ACE_player setVariable ['ace_map_light',objNull]; - }; - }; - };*/ -}; +if (GVAR(mapIllumination)) then { + private ["_data","_darkenFill"]; -_ctrl = ((findDisplay 12) displayCtrl 51); -_scale = ctrlMapScale _ctrl; + // Calculate map illumination + _data = [[ACE_player], FUNC(determineMapLight), missionNamespace, QGVAR(mapLight), 0.1] call EFUNC(common,cachedCall); -_speed = 0; -if (vehicle ACE_player == ACE_player) then { - _speed = vectorMagnitude (velocity ACE_player); -}; - - -if (_speed > 0.1) then { - if (ctrlMapAnimDone _ctrl) then { - - _amplitude = (_speed - 0.1) / 5 * (1000 * _scale); - _time = 0.1; - - _shakePos = [(GVAR(lastStillPosition) select 0) + sin((time + _time - GVAR(lastStillTime))*100) * _amplitude * 0.25, - (GVAR(lastStillPosition) select 1) + sin((time + _time - GVAR(lastStillTime))*260) * _amplitude]; - - _ctrl ctrlMapAnimAdd [_time, _scale, _shakePos]; - ctrlMapAnimCommit _ctrl; - - GVAR(isShaking) = true; + EXPLODE_2_PVT(_data,_darkenMap,_darkenColor); + if (_darkenMap) then { + _darkenFill = format["#(rgb,1,1,1)color(%1,%2,%3,%4)",_darkenColor select 0, _darkenColor select 1, _darkenColor select 2, _darkenColor select 3]; + _mapCtrl drawRectangle [(getArray(configFile >> 'CfgWorlds' >> worldName >> 'centerPosition')),80000,80000,0,_darkenColor,_darkenFill]; }; -} else { - if (GVAR(isShaking)) then { - _ctrl ctrlMapAnimAdd [0, _scale, GVAR(lastStillPosition)]; - ctrlMapAnimCommit _ctrl; - GVAR(isShaking) = false; +}; + +if (GVAR(mapShake)) then { + private ["_speed","_amplitude", "_time", "_shakePos"]; + + // Only shake map while moving on foot + _speed = 0; + if (vehicle ACE_player == ACE_player) then { + _speed = vectorMagnitude (velocity ACE_player); + }; + + // If speed is large enough, create anims to shake map + if (_speed > 0.1) then { + if (ctrlMapAnimDone _mapCtrl) then { + + _amplitude = (_speed - 0.1) / 5 * (1000 * _mapScale); + _time = 0.1; + + _shakePos = [(GVAR(lastStillPosition) select 0) + sin((time + _time - GVAR(lastStillTime))*100) * _amplitude * 0.25, + (GVAR(lastStillPosition) select 1) + sin((time + _time - GVAR(lastStillTime))*260) * _amplitude]; + + _mapCtrl ctrlMapAnimAdd [_time, _mapScale, _shakePos]; + ctrlMapAnimCommit _mapCtrl; + + GVAR(isShaking) = true; + }; } else { - ctrlMapAnimClear _ctrl; - GVAR(lastStillPosition) = _ctrl ctrlMapScreenToWorld [0.5, 0.5]; - GVAR(lastStillTime) = time; - - if (GVAR(limitZoom)) then { - if (GVAR(minMapSize) >= _scale) then { - _ctrl ctrlMapAnimAdd [0, GVAR(minMapSize) + 0.001, (_ctrl ctrlMapScreenToWorld [0.5, 0.5])]; - ctrlMapAnimCommit _ctrl; - }; + if (GVAR(isShaking)) then { + // Stop shaking, return to original position + _mapCtrl ctrlMapAnimAdd [0, _mapScale, GVAR(lastStillPosition)]; + ctrlMapAnimCommit _mapCtrl; + GVAR(isShaking) = false; + } else { + // The map is still, store state + ctrlMapAnimClear _mapCtrl; + GVAR(lastStillPosition) = _mapCtrl ctrlMapScreenToWorld [0.5, 0.5]; + GVAR(lastStillTime) = time; }; }; }; + +if (GVAR(mapLimitZoom)) then { + if (GVAR(minMapSize) >= _mapScale) then { + ctrlMapAnimClear _mapCtrl; + _mapCtrl ctrlMapAnimAdd [0, GVAR(minMapSize) + 0.001, (_mapCtrl ctrlMapScreenToWorld [0.5, 0.5])]; + ctrlMapAnimCommit _mapCtrl; + }; +};