Jump to content

Hydra Lock System


Tron

Recommended Posts

Hello out there,

I wanted to edit the following hydra lock script so that you have to press handbrake only once to lock a vehicle. Lock will be turned off when the opponent goes out of range or when you press handbrake again.

Any help regarding this would be much appreciated.

--[[
Luca aka
specahawk aka
spopo aka
Anirudh Katoch

(All rights reserved)
MIT License - Do whatever you want.
]]

----User settings---

local SHOOT_COOLDOWN = 1500 --Cooldown between homing shots
local LOCKON_TIME = 1500 --Time required to lock on to a target
local LOCK_RANGE = 330 --Maximum distance between you and the target
local LOCK_ANGLE = 0.95 --(in radians) We cannot lock on targets unless they are within this angle of the front of the hydra
local VALID_TARGET_FUNCTION = function (vehicle) --Used to decide whether a vehicle should appear as a lock-on option
	-- local targetTeam = vehicle.controller and vehicle.controller.team
	-- local ourTeam = localPlayer.team
	-- if targetTeam and ourTeam and targetTeam == ourTeam then
		-- return false --The target vehicle has someone driving, and both of you are on the same team
	-- end
	return true
end

--[[
	to implement team tagging, or to disallow certain vehicles from being targetted, define the VALID_TARGET_FUNCTION
	VALID_TARGET_FUNCTION should take as parameter a vehicle, and return a boolean (true means it can be targetted)
	Here is an example of a function that will only let us target HYDRAS of OTHER TEAMS that are MORE THAN 50m AWAY and are DIRECTLY VISIBLE
	local VALID_TARGET_FUNCTION = function(vehicle)
		local targetTeam = vehicle.controller and vehicle.controller.team
		local ourTeam = localPlayer.team
		if targetTeam and ourTeam and targetTeam == ourTeam then
			return false --The target vehicle has someone driving, and both of you are on the same team
		end
		if vehicle.model ~= 520 then
			return false --Target is not a hydra, so it's not allowed
		end
		if (vehicle.position-localPlayer.position).length < 50 then
			return false --Closer than 50 metres
		end
		if not isLineOfSightClear(localPlayer.position, vehicle.position, true, false) then
			return false --Not directly visible
			--(Remember to account for your own vehicle and the target blocking the line)
		end
		return true --Target satisfied all criteria
	end
]]

local validTarget = VALID_TARGET_FUNCTION or function() return true end
LOCK_ANGLE = math.cos(LOCK_ANGLE)

local inHydra = false
local firestate = nil
local visibleVehicle = {}
local targetVehicle = nil
local nearbyVehicles = {}
getNearbyVehicles = function() return nearbyVehicles end --Used by other files
local currentHydra = nil

local function getTarget()
	-- Look for the nearest targets and lock on
	local nearestVehicle = nil
	local shortestDistance = LOCK_RANGE

	for _, vehicle in ipairs(nearbyVehicles) do
		local targPos = vehicle.position
		local myPos = localPlayer.position
		local displacement = targPos-myPos
		local dist = displacement.length

		if vehicle ~= localPlayer.vehicle and  dist < shortestDistance then
			shortestDistance = dist
			nearestVehicle = vehicle
		end
	end
	return nearestVehicle
end

local function checkForLockout(vehicle)
	if visibleVehicle[vehicle] then
		triggerEvent("onClientHydraMissilesSystemLockout", localPlayer, vehicle)
		visibleVehicle[vehicle] = nil
		lockedVehicle = nil
		targetVehicle = nil
	end
end

local lastShot = SHOOT_COOLDOWN*-2
local function shootMissile()
	if not inHydra then
		return
	end
	local target = lockedVehicle
	if not target or getTickCount() < lastShot + SHOOT_COOLDOWN then
		return
	end
	lastShot = getTickCount()
	local hydra = localPlayer.vehicle
	local vX, vY, vZ = hydra.velocity
	-- Shoot missile
	createProjectile( hydra, 20, hydra.position, 5000, target, _, _, _, vX+5000, vY, vZ)
  --  dxDrawText ( playerZoneName, 44, screenHeight - 43, screenWidth, screenHeight, tocolor ( 255, 255, 255, 255 ), 1, "pricedown" ) DRAW WARNING ON PLAYER SCREEN
	lockedVehicle = nil
	targetVehicle = nil
	visibleVehicle[target] = nil
end



