Go to QuArK Web Site
Introducing QuArK development
Updated 22 Apr 2001
Upper levels:
QuArK Information Base
3. Advanced customization

 3.1. Introducing QuArK development

 [ Prev - Up - Next ] 

 Index


 Introduction

Tiglari - 22 Apr 2001   [ Top ] 

QuArK development can be carried out at three levels:

the *.qrk configuration files

the Python code

the Delphi code.

The first two require just a text-editor, since a functioning QuArK installation includes the Python interpreter, while the last requires Delphi (Borland;s version of Pascal, enhanced with visual development tools). The current developers seem to be using versions 4 or 5; it's possible that older versions such as 3 or even 2, might work. Older versions can sometimes be acquired free on computer magazine CD's. The Delphi is written in a mixture of French and English, and the French is slowing being converted to English (so there is a possibility that some references to things in the Delphi here will be outdated).

TC's can typically be supported by creating new *.qrk files in the form of `addons', while supporting a new game usually requires some delphi coding (mostly because each game tends to introduce some quirks into the texture and map formats, and the read/write code for these needs to be reasonably fast). Interface ideas on the other hand can often be supported just in Python, with maybe a little bit of Delphi to support a new `specific type' in a form (if you have a bright idea and think you need a new specific type, some delphi coder might well be able to provide it).

Central to eveything is the concept of `QObject', QuArK's universal format for the storage and management of structured information. Maps, game information supplied in add-ons, and the descriptions of most of the dialog boxes and other data-entry windows in QuArK are all described as QOjects. The .Qrk files are just QObjects presented in a written format for QObjects, and understanding them is essential for following the Python and Delphi as well.

A QObject is a thing (technically an instance of a class in Delphi) with two kinds of properties:

  • A list of attributes called `Specifics', each with a value, which might be a string, a number, a sequence of numbers or a few other things.
  • A list of `subelements' (SubElements in the Delphi, .subitems in the Python), each of which is just another QObject.

So a face is a QObject with a `v' specific of 9 numbers indicating the face and texture position information (the location of the corner and two ends of the Cyan L), and a `tex' specific giving the name of the texture. You can see the specifics of a map object by hittng the second button over the multi-page panel (it's usually only interesting for entities).

And a poly (brush) is a QObject whose list of subitems are the non-shared faces of that poly (shared faces appear in the subitem list of the group containing that poly). And so on.

There's one special specific that should always be there, and maybe shouldn't be thought of as a specific at all, and that is `name'. A QObject's name is divided into two parts, shortname, and extension. The shortname is usually just an identifying label (tho for entities it's the classname), but the extension, separated by a dot or colon, specifies the kind of object. The dot separator is used for types of QObjects that can plausibly be stored in a file of their own (so they are in effect a file-type), while the colons are for smaller types of objects, such as the different components of a map.

Here are some of the more important extensions:

  • .qctx - Quake Context. Contains info that modifies how things are done
  • .qtx - Toolbox. Collection of objects that can be chosen from and inserted into something.
  • .qtxfolder - folder in .qtx
  • :form - specifies a format for a window whereby info about something is entered into QuArK. To support a mod, you'll have to get familiar with the :form object associated with each entity, these are found in the entity forms.qctx of the .qrk
  • :f - face
  • :p - poly (brush; faces in subitems thereof, shortname arbitrary label)
  • :g - group (contained faces, brushes & entities in subitems, shortname arbitrary label)
  • :b - brush entity (attached brushes in subitems, entity attributes in specifics, shortname = classname)
  • :b2 - (quadratic) bezier patch or quilt
  • :e - point entity (entity attributes in specifics, shortname = classname)

Because each specific has a unique identifying name, the order of the specifics list doesn't matter, but the subelements don't have labels; for map objects, they are displayed in the tree-view, and the order is as given. In principle you could make something depend on it, tho I don't think anyone ever has).

It might be useful to note that QObjects are sort of like a limited form of XML, with no character data intererspersed betweeen subelements. With QObjects in hand, we push on to .qrk's.


 .Qrk files

Tiglari - 02 Mar 2001   [ Top ] 
Useful additions:
  *a rundown of the major compoments of a game-support file and an addon file.
  *a guide to Typ's in :form's

.qrk files are just QObjects stored in files. There are actually two kinds of .qrk files, text and binary (both unfortunately with the extension .qrk). The text files can be read an edited with a text-editor (although the format is initially forbidding), whereas the binaries are much more compact, and allow `delay loading' which helps QuArK manage big ones with less chugging.

