fn ReplacePortal sel parentObj = ( if classof sel == GtaMloPortal then ( idxOneWay = GetAttrIndex "Gta MloPortal" "One Way" idxMloLink = GetAttrIndex "Gta MloPortal" "MLO Link" isOneWay = GetAttr sel idxOneWay isMloLink = GetAttr sel idxMloLink length = sel.Grid.Length width = sel.Grid.Width grid = sel.Grid.Grid link1 = sel.LinkFirst link2 = sel.LinkSecond doorObj = sel.PortalObject pos = sel.Position rot = sel.Rotation trans = sel.transform parentObj = sel.parent delete sel newPortal = GtaMloPortal LinkFirst:link1 LinkSecond:link2 PortalObject:doorObj SetAttr newPortal idxOneWay isOneWay SetAttr newPortal idxMloLink isMloLink newPortal.transform = trans newPortal.Grid.Length = length newPortal.Grid.Width = width newPortal.Grid.Grid = grid attachObjects parentObj newPortal move:false ) ) fn FindAndReplace = ( select $* allObjs = selection for sel in allObjs do ( for childObj in sel.children do ( ReplacePortal childObj sel ) ReplacePortal sel rootnode ) ) struct Milo ( miloName, entries=#(), portals=#(), rooms=#() ) fn SortPortalLinks = ( select $* allObjs = selection allPortals = #() -- First pass to store all portals for sel in allObjs do ( if classof sel == GtaMloPortal then ( append allPortals sel ) ) struct MiloRoom ( roomName, room, centroid ) allRooms = #() -- Second pass to build rooms for sel in allObjs do ( if classof sel == Gta_MILO then ( for childObj in sel.children do ( if classof childObj == GtaMloRoom then ( thisRoom = MiloRoom roomName:childObj.name room:childObj bbMin = [10000.0, 10000.0, 10000.0] bbMax = [-10000.0, -10000.0, -10000.0] for grandChildObj in childObj.children do ( if grandChildObj.pos.x < bbMin.x then bbMin.x = grandChildObj.pos.x if grandChildObj.pos.y < bbMin.y then bbMin.y = grandChildObj.pos.y if grandChildObj.pos.z < bbMin.z then bbMin.z = grandChildObj.pos.z if grandChildObj.pos.x > bbMax.x then bbMax.x = grandChildObj.pos.x if grandChildObj.pos.y > bbMax.y then bbMax.y = grandChildObj.pos.y if grandChildObj.pos.z > bbMax.z then bbMax.z = grandChildObj.pos.z ) thisRoom.centroid = (bbMin + bbMax) / 2 append allRooms thisRoom ) ) ) ) for portal in allPortals do ( switched == false notFound = true if portal.LinkFirst != undefined then ( for room in allRooms while notFound do ( if room.roomName == portal.LinkFirst.name then ( centroidVec = portal.pos - room.centroid arrowPt = [ 0.0, 0.0, 5.0 ] arrowPt = arrowPt * portal.transform portalVec = arrowPt - portal.pos centroidVec = normalize centroidVec portalVec = normalize portalVec dotProd = dot portalVec centroidVec if (dot centroidVec portalVec) < 0 then ( if (dot portalVec [0.0,0.0,1.0]) > 0.95 or (dot portalVec [0.0,0.0,1.0]) < -0.95 then ( rotatePortal = eulerangles 0 180 0 rotate portal rotatePortal ) else ( rotatePortal = eulerangles 0 0 180 rotate portal rotatePortal ) --rotPortal = eulerangles 0 0 180 --rotate portal rotPortal switched = true notFound = false ) ) ) ) if portal.LinkSecond != undefined and switched == false then ( for room in allRooms do ( if room.roomName == portal.LinkSecond.name then ( centroidVec = portal.pos - room.centroid arrowPt = [ 0.0, 0.0, 5.0 ] arrowPt = arrowPt * portal.transform portalVec = arrowPt - portal.pos centroidVec = normalize centroidVec portalVec = normalize portalVec dotProd = dot portalVec centroidVec if (dot centroidVec portalVec) > 0 then ( if (dot portalVec [0.0,0.0,1.0]) > 0.95 or (dot portalVec [0.0,0.0,1.0]) < -0.95 then ( rotatePortal = eulerangles 0 180 0 rotate portal rotatePortal ) else ( rotatePortal = eulerangles 0 0 180 rotate portal rotatePortal ) --rotPortal = eulerangles 0 0 180 --rotate portal rotPortal ) ) ) ) ) ) fn DoIt = ( FindAndReplace() SortPortalLinks() )