Console Black Magic

by Scott Alden, Ritual Entertainment

Last Updated On 08/19/98

The purpose of this document is to teach a level designer how to use consoles in their levels.  This document will evolve as things change in SiN, so check back often.  I apologize in advance for any spelling errors. If you find any logical errors, please send them to aldie@ritual.com

"Console" is a generic name for 2D things that are drawn on 3D surfaces in the game. For instance a "console" can have a combination of text strings, graphics, menus, scrolling consoles (that is similar to the Quake main console) and other things.

Consoles can have 2 modes set that tells the functions what to draw. If the scroll flag is set, then there is a scrolling, word-wrapping, user inputable quake style console on the surface. If the menu flag is set, then there is a menu system that is drawn similar in style to the main game menu system.

Layout strings are used to draw strings and graphics on the surface. Each "console" has a layout string that can be used to display just about anything the user wants. If menu is set, then each menu item has multiple layout strings and which one is drawn depends on whether or not that item is selected.  Menus are designed in separate text files and loaded from the client.

The user input is also redirected when a console is used. A message from the server will tell this function how to change the input. "Consoles" can have 2 types of input - console or menu. Each one has its own input handler and the script can change the focus dynamically.


You can have both menu and scroll set simultaneously.  This will allow you to get input from a menu and print to the scrolling console (or get user input from it).   You must set the fraction value between 0.0 and 1.0 otherwise the scrolling part of the console will cover the menus.


How to Create a Console in SinEd:

Make an entity with the following name value pairs:

classname "console"
consolename "con<your console name>"
scroll 1 (If you want a scrolling console that takes user input)
menu 1 (If you want a user controlled menu)
fraction <0.0 - 1.0> This is the fraction of the console you want the scrolling part to take up on the screen.
rows number of rows for scrolling console
cols number of columns for scrolling console
virtualwidth virtual width of the coordinate system
virtualheight virtual height of the coordinate system
menufile Filename that contains the menu specification for this console.  Go here if you want to see the syntax of a menufile.

The consolename must start with "con".  Now using the surface editor, pick a surface on the entity and give it a surface name that exactly matches the consolename and flag it with the surface property called CONSOLE.  Surface names are currently set in the groupname field of the surface editor.  You can flag different surfaces with the same name.  These will all display the same thing since they are tied to the same console name.  The console entity must be in the PVS of the console surface if you want the user to see it.  

Example: If I had a console called "con1", the surface on that console that I want to display the console must be called "con1" also. 


How to Access the Console in Script

Shown below is pseudocode for a script that sets up a thread called rotate which will wait for console input and perform the appropriate command based on what the user types in.  All the commands and script source will follow below.

Pseudocode for Rotate Thread

1 Call the thread "rotate"
2 wait for input from the console
3 get the input from the console
4 Check the input against my list of commands.
5 if input equals "start", goto 9
6 if input equals "stop", goto 10
7 if input equals "help", goto 11
8 If there are no matches, then print out an error message and goto 2
9 start rotating $thing, put up some layout graphics and text and goto 2
10 stop rotating $thing, remove the layout graphics, and goto 2
11 print out the help text and goto 2

Now, you may be wondering what layout graphics are?   And how the hell do I print out stuff to the console?  Here are all the commands that you can use from the script to access consoles.

Variables and Console Commands

When input comes into a thread, a console variable is created with the same name as the console.  Example: I have a console called "con1", the input from that console will be assigned to a variable called console.con1. These variables behave like level variables and will cleared between levels.   Even though these variables exist, you should get input from consoles using the coninput command below.  You can also store the name of the console in a variable and execute console commands on it.

Console Commands

These commands can be sent directly to a console to control it.  Here is the syntax:

%console_name command args

conprint <string> Prints the string to the console. Note: You can use \n in the string to make a newline.
connewline Prints a carriage return to the console.
conlayout <layout_string> Sets the layout for the console to this string.
conlayoutfile <layout_filename> Loads the layout file from disk.  This is good for large layouts so they don't have to be sent over the net and it keeps the scripts clean.
conapplayout <layout_string> Appends the layout string onto the current layout for this console.
conclearlayout Clears the layout for this console.
convirtualwidth <width> Sets the width of the virtual coordinate system for the console.
convirtualheight <height> Sets the height of the virtual coordinate system for the console.
confraction <frac> Sets the fraction of visible console. Ranges from 0 to 1
conclear Clears the console text.
rows <num rows> Sets the number of rows for the console.
cols <num cols> Sets the number of columns for the console.
focus <console | menu> Sets the focus of the console. The | means specify console OR menu.
foreground <red> <green> <blue> <alpha> Sets the foreground of the console to r,g,b,a.   They range from 0 to 1.  This sets the global color of the foreground of the console.
menuinactive Makes the menu inactive and it won't be drawn.
menuactive Makes the menu active and it will be drawn.
sbar <num> <w> <h> <min> <max> <value> <r> <g> <b> <a> Creates status bar <num> of width <w> and height <h> that ranges from <min> to <max> and the value is <value> and the color is r,g,b,a.
sbarvalue <num> <value> Sets the status bar <num> to <value>

Other Console Commands

Here are some more console commands that use a different format than the others.

<variable> coninput <console_name> Gets the input from the console and stores it in variable.
waitForConsole <console_name> Stalls the thread until the console has input available on it.
waitForVariable <variable_name> Stalls the thread until the console variable has changed.

Console Layout

A console can only have one layout at a time, but you can change it anytime you want to within a script.  There also will be some pre-defined layouts so you don't have to specifically type in layout commands in your script.   This will also save on network traffic.  More information on this will be forthcoming.

A layout is a list of commands that the client processes and draws onto a console.  Here is an example of a layout string:

"xl 0 yb 0 string \"Today is a good day to die\" xl 25 yt -25 bstring \"BLINKING STRING\" xv 0 yv -10 picn happyface"

Here is a description of what this layout string will do when the client processes it. Move the drawing position to 0 units from the left in the x direction and 0 units from the bottom in the y direction (This is the lower left corner of the console).  Draw the string "Today is a good day to die". Move the drawing position to 25 units from the left in the x direction and -25 units from the top in the y direction. Draw the string "BLINKING STRING" and make it blink.   Move the drawing position 0 units from the center of console in the x direction and -10 units from the center of the console in the y direction. Draw the picture that is called "happyface".

Wow.  That was a lot of stuff.  Basically the layout allows you to position text and graphics anywhere on the console you want to.   But what the hell is all that -25 units stuff?  Well remember when you defined your coordinate system in the script?  This is telling the console that you want to have a virtual coordinate system that ranges in x from 0 to 319 and ranges in y from 0 to 239.  So if you issue a layout command that says "xl 160 yb 120" this puts the drawing position in the exact center of the console.  Of course you could have used "xv 0 yv 0" and gotten the same results. 

Weird stuff with the console layout.  Since the layout commands are pretty dumb, you can actually put layout commands that will draw outside of the console.  For example if I issued this command with a 320x240 coordinate system - "xl 0 yt 100 string \"SKYHIGH\"" This would print the "SKYHIGH" string 100 units above the top of the console (because I set yt at 100).  So, use caution when drawing stuff using the layout system.

Here is the current list of layout commands:

LAYOUT COMMANDS

