Jekyll2026-02-15T13:42:06+00:00https://melon.zone/feed.xmlmelon’s zonegamedev and other bits and pieces by drmelon (a. j. brown) drmelon<contact@melon.zone>pickin’ up old skills2026-02-15T00:00:00+00:002026-02-15T00:00:00+00:00https://melon.zone/blog/blog/life/gamedev/tech/old-skillsah! the refreshing feeling of getting back into an old, lapsed hobby and/or skill. recently, i’ve taken to dabbling in one of my old passions. a long time ago, before i decided on game development as my career, i was thinking about going into cybersecurity. i had a knack for burrowing into filesystems and finding gaps in protections early on in my dalliances with computers.

for example, i remember clearly a time when i was enjoying some shareware creative software on a cd from the front cover of Computer Buyer magazine, and i realised that the 30-day lockout was entirely part of the software, since i didn’t have an internet connection on the PC i was using at the time - so it obviously had no way of phoning home to a server or anything. so i did what any enterprising young 10 year old would do and messed with the date/time settings on the PC to use the software whenever i wanted. later, i found that it stored the install date in a registry key, so i set it years in the future and found to my delight the software displayed a negative “days left” counter in the About window.

that was the first taste of what would become a hobby of setting up little puzzles for myself and cracking them, especially once i started learning some programming skills. eventually this progressed to experimenting with networking and particularly once i got into using Linux for the first time in high school, using my laptop to break into my aging desktop PC through various means. my first ever paid job was a couple months at a (2-hour-away) local it management and cybersecurity company, writing perl scripts on some crusty laptop running Slackware to locate lost emails that some rogue spam filter had obliterated accidentally. figuring out how to get the spam filter to not reject them a second time by messing with the email post IDs on the backend felt very natural at that point! but, i found myself craving creativity, and had already set my sights on game development at this point.

so, fast-forward to now; reminiscing about those days after playing a little bit of hackmud (and feeling a little underwhelmed by it once i got through the initial tutorials), i started messing with VMs! turns out, there are entire sites full of vulnerable-by-design toy VMs you can spin up and break into. they’re kind of like virtual escape rooms, except you’re not really escaping the room so much as intruding into it. intrusion rooms!

it’s a lot of fun. some people really make an effort to build plausible real-world looking VMs, with little user accounts with their own stories and internal communications (e.g, a sysadmin berating another user for having a bad password, only to be backing up ssh keys in an unsecured storage location). it’s really, really cute, and i love that kind of narrative design meeting practical security teaching. i’ve even thought myself about building some crackable VMs with maybe a larger story focus. could be fun to do, and sorta blend my interest in narrative game design with the cybersecurity stuff!

it’s also an interesting thing to do to remind myself of the various vulnerabilities computers and servers can have, and how important it is to follow best-practice guides when it comes to server hosting and things like that - especially important NOT to start fiddling with settings unless you really know the full ramifications of what they can do!

]]>
drmelon<contact@melon.zone>
making, and becoming2025-11-24T00:00:00+00:002025-11-24T00:00:00+00:00https://melon.zone/blog/blog/life/making-and-becomingI feel like making things is intrinsically important to being the person I am. I don’t know exactly how to explain it, but when I’m not making something it feels a little like my existence is on hold. Not like I stop existing or anything, but more like… I’m just not really living when I’m not making something. It doesn’t have to be a public work, either; I don’t mind so much about the reaction to the thing as I do the fact that the thing has undergone the process of being made. It doesn’t always have to be finished; just the picking away at the creating is the key. And it doesn’t need to be big, sometimes just cooking a nice dinner satisfies the need to make!

I think it’s because when I’m making something, I’m also processing all of the millions of tiny things I thought or saw over many days. It’s a bit like dreaming, I suppose, in the sort of way they are made up ofa swirl of all kinds of life experiences.
Tumbling them around and condensing new ideas and thoughts and feelings out of them, and then spinning them into the work, like geologic strata. And so, when I’m making something, I’m also kind of making myself too, a little bit. And I think that’s the reason I feel the need to make things so much, because it feels like I’m participating in being alive rather than just observing it.

I don’t have any particular interest in the balance of how much I make versus how much I experience, either. I know some folks get irritated that they “consume” more than they make, in terms of media, but I think fundamentally that because experiencing a work is chiefly done simply by it existing within your awareness, it would be kind of impossible to make more things than you experience.

I think I’m going to just try and keep making things as long as I’m alive. The form they take will vary wildly over my life, as they already do. Today, I made this blog post, an update for my 88x31 icon, and my QBJ3 entry. Tomorrow, who knows? Maybe some photography, maybe some food, maybe just a silly song I’ll never share with anyone. Maybe a tiny sculpture from the small wad of blutack on my desk, which I’ll absentmindedly crush against the edge of my keyboard with my thunb while I think about stuff at work. The possibilities of what can be made are completely infinite.

Thanks for readin’! I hope you make some things too!

]]>
drmelon<contact@melon.zone>
repeating digit birthday!2025-11-04T00:00:00+00:002025-11-04T00:00:00+00:00https://melon.zone/blog/blog/gamedev/repeating-digitsI’m 33 years old today! That’s as many as three elevens, and that’s just dandy. As is my wont, I’m hammering away at my keyboard to get my birthday thoughts enscribed and on the internet for all to see. It’s been a pretty good year so far! I like to break the previous year apart into little bits when I do this, so here we go again:

