-- DESCRIPTION: transloc wip local U = require "scriptbank\\utillib" local Q = require "scriptbank\\quatlib" local P = require "scriptbank\\physlib" local V = require "scriptbank\\vectlib" local rad = math.rad local deg = math.deg local max = math.max local min = math.min local floor = math.floor local transloc = {} local epressed = false local throw_speed = 15 --how fast you throw the entity throw_speed * max_throw_dist = distance thrown local rotSpeed = 15 --how fast the entity spins local move_speed = .7 --how fast you are 'pulled' to the entity local returnSpeed = .1 --how fast the entity returns to you. either by timer or lmb local hold_height = -5 --height entity is held. changes here will effect the Y direction thrown. decrease throws down, increase throws up. local hold_dist = 50 --distance entity is held from you. too low and the collision barriers collide pushing you backwards. local max_throw_dist = 1.4 --maximum time (in seconds) the hook will travel, before returng, if it doesnt hit anything local max_charge_time = 0.001 --seconds til max throw length reached//charger and display are turned off local show_timer = true local tltimer = 0 local perc = 0 local n_max_time = 0 local startMouseWheel local tppEnt = GetGamePlayerControlThirdpersonCharactere() function transloc_init_name( e, name ) Include( "utillib.lua" ) Include( "quatlib.lua" ) Include("physlib.lua") Include("vectlib.lua") transloc[ 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 floor( num * mult + 0.5 ) / mult end local function getPlayerEyePos() -- correct player y pos for crouching if GetGamePlayerStatePlayerDucking() == 0 then return g_PlayerPosX, g_PlayerPosY + 31 + hold_height, g_PlayerPosZ else return g_PlayerPosX, g_PlayerPosY + 10 + hold_height, g_PlayerPosZ end end local tppObj = 0 local function findClearPos( x, y, z, allowedObj) if tppEnt ~= nil and tppEnt ~= 0 and tppObj == 0 then tppObj = g_Entity[ tppEnt ].obj end allowedObj = allowedObj or 0 local ny = y local found = false local numChecks = 0 local obhit = 0 while not found and numChecks < 100 do obhit = IntersectAll( x, ny, z, x, ny + 50, z, tppObj ) or 0 if obhit == 0 or obhit == allowedObj then found = true else ny = ny + 10 numChecks = numChecks + 1 end end ny = max( ny, GetTerrainHeight( x, z ) + 50 ) --PromptDuration("ray hit = "..obhit) return x, ny, z end local controlEnt = nil local lastTime = 0 local tDiff = 1 function transloc_main( e ) local tl = transloc[ e ] local Ent = g_Entity[ e ] local visibility = GetEntityVisibility(e) if startMouseWheel == nil then startMouseWheel = g_MouseWheel end local mouseWheel = g_MouseWheel local colList = P.GetObjectCollisionDetails( Ent.obj ) if controlEnt == nil then controlEnt = e end local timeNow = g_Time if controlEnt == e then if lastTime ~= 0 then tDiff = ( timeNow - lastTime ) / 20 end lastTime = timeNow end if tl == nil then return end Prompt( tl.state ) if tl.state == "wait pick up" then CollisionOn(e) --Added to make entity drop when 'R' pressed if U.PlayerLookingNear( e, 150, 20 ) then PromptLocal( e, "Collect the " .. tl.name .. "? (E)" ) if g_KeyPressE == 1 then if not epressed then tl.state = "picking" end epressed = true else epressed = false end end elseif tl.state == "picking" then if g_KeyPressE == 0 then epressed = false StartTimer( e ) tl.state = "holding" end elseif tl.state == "holding" then --#1 ---------------------------------------------- Hide/Show with scrollwheel while in the "holding" state if mouseWheel < startMouseWheel then startMouseWheel = mouseWheel Show(e) -- Show the entity when scrolling up elseif mouseWheel > startMouseWheel then startMouseWheel = mouseWheel Hide(e) -- Hide the entity when scrolling down if visibility == 0 then CollisionOff(e) end end ----------------------------------------- Hide with 'E' keypress. This will allow only one to be shown and functional at a time if tl.state == "holding" then if g_KeyPressE == 1 then if not epressed then if visibility == 1 then Hide(e) end end end epressed = true else epressed = false end ------------------------------------------ 'R' keypress drops entity if not visible then shows when dropping. if tl.state == "holding" then if visibility == 0 then if g_KeyPressR == 1 then tl.state = "wait pick up" Show(e) end end end ----------------------------------------------- --If entity is hidden then it doesn't function. Charge Display off for transloc --UnREM the "cd" lines to show Charge Display ----------------------------------------------- local pax, pay, paz = rad( g_PlayerAngX ), rad( g_PlayerAngY ), rad( g_PlayerAngZ ) if visibility == 1 then if g_MouseClick == 1 then tltimer = GetTimer( e ) --Panel( 40, 80, 64, 86 ) cd if tltimer > max_charge_time then tltimer = max_charge_time end --perc = ( ( tltimer / max_charge_time ) * 10 ) * 2 cd --for a = 1, perc do cd --Panel( 40 + a, 81, 41 + a, 82 ) cd --end cd else perc = tltimer / max_charge_time n_max_time = max_throw_dist * perc perc = perc * 100 perc = round( perc, 0 ) --TextCenterOnX( 50, 76, 3, perc .. " % " ) cd if perc > 0 then CollisionOn( e ) tl.state = "firing" tl.validloc = false tltimer = 0 StartTimer( e ) -- calculate a vector describing the direction and speed of the throw local force = throw_speed * n_max_time / max_throw_dist --force=speed local vx, vy, vz = U.Rotate3D( 0, 0, force, pax, pay, paz ) local ox, oy, oz = U.Rotate3D( 0.5, 0, 0, pax, pay, paz ) AddObjectCollisionCheck( Ent.obj ) PushObject( Ent.obj, vx, vy, vz, ox, oy, oz ) --throw end tltimer = 0 StartTimer( e ) --[[--------------------------------------------- local gex, gey, gez = (GetEntityPositionX ( e ) ), (GetEntityPositionY ( e ) ), (GetEntityPositionZ ( e ) ) if tl.state == 'firing' then if g_MouseClick == 2 then SetFreezePosition( tl.hit.x ), ( tl.hit.y), ( tl.hit.z) TransportToFreezePositionOnly() -----------------------------------------------]] end if tl.state ~= "firing" then local ppx, ppy, ppz = getPlayerEyePos() -- calculate carry position based on player angles local xo, yo, zo = U.Rotate3D( 0, 0, hold_dist, pax, pay, paz ) -- position entity wrt player CollisionOff( e ) RotateObject( Ent.obj, g_PlayerAngX, g_PlayerAngY, g_PlayerAngZ ) PositionObject( Ent.obj, ppx + xo, ppy + yo, ppz + zo ) --CollisionOn( e ) --Deactivated to make entity collision off when holding if visibility == 0 then CollisionOff(e) else CollisionOn(e) end ---------------------------------------------- If player looks down past 65 deg then entity is non-solid if ( GetGamePlayerStateCamAngleX()>65 ) then --so it won't collide with player capsule CollisionOff(e) end else CollisionOn(e) end end --goto on RMB click while in 'firing' ---------------------------------------------- elseif tl.state == "firing" then if g_MouseClick == 2 then if (GetGamePlayerControlJumpmax() >215) then SetGamePlayerControlJumpmax(215) --reset max jump height for "return" state end if visibility == 1 then tl.validloc = true tl.state = "hit" tl.timer = timeNow + 4000 tl.hit = { x = Ent.x, y = Ent.y, z = Ent.z } elseif visibility == 0 then tltimer = 0 CollisionOff(e) end end --#1 ---------------------------------------------- Hide/Show with scrollwheel while in the "holding" state if mouseWheel < 0 then Show(e) -- Show the entity when scrolling up elseif mouseWheel > 0 then Hide(e) -- Hide the entity when scrolling down end ---------------------------------------------- if tl.state == "firing" then if g_KeyPressE == 1 then if visibility == 1 then Hide(e) tl.state = "return" end end ---------------------------------------------- if tl.state == "firing" then if g_MouseClick == 1 then --returns to player on LMB click while in 'firing' tl.state = 'return' end end end ---------------------------------------------- 'R' keypress drops entity if not visible then shows when dropping. if tl.state == "firing" then if visibility == 0 then if g_KeyPressR == 1 then tl.state = "wait pick up" Show(e) end end end if (GetGamePlayerControlJumpmax() < 530) then SetGamePlayerControlJumpmax(530) --change max jump height for "fired" state. Default is 215 end --#2 ----------------------------------------------- Hide/Show with scrollwheel while in the "firing" state if mouseWheel > 0 then Show(e) -- Show the entity when scrolling up elseif mouseWheel < 0 then Hide(e) -- Hide the entity when scrolling down end ----------------------------------------------- Hide with 'E' keypress and pickup another if tl.state == "firing" then if g_KeyPressE == 1 then if visibility == 1 then Hide(e) tl.state = "return" end end end ----------------------------------------------- 'R' keypress drops entity if hidden then shows when dropping. if tl.state == "firing" then if visibility == 0 then if g_KeyPressR == 1 then tl.state = "wait pick up" Show(e) end end end ----------------------------------------------- -- see if we've hit anything if colList ~= nil then for i, v in ipairs( colList ) do if v.obj ~= 0 then tl.state = "hit" tl.timer = timeNow + 3000 tl.hit = { x = v.x, y = v.y, z = v.z } -- we hit an entity so check the angle (not perfect as it just uses origin points but it should be ok) local tray = IntersectAll(Ent.x, Ent.y+2, Ent.z, v.x, v.y - 5, v.z, Ent.obj) if tray == nil then tray = -1 end --PromptDuration("x1 : "..Ent.x.." x2 : "..v.x.." , y1 : "..Ent.y.." y2 : "..v.y.." , z1 : "..Ent.z.." , z2 : "..v.z.." , tray = "..tray,4000) if tray > 0 then tl.nx = GetIntersectCollisionNX() tl.ny = GetIntersectCollisionNY() tl.nz = GetIntersectCollisionNZ() -- compare the hit normal to the world up local v1 = V.Create(tl.nx,tl.ny,tl.nz) v1 = V.Norm(v1) tl.nx = v1.x tl.ny = v1.y tl.nz = v1.z local v2 = V.Create(0,1,0) local vDot = V.Dot(v1,v2) PromptDuration("nx : "..tl.nx.." , ny : "..tl.ny.." , nz : "..tl.nz.." , dot = "..vDot,5000) -- dot product returns -1 = directly behind, + 1 = directly in front if vDot > 0.3 then tl.hitobj = v.obj tl.validloc = true end end RemoveObjectCollisionCheck( Ent.obj ) break end end end ---------------------------- ---------------------------- -- terrain is a valid location if tl.state ~= "hit" then --Prompt( GetTerrainNumCollisions( Ent.obj ) ) colList = P.GetTerrainCollisionDetails( Ent.obj ) if colList ~= nil then PromptDuration( "Terrain Hit!", 2000 ) for _, v in ipairs( colList ) do if v.x ~= 0 then tl.state = "hit" tl.timer = timeNow + 3000 tl.hit = { x = v.x, y = v.y, z = v.z } tl.hitobj = 0 tl.validloc = true RemoveObjectCollisionCheck( Ent.obj ) break end end end end if tl.state == "hit" then if (GetGamePlayerControlJumpmax() >215) then SetGamePlayerControlJumpmax(215) --reset max jump height for "hit" state end CollisionOff( e ) PositionObject( Ent.obj, tl.hit.x, tl.hit.y, tl.hit.z ) RotateObject( Ent.obj, g_PlayerAngX, g_PlayerAngY, g_PlayerAngZ ) -- if not considered a valid location we should return the grapple to the player? if not tl.validloc then tl.state = "return" return end elseif GetTimer( e ) > n_max_time then tl.state = "return" end elseif tl.state == 'hit' then -------------------------------------------- if g_MouseClick == 1 then --returns entity to player on LMB click tl.state = 'return' end --------------------------------------------- local ppx, ppy, ppz = g_PlayerPosX, g_PlayerPosY, g_PlayerPosZ local pox, poy, poz =( tl.hit.x - ppx ) * move_speed, ( tl.hit.y - ppy ) * move_speed, ( tl.hit.z - ppz ) * move_speed ppx, ppy, ppz = findClearPos( ppx + pox, ppy + poy, ppz + poz, tl.hitobj ) SetFreezePosition( ppx, ppy, ppz ) if g_MouseClick == 2 then TransportToFreezePositionOnly() if U.PlayerCloserThanPos( tl.hit.x, tl.hit.y, tl.hit.z, 100 ) or timeNow > tl.timer then tl.state = "holding" end end elseif tl.state == "return" then if (GetGamePlayerControlJumpmax() >215) then SetGamePlayerControlJumpmax(215) --reset default jump height for "return" state end if not U.PlayerCloserThan( e, 170 ) then local x, y, z, xa, ya, za = GetEntityPosAng( e ) local ppx, ppy, ppz = getPlayerEyePos() local nox, noy, noz = ( ppx - x ) * returnSpeed, ( ppy - y ) * returnSpeed, ( ppz - z ) * returnSpeed -- move and rotate the entity local quat = Q.FromEuler( rad( xa ), rad( ya ), rad( za ) ) local rotquat = Q.FromEuler( 0, rad( rotSpeed * tDiff ), 0 ) xa, ya, za = Q.ToEuler( Q.Mul( quat, rotquat ) ) CollisionOff( e ) RotateObject( Ent.obj, deg( xa ), deg( ya ), deg( za )) PositionObject( Ent.obj, x + nox, y + noy, z + noz ) CollisionOn( e ) else tl.state = "holding" end end --Prompt(tl.state.." visible = "..visibility) end