local U = require "scriptbank\\utillib" local rad = math.rad local sin = math.sin local cos = math.cos local atan = math.atan2 local grappleHooks = {} local epressed = false local throw_speed = 700 local hold_height = 10 local hold_dist = 50 local max_throw_dist = 5 --maximum time (in seconds) the hook will travel if it doesnt hit anything local max_charge_time = 1 --seconds til max throw length reached local show_timer = false local ghtimer = 0 local perc = 0 local n_max_time = 0 local angle_Y = 0 function grapplinghook_init_name( e, name ) Include( "utillib.lua" ) grappleHooks[ e ] = { name = name, state = "wait pick up" } max_charge_time = max_charge_time * 1000 max_throw_dist = max_throw_dist * 1000 end local function round( num, idp ) local mult = 10^( idp or 0 ) return math.floor( num * mult + 0.5 ) / mult end function RotatePlayerToEntity( e ) if g_Entity[e] ~= nil then local x = g_Entity[e]['x'] - g_PlayerPosX local z = g_Entity[e]['z'] - g_PlayerPosZ local angle = atan( x, z ) angle = angle * ( 180.0 / math.pi ) if angle < 0 then angle = 360 + angle elseif angle > 360 then angle = angle - 360 end SetFreezeAngle(g_PlayerAngX,angle,g_PlayerAngZ) SetFreezePosition(g_PlayerPosX,g_PlayerPosY,g_PlayerPosZ) TransportToFreezePosition() return angle end return 0 end function grapplinghook_main( e ) local gh = grappleHooks[ e ] local Ent = g_Entity[ e ] if gh == nil then return end -- Prompt( gh.state ) if gh.state == "wait pick up" then if U.PlayerLookingNear( e, 150, 20 ) then PromptLocal( e, "Collect the " .. gh.name .. "? (E)" ) if g_KeyPressE == 1 and not epressed then epressed = true gh.state = "picking" end end elseif gh.state == "picking" then if g_KeyPressE == 0 then epressed = false StartTimer( e ) gh.state = "holding" end elseif gh.state == "holding" then CollisionOff( e ) SetRotation( e, g_PlayerAngX, g_PlayerAngY, g_PlayerAngZ ) SetPosition( e, g_PlayerPosX, g_PlayerPosY + hold_height, g_PlayerPosZ ) angle_Y = rad( g_PlayerAngY ) local pos_X = g_PlayerPosX + ( sin( angle_Y ) * hold_dist ) local pos_Z = g_PlayerPosZ + ( cos( angle_Y ) * hold_dist ) SetPosition( e, pos_X, g_PlayerPosY + hold_height, pos_Z ) CollisionOn( e ) if g_KeyPressE == 1 then ghtimer = GetTimer( e ) Panel( 40, 80, 64, 86 ) if ghtimer > max_charge_time then ghtimer = max_charge_time end perc = ( ( ghtimer / max_charge_time ) * 10 ) * 2 for a = 1, perc do Panel( 40 + a, 81, 41 + a, 82 ) end perc = ghtimer / max_charge_time n_max_time = max_throw_dist * perc perc = perc * 100 perc = round( perc, 0 ) TextCenterOnX( 50, 76, 3, perc .. " % " ) else if perc > 0 then perc = 0 gh.state = "firing" end ghtimer = 0 StartTimer( e ) end elseif gh.state == "firing" then CollisionOff( e ) MoveForward( e, throw_speed ) CollisionOn( e ) local x1 = GetEntityPositionX( e ) local y1 = GetEntityPositionY( e ) local z1 = GetEntityPositionZ( e ) local y2 = y1 local x2 = x1 + ( sin( angle_Y ) * 45 ) local z2 = z1 + ( cos( angle_Y ) * 45 ) local obstructionhit = IntersectAll( x1, y1, z1, x2, y2, z2, Ent.obj ) if obstructionhit == nil then obstructionhit = 0 end if obstructionhit ~= 0 then --Prompt ("obstructed") gh.state = "hit" else local thit = RayTerrain( x1, y1, z1, x2, y2 + 10, z2 ) if thit ~= 1 then else gh.state = "hit" --prompt ("obstructed") end end if gh.state ~= "hit" then if GetTimer( e ) > n_max_time then gh.state = "return" end end elseif gh.state == "hit" then StartTimer( e ) angle_Y = g_PlayerAngY local x1 = g_PlayerPosX local y1 = g_PlayerPosY + 10 local z1 = g_PlayerPosZ local y2 = y1 local x2 = x1 + ( sin( angle_Y ) * 80 ) local z2 = z1 + ( cos( angle_Y ) * 80 ) local obstructionhit = IntersectAll( x1, y1, z1, x2, y2, z2, 0 ) if obstructionhit == nil then obstructionhit = 0 end if obstructionhit ~= 0 then angle_Y = RotatePlayerToEntity( e ) angle_Y = rad( angle_Y ) local pos_X = g_PlayerPosX + ( sin( angle_Y ) * -throw_speed / 10 ) local pos_Z = g_PlayerPosZ + ( cos( angle_Y ) * -throw_speed / 10 ) SetFreezePosition( pos_X, g_PlayerPosY, pos_Z ) SetFreezeAngle( 0, g_PlayerAngY, 0 ) TransportToFreezePosition() gh.state = "return" return end if U.PlayerCloserThan( e, 200 ) then gh.state = "holding" return end angle_Y = RotatePlayerToEntity( e ) angle_Y = rad( angle_Y ) local pos_X = g_PlayerPosX + ( sin( angle_Y ) * throw_speed / 10 ) local pos_Z = g_PlayerPosZ + ( cos( angle_Y ) * throw_speed / 10 ) SetFreezePosition( pos_X, g_PlayerPosY, pos_Z ) SetFreezeAngle( 0, g_PlayerAngY, 0 ) TransportToFreezePosition() elseif gh.state == "return" then StartTimer( e ) if U.PlayerCloserThan( e, 150 ) then CollisionOff( e ) RotateToPlayer( e ) MoveForward( e, throw_speed ) CollisionOn( e ) else gh.state = "holding" end end end function grapplinghook_preexit(e) end function grapplinghook_exit(e) end