mirror of
https://github.com/acemod/ACE3.git
synced 2024-08-30 18:23:18 +00:00
Trenches - Terrain Trenching (#9148)
* Common - Use hashmap variable for canDig surfaces * Update XEH_preInit.sqf * Trenches - Terrain Trenching (simple blocks) * Update fnc_canDig.sqf * Update fnc_canDig.sqf * Handle locality * move code around, stringtable * use third block for floor * cleanup debug * update includes, add tooltip
This commit is contained in:
parent
98e189bfb4
commit
bd43c32334
@ -1,4 +1,5 @@
|
|||||||
|
|
||||||
|
PREP(blockTrench_place);
|
||||||
PREP(camouflageTrench);
|
PREP(camouflageTrench);
|
||||||
PREP(canCamouflageTrench);
|
PREP(canCamouflageTrench);
|
||||||
PREP(canContinueDiggingTrench);
|
PREP(canContinueDiggingTrench);
|
||||||
|
@ -3,6 +3,17 @@
|
|||||||
if (isServer) then {
|
if (isServer) then {
|
||||||
// Cancel dig on hard disconnection. Function is identical to killed
|
// Cancel dig on hard disconnection. Function is identical to killed
|
||||||
addMissionEventHandler ["HandleDisconnect", {_this call FUNC(handleKilled)}];
|
addMissionEventHandler ["HandleDisconnect", {_this call FUNC(handleKilled)}];
|
||||||
|
|
||||||
|
// Wrapper for blockTrench_place, on failure send hint back to source
|
||||||
|
[QGVAR(layTrenchline), {
|
||||||
|
params [["_source", objNull, [objNull]], ["_args", [], [[]]]];
|
||||||
|
private _return = _args call FUNC(blockTrench_place);
|
||||||
|
TRACE_3("layTrenchline EH",_source,_args,_return);
|
||||||
|
_return params ["_success", "_reason", ["_info", ""]];
|
||||||
|
if ((!_success) && {!isNull _source}) then {
|
||||||
|
[QEGVAR(common,displayTextStructured), [["%1:<br/>%2<br/>%3", "str_mis_state_failed", _reason, _info], 3], [_source]] call CBA_fnc_targetEvent;
|
||||||
|
};
|
||||||
|
}] call CBA_fnc_addEventHandler;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!hasInterface) exitWith {};
|
if (!hasInterface) exitWith {};
|
||||||
|
164
addons/trenches/functions/fnc_blockTrench_place.sqf
Normal file
164
addons/trenches/functions/fnc_blockTrench_place.sqf
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
#include "..\script_component.hpp"
|
||||||
|
/*
|
||||||
|
* Author: PabstMirror
|
||||||
|
* Dig trenchline
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* 0: Position <ARRAY>
|
||||||
|
* 1: Position <ARRAY>
|
||||||
|
* 2: Force - ignoring saftey checks (optional: false) <BOOL>
|
||||||
|
* 3: Cut Grass (optional: false) <BOOL>
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* <ARRAY>
|
||||||
|
* 0: Success <BOOL>
|
||||||
|
* 1: Failure reason <STRING>
|
||||||
|
* 2: Extra info <ANY>
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* [a, b] call ace_trenches_fnc_blockTrench_place
|
||||||
|
*
|
||||||
|
* Public: No
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!isServer) exitWith { ERROR("function must be called on server"); [false, "server-only"]; };
|
||||||
|
|
||||||
|
params [["_start2d", [], [[]]], ["_end2d", [], [[]]], ["_force", false, [false]], ["_cutGrass", false, [false]]];
|
||||||
|
TRACE_3("blockTrench_place",_start2d,_end2d,_force);
|
||||||
|
|
||||||
|
scopeName "main";
|
||||||
|
|
||||||
|
// get maths
|
||||||
|
getTerrainInfo params ["", "", "_cellsize"];
|
||||||
|
if ((_cellsize < 1) || {_cellsize > 10}) exitWith { [false, "world cellsize"] breakOut "main" }; // malden is 12.5
|
||||||
|
|
||||||
|
// for Land_Trench_01_forest_F
|
||||||
|
private _modelX = 2.1;
|
||||||
|
private _modelZ = 1.1;
|
||||||
|
private _modelSize = 3.75;
|
||||||
|
|
||||||
|
private _landAdjust = -1.7; // how deep we dig into the terrain
|
||||||
|
private _trenchDepth = -1; // how deep the floor is
|
||||||
|
private _trenchWidth = 1; // offset for each side from center
|
||||||
|
private _blockAdjust = -0.45; // get block to sit flush
|
||||||
|
private _blockScale = _cellsize / _modelSize; // scale up block to fit cellsize
|
||||||
|
|
||||||
|
private _xOffset = _trenchWidth + _blockScale * _modelX;
|
||||||
|
private _zOffset = _blockAdjust - (_blockScale - 1) * _modelZ;
|
||||||
|
private _testRadius = 1 * _blockScale * _modelSize;
|
||||||
|
|
||||||
|
// convert to terrain grid
|
||||||
|
_start2d = (_start2d select [0,2]) apply {_cellsize * round (_x / _cellsize)};
|
||||||
|
_end2d = (_end2d select [0,2]) apply {_cellsize * round (_x / _cellsize)};
|
||||||
|
_start2d params ["_ax", "_ay"];
|
||||||
|
_end2d params ["_bx", "_by"];
|
||||||
|
{ // make sure points aren't outside terrain
|
||||||
|
if (_x < _cellsize || {_x > (worldSize - _cellsize)}) exitWith { [false, "outside map boundry"] breakOut "main" };
|
||||||
|
} forEach [_ax, _ay, _bx, _by];
|
||||||
|
TRACE_3("adjusted",_cellsize,_start2d,_end2d);
|
||||||
|
|
||||||
|
// get direction and start/end
|
||||||
|
private _east = (abs (_ax - _bx)) >= (abs (_ay - _by));
|
||||||
|
private _origin2D = [];
|
||||||
|
private _length = 0;
|
||||||
|
if (_east) then {
|
||||||
|
_origin2D = if (_ax < _bx) then { _start2d } else { _end2d };
|
||||||
|
_length = (abs (_ax - _bx)) / _cellsize;
|
||||||
|
} else {
|
||||||
|
_origin2D = if (_ay < _by) then { _start2d } else { _end2d };
|
||||||
|
_length = (abs (_ay - _by)) / _cellsize;
|
||||||
|
};
|
||||||
|
TRACE_3("",_east,_origin2D,_length);
|
||||||
|
if (_length < 2) exitWith { [false, "too short"] breakOut "main" };
|
||||||
|
|
||||||
|
|
||||||
|
// Test and get block data
|
||||||
|
private _blockData = [];
|
||||||
|
for "_i" from 0 to _length do { // intentionally inclusive
|
||||||
|
private _posCenter = _origin2D;
|
||||||
|
private _posLeft = _origin2D;
|
||||||
|
private _posRight = _origin2D;
|
||||||
|
private _direction = [];
|
||||||
|
if (_east) then {
|
||||||
|
_posCenter = _posCenter vectorAdd [(_i + 0.5) * _cellsize, 0];
|
||||||
|
_posLeft = _posCenter vectorAdd [0, _xOffset];
|
||||||
|
_posRight = _posCenter vectorAdd [0, -_xOffset];
|
||||||
|
_direction = [0,-1,0];
|
||||||
|
} else {
|
||||||
|
_posCenter = _posCenter vectorAdd [0, (_i + 0.5) * _cellsize];
|
||||||
|
_posLeft = _posCenter vectorAdd [_xOffset, 0];
|
||||||
|
_posRight = _posCenter vectorAdd [-_xOffset, 0];
|
||||||
|
_direction = [-1,0,0];
|
||||||
|
};
|
||||||
|
|
||||||
|
{ // Test if each point is valid
|
||||||
|
private _pos2d = _x;
|
||||||
|
// check water
|
||||||
|
if ((!_force) && {(getTerrainHeightASL _pos2D) < 0}) then { [false, "water"] breakOut "main" };
|
||||||
|
// check canDig (surface type)
|
||||||
|
if ((!_force) && {!([_pos2d] call EFUNC(common,canDig))}) then { [false, "canDig surface"] breakOut "main" };
|
||||||
|
// check canDig (surface type)
|
||||||
|
if ((!_force) && {isOnRoad _pos2D}) then { [false, "road"] breakOut "main" };
|
||||||
|
// check terrain objects
|
||||||
|
private _terrainObjects = nearestTerrainObjects [_pos2d, [], _testRadius, false, true];
|
||||||
|
// todo: want to avoid touching trees and large rocks but could allow some small shrubs to be overlapped
|
||||||
|
if (_terrainObjects isNotEqualTo []) then {
|
||||||
|
if (_force) then {
|
||||||
|
WARNING_1("overlapping terrainObjects %1",_terrainObjects);
|
||||||
|
} else {
|
||||||
|
[false, "terrain object", _terrainObjects] breakOut "main";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
// check mission objects
|
||||||
|
private _missionObjects = nearestObjects [_origin2D, ["All"], _testRadius, true];
|
||||||
|
_missionObjects = _missionObjects select { !(_x isKindOf "Logic") };
|
||||||
|
if (_missionObjects isNotEqualTo []) then {
|
||||||
|
_missionObjects = _missionObjects apply {typeOf _x};
|
||||||
|
if (_force) then {
|
||||||
|
WARNING_1("blocking missionObjects %1",_missionObjects);
|
||||||
|
} else {
|
||||||
|
[false, "mission object", _missionObjects] breakOut "main";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} forEach [_posCenter, _posLeft, _posRight];
|
||||||
|
|
||||||
|
_posCenter set [2, (getTerrainHeightASL _posCenter) + _zOffset + _trenchDepth];
|
||||||
|
_posLeft set [2, (getTerrainHeightASL _posLeft) + _zOffset];
|
||||||
|
_posRight set [2, (getTerrainHeightASL _posRight) + _zOffset];
|
||||||
|
|
||||||
|
if (_cutGrass && {_i != 0} && {_i != _length}) then {
|
||||||
|
_blockData pushBack ["Land_ClutterCutter_medium_F", _blockScale, _posCenter, [0,1,0], surfaceNormal _posCenter];
|
||||||
|
};
|
||||||
|
// todo: there also is a snow textured block or do it right and make our own re-texturable model
|
||||||
|
_blockData pushBack ["Land_Trench_01_forest_F", _blockScale, _posCenter, _direction, surfaceNormal _posCenter];
|
||||||
|
_blockData pushBack ["Land_Trench_01_forest_F", _blockScale, _posLeft, _direction, surfaceNormal _posLeft];
|
||||||
|
_blockData pushBack ["Land_Trench_01_forest_F", _blockScale, _posRight, _direction vectorMultiply -1, surfaceNormal _posRight];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Adjust terrain heights
|
||||||
|
private _terrainData = [];
|
||||||
|
for "_i" from 1 to (_length - 1) do { // skip first and last
|
||||||
|
private _posCenter = _origin2D;
|
||||||
|
if (_east) then {
|
||||||
|
_posCenter = _posCenter vectorAdd [_i * _cellsize, 0];
|
||||||
|
} else {
|
||||||
|
_posCenter = _posCenter vectorAdd [0, _i * _cellsize];
|
||||||
|
};
|
||||||
|
|
||||||
|
_posCenter set [2, (getTerrainHeight _posCenter) + _landAdjust];
|
||||||
|
_terrainData pushBack _posCenter
|
||||||
|
};
|
||||||
|
TRACE_1("setTerrainHeight",count _terrainData);
|
||||||
|
setTerrainHeight [_terrainData, true];
|
||||||
|
|
||||||
|
|
||||||
|
// Place blocks
|
||||||
|
{
|
||||||
|
_x params ["_xClass", "_xScale", "_xPosASL", "_xDir", "_xUp"];
|
||||||
|
private _block = createSimpleObject [_xClass, _xPosASL];
|
||||||
|
_block setVectorDirAndUp [_xDir, _xUp];
|
||||||
|
if (_xScale != 1) then { _block setObjectScale _xScale; };
|
||||||
|
} forEach _blockData;
|
||||||
|
|
||||||
|
[true, "", _length]
|
@ -179,6 +179,11 @@ class CfgVehicles {
|
|||||||
function = QFUNC(moduleHeal);
|
function = QFUNC(moduleHeal);
|
||||||
icon = QPATHTOF(ui\Icon_Module_Zeus_Heal_ca.paa);
|
icon = QPATHTOF(ui\Icon_Module_Zeus_Heal_ca.paa);
|
||||||
};
|
};
|
||||||
|
class GVAR(moduleLayTrench): GVAR(moduleBase) {
|
||||||
|
category = QGVAR(Utility);
|
||||||
|
displayName = CSTRING(ModuleLayTrenchline_DisplayName);
|
||||||
|
function = QFUNC(moduleLayTrench);
|
||||||
|
};
|
||||||
class GVAR(moduleLoadIntoCargo): GVAR(moduleBase) {
|
class GVAR(moduleLoadIntoCargo): GVAR(moduleBase) {
|
||||||
curatorCanAttach = 1;
|
curatorCanAttach = 1;
|
||||||
category = QGVAR(Utility);
|
category = QGVAR(Utility);
|
||||||
|
@ -21,6 +21,7 @@ PREP(moduleGarrison);
|
|||||||
PREP(moduleGlobalSetSkill);
|
PREP(moduleGlobalSetSkill);
|
||||||
PREP(moduleGroupSide);
|
PREP(moduleGroupSide);
|
||||||
PREP(moduleHeal);
|
PREP(moduleHeal);
|
||||||
|
PREP(moduleLayTrench);
|
||||||
PREP(moduleLoadIntoCargo);
|
PREP(moduleLoadIntoCargo);
|
||||||
PREP(moduleRemoveArsenal);
|
PREP(moduleRemoveArsenal);
|
||||||
PREP(moduleRemoveAceArsenal);
|
PREP(moduleRemoveAceArsenal);
|
||||||
|
@ -92,6 +92,11 @@ class CfgPatches {
|
|||||||
QGVAR(moduleBurn)
|
QGVAR(moduleBurn)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
class GVAR(trenches): ADDON {
|
||||||
|
units[] = {
|
||||||
|
QGVAR(moduleLayTrench)
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
class ACE_Curator {
|
class ACE_Curator {
|
||||||
@ -104,6 +109,7 @@ class ACE_Curator {
|
|||||||
GVAR(pylons) = "ace_pylons";
|
GVAR(pylons) = "ace_pylons";
|
||||||
GVAR(arsenal) = "ace_arsenal";
|
GVAR(arsenal) = "ace_arsenal";
|
||||||
GVAR(fire) = "ace_fire";
|
GVAR(fire) = "ace_fire";
|
||||||
|
GVAR(trenches) = "ace_trenches";
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "CfgFactionClasses.hpp"
|
#include "CfgFactionClasses.hpp"
|
||||||
|
50
addons/zeus/functions/fnc_moduleLayTrench.sqf
Normal file
50
addons/zeus/functions/fnc_moduleLayTrench.sqf
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#include "..\script_component.hpp"
|
||||||
|
/*
|
||||||
|
* PabstMirror
|
||||||
|
* Dig trenchline
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* 0: Module logic <OBJECT>
|
||||||
|
* 1: Synchronized units <ARRAY>
|
||||||
|
* 2: Activated <BOOL>
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* [LOGIC, [], true] call ace_zeus_fnc_moduleLayTrench
|
||||||
|
*
|
||||||
|
* Public: No
|
||||||
|
*/
|
||||||
|
if (canSuspend) exitWith {[FUNC(moduleLayTrench), _this] call CBA_fnc_directCall;};
|
||||||
|
|
||||||
|
params ["_logic", "_units", "_activated"];
|
||||||
|
if !(_activated && {local _logic}) exitWith {};
|
||||||
|
TRACE_1("",_logic);
|
||||||
|
|
||||||
|
if !(["ace_trenches"] call EFUNC(common,isModLoaded)) exitWith {
|
||||||
|
deleteVehicle _logic;
|
||||||
|
[LSTRING(RequiresAddon)] call FUNC(showMessage);
|
||||||
|
};
|
||||||
|
|
||||||
|
private _startPos = getPosASL _logic; // change position of logic to be aligned with grid
|
||||||
|
getTerrainInfo params ["", "", "_cellsize"];
|
||||||
|
_startPos = (_startPos select [0,2]) apply {_cellsize * round (_x / _cellsize)};
|
||||||
|
_logic setPos _startPos;
|
||||||
|
|
||||||
|
|
||||||
|
// todo: it would be nice to show visually that trenches can only be dug north/south or east/west
|
||||||
|
private _text = format ["%1 %2", LELSTRING(trenches,ConfirmDig), LLSTRING(ModuleLayTrenchline_Tooltip)];
|
||||||
|
[_logic, {
|
||||||
|
params ["_successful", "_logic", "_mousePosASL", "_shift"];
|
||||||
|
TRACE_4("getModuleDestination",_successful,_logic,_mousePosASL,_shift);
|
||||||
|
|
||||||
|
private _startPosASL = getPosASL _logic;
|
||||||
|
deleteVehicle _logic;
|
||||||
|
if (isNull _logic) exitWith { TRACE_1("exit",isNull _logic); };
|
||||||
|
if (!_successful) exitWith { TRACE_1("exit",_successful); };
|
||||||
|
|
||||||
|
private _args = [_startPosASL, _mousePosASL, _shift];
|
||||||
|
TRACE_1("sending event",_args);
|
||||||
|
[QEGVAR(trenches,layTrenchline), [ace_player, _args]] call CBA_fnc_serverEvent;
|
||||||
|
}, _text, "\a3\ui_f\data\IGUI\Cfg\Cursors\select_target_ca.paa", [0, 1, 0, 1], 45] call FUNC(getModuleDestination);
|
@ -1933,5 +1933,11 @@
|
|||||||
<Russian>Поджечь юнита</Russian>
|
<Russian>Поджечь юнита</Russian>
|
||||||
<Spanish>Quemar a unidad</Spanish>
|
<Spanish>Quemar a unidad</Spanish>
|
||||||
</Key>
|
</Key>
|
||||||
|
<Key ID="STR_ACE_Zeus_ModuleLayTrenchline_DisplayName">
|
||||||
|
<English>Lay Trenchline</English>
|
||||||
|
</Key>
|
||||||
|
<Key ID="STR_ACE_Zeus_ModuleLayTrenchline_Tooltip">
|
||||||
|
<English>+SHIFT to force (Can only lay N/S or E/W)</English>
|
||||||
|
</Key>
|
||||||
</Package>
|
</Package>
|
||||||
</Project>
|
</Project>
|
||||||
|
Loading…
Reference in New Issue
Block a user