local function update()
	local curtime = getTickCount()
	if not localPlayer.vehicle then --idk why, but sometimes the player has no vehicle sometime before vehicle exit event is fired
		stopHydra() --The Avengers
		return
	end

	local vehicle = targetVehicle
	if not vehicle then return end
	local visibleNow = false
	if vehicle ~= localPlayer.vehicle and not vehicle.blown and validTarget(vehicle) then
		local targPos = vehicle.position
		local myPos = localPlayer.position
		local displacement = targPos-myPos
		local dist = displacement.length
		local cosAngle = localPlayer.vehicle.matrix.forward:dot(displacement)/dist
		if dist < LOCK_RANGE and cosAngle>LOCK_ANGLE and firestate then
			local aX, aY = getScreenFromWorldPosition(targPos)
			if (aX and aY) then
				visibleNow = true
				--Draw the corners of the target box outline
				if lockedVehicle == vehicle then
					dxDrawImage (aX-118,aY-118, 246, 246, 'lock.png')
				else
					dxDrawImage (aX-118, aY-118, 246, 246, 'lock2.png')
				end
			end
		end
	end

	if not visibleNow then
		checkForLockout()
	elseif visibleVehicle[vehicle] then
		if curtime - visibleVehicle[vehicle] > LOCKON_TIME then
			lockedVehicle = vehicle
		end
	else
		visibleVehicle[vehicle] = curtime
	end
end


local function homingState(key,state)
	if not inHydra then return end
	if state == "down" then
		targetVehicle = getTarget()
		firestate = isControlEnabled("vehicle_secondary_fire")
		toggleControl("vehicle_secondary_fire",false)
		bindKey("vehicle_secondary_fire","down",shootMissile)
                
	else
		targetVehicle = nil
		lockedVehicle = nil
		toggleControl("vehicle_secondary_fire",firestate)
		firestate = nil
		unbindKey("vehicle_secondary_fire","down",shootMissile)
	end
end

local function vehicleGoneHandler() --This also triggers on localPlayer's vehicle, and does nothing to it
	removeEventHandler("onClientElementDestroy", source, vehicleGoneHandler)
	removeEventHandler("onClientElementStreamOut", source, vehicleGoneHandler)
	if getElementType( source ) == "vehicle" then
		for i, v in ipairs(nearbyVehicles) do
			if v == source then
				checkForLockout(source)
				table.remove(nearbyVehicles, i)
				return
			end
		end
	end
end

local function prepAfterStreamIn(vehicle)
	addEventHandler("onClientElementStreamOut", vehicle, vehicleGoneHandler)
	addEventHandler("onClientElementDestroy", vehicle, vehicleGoneHandler)
end

local function streamInHandler()
	if getElementType( source ) == "vehicle" then
		table.insert(nearbyVehicles, source)
		prepAfterStreamIn(source)
	end
end


local function startHydra(vehicle)
	if not inHydra and vehicle and isElement(vehicle) and vehicle.model == 520 then
		nearbyVehicles = getElementsByType("vehicle", root, true)
		for i, v in ipairs(nearbyVehicles) do
			prepAfterStreamIn(v)
		end
		addEventHandler("onClientElementStreamIn", root, streamInHandler)
		addEventHandler("onClientVehicleExplode", vehicle, stopHydra)
		addEventHandler("onClientElementDestroy", vehicle, stopHydra)
		addEventHandler("onClientElementStreamOut", vehicle, stopHydra) --Is this even possible?
		inHydra = isControlEnabled("handbrake")
		currentHydra = vehicle --To remove the listeners later
		toggleControl("handbrake", false)
		bindKey("handbrake","down",homingState)
		bindKey("handbrake","up",homingState)
		addEventHandler( "onClientRender", root,  update)
	end
end

function stopHydra()
	if inHydra then
		local target = getTarget()
		for i, v in ipairs(nearbyVehicles) do
			if v ~= target then
				removeEventHandler("onClientElementDestroy", v, vehicleGoneHandler)
				removeEventHandler("onClientElementStreamOut", v, vehicleGoneHandler)
				checkForLockout(v)
			end
		end
		checkForLockout(target)
		if target then
			removeEventHandler("onClientElementDestroy", target, vehicleGoneHandler)
			removeEventHandler("onClientElementStreamOut", target, vehicleGoneHandler)
		end
		removeEventHandler("onClientRender", root, update)
		unbindKey("handbrake","down",homingState)
		unbindKey("handbrake","up",homingState)
		if firestate ~= nil then
			homingState("handbrake","up")
		end
		local vehicle = currentHydra
		currentHydra = nil
		toggleControl("handbrake", inHydra)
		inHydra = false
		removeEventHandler("onClientElementStreamIn", root, streamInHandler)
		if isElement(vehicle) then
			removeEventHandler("onClientVehicleExplode", vehicle, stopHydra)
			removeEventHandler("onClientElementDestroy", vehicle, stopHydra)
			removeEventHandler("onClientElementStreamOut", vehicle, stopHydra)
		end
	end
end

local function initScript()
	if localPlayer.vehicle and localPlayer.vehicle.model == 520 then
		startHydra(localPlayer.vehicle)
	end
	addEventHandler("onClientResourceStop", resourceRoot, stopHydra)
	addEventHandler("onClientPlayerVehicleExit",localPlayer,stopHydra)
	addEventHandler("onClientPlayerWasted",localPlayer,stopHydra)
	addEventHandler("onClientPlayerVehicleEnter",localPlayer,startHydra)
end

addEventHandler("onClientResourceStart",resourceRoot,initScript)

 

Edited by Tron
  • Thanks 1
Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...