Day-to-day Work Stuff!

My game optimization services freelancing gig has been working out well for me this year! I’ve been helping lots of nice and lovely folks get their games running fast and smooth on the platforms they like. When I got started doing this as a freelancer early last year, I wasn’t sure if it would entirely work out, but it’s been great. I’ve been able to keep the lights on, work on interesting things, and help people - and that’s all I really wanted!
Things have also been ticking away in the Very Evil Demons co-op too! Nothing huge for us, but nice bits of prototyping work and mentoring work here and there, also with lovely people! So all in all, my day-to-day has been trundling along rather well!

Projects, Projects, Projects!

I have been snowed under by in-flight projects. It’s been a lot of fun, but also a little bit more stressful than I’d like trying to spin all these plates. I think my capacity for personal projects along with everything else in my life is probably around three; any more projects than that and I can find it a little paralyzing trying to choose what to work on, and less than that I can find it difficult to stay super focused. Something unique for me this year has been that most of the projects were and are longer term things; I think I should make sure I have some smaller ones in rotation to stop myself from feeling entrenched.
As for the projects themselves, probably the big-ticket one was my recreation-slash-fangame of a certain part of Deltarune Chapter 3 on the NES!. This one took about three months and was a hell of a lot of fun. In true melon style and spirit, instead of writing a proper project page for it and a blog post about how I built it, I instead have decided to try and take on making a video about how I made it, which, uh, is proving to be quite a lot of work to edit together. The VO runtime is about 45 minutes, so… I might split this up into separate parts…
I’m also participating in Quake Brutalist Jam 3 this year! I love working in Trenchbroom and making maps, so it’s been really fun to build something with the all-new total conversion the QBJ3 organizers put together this year. It’s probably going to be my biggest and most detailed map yet!
And I still have a bunch of things to do for various unannounced things, and I really need to get back to working on my little first-person-acrobatic-shotgun game, and and and-

Playing Videogames

Oh yeah! I played a bunch of games this year so far. Amongst many, some standouts I wanted to say somethin’ about!

  • Deltarune Chapters 3 and 4 - how do Toby Fox and the team keep doing it? How do they keep managing to perfectly thread the needle between comedy and mystery, text and metanarrative?! I can’t wait to find out what happens next. I mean, obviously you know I liked this, since as I already mentioned I spent 3 months making a fangame for it on a console older than I am. As you do!
  • Skin Deep - hilarious and detailed comedy imsim. You probably have seen stuff about it on my blog before!
  • Hollow Knight Silksong - brutally difficult at the start, but opened way way up for me once I explored some more and got a bunch of tools! Saw most of the endings, and finished it out at 92% complete. Fantastic movement, combat, art, and vibes. A truly worthy sequel, and you can really feel the love poured into every centimeter of it.
  • skate. beta - a fun game to have little chill hangout sessions in; still nailing the skating feel, still has a bunch of funny comedic physicsy things you can do. I wish EA didn’t own it.
  • Donkey Kong Bananza - I just finished this the other day! A very different take on 3D platforming from the Mario Odyssey team. Top-notch gameplay, if a bit mentally fatiguing in extended sessions from going 100% ape at all times. Highly recommended to make gorilla noises and yell as soon as you see a banana on screen. Kind of surprised though, that to me, most of the level music wasn’t super memorable?
  • PEAK - This is real fun to play with friends, but I think I got the most out of it was actually playing it with people I was freelancing for. Two of my clients this year had PEAK multiplayer sessions where they invited me, and I think hauling eachother up a mountain and feeding eachother maybe-poisonous berries is actually a great way to bond and get to know people better.

Food and Cooking

I’ve been eating a lot less red meat this year due to a few different factors, and that means I’ve spent a lot more time cooking with alternatives like tofu. One thing I’ve been enjoying a lot has been making what my girlfriend and I call “the crumblies” - by grating up firmly pressed tofu into shreds, dousing them in soy sauce and marmite, and then frying until crispy and crumbly, you get this really tasty minced-beef-like stuff. It’s a great ingredient to mix in to make chilli, tacos, or bolognese and it keeps super well. It’s has a really robust savoury flavour that’s surprisingly meatful!
In addition to this, we got a Panasonic bread machine at the tail end of last year after being frustrated with short-dated supermarket bread, and it has been awesome getting to enjoy freshly baked bread every few days. We’ve really been putting the machine through its paces; where it really shines is the ability to put in all the ingredients late at night and program it for the morning, so that I can get up and take the fresh loaf out and have a slice at breakfast. We’ve made a few different types of loaves - a cheese and jalapeno loaf, an olive and herb loaf, and so on, but our standby right now is a 50-50 white flour and wholemeal flour mix with toasted seeds. Lots of good flavour and texture, and perfect when thickly buttered with soup.

Wrappin’ Up

