309 lines
8.7 KiB
Plaintext
309 lines
8.7 KiB
Plaintext
/*
|
|||
|
|
* 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;
|
||
|
|
};
|
||
|
|
|