--
-- FS22 - Towing Bar With Hook v1.0.0.0
-- @author:    	kenny456 (kenny456@seznam.cz)
-- @history:	v1.0.0.0 - 2020-09-27 - first release
-- 						   2022-02-07 - FS22 conversion
-- Copyright (C) kenny456, All Rights Reserved.
--
PushBar = {}
PushBar.confDir = getUserProfileAppPath().. "modSettings/PushBar/"
PushBar.modDirectory = g_currentModDirectory
local modName = g_currentModName
PushBar.bar = {}
PushBar.lastSelectedBarId = 1

PushBar.IdsDistanceViews = { 1, 2, 3, 4, 5, 10, 15, 20, 30, 40, 50 }
PushBar.barDistanceViews = { 10, 20, 30, 40, 50, 70, 100, 150, 200 }
PushBar.booleans = { true, false }
PushBar.steeringModes = { 1, 2, 3 }

PushBar.IdsDistanceViewsTexts = { '1m', '2m', '3m', '4m', '5m', '10m', '15m', '20m', '30m', '40m', '50m' }
PushBar.barDistanceViewsTexts = { '10m', '20m', '30m', '40m', '50m', '70m', '100m', '150m', '200m' }
PushBar.booleansTexts = { 'On', 'Off' }
PushBar.steeringModesTexts = { g_i18n:getText('gui_tc_both'), g_i18n:getText('gui_tc_auto'), g_i18n:getText('gui_tc_manual') }

PushBar.manualAttach = true
PushBar.showHelp = true
PushBar.showIds = true
PushBar.IdsDistanceView = 5
PushBar.barDistanceView = 100
PushBar.steeringMode = 1
PushBar.autoOffVehicle = false

PushBar.manualAttachIndex = 1
PushBar.showHelpIndex = 1
PushBar.showIdsIndex = 1
PushBar.IdsDistanceViewIndex = 5
PushBar.barDistanceViewIndex = 7
PushBar.steeringModeIndex = 1
PushBar.autoOffVehicleIndex = 2

function getIndexFromElement(table, element)
	for index, el in pairs(table) do
		if type(element) == 'number' then
			if string.format("%.2f", element) == string.format("%.2f", el) then
				return index
			end
		else
			if element == el then
				return index
			end
		end
	end
	return false
end

function PushBar.prerequisitesPresent(specializations)
	return true
end
function PushBar.initSpecialization()
    local schema = Vehicle.xmlSchema
    schema:setXMLSpecializationType("PushBar")
	AttacherJoints.registerAttacherJointXMLPaths(schema, "vehicle.pushBar.attacherJoints.attacherJoint(?)")

    schema:setXMLSpecializationType()
end
function PushBar.registerOverwrittenFunctions(vehicleType)
	SpecializationUtil.registerOverwrittenFunction(vehicleType, "isDetachAllowed", 		PushBar.isDetachAllowed)
	SpecializationUtil.registerOverwrittenFunction(vehicleType, "getCanBePickedUp", 	PushBar.getCanBePickedUp)
	if PushBar.twPlayer == nil then
		Player.registerActionEvents = Utils.appendedFunction(Player.registerActionEvents, PushBar.registerActionEventsPlayer);
		PushBar.twPlayer = true
	end
end
function PushBar.registerFunctions(vehicleType)
	SpecializationUtil.registerFunction(vehicleType, "attachVehicles", 					PushBar.attachVehicles)
	SpecializationUtil.registerFunction(vehicleType, "detachVehicles", 					PushBar.detachVehicles)
	SpecializationUtil.registerFunction(vehicleType, "playerInRange", 					PushBar.playerInRange)
	SpecializationUtil.registerFunction(vehicleType, "getIsTurnedOn", 					PushBar.getIsTurnedOn)
	SpecializationUtil.registerFunction(vehicleType, "mountHook", 						PushBar.mountHook)
	SpecializationUtil.registerFunction(vehicleType, "unmountHook", 					PushBar.unmountHook)
	SpecializationUtil.registerFunction(vehicleType, "switchToNextBar", 				PushBar.switchToNextBar)
	SpecializationUtil.registerFunction(vehicleType, "getIsControlled", 				PushBar.getIsControlled)
	SpecializationUtil.registerFunction(vehicleType, "toggleControlVehicle", 			PushBar.toggleControlVehicle)
	SpecializationUtil.registerFunction(vehicleType, "getFirstAttacher", 				PushBar.getFirstAttacher)
	SpecializationUtil.registerFunction(vehicleType, "getFirstVehicleAttached", 		PushBar.getFirstVehicleAttached)
	SpecializationUtil.registerFunction(vehicleType, "getIsVehicleControlledByPlayer", 	PushBar.getIsVehicleControlledByPlayer)
	SpecializationUtil.registerFunction(vehicleType, "getBarCanBeAttached", 			PushBar.getBarCanBeAttached)
	SpecializationUtil.registerFunction(vehicleType, "moveHook", 						PushBar.moveHook)
	SpecializationUtil.registerFunction(vehicleType, "saveConfigTc", 					PushBar.saveConfigTc)
	SpecializationUtil.registerFunction(vehicleType, "loadConfigTc", 					PushBar.loadConfigTc)
	SpecializationUtil.registerFunction(vehicleType, "updateManualSteering", 			PushBar.updateManualSteering)
	SpecializationUtil.registerFunction(vehicleType, "vehicleIdToVehicle", 				PushBar.vehicleIdToVehicle)
	SpecializationUtil.registerFunction(vehicleType, "vehicleToVehicleId", 				PushBar.vehicleToVehicleId)
	SpecializationUtil.registerFunction(vehicleType, "updateDirtAndWear", 				PushBar.updateDirtAndWear)
end
function PushBar.registerEvents(vehicleType)
end
function PushBar:registerActionEventsPlayer()
	local spec = self.spec_pushBar
	
	if g_dedicatedServerInfo ~= nil then
		return
	end
	if PushBar.event_IDsPlayer == nil then
		PushBar.event_IDsPlayer = {}
	end
	local actions = { InputAction.PUSHBAR_MANUAL_ATTACH, InputAction.PUSHBAR_SWITCH, InputAction.PUSHBAR_MOVE_HOOK_TRIGGER, InputAction.PUSHBAR_MOVE_HOOK_LEFT, InputAction.PUSHBAR_MOVE_HOOK_RIGHT,
					InputAction.PUSHBAR_MOVE_HOOK_FORWARD, InputAction.PUSHBAR_MOVE_HOOK_BACKWARD, InputAction.PUSHBAR_MOVE_HOOK_UP, InputAction.PUSHBAR_MOVE_HOOK_DOWN, InputAction.PUSHBAR_OPEN_MENU }

	for _,actionName in pairs(actions) do
		local always = (actionName == InputAction.PUSHBAR_CHANGE_MOVE_HOOK_LEFT or actionName == InputAction.PUSHBAR_CHANGE_MOVE_HOOK_RIGHT or actionName == InputAction.PUSHBAR_CHANGE_MOVE_HOOK_FORWARD or
						actionName == InputAction.PUSHBAR_CHANGE_MOVE_HOOK_BACKWARD or actionName == InputAction.PUSHBAR_CHANGE_MOVE_HOOK_UP or actionName == InputAction.PUSHBAR_CHANGE_MOVE_HOOK_DOWN or actionName == InputAction.PUSHBAR_MOVE_HOOK_TRIGGER) and true or false
		local __, eventID = InputBinding.registerActionEvent(g_inputBinding, actionName, self, PushBar.actionCallbackPlayer, true, true, always, true)
		PushBar.event_IDsPlayer[actionName] = eventID
		if g_inputBinding ~= nil and g_inputBinding.events ~= nil and g_inputBinding.events[eventID] ~= nil then
			if actionName == 'something with lower priority' then
				g_inputBinding:setActionEventTextPriority(eventID, GS_PRIO_NORMAL)
			else
				g_inputBinding:setActionEventTextPriority(eventID, GS_PRIO_VERY_HIGH)
			end
			if actionName == InputAction.AUTOLOADWOOD2_TOGGLE_HELP then
				g_inputBinding:setActionEventTextVisibility(eventID, true)
			else
				g_inputBinding:setActionEventTextVisibility(eventID, PushBar.showHelp)
			end
			g_inputBinding:setActionEventActive(eventID, false)
		end
		local colliding = false
		_, colliding, _ = g_inputBinding:checkEventCollision(actionName)
		if colliding then
			print(string.format("Warning: PushBar got a colliding action for player: %s", actionName))
		end
	end
end
function PushBar:onRegisterActionEvents(isSelected, isOnActiveVehicle)
	local spec = self.spec_pushBar
	
	if self.spec_attachable.attacherVehicle ~= nil then
		local firstAttVehicle = self:getFirstAttacher(self, nil, false)
		local firstVehicleAttached = self:getFirstVehicleAttached(self, nil, false)
		if firstAttVehicle ~= nil then
			if firstAttVehicle:getIsControlled() or self.spec_attachable.attacherVehicle:getIsControlled() then-------------------------------------------------------------------	ADDED
				if firstVehicleAttached ~= nil and self.isServer and not spec.isUsedSelf then
					if g_currentMission.missionInfo.automaticMotorStartEnabled then
						if not spec.controlVehicle and (spec.attachedVehicleThrottle or spec.steeringMode == 2 or spec.steeringMode == 3) then
							--print(spec.barId..' - toggleControlVehicle 1')
							self:toggleControlVehicle(spec.attachedVehicleThrottle, spec.steeringMode, spec.reverseDrivingMode, true, false)
						end
					else
						if spec.controlVehicle and not firstVehicleAttached.spec_motorized.isMotorStarted then
							firstVehicleAttached:startMotor(false)
						elseif not spec.controlVehicle then
							if spec.attachedVehicleThrottle or spec.steeringMode == 2 or spec.steeringMode == 3 then
								--print(spec.barId..' - toggleControlVehicle 2')
								self:toggleControlVehicle(spec.attachedVehicleThrottle, spec.steeringMode, spec.reverseDrivingMode, true, false)
							elseif firstVehicleAttached.spec_motorized.isMotorStarted then
								firstVehicleAttached:stopMotor(false)
							end
						end
					end
				end
				if spec.isAttached then
					PushBar.selectedBarId = spec.barId
				end
				self:loadConfigTc()
			else
				if firstVehicleAttached ~= nil and self.isServer and not spec.isUsedSelf then
					if spec.controlVehicle then
						Drivable.updateVehiclePhysics(firstVehicleAttached, 0, spec.reverseDrivingMode and spec.axisSteer or spec.axisSteer, false, 1)
						if g_currentMission.missionInfo.automaticMotorStartEnabled then
							--print(spec.barId..' - toggleControlVehicle 3')
							self:toggleControlVehicle(spec.attachedVehicleThrottle, spec.steeringMode, spec.reverseDrivingMode, true, false)
						end
					end
				end
			end
		end
	end
	
	if g_dedicatedServerInfo ~= nil then
		return
	end
	if spec.event_IDs == nil then
		spec.event_IDs = {}
	else
		self:clearActionEventsTable(spec.event_IDs)
	end
	if self:getIsActiveForInput() then
		local actions = { InputAction.PUSHBAR_ATTACH_VEHICLE, InputAction.PUSHBAR_VEHICLE_THROTTLE, InputAction.PUSHBAR_TOGGLE_STEERING_MODE, InputAction.PUSHBAR_STEER_LEFT,
						InputAction.PUSHBAR_STEER_RIGHT, InputAction.PUSHBAR_CHANGE_ATTACHED_DIRECTION, InputAction.PUSHBAR_OPEN_MENU_VEHICLE }

		for _,actionName in pairs(actions) do
			local always = (actionName == InputAction.PUSHBAR_STEER_LEFT or actionName == InputAction.PUSHBAR_STEER_RIGHT) and true or false
			local _, eventID = g_inputBinding:registerActionEvent(actionName, self, PushBar.actionCallback, true, true, always, true)
			spec.event_IDs[actionName] = eventID
			if g_inputBinding ~= nil and g_inputBinding.events ~= nil and g_inputBinding.events[eventID] ~= nil then
				if actionName == InputAction.PUSHBAR_STEER_LEFT or actionName == InputAction.PUSHBAR_STEER_RIGHT then
					g_inputBinding:setActionEventTextPriority(eventID, GS_PRIO_NORMAL)
				elseif actionName == InputAction.PUSHBAR_CHANGE_ATTACHED_DIRECTION then
					g_inputBinding:setActionEventTextPriority(eventID, GS_PRIO_HIGH)
				else
					g_inputBinding:setActionEventTextPriority(eventID, GS_PRIO_VERY_HIGH)
				end
				if actionName == InputAction.RC_TOGGLE_HELP then
					g_inputBinding:setActionEventTextVisibility(eventID, true)
				elseif actionName == InputAction.RC_TOGGLE or actionName == InputAction.RC_TOGGLE_ALL then
					g_inputBinding:setActionEventTextVisibility(eventID, false)
				else
					g_inputBinding:setActionEventTextVisibility(eventID, PushBar.showHelp)
				end
				g_inputBinding:setActionEventActive(eventID, true)
			end
			local colliding = false
			_, colliding, _ = g_inputBinding:checkEventCollision(actionName)
			if colliding then
				if g_inputBinding.nameActions[actionName].bindings[1] ~= nil then
					if g_inputBinding.nameActions[actionName].bindings[1].inputString ~= nil then
						print(string.format('Warning: PushBar got a colliding input action: %s', actionName)..' ('..g_inputBinding.nameActions[actionName].bindings[1].inputString..'). You can remap it in controls settings')
					end
				else
					print(string.format('Warning: PushBar got a colliding input action: %s', actionName))
				end
			end
		end
	end
end
function PushBar.registerEventListeners(vehicleType)
	for _,n in pairs( { "onLoad", "onPostLoad", "onPreDelete", "onUpdate", "onUpdateTick", "onDraw", "onReadStream", "onWriteStream", "onRegisterActionEvents", "moveHook", "attachVehicles", "detachVehicles", "mountHook", "unmountHook" } ) do
		SpecializationUtil.registerEventListener(vehicleType, n, PushBar)
	end