Well, I think that probably wraps things up for this post for now! I swear I’ll get back into blogging more often, it’s been real fun writing this post. Have yourselves another good year, friends!!

]]>
drmelon<contact@melon.zone>
reblog - Noel Berry, Making Games in 20252025-06-19T00:00:00+00:002025-06-19T00:00:00+00:00https://melon.zone/blog/blog/gamedev/reblog-noelfbJust wanted to share a link to this excellent post by Noel Berry, about making games with small frameworks. I absolutely adore doing this as well, and I feel like this post summarizes so many of my feelings about it in a very succinct and easy to understand way.

]]>
drmelon<contact@melon.zone>
skin deep modding guide 12025-05-07T00:00:00+00:002025-05-07T00:00:00+00:00https://melon.zone/blog/blog/gamedev/skindeep-moddingRecently, I’ve been playing the fantastic comedy imsim, Skin Deep by Blendo Games. It’s made in a spinoff of the Doom 3 engine, and has a built-in mod loader on the main menu, so I decided to crack open the game’s existing maps and figure out how to make my own! Read on for the things I found out, and how to get started yourself.

My Experimental Mod

I made a bunch of weird little test thingimajigs in a big boxy map as I was learning how the levels worked. You can see a video of it on YouTube here:

As you can see, the map is full of little text nodes explaining how to make bits of it, so you can download the mod yourself and try editing it yourself! Click here to download the mod.

The Guide

This is a little text guide describing how to set up Skin Deep for modding and how to make your first functioning map.
NOTE: This guide is now outdated. Check out the official Blendo guide on Steam, and the in-game Mod Museum!

Requirements

You will need:

  • Skin Deep (of course)
  • The latest version of DarkRadiant (This is version 3.9.0 at the time of writing)
  • A text editor.

Initial Setup

First, we need to make the mod folder so that Skin Deep can load our custom map, any custom textures or script behaviours we need, and so that you can distribute it to other players.

  1. Go to your Skin Deep installation directory. It’s usually in <Steam Installation Folder or SteamLibrary folder>/steamapps/common/Skin Deep/ if you have installed the game from Steam. You should see a folder named base in there; that’s the base game, and you can look at all the scripts and assets there for inspiration!
  2. Create a new folder next to base named whatever you like; it should probably not have any spaces in the name though. This is your mod folder!
  3. Inside this folder, create two empty files: description.txt and pak000.pk4.
  4. Write a single line of text in description.txt; this is how your mod will display in the ingame mod browser.

Setting Up DarkRadiant

Now we need to set up DarkRadiant so that we can make a map for Skin Deep.

  1. Open DarkRadiant. If it’s your first time using it, you will be prompted to configure the Game Setup.
  2. Choose “Doom 3” as the Game Type, and use Skin Deep’s installation directory.
  3. Enter base in the “Mod Base” field.
  4. Enter your mod folder’s name in the “Mod” field. This will let DarkRadiant read your map, but also reference all the existing sounds, models, textures, etc from the base game.
  5. You can perform the above steps using DarkRadiant’s Game Setup menu option if you already use it - but you already know that, if you do!

Creating your first map

  1. Create a new map in DarkRadiant, and save it inside mod-folder/maps/. Name it whatever you like; in this guide, let’s name it first_level.map.
  2. Then, create a new empty file next to it in mod-folder/maps/ called first_level.script.
  3. Write the following in that file:
    namespace first_level
    {
     void main()
     {
         sys.println("loaded map script first_level!");
     }
    }
    
  4. This file will be used by your map to perform any kind of custom logic, like tracking objectives or performing special scripted actions. You can read some of the base game map scripts for examples of the kinds of things they do!
  5. Make a simple box room in DarkRadiant. Exactly how to do this is a little outside the scope of this guide, which will focus on Skin Deep specific setups, but the DarkRadiant User Guide and the DarkMod wiki’s Video Tutorials Page do a great job of how to use the editor to make maps for the community-maintained Thief-like game “The Dark Mod”. If you are familiar with Hammer or TrenchBroom, then a lot of those skills will transfer over to DarkRadiant - I only started using it a few days ago myself!
  6. Edit the worldspawn properties for your map, adding/setting the following keys and values:
    call: first_level::main
    cryo_briefing: Welcome to my cool level!
    shipname: First Level
    shipdesc: Simple Box Freighter
    
  7. Create an info_location entity somewhere in the room. This will tell the game that this room is a specific place on the ship; a lot of systems depend on locations existing, such as cats being able to tell you where the nearest key is.
  8. Set the location value on the info_location entity to name your room. In this tutorial, we’ll call it Main Room.
  9. And just so it’s not dark in here, add a light to the room. We’ll discuss destructible lights later.

Spawning Nina and Testing

