Serpens Posted September 8, 2017 Share Posted September 8, 2017 Is it possible to get the room/task an entity is located? I mean if you select your character with c_select() and hit backspace, you enable the DebugRender. And this is showing you besides other information, also the room and task you are currently located. But what is the function to get this room/task name? Link to comment Share on other sites More sharing options...
ZupaleX Posted September 8, 2017 Share Posted September 8, 2017 I would use GetClosestNodeToPlayer() This returns you a node which have a field "data" containing all the info you are asking about. Link to comment Share on other sites More sharing options...
Serpens Posted September 8, 2017 Author Share Posted September 8, 2017 (edited) 33 minutes ago, ZupaleX said: I would use GetClosestNodeToPlayer() This returns you a node which have a field "data" containing all the info you are asking about. thank you The goal is to connect wormholes depending on the task they are located in. So I used GetClosestNode(x,y) instead, but this does not contain "data". It does contain this: neighbours table: 5D1D4268 type 0 c 7 tags table: 0C20C030 cent table: 0C20C648 y -19 poly table: 0C20C300 validedges table: 5D18C428 x 42 area 323 So what now? =/ My Code: AddPrefabPostInit("wormhole",function(inst) if inst.components.teleporter then inst:DoTaskInTime(0,function(inst) local x, y, z = inst.Transform:GetWorldPosition() local n = GLOBAL.GetClosestNode(x,y) -- ... end) end end) Why I'm asking: Spoiler I'm working on the Adventure Mod, which will allow playing the DS adventure. There is a world "Archipelago", which has 5 islands and a start island. Unfortunately islands do not work by default and it is too complicated to rewrite the worldgeneration code. Therefore I made them half-islands linked with a small path, but this path is blocked by undestroyable basalt. But the game is not generating wormholes by itself. So I added 5 wormholes to the start-task and 1 wormhole for each of the other island tasks. In map/network the wormholes are randomly connected. The only solution I can imagine so far, is to iterate after world generation over all exisiting wormholes and make them connect correctly, depending on their task they are located. Edited September 8, 2017 by Serpens Link to comment Share on other sites More sharing options...
ZupaleX Posted September 8, 2017 Share Posted September 8, 2017 I was expecting this function to return a table of this type Spoiler Node = Class(function(self, id, data) self.id = id self.graph = nil self.delta_graph = nil -- Graph properties self.edges = {} -- Data self.data = data -- Search self.visited = false self.colour = data.colour or {r=255,g=255,b=0,a=55} self.ents = nil self.populateFn = nil self.tileFn = nil self.populated = false self.children_populated = false if self.data.custom_tiles ~= nil then self:SetTilesFunction(self.data.custom_tiles) self.data.custom_tiles = nil end if self.data.custom_objects ~= nil then self:SetPopulateFunction(self.data.custom_objects) self.data.custom_objects = nil end end) but obviously it does not. Well there is a bit more research to do then, sorry about that. Link to comment Share on other sites More sharing options...
ptr Posted September 10, 2017 Share Posted September 10, 2017 I believe this is what you want. It is based on the 'GetClosestNode'. A small change was made to make it more precise for edges. function GetRoom(entity) local closestdist = math.huge local closestid = nil x,_,y=entity.Transform:GetWorldPosition() for i,v in pairs(GLOBAL.TheWorld.topology.nodes) do if #v.neighbours > 0 then local dx = math.floor((math.abs(v.x - x)+2)/4) local dy = math.floor((math.abs(v.y - y)+2)/4) local distsq = dx*dx + dy*dy if distsq < closestdist then closestdist = distsq closestid = i end end end return GLOBAL.TheWorld.topology.ids[closestid] end Link to comment Share on other sites More sharing options...
Serpens Posted September 10, 2017 Author Share Posted September 10, 2017 (edited) 51 minutes ago, ptr said: I believe this is what you want. It is based on the 'GetClosestNode'. A small change was made to make it more precise for edges. O.ô brilliant it works ! eg returning "IslandHop_Start:2:SpiderMarsh" (task and room) By the way I just implemented another solution I created a new room which includes countstaticlayout. And made a new layout that includes a wormhole with a scenario. The scenario is adding the Tag "wormholeX". (while X is a number from 1 to 10). Then I added those rooms to the the island tasks. Now in modmain I was able to connect the wormhole with Tag "wormhole1" with the wormhole with tag "wormhole2" (FindFirstEntityWithTag). But with your solution it is much better (just have to think about how to find the other wormholes... hmm.. only solution is a worldwide FindEntities and then checking their Task/Room ? ... or better adding the Tags from above in AddPrefabPostInit depending on their room and then do a DoTaskInTime and connect them via FindFirstEntityWithTag) ok, this is my solution now in modmain: Spoiler AddPrefabPostInit("wormhole",function(inst) if inst.components.teleporter then inst:DoTaskInTime(0,function(inst) taskandroom = GetRoom(inst) -- eg "IslandHop_Start:2:SpiderMarsh" if string.find(taskandroom,"IslandHop_Start") then if not GLOBAL.TheSim:FindFirstEntityWithTag("wormhole1") then inst:AddTag("wormhole1") elseif not GLOBAL.TheSim:FindFirstEntityWithTag("wormhole2") then inst:AddTag("wormhole2") elseif not GLOBAL.TheSim:FindFirstEntityWithTag("wormhole3") then inst:AddTag("wormhole3") elseif not GLOBAL.TheSim:FindFirstEntityWithTag("wormhole4") then inst:AddTag("wormhole4") elseif not GLOBAL.TheSim:FindFirstEntityWithTag("wormhole5") then inst:AddTag("wormhole5") end elseif string.find(taskandroom,"IslandHop_Hounds") then inst:AddTag("wormhole6") elseif string.find(taskandroom,"IslandHop_Forest") then inst:AddTag("wormhole7") elseif string.find(taskandroom,"IslandHop_Savanna") then inst:AddTag("wormhole8") elseif string.find(taskandroom,"IslandHop_Rocky") then inst:AddTag("wormhole9") elseif string.find(taskandroom,"IslandHop_Merm") then inst:AddTag("wormhole10") end inst:DoTaskInTime(0.1,function(inst) if inst:HasTag("wormhole1") then local worm6 = GLOBAL.TheSim:FindFirstEntityWithTag("wormhole6") inst.components.teleporter.targetTeleporter = worm6 elseif inst:HasTag("wormhole2") then local worm7 = GLOBAL.TheSim:FindFirstEntityWithTag("wormhole7") inst.components.teleporter.targetTeleporter = worm7 elseif inst:HasTag("wormhole3") then local worm8 = GLOBAL.TheSim:FindFirstEntityWithTag("wormhole8") inst.components.teleporter.targetTeleporter = worm8 elseif inst:HasTag("wormhole4") then local worm9 = GLOBAL.TheSim:FindFirstEntityWithTag("wormhole9") inst.components.teleporter.targetTeleporter = worm9 elseif inst:HasTag("wormhole5") then local worm10 = GLOBAL.TheSim:FindFirstEntityWithTag("wormhole10") inst.components.teleporter.targetTeleporter = worm10 elseif inst:HasTag("wormhole6") then local worm1 = GLOBAL.TheSim:FindFirstEntityWithTag("wormhole1") inst.components.teleporter.targetTeleporter = worm1 elseif inst:HasTag("wormhole7") then local worm2 = GLOBAL.TheSim:FindFirstEntityWithTag("wormhole2") inst.components.teleporter.targetTeleporter = worm2 elseif inst:HasTag("wormhole8") then local worm3 = GLOBAL.TheSim:FindFirstEntityWithTag("wormhole3") inst.components.teleporter.targetTeleporter = worm3 elseif inst:HasTag("wormhole9") then local worm4 = GLOBAL.TheSim:FindFirstEntityWithTag("wormhole4") inst.components.teleporter.targetTeleporter = worm4 elseif inst:HasTag("wormhole10") then local worm5 = GLOBAL.TheSim:FindFirstEntityWithTag("wormhole5") inst.components.teleporter.targetTeleporter = worm5 end end) end) end end) Edited September 10, 2017 by Serpens Link to comment Share on other sites More sharing options...
ptr Posted September 10, 2017 Share Posted September 10, 2017 Why not save all the wormholes in a global table like the sinkholes do in addprefabpostinit? Then you can connect them in a function once all wormholes are saved. Link to comment Share on other sites More sharing options...
Serpens Posted September 10, 2017 Author Share Posted September 10, 2017 (edited) 14 hours ago, ptr said: Why not save all the wormholes in a global table like the sinkholes do in addprefabpostinit? Then you can connect them in a function once all wormholes are saved. Are you interested in helping me to improve the code from the adventure mod?https://github.com/Serpens66/DST-Adventure-Mod/tree/master/Adventure-Mod Especially the level code is very poor.. It works like this: In Adventure we have a "Chapter" from 0 to 6. And a Level (I call it Overridelevel, currently 1 to 8). The levels are all designed worlds we have, egl Archipelago, King of Winter and so on. From those worlds not all are selected (only so many to fill the available chapters). So basic problem is now, that when we complete the first chapter, the game has to "restart", but load the next world now, instead of the old one again. DarkXero solved that by basically writing the next world in a file located in modfolder when doing the "adventurejump". When next world is loaded it reads that file, loads the correct world, and empties that file again. In modworldgenmain I save this actual level (and chapter) in GLOBAL.CHAPTER_GEN and GLOBAL.OVERRIDELEVEL_GEN. The problem is now, that modworldgenmain runs ~ 2 or 3 times at gamestart, and also when world is not generating 1 or 2 times. Also modmain is running several times each gamestart. But the file where the actual level is saved, does only exist directly when doing the worldjump. That means that GLOBAL.OVERRIDELEVEL_GEN is not usable each time we load the game (without generating a new world). Therefore a component attached to the world is saving that information instead. So now I have a cluttered system to get the actual world/chapter, which is only known after the world added and started their components. The problem now is, that I don't 100% know when this component is successfully loaded. Eg. for the AddPrefabPostInit with the wormholes, I did a "AddTaskPostInit" with DoTaskInTime of 0.05 seconds. Cause I thought the world and their components are initilaiied before all the prefabs. But obviously this is not true, cause level was unknown. So now I do wait 0.5 seconds instead, wich is working. But in the PostInit of the world I now have to connect those wormholes I saved in GLOBAL variable in PostInit of wormholes. But I have to do it after I saved the wormholes, so I use DoTaskInTime of 1 second now. The result is, everywhere were I need to know the actual level, has a "DoTaskInTime" with some seconds to wait. But what if for some reason the game takes longer to load the world components? And it really sucks to make sure that everywhere the seconds are increased if it depends on each other. I this is very error prone, cause I can also miss to increase the time for depending things (like the wormhole code) and not always an error is thrown. All in all I don't like this and I hope there is a btter way of doing it... Edited September 10, 2017 by Serpens Link to comment Share on other sites More sharing options...
ptr Posted September 10, 2017 Share Posted September 10, 2017 3 hours ago, Serpens said: Are you interested in helping me to improve the code from the adventure mod?https://github.com/Serpens66/DST-Adventure-Mod/tree/master/Adventure-Mod Especially the level code is very poor.. It works like this: In Adventure we have a "Chapter" from 0 to 6. And a Level (I call it Overridelevel, currently 1 to 8). The levels are all designed worlds we have, egl Archipelago, King of Winter and so on. From those worlds not all are selected (only so many to fill the available chapters). So basic problem is now, that when we complete the first chapter, the game has to "restart", but load the next world now, instead of the old one again. DarkXero solved that by basically writing the next world in a file located in modfolder when doing the "adventurejump". When next world is loaded it reads that file, loads the correct world, and empties that file again. In modworldgenmain I save this actual level (and chapter) in GLOBAL.CHAPTER_GEN and GLOBAL.OVERRIDELEVEL_GEN. The problem is now, that modworldgenmain runs ~ 2 or 3 times at gamestart, and also when world is not generating 1 or 2 times. Also modmain is running several times each gamestart. But the file where the actual level is saved, does only exist directly when doing the worldjump. That means that GLOBAL.OVERRIDELEVEL_GEN is not usable each time we load the game (without generating a new world). Therefore a component attached to the world is saving that information instead. So now I have a cluttered system to get the actual world/chapter, which is only known after the world added and started their components. The problem now is, that I don't 100% know when this component is successfully loaded. Eg. for the AddPrefabPostInit with the wormholes, I did a "AddTaskPostInit" with DoTaskInTime of 0.05 seconds. Cause I thought the world and their components are initilaiied before all the prefabs. But obviously this is not true, cause level was unknown. So now I do wait 0.5 seconds instead, wich is working. But in the PostInit of the world I now have to connect those wormholes I saved in GLOBAL variable in PostInit of wormholes. But I have to do it after I saved the wormholes, so I use DoTaskInTime of 1 second now. The result is, everywhere were I need to know the actual level, has a "DoTaskInTime" with some seconds to wait. But what if for some reason the game takes longer to load the world components? And it really sucks to make sure that everywhere the seconds are increased if it depends on each other. I this is very error prone, cause I can also miss to increase the time for depending things (like the wormhole code) and not always an error is thrown. All in all I don't like this and I hope there is a btter way of doing it... Well, I will look into that when I get time. Link to comment Share on other sites More sharing options...
ptr Posted September 19, 2017 Share Posted September 19, 2017 After endless trial and error, I finally found a way to disconnect the islands. However, it is quite a rough solution... By the way, maybe you can save the next world into a file only when jumping to the next world, and read it in worldgenmain but do not delete it. the file will be better to be in the shard folder to prevent affecting other save slots. Link to comment Share on other sites More sharing options...
Serpens Posted September 19, 2017 Author Share Posted September 19, 2017 (edited) 6 hours ago, ptr said: After endless trial and error, I finally found a way to disconnect the islands. However, it is quite a rough solution... By the way, maybe you can save the next world into a file only when jumping to the next world, and read it in worldgenmain but do not delete it. the file will be better to be in the shard folder to prevent affecting other save slots. nice I did not expected anyone to find a solution for the island generation O.ô Yes, only reason for deleting is to not affect other save slots. But is it save/possible to save in the shard folder? I would think if this would be possible DarkXero would have done this (sry egnlish is not my native, absolutely unsure if tense is correct :D) ... but of course even DarkXero may not think about every kind of solutions Feel free to also contact me via PM with details or if you want to discuss public, maybe we should start a new thread, to better fit the topic edit: Of course you can also participate directly at github with code improvements:https://github.com/Serpens66/DST-Adventure-Mod Edited September 19, 2017 by Serpens Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now