xl num Sets the drawing position num units from the left side in the x direction.
xr num Sets the drawing position num units from the right side in the x direction.
yb num Sets the drawing position num units from the bottom side in the y direction.
yt num Sets the drawing position num units from the top side in the y direction.
yv num Sets the drawing position num units from the center in the y direction.
xv num Sets the drawing position num units from the center in the x direction.
oxl num Sets the drawing position num units from the left side in the x direction + the resolution offset.  This is mainly used for the main menu and huds
oxr num Sets the drawing position num units from the right side in the x direction + the resolution offset. This is mainly used for the main menu and huds/font
oyb num Sets the drawing position num units from the bottom side in the y direction + the resolution offset.  This is mainly used for the main menu and huds
oyt num Sets the drawing position num units from the top side in the y direction + the resolution offset.  This is mainly used for the main menu and huds
jcx Sets the drawing position centered in the x-axis based on the length of the string or pic that you are drawing.
jcy Sets the drawing position centered in the y-axis based on the length of the string or pic that you are drawing.
jl Sets the drawing position left justfied for the next pic or string
jr Sets the drawing postion right justified for the next pic or string
jb Sets the drawing position bottom justified for the next pic or string
jt Setst the drawing position top justified for the next pic or string
picn name Draw the picture called name
spicn name scalex scaley Draw the picture called name and scale it by scalex and scaley
string s Draw the string s
string2 s Draw the string s in the alternate color
bstring s Draw the string s and make it blink
bstring2 s Draw the string s and make it blink in the alternate color
hstring r g b s Draw the string s with the background set to r,g,b (They range from 0 to 1)
hstring2 r g b s Draw the string s in the alternate color with the background set to r,g,b (They range from 0 to 1).
hbstring r g b s Draw the string s and make it blink and have the background set to r,g,b (They range from 0 to 1).
hbstring2 r g b s Draw the string s in the alternate color and make it blink and have the background set to r,g,b (They range from 0 to 1).
br num Set the rate for blinking strings (default is 3). (NOTE: Blinking strings are annoying and should be used with discretion)
cb name Sets the background of the console to the picture name.  Note that this will overwrite the console background and all the text on it because it is drawn after the console text is drawn.
fc r g b a Sets the foreground color of the current layout.  Strings will be drawn with the color and alpha specified.  Pics will also be modulated with the color and drawn at the specified alpha.
drawsbar num Draws the status bar num
hnum Draws the user's health num at the current position
rnum Draws the user's armor value at the current position
anum Draws the user's ammo value at the current position
date Draws the current date as a string
time Draws the current time as a string
fdate yy Gives a future date with the month and day are the same as the present, but the year is yy.
datebox Draws the date in a box
timebox Draws the time in a box
boxstring s Draws the string s in a box
textbox s Draws the text paragraph in a box.  The string can have \n in the contents specifying the end of a line.
box w h Draws a box w characters wide and h characters tall.
fade alpha Fades this item into the alpha specified
border width height Draws a border at the width and height (specified in pixels)
box width height Draws a box at the line width and line height (specified in characters)
boxtext s Draws string s in a box
dialogstring Draws the current dialog message.  (Used for huds)
cvarstring cvar Draws the specified cvar value as a string
type 1 or 0 Turns teletype effect on or off
fill r g b a w h Creates a filled rectangle of r,g,b,a color of width w and height h
fullfill r g b a Fills the entire screen with rectangle r,g,b,a color
pic Draw pic from an index on a stat (Used for huds)
dialogpic Draws the current dialog pic. (Used for huds)
drawinv Draws the inventory off dead bodies in the specified location
anim <lastpicnum> <basepic> Loops the animation using the basepic for the pic name. Draws the animation using <basepic>0, <basepic>1, <basepic>2, etc... up to <basepic><lastpicnum>.
animonce <lastpicnum> <basepic> Draws the animation once using the basepic for the pic name. Draws the animation using <basepic>0, <basepic>1, <basepic>2, etc... up to <basepic><lastpicnum>. Note: command doesn't work.
smnum Draws the statnum using a small font (Used for huds)
clipammo Draws the amount of ammo left in the current clip (Used for huds)
pickitem up/down/left/right Draws the picked up items in the specified direction (Used for huds)
pickarmor up/down/left/right Draws the picked up armor in the specified direction (Used for huds)
pickweap up/down/left/right Draws the picked up weapons in the specified direction (Used for huds)
pickhealth up/down/left/right Draws the picked up health in the specified direction (Used for huds)

