Jump to content

[HELP]Interiors


BluntZ

Recommended Posts

Client_Anim

--STOLED FROM ARC_ LUL 
--[[ 
    Anim queue: list of animation specifications that have to complete their animation one after the other 
    Anim: an element (GUI, player, vehicle...) and a list of phases 
    Anim phase: a list of parameters with start/end value, time, eventually a transformation function, 
        and a function that applies the parameter to the element. May also have an attribute setting number 
        of repeats (0 = infinite). 
--]] 
  
Animation = {} 
Animation.__index = Animation 
  
Animation.collection = {} 
  
function Animation.create(elem, ...) 
    local anim = setmetatable({ type = 'anim', elem = elem, phases = {...} }, Animation) 
    for i,phase in ipairs(anim.phases) do 
        if type(phase) == 'table' then 
            phase.from = phase.from or 0 
            phase.to = phase.to or 1 
            phase.time = phase.time or 0 
            phase.value = phase.from 
            phase.speed = phase.time > 0 and ((phase.to - phase.from) / phase.time) or 0 
        end 
    end 
    return anim 
end 
  
function Animation.createAndPlay(elem, ...) 
    local anim = Animation.create(elem, ...) 
    anim:play() 
    return anim 
end 
  
function Animation.createQueue(...) 
    local queue = setmetatable({ type = 'queue' }, Animation) 
    local args = { ... } 
    if type(args[1]) == 'string' then 
        queue.name = table.remove(args, 1) 
    end 
    for i,obj in ipairs(args) do 
        queue:add(obj) 
    end 
    return queue 
end 
  
function Animation.createQueueAndPlay(...) 
    local queue = Animation.createQueue(...) 
    queue:play() 
    return queue 
end 
  
function Animation.getQueue(name) 
    for i,obj in ipairs(Animation.collection) do 
        if obj:isQueue() and obj.name == name then 
            return obj 
        end 
    end 
    return false 
end 
  
function Animation.getOrCreateQueue(name) 
    local queue = Animation.getQueue(name) 
    if not queue then 
        queue = Animation.createQueue(name) 
    end 
    return queue 
end 
  
function Animation:isPlaying() 
    return self.playing or false 
end 
  
function Animation.playingAnimationsExist() 
    return table.find(Animation.collection, 'playing', true) and true 
end 
  
function Animation:add(anim) 
    if self:isQueue() then 
        if type(anim) == 'function' then 
            anim = setmetatable({ type = 'function', fn = anim }, Animation) 
        end 
        anim.queue = self 
        table.insert(self, anim) 
    end 
end 
  
function Animation:remove() 
    if self.queue then 
        table.removevalue(self.queue, self) 
        if #self.queue == 0 then 
            self.queue:remove() 
        end 
    else 
        table.removevalue(Animation.collection, self) 
        if not Animation.playingAnimationsExist() then 
            removeEventHandler('onClientRender', getRootElement(), updateAnim) 
            Animation.prevTick = nil 
        end 
    end 
    self.playing = false 
end 
  
function Animation:isAnimation() 
    return self.type == 'anim' 
end 
  
function Animation:isQueue() 
    return self.type == 'queue' 
end 
  
function Animation:play() 
    if self:isPlaying() then 
        return 
    end 
    if not table.find(Animation.collection, self) then 
        table.insert(Animation.collection, self) 
    end 
    if not Animation.playingAnimationsExist() then 
        Animation.prevTick = getTickCount() 
        addEventHandler('onClientRender', getRootElement(), updateAnim) 
    end 
    self.playing = true 
end 
  
function Animation:pause() 
    self.playing = false 
    if not Animation.playingAnimationsExist() then 
        removeEventHandler('onClientRender', getRootElement(), updateAnim) 
        Animation.prevTick = nil 
    end 
end 
  
