blingtron = CreateBlingtron() Wait(1) blingtron:BroadcastText(BroadcastType.Say, 133215) Wait(1) Wait(1) RideVehicleActor(blingtron, playerDisplay, 1, AttachmentPoint.Head, sceneOffset+BLINGTRON_OFFSET, Vector:New(playerDisplay:GetTransform().yaw+180, 0, 0)) Wait(1) while(true) do nodes = {} rawNodes = {} lines = {} selected = nil levelComplete = false nodeCount = 0 Wait(1) --Broadcast("Generate nodes") GenerateNodes(currentLevel) Wait(1) while(levelComplete==false) do Wait(0) end --Broadcast("Win triggered") blingAnim = blingtron:PlayLoopingAnimKit(3284) Wait(1) --Broadcast("Despawn nodes") for i=1, #rawNodes do rawNodes[i]:Despawn() end --Broadcast("Nodes despawned") Wait(2) scene:TriggerServerEvent("win") end --FUNCTIONS------------------------------------------------------------ local NodeCoroutine function AddNodeCoroutine(...) scene:AddCoroutineWithParams(NodeCoroutine, ...) end NodeCoroutine = function(actor) while (true) do actor:WaitRightClick() if (not switching and not levelComplete ) then if (actor.isSelected==true) then actor.isSelected = false selected = nil actor:ClearSpellVisual( actor.myVisual) actor:PlaySpellCastVisual(SPELL_VISUAL_CLICK_OFF) else if (selected ~= nil) then selected.isSelected = false selected:ClearSpellVisual( selected.myVisual) --actor:PlaySpellCastVisual(SPELL_VISUAL_CLICK) Switch(actor, selected) selected = nil else actor.isSelected = true actor.myVisual = actor:PlaySpellStateVisual(SELECTED_STATE) selected = actor actor:PlaySpellCastVisual(SPELL_VISUAL_CLICK) end end end end end function Switch(actorA, actorB) if (actorA==nil or actorB==nil or actorA==actorB) then return end switching = true local offsetA = actorA.offset local offsetB = actorB.offset --Broadcast("A: "..offsetA.x..", "..offsetA.y..", "..offsetA.z) --Broadcast("B: "..offsetB.x..", "..offsetB.y..", "..offsetB.z) --Broadcast("Scene: "..sceneOffset.x..", "..sceneOffset.y..", "..sceneOffset.z) actorA:PlaySpellCastVisual(SPELL_VISUAL_SWITCH) RideVehicleActor(actorA, playerDisplay, MOVE_TIME, AttachmentPoint.Head, sceneOffset+offsetB, Vector:New()) RideVehicleActor(actorB, playerDisplay, MOVE_TIME, AttachmentPoint.Head, sceneOffset+offsetA, Vector:New()) Wait(MOVE_TIME/2) actorA.offset = offsetB actorB.offset = offsetA Wait(MOVE_TIME/2) switching = false if (CheckAllIntersections()==false) then levelComplete=true selected=nil if currentLevel >= ACHIEVEMENT_LEVEL_THRESHOLD then scene:TriggerServerEvent("achievement") end end end function NodeShuffle(t) if ((t == nil) or (type(t) ~= "table")) then return nil; end local count = #t; if (count < 1) then return {}; end local orderTable = {}; local o = {}; for i = 1, count do table.insert(orderTable, { idx = i; order = math.random(); } ); end table.sort(orderTable, function(a, b) return a.order < b.order end); for i = 1, count do o[i] = t[orderTable[i].idx].offset; end for i = 1, count do RideVehicleActor(t[i], playerDisplay, 0, AttachmentPoint.Head, sceneOffset+o[i], Vector:New()) end for i = 1, count do t[i].offset = o[i] end Wait(0) local intersectionFound = CheckAllIntersections() if currentLevel >= ACHIEVEMENT_LEVEL_THRESHOLD then scene:TriggerServerEvent("achievement") end return intersectionFound end function Round(num) return math.floor(num+0.5) end function GenerateNodes(level) --create node objects local type = LEVELS[level].type if (type=="linked rings") then local totalRings = #LEVELS[level].data for i=1, totalRings do nodes[i] = {} local thisRadius = MAX_RADIUS*(1-(i-1)/(totalRings)) local nodesThisRing = LEVELS[level].data[i] for j=1, nodesThisRing do local thisAngle = j*2*math.pi/nodesThisRing + i*RING_ANGLE_OFFSET nodes[i][j] = CreateNode(thisRadius, thisAngle) table.insert(rawNodes, nodes[i][j]) nodes[i][j].index = nodeCount --Broadcast("added node, gave it index "..nodes[i][j].index) nodeCount = nodeCount+1 end end --draw rings for i=1, totalRings do local nodesThisRing = LEVELS[level].data[i] for j=1, nodesThisRing do local casterNode = nodes[i][j] local targetNode = nodes[i][j%nodesThisRing+1] AddLine(casterNode, targetNode) end end --draw bridges for i=2, totalRings do local nodesThisRing = LEVELS[level].data[i] local nodesLastRing = LEVELS[level].data[i-1] for j=1, nodesThisRing do local casterNode = nodes[i][j] local targetNode = nodes[i-1][math.floor(j*nodesLastRing/nodesThisRing + 0.5)] AddLine(casterNode, targetNode) end end local intersectionFound = false -- local intersectionFound = true while intersectionFound==false do intersectionFound = NodeShuffle(rawNodes) end elseif (type=="rings") then local totalRings = #LEVELS[level].data for i=1, totalRings do nodes[i] = {} local thisRadius = MAX_RADIUS*(1-(i-1)/(totalRings)) local nodesThisRing = LEVELS[level].data[i] for j=1, nodesThisRing do local thisAngle = j*2*math.pi/nodesThisRing + i*RING_ANGLE_OFFSET nodes[i][j] = CreateNode(thisRadius, thisAngle) table.insert(rawNodes, nodes[i][j]) nodes[i][j].index = nodeCount --Broadcast("added node, gave it index "..nodes[i][j].index) nodeCount = nodeCount+1 end end --draw rings for i=1, totalRings do local nodesThisRing = LEVELS[level].data[i] for j=1, nodesThisRing do local casterNode = nodes[i][j] local targetNode = nodes[i][j%nodesThisRing+1] AddLine(casterNode, targetNode) end end local intersectionFound = false while intersectionFound==false do intersectionFound = NodeShuffle(rawNodes) end elseif (type=="box") then local columns = LEVELS[level].data[1] local rows = LEVELS[level].data[2] for i=1, columns do nodes[i] = {} local thisY = MAX_RADIUS*(((2*i-2)/(columns-1))-1) for j=1, rows do local thisZ = MAX_RADIUS*(((2*j-2)/(rows-1))-1) nodes[i][j] = CreateNode(thisY, thisZ, true) table.insert(rawNodes, nodes[i][j]) nodes[i][j].index = nodeCount nodeCount = nodeCount+1 end end --draw lines for i=1, columns do for j=1, rows-1 do local casterNode = nodes[i][j] local targetNode = nodes[i][j+1] AddLine(casterNode, targetNode) end end for i=1, columns-1 do for j=1, rows do local casterNode = nodes[i][j] local targetNode = nodes[i+1][j] AddLine(casterNode, targetNode) end end local intersectionFound = false while intersectionFound==false do intersectionFound = NodeShuffle(rawNodes) end end end function CreateNode(radius, angle, _isBox) local isBox = _isBox or false local nodeOffset nodeCreateData.creatureDisplayID = DISPLAY if (isBox==true) then nodeOffset = Vector:New(0, radius, angle) else nodeOffset = Vector:New(0, radius*math.cos(angle), radius*math.sin(angle)) end nodeCreateData.transform = Transform:New(sceneOffset+nodeOffset, 180, 0, 0) local thisNode = scene:SpawnActor(nodeCreateData) thisNode:SetInteractCursor("interact", CursorRange.RangeFromPlayer, 20, nil) scene:SetRelativeCoords(true) playerDisplay = scene:GetActivePlayerDisplay() SCALE_NODE = .05 GAME_HEIGHT = 0.0 GAME_FRONT = 1.7 SELECTED_STATE = 50827 MOVE_TIME = 0.3 DISPLAY = 71953 MAX_RADIUS = 0.75 RING_ANGLE_OFFSET = 11.487187 --RING_ANGLE_OFFSET = 0 BLINGTRON_CREATURE = 110808 SCALE_BLING = .15 BLINGTRON_OFFSET = Vector:New(0, -1, -0.5) BEAM_BLUE = 71263 BEAM_RED = 71262 SPELL_VISUAL_CLICK = 71264 SPELL_VISUAL_CLICK_OFF = 71266 SPELL_VISUAL_SWITCH = 71265 LEVELS = { { ["type"] = "rings", ["data"] = {3, 4, 5, 6, 7} }, } currentLevel = 1 selected = nil nodes = {} rawNodes = {} lines = {} sceneFacing = 180 switching = false nodeCount = 0 levelComplete = false sceneOffset = Vector:New(GAME_FRONT, 0, GAME_HEIGHT) nodeCreateData = ActorCreateData:Default() nodeCreateData.groundSnap = false nodeCreateData.interactible = true nodeCreateData.selectable = false nodeCreateData.floatingTooltip = true nodeCreateData.scale = SCALE_NODE score = 0 ACHIEVEMENT_LEVEL_THRESHOLD = 20