end
function PushBar:onLoad(savegame)
	self.spec_pushBar = {}
	local spec = self.spec_pushBar
	
    spec.attachPoint = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile.handle,"vehicle.pushBar#index"));
    spec.attachPointColli = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile.handle,"vehicle.pushBar#rootNode"));
    spec.isUsed = false
	spec.isUsedSelf = false
    spec.joint = {};
    spec.lastVehicle = nil;
	local baseName = "vehicle"
	spec.sampleAttach = g_soundManager:loadSampleFromXML(self.xmlFile.handle, baseName, "attachSound", self.baseDirectory, self.components, 1, AudioGroup.VEHICLE, self.i3dMappings, self)
	spec.inputBarAttachVehicle = false
	spec.inputBarVehicleThrottle = false
	spec.inputControlVehicle = false
	spec.attachedVehicleThrottle = false
	spec.controlVehicle = false
	PushBar.input_manualAttach = false
	spec.timer = 0
	spec.firsRun = true
	spec.hookMounted = false
	spec.barId = #PushBar.bar + 1
	spec.isAttached = false
	spec.isInRange = false
	spec.axisSteer = 0
	spec.axisForward = 0
	spec.autoSteer = true
	spec.steeringMode = 1
	spec.steeringModeLast = 1
	spec.reverseDrivingMode = false
	spec.timerHook = 0
	spec.hookIsMoving = false
	spec.timer2 = 0
	spec.input_STEER_LEFT = false
	spec.input_STEER_RIGHT = false
	spec.debug = false
	if self.selectionObject.vehicle.isVehicleSaved then
		PushBar.bar[spec.barId] = self
	end
	if PushBar.selectedBarId == nil then
		PushBar.selectedBarId = spec.barId
	end
	--gui
	source(Utils.getFilename(PushBar.modDirectory .. "gui/tcGui.lua")) 
    PushBar.gui = {};
    PushBar.gui["tcSettingGui"] = tcGui:new();
	g_gui:loadGui(PushBar.modDirectory .. "gui/tcGui.xml", "tcGui", PushBar.gui.tcSettingGui)
	PushBar:loadConfigTc()
end
function PushBar:onPostLoad(savegame)
	local spec = self.spec_pushBar
	
	if savegame ~= nil then
		local xmlFile = savegame.xmlFile.handle
		local key = savegame.key.."."..modName..".PushBar"
		local isUsed = Utils.getNoNil(getXMLBool(xmlFile, key.."#isUsed"), spec.isUsed)
		local hookMounted = Utils.getNoNil(getXMLBool(xmlFile, key.."#hookMounted"), spec.hookMounted)
		
		if hookMounted then
			spec.hookMountedBack = getXMLBool(xmlFile, key.."#hookMountedBack")
			spec.hookX = getXMLFloat(xmlFile, key.."#hookX")
			spec.hookY = getXMLFloat(xmlFile, key.."#hookY")
			spec.hookZ = getXMLFloat(xmlFile, key.."#hookZ")
			local hookedVehicleId = getXMLInt(xmlFile, key.."#hookedVehicleId2")
			if hookedVehicleId ~= nil then
				spec.postMountHook = true
				spec.postMountHookVal = {hookedVehicleId}
			end
		end
		if isUsed then
			local attachedVehicleId = getXMLInt(xmlFile, key.."#attachedVehicleId2")
			local attacherJointId = getXMLInt(xmlFile, key.."#attacherJointId")
			if attachedVehicleId ~= nil and attacherJointId ~= nil then
				spec.postAttachVehicles = true
				spec.postAttachObjectVal = {attachedVehicleId, attacherJointId}
			end
		end
	end
end
function PushBar:saveConfigTc()
	local spec = self.spec_pushBar

	if g_dedicatedServerInfo ~= nil then
		return
	end

	local configFile = PushBar.confDir .. "PushBarConfig.xml"
	createFolder(getUserProfileAppPath().. "modSettings/")
	createFolder(PushBar.confDir)
	PushBar.configXml = createXMLFile("PushingBar_XML", configFile, "PushBarConfig")

	if PushBar ~= nil then  
		setXMLBool(PushBar.configXml, "PushBarConfig.manualAttach", PushBar.manualAttach)
		setXMLBool(PushBar.configXml, "PushBarConfig.showHelp", PushBar.showHelp)
		setXMLBool(PushBar.configXml, "PushBarConfig.showIds", PushBar.showIds)
		setXMLFloat(PushBar.configXml, "PushBarConfig.IdsDistanceView", PushBar.IdsDistanceView)
		setXMLFloat(PushBar.configXml, "PushBarConfig.barDistanceView", PushBar.barDistanceView)
		setXMLFloat(PushBar.configXml, "PushBarConfig.steeringMode", PushBar.steeringMode)
		setXMLBool(PushBar.configXml, "PushBarConfig.autoOffVehicle", PushBar.autoOffVehicle)
	end
	saveXMLFile(PushBar.configXml)
end
function PushBar:loadConfigTc()
	local spec = self.spec_pushBar
	
	if g_dedicatedServerInfo ~= nil then
		return
	end

	local configFile = PushBar.confDir .. "PushBarConfig.xml"
	if not fileExists(configFile) then
		PushBar:saveConfigTc()
	else
		PushBar.configXml = loadXMLFile("PushingBar_XML", configFile)
		if PushBar ~= nil then
			PushBar.manualAttach = getXMLBool(PushBar.configXml, "PushBarConfig.manualAttach")
			PushBar.showHelp = getXMLBool(PushBar.configXml, "PushBarConfig.showHelp")
			PushBar.showIds = getXMLBool(PushBar.configXml, "PushBarConfig.showIds")
			PushBar.IdsDistanceView = getXMLFloat(PushBar.configXml, "PushBarConfig.IdsDistanceView")
			PushBar.barDistanceView = getXMLFloat(PushBar.configXml, "PushBarConfig.barDistanceView")
			PushBar.steeringMode = getXMLFloat(PushBar.configXml, "PushBarConfig.steeringMode")
			PushBar.autoOffVehicle = getXMLBool(PushBar.configXml, "PushBarConfig.autoOffVehicle")
			
			PushBar.manualAttachIndex = getIndexFromElement(PushBar.booleans, PushBar.manualAttach)
			PushBar.showHelpIndex = getIndexFromElement(PushBar.booleans, PushBar.showHelp)
			PushBar.showIdsIndex = getIndexFromElement(PushBar.booleans, PushBar.showIds)
			PushBar.IdsDistanceViewIndex = getIndexFromElement(PushBar.IdsDistanceViews, PushBar.IdsDistanceView)
			PushBar.barDistanceViewIndex = getIndexFromElement(PushBar.barDistanceViews, PushBar.barDistanceView)
			PushBar.steeringModeIndex = getIndexFromElement(PushBar.steeringModes, PushBar.steeringMode)
			PushBar.autoOffVehicleIndex = getIndexFromElement(PushBar.booleans, PushBar.autoOffVehicle)
			
			PushBar.gui.tcSettingGui:setManualAttach(PushBar.manualAttachIndex)
			PushBar.gui.tcSettingGui:setShowHelp(PushBar.showHelpIndex)
			PushBar.gui.tcSettingGui:setShowIds(PushBar.showIdsIndex)
			PushBar.gui.tcSettingGui:setIdsDistanceView(PushBar.IdsDistanceViewIndex)
			PushBar.gui.tcSettingGui:setBarDistanceView(PushBar.barDistanceViewIndex)
			PushBar.gui.tcSettingGui:setSteeringMode(PushBar.steeringModeIndex)
			PushBar.gui.tcSettingGui:setAutoOffVehicle(PushBar.autoOffVehicleIndex)
		else
			print("PushBar: Error loading settings - PushBar == nil")
		end
	end
	
		
end
function PushBar:saveToXMLFile(xmlFile, key, usedModNames)
	local spec = self.spec_pushBar
	
	setXMLBool(xmlFile.handle, key.."#isUsed", spec.isUsed)
	setXMLBool(xmlFile.handle, key.."#hookMounted", spec.hookMounted)
	if spec.hookMounted then
		setXMLInt(xmlFile.handle, key.."#hookedVehicleId", spec.hookedVehicleId.rootNode)
		setXMLString(xmlFile.handle, key.."#hookedVehicleName", spec.hookedVehicleId:getFullName())
		local x,y,z = getWorldTranslation(spec.hookedVehicleId.rootNode)
		setXMLFloat(xmlFile.handle, key.."#hookedVehicleX", x)
		setXMLFloat(xmlFile.handle, key.."#hookedVehicleY", y)
		setXMLFloat(xmlFile.handle, key.."#hookedVehicleZ", z)
		setXMLBool(xmlFile.handle, key.."#hookMountedBack", spec.hookMountedBack)
		setXMLFloat(xmlFile.handle, key.."#hookX", spec.hookX)
		setXMLFloat(xmlFile.handle, key.."#hookY", spec.hookY)
		setXMLFloat(xmlFile.handle, key.."#hookZ", spec.hookZ)
		setXMLInt(xmlFile.handle, key.."#hookedVehicleId2", self:vehicleToVehicleId(spec.hookedVehicleId))
	end
	if spec.isUsed then
		setXMLInt(xmlFile.handle, key.."#attachedVehicleId", spec.joint.vehicleId.rootNode)
		setXMLString(xmlFile.handle, key.."#attachedVehicleName", spec.joint.vehicleId:getFullName())
		setXMLInt(xmlFile.handle, key.."#attacherJointId", spec.joint.attacherJointId)
		local x,y,z = getWorldTranslation(spec.joint.vehicleId.rootNode)
		setXMLFloat(xmlFile.handle, key.."#attachedVehicleX", x)
		setXMLFloat(xmlFile.handle, key.."#attachedVehicleY", y)
		setXMLFloat(xmlFile.handle, key.."#attachedVehicleZ", z)
		setXMLInt(xmlFile.handle, key.."#attachedVehicleId2", self:vehicleToVehicleId(spec.joint.vehicleId))
	end
end
function PushBar:onPreDelete()
	local spec = self.spec_pushBar
	
	if self.selectionObject.vehicle.isVehicleSaved then
		if self.isServer and spec.isUsed then
			self:detachVehicles(false)
		end
		if self.isServer and spec.hookMounted then
			self:unmountHook(spec.hookedVehicleId, false)
		end
		PushBar.bar[spec.barId] = nil
		local count = 0
		if PushBar.selectedBarId == spec.barId then
			for k,v in pairs(PushBar.bar) do
				if v ~= nil then
					count = count + 1
					PushBar.selectedBarId = k
					PushBar.lastSelectedBarId = k
					break
				end
			end
			if count == 0 then
				PushBar.selectedBarId = 1
				PushBar.lastSelectedBarId = 1
				if PushBar.event_IDsPlayer ~= nil then
					for actionName,eventID in pairs(PushBar.event_IDsPlayer) do
						g_inputBinding:setActionEventActive(eventID, false)
					end
				end
			end
		end
	end
end
function PushBar:switchToNextBar()
	local currentFound = false
	local firstKey = nil
	local newKey = nil
	
	local anyBarInRange = false
	local activeYardersCount = 0
	for k,v in pairs(PushBar.bar) do
		if v ~= nil and v.spec_pushBar.isInRange then
			anyBarInRange = true
			activeYardersCount = activeYardersCount + 1
		end
	end
	if activeYardersCount == 1 and PushBar.bar[PushBar.selectedBarId].spec_pushBar.isInRange then
		newKey = PushBar.selectedBarId
	elseif activeYardersCount == 0 then
		newKey = PushBar.lastSelectedBarId
	else
		for k,v in pairs(PushBar.bar) do
			if firstKey == nil then
				firstKey = k
			end
			if currentFound and v.spec_pushBar.isInRange then
				newKey = k
				break
			end
			if k == PushBar.selectedBarId then
				currentFound = true
			end
		end
		if newKey == nil then
			newKey = firstKey
		end
	end
	PushBar.selectedBarId = newKey
	PushBar.lastSelectedBarId = newKey
end
function PushBar:toggleControlVehicle(throttle, steering, reverseDrivingMode, forced, noEventSend)
	local spec = self.spec_pushBar
	
	PushingBarToggleControlVehicleEvent.sendEvent(self, throttle, steering, reverseDrivingMode, forced, noEventSend)
	
	local changed = false
	if spec.attachedVehicleThrottle ~= throttle then
		spec.attachedVehicleThrottle = throttle
		if spec.steeringMode == 1 then
			changed = true
		end
	end
	if spec.steeringMode ~= steering then
		spec.steeringMode = steering
		if (spec.steeringMode == 1 or spec.steeringMode == 2 or (spec.steeringMode == 3 and spec.steeringModeLast == 1)) and not spec.attachedVehicleThrottle then
			changed = true
																-------------------------------------------------------------------------------------------		ADDED
		end
		spec.steeringModeLast = spec.steeringMode
	end
	if spec.reverseDrivingMode ~= reverseDrivingMode then
		spec.reverseDrivingMode = reverseDrivingMode
	end
	local firstAttVehicle = self:getFirstAttacher(self, nil, false)
	local firstVehicleAttached = self:getFirstVehicleAttached(self, nil, false)
	if firstVehicleAttached == nil and spec.firstVehicleAttachedLast ~= nil then
		firstVehicleAttached = spec.firstVehicleAttachedLast
	end
	if (changed or forced) and spec.isUsed and not spec.isUsedSelf then
		spec.controlVehicle = not spec.controlVehicle
		if spec.firstVehicleAttachedLast ~= nil and not entityExists(spec.firstVehicleAttachedLast.rootNode) then
			return
		end
		if spec.controlVehicle then
			firstVehicleAttached:raiseActive()
			firstVehicleAttached.spec_enterable.playerStyle = firstAttVehicle.spec_enterable.playerStyle	-------------Fix for VCA-----------------
			if self.isServer or not self.isServer then
				firstVehicleAttached.getIsControlled = PushBar.getIsControlled
				firstVehicleAttached.getIsVehicleControlledByPlayer = PushBar.getIsVehicleControlledByPlayer
				firstVehicleAttached:startMotor(false)
			end
			if not g_currentMission.missionInfo.automaticMotorStartEnabled then
				if not firstVehicleAttached.spec_motorized.isMotorStarted then
					firstVehicleAttached:startMotor(false)
				end
			end
		else
			if self.isServer or not self.isServer then
				firstVehicleAttached.getIsControlled = firstVehicleAttached.getIsControlledBackup
				firstVehicleAttached.getIsVehicleControlledByPlayer = firstVehicleAttached.getIsVehicleControlledByPlayerBackup
			end
			if firstVehicleAttached.spec_drivable ~= nil then
				if firstVehicleAttached.spec_drivable.reverserDirection ~= nil then
					PushBar.leaveVehicle(firstVehicleAttached, firstVehicleAttached.leaveVehicle)
				end
				if not g_currentMission.missionInfo.automaticMotorStartEnabled then
					if firstVehicleAttached.spec_motorized.isMotorStarted then
						firstVehicleAttached:stopMotor(false)
					end
				end
			elseif firstVehicleAttached.spec_attachable ~= nil then
				if firstVehicleAttached.spec_attachable.attacherVehicle ~= nil then
					if firstVehicleAttached.spec_attachable.attacherVehicle.spec_drivable ~= nil then
						if firstVehicleAttached.spec_attachable.attacherVehicle.spec_drivable.reverserDirection ~= nil then
							--PushBar.leaveVehicle(firstVehicleAttached.spec_attachable.attacherVehicle, firstVehicleAttached.spec_attachable.attacherVehicle.leaveVehicle)
						end
					end
				end
			end
		end
	end
end
function PushBar:updateManualSteering(left, right, noEventSend)
	local spec = self.spec_pushBar
	
	PushingBarupdateManualSteeringEvent.sendEvent(self, left, right, noEventSend)
	
	spec.input_STEER_LEFT = left
	spec.input_STEER_RIGHT = right
end
function PushBar:getFirstAttacher(vehicle, passVehicles, debug)
	local spec = self.spec_pushBar
	
	local firstAttacherVehicle = nil
	local firstAttacherVehicleTemp = nil
	local tempVehicle
	local lastTempVehicle
	if passVehicles == nil then
		passVehicles = {}
		if debug then print('first round') end
	end
	if vehicle.spec_attachable.attacherVehicle ~= nil then
		tempVehicle = vehicle
		lastTempVehicle = tempVehicle
		if debug then print('----------------------------') end
		local j = 0
		while true do
			j = j + 1
			if j > 20 then break end
			if debug then print(spec.barId..' - '..tempVehicle:getFullName()) end
			if not entityExists(tempVehicle.rootNode) then
				if debug then print('not exists break') end
				break
			end
			if tempVehicle.spec_drivable ~= nil then
				firstAttacherVehicleTemp = tempVehicle
				if debug then print(spec.barId..' - 6') end
				passVehicles[tempVehicle] = tempVehicle
			end
			if tempVehicle.pushBarAttached then
				lastTempVehicle = tempVehicle
				passVehicles[tempVehicle] = tempVehicle
				tempVehicle = PushBar.bar[tempVehicle.pushBarAttachedId]
				if debug then print(spec.barId..' - 1') end
			elseif tempVehicle.spec_pushBar ~= nil then
				if tempVehicle.spec_attachable.attacherVehicle ~= nil then
					lastTempVehicle = tempVehicle
					passVehicles[tempVehicle] = tempVehicle
					tempVehicle = tempVehicle.spec_attachable.attacherVehicle
					if debug then print(spec.barId..' - 2') end
				else
					if debug then print(spec.barId..' - 3') end
					break
				end
			elseif tempVehicle.spec_attachable ~= nil and tempVehicle.spec_attachable.attacherVehicle ~= nil and tempVehicle.spec_attachable.attacherVehicle ~= lastTempVehicle and passVehicles[tempVehicle.spec_attachable.attacherVehicle] == nil then
				lastTempVehicle = tempVehicle
				passVehicles[tempVehicle] = tempVehicle
				tempVehicle = tempVehicle.spec_attachable.attacherVehicle
				if debug then print(spec.barId..' - 4') end
			elseif tempVehicle.spec_attacherJoints ~= nil and tempVehicle.spec_attacherJoints.attachedImplements ~= nil and #tempVehicle.spec_attacherJoints.attachedImplements > 0 then
				if debug then print(spec.barId..' - 7') end
				local veh = nil
				local someAtt = false
				for i,implement in pairs(tempVehicle.spec_attacherJoints.attachedImplements) do
					if debug then print(implement.object:getFullName()) end
					if passVehicles[implement.object] == nil then
						someAtt = true
						passVehicles[implement.object] = implement.object
						if debug then print(spec.barId..' - 8') end
						veh = self:getFirstAttacher(implement.object, passVehicles, debug)
						if veh ~= nil then
							if debug then print(spec.barId..' - 9') end
							firstAttacherVehicleTemp = veh
							if debug then print('break veh not nil 1') end
							break
						end
					end
				end
				if veh ~= nil then
					firstAttacherVehicleTemp = veh
					if debug then print('break veh not nil') end
					break
				end
				if not someAtt then
					if debug then print('break not someAtt') end
					break
				end
			elseif firstAttacherVehicleTemp ~= nil then
				firstAttacherVehicle = firstAttacherVehicleTemp
				if debug then print(spec.barId..' - 5 break') end
				break
			else
				if debug then print('break last') end
				break
			end
			
		end
		firstAttacherVehicle = firstAttacherVehicleTemp
	end
	return firstAttacherVehicle
end
function PushBar:getFirstVehicleAttached(vehicle, passVehicles, debug)
	local spec = self.spec_pushBar
	
	if debug then print(spec.barId..'----------------------------') end
	local firstVehicleAttached = nil
	local tempVehicle
	local lastTempVehicle
	if passVehicles == nil then
		passVehicles = {}
		if debug then print(spec.barId..' first round--------------------------------------') end
	end
	tempVehicle = vehicle
	lastTempVehicle = tempVehicle
	while true do
		if debug then print(spec.barId..' - '..tempVehicle:getFullName()) end
		if not entityExists(tempVehicle.rootNode) then
			if debug then print(spec.barId..' - none break') end
			break
		end
		if tempVehicle.spec_drivable ~= nil then
			if debug then print(spec.barId..' - drivable') end
			firstVehicleAttached = tempVehicle
			break
		elseif tempVehicle.pushBarAttached and tempVehicle.spec_pushBar == nil and (PushBar.bar[tempVehicle.pushBarAttachedId] ~= lastTempVehicle or passVehicles[PushBar.bar[tempVehicle.pushBarAttachedId]] == nil) then
			if debug then print(spec.barId..' - detach1') end
			PushBar.bar[tempVehicle.pushBarAttachedId]:detachVehicles(false)
			break
		elseif tempVehicle.spec_pushBar ~= nil then
			if debug then print(spec.barId..' - pushbar') end
			if tempVehicle.spec_pushBar.isUsed then
				if debug then print(spec.barId..' - pushbar used') end
				if tempVehicle.spec_pushBar.joint.vehicleId ~= lastTempVehicle then
					lastTempVehicle = tempVehicle
					passVehicles[tempVehicle] = tempVehicle
					tempVehicle =  tempVehicle.spec_pushBar.joint.vehicleId
					if debug then print(spec.barId..' - push bar vehicleid') end
				else
					if debug then print(spec.barId..' - detach2') end
					PushBar.bar[tempVehicle.pushBarAttachedId]:detachVehicles(false)
					break
				end
			else
				break
			end
		elseif tempVehicle.spec_attachable ~= nil and tempVehicle.spec_attachable.attacherVehicle ~= nil and tempVehicle.spec_attachable.attacherVehicle ~= lastTempVehicle and passVehicles[tempVehicle.spec_attachable.attacherVehicle] == nil then
			if debug then print(spec.barId..' - 1') end
			lastTempVehicle = tempVehicle
			passVehicles[tempVehicle] = tempVehicle
			tempVehicle = tempVehicle.spec_attachable.attacherVehicle
		elseif tempVehicle.spec_attacherJoints ~= nil and tempVehicle.spec_attacherJoints.attachedImplements ~= nil and #tempVehicle.spec_attacherJoints.attachedImplements > 0 then
			if debug then print(spec.barId..' - 7') end
			passVehicles[tempVehicle] = tempVehicle
			local veh = nil
			local someAtt = false
			for i,implement in pairs(tempVehicle.spec_attacherJoints.attachedImplements) do
				if debug then print(implement.object:getFullName()) end
				if passVehicles[implement.object] == nil then
					someAtt = true
					passVehicles[implement.object] = implement.object
					if debug then print(spec.barId..' - 8') end
					veh = self:getFirstVehicleAttached(implement.object, passVehicles, false)
					if veh ~= nil then
						if debug then print(spec.barId..' - 9') end
						firstVehicleAttached = veh
						if debug then print('break veh not nil 1') end
						break
					end
				end
			end
			if veh ~= nil then
				firstVehicleAttached = veh
				if debug then print('break veh not nil') end
				break
			end
			if not someAtt then
				if debug then print('break not someAtt') end
				break
			end
		
		else
			if debug then print(spec.barId..' - break') end
			break
		end
	end
	if debug then print(spec.barId..'----------------------------END') end
	if firstVehicleAttached ~= nil and (firstVehicleAttached.getIsControlledBackup == nil or firstVehicleAttached.getIsVehicleControlledByPlayerBackup == nil) then
		firstVehicleAttached.getIsControlledBackup = firstVehicleAttached.getIsControlled
		firstVehicleAttached.getIsVehicleControlledByPlayerBackup = firstVehicleAttached.getIsVehicleControlledByPlayer
	end
	return firstVehicleAttached
end
function PushBar:getBarCanBeAttached(vehicle, passVehicles, debug, detach)
	local spec = self.spec_pushBar
	
	if debug then print(spec.barId..'----------------------------') end
	local firstVehicleAttached = nil
	local tempVehicle
	local lastTempVehicle
	if passVehicles == nil then
		passVehicles = {}
		if debug then print(spec.barId..' first round--------------------------------------') end
	end
		tempVehicle = vehicle
		lastTempVehicle = tempVehicle
		while true do
			if debug then print(spec.barId..' - '..tempVehicle:getFullName()) end
			if not entityExists(tempVehicle.rootNode) then
				if debug then print(spec.barId..' - none break') end
				break
			end
			if tempVehicle.pushBarAttached and not tempVehicle.pushBarAttachedSelf and tempVehicle.spec_pushBar == nil and (PushBar.bar[tempVehicle.pushBarAttachedId] ~= lastTempVehicle or passVehicles[PushBar.bar[tempVehicle.pushBarAttachedId]] == nil) then
				if debug then print(spec.barId..' - detach1') end
				if detach then PushBar.bar[tempVehicle.pushBarAttachedId]:detachVehicles(false) end
				return false
			elseif tempVehicle.spec_pushBar ~= nil then
				if debug then print(spec.barId..' - pushbar') end
				if tempVehicle.spec_pushBar.isUsed then
					if debug then print(spec.barId..' - pushbar used') end
					if tempVehicle.spec_pushBar.joint.vehicleId ~= lastTempVehicle then
						lastTempVehicle = tempVehicle
						passVehicles[tempVehicle] = tempVehicle
						tempVehicle =  tempVehicle.spec_pushBar.joint.vehicleId
						if debug then print(spec.barId..' - push bar vehicleid') end
					else
						if debug then print(spec.barId..' - detach2') end
						if detach then PushBar.bar[tempVehicle.pushBarAttachedId]:detachVehicles(false) end
						return false
					end
				else
					break
				end
			elseif tempVehicle.spec_attachable ~= nil and tempVehicle.spec_attachable.attacherVehicle ~= nil and tempVehicle.spec_attachable.attacherVehicle ~= lastTempVehicle and passVehicles[tempVehicle.spec_attachable.attacherVehicle] == nil then
				if debug then print(spec.barId..' - 1') end
				lastTempVehicle = tempVehicle
				passVehicles[tempVehicle] = tempVehicle
				tempVehicle = tempVehicle.spec_attachable.attacherVehicle
			elseif tempVehicle.spec_attacherJoints ~= nil and tempVehicle.spec_attacherJoints.attachedImplements ~= nil and #tempVehicle.spec_attacherJoints.attachedImplements > 0 then
				if debug then print(spec.barId..' - 7') end
				passVehicles[tempVehicle] = tempVehicle
				local veh = nil
				local someAtt = false
				for i,implement in pairs(tempVehicle.spec_attacherJoints.attachedImplements) do
					if debug then print(implement.object:getFullName()) end
					if passVehicles[implement.object] == nil then
						someAtt = true
						passVehicles[implement.object] = implement.object
						if debug then print(spec.barId..' - 8') end
						if not self:getBarCanBeAttached(implement.object, passVehicles, debug, detach) then
							if debug then print(spec.barId..' - false') end
							return false
						end
					end
				end
				if not someAtt then
					if debug then print('break not someAtt') end
					break
				end
			else
				if debug then print(spec.barId..' - break') end
				break
			end
		end
		if debug then print(spec.barId..'----------------------------END') end
	return true
