Results 1 to 4 of 4

Thread: onChat Unknown Script Error

  1. #1

    onChat Unknown Script Error

    I am currently writing a camera manipulation script that is to be used for cut-scene like elements within a D&D map. I have the code (mostly) working, however it appears when a cutscene is triggered by a chat command, the next one I attempt to trigger during this testing causes the following:
    Code:
    Error in Script (Script Card - ccc270) function <onChat>: Unknown Error
    I'm not entirely sure why this is happening, and after fiddling with the code to see why this may be the case, I cannot find a solution or the cause for it or any topics here or on the steam discussions with similar function problems. Any and all help is much appreciated to this problem and I hope it's something I'm easily overlooking.

    To replicate: Paste below script onto a notecard, become player Black and use the command "!cs1" to start the camera manipulation for the cutscene, once it has finished (an additional lookAt should change camera perspective to indicate its over) try using !cs1 or !cs2 to trigger the same/next cutscene and the error will have happened.

    The entire script, attached to a notecard, is as follows:

    Code:
    local cameraObj = "" -- Previously used: camera object GUID. Will need to edit lockCamera() to no longer use this at a later date
    local camObj = nil -- Camera Object variable
    local camID = 0 -- To hold for future possible uses the Wait.time assigned ID
    
    -- ---------------------------------
    -- Chat Command Handling
    -- ---------------------------------
    function onChat(msg, sender)
        if sender.color == "Black" then
            if msg == "!lock" then -- Manually Lock Player Cameras
                lockCamera()
                return false
            elseif msg == "!unlock" then -- Manually Unlock Player Cameras
                unlockCamera()
                return false
            elseif msg == "!cs1" then -- Start Scene Command
                startScene()
                return false
            elseif msg == "!cs2" then -- Portal Scene Command
                portalScene()
                return false
            elseif contains(msg, "!tcam ") then -- Test command: determining proper yaw/pitch values for initial camera lookAt
                local tbl = {}
                local i = 1
                for str in string.gmatch(msg, "([^%s]+)") do
                    tbl[i] = str
                    i = i + 1
                end
                log("Yaw: " .. tbl[2] .. ", Pitch: " .. tbl[3], "Detected Values")
                local yawV = tonumber(tbl[2])
                local pitchV = tonumber(tbl[3])
                Player["Black"].lookAt({
                    position = {0, 1, 0},
                    pitch    = pitchV,
                    yaw      = yawV,
                    distance = 15,
                })
                return false
            end
        end
    end
    
    -- ---------------------------------
    -- Individual Scene Portions
    -- ---------------------------------
    
    -- Start Scene: Beginning of Map
    function startScene()
        if cObj then destroyPreviousCam() end
        cObj = spawnObject({
            type              = "BlockSquare",
            position          = {-3.62, 1, 82.21},
            rotation          = {0, 0, 0},
            scale             = {0.25, 0.25, 0.25},
            sound             = false,
            snap_to_grid      = false,
            callback_function = startSceneCam,
        })
    end
    
    function startSceneCam(o, n, c)
        camObj = o
        o.setLock(true)
        o.setPosition({-3.62, 1, 82.21})
        o.interactable = false
        o.setScale({0,0,0})
    
        aP = Player.getPlayers()
        for _, p in ipairs(aP) do
    
            p.attachCameraToObject({
                object = o,
                offset = {0, 10, 0},
            })
            p.lookAt({
                position = o.getPosition(),
                pitch = 90,
                yaw = 180,
                distance = 10,
            })
        end
    
        camID = Wait.time(function()
            moveCam({{-3.62, 1, 82.21}, -- Locations to move camera object to
                     {-2.6, 1, 75.47},
                     {9.04, 1, 71.46},
                     {18.41, 1, 72.05},
                    }, 1, 0, 0, 0,
                    nil, nil
                    ) -- Beginning Index, dx, dy, dz
            end, 5) -- Amount of time to intially wait
    end
    
    -- Portal Scene: To happen when players first begin entry into dungeon
    function portalScene()
        if cObj then destroyPreviousCam() end
        cObj = spawnObject({
            type              = "BlockSquare",
            position          = {26.49, 1, 64.47},
            rotation          = {0, 0, 0},
            scale             = {0.25, 0.25, 0.25},
            sound             = false,
            snap_to_grid      = false,
            callback_function = portalSceneCam,
        })
    end
    
    function portalSceneCam(o, n, c    )
        camObj = o
        o.setLock(true)
        o.setPosition({26.49, 1, 64.47})
        o.interactable = false
        o.setScale({0,0,0})
    
        aP = Player.getPlayers()
        for _, p in ipairs(aP) do
    
            p.attachCameraToObject({
                object = o,
                offset = {0, 10, 0},
            })
            p.lookAt({
                position = o.getPosition(),
                pitch = 90,
                yaw = 180,
                distance = 10,
            })
        end
    
        camID = Wait.time(function()
            moveCam({{26.49, 1, 64.47}, -- Locations to move camera object to
                     {24.57, 1, 54.51},
                     {17.64, 1, 53.46},
                     {12.02, 1, 52.53},
                    }, 1, 0, 0, 0, -- Beginning Index, dx, dy, dz
                    potalSceneHandler, {0, 0, 0, 1} -- Handler function to call and associated table
                    )
            end, 5) -- Amount of time to intially wait
    end
    
    function portalSceneHandler(idx)
     -- To be filled out later for additional effects based on current table index number, called by moveCam()
    end
    -- ---------------------------------
    -- END SCENE CODE
    -- ---------------------------------
    
    
    
    -- ---------------------------------
    -- Camera Manipulation Code
    -- ---------------------------------
    function destroyPreviousCam()
        if camObj then
            camObj.destruct()
        end
    end
    
    function lockCamera()
        aP = Player.getPlayers()
        for _, p in ipairs(aP) do
            p.attachCameraToObject({object=getObjectFromGUID(cameraObj)})
        end
    end
    
    function unlockCamera()
        aP = Player.getPlayers()
        for _, p in ipairs(aP) do
            p.lookAt({
                position = camObj.getPosition(),
                pitch = 180,
                yaw = 90,
                distance = 15,
    
            })
        end
        camObj.destruct()
    end
    
    function moveCam(locs, idx, dx, dy, dz, call_func, call_tbl)
        log("moveCam Started")
        l = camObj.getPosition() -- Current Cam Position
        l2 = locs[idx]           -- Current Location Target
        
        log("Moving camera object position")
        log("{" .. dx .. ", " .. dy .. ", " .. dz .. "}", "DVals")
        tLoc = {l[1] + dx, l[2] + dy, l[3] + dz} -- Target Location Table
        
        -- Target Location Table Clamping
        tLoc[1] = dx > 0 and math.min(tLoc[1], l2[1]) or dx < 0 and math.max(tLoc[1], l2[1]) or tLoc[1]
        tLoc[2] = dy > 0 and math.min(tLoc[2], l2[2]) or dy < 0 and math.max(tLoc[2], l2[2]) or tLoc[2]
        tLoc[3] = dz > 0 and math.min(tLoc[3], l2[3]) or dz < 0 and math.max(tLoc[3], l2[3]) or tLoc[3]
    	
    	-- Round both target and current location values to hundredths
    	rl = {round(l[1], 2), round(l[2], 2), round(l[3], 2)}
    	rl2 = {round(l2[1], 2), round(l2[2], 2), round(l2[3], 2)}
    
        log("Checking for location identicalness")
        log(rl[1] .. " ? " .. rl2[1] .. "\n" .. rl[2] .. " ? " .. rl2[2] .. "\n" .. rl[3] .. " ? " .. rl2[3] .. "\n" .. idx .. " ? " .. #locs, "Rounded Vals")
        if rl[1] == rl2[1] and rl[2] == rl2[2] and rl[3] == rl2[3] and idx ~= #locs then -- We are moving into next spot
            log("location identicalness confirmed")
            idx = idx + 1
            l2 = locs[idx] -- Update second location info with location table
    
            dx = (l2[1] - l[1]) / 60
            dy = (l2[2] - l[2]) / 60
            dz = (l2[3] - l[3]) / 60
        end
        
        log("{" .. tLoc[1] .. ", " .. tLoc[2] .. ", " .. tLoc[3] .. "}", "Post-Clamped Values")
    
        -- Set camera position
        camObj.setPositionSmooth(tLoc, false, false)
        
        -- Call associated function, if set
        if call_func ~= nil then
            if call_tbl[idx] then
                call_func(idx)
            end
        end
    
        -- Progress to next camera shot
        log("Checking if we're at last index")
        if idx >= #locs and tLoc[3] == l2[3] and tLoc[2] == l2[2] and tLoc[1] == l2[1] then
            log("We were")
            unlockCamera()
        else
            log("We were not")
            Wait.time(function() moveCam(locs, idx, dx, dy, dz, call_func, call_tbl) end, 0.1)
        end
    end
    -- ---------------------------------
    -- END CAM MANIPULATION
    -- ---------------------------------
    
    
    -- ---------------------------------
    -- Helper Functions
    -- ---------------------------------
    function round(num, decs)
        local mult = 10^(decs or 0)
        return math.floor(num * mult + 0.5) / mult
    end
    
    function contains(haystack, needle)
        if string.find(haystack, needle) then return true else return false end
    end



    As an aside: I am a programmer, of multiple years using a large amount of languages (C to VB6 to .NET [all] to HTML, PHP, Ms/MySQL) and am not new to programming at all. So reference links, documentation, etc is welcomed as valid solutions. And some of the code is a bit messy in terms of what it does, it'll be cleaned up once it's out of these initial testing phases.

    As another aside: I also have had problems with the camera manipulation portion not 100% consistently going to the location and clamping onto it and it sometimes gets stuck within 0.01 of the destination value even though dx/dy/dz should put it below/over it (depending on dx/dy/dz <> 0) but this may just be a mathematical error on my part or something I'm overlooking, even if it does work most of the time the identical code is executed. But this problem I'm not necessarily looking for help on, but if you happen to see why this may be the case while giving an answer to my initial problem then I won't complain at all.
    Last edited by Kalbintion; 01-09-2019 at 10:32 PM. Reason: Marking prefix for solved

  2. #2
    My above issue has been resolved after having spent the last 4 hours messing around with the script again. For those who are wondering:

    The Unknown Script Error seems to stem from having the camObj.destruct() located in the unlockCamera() and destroyPreviousCam() function. Not having set the variable back to nil after destruction caused the next calls checking if it exists previously (as if a cam was interrupted or failed to delete from an interrupted cutscene) was causing this unknown error and why it was falling back to onChat event as that was the overall handler for the script but was not the actual culprit. If I had to guess internally, it was through a null value error back in a way it doesn't have handled properly for displaying as an error message on where it was actually located. Could be a pointer problem on the variable itself.

    This error can be seen again through an alternative method by using the event onPlayerTurn() and the following code and triggering the player turns (by turning them off/on for example) giving the error as a result from the onPlayerTurn function rather than onChat.

    Code:
    function onPlayerTurn(color)
    onChat("!cs1", Player["Black"])
    end



    TLDR: the Object.destruct() function, when used through a variable, does not set the variable to nil. Not manually doing this after calling destruct() and when checking if the object exists through if variable then variable.doSomething, an Unknown Script Error appears to happen.
    Last edited by Kalbintion; 01-09-2019 at 10:42 PM. Reason: Additional info

  3. #3
    After you destroy an object, it's ref will compare to nil. See here: https://www.reddit.com/r/tabletopsim...le_is/ec2lckg/

  4. #4
    hi mate im french, who can help me plz i would like ti replace uk card by fr card on starwars legion on the script. i dont arrive. can you add me at m.g.concept38160@gmail.com

    thx u very much mate

Similar Threads

  1. help script error
    By sejo in forum Scripting
    Replies: 1
    Last Post: 08-23-2018, 05:28 AM
  2. [SUPPORT] Unknown banned
    By LdK1 in forum Technical Support
    Replies: 4
    Last Post: 07-23-2018, 09:27 AM
  3. Replies: 0
    Last Post: 09-05-2017, 06:10 AM
  4. Replies: 12
    Last Post: 09-03-2017, 11:14 AM
  5. [SOLVED] error in this script (object facing the camera)
    By Bobsen in forum Scripting
    Replies: 2
    Last Post: 02-19-2017, 03:31 PM

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •