local U = require "scriptbank\\utillib" local Q = require "scriptbank\\quatlib" local P = require "scriptbank\\physlib" local rad = math.rad local deg = math.deg local floor = math.floor local atan = math.atan2 local abs = math.abs local sqrt = math.sqrt state = {} local thisID = 0 portal = {} epressed = 0 local otherPortal = {} local thisID = 0 local portalUsed = {} local placedPortal = 0 local cportal = 0 local portedRecently = {} local portalVisible = {} local portal_direction = 2 --set to 2 for travel in either portal otherwise only first portal will work function portal_gun_init(e) state[e] = "set up" portal_gunE = e end function portal_gun_main(e) obj = g_Entity[e]['obj'] local ent = g_Entity[e] if state[e] == "set up" then local px,py,pz = GetEntityPosAng(e) for p = 1, 2 do portalVisible[p] = 0 for a,b in pairs(portals) do if portalUsed[a] == nil then local ppx,ppy,ppz = GetEntityPosAng(a) if U.CloserThan(px,py,pz,ppx,ppy,ppz,300) then portal[p] = a Hide(a) CollisionOff(a) portalUsed[a] = 1 break end end end end if portal[2] == nil then state[e] = "error" else otherPortal[1] = portal[2] otherPortal[2] = portal[1] state[e] = "wait pick" end elseif state[e] == "error" then PromptLocal(e,"No portals found, place 2 portals nearby") elseif state[e] == "wait pick" then if U.PlayerLookingAtObj( obj, 120, 0 ) then Prompt("Collect the Portal gun? (E)") if g_KeyPressE == 1 then if epressed == 0 then epressed = 1 AddPlayerWeapon(e) Hide(e) CollisionOff(e) state[e] = "wait collect" end else epressed = 0 end end elseif state[e] == "wait collect" then if g_PlayerGunID > 0 then thisID = g_PlayerGunID state[e] = "holding" placedPortal = 0 cportal = 1 end elseif state[e] == "holding" then if g_PlayerGunID == thisID then if g_projectileevent_explosion ~= 0 then if g_projectileevent_entityhit ~= 0 or strict_portals == 0 then if placedPortal == 0 then local bx,by,bz = g_projectileevent_x,g_projectileevent_y,g_projectileevent_z local pxp, pyp, pzp = g_PlayerPosX, g_PlayerPosY, g_PlayerPosZ local pxa, pya, pza = g_PlayerAngX, g_PlayerAngY, g_PlayerAngZ if GetGamePlayerStatePlayerDucking() == 0 then pyp = pyp + 31 else pyp = pyp + 10 end local playerObj = 0 rayX, rayY, rayZ = U.Rotate3D ( 0, 0, 1, rad( pxa ), rad( pya ), rad( pza ) ) local obj = IntersectAll( pxp + 20 * rayX, pyp + 20 * rayY, pzp + 20 * rayZ, bx + rayX * 30, by + rayY * 30, bz + rayZ * 30 , playerObj ) local ox, oy, oz = bx - rayX / 2, by - rayY / 2, bz - rayZ / 2 if obj and obj ~= 0 then -- don't put bullet holes on active entities local e = P.ObjectToEntity( obj ) if e and g_Entity[ e ].active == 1 then return false end --PromptDuration( obj, 3000 ) -- check all around the hit point and figure out if we find the same object -- if so calculate the angles at which to position the decal local lrayX, lrayY, lrayZ = U.Rotate3D ( 1, 0, 0, rad( pxa ), rad( pya ), rad( pza ) ) local lobj = IntersectAll( pxp - lrayX, pyp, pzp - lrayZ, bx - lrayX + rayX * 30, by + rayY * 30, bz - lrayZ + rayZ * 30, playerObj ) if lobj ~= obj then return false end local lx, ly, lz = GetIntersectCollisionX(), GetIntersectCollisionY(), GetIntersectCollisionZ() local robj = IntersectAll( pxp + lrayX, pyp, pzp + lrayZ, bx + lrayX + rayX * 30, by + rayY * 30, bz + lrayZ + rayZ * 30, playerObj ) if robj ~= obj then return false end local rx, ry, rz = GetIntersectCollisionX(), GetIntersectCollisionY(), GetIntersectCollisionZ() local urayX, urayY, urayZ = U.Rotate3D ( 0, 1, 0, rad( pxa ), rad( pya ), rad( pza ) ) local uobj = IntersectAll( pxp, pyp + urayY, pzp, bx + rayX * 30, by + urayY + rayY * 30, bz + rayZ * 30, playerObj ) if uobj ~= obj then return false end local ux, uy, uz = GetIntersectCollisionX(), GetIntersectCollisionY(), GetIntersectCollisionZ() local bobj = IntersectAll( pxp, pyp - urayY, pzp, bx + rayX * 30, by - urayY + rayY * 30, bz + rayZ * 30, playerObj ) if bobj ~= obj then return false end local bx, by, bz = GetIntersectCollisionX(), GetIntersectCollisionY(), GetIntersectCollisionZ() local ya = deg( atan( rx - lx, rz - lz ) ) - 90 local xa = deg( atan( abs( uy - by ), sqrt( ( ux - bx )^2 + ( uz - bz )^2 ) ) ) - 90 --SetPosition(portal[cportal],bx,by,bz) SetPosition(portal[cportal], ox, oy, oz) SetRotation(portal[cportal], xa, ya, 0) end --RotateToPlayer(portal[cportal]) Show(portal[cportal]) portalVisible[cportal] = 1 cportal = cportal + 1 if cportal > 2 then cportal = 1 end placedPortal = 1 g_projectileevent_explosion = 0 end end else placedPortal = 0 end end local plx,ply,plz = g_PlayerPosX, g_PlayerPosY, g_PlayerPosZ for a = 1,2 do if portalVisible[a] == 1 then local px,py,pz = GetEntityPosAng(portal[a]) if U.CloserThan(px,py,pz,plx,ply,plz,120) then PlaySoundIfSilent(portal[a],0) if portedRecently[a] == 0 then if portal_direction == 2 or a == 1 then local b = 0 if a == 1 then b = 2 else b = 1 end if portalVisible[b] == 1 then local opx,opy,opz,opax,opay,opaz = GetEntityPosAng(portal[b]) SetFreezePosition(opx,opy,opz) SetFreezeAngle(opax,opay,opaz) TransportToFreezePosition() portedRecently[a] = 1 portedRecently[b] = 1 StartTimer(portal[a]) StartTimer(portal[b]) PlaySound(portal[b],1) end end end elseif GetTimer(portal[a]) > 50 then portedRecently[a] = 0 end end end end --Text(1,1,3,state[e].." , "..g_projectileevent_explosion) end