end
function PushBar:onUpdate(dt)
	local spec = self.spec_pushBar
	
	
	if spec.postAttachVehicles and spec.hooksMounted then
		spec.postAttachVehicles = false
		if self.isServer then
			local attachedVehicleId = self:vehicleIdToVehicle(spec.postAttachObjectVal[1])
			spec.lastVehicle = {}
			spec.lastVehicle[1] = attachedVehicleId
			spec.lastVehicle[2] = spec.postAttachObjectVal[2]
			self:attachVehicles(spec.lastVehicle[1],spec.lastVehicle[2], true)
		elseif self.isClient and g_dedicatedServerInfo == nil then
			local attachedVehicleId = self:vehicleIdToVehicle(spec.vehicleIdAttached)
			spec.lastVehicle = {}
			spec.lastVehicle[1] = attachedVehicleId
			spec.lastVehicle[2] = spec.jointIdAttached
			self:attachVehicles(spec.lastVehicle[1],spec.lastVehicle[2], true)
		end
	end
	if spec.postMountHook then
		spec.postMountHook = false
		if self.isServer then
			spec.lastVehicleHook = {}
			local hookedVehicleId = self:vehicleIdToVehicle(spec.postMountHookVal[1])
			spec.lastVehicleHook[1] = hookedVehicleId
			self:mountHook(hookedVehicleId, spec.hookMountedBack, true)
			self:moveHook(spec.hookX, spec.hookY, spec.hookZ, true)
		elseif self.isClient and g_dedicatedServerInfo == nil then
			local hookedVehicleId = self:vehicleIdToVehicle(spec.vehicleIdHooked)
			spec.lastVehicleHook = {}
			spec.lastVehicleHook[1] = hookedVehicleId
			self:mountHook(hookedVehicleId, spec.hookMountedBack, true)
			self:moveHook(spec.hookX, spec.hookY, spec.hookZ, true)
		end
	end
	spec.hooksMounted = true
	
	if spec.justAttached or spec.justDetached then
		spec.timer2 = spec.timer2 + dt
		local i = 0
		for _,component in pairs(self.components) do
			local key = i..'>1'
			local col = I3DUtil.indexToObject(self.components, key)
			local mass
			local massAttached = 0.15
			local massDetached = 0.03
			if spec.justAttached then
				mass = spec.timer2 * (massAttached / 1000)
				if mass > massAttached then mass = massAttached end
				if mass < massDetached then mass = massDetached end
				setMass(component.node, mass)
			end
			if spec.justDetached then
				mass = (1000 - spec.timer2) * (massAttached / 1000)
				if mass < massDetached then mass = massDetached end
				setMass(component.node, mass)
			end
			i = i + 1
		end
		if spec.timer2 >= 1000 then
			spec.timer2 = 0
			spec.justAttached = false
			spec.justDetached = false
		end
	end
	if self.selectionObject.vehicle.isVehicleSaved then
		local i = 0
		if spec.firsRun then
			spec.timer = spec.timer + dt
			if spec.timer >= 2500 then
				spec.firsRun = false
				for _,component in pairs(self.components) do
					local key = i..'>1'
					local col = I3DUtil.indexToObject(self.components, key)
					setScale(col, 0.3,0.3,1)
					i = i + 1
				end
			end
		end
	end
	if self.spec_attachable.attacherVehicle ~= nil or spec.isUsed or PushBar.playerInRange(self, spec.attachPoint, 3) or self.spec_attachable.attacherVehicle == nil then
		self:raiseActive()
	end
	spec.isAttached = self.spec_attachable.attacherVehicle ~= nil
	if self.isServer and spec.isUsed and not entityExists(spec.joint.vehicleId.rootNode) then
		self:detachVehicles(false)
	end
	if self.isServer and spec.hookMounted and not entityExists(spec.hookedVehicleId.rootNode) then
		self:unmountHook(spec.hookedVehicleId, false)
	end
	local barIsSelected = (PushBar.selectedBarId == spec.barId)
	
	if g_currentMission.controlPlayer and g_currentMission.player ~= nil and self.selectionObject.vehicle.isVehicleSaved then
		target = g_currentMission.player.rootNode
		local x,y,z = getWorldTranslation(target)
		local a,b,c = getWorldTranslation(spec.attachPoint)
		local distance = MathUtil.vector3Length(x-a, y-b, z-c)
		local barIsSelected = (PushBar.selectedBarId == spec.barId)
		if distance <= PushBar.barDistanceView and (spec.isAttached or not spec.isAttached or spec.isUsed or PushBar.playerInRange(self, spec.attachPoint, 3)) then
			spec.isInRange = true
		else
			spec.isInRange = false
		end
		local count = 0
		for i,bar in pairs(PushBar.bar) do
			if bar ~= nil and bar.spec_pushBar.isInRange then
				count = count + 1
			end
		end
		if not spec.isInRange and PushBar.selectedBarId == spec.barId and count > 0 then
			PushBar.switchToNextBar()
		end
		if spec.isInRange and count > 0 and PushBar.showHelp then
			g_currentMission:addExtraPrintText(g_i18n:getText('pushBar')..spec.barId..": "..string.format("%.1f",distance) .. " m ("..(spec.isUsed and g_i18n:getText('pushBarAttached') or g_i18n:getText('pushBarNotAttached'))..", "..(spec.hookMounted and g_i18n:getText('pushBarMounted') or g_i18n:getText('pushBarNotMounted'))..(barIsSelected and g_i18n:getText('pushBarSelected')..")" or ")"))
		end
		if PushBar.playerInRange(self, self.rootNode, 4) then
			for _,component in pairs(self.components) do
				if Player.PICKED_UP_OBJECTS[component.node] == true then
					PushBar.selectedBarId = spec.barId
				end
			end
		end
		local menuOpened = false
		if g_currentMission.hud ~= nil then
			if g_currentMission.hud.isMenuVisible ~= nil then
				menuOpened = g_currentMission.hud.isMenuVisible
			end
		end
		if PushBar.showIds and not menuOpened then
			local text = barIsSelected and '*'..tostring(spec.barId)..'*' or tostring(spec.barId)
			if PushBar.playerInRange(self, self.rootNode, PushBar.IdsDistanceView) then
				local object = I3DUtil.indexToObject(self.components, '0>')
				--local x,y,z = getWorldTranslation(object)
				local x,y,z = localToWorld(object, 0,0.5,0)
				Utils.renderTextAtWorldPosition(x, y, z, text, getCorrectTextSize(0.03), 0)
			end
			if spec.hookMounted and PushBar.playerInRange(self, spec.hook, PushBar.IdsDistanceView) then
				local x,y,z = getWorldTranslation(spec.hook)
				Utils.renderTextAtWorldPosition(x, y, z, text, getCorrectTextSize(0.03), 0)
			end
		end
	end
	
	if not self:getIsActiveForInput() and barIsSelected then
		if spec.lastVehicle ~= nil then 
            if not spec.isUsed then
                if PushBar.manualAttach and PushBar.playerInRange(self, spec.attachPoint, 2) and PushBar.input_manualAttach and (spec.isAttached or self.pushBarAttached or not spec.isAttached) then
					PushBar.input_manualAttach = false
                    if spec.lastVehicle[1].pushBarAttached then
						g_currentMission:showBlinkingWarning(g_i18n:getText('pushBarThisVehicle')..' ('..spec.lastVehicle[1]:getFullName()..') '..g_i18n:getText('pushBarAlreadyAttached'), 2000)
					elseif not self:getBarCanBeAttached(spec.lastVehicle[1], nil, false, false) then
						g_currentMission:showBlinkingWarning(g_i18n:getText('pushBarAllBars'), 2000)
					else
						self:attachVehicles(spec.lastVehicle[1], spec.lastVehicle[2], false)
						g_soundManager:playSample(spec.sampleAttach)
					end
                end
            end
		else
            if spec.isUsed then
                if PushBar.input_manualAttach then
					if not spec.controlVehicle or PushBar.autoOffVehicle then
						if PushBar.autoOffVehicle then						------------------------------------------------------------------------------------------			ADDED
							if spec.attachedVehicleThrottle then
								self:toggleControlVehicle(not spec.attachedVehicleThrottle, spec.steeringMode, spec.reverseDrivingMode, false, false)
							end
							if spec.steeringMode ~= 1 then
								self:toggleControlVehicle(spec.attachedVehicleThrottle, 1, spec.reverseDrivingMode, false, false)
							end
						end
						self:detachVehicles(false)
						g_soundManager:playSample(spec.sampleAttach)
						PushBar.input_manualAttach = false
					elseif spec.attachedVehicleThrottle then
						g_currentMission:showBlinkingWarning(g_i18n:getText('pushBarThrottleOff'), 2000)
					elseif spec.steeringMode ~= 1 then
						g_currentMission:showBlinkingWarning(g_i18n:getText('pushBarSteeringOff'), 2000)
					end
                end
			end
        end
		if spec.lastVehicleHook ~= nil then
			if PushBar.input_mountHook then
				PushBar.input_mountHook = false
				if not spec.hookMounted then
					if not spec.lastVehicleHook[1].pushHookMounted then
						self:mountHook(spec.lastVehicleHook[1], nil, false)
					else
						g_currentMission:showBlinkingWarning(g_i18n:getText('pushBarAlreadyHook')..' '..spec.lastVehicleHook[1].pushHookMountedId, 2000)
					end
				elseif spec.hookMounted then
					if spec.lastVehicleHook[1] == spec.hookedVehicleId then
						if not spec.lastVehicleHook[1].pushBarAttached or (spec.lastVehicleHook[1].pushBarAttached and not spec.lastVehicleHook[1].mountedHookAttached) then
							self:unmountHook(spec.lastVehicleHook[1], false)
						else
							g_currentMission:showBlinkingWarning(g_i18n:getText('pushBarFirstDetach1')..' '..spec.lastVehicleHook[1].pushBarAttachedId..' '..g_i18n:getText('pushBarFirstDetach2'), 2000)
						end
					else
						g_currentMission:showBlinkingWarning(g_i18n:getText('pushBarFirstUnmount')..' '..spec.hookedVehicleId:getFullName(), 2000)
					end
				end
			end
		end
	elseif self:getIsActiveForInput() then
        if spec.lastVehicle ~= nil then 
            if not spec.isUsed then
                if spec.inputBarAttachVehicle and spec.isAttached then
					spec.inputBarAttachVehicle = false
					if spec.lastVehicle[1].pushBarAttached then
						g_currentMission:showBlinkingWarning(g_i18n:getText('pushBarThisVehicle')..' ('..spec.lastVehicle[1]:getFullName()..') '..g_i18n:getText('pushBarAlreadyAttached'), 2000)
					elseif not self:getBarCanBeAttached(spec.lastVehicle[1], nil, false, false) then
						g_currentMission:showBlinkingWarning(g_i18n:getText('pushBarAllBars'), 2000)
					else
						self:attachVehicles(spec.lastVehicle[1], spec.lastVehicle[2], false)
						g_soundManager:playSample(spec.sampleAttach)
					end
                end
            end
        else
            if spec.isUsed then
                if spec.inputBarAttachVehicle then
					if not spec.controlVehicle or PushBar.autoOffVehicle then
						if PushBar.autoOffVehicle then
							if spec.attachedVehicleThrottle then
								self:toggleControlVehicle(not spec.attachedVehicleThrottle, spec.steeringMode, spec.reverseDrivingMode, false, false)
							end
							if spec.steeringMode ~= 1 then
								self:toggleControlVehicle(spec.attachedVehicleThrottle, 1, spec.reverseDrivingMode, false, false)
							end
						end
						self:detachVehicles(false)
						g_soundManager:playSample(spec.sampleAttach)
						spec.inputBarAttachVehicle = false
					elseif spec.attachedVehicleThrottle then
						g_currentMission:showBlinkingWarning(g_i18n:getText('pushBarThrottleOff'), 2000)
					elseif spec.steeringMode ~= 1 then
						g_currentMission:showBlinkingWarning(g_i18n:getText('pushBarSteeringOff'), 2000)
					end
                end
            else
				if spec.inputBarAttachVehicle then
					if self.spec_attachable ~= nil then
						if self.spec_attachable.attacherVehicle ~= nil then
							local jointDesc = self.spec_attachable.attacherVehicle:getAttacherJointIndexFromObject(self)
							if jointDesc ~= nil then
								spec.isUsedSelf = true
								self:attachVehicles(self.spec_attachable.attacherVehicle, jointDesc, false)
								g_soundManager:playSample(spec.sampleAttach);
								spec.inputBarAttachVehicle = false
							end
						end
					end
				end
			end
        end
	end
	local firstAttVehicle = self:getFirstAttacher(self, nil, false)
	local firstVehicleAttached = self:getFirstVehicleAttached(self, nil, false)
	
	if spec.isUsed and not spec.isUsedSelf then
		self:getBarCanBeAttached(self, nil, false, true)
		if firstAttVehicle ~= nil then
			--spec.infoText = spec.infoText..'first attacher - '..tostring(firstAttVehicle:getFullName())..'\n'
		else
			--spec.infoText = spec.infoText..'first attacher - none\n'
		end
		if firstVehicleAttached ~= nil then
			--spec.infoText = spec.infoText..'first att.Vehicle - '..tostring(firstVehicleAttached:getFullName())..'\n'
		else
			--spec.infoText = spec.infoText..'first att.Vehicle - none\n'
		end
		if firstAttVehicle ~= nil and firstVehicleAttached ~= nil then
			spec.firstVehicleAttachedLast = firstVehicleAttached
			if firstAttVehicle.spec_enterable.getIsControlled ~= nil and (firstAttVehicle.spec_enterable:getIsControlled() or not firstAttVehicle.spec_enterable:getIsControlled()) and not firstVehicleAttached.spec_enterable.isControlled then-------------------------------------------------------------------------
				if firstVehicleAttached.spec_drivable ~= nil then
					local mode = 0
					local brake = 0
					if firstVehicleAttached.spec_drivable.reverserDirection ~= nil then
						if spec.steeringMode == 2 then
							local x,y,z
							if firstVehicleAttached.pushBarAttachedId ~= nil then
								x,y,z = getWorldTranslation(PushBar.bar[firstVehicleAttached.pushBarAttachedId].spec_pushBar.transform)
							else
								x,y,z = getWorldTranslation(spec.transform)
							end
							local xx,yy,zz = worldToLocal(self.spec_attachable.attacherVehicle.rootNode, x,y,z)
							--spec.infoText = spec.infoText..'xx - '..string.format("%.3f",xx)..',        '..string.format("%.3f",yy)..','..string.format("%.3f",zz)..'\n'
							local a, b, c = localDirectionToWorld(firstVehicleAttached.rootNode, 0, 0, 1)
							local x, y, z = worldDirectionToLocal(self.spec_attachable.attacherVehicle.rootNode, a,b,c)
							local diffXX = x
							if firstVehicleAttached.movingDirection < 0 then
								diffXX = diffXX * -1
							end
							--spec.infoText = spec.infoText..'diffXX - '..string.format("%.3f",diffXX)..'\n'
							if self.spec_attachable.attacherVehicle:getLastSpeed() > 0.1 then
								if spec.axisSteerLast == nil then
									spec.axisSteerLast = 0
								end
								if diffXX < -0.001 and xx < 0 then
									spec.axisSteer = xx * 1.5
									mode = 1
								elseif diffXX > 0.001 and xx > 0 then
									spec.axisSteer = xx * 1.5
									mode = 2
								else
									if xx > 0.001 then
										spec.axisSteer =(xx * 0.1)
										mode = 31
									elseif xx < -0.001 then
										spec.axisSteer = (xx * 0.1)
										mode = 32
									else
										spec.axisSteer = 0
										mode = 0
									end
								end
								if firstVehicleAttached.movingDirection < 0 then
									spec.axisSteer = spec.axisSteer * -1
								end
								spec.axisSteerLast = spec.axisSteer
							end
						elseif spec.steeringMode == 3 then
							if spec.input_STEER_LEFT then
								if spec.axisSteer > -1 then
									spec.axisSteer = spec.axisSteer - 0.05
								else
									spec.axisSteer = -1
								end
							elseif spec.input_STEER_RIGHT then
								if spec.axisSteer < 1 then
									spec.axisSteer = spec.axisSteer + 0.05
								else
									spec.axisSteer = 1
								end
							else
								if spec.axisSteer < -0.05 then
									spec.axisSteer = spec.axisSteer + 0.05
								elseif spec.axisSteer > 0.05 then
									spec.axisSteer = spec.axisSteer - 0.05
								else
									spec.axisSteer = 0
								end
							end
						else
							spec.axisSteer = 0
						end
						
						local x,y,z = getWorldTranslation(self.rootNode)
						local a,b,c = getWorldTranslation(spec.attachPoint)
						local distance = MathUtil.vector3Length(x - a, y - b, z - c)
						--spec.infoText = spec.infoText..'distance - '..string.format("%.3f",distance)..'\n'
						spec.axisForward = 0
						if spec.attachedVehicleThrottle then
							if firstAttVehicle.spec_drivable.axisForward > 0 then
								spec.axisForward = distance / 3.2
							elseif  firstAttVehicle.spec_drivable.axisForward < 0 then
								spec.axisForward = firstAttVehicle.spec_drivable.axisForward
							end
						end
						if spec.controlVehicle then
							Drivable.updateVehiclePhysics(firstVehicleAttached, spec.reverseDrivingMode and -spec.axisForward or spec.axisForward, spec.reverseDrivingMode and spec.axisSteer or spec.axisSteer, false, dt)
						end
						if (firstAttVehicle.spec_drivable.axisForward == 0 or firstAttVehicle.spec_drivable.axisForward < 0) and firstAttVehicle.spec_drivable.cruiseControl.state == 0 then
							brake = 1
						elseif distance <= 2.2 then
							brake = 1.2 - (distance / 2.2)
						else
							brake = 0.1
						end
						if brake ~= 0 or brake == 0 then
							firstVehicleAttached:brake(brake)
						end
						--[[local source = self.spec_attachable.attacherVehicle.rootNode
						if source ~= nil then
							local x,y,z = getWorldTranslation(source)
							local nx, ny, nz = localDirectionToWorld(source, 5, 0, 0)
							local yx, yy, yz = localDirectionToWorld(source, 0, 5, 0)
							local zx, zy, zz = localDirectionToWorld(source, 0, 0, 5)
							drawDebugLine(x,y,z, 1, 0, 0, x + nx, y + ny, z + nz, 1, 0, 0);
							drawDebugLine(x,y,z, 0, 1, 0, x + yx, y + yy, z + yz, 0, 1, 0);
							drawDebugLine(x,y,z, 0, 0, 1, x + zx, y + zy, z + zz, 0, 0, 1);
						end
						local source
						if firstVehicleAttached.pushBarAttachedId ~= nil then
							source = PushBar.bar[firstVehicleAttached.pushBarAttachedId].spec_pushBar.transform
						else
							source = spec.transform
						end
						if source ~= nil then
							local x,y,z = getWorldTranslation(source)
							local nx, ny, nz = localDirectionToWorld(source, 3, 0, 0)
							local yx, yy, yz = localDirectionToWorld(source, 0, 3, 0)
							local zx, zy, zz = localDirectionToWorld(source, 0, 0, 3)
							drawDebugLine(x,y,z, 1, 0, 0, x + nx, y + ny, z + nz, 1, 0, 0);
							drawDebugLine(x,y,z, 0, 1, 0, x + yx, y + yy, z + yz, 0, 1, 0);
							drawDebugLine(x,y,z, 0, 0, 1, x + zx, y + zy, z + zz, 0, 0, 1);
						end]]
					end
					--[[spec.infoText = spec.infoText..'axisSteer - '..string.format("%.3f",spec.axisSteer)..'\n'
					spec.infoText = spec.infoText..'axisForward - '..string.format("%.3f",spec.axisForward)..'\n'
					spec.infoText = spec.infoText..'brake - '..string.format("%.3f",brake)..'\n'
					spec.infoText = spec.infoText..'mode - '..string.format("%.0f",mode)..'\n'
					spec.infoText = spec.infoText..'getLastSpeed() - '..string.format("%.0f",self.spec_attachable.attacherVehicle:getLastSpeed())..'\n'
					spec.infoText = spec.infoText..'reverserDirection - '..tostring(firstVehicleAttached.spec_drivable.reverserDirection)..'\n'
					spec.infoText = spec.infoText..'reverserDir. Att. - '..tostring(firstAttVehicle.spec_drivable.reverserDirection)..'\n'
					spec.infoText = spec.infoText..'cruiseControl Att. - '..tostring(firstAttVehicle.spec_drivable.cruiseControl.state)..'\n'
					spec.infoText = spec.infoText..'movingDirection - '..tostring(firstVehicleAttached.movingDirection)..'\n'
					spec.infoText = spec.infoText..'getBrakeForce() - '..tostring(firstVehicleAttached.spec_motorized.motor:getBrakeForce())..'\n']]
				elseif firstVehicleAttached.spec_attachable ~= nil then
					if firstVehicleAttached.spec_attachable.attacherVehicle ~= nil then
						if firstVehicleAttached.spec_attachable.attacherVehicle.spec_drivable ~= nil then
							if firstVehicleAttached.spec_attachable.attacherVehicle.spec_drivable.reverserDirection ~= nil then
								Drivable.updateVehiclePhysics(firstVehicleAttached.spec_attachable.attacherVehicle, firstAttVehicle.spec_drivable.axisForward, firstAttVehicle.spec_drivable.axisSide, firstAttVehicle.spec_drivable.doHandbrake, dt)
							end
						end
					end
				end
			end
		else
			if spec.controlVehicle and self.isServer then
				self:toggleControlVehicle(false, 1, false, true, false)
			end
			if firstVehicleAttached == nil and spec.firstVehicleAttachedLast ~= nil then
				if spec.firstVehicleAttachedLast == spec.joint.vehicleId then
					self:detachVehicles(false)
					spec.firstVehicleAttachedLast = nil
				end
			end
			
		end
	end
	
	if self.isClient then
		if self:getIsActiveForInput() then
			if spec.event_IDs ~= nil and g_dedicatedServerInfo == nil then
				for actionName,eventID in pairs(spec.event_IDs) do
					g_inputBinding:setActionEventTextVisibility(eventID, PushBar.showHelp)
					if actionName == InputAction.PUSHBAR_ATTACH_VEHICLE then
						g_inputBinding:setActionEventActive(eventID, true)
						if spec.lastVehicle == nil then
							g_inputBinding:setActionEventText(eventID, spec.isUsed and (spec.isUsedSelf and g_i18n:getText('pushBarSelfDetach') or g_i18n:getText('pushBarVehicleDetach')) or g_i18n:getText('pushBarSelfAttach'))
						else
							g_inputBinding:setActionEventText(eventID, g_i18n:getText('pushBarVehicleAttach'))
						end
					
					elseif actionName == InputAction.PUSHBAR_VEHICLE_THROTTLE then
						g_inputBinding:setActionEventActive(eventID, (spec.isUsed and not spec.isUsedSelf) and true or false)
						g_inputBinding:setActionEventText(eventID, spec.attachedVehicleThrottle and g_i18n:getText('pushBarVehicleThrottleOff') or g_i18n:getText('pushBarVehicleThrottleOn'))
					
					elseif actionName == InputAction.PUSHBAR_TOGGLE_STEERING_MODE then
						g_inputBinding:setActionEventActive(eventID, (spec.isUsed and not spec.isUsedSelf) and true or false)
						g_inputBinding:setActionEventText(eventID, spec.steeringMode==1 and g_i18n:getText('pushBarSteeringModeOff') or (spec.steeringMode==2 and g_i18n:getText('pushBarSteeringModeAuto') or g_i18n:getText('pushBarSteeringModeManual')))
					
					elseif actionName == InputAction.PUSHBAR_STEER_LEFT or actionName == InputAction.PUSHBAR_STEER_RIGHT then
						g_inputBinding:setActionEventActive(eventID, spec.steeringMode == 3)
					elseif actionName == InputAction.PUSHBAR_CHANGE_ATTACHED_DIRECTION then
						g_inputBinding:setActionEventActive(eventID, (spec.isUsed and not spec.isUsedSelf and spec.attachedVehicleThrottle) and true or false)
						g_inputBinding:setActionEventText(eventID, spec.reverseDrivingMode and g_i18n:getText('pushBarAttachedDirectionBackward') or g_i18n:getText('pushBarAttachedDirectionForward'))
					end
				end
			end
		else
			if spec.hook ~= nil and barIsSelected then
				if PushBar.playerInRange(self, spec.hook, 4) then
					if spec.input_MOVE_HOOK_LEFT or spec.input_MOVE_HOOK_RIGHT or spec.input_MOVE_HOOK_FORWARD or spec.input_MOVE_HOOK_BACKWARD or spec.input_MOVE_HOOK_UP or spec.input_MOVE_HOOK_DOWN then
						spec.hookIsMoving = true
						local x, y, z = getTranslation(spec.hook)
						local origZ = spec.hookedVehicleId.spec_pushBar and -0.1 or spec.hookedVehicleId.size.length / 2.3 * (spec.hookMountedBack and -1 or 1)
						spec.timerHook = spec.timerHook + dt
						if spec.input_MOVE_HOOK_LEFT then
							if spec.timerHook > 1000 then
								x = x + 0.01
							else
								x = x + 0.001
							end
							if x > 10.5 then x = 10.5 end
						end
						if spec.input_MOVE_HOOK_RIGHT then
							if spec.timerHook > 1000 then
								x = x - 0.01
							else
								x = x - 0.001
							end
							if x < -1.5 then x = -1.5 end
						end
						if spec.input_MOVE_HOOK_FORWARD then
							if spec.timerHook > 1000 then
								z = z + 0.01
							else
								z = z + 0.001
							end
							if z > origZ + 1.5 then z = origZ + 1.5 end
						end
						if spec.input_MOVE_HOOK_BACKWARD then
							if spec.timerHook > 1000 then
								z = z - 0.01
							else
								z = z - 0.001
							end
							if z < origZ - 1.5 then z = origZ - 1.5 end
						end
						if spec.input_MOVE_HOOK_UP then
							if spec.timerHook > 1000 then
								y = y + 0.01
							else
								y = y + 0.001
							end
							if y > 2.5 then y = 2.5 end
						end
						if spec.input_MOVE_HOOK_DOWN then
							if spec.timerHook > 1000 then
								y = y - 0.01
							else
								y = y - 0.001
							end
							if y < 0 then y = 0 end
						end
						spec.hookX = x
						spec.hookY = y
						spec.hookZ = z
						setTranslation(spec.hook, x, y, z)
					else
						spec.timerHook = 0
					end
				else
					if spec.hookIsMoving then
						spec.hookIsMoving = false
						spec.input_MOVE_HOOK_TRIGGER = false
						spec.input_MOVE_HOOK_LEFT = false
						spec.input_MOVE_HOOK_RIGHT = false
						spec.input_MOVE_HOOK_FORWARD = false
						spec.input_MOVE_HOOK_BACKWARD = false
						spec.input_MOVE_HOOK_UP = false
						spec.input_MOVE_HOOK_DOWN = false
						self:moveHook(spec.hookX, spec.hookY, spec.hookZ, false)
					end
				end
			end
		end
		if PushBar.event_IDsPlayer ~= nil and barIsSelected then
			local anyBarInRange = false
			for k,v in pairs(PushBar.bar) do
				if v ~= nil and v.spec_pushBar.isInRange then
					anyBarInRange = true
				end
			end
			for actionName,eventID in pairs(PushBar.event_IDsPlayer) do
				g_inputBinding:setActionEventTextVisibility(eventID, PushBar.showHelp)
				if actionName == InputAction.PUSHBAR_SWITCH then
					g_inputBinding:setActionEventActive(eventID, anyBarInRange)
				elseif actionName == InputAction.PUSHBAR_OPEN_MENU then
					g_inputBinding:setActionEventActive(eventID, true)
				elseif actionName == InputAction.PUSHBAR_MANUAL_ATTACH then
					g_inputBinding:setActionEventActive(eventID, ((spec.lastVehicle ~= nil and (spec.isAttached or self.pushBarAttached or not spec.isAttached)) or spec.isUsed) and PushBar.playerInRange(self, spec.attachPoint, 2) and PushBar.manualAttach)
					g_inputBinding:setActionEventText(eventID, spec.isUsed and g_i18n:getText('pushBarVehicleDetach') or g_i18n:getText('pushBarVehicleAttach'))
				elseif actionName == InputAction.PUSHBAR_ATTACH_HOOK then
					g_inputBinding:setActionEventActive(eventID, spec.lastVehicleHook ~= nil and (not spec.hookMounted or (spec.hookMounted and PushBar.playerInRange(self, spec.hook, spec.lastVehicleHook[1].size.length/1.8))))
					if spec.lastVehicleHook ~= nil then
						g_inputBinding:setActionEventText(eventID, (spec.hookMounted and spec.lastVehicleHook[1] == spec.hookedVehicleId) and g_i18n:getText('pushBarUnmountHook')..' '..spec.lastVehicleHook[1]:getFullName() or g_i18n:getText('pushBarMountHook')..' '..spec.lastVehicleHook[1]:getFullName())
					end
				elseif actionName == InputAction.PUSHBAR_MOVE_HOOK_TRIGGER then
					g_inputBinding:setActionEventActive(eventID, spec.hook ~= nil and PushBar.playerInRange(self, spec.hook, 3) and not spec.hookedVehicleId.mountedHookAttached and not spec.hookedVehicleId.spec_pushBar)
				elseif actionName == InputAction.PUSHBAR_MOVE_HOOK_LEFT or actionName == InputAction.PUSHBAR_MOVE_HOOK_RIGHT or actionName == InputAction.PUSHBAR_MOVE_HOOK_FORWARD or actionName == InputAction.PUSHBAR_MOVE_HOOK_BACKWARD
				or actionName == InputAction.PUSHBAR_MOVE_HOOK_UP or actionName == InputAction.PUSHBAR_MOVE_HOOK_DOWN then
					g_inputBinding:setActionEventActive(eventID, spec.hook ~= nil and PushBar.playerInRange(self, spec.hook, 4) and spec.input_MOVE_HOOK_TRIGGER)
				end
			end
		end
	end
	if self:getIsActiveForInput() then
		if spec.debug then
			spec.infoText = ''
			spec.infoText = spec.infoText..'selectedBarId - '..string.format("%.1f",PushBar.selectedBarId)..'\n'
			spec.infoText = spec.infoText..'steeringMode - '..string.format("%.0f",spec.steeringMode)..'\n'
			spec.infoText = spec.infoText..'attachedVehicleThrottle - '..tostring(spec.attachedVehicleThrottle)..'\n'
			spec.infoText = spec.infoText..'controlVehicle - '..tostring(spec.controlVehicle)..'\n'
			spec.infoText = spec.infoText..'reverseDrivingMode - '..tostring(spec.reverseDrivingMode)..'\n'
			spec.infoText = spec.infoText..'----------------------------------------\n'
			renderText(0.7, 0.97, 0.015, spec.infoText)
		end
	end
	if self:getIsActiveForInput() or (g_currentMission.controlPlayer and g_currentMission.player ~= nil and PushBar.selectedBarId == spec.barId) then
		if spec.debug then
			spec.infoText2 = ''
			spec.infoText2 = spec.infoText2..'selectedBarId - '..string.format("%.1f",PushBar.selectedBarId)..'\n'
			for i,bar in pairs(PushBar.bar) do
				spec.infoText2 = spec.infoText2..'bar '..bar.spec_pushBar.barId..':------------------------------------\n'
				if firstAttVehicle ~= nil then
					spec.infoText2 = spec.infoText2..'first attacher - '..tostring(firstAttVehicle:getFullName())..'\n'
				else
					spec.infoText2 = spec.infoText2..'first attacher - none\n'
				end
				if firstVehicleAttached ~= nil then
					spec.infoText2 = spec.infoText2..'first att.Vehicle - '..tostring(firstVehicleAttached:getFullName()) or 'none'..'\n'
				else
					spec.infoText2 = spec.infoText2..'first att.Vehicle - none\n'
				end
				if bar:getIsActive() then
					spec.infoText2 = spec.infoText2..'getIsActive - true\n'
				else
					spec.infoText2 = spec.infoText2..'getIsActive - false\n'
				end
				spec.infoText2 = spec.infoText2..'getIsActiveForInput - '..tostring(bar:getIsActiveForInput())..'\n'
				spec.infoText2 = spec.infoText2..'isAttached - '..tostring(bar.spec_pushBar.isAttached)..'\n'
				spec.infoText2 = spec.infoText2..'isUsed - '..tostring(bar.spec_pushBar.isUsed)..'\n'
				spec.infoText2 = spec.infoText2..'isUsedSelf - '..tostring(bar.spec_pushBar.isUsedSelf)..'\n'
				spec.infoText2 = spec.infoText2..'hookMounted - '..tostring(bar.spec_pushBar.hookMounted)..'\n'
			end
			setTextColor(0,1,0,1)
			renderText(0.85, 0.92, 0.015, spec.infoText2)
		end
	end
