From 6460abce8db9a75822b91a8699c24f3336939854 Mon Sep 17 00:00:00 2001 From: IIYAMA Date: Thu, 23 Nov 2023 22:04:32 +0100 Subject: [PATCH 1/5] Add aclrequest for loadstring --- [admin]/runcode/meta.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/[admin]/runcode/meta.xml b/[admin]/runcode/meta.xml index 318a03f6a..7b4d8bcab 100644 --- a/[admin]/runcode/meta.xml +++ b/[admin]/runcode/meta.xml @@ -22,4 +22,9 @@ + + + + From 5cc90dd45ddd56f7c2f4974e7719dc1b6ceee252 Mon Sep 17 00:00:00 2001 From: IIYAMA Date: Thu, 23 Nov 2023 23:12:37 +0100 Subject: [PATCH 2/5] Remove linebreak from meta.xml runcode --- [admin]/runcode/meta.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/[admin]/runcode/meta.xml b/[admin]/runcode/meta.xml index 79ecb109f..35ea525ae 100644 --- a/[admin]/runcode/meta.xml +++ b/[admin]/runcode/meta.xml @@ -24,7 +24,6 @@ - + From 1de35ae23d9abf722a9adc29e413e201657811a3 Mon Sep 17 00:00:00 2001 From: IIYAMA Date: Wed, 24 Dec 2025 16:18:04 +0100 Subject: [PATCH 3/5] Ability to make objects move in the editor --- [editor]/edf/edf.lua | 11 ++ [editor]/edf/properties.lua | 40 ++++++ [editor]/edf/properties_client.lua | 40 ++++++ [editor]/editor_main/client/gridlines.lua | 126 +++++++++++++++++- [editor]/editor_main/editor_main.edf | 5 + .../server/mapEditorScriptingExtension_s.lua | 70 +++++++++- .../server/saveloadtest_server.lua | 12 +- 7 files changed, 298 insertions(+), 6 deletions(-) diff --git a/[editor]/edf/edf.lua b/[editor]/edf/edf.lua index d5dd20592..53a3c3af4 100644 --- a/[editor]/edf/edf.lua +++ b/[editor]/edf/edf.lua @@ -1131,6 +1131,17 @@ function edfAddElementNodeData(node, resource) local validModels = xmlNodeGetAttribute(subnode, "validModels") dataFields[dname].validModels = validModels and split(validModels, ",") or dataFields[dname].validModels + --[[ Set to false to only save the value if it is not the default value, + useful to prevent map files from growing too much, + especially for properties that are not always required (default: true) + ]] + local persistDefault = xmlNodeGetAttribute(subnode, "persistDefault") + if persistDefault then + dataFields[dname].persistDefault = convert.boolean(persistDefault) + else + dataFields[dname].persistDefault = dataFields[dname].persistDefault or true + end + -- update the required flag (default: true) local requiredAttribute = xmlNodeGetAttribute(subnode,"required") if requiredAttribute then diff --git a/[editor]/edf/properties.lua b/[editor]/edf/properties.lua index 148b46457..7f4341502 100644 --- a/[editor]/edf/properties.lua +++ b/[editor]/edf/properties.lua @@ -37,6 +37,46 @@ propertyGetters = { else return "false" end + end, + moveSpeed = function(element) + local time = getElementData(element, "moveSpeed") + if time == nil or time == false then + return 1 + else + return time + end + end, + moveDelay = function(element) + local delay = getElementData(element, "moveDelay") + if delay == nil or delay == false then + return 0 + else + return delay + end + end, + moveX = function(element) + local offsetX = getElementData(element, "moveX") + if offsetX == nil or offsetX == false then + return 0 + else + return offsetX + end + end, + moveY = function(element) + local offsetY = getElementData(element, "moveY") + if offsetY == nil or offsetY == false then + return 0 + else + return offsetY + end + end, + moveZ = function(element) + local offsetZ = getElementData(element, "moveZ") + if offsetZ == nil or offsetZ == false then + return 0 + else + return offsetZ + end end }, ped = { diff --git a/[editor]/edf/properties_client.lua b/[editor]/edf/properties_client.lua index 80a8811af..9e00d2376 100644 --- a/[editor]/edf/properties_client.lua +++ b/[editor]/edf/properties_client.lua @@ -17,6 +17,46 @@ propertyGetters = { else return "false" end + end, + moveSpeed = function(element) + local time = getElementData(element, "moveSpeed") + if time == nil or time == false then + return 1 + else + return time + end + end, + moveDelay = function(element) + local delay = getElementData(element, "moveDelay") + if delay == nil or delay == false then + return 0 + else + return delay + end + end, + moveX = function(element) + local offsetX = getElementData(element, "moveX") + if offsetX == nil or offsetX == false then + return 0 + else + return offsetX + end + end, + moveY = function(element) + local offsetY = getElementData(element, "moveY") + if offsetY == nil or offsetY == false then + return 0 + else + return offsetY + end + end, + moveZ = function(element) + local offsetZ = getElementData(element, "moveZ") + if offsetZ == nil or offsetZ == false then + return 0 + else + return offsetZ + end end }, ped = { diff --git a/[editor]/editor_main/client/gridlines.lua b/[editor]/editor_main/client/gridlines.lua index b6f0ab3b6..f4f95400b 100644 --- a/[editor]/editor_main/client/gridlines.lua +++ b/[editor]/editor_main/client/gridlines.lua @@ -109,11 +109,135 @@ function drawXYZLines() drawLine({x,y,z},{zx,zy,zz},tocolor(0,0,200,200),thickness) end +--[[ + Draws the where the object will be moved to. +]] +function drawObjectMoveLines() + if not isElement(attachedToElement) then return end + if not getElementType(attachedToElement) == "object" then return end + if getElementDimension(attachedToElement) ~= getElementDimension(localPlayer) then return end + local x,y,z = edf.edfGetElementPosition(attachedToElement) + if not x then return end + + local offsetX = edf.edfGetElementProperty(attachedToElement, "moveX") + local offsetY = edf.edfGetElementProperty(attachedToElement, "moveY") + local offsetZ = edf.edfGetElementProperty(attachedToElement, "moveZ") + + if offsetX and math.abs(offsetX) > 0 or offsetY and math.abs(offsetY) > 0 or offsetZ and math.abs(offsetZ) > 0 then + if not offsetX then offsetX = 0 end + if not offsetY then offsetY = 0 end + if not offsetZ then offsetZ = 0 end + + local speed = tonumber(edf.edfGetElementProperty(attachedToElement, "moveSpeed")) + if not speed then speed = 1 end + local delay = tonumber(edf.edfGetElementProperty(attachedToElement, "moveDelay")) + if not delay then delay = 0 end + local time = getDistanceBetweenPoints3D(x,y,z,x + offsetX,y + offsetY,z + offsetZ) / speed * 1000 + local lineStartPos = {x,y,z} + local lineEndPos = {x + offsetX,y + offsetY,z + offsetZ} + local timeNow = getTickCount() + + local progress = timeNow % (time + delay) / time + if progress > 1 then + progress = 1 + end + + local movementAnimationOffset = { + (lineEndPos[1] - lineStartPos[1]) * progress, + (lineEndPos[2] - lineStartPos[2]) * progress, + (lineEndPos[3] - lineStartPos[3]) * progress + } + + + local minX,minY,minZ,maxX,maxY,maxZ = edf.edfGetElementBoundingBox ( attachedToElement ) + if not minX then + local radius = edf.edfGetElementRadius ( attachedToElement ) + if radius then + minX,minY,minZ,maxX,maxY,maxZ = -radius,-radius,-radius,radius,radius,radius + end + end + + if minX and minY and minZ and maxX and maxY and maxZ then + -- Define the 8 corners in relative coordinates + local relativeCorners = { + {minX, minY, minZ}, -- 1: min corner + {maxX, minY, minZ}, -- 2 + {maxX, maxY, minZ}, -- 3 + {minX, maxY, minZ}, -- 4 + {minX, minY, maxZ}, -- 5 + {maxX, minY, maxZ}, -- 6 + {maxX, maxY, maxZ}, -- 7 + {minX, maxY, maxZ} -- 8: max corner + } + + -- Draw the bounding box moving to the destination position + do + local corners = {} + for i, relCorner in ipairs(relativeCorners) do + local worldX, worldY, worldZ = getPositionFromElementAtOffset(attachedToElement, relCorner[1], relCorner[2], relCorner[3]) + corners[i] = {worldX + movementAnimationOffset[1], worldY + movementAnimationOffset[2], worldZ + movementAnimationOffset[3]} + end + + local boxColor = tocolor(255, 255, 255, 100) + local lineWidth = 2 + + -- Bottom face (z = minZ) + dxDrawLine3D(corners[1][1], corners[1][2], corners[1][3], corners[2][1], corners[2][2], corners[2][3], boxColor, lineWidth) + dxDrawLine3D(corners[2][1], corners[2][2], corners[2][3], corners[3][1], corners[3][2], corners[3][3], boxColor, lineWidth) + dxDrawLine3D(corners[3][1], corners[3][2], corners[3][3], corners[4][1], corners[4][2], corners[4][3], boxColor, lineWidth) + dxDrawLine3D(corners[4][1], corners[4][2], corners[4][3], corners[1][1], corners[1][2], corners[1][3], boxColor, lineWidth) + + -- Top face (z = maxZ) + dxDrawLine3D(corners[5][1], corners[5][2], corners[5][3], corners[6][1], corners[6][2], corners[6][3], boxColor, lineWidth) + dxDrawLine3D(corners[6][1], corners[6][2], corners[6][3], corners[7][1], corners[7][2], corners[7][3], boxColor, lineWidth) + dxDrawLine3D(corners[7][1], corners[7][2], corners[7][3], corners[8][1], corners[8][2], corners[8][3], boxColor, lineWidth) + dxDrawLine3D(corners[8][1], corners[8][2], corners[8][3], corners[5][1], corners[5][2], corners[5][3], boxColor, lineWidth) + + -- Vertical edges connecting bottom to top + dxDrawLine3D(corners[1][1], corners[1][2], corners[1][3], corners[5][1], corners[5][2], corners[5][3], boxColor, lineWidth) + dxDrawLine3D(corners[2][1], corners[2][2], corners[2][3], corners[6][1], corners[6][2], corners[6][3], boxColor, lineWidth) + dxDrawLine3D(corners[3][1], corners[3][2], corners[3][3], corners[7][1], corners[7][2], corners[7][3], boxColor, lineWidth) + dxDrawLine3D(corners[4][1], corners[4][2], corners[4][3], corners[8][1], corners[8][2], corners[8][3], boxColor, lineWidth) + end + + -- Draw the bounding box at the destination position + do + local corners = {} + for i, relCorner in ipairs(relativeCorners) do + local worldX, worldY, worldZ = getPositionFromElementAtOffset(attachedToElement, relCorner[1], relCorner[2], relCorner[3]) + corners[i] = {worldX + offsetX, worldY + offsetY, worldZ + offsetZ} + end + + local boxColor = tocolor(255, 255, 0, 200) + local lineWidth = 2 + + -- Bottom face (z = minZ) + dxDrawLine3D(corners[1][1], corners[1][2], corners[1][3], corners[2][1], corners[2][2], corners[2][3], boxColor, lineWidth) + dxDrawLine3D(corners[2][1], corners[2][2], corners[2][3], corners[3][1], corners[3][2], corners[3][3], boxColor, lineWidth) + dxDrawLine3D(corners[3][1], corners[3][2], corners[3][3], corners[4][1], corners[4][2], corners[4][3], boxColor, lineWidth) + dxDrawLine3D(corners[4][1], corners[4][2], corners[4][3], corners[1][1], corners[1][2], corners[1][3], boxColor, lineWidth) + + -- Top face (z = maxZ) + dxDrawLine3D(corners[5][1], corners[5][2], corners[5][3], corners[6][1], corners[6][2], corners[6][3], boxColor, lineWidth) + dxDrawLine3D(corners[6][1], corners[6][2], corners[6][3], corners[7][1], corners[7][2], corners[7][3], boxColor, lineWidth) + dxDrawLine3D(corners[7][1], corners[7][2], corners[7][3], corners[8][1], corners[8][2], corners[8][3], boxColor, lineWidth) + dxDrawLine3D(corners[8][1], corners[8][2], corners[8][3], corners[5][1], corners[5][2], corners[5][3], boxColor, lineWidth) + + -- Vertical edges connecting bottom to top + dxDrawLine3D(corners[1][1], corners[1][2], corners[1][3], corners[5][1], corners[5][2], corners[5][3], boxColor, lineWidth) + dxDrawLine3D(corners[2][1], corners[2][2], corners[2][3], corners[6][1], corners[6][2], corners[6][3], boxColor, lineWidth) + dxDrawLine3D(corners[3][1], corners[3][2], corners[3][3], corners[7][1], corners[7][2], corners[7][3], boxColor, lineWidth) + dxDrawLine3D(corners[4][1], corners[4][2], corners[4][3], corners[8][1], corners[8][2], corners[8][3], boxColor, lineWidth) + end + end + end +end + function doBasicElementRenders() if not isElement(attachedToElement) then return end if exports["editor_gui"]:sx_getOptionData("enableBox") then renderGridlines() end if exports["editor_gui"]:sx_getOptionData("enableXYZlines") then drawXYZLines() end - + drawObjectMoveLines() end addEventHandler ( "onClientRender", root, doBasicElementRenders ) diff --git a/[editor]/editor_main/editor_main.edf b/[editor]/editor_main/editor_main.edf index cd3f20435..05e9a8ecf 100644 --- a/[editor]/editor_main/editor_main.edf +++ b/[editor]/editor_main/editor_main.edf @@ -11,6 +11,11 @@ + + + + + diff --git a/[editor]/editor_main/server/mapEditorScriptingExtension_s.lua b/[editor]/editor_main/server/mapEditorScriptingExtension_s.lua index fcf043523..de492db4d 100644 --- a/[editor]/editor_main/server/mapEditorScriptingExtension_s.lua +++ b/[editor]/editor_main/server/mapEditorScriptingExtension_s.lua @@ -31,9 +31,8 @@ function onResourceStartOrStop(startedResource) if startEvent then local resourceName = getResourceName(startedResource) local useLODs = get(resourceName..".useLODs") - + local objectsTable = getElementsByType("object", source) if useLODs then - local objectsTable = getElementsByType("object", source) for objectID = 1, #objectsTable do local objectElement = objectsTable[objectID] @@ -57,11 +56,78 @@ function onResourceStartOrStop(startedResource) end end end + for i = 1, #objectsTable do + local objectElement = objectsTable[i] + local x, y, z = getElementPosition(objectElement) + local offsetX = tonumber(getElementData(objectElement, "moveX")) + local offsetY = tonumber(getElementData(objectElement, "moveY")) + local offsetZ = tonumber(getElementData(objectElement, "moveZ")) + if (offsetX and math.abs(offsetX) > 0) or (offsetY and math.abs(offsetY) > 0) or (offsetZ and math.abs(offsetZ) > 0) then + if not offsetX then offsetX = 0 end + if not offsetY then offsetY = 0 end + if not offsetZ then offsetZ = 0 end + + local speed = tonumber(getElementData(objectElement, "moveSpeed")) or 1 + local delay = tonumber(getElementData(objectElement, "moveDelay")) or 0 + local time = getDistanceBetweenPoints3D(x,y,z,x + offsetX,y + offsetY,z + offsetZ) / speed * 1000 + + if time then + local currentPosX, currentPosY, currentPosZ = getElementPosition(objectElement) + local endPosX = currentPosX + offsetX + local endPosY = currentPosY + offsetY + local endPosZ = currentPosZ + offsetZ + local properties = { + moveTime = time, + delay = delay, + initialPosX = currentPosX, + initialPosY = currentPosY, + initialPosZ = currentPosZ, + endPosX = endPosX, + endPosY = endPosY, + endPosZ = endPosZ, + } + if delay > 0 then + setTimer(onObjectReachedInitialPosition, delay, 1, objectElement, properties) + else + onObjectReachedInitialPosition(objectElement, properties) + end + end + end + end end end addEventHandler("onResourceStart", resourceRoot, onResourceStartOrStop) addEventHandler("onResourceStop", resourceRoot, onResourceStartOrStop) +function onObjectReachedEndPosition(objectElement, properties) + if not isElement(objectElement) then + return + end + stopObject(objectElement) + local time = properties.moveTime + local delay = properties.delay + local initialPosX = properties.initialPosX + local initialPosY = properties.initialPosY + local initialPosZ = properties.initialPosZ + moveObject(objectElement, time, initialPosX, initialPosY, initialPosZ) + setTimer(onObjectReachedInitialPosition, time + delay, 1, objectElement, properties) +end + +function onObjectReachedInitialPosition(objectElement, properties) + if not isElement(objectElement) then + return + end + stopObject(objectElement) + local time = properties.moveTime + if not time then return end + local delay = properties.delay + local endPosX = properties.endPosX + local endPosY = properties.endPosY + local endPosZ = properties.endPosZ + moveObject(objectElement, time, endPosX, endPosY, endPosZ) + setTimer(onObjectReachedEndPosition, time + delay, 1, objectElement, properties) +end + local function onPlayerResourceStart(resourceElement) local mapResource = resourceElement == resource diff --git a/[editor]/editor_main/server/saveloadtest_server.lua b/[editor]/editor_main/server/saveloadtest_server.lua index 0232f3142..3b77a6b39 100644 --- a/[editor]/editor_main/server/saveloadtest_server.lua +++ b/[editor]/editor_main/server/saveloadtest_server.lua @@ -646,7 +646,8 @@ function createElementAttributesForSaving(xmlNode, element) -- Add an ID attribute first off xmlNodeSetAttribute(elementNode, "id", getElementID(element)) -- Dump raw properties from the getters - for dataField in pairs(loadedEDF[edf.edfGetCreatorResource(element)].elements[getElementType(element)].data) do + local dataFields = loadedEDF[edf.edfGetCreatorResource(element)].elements[getElementType(element)].data + for dataField, dataDefinition in pairs(dataFields) do if (dataField ~= "color1" and dataField ~= "color2" and dataField ~= "color3" and dataField ~= "color4") then local value if ( specialSyncers[dataField] ) then @@ -655,7 +656,9 @@ function createElementAttributesForSaving(xmlNode, element) value = edf.edfGetElementProperty(element, dataField) end if type(value) == "number" or type(value) == "string" then - xmlNodeSetAttribute(elementNode, dataField, value ) + if dataDefinition.persistDefault == true or dataDefinition.default ~= value then + xmlNodeSetAttribute(elementNode, dataField, value ) + end end end end @@ -686,7 +689,10 @@ function createElementAttributesForSaving(xmlNode, element) elseif ( dataName == "rotX" or dataName == "rotY" or dataName == "rotZ") then xmlNodeSetAttribute(elementNode, dataName, toAttribute(round(dataValue, 3))) elseif ( dataName ~= "color1" and dataName ~= "color2" and dataName ~= "color3" and dataName ~= "color4" and ( not specialSyncers[dataName] or dataValue ~= getWorkingDimension() ) ) then - xmlNodeSetAttribute(elementNode, dataName, toAttribute(dataValue)) + local dataDefinition = dataFields[dataName] + if not dataDefinition or dataDefinition.persistDefault == true or dataDefinition.default ~= dataValue then + xmlNodeSetAttribute(elementNode, dataName, toAttribute(dataValue)) + end end end -- Ensure that the element has a position set, else the map file can't load From 484378373599438a1a976951ebf2f701d731bb81 Mon Sep 17 00:00:00 2001 From: IIYAMA Date: Wed, 24 Dec 2025 17:14:14 +0100 Subject: [PATCH 4/5] Fix merge conflict --- .../server/saveloadtest_server.lua | 65 ++++++++++++++++++- 1 file changed, 63 insertions(+), 2 deletions(-) diff --git a/[editor]/editor_main/server/saveloadtest_server.lua b/[editor]/editor_main/server/saveloadtest_server.lua index 706e47b1b..e9f566409 100644 --- a/[editor]/editor_main/server/saveloadtest_server.lua +++ b/[editor]/editor_main/server/saveloadtest_server.lua @@ -1032,9 +1032,8 @@ function onResourceStartOrStop(startedResource) if startEvent then local resourceName = getResourceName(startedResource) local useLODs = get(resourceName..".useLODs") - + local objectsTable = getElementsByType("object", source) if useLODs then - local objectsTable = getElementsByType("object", source) for objectID = 1, #objectsTable do local objectElement = objectsTable[objectID] @@ -1058,11 +1057,73 @@ function onResourceStartOrStop(startedResource) end end end + + for i = 1, #objectsTable do + local objectElement = objectsTable[i] + local x, y, z = getElementPosition(objectElement) + local offsetX = tonumber(getElementData(objectElement, "moveX")) + local offsetY = tonumber(getElementData(objectElement, "moveY")) + local offsetZ = tonumber(getElementData(objectElement, "moveZ")) + if (offsetX and math.abs(offsetX) > 0) or (offsetY and math.abs(offsetY) > 0) or (offsetZ and math.abs(offsetZ) > 0) then + if not offsetX then offsetX = 0 end + if not offsetY then offsetY = 0 end + if not offsetZ then offsetZ = 0 end + + local speed = tonumber(getElementData(objectElement, "moveSpeed")) or 1 + local delay = tonumber(getElementData(objectElement, "moveDelay")) or 0 + local time = getDistanceBetweenPoints3D(x,y,z,x + offsetX,y + offsetY,z + offsetZ) / speed * 1000 + + local currentPosX, currentPosY, currentPosZ = getElementPosition(objectElement) + local endPosX = currentPosX + offsetX + local endPosY = currentPosY + offsetY + local endPosZ = currentPosZ + offsetZ + local properties = { + moveTime = time, + delay = delay, + initialPosX = currentPosX, + initialPosY = currentPosY, + initialPosZ = currentPosZ, + endPosX = endPosX, + endPosY = endPosY, + endPosZ = endPosZ, + } + if delay > 0 then + setTimer(onObjectReachedInitialPosition, delay, 1, objectElement, properties) + else + onObjectReachedInitialPosition(objectElement, properties) + end + end + end end end addEventHandler("onResourceStart", resourceRoot, onResourceStartOrStop) addEventHandler("onResourceStop", resourceRoot, onResourceStartOrStop) +function onObjectReachedEndPosition(objectElement, properties) + if not isElement(objectElement) then return end + stopObject(objectElement) + local time = properties.moveTime + local delay = properties.delay + local initialPosX = properties.initialPosX + local initialPosY = properties.initialPosY + local initialPosZ = properties.initialPosZ + moveObject(objectElement, time, initialPosX, initialPosY, initialPosZ) + setTimer(onObjectReachedInitialPosition, time + delay, 1, objectElement, properties) +end + +function onObjectReachedInitialPosition(objectElement, properties) + if not isElement(objectElement) then return end + stopObject(objectElement) + local time = properties.moveTime + if not time then return end + local delay = properties.delay + local endPosX = properties.endPosX + local endPosY = properties.endPosY + local endPosZ = properties.endPosZ + moveObject(objectElement, time, endPosX, endPosY, endPosZ) + setTimer(onObjectReachedEndPosition, time + delay, 1, objectElement, properties) +end + local function onPlayerResourceStart(resourceElement) local mapResource = resourceElement == resource From d083f9de9adce8b9ac465b414ab30a2f2fa95831 Mon Sep 17 00:00:00 2001 From: IIYAMA Date: Wed, 24 Dec 2025 17:19:16 +0100 Subject: [PATCH 5/5] fix linter errors --- [editor]/edf/edf.lua | 4 ++-- [editor]/editor_main/client/gridlines.lua | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/[editor]/edf/edf.lua b/[editor]/edf/edf.lua index 5ac658d78..23c6a29c7 100644 --- a/[editor]/edf/edf.lua +++ b/[editor]/edf/edf.lua @@ -1198,8 +1198,8 @@ function edfAddElementNodeData(node, resource) local validModels = xmlNodeGetAttribute(subnode, "validModels") dataFields[dname].validModels = validModels and split(validModels, ",") or dataFields[dname].validModels - --[[ Set to false to only save the value if it is not the default value, - useful to prevent map files from growing too much, + --[[ Set to false to only save the value if it is not the default value, + useful to prevent map files from growing too much, especially for properties that are not always required (default: true) ]] local persistDefault = xmlNodeGetAttribute(subnode, "persistDefault") diff --git a/[editor]/editor_main/client/gridlines.lua b/[editor]/editor_main/client/gridlines.lua index aed308b94..fc8be095f 100644 --- a/[editor]/editor_main/client/gridlines.lua +++ b/[editor]/editor_main/client/gridlines.lua @@ -130,7 +130,7 @@ end ]] function drawObjectMoveLines() if not isElement(attachedToElement) then return end - if not getElementType(attachedToElement) == "object" then return end + if getElementType(attachedToElement) ~= "object" then return end if getElementDimension(attachedToElement) ~= getElementDimension(localPlayer) then return end local x,y,z = edf.edfGetElementPosition(attachedToElement) if not x then return end