Epoch/Sources/epoch_code/compile/building/EPOCH_staticMove.sqf
He-Man 51f4564550 Update EPOCH_staticMove.sqf
Throw _object to EPOCH_isBuildAllowed, so it can be ignored in element counting
2016-12-10 20:26:32 +01:00

375 lines
11 KiB
Plaintext

/*
Author: Aaron Clark - EpochMod.com
Contributors:
Description:
Base building base building with ghost preview.
Licence:
Arma Public License Share Alike (APL-SA) - https://www.bistudio.com/community/licenses/arma-public-license-share-alike
Github:
https://github.com/EpochModTeam/Epoch/tree/release/Sources/epoch_code/compile/building/EPOCH_simulSwap.sqf
Example:
[_object,_item] spawn EPOCH_staticMove;
Parameter(s):
_this select 0: OBJECT - Base building object
_this select 1: STRING - Item to consume on build finalization
Returns:
NOTHING
*/
//[[[cog import generate_private_arrays ]]]
private ["_EPOCH_1","_EPOCH_2","_allowedSnapObjects","_allowedSnapPoints","_arr_snapPoints","_baselineSnapPos","_cfgBaseBuilding","_class","_currentOffSet","_currentPos","_currentTarget","_dir2","_direction","_distance","_energyCost","_ins","_isSnap","_lastCheckTime","_maxHeight","_maxSnapDistance","_nearestObject","_nearestObjects","_numberOfContacts","_objSlot","_objType","_offSet","_offsetZPos","_pOffset","_pos1","_pos1_snap","_pos2","_pos2ATL","_pos2_snap","_pos_snapObj","_rejectMove","_simulClass","_snapChecks","_snapConfig","_snapDistance","_snapPointsPara","_snapPointsPerp","_snapPos","_snapPos1","_snapPosition","_snapType","_stabilityCheck","_up2","_worldspace"];
//[[[end]]]
if !(isNil "EPOCH_simulSwap_Lock") exitWith{};
params [
["_object",objNull],
["_item",""]
];
// exit if object is nulll
if (isNull _object) exitWith{ EPOCH_target = objNull; };
// exit if item is not given
if (_item == "") exitWith{ EPOCH_target = objNull; };
if (EPOCH_playerEnergy <= 0) exitWith{
["Need Energy", 5] call Epoch_message;
};
// Remove object if not allowed
if !(_object call EPOCH_isBuildAllowed) exitWith{ deleteVehicle _object };
EPOCH_simulSwap_Lock = true;
_objType = typeOf _object;
_cfgBaseBuilding = 'CfgBaseBuilding' call EPOCH_returnConfig;
_energyCost = getNumber(_cfgBaseBuilding >> _objType >> "energyCost");
if (_energyCost == 0) then {
_energyCost = 0.1;
};
_class = getText(_cfgBaseBuilding >> _objType >> "GhostPreview");
_maxHeight = getNumber(_cfgBaseBuilding >> _objType >> "maxHeight");
_simulClass = getText(_cfgBaseBuilding >> _objType >> "simulClass");
_snapChecks = getArray(("CfgSnapChecks" call EPOCH_returnConfig) >> _objType >> "nails");
_maxSnapDistance = 1;
_lastCheckTime = diag_tickTime;
_stabilityCheck = false;
// force sim check if object has sim class and default max height to 9m if not already specified
if (_simulClass != "") then {
_stabilityCheck = true;
if (_maxHeight == 0) then {
_maxHeight = 500;
};
};
if (_class != "") then {
_objSlot = _object getVariable["BUILD_SLOT", -1];
deleteVehicle _object;
_pos2 = player modelToWorldVisual[EPOCH_X_OFFSET, EPOCH_Y_OFFSET, EPOCH_Z_OFFSET];
EPOCH_target = createVehicle[_class, _pos2, [], 0, "CAN_COLLIDE"];
// send to server
[EPOCH_target] remoteExec ["EPOCH_localCleanup",2];
if (_pos2 select 2 > _maxHeight) then {
_pos2 set[2, _maxHeight];
};
_pos2ATL = _pos2;
if (surfaceIsWater _pos2ATL) then {
_pos2ATL = ASLtoATL _pos2ATL;
};
EPOCH_target setposATL _pos2ATL;
EPOCH_target attachTo[player];
_currentTarget = EPOCH_target;
if (_objSlot != -1) then {
_currentTarget setVariable["BUILD_SLOT", _objSlot, true];
};
_allowedSnapPoints = getArray(_cfgBaseBuilding >> _class >> "allowedSnapPoints");
_allowedSnapObjects = getArray(_cfgBaseBuilding >> _class >> "allowedSnapObjects");
_currentOffSet = [];
EP_snap = objNull;
EP_snapPos = [0, 0, 0];
_isSnap = false;
_EPOCH_1 = diag_tickTime;
_EPOCH_2 = diag_tickTime;
_nearestObjects = [];
while {EPOCH_target == _currentTarget} do {
_rejectMove = false;
if ((diag_tickTime - _lastCheckTime) > 10) then {
_lastCheckTime = diag_tickTime;
_rejectMove = !(_object call EPOCH_isBuildAllowed);
};
if (_rejectMove) exitWith{
deleteVehicle EPOCH_target;
};
_offSet = [EPOCH_X_OFFSET, EPOCH_Y_OFFSET, EPOCH_Z_OFFSET];
_pos2 = player modelToWorldVisual _offSet;
if (surfaceIsWater _pos2) then {
_pos2 set[2, ((getPosASL player) select 2) + EPOCH_Z_OFFSET];
};
if !(_currentOffSet isEqualTo _offSet) then {
_currentOffSet = _offSet;
{
detach _x;
} forEach attachedObjects player;
if (_pos2 select 2 > _maxHeight) then {
_pos2 set[2, _maxHeight];
};
_pos2ATL = _pos2;
if (surfaceIsWater _pos2ATL) then {
_pos2ATL = ASLtoATL _pos2ATL;
};
EPOCH_target setposATL _pos2ATL;
EPOCH_target attachTo[player];
};
if (EPOCH_doRotate) then {
_dir2 = [vectorDir player, EPOCH_buildDirection] call BIS_fnc_returnVector;
_up2 = (vectorUp player);
EPOCH_doRotate = false;
EPOCH_target setVectorDirAndUp [_dir2,_up2];
};
{
_nearestObject = _x;
if !(isNull EP_snap) then {
if ((_pos2 distance EP_snapPos) < _maxSnapDistance) then {
_nearestObject = EP_snap;
};
};
if (!isNull _nearestObject && _nearestObject isEqualTo _x) then {
_isSnap = false;
_snapPosition = [0, 0, 0];
_snapConfig = _cfgBaseBuilding >> (typeOf _nearestObject);
_snapPointsPara = getArray(_snapConfig >> "snapPointsPara");
_snapPointsPerp = getArray(_snapConfig >> "snapPointsPerp");
// base line for z height offset
_baselineSnapPos = _nearestObject modelToWorldVisual [0,0,0];
if (EPOCH_buildMode == 1) then {
{
_x params ["_snapPoints","_type"];
{
if (_x in _allowedSnapPoints) then {
_pOffset = _nearestObject selectionPosition _x;
_snapPos = _nearestObject modelToWorldVisual _pOffset;
if (surfaceIsWater _snapPos) then {
_snapPos set[2, ((getPosASL _nearestObject) select 2) + (_pOffset select 2)];
};
_snapDistance = _pos2 distance _snapPos;
if (_snapDistance < _maxSnapDistance) exitWith{
_isSnap = true;
_snapPosition = _snapPos;
_snapType = _type;
};
};
} forEach _snapPoints;
} forEach [[_snapPointsPara,"para"],[_snapPointsPerp,"perp"]];
};
_distance = _pos2 distance _currentTarget;
if (_isSnap && _distance < 5) then {
EP_snap = _nearestObject;
EP_snapPos = _snapPosition;
_direction = getDir _nearestObject;
if (_snapType == "perp") then {
_snapPos1 = [_snapPosition select 0, _snapPosition select 1, 0];
_pos_snapObj = getposATL _nearestObject;
_pos_snapObj set[2, 0];
_direction = _direction - (_snapPos1 getDir _pos_snapObj);
} else {
_direction = 0;
};
if (EPOCH_snapDirection > 0) then {
if (EPOCH_snapDirection == 1) then {
_direction = _direction + 90;
};
if (EPOCH_snapDirection == 2) then {
_direction = _direction + 180;
};
if (EPOCH_snapDirection == 3) then {
_direction = _direction + 270;
};
};
if (_direction > 360) then {
_direction = _direction - 360;
};
if (_direction < 0) then {
_direction = 360 + _direction;
};
if !(attachedObjects player isEqualTo[]) then {
{
detach _x;
} forEach attachedObjects player;
if (EPOCH_snapDirection > 0) then {
if (EPOCH_snapDirection == 1) then {
_direction = _direction + 90;
};
if (EPOCH_snapDirection == 2) then {
_direction = _direction + 180;
};
if (EPOCH_snapDirection == 3) then {
_direction = _direction + 270;
};
};
if (_direction > 360) then {
_direction = _direction - 360;
};
if (_direction < 0) then {
_direction = 360 + _direction;
};
_dir2 = [vectorDir _nearestObject, _direction] call BIS_fnc_returnVector;
if (_pos2 select 2 > _maxHeight) then {
_pos2 set[2, _maxHeight];
};
if (surfaceIsWater _snapPosition) then {
_snapPosition = ASLtoATL _snapPosition;
};
_currentTarget setVectorDirAndUp[_dir2, (vectorUp _nearestObject)];
_currentTarget setposATL _snapPosition;
if ((diag_tickTime - _EPOCH_2) > 2) then {
_EPOCH_2 = diag_tickTime;
_arr_snapPoints = [];
EPOCH_arr_snapPoints = [];
{
_pos1_snap = _currentTarget modelToWorldVisual (_x select 0);
_pos2_snap = _currentTarget modelToWorldVisual (_x select 1);
_ins = lineIntersectsSurfaces [AGLToASL _pos1_snap, AGLToASL _pos2_snap,player,_currentTarget,true,1,"VIEW","FIRE"];
if (count _ins > 0) then {
if (surfaceIsWater _snapPosition) then {
_arr_snapPoints pushBackUnique (_ins select 0 select 0);
} else {
_arr_snapPoints pushBackUnique ASLToATL(_ins select 0 select 0);
};
};
if (count _arr_snapPoints >= 2) exitWith { EPOCH_arr_snapPoints = _arr_snapPoints; }
} forEach _snapChecks;
};
};
} else {
EPOCH_arr_snapPoints = [];
if !(attachedObjects player isEqualTo[]) then {
_offSet = [EPOCH_X_OFFSET, EPOCH_Y_OFFSET, EPOCH_Z_OFFSET];
_pos1 = player modelToWorldVisual _offSet;
if (surfaceIsWater _pos1) then {
_pos1 set[2, ((getPosASL player) select 2) + EPOCH_Z_OFFSET];
_pos1 = ASLtoATL _pos1;
};
EPOCH_target setposATL _pos1;
EPOCH_target attachTo[player];
};
};
};
} forEach _nearestObjects;
if ((diag_tickTime - _EPOCH_1) > 1) then {
_EPOCH_1 = diag_tickTime;
if !(isNull EPOCH_target) then {
_nearestObjects = nearestObjects[EPOCH_target, _allowedSnapObjects, 12];
EPOCH_playerEnergy = (EPOCH_playerEnergy - _energyCost) max 0;
};
};
};
EPOCH_arr_snapPoints = [];
{
detach _x;
} forEach attachedObjects player;
if !(isNull _currentTarget) then {
// check if touching ground
_currentPos = getPosATL _currentTarget;
if (_currentPos select 2 > _maxHeight) then {
_currentPos set[2, _maxHeight];
_currentTarget setPosATL _currentPos;
};
_currentPos set[2, (_currentPos select 2) + 0.1];
// remove item here
if (([player, _item] call BIS_fnc_invRemove) == 1) then {
if (_stabilityCheck && !isTouchingGround _currentTarget) then {
_offsetZPos = [_currentPos select 0, _currentPos select 1, (_currentPos select 2) - 0.5];
if !(terrainIntersect[_currentPos, _offsetZPos]) then {
_numberOfContacts = 0;
{
_pos1_snap = _currentTarget modelToWorldVisual (_x select 0);
_pos2_snap = _currentTarget modelToWorldVisual (_x select 1);
_ins = lineIntersectsSurfaces [AGLToASL _pos1_snap, AGLToASL _pos2_snap,player,_currentTarget,true,1,"VIEW","FIRE"];
if (count _ins > 0) then {
_numberOfContacts = _numberOfContacts + 1;
};
if (_numberOfContacts >= 2) exitWith {}
} forEach _snapChecks;
if (_numberOfContacts < 2) then {
// TODO: foundations need to be handled
// change to sim
_worldspace = [getposATL _currentTarget, vectordir _currentTarget, vectorup _currentTarget];
deleteVehicle _currentTarget;
_currentTarget = createVehicle[_simulClass, (_worldspace select 0), [], 0, "CAN_COLLIDE"];
_currentTarget setVectorDirAndUp[_worldspace select 1, _worldspace select 2];
_currentTarget setposATL(_worldspace select 0);
};
};
};
_currentTarget spawn EPOCH_countdown;
};
};
};
[] spawn{
uiSleep 2;
EPOCH_simulSwap_Lock = nil;
};