end
function PushBar:onUpdateTick(dt)
	local spec = self.spec_pushBar
	
	if self.spec_attachable.attacherVehicle ~= nil or spec.isUsed then
		self:raiseActive()
	end
	spec.lastVehicle = nil
	if (self:getIsActiveForInput() or PushBar.manualAttach == true) and not spec.isUsed then
		local x,y,z = getWorldTranslation(spec.attachPoint)
		for k,v in pairs(g_currentMission.vehicles) do
			if v ~= self and v ~= self.spec_attachable.attacherVehicle then
				local vx, vy, vz = getWorldTranslation(v.rootNode);
				if MathUtil.vector3Length(x - vx, y - vy, z - vz) <= 50 then
					if v.spec_attacherJoints ~= nil then
						for index,joint in pairs(v.spec_attacherJoints.attacherJoints) do
							if joint.jointType == AttacherJoints.JOINTTYPE_TRAILER or joint.jointType == AttacherJoints.JOINTTYPE_TRAILERLOW or joint.jointType == AttacherJoints.JOINTTYPE_TOWINGHOOK then
								local x1,y1,z1 = getWorldTranslation(joint.jointTransform)
								local distance = MathUtil.vector3Length(x-x1,y-y1,z-z1)
								if distance <= 1.5 then   
									spec.lastVehicle = {}
									spec.lastVehicle[1] = v
									spec.lastVehicle[2] = index
									break
								end
							end
						end
						if v.spec_attacherJoints.attacherJoint ~= nil and spec.lastVehicle == nil then
							if v.attacherJoint.jointType == AttacherJoints.JOINTTYPE_TRAILER or v.attacherJoint.jointType == AttacherJoints.JOINTTYPE_TRAILERLOW or joint.jointType == AttacherJoints.JOINTTYPE_TOWINGHOOK then
								local x1,y1,z1 = getWorldTranslation(v.spec_attacherJoints.attacherJoint.node)
								local distance = MathUtil.vector3Length(x-x1,y-y1,z-z1)
								if distance <= 1 then                        
									spec.lastVehicle = {}
									spec.lastVehicle[1] = v
									spec.lastVehicle[2] = 0
									break
								end
							end
						end
					end
				end
			end
		end
    end
	spec.lastVehicleHook = nil
	if not self:getIsActiveForInput() and g_currentMission.controlPlayer and g_currentMission.player ~= nil then
		local x,y,z = getWorldTranslation(g_currentMission.player.rootNode)
		for k,v in pairs(g_currentMission.vehicles) do
			if v ~= self and (not v.spec_pushBar or not v.spec_pushBar.isAttached) then
				local vx, vy, vz = getWorldTranslation(v.rootNode)
				local distance = MathUtil.vector2Length(x - vx, z - vz)
				--DebugUtil.printTableRecursively(v,"-",0,1)
				if distance <= v.size.length / 1.8 then
					if v.spec_attacherJoints ~= nil then
						spec.lastVehicleHook = {}
						spec.lastVehicleHook[1] = v
						break
					end
				end
			end
		end
    end
	if spec.hookMounted and spec.hookedVehicleId ~= nil and spec.hookedVehicleId.spec_washable ~= nil and spec.hookedVehicleId.spec_washable.washableNodes ~= nil and spec.hookedVehicleId.spec_washable.washableNodes[1] ~= nil and spec.hookedVehicleId.spec_washable.washableNodes[1].nodes[1] ~= nil then
		local x, y, z, w = getShaderParameter(spec.hookedVehicleId.spec_washable.washableNodes[1].nodes[1], "RDT")
		if x ~= spec.wearLast or y ~= spec.dirtLast then
			spec.wearLast = x
			spec.dirtLast = y
			self:updateDirtAndWear()
		end
	end
