/* * Author: Clarky * Usage: * [_class, _cost, _buildTime, _specialisation] call CLF_fnc_factoryBuild; * * Intended to be called via the factoryConfirmSelection function * * Purpose: * Begins the process of building a vehicle with player selection on the VehicleFactory dialog * */ params ["_player", "_vehicleClass", "_cost", "_buildTime", "_specialisation", "_specialisationData"]; // Stow weapon at start of process player action ["SWITCHWEAPON", player, player, -1]; private _rotation = getDir player; missionNamespace setVariable ["previewRotation", _rotation]; private _confirm = false; private _cancel = false; private _hq = uiNamespace getVariable ["localHQ", ""]; if (_hq isEqualTo "") exitWith { hint "No local HQ"; }; // Spawn the vehicle locally - only player who clicked the dialog will see it at this stage private _vehiclePreview = createVehicleLocal [ _vehicleClass, [0, 0, 0], [], 0, "NONE" ]; _vehiclePreview disableCollisionWith _player; //waitUntil { _vehiclePreview == _vehiclePreview }; // Disable all damage and simulation until build is confirmed _vehiclePreview enableSimulation false; _vehiclePreview enableSimulationGlobal false; _vehiclePreview allowDamage false; //_vehiclePreview setPhysicsCollisionFlag false; removeAllActions _vehiclePreview; _vehiclePreview setVehicleLock "LOCKED"; _vehiclePreview lockInventory true; // Apply a slight tint/texture which will be used to show the player if it can be placed or not _vehiclePreview setObjectTextureGlobal [0, "#(argb,8,8,3)color(0,1,0,0.35,ca)"]; // Load the 'display' handling input events private _display = findDisplay 46; private _mouseScroll = _display displayAddEventHandler [ // Handle mouse scroll wheel axis input "MouseZChanged", { params ["_display", "_scroll"]; private _dir = missionNamespace getVariable ["previewRotation", 0]; _dir = _dir + (_scroll * 5); missionNamespace setVariable ["previewRotation", _dir]; } ]; private _mouseInput = _display displayAddEventHandler [ // Handle LMB/RMB click "MouseButtonDown", { params ["", "_button"]; switch (_button) do { case 0: // LMB { missionNamespace setVariable [ "confirmPlacement", true ]; }; case 1: // RMB { missionNamespace setVariable [ "cancelPlacement", true ]; }; }; false; } ]; private _keyboardInput = _display displayAddEventHandler [ // Handle keyboard clicks as extra verification tools "KeyDown", { params ["", "_key"]; switch (_key) do { case 28: // Enter { missionNamespace setVariable [ "confirmPlacement", true ]; }; case 1: // Escape { missionNamespace setVariable [ "cancelPlacement", true ]; }; }; false; } ]; // Load up variables for closing out the build preview one way or the other missionNamespace setVariable ["confirmPlacement",false]; missionNamespace setVariable ["cancelPlacement",false]; _previewUI = addMissionEventHandler [ "Draw3D", { //hint "sucessfully spawned preview"; if (missionNamespace getVariable ["confirmPlacement", false]) exitWith {}; if (missionNamespace getVariable ["cancelPlacement", false]) exitWith { hintSilent ""; }; hintSilent "VEHICLE CONSTRUCTION\n\nLMB: Confirm\nRMB: Cancel\nScrollwheel: Rotate"; /* drawIcon3D [ "", [1, 1, 1, 1], positionCameraToWorld [0, 3, 0], 0, 0, 0, "LMB: Place | RMB: Cancel | Scroll: Rotate", 2, 0.04, "PuristaMedium" ];*/ } ]; // Spawn code that runs until the player while { (player call ace_medical_fnc_isInStableCondition) && !_confirm && !_cancel } do { private _rotation = missionNamespace getVariable ["previewRotation", 0]; // Raycast out from player perspective to find location to place the preview vehicle private _maxDistance = 15; private _start = eyePos player; private _direction = getCameraViewDirection player; private _end = _start vectorAdd ( _direction vectorMultiply _maxDistance ); private _hits = lineIntersectsSurfaces [ _start, _end, player, _vehiclePreview, true, 1, "GEOM", "NONE" ]; ///////////////////////////////////////////////////////////////////// // Validation on placement ///////////////////////////////////////////////////////////////////// private _valid = false; // Only proceed with updates to vehicle pos if we get a result back from the raycast if (_hits isNotEqualTo []) then { private _groundPos = (_hits select 0) select 0; //hint format ["Raycast Hit: %1", str _groundPos]; _vehiclePreview setDir _rotation; _vehiclePreview setPosASL _groundPos; _vehiclePreview setVectorUp surfaceNormal position _vehiclePreview; private _nearbyObjects = _vehiclePreview nearObjects 7; _nearbyObjects = _nearbyObjects - [_vehiclePreview]; { if ( !(_x isKindOf "Man") && !(_x isKindOf "Items_base_F") && !(_x isKindOf "LandVehicle") && !(_x isKindOf "Air") && !(_x isKindOf "Ship") && !(_x isKindOf "Building") && !(_x isKindOf "StaticWeapon") ) then { _nearbyObjects = _nearbyObjects - [_x]; } } forEach _nearbyObjects; //hint str _nearbyObjects; private _collision = false; // Bit quick and dirty but this should get the job done for now - checking for nearby objects near the preview vehicle { if (_vehiclePreview distance _x < 7) exitWith { _collision = true; } } forEach _nearbyObjects; //hint format ["%1", _nearbyObjects]; // If the raycast returns a point on terrain, and we reach this point and confirm there is no nearby objects going to potentially cause issues, mark _valid as true if (!_collision) then { _valid = true; }; }; // else // { // private _terrainInferrence = screenToWorld [0.5, 0.5]; // _vehiclePreview setDir _rotation; // _vehiclePreview setPosASL _terrainInferrence; // } ///////////////////////////////////////////////////////////////////// // Update texture according to current validity ///////////////////////////////////////////////////////////////////// if (_valid) then { _vehiclePreview setObjectTextureGlobal [ 0, "#(argb,8,8,3)color(0,1,0,0.35,ca)" ]; } else { _vehiclePreview setObjectTextureGlobal [ 0, "#(argb,8,8,3)color(1,0,0,0.35,ca)" ]; }; ///////////////////////////////////////////////////////////////////// // Check for updated input variables ///////////////////////////////////////////////////////////////////// if (missionNamespace getVariable ["confirmPlacement", false]) then { if (_valid) then { _confirm = true; } else { // Reset confirm variable back to false, as otherwise this code will fire off at next available 'valid' opportunity missionNamespace setVariable [ "confirmPlacement", false ]; } }; if (missionNamespace getVariable ["cancelPlacement", false]) then { _cancel = true; }; uiSleep 0.01; }; // Remove display eventhandlers to stop capturing inputs needlessly _display displayRemoveEventHandler ["onMouseButtonDown", _mouseInput]; _display displayRemoveEventHandler ["MouseZChanged", _mouseScroll]; _display displayRemoveEventHandler ["KeyDown", _keyboardInput]; removeMissionEventHandler ["Draw3D", _previewUI]; private _pos = getPosATL _vehiclePreview; private _up = surfaceNormal position _vehiclePreview; // Cleanup _vehiclePreview deleteVehicle _vehiclePreview; // Proceed to call the build confirm function if valid from checks above if (_confirm) then { [ "CLF_ConfirmFactoryBuildServer", [ _hq, _player, _vehicleClass, _pos, missionNamespace getVariable ["previewRotation", 0], _up, _cost, _buildTime, _specialisation, _specialisationData ] ] call CBA_fnc_serverEvent; };