Currently the layout commands look in the pics directory for .TGA files that match the name that you specify when using the picn or cb command.   You don't need to specify the extension of the file (i.e. tga),  just the base name.

Note, by using the console command "foreground" you can set the color of the font to any value you want, this will pretty much obsolete all of the string2 commands.  They are just kept up there for completeness.

Menu Specification

Menus are broken down into menu levels.  To specify a new level, use the menulevel command. Here is a sample menu and the description of it will follow:

// Test Menu

// MAIN MENU
menulevel main
menuitem "xv 0 yt -80 string \" MENU 1\""
actionitem "pushmenu sub1"
selitem "xv 0 yt -80 string \"> MENU 1\""
enditem

menuitem "xv 0 yt -100 string \" MENU 2\""
actionitem "pushmenu sub2"
selitem "xv 0 yt -100 string \"> MENU 2\""
enditem

slideritem bob 0 20 1 10 "xv 0 yt -120 string \" SLIDER\" xv 10 yt -140 drawslider"
actionitem ""
selitem "xv 0 yt -120 string \"> SLIDER\" xv 10 yt -140 drawslider"
enditem

listitem tom 0 "xv 0 yt -160 drawlist \"numchars 19 red 1.0 green 0 blue 0\""
numitems 2
"[ clockwise ]"
"[counterclockwise]"
selitem "xv 0 yt -160 drawlist \"numchars 19 red 0 green 0 blue 1\""
enditem

fielditem field1 25 15 "Test" "jcl yt -260 string \" FIELD\" jcx yt -260 drawfield \"red 0 green 1 blue 0\""
selitem "jcl yt -260 string \"> FIELD\" jcx yt -260 drawfield \"red 0 green 0 blue 1\""
enditem


// SUB1 MENU
menulevel sub1
menuitem "xv 0 yt -80 string \" START BOX\""
actionitem "consolecmd start"
selitem "xv 0 yt -80 string \"> START BOX\""
enditem

// SUB2 MENU
menulevel sub2
menuitem "xv 0 yt -80 string \" STOP BOX\""
actionitem "consolecmd stop"
selitem "xv 0 yt -80 string \"> STOP BOX\""
enditem


Here's an explanation of the menu syntax for each command:

menulevel <name> [action] Starts a new menu level called <name>.   Specifies a action for this menu when it is brought up.  The action is optional.
headeritem "layout string" Creates a menu header that will draw the layout string.  Headers cannot be selected and cannot have actions associated with them.
menuitem "layout string" Creates a menu item that will draw the layout string when it is not selected
actionitem "action string" Creates an action for the current item.   See the actionitems list below for more information
selitem "layout string" Creates the look of the current item when it is selected by the user.
listitem <name> <selected item> "layout string" <numitems> <itemlist> Creates a list item selector called <name> with the currently selected item <selected item> that will be drawn with "layout string" and has <numitems> in <itemlist>.  Items in itemlist are numbered sequentially starting at 0. 

Here is the format of <itemlist>.  There should be one item per line:

item string This is the string that is displayed in the list
command (optional) This is an optional string that is stuffed into the command buffer on the client.
Example:

listitem test 0 "xv 0 yv 0 drawlist"
numitems 2
"Sin Deathmatch Map 1" "map sindm1"
"Sin Deathmatch Map 2" "map sindm2"

In the layout string, there have been some additional commands added:

drawlist This will draw the list item at the currently specified location
numchars Specifies how many characters wide the listitem should be.
red <0.0 - 1.0> red portion of the background color of the selector
green <0.0 - 1.0> green portion of the background color of the selector
blue <0.0 - 1.0> blue portion of the background color of the selector
slideritem <name> <minvalue> <maxvalue> <current value> <length> "layout string" Creates a slider item called <name> which ranges from <minvalue> to <maxvalue> and starts at <current value> and is <length> long and is drawn with "layout string". In the layout string the following additional commands have been added:
drawslider This will draw the slider item at the currently specified location
fielditem <name> <length> <visible length> <initial contents> Creates a field entry item called <name> with the <initial contents> where the internal length is <length> and the number of visible characters is <visible length>.  In the layout string, there have been some additional commands added:
drawfield This will draw the field item at the currently specified location
red <0.0 - 1.0> red portion of the background color of the selector
green <0.0 - 1.0> green portion of the background color of the selector
blue <0.0 - 1.0> blue portion of the background color of the selector
enditem Tells the parser that this is the end of the current item.
autoheight <y drawing position> Automatically calculates the height of all the menu items and positions y down the console.

Example:

autoheight yt -50

This will start the first menu item at 50 units down from the top of the console and space them vertically at 50 units from one another.

actionitem commands

You must provide an actionitem immediately after the menu item is specified.

pushmenu name menu name to make current.  If the user presses the ESCAPE key, control will return to the previous menu.
consolecmd string sends the string to the script.
stuffcmd command string sends a command to the execute buffer on the client.
callback function_string calls the function that is associated with function_string in the client.  This is called whenever the menu item is changed.
function function_string calls the function that is associated with function_string in the client.  This is called when the menu item is activated.
centerprint string Prints the string to the center of the screen.   (This is used in the main menu)

Now here's that script you've been waiting for:

thread console
end

//=================================================================
// console - This is a thread that gets input from a console and
// prints it back to the user.  It also checks for recognized commands
// and performs actions based on the input.
//=================================================================
console:

local.Console string con1
local.ConObj string %con1

// Set focus to the console portion 
local.ConObj focus console

// Wait until there is some input available
waitinput:
waitForConsole local.Console

// Once we are at this point, the console has given us some input,
// now we can read in the commands.
local.input coninput local.Console

//=================================================================
// main - This checks for commands and does takes the 
// appropriate actions
//=================================================================
rotatemain:
local.input ifstrequal "start" goto startBox
local.input ifstrequal "stop"  goto stopBox
local.input ifstrequal "help"  goto help
local.input ifstrequal "menu"  goto menu
local.input ifstrequal "clear"  goto clear
local.input ifstrequal "" goto waitinput

//=================================================================
// error - This prints an error message to the console.
//=================================================================
error:
local.ConObj conprint "Unknown command:"
local.ConObj conprint local.input
local.ConObj connewline 
goto waitinput

//=================================================================
// clear - Clear the text from the scrolling console.
//=================================================================
clear:
local.ConObj conclear
goto waitinput

//=================================================================
// startBox - Starts the $thing rotating, and sends a layout command
// to the console.  
//=================================================================
startBox:
local.ConObj conlayout "xv 0 yv 0 picn net"
local.ConObj conapplayout "xv -24 yv 64 bstring \"SPINNING THE BOX\""
local.ConObj conprint "Started the box.\n"
$thing rotateX 360
goto waitinput

//=================================================================
// startBox - Stops the $thing rotating, and clears the layout for
// the console
//=================================================================
stopBox:
local.ConObj conclearlayout 
local.ConObj conprint "Stopped the box.\n"
$thing rotateX 0
goto waitinput

//=================================================================
// menu - Load a menu file and set the focus on it.
//=================================================================
menu:
local.ConObj conmenufile "maps/aldie/contest.mnu"
local.ConObj focus menu
goto waitinput

//=================================================================
// help - Prints out the help message
//=================================================================
help:
local.ConObj conprint "Available Commands\n"
local.ConObj conprint "------------------\n"
local.ConObj conprint "start\n"
local.ConObj conprint "stop\n"
local.ConObj conprint "menu\n"
local.ConObj conprint "clear\n"
goto waitinput


Copyright Ritual Entertainment 1998. All rights reserved.