end
function PushBar:attachVehicles(vehicleId, jointId, noEventSend)
	local spec = self.spec_pushBar
	
    PushingBarAttachEvents.sendEvent(self, vehicleId, jointId,noEventSend)
	
    local joint = spec.joint
    joint.vehicle = vehicleId
    local jointFA = nil
    if jointId == 0 then
        jointFA = vehicleId.spec_attacherJoints.attacherJoint
    else
        jointFA = vehicleId.spec_attacherJoints.attacherJoints[jointId]
    end
	if vehicleId == self.spec_attachable.attacherVehicle then
		spec.isUsedSelf = true
	end
    if self.isServer then
        local colli = jointFA.rootNode;
        local colli2 = spec.attachPointColli
        local jointTransform = Utils.getNoNil(jointFA.jointTransform, jointFA.node)
        local jointTransform2 = spec.attachPoint
        local constr = JointConstructor:new()                 
        constr:setActors(colli2, colli)
        constr:setJointTransforms(jointTransform2,  jointTransform)
        for i=1, 3 do
            constr:setTranslationLimit(i-1, true, 0, 0)
            constr:setRotationLimit(i-1, i == 1 and 0 or -math.rad(10), i == 1 and 0 or math.rad(10))
        end;
        spec.joint.index = constr:finalize()
		if not spec.isUsedSelf then
			if vehicleId.spec_drivable ~= nil then
				if vehicleId.spec_drivable.reverserDirection ~= nil then
					vehicleId.getIsControlledBackup = vehicleId.getIsControlled
					vehicleId.getIsVehicleControlledByPlayerBackup = vehicleId.getIsVehicleControlledByPlayer
					PushBar.leaveVehicle(vehicleId, vehicleId.leaveVehicle)
				end
			elseif vehicleId.spec_attachable ~= nil then
				if vehicleId.spec_attachable.attacherVehicle ~= nil then
					if vehicleId.spec_attachable.attacherVehicle.spec_drivable ~= nil then
						if vehicleId.spec_attachable.attacherVehicle.spec_drivable.reverserDirection ~= nil then
							--PushBar.leaveVehicle(vehicleId.spec_attachable.attacherVehicle, vehicleId.spec_attachable.attacherVehicle.leaveVehicle)
						end
					end
				end
			end
		end
		spec.joint.attacherJointId = jointId
		if not spec.isUsedSelf then
			if vehicleId.leaveVehicle ~= nil then
				vehicleId.backupLeaveVehicle = vehicleId.leaveVehicle
			elseif vehicleId.spec_attachable ~= nil then
				if vehicleId.spec_attachable.attacherVehicle ~= nil then
					if vehicleId.spec_attachable.attacherVehicle.leaveVehicle ~= nil then
						--vehicleId.spec_attachable.attacherVehicle.backupLeaveVehicle = vehicleId.spec_attachable.attacherVehicle.leaveVehicle
					end
				end
			end
		end
		if not spec.isUsedSelf then
			spec.justAttached = true
			spec.justDetached = false
		end
    end
    vehicleId.forceIsActive = true
	spec.joint.vehicleId = vehicleId
    spec.isUsed = true
    spec.lastVehicle = nil
	
	if not spec.isUsedSelf then
		vehicleId.pushBarAttached = true
		vehicleId.pushBarAttachedId = spec.barId
		if vehicleId.pushHookMounted ~= nil then
			vehicleId.mountedHookAttached = vehicleId.pushHookMounted and PushBar.bar[vehicleId.pushHookMountedId].spec_pushBar.hookedVehicleAttacherIndex == jointId
		else
			vehicleId.mountedHookAttached = false
		end
		local x,y,z = getWorldTranslation(jointFA.jointTransform)
		local xx,yy,zz = worldToLocal(spec.joint.vehicleId.rootNode, x,y,z)
		spec.transform = createTransformGroup("transform")
		link(spec.joint.vehicleId.rootNode, spec.transform)
		setTranslation(spec.transform, 0,yy,zz+(zz>=0 and 1 or -1))
	else
		vehicleId.pushBarAttachedSelf = true																------------------------------------------------------------------------------		ADDED
	end
end
function PushBar:detachVehicles(noEventSend)
	local spec = self.spec_pushBar
	
	if spec.controlVehicle and self.isServer then
		self:toggleControlVehicle(false, 1, false, true, false)
	end
	PushingBarDetachEvents.sendEvent(self, noEventSend)
    if self.isServer and entityExists(spec.joint.vehicle.rootNode) then
		if not spec.isUsedSelf then
			if spec.joint.vehicleId.leaveVehicle ~= nil and spec.joint.vehicleId.backupLeaveVehicle ~= nil then
				spec.joint.vehicleId.leaveVehicle = spec.joint.vehicleId.backupLeaveVehicle
				spec.joint.vehicleId.backupLeaveVehicle = nil
			elseif spec.joint.vehicleId.spec_attachable ~= nil then
				if spec.joint.vehicleId.spec_attachable.attacherVehicle ~= nil then
					if spec.joint.vehicleId.spec_attachable.attacherVehicle.leaveVehicle ~= nil and spec.joint.vehicleId.spec_attachable.attacherVehicle.backupLeaveVehicle ~= nil then
						spec.joint.vehicleId.spec_attachable.attacherVehicle.leaveVehicle = spec.joint.vehicleId.spec_attachable.attacherVehicle.backupLeaveVehicle
						spec.joint.vehicleId.spec_attachable.attacherVehicle.backupLeaveVehicle = nil
					end
				end
			end
		end
        removeJoint(spec.joint.index)
		if not spec.isUsedSelf then
			if spec.joint.vehicle.spec_enterable ~= nil and spec.joint.vehicle.spec_motorized ~= nil and spec.joint.vehicle.spec_wheels ~= nil then
				if not spec.joint.vehicle.spec_enterable.isControlled and spec.joint.vehicle.spec_motorized.motor ~= nil and spec.joint.vehicle.spec_wheels.wheels~= nil then
					for k,wheel in pairs(spec.joint.vehicle.spec_wheels.wheels) do
						setWheelShapeProps(wheel.node, wheel.wheelShape, 0, spec.joint.vehicleId.spec_motorized.motor:getBrakeForce() * wheel.brakeFactor, 0, wheel.rotationDamping)
					end
				end
			end
		end
		if not spec.isUsedSelf then
			spec.justDetached = true
			spec.justAttached = false
		end
    end
	if not spec.isUsedSelf then
		spec.joint.vehicleId.pushBarAttached = false
		spec.joint.vehicleId.pushBarAttachedId = nil
		spec.joint.vehicleId.mountedHookAttached = false
	end
    spec.joint.vehicle.forceIsActive = false
    spec.joint = nil
    spec.joint = {}
    spec.isUsed = false
	spec.isUsedSelf = false
	spec.attachedVehicleThrottle = false
	spec.steeringMode = 1
	spec.reverseDrivingMode = false
end
function PushBar:mountHook(vehicleId, hookMountedBack, noEventSend)
	local spec = self.spec_pushBar
	
	if vehicleId ~= nil then
		local vehicle = vehicleId
		spec.hookI3d = g_i3DManager:loadSharedI3DFile(PushBar.modDirectory..'models/hook.i3d', false, false)
		spec.hook = I3DUtil.indexToObject(spec.hookI3d, '0|0')
		spec.hookAttacher = I3DUtil.indexToObject(spec.hookI3d, '0|0|1')
		spec.washIndexes = {'0|0|0'}
		spec.washNodes = {}
		for i, node in pairs(spec.washIndexes) do
			spec.washNodes[i] = I3DUtil.indexToObject(spec.hookI3d, node)
		end
		local i=0
		while true do
			local baseName = string.format("vehicle.pushBar.attacherJoints.attacherJoint(%d)", i)
			if not hasXMLProperty(self.xmlFile.handle, baseName) then
				break
			end
			local attacherJoint = {}
			if vehicle:loadAttacherJointFromXML(attacherJoint, self.xmlFile, baseName, i) then
				table.insert(vehicle.spec_attacherJoints.attacherJoints, attacherJoint)
				attacherJoint.index = #vehicle.spec_attacherJoints.attacherJoints
				attacherJoint.jointTransform  = spec.hookAttacher
				spec.hookedVehicleAttacherIndex = attacherJoint.index
				attacherJoint.jointOrigRot = { getRotation(attacherJoint.jointTransform) }
				attacherJoint.jointOrigTrans = { getTranslation(attacherJoint.jointTransform) }
			end
			i = i + 1
		end
		spec.hookMountedBack = hookMountedBack
		if spec.hookMountedBack == nil then
			if g_currentMission.controlPlayer and g_currentMission.player ~= nil then
				local x,y,z = getWorldTranslation(g_currentMission.player.rootNode)
				local xx,yy,zz = worldToLocal(vehicle.rootNode, x,y,z)
				spec.hookMountedBack = zz < 0
			end
		end
		if spec.hookX == nil and spec.hookY == nil and spec.hookZ == nil then
			spec.hookX = 0
			spec.hookY = vehicleId.spec_pushBar ~= nil and 0.5 or 1
			spec.hookZ = vehicleId.spec_pushBar ~= nil and 0 or ((vehicle.size.length/2.3) * (spec.hookMountedBack and -1 or 1))
		end
		setTranslation(spec.hook, spec.hookX, spec.hookY, spec.hookZ)
		setRotation(spec.hook, 0, vehicleId.spec_pushBar ~= nil and 0 or (spec.hookMountedBack and math.rad(0) or math.rad(180)), 0)
		--link(vehicle.rootNode, spec.hookI3d)
		link(vehicle.rootNode, spec.hook)
		spec.hookMounted = true
		spec.hookedVehicleId = vehicle
		vehicle.pushHookMounted = true
		vehicle.pushHookMountedId = spec.barId
		self:updateDirtAndWear()
	end
	
	PushingBarMountHookEvent.sendEvent(self, vehicleId, spec.hookMountedBack, noEventSend)
end
function PushBar:unmountHook(vehicleId, noEventSend)
	local spec = self.spec_pushBar
	
	if self.isServer then
		if vehicleId ~= nil then
			if vehicleId.pushBarAttached and PushBar.bar[vehicleId.pushBarAttachedId].spec_pushBar.joint.attacherJointId == spec.hookedVehicleAttacherIndex then
				PushBar.bar[vehicleId.pushBarAttachedId]:detachVehicles(false)
			end
		end
	end
	PushingBarUnmountHookEvent.sendEvent(self, vehicleId, noEventSend)
	spec.hookMounted = false
	spec.hookedVehicleId = nil
	if vehicleId ~= nil then
		vehicleId.spec_attacherJoints.attacherJoints[spec.hookedVehicleAttacherIndex] = nil
		vehicleId.pushHookMounted = false
		vehicleId.pushHookMountedId = 0
	end
	g_i3DManager:releaseSharedI3DFile(spec.hookI3d, false)
	if self.isServer then
		if entityExists(vehicleId.rootNode) then
			delete(spec.hook)
		end
	elseif self.isClient then
		if vehicleId ~= nil then
			delete(spec.hook)
		end
	end
	spec.hook = nil
	spec.hookAttacher  = nil
	spec.hookMountedBack = nil
	spec.hookX = nil
	spec.hookY = nil
	spec.hookZ = nil