To get a text version of a binary *.qrk, just open it, and save then save it (as `structured text', with the extension .txt to keep the file system happy). The `technical info' zips for the older QuArK versions, and the current development snapshots, contain the text versions of the *.qrk files, which furthermore tend to contain useful information such as comments on the syntax, etc.

A (text format) .Qrk begins with the line `QQRKSRC1', which says that it's a QuArK text format file. Then there can be comment lines beginning with `//' (everything after `//' on a line is igored), whitespace and blank lines etc. until we get down to business with a line whose first nonblack character is:

'{'.

'{' opens a QObject. We already know that QObjects have two `Specifics' (name-value pairs), and `Subitems', which are QObjects which will have a `name' specific. So it's not too suprisiing that the rest of a QObject will consist of a series of pairs:

  <Name> = <Value>

(where <Value> can be as large an expanse of text as you like, if it's a great big QOobject)

Until we fetch up at the end with the closing `}', after which the file must end.

So let's look at the beginning of the Portal of Praevus add-on (I started as a Hexen II entity guy, so we gotta have some Hx2 content here ...)

QQRKSRC1
// This file has been written by QuArK Version 5.0.b5
// It's the text version of file: Praevus.qrk
// Portal of Praevus add-on by tiglari@hexenworld.com
//   to be added on to datah2.qrk (data file for Hexen II)
//
// The Textures need to be further subsorted into wall, floor/ceiling,
//  button, etc; if you want to do this please do, it's not rocket
//  science!

{
  QuArKProtected = "1"
  Description = "Portal of Praevus Data"

    praevus directory infos.qctx =
    {
        Game = "Hexen II"
        SourceDir = "PORTALS"
//      GameDir = "fortress"
    }

After the opening guff, we see that the first specific is `QuArKProtected', I don't know exactly what it does, but that doesn't matter. Its value is a string, enclosed in quotes. There are several other schemes for representing values, such as Hex codes, which we'll get into shortly.

Then comes our first subelement. Its Name specific will be `praevus directory infos.qctx'. Its shortname is `praevus directory infos' and its extension is .qctx, so it's a Quake Context, and modifies how things are done (here where to look for info about the game). This particular QObject has two ordinary string-specifics, and then ends. So it goes on with more subelements until the final '}' on line 6108.

So that's the basic idea, but there is a bit more to it that that.

First, in addition to strings, there are several additional types of specific-values. Binary data is introduced with `$'. So for example the line from the Defaults.qrk file prescribing the red default color for tags is:

  Tag        = $FF0000

(a standard RGB color code, for those new to such things)

Multiline strings can be specified as sequences of ordinary "-bounded strings separated by `$0D':

  Hint = "This ought to work"
      $0D"  if it doesn't, why not try extreme skiing?"

And sequences of numbers are bounded by ', a bounding box for example might be specified as:

     bbox = '-8 -8 -8 8 8 8'

All this and some more stuff that I haven't seen exemplified is prescribed in the function ConstructObjsFromText in the file QkFileObject.

* sections on the major components of the major kinds of .qrk file would go nicely here *

Forms: For game supporters, one of the most important kinds of components of .qrk files are :forms, since these control how the specifics of entities are entered into maps. :forms are also important in Python coding, since they are used to control in making dialog boxes, etc.

To get a sense of how it goes, here's the beginning of the entity forms specifications from DATAH2.QRK:

   Entity forms.qctx =
   {  // ENTFRM
     Ring_Flight:form =
     {
      Help = "Ring of Flight"
      bbox = '-8 -8 -44 8 8 20'
      mdl = "models/ringft.mdl"
     more: = {
       Typ="B"
       Txt="triggering"
       Cap="Push"
       Form="item_triggers:form"
       Hint="specifics for triggering when item is taken"
     }
      spawnflags: =
        {Txt="&"
         Typ="X1"
         Cap="FLOAT"
         Hint="item doesn't drop to floor when spawned  "}
     }
     Ring_Regeneration:form =
     { ...
     ....

Entity Forms is a Quake Context, its subitems are a (big) list of :form objects. These have some specifics (all QObjects, regardless of type, can have specifics freely added to them), and then comes a list of subitems. Each subitem is a little window, `control' or `widget' (GUI geekspeak) whereby some attribute of the entity can be set by the editor. I need to call them something, so I'll call them `fields'.

The way fields work is a bit devious. They have names like `more:', `spawnflags:', etc. (colon, null extension). Then inside the brackets are listed further specifics, of which the most important is `Typ'. Typ determines what kind of control is used; X1 for example is a checkbox that sets the first bit position (flag) in an integer. Usually the name determines what attribute of the entity is being set, so the `spawnflags' subitem sets the the first bit position of the `spawnflags' attribute of the entity. But not always; `more:' above is just a label.

Another important specific of fields is `Txt'. This is the `label' that appears to the left of the data-entry widget itself. If it's "&", then the name of the field is used as the label, so if you look at entity specifics in the map editor, you'll see the name of the various entity attributes on the left, their values on the right (in the data-entry widgets). Their are various further field specifics, "Cap" for additional text (appearing on the right) and "Hint", for flyover hints, and whatever more the delphi code for that kind of Typ happends to support. So the :more button calls up an additional window for entering further specifics, its form is given as the value of the Form specific.

Unfortunately, there is no solid list of all the Typs (programmers might like to know that they're defined in a big cascade of Case statements in prog/FormCfg.pas:TFormCfg..wmMessageInterne; once you've got the hang of it, it's not too hard to add new ones, without fully understanding everything that's going on). Browsing in the text versions of the game support files, especially dataq2.qrk, is a way to get started learning them.

* A guide to Typ's would also be nice to have *


 Guide to Typ's

Decker - 14 Feb 2001   [ Top ] 

Here is a list of the most common used Typ's in .QRK :form definitions.

Typ'sDescriptionExample
E[-R] Entry field.
This is the default type, if Typ="..." is not given.
The last "R" (at third position) means Read/Only
targetname: = { Typ="E" Txt="&" }
target: = { Txt="&" }
EF[R]
EF[999]
Entry field containing Float(s).
The last "R" (at third position) means Read/Only
.
ED[L]
Entry field containing Directory-path (with browse button).
The last "L" (at third position) means only the last foldername of the path is to be used.
SourceDir: = { Typ="ED" Hint="Full directory-path" }
GameMod: = { Typ="EDL" Hint="Modification folder" }
ET
Entry field containing Texture-name (with browse button).
Opens the texture-browser, if the browse button is pressed.
Texture: = { Typ="ET" Hint="Choose texture" }
EP
Entry field containing Path and File-name (with browse button).
Opens a file-dialog, so the user can choose a filename.
QBSP1: = { Typ="EP" Txt="Path to QBSP" DefExt="exe" }
LIGHT1: = { Typ="EP" Txt="Path to QRAD3" DefExt="exe" }
X<value> Checkbox, which sets the bits according to <value>.
The same specificname may appear, with different <values>, so each bit in the specific can be controlled individually.
Usually used together with a Cap="...", to tell what the bit controls.
spawnflags: = { Typ="X1" Cap="Ambush" Txt="&" }
spawnflags: = { Typ="X2" Cap="On Trigger" Txt="&" }
spawnflags: = { Typ="X128" Cap="X Axis" Txt="&" }
C Combo box.
A predefined list of choices and their values. To use this type, the items  and values  must also be set, as can be seen in the example.
Each choice in the list will be indicated by a newline ($0D), except for the last choice!
mylist: = { Typ="C" Txt="&"
  items =
      "Choice 1" $0D
      "Choice 2" $0D
      "Choice 3"
  values =
      "1" $0D
      "2" $0D
      "3"
}
B Pushbutton.
Usually used to activate a second spec/arg view (a :form), which contains other spec/args thats more specialized for some purpose.
The Cap="..." controls the text in the pushbutton.
more: = { Typ="B" Txt="Specialize"
  Cap = "Push..."
  Form = "specialize_this:form"
}
L[N[4]] Color-picker pushbutton.
A pushbutton which shows the choosen color, and when activated, will bring up a color dialog.
If only Typ="L" is given, the resulting RGB values, will be in range 0 - 255.
If Typ="LN" is given, the RGB values will be normalized to range 0.0 - 1.0.
If Typ="LN4" or Typ="L 4" is given, there will be created a fourth value, which controls the brightness of the light. This however, must be changed using a second spec/arg pair, with Typ="E".
_color: = { Typ="L" Txt="&" }
_light: = { Typ="LN" Txt="&" }
light: = { Typ="L 4" Txt="&" }
_lightbright: = { Typ="LN4" Txt="&" }

//To view the exact values, create a
//second spec/arg pair
color: = { Txt="&" Typ="L" } //Pushbutton
color: = { Txt="&" } //Entryfield
S Seperator.
sep: = { Typ="S" }



GNU General Public License by The QuArK (Quake Army Knife) Community - http://www.planetquake.com/quark

 [ Prev - Top - Next ]