function updateAnim() 
    local phase 
    local curTick = getTickCount() 
     
    for i,obj in ipairs(Animation.collection) do 
        if not isElement(obj.elem) then 
            obj:remove() 
        end 
        if obj.playing then 
            if obj:isQueue() then 
                obj = obj[1] 
            end 
            phase = obj.phases[1] 
            if (type(phase) == 'function') 
              or (phase.speed > 0 and phase.value >= phase.to) 
              or (phase.speed < 0 and phase.value <= phase.to) 
              or (phase.speed == 0) then 
                local doRemove = true 
                if type(phase) == 'function' then 
                    phase(obj.elem) 
                elseif phase.repeats then 
                    if phase.repeats == 0 then 
                        doRemove = false 
                    else 
                        phase.repeats = phase.repeats - 1 
                        doRemove = phase.repeats == 0 
                    end 
                    phase.starttick = getTickCount() 
                    phase.value = phase.from 
                end 
                if doRemove then 
                    table.remove(obj.phases, 1) 
                    phase = false 
                    if #obj.phases == 0 then 
                        obj:remove() 
                        obj = false 
                    end 
                end 
            end 
            if obj and phase then 
                if phase.fn then 
                    phase.fn(obj.elem, phase.transform and phase.transform(phase.value) or phase.value, phase) 
                end 
                if not phase.starttick then 
                    phase.starttick = curTick 
                end 
                phase.value = phase.from + phase.speed*(curTick - phase.starttick) 
            end 
        end 
    end 
end 
  
Animation.presets = {} 
  
function Animation.presets.pulse(elem, value, phase) 
    if not value then 
        return { from = 0, to = 2*math.pi, transform = math.sin, time = elem, repeats = 0, fn = Animation.presets.pulse } 
    else 
        if not phase.width then 
            phase.width, phase.height = guiGetSize(elem, false) 
            phase.centerX, phase.centerY = guiGetPosition(elem, false) 
            phase.centerX = phase.centerX + math.floor(phase.width/2) 
            phase.centerY = phase.centerY + math.floor(phase.height/2) 
        end 
        local pct = 1 - (value+1)*0.1 
        local width = pct*phase.width 
        local height = pct*phase.height 
        local x = phase.centerX - math.floor(width/2) 
        local y = phase.centerY - math.floor(height/2) 
        guiSetPosition(elem, x, y, false) 
        guiSetSize(elem, width, height, false) 
    end 
end 
  
function table.removevalue(t, val) 
    for i,v in ipairs(t) do 
        if v == val then 
            table.remove(t, i) 
            return i 
        end 
    end 
    return false 
end 
  
function table.find(tableToSearch, index, value) 
    if not value then 
        value = index 
        index = false 
    elseif value == '[nil]' then 
        value = nil 
    end 
    for k,v in pairs(tableToSearch) do 
        if index then 
            if v[index] == value then 
                return k 
            end 
        elseif v == value then 
            return k 
        end 
    end 
    return false 
end 

Interiors_client

local interiorAnims = {} 
local setInteriorMarkerZ = {
    interiorEntry = function(marker,z)
        local interiorElement = getElementParent(marker)
        local vx = getElementData ( interiorElement,"posX" )
        local vy = getElementData ( interiorElement,"posY" )
        local vz = getElementData ( interiorElement,"posZ" )
        --
        setElementPosition(marker, vx, vy, vz + z/2 + 2.4)
    end,
    interiorReturn = function(marker,z)
        local interiorElement = getElementParent(marker)
        local vx = getElementData ( interiorElement,"posX" )
        local vy = getElementData ( interiorElement,"posY" )
        local vz = getElementData ( interiorElement,"posZ" )
        --
        setElementPosition(marker, vx, vy, vz + z/2 + 2.4) 
    end
}
 
-- addEventHandler("onClientElementStreamIn",getRootElement(),
    -- function()
        -- if getElementType ( source ) == "marker" then
            -- local parent = getElementParent ( source )
            -- local parentType = getElementType(parent)
            -- if parentType == "interiorEntry" or parentType == "interiorReturn" then
                -- interiorAnims[source] = Animation.createAndPlay(
        -- source,
        -- { from = 0, to = 2*math.pi, time = 2000, repeats = 0, transform = math.sin, fn = setInteriorMarkerZ[parentType] }
-- )
            -- end
        -- end
    -- end
-- )
 
-- addEventHandler("onClientElementStreamOut",getRootElement(),
    -- function()
        -- if getElementType ( source ) == "marker" then
            -- local parent = getElementParent ( source )
            -- local parentType = getElementType(parent)
            -- if parentType == "interiorEntry" or parentType == "interiorReturn" then
                -- if (interiorAnims[source] ) then
                    -- interiorAnims[source]:remove()
                -- end
            -- end
        -- end
    -- end
-- )
 
----Main
local interiors = {}
local interiorCols = {}
local interiorFromCol = {}
local resourceFromInterior = {}
local blockPlayer
addEvent ( "doWarpPlayerToInterior", true )
addEvent ( "onClientInteriorHit" )
addEvent ( "onClientInteriorWarped" )
 
