Time only moves when you're thinking with portals.

Post news Report RSS PORTALHOT Development Diary #2

The second development diary for the PORTALHOT mod.

Posted by on

In the last entry I mentioned that I was going to work on the cutscene/intermission system that would allow me to make those segments (when the game freezes and it rapidly flashes text on the screen) easier to make. And this is precisely what I did.

Cutscene System


These segments were a bit of a pain to set up using the I/O system, since you had to manually set up all the millisecond delays to change game_text to whatever you wanted and then display it, and then repeat it all x number of times for each word that you wanted to have in the cutscene. The straw that broke the camel's back was when I run into some trouble with game_ui (which actually persisted even in the new implementation, but more on that later), and decided that I'll just write a Vscript that will take whatever sentence I parse into it and all the dirty work by itself.

As this things usually tend to go, it was not a simple as it seemed.

The first problem I run into was actually due to a pretty big oversight on Valve's part. You see, the level designer can parse data into a vscript by using a runscriptcode input on the entity holding that script and then putting a snippet of code that calls the function with whatever parameters he desires as the input parameter. For instance:

PlaySuperhot([5, 8, 7])

Basically, the huge mess-up on Valve's part is that you can't parse strings because if you put quotation marks in a parameter field anywhere in hammer, your map will brake.

I wish I was making this up.

So basically, at this point I had two possible solutions I could see:

A) Create a complicated system that takes numbers and somehow turns them into characters and words to be displayed in the code (how would that even work?)

B) Keep all the text in variables in code and only reference which variable to display from the level editor

I obviously run with the simpler option.

So, the way things are now, all the text is contained in those nice arrays at the beginning of the .nut file:

text <- ["HELLO", "READERS", "YOU", "SMELL", "NICE"]

And now you can display it from the level editor like this:

PlaySuperhot(text)

and it works!

The reason why I didn't initially like this solution is because it means that the code needs to be edited for each new sentence that you would want to play on your map as a cutscene. This isn't a problem for me, but if someone was to make a custom PORTALHOT map, they would either need to include their own version of the script, or just do everything manually with I/O, like I did at the beginning.

The function that displays the cutscene itself (which is the longest function in the entire script) is pretty compact - it only has about 10 lines of code:

function PlaySuperhot(input) {
DisableController(0)
SetTimescale(0.1, 0)
EnableCutsceneOverlay(0)

foreach (idx, val in input) {
ShowTextPiece(val, 0.1*idx)
}

local inputLenght = (input.len() + 1)
EnableController(inputLenght*0.1)
EnableNormalOverlay(inputLenght*0.1)
}

As you can see, delays for the specific inputs are calculated on the fly, based on how many words there are in a sentence that you want it to play. If I was to do it by myself, I would have to do it manually and I would be a bit of a hassle.

There was one funny glitch that I found, that I suspect has something to do with Valve's hacky coding. Basically, whenever you try to display the word ON (with all caps and stuff), the game_text will instead display it as "the" (in low caps). At first I thought it was some mistake on my part (that I messed something with arrays or whatnot) but then I realized what was going on, and I just can't help but find it really funny.

What I found less funny, was the fact that this problem with game_ui that has driven me to switch to Vscripts originally, was still present here.

New "SUPERHOT mechanic" system


You see, when the cutscene plays, I temporarily disable player's ability to unfreeze time, until the messages are displayed. I did this by firing the Deactivate output on the game_ui. The problem is, there is something about this entity that makes it just not work anymore after it was disabled once. It appears to be permanent.

When I discovered this, it was already a late at night, and I started coming up with various ideas on how to fix it. Most of them were terrible, like having a number of game_uis in the map and activating them one after the other leaving "depleted" ones behind, or even creating and destroying one entity via vscript (how would I connect the inputs? no idea).

It wasn't until I took a shower that I realized that there was a simple method to do this: re-write the whole time-freezing mechanic using vscripts. This way, the game_ui could be active all the time, and I would control whether the mechanic works or not on the code side of things.

You see, until now the whole system was made in 100% using the hammer's I/O system: game_ui connected to math_counter, math_counter froze time (using logic_timescale) when it detected that the number of buttons being pressed at a given time was 0. There weren't even any logic_relays in place (I couldn't use them since they have stupid re-fire periods that get even worse when working in slow-motion), so the whole thing was super bare-bones.

I sat down and wrote a script that did everything the I/O system did - and more! Thanks to the fact that working with code made everything much less complex, I was able to sneak in some improvements that I probably could not come up with normally. Firing a portal now only unfreezes time for 0.5 seconds if the portal placement was successful - which made the gameplay somewhat more intuitive and less frustrating. The previous way of doing this was a mess on the logic side of things, too - you can see how in the old video demonstration I posted time sometimes speeds up and slows down without rhyme or reason, especially towards the end. This is no longer the case!

So, in a way, the fact that game_ui was broken actually made me improve something about my mod and make it better. This, I guess, is kinda funny.

Conclusion

So, to sum up, even though I haven't really done anything "new" from the perspective of the end player (both cutscenes and the system had already "worked" in one form or another and you could see them on the demo video), the improvements that I've made will not only allow me to make new stuff faster, but also make the overall gameplay experience smoother and more fun.

This is all for now! The next thing I will focus now will be making a few levels to show, after which I will once again delve into the vscripts to make... something that is going to be a surprise of sorts, so I don't want to talk about it now. However, for the next couple of days I'm taking a break from PORTALHOT since I need to study and write a couple of essays for school. Hopefully, this shouldn't take long.

Stay tuned for more!

Post a comment

Your comment will be anonymous unless you join the community. Or sign in with your social account: