Tutorial *82*
NOTE: This tutorial was revised on 3 January 2000, based on suggestions by Phoenix of QER fame.

I've wanted to learn C for a long time but never had a "project" that was dear enough to hold my short attention span. I've been patiently waiting for the Quake source to be released since it first got rumoured a year ago. I figured, "That will be my driving force". Having never used C past the "Hello World!" stage I knew it would be a challenge to dig into. Fortunately, the QuakeC progs.dat and I are VERY old friends and I figured knowing the engine as well as I do as an end-user would probably help a little bit as I first delved into it. I figured I'd start with some of the simple drawing routines and it didn't take long to find a place to start hacking. Here is the result...

Radix's Console Transparency tutorial made me think, "Hey I can see the game thru the console, cool!". I spend a lot of time in the console since I do admin for my Quake server via remote at home. I wanted a bigger in-game console! Took about 5 minutes to figure out how to do it. Hmmm. maybe someone wants a smaller console... Another 5 minutes.. Ok, cool... Another 40 minutes to unbreak everything I broke along the way and here ya go. An in-game console to suit everyone, from the itty-bitty couple-o-line console, to the standard half-screen, to the full-screen monty. If you are coding for GLQuake, this tutorial assumes you have already added Radix's Console Transparency tutorial to your source. If you haven't, go ahead and do it. It's a quicky. (NOTE: WinQuaker's won't get as cool an effect because there's no console transparency, but this will still work).

Done with that? Ok, here we go...

First off. How to control it? We'll need a new CVAR.

In both SCREEN.C (software rendering) and GL_SCREEN.C (OpenGL rendering) find the line:

   cvar_t scr_printspeed = {"scr_printspeed","8"};

and right after it add:

   cvar_t scr_conheight = {"scr_conheight", "0.5"};

We'll register it in a comparable area, so in BOTH files again, go to SCR_Init and find:

   Cvar_RegisterVariable (&scr_printspeed);

again, right after that line add:

   Cvar_RegisterVariable (&scr_conheight);

Ok. Now that we've got our new console variable, let's put it to use. In BOTH of the same files go to SCR_SetUpToDrawConsole and find the lines:

   else if (key_dest == key_console)

        scr_conlines = vid.height/2; // half screen

This is what gives us our standard half-screen console. For a quick hack you can just change the second line as follows and it'll work:

   else if (key_dest == key_console)

        scr_conlines = vid.height*scr_conheight.value; // in-game console

That's what I did the first time around and was pleased that my system didn't lock up. However, I did find very quickly that a value less than 0 or greater than 1 was definitely not a good thing. We need to restrict the range that the user can set the new CVAR to. We'll assume that you want at lease a couple of lines, minimum.

To do this, simply change the above code to match this:

    else if (key_dest == key_console) {

        float twolines;

        twolines = (27.0 / vid.height); // always leave two lines visible

        if (scr_conheight.value < twolines) {

           Cvar_SetValue("scr_conheight", twolines);


        else if (scr_conheight.value > 1) {

           Cvar_SetValue("scr_conheight", 1);


    scr_conlines = vid.height * scr_conheight.value;


Now that we've got our sanity checks in, we're all set. Well, almost. WinQuaker's can pretty much stop here. But those blessed with GL Rendering need to look further in order to "clean things up".

Remember I said that I thought of this AFTER fooling around with Radix's Console Transparency tutorial. I found some odd behaviour when I mixed these two together.

First off, the console goes solid if SCR_CONHEIGHT is greater than 0.74 (slightly more or less depending on resolution). I found the solution to this poking around near Draw_ConsoleBackground in GL_DRAW.C:

   void Draw_ConsoleBackground (int lines)


      int y = (vid.height * 3) >> 2;

      if (lines > y)

         Draw_Pic(0, lines - vid.height, conback);


         Draw_AlphaPic (0, lines - vid.height, conback, (float)(2 * con_alpha.value * lines)/y);


You'll recognize this routine from Radix's tutorial. With a little experimentation (can you say "trial and error"?) I found that the variable 'y' ends up signifying what essentially realates to "three-quarters of the way down the screen". GLQuake as presented in the released source has a subtle transparency in the in-game console, even before the Radix modifiation. Basically what J.C. (or Zoid, or whomever) did was to declare "If the console covers more that three quarters of the screen then we'll draw it solid and if it's less that three-quarters we'll draw it transparent". Since the original console only had three states, none, half or full, no problem. Our variable size throws a monkey wrench in that philosophy.

I thought out a bunch of math to try and work out 'lines' vs 'y' vs 'scr_conheight.value' and then said, "There must be an easier way". In fact, there is. The console goes full screen in response to a keypress which set a value to 'con_forcedup'. If 'con_forcedup' has a value we must be full-screen, if it doesn't... you get the picture. After this revelation, the fix is a no-brainer.


   if (lines > y)


   if (con_forcedup)

Now we've got transparency throughout the whole range of the console. However, we have another problem. It seems that the larger the console, the less transparent it gets. Take a look at this line from Draw_ConsoleBackground:

   Draw_AlphaPic (0, lines - vid.height, conback, (float)(2 * con_alpha.value * lines)/y);

I don't know exactly what this magic formula means. But I do know this... The transparency of the console varies (almost) proportionately to the height of our new console. A larger console results in less transpareny and a smaller one gets more transparent. Since I wanted more space AND the ability to see through it, this situation just isn't acceptable. In order to fix this we have to play with the magic formula a little bit.

A little trial and error and a math primer later we have the following:

   Draw_AlphaPic (0, lines - vid.height, conback,

   	(float)(con_alpha.value * (lines / (vid.height * scr_conheight.value)));

One more thing. If you've tried to compile at this point, it bombed out. That's because the when we referenced the 'con_alpha' variable in Draw_ConsoleBackground we hadn't set it up to be seen anyplace other than GL_SCREEN.C where it was declared. There's a quick fix for that. Open up SCREEN.H (yes, the header file) and after the last line add:

   extern cvar_t scr_conheight;

SCREEN.H is common to software and OpenGL rendering so you're covered on the WinQuake side as well if you ever find you have a need to access this value. Now we have a CVAR that is available to externel modules and everything should compile cleanly.

Ok, everything is fine now and we learned something. However, I decided I hated having to set my console size everytime I fired up the game.

Go back to SCREEN.C and GL_SCREEN.C find the line we added before:

   cvar_t scr_conheight = {"scr_conheight", "0.5"};

By adding true after the default value of 0.5, we can make Quake write this variable to config.cfg upon exit, saving it for us the next time we open up Quake.

   cvar_t scr_conheight = {"scr_conheight", "0.5", true};

Not bad, now the 'scr_conheight' gets saved and is ready at our preferred size everytime we fire up the game.


btw.. thanks to Radix for the console transparency. I like 0.3 myself.

And special thanks to Pheonix for the math tutorial!

Sign up
[Remember Me]