I got a script from a post that was started by 'gubbyBlips', Smallg, and Amen Moses about a grappling gun. I just took that and added to it for my needs. I've made it into a UT99 translocater and it works just like it.
1-LMB throws it
2-RMB travels to it
3-Scrollwheel hides it and shows it. I did this so that you can hold 2 items with only one being usable and only the visible one functions.
4-'E' hides it and picks up another so that only one is visible at a time therefore only one works
5-'R' drops the hidden object then shows it on the ground. It can be pick-up again
here is the script
-- DESCRIPTION: transloc wip
local U = require "scriptbank\\utillib"
local Q = require "scriptbank\\quatlib"
local P = require "scriptbank\\physlib"
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 tppEnt = GetGamePlayerControlThirdpersonCharactere()
function transloc_init_name( e, name )
Include( "utillib.lua" )
Include( "quatlib.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 )
if tppEnt ~= nil and tppEnt ~= 0 and tppObj == 0 then
tppObj = g_Entity[ tppEnt ].obj
end
local ny = y
local found = false
local numChecks = 0
while not found and numChecks < 100 do
local obhit = IntersectAll( x, ny, z, x, ny + 50, z, tppObj ) or 0
if obhit == 0 then
found = true
else
ny = ny + 10
numChecks = numChecks + 1
end
end
ny = max( ny, GetTerrainHeight( x, z ) + 50 )
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)
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 and not epressed then
epressed = true
tl.state = "picking"
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 < 0 then
Show(e) -- Show the entity when scrolling up
elseif mouseWheel > 0 then
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
visibility == 1 then
Hide(e)
end
end
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"
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.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 }
RemoveObjectCollisionCheck( Ent.obj )
break
end
end
end
----------------------------
----------------------------
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 }
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 )
RotateObject( Ent.obj, g_PlayerAngX, g_PlayerAngY, g_PlayerAngZ )
PositionObject( Ent.obj, tl.hit.x, tl.hit.y, tl.hit.z )
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 GetTerrainHeight(x,z)
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 )
SetFreezePosition( ppx, ppy, ppz )
TransportToFreezePositionOnly()
if U.PlayerCloserThanPos( tl.hit.x, tl.hit.y, tl.hit.z, 100 ) or
timeNow > tl.timer then
tl.state = "holding"
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
end
I use either a 'proximty mine or a landmine for this as it's a disc like the transloc.
The problem lies in the 'goto' part of it. Being from a 'grapplinghook' script it wants to pull you to it as soon as it hits something which is fine for the hook. I can evade this by inserting 'g_MouseClick==2' before or after the 'setfreezeposition'. This way it won't pull you until you press RMB. What's happening though is that it sticks to everything, walls, terrain, upside down platforms, etc.... I want it to only 'stick' to the terrain or the 'topside' of a flat object. All else it should fall from or bounce off of. This works fine for UT99 but that old Unrealscript is difficult to read to find out where that's being conveyed, or how. If someone could tell me how to do this it would be greatly appreciated.
here is the downloadable script