end
function PushBar:updateDirtAndWear()
	local spec = self.spec_pushBar
	
	if spec.hookedVehicleId.spec_washable ~= nil and spec.hookedVehicleId.spec_washable.washableNodes ~= nil and spec.hookedVehicleId.spec_washable.washableNodes[1] ~= nil and spec.hookedVehicleId.spec_washable.washableNodes[1].nodes[1] ~= nil then
		local x, y, z, w = getShaderParameter(spec.hookedVehicleId.spec_washable.washableNodes[1].nodes[1], "RDT")
		for _, node in pairs(spec.washNodes) do
			setShaderParameter(node, "RDT", x, y, z, w, false)
		end
	end
end
function PushBar:moveHook(x, y, z, noEventSend)
	local spec = self.spec_pushBar
	
	setTranslation(spec.hook, x, y, z)
	spec.hookX = x
	spec.hookY = y
	spec.hookZ = z
	
	PushingBarMoveHookEvent.sendEvent(self, x, y, z, noEventSend)
end
function PushBar:leaveVehicle(superFunc)
	local spec = self.spec_pushBar
	
    if not self:getIsControlled() then
		if superFunc ~= nil then
			superFunc(self)
		end
		if self.isServer then
			if self.spec_enterable ~= nil and self.spec_motorized ~= nil and self.spec_wheels ~= nil then
				if not self.spec_enterable.isControlled and self.spec_motorized.motor ~= nil and self.spec_wheels.wheels ~= nil then
					for k, wheel in pairs(self.spec_wheels.wheels) do
						setWheelShapeProps(wheel.node, wheel.wheelShape, 0, self:getBrakeForce()*wheel.brakeFactor, 0.5, wheel.rotationDamping)
					end
				end
			end
		end
	end
end
function PushBar:playerInRange(target, dist)
	local spec = self.spec_pushBar
	
	local inRange = false
	local source
	if g_currentMission.controlPlayer and g_currentMission.player ~= nil then
		source = g_currentMission.player.rootNode
	end
	if source ~= nil and target ~= nil then
		local x,y,z = getWorldTranslation(target)
		local a,b,c = getWorldTranslation(source)
		local distance = MathUtil.vector3Length(x-a, y-b, z-c);
		if distance < dist then
			inRange = true
		end
	end
	return inRange
end
function PushBar:getIsTurnedOn()
	local spec = self.spec_pushBar
	
    return spec.controlVehicle
end
function PushBar:isDetachAllowed(superFunc)
	local spec = self.spec_pushBar
	
    if superFunc ~= nil then
        if not superFunc(self) then
            return false
        end
    end
    return (not spec.controlVehicle and not spec.isUsed)
end
function PushBar:getCanBePickedUp(superFunc)
	return true
end
function PushBar:getIsVehicleControlledByPlayer()
	return self.spec_enterable.isControlled
end
function PushBar:getIsControlled()
	local spec = self.spec_pushBar
    
	return true
end
function PushBar:onDraw()
	local spec = self.spec_pushBar
end
function PushBar:actionCallback(actionName, keyStatus, arg4, arg5, arg6)
	local spec = self.spec_pushBar
	
	if self:getIsActiveForInput() then
		if keyStatus > 0 then
			if actionName == 'PUSHBAR_ATTACH_VEHICLE' then
				spec.inputBarAttachVehicle = true
			elseif actionName == 'PUSHBAR_VEHICLE_THROTTLE' then
				if self:getFirstVehicleAttached(self, nil, false) ~= nil then
					self:toggleControlVehicle(not spec.attachedVehicleThrottle, spec.steeringMode, spec.reverseDrivingMode, false, false)
				else
					g_currentMission:showBlinkingWarning(g_i18n:getText('pushBarNoDrivable'), 2000)
				end
			elseif actionName == 'PUSHBAR_TOGGLE_STEERING_MODE' then
				if self:getFirstVehicleAttached(self, nil, false) ~= nil then
					local steeringMode = spec.steeringMode
					local max = PushBar.steeringMode == 2 and 2 or 3
					local step = PushBar.steeringMode == 3 and 2 or 1
					if steeringMode + step <= max then
						steeringMode = steeringMode + step
					else
						steeringMode = 1
					end
					self:toggleControlVehicle(spec.attachedVehicleThrottle, steeringMode, spec.reverseDrivingMode, false, false)
				else
					g_currentMission:showBlinkingWarning(g_i18n:getText('pushBarNoDrivable'), 2000)
				end
			elseif actionName == 'PUSHBAR_CHANGE_ATTACHED_DIRECTION' then
				if self:getFirstVehicleAttached(self, nil, false) ~= nil then
					self:toggleControlVehicle(spec.attachedVehicleThrottle, spec.steeringMode, not spec.reverseDrivingMode, false, false)
				else
					g_currentMission:showBlinkingWarning(g_i18n:getText('pushBarNoDrivable'), 2000)
				end
			elseif actionName == 'PUSHBAR_OPEN_MENU_VEHICLE' then
				if PushBar.gui.tcSettingGui.isOpen then
					PushBar.gui.tcSettingGui:onClickBack()
				elseif g_gui.currentGui == nil then
					PushBar.gui.tcSettingGui:setManualAttach(PushBar.manualAttachIndex)
					PushBar.gui.tcSettingGui:setShowHelp(PushBar.showHelpIndex)
					PushBar.gui.tcSettingGui:setShowIds(PushBar.showIdsIndex)
					PushBar.gui.tcSettingGui:setIdsDistanceView(PushBar.IdsDistanceViewIndex)
					PushBar.gui.tcSettingGui:setBarDistanceView(PushBar.barDistanceViewIndex)
					PushBar.gui.tcSettingGui:setSteeringMode(PushBar.steeringModeIndex)
					PushBar.gui.tcSettingGui:setAutoOffVehicle(PushBar.autoOffVehicleIndex)
					PushBar.gui.tcSettingGui.IdsDistanceView:setDisabled(not PushBar.showIds)
					g_gui:showGui("tcGui")
				end
			end
		elseif keyStatus == 0 then
			if actionName == 'PUSHBAR_ATTACH_VEHICLE' then
				spec.inputBarAttachVehicle = false
			elseif actionName == 'PUSHBAR_VEHICLE_THROTTLE' then
				spec.inputBarVehicleThrottle = false
			end
		end
		if actionName == 'PUSHBAR_STEER_LEFT' then
			spec.input_STEER_LEFT = keyStatus > 0
			self:updateManualSteering(spec.input_STEER_LEFT, spec.input_STEER_RIGHT, false)
		elseif actionName == 'PUSHBAR_STEER_RIGHT' then
			spec.input_STEER_RIGHT = keyStatus > 0
			self:updateManualSteering(spec.input_STEER_LEFT, spec.input_STEER_RIGHT, false)
		end
	end
end
function PushBar:actionCallbackPlayer(actionName, keyStatus, arg4, arg5, arg6)
	local count = 0
	for i,bar in pairs(PushBar.bar) do
		if bar ~= nil and bar.spec_pushBar.isInRange then
			count = count + 1
		end
	end
	--if count ~= 0 then
		if keyStatus > 0 then
			if count ~= 0 then
				if actionName == 'PUSHBAR_MANUAL_ATTACH' then
					PushBar.input_manualAttach = true
					self:pickUpObject(false)
				elseif actionName == 'PUSHBAR_ATTACH_HOOK' then
					PushBar.input_mountHook = true
				elseif actionName == 'PUSHBAR_SWITCH' then
					PushBar.switchToNextBar()
				end
			end
			if actionName == 'PUSHBAR_OPEN_MENU' then
				if PushBar.gui.tcSettingGui.isOpen then
					PushBar.gui.tcSettingGui:onClickBack()
				elseif g_gui.currentGui == nil then
					PushBar.gui.tcSettingGui:setManualAttach(PushBar.manualAttachIndex)
					PushBar.gui.tcSettingGui:setShowHelp(PushBar.showHelpIndex)
					PushBar.gui.tcSettingGui:setShowIds(PushBar.showIdsIndex)
					PushBar.gui.tcSettingGui:setIdsDistanceView(PushBar.IdsDistanceViewIndex)
					PushBar.gui.tcSettingGui:setBarDistanceView(PushBar.barDistanceViewIndex)
					PushBar.gui.tcSettingGui:setSteeringMode(PushBar.steeringModeIndex)
					PushBar.gui.tcSettingGui:setAutoOffVehicle(PushBar.autoOffVehicleIndex)
					PushBar.gui.tcSettingGui.IdsDistanceView:setDisabled(not PushBar.showIds)
					g_gui:showGui("tcGui")
				end
			end
		elseif keyStatus == 0 then
			if count ~= 0 then
				if actionName == 'PUSHBAR_MANUAL_ATTACH' then
					PushBar.input_manualAttach = false
				elseif actionName == 'PUSHBAR_ATTACH_HOOK' then
					PushBar.input_mountHook = false
				end
			end
		end
		
		local spec = PushBar.bar[PushBar.selectedBarId].spec_pushBar
		local bar = PushBar.bar[PushBar.selectedBarId]
		if actionName == 'PUSHBAR_MOVE_HOOK_TRIGGER' then
			spec.input_MOVE_HOOK_TRIGGER = keyStatus > 0
		elseif actionName == 'PUSHBAR_MOVE_HOOK_LEFT' then
			spec.input_MOVE_HOOK_LEFT = keyStatus > 0
			if keyStatus == 0 then bar:moveHook(spec.hookX, spec.hookY, spec.hookZ, false) end
		elseif actionName == 'PUSHBAR_MOVE_HOOK_RIGHT' then
			spec.input_MOVE_HOOK_RIGHT = keyStatus > 0
			if keyStatus == 0 then bar:moveHook(spec.hookX, spec.hookY, spec.hookZ, false) end
		elseif actionName == 'PUSHBAR_MOVE_HOOK_FORWARD' then
			spec.input_MOVE_HOOK_FORWARD = keyStatus > 0
			if keyStatus == 0 then bar:moveHook(spec.hookX, spec.hookY, spec.hookZ, false) end
		elseif actionName == 'PUSHBAR_MOVE_HOOK_BACKWARD' then
			spec.input_MOVE_HOOK_BACKWARD = keyStatus > 0
			if keyStatus == 0 then bar:moveHook(spec.hookX, spec.hookY, spec.hookZ, false) end
		elseif actionName == 'PUSHBAR_MOVE_HOOK_UP' then
			spec.input_MOVE_HOOK_UP = keyStatus > 0
			if keyStatus == 0 then bar:moveHook(spec.hookX, spec.hookY, spec.hookZ, false) end
		elseif actionName == 'PUSHBAR_MOVE_HOOK_DOWN' then
			spec.input_MOVE_HOOK_DOWN = keyStatus > 0
			if keyStatus == 0 then bar:moveHook(spec.hookX, spec.hookY, spec.hookZ, false) end
		end
	--end
end
function PushBar:settingsFromGui(manualAttachState, showHelpState, showIdsState, IdsDistanceViewState, barDistanceViewState, steeringModeState, autoOffVehicleState)
	PushBar.manualAttach = PushBar.booleans[manualAttachState]
	PushBar.showHelp = PushBar.booleans[showHelpState]
	PushBar.showIds = PushBar.booleans[showIdsState]
	PushBar.IdsDistanceView = PushBar.IdsDistanceViews[IdsDistanceViewState]
	PushBar.barDistanceView = PushBar.barDistanceViews[barDistanceViewState]
	PushBar.steeringMode = PushBar.steeringModes[steeringModeState]
	PushBar.autoOffVehicle = PushBar.booleans[autoOffVehicleState]

	PushBar.manualAttachIndex = manualAttachState
	PushBar.showHelpIndex = showHelpState
	PushBar.showIdsIndex = showIdsState
	PushBar.IdsDistanceViewIndex = IdsDistanceViewState
	PushBar.barDistanceViewIndex = barDistanceViewState
	PushBar.steeringModeIndex = steeringModeState
	PushBar.autoOffVehicleIndex = autoOffVehicleState
	PushBar:saveConfigTc()
end
function PushBar:settingsResetGui()
	PushBar.gui.tcSettingGui:setManualAttach(1)
	PushBar.gui.tcSettingGui:setShowHelp(1)
	PushBar.gui.tcSettingGui:setShowIds(1)
	PushBar.gui.tcSettingGui:setIdsDistanceView(4)
	PushBar.gui.tcSettingGui:setBarDistanceView(7)
	PushBar.gui.tcSettingGui:setSteeringMode(1)
	PushBar.gui.tcSettingGui:setSteeringMode(1)
	PushBar.gui.tcSettingGui:setAutoOffVehicle(2)
end
function PushBar:guiClosed()
	print('set2')
	PushBar.gui.tcSettingGui:setManualAttach(PushBar.manualAttachIndex)
	PushBar.gui.tcSettingGui:setShowHelp(PushBar.showHelpIndex)
	PushBar.gui.tcSettingGui:setShowIds(PushBar.showIdsIndex)
	PushBar.gui.tcSettingGui:setIdsDistanceView(PushBar.IdsDistanceViewIndex)
	PushBar.gui.tcSettingGui:setBarDistanceView(PushBar.barDistanceViewIndex)
	PushBar.gui.tcSettingGui:setSteeringMode(PushBar.steeringModeIndex)
	PushBar.gui.tcSettingGui:setAutoOffVehicle(PushBar.autoOffVehicleIndex)
end
function PushBar:onReadStream(streamId, connection)
	local spec = self.spec_pushBar
	
	local hookMounted = streamReadBool(streamId)
	if hookMounted then
		local hookedVehicleId = streamReadInt32(streamId)
		local hookMountedBack = streamReadBool(streamId)
		local hookX = streamReadFloat32(streamId)
		local hookY = streamReadFloat32(streamId)
		local hookZ = streamReadFloat32(streamId)
		if hookedVehicleId ~= nil and hookMountedBack ~= nil and hookX ~= nil and hookY ~= nil and hookZ ~= nil then
			spec.postMountHook = true
			spec.vehicleIdHooked = hookedVehicleId
			spec.hookMountedBack = hookMountedBack
			spec.hookX = hookX
			spec.hookY = hookY
			spec.hookZ = hookZ
		end
	end
	
    local isUsed = streamReadBool(streamId)
    if isUsed then
		local attachedVehicleId = streamReadInt32(streamId)
		local attacherJointId = streamReadInt32(streamId)
		if attachedVehicleId ~= nil and attacherJointId ~= nil then
			spec.postAttachVehicles = true
			spec.vehicleIdAttached = attachedVehicleId
			spec.jointIdAttached = attacherJointId
		end		
    end
	local throttle = streamReadBool(streamId)
	local steering = streamReadInt8(streamId)
	local reverse = streamReadBool(streamId)
	self:toggleControlVehicle(throttle, steering, reverse, false, true)
	if steering == 3 then
		local left = streamReadBool(streamId)
		local right = streamReadBool(streamId)
		self:updateManualSteering(left, right, true)
	end