addEventHandler ( "onClientResourceStart", getRootElement(),
function ( resource )
    interiorLoadElements ( getResourceRootElement(resource), resource )
    interiorCreateMarkers ( resource )
end )
 
addEventHandler ( "onClientResourceStop", getRootElement(),
function ( resource )
    if not interiors[resource] then return end
    for id,interiorTable in pairs(interiors[resource]) do
        local interior1 = interiorTable["entry"]
        local interior2 = interiorTable["return"]
        destroyElement ( interiorCols[interior1] )
        destroyElement ( interiorCols[interior2] )
    end
    interiors[resource] = nil
end )
 
function interiorLoadElements ( rootElement, resource )
    ---Load the exterior markers
    local entryInteriors = getElementsByType ( "interiorEntry", rootElement )
    for key, interior in pairs (entryInteriors) do
        local id = getElementData ( interior, "id" )
        if not interiors[resource] then interiors[resource] = {} end
        if not id then outputDebugString ( "Interiors: Error, no ID specified on entryInterior.  Trying to load anyway.", 2 )
        end
        interiors[resource][id] = {}
        interiors[resource][id]["entry"] = interior
        resourceFromInterior[interior] = resource
    end
    --Load the interior markers
    local returnInteriors = getElementsByType ( "interiorReturn", rootElement )
    for key, interior in pairs (returnInteriors) do
        local id = getElementData ( interior, "refid" )
        if not interiors[resource][id] then outputDebugString ( "Interiors: Error, no refid specified to returnInterior.", 1 )
            return
        else
            interiors[resource][id]["return"] = interior
            resourceFromInterior[interior] = resource
        end
    end
end
 
imgW = 150
imgH = 150
local sX, sY = guiGetScreenSize()
intIcons = {}
 
function drawIntLogo()
    if not intIcons then
        return
    end
    for k, v in ipairs(intIcons) do
        local hX, hY, hZ = unpack(v)
        local cX, cY, cZ = getCameraMatrix()
        local pX,pY,pZ = getPedBonePosition(localPlayer, -- s8) -->
        pZ = pZ + 0.5
        if getScreenFromWorldPosition(hX, hY, hZ) and isLineOfSightClear(cX,cY,cZ + 0.5, hX,hY,hZ) then
            if getDistanceBetweenPoints3D ( cX,cY,cZ + 0.5, hX,hY,hZ ) < 35 then
                local sX, sY, sD = getScreenFromWorldPosition(hX, hY, hZ)
                local relative = (35 - sD) / 35
                if relative > 0 then
                    local iW = imgW * relative
                    local iH = imgH * relative
                    local iX = sX - (iW / 2)
                    local iY = sY - (iH / 2)
                    dxDrawImage(iX, iY, iW, iH, "door.png")
                end
            end
        end
    end
end
addEventHandler("onClientRender", root, drawIntLogo)
 
function interiorCreateMarkers ( resource )
    if not interiors[resource] then return end
    for interiorID, interiorTypeTable in pairs(interiors[resource]) do
        local entryInterior = interiorTypeTable["entry"]
        local entX,entY,entZ = getElementData ( entryInterior, "posX" ),getElementData ( entryInterior, "posY" ),getElementData ( entryInterior, "posZ" )
        entX,entY,entZ = tonumber(entX),tonumber(entY),tonumber(entZ)
        table.insert(intIcons, {entX, entY, entZ + 1.2})
        local col = createColSphere ( entX, entY, entZ, 1.5 )
        setElementParent ( col, entryInterior )
        interiorCols[entryInterior] = col
        interiorFromCol[col] = entryInterior
        addEventHandler ( "onClientColShapeHit", col, colshapeHit )
        --
        local dimension = tonumber(getElementData ( entryInterior, "dimension" ))
        local interior = tonumber(getElementData ( entryInterior, "interior" ))
        if not dimension then dimension = 0 end
        if not interior then interior = 0 end
        --
        setElementInterior ( col, interior )
        setElementDimension ( col, dimension )
        ---create return markers
        local returnInterior = interiorTypeTable["return"]
        local retX,retY,retZ = getElementData ( returnInterior, "posX" ),getElementData ( returnInterior, "posY" ),getElementData ( returnInterior, "posZ" )
        retX,retY,retZ = tonumber(retX),tonumber(retY),tonumber(retZ)      
        --
        local oneway = getElementData ( entryInterior, "oneway" )
        if oneway == "true" then return end
        --
        table.insert(intIcons, {retX, retY, retZ + 1.2})
        local col1 = createColSphere ( retX, retY, retZ, 1.5 )
        interiorFromCol[col1] = returnInterior
        interiorCols[returnInterior] = col1
        setElementParent ( col1, returnInterior )
        addEventHandler ( "onClientColShapeHit", col1, colshapeHit )
        --
        local dimension1 = tonumber(getElementData ( returnInterior, "dimension" ))
        local interior1 = tonumber(getElementData ( returnInterior, "interior" ))
        if not dimension1 then dimension1 = 0 end
        if not interior1 then interior1 = 0 end
        --
        setElementInterior ( col1, interior1 )
        setElementDimension ( col1, dimension1 )
    end
