News | Forum | People | FAQ | Links | Search | Register | Log in
FTEQCC Coding Thread
FTEQCC deserves its own thread. I'm switching to it now, and its current version has a lot of features that allows for substantially different coding styles.

Some examples from the readme (the whole document is a good read):


unary ++ and --

unary ~ bitwise not

<< left shift

>> right shift

+= -= |= &= &~= ^= *= <<= >>= /=

ternary ?: conditional

Given the line 'result = A ? B : C;', the result will be be equal to B ONLY if A is true, otherwise equal to C. B may be ommitted, and if so will be equivelent to A. Side effects will not be executed in the side that was not taken.
(FrikQCC only supports ternary operations as a replacement for "if" statements, with no return value. FTEQCC's implementation is more complete)

vector
Vector immediates traditionally take the form of 'x y z', but using [x, y, z] allows formulas and thus simpler argument passing.
Normally vectors act a bit like unions and define both 'vec' and 'vec_x' 'vec_y' 'vec_z' variables allowing for direct channel access. The modern way to access individual channels is with eg vec.x instead.


arrays
FTEQCC supports single-dimension arrays.
(Arrays are also supported within structs, allowing for (clumsy) multi-dimensional arrays.)

float foo[] = {1, 2, 3, 4}; will thus define a float array and will infer its length as 4. If you need to use an explicit length, or you do not wish to initialize the array, then you must put the needed length inside the square brackets.
foo.length can be read if you wish to know how long an array is (especially if the length was inferred instead of explicit).
Dynamic lengths are not supported at this time.

Indexes will be rounded down.
Dynamic indexes ARE supported in all cases, however they may come at a significant performance loss if you do not have extended opcodes enabled, so it is generally preferable to unroll small loops such that constant indexes can be used.


struct
Allows you to define a struct, which is useful for boxing multiple related variables.

union
Equivelent to structs, except all struct members start at the same offset. This can be used for either type punning or compressing mutually-exclusive fields inside complex struct layouts. By nesting structs, unions and arrays, you can get some quite complex data structures.
Note that unions and structs define within unions or structs do not need to be named. Members from child structs will automatically be accessed as if they were part of the containing stuct.

struct
{
     float type;
     union
     {
          struct
          {
               float f;
               vector bar;
          };
          struct
          {
               string s[2];
          };
     };
} foo[8];

float() foobar =
{
     if (foo[4].type)
          return stof (foo[4].s[1]);
     else
          return foo[4].f;
};


class
Class constructors double up as spawn functions, and the spawn intrisic works in the same way - the named members will be set before the constructor is called, instead of passing arguments to the constructor (which avoids the need for overloads etc).
If the parent class is omitted, entity will be assumed. The 'interval' field below is defined as a class field. Such class fields are valid ONLY on entities of that class, which allows for more efficient memory usage.
Member functions can be defined as virtual (such functions are technically pre-initialised fields, and thus compatible with things like think or touch), non-virtual (read: non-inherited), or static (where 'this' cannot be used).
Public, private, protected are parsed like in C++, but ignored.
Only a single parent type can be inherited, and it must be a class or the general entity type.

class foo : entity
{
     float interval;
     virtual void() think =
     {
          centerprint (enemy, this.message);
          nextthink = time + interval;
     };
     nonvirtual void(enemy e) setEnemy =
     {
          enemy = e;
     };
     void() foo =
     {
          nextthink = time + interval;
     };
};

void() someiplayerfunction =
{
     foo myfoo = spawn (foo, message:"Hello World", interval:5);
     myfoo.setEnemy (self);
};


 
Its GUI is a little buggy under Windows 7: screenshot
Frame Macros On Switches 
Hey, don't know if this is intended behaviour, but when I use frame macros inside switches the compiler doesn't recognize them.

Example:
$frame stand1 stand2 stand3 stand4 stand5 stand6 stand7 stand8 stand9
void() test = {
int frame = $stand1;
switch(frame)
{
case $stand1:
//
break;
}
};

Gives me:
test.qc:33: error: Unknown frame macro $stand1: 
 
Asked Spike, he told me to add a space after the frame macro name.
This works:

case $stand1 :

This doesn't:

case $stand1: 
Unclear 
I'm trying to add entities to the quake extention, but using a macro with equal statements give an error after compiling with fteqcc.
I know a lot of warnings can be corrected quiete easy, I keep getting a stale macro for some monsters.
warning F317: Stale macro used (paina, defined in monsters bla.qc)

Can I just ignore it? 
Not A Good Idea 
Somewhere in the file the warning comes from, you've got $paina (most likely as the frame in an animation). But you don't have $paina in that file, so it's using the frame number from $paina in "monsters bla.qc". You will be getting a random frame of animation rather than what you really want. Find the place where you are using $paina, and change it to the correct frame. 
Yes 
I hadn't made enough statements in the $frame count so this warning kept on appearing. Now they're vanished. 
1 post not shown on this page because it was spam
You must be logged in to post in this thread.
Website copyright © 2002-2019 John Fitzgibbons. All posts are copyright their respective authors.