A level is nothing without Nina Pasadena, our favourite deep-freeze insurance agent! Let’s get her out of cryosleep and into action.

  1. Create a second box room away from the first; this room will hold Nina’s cryo pod interior, so it needs to be unlit and inaccessible to the player during normal gameplay.
  2. In this room, add an env_cryointerior entity. This is where the player will spawn, and the game will automatically set up lights and interactivity for it.
  3. Back in the first box room, create an env_cryospawn and place it on one of the walls, so that its back side is flush with the wall. This is where Nina will pop out at the start, and where the player can peek into the level to get a sense of what to do when they emerge.
  4. Set the env_cryospawn’s target0 property to point at the env_cryointerior you made. Its name by default will be env_cryointerior_1.
  5. Now you’re ready to test your map!
  6. Open Skin Deep, and load your mod from the mods button on the main menu.
  7. Then, open the developer console with Shift+Esc, the ` key on a UK keyboard, or the ~ key on a US keyboard.
  8. Type dmap first_level and hit enter. The dmap command builds lighting and collision for your map - you will need to run it every time you make changes to your map.
  9. You should spawn into the cryo pod and be able to enter the level! Hooray!

Adding Stuff

It’s a little boring to walk around an empty room with no items, cats, pirates, or anything to do. So let’s change that, shall we?

Cats and Keys

Get meowt of here!

  1. You can add a cat to rescue by creating an env_catcage or env_catcage_b entity. They both work identically, but they have different voice acting.
  2. Set the name_cat property on the env_catcage to give this cat a name! In this tutorial, we’ll call them Sparkles.
  3. Don’t forget to add an item_cat_key to the level… otherwise, that cat’s never getting out!
  4. The game will automatically track how many cats are in the map, and the player’s progress.

Necessary Machinery

Many of the ship’s machines provide vital gameplay functionality for players. Let’s get the basics set up!

  1. You’ll need a health station when you slip on a banana peel, get shot, step in glass, get exploded, and so on. Add one by creating an env_healthstation entity, and place it so that the little handle is facing outwards from the wall.
  2. It’s really, really easy to lose items - every map needs a Lost and Found. Also, pirate skulls will complain in the debug console if one doesn’t exist, so it might even be necessary to get them to work right. Create one with an env_lostandfound entity.
  3. A healthy ship requires frequent repairs - if you damage a vital system in a pirate-jockeying-related accident, you’ll need a way to get it working again. Create a func_repairhatch entity and place it on the ceiling. Then, create an aas32_flood_flybot entity and place it in the air; this will generate pathfinding for flying objects like swordfish and repair bots.
  4. A ship isn’t a ship without an FTL drive. No, really, a bunch of stuff does not work unless you have an FTL drive - this is a holdover from earlier versions of the game. You can place an env_ftl_mini outside the ship somewhere to satisfy the requirement if you don’t want a big internal one.
  5. Players will be lost without an in-game map screen, and need a way to save the game. Details on setting up the visual component of the in-game map screen will be given later in this guide, but for now, place an env_infostation on a wall. It will automatically track various kinds of objects for you once the visuals are set up, and you can now save the game and request repairs.

Deadly Weaponry

The tools of the trade.

  1. Many of the game’s useful items are named moveable_*. For example, Soap is moveable_soap. Place some around and the player can pick them up and hurl them around. Same goes for bananas and pepper.
  2. Loadable weapons like the shotgun (moveable_item_shotgun) can be given initial starting ammo. For the shotgun, use the inv_ammo_shells value to set how many shells it starts with already loaded.

Pilfering Pirates

Let’s get the Numb Bunch involved.

  1. Create an aas_flood_48 object on the floor. This will produce navigational data for the enemies to use to navigate your map.
  2. Create a monster_thug entity; this is your first pirate! Name them with their displayname attribute. We’ll call ours Stinky.
  3. You can attach some (but not all) objects to a pirate’s belt with the def_beltattach1, def_beltattach2, etc variables. Try attaching a cat key by setting def_beltattach2 to item_cat_key!
  4. Create an info_enemyspawnpoint on the floor somewhere. This will be used by your pirates skulls to respawn; they will automatically pathfind to it.
  5. You can also set up patrols for enemies by making their target0 point to certain path entities, but I haven’t fully experimented with this yet. Without a path target, they will patrol randomly in rooms and occasionally go through doors.

Doors

One room is simply not enough. It’s getting too busy in here with all this stuff! Let’s make some more rooms, and some doors between them.

  1. Create a second room joining the first; cut a hole in the wall so you can walk between them. Make sure not to leave any gaps that would cause leaks. Also create a second info_location and name it!
  2. Add a func_static entity, and set its model variable to models/objects/doorframes/frame_b.ase. Set its gui variable to guis/game/doorframe_infopanel.gui. Place this in the doorway between the rooms.
  3. Create a func_door_single entity and place it in the empty area that the func_static provides; it should fit like a glove.
  4. Set the autodir value to 1 on the func_door_single. That will allow it to open and close correctly.
  5. Set the autobutton value to 1 if it is not already set. This will let the door spawn buttons on the frame!
  6. Now, here’s a slightly tricky part. Create a brush the that slightly overlaps the doorframe’s size, and make it 1 unit thick so that it can fit inside the door’s model. Give it a nodraw texture on all sides, but then set a single side facing out from the door to the visportal texture. This is a visportal, and creating these will be very useful for a huge number of reasons.
  7. Place the visportal inside the door so that it completely seals the hole, and sits inside the door model, dividing one room from the other.
  8. Create an info_locationSeparator and place it so that it overlaps with the visportal. This will tell the game how to split the two locations up, and will help with things like vacuum breaches (we’ll get to setting up outer space later).
  9. Run the map with the dmap command and you should be able to walk between the two rooms!
  10. Add env_sign_marquee96 entities on either side at the top of the door frame to provide useful signage to the player. Set the gui_parm0 variable to set the text of the signs.

Vents

Why take the obvious route, when you can take the sneaky one? Let’s make a vent.

  1. Create a third room. Position it some distance from the first two, so that there’s room to crawl between the rooms. Don’t forget its info_location!
  2. Make a tunnel between the third room and whichever room you want to connect it to; it should be 64 units wide, and 32 units tall. If you have corners in your tunnel, make them a little bigger than 64x64x32, to help clue the player in they can turn around, if you like.
  3. Add a func_static entity, and set its model variable to models/objects/grate/grate_hole_64x32.ase. This is similar to the door frame model, and gives you a nice frame in which to position the vent itself. Put it just inside the tunnel holes, so that it is flat on the outside and has no lip sticking out.
  4. You can also set its noclipmodel value to 1; this will prevent the player bumping into it during gameplay, but may allow things like bullets in and out. If you do not set this to 1, you will need to make a tiny clip brush with a slope that lets the player crawl over the lip of the model.
  5. Create a func_ventdoor_inter_64x32. This behaves much like the door. Set its movedir value to -1. Place it within the vent frame. Place it so that the handle on the texture faces the room and not the vent itself.
  6. Set gui_parm0 to choose which text to display on the outside, and gui_parm1 for the text on the inside.
  7. Create a thin visportal, like you did for the door, and place it so that it intersects the vent door. You do not need a locationSeparator for vents.
  8. Make another vent door with a frame and a visportal at the other end of the tunnel for the other room. Boom! Vent time!
  9. You should now be able to get into and out of the vent when you compile and run your map! But it’s not dusty inside the vent, and you can turn around easily. To solve this, you need to add a brush inside the vent for the length of the tunnel, a little smaller than the vent itself, and assign it to be a func_confinedtunnel. Set its texture to the confined texture.
  10. Set the baseangle value on the func_confinedtunnel to select which direction to confine the player in. This will usually be either 90 or 0.
  11. Set its confined value to 1. This will restrict the players movement, shadow them, and make their sneeze meter build as long as they remain inside the trigger volume.
  12. If you have corners in your tunnel, or larger spaces that you would like to remain dusty but not constrict the player’s movement, create new func_confinedtunnel brushes and set their confined value to 0. They will keep the player shadowed and keep building the sneeze meter, but won’t stop them from turning.
  13. These volumes will also enable vent purges if a pirate sees the player enter a vent.

Vent Barricades, Keypads, Notes

It’s too easy to get between rooms. Let’s add a simple keypad puzzle.

  1. Edit the func_ventdoor_inter_64x32’s variables and set barricaded to 1. This will make the vent locked by a barricade when the level starts.
  2. Add an env_maintpanel_vent on a wall somewhere. When the player interacts with this, it will unlock the vent! Compile and play the map to see it for yourself.
  3. Seems a bit easy… let’s lock the maintenance panel. Add a func_keypad entity near the panel, and set its target0 variable to point to the panel. The panel’s name, by default, will be env_maintpanel_vent_1.
  4. Then, set the func_keypad’s code variable to a four-letter word, like bees.
  5. If you play the level now, you have to type in BEES to unlock the panel and then unlock the vent!
  6. So far so good - but the player won’t know that, so let’s add a note to the wall.
  7. Create an env_note_paperwall entity and put it on a wall somewhere. Write some useful text in the gui_parm0 variable, something like:
    Hey, numbskulls!\n
    Don't forget the password: 'BEES'!
    
  8. Take care not to use double-quote marks, as they will terminate the text early in-game.
  9. Great! But the code is the same every time, and in the base game, it isn’t. So what’s up with that?
  10. Open the worldspawn properties, and set the variable keypad_random to 1. This will randomize keypad codes every time the level is played!
  11. But now our note doesn’t make sense any more. BEES will not be the password! To fix this, set the note’s target0 property to point at the func_keypad (by default, it will be func_keypad_1).
  12. Edit the gui_parm0 text, and replace the password with the magic string %s%s%s%s, so it’ll look like this:
    Hey, numbskulls!\n
    Don't forget the password: '%s%s%s%s'!
    
  13. And boom. Now you’re cooking!
  14. Note, the string subtitution doesn’t work unless keypad_random is on. So if you use fixed passwords, you’ll have to write the notes manually.
  15. Forget-me-nots work the same way, they just use a string to display the code. If you make one, just set its gui_parm0 to %s%s%s%s.
  16. It’s also possible to mangle the order of the displayed code, like showing it backwards; set the codeindexes value on a note to any order other than 1234 (e.g, backwards would be 4321) and it’ll automatically rearrange the code when displayed. Good for sneaky pirate op-sec..!

Airlocks and Outer Space

Whew, it’s getting kinda cramped in here. Let’s get some fresh air… wait!!!

  1. There is currently nowhere for Outer Space to exist. Make a large box around the entire map, and set its texture to one of the sky textures, like textures/skies/sky_pinksky. We can set up a more complex skybox using an info_portalsky and the skyportal texture, but that’s not necessary right now.
  2. Now that the ship is safely inside and the map won’t leak, punch open a hole in one of the rooms.
  3. If you play the game now, you’ll notice that, uh, you can just… walk outside, and there’s air out there, and you can fall down into nothing with gravity that should not be there.
  4. Let’s fix this. First, create an info_vacuum entity outside the ship somewhere. This tells the game that this location has no air.
  5. Next, create an info_location out here in space, and set the location value to exactly #str_00000. This specific localisation key is required to tell the game that this particular vacuum location is actually outer space itself, and not an interior location in the ship with no air; if you don’t have this location set up correctly, Skullsavers will not correctly disappear when thrown out into space, and the lost and found will not work either.
  6. Make the hole in the ship big enough to fit an env_airlock object; make sure to rotate it so that the external door faces outside, and not inside the ship.
  7. Seal the edges of the airlock with walls; this may mean you need to make your room a little longer, or otherwise you can have a kind of tube that the airlock sits inside.
  8. Place thin visportals inside each of the two door areas of the airlock to seal the entrances to it.
  9. Now when you run the game, you should be able to open the airlock and exit to space correctly! You can fly around, and dunk that pirate’s skull out here!

Windows

Peering out into the void…

  1. Windows are a little complex compared to airlocks. Create a window-sized hole in one of your rooms, out to space.
  2. First, create a patch brush in DarkRadiant. This workflow is a little strange compared to the usual brushes, so you may need to consult the manual a bit. I certainly had to! This will make a one-sided rectangle brush.
  3. Use the Patch Thicken option; depending on the axis that the window will be placed, select thicken on X, or Y. Set the thicken value to 0, and it should make the patch be a two-sided plane; it will have no depth, but will be solid on two of its sides.
  4. Place this patch so that it completely fills the window area. Give it one of the glass textures; I recommend glass1_spacewindow_filter_subtle so that it’s easy to see through.
  5. Set this patch to be a func_fracture entity.
  6. Next, create an info_vacuumSeparator entity, and position it so that it overlaps the func_fracture.
  7. Create a visportal, and make sure it wraps around the func_fracture and overlaps the info_vacuumSeparator.
  8. Create a thicker brush that surrounds all of these other brushes. Set the texture to windowseal01_interior for the face facing into the room, and windowseal01_exterior for the face facing outside the ship.
  9. Set that brush to be a func_windowseal entity.
  10. Now the tricky part. Make the func_fracture’s target0 target the info_vacuumSeparator, and its target1 target the func_windowseal. Then, make the func_windowseal’s target0 target the info_vacuumSeparator, and its target1 target the func_fracture. Whew..!
  11. Now, when you play, you should be able to see out of the window and break it with something to vent the room to space. If everything is OK on your map, only that room should be vented to space, and other rooms (which you can visit with a vent or with the noclip command) should still function normally. You may need to adjust the position of the seal, visportal, and func_fracture to get things to render and behave correctly. I don’t know the exact details, but sometimes it doesn’t work quite right and you have to nudge things around.

Signal Lamps and Pirate Invasion

So, we can rescue cats and dunk pirates. But how do we finish the mission? Let’s get the level’s last setpiece working.

  1. Create an env_signalkit and put it somewhere in your map. Inside, outside, your choice! Usually the base game puts them inside near airlocks and outside near airlocks, windows, and trash chutes. If Outer Space is set up correctly, you should be able to summon a pod the usual way. But first…
  2. Create a closed-off space in your map, like we did way back for the cryopod, then put an env_catpod_interior inside it. This will automatically populate with weapons for the invasion phase, and will appear when you summon the pod with the signal lamp.
  3. Now for the pirates. Create a func_pirateship somewhere in your level; one of the corners in space is the best idea. It won’t be visible to the player when the game starts, so don’t worry if it would be seen from somewhere.
  4. Create a NURBS curve in DarkRadiant. This is a special spline object; you can fill in an arbitrary number of control points in its curve_Nurbs field. Create a path from the pirate ship’s spawn location to a point about 128 units outside your airlock.
  5. Set the curve to be a func_splinemover entity.
  6. Create yet another locked-off, unlit area in your map. Make this one far away from the ship - outside of the skybox, even. This is where you’ll place the pirates who come aboard the ship in the invasion; you can use monster_engineer for tougher pirates that use swordfish, for example. Put a pirate in here, and set their hide variable to 1.
  7. Set target0 on the func_pirateship to point to your func_splinemover NURBS curve.
  8. Set target1 on the func_pirateship to point to the reinforcement pirate inside the dark box.
  9. Set target2 on the func_pirateship to point to the airlock.
  10. If all went well, when you summon the catpod and rescue the cats, the pirate ship will spawn, travel along the spline curve, and then dock at the airlock. Once docked, it will move the pirate from the locked-off area to the interior of the ship, and they will move through the airlock.
  11. And that’s it! Your level is done, basically! You can now get the glorious “NINAAAAA!” chant after disposing of the invading pirates! Just one last thing…

The Interactive Map

Information superhighway…

  1. To get the infoscreen map and the player’s wrist-computer map to work, there’s a little setup that needs to be done for your map.
  2. First add two target_null entities in your map called loc_topleft and loc_bottomright.
  3. Position them so that they form the top left and bottom right corners of a square that covers the boundary of your ship’s floorplan (this is easiest to do from the top view in DarkRadiant). It must be a square, not a rectangle! The game will tell you in the console if the sides aren’t the same length.
  4. Add two properties to your worldspawn called map_topleft and map_bottomright, and give them the values loc_topleft and loc_bottomright respectively.
  5. Add a .tga format texture for your map display to guis/assets/mapguis inside your mod folder. The top-left and bottom-right pixels will be relative to your top-left and bottom-right location markers. Look at the base game maps for examples.
  6. Create a materials/mapgui.mtr file inside your mod folder. Using the base game’s file as an example, add a new entry for your new map, referencing the new texture you just made.
  7. In the worldspawn, add a new property called mtr_image and make the value the name of the entry in mapgui.mtr you just made.
  8. Close and re-open Skin Deep if it’s running, to refresh the image cache when you load your mod.

Loading your map from the Menu

It’d kinda suck if players had to open the devconsole to play your map, right?

  1. Add a new file to your mod folder: def/maps.def.
  2. Write the following in it:
    mapDef first_level 
    {
     "name" "first_level"
     "description" "First Level"
     "singleplayer" "1"
     "levelindex" "1"
     "internalname" "first_level"
     "levelimage" ""
        
     "size0" "805702930"
     "size1" "805702930"
     "size2" "805702930"
     "size3" "805702930"
    }
    

Note: the size* values here relate to the estimated time the loading screen should take, to help inform the progress bar. There is a warning against altering this value in the pre-existing test_scout map by level designer and Skin Deep developer Suzanne Will, so I definitely won’t touch it!

All Done!

And that’s as far as I’ve learned! There’s so much more to find out - security cameras, turrets, pirate loadouts, window barricades, door keycards… get out there and make something awesome! You can share your map by zipping up your mod folder and giving out to people. At the time of writing, I haven’t yet found the workshop upload tools, but they’re probably not too hard to figure out somewhere.

Thank you for reading this guide. If it helped you, please give this guide a mention when you upload a cool map for other people to play! Adios!

]]>
drmelon<contact@melon.zone>
redscale adventures2025-03-18T00:00:00+00:002025-03-18T00:00:00+00:00https://melon.zone/blog/blog/fun/photography/redscale-adventuresI recently got hold of a roll of Harman RED; it’s a 35mm redscale film stock. Redscale film is film that is wound backwards in the film canister; that is, it’s wound in a way that you shoot through the layers of the emulsion back-to-front. This results in a large amount of the light entering the camera being absorbed by the red backing layer, resulting in images that are saturated with reds and oranges! You end up with these wonderfully strange and apocalyptic pictures. On top of this, some film scanning machines can get a little confused by this and try to correct the image by massively upping the missing blue levels in the image, which gives you this incredible orange-to-pink-to-blue gradient over the image. Let’s tell a little narrative with these dramatic crimson captures!

wild construction

Scaffolds give way to the infinite beyond above, gleaming a dark bloody rust as the rickety spindles of humanity stab the air in their sickly triumph.

fallen cola

Their chromed godsblood is spilled upon the ground. The parched earth soaks up what it is owed.

beep beep beep

False eyes peer from every edifice, searching for malcontent in the tired faces of long-gone wanderers. They report back their findings to an unlistening void, a silent obelisk, alone and proud in the data center that no longer stirs the dust with its fitful, air-conditioned gasping.

dogs

Their trust in us was broken. Promises unkept ring hollow to beings of unfiltered loyalty.

invent

Ingenuity drove the gears of malice. A twisted celebration of the force which ground the masses into slurry.

stairs

Homes within factories. Work within sleep. Solace within terror. Peace within war. All but mere steps from eachother, as the borders grew thin and weary.

tower

And so, as with all towers that race towards the heavens, the fall was at once sudden and glacial. And with time, the birds and plants regrew in the nooks and crannies of artifice, turning it once more back into nature. Those who were ground down into the earth sprang forth out of it again, the dancing union of clay and thought once again spiralling into new shapes to spite the entropy.

And so our story ends, as a new one begins.

(Can you tell I’ve been playing a lot of Caves of Qud recently?) Here’s a bonus picture where the film slipped and stopped advancing in my camera, and I got a triple exposure of a building, a cup of coffee, and a dog someone was kind enough to let me take a picture of.

triple time

Have a good one, folks!

]]>
drmelon<contact@melon.zone>
a cool video about UI layout engines2025-03-02T00:00:00+00:002025-03-02T00:00:00+00:00https://melon.zone/blog/blog/gamedev/ui-layoutHere’s a link to a really, really well-made video about UI layout engines and how they actually work - specifically, the Clay UI layout engine. Anyone who has tried making their own UI system in a game engine will get a kick out of this, I think! Check it out: https://www.youtube.com/watch?v=by9lQvpvMIc

]]>
drmelon<contact@melon.zone>
february snaps2025-02-15T00:00:00+00:002025-02-15T00:00:00+00:00https://melon.zone/blog/blog/fun/photography/snap-snap-snapIt’s been a slow and meandering winter, amidst a backdrop of unfortunate chaos from overseas. Let us instead turn our attention to the interplay of light and chemicals! I’ve got a few tasty snaps I took during December last year. I travelled to Saltburn-by-the-Sea to spend Christmas with my girlfriend’s family, so I wanted to capture some of the various sights and sounds of the seaside town in the off-season. Read on and enjoy the sights!

Let’s kick things off with some shots I took on a roll of Ilford HP5, of a very famous Saltburn landmark: the pier! saltburn's pier

It was super windy and a bitterly cold spray was coming up from the sea. Desptie the inclement weather, they were still running the famous cliff lift, one of very few remaining water-powered funiculars.

the cliff lift view

It’s hard to see, but this carriage was carrying a Santa. He was very jolly, despite the temperatures.

a cliff lift carriage making its way up

Making our way onto the pier, some seagulls were taking advantage of the fact that the pier’s arcade was still open, and performing hovering maneuvers against the fierce wind. Remaining in place above the boardwalk, they were able to snipe chips from the freezing fingers of unfortunate walkers.

a hovering gull

Better instead to retreat to the safety of a cafe and enjoy some coffee and enormous pastries.

giant pastries

There’s a tradition in Saltburn of adorning postboxes with all manner of knitted creatures around Christmastime, so I got this picture of a cute little snowman perched on top of a red pillarbox:

a postbox snowman

Between these shots and others, I ran out of the Ilford HP5. I realized this mid-walk on another day, when the sun was out and we were in the local woods, so I had to load up some Kodak Ultramax quietly, trying not to disturb these squirrels:

squirrel A

squirrel B

Lest I incur the wrath of this forest deity:

the acorn god, possibly

Last but not least, enjoy a very tiny bird, silhouetted against the setting winter sun - and may spring burst forth soon!

tweet tweet

That’s all from me for now, but expect more snaps soon from January and February! I’ve also amassed a bunch of new film stock (including some very interesting and weird ones), so there’ll be a flurry of photographic activity from me before long. Have a great one!

]]>
drmelon<contact@melon.zone>
plans, plots, and schemes2024-11-24T00:00:00+00:002024-11-24T00:00:00+00:00https://melon.zone/blog/blog/fun/gamedev/work/life/plansYou know what rules? Hot chocolate. And with a recent cold snap, that’s exactly what has been keeping warmth in my beslippered toes when I shuffle through to work at 8:00am on the weekdays. My freelance game optimization work has been chugging along nicely, and I’m currently working with a really lovely client based in mainland Europe - so I’ve been keeping an earlier schedule than I usually do this time of year. It’s been nice seeing the frost on the grass outside, as I warm up my brain and body for the day. But, as I’m prone to do, I’ve been planning for the year ahead. Here are my schemes laid bare for all to see:

Development Streams

I’ve mentioned this before on the blog, but I really want to stream the development of my forthcoming personal projects. I think it’s a fantastic way of accomplishing a few things; one, it’ll stop me from procrastinating. It’s hard to goof off and watch an hour of YouTube when you have an audience. Two, by setting a streaming schedule, it’ll give me a nice production schedule which is otherwise something I struggle with when it’s my own self-directed work. If someone asks me to do something, I can get on it right away - but when it’s me asking me, I’m more likely to let things slip. Three, it’s a better way for me to receive feedback about my independent work than to simply work in silence and hope that things are good.
As for the streams themselves, I want to set up a minimal vtuber-style rig. Well, something more akin to a pngtuber rig; I can use my melon avatar and do some mouth flapping with audio, simple enough, but I also want to rig up a pair of basic Rayman-style hands that I can use to point at things on the screen or follow my typing/gamepad movements for fun. This is definitely not a necessary thing for dev streams of course, but I think it’d be fun, and fun is the point of the whole thing!
But what, exactly, will I be working on? Well…

ShotFun

This is a working title for a game I’ve been building slowly. It’s kind of a love-letter to rocket-jumping in games like Quake and TF2 - it’s a first-person acrobatic traversal game, where one of your primary movement tools is being blasted backwards by the massive double-barreled shotgun you carry. The gist of the whole thing is that mysterious crystalline entities have been invading various worlds and strip-mining them of their uniqueness, turning them into a homogenous crystal slop (boy, I wonder what recent phenomena have inspired this idea) and the Universe, in some kind of immune response, has created You to take them out. The game is therefore about leaping through various 3D worlds and blasting crystal dudes into shards. It’s in an extremely early form at present, but here’s a sneak preview of what I have so far…

Naturally, I want to have things like timed speedrunning modes, ghosts and replays, that sort of thing. It’s pretty ambitious, in terms of the scope I have planned, but I think it’s manageable.

Bean to Me Patch and News

Bean to Me was always a smaller-scoped project for me, particularly because it was something I was doing while resting and recovering from quitting my old job at Unity. However, there are a couple of things about it in its released state that I want to change. First, I feel that there isn’t enough to do for players who have beaten all the characters that are in the game so far. I worried about making them too difficult to beat, but it seems that there are plenty of players who have had no trouble doing so. For them, I want to introduce a more complex and forward-thinking opponent to really challenge them! Second, there are a few quality-of-life things that I just didn’t have the time or energy to get around to, that would just make the general gameplay experience a little smoother for everyone. Overall, I’m very happy with how the game has been received; for something written in a custom engine, with custom netcode, it has been behaving itself incredibly well (thanks to Emmy’s hard work on Lutra!) and I couldn’t be more pleased with that.
In terms of sales, it’s about what I expected (double-digit sales) since it has a marketing budget of exactly £0, but Steam Next Fest did very well at increasing the number of wishlists it has. I’m hoping that a winter-time sale might shift the needle a little there, and the patch itself should generate a little additional interest.
Bean to Me was very fortunate to get a lovely write-up at GamingOnLinux.com, and all the reviews it’s had on Steam so far have been positive and thoughtful too!

So, these are the main things I’m thinking about in terms of my personal projects and non-main-job-work! As for right now, I’m going to end this post the way I started it - with some hot chocolate. Bye for now!

]]>
drmelon<contact@melon.zone>
perfectly normal table2024-11-16T00:00:00+00:002024-11-16T00:00:00+00:00https://melon.zone/blog/blog/fun/games/tableSo I’ve been slowly picking through the HL2 anniversary update commentary and, uh, this happened:

]]>
drmelon<contact@melon.zone>