end
 
function getInteriorMarker ( elementInterior )
    if not isElement ( elementInterior ) then outputDebugString("getInteriorName: Invalid variable specified as interior.  Element expected, got "..type(elementInterior)..".",0,255,128,0) return false end
    local elemType = getElementType ( elementInterior )
    if elemType == "interiorEntry" or elemType == "interiorReturn" then
        return interiorMarkers[elementInterior] or false
    end
    outputDebugString("getInteriorName: Bad element specified.  Interior expected, got "..elemType..".",0,255,128,0)
    return false
end
 
local opposite = { ["interiorReturn"] = "entry",["interiorEntry"] = "return" }
local idLoc = { ["interiorReturn"] = "refid",["interiorEntry"] = "id" }
function colshapeHit( player, matchingDimension )
    if not isElement ( player ) or getElementType ( player ) ~= "player" then return end
    if player ~= localPlayer then return end
    if ( not matchingDimension ) or ( isPedInVehicle ( player ) ) or
    ( doesPedHaveJetPack ( player ) ) or ( not isPedOnGround ( player ) ) or
    ( getControlState ( "aim_weapon" ) ) or ( blockPlayer )
    then return end
    local interior = interiorFromCol[source]
    local id = getElementData ( interior, idLoc[getElementType(interior)] )
    local resource = resourceFromInterior[interior]
    eventCanceled = triggerEvent ( "onClientInteriorHit", interior )
    if ( eventCanceled ) then
        triggerServerEvent ( "doTriggerServerEvents", localPlayer, interior, getResourceName(resource), id )
    end
end
 
addEventHandler ( "doWarpPlayerToInterior",localPlayer,
    function ( interior, resource, id )
        resource = getResourceFromName(resource)
        local oppositeType = opposite[getElementType(interior)]
        local targetInterior = interiors[resource][id][oppositeType]
       
        local x = getElementData ( targetInterior, "posX" )
        local y = getElementData ( targetInterior, "posY" )
        local z = getElementData ( targetInterior, "posZ" ) + 1
        local dim = getElementData ( targetInterior, "dimension" )
        local int = getElementData ( targetInterior, "interior" )
        local rot = getElementData ( targetInterior, "rotation" )
        toggleAllControls ( false, true, false )
        fadeCamera ( false, 1.0 )
        setTimer ( setPlayerInsideInterior, 1000, 1, source, int,dim,rot,x,y,z, interior )
        blockPlayer = true
        setTimer ( function() blockPlayer = nil end, 3500, 1 )
    end
)
 
function setPlayerInsideInterior ( player, int,dim,rot,x,y,z, interior )
    setElementInterior ( player, int )
    setCameraInterior ( int )
    setElementDimension ( player, dim )
    setPedRotation ( player, rot%360 )
    setTimer ( function(p) if isElement(p) then setCameraTarget(p) end end, 200,1, player )
    setElementPosition ( player, x, y, z )
    toggleAllControls ( true, true, false )
    setTimer ( fadeCamera, 500, 1, true, 1.0 )
    triggerEvent ( "onClientInteriorWarped", interior )
    triggerServerEvent ( "onInteriorWarped", interior, player )
    triggerServerEvent ( "onPlayerInteriorWarped", player, interior )
end
 
function getInteriorName ( interior )
    if not isElement ( interior ) then outputDebugString("getInteriorName: Invalid variable specified as interior.  Element expected, got "..type(interior)..".",0,255,128,0) return false end
    local elemType = getElementType ( interior )
    if elemType == "interiorEntry" then
        return getElementData ( interior, "id" )
    elseif elemType == "interiorReturn" then
        return getElementData ( interior, "refid" )
    else
        outputDebugString("getInteriorName: Bad element specified.  Interior expected, got "..elemType..".",0,255,128,0)
        return false
    end
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...