Files
DayZ-Epoch/SQF/dayz_code/actions/modular_build.sqf
2021-09-20 11:47:33 +02:00

856 lines
31 KiB
Plaintext

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// DayZ Base Building
//
// Author: vbawol@veteranbastards.com
// Updated by: Victor the Cleaner
// Date: August 2021
//
// - Players may no longer build objects outside the plot radius.
// This is calculated using the object's pivot point, not its geometry nor its bounding box.
// - Players may move an object any distance or height within the plot boundary/sphere.
// Therefore, DZE_buildMaxMoveDistance and DZE_buildMaxHeightDistance are now obsolete.
//
// - Players may move a small distance outside the plot radius, provided the object remains inside. Enabled with DZE_PlotOzone. Default: 10 meters.
// - A line of helpers now appears through the plot's vertical axis to aid line-of-sight to the pole. Enabled with DZE_AxialHelper.
// This may be useful for nearby plots that are grouped together, or where their radii overlap.
//
// - Players may now cancel the build by fast movement, i.e. running, or fast walking on steep terrain.
// This only applies when the player is holding the object. They may press F to release it, then run without cancelling.
// Crouch-walking or slow-walking will not cancel the build.
// Pressing ESC will also cancel without opening the exit menu.
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if (dayz_actionInProgress) exitWith {localize "str_epoch_player_40" call dayz_rollingMessages;}; // Building already in progress.
dayz_actionInProgress = true;
///////////////////////////////////////////////////////////////////////////////////////////////////
//
// _misc_checks function
//
///////////////////////////////////////////////////////////////////////////////////////////////////
local _misc_checks = {
local _onLadder = (getNumber (configFile >> "CfgMovesMaleSdr" >> "States" >> (animationState player) >> "onLadder")) == 1;
local _inVehicle = ((vehicle player) != player);
local _ctime = (player getVariable["combattimeout",0] >= diag_tickTime);
local _reason = "";
call {
if (_onLadder) exitWith {_reason = "str_player_21"}; // You cannot do this while you are on a ladder.
if (dayz_isSwimming) exitWith {_reason = "str_player_26"}; // You cannot do this while you are in the water.
if (_inVehicle) exitWith {_reason = "str_epoch_player_42"}; // You cannot build while in a vehicle.
if (_ctime) exitWith {_reason = "str_epoch_player_43"}; // You cannot build while in combat.
};
_reason;
};
///////////////////////////////////////////////////////////////////////////////////////////////////
//
// _cancel_build function
//
///////////////////////////////////////////////////////////////////////////////////////////////////
_cancel_build = {
_isOk = false;
_cancel = true;
detach _object;
deleteVehicle _object;
detach _objectHelper;
deleteVehicle _objectHelper;
};
///////////////////////////////////////////////////////////////////////////////////////////////////
local _reason = call _misc_checks;
if (_reason != "") exitWith {
dayz_actionInProgress = false;
localize _reason call dayz_rollingMessages;
};
///////////////////////////////////////////////////////////////////////////////////////////////////
//
// Initialise
//
///////////////////////////////////////////////////////////////////////////////////////////////////
DZE_buildItem = _this; // buildable classname, e.g. "full_cinder_wall_kit"
DZE_5 = false; // space bar - build
DZE_4 = false; // Q Key - rotate left
DZE_6 = false; // E Key - rotate right
DZE_F = false; // F Key - hold/release
DZE_Q = false; // PgUp
DZE_Z = false; // PgDn
DZE_Q_alt = false; // Alt + PgUp
DZE_Z_alt = false; // Alt + PgDn
DZE_Q_ctrl = false; // Ctrl + PgUp
DZE_Z_ctrl = false; // Ctrl + PgDn
DZE_cancelBuilding = false; // ESC Key
DZE_updateVec = false; // vector changed via build_vectors.sqf
DZE_memDir = 0; // object rotation (Q/E keys)
DZE_memForBack = 0; // pitch forward/back
DZE_memLeftRight = 0; // bank left/right
call gear_ui_init;
closeDialog 1;
local _playerPos = [player] call FNC_GetPos;
local _buildCheck = [_playerPos, DZE_buildItem, true] call dze_buildChecks; // input: [player position, kit classname, toolcheck] // return value: [_canBuild, _isPole, _nearestPole];
local _canBuild = (_buildCheck select 0); // bool
///////////////////////////////////////////////////////////////////////////////////////////////////
if (_canBuild) then {
player playActionNow "Crouch"; // prevent instant cancel from moving too fast
local _isPole = (_buildCheck select 1); // bool
local _nearestPole = (_buildCheck select 2); // object or objNull
local _findNearestPole = [];
local _inRadius = (!_isPole && !(isNull _nearestPole)); // bool // is the player attempting to place an object within a plot boundary?
local _radius = DZE_PlotPole select 0; // max distance from plot pole an object may be built
local _minDistance = DZE_PlotPole select 1; // minimum distance between plot poles
local _diameter = _radius * 2; // plot diameter
local _ozone = _radius + DZE_PlotOzone; // zone outside plot radius where a player may stand before placing an object, but the object must remain within the plot radius
local _isBHL = (DZE_BuildHeightLimit > 0); // is build height limit enabled
local _BHL = DZE_BuildHeightLimit; // short name
local _sphere = "Sign_sphere100cm_EP1"; // helper classname
local _polePos = [];
local _pArray = [];
local _isAdmin = dayz_playerUID in DZE_PlotManagementAdmins;
local _dir = 0;
local _vector = [];
local _object = objNull;
local _objectPos = [];
local _zPos = 0;
local _objectHelper = objNull;
local _objectHelperPos = [];
local _walk = "amovpercmwlk"; // animation state substrings
local _run = "amovpercmrun";
local _sprint = "meva";
helperDetach = false;
local _isOk = true;
local _cancel = false;
///////////////////////////////////////////////////////////////////////////////////////////
//
// create vertical helpers at the plot center to which the object will be assigned
//
///////////////////////////////////////////////////////////////////////////////////////////
if (_inRadius && DZE_AxialHelper) then {
local _density = 4; // minimum distance between helpers
local _segments = floor (_diameter / _density); // total helpers = _segments + 1
local _segments = _segments - (_segments % 2); // get even number of segments
local _spacing = -(_diameter / _segments); // actual distance between helpers
local _zenith = _radius;
local _polePos = [_nearestPole] call FNC_GetPos;
if (!isNil "PP_Marks") then {
_zenith = _zenith + _spacing; // subtract upper and lower positions
};
for "_i" from _zenith to -_zenith step _spacing do { // start at the zenith
local _offset = [0,0,_i]; // decrement towards nadir
local _pos = _nearestPole modelToWorld _offset; // translate to world
local _pZ = (_pos select 2); // get Z height
if (_pZ < 0) exitWith {}; // too low
local _texture = DZE_plotGreen; // green
if (_isBHL && (_pZ > _BHL)) then { // too high
_texture = DZE_plotRed; // red
};
local _helper = _sphere createVehicleLocal [0,0,0]; // create helper
_helper setObjectTexture _texture; // add colour
_pos set [2,(_polePos select 2) + _i]; // align to radial height
if (surfaceIsWater _pos) then { // adjust for land and sea
_helper setPosASL _pos;
} else {
_helper setPosATL _pos;
};
_pArray = _pArray + [_helper]; // record helper
};
};
///////////////////////////////////////////////////////////////////////////////////////////
//
// get config data
//
///////////////////////////////////////////////////////////////////////////////////////////
local _classname = getText (configFile >> "CfgMagazines" >> DZE_buildItem >> "ItemActions" >> "Build" >> "create"); // e.g. "CinderWall_DZ"
local _classnametmp = _classname;
local _text = getText (configFile >> "CfgVehicles" >> _classname >> "displayName"); // e.g. "Cinder Wall Full"
local _ghost = getText (configFile >> "CfgVehicles" >> _classname >> "ghostpreview"); // e.g. "CinderWall_Preview_DZ"
local _lockable = getNumber (configFile >> "CfgVehicles" >> _classname >> "lockable"); // defaults to 0
local _offset = getArray (configFile >> "CfgVehicles" >> _classname >> "offset");
local _isAllowedUnderGround = 1;
if (isNumber (configFile >> "CfgVehicles" >> _classname >> "nounderground")) then {
_isAllowedUnderGround = getNumber(configFile >> "CfgVehicles" >> _classname >> "nounderground");
};
if (_ghost != "") then {
_classname = _ghost;
};
///////////////////////////////////////////////////////////////////////////////////////////
//
// create ghost object and helper during pre-build
//
///////////////////////////////////////////////////////////////////////////////////////////
_object = _classname createVehicle [0,0,0];
if (count _offset == 0) then {
_offset = [0, abs (((boundingBox _object) select 0) select 1), 0];
};
_objectHelper = "Sign_sphere10cm_EP1" createVehicle [0,0,0];
_objectHelper setobjecttexture [0,"#(argb,8,8,3)color(0,1,0,1,ca)"]; // solid helper sphere
local _tempPos = player modelToWorld _offset;
_dir = getDir player;
_objectHelper setDir _dir;
_object setDir _dir;
if ((_isAllowedUnderGround == 0) && ((_tempPos select 2) < (_offset select 2))) then {
_tempPos set [2, _offset select 2]; // raise up to ground/sea level
};
if (surfaceIsWater _tempPos) then {
_objectHelper setPosASL _tempPos;
_object setPosASL _tempPos;
} else {
_objectHelper setPosATL _tempPos;
_object setPosATL _tempPos;
};
_objectHelper attachTo [player];
_object attachTo [_objectHelper];
if (isClass (configFile >> "SnapBuilding" >> _classname)) then {
["","","",["Init", _object, _classname, _objectHelper]] spawn snap_build;
};
if !(DZE_buildItem in DZE_noRotate) then {
["","","",["Init", "Init", 0]] spawn build_vectors;
};
///////////////////////////////////////////////////////////////////////////////////////////
//
// _change_height function
//
///////////////////////////////////////////////////////////////////////////////////////////
local _change_height = {
local _delta = _this;
local _helperPos = [_objectHelper] call FNC_GetPos;
if (!helperDetach) then {
detach _objectHelper;
};
_helperPos set [2,((_helperPos select 2) + _delta)];
if (_isAllowedUnderGround == 0 && (_helperPos select 2) < (_offset select 2)) then {
_helperPos set [2, _offset select 2];
};
if (surfaceIsWater _helperPos) then {
_objectHelper setPosASL _helperPos;
} else {
_objectHelper setPosATL _helperPos;
};
if (!helperDetach) then {
_objectHelper attachTo [player];
};
[_objectHelper, [DZE_memForBack, DZE_memLeftRight, DZE_memDir]] call fnc_SetPitchBankYaw;
_helperPos = _objectHelper modelToWorld [0,0,0];
local _objectPos = _object modelToWorld [0,0,0];
};
///////////////////////////////////////////////////////////////////////////////////////////
//
// _rotate function
//
///////////////////////////////////////////////////////////////////////////////////////////
local _rotate = {
local _degrees = [45, DZE_curDegree] select DZE_dirWithDegrees;
if (_this == -1) then {_degrees = -_degrees}; // Q Key
DZE_memDir = DZE_memDir + _degrees;
[_objectHelper, [DZE_memForBack, DZE_memLeftRight, DZE_memDir]] call fnc_SetPitchBankYaw;
};
///////////////////////////////////////////////////////////////////////////////////////////
//
// _attach function
//
///////////////////////////////////////////////////////////////////////////////////////////
local _attach = {
_objectHelper attachTo [player];
DZE_memDir = DZE_memDir - (getDir player);
[_objectHelper, [DZE_memForBack, DZE_memLeftRight, DZE_memDir]] call fnc_SetPitchBankYaw;
helperDetach = false;
};
///////////////////////////////////////////////////////////////////////////////////////////
//
// _detach function
//
///////////////////////////////////////////////////////////////////////////////////////////
local _detach = {
_objectHelperPos = getPosATL _objectHelper;
detach _objectHelper;
DZE_memDir = getDir _objectHelper;
[_objectHelper, [DZE_memForBack, DZE_memLeftRight, DZE_memDir]] call fnc_SetPitchBankYaw;
_objectHelper setPosATL _objectHelperPos;
_objectHelper setVelocity [0,0,0];
helperDetach = true;
};
///////////////////////////////////////////////////////////////////////////////////////////
//
// Main Loop
//
///////////////////////////////////////////////////////////////////////////////////////////
while {_isOk} do {
// raise/lower object
call {
if (DZE_Q) exitWith {DZE_Q = false; 0.10 call _change_height;}; // +10cm
if (DZE_Z) exitWith {DZE_Z = false; -0.10 call _change_height;}; // -10cm
if (DZE_Q_alt) exitWith {DZE_Q_alt = false; 1.00 call _change_height;}; // +1m
if (DZE_Z_alt) exitWith {DZE_Z_alt = false; -1.00 call _change_height;}; // -1m
if (DZE_Q_ctrl) exitWith {DZE_Q_ctrl = false; 0.01 call _change_height;}; // +1cm
if (DZE_Z_ctrl) exitWith {DZE_Z_ctrl = false; -0.01 call _change_height;}; // -1cm
};
// rotate object
call {
if (DZE_4) exitWith {DZE_4 = false; -1 call _rotate;}; // Q Key
if (DZE_6) exitWith {DZE_6 = false; 1 call _rotate;}; // E Key
};
// vector object
if (DZE_updateVec) then {
[_objectHelper, [DZE_memForBack, DZE_memLeftRight, DZE_memDir]] call fnc_SetPitchBankYaw;
DZE_updateVec = false;
};
local _canDo = (!r_drag_sqf && !r_player_unconscious);
// hold or release object
if (DZE_F and _canDo) then { // F Key
if (helperDetach) then {
call _attach;
} else {
call _detach;
};
DZE_F = false;
};
uiSleep 0.1; // default: 0.5
// Swimming, in vehicle, on ladder, in combat
_reason = call _misc_checks;
if (_reason != "") exitWith {
call _cancel_build;
_reason = localize _reason;
};
///////////////////////////////////////////////////////////////////////////////////
//
// player has plot pole
//
///////////////////////////////////////////////////////////////////////////////////
_objectPos = [_object] call FNC_GetPos; // object position
if (_isPole) then {
_findNearestPole = _objectPos nearEntities ["Plastic_Pole_EP1_DZ", _minDistance]; // check for nearby plots within range of current pole
_findNearestPole = _findNearestPole - [_object]; // exclude current pole
};
if (count _findNearestPole > 0) exitWith { // pole is too close to another plot
call _cancel_build;
_reason = format[localize "str_epoch_player_44", _minDistance];
};
///////////////////////////////////////////////////////////////////////////////////
//
// object was initially within plot radius
//
///////////////////////////////////////////////////////////////////////////////////
_playerPos = [player] call FNC_GetPos; // player's current position
if (_inRadius) then {
_polePos = [_nearestPole] call FNC_GetPos;
call {
if ((_polePos distance _playerPos) > _ozone) exitWith {_reason = localize "STR_EPOCH_BUILD_MOVE_TOO_FAR"}; // You moved too far!
if ((_polePos distance _objectPos) > _radius) exitWith {_reason = localize "STR_EPOCH_BUILD_OBJ_MOVE_TOO_FAR"}; // Object moved too far!
};
};
if (_reason != "") exitWith {
call _cancel_build;
};
///////////////////////////////////////////////////////////////////////////////////
//
// other checks
//
///////////////////////////////////////////////////////////////////////////////////
local _anim = animationState player;
local _speed = floor(abs(speed player));
local _isWalking = ([_walk, _anim] call fnc_inString);
local _isRunning = ([_run, _anim] call fnc_inString);
local _isSprinting = ([_sprint, _anim] call fnc_inString);
local _isFastWalking = (_isWalking && (_speed >= 10)); // fast walking on steep incline
local _tooFast = (!helperDetach && (_isRunning || _isSprinting || _isFastWalking)); // fast movement on level ground
local _tooHigh = (_isBHL && ((_objectPos select 2) > _BHL));
call {
if (_tooFast) exitWith {_reason = localize "STR_EPOCH_BUILD_MOVE_TOO_FAST"}; // You moved too fast!
if (_tooHigh) exitWith {_reason = format[localize "STR_EPOCH_PLAYER_168", _BHL]}; // object moved above height limit
if (!canbuild) exitWith {_reason = format[localize "STR_EPOCH_PLAYER_136", localize "STR_EPOCH_TRADER"]}; // trader nearby
if (DZE_cancelBuilding) exitWith {_reason = localize "STR_EPOCH_PLAYER_46"}; // ESC Key
};
if (_reason != "") exitWith {
call _cancel_build;
};
///////////////////////////////////////////////////////////////////////////////////
//
// space bar - place object
//
///////////////////////////////////////////////////////////////////////////////////
if (DZE_5) exitWith {
_isOk = false;
_objectPos = [_object] call FNC_GetPos;
_zPos = (_objectPos select 2);
detach _object;
_dir = getDir _object;
_vector = [(vectorDir _object),(vectorUp _object)];
deleteVehicle _object;
detach _objectHelper;
deleteVehicle _objectHelper;
};
};
///////////////////////////////////////////////////////////////////////////////////////////
// Delete Helper Array
{deleteVehicle _x;} count _pArray;
_pArray = [];
///////////////////////////////////////////////////////////////////////////////////////////
//
// Double check that object/pole height does not violate distance requirements
//
///////////////////////////////////////////////////////////////////////////////////////////
if (!_cancel && (_isAllowedUnderGround == 0) && (_zPos < (_offset select 2))) then { // object/pole was improperly placed below ground
_objectPos set [2, _offset select 2]; // raise up to ground/sea level
if (_isPole) then { // check for nearby plots within range
local _findNearestPole = [];
_findNearestPole = _objectPos nearEntities ["Plastic_Pole_EP1_DZ", _minDistance];
_findNearestPole = _findNearestPole - [_object];
if (count _findNearestPole > 0) then {
_cancel = true;
_reason = format[localize "str_epoch_player_44", _minDistance]; // pole is too close to another plot
};
} else {
if (_inRadius && ((_polePos distance _objectPos) > _radius)) then {
_cancel = true;
_reason = localize "STR_EPOCH_BUILD_OBJ_MOVE_TOO_FAR"; // object has moved outside radius
};
};
};
///////////////////////////////////////////////////////////////////////////////////////////
//
// You cannot build on a road.
//
///////////////////////////////////////////////////////////////////////////////////////////
if (!_cancel && !DZE_BuildOnRoads && (isOnRoad _objectPos)) then {
_cancel = true;
_reason = localize "STR_EPOCH_BUILD_FAIL_ROAD";
};
///////////////////////////////////////////////////////////////////////////////////////////
//
// You do not have access to build on this plot.
//
///////////////////////////////////////////////////////////////////////////////////////////
if (!_cancel) then {
_findNearestPole = _objectPos nearEntities ["Plastic_Pole_EP1_DZ", _minDistance]; // check for nearby plots within range of current pole
_findNearestPole = _findNearestPole - [_object]; // exclude current pole
if (count _findNearestPole > 0) then { // is near plot
_nearestPole = _findNearestPole select 0; // get first entry
_ownerID = _nearestPole getVariable["CharacterID","0"];
if (dayz_characterID != _ownerID) then { // not the owner
_buildcheck = [player, _nearestPole] call FNC_check_access;
_isowner = _buildcheck select 0;
_isfriendly = ((_buildcheck select 1) || (_buildcheck select 3));
if (!_isowner && !_isfriendly) then {
_cancel = true;
};
if (_cancel) then {
_reason = localize "STR_EPOCH_PLAYER_134"; // You do not have access to build on this plot.
};
};
};
};
///////////////////////////////////////////////////////////////////////////////////////////
//
// You cannot build. There are too many objects within "DZE_maintainRange" m.
//
///////////////////////////////////////////////////////////////////////////////////////////
if (!_cancel) then {
_buildables = DZE_maintainClasses + DZE_LockableStorage + ["DZ_storage_base"];
if (_isPole && ((count (nearestObjects [_objectPos, _buildables, DZE_maintainRange])) >= DZE_BuildingLimit)) then { // object's position
_cancel = true;
_reason = format[localize "str_epoch_player_41", floor DZE_maintainRange]; // You cannot build. There are too many objects within %1m.
};
};
///////////////////////////////////////////////////////////////////////////////////////////
//
// You can't build a "displayName" within "_distance" meters of a safe zone.
//
///////////////////////////////////////////////////////////////////////////////////////////
if (!_cancel) then {
local _checkOK = false;
local _distance = DZE_SafeZoneNoBuildDistance;
{
if (typeName _x == "ARRAY") then {
if (_x select 0 == _classname) then {
_checkOK = true;
_distance = _x select 1;
};
} else {
if (_x == _classname) then {
_checkOK = true;
};
};
if (_checkOK) exitWith {};
} count DZE_SafeZoneNoBuildItems;
if (_checkOK && !_isAdmin) then {
_canBuild = !([_objectPos, _distance] call DZE_SafeZonePosCheck); // object's position
};
if (!_canBuild) then {
_cancel = true;
_reason = format [localize "STR_EPOCH_PLAYER_166", _text, _distance]; // You can't build a %1 within %2 meters of a safe zone.
};
};
///////////////////////////////////////////////////////////////////////////////////////////
//
// You can't build a "displayName" within "DZE_NoBuildNearDistance" meters of a "class".
//
///////////////////////////////////////////////////////////////////////////////////////////
if (!_cancel) then {
if ((count DZE_NoBuildNear > 0) && !_isAdmin) then {
_near = (nearestObjects [_objectPos, DZE_NoBuildNear, DZE_NoBuildNearDistance]); // object's position
if ((count _near) > 0) then {
_cancel = true;
_reason = format [localize "STR_EPOCH_PLAYER_167", _text, DZE_NoBuildNearDistance, typeOf (_near select 0)]; // You can't build a %1 within %2 meters of a %3.
};
};
};
///////////////////////////////////////////////////////////////////////////////////////////
if (!_cancel) then {
_classname = _classnametmp;
local _tmpbuilt = _classname createVehicle [0,0,0];
//_tmpbuilt setdir _dir; // setdir is incompatible with setVectorDirAndUp and should not be used together on the same object https://community.bistudio.com/wiki/setVectorDirAndUp
_tmpbuilt setVariable["memDir", _dir, true];
local _position = _objectPos;
_tmpbuilt setVectorDirAndUp _vector;
if (surfaceIsWater _position) then {
_tmpbuilt setPosASL _position;
_position = ASLtoATL _position;
} else {
_tmpbuilt setPosATL _position;
};
//format[localize "str_epoch_player_138", _text] call dayz_rollingMessages; // Placing %1, move to cancel.
local _limit = 3;
if (DZE_StaticConstructionCount > 0) then {
_limit = DZE_StaticConstructionCount;
} else {
if (isNumber (configFile >> "CfgVehicles" >> _classname >> "constructioncount")) then {
_limit = getNumber(configFile >> "CfgVehicles" >> _classname >> "constructioncount");
};
};
_isOk = true;
local _counter = 0;
local _proceed = false;
while {_isOk} do {
format[localize "str_epoch_player_139", _text, (_counter + 1), _limit] call dayz_rollingMessages; // Constructing %1 stage %2 of %3, move to cancel.
[player, (getPosATL player), 40, "repair"] spawn fnc_alertZombies;
local _finished = ["Medic", 1, {player getVariable["combattimeout", 0] >= diag_tickTime or DZE_cancelBuilding}] call fn_loopAction;
if (!_finished) exitWith {
_isOk = false;
_proceed = false;
};
if (_finished) then {
_counter = _counter + 1;
};
if (_counter == _limit) exitWith {
_isOk = false;
_proceed = true;
};
};
if (_proceed) then {
local _num_removed = ([player, DZE_buildItem] call BIS_fnc_invRemove); // remove item's magazine from inventory
if (_num_removed == 1) then {
local _friendsArr = [];
["Working", 0, [20,10,5,0]] call dayz_NutritionSystem;
call player_forceSave;
[format[localize "str_build_01", _text], 1] call dayz_rollingMessages;
_tmpbuilt setVariable ["OEMPos", _position, true]; // store original location as a variable
if (_lockable > 1) then { //if item has code lock on it
local _combination = "";
local _combinationDisplay = ""; //define new display
local _combination_1_Display = "";
local _combination_1 = 0;
local _combination_2 = 0;
local _combination_3 = 0;
local _combination_4 = 0;
dayz_combination = "";
dayz_selectedVault = objNull;
call { // generate random combinations depending on item type
///////////////////////////////////////////////////
//
// 2 Lockbox
//
///////////////////////////////////////////////////
if (_lockable == 2) exitWith {
createDialog "KeyPadUI";
waitUntil {!dialog};
_combinationDisplay = dayz_combination call fnc_lockCode;
if (keypadCancel || {typeName _combinationDisplay == "SCALAR"}) then {
_combination_1 = (floor(random 3)) + 100; // 100=red / 101=green / 102=blue
_combination_2 = floor(random 10);
_combination_3 = floor(random 10);
_combination = format["%1%2%3",_combination_1,_combination_2,_combination_3];
dayz_combination = _combination;
call {
if (_combination_1 == 100) exitWith {_combination_1_Display = localize "STR_TEAM_RED"};
if (_combination_1 == 101) exitWith {_combination_1_Display = localize "STR_TEAM_GREEN"};
if (_combination_1 == 102) exitWith {_combination_1_Display = localize "STR_TEAM_BLUE"};
};
_combinationDisplay = format["%1%2%3", _combination_1_Display, _combination_2, _combination_3];
} else {
_combination = dayz_combination;
};
};
///////////////////////////////////////////////////
//
// 3 Combo Lock
//
///////////////////////////////////////////////////
if (_lockable == 3) exitWith {
DZE_topCombo = 0;
DZE_midCombo = 0;
DZE_botCombo = 0;
DZE_Lock_Door = "";
dayz_selectedDoor = objNull;
dayz_actionInProgress = false;
createDialog "ComboLockUI";
waitUntil {!dialog};
dayz_actionInProgress = true;
if (keypadCancel || {parseNumber DZE_Lock_Door == 0}) then {
_combination_1 = floor(random 10);
_combination_2 = floor(random 10);
_combination_3 = floor(random 10);
_combination = format["%1%2%3", _combination_1, _combination_2, _combination_3];
DZE_Lock_Door = _combination;
} else {
_combination = DZE_Lock_Door;
};
if (_classname in ["WoodenGate_1_DZ","WoodenGate_2_DZ","WoodenGate_3_DZ","WoodenGate_4_DZ"]) then {
GateMethod = DZE_Lock_Door;
};
_combinationDisplay = _combination;
};
///////////////////////////////////////////////////
//
// 4 Safe
//
///////////////////////////////////////////////////
if (_lockable == 4) exitWith {
createDialog "SafeKeyPad";
waitUntil {!dialog};
if (keypadCancel || {(parseNumber dayz_combination) > 9999} || {count (toArray (dayz_combination)) < 4}) then {
_combination_1 = floor(random 10);
_combination_2 = floor(random 10);
_combination_3 = floor(random 10);
_combination_4 = floor(random 10);
_combination = format["%1%2%3%4", _combination_1, _combination_2, _combination_3, _combination_4];
dayz_combination = _combination;
} else {
_combination = dayz_combination;
};
_combinationDisplay = _combination;
};
};
_tmpbuilt setVariable ["CharacterID", _combination, true]; // set combination as a character ID
// call publish precompiled function with given args and send public variable to server to save item to database
_tmpbuilt setVariable ["ownerPUID", dayz_playerUID, true];
PVDZ_obj_Publish = [_combination, _tmpbuilt, [_dir, _position, dayz_playerUID, _vector], [], player, dayz_authKey];
if (_lockable == 3) then {
_friendsArr = [[dayz_playerUID, toArray (name player)]];
_tmpbuilt setVariable ["doorfriends", _friendsArr, true];
PVDZ_obj_Publish = [_combination, _tmpbuilt, [_dir, _position, dayz_playerUID, _vector], _friendsArr, player, dayz_authKey];
};
publicVariableServer "PVDZ_obj_Publish";
[format[localize "str_epoch_player_140", _combinationDisplay, _text], 1] call dayz_rollingMessages; // display new combination
systemChat format[localize "str_epoch_player_140", _combinationDisplay, _text]; // You have setup your %2. The combination is %1
} else { // if not lockable item
_tmpbuilt setVariable ["CharacterID", dayz_characterID, true];
// fireplace
if (_tmpbuilt isKindOf "Land_Fire_DZ") then { // if campfire, then spawn, but do not publish to database
[_tmpbuilt, true] call dayz_inflame;
_tmpbuilt spawn player_fireMonitor;
} else {
_tmpbuilt setVariable ["ownerPUID", dayz_playerUID, true];
if (_isPole) then {
_friendsArr = [[dayz_playerUID, toArray (name player)]];
_tmpbuilt setVariable ["plotfriends", _friendsArr, true];
PVDZ_obj_Publish = [dayz_characterID, _tmpbuilt, [_dir, _position, dayz_playerUID, _vector], _friendsArr, player, dayz_authKey];
} else {
PVDZ_obj_Publish = [dayz_characterID, _tmpbuilt, [_dir, _position, dayz_playerUID, _vector], [], player, dayz_authKey];
};
publicVariableServer "PVDZ_obj_Publish";
};
};
if (DZE_GodModeBase && {!(_classname in DZE_GodModeBaseExclude)}) then {
_tmpbuilt addEventHandler ["HandleDamage", {false}];
};
} else { // if magazine was not removed, cancel publish
deleteVehicle _tmpbuilt;
localize "str_epoch_player_46" call dayz_rollingMessages; // Canceled building.
};
} else { // if player was interrupted cancel publish
deleteVehicle _tmpbuilt;
localize "str_epoch_player_46" call dayz_rollingMessages; // Canceled building.
};
} else { // cancel build if passed _cancel arg was true or building on roads/trader city
format[localize "str_epoch_player_47", _text, _reason] call dayz_rollingMessages; // Canceled construction of %1, %2.
};
};
DZE_buildItem = nil;
dayz_actionInProgress = false;