end
function PushBar:onWriteStream(streamId, connection)
	local spec = self.spec_pushBar
	
    streamWriteBool(streamId, spec.hookMounted)
	if spec.hookMounted then
		local vehicle = self:vehicleToVehicleId(spec.hookedVehicleId)
		streamWriteInt32(streamId, vehicle)
		streamWriteBool(streamId, spec.hookMountedBack)
		streamWriteFloat32(streamId, spec.hookX)
		streamWriteFloat32(streamId, spec.hookY)
		streamWriteFloat32(streamId, spec.hookZ)
	end
    streamWriteBool(streamId, spec.isUsed)
    if spec.isUsed then
		local vehicle = self:vehicleToVehicleId(spec.joint.vehicle)
		streamWriteInt32(streamId, vehicle)
        streamWriteInt32(streamId, spec.joint.attacherJointId)
    end
	streamWriteBool(streamId, spec.attachedVehicleThrottle)
	streamWriteInt8(streamId, spec.steeringMode)
	streamWriteBool(streamId, spec.reverseDrivingMode)
	if spec.steering == 3 then
		streamWriteBool(streamId, spec.input_STEER_LEFT)
		streamWriteBool(streamId, spec.input_STEER_RIGHT)
	end
end
function PushBar:vehicleToVehicleId(vehicle)
	local id
	for k,v in pairs(g_currentMission.vehicles) do
		if v == vehicle then
			id = k
			break
		end
	end
	return id
end
function PushBar:vehicleIdToVehicle(id)
	local vehicle
	for k,v in pairs(g_currentMission.vehicles) do
		if k == id then
			vehicle = v
			break
		end
	end
	return vehicle
end
------------------Events---------------------------
PushingBarAttachEvents = {};
PushingBarAttachEvents_mt = Class(PushingBarAttachEvents, Event);

InitEventClass(PushingBarAttachEvents, "PushingBarAttachEvents");

function PushingBarAttachEvents.emptyNew()
    local self = Event.new(PushingBarAttachEvents_mt);
	self.className="PushingBarAttachEvents";
    return self;
end
function PushingBarAttachEvents.new(vehicle, vehicleId, jointId)
    local self = PushingBarAttachEvents.emptyNew()
    self.vehicle = vehicle;
    self.vehicleId = vehicleId;
    self.jointId = jointId;
    return self;
end
function PushingBarAttachEvents:readStream(streamId, connection)
    self.vehicle = NetworkUtil.readNodeObject(streamId);
    self.vehicleId = NetworkUtil.readNodeObject(streamId);
    self.jointId = streamReadInt32(streamId);
    self:run(connection);
end
function PushingBarAttachEvents:writeStream(streamId, connection)
    NetworkUtil.writeNodeObject(streamId, self.vehicle);
    NetworkUtil.writeNodeObject(streamId, self.vehicleId);
    streamWriteInt32(streamId, self.jointId);
end
function PushingBarAttachEvents:run(connection)
    PushBar.attachVehicles(self.vehicle, self.vehicleId, self.jointId, true);
    if not connection:getIsServer() then
        g_server:broadcastEvent(PushingBarAttachEvents.new(self.vehicle, self.vehicleId, self.jointId), nil, connection, self.vehicle);
    end
end
function PushingBarAttachEvents.sendEvent(vehicle, vehicleId, jointId, noEventSend)
    if noEventSend == nil or noEventSend == false then
        if g_server ~= nil then
            g_server:broadcastEvent(PushingBarAttachEvents.new(vehicle, vehicleId, jointId), nil, nil, vehicle);
        else
            g_client:getServerConnection():sendEvent(PushingBarAttachEvents.new(vehicle, vehicleId, jointId));
        end
    end
end

PushingBarDetachEvents = {}
PushingBarDetachEvents_mt = Class(PushingBarDetachEvents, Event)

InitEventClass(PushingBarDetachEvents, "PushingBarDetachEvents")

function PushingBarDetachEvents.emptyNew()
    local self = Event.new(PushingBarDetachEvents_mt)
	self.className="PushingBarDetachEvents"
    return self
end
function PushingBarDetachEvents.new(vehicle)
    local self = PushingBarDetachEvents.emptyNew()
    self.vehicle = vehicle;
    return self
end
function PushingBarDetachEvents:readStream(streamId, connection)
    self.vehicle = NetworkUtil.readNodeObject(streamId)
    self:run(connection)
end
function PushingBarDetachEvents:writeStream(streamId, connection)
    NetworkUtil.writeNodeObject(streamId, self.vehicle)
end
function PushingBarDetachEvents:run(connection)
    PushBar.detachVehicles(self.vehicle, true)
    if not connection:getIsServer() then
        g_server:broadcastEvent(PushingBarDetachEvents.new(self.vehicle), nil, connection, self.vehicle)
    end
end
function PushingBarDetachEvents.sendEvent(vehicle, noEventSend)
    if noEventSend == nil or noEventSend == false then
        if g_server ~= nil then
            g_server:broadcastEvent(PushingBarDetachEvents.new(vehicle), nil, nil, vehicle)
        else
            g_client:getServerConnection():sendEvent(PushingBarDetachEvents.new(vehicle))
        end
    end
end

PushingBarMountHookEvent = {};
PushingBarMountHookEvent_mt = Class(PushingBarMountHookEvent, Event);

InitEventClass(PushingBarMountHookEvent, "PushingBarMountHookEvent");

function PushingBarMountHookEvent.emptyNew()
    local self = Event.new(PushingBarMountHookEvent_mt);
	self.className="PushingBarMountHookEvent";
    return self;
end
function PushingBarMountHookEvent.new(object, vehicleId, hookMountedBack)
    local self = PushingBarMountHookEvent.emptyNew()
    self.object = object;
    self.vehicleId = vehicleId;
    self.hookMountedBack = hookMountedBack;
    return self;
end
function PushingBarMountHookEvent:readStream(streamId, connection)
    self.object = NetworkUtil.readNodeObject(streamId);
    self.vehicleId = NetworkUtil.readNodeObject(streamId);
	self.hookMountedBack = streamReadBool(streamId)
    self:run(connection);
end
function PushingBarMountHookEvent:writeStream(streamId, connection)
    NetworkUtil.writeNodeObject(streamId, self.object);
    NetworkUtil.writeNodeObject(streamId, self.vehicleId);
	streamWriteBool(streamId, self.hookMountedBack)
end
function PushingBarMountHookEvent:run(connection)
	if self.object ~= nil then
		self.object:mountHook(self.vehicleId, self.hookMountedBack, true)
	end
    if not connection:getIsServer() then
		g_server:broadcastEvent(self, false, connection, self.object)
    end
end
function PushingBarMountHookEvent.sendEvent(vehicle, vehicleId, hookMountedBack, noEventSend)
    if noEventSend == nil or noEventSend == false then
        if g_server ~= nil then
            g_server:broadcastEvent(PushingBarMountHookEvent.new(vehicle, vehicleId, hookMountedBack), nil, nil, vehicle);
        else
            g_client:getServerConnection():sendEvent(PushingBarMountHookEvent.new(vehicle, vehicleId, hookMountedBack));
        end
    end
end

PushingBarUnmountHookEvent = {};
PushingBarUnmountHookEvent_mt = Class(PushingBarUnmountHookEvent, Event);

InitEventClass(PushingBarUnmountHookEvent, "PushingBarUnmountHookEvent");

function PushingBarUnmountHookEvent.emptyNew()
    local self = Event.new(PushingBarUnmountHookEvent_mt);
	self.className="PushingBarUnmountHookEvent";
    return self;
end
function PushingBarUnmountHookEvent.new(object, vehicleId)
    local self = PushingBarUnmountHookEvent.emptyNew()
    self.object = object;
    self.vehicleId = vehicleId;
    return self;
end
function PushingBarUnmountHookEvent:readStream(streamId, connection)
    self.object = NetworkUtil.readNodeObject(streamId);
    self.vehicleId = NetworkUtil.readNodeObject(streamId);
    self:run(connection);
end
function PushingBarUnmountHookEvent:writeStream(streamId, connection)
    NetworkUtil.writeNodeObject(streamId, self.object);
    NetworkUtil.writeNodeObject(streamId, self.vehicleId);
end
function PushingBarUnmountHookEvent:run(connection)
	if self.object ~= nil then
		self.object:unmountHook(self.vehicleId, true)
	end
    if not connection:getIsServer() then
		g_server:broadcastEvent(self, false, connection, self.object)
    end
end
function PushingBarUnmountHookEvent.sendEvent(vehicle, vehicleId, noEventSend)
    if noEventSend == nil or noEventSend == false then
        if g_server ~= nil then
            g_server:broadcastEvent(PushingBarUnmountHookEvent.new(vehicle, vehicleId), nil, nil, vehicle);
        else
            g_client:getServerConnection():sendEvent(PushingBarUnmountHookEvent.new(vehicle, vehicleId));
        end
    end
end

PushingBarToggleControlVehicleEvent = {};
PushingBarToggleControlVehicleEvent_mt = Class(PushingBarToggleControlVehicleEvent, Event);

InitEventClass(PushingBarToggleControlVehicleEvent, "PushingBarToggleControlVehicleEvent");

function PushingBarToggleControlVehicleEvent.emptyNew()
    local self = Event.new(PushingBarToggleControlVehicleEvent_mt);
	self.className="PushingBarToggleControlVehicleEvent";
    return self;
end
function PushingBarToggleControlVehicleEvent.new(object, throttle, steering, reverse, forced)
    local self = PushingBarToggleControlVehicleEvent.emptyNew()
    self.object = object
    self.throttle = throttle
    self.steering = steering
    self.reverse = reverse
    self.forced = forced
    return self
end
function PushingBarToggleControlVehicleEvent:readStream(streamId, connection)
    self.object = NetworkUtil.readNodeObject(streamId);
    self.throttle = streamReadBool(streamId)
    self.steering = streamReadInt8(streamId)
    self.reverse = streamReadBool(streamId)
    self.forced = streamReadBool(streamId)
    self:run(connection)
end
function PushingBarToggleControlVehicleEvent:writeStream(streamId, connection)
    NetworkUtil.writeNodeObject(streamId, self.object);
    streamWriteBool(streamId, self.throttle)
    streamWriteInt8(streamId, self.steering)
    streamWriteBool(streamId, self.reverse)
    streamWriteBool(streamId, self.forced)
end
function PushingBarToggleControlVehicleEvent:run(connection)
	if self.object ~= nil then
		self.object:toggleControlVehicle(self.throttle, self.steering, self.reverse, self.forced, true)
	end
    if not connection:getIsServer() then
		g_server:broadcastEvent(self, false, connection, self.object)
    end
end
function PushingBarToggleControlVehicleEvent.sendEvent(vehicle, throttle, steering, reverse, forced, noEventSend)
	if throttle ~= vehicle.throttle and steering ~= vehicle.steering and reverse ~= vehicle.reverse and forced ~= vehicle.forced then
		if noEventSend == nil or noEventSend == false then
			if g_server ~= nil then
				g_server:broadcastEvent(PushingBarToggleControlVehicleEvent.new(vehicle, throttle, steering, reverse, forced), nil, nil, vehicle)
			else
				g_client:getServerConnection():sendEvent(PushingBarToggleControlVehicleEvent.new(vehicle, throttle, steering, reverse, forced))
			end
		end
	end
end

PushingBarupdateManualSteeringEvent = {}
PushingBarupdateManualSteeringEvent_mt = Class(PushingBarupdateManualSteeringEvent, Event)

InitEventClass(PushingBarupdateManualSteeringEvent, "PushingBarupdateManualSteeringEvent")

function PushingBarupdateManualSteeringEvent.emptyNew()
    local self = Event.new(PushingBarupdateManualSteeringEvent_mt)
	self.className="PushingBarupdateManualSteeringEvent"
    return self
end
function PushingBarupdateManualSteeringEvent.new(object, left, right)
    local self = PushingBarupdateManualSteeringEvent.emptyNew()
    self.object = object
    self.left = left
    self.right = right
    return self
end
function PushingBarupdateManualSteeringEvent:readStream(streamId, connection)
    self.object = NetworkUtil.readNodeObject(streamId);
    self.left = streamReadBool(streamId)
    self.right = streamReadBool(streamId)
    self:run(connection)
end
function PushingBarupdateManualSteeringEvent:writeStream(streamId, connection)
    NetworkUtil.writeNodeObject(streamId, self.object);
    streamWriteBool(streamId, self.left)
    streamWriteBool(streamId, self.right)
end
function PushingBarupdateManualSteeringEvent:run(connection)
	if self.object ~= nil then
		self.object:updateManualSteering(self.left, self.right, true)
	end
    if not connection:getIsServer() then
		g_server:broadcastEvent(self, false, connection, self.object)
    end
end
function PushingBarupdateManualSteeringEvent.sendEvent(vehicle, left, right, noEventSend)
	if left ~= vehicle.left and right ~= vehicle.right then
		if noEventSend == nil or noEventSend == false then
			if g_server ~= nil then
				g_server:broadcastEvent(PushingBarupdateManualSteeringEvent.new(vehicle, left, right), nil, nil, vehicle)
			else
				g_client:getServerConnection():sendEvent(PushingBarupdateManualSteeringEvent.new(vehicle, left, right))
			end
		end
	end
end

PushingBarMoveHookEvent = {};
PushingBarMoveHookEvent_mt = Class(PushingBarMoveHookEvent, Event);

InitEventClass(PushingBarMoveHookEvent, "PushingBarMoveHookEvent");

function PushingBarMoveHookEvent.emptyNew()
    local self = Event.new(PushingBarMoveHookEvent_mt);
	self.className="PushingBarMoveHookEvent";
    return self;
end
function PushingBarMoveHookEvent.new(object, x, y, z)
    local self = PushingBarMoveHookEvent.emptyNew()
    self.object = object
    self.x = x
    self.y = y
    self.z = z
    return self
end
function PushingBarMoveHookEvent:readStream(streamId, connection)
    self.object = NetworkUtil.readNodeObject(streamId);
    self.x = streamReadFloat32(streamId)
    self.y = streamReadFloat32(streamId)
    self.z = streamReadFloat32(streamId)
    self:run(connection);
end
function PushingBarMoveHookEvent:writeStream(streamId, connection)
    NetworkUtil.writeNodeObject(streamId, self.object);
	streamWriteFloat32(streamId, self.x)
	streamWriteFloat32(streamId, self.y)
	streamWriteFloat32(streamId, self.z)
end
function PushingBarMoveHookEvent:run(connection)
	if self.object ~= nil then
		self.object:moveHook(self.x, self.y, self.z, true)
	end
    if not connection:getIsServer() then
		g_server:broadcastEvent(self, false, connection, self.object)
    end
end
function PushingBarMoveHookEvent.sendEvent(vehicle, x, y, z, noEventSend)
	if x ~= vehicle.x and y ~= vehicle.y and z ~= vehicle.z then
		if noEventSend == nil or noEventSend == false then
			if g_server ~= nil then
				g_server:broadcastEvent(PushingBarMoveHookEvent.new(vehicle, x, y, z), nil, nil, vehicle)
			else
				g_client:getServerConnection():sendEvent(PushingBarMoveHookEvent.new(vehicle, x, y, z))
			end
		end
	end
end