• I like level generation
    52 replies, posted
Man that's some really cool shit you have here, good job!
There is a new version available now. The compiler now optimizes the code that's compiled. This involves dead code removal, substituting variables for constants where possible, statically precomputing all the math expressions it can, and collapsing local variable slots. Overall, this allows for scripts to be understood a little better, with more local variables and more elaborate formulas without a penalty on performance. Because of the constants and dead code removal, it now makes sense to have debug code guarded by a simple switch variable initialized to false. A few system functions have changed (e.g. toString -> show, toInt -> readInt, minDelta), and added (e^x, log to base e). The reinterpret cast for manipulating bit patterns of floating-point numbers has been removed in favor of a new, overloaded "reinterpret" system function. Work on this has been extremely difficult for the past month, but I eventually had to tackle this topic.
If someone is interested in compiler construction and virtual processors, I've put up a new version again now that allows for looking at the intermediate code the compiler works with, and the final low-level code it outputs to the cache and runs on its virtual processor. I've used these textual outputs a lot in development for debugging and verification, and finally got around to making them accessible cleanly. : ) Yes, it was a bit much to make my own programming language for this, but that's the hobby. https://files.facepunch.com/forum/upload/132786/4a1784a4-44da-44aa-8add-2dd14ae996e3/2018-12-08 optimizations and code dumps.png
This is all very complex. Can you explain how this tool could help me, a mapper, create levels easier and more dynamically?
Very nice! Level generation is very underrated tools for certain kinds of games.
@Statua: I've not progressed far enough yet for anything about it to be easy. :| As time passes, less and less programming skill should be necessary to make use of it.
That's fair. I'll just watch quietly from the corner. More brush generating tools are definitely needed in hammer tho. So far I only know of the one that automatically fills the inside of buildings with trusses, made for TF2 maps.
If people could tell me what kind of tool support they deem useful, I wouldn't have to invent so much from scratch and develop less in an information void. :P For me, programming-wise, it's difficult to interpret existing geometry (existing brush face shapes and resulting displacement points). And I don't have support for preserving visgroups, groups and such stuff when saving a file. I've cut the latter out for simplicity. Everything else is a go. I have access to all the face and entity data and can synthesize new geometry. Stuff can just be saved into a new file to not break anything that existed before. Things such as doing some bookkeeping on entity names and properties as well as fiddling with texture, lightmap, etc. settings are possible. Complex entity systems and architectural parts too difficult to make by hand can be a staple of this thing.
Off the top of my head, I can think of a couple things: -Road path tool: Generates roads using this method where you can set the width of the road and the 'shoulders'. Doesn't have to turn them into displacements. Just put the brushes down. Should be able to follow a path in all 3 dimensions. Maybe have it so mappers can plan the path using info_targets with a special targetname placed where the path would change direction. -Yaw Randomizer: Finds all props that match the model name you enter and gives each one a random Yaw value. Good for trees. I'm aware something like this sort of exists in hammer but it's pretty useless since it only randomly rotates blank new entities. -Anti-floaters: Finds all props that match the model name you enter and moves the origin down until it hits geometry. Bit of a stretch but would be awesome if it works.
That's something I can work with. Keep the ideas coming. :3
There is a new version of the program available. It has no changes in the scripts, but comes with new data types for queues and associative dictionaries (implemented using hash maps). I've needed the latter to better make sense of entity data in existing vmf files. Also new are functions for reading and writing plain byte and UTF-8 files because I have a need for outputting .svg graphics files.
Really, really cool stuff, you and Silverlan should co-operate on Pragma
I've pondered a bit about @Statua 's suggestions, especially about the random rotation of models... and I think I have an elegant general solution for that. I'll just "invent" new entities, or rather, use existing entities with special names and new properties, and piggyback my vmf manipulation on those existing systems. For the rotation thing, there could be an entity that's dropped into the world and configured with a radius, and all models within that radius are then rotated. The entity itself can just be discarded when outputting the manipulated vmf. That way, a bit of interactivity is there, and it's done in the interface everyone already knows: In Hammer itself. - With a very short detour to make and load a new vmf file.
Not sure if it needs to be that complex. Just need something so I can take all my copypasta'd trees and rotate them randomly. Currently, I just do find by model, select a quarter of them, and rotate them 90 degrees. Then repeat for the 2 remaining quarters (with the last not being rotated). Its not ideal tho.
Okay, this was surprisingly difficult. I've managed to rotate things around their "up" axis regardless of their orientation before that. This could work with foliage on a hill/slope, too. I had to use a method to calculate the Euler angles that I've learned 10 years ago and luckily still had readily available. Not all drums are rotated because the control entities' radii intentionally didn't catch all of them. Before (the info_nulls are the control entities): https://files.facepunch.com/forum/upload/132786/4c8661e0-29dc-40cf-8302-28d9cf6ff3f2/rotations 1.png After: https://files.facepunch.com/forum/upload/132786/225f678b-2ea8-4779-bac8-3e0e39a65bdf/rotations 2.png
Here's a new tool. This goes through all brushes in the level and detects which textures are mirrored. It then mirrors those along their horizontal axis. This can prevent mirrored text and icon oversights everywhere in the brush geometry of a level. Things might still be upside-down in the output, but they will be readable. https://files.facepunch.com/forum/upload/132786/e088fe44-73a7-4738-99d0-49eab60d8ef6/2018-12-28 unmirror textures 1.png https://files.facepunch.com/forum/upload/132786/ba6efbc9-2963-4f45-89eb-f3f3906b3177/2018-12-28 unmirror textures 2.png It's included in the new version from today.
Damn these are good. Unfortunately, I would need a UI to use it as I'm prone to breaking things.
I can't offer you a UI beyond the one you already have in Hammer. I could walk you through it in chat if you like!
I've scrapped my original idea for a deathmatch level and started anew. This is how far I've got so far. https://files.facepunch.com/forum/upload/132786/a3fb293c-31b0-4421-94ee-102875e1ad0f/image.png My todo list is still long, but it's a nice feeling to run through a level that, albeit following your own rough layout, is defined by tons of random decisions from the program. Thinking about level design is so different when you don't make definite decisions about how things should look in one particular version of the level, but rather work out the rules governing what things can be like. Every corner of the level must have two flights of stairs to reach all stories, but their orientation as well as order is random, and so is will be the decision of that corner of the level is even generated in the first place. Does this corner look nice? If so, that is by chance. https://files.facepunch.com/forum/upload/132786/b57ac1f5-37f2-4d7e-9767-c730b9ca38b1/r1.jpg There are 2^4 = 16 ways the central room can be connected to the corners if all four are generated - with the small tunnels going either way: https://files.facepunch.com/forum/upload/132786/7b958793-cb7d-4683-b7ed-8dae1e5ec9bf/r2.jpg Some key measurements of the floor plan can also be randomized within some constraints - so the central room or a corner needn't be squareish, they could also be elongated a little. The lighting here is almost completely random. The light levels are varied slightly between lamps. I had to compromise between scattering lamps randomly and analyzing/defining enough so no too dark spots would occur. That's why all flights of stairs now have lamps directly above them. https://files.facepunch.com/forum/upload/132786/1ffe98ab-9784-4b4d-813c-06125f634c84/r3.jpg The hallway we're looking down here connects two of the level's corners. If only one of them was generated for this side, it would not exist, and there'd instead be a wall ahead. When I hit generate again, it looks just a little different: https://files.facepunch.com/forum/upload/132786/765f8e89-2aad-4efb-87c0-4fd1dbcf32a8/image.png And again: https://files.facepunch.com/forum/upload/132786/73bb8e91-7710-4908-99ec-84403c8d703e/image.png
The layout of that level (levels? level type?) is now finished and cleaned up. A new version of Badger with the script to generate this level is available on the project page (first post, t-dm2.bad). At the moment, you need to place the player start manually. https://files.facepunch.com/forum/upload/132786/d5348e5b-fe61-4d26-8552-e5bddb8a9453/2019-01-18 deathmatch editor.png
That deathmatch level is still my main project now. One strategic goal of this level generation part for me was splitting it up into different stages that could be combined in various ways. The theme (textures, lighting, etc.) would be independent of the layout, and there could be various gameplay/item distribution styles. I've taken the time to split up the code accordingly, and then went a step further and made independent precompiled libraries from those compilation modules. Unfortunately it crashed. This was the first time things got really recursive with my library system and I also needed to load stuff on demand. It took some debugging to get right, but now it is up to the task. There is a new download available - It's pretty much just a maintenance release with the code for this level restructured and the library system finally working as intended - able to go wild with loading new libs practically anywhere in the code and recursing calls in cycles like there's no tomorrow. This was quite a challenge and I was already afraid I'd figure out why it could _not_ work as I wanted.
Here is some progress in detailing the main theme. I should be able to put together another release soon. Yesterday I got wall details working, today I've added two more variants of those. https://files.facepunch.com/forum/upload/132786/a945602d-3e07-4fca-903a-4f4d7a7ef68d/D0hvwaHWsAM9itx.jpg orig.jpg https://files.facepunch.com/forum/upload/132786/5475579c-4b7d-4025-a04d-9d6bc5cb7032/D0hvkhGXcAA3Inc.jpg orig.jpg https://files.facepunch.com/forum/upload/132786/d9438cd9-0150-4bd1-ac1e-9981a84b35e0/D0hwIigWoAERXh5.jpg orig.jpg https://files.facepunch.com/forum/upload/132786/ac2cf735-a40a-4540-9ba5-ff832e59c3b2/side.png
A new version of Badger (03-01) is available at http://shrinker.seriouszone.com/projects/Badger/ . The other version of my website will follow later. This version has details in the "Concrete" theme, and a new script "gen random dm level.bad" to do just that. https://files.facepunch.com/forum/upload/132786/b0b0a12a-eb39-4b91-a9f8-3599fc865028/image.png
Sorry, you need to Log In to post a reply to this thread.