topameng's profileQuake3 启示录PhotosBlogListsMore Tools Help

Blog


    May 20

    quake3 rendercmds

    quake3 对于ui,客户端执行渲染命令都是先写入rendercmd列表:
    backEndData[tr.smpFrame]->commands
    等全部写入完毕后
    从这个列表获得渲染数据
    把顶点、颜色、法线等数据写入本地数据
    提交渲染数据
    看似多走了几步,浪费效率。
    1 写入渲染列表可以使图形渲染和客户端,UI分开。这样测试各个模块效率才能更准确。
    2 统一提交顶点颜色法线等数据能够提高效率,减少和显卡通信次数
    3 封装性更强,把渲染细节同UI客户端分离.
    缺点:
    难于调试,因为先填充列表而没有直接draw.难于拦截draw特定图像或者mesh的位置。

    可以在游戏引擎完善时加入这个特性。

    November 15

    winsock 10053

    这是个比较烦人的错误。不好遇到不好调试。而往往又不是软件的问题。
    当浏览 quake3 网络代码时,被他的delta 网络压缩搞得头昏脑胀。里面就有一项拆包的。既udp 包要小于服务器mtu 允许的大小(设置为1400).
    所以当用tcp send 消息时最好不要全部 send 再取发送长度,这样可能因为超过 mtu 允许而造成失败。而有时由于网络一次发送的又少于mtu极限,搞得时而成功时而失败。默认xp操作系统的mtu限制是1500,而有些服务器对adsl 限制是1492.
    其实真正好的做法应该是拆成小的包。如512大小。再加上包头指定包大小。这样更有利于网络传输。
    还有iocp之类的。
    当然如果你 send 的数据 buf 长度小于 len 指定的。一定会发生这个错误。
    或许这只是其中一个原因。先留一笔记住他

    November 14

    Quake 3 Network Protocol

    This document describes the network protocol that quake 3 uses to converse with clients and the outside world (query servers). Currently more of a work in progress.

    Query

    To query a server is very simple. Send a connectionless (UDP  对应服务器接收函数SV_ConnectionlessPacket) packet with 4 OOB header bytes (0xff) and the text string getstatus.(例如:NET_OutOfBandPrint( NS_CLIENT, to, "getstatus" )) There are many sites which contain a thorough description of this so I won't go into details.

    Game Protocol 68 - used by 1.32

    All game packets are connectionless (UDP), but there is still a handshaking process which much occur before you are allowed to join the server.

    The client sends a challenge request (sometimes you need to send multiple requests before the server will respond).
    NET_OutOfBandPrint(NS_CLIENT, clc.serverAddress, "getchallenge");

    +------------+----------------+
    | Header     | Content        |
    +------------+----------------+
    | 0xffffffff | getchallenge   |
    +------------+----------------+

    If the server is able to accept more connections it will reply with.
    NET_OutOfBandPrint( NS_SERVER, from, "challengeResponse %i", challenge->challenge )

    +------------+------------------------+
    | Header     | Content                |
    +------------+------------------------+
    | 0xffffffff | challengeResponse <ID> |
    +------------+------------------------+

    Once the client has the <ID> it can send a connect request. However, the CS is huffman compressed in protocol 68 and is NOT clear text as indicated below. Protocol 43 uses the plain text version.

    +------------+----------------+
    | Header     | Content        |
    +------------+----------------+
    | 0xffffffff | connect "<CS>" |
    +------------+----------------+
    <CS> represents a connection string containing the player details, e.g.
    \cg_predictItems\1\sex\male\handicap\100\color\3\snaps\40\rate\10000\model\doom/red\name\UnnamaedPlayer\protocol\68\qport\<PORT>\challenge\<ID>
    <PORT> represents the local port used to send this packet

    If the connect is successful the server will reply with the following

    +------------+-----------------+
    | Header     | Content         |
    +------------+-----------------+
    | 0xffffffff | connectResponse |
    +------------+-----------------+

    The server will now place you in the CNCT (connecting) state and start sending you game updates.

    This is where the communication gets substantially more difficult, so I warn you what follows may be incomplete and perhaps incorrect - although I hope not!.

    Client to Server
    clienttoserver 

    Client commands

    0 - clc_bad
    1 - clc_nop
    2 - clc_move
    3 - clc_moveNoDelta
    4 - clc_clientCommand
    5 - clc_EOF
    clientcommands

    Server to Client

     servertoclient

    Server Commands

    0 - svc_bad
    1 - svc_nop
    2 - svc_gamestate
    3 - svc_configstring
    4 - svc_baseline
    5 - svc_serverCommand
    6 - svc_download
    7 - svc_snapshot
    8 - svc_EOF
    Details

    (1) - Huffman compression using a predefined set of nodes to further reduce message length (detailed below).

    int msg_hData[256] = {
    250315,// 0
    41193,// 1
    6292,// 2
    7106,// 3
    3730,// 4
    3750,// 5
    6110,// 6
    23283,// 7
    33317,// 8
    6950,// 9
    7838,// 10
    9714,// 11
    9257,// 12
    17259,// 13
    3949,// 14
    1778,// 15
    8288,// 16
    1604,// 17
    1590,// 18
    1663,// 19
    1100,// 20
    1213,// 21
    1238,// 22
    1134,// 23
    1749,// 24
    1059,// 25
    1246,// 26
    1149,// 27
    1273,// 28
    4486,// 29
    2805,// 30
    3472,// 31
    21819,// 32
    1159,// 33
    1670,// 34
    1066,// 35
    1043,// 36
    1012,// 37
    1053,// 38
    1070,// 39
    1726,// 40
    888,// 41
    1180,// 42
    850,// 43
    960,// 44
    780,// 45
    1752,// 46
    3296,// 47
    10630,// 48
    4514,// 49
    5881,// 50
    2685,// 51
    4650,// 52
    3837,// 53
    2093,// 54
    1867,// 55
    2584,// 56
    1949,// 57
    1972,// 58
    940,// 59
    1134,// 60
    1788,// 61
    1670,// 62
    1206,// 63
    5719,// 64
    6128,// 65
    7222,// 66
    6654,// 67
    3710,// 68
    3795,// 69
    1492,// 70
    1524,// 71
    2215,// 72
    1140,// 73
    1355,// 74
    971,// 75
    2180,// 76
    1248,// 77
    1328,// 78
    1195,// 79
    1770,// 80
    1078,// 81
    1264,// 82
    1266,// 83
    1168,// 84
    965,// 85
    1155,// 86
    1186,// 87
    1347,// 88
    1228,// 89
    1529,// 90
    1600,// 91
    2617,// 92
    2048,// 93
    2546,// 94
    3275,// 95
    2410,// 96
    3585,// 97
    2504,// 98
    2800,// 99
    2675,// 100
    6146,// 101
    3663,// 102
    2840,// 103
    14253,// 104
    3164,// 105
    2221,// 106
    1687,// 107
    3208,// 108
    2739,// 109
    3512,// 110
    4796,// 111
    4091,// 112
    3515,// 113
    5288,// 114
    4016,// 115
    7937,// 116
    6031,// 117
    5360,// 118
    3924,// 119
    4892,// 120
    3743,// 121
    4566,// 122
    4807,// 123
    5852,// 124
    6400,// 125
    6225,// 126
    8291,// 127
    23243,// 128
    7838,// 129
    7073,// 130
    8935,// 131
    5437,// 132
    4483,// 133
    3641,// 134
    5256,// 135
    5312,// 136
    5328,// 137
    5370,// 138
    3492,// 139
    2458,// 140
    1694,// 141
    1821,// 142
    2121,// 143
    1916,// 144
    1149,// 145
    1516,// 146
    1367,// 147
    1236,// 148
    1029,// 149
    1258,// 150
    1104,// 151
    1245,// 152
    1006,// 153
    1149,// 154
    1025,// 155
    1241,// 156
    952,// 157
    1287,// 158
    997,// 159
    1713,// 160
    1009,// 161
    1187,// 162
    879,// 163
    1099,// 164
    929,// 165
    1078,// 166
    951,// 167
    1656,// 168
    930,// 169
    1153,// 170
    1030,// 171
    1262,// 172
    1062,// 173
    1214,// 174
    1060,// 175
    1621,// 176
    930,// 177
    1106,// 178
    912,// 179
    1034,// 180
    892,// 181
    1158,// 182
    990,// 183
    1175,// 184
    850,// 185
    1121,// 186
    903,// 187
    1087,// 188
    920,// 189
    1144,// 190
    1056,// 191
    3462,// 192
    2240,// 193
    4397,// 194
    12136,// 195
    7758,// 196
    1345,// 197
    1307,// 198
    3278,// 199
    1950,// 200
    886,// 201
    1023,// 202
    1112,// 203
    1077,// 204
    1042,// 205
    1061,// 206
    1071,// 207
    1484,// 208
    1001,// 209
    1096,// 210
    915,// 211
    1052,// 212
    995,// 213
    1070,// 214
    876,// 215
    1111,// 216
    851,// 217
    1059,// 218
    805,// 219
    1112,// 220
    923,// 221
    1103,// 222
    817,// 223
    1899,// 224
    1872,// 225
    976,// 226
    841,// 227
    1127,// 228
    956,// 229
    1159,// 230
    950,// 231
    7791,// 232
    954,// 233
    1289,// 234
    933,// 235
    1127,// 236
    3207,// 237
    1020,// 238
    927,// 239
    1355,// 240
    768,// 241
    1040,// 242
    745,// 243
    952,// 244
    805,// 245
    1073,// 246
    740,// 247
    1013,// 248
    805,// 249
    1008,// 250
    796,// 251
    996,// 252
    1057,// 253
    11457,// 254
    13504,// 255
    };

    (2) - XOR algorithm used by the server to decode the message content.

    #define CL_ENCODE_START 12
    byte key, *string;
    int i, index;

    string = (byte *)clc.serverCommands[ reliableAcknowledge & (MAX_RELIABLE_COMMANDS-1) ];
    index = 0;
    //
    key = clc.challenge ^ serverId ^ messageAcknowledge;
    for (i = CL_ENCODE_START; i < msg->cursize; i++)
    {
        // modify the key with the last received now acknowledged server command
        if (!string[index])
        {
            index = 0;
        }

        if (string[index] > 127 || string[index] == '%')
        {
            key ^= '.' << (i & 1);
        }
       else
       {
            key ^= string[index] << (i & 1);
      }
      index++;
    // encode the data with this key
    *(msg->data + i) = (*(msg->data + i)) ^ key;
    }

    3) - XOR algorithm used by the client to decode the message content.

    Notes

    data has mixed endianess - is this right?

    Packet fragmentation is worked out using a sequencetNumber & FRAGMENT_BIT (where FRAGMENT_BIT is 1<<31) calculation. If fragmented, flip the bit to 0 to correct the sequence number.

    cl_shownet 1 - MSG_SIZE
    cl_shownet 2|3 - READ_COUNT - CMD
    showpackets 1 - WHO recv MSG_SIZE : s=SEQ_NO (optional fragment info)

    October 20

    读取jpeg文件

    jpeglib 下载地址 
    quake3 使用的是这个lib的上一个版本,jpeg_stdio_src 函数略有变化。可以直接传递文件指针了。
    quake3 有些奇怪,读取得是垂直翻转的jpeg图片. 可能在画图时通过顶点顺序进行了纠正。
    正常读取jpeg 数据需要从底部向上读取(这段是错的,还是被一个老外代码忽悠的,郁闷) .不需要从底部读取。 

    quake3 jpeg 库读取的是RGBA像素格式。新的库是 RGB 格式。
    有了库读取的代码很固定。基本没什么大的变化:
    cinfo.output_components 对于上面的库是3,即返回的*pic 是RGB格式。但 quake3 用的alpha版lib返回的是4.*pic 是RGBA格式。
    static void LoadJPG( const char *filename, unsigned char **pic, int *width, int *height )
    {
     struct jpeg_decompress_struct cinfo;
     struct jpeg_error_mgr jerr;
     JSAMPARRAY buffer;  /* Output row buffer */
     int row_stride;  /* physical row width in output buffer */
     unsigned char *out;
     byte  *bbuf;
     FILE* pFile = NULL;
     if((pFile = fopen(filename, "rb")) == NULL)
     {
      MessageBox(hWnd, "Error loading jpg file.", "ERROR", MB_OK);
      return;
     }
     cinfo.err = jpeg_std_error(&jerr);
     jpeg_create_decompress(&cinfo);
     jpeg_stdio_src(&cinfo, pFile);
     (void) jpeg_read_header(&cinfo, TRUE);
     (void) jpeg_start_decompress(&cinfo);
     row_stride = cinfo.output_width * cinfo.output_components;
     out = (unsigned char*)malloc(cinfo.output_width*cinfo.output_height*cinfo.output_components);
     *pic = out;
     *width = cinfo.output_width;
     *height = cinfo.output_height;
     while (cinfo.output_scanline < cinfo.output_height)
     {
      bbuf = ((out+(row_stride*cinfo.output_scanline)));
      buffer = &bbuf;
      (void) jpeg_read_scanlines(&cinfo, buffer, 1);
     }
     jpeg_finish_decompress(&cinfo);
     jpeg_destroy_decompress(&cinfo);
     fclose(pFile);
    }

    演示代码地址:(opengl 版,改天用MFC实现一个)
    opengl : http://www.91files.com/?ADPDMNF5EKJG9GR3EBSQ
    对于 dx9 不需要,dx9 支持 jpg png bmp dds 等等相当广泛的图形文件格式
    October 17

    quake3 技术随笔

    关于纹理压缩
    r_ext_compressed_textures  开启纹理压缩,可以提高速度。和图像大小压缩不是一个概念
    typedef enum
    {
    TC_NONE,
    TC_S3TC
    } textureCompression_t;
    现在 directx9c 已经支持到了3dc技术
     

    运行中显示控制台窗口

    在运行时打开(按tab上面的~键),输入:  viewlog 2

    去掉CD-KEY菜单
    去掉启动时CD 界面 修改 cl_ui.c 中函数
    int CL_UISystemCalls( int *args )
    {
    。。。。。。。。

    case UI_VERIFY_CDKEY:
        //return CL_CDKeyValidate(VMA(1), VMA(2));
        return qtrue;

    。。。。。。。。

    }


    获得投影坐标系


    奇怪使用了正交投影而不是游戏常用的透视投影 ?
    quake3 的透视投影是自己实现的,没有调用opengl的函数 glFrustum 或 gluPerspective。而是自己实现了一个函数来设置投影矩阵 R_SetupFrustum

    投影原点为左上点(如魔兽世界)
      (0,0)-----------------------(width, 0  )
           |
           |
           |
           |
       (0, height)--------------------- (width,height)
    获得2d投影坐标:

    qglViewport( 0, 0, glConfig.vidWidth, glConfig.vidHeight );  //规一化设备坐标到窗口坐标
    qglScissor( 0, 0, glConfig.vidWidth, glConfig.vidHeight );      //设置裁切范围
    qglMatrixMode(GL_PROJECTION);
    qglLoadIdentity ();
    //glOrtho(left,right,bottom,top,near,far)
    qglOrtho (0, glConfig.vidWidth, glConfig.vidHeight, 0, 0, 1);
    qglMatrixMode(GL_MODELVIEW);
    qglLoadIdentity ();

    GL_State( GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );

    qglDisable( GL_CULL_FACE );
    qglDisable( GL_CLIP_PLANE0 );

    设置之后就可以当成平面坐标系使用了:如下在(0,0,640,480) 区域画一张图片
    glBindTexture(GL_TEXTURE_2D, 0);   //假定纹理 Num 为0
    glBegin(GL_TRIANGLES);
    glTexCoord2f(0.0f, 1.0f);
    glVertex3f(0, 480, 0);
    glTexCoord2f(0.0f, 0.0f);
    glVertex3f(0, 0, 0);
    glTexCoord2f(1.0f, 1.0f);
    glVertex3f(640, 480, 0);

    glTexCoord2f(1.0f, 1.0f);
    glVertex3f(640, 480, 0);
    glTexCoord2f(0.0f, 0.0f);
    glVertex3f(0, 0, 0);
    glTexCoord2f(1.0f, 0.0f);
    glVertex3f(640, 0, 0);
    glEnd();


    对于 directx 设置2d坐标画纹理,只需要 SetFvF 的 FVF 包含 D3DFVF_XYZRHW 就可以(w 值为1.0即可)然后画顶点流


    Huffman 压缩

    使用动态huffman 网络压缩算法,但网络传输中不再修改编码。还是相当于静态huffman压缩



    Mipmap

    自定义的  mipmap 算法函数进行 mipmap 计算

    混合

    OpenGL 通过glColorPointer 设置顶点颜色color,相当与 directx 顶点的 diffuse color。
    对于带alpha通道的图片。如果alpha值大于0像素为纯颜色图像(RGB值只有1个分量不为0,如红色) ,而diffuse color中不包含该颜色分量的话,将不会显示图像。对于白色将能反射所有颜色。


    所以一个带alpha通道的白色文字图像,只要指定不同的顶点color 。就能变成不同颜色的字


    去掉 alpha 为 0 的像素办法。画该纹理时
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
    这样源文件中alpha为0的像素,完全取目标图像得像素值

    使用GL_CONSTANT_ALPHA 时可以通过
    glBlendColor(r,g,b,a) 来指定一个常量颜色

     

    对于半透明特效,如火、水。可以使用不用 alpha 的 jpg 纹理,图片火之外的颜色设为黑色,如下使用混合参数:
    glBlendFunc(GL_ONE,GL_ONE);
    因为源中黑色值RGB均为0,所以取的目标RGB值。而火颜色部分则和目标背景相加混合.这比使用alpha测试速度要好。如果火颜色的alpha值要动态变化(这样效果才好),则无法用alpha测试
    如果原图片颜色不够明亮,如蓝色过多。GL_ONE,GL_ONE 让源图片有位于目标图片背后的感觉,但黄色火焰则感觉较小

    bluetoback 
    蓝色图是后画的采用 glBlendFunc(GL_ONE,GL_ONE)混合,感觉跑到目标图后面去了。但如果是明亮的黄色则不会有这种感觉。

    蒙版效果:
    而 glBlendFunc(GL_DST_COLOR,GL_ZERO) 可以形成蒙版效果。源图像为黑白图,所以白色部分,为目标图像中的部分。而黑色部分,则目标图颜色被去掉成为黑色。然后黑白图相同位置,用glBlendFunc(GL_ONE,GL_ONE)再渲染需要真正叠加到上面的图。类似于 alpha 效果,但画图可以更精确一些。

    maskeffect

      maskover

    对应 directx SetRenderState 函数


    static qboolean ParseStage( shaderStage_t *stage, char **text )
    屏蔽的地方影响火的特效,有多个图片形成动画

    // parse up to MAX_IMAGE_ANIMATIONS animations
    while ( 1 ) {
        int        num;

        token = COM_ParseExt( text, qfalse );
        if ( !token[0] ) {
            break;
        }
        num = stage->bundle[0].numImageAnimations;
        if ( num < MAX_IMAGE_ANIMATIONS ) {
            stage->bundle[0].image[num] = R_FindImageFile( token, !shader.noMipMaps, !shader.noPicMip, GL_REPEAT );
            /*if ( !stage->bundle[0].image[num] )
            {
                ri.Printf( PRINT_WARNING, "WARNING: R_FindImageFile could not find '%s' in shader '%s'\n", token, shader.name );
                return qfalse;
            }
            stage->bundle[0].numImageAnimations++;*/
        }
    }


    下面的是火特效的脚本。

    如果不是放到3d游戏场景中,surfaceparm nomarks ,surfaceparm nolightmap ,cull none  三个可以不需要. 如放到 UI 某个界面。

    注意 animMap 后面的参数中不能有回车。 shader 一条命令中的字符串是不允许回车存在的

    animMap <播放频率> <依次要播放的图片,最多8个>
    blendFunc <参数1> <参数2>  混合方式 glBlendFunc(GL_ONE,GL_ONE)
    rgbGen 顶点rgb 操作命令。 wave 是指调整顶点RGB颜色,形成波动效果。 inverseSawtooth  wave调整函数

    textures/sfx/testfire
    {

        //    *************************************************
        //    *          ameng designed to test fire effect        *
        //    *************************************************
            surfaceparm nomarks
            surfaceparm nolightmap
           cull none       
        {
            animMap 10     textures/sfx/flame1.tga textures/sfx/flame2.tga textures/sfx/flame3.tga textures/sfx/flame4.tga textures/sfx/flame5.tga textures/sfx/flame6.tga textures/sfx/flame7.tga textures/sfx/flame8.tga
            blendFunc GL_ONE GL_ONE
            rgbGen wave inverseSawtooth 0 1 0 10
        }   
        {
            animMap 10     textures/sfx/flame2.tga textures/sfx/flame3.tga textures/sfx/flame4.tga textures/sfx/flame5.tga textures/sfx/flame6.tga textures/sfx/flame7.tga textures/sfx/flame8.tga textures/sfx/flame1.tga
            blendFunc GL_ONE GL_ONE
            rgbGen wave sawtooth 0 1 0 10
        }   

        {
            map textures/sfx/flameball.tga
            blendFunc GL_ONE GL_ONE
            rgbGen wave sin .6 .2 0 .6   
        }

    }




    一次消息循环调用了2次 Com_EventLoop 。一次在开头处理消息(大部分为键盘鼠标消息)。第二个为网络通讯后处理消息使网络消息能在当前帧内处理。

    Com_EventLoop() -> Com_GetEvent()  首先查看 com_pushedEvents[] 中是否有消息。没有才通过 Com_GetRealEvent() 获得消息。 com_pushEvents  中的事件是 Com_Milliseconds()函数写入的。通过此函数即可获得当前时间,也可压入当前事件。防止当前函数调用时间过长影响事件相应速度



    glTexImage2D 生成纹理函数,如果不支持自动 mipmap, 指定纹理滤波的参数必须是 GL_LINEAR. 否则没有图片。为白色图像

    qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
    qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

    quake3 主要参数说明

    4506版q3参数. 红色字为修改过的说明,参照英文或者 q3.1.32b 源代码
    activeaction "" 定义一个命令,这个命令可以在下一张地图载入前执行
    arch "win98" 标明操作系统
    bot_aasoptimize "0" 优化.aas文件
    bot_challenge "0" 加强bot的挑战性
    bot_debug "0" 启动/关闭bot代码debug工具
    bot_developer "0" 启动/关闭bot开发模式
    bot_enable "0" 使地图中和游戏中所带的BOT可以出现或者不能出现r
    bot_fastchat "0" 切换bot说话的频率,如果设置成1的话,bot的话会特别多
    bot_forceclustering "0" 强迫重新计算aas群集
    bot_forcereachability "0" 强迫重新计算aas的可涉及能力
    bot_forcewrite "0" 强迫写出一个.ass文件
    bot_grapple "0" 决定bot是否使用抓钩
    bot_groundonly "1" 这是个debug变量,可以显示零售版本中没有的区域
    bot_interbreedbots "10" 将电脑bot的性格和逻辑思维的进行综合所应用到几个bot身上
    bot_interbreedchar "" 将电脑bot的性格和逻辑思维的进行综合
    bot_interbreedcycle "20" 综合过程中相似点的数目
    bot_interbreedwrite "" 综合思维写进文件
    bot_maxdebugpolys "128" debug时用到的最多的多边形数目
    bot_memorydump "0" 可能是debug时用来显示bot所分配和占用的内存
    bot_minplayers "0" 这个是用来确保游戏服务器上最少在线人数所用的命令,bot的数目会根据玩家的人数自动增加或者减少
    bot_nochat "0" 决定bot是否说话,设置为0的时候bot可以说话
    bot_pause "0" debug时用到一个参数用来暂停bot
    bot_reachability "0" 这是个debug变量,不能在零售版本中使用
    bot_reloadcharacters "0" 当这个变量设置为1的时候,bot角色文件不能被缓存,一般用于边运行Q3A边开发bot的时候
    bot_report "0"  debug中的命令用于电脑bot能在CTF时进行报告
    bot_rocketjump "1" 决定bot是否使用火箭跳技术
    bot_testichat "0" 用来看bot的初始的话,如果设置成1,然后加入一个bot,这个bot会滔滔不把Id为他做的话全说出来。
    bot_testrchat "0" 用来测试bot的回答功能。如果设置成1,只要你说一些他可以懂的话他就会说一大堆话来回答你
    bot_testsolid "0" 测试.ass文件中的"固体区域"
    bot_thinktime "100" 设置bot的两个AI帧之间的时间,单位是毫秒
    bot_usehook "0" 设定bot是否使用抓钩
    bot_visualizejumppads "0" 
    capturelimit "8" 设定夺棋比赛获胜所需要夺旗子的次数
    cf_AmmoStatusbar "8*8" ch_statusbarFormat 2或3时,显示子弹的字体大小
    cf_CrosshairNames "16*16" 准星指向名称字体大小
    cf_Following "12*12" "Following"信息字体大小
    cf_Fragmsg "16*16"  HUD顶端"you fragged"字体大小
    cf_Scores "16*16" HUD右下角分数字体大小
    cf_Pickupstring "16*16" 拾取信息字体大小
    cf_Statusbar "48*48" 当ch_statusbarFormat为1时,状态栏字体的大小
    cf_Teamchat "16*16" teamchat字体大小
    cf_TeamCrosshairHealth "12*12" 准星指向显示的健康程度信息字体的大小
    cf_Teamoverlay "7*17" teamoverlay字体大小
    cf_Vote "12*12" vote信息字体大小
    cf_WeaponName "12*12"  ch_weaponswitch为1时,武器名称字体大小
    cf_WeaponSwitch "32*32" 武器开关图象大小
    cg_altGrenades "0" 使用可选的手雷skin/model(默认0 - 使用baseq3的手雷skin)
    cg_altLightning "0" 使用1.29以前的电枪skin(默认0 - 使用新的1.29/promode skin)
    cg_altPlasma "0" 使用可选的离子枪skin(默认0 - baseq3的skin)
    cg_ammoCheck "9" 取消切换到没有子弹的武器的功能(默认为0)
    cg_animspeed "1" 使玩家更有活力 (详见 cg_noplayeranims 命令)
    cg_autoAction "0" 在游戏特定点自动执行一个动作.(默认为0) 1 - 在比赛结束时在本地自动保存一个文本文件 文件被保存在/stats//.txt 2 - 自动保存一比赛结束时的画面  4 - 自动录demo(需要一个full warmup的服务器-g_warmup = 0)
    cg_autoswitch "1" 设定在拾到武器后会自动切换武器。
    cg_bobpitch "0.002" 在移动过程中玩家视角的前/后移动
    cg_bobroll "0.002" 在移动过程中玩家视角的左/右移动
    cg_bobup "0.005" set 在移动过程中玩家视角的上/下移动
    cg_brassTime "1250" 设定游戏启动时载入外壳所需要时间,设定为0不载入外壳。
    cg_centertime "3" 设定在屏幕中央讯息显示时间(设定0不显示)
    cg_clientLog "0" 打开客户端log记录。一个非0的数值"X"(这里"X"为1或更高的数字)会记录下游戏中的所有可得的信息。表示颜色的字符被去掉了,时间标记被保留。所有信息被记录在osp/client_logs/clientX.txt中(这里的clientX.txt中的X就是你前面输入的那个非0的数字)。
    cg_crosshairHealth "1" 通过准星的颜色变化大致知道自己现在的Health。
    cg_crosshairSize "24" 调整准星大小
    cg_crosshairX "0" 如果cg_crosshairSize 不为0,此参数设定准星的X坐标
    cg_crosshairY "0" 如果cg_crosshairSize 不为0,此参数设定准星的Y坐标
    cg_Customloc "0" 使用locs/.cfg的自定义位置.现在只支持teamoverly的自定义位置. 以后会支持teamchat位置.要在地图加入一个位置,移动到特定点,然后输入 \addpos 你可以在文件中使用所有的颜色和字体特性.这些位置会被记在locs\.cfg 中.当地图被调入或客户端使用vid_restart后,这些位置会被一起调入
    cg_deadBodyFilter "0" 打开/关闭地图中对尸体的显示
    cg_debuganim "0" 开启 model 活跃程度 debug 模式
    cg_debugevents "0" 开启事件debug 模式
    cg_debugposition "0" 开启玩家位置debug模式
    cg_deferPlayers "1" 如果有玩家用新的Model或者Skin在你之后加入游戏,在换地图之前服务器不会让你马上去D/L这个新的Model或者Skin。
    cg_demoLook "0" 可能是改变看demo的方式
    cg_draw2D "1" 切换状态栏显示的物品是2D图标还是文字模式
    cg_draw3dIcons "1" 切换HUD中弹药等显示方式是3D图标还是2D图标
    cg_drawAmmoWarning "1" 是否显示弹药缺少警告
    cg_drawAttacker "1" 是否显示最后一个攻击你的人是谁
    cg_drawCrosshair "1" 选择准星的形状,如果你对自己的水平有信心的话,可以设定为“0”——没有准星 ;)
    cg_drawCrosshairNames "1" 是否显示你瞄准的人的名字
    cg_drawDecals "1" 打开/关闭in-game的decals的绘制(默认1 - 打开)
    cg_drawFPS "0" toggle设置每秒显示帧数,“0”是默认值
    cg_drawGun "1" 是否显示你拿的武器
    cg_drawIcons "1" 是否显示在HUB和积分牌上显示物品和角色的图标
    cg_drawRewards "1" 是否显示奖励的图标
    cg_drawKiller "1" 是否显示上次把你杀了的那个人的名字和图象
    cg_drawSnapshot "0" 是否从游戏开始的显示射击次数
    cg_drawStatus "1" 是否显示个人得分和健康状态
    cg_drawTeamOverlay "0" 是否在屏幕右上方显示己方队伍的当前状态,如果是的话,可以显示己方队伍的队员名称,位置,武器类型,弹药数量以及各人得分情况
    cg_drawTimer "1" 在HUD上显示时间,如果有时间限制,会显示还有多少时间剩下
    cg_enableOSPHUD "1" 使用OSP的HUD(默认为1)
    cg_enemyColors <RHSL> 如果使用q3 model的默认的“pm”skin,则定义敌人的颜色,R - rg的颜色(要cg_teamrails 2),H - 头颜色 ,S - 身体颜色 ,L - 腿颜色 -----> 注意:RHSL参数可以使用0-9,a-z
    cg_enemyModel <modelname> 设置敌人为这种model,队友仍然为各自的model,除非你使用g_forcemodel 1 这样队友将和你使用同一种model(默认为""即关闭)
    cg_errordecay "100" 可能是用于设置终止错误扩散的间隔
    cg_extrapolate "1"
    cg_float "0" 允许使用飘动的记分板效果(默认为0)
    cg_followkiller "0" 自动跟踪到杀死现在被跟踪者的玩家
    cg_followpowerup "0" 允许客户端自动跟踪吃到宝物的玩家。在自动跟踪宝物携带者的设置下,携带旗帜的玩家处于被跟踪的最高级别。当你跟踪的正是携带旗帜的玩家时,你不能自动进行视角的切换,除非他被击毙或夺旗成功。当然如果你跟踪的携带宝物的玩家被击毙后,如果还存在携带宝物的玩家,那你的视角会自动切换到另外一个携带报务玩家身上。
    cg_followviewcam "1" 定义使用动态的、特殊的玩家跟踪视角(默认为1,跟踪特定玩家)
    cg_footsteps "1" 是否在游戏中开启脚步声
    cg_forceColors "0" 如果使用“pm”skin,强制所有队友都为你的颜色设置
    cg_forceModel "0" 强制Model的选择,强制特定声音
    cg_fov "90" 设置视野角度,默认是90,如果数字更大的话,视野也更大,不过不要太大了。
    cg_gibs "1" toggle the display of animated gibs (explosions flying body parts!)
    cg_gun "1" toggle是否显示你手中拿的武器
    cg_gunX "0" 如果cg_drawGun 设置为1,此参数用来设置可见武器的X轴
    cg_gunY "0" 如果cg_drawGun 设置为1,此参数用来设置可见武器的Y轴
    cg_gunZ "0" 如果cg_drawGun 设置为1,此参数用来设置可见武器的Z轴,确定武器和Model的前后位置关系
    cg_ignore "0" 可能是允许或者不允许自己设置硬件的驱动参数
    cg_lagometer "1" 如果设置为1时在HUD上显示lag显示表为网络图形,如果设置为0就显示为得分计数器,它会变换颜色来显示你当前的情况,3Test_Instructions_Readme.txt第6章中已经详细介绍过这个工具。在屏幕顶端会有一个蓝黄色图形:一条线描绘出每一帧的情况。如果一条蓝线在基本线下运行,说明帧与帧之间的连贯性很好,如果一条黄线超过基本线在其上面运行,就说明帧与帧之间不是那么连贯了。(怎么看着象KDJ指数图形啊),在底端的绿黄红图表上:一条线用于描绘接受到的每一个snapshot ,如果线是绿的,说明可能收到了,线的高度Ping的大小是成比例的,如果线是黄的,说明snapshot被退回,如果线是红的,说明snapshot在网络中丢失了。
    cg_markoffset "1" 设置贴图的偏移量,许多显示卡的贴图会产生错误的偏移,所以有时候会在墙壁上看见很明显的方块贴图,改变偏移量贴图就会恢复正常。
    cg_marks "1" 是否显示弹孔
    cg_MaxlocationWidth "16" 设置teamoverly和teamchat时的本地最大显示长度
    cg_muzzleFlash "1" 设置当cg_drawGun为1时,是否显示开火时枪口处的溅火效果
    cg_nochatbeep "0" 允许客户端在接到正常交谈消息时听到提示音
    cg_nomip "0" 不管现在的r_picmip设置为什么,允许图象变换到picmip 0的设置. (默认为0,所有gfx设置与r_picmip相同) 1-LightningGun shaft电枪 2-PlasmaGun bolt等离子枪 4 - Rocket Launcher explosions火箭炮的爆炸效果  8-Grenade Launcher explosions手雷的爆炸效果  16-Bullets (machinegun and shotgun)子弹(机枪和霰弹枪) 32-Railgun涡轮枪 64-BFG 128-Blood marks 血迹
    cg_noplayeranims "0" 设置Model活跃性
    cg_nopredict "0" 是否对客户端玩家预报
    cg_oldCTFSounds "0" 允许使用1.27以前的CTF音效(默认不使用)
    cg_oldPlasma "1" 定义使用老的或新的离子枪子弹效果
    cg_oldRail "1" 定义使用老的或新的RG子弹效果
    cg_oversampleMouse "0" 如果pmove_fixed在服务器被强制为0,允许客户端使用pmove增强鼠标采样率(默认0 - 普通鼠标采样)
    cg_predictItems "1" 是否对客户端物品进行预报
    cg_q3compScoreboard "0" 0 - id默认的记分板 1 - q3comp记分板(TDM、CTF和CA模式下)
    cg_railTrailTime "400" 设置RG的轨迹持续显示时间
    cg_runpitch "0.002" 设置玩家在跑动时上下振动的次数
    cg_runroll "0.005" 设置玩家在跑动是左右晃动的次数
    cg_scoreTransparency "1.0" 调整记分板字体的alpha通道.数越小,字体约透明 (默认为1.0)
    cg_shadows "0" 设置阴影细节描绘的级别(0 = 关闭, 1 = 最基本, 2 = 模板缓冲 3 = 简单模板缓冲(如果 r_stencilebits不为=0))
    cg_showcrosshair "1"
    cg_showmiss "0" 是否在HUD上显示或者预示在传输中丢失的包
    cg_showPlayerLean " 允许关闭1.27中的model倾斜问题
    cg_simpleItems "0" 使一些物品以简单的模式显示,这样可以加快游戏速度。
    cg_stats "0" 是否按顺序显示客户的帧,丢失的帧不显示
    cg_statscrolltime "0.15" 设置stat窗口卷入卷出的时间.设置为0则强制直接显示
    cg_stereoSeparation "0.4" 设置立体声分离,不过基本上好没什么用,不同的设置得到的效果好象没什么不同
    cg_swapSkins "0" 允许你使用与当前相反的皮肤颜色.但是announcements, overlays,记分板 仍然显示你真正的颜色
    cg_swingSpeed "0.3" 设置Model在对战时的旋转(1 为不停顿, 0 为不转)
    cg_teamChatHeight "8" 在团队作战时设置在屏幕上显示的文字的大小
    cg_teamChatTime "3000" 设定队友的交谈在屏幕上保留多长时间
    cg_teamRails "0" 设置玩家rg轨迹的颜色,但只在组队模式下有效 0-rg轨迹为玩家各自设置的颜色 1-rg轨迹为队伍的颜色(比如红队所有队员的rg轨迹都是红色的) 2-队友rg轨迹颜色由color1中的R参数决定,敌人rg轨迹颜色由cg_enemyColors的R参数决定
    cg_temp "0"
    cg_testentities "0"
    cg_thirdPerson "0" 将游戏视野切换为第三人称角度
    cg_thirdPersonAngle "0" 改变你观看你所控制的角色的视角(设置为180是从前面看)
    cg_thirdPersonRange "40" 改变你对你自己的后视距离
    cg_tracerchance "0.4" 设定跟踪弹药的频率
    cg_tracerlength "100" 设定跟踪弹药的长度
    cg_tracerwidth "1" 设定跟踪弹药的宽度
    cg_truelightning "0" 0-在baseq3下看到的默认的电枪反馈 1-pure客户端渲染的电枪 2-综合服务器和客户端渲染的电枪
    cg_useScreenShotJPEG "0" 允许玩家使用jpg的截图来实现自动截图 0-使用tga截图 1-使用jpg截图
    cg_viewsize "100" 改变视野大小
    cg_zoomfov "22.5" 设置阻击模式的视角放大倍数,可以超过30
    cg_waveamplitude "1"
    cg_wavefrequency1 "0.4"
    ch_ColorLocations "0" 如果位置的文本颜色为红或蓝,改变teamoverly中位置的颜色到红或蓝
    ch_CrosshairColor "white" 改变准星的颜色。用法: ch_crosshaircolor 0xRRGGBB|<color> <color>:white, black, red, green, blue, yellow, magenta,cyan, 和 grey.用RGB的数值,例子ch_crosshaircolor 0xFF3377会产生一种奇妙的颜色。特别要注意:cg_crosshairHealth必须关闭掉(cg_crosshairHealth要为0),ch_CrosshairColor才能起作用
    ch_CrosshairNamesLeft "0" 如果打开,则在teamchat顶端HUD的左边显示名字
    ch_drawFlagNames "0" 0-id默认 1-显示夺旗手名字(没有icon) 2-显示夺旗手名字和icon  3-在右下脚显示夺旗手名字(没有icon)(只在q3comp状态栏下有效)  4-在右下脚显示夺旗手名字和icon(只在q3comp状态栏下有效)
    ch_FilterLocationsTeamchat "0" 从teamchat中过滤掉位置信息
    ch_InverseTeamChat "0" 反转teamchat窗口.如果打开,则先到的信息显示在顶端
    ch_Obituaries "1" 在控制台是否显示玩家被杀信息
    ch_Pickupitem "1" 当物品被吃时,显示他们的icon和字符
    ch_StatusbarFormat "0" 0-使用id默认的状态条 1-使用osp默认的状态条.显示子弹图标、武器图标、健康状况、旗子(ctf下) 和盔甲.使用cf_statusbar来scale状态条字体大小 2-和1一样,但在边上显示每种武器子弹的图象 3-和1一样,但武器子弹以数字显示 4-CPM 风格0 hud (象 vq3)  5-CPM 血/甲 条  6-CPM 风格 3  7-CPM 风格 4  8-CPM 风格 5  9-Q3Comp 风格 1  10-Q3Comp 风格 2  11-Q3Comp 风格 3  12-Q3Comp 风格 4
    ch_TeamBackground "0" 在状态条,teamchat中关闭组队背景颜色
    ch_TeamchatOnly "0" 如果打开,则在HUD的左下只显示teamchat
    ch_TeamCrosshairHealth "0" 如果打开,则当准星对准队友时,显示其血、甲,只有在teamoverlay打开时有效 h_Teamoverlay "p12n h/aw" 定义显示teamoverlay中的信息的大小. p-宝物图标,在左  12n-名字宽度(名字是必须的)  h-玩家血  a-玩家甲  w-武器图标 l-玩家位置 所有其他不能分列的物品将被插入到玩家fields中(比如` ` 和 `/`)
    ch_Weaponswitch "0" 0-老的id风格,在teamchat的顶端 1-和0相同,但是为数字 2-垂直的,表现在HUD的右边 3-和2相同,但是为数字 4-垂直的,表现在HUD的左边 5-和4相同,但是为数字并且显示每个相邻武器的子弹 6-CPM左边风格 7-CPM右边风格 8-CPM底端风格 9-不显示武器开关
    cheats "0" 允许作弊命令,比如(give all) (仅在服务器端可执行)
    cl_anglespeedkey "1.5" 设置方向键改变视角的时间
    cl_avidemo "0" 是否把抓图以幻灯片形式存入snapshot文件夹。
    cl_allowDownload "0" 是否从服务器更新地图等文件。客户端参数
    cl_cdkey "123456789" 设置CDKEY
    cl_debugMove "0"
    cl_freelook "1" 是否用鼠标来让你可以自由的上下左右看
    cl_freezeDemo "0" 中止Demo的播放,停在某以帧上
    cl_guid "" punkbuster自带的一个参数,用来唯一标识客户端的
    cl_maxpackets "30" 设置1秒内客户端传输多少包给服务器 范围 15-125
    cl_maxPing "800" 控制哪个服务器出现在 in-game server 浏览器里
    cl_motd "1" toggle 当Q3A服务器开始运行的时候,他会发一道短消息(Motd--Message of theday)给ID的Motd服务器,然后会有个回应包,如果你设置为0,就可以关掉这个功能
    cl_mouseAccel "0" 给鼠标加速,转身等等速度会得到提高。
    cl_nodelta "0" disable取消delta压缩 (会降低网络性能, 只有当网络出错时才用否则不推荐使用)
    cl_noprint "0" 是否在你的屏幕上或者控制台上显示交谈内容
    cl_packetdup "1" 当丢包时是否重传,设置范围1到5,默认为1,即出现丢包时,自动重传1次丢失包的备份
    cl_paused "0" variable这个变量可以在客户端保持暂停状态
    cl_pitchspeed "140" 设置向上看和向下看的倾斜速度
    cl_punkbuster "0" 允许在服务器列表中允许punkbuster客户端
    cl_run "1" 总是跑
    cl_running "1" 可能是服务器端控制跑的命令,大概要优先于客户端的 cl_run 命令
    cl_showmouserate "0" 用鼠标测试帧来显示鼠标速率
    cl_shownet "0" 显示网络质量信息
    cl_showSend "0" 网络debug工具
    cl_showTimeDelta "0"  display time delta between server updates
    cl_timeNudge "0" 有效改善lag情况,实际上是用于调整客户端预测量的一个参数.这个命令有两个作用:
    Offline时,可以设置为正数(设置为85试试 ),用来模拟一定的ping值,免得人家说你0 ping欺负bot:P,同时正数也起到一定的稳定fps值的作用(偶没感觉到。。。)。
    另一个作用是online时,设置为负数,也就是调整客户端的预测提前量。一般用于较高ping时,补偿ping值的影响时使用。这个负数的大小,应该是你平均ping值的25%到50%,平均ping值指的是你按Tab看到的,不是drawping看到的值。比如,ping为100,那么cl_timenudge应该设置在-25到-50之间。不要忘了,设置为负值时,要把smoothclients设置为0!
    Online时尽量不要使用这个参数,应该设置为默认值0,毕竟它是用预测算法来工作的,预测。。。除非你要减少ping值对你的影响。
    cl_timeout "125" 当你由于过度lag导致服务器把你断线这中间等待的时间
    cl_updateInfoString "" "challenge\14985\motd\用于ID的新版本出来的时候"
    cl_yawspeed "140" 设定左右移动的偏移速度
    cm_curveClipHack "0" 这无疑是个作弊参数!已经被移除
    cm_noAreas "0"
    cm_noCurves "0" 是否有能力穿越弯曲表面
    cm_playerCurveClip "1"
    color "1" RG轨迹的颜色blue/green/cyan/red/magenta/yellow/white 对应为 1/2/3/4/5/6/7
    color2 "1" 定义rg轨迹涡轮颜色---> 注意:color1/color2 "char"可从0-9,a-z
    com_blood "1" 是否在被攻击时眼前出现血光,建议关掉
    com_buildScript "0" 可能是允许为通信事件建立脚本语言
    com_dropsim "0" 测试通信停止时丢失的模拟信息包设置一个值,当随机值小于次数时扔掉网络包,来模拟网络丢失
    com_hunkMegs "20" 用于服务器内存优化。 例如: com_hunkMegs "4" sv_maxclients
    bot_enable 0
    com_introplayed "1" 是否放片头动画
    com_maxfps "100" 设置每秒你可以从服务器接受的最大帧数
    com_showtrace "0" 是否显示信息包的踪迹. 0=取消,1=开启
    com_speeds "0" 可能是选择是否显示连接速度
    con_notifytime "3" 限制来自玩家或者服务器信息显示在屏幕上的行数还是时间??
    conback "" 选择控制台背景文件"gfx/2d/conback.tga"
    crosshairhealth "1" 在准星上显示血的多少
    crosshairsize "24" 准星的大小
    d_bot "" 所有d_ 命令已经被取消
    d_botai "0" 所有d_ 命令已经被取消
    d_botaiming "0" 所有d_ 命令已经被取消
    d_botfreeze "0" 所有d_ 命令已经被取消
    d_break "0" 所有d_ 命令已经被取消
    d_noroam "0" 所有d_ 命令已经被取消
    debuggraph "0"
    dedicated "0" 设置服务器十使用,如果设置为1的话就不载入整个3D引擎和游戏,可以节省资源,比如 C:\Q3TEST\quake3.exe +set dedicated 1
    developer "0" 启动开发者模式
    dmflags "0" 设置DM模式的胜利得分数
    fixedtime "0" 是否一定要等到上一帧已经完全回馈才发送下一帧
    fov "90" 设置视角宽度
    fraglimit "20" 在服务器上设置胜利要求的得分(0是无限)
    freelook "1" 用鼠标控制瞄准和头的转动
    fs_basepath "" 设置一个文件自动下载的基本路径,比如C:\quake3
    fs_cdpath "" 大概是设置CD-ROM的盘符
    fs_copyfiles "0" 大概是设置文件可否从服务器拷贝,客户端是否可以下载.更正:是否从CD逐步拷贝文件到硬盘
    fs_debug "0" 大概是启动文件服务器的Debug功能
    fs_game "" 设置游戏模式?
    fs_restrict "" 受限制模式,demo 版本不允许从服务器下载文件。只能加载 pk3 文件中的*.qvm,而不是对应的dll.
    g_aimTest "0" 此命令取消,大概因为是个作弊命令,类似机器人自动瞄准
    g_allowVote "1" 是否可以在服务器上进行vote(投票,一般用于决定使用地图)
    g_arenaName "0" 大概是决定是否显示当前区域的名字
    g_arenaRank "" 大概是一个进行归类的参数
    g_arenaScores "" 大概是一个保持上一系列得分级数的参数
    g_arenasFile "" 大概是Q3的一个log文件
    g_banIPs "" 设置哪些IP禁止连上服务器
    g_botsFile "" 设置一个用与设置bot配置和角色的文件名
    g_debugAlloc "0" 大概是一个内存分配debug工具,在1.11版本中存在
    g_debugDamage "0" 大概是伤害力的debug工具?
    g_debugMove "0" 大概是角色移动的debug工具
    g_doWarmup "0" 是否在团队比赛和CTF开始前有一段警告时间,类似倒计时之类的
    g_filterBan "1" 是否使用特定的过滤模式来拒绝某些玩家的连入
    g_forcerespawn "10" 设置重生的最大时间间隔,设置为 0 就是不强制重生
    g_friendlyFire "0" 设置是否会被队友误伤,设置为 1 为可以被队友所杀或者伤害
    g_gametype "0" 0 - Free For All 1 - Tournament 2 - Single Player 3 - Team Deathmatch 4 - Capture the Flag 用于设置服务器的游戏模式,如果你想开一个 tournament 模式的服务器,你打这样一个命令: quake3.exe +set dedicated 2 +set sv_zone tournaments +set g_gametype 1 +map q3tourney2
    g_gravity "800" 设置重力
    g_inactivity "0" 设置一个玩家长时间在服务器上没有行动直到被服务器踢掉的时间间隔
    g_knockback "1000" 武器的反作用力,数字越大,反作用力越大
    g_log "1" 是否记录游戏的数据和状态
    g_logSync "0" 可能是同步记录游戏的log和控制台log
    g_maxGameClients "0" 设置服务器可以接纳的最多连接人数
    g_motd "" 设置当日短信息(详见 "cl_motd" 命令)
    g_needpass "0" 设置连入你的服务器是否需要密码
    g_password "" 设置服务器连入密码
    g_podiumDist "80" 在比赛结束后排名次时设置领奖台上Model之间距离
    g_podiumDrop "70" 在比赛结束后排名次时设置领奖台上Model的高度
    g_quadfactor "3" 允许管理员设置加倍伤害宝物的伤害倍数
    g_restarted "0" 可能是是否显示游戏重新启动的一个标志
    g_singlePlayer "0" 可能是允许第三方加入原本是单人的游戏?
    g_spAwards "" 是否在单人游戏中显示得奖的标志
    g_speed "320" Q3Test中设置移动速度的参数
    g_spScores1 "" 为你在单人游戏的第一难度级别打分
    g_spScores2 "" 为你在单人游戏的第二难度级别打分
    g_spScores3 "" 为你在单人游戏的第三难度级别打分
    g_spScores4 "" 为你在单人游戏的第四难度级别打分
    g_spScores5 "" 为你在单人游戏的第五难度级别打分
    g_spSkill "2" 显示你当前所在的难度级别
    g_spVideos "" 显示过关电影片段的名称
    g_syncronousClients "0" 同步记录所有客户端的移动(1是用于录制demo)
    g_teamAutoJoin "0" 自动加入人数少或者落后的一方
    g_teamForceBalance "0" 是否强制队伍双方人数相等
    g_teamForceBalance "0" 是否强制队伍双方人数相等
    g_warmup "" 是否在单挑模式中显示时间告警
    g_weaponrespawn "5" 设置武器重生时间
    gamedate ""
    gamename "baseq3" 设置游戏目录
    GL_EXT_cull_vertex GL_EXT_packed_pixels GL_EXT_point_parameters
    GL_EXT_texture_object GL_EXT_vertex_array GL_WIN_swap_hint
    gl_extensions "GL_EXT_abgr GL_EXT_bgra GL_EXT_compiled_vertex_array
    GL_KTX_buffer_region "
    gl_pixelformat "" 设置每一像素上的色数,是8bit.16it还是32bit
    gl_renderer "" 设置显示卡GL驱动信息,比如:"RIVA 128/RIVA 128 ZX (PCI)"
    gl_vendor "" 设置显示卡制造商,比如 "NVIDIA Corporation"
    gl_version "" v设置显示卡驱动程序版本,比如:"1.1.0"
    graphheight "32" 是用于设置像素的高?用于图形显示
    graphscale "1" 设置图形显示的增加范围
    graphshift "0" 设置图形显示偏移量
    gun_frame "0" 关闭武器的动画,在武器动画序列中连续显示
    gun_x "0" 设置枪的模型的X坐标位置
    gun_y "0" 设置枪的模型的Y坐标位置
    gun_z "0" 设置枪的模型的Z坐标位置
    handicap "100" 设置最大生命指 参数范围0 - 100
    host_speeds "0" 显示时间信息 sv=服务器 cl=客户端 gm=游戏时间 rf=加时 all=全部时间
    in_debugjoystick "0" 可能是设置操纵杆的Debug工具
    in_joyBallScale "0.02" 设置玩家model的旋转刻度表?
    in_joyBall "0" 可能支持轨迹球之类的操纵杆
    in_joystick "0" 初始化操纵杆
    in_logitechbug "0" 打开游戏中追踪logitech鼠标程序错误地址的功能
    in_midi "0" 使用一个midi端口作为输入设备tr-d-x
    in_midichannel "1" 使用一个midi通道作为输入设备tr-d-x
    in_mididevice "0" 使用一个midi设备作为输入设备tr-d-x
    in_midiport "1" 使用一个midi端口作为输入设备tr-d-x
    in_mouse "1" 初始化一个鼠标作为输入设备
    journal "0" 记录在一个demo录制过程中的所有操作事件
    joy_advanced "0" 游戏控制键位映射
    joy_advaxisr "0" 绑定一个动作到操纵杆的 r 轴
    joy_advaxisu "0" 绑定一个动作到操纵杆的 u 轴
    joy_advaxisv "0" 绑定一个动作到操纵杆的 v 轴
    joy_advaxisx "0" 绑定一个动作到操纵杆的 x 轴
    joy_advaxisy "0" 绑定一个动作到操纵杆的 y 轴
    joy_advaxisz "0" 绑定一个动作到操纵杆的 z 轴
    joy_forwardsensitivity "-1" 设置操纵杆前进后退的灵敏度(负数为相反)
    joy_forwardthreshold "0.15" 设置操纵杆前进后退的极限点
    joy_name "joystick" 设置操纵杆的名字
    joy_pitchsensitivity "1" 设置操纵杆倾斜的灵敏度(负数为相反)
    joy_pitchthreshold "0.15" 设置操纵杆倾斜的极限点
    joy_sidesensitivity "-1" 设置操纵杆左右移动的灵敏度(负数为相反)
    joy_sidethreshold "0.15" 设置操纵杆左右移动的极限点
    joy_threshold "0.15"
    joy_upsensitivity "-1" 设置操纵杆上下的灵敏度(负数为相反)
    joy_upthreshold "0.15" 设置操纵杆上下的极限点
    joy_yawsensitivity "-1" 设置操纵杆偏转的灵敏度(负数为相反)
    joy_yawthreshold "0.15" 设置操纵杆偏转的极限点
    logfile "0" 运行进行操作的记录 0=不记录 1=磁盘缓存 2=继续 3=在原有的log文件上继续记录
    m_filter "1" 开启鼠标使用的平滑设置
    m_forward "0.25" 设置鼠标移动的幅度与游戏中前后移动距离的比例
    m_pitch "0.022" 设置鼠标移动的幅度与游戏中上下移动距离的比例
    m_side "0.25" 设置鼠标移动的幅度与游戏强力移动距离的比例
    m_yaw "0.022" 设置鼠标移动的幅度于游戏中左右转动的速度的比例
    mapname "" 显示当前使用地图的名字
    memorydump "0" 可能是用来debug当前内存分配的
    maxfps "0" 设置每秒最大帧数
    model "visor/blue" 设置你使用哪个model和颜色
    name "Commander Keen" 设置你自己的名字
    net_ip "localhost" 设置本地机器的ip或者是机器的名字
    net_noipx "0" 是否使用IPX/SPX 网络协议
    net_noudp "0" 是否使用TCP/IP 网络协议
    net_port "27960" 如果你想在一台机器上开几个服务器,你就必须设置不同的端口
    net_qport "16392" 设置内部网络端口,这样可以使处于网关后面使用同一个IP的几个玩家同时连上服务器
    net_socksEnabled "0" 允许通过防火墙的sock5端口连接服务器
    net_socksPassword "" 如果sock5端口需要密码验证,在这里设置
    net_socksPort "1080" 设置防火墙的端口
    net_socksServer "" 设置防火墙的IP地址
    net_socksUsername "" 如果sock5端口需要用户名验证,在这里设置
    nextmap "" 在载入下一张地图之前执行一个命令
    nohealth "0" 决定在下一张地图是否有补血物品
    password "" 置登陆服务器的密码(需要输入密码才能进入的服务器)
    port "27960" 如果你想在一台机器上开几个服务器,你就必须设置不同的端口
    paused "0" 在单人游戏中是否允许暂停
    pmove_fixed "0" 允许客户端使用客户端取样.但必须是服务器支持
    protocol "36" 设置网络协议版本
    qport "59337" 设置内部网络端口,这样可以使处于网关后面使用同一个IP的几个玩家同时连上服务器
    r_allowExtensions "1" 是否使用你的显示卡的OpenGL扩展功能
    r_allowSoftwareGL "0" 是否使用系统默认的软加速
    r_ambientScale "0.5" 设置亮度,主光源亮度比例
    r_clear "0" 是否在帧与争之间清除屏幕
    r_colorbits "16" 设置颜色的bit数8, 16, 还是32 bit?
    r_colorMipLevels "0" 材质细节工具
    r_customaspect "1.33334" 定制的屏幕宽高比,常见的为 4/3和16/9
    r_customheight "768" 定制分辨率的高
    r_customwidth "1024" 定制分辨率的宽
    r_debuglight "0" 可能是开启光线的debug工具
    r_debugSort "0
    r_debugSurface "0" 可能是用于曲面贴图的debug工具,多用于地图调试
    r_debugSurfaceUpdate "1" 可能是用于曲面贴图的debug工具,多用于地图调试
    r_depthbits "16" 设置z-buffer 8, 16, 或者32 bit
    r_detailtextures "1" 是否开启材质的细节
    r_directedScale "1" 可能是另一个调试直接光源的亮度和范围的参数,直射光
    r_displayRefresh "0" 设置显示器的刷新率,桌面设置也会随之改变
    r_dlightBacks "1" "brighter areas are changed more by dlights than dark areas. I don't feel TOO bad about that, because its not like the dlight is much of a proper lighting simulation even in the best case..."John Carmack
    r_drawBuffer "GL_BACK" 设置哪一帧的缓存绘入
    r_drawentities "1" 是否完整绘出实体
    r_drawstrips "1" 设置三角形填充方法
    r_drawSun "1" 如果不想把阳光加入光源,设置为0
    r_drawworld "1" 开启地图构建描绘
    r_dynamiclight "0" 开启动态光影效果
    r_ext_compiled_vertex_array "1" 开启硬件三角形排列顶角填充方法
    r_ext_compressed_textures "1" 开启材质压缩 (1.27版 changed to past tense compressed)
    r_ext_gamma_control "1" 开启外部伽玛设置
    r_ext_multitexture "1" 开启硬件多重材质
    r_ext_swapinterval "1" 开启硬件帧交换
    r_ext_texenv_add "1" 可能是个扩展参数.toggle additive blending in multitexturing. If not present, OpenGL limits you to multiplicative blending only, so additive will require an extra pass.
    切换是否使用additive多纹理混合,如果没有设置,OpenGL 限制你只能使用multiplicative  混合,所以additive混合需要附加的 pass

    r_ext_texture_env_add "1" 开启附加混合多重材质
    r_facePlaneCull "1" toggle culling of brush faces not in view (0 will slow FPS) .是否裁切不在摄像机内的平面
    r_fastsky "1" 开启天空快速贴图,设置为o会降低FPS
    r_finish "1" 是否开启同步帧填充 toggle synchronization of rendered frames (engine will wait for GL calls to finish)
    r_fixtjunctions "1" toggle开启model三角形顶点组合问题修正功能,这个问题会导致多边形之间出现缝隙
    r_flareFade "7" 设置闪光的暗淡下来的时间长度
    r_flares "0" 开启发射闪光和光线效果,会产生半透明和光环效果
    r_flaresSize "40" 设置闪光的大小
    r_fullbright "0" 开启材质最高的亮度级别
    r_fullscreen "1" 开启全屏模式
    r_gamma "1" 伽玛修正
    r_glDriver "opengl32" 设置OpenGL驱动(标准的 OpenGL32 或者 3dfxvgl)
    r_ignore "0" 可能是取消硬件驱动,代之以自己喜欢的参数设置
    r_ignoreFastPath "0" 是否忽略渲染捷径.
    r_ignoreGLErrors "1" 禁止OpenGL出现错误
    r_ignorehwgamma "0" 可能是开启DirectX伽玛纠错或者是显示驱动伽玛纠错
    r_ignoreOffset "0" 完全取消偏移量
    r_intensity "1" 增加材质颜色亮度
    r_lastValidRenderer "" 给出显示卡信息(比如:RIVA 128/RIVA 128 ZX (PCI))
    r_lightmap "0" 地图全亮,不再根据光源控制亮暗(古墓丽影1代和2代的照明效果差别就是如此)
    r_lightningSegmentLength "32" 可能是设置闪电枪发出的闪电的宽度
    r_lockpvs "0" 在游戏者穿过地图后禁止升级PVS表
    r_lockview "0"
    r_lodbias "0" 设置几何体显示细节级别 (0 - 2)
    r_lodCurveError "250" 另一个显示细节级别设置参数
    r_lodscale "5" 设置显示细节级别调整范围
    r_logFile "0" 设置log文件名
    r_mapOverBrightBits "2" 设置材质光线反射强度级别
    r_maskMinidriver "0" 把当前的OpenGL32 驱动当做ICD, 即使实际上是MCD
    r_measureOverdraw "0" 用于软件填充,特别是同一像素多次填充
    r_mode "3" 设置显示分辨率,当 r_mode = -1 的时候, r_customwidth,r_customheightr,r_customaspect 才起作用
    { "Mode  0: 320x240"},
    { "Mode  1: 400x300"},
    { "Mode  2: 512x384"},
    { "Mode  3: 640x480"},
    { "Mode  4: 800x600"},
    { "Mode  5: 960x720"},
    { "Mode  6: 1024x768"},
    { "Mode  7: 1152x864"},
    { "Mode  8: 1280x1024"},
    { "Mode  9: 1600x1200"},
    { "Mode 10: 2048x1536"},
    { "Mode 11: 856x480 (wide)"}

    r_nobind "0" 开启三角形绑定材质
    r_nocull "0" 开启隐藏物体的填充 (1=暂缓执行)
    r_nocurves "0" 开启曲线几何 ( 因为可能用于作弊,所以关闭为好 )
    r_nolightcalc "0" 关闭光阴计算
    r_noportals "0" 通过玩家的视角开启入口
    r_norefresh "0" 是否开启填充刷新显示
    r_novis "0" 切换是否使用bsp树vis表进行裁切,设为1不使用,将会慢很多cheat 命令
    r_offsetfactor "-1" 控制OpenGL多边形偏移量,如果你看见有贴图错误,这个参数可以帮助修正
    r_offsetunits "-2" 功能见上 r_offsetfactor
    r_overBrightBits "1" 可能类似于 r_mapOverBrightBits 参数
    r_picmip "0" 设置最大材质的大小 (数字越小画质越好,数字越大速度越快,但不是绝对的,好像影响不大) 范围0 - 16.
    r_portalOnly "0" 设置 "1" 关闭入口缓冲模板
    r_preloadTextures "0" 开启显示芯片处理以前缓存的材质功能
    r_primitives "0" r_primitives 3 通道无顶点序列测试
    r_printShaders "0" 开启打印正在使用的shader名称
    r_railCoreWidth "16" 设置RG轨迹中心宽度
    r_railSegmentLength "64" 设置RG的脉冲长度
    r_railWidth "128" 设置RG轨迹宽度
    r_roundImagesDown "1" set rounding down amount (larger = faster, lower quality) - Randy
      When textures need to be resized they are rounded up or down based on the value of the r_roundImagesDown cvar setting.
      A setting of  1 or 2 results in less detailed textures as they are being rounded down when they need to be resized, this means less chance of speed problems and running out of local texture memory on the card. A setting of 0 means more detailed textures as they are rounded up when they need to be resized but can result in texture thrashing and slowdowns. Bad drivers or AGP texturing problems can cause the machine to lockup when local texture memory is full.
      Note that round_down is not the same as picmip. Picmip is texture mipmap size of the original texture, round_down determines how that texture is resized.
    r_showcluster "0" toggle the display of clusters by number as the player enters them on the currently loaded map。当前地图玩家进入一个簇(切割出来的小房间)时是否显示其号码,调试 bsp 树用。cheat 命令
    r_showImages "0" 显示所有图象文件的拼图,材质调试工具
    r_shownormals "0" 绘出短线和完整的多边形顶点;在调试Model的光线时很有用.绘制法线
    r_showsky "0" 在其它物体之前填充天空
    r_showSmp "0" 在HUD上显示多处理器信息
    r_showtris "0" 显示三角形
    r_simpleMipMaps "1" 开启简单指令映射,用于比较慢的机器
    r_singleShader "0" 可能是用一个阴影来代替物体上的多个阴影
    r_skipBackEnd "0" 可能是用来跳过后端视频,不再画后表面,用于调试,使客户端不显示任何图形
    r_smp "0" 起用多处理器加速代码
    r_speeds "0" 显示填充信息.
    r_stencilbits "8" 模板缓冲大小 (0, 8bit, 和16bit)
    r_stereo "0" 用于3D眼镜?
    r_subdivisions "4" 设置最大细节级别,1为最大
    r_swapInterval "0" 开启帧交换  是否开启垂直同步功能。如果开启,游戏最大刷新率和桌面的刷新率相同
    水平同步信号,显示设备(显示器)接收到这个信号后,就开始画下一行。
    垂直同步信号,显示设备(显示器)接收到这个信号后,就开始画下一帧。

    关闭能够提示游戏FPS
    r_texturebits "0" 设置材质色数,set number of bits used for each texture from 0 to 32 bit
    r_textureMode "GL_LINEAR_MIPMAP_NEAREST" 选择材质模式
    r_verbose "0" 在控制台上显示填充命令
    r_vertexLight "1" 开启顶点光源(比lightmap快但是细节效果差) (建议dynamiclight 设置1这个参数设置为1)
    r_znear "4" 设置物体和玩家最贴近的距离
    rate "" 设置传输速率, 简单的说,是用于控制客户端每秒种最多能收到多少字节来自服务器端的数据。大部分服务器设置为sv_maxrate 10000或25000,即只允许最高25000的传输速率,对应客户端的rate 25000,这个值也是你在q3菜单选择LAN/Xdsl时的值。另外:我们在LAN建server的时候,服务器端有一个参数,可以强迫所有客户端使用最大的rate值,即sv_lanForceRate 1。
    rcon_password "" 已经取消
    rconAddress "" 为rcon命令保存服务器的IP地址的变量
    rconPassword "" 设置远程控制服务器的密码
    s_2dvolume "0.7" 设置声音级别 --2D
    s_bloat "2.0"
    s_compression "1" 开启声音压缩
    s_distance "100.0"
    s_doppler "1.0"
    s_fogeq "0.8"
    s_geometry "1"
    s_initsound "1" 决定是否初始化下一场游戏的声音
    s_khz "11" 设置声音频率取样,单位HZ
    s_leafnum "0"
    s_loadas8bit "1" 以8bit模式载入声音
    s_max_distance "1000.0" 可能是设置在地图中可以听到声音的最大距离范围
    s_min_distance "3.0" 可能是设置在地图中可以听到声音的最小距离范围
    s_mixahead "0.2" 设置混合声音前的延迟
    s_mixPreStep "0.05" 设置声音的逼真程度如果你的声卡够棒的话!
    s_musicvolume "1" 设置音乐的音量
    s_numpolys "400"
    s_occ_eq "0.75"
    s_occfactor "0.5"
    s_occlude "0"
    s_polykeep "1000000000"
    s_polyreflectsize "10000000"
    s_polysize "10000000"
    s_refdelay "2.0"
    s_refgain "0.45"
    s_reflect "1"
    s_rolloff "1.0"
    s_separation "0.5" 设置左右声道分离的距离
    s_show "0" 显示所有在播放的声音文件的路径
    s_testsound "0" 开启一个音质测试来测试声音系统
    s_usingA3D "0" 开启A3D支持
    s_volume "0.7" 设置声音FX的音量
    s_watereq "0.2"
    scr_conspeed "3" 设置控制台下拉、上去的速度
    sensitivity "9" 设置鼠标灵敏度(非常重要!)
    server1 "" 保存你最喜爱的服务器的地址
    server2 "" 保存你最喜爱的服务器的地址
    server3 "" 保存你最喜爱的服务器的地址
    server4 "" 保存你最喜爱的服务器的地址
    server5 "" 保存你最喜爱的服务器的地址
    server6 "" 保存你最喜爱的服务器的地址
    server7 "" 保存你最喜爱的服务器的地址
    server8 "" 保存你最喜爱的服务器的地址
    server9 "" 保存你最喜爱的服务器的地址
    server10 "" 保存你最喜爱的服务器的地址
    server11 "" 保存你最喜爱的服务器的地址
    server12 "" 保存你最喜爱的服务器的地址
    server13 "" 保存你最喜爱的服务器的地址
    server14 "" 保存你最喜爱的服务器的地址
    server15 "" 保存你最喜爱的服务器的地址
    server16 "" 保存你最喜爱的服务器的地址
    session "2" 可能是当在一台机器上上运行多个服务时要保存一个当前值
    session0 ""0 300 1 0 0 0" 可能是为了要在一台机器上上运行多个服务而设置多个地址和socket
    session1 "0 300 1 0 0 0" 可能是为了要在一台机器上上运行多个服务而设置多个地址和socket
    session2 "0 300 1 0 0 0" 可能是为了要在一台机器上上运行多个服务而设置多个地址和socket
    session3 "0 300 1 0 0 0" 可能是为了要在一台机器上上运行多个服务而设置多个地址和socket
    session4 "0 300 1 0 0 0" 可能是为了要在一台机器上上运行多个服务而设置多个地址和socket
    sex "male" 设置角色性别
    showdrop "0" 显示丢失的数据包 . 0=disables,1=enable.
    showpackets "0" 显示所有发送和接受的数据包 0=disables,1=enable.
    showtrace "0" 显示数据包的踪迹 0=disables,1=enable.
    snaps "20"  服务器将向客户端发送的快照的数目(server run at 40Hz, so use 40, 20, or 10)
    snd "visor" 选择使用哪个model的专有声音
    sv_allowdownload "1" 允许客户端从服务器下载文件比如地图等,服务器参数
    sv_cheats "1" 允许使用作弊命令 (give all) (服务器端使用)
    sv_floodProtect "1" 开启服务器的溢出保护
    sv_fps "20" 设置服务器每秒向客户端发送帧的最大值
    sv_hostname "" 设置服务器的名字
    sv_keywords "" 在网络连接菜单里输入的搜索字符串
    sv_killserver "0" 输入后服务器关闭
    sv_lanForceRate "1" 迫使LAN里面的客户机使用最大rate值
    sv_mapChecksum "" 开启地图检查功能,确认客户端和服务器的地图相同
    sv_mapname "" 显示服务器当前使用地图名称
    sv_master1 "" 设置ID的主服务器的地址 "master3.idsoftware.com"
    sv_master2 "" 主服务器地址 2
    sv_master3 "" 主服务器地址 3
    sv_master4 "" 主服务器地址 4
    sv_master5 "" 主服务器地址 5
    sv_maxclients "8" 设置服务器以允许连入最多人数
    sv_maxPing "0" 设置服务器允许的最大ping值
    sv_maxRate "" 这个命令用来强迫所有的客户端具有相同的连接速度。这样可以限制一些ping特别低的人的优势,还可以有效配置服务器的带宽。对于lan同样有效
    sv_minPing "0" 设置服务器允许的最小ping值
    sv_nopredict "0" 大概是使服务器具有对客户端位置的预处理能里
    sv_pad "0"
    sv_padPackets "0"
    sv_paks "182784856 "
    sv_paused "0" 允许服务器端暂停游戏
    sv_privateClients "0" 设置特别客户端人数(在一个比较热闹的服务器上很有用,保证有空位给你玩)
    sv_privatePassword "" 设置特别客户端密码
    sv_punkbuster "0" 允许建立服务器的时候打开防作弊功能
    sv_pure "1" 禁止本地DLL载入,客户端只能根据服务器端使用的数据而从PAK文件中读取qvm数据
    sv_reconnectlimit "3" 允许断线的客户端重新连接的时间长度
    sv_running "1" 这个参数告诉控制台是否一个本地服务器运行着
    sv_serverid "" hmm?配额;8021204"
    sv_showloss "0" 开启服务器数据包丢失显示
    sv_strictAuth "1" 服务器端用于验证CDKEY的认证,这个命令使得服务器可以得到合法cl_guid值的客户端
    sv_timeout "120" 设置服务器 在确认客户端断开之前等待的时间
    sv_zombietime "2" 设置服务器在移除一个没有反应的客户端之前等待的时间
    sv_zone "default" 设置客户端可能搜索的关键字,管理者最好是设置运行的服务器类型FFAl,
    tournament, T-DM或者其他
    sys_cpuid "33"
    sys_cpustring "" 设置一个字符串来识别你的CPU,如 "x86 (P5/PPro, non-MMX)"
    teamoverlay "0" 开启在HUD上显示队伍的颜色
    teamflags "0" 设置团队比赛的标志
    timedemo "0" 在播放 demo 时是否快速播放
    timegraph "0" 开启显示时间图
    timelimit "0" 设置每个地图的运行时间
    timescale "1" 设置游戏时间和真实时间之间的比率
    ui_browserGameType "0" 设置在浏览列表中搜索服务器类型
    ui_browserMaster "0" 设置服务器搜索类型 0=LAN 1=Mplayer 2=Internet 3=Favorites
    ui_browserShowEmpty "1" 把没有人的服务器也列出来
    ui_browserShowFull "1" 把满人的服务器列出来
    ui_browserSortKey "4" 设置服务器列表的排列依据 0=服务器名字 1=地图名字 2=连接人数 3=游戏类型 4=ping 的时间
    ui_cdkeychecked "1" 可能是在cdkey验证后设置一个标志
    ui_ctf_capturelimit "8" 可能是在单人与BOT的CTF游戏中设置夺旗限制
    ui_ctf_friendly "0" 可能是在单人与BOT的CTF游戏中开启队友伤害
    ui_ctf_timelimit "30" 可能是在单人与BOT的CTF游戏中设置时间限制
    ui_ffa_fraglimit "20" 可能是在单人与BOT的FFA游戏中设置得分限制
    ui_ffa_timelimit "0" 可能是在单人与BOT的FFA游戏中设置时间限制
    ui_master "0" 设置服务器搜索 0=LAN 1=Mplayer 2=Internet 3=Favorites
    ui_spSelection "2" 可能是在单人游戏中设置游戏类型? 16 = CTF 2 = FFA DM
    ui_team_fraglimit "0" 可能是在单人与BOT的Team游戏中设置得分限制
    ui_team_friendly "1" 可能是在单人与BOT的Team游戏中开启队友伤害
    ui_team_timelimit "20" 可能是在单人与BOT的Team游戏中设置时间限制
    ui_tourney_fraglimit "0" 可能是在单人与BOT的Team游戏设置得分限制
    ui_tourney_timelimit "15" 可能是在单人与BOT的Tourney游戏中设置时间限制
    username "vern" 设置你的连接代号 %username% 环境参数?
    version "" 设置版本
    versionNumber "" 设置版本号
    vid_xpos "30" 当使用窗口模式时的X轴位置
    vid_ypos "30" 当使用窗口模式时的Y轴位置
    viewlog "0" 在启动时显示控制台窗口
    viewsize "100" 改变显示窗口尺寸(最好别小于100)
    vm_cgame "0" 虚拟机解释器部份参数
    vm_game "0" 开启虚拟机解释器,这个参数可以在载入DLL库和qvm解释文件之间切换
    vm_ui "0" 虚拟机解释器部份参数,0 表示加载 dll 链接库。2 表示加载 qvm 虚拟码
    win_hinstance "" 在Window下Q3的实例句柄
    win_wndproc ""  Q3 的消息处理函数
    zoomfov "22.5" 阻击模式视角宽度,不要大于30
    Red Font 红色字体
    Green Font 绿色字
    cl_conXOffset  offset the console message display 0 - top left 999 - extreme top right (off the page)
    r_inGameVideo  "1" toggle the display of in game animations on bigscreen map objects that display a camera view of the current game
    cl_serverStatusResendTime 

    g_redTeam "" set the team icon for the red team (example Stroggs)
    g_blueTeam   set the team icon for the red team (example Pagans)
    r_uiFullScreen "0"  设置UI
    cg_shadows  set shadow detail level (0 = OFF, 1 = basic discs, 2 = stencil buffered 3 = simple stencil buffered(if r_stencilebits is not=0)) - Andre Lucas

    September 24

    终于可以显示图像了

    quake3menu

    几个月用零零碎碎地时间,从不了解OpenGL 到逐步能显示菜单,发个图片纪念一下。

    August 22

    tga图像文件格式读取

    根据david mcduffe编写的TGA文件格式资料翻译而成 
    
    本文档是为满足许多对 TGA 图像格式的了解需要而创建的。本文摘录自truevision 
    技术指南的附录 C,如果
    需要更进一步的信息,请致信以下地址:
               at&t
               electronic photography and imaging center
               2002 wellesley ave.
               indianapolis, in 42619
    本文档不求全面,但力求准确。如果你发现了任何拼写错误或内容错误,请告诉我,(
     david mcduffe, 
    75530,2626 ),我将改正这些错误,谢谢。
    
    不全面的原因是 TGA 包含了超过六种图像文件格式,而其中的几种较为常用。 
    我选择了我现在使用的格式并在本文中加以详解。 如果你需要本文中没有包含的格式说明,你可以与你的 
    truevision 代理商联系。
    对所有的 TGA 格式的文件而言,其第三字节(二进制整数)用来区别各种不同的 
    TGA 文件。下面列出了该字节表明的对应文件类型:
        0  -  文件中没有图像数据
        1  -  未压缩的,颜色表图像
        2  -  未压缩的,rgb 图像
        3  -  未压缩的,黑白图像
        9  -  runlength 编码的颜色表图像
        10 -  runlength 编码的 rgb 图像
        11 -  压缩的,黑白图像
        32 -  使用 huffman,delta 和 runlength 编码的颜色表图像
        33 -  使用 huffman,delta 和 runlength 编码的颜色映射图像,4 
    趟四叉树类型处理。
        本文仅仅描述对应 1,2,9 和 10 的文件格式。 代码里则处理了2,3 10的情况
    ----------------------------------------------------------------------------
    |数据类型 1: 颜色表(color-mapped)图像
    |--------|--------|---------------------------------------------------------
    |  偏移   |  长度   |                            描述
    |--------|--------|---------------------------------------------------------
    |    0   |     1  |  图像信息字段(见本子表的后面)的字符数                                                      
    |        |        |  本字段是1字节无符号整型,指出了图像格式区别字段长度     
    |        |        |  其取值范围是 0 到 255 ,当它为 0 时表示没有图像的     
    |        |        |  信息字段。                                
    |--------|--------|---------------------------------------------------------
    |    1   |     1  |  颜色表的类型                                          
    |        |        |  该字段为表示对应格式 1 的图像而包含一个二进制1
    |--------|--------|---------------------------------------------------------
    |    2   |     1  |  图像类型码                                            
    |        |        |  该字段总为 1 , 这也是此类型为格式1的原因               
    |--------|--------|---------------------------------------------------------
    |    3   |     5  |  颜色表规格                                    
    |        |        |                                            
    |    3   |     2  |  颜色标首址
    |        |        |  颜色表首元表项的整型(低位-高位)索引           
    |    5   |     2  |  颜色表的长度                                          
    |        |        |  颜色表的表项总数,整型(低位-高位)   
    |    7   |     1  |  颜色表表项的位(bit)数
    |        |        |  16代表16位TGA ,24代表24位TGA 32代表32位TGA      
    |--------|--------|---------------------------------------------------------
    |    8   |    10  |  图像规格                                              
    |        |        |
    |    8   |     2  |  图像 x 坐标起始位置              
    |        |        |  图像左下角 x 坐标的整型(低位-高位)值            
    |        |        |         
    |   10   |     2  |  图像 y 坐标起始位置      
    |        |        |  图像左下角 y 坐标的整型(低位-高位)值     
    |   12   |     2  |  图像宽度                                 
    |        |        |  以像素为单位,图像宽度的整型(低位-高位)值     
    |   14   |     2  |  图像高度                                  
    |        |        |  以像素为单位,图像高度的整型(低位-高位)值
    |   16   |     1  |  图像每像素存储占用位(bit)数
    |        |        |
    |   17   |     1  |  图像描述符字节                                        
    |        |        |  bits 3-0 - 每像素的属性位(bit)数                
    |        |        |                                                        
    |        |        |  bit 4    - 保留,必须为 0                             
    |        |        |  bit 5    - 屏幕起始位置标志                           
    |        |        |             0 = 原点在左下角                       
    |        |        |             1 = 原点在左上角                       
    |        |        |             truevision 图像必须为 0
    |        |        |  bits 7-6 - 交叉数据存储标志                       
    |        |        |             00 = 无交叉                                
    |        |        |             01 = 两路奇/偶交叉                     
    |        |        |             10 = 四路交叉                              
    |        |        |             11 = 保留                                  
    |        |        |  这一项应该设为 0,不要问我为什么                  
    |--------|--------|---------------------------------------------------------
    |   18   |  可变  |  图像信息字段                                      
    |        |        |  包含一个自由格式的,长度是图像记录块偏移0处的字节中的
    |        |        |  值。它常常被忽略(即偏移 0 处值为 0),注意其最大可以
    |        |        |  含有 255个字符。如果需要存储更多信息,可以放在图像数据
    |        |        |  之后                                                                   
    |--------|--------|---------------------------------------------------------
    |  可变   |  可变   |  颜色表数据    
    |        |        |  起始位置由前一个字段的大小决定;其长度由单项数据大小
    |        |        |  和数据项数目决定(在前面相应的说明字段中给出)
    |        |        |  每项是 2 字节,3 字节或 4字节,字节中没有使用的位(bit)
    |        |        |  被认为是属性位。      
    |        |        |  4 字节表项中,字节 1 表示 BLUE,字节 2 表示 GREEN,
    |        |        |             字节 3 表示 RED,字节 4 表示属性           
    |        |        |  3 字节表项中各字节依次对应 BLUE,GREEN,RED
    |        |        |  2 字节表项中,两个字节分解成如下形式:            
    |        |        |  arrrrrgg gggbbbbb                         
    |        |        | 但是,由于低位在前,高位在后的存储顺序,从文件中读出表项
    |        |        |  时,将先读入 gggbbbbb 而后读入 arrrrrgg ;a 表示属性位
    |--------|--------|---------------------------------------------------------
    |  可变   |  可变   |  图像数据字段                       
    |        |        |  该字段给出了 (高度)x(宽度)个颜色表项索引,每个索引
    |        |        |  以整数个字节的形式存储(典型的例子如 1 或 2 个字节
    |        |        |  所有的数据都没有符号,对于2-字节表项而言,低位字节是
    |        |        |  先存储的。                                                                                  
    ----------------------------------------------------------------------------
    
    ----------------------------------------------------------------------------
    |数据类型 2: 无颜色表 rgb 图像                               
    |--------|--------|---------------------------------------------------------
    |   偏移  |   长度  |       描述                              
    |--------|--------|---------------------------------------------------------
    |    0   |     1  |  图像信息字段( 见本子表的后面 )的字符数                                    
    |        |        |  本字段是 1 字节无符号整型,指出了图像格式区别字段长度
    |        |        |  其取值范围是 0 到 255 ,当它为 0 时表示没有图像的
    |        |        |  信息字段。
    |--------|--------|---------------------------------------------------------
    |    1   |     1  |  颜色表类型                                             
    |        |        |  该字段的内容或者为 0 或者为 1;0 表示没有颜色表,1表示
    |        |        |  颜色表存在。由于本格式是无颜色表的,因此此项通常被忽略
    |        |        |  提示:如果置为 1(targa绘画程序)将把边框颜色设置为映射
    |        |        |        中的第一种颜色
    |--------|--------|---------------------------------------------------------
    |    2   |     1  |  图像类型码
    |        |        |                                                     
    |        |        |  该字段总为 2 , 这也是此类型为格式 2 的原因    
    |--------|--------|---------------------------------------------------------
    |    3   |     5  |  颜色表规格
    |        |        |                              
    |        |        |  如果颜色表类型字段为 0 则被忽略;否则描述如下
    |        |        |  
    |    3   |     2  |  颜色表首址
    |        |        |  颜色表首元入口的整型(低位-高位)索引
    |        |        |                  
    |    5   |     2  |  颜色表的长度
    |        |        |  颜色表的表项总数,整型(低位-高位)     
    |        |        |                                   
    |    7   |     1  |  颜色表表项的位(bit)数
    |        |        |  16代表16位TGA ,24 代表 24 位 TGA ,32 代表 32 位 TGA
    |        |        |                                              
    |--------|--------|---------------------------------------------------------
    |    8   |    10  |  图像规格
    |        |        |                             
    |    8   |     2  |  图像 x 坐标起始位置       
    |        |        |  图像左下角 x 坐标的整型(低位-高位)值
    |   10   |     2  |  图像 y 坐标起始位置
    |        |        |  图像左下角 y 坐标的整型(低位-高位)值
    |   12   |     2  |  图像宽度 
    |        |        |  以像素为单位,图像宽度的整型(低位-高位)值
    |   14   |     2  |  图像高度
    |        |        |  以像素为单位,图像高度的整型(低位-高位)值
    |   16   |     1  |  图像每像素存储占用位(bit)数
    |        |        |  它的值为16,24 或 32 等等决定了该图像是 TGA 16,TGA24
    |        |        |  TGA 32 等等
    |   17   |     1  |  图像描述符字节
    |        |        |  bits 3-0 - 每像素对应的属性位的位数;对于  TGA 16,
    |        |        |             该值为 0 或 1,对于 TGA 24,该值为 0,
    |        |        |             对于 TGA 32,该值为 8       
    |        |        |  bit 4    - 保留,必须为 0
    |        |        |  bit 5    - 屏幕起始位置标志
    |        |        |             0 = 原点在左下角
    |        |        |             1 = 原点在左上角
    |        |        |             对于 truevision 图像必须为 0
    |        |        |  bits 7-6 - 交叉数据存储标志
    |        |        |             00 = 无交叉                                
    |        |        |             01 = 两路奇/偶交叉                     
    |        |        |             10 = 四路交叉                              
    |        |        |             11 = 保留
    |--------|--------|---------------------------------------------------------
    |   18   | 可变    |  图像信息字段                                      
    |        |        |  包含一个自由格式的,长度是图像记录块偏移 0处的字节中的
    |        |        |  值。它常常被忽略(即偏移 0 处值为 0),注意其最大可以
    |        |        |  含有 255个字符。如果需要存储更多信息,可以放在图像数据
    |        |        |  之后                              
    |--------|--------|---------------------------------------------------------
    |  可变   |  可变   |  颜色表数据                                     
    |        |        |                                                
    |        |        |  如果颜色表类型为 0,则该域不存在,否则越过该域直接读取
    |        |        |  图像颜色表规格中描述了每项的字节数,为 2,3,4 之一
    |        |        |  
    |        |        |  
    |        |        |  
    |        |        |  
    |--------|--------|---------------------------------------------------------
    |  可变  |  可变    |  图像数据域                                               
    |        |        |  这里存储了(宽度)x(高度)个像素,每个像素中的 rgb色值
    |        |        |  该色值包含整数个字节                                  
    |        |        |  3 字节表项中各字节依次对应BLUE,GREEN,RED                                 
    |        |        |  2 字节表项中,两个字节分解成如下形式:            
    |        |        |  arrrrrgg gggbbbbb                         
    |        |        | 但是,由于低位在前,高位在后的存储顺序,从文件中读出表项
    |        |        |  时,将先读入 gggbbbbb 而后读入 arrrrrgg ;a 表示属性位                                    
    |        |        |  4 字节表项包含了分别代表 blue,green,red 及属性的四个
    |        |        |  字节;(由于硬件上的原因)有的时候 TGA 24类型的图像也象
    |        |        |  TGA 32 类型的图像那样存储                              
    ----------------------------------------------------------------------------
    
    ----------------------------------------------------------------------------
    |数据类型 9:  runlength 编码,带颜色表的图像
    |--------|--------|---------------------------------------------------------
    |  偏移  |  长度  |                            描述
    |--------|--------|---------------------------------------------------------
    |    0   |     1  |  图像信息字段(见本子表的后面)的字符数                                                  
    |        |        |  本字段是 1 字节无符号整型,指出了图像格式区别字段长度
    |        |        |  其取值范围是 0 到 255 ,当它为 0 时表示没有图像的     
    |        |        |  信息字段。                                         
    |--------|--------|---------------------------------------------------------
    |    1   |     1  |  颜色表的类型                                                                           
    |        |        |  该字段为表示对应带颜色表的图像而总为 1                                   
    |--------|--------|---------------------------------------------------------
    |    2   |     1  |  图像类型码                                    
    |        |        |  本类型该字段为二进制 9                                   
    |--------|--------|---------------------------------------------------------
    |    3   |     5  |  颜色表规格                                   
    |        |        |  如果颜色表类型字段为 0 则被忽略;否则描述如下
    |    3   |     2  |  颜色表首址
    |        |        |  颜色表首元入口的整型(低位-高位)索引    
    |    5   |     2  |  颜色表的长度
    |        |        |  颜色表的表项总数,整型(低位-高位)     
    |    7   |     1  |  颜色表表项的位(bit)数
    |        |        |  16 代表 16 位 TGA ,24 代表24位 TGA 32代表32 位TGA      
    |--------|--------|---------------------------------------------------------
    |    8   |    10  |  图像规格                                                                                 
    |    8   |     2  |  图像 x 坐标起始位置                                 
    |        |        |  图像左下角 x 坐标的整型(低位-高位)值            
    |   10   |     2  |  图像 y坐标起始位置                              
    |        |        |  图像左下角 y 坐标的整型(低位-高位)值                                             
    |   12   |     2  |  图像宽度                                        
    |        |        |  以像素为单位,图像宽度的整型(低位-高位)值                                           
    |   14   |     2  |  图像高度                                        
    |        |        |  以像素为单位,图像高度的整型(低位-高位)值                                    
    |   16   |     1  |  图像每像素存储占用位(bit)数                                  
    |   17   |     1  |  图像描述符字节                                        
    |        |        |  bits 3-0 - 每像素的属性位(bit)数                                                            
    |        |        |  bit 4    - 保留,必须为 0                             
    |        |        |  bit 5    - 屏幕起始位置标志                           
    |        |        |             0 = 原点在左下角                       
    |        |        |             1 = 原点在左上角                       
    |        |        |             truevision 图像必须为 0              
    |        |        |  bits 7-6 - 交叉数据存储标志                       
    |        |        |             00 = 无交叉                                
    |        |        |             01 = 两路奇/偶交叉                     
    |        |        |             10 = 四路交叉                              
    |        |        |             11 = 保留
    |--------|--------|---------------------------------------------------------
    |   18   | 可变   |  图像信息字段                                      
    |        |        |  包含一个自由格式的,长度是图像记录块偏移 0 处的字节中的
    |        |        |  值。它常常被忽略(即偏移 0 处值为 0 ),注意其最大可以
    |        |        |  含有 255 个字符。如果需要存储更多信息,可以放在图像数据
    |        |        |  之后
    |--------|--------|---------------------------------------------------------
    |  可变  |  可变  |  颜色表数据                                      
    |        |        |  起始位置由前一个字段的大小决定;其长度由单项数据大小
    |        |        |  和数据项数目决定(在前面相应的说明字段中给出)
    |        |        |  每项是 2 字节,3 字节或 4字节,字节中没有使用的位(bit)
    |        |        |  被认为是属性位。                          
    |        |        |  4 字节表项中,字节 1 表示 BLUE,字节 2 表示 GREEN,
    |        |        |             字节 3 表示 RED,字节 4 表示属性           
    |        |        |  3 字节表项中各字节依次对应BLUE,GREEN,RED   
    |        |        |  2 字节表项中,两个字节分解成如下形式:            
    |        |        |  arrrrrgg gggbbbbb                         
    |        |        |  但是,由于低位在前,高位在后的存储顺序,从文件中读出表项
    |        |        |  时,将先读入 gggbbbbb 而后读入 arrrrrgg ;a表示属性位
    |--------|--------|---------------------------------------------------------
    | 可变   |  可变  |  图像数据域                                
    |        |        |  本区域给出了(宽度)x(高度)个颜色表索引这些索引存放
    |        |        |  在数据包中;有两中类型的数据包:run-length 数据包,
    |        |        |  以及未加工的数据包,每种类型的数据包含有1-字节的头信息,
    |        |        |  (其中指出了数据包类型和数目),其后是可变长度的数据域
    |        |        |  头信息中最高位为 1 表示 run-length 类型的数据包,当
    |        |        |  它为 0 时,表示未加工的数据包                                    
    |        |        |  对于 run-length 数据包,头信息含义如下
    |        |        |      __________________________________________________
    |        |        |      | 1 bit |   7 位的重复记数减一                   |
    |        |        |      |   id  |   由于 7 位表示的最大值为 127,故最大  |
    |        |        |      |       |   的运行大小为 128,(译注:原文为     |
    |        |        |      |       |   the largest run size)               |
    |        |        |      |-------|----------------------------------------|
    |        |        |      |   1   |  c     c     c     c     c     c    c  |
    |        |        |      --------------------------------------------------                                          
    |        |        |  对于未加工数据包,头信息的含义如下
    |        |        |      __________________________________________________
    |        |        |      | 1 bit |   7 位的像素个数减一                   |
    |        |        |      |   id  |   由于 7 位表示的最大值为 127,故该    |
    |        |        |      |       |   类型的一个数据包中像素个数不能大于   |
    |        |        |      |       |   128                                  |
    |        |        |      |-------|----------------------------------------|
    |        |        |      |   0   |  n     n     n     n     n     n    n  |
    |        |        |      --------------------------------------------------                                          
    |        |        |  对于 run-length 数据包而言,头信息之后是一个简单的
    |        |        |  颜色索引,且假定该索引被重复头信息中低 7 位表示的次数
    |        |        |  run-length 数据包也许会跨越扫描线
    |        |        |  (扫描线起始于某行结束于下一行)
    |        |        |                                                        
    |        |        |  对于未加工的数据包,头信息之后是颜色索引(数值由头信息
    |        |        |  给出)该类型的数据包也可能跨越扫描线
    ----------------------------------------------------------------------------
    
    
    ----------------------------------------------------------------------------
    |数据类型 10:run length 编码,rgb 图像
    |--------|--------|---------------------------------------------------------
    |   偏移 |   长度 |  描述                              
    |--------|--------|---------------------------------------------------------
    |    0   |     1  |  图像信息字段(见本子表的后面)的字符数                                         
    |        |        |  本字段是 1 字节无符号整型,指出了图像格式区别字段长度 
    |        |        |  其取值范围是 0 到 255 ,当它为 0 时表示没有图像的     
    |        |        |  信息字段。 
    |--------|--------|---------------------------------------------------------
    |    1   |     1  |  该字段的内容或者为 0 或者为 1;0 表示没有颜色表,1表示
    |        |        |  颜色表存在。由于本格式是无颜色表的,因此此项通常被忽略
    |        |        |  提示:如果置为 1(targa绘画程序)将把边框颜色设置为映射
    |        |        |        中的第一种颜色                                
    |--------|--------|---------------------------------------------------------
    |    2   |     1  |  图像类型代码
    |        |        |  本类型该字段为二进制 10            
    |--------|--------|---------------------------------------------------------
    |    3   |     5  |  颜色表规格                                
    |        |        |  如果颜色表类型字段为 0 则被忽略;否则描述如下
    |    3   |     2  |  颜色表首址
    |        |        |  颜色表首元入口的整型(低位-高位)索引
    |    5   |     2  |  颜色表的长度
    |        |        |  颜色表的表项总数,整型(低位-高位)     
    |    7   |     1  |  颜色表表项的位(bit)数
    |        |        |  16代表16位 TGA ,24 代表 24 位 TGA ,32 代表 32 位TGA       
    |--------|--------|---------------------------------------------------------
    |    8   |    10  |  图像规格                                                                                         
    |    8   |     2  |  图像 x 坐标起始位置                                
    |        |        |  图像左下角 x 坐标的整型(低位-高位)值            
    |   10   |     2  |  图像 y 坐标起始位置                      
    |        |        |  图像左下角 y 坐标的整型(低位-高位)值            
    |   12   |     2  |  图像宽度                                        
    |        |        |  以像素为单位,图像宽度的整型(低位-高位)值                                                     
    |   14   |     2  |  图像高度                                            
    |        |        |  以像素为单位,图像高度的整型(低位-高位)值                                   
    |   16   |     1  |  图像每像素存储占用位(bit)数                                   
    |   17   |     1  |  图像描述符字节                                        
    |        |        |  bits 3-0 - 每像素的属性位(bit)数                                                 
    |        |        |  bit 4    - 保留,必须为 0                             
    |        |        |  bit 5    - 屏幕起始位置标志                           
    |        |        |             0 = 原点在左下角                       
    |        |        |             1 = 原点在左上角                       
    |        |        |             truevision 图像必须为 0                
    |        |        |  bits 7-6 - 交叉数据存储标志                       
    |        |        |             00 = 无交叉                                
    |        |        |             01 = 两路奇/偶交叉                     
    |        |        |             10 = 四路交叉                              
    |        |        |             11 = 保留                                                            
    |--------|--------|---------------------------------------------------------
    |   18   | 可变   |  图像信息字段                                      
    |        |        |  包含一个自由格式的,长度是图像记录块偏移 0 处的字节中的
    |        |        |  值。它常常被忽略(即偏移 0 处值为 0 ),注意其最大可以
    |        |        |  含有 255个字符。如果需要存储更多信息,可以放在图像数据
    |        |        |  之后                                        
    |--------|--------|---------------------------------------------------------
    |  可变  |  可变  |  颜色表数据                                                                    
    |        |        |  如果颜色表类型为 0,则该域不存在,否则越过该域直接读取
    |        |        |  图像颜色表规格中描述了每项的字节数,为 2,3,4 之一
    |--------|--------|---------------------------------------------------------
    | 可变   |  可变  |  图像数据域                         
    |        |        |  本区域给出了(宽度)x(高度)个颜色表索引这些索引存放
    |        |        |  在数据包中;有两中类型的数据包:run-length 数据包,
    |        |        |  以及未加工的数据包,每种类型的数据包含有1-字节的头信息,
    |        |        |  (其中指出了数据包类型和数目),其后是可变长度的数据域
    |        |        |  头信息中最高位为 1 表示 run-length 类型的数据包,当
    |        |        |  它为 0 时,表示未加工的数据包                             
    |        |        |  对于 run-length 数据包,头信息含义如下
    |        |        |      __________________________________________________
    |        |        |      | 1 bit |   7 位的重复记数减一                   |
    |        |        |      |   id  |   由于 7 位表示的最大值为 127,故最大  |
    |        |        |      |       |   的运行大小为 128,(译注:原文为     |
    |        |        |      |       |   the largest run size)               |  
    |        |        |      |-------|----------------------------------------|
    |        |        |      |   1   |  c     c     c     c     c     c    c  |
    |        |        |      --------------------------------------------------
    |        |        |                                                        
    |        |        |  对于未加工数据包,头信息的含义如下
    |        |        |      __________________________________________________
    |        |        |      | 1 bit |   7 位的像素个数减一                   |
    |        |        |      |   id  |   由于 7 位表示的最大值为 127,故该    |
    |        |        |      |       |   类型的一个数据包中像素个数不能大于   |
    |        |        |      |       |   128                                  |
    |        |        |      |-------|----------------------------------------|
    |        |        |      |   0   |  n     n     n     n     n     n    n  |
    |        |        |      --------------------------------------------------
    |        |        |
    |        |        |  对于 run length 数据包,头信息之后是一个简单颜色值,
    |        |        |  且假定该值重复的次数为头信息中记录的数
    |        |        |  run-length 数据包也许会跨越扫描线
    |        |        |  (扫描线起始于某行结束于下一行)                                      
    |        |        | 对于未加工数据包,头信息之后是颜色值(数目由头信息指出)                                 
    |        |        |  颜色表项自身有 2-字节,3-字节或 4-字节几种大小(分别
    |        |        |  对应 TGA 16,TGA 24 和 TGA 32)形式如下:
    |        |        |  3 字节表项中各字节依次对应BLUE,GREEN,RED           
    |        |        |  2 字节表项中,两个字节分解成如下形式:            
    |        |        |  arrrrrgg gggbbbbb                         
    |        |        |但是,由于低位在前,高位在后的存储顺序,从文件中读出表项  
    |        |        |  时,将先读入 gggbbbbb 而后读入 arrrrrgg ;a 表示属性位
    |        |        |
    |        |        |  4 字节表项包含了分别代表 blue,green,red 及属性的四个
    |        |        |  字节;(由于硬件上的原因)有的时候 TGA 24类型的图像也象
    |        |        |  TGA 32 类型的图像那样存储
    ----------------------------------------------------------------------------
    quake3 中读取 tga 图像代码:
    name 要加载的图片名称. 指向pic 返回的 tga 图片像素数据.width 返回图片宽度.height 返回图片高度
    ri.FS_ReadFile 读取文件,并返回文件内容指针
    ri.FS_FreeFile 释放文件内容缓存
    ri.Malloc 分配内存
    typedef struct _TargaHeader
    {
     unsigned char  id_length, colormap_type, image_type;
     unsigned short colormap_index, colormap_length;
     unsigned char colormap_size;
     unsigned short x_origin, y_origin, width, height;
     unsigned char pixel_size, attributes;
    } TargaHeader;

    static void LoadTGA ( const char *name, byte **pic, int *width, int *height)
    {
     int  columns, rows, numPixels;
     byte *pixbuf;
     int  row, column;
     byte *buf_p;
     byte *buffer;
     TargaHeader targa_header;
     byte  *targa_rgba;
     *pic = NULL;
     // load the file
     ri.FS_ReadFile ( ( char * ) name, (void **)&buffer);
     if (!buffer)
     {
      return;
     }
     buf_p = buffer;
     targa_header.id_length = *buf_p++;
     targa_header.colormap_type = *buf_p++;    //如果colormap_type为0从18位开始为图像数据
     targa_header.image_type = *buf_p++;         // 第三个字节为文件类型
     targa_header.colormap_index = LittleShort ( *(short *)buf_p );  //对于 win32 LittleShort 是空的宏
     buf_p += 2;
     targa_header.colormap_length = LittleShort ( *(short *)buf_p );
     buf_p += 2;
     targa_header.colormap_size = *buf_p++;
     targa_header.x_origin = LittleShort ( *(short *)buf_p );   //8  图像 x 坐标起始位置                               
     buf_p += 2;
     targa_header.y_origin = LittleShort ( *(short *)buf_p );   //10 图像 y 坐标起始位置  
     buf_p += 2;
     targa_header.width = LittleShort ( *(short *)buf_p );    //12 图像宽度
     buf_p += 2;
     targa_header.height = LittleShort ( *(short *)buf_p );    //14 图像高度
     buf_p += 2;
     targa_header.pixel_size = *buf_p++;         //16 图像每像素存储占用位(bit)数   
     targa_header.attributes = *buf_p++;         //17 
     //2  -  未压缩的,rgb 图像
     //3  -  未压缩的,黑白图像
     //10 -  runlength 编码的 rgb 图像
     if (targa_header.image_type!=2&& targa_header.image_type!=10&& targa_header.image_type != 3 ) 
     {
      ri.Error (ERR_DROP, "LoadTGA: Only type 2 (RGB), 3 (gray), and 10 (RGB) TGA images supported\n");
     }
     //该字段的内容或者为 0 或者为 1,0 表示没有颜色表,1 表示颜色表存在.格式 2,3,10 是无颜色表的
     if ( targa_header.colormap_type != 0 )
     {
      ri.Error( ERR_DROP, "LoadTGA: colormaps not supported\n" );
     }
     //图像每像素存储占用位(bit)数   
     if ( ( targa_header.pixel_size != 32 && targa_header.pixel_size != 24 ) && targa_header.image_type != 3 )
     {
      ri.Error (ERR_DROP, "LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
     }
     columns = targa_header.width;
     rows = targa_header.height;
     numPixels = columns * rows;     //像素个数
     if (width)
      *width = columns;
     if (height)
      *height = rows;
     targa_rgba = (byte *)ri.Malloc (numPixels*4);    //分配内存保存图像像素数据
     *pic = targa_rgba;
     if (targa_header.id_length != 0)
      buf_p += targa_header.id_length;  // skip TARGA image comment
     if ( targa_header.image_type==2 || targa_header.image_type == 3 )
     {
      // Uncompressed RGB or gray scale image
      for(row=rows-1; row>=0; row--)
      {
       pixbuf = targa_rgba + row*columns*4;
       for(column=0; column<columns; column++)
       {
        unsigned char red,green,blue,alphabyte;
        switch (targa_header.pixel_size)
        {
        case 8:
         blue = *buf_p++;
         green = blue;
         red = blue;
         *pixbuf++ = red;
         *pixbuf++ = green;
         *pixbuf++ = blue;
         *pixbuf++ = 255;
         break;
        case 24:
         blue = *buf_p++;
         green = *buf_p++;
         red = *buf_p++;
         *pixbuf++ = red;
         *pixbuf++ = green;
         *pixbuf++ = blue;
         *pixbuf++ = 255;
         break;
        case 32:
         blue = *buf_p++;        //tga 存放像素以BGRA 顺序。我们需要转换为 RGBA 顺序
         green = *buf_p++;
         red = *buf_p++;
         alphabyte = *buf_p++;
         *pixbuf++ = red;
         *pixbuf++ = green;
         *pixbuf++ = blue;
         *pixbuf++ = alphabyte;
         break;
        default:
         ri.Error( ERR_DROP, "LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name );
         break;
        }
       }
      }
     }
     else if (targa_header.image_type==10)
     {   // Runlength encoded RGB images
      unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j;
      red = 0;
      green = 0;
      blue = 0;
      alphabyte = 0xff;
      for(row=rows-1; row>=0; row--)
      {
       pixbuf = targa_rgba + row*columns*4;
       for(column=0; column<columns; )
       {
        packetHeader= *buf_p++;
        packetSize = 1 + (packetHeader & 0x7f);
        if (packetHeader & 0x80)
        {        // run-length packet
         switch (targa_header.pixel_size)
         {
          case 24:
           blue = *buf_p++;
           green = *buf_p++;
           red = *buf_p++;
           alphabyte = 255;
           break;
          case 32:
           blue = *buf_p++;
           green = *buf_p++;
           red = *buf_p++;
           alphabyte = *buf_p++;
           break;
          default:
           ri.Error( ERR_DROP, "LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name );
           break;
         }
         for(j=0;j<packetSize;j++)
         {
          *pixbuf++=red;
          *pixbuf++=green;
          *pixbuf++=blue;
          *pixbuf++=alphabyte;
          column++;
          if (column==columns)
          { // run spans across rows
           column=0;
           if (row>0)
            row--;
           else
            goto breakOut;
           pixbuf = targa_rgba + row*columns*4;
          }
         }
        }
        else {                            // non run-length packet
         for(j=0;j<packetSize;j++)
         {
          switch (targa_header.pixel_size)
          {
           case 24:
            blue = *buf_p++;
            green = *buf_p++;
            red = *buf_p++;
            *pixbuf++ = red;
            *pixbuf++ = green;
            *pixbuf++ = blue;
            *pixbuf++ = 255;
            break;
           case 32:
            blue = *buf_p++;
            green = *buf_p++;
            red = *buf_p++;
            alphabyte = *buf_p++;
            *pixbuf++ = red;
            *pixbuf++ = green;
            *pixbuf++ = blue;
            *pixbuf++ = alphabyte;
            break;
           default:
            ri.Error( ERR_DROP, "LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name );
            break;
          }
          column++;
          if (column==columns)
          { // pixel packet run spans across rows
           column=0;
           if (row>0)
            row--;
           else
            goto breakOut;
           pixbuf = targa_rgba + row*columns*4;
          }      
         }
        }
       }
    breakOut:;
      }
     }

     // instead we just print a warning
     if (targa_header.attributes & 0x20)
     {
      ri.Printf( PRINT_WARNING, "WARNING: '%s' TGA file header declares top-down image, ignoring\n", name);
     }
     ri.FS_FreeFile (buffer);
    August 06

    quake3 使用到的 opengl 函数说明

    对于opengl 扩展函数必须在初始化窗口结束后才能使用 wglGetProcAddress 获得

    Opengl 没有重载函数,对于功能相同但参数类型和数量不同的函数加上后缀,最长可达4个,第一个字符指出有几个参数,第4个为v(如果有的话),指出函数接受一个地址做为参数
    //opengl1.1版本扩展函数,用来切换纹理层,参数如下
    #define GL_TEXTURE0_ARB                     0x84C0
    #define GL_TEXTURE1_ARB                     0x84C1
    #define GL_TEXTURE2_ARB                     0x84C2
    #define GL_TEXTURE3_ARB                     0x84C3

    1.void ( APIENTRY * glActiveTextureARB)( GLenum texture );
    调用扩展提供的函数glActiveTextureARB()来指定当前操作的是哪一个纹理单元,在下一次调用glActiveTextureARB之前所有的函数适用于当前选定的纹理单元
    glActiveTextureARB的Active不能理解为激活,使发生作用!!!应理解为选择(Select)某纹理单元(Texture Unit),即表示后续的
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, texture);
    作用于此所选的纹理单元.而glEnable(GL_TEXTURE_2D)才是真正激活纹理单元的调用. 新函数 qlActiveTexture

        glActiveTextureARB(GL_TEXTURE0_ARB);  // 选择TEXTURE0为设置目标
        glEnable(GL_TEXTURE_2D);                    // 激活TEXTURE0单元
        glBindTexture(GL_TEXTURE_2D, texture); // 为TEXTURE0单元绑定texture纹理图像
        glActiveTextureARB(GL_TEXTURE1_ARB);  // 选择TEXTURE1为设置目标
        glDisable(GL_TEXTURE_2D);                   // 关闭禁用TEXTURE1单元
        glDrawArrays(GL_TRIANGLE_STRIP, 0, NUM_STRIP_VERTICE); // 由于TEXTURE1单元被关闭,执行此Pass渲染时只有TEXTURE0单元发生了作用。

    如果,
    glActiveTextureARB(GL_TEXTURE1_ARB);  // 选择TEXTURE1为设置目标
    glEnable(GL_TEXTURE_2D);                     // 激活TEXTURE1单元
    glBindTexture(GL_TEXTURE_2D, alphaTex); // 为TEXTURE1单元绑定alphaTex纹理图像
    此时由于有2个纹理单元被激活,glDrawArrays调用将Blend两个纹理单元形成最终的画面.

    2.void ( APIENTRY * glClientActiveTextureARB )( GLenum texture );
    要设置纹理单元的纹理顶点数组,不能使用glActiveTextureARB,而应该使用glClientActiveTextureARB,如:
    glClientActiveTextureARB(GL_TEXTURE0_ARB);
    glTexCoordPointer(2, GL_FLOAT, 0, tp0);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

    关闭多重纹理:禁用所有非GL_TEXTURE0_ARB层纹理,最后激活GL_TEXTURE0_ARB纹理
    glActiveTextureARB(GL_TEXTURE1_ARB);
    glDisable(GL_TEXTURE_2D);
    glActiveTextureARB(GL_TEXTURE0_ARB);
    glEnable(GL_TEXTURE_2D);
    特别需要小心的是:既不能在glActiveTextureARB状态下使用glTexCoordPointer设置当前纹理单元的纹理坐标数组指针,更不能在glClientActiveTextureARB状态下设置当前纹理单元的非Client属性,即此时调用的glEnable(GL_TEXTURE_2D);glBindTexture(GL_TEXTURE_2D, tex);均为无效操作.
    glEnableClientState必须进入glClientActiveTextureARB状态后设置才对纹理单元有效,在外部所作设置修改不了纹理单元的设置.

     
    对应的头文件 qgl.h : quake 中采用 q+opengl函数名 替代被使用的opengl函数

    extern void ( APIENTRY * qglMultiTexCoord2fARB )( GLenum texture, GLfloat s, GLfloat t );
    /*opgl1.0版本扩展函数
    为了方便指定包含多组纹理坐标的顶点数组,opengl提供了命令glClientActiveTexture。应用程序使用glTexCoordPointer()指定纹理坐标数组时,Opengl将这组纹理坐标分配给glClientActiveTexture指定的纹理单元
    /*
    extern void ( APIENTRY * qglActiveTextureARB )( GLenum texture );
    extern void ( APIENTRY * qglClientActiveTextureARB )( GLenum texture );
     
    /*
     
    */
    extern void ( APIENTRY * qglLockArraysEXT) (GLint, GLint);
    extern void ( APIENTRY * qglUnlockArraysEXT) (void);

    extern  void ( APIENTRY * qglAccum )(GLenum op, GLfloat value);
    extern  void ( APIENTRY * qglAlphaFunc )(GLenum func, GLclampf ref);
    extern  GLboolean ( APIENTRY * qglAreTexturesResident )(GLsizei n, const GLuint *textures, GLboolean *residences);
    extern  void ( APIENTRY * qglArrayElement )(GLint i);
    extern  void ( APIENTRY * qglBegin )(GLenum mode);
    /*
    tells OpenGL to bind the named texture texture to a texture target
    将纹理名字texture代表的纹理绑定到纹理目标上。
    target: GL_TEXTURE_1D 或者 GL_TEXTURE_2D,代表纹理的维数
    texture: 一个数字用来绑定并代表一个纹理目标。
    使用它来切换纹理
    */
    extern  void ( APIENTRY * qglBindTexture )(GLenum target, GLuint texture);
    extern  void ( APIENTRY * qglBitmap )(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap);
    /*
    混合方程:
    c = (src * sfactor) + (dst * dfactor)
    参数 RGB混合因子

    Alpha 混合因子

    GL_ZERO

    (0,0,0)

    0

    GL_ONE

    (1,1,1)

    1

    GL_SRC_COLOR

    (Rs,Gs,Bs)

    As

    GL_ONE_MINUS_SRC_COLOR

    (1,1,1) - (Rs,Gs,Bs)

    1 - As

    GL_DST_COLOR

    (Rd,Gd,Bd)

    Ad

    GL_ONE_MINUS_DST_COLOR

    (1,1,1) - (Rd,Gd,Bd)

    1-Ad

    GL_SRC_ALPHA

    (As,As,As)

    As

    GL_ONE_MINUS_SRC_ALPHA

    (1,1,1) - (As,As,As)

    1-As

    GL_DST_ALPHA

    (Ad,Ad,Ad)

    Ad

    GL_ONE_MINUS_DST_ALPHA

    (1,1,1) - (Ad,Ad,Ad)

    1-Ad

    GL_SRC_ALPHA_SATURATE

    (f,f,f)*

    1

     
    例如:半透明效果
    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
    设:
    dst = (1.0f,0.0f,0.0f,0.0f)  red
    src = (0.0f,0.0f,1.0f,0.3f)  blue
    sfactor = 源Alpha值 = 0.3f
    dfactor = 1 - 源Alpha值 = 1 - 0.3f
    则最终混合后颜色:
    c = (blue * 0.3f) + (red * 0.7f)
    sfactor 是输入的片元颜色值混合参数。dfactor 是目前帧缓存中的像素颜色值混合参数
    */
    extern  void ( APIENTRY * qglBlendFunc )(GLenum sfactor, GLenum dfactor);
     

    extern  void ( APIENTRY * qglCallList )(GLuint list);
    extern  void ( APIENTRY * qglCallLists )(GLsizei n, GLenum type, const GLvoid *lists);
    /*
    清空帧缓存。mask 可以设置为GL_COLOR_BUFFER_BIT 清空颜色缓存 GL_DEPTH_BUFFER_BIT 清空深度缓存 GL_STENCIL_BUFFER_BIT 清空模板缓存
    例如: glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT )
    */
    extern  void ( APIENTRY * qglClear )(GLbitfield mask);
    extern  void ( APIENTRY * qglClearAccum )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
    /*
    指定glClear 清空颜色缓存时使用的颜色,取值范围 0.0-1.0
    例如: qglClearColor( 1, 0, 0.5, 1 )
    */
    extern  void ( APIENTRY * qglClearColor )(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
    /*glClearDepth 指定 glClear 函数清除深度缓存使用的深度值
    当调用glClear(GL_DEPTH_BUFFER_BIT)时清空深度缓存写入深度值depth,如果不通过glClearDepth设置,默认写入最大的深度值
    例如: glClearDepth( 1.0f )
    */
    extern  void ( APIENTRY * qglClearDepth )(GLclampd depth);
    extern  void ( APIENTRY * qglClearIndex )(GLfloat c);
    extern  void ( APIENTRY * qglClearStencil )(GLint s);
    extern  void ( APIENTRY * qglClipPlane )(GLenum plane, const GLdouble *equation);
    extern  void ( APIENTRY * qglColor3b )(GLbyte red, GLbyte green, GLbyte blue);
    extern  void ( APIENTRY * qglColor3bv )(const GLbyte *v);
    extern  void ( APIENTRY * qglColor3d )(GLdouble red, GLdouble green, GLdouble blue);
    extern  void ( APIENTRY * qglColor3dv )(const GLdouble *v);
    extern  void ( APIENTRY * qglColor3f )(GLfloat red, GLfloat green, GLfloat blue);
    extern  void ( APIENTRY * qglColor3fv )(const GLfloat *v);
    extern  void ( APIENTRY * qglColor3i )(GLint red, GLint green, GLint blue);
    extern  void ( APIENTRY * qglColor3iv )(const GLint *v);
    extern  void ( APIENTRY * qglColor3s )(GLshort red, GLshort green, GLshort blue);
    extern  void ( APIENTRY * qglColor3sv )(const GLshort *v);
    extern  void ( APIENTRY * qglColor3ub )(GLubyte red, GLubyte green, GLubyte blue);
    extern  void ( APIENTRY * qglColor3ubv )(const GLubyte *v);
    extern  void ( APIENTRY * qglColor3ui )(GLuint red, GLuint green, GLuint blue);
    extern  void ( APIENTRY * qglColor3uiv )(const GLuint *v);
    extern  void ( APIENTRY * qglColor3us )(GLushort red, GLushort green, GLushort blue);
    extern  void ( APIENTRY * qglColor3usv )(const GLushort *v);
    extern  void ( APIENTRY * qglColor4b )(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha);
    extern  void ( APIENTRY * qglColor4bv )(const GLbyte *v);
    extern  void ( APIENTRY * qglColor4d )(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha);
    extern  void ( APIENTRY * qglColor4dv )(const GLdouble *v);
    extern  void ( APIENTRY * qglColor4f )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
    extern  void ( APIENTRY * qglColor4fv )(const GLfloat *v);
    extern  void ( APIENTRY * qglColor4i )(GLint red, GLint green, GLint blue, GLint alpha);
    extern  void ( APIENTRY * qglColor4iv )(const GLint *v);
    extern  void ( APIENTRY * qglColor4s )(GLshort red, GLshort green, GLshort blue, GLshort alpha);
    extern  void ( APIENTRY * qglColor4sv )(const GLshort *v);
    extern  void ( APIENTRY * qglColor4ub )(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha);
    extern  void ( APIENTRY * qglColor4ubv )(const GLubyte *v);
    extern  void ( APIENTRY * qglColor4ui )(GLuint red, GLuint green, GLuint blue, GLuint alpha);
    extern  void ( APIENTRY * qglColor4uiv )(const GLuint *v);
    extern  void ( APIENTRY * qglColor4us )(GLushort red, GLushort green, GLushort blue, GLushort alpha);
    extern  void ( APIENTRY * qglColor4usv )(const GLushort *v);
    extern  void ( APIENTRY * qglColorMask )(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
    extern  void ( APIENTRY * qglColorMaterial )(GLenum face, GLenum mode);
     
    /*提交颜色数组供OpenGL使用
    size:  数据大小 . 如:4
    type:  数据类型. 如:GL_UNSIGNED_BYTE ,颜色数据针对 GL_UNSIGNED_BYTE  做了优化。
    stride: 如果数据是紧密连接指定其为0,否则为颜色数据之间的跨距
    pointer: 数组的位置
    例如:
    qglColorPointer( 4,GL_UNSIGNED_BYTE,0,colors);
    */
    extern  void ( APIENTRY * qglColorPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);

    extern  void ( APIENTRY * qglCopyPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
    extern  void ( APIENTRY * qglCopyTexImage1D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border);
    extern  void ( APIENTRY * qglCopyTexImage2D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
    extern  void ( APIENTRY * qglCopyTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
    extern  void ( APIENTRY * qglCopyTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
    /*
    OpenGl 面剔除特性根据填充图元面对的方向决定是否将其丢弃,使用前需要掉用 glEnable(GL_CULL_FACE)
    mode 参数:
    GL_FRONT  剔除正面
    GL_BACK    剔除背面
    */
    extern  void ( APIENTRY * qglCullFace )(GLenum mode);
    extern  void ( APIENTRY * qglDeleteLists )(GLuint list, GLsizei range);
    extern  void ( APIENTRY * qglDeleteTextures )(GLsizei n, const GLuint *textures);
    /*
    深度值比较,默认为 GL_LESS 如果片元窗口空间z值小于存储的在深度缓存中的值,片元将通过深度测试。
    如果参数为GL_LEQUAL, 片元窗口空间z值小于或等于存储的在深度缓存中的值,片元将通过深度测试。
    这在multipass中很有用。
    例如: glDepthFunc( GL_LEQUAL )
    */
    extern  void ( APIENTRY * qglDepthFunc )(GLenum func);

    /*
    调用glDepthMask(GL_FALSE);可将深度缓冲区设置为只读形式。
    调用glDepthMask(GL_TRUE);可将深度缓冲区设置为可读可写形式
    画透明物体时必须将深度缓冲区设置为只读形式.防止深度缓冲起作用,不画透明物体后面的物体
    */
    extern  void ( APIENTRY * qglDepthMask )(GLboolean flag);

    /*
    深度缓冲区所存储的值范围在-1.0-1.0之间。这个函数允许把一个特定的线性深度值映射到一个标准范围的窗口z坐标。窗口z值的缺省范围是0到1,分别对应近和远裁剪平面
    */
    extern  void ( APIENTRY * qglDepthRange )(GLclampd zNear, GLclampd zFar);
    extern  void ( APIENTRY * qglDisable )(GLenum cap);
    extern  void ( APIENTRY * qglDisableClientState )(GLenum array);
     
    /*
    只用1个函数的调用就可以替代几个函数调用:glNormal glColor glVertex 等等
    mode: 指定要被渲染的图元
    first: 指定从已启用数组什么位置开始
    count: 表示有多少个数组元素被提取
    */
    extern  void ( APIENTRY * qglDrawArrays )(GLenum mode, GLint first, GLsizei count);
     
    /*
    指定要写入的缓存,使用双缓存时,通常只绘制后缓存,并在绘制完成后交换缓存。
    还可以指定要将立体图像(电子眼镜)渲染到那个缓存(GL*LEFT 和 GL*RIGHT),以及将图像渲染到辅助缓存(GL_AUXi)中
    使用单缓存时,mode默认为 GL_FRONT,  使用双缓存时,mode 默认为GL_BACK
    */
    extern  void ( APIENTRY * qglDrawBuffer )(GLenum mode);
     
    /*
    绘制单个Opengl图元,mode可以是任何合法的OpenGL图元类型:GL_POINTS  GL_LINES  GL_TRIANGLES
    count: 要渲染的索引个数
    type: 是数组indeces的数据类型
    indices 是一个索引数组
    例如: qglDrawElements( GL_TRIANGLES,numIndexes,GL_UNSIGNED_INT,indexes );
    */
    extern  void ( APIENTRY * qglDrawElements )(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
    extern  void ( APIENTRY * qglDrawPixels )(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
    extern  void ( APIENTRY * qglEdgeFlag )(GLboolean flag);
    extern  void ( APIENTRY * qglEdgeFlagPointer )(GLsizei stride, const GLvoid *pointer);
    extern  void ( APIENTRY * qglEdgeFlagv )(const GLboolean *flag);
    /*
    设置Opengl特性的启用状态。
    默认情况大多数OpenGL特性都被禁用,事实上只有两项特性默认被起用,抖动(GL_DITHER) 和多重采样(GL_MULTISMAPLE)
    实际上游戏很多时候不需要抖动
    GL_BLEND 混合
    GL_DEPTH_TEST 深度测试
    GL_LIGHTING 光照
    GL_ALPHA_TEST 启用alpha测试
    GL_CULL_FACE 启用面剔除
    GL_TEXTURE_2D  启用2维纹理映射模式

    例如: glEnable(GL_DEPTH_TEST) 启动深度测试
    */
    extern  void ( APIENTRY * qglEnable )(GLenum cap);
     
    /*
    启用Opengl客户端状态:
    array:
    GL_VERTEX_ARRAY                 启用顶点数组
    GL_NORMAL_ARRAY                启用法线数组
    GL_TEXTURE_COORD_ARRAY  启用纹理坐标数组
    GL_COLOR_ARRAY                   启用颜色数组
    */
    extern  void ( APIENTRY * qglEnableClientState )(GLenum array);
    extern  void ( APIENTRY * qglEnd )(void);
    extern  void ( APIENTRY * qglEndList )(void);
    extern  void ( APIENTRY * qglEvalCoord1d )(GLdouble u);
    extern  void ( APIENTRY * qglEvalCoord1dv )(const GLdouble *u);
    extern  void ( APIENTRY * qglEvalCoord1f )(GLfloat u);
    extern  void ( APIENTRY * qglEvalCoord1fv )(const GLfloat *u);
    extern  void ( APIENTRY * qglEvalCoord2d )(GLdouble u, GLdouble v);
    extern  void ( APIENTRY * qglEvalCoord2dv )(const GLdouble *u);
    extern  void ( APIENTRY * qglEvalCoord2f )(GLfloat u, GLfloat v);
    extern  void ( APIENTRY * qglEvalCoord2fv )(const GLfloat *u);
    extern  void ( APIENTRY * qglEvalMesh1 )(GLenum mode, GLint i1, GLint i2);
    extern  void ( APIENTRY * qglEvalMesh2 )(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2);
    extern  void ( APIENTRY * qglEvalPoint1 )(GLint i);
    extern  void ( APIENTRY * qglEvalPoint2 )(GLint i, GLint j);
    extern  void ( APIENTRY * qglFeedbackBuffer )(GLsizei size, GLenum type, GLfloat *buffer);
    /*
    The glFinish function does not return until the effects of all previously called OpenGL functions are complete. Such effects include all changes to the OpenGL state, all changes to the connection state, and all changes to the framebuffer contents.
    阻塞直到Opengl 执行命令结束
    */
    extern  void ( APIENTRY * qglFinish )(void);
    /*
    */
    extern  void ( APIENTRY * qglFlush )(void);
    extern  void ( APIENTRY * qglFogf )(GLenum pname, GLfloat param);
    extern  void ( APIENTRY * qglFogfv )(GLenum pname, const GLfloat *params);
    extern  void ( APIENTRY * qglFogi )(GLenum pname, GLint param);
    extern  void ( APIENTRY * qglFogiv )(GLenum pname, const GLint *params);
    extern  void ( APIENTRY * qglFrontFace )(GLenum mode);
    extern  void ( APIENTRY * qglFrustum )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
    extern  GLuint ( APIENTRY * qglGenLists )(GLsizei range);
    extern  void ( APIENTRY * qglGenTextures )(GLsizei n, GLuint *textures);
    extern  void ( APIENTRY * qglGetBooleanv )(GLenum pname, GLboolean *params);
    extern  void ( APIENTRY * qglGetClipPlane )(GLenum plane, GLdouble *equation);
    extern  void ( APIENTRY * qglGetDoublev )(GLenum pname, GLdouble *params);
    /*
    返回 Opengl 错误信息
    GL_NO_ERROR
    没有错误. 这个常量值为0
    GL_INVALID_ENUM
    向 Opengl 命令传递了无效的枚举值
    GL_INVALID_VALUE
    向 Opengl 传递的值不再允许的范围内
    GL_INVALID_OPERATION
    发出的Opengl 命令非法(就当前状态而言,此函数命令不合适)
    GL_STACK_OVERFLOW
    命令导致Opengl堆栈溢出
    GL_STACK_UNDERFLOW
    命令导致Opengl堆栈下溢
    GL_OUT_OF_MEMORY
    Opengl 无法分配足够的内存来处理命令
    Opengl 错误是应用程序的bug,需要修改代码。在应用程序中,通常在初始化后面以及渲染动画中的每帧后调用glGetError().为了避免影响性能通常在非生产代码中调用它
    如: assert(glGetError() == GL_NO_ERROR);
    */
    extern  GLenum ( APIENTRY * qglGetError )(void);
    extern  void ( APIENTRY * qglGetFloatv )(GLenum pname, GLfloat *params);
    /*
    查询特定的阀值
    GL_MAX_TEXTURE_SIZE  查询支持的最大纹理大小
    GL_MAX_TEXTURE_UNITS  查询支持的纹理单元个数 quake3 中重定义为 GL_MAX_ACTIVE_TEXTURES_ARB
    GL_MAX_ELEMENTS_VRTICES  最大支持的顶点数
    GL_MAX_ELEMENTS_INDICES   最大支持的索引数
    GL_MAX_LIGHTS  查询支持的最大灯光数量
    */
    extern  void ( APIENTRY * qglGetIntegerv )(GLenum pname, GLint *params);
    extern  void ( APIENTRY * qglGetLightfv )(GLenum light, GLenum pname, GLfloat *params);
    extern  void ( APIENTRY * qglGetLightiv )(GLenum light, GLenum pname, GLint *params);
    extern  void ( APIENTRY * qglGetMapdv )(GLenum target, GLenum query, GLdouble *v);
    extern  void ( APIENTRY * qglGetMapfv )(GLenum target, GLenum query, GLfloat *v);
    extern  void ( APIENTRY * qglGetMapiv )(GLenum target, GLenum query, GLint *v);
    extern  void ( APIENTRY * qglGetMaterialfv )(GLenum face, GLenum pname, GLfloat *params);
    extern  void ( APIENTRY * qglGetMaterialiv )(GLenum face, GLenum pname, GLint *params);
    extern  void ( APIENTRY * qglGetPixelMapfv )(GLenum map, GLfloat *values);
    extern  void ( APIENTRY * qglGetPixelMapuiv )(GLenum map, GLuint *values);
    extern  void ( APIENTRY * qglGetPixelMapusv )(GLenum map, GLushort *values);
    extern  void ( APIENTRY * qglGetPointerv )(GLenum pname, GLvoid* *params);
    extern  void ( APIENTRY * qglGetPolygonStipple )(GLubyte *mask);
    /*
    查询信息
    根据name的值返回不同的字符串值
    GL_VENDOR: 返回OpenGL 实现的厂商
    GL_VERSION:返回OpenGL 版本
    GL_EXTENSISONS:返回OpenGL实现中可用的扩展
    GL_RENDERER: 返回厂商特定的渲染器信息
    必须具备渲染上下文时才能调用这个函数
    */
    extern  const GLubyte * ( APIENTRY * qglGetString )(GLenum name);
    extern  void ( APIENTRY * qglGetTexEnvfv )(GLenum target, GLenum pname, GLfloat *params);
    extern  void ( APIENTRY * qglGetTexEnviv )(GLenum target, GLenum pname, GLint *params);
    extern  void ( APIENTRY * qglGetTexGendv )(GLenum coord, GLenum pname, GLdouble *params);
    extern  void ( APIENTRY * qglGetTexGenfv )(GLenum coord, GLenum pname, GLfloat *params);
    extern  void ( APIENTRY * qglGetTexGeniv )(GLenum coord, GLenum pname, GLint *params);
    extern  void ( APIENTRY * qglGetTexImage )(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels);
    extern  void ( APIENTRY * qglGetTexLevelParameterfv )(GLenum target, GLint level, GLenum pname, GLfloat *params);
    extern  void ( APIENTRY * qglGetTexLevelParameteriv )(GLenum target, GLint level, GLenum pname, GLint *params);
    extern  void ( APIENTRY * qglGetTexParameterfv )(GLenum target, GLenum pname, GLfloat *params);
    extern  void ( APIENTRY * qglGetTexParameteriv )(GLenum target, GLenum pname, GLint *params);
    extern  void ( APIENTRY * qglHint )(GLenum target, GLenum mode);
    extern  void ( APIENTRY * qglIndexMask )(GLuint mask);
    extern  void ( APIENTRY * qglIndexPointer )(GLenum type, GLsizei stride, const GLvoid *pointer);
    extern  void ( APIENTRY * qglIndexd )(GLdouble c);
    extern  void ( APIENTRY * qglIndexdv )(const GLdouble *c);
    extern  void ( APIENTRY * qglIndexf )(GLfloat c);
    extern  void ( APIENTRY * qglIndexfv )(const GLfloat *c);
    extern  void ( APIENTRY * qglIndexi )(GLint c);
    extern  void ( APIENTRY * qglIndexiv )(const GLint *c);
    extern  void ( APIENTRY * qglIndexs )(GLshort c);
    extern  void ( APIENTRY * qglIndexsv )(const GLshort *c);
    extern  void ( APIENTRY * qglIndexub )(GLubyte c);
    extern  void ( APIENTRY * qglIndexubv )(const GLubyte *c);
    extern  void ( APIENTRY * qglInitNames )(void);
    extern  void ( APIENTRY * qglInterleavedArrays )(GLenum format, GLsizei stride, const GLvoid *pointer);
    extern  GLboolean ( APIENTRY * qglIsEnabled )(GLenum cap);
    extern  GLboolean ( APIENTRY * qglIsList )(GLuint list);
    extern  GLboolean ( APIENTRY * qglIsTexture )(GLuint texture);
    extern  void ( APIENTRY * qglLightModelf )(GLenum pname, GLfloat param);
    extern  void ( APIENTRY * qglLightModelfv )(GLenum pname, const GLfloat *params);
    extern  void ( APIENTRY * qglLightModeli )(GLenum pname, GLint param);
    extern  void ( APIENTRY * qglLightModeliv )(GLenum pname, const GLint *params);
    extern  void ( APIENTRY * qglLightf )(GLenum light, GLenum pname, GLfloat param);
    extern  void ( APIENTRY * qglLightfv )(GLenum light, GLenum pname, const GLfloat *params);
    extern  void ( APIENTRY * qglLighti )(GLenum light, GLenum pname, GLint param);
    extern  void ( APIENTRY * qglLightiv )(GLenum light, GLenum pname, const GLint *params);
    extern  void ( APIENTRY * qglLineStipple )(GLint factor, GLushort pattern);
    extern  void ( APIENTRY * qglLineWidth )(GLfloat width);
    extern  void ( APIENTRY * qglListBase )(GLuint base);
    /*
    修改当前活动矩阵堆栈的栈顶,将栈顶矩阵替换为单位矩阵
    */
    extern  void ( APIENTRY * qglLoadIdentity )(void);
    /*
    修改当前活动矩阵堆栈的栈顶,将栈顶矩阵替换为矩阵m
    */
    extern  void ( APIENTRY * qglLoadMatrixd )(const GLdouble *m);
    //同上
    extern  void ( APIENTRY * qglLoadMatrixf )(const GLfloat *m);
    extern  void ( APIENTRY * qglLoadName )(GLuint name);
    extern  void ( APIENTRY * qglLogicOp )(GLenum opcode);
    extern  void ( APIENTRY * qglMap1d )(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points);
    extern  void ( APIENTRY * qglMap1f )(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points);
    extern  void ( APIENTRY * qglMap2d )(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points);
    extern  void ( APIENTRY * qglMap2f )(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points);
    extern  void ( APIENTRY * qglMapGrid1d )(GLint un, GLdouble u1, GLdouble u2);
    extern  void ( APIENTRY * qglMapGrid1f )(GLint un, GLfloat u1, GLfloat u2);
    extern  void ( APIENTRY * qglMapGrid2d )(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2);
    extern  void ( APIENTRY * qglMapGrid2f )(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2);
    extern  void ( APIENTRY * qglMaterialf )(GLenum face, GLenum pname, GLfloat param);
    extern  void ( APIENTRY * qglMaterialfv )(GLenum face, GLenum pname, const GLfloat *params);
    extern  void ( APIENTRY * qglMateriali )(GLenum face, GLenum pname, GLint param);
    extern  void ( APIENTRY * qglMaterialiv )(GLenum face, GLenum pname, const GLint *params);
    /*
    mode 可以为 GL_PROJECTION GL_MODELVIEW 或 GL_TEXTURE
    选择活动矩阵堆栈:
    GL_PROJECTION 选择投影矩阵堆栈
    GL_MODELVIEW 选择模型视点矩阵堆栈
    */
    extern  void ( APIENTRY * qglMatrixMode )(GLenum mode);
    extern  void ( APIENTRY * qglMultMatrixd )(const GLdouble *m);
    extern  void ( APIENTRY * qglMultMatrixf )(const GLfloat *m);
    extern  void ( APIENTRY * qglNewList )(GLuint list, GLenum mode);
    extern  void ( APIENTRY * qglNormal3b )(GLbyte nx, GLbyte ny, GLbyte nz);
    extern  void ( APIENTRY * qglNormal3bv )(const GLbyte *v);
    extern  void ( APIENTRY * qglNormal3d )(GLdouble nx, GLdouble ny, GLdouble nz);
    extern  void ( APIENTRY * qglNormal3dv )(const GLdouble *v);
    extern  void ( APIENTRY * qglNormal3f )(GLfloat nx, GLfloat ny, GLfloat nz);
    extern  void ( APIENTRY * qglNormal3fv )(const GLfloat *v);
    extern  void ( APIENTRY * qglNormal3i )(GLint nx, GLint ny, GLint nz);
    extern  void ( APIENTRY * qglNormal3iv )(const GLint *v);
    extern  void ( APIENTRY * qglNormal3s )(GLshort nx, GLshort ny, GLshort nz);
    extern  void ( APIENTRY * qglNormal3sv )(const GLshort *v);
    extern  void ( APIENTRY * qglNormalPointer )(GLenum type, GLsizei stride, const GLvoid *pointer);
    extern  void ( APIENTRY * qglOrtho )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
    extern  void ( APIENTRY * qglPassThrough )(GLfloat token);
    extern  void ( APIENTRY * qglPixelMapfv )(GLenum map, GLsizei mapsize, const GLfloat *values);
    extern  void ( APIENTRY * qglPixelMapuiv )(GLenum map, GLsizei mapsize, const GLuint *values);
    extern  void ( APIENTRY * qglPixelMapusv )(GLenum map, GLsizei mapsize, const GLushort *values);
    extern  void ( APIENTRY * qglPixelStoref )(GLenum pname, GLfloat param);
    extern  void ( APIENTRY * qglPixelStorei )(GLenum pname, GLint param);
    extern  void ( APIENTRY * qglPixelTransferf )(GLenum pname, GLfloat param);
    extern  void ( APIENTRY * qglPixelTransferi )(GLenum pname, GLint param);
    extern  void ( APIENTRY * qglPixelZoom )(GLfloat xfactor, GLfloat yfactor);
    extern  void ( APIENTRY * qglPointSize )(GLfloat size);
    /*
    Opengl可以将填充图元渲染为线段或点。
    mode 可以为 GL_POINT 绘制点 GL_LINE 绘制多边形线框 GL_FILL填充多边形
    face 可以为 GL_FONT GL_BACK GL_FONT_AND_BACK 它指定用于正面图元,背面图元还是两者
    glPloygonMode(GL_FONT_AND_BACK,GL_FILL)
    */
    extern  void ( APIENTRY * qglPolygonMode )(GLenum face, GLenum mode);
    extern  void ( APIENTRY * qglPolygonOffset )(GLfloat factor, GLfloat units);
    extern  void ( APIENTRY * qglPolygonStipple )(const GLubyte *mask);
    //glPopAttrib此函数未使用
    extern  void ( APIENTRY * qglPopAttrib )(void);
    //glPopClientAttrib 此函数未使用
    extern  void ( APIENTRY * qglPopClientAttrib )(void);
    extern  void ( APIENTRY * qglPopMatrix )(void);
    extern  void ( APIENTRY * qglPopName )(void);
    extern  void ( APIENTRY * qglPrioritizeTextures )(GLsizei n, const GLuint *textures, const GLclampf *priorities);
    //此函数未使用
    extern  void ( APIENTRY * qglPushAttrib )(GLbitfield mask);
    //此函数未使用
    extern  void ( APIENTRY * qglPushClientAttrib )(GLbitfield mask);
    extern  void ( APIENTRY * qglPushMatrix )(void);
    extern  void ( APIENTRY * qglPushName )(GLuint name);
    extern  void ( APIENTRY * qglRasterPos2d )(GLdouble x, GLdouble y);
    extern  void ( APIENTRY * qglRasterPos2dv )(const GLdouble *v);
    extern  void ( APIENTRY * qglRasterPos2f )(GLfloat x, GLfloat y);
    extern  void ( APIENTRY * qglRasterPos2fv )(const GLfloat *v);
    extern  void ( APIENTRY * qglRasterPos2i )(GLint x, GLint y);
    extern  void ( APIENTRY * qglRasterPos2iv )(const GLint *v);
    extern  void ( APIENTRY * qglRasterPos2s )(GLshort x, GLshort y);
    extern  void ( APIENTRY * qglRasterPos2sv )(const GLshort *v);
    extern  void ( APIENTRY * qglRasterPos3d )(GLdouble x, GLdouble y, GLdouble z);
    extern  void ( APIENTRY * qglRasterPos3dv )(const GLdouble *v);
    extern  void ( APIENTRY * qglRasterPos3f )(GLfloat x, GLfloat y, GLfloat z);
    extern  void ( APIENTRY * qglRasterPos3fv )(const GLfloat *v);
    extern  void ( APIENTRY * qglRasterPos3i )(GLint x, GLint y, GLint z);
    extern  void ( APIENTRY * qglRasterPos3iv )(const GLint *v);
    extern  void ( APIENTRY * qglRasterPos3s )(GLshort x, GLshort y, GLshort z);
    extern  void ( APIENTRY * qglRasterPos3sv )(const GLshort *v);
    extern  void ( APIENTRY * qglRasterPos4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
    extern  void ( APIENTRY * qglRasterPos4dv )(const GLdouble *v);
    extern  void ( APIENTRY * qglRasterPos4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
    extern  void ( APIENTRY * qglRasterPos4fv )(const GLfloat *v);
    extern  void ( APIENTRY * qglRasterPos4i )(GLint x, GLint y, GLint z, GLint w);
    extern  void ( APIENTRY * qglRasterPos4iv )(const GLint *v);
    extern  void ( APIENTRY * qglRasterPos4s )(GLshort x, GLshort y, GLshort z, GLshort w);
    extern  void ( APIENTRY * qglRasterPos4sv )(const GLshort *v);
    extern  void ( APIENTRY * qglReadBuffer )(GLenum mode);
    extern  void ( APIENTRY * qglReadPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
    extern  void ( APIENTRY * qglRectd )(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2);
    extern  void ( APIENTRY * qglRectdv )(const GLdouble *v1, const GLdouble *v2);
    extern  void ( APIENTRY * qglRectf )(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2);
    extern  void ( APIENTRY * qglRectfv )(const GLfloat *v1, const GLfloat *v2);
    extern  void ( APIENTRY * qglRecti )(GLint x1, GLint y1, GLint x2, GLint y2);
    extern  void ( APIENTRY * qglRectiv )(const GLint *v1, const GLint *v2);
    extern  void ( APIENTRY * qglRects )(GLshort x1, GLshort y1, GLshort x2, GLshort y2);
    extern  void ( APIENTRY * qglRectsv )(const GLshort *v1, const GLshort *v2);
    extern  GLint ( APIENTRY * qglRenderMode )(GLenum mode);
    extern  void ( APIENTRY * qglRotated )(GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
    extern  void ( APIENTRY * qglRotatef )(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
    extern  void ( APIENTRY * qglScaled )(GLdouble x, GLdouble y, GLdouble z);
    extern  void ( APIENTRY * qglScalef )(GLfloat x, GLfloat y, GLfloat z);
    /*
    裁剪测试,可以定义窗口中的一个矩形区域,并将作图限制在其中。若片元部分落在该矩形区,则剪取测试通过,否则片元被删除。超出的部分不会画出
    启用裁剪测试 qglEnable(GL_SCISSOR_TEST)
    qglScissor( 0, 0, glConfig.vidWidth, glConfig.vidHeight );
    */
    extern  void ( APIENTRY * qglScissor )(GLint x, GLint y, GLsizei width, GLsizei height);
    extern  void ( APIENTRY * qglSelectBuffer )(GLsizei size, GLuint *buffer);
    /*
    指定使用平滑着色还是恒定着色。mode  可以是 GL_SMOOTH 或 GL_FLAT。
    默认为平滑着色,Opengl 在渲染时对顶点颜色执行插值计算
    如果用GL_FLAT,一般使用最后一个顶点做为图元的颜色
    qglShadeModel( GL_SMOOTH );
    */
    extern  void ( APIENTRY * qglShadeModel )(GLenum mode);
    extern  void ( APIENTRY * qglStencilFunc )(GLenum func, GLint ref, GLuint mask);
    extern  void ( APIENTRY * qglStencilMask )(GLuint mask);
    extern  void ( APIENTRY * qglStencilOp )(GLenum fail, GLenum zfail, GLenum zpass);
    extern  void ( APIENTRY * qglTexCoord1d )(GLdouble s);
    extern  void ( APIENTRY * qglTexCoord1dv )(const GLdouble *v);
    extern  void ( APIENTRY * qglTexCoord1f )(GLfloat s);
    extern  void ( APIENTRY * qglTexCoord1fv )(const GLfloat *v);
    extern  void ( APIENTRY * qglTexCoord1i )(GLint s);
    extern  void ( APIENTRY * qglTexCoord1iv )(const GLint *v);
    extern  void ( APIENTRY * qglTexCoord1s )(GLshort s);
    extern  void ( APIENTRY * qglTexCoord1sv )(const GLshort *v);
    extern  void ( APIENTRY * qglTexCoord2d )(GLdouble s, GLdouble t);
    extern  void ( APIENTRY * qglTexCoord2dv )(const GLdouble *v);
    extern  void ( APIENTRY * qglTexCoord2f )(GLfloat s, GLfloat t);
    extern  void ( APIENTRY * qglTexCoord2fv )(const GLfloat *v);
    extern  void ( APIENTRY * qglTexCoord2i )(GLint s, GLint t);
    extern  void ( APIENTRY * qglTexCoord2iv )(const GLint *v);
    extern  void ( APIENTRY * qglTexCoord2s )(GLshort s, GLshort t);
    extern  void ( APIENTRY * qglTexCoord2sv )(const GLshort *v);
    extern  void ( APIENTRY * qglTexCoord3d )(GLdouble s, GLdouble t, GLdouble r);
    extern  void ( APIENTRY * qglTexCoord3dv )(const GLdouble *v);
    extern  void ( APIENTRY * qglTexCoord3f )(GLfloat s, GLfloat t, GLfloat r);
    extern  void ( APIENTRY * qglTexCoord3fv )(const GLfloat *v);
    extern  void ( APIENTRY * qglTexCoord3i )(GLint s, GLint t, GLint r);
    extern  void ( APIENTRY * qglTexCoord3iv )(const GLint *v);
    extern  void ( APIENTRY * qglTexCoord3s )(GLshort s, GLshort t, GLshort r);
    extern  void ( APIENTRY * qglTexCoord3sv )(const GLshort *v);
    extern  void ( APIENTRY * qglTexCoord4d )(GLdouble s, GLdouble t, GLdouble r, GLdouble q);
    extern  void ( APIENTRY * qglTexCoord4dv )(const GLdouble *v);
    extern  void ( APIENTRY * qglTexCoord4f )(GLfloat s, GLfloat t, GLfloat r, GLfloat q);
    extern  void ( APIENTRY * qglTexCoord4fv )(const GLfloat *v);
    extern  void ( APIENTRY * qglTexCoord4i )(GLint s, GLint t, GLint r, GLint q);
    extern  void ( APIENTRY * qglTexCoord4iv )(const GLint *v);
    extern  void ( APIENTRY * qglTexCoord4s )(GLshort s, GLshort t, GLshort r, GLshort q);
    extern  void ( APIENTRY * qglTexCoord4sv )(const GLshort *v);
    /*
    应用程序使用glTexCoorPointer()指定纹理坐标数组时,Opengl将这组纹理坐标分配给glClientActiveTexture指定的纹理单元.
    定义一组纹理坐标数组,用于OpenGL的顶点数组功能
    size 每个数组元素坐标数量。有效值 1-4
    type 数组的数据类型.GL_FLOAT GL_INT GL_SHORT GL_DOUBLE
    stride 数组坐标之间的字节偏移。0 表示数据是紧密相邻的
    pointer 一个指定顶点数组的数据开始位置的指针
    例如:
    qglTexCoordPointer( 2, GL_FLOAT, 0, texcoords[0] );
    */
    extern  void ( APIENTRY * qglTexCoordPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);

    /*
    在进行纹理贴图时,纹理贴图可以直接贴到物体上从而覆盖物体已有的颜色,也可以和物体原有的颜色进行融合。融合是一种重要的图像处理技术,主要用于透明,发光等等效果的处理。
    void glTexEnvf(GLenum target,GLenum pname,GLfloat param);
    target
    的参数必须是GL_TEXTURE_ENV;
    pname的参数可以为GL_TEXTURE_ENV_MODEGL_TEXTURE_ENV_COLOR;
    param可以为GL_MODULATEGL_DECALGL_BLEND 、GL_ADD、GL_REPLACE 等等
    */

    extern  void ( APIENTRY * qglTexEnvf )(GLenum target, GLenum pname, GLfloat param);
    extern  void ( APIENTRY * qglTexEnvfv )(GLenum target, GLenum pname, const GLfloat *params);
    extern  void ( APIENTRY * qglTexEnvi )(GLenum target, GLenum pname, GLint param);
    extern  void ( APIENTRY * qglTexEnviv )(GLenum target, GLenum pname, const GLint *params);
    extern  void ( APIENTRY * qglTexGend )(GLenum coord, GLenum pname, GLdouble param);
    extern  void ( APIENTRY * qglTexGendv )(GLenum coord, GLenum pname, const GLdouble *params);
    extern  void ( APIENTRY * qglTexGenf )(GLenum coord, GLenum pname, GLfloat param);
    extern  void ( APIENTRY * qglTexGenfv )(GLenum coord, GLenum pname, const GLfloat *params);
    extern  void ( APIENTRY * qglTexGeni )(GLenum coord, GLenum pname, GLint param);
    extern  void ( APIENTRY * qglTexGeniv )(GLenum coord, GLenum pname, const GLint *params);
    extern  void ( APIENTRY * qglTexImage1D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);

    /*qglTexImage2D 定义一个二维纹理映射。
    参数target必须是常数GL_TEXTURE_2D
    参数level表示多级分辨率的纹理图像的级数(mipmap level),若只有一种分辨率,则level设为0。Level n is the nth mipmap reduction image
    参数internalformat纹理像素中存储那些分量.可以是1到4的整数,指出选择了R、G、B、A中的哪些分量用于调整和混合,1表示选择了R分量,2表示选择了R和A两个分量,3表示选择了R、G、B三个分量,4表示选择了R、G、B、A四个分量. 或者是如下的值:红色为quake3中用到的
    GL_ALPHA, GL_ALPHA4, GL_ALPHA8, GL_ALPHA12, GL_ALPHA16, GL_LUMINANCE, GL_LUMINANCE4, GL_LUMINANCE8, GL_LUMINANCE12, GL_LUMINANCE16, GL_LUMINANCE_ALPHA, GL_LUMINANCE4_ALPHA4, GL_LUMINANCE6_ALPHA2, GL_LUMINANCE8_ALPHA8, GL_LUMINANCE12_ALPHA4, GL_LUMINANCE12_ALPHA12, GL_LUMINANCE16_ALPHA16, GL_INTENSITY, GL_INTENSITY4, GL_INTENSITY8, GL_INTENSITY12, GL_INTENSITY16, GL_R3_G3_B2, GL_RGB, GL_RGB4, GL_RGB5, GL_RGB8(24位), GL_RGB10, GL_RGB12, GL_RGB16, GL_RGBA, GL_RGBA2, GL_RGBA4(16位), GL_RGB5_A1, GL_RGBA8(32位),GL_RGB4_S3TC,GL_RGB10_A2, GL_RGBA12, or GL_RGBA16.
    参数width和height给出了纹理图像的长度和宽度.
    参数border为纹理边界宽度,它通常为 0
    width和height必须是2n + 2(border),这里n是整数,长和宽可以有不同的值,b是border的值。
    纹理映射的最大尺寸依赖于OpenGL,但它至少必须是使用64x64(若带边界为66x66),若width和height设置为0,则纹理映射有效地关闭。

    参数format和type描述了输入图像数据pixels的格式和类型,它们在这里的意义与在函数glDrawPixels()中的意义相同,事实上,纹理数据与glDrawPixels()所用的数据有同样的格式。
    参数format可以是GL_COLOR_INDEX、GL_RGB、GL_RGBA、GL_RED、GL_GREEN、GL_BLUE、GL_ALPHA、GL_LUMINANCE或GL_LUMINANCE_ALPHA(注意:不能用GL_STENCIL_INDEX和GL_DEPTH_COMPONENT)。

    参数type是GL_BYPE、GL_UNSIGNED_BYTE、GL_SHORT、 GL_UNSIGNED_SHORT、GL_INT、GL_UNSIGNED_INT、GL_FLOAT或GL_BITMAP。  0-255RGBA 类型数据 对应GL_UNSIGNED_BYTE 类型
    参数pixels 指向纹理图像数据,A pointer to the image data in memory。
    例子: qglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
    如果低于 opengl 1.4 glTexImage2D 不支持自动 mipmap . 且没有手动设置mipmap。既对不同level指定纹理数据
    设置纹理滤波时只能使用 GL_LINEAR.否则没有图像显示
    qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
    qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

    */
    extern  void ( APIENTRY * qglTexImage2D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);

    /*滤波
    设置如何将纹理图像的纹理对应到屏幕上的像素;当纹理图像较大或较小时,怎样通过纹理贴图实现纹理缩放和重复。
    void glTexParameterf(GLenum target,GLenum pname,GLfloat param);
    target 的参数可以为GL_TEXTURE_1D(1维纹理)GL_TEXTURE_2D(2维纹理), GL_TEXTURE_3D(3维纹理) 或 GL_TEXTURE_CUBE_MAP
    pname 的参数可以为: GL_TEXTURE_MAG_FILTER (指定放大滤波)或 GL_TEXTURE_MIN_FILTER(指定缩小滤波)

    pname

    含义

    param常用值

    GL_TEXTURE_MIN_FILTER

    一个像素对应多个纹素.
    放大滤波

    GL_NEAREST 使用坐标离像素中心最近的纹理像素,最近点采样
    GL_LINEAR  离像素坐标中心2x2纹理像素,线性插值
    GL_NEAREST_MIPMAP_NEAREST 使用1个mipmap最近点采样
    GL_LINEAR_MIPMAP_NEAREST 使用1个mipmap取线性插值
    GL_NEAREST_MIPMAP_LINEAR 从2个mipmap最近点采样,进行线性插质
    GL_LINEAR_MIPMAP_LINEAR  三线性过滤:从 2个mipmap 线性插值取得2个点后,然后在两个值之间进行线性插值

    GL_TEXTURE_MAG_FILTER

    多个像素对应一个纹素
    缩小滤波

    GL_NEAREST
    GL_LINEAR

    GL_TEXTURE_WRAP_S

    设置纹理在s方向上的被控行为纹理环绕方式

    GL_CLAMP
    GL_REPEAT

    GL_TEXTURE_WRAP_T

    设置纹理在t方向上的被控行为:纹理环绕方式

    GL_CLAMP
    GL_REPEAT

    GL_TEXTURE_BORDER_COLOR

    设置边界颜色

     

    */
    extern  void ( APIENTRY * qglTexParameterf )(GLenum target, GLenum pname, GLfloat param);
    extern  void ( APIENTRY * qglTexParameterfv )(GLenum target, GLenum pname, const GLfloat *params);
    extern  void ( APIENTRY * qglTexParameteri )(GLenum target, GLenum pname, GLint param);
    extern  void ( APIENTRY * qglTexParameteriv )(GLenum target, GLenum pname, const GLint *params);
    extern  void ( APIENTRY * qglTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
    extern  void ( APIENTRY * qglTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
    extern  void ( APIENTRY * qglTranslated )(GLdouble x, GLdouble y, GLdouble z);
    extern  void ( APIENTRY * qglTranslatef )(GLfloat x, GLfloat y, GLfloat z);
    extern  void ( APIENTRY * qglVertex2d )(GLdouble x, GLdouble y);
    extern  void ( APIENTRY * qglVertex2dv )(const GLdouble *v);
    extern  void ( APIENTRY * qglVertex2f )(GLfloat x, GLfloat y);
    extern  void ( APIENTRY * qglVertex2fv )(const GLfloat *v);
    extern  void ( APIENTRY * qglVertex2i )(GLint x, GLint y);
    extern  void ( APIENTRY * qglVertex2iv )(const GLint *v);
    extern  void ( APIENTRY * qglVertex2s )(GLshort x, GLshort y);
    extern  void ( APIENTRY * qglVertex2sv )(const GLshort *v);
    extern  void ( APIENTRY * qglVertex3d )(GLdouble x, GLdouble y, GLdouble z);
    extern  void ( APIENTRY * qglVertex3dv )(const GLdouble *v);
    extern  void ( APIENTRY * qglVertex3f )(GLfloat x, GLfloat y, GLfloat z);
    extern  void ( APIENTRY * qglVertex3fv )(const GLfloat *v);
    extern  void ( APIENTRY * qglVertex3i )(GLint x, GLint y, GLint z);
    extern  void ( APIENTRY * qglVertex3iv )(const GLint *v);
    extern  void ( APIENTRY * qglVertex3s )(GLshort x, GLshort y, GLshort z);
    extern  void ( APIENTRY * qglVertex3sv )(const GLshort *v);
    extern  void ( APIENTRY * qglVertex4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
    extern  void ( APIENTRY * qglVertex4dv )(const GLdouble *v);
    extern  void ( APIENTRY * qglVertex4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
    extern  void ( APIENTRY * qglVertex4fv )(const GLfloat *v);
    extern  void ( APIENTRY * qglVertex4i )(GLint x, GLint y, GLint z, GLint w);
    extern  void ( APIENTRY * qglVertex4iv )(const GLint *v);
    extern  void ( APIENTRY * qglVertex4s )(GLshort x, GLshort y, GLshort z, GLshort w);
    extern  void ( APIENTRY * qglVertex4sv )(const GLshort *v);

    /*

    提交顶点数组供opengl使用
    size    数据大小,发送3d顶点时指定为: 3.  范围2,3,4
    type   要提交的数据类型,通常为GL_FLOAT
    stride  如果数据是紧密相连的,将stride指定为0。否则指定为顶点间的跨距,单位为字节。
    pointer 指向数据或者缓存对象中的偏移量
    typedef float vec4_t[4];
    vec4_t xyzw[1000];
    例如: glVertexPointer(3,GL_FLOAT,16,xyzw) //只需要3个顶点,但数据是16位包含xyzw

    */
    extern  void ( APIENTRY * qglVertexPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);

    /*
    规一化设备坐标到窗口坐标
    qglViewport( 0, 0, 640, 480);
    */
    extern  void ( APIENTRY * qglViewport )(GLint x, GLint y, GLsizei width, GLsizei height);

    extern  int   ( WINAPI * qwglChoosePixelFormat )(HDC, CONST PIXELFORMATDESCRIPTOR *);
    extern  int   ( WINAPI * qwglDescribePixelFormat) (HDC, int, UINT, LPPIXELFORMATDESCRIPTOR);
    extern  int   ( WINAPI * qwglGetPixelFormat)(HDC);
    extern  BOOL  ( WINAPI * qwglSetPixelFormat)(HDC, int, CONST PIXELFORMATDESCRIPTOR *);
    extern  BOOL  ( WINAPI * qwglSwapBuffers)(HDC);

    extern BOOL  ( WINAPI * qwglGetDeviceGammaRamp3DFX)( HDC, LPVOID );
    extern BOOL  ( WINAPI * qwglSetDeviceGammaRamp3DFX)( HDC, LPVOID );

    extern BOOL  ( WINAPI * qwglCopyContext)(HGLRC, HGLRC, UINT);
    extern HGLRC ( WINAPI * qwglCreateContext)(HDC);
    extern HGLRC ( WINAPI * qwglCreateLayerContext)(HDC, int);
    extern BOOL  ( WINAPI * qwglDeleteContext)(HGLRC);
    extern HGLRC ( WINAPI * qwglGetCurrentContext)(VOID);
    extern HDC   ( WINAPI * qwglGetCurrentDC)(VOID);
    extern PROC  ( WINAPI * qwglGetProcAddress)(LPCSTR);
    extern BOOL  ( WINAPI * qwglMakeCurrent)(HDC, HGLRC);
    extern BOOL  ( WINAPI * qwglShareLists)(HGLRC, HGLRC);
    extern BOOL  ( WINAPI * qwglUseFontBitmaps)(HDC, DWORD, DWORD, DWORD);
    extern BOOL  ( WINAPI * qwglUseFontOutlines)(HDC, DWORD, DWORD, DWORD, FLOAT,
                                               FLOAT, int, LPGLYPHMETRICSFLOAT);
    extern BOOL ( WINAPI * qwglDescribeLayerPlane)(HDC, int, int, UINT,
                                                LPLAYERPLANEDESCRIPTOR);
    extern int  ( WINAPI * qwglSetLayerPaletteEntries)(HDC, int, int, int,
                                                    CONST COLORREF *);
    extern int  ( WINAPI * qwglGetLayerPaletteEntries)(HDC, int, int, int,
                                                    COLORREF *);
    extern BOOL ( WINAPI * qwglRealizeLayerPalette)(HDC, int, BOOL);
    extern BOOL ( WINAPI * qwglSwapLayerBuffers)(HDC, UINT);
    /*
    开启或关闭垂直同步。关闭垂直同步可以提高FPS
    水平同步信号,显示设备(显示器)接收到这个信号后,就开始画下一行。
    垂直同步信号,显示设备(显示器)接收到这个信号后,就开始画下一帧。

    */
    extern BOOL ( WINAPI * qwglSwapIntervalEXT)( int interval );

     

    没有使用 gluLookAt 函数。相机使用默认位置的方向。默认情况下,相机位于原点,镜头指向z轴负方向,向上向量为(0,1,0)

     
    July 04

    2D bsp 简介

    凸多边形
    所谓凸多边形,就是把一个多边形任意一边向两方无限延长成为一条直线,如果多边形的其他各边均在此直线的同旁,那么这个多边形就叫做凸多边形。如图1,多边形ABCDEF,把线段AF向两方无限延长,此多边形的其他各边AB、BC、CD、DE、EF均在此直线的同旁,所以多边形ABCDEF是凸多边形。
     
     
     
    凹多边形
    把一个各边不自交的多边形任意一边向两方无限延长成为一直线,如果多边形的其他各边不在此直线的同旁,那么这个多边形就叫做凹多边形。
       凹多边形的内角和的解,其实我们可以通过(n-2)·180来计算。实际上是把大于平角的角划分为两个角(如图)

    这不是quake 中bsp实现方式,而是早期doom的。或者说不是3d 关卡的bsp实现方式,希望从简单的2d 开始了解bsp概念的可以看看

    BSP 树
    ------
    解释BSP树的运用,最好是从一个例子开始.设想一个很简单的DOOM关卡的例子.

    这个关卡由一个屋子套在另一个屋子里构成.玩家被封闭在矩形ABHG中.
    先给出几个定义.(如图)

    我们用矢量定义直线,所以

          a = (A,B)  e = (E,C)  f = (C,D)  g = (F,D)

    当一个点在直线矢量方向的左边时,我们称点在直线的左边.

    因此,在这个例子里,a的左边什么也没有;所有的东东都在它的右边.注意这些
    依赖与我们对a的定义,如果我们定义 a = (B,A) 则所有的东东都在a的左边.

    面是玩家看到的直线的一边.例如墙e,就有两个面(e'和e").不是所有的墙都有
    两个面 -- 如果玩家只能看见墙的一面,那么这堵墙就只有一个面.

    面是由矢量方向定义的,直线的两个面分别被称作左表面和右表面.

    这个例子中的BSP树是这样的:


                         f
                        / \
                       /   \
                      /     \
               a,d1,b1       e
                            / \
                           /   \
                          /     \
                     d2,c1       g
                                / \
                               /   \
                              /     \
                            c2       c3,b2


    每个节点都是一条直线.所有在直线左边的东东都在它的左子树上,所有在它
    右边的东东都在它的右子树上.

    注意 d 面不是完全在 f 面的右边或左边.为了描述这种情况,我们把它分为
    了两个部分,一个部分放在左子树,一部分放在右子树.因而,我们必须产生新
    的面来构造BSP树.

    我将在后面解释BSP数是怎样创建的.首先,我将给出使用BSP树来产生一幅画的方法.

    假设玩家站在点'x',看着北方.

    我们从树的顶端直线 f 开始.我们站在直线 f 的右边,所以我们向树的左子
    树进行下去.这是因为我们想最先画最远的多边形.

    我们来到了最左的节点.请在笔记本上记下节点上的东东--"a,d1,b1".

    当我们不能再往下时,回到父节点.现在回到了根节点,我们还不能马上去右子树.
    首先,我们看见了 f 面--写在这个节点上的.我们已经在我们列出的表上得到了
    处在它后面的所有东东,我们还将看见它前面的东东,但是我们必须先把它记入我
    们的表中.注意,f 面有两个表面--f' 和 f".既然我们已经知道我们处在直线 f
    的右边,当然就只能看到它的右表面--所以我们在笔记本上记下 f".现在本子上
    写着 a,d1,b1,f".

    注意,如果我们是看着南方(视线远离 f 面),看不到 f 的任何一个面和 f 的那
    一面后的所有东东.在这种情况下,我们就不必做前面这些.

    现在我们向下到节点 e.我们在 e 的右边,所以要往左子树去,这样便得到了一个
    叶节点.现在把 d2,c1 记下来.

    再回来,看看该记下 e 的哪一面.应该是 e'.现在笔记本上写着
    a,d1,b1,f",d2,c1,e'.

    向右子树,来到 g 节点.我们在左边,所以向右得到 c3,b2,再回来,检查 g (我
    们在左边,应为g'),去最后一个节点得到 c2,回溯,回溯,回溯,回到根节点,遍历
    完成.

    最后笔记本上写着:

    a d1 b1 f" d2 c1 e' c3 b2 g' c2

    如果我们以这个次序来画这些墙,将得到正确的图象.建议你使用3D-buffer而
    不要用画家算法,这样速度要快的多.

    创建 BSP 树
    -----------


    BSP树完全是递归创建的.唯一的困难是知道何时该停止递归.应该注意到叶节
    点将被整个放入表中--因此将一组平面放在一个叶节点上的充分条件是它们能
    够以任何次序画出来而不致有错.也就是说,无论玩家站在哪儿,这一组墙之间
    都不会被别的挡住.

    好吧,让我们开始:选择一个面 f (这个选择相当随便--最好是选一个面,它能
    最少的分割其它面.当然,分割是不可避免的).分割 d 面和 b 面,因为它们被
    直线 f 分开了.(用DOOM中的说法,去分割区域的线被称为节点线 _nodeline_ )

    然后把 f 左边的东东放在左子树,右边也如此:


                                f
                               / \
                              /   \
                             /     \
                      a,d1,b1       b2,c,d2,e,g

    我们可以不再处理左子树--因为墙 a,d1,b1 构成一个凸多边形,从任意角度
    看它们都互不重叠.然而在另一边,平面 e 却使得从特定点去观察平面 d2 会
    被其挡住,所以我们从 e 处分开,这就造成了平面 c 的分割,但是同样被分割
    的平面 a 却不用被分割,这是因为 a 不在现在分析的平面中.

    第二级 BSP 树为:

                                f
                               / \
                              /   \
                             /     \
                      a,d1,b1       e
                                   / \
                                  /   \
                                 /     \
                            d2,c1       b2,c2,g

    现在,c1 和 d2 从不重叠,顾而我们将它们作为另一个叶节点.下一步我们
    从 g 处分开,将 c2 分成 c2 和 c3,剩下的节点都是叶节点.

    下面这棵 BSP 树的最简单运用--再给一个例子来加深印象.考虑一下站在
    y 点向北看的情况.因为看不到 f 面,你只用搜索左子树.这样马上就得到
    了需要的循序: a,d1,b1.

    精华
    ----

    如果我们在每个节点上为每个子树定义一个特定空间,记录子树中的信息,
    这样我们就能以锥形视野比较这些信息将一些不可见的多边形截掉(屏幕
    左边和右边的东东)--如果它们不相交,这样你就不必搜索整个子树.DOOM
    就是这样做的,在一个巨大的 BSP 树中用特定空间储存了每一级的完整
    (*entire*)信息.

    下面是搜索 BSP 树的伪代码.函数 left() 当第二个输入矢量在第一个输
    入矢量的左边时返回 TRUE.这就是两个矢量的点积,...
    ... Sorry,小D这一句不太明白
    >This is a simple dot product, and by pre-calculating the slope of the
    >nodeline can be done with one multiply and one subtract.

    vector  player                         ; player's map position
                                           ; 玩家在地图上的位置矢量
    vector  left_sightline                 ; vector representing a ray cast through
                                           ; the left-most pixel of the screen
                                           ; 描述发射到屏幕最左边的光线的矢量
    vector  right_sightline                ; the right-most pixel of the screen
                                           ; 描述发射到屏幕最右边的光线的矢量


    structure node
    {
      vector vertex1
      vector vertex2
      node   left_subtree
      node   right_subtree
      face   left_face
      face   right_face
      box    bounding_box
      bool   terminal_node
      face   terminal_node_faces[lots]
    }

    recurse(node input)

    if (cone defined by left and right sightlines does not intersect the node's
        bounding box)
      return
    fi

    if node.terminal_node
      ; terminal node - add faces to list
      ; 叶节点--将平面填入表中
      add(node.terminal_node_faces)
      return
    fi

    if left(vertex2-vertex1,player-vertex1)
      ; player is to the left of the nodeline
      ; 玩家在节点线的左边
      if not left(vertex2-vertex1,right_sightline)
        ; sight points right - we are looking at the face
        ; 视线指向右边--我们正看着这个面
        recurse(node.right_subtree)
        add(node.left_face)
      fi
      ; now go down the left subtree
      ; 现在向左子树搜索
      recurse(node.left_subtree)
    else
      ; player is to the right of the nodeline
      ; 玩家在节点线的右边
      if left(vertex2-vertex1,left_sightline)
        ; sight points left - we are looking at the face
        ; 视线指向左边--我们正看着这个面
        recurse(node.left_subtree)
        add(node.right_face)
      fi
      ; now go down the right subtree
      ; 现在向右子树搜索
      recurse(node.right_subtree)
    fi

    return                                                                        

    end recurse

    这不是正规的代码--象数据结构之类的很多东东都没写. :)

    June 26

    quake3 脚本

    首先,为了记住你上一次使用的枪,需要设定一个变量,这里用prevweapon,并且把它的值的设定绑定在每把枪上。譬如你用5做炮:
    bind 5 "weapon 5;set prevweapon weapon 5"
    然后是具体动作的脚本了。先设定一个摁下一个键的动作。
    set sniper_hold "weapon 7;+zoom"
    weapon 7是RG,+zoom是放大,呵呵,有点废话。之后是放开这个键的动作。
    set sniper_release "+attack;wait;-attack;-zoom;vstr prevweapon"
    这句话里,+attack是攻击,-attack是停止攻击。为什么非得这么写呢?因为在Quake3里,和Zoom,Speed一样,attack分两个状态,当你把它独自绑定在一个键上,摁下代表+attack,松开就是-attack,在这里,由于不是这样的一个键上的单独绑定,+attack就会使“小人儿”处于攻击状态,不停的开枪。所以之后要加一个-attack。为了防止-attack在+attack还没发生做用的时候执行,所以在中间加了一个wait。其实还可以加更多。如果你本来就开了一枪,那么+attack这个状态将在装子弹不能攻击的时候发生作用,而-attack发生作用的时候,根本就没有开枪。根据自己的情况,可以将其改为wait 20之类,这相当于你写20个wait:)。

    -zoom没什么说的。接下来的一句,首先,你要明白set prevweapon weapon 5这一句并不是说prevweapon就是等于weapon 5的作用了。prevweapon是一个变量,而不是命令或者代命令。要想使得其中储存的命令得以执行,就需要vstr这个命令。vstr,说白了就是执行变量里的命令的命令。最开始我写脚本的时候,就总忘了vstr呵呵。现在vstr了prevweapon,由于你上次用的枪是RL,当你摁下q的时候,prevweapon里的值是weapon 5,所以在放开这个sniper用的键的最后,它将换回weapon 5,RL。

    接下来我们要把它们真正绑定在一个键上了,我这里用MOUSE3。我们要把sniper_hold绑在摁下去、把sniper_release绑在松开来上。
    这里有两种方法,其中一种已经过时了,而且特别容易出毛病,我在这里就不说了。另外一种是osp的方法,其实osp文档里就有说明的。我在这里用这个实例给初学者再说一下。
     
    bind Mouse3 "+vstr sniper_hold sniper_release"
    这个是osp模式里最好的实现方式了,其他的方式也需要osp、很难使而且可以绑定的键有限。毫不夸张的说,+vstr这个命令是osp发明以来对脚本的最大贡献!举个例子,RB上次发布cfg大家都用了,如果大概意思不改动,实现换电枪无抖动也需要用到+vstr。我认为,只要你想得到,很多地方+vstr已经可以代替以前很多vstr来实现的脚本,一方面它功能强大,可以做出很炫的功能;另一方面,用+vstr可以将一些现存的脚本简化,使得脚本有更大的可读性。

    没有安装 osp mod , 对于quake3.1.32b 的代码可以使用如下的脚本:
    set sniper_hold "weapon 7;+zoom;bind Mouse3 vstr sniper_release"
    set sniper_release "+attack;wait ;-attack;-zoom;vstr prevweapon;bind Mouse3 vstr sniper_hold"
    bind Mouse3 "vstr sniper_hold"
     
    保存脚本到 myscript.cfg 中,进入关卡执行 exec myscript.cfg
    或者在 q3config.cfg 中绑定一个键来加载这个文件
     
    由此可以看到 cvar 控制台命令的强大。可以组合各种命令来简化操作。很类似魔兽世界的宏,只是缺少了条件判断。而魔兽的宏更类似脚本,写起来似乎有些长而不实用
     
    June 24

    CVars、Commands and vm Communication

    One of the most common questions I'm asked through e-mail is "How do I get the client to do something from the server code?"... or variations on the theme. The issue is made more complicated by the fact that client, server, and user interface each have their own methods and restrictions.

    This article aims to de-mystify the methods you can use to pass information between the three Virtual Machines (VM's). There are several complementary methods, and I'll outline the advantages and problems with each.

    We'll start with a desciption of the client/server/interface model in Quake3. Understanding the relationship between these components is at the core of the need to communicate between them. Some of the restrictions in the system are also clarified.

    We'll then move onto the main methods: the setting of variables, also called Cvars, and how they're related to configuration strings maintained by the server. We'll then look at the sending of console commands, and finish off by seeing how we can drive the server scripting engine.

    I've tried to write each main section as an overview and introduction to the sub-sections that follow. As the ideas and definitions can get confusing IT IS IMPORTANT THAT YOU READ AND UNDERSTAND EACH OF THESE OVERVIEWS before proceeding with the more specialized descriptions.

     

     

    1. Server, client, and user interface

    Whether you're compiling binaries or bytecode for the platform independant VMs, it's clear that the game is split into three parts: server (qagame), client (cgame), and user interface (ui). Each carries responsibility for implementing a separate part of the game. What isn't so obvious, and is often forgotten, is that there's a fourth part: the executable that runs the VMs.

    The server and client complement each other and carry just about everything needed to play the game. The server controls and arbitrates the game: it decides where a player is on the map, whether they've been hit by that rocket, and where the momentum kick sends their corpse. The final word in what happens in the game, the server makes sure that the game world remains consistant.

    On the other hand, the client has only a limited view of the world. It's given information by the server that it needs to present this localized view to the player... and little else.

    The client is responsible for drawing the screen, playing the sounds, and adding all those little meaty gibs. It also includes an understanding of the game physics so it can predict motion and make gameplay smoother over an Internet connection, but it doesn't settle the final position of the other players (or yourself).

    To make this clear with an example: the server concerns itself over who has the quad, applying the damage multiplier, and settling disputes when two players try to pick it up at the same time. The client is told who has the quad, plays announcements and damage sfx, and draws that blue glow that warns "something dangerous comes this way!"

    It's possible for the client and server to be on separate machines, this is how an Internet game is played. Communication has to occur over a time delay determined by the connection quality and latency (ping), so there will be a delay between a command being sent and received. There's nothing that can be done about that.

    The client and user interface are always on your local machine. Think of them as connected to your graphics and sound cards, and you won't go far wrong. Servers don't care about these things directly, the closest they get is sending out a command saying "play this sound" or "do this action".

    The user interface covers all of the menus and pages of controls used to set up personal preferences and game parameters. It is the user interface that draws the menu when you hit the Escape key while playing a game. Anything the behaves like a dialog box or page of controls is drawn (and interacted with) in the user interface.

    Finally, it's important to recognize that there's a fourth part to all this, hidden away from prying eyes because the source code isn't available: the binary executable. This runs the VMs required to play the game, manages the communication between the VMs, controls the network connection if there is one, and handles all the OpenGL drawing of the graphics.

    Any communication between VMs is going to have to pass through the binary executable. It's the only way.

     

    2. Cvars and configuration strings - passive changes of state

    Console variables (Cvars) store the current state of the game system in a way that can be accessed through the console while playing, and directly in the game code. Many Cvars are read only: you can't change their value. Some can only be modified when cheats are enabled. Most are saved for the next time you play Q3.

    As a variable a Cvar isn't a command that must be obeyed immediately. What usually happens is that your code will check the value the next time it needs to use it, and adjusts its behaviour depending on the value it finds stored.

    This is helped by the way a Cvar is updated. A copy of the Cvar is maintained in the source code, this can be read and used in any part of that source code module. This local copy is updated at regular intervals so you have both consistancy of value, and an (almost) up to date value.

    Note that we are accessing a "copy" in the source code, the original or "master" of the variable is stored and maintained by the executable. We'll talk about this in more detail when we look at how and when the Cvar copy is updated (section 2.2).

     

    2.1 Where to place your Cvar

    A Cvar is created in the code as a data structure. You need to provide a default initialization value, and flags that control access and if it will be saved in q3config.cfg for permanent storage.

    The Cvar that you access in your code is placed in either game/g_main.c, cgame/cg_main.c, or ui/ui_main.c. You need to choose the most appropriate place: there is no point in putting a Cvar that controls behaviour of the server in the user interface code!

    There are benefits to putting the Cvar in the correct place, described in section 2.2.

    You can place a Cvar in another source code file, but you won't get the benefit of automatic initialization and updating.

     

    Example - Setting up a Cvar

    We'll take a quick look at how you initialize a Cvar and make it available for the rest of your code to use. This example looks at the cg_drawFPS variable in the client that draws the frame rate counter on the screen.

    Although taken from cgame code it applies equally well to the ui in ui_main.c. Its done slightly differently in game, and we'll look at that in a moment.

    Taken from cg_main.c:

    vmCvar_t	cg_drawFPS;
    
    
    cvarTable_t		cvarTable[] = {
    	// earlier Cvars snipped
    
    	{ &cg_drawFPS, "cg_drawFPS", "0", CVAR_ARCHIVE  },
    
    	// following Cvars snipped
    };
    

    A variable of type vmCvar_t is created to store the current value. To take advantage of the automatic updating of the Cvar we need a reference in the array cvarTable[]. This reference takes four components, from left to right they are:

    &cg_drawFPS
    A pointer to the vmCvar_t that stores the Cvar value

    "cg_drawFPS"
    The name of the Cvar as typed into the console

    "0"
    The default initialization for the variable, this can be any string

    CVAR_ARCHIVE
    A flag controlling the behaviour of the variable

    You can find more of the CVAR_* flags in q_shared.h, they're quite well documented there.

    Finally, so that the Cvar can be accessed easily from within related source code files, you need to add a reference to the vmCvar_t into the local header file. For cgame this is cg_local.h, while the ui and game have their equivalent in ui_local.h and g_local.h respectively.

    For our example you'll find this in cg_local.h:

    extern	vmCvar_t		cg_drawFPS;
    

     

    I mentioned earlier that the server was slightly different. The change is in how the Cvar is linked into the list for automatic initialization. Here's what a typical Cvar looks like in g_main.c:

    vmCvar_t	g_gametype;
    
    cvarTable_t		gameCvarTable[] = {
    	// earlier Cvars snipped
    
    	// latched vars
    	{ &g_gametype, "g_gametype", "0", CVAR_SERVERINFO | CVAR_LATCH, 0, qfalse  },
    
    	// following Cvars snipped
    };
    

    The first four entries are identical to their cgame and ui counterparts, but there are two new entries at the end:

    0
    Always initialized as zero, this is the number of times the value of the variable has changed.

    qfalse
    If set to qtrue then an announcement (text message) is sent to all clients that this Cvar has been changed.

     

    2.2 When Cvars are updated

    Even though we can access the Cvars from within the source code, these are not the "master" or "primary" record of the Cvar value. This might sound surprising, but arises from the need to communicate these values between VMs.

    The authoritative value of each Cvar is stored within the executable running the client or server, and the Cvars within the source code are updated to reflect new values on a regular basis. This update might be slightly delayed, but ensures consistancy in use. More on this in a moment.

    In the situation where the client and server are running on separate machines, the client still has access to most of the server Cvars. They can only be read by the client, and not modified.

    The reverse situation where the server accesses a clients Cvars is complicated by the fact that the server can have multiple clients. The mechanism by which a server can access the client is covered in detail in section 2.3.3.

    The copy of the Cvars stored in each of the *_main.c is updated on a regular basis at a "convenient" point in the game play cycle. This point is usually slightly delayed from the time when it was modified in the primary record.

    For the client this update occurs just before the next screen is drawn by CG_DrawActiveFrame() in cg_view.c. This makes sense when you realize that these local copies can be accessed through the vmCvar_t data structure without reference to the primary record. For the entire frame that is about to be drawn you will get a consistant value for the Cvar if you use the value stored in a vmCvar_t variable structure.

    This is important. Go back, read and understand that last paragraph again. Even if the Cvar changes in the primary record while the client is rendering the screen, you get a consistant value to work with while drawing the entire screen. If you always grab the "most up to date value" with a trap_* call then you might get rendering errors for that frame. Also, if you change the value of a Cvar through a trap_* call then you won't see the new value until the next update.

    For the user interface this Cvar update occurs every time the screen is drawn in UI_Refresh() in ui_atoms.c. For the server code the update is triggered in G_RunFrame() in g_main.c, when the server updates the postion of each entity in the world.

    As you can see, the Cvars are updated frequently, but not so frequently as to disrupt a frame of activity. The benefit of these local copies is twofold: constancy and speed of access to a local data structure.

     

    2.3 Reading and setting a Cvar

    With the Cvar created, we need to look at how the value within it can be accessed and changed. The user interface and client behave in a similar way, while there are special considerations for the server.

    By using a trap_* function to set the variable the primary record is updated correctly. You MUST NOT change the value of the local copy of the Cvar - it won't be moved to the primary record, and will only be over-written at the next update. If the Cvar is archived in q3config.cfg then the new value won't be saved either.

    A Cvar data structure looks like this:

    typedef struct {
    	cvarHandle_t	handle;
    	int		modificationCount;
    	float		value;
    	int		integer;
    	char		string[MAX_CVAR_VALUE_STRING];
    } vmCvar_t;
    

    You can read the value of the Cvar by accessing the value, integer, or string fields. This is only possible when the Cvar is stored within the VM you are coding in. In this case it is the optimal method of access. For a Cvar from another VM refer to the methods described below.

    Although, in principle, you can read and modify Cvars from other VMs, the most cautious approach is to treat Cvars from a different VM as read-only. You might need to know a clients preferences to help make the server run more efficiently, but indiscriminantly changing a clients preferences from the server is anti-social.

     

    2.3.1 Cvars in the ui

    The method used to set the value of the Cvar happens to be the same in all three modules, treating the Cvar as a string value that can be changed:

    void trap_Cvar_Set( const char *var_name, const char *value );
    

    var_name
    The name of the Cvar as typed on the console

    value
    The new string that replaces the old one

    The ui also has an additional method that sets the string using a float value rather than a string:

    void trap_Cvar_SetValue( const char *var_name, float value );
    

     

    Retrieving the value of the string is done through the complementary methods:

    void trap_Cvar_VariableStringBuffer(const char *var_name, char *buffer, int bufsize );
    float trap_Cvar_VariableValue( const char *var_name );
    

    var_name
    The name of the Cvar as typed in the console

    buffer
    Pointer to the char array to store the current string value in

    bufsize
    The size of the buffer for storing the string, prevents memory overflow and corruption

     

    Special methods - Configuration Strings

    These are described in great detail in the discussion of client Cvars (section 2.3.2, Special methods - Configuration strings). They represent a method that allows the client and user interface to read a set of strings that the server has set: these strings being common to (and used by) all connected clients.

    You can access these strings through a call to the following function:

    int trap_GetConfigString( int index, char* buff, int buffsize );
    

    index
    type of string you want to retrieve

    buff
    pointer to the buffer to store the configuration string into

    buffsize
    size of the buff array, I'd recommend using MAX_INFO_STRING

    You can't change the value of the configuration strings from the user interface. Check below in the client and server sections on how to process and extract information from them.

    (The truth be told: I didn't find out that the user interface could access these strings until after I'd written the client description of them. I'm too lazy to re-write that description for here :)

     

    2.3.2 Cvars in cgame

    Setting the value of a Cvar in cgame occurs through the same function call as in ui:

    void trap_Cvar_Set( const char *var_name, const char *value );
    

    You can read a Cvar's string value by making a call into the following function:

    void trap_Cvar_VariableStringBuffer( const char *var_name, char *buffer, int bufsize );
    

    and this behaves in the same way as the identically named function in the ui module.

     

    Special methods - Configuration Strings

    For quick access to important Cvars stored in the server, there is a flexible and powerful method available for use. Strictly speaking not all of variables passed through these configuration strings are Cvars, neither are all the server Cvars accessible through this method. However just about all the important ones you'll need in the client are available.

    These configuration strings are set and maintained by the server, and replicated to each client when a connection is first made. When the server updates any of these configuration strings, each connected client gets an updated version.

    These configuration strings are also used to pass information about other clients connected to a server. This information is limited (but useful), and includes things like player name, choice of model, and railgun trail colour. Take a look in ClientUserinfoChanged() in game/g_client.c to see how this string is constructed by the server, and in CG_NewClientInfo() in cgame/cg_players.c for parsing of this info in the client.

    The most up to date version of the configuration strings known to the client can be read through a call to:

    const char *CG_ConfigString( int index );
    

    index
    takes a value related to the type of string(s) you want to retrieve

    Most of the values that index can take are documented in bg_public.h as the CS_* family of flags. You can extend these values by adding new CS_* flags, it looks like there are gaps before CS_MODELS available for expansion, and about 350 free slots after the current value of CS_MAX.

    When a change is made to one of these configuration strings, the client gets notification though CG_ConfigStringModified() in cg_servercmds.c. You can add or extend any processing of the changed configuration string here, or examine how existing strings are parsed to gain further understanding.

    Setting these strings is described in the next section about the server. You can also add strings using two of the existing values of index provided (described below).

    You shouldn't move any of the CS_* values around because comments about the sound values in the source code suggests optimizations within the executable for sending this information across the network. As you can't change the executable, don't mess with the CS_* flags too much!

    The pointer returned by CG_ConfigString() can currently take two forms, and you need to find out which by examining how these CS_* returned strings are used in the source code. Take a look in CG_ConfigStringModified() in cg_servercmds.c or do a GREP through the source code to find out where else they're used or set.

    The first form is a simple string that contains the current value. An index value of CS_MOTD, CS_WARMUP, and CS_MESSAGE behave in this way. You can then process them with an atoi() if they're numerical, or treat them as strings.

    The second form is a list of variable names and value pairs. These can be queried through the provided method:

    char *Info_ValueForKey( const char *string, const char *key );
    

    string
    the pointer returned by CG_ConfigString()

    key
    the name of the Cvar string found on the server, and located in string

    You'll find that the two most powerful values of index are CS_SYSTEMINFO, and CS_SERVERINFO. They contain the server Cvars that are described respectively by the CVAR_SYSTEMINFO and CVAR_SERVERINFO flags in g_main.c.

    You can add your own Cvars in the server using these flags, they'll then be sent to each client when they're updated by the server. Use CVAR_SERVERINFO to describe a string that characterizes the game playing on the server (gametype, fraglimit, mapname etc.). Typically these are the values that a program like GameSpy-3D queries and displays. For the remaining Cvars that describe the low-level state of the sytem, CVAR_SYSTEMINFO should be used (g_syncronousClients is an example).

    Don't put frequently changing values into the CVAR_SERVERINFO or CVAR_SYSTEMINFO flags as the entire string is resent for the change of one variable. Very network inefficient.

    How the server sets these configuration strings is described later in this article.

     

    Example - Using Info_ValueForKey()

    Taken from CG_DrawInformation(void) in cg_info.c, we'll get the short name of the map (q3dm10, q3tourney6 etc.) from CS_SERVERINFO and load an image of the level ready for drawing.

    const char	*s;
    const char	*info;
    qhandle_t	levelshot;
    
    info = CG_ConfigString( CS_SERVERINFO );
    
    s = Info_ValueForKey( info, "mapname" );
    levelshot = trap_R_RegisterShaderNoMip( va( "levelshots/%s.tga", s ) );
    if ( !levelshot ) {
    	levelshot = trap_R_RegisterShaderNoMip( "menu/art/unknownmap" );
    }
    

    Initialization of mapname is slightly unusual and occurs as part of the bot AI in ai_main.c instead of g_main.c. Nevertheless, it has been correctly registered and flagged as CVAR_SERVERINFO.

     

    2.3.3 Cvars in game

    Just as in ui and cgame, we have to set the new value of a Cvar through this function:

    void trap_Cvar_Set( const char *var_name, const char *value );
    

    There are two methods available for reading the value of a Cvar. These are

    int trap_Cvar_VariableIntegerValue( const char *var_name );
    void trap_Cvar_VariableStringBuffer( const char *var_name, char *buffer, int bufsize );
    

    The former takes a Cvar name and returns its integer value, and the latter is used in the way described in the ui (section 2.3.1), above.

     

    Special methods - accessing Cvars set in a client

    Of particular importance to the server is the ability to obtain some of the client parameters. Some of these parameters might be used to optimize the servers behaviour towards that client, others repackaged and sent on to the remaining clients for accurate representation.

    For a client Cvar to be forwarded to the server when it is changed, it must be described by the CVAR_USERINFO flag. The only example of this is the teamoverlay Cvar in the client: it's also a CVAR_ROM so it can only be changed from within the source code, not on the console. This Cvar controls whether the server sends bandwith sucking stats during team games. Other critical Cvars appear to be flagged as CVAR_USERINFO by the executable directly.

    When a client changes one of its Cvars, the updated value is sent to the server and notification arrives at ClientUserinfoChanged() in g_client.c. The information can be validated (if required), modified (if absolutely necessary), or repackaged as a configuration string and sent on for other clients to use.

    The client configuration is read and set through the following functions:

    void trap_GetUserinfo( int num, char *buffer, int bufferSize );
    void trap_SetUserinfo( int num, const char *buffer );
    

    num
    the index value identifying the client

    buffer
    pointer to the buffer string for storing/setting the user info. I'd recommend char buffer[MAX_INFO_STRING]

    bufferSize
    size of the buffer string, preventing overflow on read

    The client index is just the array index of the global server array level.clients that points to the gclient_t data structure representing that player. Look in ClientConnect() in g_client.c to see this. To obtain the client index given a gentity_t* use the following code (which relies on the properties of C pointer subtraction):

    int clientNum;
    gclient_t* client;
    gentity_t* ent;	// must point to a valid entity structure
    
    client = ent->client;	// must be non-zero for an entity that's a client
    clientNum = client - level.clients;
    

    Just like the configuration strings described earlier, you can access the value pairs using Info_ValueForKey(). This example checks whether cg_predictItems is enabled in the client. It's derived from ClientUserinfoChanged() in g_client.c:

    int clientNum;	// set in the argument to ClientUserinfoChanged()
    gentity_t *ent;
    char	*s;
    gclient_t	*client;
    char	userinfo[MAX_INFO_STRING];
    
    ent = g_entities + clientNum;
    client = ent->client;
    
    trap_GetUserinfo( clientNum, userinfo, sizeof( userinfo ) );
    
    // check the item prediction
    s = Info_ValueForKey( userinfo, "cg_predictItems" );
    if ( !atoi( s ) ) {
    	client->pers.predictItemPickup = qfalse;
    } else {
    	client->pers.predictItemPickup = qtrue;
    }
    

     

    In order to use the special parsing function Info_ValueForKey() when constructing your own configuration strings, you need to know how to build these strings.

    There's a working example in ClientUserinfoChanged() in g_client.c, but we'll take a trivial one for clarity. This is how the string would be constructed in the C source (note that the double slash as used in the source code is reduced to a single slash by the compiler).

    "string_one_key\\string_one_value\\string_two_key\\string_two_value"
    

    Values are paired up: each having a unique identifying name (key) and an associated value. The '\\' character is used to separate the values, and you shouldn't pass this character as part of a key name or value (this will prevent Info_ValueForKey() from working), nor a quote ("), or a semi-colon (;). I got these limitations from Info_Validate() in q_shared.c, but be wary of using non-standard characters, and never use a string termination '\0'.

    In this example string_one_key and string_two_key are the possible arguments to Info_ValueForKey(), and string_one_value and string_two_value will be returned.

    The key values shouldn't need to be Cvars, they're just a means of identifying the associated value uniquely. If you are only ever going to send a single string value, then you don't need to use this key/value pair system.

    You will almost certainly end up constructing these strings using the va() variable argument substitution strings, I deliberately avoided them to reduce the complexity of this explanation.

     

    Although there are no examples of the server over-riding the client settings using trap_SetUserinfo(), presumable you just need to send the variables you want changed using the key/value pairing described above. The best place for the server to do this is in ClientUserinfoChanged() in g_client.c

     

    Special methods - configuration strings in the server

    As already described earlier from the point of view of the client, configuration strings contain global information that is maintained by the server. It is transmitted to all the clients connected to the server, and updated when changes are made by the server. The client can't modify these strings, but can (and does) make use of the information.

    A configuration string is read or changed using these functions:

    void trap_GetConfigstring( int num, char *buffer, int bufferSize );
    void trap_SetConfigstring( int num, const char *string );
    

    num
    the index of the configuration string

    buffer
    destination buffer for copying the config stirng to. Use a char array of size MAX_INFO_STRING

    bufferSize
    the size of buffer, prevents overflow

    string
    new value for the configuration string

    Each configuration string is described by an index CS_*, a list of these values can be found in bg_public.h. Although there's space for MAX_CONFIGSTRINGS (1024) values, the smallest amount of change that can be transmitted across a network connection is a single string. This is a network efficient way of transmitting state changes in the server, and other global variables maintained by the server.

    Two special config strings are CS_SYSTEMINFO and CS_SERVERINFO. Described in more detail in the client section above, the Cvars that belong to this group are automatically updated when they're modified by the server using trap_Cvar_Set(). Try to avoid putting frequently changing values in here because it's almost certain that all Cvar strings in this group are transmitted in one go, and this is network inefficient. You can create your own specific CS_* flags and groups instead (like CS_FLAGSTATUS).

    For an example we'll take a look at how the server updates CS_FLAGSTATUS, this code is from g_team.c:

    void Team_SetFlagStatus( int team, flagStatus_t status )
    {
    	qboolean modified = qfalse;
    
    	switch (team) {
    	case TEAM_RED :
    		if ( teamgame.redStatus != status ) {
    			teamgame.redStatus = status;
    			modified = qtrue;
    		}
    		break;
    	case TEAM_BLUE :
    		if ( teamgame.blueStatus != status ) {
    			teamgame.blueStatus = status;
    			modified = qtrue;
    		}
    		break;
    	}
    
    	if (modified) {
    		char st[4];
    
    		st[0] = '0' + (int)teamgame.redStatus;
    		st[1] = '0' + (int)teamgame.blueStatus;
    		st[2] = 0;
    
    		trap_SetConfigstring( CS_FLAGSTATUS, st );
    	}
    }
    

    The flag status is sent as a two digit pair, one each for the red and blue flags. Sending the values as a pair of numbers is a limitation of strings: we must avoid sending anything that might prematurely terminate the string (a char value of '\0'), so its encoded based on the ASCII value for the character '0'.

    This code fragment shows how its decoded in the client, in the function CG_ConfigStringModified() in cg_servercmds.c:

    } else if ( num == CS_FLAGSTATUS ) {
    	// format is rb where its red/blue, 0 is at base, 1 is taken, 2 is dropped
    	cgs.redflag = str[0] - '0';
    	cgs.blueflag = str[1] - '0';
    }
    

    and you can see that the binary value of zero, if stored directly in str[0], would have prevented the rest of the string from being transmitted. The status of the blue flag would then be unknown.

     

    2.4 Some special Cvars

    There are some Cvars that have slightly unusual properties. There are only a few of these Cvars, and I'll only touch on them briefly.

    One reason for these special Cvars is so that one VM can control or influence another in a transparent manner. The three Cvars that fall into this category are sv_running, cl_paused, and g_syncronousClients.

     

    If sv_running is set then the server is running on your local machine. This is important as its presence enables some menu items in the ui that can be used to influence the local server.

    You can also check for this in the client code by accessing cgs.localServer (zero if we're connected to a remote server), it's set in the following manner:

    char var[MAX_TOKEN_CHARS];
    trap_Cvar_VariableStringBuffer( "sv_running", var, sizeof( var ) );
    cgs.localServer = atoi( var );
    

     

    cl_paused is used to indicate to the client that the user interface has drawn a menu on screen while the client is running. Setting this variable to a value of 1 (one) will pause the game if the server is local. This appears to be managed by the executable, stopping the server and client VM's temporarily, rather than in any of the VM code itself.

     

    The third variable is g_syncronousClients, this is set if the server allows demo recording, and it also plays a part in client side prediction. It is created in the server VM, and replicated to the client VM via the CS_SYSTEMINFO configuration string. The client can't modify this value, but it can be read in and acted upon.

    Note that the creation in the client of the vmCvar_t structure doesn't have any CVAR_* flags associated with it, this is because the server stored value is the one with the CVAR_ARCHIVE flag set. In other words, the server has control over the value, while the client contains only a reference.

     

    Another variable, apparently set by the executable, is bot_enable. If this is set to zero then bots aren't loaded onto the system. There is no corresponding copy stored in a VM, it appears to be managed by the executable running the server (but is available to the client). Again, some menu options depend on this value to determine whether they are enabled or not.

     

    3. Console commands - do this, now!

    With the large amount of ground covered by the Cvars and server configuration strings, you're going to find console commands has less content. Unfortunately the picture is made difficult to follow because of the possibility of confusion between the client and server consoles. In addition the server can issue commands to the client, in a way that looks like the console commands, but is in fact separate. I've tried to give the best description of these as I possibly can below.

    Client console commands, as their name suggests, can be typed in from the drop down console. There is also a way of executing these commands from within the source code. Whether the command originates from the console or code is irrelevant when it's acted upon. This means that these commands can't be hidden from the user in the same way as configuration strings can.

    A client console command can be handled in either the user interface, client, or server parts of the code. This makes it a very useful way of asking another VM to do something for you (for example: displaying a menu system using the user interface). We'll look at the client console in section 3.1.

    The server console is another matter. These commands control how the server behaves and they can only be accessed when the server is running on the same machine, or a particular client has the administrator privilige to change the setup of the server remotely. Some commands that fall into this category are addip and addbot, and we'll cover the server console in section 3.2.

    What is potentially confusing is that when the client and server are running on the same machine, both the client and server console commands are entered in the same way. The typing of commands through the drop down console is, at best, a confusing use of terminology.

    Apply this rule of thumb: A command typed in by the player is a client console command if is expected to behave the same whether the server is local (running on the same machine) or remote (on a LAN or across the Internet).

     

    3.1 Client console commands

    Once a console command has been recognized (Cvars are filtered out first), it arrives at the handler for each of the VM modules. For the user interface this handling function is UI_ConsoleCommand() in ui_atoms.c, the client has CG_ConsoleCommand() in cg_consolecmds.c, while the server uses ClientCommand() in g_cmds.c.

    Some pre-processing has already been done for you, and you can get at arguments for the command by using trap_Argv(int pos) (the argument at a given position), and trap_Argc() (the total number of arguments). The user interface and client have "wrappered" versions that can also be accessed through UI_Argv() and CG_Argv(). You'll find that Argv(0) is always the command string itself.

     

    3.1.1 Client console commands in the user interface

    There's no rocket science to adding a console command to the user interface: just add a Q_stricmp( cmd , "yourcmd")==0 comparison into UI_ConsoleCommand() and route it to you handling function.

    The most obvious use of a command in the user interface is to pull up a menu for the user to interact with, and there's an obvious example in the ui_teamOrders command. One thing to be cautious of if you're displaying a menu: you'll need to protect against repeatedly adding new menus until the menu stack is used up.

    Surprisingly there's no way of sending out a console command from the user interface, it has to go through Cvars or server scripting (see section 4). I would guess that's because it's possible for the user interface to be running when the client and server code aren't. Any Cvars that are important and stored outside the user interface are latched anyway - so any updated value is still passed correctly.

    You can get some information about the state of the client through a call to trap_GetClientState(uiClientState_t*). This data structure is described in ui_public.h, and includes (amongst other things) access to the connection state of the client. This might influence how you draw the menu: in a connected game you'll want to leave the background "transparent" so the player can see the game screen. This code fragment taken from UI_ConfirmMenu() in ui_confirm.c shows how this is done:

    uiClientState_t	cstate;
    
    trap_GetClientState( &cstate );
    if ( cstate.connState >= CA_CONNECTED ) {
    	s_confirm.menu.fullscreen = qfalse;	// no black background
    }
    else {
    	s_confirm.menu.fullscreen = qtrue;
    }
    

    See my articles on the user interface menu for more information on how and why ths works.

     

    Special treatment - The In Game (ESC) Menu

    When you press the Escape key while playing a game you get the In Game Menu that allows you to change teams, add bots, change game settings etc. This menu is unusual: it doesn't use a console command to activate it.

    The ESC key is recognized in the executable and passed into the user interface VM through vmMain() in ui_main.c. Although several menus are created by this method, and all pass through UI_SetActiveMenu() in ui_atoms.c I haven't been able to find a way for the user to extend this and add their own menus.

    The good news is that you can use console commands to create your own menus. Just make sure that the commands in UI_SetActiveMenu() don't overwrite your menu, and that UIMENU_NONE is always honoured.

     

    3.1.2 Client console commands in cgame

    Once again, adding a client console command is straight forward. It's made even easier by the use of an array of console commands and associated function handlers in cg_consolecmds.c.

    As the code fragment below shows, just add an new entry into the the commands[] array, with your command name and your handling function. This handling function must be of type void function_name(void) for the array to work.

    typedef struct {
    	char	*cmd;
    	void	(*function)(void);
    } consoleCommand_t;
    
    static consoleCommand_t	commands[] = {
    	{ "testgun", CG_TestGun_f },
    	{ "testmodel", CG_TestModel_f },
    
    	// code snipped
    
    	{ "tcmd", CG_TargetCommand_f },
    	{ "loaddefered", CG_LoadDeferredPlayers }	// spelled wrong, but not changing for demo...
    };
    

     

    You can send out a client command to another VM by calling trap_SendConsoleCommand(const char* cmd_string). You can add arguments with additional information so long as you separate each of them with a space. When they arrive at the VM that handles them they'll already be processed so each argument is easily accessible.

    There is also a similarly named (and possibly confusing) function called trap_SendClientCommand(const char* cmd_string). This sends the command string directly to the server, without a chance being given to the user interface to act upon it. Use it as part of exclusively client-server issues.

    When the command string arrives at the server, whether it came from trap_SendConsoleCommand() or trap_SendClientCommand(), it is handled in ClientCommand() in g_cmds.c.

    This example shows how the tell_target client console command is broken down into a single tell command. Ultimately this will be processed in the server for distribution to the victim under the crosshair.

    static void CG_TellTarget_f( void ) {
    	int		clientNum;
    	char	command[128];
    	char	message[128];
    
    	clientNum = CG_CrosshairPlayer();
    	if ( clientNum == -1 ) {
    		return;
    	}
    
    	trap_Args( message, 128 );
    	Com_sprintf( command, 128, "tell %i %s", clientNum, message );
    	trap_SendClientCommand( command );
    }
    

     

    If you create a command in the server and you want TAB completion to work in the client, then you should also register the server command in the client. This is done in CG_InitConsoleCommands() in cg_consolecmds.c by adding another trap_AddCommand() to the list.

    Why do it this way? Well if the server is running on another machine then you don't want TAB completion to depend on the availability of the network connection.

     

    3.1.3 Client console commands in the server

    There are two types of command that the server can accept, so it's important to put your command into the right place. Go back and read the start of section 3 to understand the difference. We'll look at the client console commands here, while dealing with the server console in section 3.2.

    Since we're looking at client console commands we need to work in ClientCommand() in g_cmds.c. Each command that you add is just a straight forward Q_stricmp() comparison that passes control to your handler if passed.

    Note that there is a watershed between commands that can be executed at any point, and those commands which don't make any sense during the intermission (when a level is over and the scoreboard is displayed, but before the next level is loaded).

    If you want TAB completion of the command name in the client, then you'll need to add the name of the command as described at the end of section 3.1.2, above.

     

    I've not found a way for the server to send a client console command to a particular client (such a command could reach either the ui or cgame). However, there is a way that the server can send a command to the client (cgame), and this is covered in section 3.3. Although this seems to be the reciprocal method for sending a client console command from the server, the commands it sends can't be typed into the client - they can only be sent by the server.

     

    3.2 Server console commands

    Notice the change of subject!

    We're now talking about commands that get to the server console, described and defined at the start of section 3.

    These are the commands that can be typed on a client drop down console when the server is running on the same machine, or if the client has administrative privilige on a remote machine. Usually these commands have a drastic effect on gameplay or the behaviour of the server. You want to be careful who you let use these commands, and many of them might be made available through the voting system.

    All of these commands arrive in ConsoleCommand() in g_svcmds.c for processing (note that console in this case means server console). You don't need to do anything special to separate them from the client console commands, this is done for you automatically (and is outside your control!)

    As this snipped version of ConsoleCommand() shows, you need to return qtrue if you do handle the server command. Trace through the code to Svcmd_AddBot_f() in g_bot.c to see how trap_Argv() is used to grab the arguments to addbot.

    qboolean	ConsoleCommand( void ) {
    	char	cmd[MAX_TOKEN_CHARS];
    
    	trap_Argv( 0, cmd, sizeof( cmd ) );
    
    	// code snipped
    
    	if (Q_stricmp (cmd, "addbot") == 0) {
    		Svcmd_AddBot_f();
    		return qtrue;
    	}
    
    	// code snipped
    
    	return qfalse;
    }
    

     

    3.3 Commands issued to the client from the server

    When the server needs to send a command to one or all clients then it uses the following function:

    trap_SendServerCommand(int clientNum, const char* command_string)
    

    The clientNum is the identifying index of the client, look in section 2.3.3 for an example of how to get a clientNum if it isn't provided for you. clientNum may also be -1, in which case the command is broadcast to all connected clients.

    The command will arrive in the client in CG_ServerCommand() in cg_servercmds.c, all ready for the client to deal with.

    In an attempt to make this clear to a possibly confused reader, try the following experiment: start up Q3 and get a map going. Pull down the console and type in "/cp test" (without the quotes of course!). It will show an error message.

    Now look at CG_ServerCommand() in cg_servercmds.c for the cp command. It draws some text in the centre of the screen (cp - center print) and is sent by the server. Can you now see that commands sent by the server aren't connected to the client console?

     

    4. Server scripting - play the game

    The last method of control is aimed purely at the server. You can send a list of commands to the server (to be accurate, the binary executable running the game VM), that are equivalent to running a script. These commands remain in memory and are used (for example) to set up a map rotation. Think of this method as having the same effect as using the /exec command in the drop down console.

    You can add these commands from the user interface part of the source code, or as part of the game code. You are effectively limited to setting up and controlling a server on your machine only, or having a server manipulate its own script. It shouldn't be possible for a local user interface to manipulate a remote server using these functions.

    From within the user interface code:

    void trap_Cmd_ExecuteText( int exec_when, const char *text );
    

    and from within the server code:

    void trap_SendConsoleCommand( int exec_when, const char *text );
    

    Don't be confused by the fact it carries the same name as a function that's used in the client, its behaviour isn't the same. Think of it as acting on the server console only.

    The text argument is easy enough: it's the text string that contains a command or sets a variable. You should add a newline character '\n' when you issue a single command, or you can put a group of commands together in the same string, separated by a semi-colon, and terminated with a newline. If you don't put the newline in then you'll get two commands running together and confusing the executable's script engine.

    The other argument, exec_when, is a bit more difficult to understand from just code reading and without access to the source code for the executable. Here's the allowed values and what I've been able to glean:

    EXEC_NOW
    The string is executed immediately and control won't return to the VM until it's completed. Use with extreme caution in case a command that you use causes the VM to unload and then reload.

    EXEC_INSERT
    This flag causes a command to be "forgotten" about after it's executed. Control will return immediately while the command is queued for execution in the immediate future.

    EXEC_APPEND
    Think of this as appending text to a script file that's stored by the server. Control returns immediately, and values will remain stored for future reference. This is the most commonly used option.

    Although the EXEC_NOW flag is clear enough, it's possible for the other two to be confused. If you start with the idea that EXEC_APPEND is building a script (list of commands) within the executable running the server, then you can see that this script will always be present until the server is shut down. Although you can add new commands and have them executed, you would use the EXEC_INSERT so that it wasn't permanently added to the script being built by EXEC_APPEND.

    It appears that the EXEC_INSERT command isn't used in the user interface, possibly because the server can't be guaranteed to be running. If you do try to use EXEC_INSERT in the user interface, use it with caution.

     

    Example - setting up a server from the ui

    Taken from ServerOptions_Start() in ui_startserver.c, this code fragment shows the bots selected for a map being added to the server script through the use of EXEC_APPEND. This code is run when you create a server from the multiplayer menu, or have a skirmish from the single player menu.

    Notice that each string for the addbot command is finished off with the '\n' character.

    The wait command is interesting: some of the server parameters are set through trap_Cvar_SetValue(), and this allows their value to propagate through to the binary executable. As this code is run when we set up a server on our local machine, the time delay only needs to be a short one.

    int		skill;
    int		n;
    char	buf[64];
    
    // add bots
    trap_Cmd_ExecuteText( EXEC_APPEND, "wait 3\n" );
    for( n = 1; n < PLAYER_SLOTS; n++ ) {
    	if( s_serveroptions.playerType[n].curvalue != 1 ) {
    		continue;
    	}
    	if( s_serveroptions.playerNameBuffers[n][0] == 0 ) {
    		continue;
    	}
    	if( s_serveroptions.playerNameBuffers[n][0] == '-' ) {
    		continue;
    	}
    	if( s_serveroptions.gametype >= GT_TEAM ) {
    		Com_sprintf( buf, sizeof(buf), "addbot %s %i %s\n",
    			s_serveroptions.playerNameBuffers[n], skill,
    			playerTeam_list[s_serveroptions.playerTeam[n].curvalue] );
    	}
    	else {
    		Com_sprintf( buf, sizeof(buf), "addbot %s %i\n",
    			s_serveroptions.playerNameBuffers[n], skill );
    	}
    	trap_Cmd_ExecuteText( EXEC_APPEND, buf );
    }
    

     

    5. The end of the road...

    We've come a long way with this article, and covered a lot of ground that turned out to be more complex that even I'd originally thought. So long as you keep a clear picture in your mind of the differences and relationships between the user interface, the client, the server, and the executable, then you should be able to use this information to the full.

    When I originally planned this article I was going to talk about manipulating information stored in entities too - I'll have to save that for another time as this article is now far too long to do entities justice.

    There are also some bot commands for setting variables, but I've left them out for reasons of space and specialization. The ideas that govern the use of these bot commands are going to be very similar to the conventional methods I've described in this article.

    Let me know if there are any problems with the article, and if it's been of help to you.

    June 11

    修改 shotgun

    shotgun 是 quake 里面的霰弹枪,射出去的子弹随机分布在一定范围内。目标:修改霰弹枪,当人物蹲射时可以增加霰弹枪精度,使子弹不至过于分散。注:霰弹一次出去为11发。而且不像火箭那样,没有飞行时间。所以当开枪后就计算是否命中。
    PMF_DUCKED 标志表示人物处于下蹲状态。
    #define PMF_DUCKED   1
    #define PMF_JUMP_HELD  2
    #define PMF_BACKWARDS_JUMP 8  // go into backwards land
    #define PMF_BACKWARDS_RUN 16  // coast down to backwards run
    #define PMF_TIME_LAND  32  // pm_time is time before rejump
    #define PMF_TIME_KNOCKBACK 64  // pm_time is an air-accelerate only time
    #define PMF_TIME_WATERJUMP 256  // pm_time is waterjump
    #define PMF_RESPAWNED  512  // clear after attack and jump buttons come up
    #define PMF_USE_ITEM_HELD 1024
    #define PMF_GRAPPLE_PULL 2048 // pull towards grapple location
    #define PMF_FOLLOW   4096 // spectate following another player
    #define PMF_SCOREBOARD  8192 // spectate as a scoreboard
    #define PMF_INVULEXPAND  16384 // invulnerability sphere set to full size
    #define PMF_ALL_TIMES (PMF_TIME_WATERJUMP|PMF_TIME_LAND|PMF_TIME_KNOCKBACK)
     
    在ShotgunPattern 函数中加入一个变量 accuracyFactor  (在 hitClient 声明后面):
     qboolean hitClient = qfalse;
     int   accuracyFactor = 4;
     // derive the right and up vectors from the forward vector, because
     // the client won't have any other information
     VectorNormalize2( origin2, forward );
     PerpendicularVector( right, forward );
     CrossProduct( forward, right, up );
     oldScore = ent->client->ps.persistant[PERS_SCORE];
     if(ent->client->ps.pm_flags & PMF_DUCKED)  //是否蹲下
     {
      accuracyFactor = 1;
     }
     // generate the "random" spread pattern
     for ( i = 0 ; i < DEFAULT_SHOTGUN_COUNT ; i++ ) {
      r = Q_crandom( &seed ) * DEFAULT_SHOTGUN_SPREAD * accuracyFactor * 16;   //这里调节
      u = Q_crandom( &seed ) * DEFAULT_SHOTGUN_SPREAD * accuracyFactor * 16;
      VectorMA( origin, 8192 * 16, forward, end);
      VectorMA (end, r, right, end);
      VectorMA (end, u, up, end);
      if( ShotgunPellet( origin, end, ent ) && !hitClient ) {
       hitClient = qtrue;
       ent->client->accuracy_hits++;
      }
     }
     
    当蹲下是和原来一样,而站立的时候,霰弹枪的子弹将会更加发散。
    同时注意在 ShotgunPattern 函数前面的注释,// this should match CG_ShotgunPattern
    和 cg_weapons.c 中的 CG_ShotgunPattern 比较起来你会发现两个函数极为相似,除了 CG_ShotgunPattern 被声明为 static ,就是说此函数只能在,cg_weapons.c 文件中使用。
    ================
    CG_ShotgunPattern
    Perform the same traces the server did to locate the
    hit splashes
    ================
    */
    static void CG_ShotgunPattern( vec3_t origin, vec3_t origin2, int seed, int otherEntNum ) {
     int   i;
     float  r, u;
     vec3_t  end;
     vec3_t  forward, right, up;
     int   accuracyFactor = 4; //add mzz,调整霰弹枪精度
     // derive the right and up vectors from the forward vector, because
     // the client won't have any other information
     VectorNormalize2( origin2, forward );
     PerpendicularVector( right, forward );
     CrossProduct( forward, right, up );
     if((otherEntNum == cg.snap->ps.clientNum) && (cg.snap->ps.pm_flags & PMF_DUCKED))  //加入的蹲下的判断
     {
      accuracyFactor = 1;
     }
     // generate the "random" spread pattern
     for ( i = 0 ; i < DEFAULT_SHOTGUN_COUNT ; i++ ) {
      r = Q_crandom( &seed ) * DEFAULT_SHOTGUN_SPREAD * accuracyFactor * 16;   //调整散射范围
      u = Q_crandom( &seed ) * DEFAULT_SHOTGUN_SPREAD * accuracyFactor * 16;
      VectorMA( origin, 8192 * 16, forward, end);
      VectorMA (end, r, right, end);
      VectorMA (end, u, up, end);
      CG_ShotgunPellet( origin, end, otherEntNum );
     }
    }
    Q_crandom( &seed ) 取圆内随机数。
    两个函数之所以这样主要为了解决网络带宽问题。这个在后面在做详细的探讨
     
    同步客户端:
    尽管在CG_ShotgunPattern 函数中不能使用 gentity_t。但在客户端当你有 一个整形变量如otherEntNum,在客户端有个变量cg, cg 是一个十分重要的变量,因为他带给你最重要的人物: 玩家
    cg.snap->ps.clientNum 代表当前客户端的 number, 对于客户端主要关心一个实体:屏幕前的玩家。cg 拥有服务端一部分属性,如玩家是否蹲下。cg.snap->ps.pm_flags
     
    对于移动的惩罚: 当前移动状态存在于 ps.velocity[] 中,这是一个 vec3_t 数据类型。velocity[0] 代表前后移动,velocity[1] 代表左右移动,velocity[2] 代表上下移动。
     
    在 服务端 shotgunpattern 中加入判断
    else if (ent->client->ps.velocity[0] || ent->client->ps.velocity[1])
      accuracyFactor = 3;
    else if (ent->client->ps.velocity[2])
      accuracyFactor = 4;
     
    在客户端为:
      if(otherEntNum == cg.snap->ps.clientNum)
      {
        if(cg.snap->ps.pm_flags & PMF_DUCKED)
           accuracyFactor = 1;
        else if (cg.snap->ps.velocity[0] || cg.snap->ps.velocity[1])
           accuracyFactor = 3
        else if(cg.snap->ps.velocity[2])
           accuracyFactor = 4;
      }
     
    一些关于榴弹的参数:
     在 fire_grenade 中 blot->s.eFlags = EF_BOUNCE_HALF; 实体的一种标志,可以让榴弹在关卡表面上弹跳而不是爆炸
     blot->s.pos.trType 为 TR_GRAVITY 表示弹道受道重力影响,火箭为TR_LINEAR 即走直线
     s.eType 是 ET_MISSILE 当遇到可以破坏的目标时, 函数 G_MissileImpact 调用。
     游戏当前时间 (level.time)
    June 05

    让火箭自动导航

    注意:前提知道如何调用自己编译的dll,而不是使用quake的qvm
    // client data that stays across multiple respawns, but is cleared
    // on each level change or team change at ClientBegin()
    // 客户端 clientPersistant_t数据会随关卡或者团队改变而改变。
    typedef struct {
     clientConnected_t connected; 
     usercmd_t cmd;    // we would lose angles if not persistant
     qboolean localClient;  // true if "ip" info key is "localhost"
     qboolean initialSpawn;  // the first spawn should be at a cool location
     qboolean predictItemPickup; // based on cg_predictItems userinfo
     qboolean pmoveFixed;   //
     char  netname[MAX_NETNAME];
     int   maxHealth;   // for handicapping
     int   enterTime;   // level.time the client entered the game
     playerTeamState_t teamState; // status in teamplay games
     int   voteCount;   // to prevent people from constantly calling votes
     int   teamVoteCount;  // to prevent people from constantly calling votes
     qboolean teamInfo;   // send team overlay updates?
    } clientPersistant_t;
    在第14行加入 qboolean homing_status 。然后变成下面这样
     .....
     qboolean homing_status;  //用于切换自动导航和正常状态
     qboolean teamInfo;   // send team overlay updates?
    } clientPersistant_t;
     
    然后创建一个控制台命令来设置这个变量。打开 g_cmds.c 文件1598行,你将会看到
    void ClientCommand( int clientNum ) {
     gentity_t *ent;
     char cmd[MAX_TOKEN_CHARS];
     
    在函数的最后你将看到:
     else if (Q_stricmp (cmd, "stats") == 0)
      Cmd_Stats_f( ent );
     else
      trap_SendServerCommand( clientNum, va("print \"unknown cmd %s\n\"", cmd ) );
    }
    在  Cmd_Stats_f( ent ); 后面我们在加入1行
    else if(Q_stricmp(cmd,"homing") == 0)
      Cmd_Homing_f( ent );
     else
      trap_SendServerCommand( clientNum, va("print \"unknown cmd %s\n\"", cmd ) );
    }
    之后加入Cmd_Homing_f(gentity_t* ent) 处理函数
    void Cmd_Homing_f(gentity_t* ent){
     if(ent->client->pers.homing_status == 1){
      trap_SendServerCommand(ent-g_entities,va("print \Homing Missile are off.\n\""));
      ent->client->pers.homing_status = 0;
     }
     else{
      trap_SendServerCommand(ent-g_entities,va("print \Homing Missile are on.\n\""));
      ent->client->pers.homing_status = 1;
     }
    }
     
    下面开始创建火箭的自动导航:
    火箭查找一点范围内的目标。如果找到目标,将修改它的方向,朝向目标。在 g_utils.c 中加入如下代码用于寻找目标
    gentity_t* findradius(gentity_t* from,vec3_t org,float rad){
     vec3_t eorg;
     int j;
     if(!from)
      from = g_entities;
     else
      from++;
     for(;from <&g_entities[level.num_entities];from++){  //level.num_entities关卡中实体数目,用MAX_CLIENTS 更好一下。
      if(!from->inuse)
       continue;
      for(j=0;j<3;j++)
       eorg[j] = org[j]- (from->r.currentOrigin[j]);//+(from->r.mins[j]+from->r.maxs[j])*0.5);
      if(VectorLength(eorg) > rad)  //检测实体之间的距离
       continue;
      return from;
     }
     return NULL;
    }
    接着加入函数:
    /*
      检查两个实体之间是否可见
    */
    qboolean visible(gentity_t* ent1,gentity_t* ent2){
     trace_t trace;
     //ent1 到 ent2 之间发射一条线检测是否与其他物体碰撞
     trap_Trace(&trace,ent1->s.pos.trBase,NULL,NULL,ent2->s.pos.trBase,ent1->s.number,MASK_SHOT);
     if(trace.contents & CONTENTS_SOLID){ //轨迹中与固体发生碰撞
      return qfalse;
     }
     return qtrue;
    }
    这个函数从1个实体像另一个发射一条线,看是否可见。如果轨迹经过了墙。返回false,否则返回 true
    接着你需要在 g_local.h 中放入 visible 和 findradius 两个函数的声明
    gentity_t* findradius(gentity_t* from,vec3_t org,float rad); 
    qboolean visible(gentity_t* ent1,gentity_t* ent2);   
    当这些完成之后打开 g_missile.c 文件 加入一个新的 think 函数
    void G_HomingMissile( gentity_t *ent ) {
     gentity_t* target = NULL;
     gentity_t* rad = NULL;
     vec3_t dir,dir2,raddir,start;
     while((rad = findradius(rad,ent->r.currentOrigin,600.0f)) != NULL){  //如果在600个单位范围是否有物体
      if(!rad->client)
       continue;        //如果目标不是一个玩家,继续
      if(rad == ent->parent)
       continue;      //是否是开枪的人,不要把自己炸了
      if(rad->health <=0 )
       continue;     //目标是否死亡,不去炸尸体
      if(rad->client->sess.sessionTeam == TEAM_SPECTATOR)  //是否为观众
       continue;
      if((g_gametype.integer == GT_TEAM || g_gametype.integer == GT_CTF)&&
       rad->client->sess.sessionTeam == rad->parent->client->sess.sessionTeam)  //是否为同一队伍玩家
       continue;
      if(!visible(ent,rad))   //目标是否可见
       continue;
      VectorSubtract(rad->r.currentOrigin,ent->r.currentOrigin,raddir);
      raddir[2] += 16;
      if(target == NULL || (VectorLength(raddir)<VectorLength(dir))){ //感觉第二个条件判断不该存在。
       target = rad;
       VectorCopy(raddir,dir);
      }
     }
     if(target != NULL)
     {
      VectorCopy(ent->r.currentOrigin,start);
      VectorCopy(ent->r.currentAngles,dir2);
      VectorNormalize(dir);         //归一化dir矢量
      //VectorScale(dir,0.2,dir);  //注掉更好一点,不至于来不及计算飞过头。即使飞过去也来得及回来
      //VectorAdd(dir,dir2,dir);   //原来作用是逐步转向,即使要这个,也不需要上面的 0.2 系数。
      //VectorNormalize(dir);
      VectorCopy(start,ent->s.pos.trBase);       //ent.s.pos 负责移动物体
      VectorScale(dir,600,ent->s.pos.trDelta);   //在指向目标的矢量上移动600个单位 ent->s.pos.trDelta = dir * 600
      //如果用 VectorCopy(raddir,ent->s.pos.trDelta) 将会发现有趣的现象,火箭一直跟着人跑,人不停,就追不上,呵呵
      SnapVector(ent->s.pos.trDelta);             //修改矢量浮点数成员x,y,z 为 int
      //VectorCopy(start,ent->r.currentOrigin);   //
      VectorCopy(dir,ent->r.currentAngles);     //改变方向
     }
     ent->nextthink = level.time + 100;
    }
     
    之后进入关卡可以在控制台输入\Homing 来调整是否使火箭自动导航
    June 04

    实体 - ENTITIES

     
    ARTICLE 1 - ENTITIES
    by SumFuka

    This is the first in a series of 'articles' explaining various things about the quake3 game world. Every wondered how you interact with the game world ? This is the first question we're going to tackle... by working from the ground up. Quake's design hasn't changed much from quake1 thru to quake3... the most basic thing in the world is - yes, an entity !

    AN ENTITY ?

    Virtually anything you can name in the game world is an entity. A rocket ? That's a simple example of an entity. An ammo pack ? An entity. A player ? Again, that's an entity (albeit a special one). Let's take an example... urm... ummm... let's fire a rocket ! Here's how it works.
     
    事实上任何游戏世界中你可以叫出名字的都是实体。火箭筒? 就是一个简单的实体的例子。一个弹药夹?是实体,一个玩家也是实体。让我们举个例子。。。如用火箭筒开火。下面是其工作过程。
    1. You press the fire button    你开枪射击
    2. An empty entity slot is chosen (i.e. a slot that is not inuse)  一个空的实体槽被选择。
    3. A rocket entity is created in that slot    在槽中创建一个火箭筒实体
    4. The rocket settings are defined (positioned just in front of you, aimed in a certain direction, moving at 900 units/second, etc)    设置火箭筒(位于你前面,朝向一个方向,900单位/秒移动速度等等)
    5. The rocket moves through the world until an event is triggered : 
      • If the rocket hits something damageable (e.g. a player or a wall) then it explodes and the entity is removed
      • If the rocket doesn't hit anything within 10 seconds, it explodes and the entity is removed
      • If the rocket hits the sky then the entity is removed (no explosion).
      • 如果火箭筒击中可破坏的东西(如玩家或者墙壁),他会爆炸,实体被移除
      • 如果火箭筒在10秒内没有击中任何东西。他将爆炸移除实体
      • 如果火箭筒击中天空实体将被移除(不会爆炸)
    6. Once the entity is removed, the slot is marked not inuse and may be re-used

        一旦一个实体被移除,槽将被标为未使用。将等待再次被使用

    As you can see, a rocket's life is relatively short ! You might be thinking, is there a limit to the number of rockets that can simultaneously be flying around the map ? Well, yes.
    在地图上同时出现的火箭筒是否有限制? 是的

    HOW MANY ENTITIES EXIST IN THE QUAKE WORLD ?
    在 quake 世界中能存在多少实体?

    Time to do some sleuth work. By the way, when we refer to the quake 'world', we mean the game world and everything in it (not 'quakeworld'). What's in the quake world ? Lots of things... like a map, like the players, and like... ENTITIES ! Jump into MSVC and do a "Find in Files" on 'g_entities'. In g_main.c at line 17 we can find :

    quake 世界存在很多东西,如地图,玩家,还有实体。在msvc 中查找'g_entities'.在 g_main.c 中你会发现:
     gentity_t		g_entities[MAX_GENTITIES];
    This line says that there exists a finite array of entities in the game world. This array is called 'g_entities' and is MAX_GENTITIES long. So what is the constant MAX_GENTITIES ?? Do a "Find in Files" on MAX_GENTITIES and we find q_shared.h line 718 (and 717) to be quite interesting :
     #define	GENTITYNUM_BITS		10		// don't need to send any more
     #define	MAX_GENTITIES		(1 << GENTITYNUM_BITS)
    
    Ok, Carmack is exhibiting some guru-level C syntax here. Take my word that (x << y) means to double x y times. Given that ENTITYNUM_BITS is 10, MAX_GENTITIES is therefore 2 to the power of 10, or 1024. In other words, there is room in the world for approximately 1024 rockets, players, weapons, armors etc at any one time.
    这个有限的数组定义了游戏世界的实体数量。2的10次方。或者1024。就是同时的火箭筒,玩家,武器等等不能超过1024个

    CAN THE ENTITIES RUN OUT ?

    What would happen if you sat at one end of a very long space map with the RL and held down the fire button ? Assuming that your rockets fly for the full ten seconds, you can have about 10 rockets in the air at once. (Remember that when a rocket explodes the entity can be re-used by the next rocket virtually right away). If you start a 32 player game with your mates and you all sit and fire into space, there would be about 320 rockets flying through the air at any one time. We still haven't run out of entities...

    There is a certain number of entities that are permanently used during the whole game (for example, players, weapons and items). All other non-permanent entities follow the cycle create - live a short life - reuse. This is something to think about when you're coding mods - If you make a cluster grenade that splits into 100 mini grenades, then one idiot could quickly run your world out of entities by firing a bunch of cluster grenades in quick succession.
    除了一定数量的实体在整个游戏是永远存在的(例如,玩家,武器物品等等)。其他临时的实体都是在创建-短暂生存-重用之间循环。这是你在编写mod代码时需要注意的。如果你制作一种手榴弹,能爆炸能100个更小的手榴弹。当你开火时,将很快超过游戏世界的实体数量

    What happens if your world runs out of entities ? Assume the worst-case scenario, that your server will crash. If an entity is going to exist for a relatively long time, make sure that it isn't possible for huge numbers of them to exist at the same time.
    当实体数量溢出将会发生什么?你的服务程序将会crash.如果一个实体存在时间较长。确定在同一时刻不会太多存在

    WHAT'S IN AN ENTITY ?

    Let's look at g_local.h, starting at line 49 :
    struct gentity_s {
    	entityState_t	s;	// communicated by server to clients
    	entityShared_t	r;	// shared by both the server system and game
    
    	// DO NOT MODIFY ANYTHING ABOVE THIS, THE SERVER
    	// EXPECTS THE FIELDS IN THAT ORDER!
    	//================================
    
    	struct gclient_s	*client;			// NULL if not a client
    
    	qboolean	inuse;
    
    	char		*classname;		// set in QuakeEd
    	int		spawnflags;		// set in QuakeEd
    
    	qboolean	neverFree;		// if true, FreeEntity will only unlink
    						// bodyque uses this
    
    	int		flags;			// FL_* variables
    
    	char		*model;
    	char		*model2;
    	int		freetime;		// level.time when the object was freed
    	
    	int		eventTime;	// events will be cleared
    	// EVENT_VALID_MSEC after set
    	qboolean	freeAfterEvent;
    	qboolean	unlinkAfterEvent;
    
    	qboolean	physicsObject;	// if true, it can be pushed by movers and fall
    					// off edges all game items are physicsObjects, 
    	float		physicsBounce;	// 1.0 = continuous bounce, 0.0 = no bounce
    	int		clipmask;	// brushes with this content value will be collided
    					// against when moving.  items and corpses
    					// do not collide against players, for instance
    
    	// movers
    	moverState_t moverState;
    	int			soundPos1;
    	int			sound1to2;
    	int			sound2to1;
    	int			soundPos2;
    	int			soundLoop;
    	gentity_t	*parent;
    	gentity_t	*nextTrain;
    	gentity_t	*prevTrain;
    	vec3_t		pos1, pos2;
    
    	char		*message;
    
    	int		timestamp;	// body queue sinking, etc
    
    	float		angle;		// set in editor, -1 = up, -2 = down
    	char		*target;
    	char		*targetname;
    	char		*team;
    	gentity_t	*target_ent;
    
    	float		speed;
    	vec3_t		movedir;
    
    	int		nextthink;
    	void		(*think)(gentity_t *self);
    	void		(*reached)(gentity_t *self);	// movers call this when
    						// hitting endpoint
    	void		(*blocked)(gentity_t *self, gentity_t *other);
    	void		(*touch)(gentity_t *self, gentity_t *other, trace_t *trace);
    	void		(*use)(gentity_t *self, gentity_t *other, gentity_t *activator);
    	void		(*pain)(gentity_t *self, gentity_t *attacker, int damage);
    	void		(*die)(gentity_t *self, gentity_t *inflictor, gentity_t *attacker,
    			int damage, int mod);
    
    	int		pain_debounce_time;
    	int		fly_sound_debounce_time;	// wind tunnel
    	int		last_move_time;
    
    	int		health;
    
    	qboolean	takedamage;
    
    	int		damage;
    	int		splashDamage;	// quad will increase this w/o increasing radius
    	int		splashRadius;
    	int		methodOfDeath;
    	int		splashMethodOfDeath;
    
    	int		count;
    
    	gentity_t	*chain;
    	gentity_t	*enemy;
    	gentity_t	*activator;
    	gentity_t	*teamchain;	// next entity in team
    	gentity_t	*teammaster;	// master of the team
    
    	int		watertype;
    	int		waterlevel;
    
    	int		noise_index;
    
    	// timing variables
    	float		wait;
    	float		random;
    
    	gitem_t		*item;	// for bonus items
    
    	qboolean	botDelayBegin;
    };
    
    Right up the top there is some important stuff - an entityState_t and entityShared_t... these bits include general stuff
    like the location of the entity, the type of entity it is, the size of the bounding box, etc.

    开始2个比较重要,entityState_t 和 entityShared_t 包含了实体的位置,实体的类型。包围盒的大小等等。
    Next comes struct gclient_s *client; - this is a pointer to additional information, if the entity is a 'client' (i.e. player or bot). If the entity is not a client, then this bit is NULL (unused).
    接着是struct gclient_s* client,如果实体是客户(例如玩家或者机器人),则指向附加信息。如果实体非客户,则为NULL

    Further down we can see heaps of interesting fields - classname, speed, movedir, target, team etc. Not all of these fields are used with all entities... a red armor would not use the 'damage' fields, for example (wheras a rocket would). Most of these are pretty self-explanatory.

    下面可以看到更多信息,类名称,速度,移动方向,目标,队伍等信息,并不是所有实体都用到这些信息。。。如红甲就没有 damage 信息(而火箭就有)。所有这些都是自说明的

    "THINKING" ETC

    Lines 110-116 in g_local.h define function pointers. The names of these are think, reached, blocked, touch, use, pain, die. Although the syntax here is very hardcore (remember, Carmack is a codecutting God), it's quite easy to explain with an example.

    在g_local.h文件110-116中定义了一些函数指针:think,reached,blocked,touch,use,pain,die.这些函数在c里面模拟了虚函数效果

    We want our rockets to explode after 10 seconds. Remember, from g_missile.c :

    	bolt->nextthink = level.time + 10000;
    	bolt->think = G_ExplodeMissile;
    

    This means that after 10 seconds, the rocket 'thinks' and the function G_ExplodeMissile is called on the rocket entity.

    Similarly, a grenade explodes after 2.5 seconds. Can you find the code for this ? (Answer : g_missile.c line 294). 'Thinking' is a nice "fire and forget" mechanism - we create an entity, define what it does at some future time, and then forget about it - the game engine takes care of the entity from then on.

    这意味这经过10秒,火箭开始'思考',在该火箭实体上,函数 G_ExplodeMissile 被调用

    10 times a second, the server checks if each entity is due to 'think'. If yes, the 'think' function is run for that entity. Similarly, other entity functions are called in response to certain events. If a player is killed, then the player_die function is called (see g_client.c line 921). The same goes for touch, blocked, pain, etc.

    1秒10次,服务器检查每个实体是否 think,如果是,该实体think 函数被调用。如果玩家被杀死, player_die 函数被调用 (g_client.c)。同样还有touch,blocked,pain 等等

    PERMANENT ENTITIES & CLIENTS

    In q_shared.h we see that the maximum number of clients (players or bots) - MAX_CLIENTS - is 64. By definition, the first MAX_CLIENTS entities in g_entities are reserved for clients. Arrays in C are numbered from 0, so g_entities[0] is reserved for client 0, g_entities[1] for client 1... up to g_entities[63] for player 63.

    在q_share.h 中我们看到最大的客户端数量 MAX_CLIENTS 64,在g_entities中开始的64个实体为客户端保留。所以g_entities[0] 代表客户端0,g_entities[1] 代表客户端1。直到 g_entities 代表玩家 63

    Just as there exists an array of entities in the world, there also exists an array of 'client information' structures - see line 18 in g_main.c :
    尽管存在世界中存在实体的数组。在 g_main.c 中还有1个客户端信息的数组:

     gclient_t		g_clients[MAX_CLIENTS];
    

    Here we have an array of 64 gclient_t's (client information structures). And each of the first 64 g_entities point to
    a corresponding g_client[x]. For example, g_entities[0]->client points to g_clients[0], etc. We'll have a look at what's in the client information structure another time.

    头64个实体对应64个客户端信息。 g_entities[0]->client 指向 g_clients[0] 等等。
    Well, entities really do make the world go round (well, they actually go around the world, kinda... anyway...). Another time we'll talk about temporary entities (rail trails, blood spurts and similar effects). Till then, remember... "West Side."
    注:rail trails 和  blood 等也是实体(临时实体)

    May 27

    Hello qworld

      TUTORIAL 3 - HELLO, QWORLD !
    by SumFuka

    "Booyakasha !". Ok, now it's a pre-requisite that you're able to compile the qagamex86.dll - if you haven't managed that, then have a look at the previous tutorials.
    这里要求你已经编译出了 qagamex86.dll 。如果没有,看看前面的教程

    In this tutorial we're not actually going to print "Hello, qworld!" on the console (Boring!), we're going to modify the speed of rockets (as suggested in the id readme file). We're also going to learn a thing or two about rockets along the way. Now let's get into it.
    在这篇教程中不是在控制台打印 "hello,qworld"。我们准备修改火箭的速度.我们将学到一些关于火箭筒的东西。马上开始

    1. MAKE A COPY OF THE CODEBASE

    It's good to always keep a pristine copy of the original codebase. Imagine if you fuck up one of your source files (delete crucial lines, whatever), you'll need a backup right ? Rather than re-install Q3aGameSource.exe every time, let's keep quake3\source as our 'pristine' codebase. NEVER MAKE MODS in quake3\source !! We'll make mods in individual mod directories... let's start by creating quake3\mymod.

    一句话,修改之前做好备份。

    Ok then, we simply copy quake3\source to quake3\mymod. Double click on quake3\mymod\q3agame.dsw - from now on, follow all the tutorials using this codebase (I made a shortcut to this .dsw file on my desktop). If you modified the "Output file name" setting correctly in the first tutorial, the .dll for mymod should compile to the quake3\mymod directory - compile the 'game' project and check this.

    Whenever we've finished messing around with a tutorial and want to refresh the codebase back to the original, simply copy quake3\source to quake3\mymod. You can have as many mod directories as you want... I often have more than one mod in progress at any one time... quake3\rail, quake3\cts, etc... your hard drive's the limit!

    2. FIND SOMETHING INTERESTING

    Let's load up the quake3\mymod\q3agame.dsw project in MSVC. Maximize MSVC - you'll need all the real estate your desktop can give you. Make sure 'game' is the active project. Select "File View" on the left hand pane, and find the source file 'g_missile.c' in the tree. Double click on 'g_missile.c' - the source file should open up in the editor window.

    在game(服务器工程)工程中找到 g_missile.c文件。

    Go to line 362 (hit Ctrl+G for an easy shortcut) and find the fire_rocket function :

    到362行(我这里是644行 . quake3 1.3.2 b 源代码)

    /*
    =================
    fire_rocket blah 参数:实体(拥有此武器的人),开始位置,朝向
    =================
    */
    gentity_t *fire_rocket (gentity_t *self, vec3_t start, vec3_t dir)
     {
        gentity_t       *bolt;
    
        VectorNormalize (dir); //归一化朝向矢量
    
        bolt = G_Spawn(); //为实体分配内存
        bolt->classname = "rocket"; //设置实体为火箭筒
        bolt->nextthink = level.time + 15000; //下一次think时间
        bolt->think = G_ExplodeMissile; //指定 think 调用的函数
        bolt->s.eType = ET_MISSILE;  //指定实体类型为火箭
        bolt->r.svFlags = SVF_USE_CURRENT_ORIGIN; //link position 似乎没有用到 
        bolt->s.weapon = WP_ROCKET_LAUNCHER;  //武器类型,对于火箭筒为5号枪
        bolt->r.ownerNum = self->s.number; //拥有者number
        bolt->parent = self;  //拥有者实体
        bolt->damage = 100;   //武器伤害
        bolt->splashDamage = 100; //溅射伤害
        bolt->splashRadius = 120; //溅射范围
        bolt->methodOfDeath = MOD_ROCKET;
        bolt->splashMethodOfDeath = MOD_ROCKET_SPLASH;
        bolt->clipmask = MASK_SHOT;
    
        bolt->s.pos.trType = TR_LINEAR;
        bolt->s.pos.trTime = level.time - MISSILE_PRESTEP_TIME;   // move a bit
    on the very first frame
        VectorCopy( start, bolt->s.pos.trBase );
        VectorScale( dir, 900, bolt->s.pos.trDelta ); //方向,移动速度
        SnapVector( bolt->s.pos.trDelta );           // save net bandwidth
        VectorCopy (start, bolt->r.currentOrigin);
    
        return bolt;
    }
    
    If you like, go and have a read thru our first article on quake entities...

    Back already ? Great ! Line 372 is creates a new entity (called bolt). The G_Spawn() function creates a 'blank' entity... then next job is to flesh out all the details (what sort of entity is it ? what are the characteristics ? etc). The next 20 or so lines of code define all this stuff.
    行372 创建了1个新的实体entity(变量名 bolt)。G_Spawn() 函数创建一个"空白"实体entity...,剩下的工作就是填充细节。

    Line 373-375 define the bolt to be a "rocket", and it will 'think' again in 10 seconds (time is measured in 1000'ths of a second in the quake world, thus 10000 equates to 10 second). When the rocket 'thinks' it will call the function G_ExplodeMissile. In other words, if it hasn't touched anything already, our rocket will explode after 10 seconds. This prevents our rockets flying off into outer space forever.
    行373-375定义 bolt 是一个 "rocket", 他将在10秒后"think",当火箭筒 "thinks" ,他将调用函数 G_ExplodeMissile. 换另一句话,在10秒后,他即使没有接触到任何东西,也将爆炸。

    Neat, we've discovered something about the game from looking thru the code! Let's see what else we can figure out about rockets...

    We can see that the rocket deals 100 damage (direct OR splash), and that the splash damage radius is 120 units. Line 391 tells us that the rocket moves at a speed of 900 units/second. There's also a whole load of constants used in this function (constants are usually in CAPS)... we can guess what most of them mean. 'ET_MISSILE' for example means 'Entitry Type: Missile' (as opposed to an item or a player).
    我们看到火箭筒会造成100伤害(直接伤害或者溅射伤害),溅射伤害辐射半径120个单位。391行告诉我们火箭筒速度900单位/秒。还有一些其他的变量。如 ET_MISSILE 意思是 实体类型:导弹

    3. OUR FIRST CODE CHANGE

    - Let's modify line 391 so that it looks like this :
        VectorScale( dir, 300, bolt->s.pos.trDelta );
    

    Hit F7 to compile our .dll. Fire up quake (Run "quake3\quake3.exe +set fs_game mymod +map q3dm1") and see if it worked - you rockets should be noticeably slower.

    让我们修改391行如下:按F7编译.dll 启动quake,记住设置启动参数 +set sv_pure 0(使用dll启动而不是qvm),你会发现火箭筒速度显著的变慢了

    Done! That's our first tutorial. Let's keep blazing onwards...

    May 18

    Quake3 控制台命令3

    "bot_nochat" - Basicaly, this command lets you turn off those automated taunts that the bots say constantly. I presume there will be a minor framerate increase but I am not sure. Once you tire of the taunts set this to 1.

    "cg_centertime" - This command lets you limit how long the "you fragged <playername>" message appears when you frag someone. The default setting is 3, but the recommended setting is 1. Setting this command to 0 means no message is displayed. This command works only is server side only.

    "cg_drawAttacker" - Displays the opponent's name when you face them. Useful for TDM or CTF, but a hinderence to your visibity. Optimal setting is disabled.

    "cg_drawRewards" - Displays rewards earned in the current battle (excellent, impressive etc...). Optimal setting is disabled.

    "cg_draw3dIcons" - When turned on, all icons in the HUD will be displayed in 3D. Optimal setting is disabled.

    "cg_drawGun" - This command let's you toggle between displaying, or not displaying the gun. Many people like to have a gun on screen at all times as it helps distinguish which weapon you currently have selected. Disabling gives the advantage of not having a gun blocking your view. Especialy helpful when using the railgun. Framerate is also noticably higher with this disabled.

    "cg_gibs" - When activated, characters will "gib" (blow into pieces) with a particulaly viscious shot. "com_blood" must be activated for this to take effect. This looks pretty, and can be satisfying but can slow down gameplay in large scale deathmatches. When turned off, FPS gain is around 1 - 5 FPS depending on the amount of action going on.

    "cg_marks" - With this enabled, every time a player shoots at the scenary, a mark is left behind. These marks will stay for approximataly 20 seconds. Because of this, noticable framerate loss occurs in large scale deathmatches. Optimal setting is disabled.

    "cg_brassTime" - With this enabled, when a gun is fired, the shells ejected are thrown and discarded in the air for added realism. Optimal setting is disabled.

    "cg_bobup / cg_bobroll / cg_bobpitch" - These 3 settings are used to create a more realistic walk or run for your character. For example, when you are slowly walking in a crouch position, you will shuffle side to side to give your character more realistic movement. The default for all settings is 0.0025 but I prefer to turn these settings to 0 as its gives a more fluid movement and prevents possible motion sickness ;-)

    "cg_fov" - This setting lets you widen or shrink your viewing area or field of vision. The default is 90 but feel free to increase this slightly for a sly advantage (I wouldn't put it over 110 though as the image looks trippy). Unfortunately, because of the larger viewing area, the CPU is under more stress so bear in mind you may get a slightly lower framerate.

    "cg_shadows" - There are 3 shadow modes - 1, 2, and 3. 1 creates round, unrealistic shadows under the feet of all characters. 2 creates incredibly lifelike shadows, but at a huge performance hit. 3 creates suitably lifelike shadows but again at the cost of some performance. For setting 2, you must ensure your graphics card supports hardware stencil buffing, and r_stencilbits must be set to 8 at the console. The optimal setting is 0 (no shadows)

    "cg_simpleItems" - With this on, all items and pickups will be displayed in 2D rather than 3D. This is especially helpful for people with slower machines as it can give noticable framerate increase.

    "com_blood" - Displays blood when a character is shot with this turned on. Additionaly, characters create a small gib when hit hard at the cost of no performance. Keep this setting on and turn "cg_gibs" off.

    "com_blindlyLoadDLLs" - If you use the Speed Dll's, you may get the warning message telling you that it is unsafe to use them. This message is quite anoying, as it pops up when you load and finish a level. Set this to 1 to disable the warning.

    "com_hunkmegs" - Only of use if you have more than 64 MB RAM. This setting alocates more system memory to Quake 3 for player models. If you have 128 MB RAM, set this to 96; if you have 96 MB RAM, set this to 64; if you have 192 MB RAM set this to 128; and finaly if you have 256 MB RAM, then set this to 170. You could try higher numbers but your system could become unstable.

    "r_picmip" - This accounts for overall texture and image quality, with 0 being the best, and higher numbers being progressively worse. This setting is a major player in having a high and consistant framerate. A setting of 1 is suitable for most computers as it ensures excellent image quality with a solid, consistant framerate. Interestingly, many people prefer to use a setting of 5 as it improves visibity between players and background textures, as well as makes weapons such as the LG easier to use.

    "r_drawsun" - This setting I believe creates shadows in relation to where thet are towards the sunlight. Of course, you will need shadows enabled. I do not think there is a drop in FPS so if you like shadows on, then set this to enabled.

    "r_gamma" - Brightens/Darkens the screen. This setting varys according to the brightness on your monitor. Default is 1 but this can be set lower to darken image (eg: 0.79010) or it can be increased to brighten the image (eg: 1.10000). Experiment to find the optimal amount.

    "r_mapOverBrightBits" - This is a setting which controls how bright the scenary, textures and objects are. Lately, I have found this is the best way to achieve optimal image quality. This setting defaults at 2 but I would recommend setting this to 3. Secondly, lower the r_gamma setting to 0.82000 and start a new game. You should either find it too bright or too dark - adjust the gamma accordingly. I have found that setting this setting to 3 results in far more clarity and detail in the textures.

    "r_intensity" - As the name suggests this setting intensifies the whole image. Default is 1 and this is recommended for most users. If you play in picmip 5 mode, set this to around 1.4 to make the characters stand out more against the background.

    "r_finish" - This is the "Sync every frame" command in the game options. It Improves response between the keyboard/mouse and the onscreen action. You set this to 1 to stop occasional input frustration. However, you may experience slight framerate loss.

    "r_railWidth / r_railCoreWidth / r_railSegmentLength" - These settings adjust the way the railgun blast looks. There are so many possible configurations but here is my personal favourite:

    seta r_railWidth "3"
    seta r_railCoreWidth "3"
    seta r_railSegmentLength "1024"

    Thanks to VyP3rR.

    "r_roundImagesDown" - Smoothes and rounds textures when they need to be resized producing slightly inferior visuals. Default is recommended. (Please note: q3dm16 will crash to the desktop if this setting is less than 1)

    "r_swapInterval" - Enabling this setting eliminates the slight screen ripping that appears when your framerate exceeds your monitors refresh rate. Bear in mind that although the FPS loss is not large, I found there to be a slight  lag between mouse/keyboard to the on screen action. Bear in mind that if you have disabled vsync externaly (perhaps through your graphics drivers tools facilty) then this setting is bypassed.

    "r_detailTextures" - This is enabled by default and produces more detailed textures if available by that particular texture. With this disabled, you get slight framerate increase.

    "r_colorbits" - Choose between rendering colours in 16 BIT or 32 BIT. 32 BIT colour renders 16.7 million individual colours compared to 16 BIT's 65,000 but can be a large burdon on computer resources. Optimal setting is 16 BIT for framerate and 32 BIT for visuals. Be aware that your video hardware must support 32 BIT colour for you to use it.

    "r_texturebits" - Similar to colourbits. However, if you run at high resolutions (1024x768 or above) this can cause texture corruption in 32 BIT colour mode. You must also have a card that supports 32 BIT colour. Optimal setting is 16 BIT for framerate and 32 BIT for visuals. Be aware that your video hardware must support 32 BIT colour for you to use it.

    "r_dynamicLight" - With this enabled, the flare from a weapon projectile will illuminate  the surrounding area creating added realism. Be aware that enabling this results in noticable framerate loss.

    "r_vertexLight" - When enabled, textures use no additional lightmaps for lighting effects. On a slow machine, this will speed things up considerably but the result is inferior visuals. Other benefits of enabling vertex lighting include better visibilty between players and textures, especialy when using r_picmip 5.

    "r_lodBias" - Produces more rounded images in the character model, objects, and pickups the lower this setting is. Through benchmarking, I have found that the default (0) is the best balance between framerate and image quality. I could see no noticable visual improvement when setting this into the low minuses (the valid range is -2 to 2) but the framerate was lower. Recommended setting is 0 (default)

    "r_smp" - If you have two CPU's, Windows NT or 2000, and have a graphics card AND  driver which supports SMP, then you can benefit from a more sustained Framerate, which may also be noticeably higher. The default of course is 0, but if your system fulfils the above requirements then ensure you set this to 1.

    "r_subDivisions" - This is a texture setting which when set low, produces a better image with more curves and less graphical inacuracies. The maximum setting I would recommend is around 100  depending on the map. I like this set at 4 but feel free to experiment for the best comprimise between image quality and framerate.

    "r_lodCurveError" - This setting determines how close you have to be towards a texture  before it clips and loses its curves. I recommend a setting between 400 - 800 depending on the power of your machine.

    "r_stencilBits" - This is a hardware dependent graphical setting which creates more realistic textures. Be sure to set this to 8 if your graphics card has a hardware stencil buffer. Be aware that the screen may darken with this enabled. Be sure to alter the gamma accordingly.

    "s_musicVolume" - Self explanatary. Bear in mind that turning off the music doesn't result in such a noticably higher framerate as in Quake 2, though the optimal setting is still disabled

    "s_loadas8bit" - With this set to 1, all the sounds in the game will be forced to be played with half the available sound memory. This increases framerate somewhat.

    "sv_pure" - Controls whether the game should be played in pure (as the developer intended) or unpure (which means that certain mods can be used).

    "vm_cgame / vm_game / vm_ui" - These settings MUST be set to 0 for the speed dll's to function correctly. If any of these are set to 1 in your config, then you are losing performance, so change them immediately.

    1.25+ new console commands:

    "cg_scorePlums" - This controls whether the "scoreplum" floats above your victim when they are fragged. Not really a necessity so set this to 0.

    "cg_smoothClients" - When g_smoothClients is enabled on the server and you enable cg_smoothClients then players in your view will be predicted and will appear more smooth even if they are on a bad network connection (LPB's should love this feature when playing laggy HPB's). However small prediction errors might appear.

    "pmove_fixed" - Think of this as ID's answer to the 125Hz mod. Basicaly, with this enabled, all players will move at the same frequency (which can be changed using the pmove_msec variable) regardless of the clients framerate. The advantages include even jump physics and movement for all players. The downside is some people have found slight stuttering with this enabled (although through my experience, it is negible). If you are playing online, the server must have first enabled this option before you can use it.

    "pmove_msec" - Sets the time in milliseconds between two advances of the player physics. Default is 8.

    "r_inGameVideo" - This feature lets you view small pre-recorded videos that the map maker created to be viewed in game. This has only been implemented in Team Arena maps as I write this, but no doubt standard Q3A levels will be including such features imminently. Be aware that enabling this can have a large impact on framerate, so te optimal setting is to disable.

    "s_doppler" - A neat sound feature, which produces a "dopplar" effect when a projectile from a rocket sweaps past you. Disabling gives a minor framerate increase, but I like the effect and thus keep it enabled.

    "headmodel" - changes only the head of the model to another model. Example: If you are playing as the Grunt model, /headmodel "sarge" will stick Sarge's head on Grunt's body. Selecting a new model will load both the model and its matching head.

    "team_model" - changes to a model that will only be used during team game play.

    "team_headmodel" - changes head model to a head that will only be used during team game play.

    Internet connection commands:

    "cg_lagometer" - This is a very useful utility which lets you monitor your connection on-line. With this enabled while you are playing on-line you will see 2 bouncing lines. The first line displays the conjunction between your graphics card updating the frames in sync with the gameworld updates recieved from the server. Idealy, this should be a straight blue line. If it has bouncing yellow spikes then your display will stutter and be more difficult to view. To combat this, first ensure you have followed my tweaking techniques and then change your snaps setting. Usually, this means lowering it by until your screen is stable and you have a nice flowing blue line in your lagometer.

    The second line shows if packets are being recieved from the server. This should be green. If it is yellow or red, try increasing your rate or try lowering your snaps. If this does not help, you may be on a bad server so try another. The height of the line is dependent on your current ping.

    "cl_timenudge" - This interesting setting is identical to the pushlatency setting in Half-Life. This is very user determined and impossible to judge for every machine and every connection. I find this setting works well if you set the cl_timenudge setting to around -30 the ping you currently have with the server. If you don't like the way it affects your timing, then leave it at default (0). Use this command in conjunction with the lagometer for best results.

    "rate" - This setting controls packets to ensure a good connection. If you have an ISDN modem (128K) then this can be set to around 8000. If you have a 56K modem then this should be around 3000-4500 depending on your connection speed. If you are on a LAN or have ADSL modem, then this can be around 24000 or perhaps even higher. Experimentation is required to find the optimal setting.

    "snaps" - This is possibly the most important setting for getting a good connection. As everyone knows, in Quake 2, your gameworld updates depended on your current FPS so slower computers were at a disadvantage. Now, in Quake 3, your snaps setting determines how many updates you recieve from the server. 56K modems should have a setting of around 20. ISDN modems (128K) should be around 40 as should any other fast connection devices (LAN, T1 etc....). Remember to read my cg_lagometer section for tips on "snaps".

    "cl_packetdups" - As the name suggests, this setting is used to send multiple packets to compensate for lost packet drops. This setting should be set at 1 unless you have a VERY good connection in which case set this to 0. Use the lagometer to decide on which setting to use.

    "cl_maxPackets" - This setting puts a limit on the maximum amount of packets that can be sent to the server via the client. This setting is useful for people with slower modems. The default setting is 30 (comparable to a 56K modem), but lower this if you have a 33.6K modem or less, and higher this setting if you have an ISDN or higher modem.

    "com_maxFPS" - This command limits your maximum FPS. Why you would want to do this? 2 reasons. Firstly, because it will help stop the server from having lag confusion when your frame rate has a sudden rise or fall. Run a timedemo, collect your average FPS and use that as the limit for when you play on-line.

    Another important aspect of this setting is that your framerate determines how high you can jump. This is why getting the max_FPS setting right is so important. Have a play around until you find a figure that allows you to make the DM13 MH jump. Once you have one (try to get it as high as it can go) stick with it.

    Unfortunately, playing online could make achieving maximum height tricky once again. Personaly, I found that setting com_maxFPS to 83 offline and 63 online the best solution for making those long, tricky jumps. Of course, this may be totaly different for your machine so play around.

    "cg_deferPlayers" - A nice simple setting. With this set to 1, new player skins will only be loaded when you are either fragged or when you look at the scoreboard. With this set to 0, new player models are loaded as soon as a new player joins the server. I like this set to 1 as the screen could stutter at a potentialy crucial time meaning frustration.

    "cg_predictItems" - This setting determines whether the server or the client decides on whether a weapon has being collected. A setting of 1 means the client decides, and a setting of 0 means the server decides. Setting it to 1 (default)  makes gameplay flow quicker for HPB's, but can cause confusion as to whether the item was picked up or not. Setting it to 0 means the server will always decide, reducing the chance of errors, but this can cause slight ldelay after the item has been picked up. I keep this set at 0 to prevent any unneccessary confusion.

    "cg_forceModel" - If you want to use only the same model or skin throughout, then set this to 1. Every character (human, or bot) will have the same character model as yourself. However, if you are using a custom model with a large polycount, this can hinder performance slightly. Default is 0.

    May 17

    Quake3 控制台命令2

    messagemode (command)
    syntax: messagemode
    Returns the keyboard to text input for the purpose of sending messages to all players. Pressing 'ENTER' will send the message and return the keyboard to gaming functions.
     
    --------------------------------------------------------------------------------
    messagemode2 (command)
    syntax: messagemode2
    Returns the keyboard to text input for the purpose of sending messages to all players on the same team. Pressing 'ENTER' will send the message and return the keyboard to gaming functions.
    --------------------------------------------------------------------------------
    messagemode3 (command)
    syntax: messagemode3
    Returns the keyboard to text input for the purpose of sending messages to your current target only. Pressing 'ENTER' will send the message and return the keyboard to gaming functions.
    --------------------------------------------------------------------------------
    messagemode4 (command)
    syntax: messagemode4
    Returns the keyboard to text input for the purpose of sending messages to the last player to injure you only. Pressing 'ENTER' will send the message and return the keyboard to gaming functions.
    --------------------------------------------------------------------------------
    midiinfo (command)
    syntax: midiinfo
    Reports status of MIDI control and device(s) used.
    --------------------------------------------------------------------------------
    model (variable)(U A)
    syntax: model [model/skin] default: "visor/default"
    Sets the player model and skin.
    --------------------------------------------------------------------------------
    modelist (command)
    syntax: modelist
    Reports all available video modes.
    --------------------------------------------------------------------------------
    modellist (command)
    syntax: modellist
    Lists all model files loaded for the current map.
    --------------------------------------------------------------------------------
    music (command)
    syntax: music [musicfile]
    Presumably plays a music file of some type.
    --------------------------------------------------------------------------------
    name (variable)(U A)
    syntax: name [string] default: Player
    Sets the player name. Font color can be changed. Possible colors:
    0 = Black
    1 = Red
    2 = Green
    3 = Yellow
    4 = Blue
    5 = Cyan
    6 = Magenta
    7 = White

    --------------------------------------------------------------------------------
    net_ip (variable)(I)
    syntax: net_ip [IP_address] default: localhost
    Allows the binding of a set IP address which is sent to the ID master server.
    - Kevin Crawley
    --------------------------------------------------------------------------------
    net_noipx (variable)(I)
    syntax: net_noipx [0/1] default: 0
    Toggles IPX network protocol. This command should be passed on the command line. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    net_noudp (variable)(I)
    syntax: net_noudp [0/1] default: 0
    Toggles UDP/IP network protocol. This command should be passed on the command line. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    net_port (variable)(I)
    syntax: net_port [value] default: 27960
    Specifies network server port.
    --------------------------------------------------------------------------------
    net_socksenabled (variable)(I)
    syntax: net_socksenabled [0/1] default: 0
    Toggles proxy and/or firewall protocol. This command should be passed on the command line. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    net_sockspassword (variable)(I)
    syntax: net_sockspassword [string] default: ""
    Sets the password on the firewall machine. This command must be passed on the command line.
    --------------------------------------------------------------------------------
    net_socksport (variable)(I)
    syntax: net_socksport [value] default: 1080
    Specifies proxy and/or firewall port. This command should be passed on the command line.
    --------------------------------------------------------------------------------
    net_socksserver (variable)(I)
    syntax: net_socksserver [value] default: ""
    Specifies proxy and/or firewall server address. This command should be passed on the command line.
    --------------------------------------------------------------------------------
    net_socksusername (variable)(I)
    syntax: net_socksusername [string] default: ""
    Sets the username on the firewall machine. This command must be passed on the command line.
    --------------------------------------------------------------------------------
    nextdemo (variable)
    syntax: nextdemo [demo demoname] default: ""
    A string using the demo command and the filename of the next demo to load. No file extension is used. If no demo is specified by the server then no further demos will be run. Note that this cvar is unavailable until it has been set at the console or in a script file.
    --------------------------------------------------------------------------------
    nextframe (command)
    syntax: nextframe [?]
    Unknown. See also prevframe (also unknown).
    --------------------------------------------------------------------------------
    nextmap (variable)
    syntax: nextmap [mapname] default: ""
    A string using the map command and the filename of the next map to load. No file extension is used. If no map is specified by the server then the one specified by the currently running map will be used, if any.
    --------------------------------------------------------------------------------
    nextskin (command)
    syntax: nextskin [?]
    Unknown. See also prevskin (also unknown).
    --------------------------------------------------------------------------------
    noclip (command)
    syntax: noclip
    Enables noclipping mode so you can pass through world brushes. Entering the command again disables it.
    --------------------------------------------------------------------------------
    nohealth (variable)(S A)
    syntax: nohealth [0/1] default: 0
    Specifies if health pickups will be spawned on the map. Changes take place on the next map loaded. 0=spawn health;1=don't spawn health.
    --------------------------------------------------------------------------------
    notarget (command)
    syntax: notarget
    Enables notarget mode so presumably bots will ignore you if they haven't seen you already. Entering the command again disables it.
    --------------------------------------------------------------------------------
    password (variable)(U)
    syntax: password [string] default: ""
    The password required for clients to connect to the host machine. Both server and clients would need to set this.
    --------------------------------------------------------------------------------
    path (command)
    syntax: path
    Reports the current quake3.exe search path, including .PK3 files.
    --------------------------------------------------------------------------------
    paused (variable)
    syntax: paused [0/1} default: 0
    Sets whether the game is paused or not. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    ping (command)
    syntax: ping [server]
    Pings a selected server.
    --------------------------------------------------------------------------------
    play (command)
    syntax: play [path/.wav]
    Plays a .WAV file in the current game directory one time.
    --------------------------------------------------------------------------------
    prevframe (command)
    syntax: prevframe [?]
    Unknown. See also nextframe (also unknown).
    --------------------------------------------------------------------------------
    prevskin (command)
    syntax: prevskin [?]
    Unknown. See also nextskin (also unknown).
    --------------------------------------------------------------------------------
    protocol (variable)(S R)
    syntax: protocol [value] default: 39
    Sets network protocol version. Useful for backwards compatibility with servers with otherwise incompatible versions.
    --------------------------------------------------------------------------------
    qport (variable)(I)
    syntax: qport [value] default: ""
    Sets internal network protocol port.
    --------------------------------------------------------------------------------
    quit (command)
    syntax: quit
    Shuts down the game immediately.
    --------------------------------------------------------------------------------
    r_allowextensions (variable)(A L)
    syntax: r_allowextensions [0/1] default: 1
    Toggles the functions of various OpenGL extensions. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    r_allowsoftwaregl (variable)(L)
    syntax: r_allowsoftwaregl [0/1] default: 0
    Toggles the use of the default software OpenGL driver as supplied by the Operating System platform. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    r_ambientscale (variable)(C)
    syntax: r_ambientscale [value] default: 0.5
    Sets the level of ambient lighting effect on entities.
    - badak
    --------------------------------------------------------------------------------
    r_clear (variable)(C)
    syntax: r_clear [0/1] default: 0
    Toggles the clearing of unrefreshed images (clears hall of mirrors effect). 0=disables;1=enables.
    --------------------------------------------------------------------------------
    r_colorbits (variable)(A L)
    syntax: r_colorbits [0 to 32] default: 0
    Sets color bits-per-pixel. Mutually exclusive with r_depthbits.
    --------------------------------------------------------------------------------
    r_colormiplevels (variable)(L)
    syntax: r_colormiplevels [0/1] default: 0
    Toggles raw RGB mipmap (texture) lighting effect. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    r_customaspect (variable)(A L)
    syntax: r_customaspect [0/1] default: 1
    Toggles the use of a custom video mode. 0=disables;1=enables. See also r_customheight and r_customwidth.
    --------------------------------------------------------------------------------
    r_customheight (variable)(A L)
    syntax: r_customheight [number of pixels] default: 1024
    Defines the height of a custom resolution when r_mode is -1. Note that your hardware may not support what you select. See also r_customwidth.
    --------------------------------------------------------------------------------
    r_customwidth (variable)(A L)
    syntax: r_customwidth [number of pixels] default: 1600
    Defines the width of a custom resolution when r_mode is -1. Note that your hardware may not support what you select. See also r_customheight.
    --------------------------------------------------------------------------------
    r_debuglight (variable)(C)
    syntax: r_debuglight [0/1] default: 0
    Toggles the display of data representing the intensity of ambient light and intensity of direct light. 0=disables;1=enables.
    - dynamite
    --------------------------------------------------------------------------------
    r_debugsurface (variable)(C)
    syntax: r_debugsurface [0/1] default: 0
    Toggles the curved surfaces debugging grid on whatever curve the weapon crosshair is aimed at. Grid size determined by cm_debugsize. Grid display is also dependent on the setting r_subdivisions. 0=disables;1=enables.
    - dynamite
    --------------------------------------------------------------------------------
    r_depthbits (variable)(A L)
    syntax: r_depthbits [0 to 32] default: 0
    Sets depth bits-per-pixel. Mutually exclusive with r_colorbits.
    --------------------------------------------------------------------------------
    r_detailtextures (variable)(A L)
    syntax: r_detailtextures [?] default: 1
    Unknown.
    --------------------------------------------------------------------------------
    r_directedscale (variable)(C)
    syntax: r_directedscale [?] default: 1
    Sets the level of direct lighting effect on entities.
    - badak
    --------------------------------------------------------------------------------
    r_displayrefresh (variable)(L)
    syntax: r_displayrefresh [value] default: 0
    Sets monitor refresh rate at the resolution the game is to be run at. This command should be passed on the command line. Note this will change your desktop refresh rate at this resolution as well.
    --------------------------------------------------------------------------------
    r_dlightbacks (variable)(A)
    syntax: r_dlightbacks [?] default: 1
    Unknown.
    --------------------------------------------------------------------------------
    r_drawbuffer (variable)
    syntax: r_drawbuffer [buffer] default: "GL BACK"
    Sets which buffer is drawn to.
    - Andy Lutomirski
    --------------------------------------------------------------------------------
    r_drawentities (variable)(C)
    syntax: r_drawentities [0/1] default: 1
    Toggles rendering of entities, including brush models. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    r_drawsun (variable)(A)
    syntax: r_drawsun [0/1] default: 0
    Toggles the drawing of the sun and accompanying glare in the sky when r_fastsky is 0. 0=disables;1=enables.
    - Ryan
    --------------------------------------------------------------------------------
    r_drawworld (variable)(C)
    syntax: r_drawworld [0/1] default: 1
    Toggles rendering of world brushes (map architecture). Entities will still be drawn. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    r_dynamiclight (variable)(A)
    syntax: r_dynamiclight [0/1] default: 1
    Toggles dynamic lighting. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    r_ext_compiled_vertex_array (variable)(A L)
    syntax: r_ext_compiled_vertex_array [0/1] default: 1
    Toggles hardware compiled vertex array rendering method if available. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    r_ext_compress_textures (variable)(A L)
    syntax: r_ext_compress_textures [0/1] default: 1
    Toggles hardware texture compression if available. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    r_ext_gamma_control (variable)(A L)
    syntax: r_ext_gamma_control [0/1] default: 1
    Toggles hardware gamma adjustments if available. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    r_ext_multitexture (variable)(A L)
    syntax: r_ext_multitexture [0/1] default: 1
    Toggles hardware mutitexturing if available. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    r_ext_texenv_add (variable)(A L)
    syntax: r_ext_texenv_add [?] default: 1
    Unknown.
    --------------------------------------------------------------------------------
    r_ext_texture_env_add (variable)(A L)
    syntax: r_ext_texture_env_add [?] default: 1
    Unknown.
    --------------------------------------------------------------------------------
    r_faceplanecull (variable)(A)
    syntax: r_faceplanecull [0/1] default: 1
    Toggles the culling of brush faces not in the direct view of the player. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    r_fastsky (variable)(A)
    syntax: r_fastsky [0/1] default: 0
    Toggles rendering of sky. Setting to 1 will also disable the view through portals. 0=enables;1=disables.
    --------------------------------------------------------------------------------
    r_finish (variable)(A)
    syntax: r_finish [0/1] default: 0
    Toggles syncing to frames. Enabling basically instructs hardware to inform game that GL calls have been completed. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    r_flarefade (variable)(C)
    syntax: r_flarefade [0 to ?] default: 7
    Sets scale of fading of flares in relation to distance when r_flares is 1.
    --------------------------------------------------------------------------------
    r_flares (variable)(A)
    syntax: r_flares [0/1] default: 0
    Toggles lighting flares effect (lights and weapon projectiles). 0=disables;1=enables.
    --------------------------------------------------------------------------------
    r_flaresize (variable)(C)
    syntax: r_flaresize [0 to ?] default: 40
    Adjusts the size of flares when r_flares is 1.
    --------------------------------------------------------------------------------
    r_fullbright (variable)(C L)
    syntax: r_fullbright [0/1] default: 0
    Toggles lightmaps when r_ext_multitexture is 0. Textures will be rendered at full brightness when enabled. See also r_lightmap. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    r_fullscreen (variable)(A L)
    syntax: r_fullscreen [0/1] default: 1
    Toggles fullscreen rendering. When set to 0, windowed rendering is attempted. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    r_gamma (variable)(A)
    syntax: r_gamma [value] default: 1
    Sets in-game gamma levels.
    --------------------------------------------------------------------------------
    r_gldriver (variable)(A L)
    syntax: r_gldriver [video driver] default: opengl32
    Specifies OpenGL driver used.
    --------------------------------------------------------------------------------
    r_ignore (variable)(C)
    syntax: r_ignore [?] default: 0
    Unknown.
    --------------------------------------------------------------------------------
    r_ignoreglerrors (variable)(A)
    syntax: r_ignoreglerrors [0/1] default: 1
    Toggles option to ignore OpenGL errors and to attempt to continue rendering. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    r_ignorefastpath (variable)(L)
    syntax: r_ignorefastpath [?] default: 0
    Unknown.
    --------------------------------------------------------------------------------
    r_ignorehwgamma (variable)(A L)
    syntax: r_ignorehwgamma [0/1] default: 0
    Toggles option to ignore external (not in-game) hardware gamma level setting made within Windows9x's Display Properties. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    r_ignoreoffset (variable)(A C)
    syntax: r_ignoreoffset [?] default: 0
    Unknown.
    --------------------------------------------------------------------------------
    r_intensity (variable)(L)
    syntax: r_intensity [0 to 5] default: 1
    Adjusts the overall strength of colors, with emphasis on the color White. Higher values result in higher apparent overall brightness. An alternative to adjusting gamma values, with the side effect of loss of texture details at too high a value.
    --------------------------------------------------------------------------------
    r_lastvalidrenderer (variable)(A)
    syntax: r_lastvalidrenderer [video component] default: ""
    Reports the video hardware that last successfully rendered the Test.
    --------------------------------------------------------------------------------
    r_lightmap (variable)(C)
    syntax: r_lightmap [0/1] default: 0
    Toggles rendering of lightmaps without rendering textures. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    r_lockpvs (variable)(C)
    syntax: r_lockpvs [0/1] default: 0
    Toggles the option of preventing the update of the PVS table as the player moves through the map. When set to 1 new areas entered will not be rendered. A mapper's tool. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    r_lodbias (variable)(A)
    syntax: r_lodbias [0 to ?] default: 0
    Sets Level-Of-Detail bias. An example would be the complexity of weapon rendering. 0=highest detail.
    --------------------------------------------------------------------------------
    r_lodcurveerror (variable)
    syntax: r_lodcurveerror [?] default: ?
    Sets rate that polygons are dropped from curved surfaces in relation to distance.
    --------------------------------------------------------------------------------
    r_lodscale (variable)(C)
    syntax: r_lodscale [0 to ?] default: 5
    Sets scale with which to adjust Level-Of-Detail.
    --------------------------------------------------------------------------------
    r_logfile (variable)(C)
    syntax: r_logfile [0/1] default: 0
    Toggles the writing of GL.LOG in the same directory as QUAKE3.EXE which records all OpenGL commands used in a game session. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    r_mapoverbrightbits (variable)(L)
    syntax: r_mapoverbrightbits [integer] default: 2
    Sets intensity of bounced light from textures (adjusts lighting saturation) when r_vertexlight is 0. Higher values=brighter lights reflected from textures.
    --------------------------------------------------------------------------------
    r_maskminidriver (variable)(L)
    syntax: r_maskminidriver [?] default: 0
    Unknown.
    --------------------------------------------------------------------------------
    r_measureoverdraw (variable)(C)
    syntax: r_measureoverdraw [?] default: 0
    Presumably implements sun's stenciling method of measuring overdraw.
    --------------------------------------------------------------------------------
    r_mode (variable)(A L)
    syntax: r_mode [integer] default: 3
    Sets a video mode. Valid resolutions:
    -1=Custom (see r_customaspect)
    0=320x240
    1=400x300
    2=512x384
    3=640x480
    4=800x600
    5=960x720
    6=1024x768
    7=1152x864
    8=1280x1024
    9=1600x1200
    10=2048x1536
    11=856x480
    --------------------------------------------------------------------------------
    r_nobind (variable)(C)
    syntax: r_nobind [?] default: 0
    Unknown.
    --------------------------------------------------------------------------------
    r_nocull (variable)(C)
    syntax: r_nocull [0/1] default: 0
    Toggles rendering of items/objects normally not seen from player's point-of-view. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    r_nocurves (variable)(C)
    syntax: r_nocurves [0/1] default: 0
    Presumably enables/disables rendering of curves.
    --------------------------------------------------------------------------------
    r_noportals (variable)(C)
    syntax: r_noportals [0/1] default: 0
    Toggles player view through portals. 0=enables view;1=disables view.
    --------------------------------------------------------------------------------
    r_norefresh (variable)(C)
    syntax: r_norefresh [0/1] default: 0
    Toggles clearing of screen prior to re-rendering. 0=allow refresh;1=disable refresh.
    --------------------------------------------------------------------------------
    r_novis (variable)(C)
    syntax: r_novis [0/1] default: 0
    Toggles the option to ignore vis data when drawing the map. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    r_offsetfactor (variable)(C)
    syntax: r_offsetfactor [?] default: -1
    Unknown.
    --------------------------------------------------------------------------------
    r_offsetunits (variable)(C)
    syntax: r_offsetunits [?] default: -2
    Unknown.
    --------------------------------------------------------------------------------
    r_overbrightbits (variable)(A L)
    syntax: r_overbrightbits [?] default: 1
    Unknown.
    --------------------------------------------------------------------------------
    r_picmip (variable)(A L)
    syntax: r_picmip [0 to 8] default: 1
    Sets maximum texture size. 0=highest detail;8=unbelievably ugly.
    --------------------------------------------------------------------------------
    r_portalonly (variable)(C)
    syntax: r_portalonly [0/1] default: 0
    Toggles seeing what the game engine can see through a portal. When enabled, if the game engine can see a portal, nothing else will be drawn except for the area the portal can see. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    r_preloadtextures (variable)(A L)
    syntax: r_preloadtextures [?] default: 0
    Unknown. Presumably enables/disables the preloading of texture info.
    --------------------------------------------------------------------------------
    r_primitives (variable)
    syntax: r_primitives [value] default: 0
    Sets rendering method. Valid settings:
    -1=skips drawing
    0=uses glDrawelements if compiled vertex arrays are present, or strips of glArrayElement if not.
    1=forces strips
    2=forces drawElements
    --------------------------------------------------------------------------------
    r_railcorewidth (variable)(A)
    syntax: r_railcorewidth [value] default: 16
    Sets the inner trail width when the Railgun is fired.
    --------------------------------------------------------------------------------
    r_railsegmentlength (variable)(A)
    syntax: r_railsegmentlength [value] default: 64
    Sets the distance between the coils when the Railgun is fired.
    --------------------------------------------------------------------------------
    r_railwidth (variable)(A)
    syntax: r_railwidth [value] default: 128
    Sets the outer trail width when the Railgun is fired.
    --------------------------------------------------------------------------------
    r_roundimagesdown (variable)(A L)
    syntax: r_roundimagesdown [?] default: 1
    Unknown.
    --------------------------------------------------------------------------------
    r_showcluster (variable)(C)
    syntax: r_showcluster [0/1] default: 0
    Toggles display of clusters by number as the player enters them on the currently loaded map. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    r_showimages (variable)
    syntax: r_showimages [?] default: 0
    Unknown.
    --------------------------------------------------------------------------------
    r_shownormals (variable)(C)
    syntax: r_shownormals [0/1] default: 0
    Toggles the drawing of short lines indicating brush and entity polygon vertices. See also r_showtris. 0=disables;1=enables..
    --------------------------------------------------------------------------------
    r_showsky (variable)(C)
    syntax: r_showsky [0/1] default: 0
    Toggles the drawing of the sky in front of other brushes. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    r_showsmp (variable)(C)
    syntax: r_showsmp [?] default: 0
    Unknown.
    --------------------------------------------------------------------------------
    r_showtris (variable)(C)
    syntax: r_showtris [0/1] default: 0
    Toggles the drawing of polygon triangles. See also r_shownormals. 0=disables,1=enables.
    --------------------------------------------------------------------------------
    r_simplemipmaps (variable)(A L)
    syntax: r_simplemipmaps [?] default: 1
    Unknown.
    --------------------------------------------------------------------------------
    r_skipbackend (variable)(C)
    syntax: r_skipbackend [?] default: 0
    Unknown.
    --------------------------------------------------------------------------------
    r_smp (variable)
    syntax: r_smp [0/1] default: 0
    Toggles multiprocessor acceleration support. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    r_speeds (variable)(C)
    syntax: r_speeds [0/1] default: 0
    Toggles the display of map geometry data. 0=disables,1=enables.
    --------------------------------------------------------------------------------
    r_stencilbits (variable)(A L)
    syntax: r_stencilbits [0 to 16] default: 8
    Adjusts rendering of hardware's stencil buffer depth.
    --------------------------------------------------------------------------------
    r_stereo (variable)(A L)
    syntax: r_stereo [0/1] default: 0
    Toggles stereoscopic glasses feature. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    r_subdivisions (variable)(A L)
    syntax: r_subdivisions [1 to 999] default: 4
    Sets the maximum Level-Of-Detail. An example would be the complexity of curves. 1=highest detail.
    --------------------------------------------------------------------------------
    r_swapinterval (variable)(A)
    syntax: r_swapinterval [0/1] default: 0
    Toggles frame swapping. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    r_texturebits (variable)(A L)
    syntax: r_texturebits [0 to 32] default: 0
    Sets texture color depth.
    --------------------------------------------------------------------------------
    r_texturemode (variable)(A)
    syntax: r_texturemode [OpenGL extension] default: GL_LINEAR_MIPMAP_NEAREST
    Sets texture filtering mode. Possible extensions used:
    GL_NEAREST (nearest interpolation filtering)
    GL_NEAREST_MIPMAP (nearest interpolation filtering with mipmapping)
    GL_LINEAR (linear interpolation filtering)
    GL_LINEAR_MIPMAP_NEAREST (linear interpolation filtering with nearest (bilinear) mipmapping)
    GL_LINEAR_MIPMAP_LINEAR (linear interpolation filtering with linear (trilinear) mipmapping)
    --------------------------------------------------------------------------------
    r_verbose (variable)(C)
    syntax: r_verbose [?] default: 0
    Unknown.
    --------------------------------------------------------------------------------
    r_vertexlight (variable)(A L)
    syntax: r_vertexlight [0/1] default: 0
    Toggles vertex lighting. Enabling would mean disabling lightmapping. 0=disables; 1=enables. See also r_lightmap.
    --------------------------------------------------------------------------------
    r_znear (variable)(C)
    syntax: r_znear [distance in map units] default: 4
    Sets the point from the player view origin that the game will set the near z-clipping plane and begin drawing the world. If set to less than 1 none of the world will be drawn.
    --------------------------------------------------------------------------------
    rate (variable)(U A)
    syntax: rate [value] default: 3000
    Sets communication rate between client and server.
    --------------------------------------------------------------------------------
    rcon (command)
    syntax: rcon [password] [string]
    A remote command to a server. The string is the command to be executed.
    --------------------------------------------------------------------------------
    rcon_password (variable)
    syntax: rcon_password [string] default: ""
    A password used to grant remote access for a client using the rcon command.
    --------------------------------------------------------------------------------
    rconaddress (variable)
    syntax: rconaddress [IP address] default: ""
    The address the rcon command is sent to.
    --------------------------------------------------------------------------------
    rconpassword (variable)
    syntax: rconpassword [string] default: ""
    A password used to grant access for an admin using the rcon command on a dedicated server.
    --------------------------------------------------------------------------------
    record (command)
    syntax: record [demoname]
    Record a demo to the /demos/ directory. If the demoname parameter is not included, then a sequentially-numbered filename will be assigned.
    --------------------------------------------------------------------------------
    reset (command)
    syntax: reset [variable]
    Resets a variable to its default value.
    --------------------------------------------------------------------------------
    restart (command)
    syntax: restart
    Restarts the game on the current map.
    --------------------------------------------------------------------------------
    s_initsound (variable)
    syntax: s_initsound [0/1] default: 1
    Toggles using the sound system. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    s_khz (variable)(A)
    syntax: s_khz [value] default: 22
    Sets the sampling rate, and therefore the quality of game sounds. Valid values are 11, 22 and 44(?).
    --------------------------------------------------------------------------------
    s_loadas8bit (variable)(A)
    syntax: s_loadas8bit [0/1] default: 1
    Toggles loading sound files as 8-bit. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    s_mixahead (variable)(A)
    syntax: s_mixahead [value] default: 0.2
    Sets the time delay before mixing sound samples.
    --------------------------------------------------------------------------------
    s_mixprestep (variable)(A)
    syntax: s_mixprestep [?] default: 0.05
    Unknown.
    --------------------------------------------------------------------------------
    s_musicvolume (variable)(A)
    syntax: s_musicvolume [0 to 1] default: 1
    Presumably sets the music volume level.
    --------------------------------------------------------------------------------
    s_separation (variable)(A)
    syntax: s_separation [value] default: 0.5
    Sets the degree of stereo sound separation.
    --------------------------------------------------------------------------------
    s_show (variable)(C)
    syntax: s_show [0/1] default: 0
    Toggles display of paths and filenames of all sound files as they are called. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    s_testsound (variable)(C)
    syntax: s_testsound [0/1] default: 0
    Toggles the playing of a test tone, overriding all other sounds. 0=disables;1=enables..
    --------------------------------------------------------------------------------
    s_volume (variable)(A)
    syntax: s_volume [0 to 1] default: 0.7
    Sets the game sounds volume level.
    --------------------------------------------------------------------------------
    say (command)
    syntax: say [string]
    Used by the server. The text in the string is sent to all players as a message.
    --------------------------------------------------------------------------------
    say_team command
    syntax: say_team [string]
    The text in the string is sent to all players on the same team only, if the server settings allow.
    --------------------------------------------------------------------------------
    scr_conspeed (variable)
    syntax: scr_conspeed [value] default: 3
    Sets the console rise/fall and text scrolling speed.
    --------------------------------------------------------------------------------
    screenshot (command)
    syntax: screenshot [levelshot/silent]
    Writes the current view to a .TGA file and saves it in \screenshots\. The parameters are optional. If used, the results are:
    levelshot = a mini screenshot will be written to the \levelshots\ folder
    silent = the "wrote shotXXXX.tga" report will not be displayed on the screen.
    - dynamite
    --------------------------------------------------------------------------------
    sectorlist (command)
    syntax: sectorlist
    Lists sectors and number of entities in each on the currently loaded map.
    --------------------------------------------------------------------------------
    sensitivity (variable)(A)
    syntax: sensitivity [value] default: 5
    Sets overall sensitivity of a mouse or similar device.
    --------------------------------------------------------------------------------
    serverinfo (command)
    syntax: serverinfo
    Shows server cvars on the local machine, including user created variables set with the sets command. Report includes:
    gamedate
    gamename
    sv_privateclients
    mapname
    protocol
    version
    teamflags
    nohealth
    sv_maxclients
    timelimit
    fraglimit
    dmflags
    sv_hostname
    cheats
    --------------------------------------------------------------------------------
    serverrecord (command)
    syntax: serverrecord [?]
    Presumably records a demo on the host machine using all client perspectives.
    --------------------------------------------------------------------------------
    serverstop (command)
    syntax: serverstop
    Presumably stops recording a demo begun with the serverrecord command.
    --------------------------------------------------------------------------------
    session (variable)
    syntax: session [value] default: 0
    Unknown.
    --------------------------------------------------------------------------------
    session0 (variable)
    syntax: session0 [?] default: 0 0 1 0
    Unknown.
    --------------------------------------------------------------------------------
    set (command)
    syntax: set [variable] [string]
    Sets the value of a valid cvar or a user-created variable.
    --------------------------------------------------------------------------------
    seta (command)
    syntax: set [variable] [string]
    Sets the value of a valid cvar or a user-created variable. It will also archive the variable and its current setting in Q3CONFIG.CFG (not user-created ones though).
    --------------------------------------------------------------------------------
    setenv (command)
    syntax: setenv [variable] [string]
    Sets an environment variable from within the game.
    --------------------------------------------------------------------------------
    sets (command)
    syntax: set [variable] [string]
    Sets the value of a valid cvar or a user-created variable in the same manner as set, but this cvar will be reported when the serverinfo command is executed.
    --------------------------------------------------------------------------------
    setu (command)
    syntax: set [variable] [string]
    Sets the value of a valid cvar or a user-created variable in the same manner as set, but this cvar will be reported when the userinfo command is executed.
    --------------------------------------------------------------------------------
    shaderlist (command)
    syntax: shaderlist
    Lists all shader files loaded on the current map.
    --------------------------------------------------------------------------------
    showdrop (variable)
    syntax: showdrop [0/1] default: 0
    When enabled, reports dropped packets should they occur. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    showpackets (variable)
    syntax: showpackets [0/1] default: 0
    Toggles the running display of all packets sent and received. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    sizedown (command)
    syntax: sizedown
    Reduces the size of the play screen by reducing viewsize in 10 percent increments.
    --------------------------------------------------------------------------------
    sizeup (command)
    syntax: sizeup
    Increases the size of the play screen by increasing viewsize in 10 percent increments.
    --------------------------------------------------------------------------------
    skinlist (command)
    syntax: skinlist
    Lists all skin files that have been loaded on the current map.
    --------------------------------------------------------------------------------
    snaps (variable)(U A)
    syntax: snaps [integer] default: 20
    Sets number of snapshots (states of the game world) per second to receive from the server. Setting to 40 would mean receiving every snapshot, 20 would mean receiving every other snaphot. The value set should be a factor of 40 (i.e., 10, 20, 40)
    - LOKi
    --------------------------------------------------------------------------------
    snd_restart (command)
    syntax: snd_restart
    Reinitializes the sound system so new settings can take effect.
    --------------------------------------------------------------------------------
    soundinfo (command)
    syntax: soundinfo
    Reports status of the sound system.
    --------------------------------------------------------------------------------
    soundlist (command)
    syntax: soundlist
    Lists all sound files loaded for the current map.
    --------------------------------------------------------------------------------
    status (command)
    syntax: status
    Reports map loaded, and information on all connected players.
    --------------------------------------------------------------------------------
    stoprecord (command)
    syntax: stoprecord
    Stops recording a demo begun with the demo command.
    Replaces stopdemo.
    --------------------------------------------------------------------------------
    stopsound (command)
    syntax: stopsound
    Stops a currently playing sound.
    --------------------------------------------------------------------------------
    sv_allowdownload (variable)
    syntax: sv_allowdownload [0/1] default: 1
    Toggles whether to enable the downloading of files. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    sv_fps (variable)
    syntax: sv_fps [integer] default: 20
    Sets the number of times per second the server will send gamesatate updates to all clients. Optimum setting dependent on available bandwidth and number of clients.
    - dynamite
    --------------------------------------------------------------------------------
    sv_hostname (variable)(S A)
    syntax: sv_hostname [string] default: noname
    Sets the name of the host machine. Font color can be changed. Possible colors:
    0 = Black
    1 = Red
    2 = Green
    3 = Yellow
    4 = Blue
    5 = Cyan
    6 = Magenta
    7 = White

    --------------------------------------------------------------------------------
    sv_keywords (variable)(S)
    syntax: sv_keywords [?] default: ""
    Unknown.
    --------------------------------------------------------------------------------
    sv_killserver (variable)
    syntax: sv_killserver [0/1] default: 0
    When set to 1, kills the server (shuts down map or demo) without shutting down quake3.exe. Value then returns to 0.
    --------------------------------------------------------------------------------
    sv_mapchecksum (variable)(R)
    syntax: sv_mapchecksum [bytes] default: ""
    Reports the file size of the currently loaded map. Used to prevent cheating by ensuring all clients are not using hacked maps.
    -stone^mhs
    --------------------------------------------------------------------------------
    sv_master1 (variable)
    syntax: sv_master1 [string] default: master3.idsoftware.com
    Sets the name or IP address of a master server.
    --------------------------------------------------------------------------------
    sv_master2 (variable)(A)
    syntax: sv_master2 [string] default: ""
    Sets the name or IP address of a master server.
    --------------------------------------------------------------------------------
    sv_master3 (variable)(A)
    syntax: sv_master3 [string] default: ""
    Sets the name or IP address of a master server.
    --------------------------------------------------------------------------------
    sv_master4 (variable)(A)
    syntax: sv_master4 [string] default: ""
    Sets the name or IP address of a master server.
    --------------------------------------------------------------------------------
    sv_master5 (variable)(A)
    syntax: sv_master5 [string] default: ""
    Sets the name or IP address of a master server.
    --------------------------------------------------------------------------------
    sv_maxclients (variable)(S A L)
    syntax: sv_maxclients [integer] default: 8
    Sets the maximum number of clients hosted on the server.
    --------------------------------------------------------------------------------
    sv_pad (variable)
    syntax: sv_pad [?] default: 0
    Unknown.
    --------------------------------------------------------------------------------
    sv_privateclients (variable)(S)
    syntax: sv_privateclients [integer] default: 0
    If set to a positive integer n, the server will reserve n connect slots for clients with the proper password. See also sv_privatepassword.
    (sv_maxclients) - (sv_privateclients) = (total number of public connect slots)
    - Sideshow_Bob, Andy Lutomirski
    --------------------------------------------------------------------------------
    sv_privatepassword (variable)
    syntax: sv_privatepassword [string] default: ""
    Password to allow for the connection of clients to reserved slots. The client would have to set the password cvar to the same value in order to connect. See also sv_privateclients.
    - Sideshow_Bob, Andy Lutomirski
    --------------------------------------------------------------------------------
    sv_reconnectlimit (variable)
    syntax: sv_reconnectlimit [value] default: 3
    Presumably sets the number of times the server will recognize a client's reconnect command. (However, there is no reconnect command...)
    --------------------------------------------------------------------------------
    sv_running (variable)(R)
    syntax: sv_running [0/1] default: 0
    Reports if the server is running on the local machine. 0=server not on local machine;1=server on local machine.
    - LOKi
    --------------------------------------------------------------------------------
    sv_serverid (variable)(R)
    syntax: sv_serverid [id #] default: ""
    The identification number of the local server.
    --------------------------------------------------------------------------------
    sv_showloss (variable)
    syntax: sv_showloss [?] default: 0
    Unknown.
    --------------------------------------------------------------------------------
    sv_timeout (variable)
    syntax: sv_timeout [time in seconds] default: 120
    Sets the amount of time for the server to wait for a client packet before assuming a disconnected state.
    --------------------------------------------------------------------------------
    sv_zombietime (variable)
    syntax: sv_zombietime [minutes] default: 2
    Sets the amount of time before removing a frozen player.
    --------------------------------------------------------------------------------
    sv_zone (variable)(S)
    syntax: sv_zone [string] default: default
    Sets a game type for the server such as Free For All, Tournament, Team Deathmatch and Capture the Flag.
    - dynamite
    --------------------------------------------------------------------------------
    sys_cpuid (variable)
    syntax: sys_cpuid [value] default: ""
    Presumably reports the CPU ID number used on the local machine.
    --------------------------------------------------------------------------------
    sys_cpustring (variable)
    syntax: sys_cpustring [string] default: ""
    Identifies the CPU in use on the local machine.
    --------------------------------------------------------------------------------
    systeminfo (command)
    syntax: systeminfo
    Reports settings for:
    g_syncronousclients
    sv_serverid
    timescale
    --------------------------------------------------------------------------------
    tcmd (command)
    syntx: tcmd [?]
    Unknown.
    --------------------------------------------------------------------------------
    team (command)
    syntax: team [string]
    Sets player status. Possible values:
    p = Player (FFA)
    s = Spectator
    blue = Blue Team
    red = Red Team
    follow# = Spectator, following player by number
    scoreboard = Be a scoreboard

    --------------------------------------------------------------------------------
    teamflags (variable)(S A)
    syntax: teamflags [value] default: 0
    Sets the game options for team play.
    --------------------------------------------------------------------------------
    tell (command)
    syntax: tell [player_name or id]
    Sends a message to the specified player.
    - dynamite
    --------------------------------------------------------------------------------
    tell_attacker (command)
    syntax: tell_attacker [string]
    Sends a message to the player who last injured you.
    --------------------------------------------------------------------------------
    tell_target (command)
    syntax: tell_target [string]
    Sends a message to the player who you are presently targeting.
    --------------------------------------------------------------------------------
    testgun (command)
    syntax: testgun [model_name]
    Unknown.
    --------------------------------------------------------------------------------
    testmodel (command)
    syntax: testmodel [model_name]
    Unknown.
    --------------------------------------------------------------------------------
    timedemo (variable)(C)
    syntax: timedemo [0/1] default: 0
    Toggles the running of the game as fast as it can, for the purpose of benchmarking with the use of demos. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    timegraph (variable)(C)
    syntax: timegraph [0/1] default: 0
    Toggles the display of the timegraph. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    timelimit (variable)(S A)
    syntax: timelimit [value] default: 0
    Sets the amount of time before a game will end if fraglimit is not reached or set. Setting to 0 disables timelimit.
    --------------------------------------------------------------------------------
    timescale (variable)(C)
    syntax: timescale [value] default: 1
    Sets the ratio between game time and 'real' time.
    --------------------------------------------------------------------------------
    toggle (command)
    syntax: toggle [cvar]
    Alternately sets a cvar to 0 and 1. It will affect cvars with valid setting of other than 0 or 1, so use with discretion.
    --------------------------------------------------------------------------------
    toggleconsole (command)
    syntax: toggleconsole
    Will bring down the console if up, or raise it if down.
    --------------------------------------------------------------------------------
    touchfile (command)
    syntax: touchfile [file]
    Unknown.
    --------------------------------------------------------------------------------
    unbind (command)
    syntax: unbind [key or button]
    Remove a binding from a selected key or button.
    --------------------------------------------------------------------------------
    unbindall (command)
    syntax: unbindall
    Unbinds all keys except for ESC and ` (tilde key).
    --------------------------------------------------------------------------------
    userinfo (command)
    syntax: userinfo
    Leftover from the previous version, now broken. Replaced by clientinfo.
    --------------------------------------------------------------------------------
    username (variable)
    syntax: username [string] default: ""
    The name of the currently logged-on user on the machine.
    --------------------------------------------------------------------------------
    version (variable)(S R)
    syntax: version [string] default: "Q3T 1.05 win-x86 May 10 1999"
    The current version of Q3Test.
    --------------------------------------------------------------------------------
    versionnumber (variable)(R)
    syntax: versionnumber [string] default: Q3T 1.06
    The current version number of Q3Test.
    --------------------------------------------------------------------------------
    vid_restart (command)
    syntax: vid_restart
    Reinitializes the video system so new settings can take effect.
    --------------------------------------------------------------------------------
    vid_xpos (variable)(A)
    syntax: vid_xpos [number of pixels] default: 3
    Positions the game screen the specified number of pixels from the left edge of the monitor screen when in windowed mode.
    --------------------------------------------------------------------------------
    vid_ypos (variable)(A)
    syntax: vid_ypos [number of pixels] default: 22
    Positions the game screen the specified number of pixels from the top edge of the monitor screen when in windowed mode.
    --------------------------------------------------------------------------------
    viewlog (variable)(C)
    syntax: viewlog [0/1] default: 0
    Toggles the display of the startup console window over the game screen. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    viewpos (command)
    syntax: viewpos
    Displays the players coordinate position (x-y-z) on the loaded map and the direction he is facing in degrees.
    --------------------------------------------------------------------------------
    viewsize (variable)(A)
    syntax: viewsize [value] default: 100
    Sets the size of the play screen as a percentage of the monitor screen. Maximum value=100.
    --------------------------------------------------------------------------------
    vm_cgame (variable)(A)
    syntax: vm_cgame [value] default: 0
    Unknown.
    --------------------------------------------------------------------------------
    vmprofile (command)
    syntax: vmprofile [?]
    Unknown.
    --------------------------------------------------------------------------------
    vmsg (command)
    syntax: vmsg [string]
    Same as the say command, except a sound file is played along with the message.
    The command is present but appears broken.
    --------------------------------------------------------------------------------
    vmsg_team (command)
    syntax: vmsg_team [string]
    Same as the say_team command, except a sound file is played along with the message.
    The command is present but appears broken.
    --------------------------------------------------------------------------------
    vstr (command)
    syntax: vstr [user-created variable]
    Executes a variable command created with set, seta, sets or setu.
    --------------------------------------------------------------------------------
    wait (command)
    syntax: wait [integer]
    Waits the specified number of game tics (0.1 seconds?). If no parameter is used it will default to a single game tic. Used in command strings to allow enough time for a command to be executed before proceeding to the next.
    --------------------------------------------------------------------------------
    weapnext (command)
    syntax: weapnext
    Selects the next available higher numbered weapon in sequence. See also weapprev.
    --------------------------------------------------------------------------------
    weapon (command)
    syntax: weapon [integer]
    Selects the weapon specified by the parameter. Valid choices:
    1 = Gauntlet
    2 = Machinegun
    3 = Shotgun
    4 = Grenade Launcher
    5 = Rocket Launcher
    6 = Lightning Gun
    7 = Railgun
    8 = Plasma Gun
    9 = BFG10K
    10 = Grappling Hook
    --------------------------------------------------------------------------------
    weapprev (command)
    syntax: weapprev
    Selects the next available lower numbered weapon in sequence. See also weapnext.
    --------------------------------------------------------------------------------
    win_hinstance (variable)(R)
    syntax: win_hinstance [instance_value] default: 4194304
    The Windows handle assigned to quake3.exe. Presumably used for debugging and/or for a mod to retrieve a handle to the Q3 application.
    - Zeb, Andy Lutomirski
    --------------------------------------------------------------------------------
    win_wndproc (variable)(R)
    syntax: win_wndproc [?] default: 4368704
    Presumably the WndProc for the Quake3 window.
    - Andy Lutomirski
    --------------------------------------------------------------------------------
    writeconfig (command)
    syntax: writeconfig [?]
    Unknown.
    --------------------------------------------------------------------------------
    z_stats (command)
    syntax: z_stats
    Displays memory and block usage.
    --------------------------------------------------------------------------------
    zoomfov (variable*)(A)
    syntax: zoomfov [value in degrees] default: 22.5
    Sets the size of the field of view when +zoom is active. Sensitivity scales automatically with the change in field of view. Maximum value=160.
     

    Quake3 控制台命令1

    Quake III Console  
     
    转自 http://www.terta.de/lwt/docs/q3commands.html
    cg_animspeed (variable)(C)
    syntax: cg_animspeed [0/1] default: 1
    Toggles player animations. 0=disables;1=enables. See also cg_noplayeranims.
    --------------------------------------------------------------------------------
    cg_autoswitch (variable)(A)
    syntax: cg_autoswitch [0/1] default: 1
    Toggles the automatic switching to the weapon the player has just picked up. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    cg_bobpitch (variable)(A)
    syntax: cg_bobpitch [value] default: 0.002
    Sets how much the player view pitches forward and back when moving.
    --------------------------------------------------------------------------------
    cg_bobroll (variable)(A)
    syntax: cg_bobroll [value] default: 0.002
    Sets how much the player view rolls from side to side when moving.
    --------------------------------------------------------------------------------
    cg_bobup (variable)(A)
    syntax: cg_bobup [value] default: 0.005
    Sets how much the player view bobs up and down when moving.
    --------------------------------------------------------------------------------
    cg_brasstime (variable)
    syntax: cg_brasstime [value] default: ?
    Sets how long weapon effects (like the ejected shells from the shotgun) will be rendered. Setting to 0 disables this effect entirely.
    --------------------------------------------------------------------------------
    cg_centertime (variable)(C)
    syntax: cg_centertime [time in seconds] default: 3
    Sets how long messages are displayed in the center of the screen. If set to 0 no messages will appear.
    --------------------------------------------------------------------------------
    cg_debuganim (variable)(C)
    syntax: cg_debuganim [0/1] default: 0
    Presumably enables/disables debugging of model animations.
    --------------------------------------------------------------------------------
    cg_debugevents (variable)(C)
    syntax: cg_debugevents [?] default: 0
    Unknown.
    --------------------------------------------------------------------------------
    cg_debugposition (variable)(C)
    syntax: cg_debugposition [?] default: 0
    Unknown.
    --------------------------------------------------------------------------------
    cg_demolook (variable)(C)
    syntax: cg_demolook [?] default: 0
    Unknown.
    --------------------------------------------------------------------------------
    cg_draw2d (variable)
    syntax: cg_draw2d [0/1] default: 1
    Toggles display of 2D items on the screen. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    cg_draw3dicons (variable)
    syntax: cg_draw3dicons [0/1] default: 1
    Toggles the drawing of the 3D ammo, skin, and armor icons. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    cg_drawammowarning (variable)(A)
    syntax: cg_drawammowarning [0/1] default: 1
    Toggles the "Low on Ammo" warning on the player screen. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    cg_drawattacker (variable)(A)
    syntax: cg_drawattacker [0/1] default: 1
    Toggles the display of the last guy to do damage to you in the upper-right corner of the screen. If you hurt yourself, that guy will be you. 0=disables;1=enables.
    Replaces cg_drawkiller.
    --------------------------------------------------------------------------------
    cg_drawcrosshair (variable)(A)
    syntax: cg_drawcrosshair [0/1] default: 1
    Toggles the drawing of the crosshair. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    cg_drawcrosshairnames (variable)(A)
    syntax: cg_drawcrosshairnames [0/1] default: 1
    Toggles the ID display of other players when your crosshair is on them. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    cg_drawfps (variable)(A)
    syntax: cg_drawfps [0/1] default: 0
    Toggles the frame rate counter. This cannot be displayed at the same time as the timer. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    cg_drawsnapshot (variable)(A)
    syntax: cg_drawsnapshot [value] default: 0
    Toggles the display of the snapshot count. This cannot be displayed at the same time as the frame rate counter or the timer. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    cg_drawstatus (variable)(A)
    syntax: cg_drawstatus [0/1] default: 1
    Toggles the drawing of the HUD, the crosshair and any text or readout. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    cg_drawtimer (variable)(A)
    syntax: cg_drawtimer [0/1] default: 1
    Toggles the game timer. This cannot be displayed at the same time as the frame rate counter. 1=disables;0=enables.
    --------------------------------------------------------------------------------
    cg_errordecay (variable)
    syntax: cg_errordecay [?] default: 100
    Unknown.
    --------------------------------------------------------------------------------
    cg_extrapolate (variable)
    syntax: cg_extrapolate [?] default: 1
    Unknown.
    --------------------------------------------------------------------------------
    cg_footsteps (variable)(C)
    syntax: cg_footsteps [0/1] default: 1
    Toggles player footstep sounds. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    cg_gibs (variable)(A)
    syntax: cg_gibs [0/1] default: 1
    Toggles the rendering of gibs. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    cg_gun (variable)(A)
    syntax: cg_gun [0/1] default: 1
    Toggles the rendering of the weapon model. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    cg_ignore (variable)
    syntax: cg_ignore [?] default: 0
    Unknown.
    --------------------------------------------------------------------------------
    cg_lagometer (variable)(A)
    syntax: cg_lagometer [0/1] default: 1
    Toggles between displaying the netgraph or the frag counter. 0=display frag counter;1=display netgraph.
    - Enforcer
    --------------------------------------------------------------------------------
    cg_markoffset (variable)(C)
    syntax: cg_markoffset [value] default: 1
    Presumably sets the offset of the gunshot marks but no effect was noted.
    --------------------------------------------------------------------------------
    cg_marks (variable)(A)
    syntax: cg_marks [0/1] default: 1
    Toggles gunshot marks on the walls, etc. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    cg_noplayeranims (variable)(C)
    syntax: cg_noplayeranims [0/1] default: 0
    Toggles player model animations. The animation frame displayed when this is disabled is rather odd, though. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    cg_nopredict (variable)
    syntax: cg_nopredict [0/1] default:0
    Toggles client-side player prediction. Disabling causes the client to wait for updates from the server before updating the local machine. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    cg_railtrailtime (variable)(A)
    syntax: cg_railtrailtime [value] default: 400
    Sets the amount of time the railgun slug trail is visible.
    --------------------------------------------------------------------------------
    cg_runpitch (variable)(A)
    syntax: cg_runpitch [value] default: 0.002
    Appears to do nothing.
    --------------------------------------------------------------------------------
    cg_runroll (variable)(A)
    syntax: cg_runroll [value] default: 0.005
    Appears to do nothing.
    --------------------------------------------------------------------------------
    cg_shadows (variable)(A)
    syntax: cg_shadows [integer] default: 1
    Sets type of shadows rendering when cg_marks is set to 1. Possible values:
    0=no shadows
    1=ordinary shadows
    2=stencil buffer shadows (r_stencilbits must be set to 8)
    3=very dark stencil buffer shadows (r_stencilbits must be set to 8)

    --------------------------------------------------------------------------------
    cg_showmiss (variable)
    syntax: cg_showmiss [?] default: 0
    Unknown.
    --------------------------------------------------------------------------------
    cg_simpleitems (variable)(A)
    syntax: cg_simpleitems [0/1] default: 0
    Toggles the drawing of weapon, ammo, powerups, health and armor entities as models or as sprites. 0=draw models;1=draw sprites.
    --------------------------------------------------------------------------------
    cg_stats (variable)
    syntax: cg_stats[0/1] default: 0
    Toggles the display of running count of client frames. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    cg_stereoseparation (variable)(A)
    syntax: cg_stereoseparation [value] default: 0.4
    Sets the degree of stereoscopic separation when r_stereo is 1.
    --------------------------------------------------------------------------------
    cg_swingspeed (variable)(C)
    syntax: cg_swingspeed [value] default: 0.3
    Sets how quickly the player model turns to match a new direction the player is facing. When set to 1 the model follows the turn with no delay, when set to 0 it will not turn (but will continue trying).
    --------------------------------------------------------------------------------
    cg_teamchattime (variable)(A)
    syntax: cg_teamchattime [value] default: 3000
    Adjusts the time team messages are displayed in bright red or blue box in the middle of the screen. Setting to "0" would causes just a one time quick flash (hardly noticeable).
    - burn
    --------------------------------------------------------------------------------
    cg_temp (variable)
    syntax: cg_temp [?] default: 0
    Unknown.
    --------------------------------------------------------------------------------
    cg_testentities (variable)(C)
    syntax: cg_testentities [?] default: 0
    Unknown.
    --------------------------------------------------------------------------------
    cg_thirdperson (variable)(C)
    syntax: cg_thirdperson [0/1] default: 0
    Toggles third person view. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    cg_thirdpersonangle (variable)(C)
    syntax: cg_thirdpersonangle [value in degrees] default: 0
    Sets the viewing angle on the horizontal plane when cg_thirdperson is set to 1.
    --------------------------------------------------------------------------------
    cg_thirdpersonrange (variable)(C)
    syntax: cg_thirdpersonrange [value] default: 40
    Sets the viewing distance from the player when cg_thirdperson is set to 1.
    --------------------------------------------------------------------------------
    cg_tracerchance (variable)(C)
    syntax: cg_tracerchance [?] default: 0.4
    Unknown. Presumably adjusts a lightning gun effect.
    --------------------------------------------------------------------------------
    cg_tracerlength (variable)(C)
    syntax: cg_tracerlength [?] default: 100
    Unknown. Presumably adjusts a lightning gun effect.
    --------------------------------------------------------------------------------
    cg_tracerwidth (variable)(C)
    syntax: cg_tracerwidth [?] default: 1
    Unknown. Presumably adjusts a lightning gun effect.
    --------------------------------------------------------------------------------
    cg_waveamplitude (variable)(C)
    syntax: cg_waveamplitude [?] default: 1
    Unknown.
    --------------------------------------------------------------------------------
    cg_wavefrequency1 (variable)(C)
    syntax: cg_wavefrequency1 [?] default: 0.4
    Unknown.
    --------------------------------------------------------------------------------
    changevectors (command)
    syntax: changevectors [definition]
    Unknown.
    --------------------------------------------------------------------------------
    cheats (variable)(R)
    syntax: cheats [0/1] default: 1
    Reports the ability to use commands and variables coded as cheats. Enabled until a map is loaded. Stays enabled if a map is loaded with the "devmap" command. 0=disabled;1=enabled.
    --------------------------------------------------------------------------------
    cinematic (command)
    syntax: cinematic [videoname]
    Presumably plays a cinematic from the \videos\ directory.
    --------------------------------------------------------------------------------
    cl_anglespeedkey (variable)
    syntax: cl_anglespeedkey [value] default: 1.5
    Seems to have no effect.
    --------------------------------------------------------------------------------
    cl_avidemo (variable)
    syntax: cl_avidemo [screenshots per second] default: 0
    Writes .TGA files of the current game screen for the creation of an .AVI file using the appropriate editing tool. Setting to 0 disables cl_avidemo. See also screenshot.
    - Ryan
    --------------------------------------------------------------------------------
    cl_debugmove (variable)
    syntax: cl_debugmove [?] default: 0
    Unknown.
    --------------------------------------------------------------------------------
    cl_freezedemo (variable)
    syntax: cl_freezedemo [0/1] default: 0
    When set to 1, stops the playback of a demo. Value then returns to 0.
    --------------------------------------------------------------------------------
    cl_maxpackets (variable)(A)
    syntax: cl_maxpackets [5-100] default: 30
    Sets maximum client transmission packet size. Optimum setting dependent on hardware type and connection quality. This setting is ignored during LAN play.
    --------------------------------------------------------------------------------
    cl_motd (variable)
    syntax: cl_motd [?] default: 1
    Toggles the sending of the GL_RENDERER string to id's Message of the Day server. The server then responds back with a message of the day. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    cl_mouseaccel (variable)(A)
    syntax: cl_mouseaccel [value] default: 0
    Sets degree of mouse acceleration. Higher numbers=higher acceleration. Setting to 0 disables it.
    - Alexander Kaiser
    --------------------------------------------------------------------------------
    cl_nodelta (variable)
    syntax: cl_nodelta [0/1] default: 0
    Toggles delta compression on connection. 0=delta compression;1=no delta compression.
    --------------------------------------------------------------------------------
    cl_noprint (variable)
    syntax: cl_noprint [0/1] default: 0
    Toggles the writing of console echoes and player messages in the console buffer, and therefore on the screen. 0=display text;1=don't display text.
    - LOKi
    --------------------------------------------------------------------------------
    cl_packetdup (variable)(A)
    syntax: cl_packetdup [0-5] default: 1
    Presumably sets the number of times the client sends duplicate packets to the server to compensate for packet loss.
    - dynamite
    --------------------------------------------------------------------------------
    cl_pitchspeed (variable)(A)
    syntax: cl_pitchspeed [value] default: 140
    Sets the pitch rate when +lookup and/or +lookdown is active.
    --------------------------------------------------------------------------------
    cl_run (variable)(A)
    syntax: cl_run [0/1] default: 1
    Toggles 'always run'. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    cl_running (variable)(R)
    syntax: cl_running [0/1] default: 1
    Reports if the server is running on the local machine. 0=server not on local machine;1=server on local machine.
    - dynamite
    --------------------------------------------------------------------------------
    cl_showmouserate (variable)
    syntax: cl_showmouserate [0/1] default: 0
    Toggles the display of mouse input info. The first number displays the degree of change when mouse input is received and the second the sensitivity value. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    cl_shownet (variable)
    syntax: cl_shownet [0/1] default: 0
    Toggles the display of numbers presumably reporting some sort of net status. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    cl_showtimedelta (variable)
    syntax: cl_showtimedelta [0/1] default: 0
    Toggles the display of numbers, purpose unknown. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    cl_timenudge (variable)
    syntax: cl_timenudge [time in seconds] default: 0
    Sets time delay between player input and game update. Serves as adding a lag effect to a local connection.
    --------------------------------------------------------------------------------
    cl_timeout (variable)
    syntax: cl_timeout [time in seconds] default: 125
    Sets the amount of time for the client to wait for a server packet before assuming a disconnected state.
    --------------------------------------------------------------------------------
    cl_updateinfostring (variable)(R)
    syntax: cl_updateinfostring [?] default: ""
    Default values are not set, and is only used internally. Updates the client info string for the dumpuser report.
    - dynamite
    --------------------------------------------------------------------------------
    cl_yawspeed (variable)(A)
    syntax: cl_yawspeed [value] default: 140
    Sets the yaw rate when +left and/or +right is active.
    --------------------------------------------------------------------------------
    clear (command)
    syntax: clear
    Clears the console buffer (removes text).
    --------------------------------------------------------------------------------
    clientinfo (command)
    syntax: clientinfo
    Shows user cvars on the local machine, including user created variables set with the setu command. Report includes:
    rate, snaps, model, snd, color, handicap, name, status, current server address
    --------------------------------------------------------------------------------
    cm_debugsize (variable)
    syntax: cm_debugsize [value] default: 2
    Sets the size of the debug surface grid for curved surfaces when r_debugsurface is 1.
    - dynamite
    --------------------------------------------------------------------------------
    cm_noareas (variable)(C)
    syntax: cm_noareas [?] default: 0
    Unknown.
    --------------------------------------------------------------------------------
    cm_nocurves (variable)(C)
    syntax: cm_nocurves [0/1] default: 0
    Toggles the ability of the player bounding box to clip through curved surfaces. 0=disables;1=enables. See also cm_playercurveclip.
    --------------------------------------------------------------------------------
    cm_playercurveclip (variable)(A C)
    syntax: cm_playercurveclip [0/1] default: 1
    Toggles the ability of the player bounding box to respect curved surfaces. 0=disables;1=enables. See also cm_nocurves.
    --------------------------------------------------------------------------------
    cmd (command)
    syntax: cmd [command]
    Executes a valid command. Usage generally not necessary.
    --------------------------------------------------------------------------------
    cmdlist (command)
    syntax: cmdlist
    Reports to the console all console commands listed.
    --------------------------------------------------------------------------------
    color (variable)(U A)
    syntax: color [integer] default: 4
    Sets the effects color for the railgun.
    1=Blue
    2=Green
    3=Cyan
    4=Red
    5=Magenta
    6=Yellow
    7=White

    --------------------------------------------------------------------------------
    com_dropsim (variable)(C)
    syntax: com_dropsim [?] default: 0
    Unknown.
    --------------------------------------------------------------------------------
    com_hunkmegs (variable)(A L)
    syntax: com_hunkmegs [Mb] default: 20
    Sets the amount of memory that QUAKE3.EXE will allocate for itself.
    - dynamite
    --------------------------------------------------------------------------------
    com_maxfps (variable)(A)
    syntax: com_maxfps[integer] default: 100
    Sets the frames/second cap. Disabled when timedemo is 1.
    --------------------------------------------------------------------------------
    com_showtrace (variable)(C)
    syntax: com_showtrace [0/1] default=0
    Toggles running display of some sort of data. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    com_speeds (variable)
    syntax: com_speeds [0/1] default=0
    Toggles the reporting of game speed data. Output includes (time in milliseconds): All; SV (server time); EV(?); CL (client time); GM (game time); RF (renderer time). 0=disables;1=enables.
    - dynamite
    --------------------------------------------------------------------------------
    con_notifytime (variable)
    syntax: con_notifytime [time in seconds] default: 3
    Sets the amount of time console messages will appear on the screen. When set to 0 no messages appear.
    --------------------------------------------------------------------------------
    conback (variable)
    syntax: conback [path/filename] default: "gfx/2d/conback.tga"
    Sets the image file used as the console background.
    --------------------------------------------------------------------------------
    condump (command)
    syntax: condump [filename.extension]
    Writes a file in the working directory containing all text in the console buffer.
    --------------------------------------------------------------------------------
    configstrings (command)
    syntax: configstrigs
    Reports server configuration info.
    --------------------------------------------------------------------------------
    connect (command)
    syntax: connect [IP address] [port]
    Connects to a server. If no port is specified the default port is used.
    --------------------------------------------------------------------------------
    crash (command)
    syntax: crash
    Crashes Q3Test immediately. Be prepared to reset your desktop resolution.
    --------------------------------------------------------------------------------
    crosshairhealth (variable)(A)
    syntax: crosshairhealth [0/1] default: 1
    Toggles the color-changing property of the crosshair based on the player's current health. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    crosshairsize (variable)(A)
    syntax: crosshairsize [value] default: 24
    Sets the size of the crosshair.
    --------------------------------------------------------------------------------
    cvar_restart (command)
    syntax: cvar_restart
    Returns all console variables to their default settings. Does not affect key bindings.
    --------------------------------------------------------------------------------
    cvarlist (command)
    syntax: cvarlist
    Reports to the console all console variables listed, and their current values.
    --------------------------------------------------------------------------------
    demo (command)
    syntax: demo [demoname.dm2]
    Plays a pre-recorded demo.
    --------------------------------------------------------------------------------
    debuggraph (variable)(C)
    syntax: debuggraph [0/1] default: 0
    Toggles the display of some sort of graph, presumably for debugging purposes. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    dedicated (variable)(L)
    syntax: dedicated [value] default: 0
    Toggles the use of the server as dedicated, meaning no graphic environment. This command should be passed on the command line. Valid values:
    0=disables
    1=enables for internet use, updating id's master server list
    2=enables for LAN play

    --------------------------------------------------------------------------------
    developer (variable)
    syntax: developer [integer] default: 0
    Toggles the display of file loadings, errors and cvar change reports on the console. Seems to only have an on/off state. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    devmap (command)
    syntax: devmap [mapname]
    Loads a map file specifying cheats 1. The .BSP file extension is not required. See also map.
    --------------------------------------------------------------------------------
    dir (command)
    syntax: dir [dir] [extension]
    Reports the contents of a directory. Examples:
    If you want to see your "scripts" folder, enter: dir scripts
    If you want to see your "quake3" folder, enter: dir ../
    If you want to see your config files, enter: dir ..\baseq3\*.cfg
    - badak
    --------------------------------------------------------------------------------
    disconnect (command)
    syntax: disconnect
    Disconnects the client from the server.
    --------------------------------------------------------------------------------
    dmflags (variable)(A S)
    syntax: dmflags [value] default: 0
    Sets the game options for deathmatch play.
    --------------------------------------------------------------------------------
    dumpuser (command)
    syntax: dumpuser [userid]
    Reports info on the specified user. Info includes: name, handicap, color, snd, model, snaps, rate
    --------------------------------------------------------------------------------
    echo (command)
    syntax: echo [string]
    Echoes text to the console on the local machine.
    --------------------------------------------------------------------------------
    error (command)
    syntax: error [string]
    Causes Q3Test to quit with the error message specified in the string. Will leave the intial Q3Test startup window on the desktop.
    --------------------------------------------------------------------------------
    exec (command)
    syntax: exec [filename.cfg]
    Loads a configuration file.
    --------------------------------------------------------------------------------
    fixedtime (variable)(C)
    syntax: fixedtime [value] default: 0
    Sets how fast the game runs. Setting to 0 disables fixedtime. Similar to timescale but frames are not dropped to maintain speed scale.
    - dynamite
    --------------------------------------------------------------------------------
    follow (command)
    syntax: follow [player_name or id]
    Follows indicated player when in team is "s" (spectator mode).
    --------------------------------------------------------------------------------
    fov (variable)(A)
    syntax: fov [value in degrees] default: 90
    Sets the size of the field of view. Values over 90 do not prevent the gun model from appearing. Maximum value=160.
    --------------------------------------------------------------------------------
    fraglimit (variable)(S A)
    syntax: fraglimit [value] default: 20
    Sets the number of frags required for the game to be won if timelimit has been not reached or set. Setting to 0 disables fraglimit.
    --------------------------------------------------------------------------------
    freelook (variable)(A)
    syntax: freelook [0/1] default: 1
    Toggles the use of "always look", so that the mouse or similar device is used for looking and turning rather than movement. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    freeze (command)
    syntax: freeze [time in seconds]
    Freezes the game for the specified number of seconds.
    --------------------------------------------------------------------------------
    fs_basepath (variable)(I)
    syntax: fs_basepath [drive\path\quake3_dir] default: C:\Q3TEST
    Sets the drive and directory where QUAKE3.EXE and associated files are located.
    - various
    --------------------------------------------------------------------------------
    fs_cdpath (variable)(I)
    syntax: fs_cdpath [drive\path\cd_dir] default: ""
    Presumably sets the CD drive and directory where QUAKE3.EXE should read files from.
    -various
    --------------------------------------------------------------------------------
    fs_copyfiles (variable)(I)
    syntax: fs_copyfiles [?] default: 0
    Unknown.
    --------------------------------------------------------------------------------
    fs_debug (variable)
    syntax: fs_debug [0/1] default: 0
    Toggles the reporting of debugging info when files are accessed. 0=disables;1=enables.
    - dynamite
    --------------------------------------------------------------------------------
    fs_game (variable)(S I)
    syntax: fs_game [game_dir] default: ""
    The game directory QUAKE3.EXE should read files from first, and where it will write files. Used for mods.
    - various
    --------------------------------------------------------------------------------
    fs_restrict (variable)(I)
    syntax: fs_restrict [0/1] default: 1
    Toggles restiction of use of the other fs_* cvars. This cannot be changed in the Test, which runs in restricted demo mode. 0=disables;1=enables.
    - dynamite
    --------------------------------------------------------------------------------
    g_arenaname (variable)(R)
    syntax: g_arenaname [?] default: 0
    Unknown.
    --------------------------------------------------------------------------------
    g_arenarank (variable)(A)
    syntax: g_arenarank [?] default:""
    Unknown.
    --------------------------------------------------------------------------------
    g_arenascores (variable)(A)
    syntax: g_arenascores [?] default:""
    Unknown.
    --------------------------------------------------------------------------------
    g_debugalloc (variable)
    syntax: g_debugalloc [?] default: 0
    Unknown.
    --------------------------------------------------------------------------------
    g_debugmove (variable)
    syntax: g_debugmove [?] default: 0
    Unknown.
    --------------------------------------------------------------------------------
    g_forcerespawn (variable)
    syntax: g_forcerespawn [time in seconds] default: 20
    Sets the amount of time a killed player will be forceably respawned. Setting to 0 disables g_forcerespawn.
    --------------------------------------------------------------------------------
    g_gametype (variable)(S A L)
    syntax: g_gametype [value] default: 0
    Sets the type of game played. Possible values:
    0=FFA
    1=Tournament(One on One)
    2=Team Deathmatch
    3=Capture the Flag

    --------------------------------------------------------------------------------
    g_gravity (variable)
    syntax: g_gravity [value] default: 800
    Sets the gravity level. This is normally set by a property of the map loaded.
    --------------------------------------------------------------------------------
    g_inactivity (variable)
    syntax: g_inactivity [time in seconds] default: 0
    Presumably sets the amount of time a player can remain inactive before kicked, or given some sort of no-camping warning.
    - value definition by burn
    --------------------------------------------------------------------------------
    g_knockback (variable)
    syntax: g_knockback [value] default: 1000
    Sets the amount of knockback effect a player recieves from weapon fire.
    --------------------------------------------------------------------------------
    g_log (variable)(A)
    syntax: g_log [0/1] default: 1
    Toggles the writing of GAMES.LOG in the current game directory, which logs gameplay events in the current session. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    g_maxgameclients (variable)(S A L)
    syntax: g_maxgameclients [value] default: 0
    Unknown.
    --------------------------------------------------------------------------------
    g_motd (variable)
    syntax: g_motd [string] default: ""
    Sets server message-of-the-day which appears when you log on to a server. Font color can be changed. Possible colors:
    0 = Black
    1 = Red
    2 = Green
    3 = Yellow
    4 = Blue
    5 = Cyan
    6 = Magenta
    7 = White
    --------------------------------------------------------------------------------
    g_passwords (variable)(U)
    syntax: g_passwords [string] default: ""
    Sets a password for a private game by the server. Clients would need to specify the password also. See also password.
    --------------------------------------------------------------------------------
    g_quadfactor (variable)
    syntax: g_quadfactor [value] default: 3
    Sets the damage multiplier of the quad.
    --------------------------------------------------------------------------------
    g_restarted (variable)
    syntax: g_restarted [value] default: 0
    Unknown.
    --------------------------------------------------------------------------------
    g_singleplayer (variable)(R)
    syntax: g_singleplayer [value] default: 0
    Unknown.
    --------------------------------------------------------------------------------
    g_speed (variable)
    syntax: g_speed [value] default: 320
    Sets the maximum speed a player can move.
    --------------------------------------------------------------------------------
    g_syncronousclients (variable)
    syntax: g_syncronousclients [0/1] default: 1
    Toggles syncing of all clients movements. Must be enabled for recording demos of a game session. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    g_weaponrespawn (variable)
    syntax: g_weaponrespawn [time in seconds] default: 5
    Sets the amount of time to wait before respawning weapons. Setting to 0 causes the weapons to respawn instantly.
    --------------------------------------------------------------------------------
    g_warmup (variable)(A)
    syntax: g_warmup [time in seconds] default: 5
    Sets the amount of warmup time in Tournament mode.
    --------------------------------------------------------------------------------
    gamedate (variable)(R)
    syntax: gamedate [string] default: "May 10 1999"
    The release date of the current version.
    --------------------------------------------------------------------------------
    gamename (variable)(S R)
    syntax: gamename [dir name] default: demoq3
    The game directory quake3.exe is working.
    --------------------------------------------------------------------------------
    gfxinfo (command)
    syntax: gfxinfo
    Reports current graphics rendering info, including: OpenGL extensions loaded, color depth, resolution, status of multithreaded support and the state of some rendering options.
    --------------------------------------------------------------------------------
    give (command)
    syntax: give [weapon, item, or ammo]
    A cheat to give yourself something. Valid choices (not a complete list):
    all (all weapons, 999 ammo of all types, 200 armor)
    shotgun
    grenade launcher
    rocket launcher
    flamethrower
    railgun
    plasma gun
    lightning gun
    bfg10k
    grappling hook
    bullets (50 - machinegun ammo)
    shells (10 - shotgun ammo)
    grenades (5 - grenade launcher ammo)
    rockets (5 - rocket launcher ammo)
    slugs (20 - railgun ammo)
    cells (30 - plasma gun ammo)
    armor (200)
    quad damage
    personal teleporter
    medkit
    flight
    speed
    invisibility
    regeneration

    --------------------------------------------------------------------------------
    globalservers (command)
    syntax: globalservers [zone]
    Searches for servers on the internat.
    --------------------------------------------------------------------------------
    god (command)
    syntax: god
    Enables invulnerability mode. Entering the command again disables it.
    --------------------------------------------------------------------------------
    graphheight (variable)(C)
    syntax: graphheight [number of pixels] default: 32
    Sets the height of a displayed graph.
    --------------------------------------------------------------------------------
    graphscale (variable)(C)
    syntax: graphscale [value] default: 1
    Sets the scale of the lines in a displayed graph.
    --------------------------------------------------------------------------------
    graphshift (variable)(C)
    syntax: graphshift [value] default: 0
    Setting shifts all graph lines up or down on a displayed graph.
    --------------------------------------------------------------------------------
    gun_x (variable)(C)
    syntax: gun_x [value] default: 0
    Determines the position the gun model will be drawn along the x axis.
    --------------------------------------------------------------------------------
    gun_y (variable)(C)
    syntax: gun_y [value] default: 0
    Determines the position the gun model will be drawn along the y axis.
    --------------------------------------------------------------------------------
    gun_z (variable)(C)
    syntax: gun_z [value] default: 0
    Determines the position the gun model will be drawn along the z axis.
    --------------------------------------------------------------------------------
    gun_frame (variable)(C)
    syntax: gun_frame [0 to 8] default: 0
    Determines the gun model animation frame drawn. Setting to 0 allows normal animation.
    --------------------------------------------------------------------------------
    handicap (variable)(U A)
    syntax: handicap [number of health points] default: 100
    Sets the maximum health of the player when spawned. Setting to a lower number while alive causes the health to slowly erode. Values of 0 and those greater than 100 are ignored.
    --------------------------------------------------------------------------------
    heartbeat (command)
    syntax: heartbeat
    Sends an update from the server to the master server with the result of updating server info.
    --------------------------------------------------------------------------------
    hunk_stats (command)
    syntax: hunkstats
    Reports how much memory is in use.
    - dynamite
    --------------------------------------------------------------------------------
    imagelist (command)
    syntax: imagelist
    Lists all image files loaded for the current map.
    --------------------------------------------------------------------------------
    in_debugjoystick (variable)
    syntax: in_debugjoystick [0/1] default: 0
    Unknown.
    --------------------------------------------------------------------------------
    in_joyball (variable)(A)
    syntax: in_joyball [0/1] default: 0
    Toggles polling the port used for game controller input, recognizing r, u, andv game controller axes. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    in_joyballscale (variable)(A)
    syntax: in_joyball [value] default: 0.02
    Sets overall sensitivity for a game controller trackball, like that of a PantherXL.
    --------------------------------------------------------------------------------
    in_joystick (variable)(A L)
    syntax: in_joystick [0/1] default: 0
    Toggles polling the port used for game controller input, recognizing x, y, and z game controller axes. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    in_midi (variable)(A)
    syntax: in_midi [?] default: 0
    Presumably enables/disables the use of MIDI music.
    --------------------------------------------------------------------------------
    in_midichannel (variable)(A)
    syntax: in_midichannel [?] default: 1
    Presumably sets number of MIDI channels.
    --------------------------------------------------------------------------------
    in_mididevice (variable)(A)
    syntax: in_mididevice [?] default: 0
    Presumably enables/disables the use of a MIDI device.
    --------------------------------------------------------------------------------
    in_midiport (variable)(A)
    syntax: in_midiport [?] default: 1
    Presumably enables/disables the MIDI input port.
    --------------------------------------------------------------------------------
    in_mouse (variable)(A L)
    syntax: in_mouse [0/1] default: 1
    Toggles polling the port used for mouse input. 0=disables;1=enables.
    --------------------------------------------------------------------------------
    in_restart (command)
    syntax: in_restart
    Reinitializes the input system so new settings can take effect.
    --------------------------------------------------------------------------------
    journal (variable)(I)
    syntax: journal [0/1] default: 0
    Sets whether the file JOURNAL.DAT is written in the game directory QUAKE3.EXE is working. 0=don't write file;1=write file.
    - badak
    --------------------------------------------------------------------------------
    kick (command)
    syntax: kick [player name or id]
    Kicks a player off the server.
    --------------------------------------------------------------------------------
    kill (command)
    syntax: kill
    Commit suicide.
    --------------------------------------------------------------------------------
    levelshot (command)
    syntax: levelshot
    This server command causes the current game to end as if fraglimit or timelimit has been reached, and writes a mini screenshot to the \levelshots\ directory if the command is executed by a player in the game
    - dynamite
    --------------------------------------------------------------------------------
    localservers (command)
    syntax: localservers
    Searches for servers on a LAN.
    --------------------------------------------------------------------------------
    logfile (variable)
    syntax: logfile [0/1/2] default: 0
    Writes all console events to qconsole.log in the current game directory. 0=don't write log;1=write log;2=append log (appending does not seem to work).
    --------------------------------------------------------------------------------
    m_forward (variable)(A)
    syntax: m_forward [value] default: 0.25
    Sets sensitivity of the mouse for forward/back movement when freelook is 0 and +mlook is inactive. Setting to negative inverts the axis action.
    --------------------------------------------------------------------------------
    m_pitch (variable)(A)
    syntax: m_pitch [value] default: 0.022
    Sets sensitivity of the mouse for looking up and down when freelook is 1 and/or +mlook is active. Setting to negative inverts the axis action.
    --------------------------------------------------------------------------------
    m_side (variable)(A)
    syntax: m_side [value] default: 0.25
    Sets sensitivity of the mouse for strafing movement when freelook is 0 and +mlook is inactive. Setting to negative inverts the axis action.
    --------------------------------------------------------------------------------
    m_yaw (variable)(A)
    syntax: m_yaw [value] default: 0.022
    Sets sensitivity of the mouse for turning action when freelook is 1 and/or +mlook is active. Setting to negative inverts the axis action.
    --------------------------------------------------------------------------------
    map (command)
    syntax: map [mapname]
    Loads a map file, specifying cheats disabled. The .BSP file extension is not required. See also devmap.
    --------------------------------------------------------------------------------
    map_restart (command)
    syntax: map_restart
    Restarts the game on the current map.
    Replaces restart.
    --------------------------------------------------------------------------------
    mapname (variable)(S R)
    syntax: mapname [filename] default: nomap
    Identifies the filename of the currently loaded map.
    --------------------------------------------------------------------------------

    zlib 常用函数说明

    quake3 的 *.pk3 文件采用的 zip 压缩算法
    typedef struct unz_global_info_s
    {
     unsigned long number_entry;          //该成员为整个压缩包包含文件的数量
     unsigned long size_comment;         /* size of the global comment of the zipfile */
    } unz_global_info;
     
    /* unz_file_info contain information about a file in the zipfile */
    typedef struct unz_file_info_s
    {
        unsigned long version;                  /* version made by                 2 unsigned chars */
        unsigned long version_needed;       /* version needed to extract       2 unsigned chars */
        unsigned long flag;                       /* general purpose bit flag        2 unsigned chars */
        unsigned long compression_method; /* compression method              2 unsigned chars */
        unsigned long dosDate;                 /* last mod file date in Dos fmt   4 unsigned chars */
        unsigned long crc;                       /* crc-32                          4 unsigned chars */
        unsigned long compressed_size;     /* compressed size                 4 unsigned chars */
        unsigned long uncompressed_size;  /* 成员为解压后文件的大小         4 unsigned chars */
        unsigned long size_filename;          /* filename length                 2 unsigned chars */
        unsigned long size_file_extra;        /* extra field length              2 unsigned chars */
        unsigned long size_file_comment;   /* file comment length             2 unsigned chars */
        unsigned long disk_num_start;       /* disk number start               2 unsigned chars */
        unsigned long internal_fa;             /* internal file attributes        2 unsigned chars */
        unsigned long external_fa;            /* external file attributes        4 unsigned chars */
        tm_unz tmu_date;
    } unz_file_info;
     
    typedef struct
    {
     FILE* file;                                       /* io structore of the zipfile */
     unz_global_info gi;                           /* public global information */
     unsigned long byte_before_the_zipfile;/* unsigned char before the zipfile, (>0 for sfx)*/
     unsigned long num_file;                    /* number of the current file in the zipfile*/
     unsigned long pos_in_central_dir;      /* pos of the current file in the central dir*/
     unsigned long current_file_ok;          /* flag about the usability of the current file*/
     unsigned long central_pos;             /* position of the beginning of the central dir*/
     unsigned long size_central_dir;        /* size of the central directory  */
     unsigned long offset_central_dir;     /* offset of start of central directory with respect to the starting disk number */
     unz_file_info cur_file_info;              /* public info about the current file in zip*/
     unz_file_info_internal cur_file_info_internal; /* private info about it*/
     file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current file if we are decompressing it */
     unsigned char* tmpFile;
     int tmpPos,tmpSize;
    } unz_s;
     
     struct s_path
    {
      char Filename[MAX_QPATH];  //文件名称
      int pos_in_central_dir;          //文件在zip包中的位置
     } zipfile_t;
     
     //打开zip文件
     unzFile ZipFile;
     ZipFile = unzOpen( FullPath );  //输入压缩文件 如 c:\quake3\pak0.pk3

     //获取zip文件信息, zip内文件数量
     unz_global_info GlobalInfo;  
     err = unzGetGlobalInfo( ZipFile, &GlobalInfo );
     
     //将文件指针移动到 zip 文件的第一个文件处。
     unzGoToFirstFile(ZipFile);
     
     //获取zip内当前文件指针指向的文件信息
     chat filename_inzip[MAX_PATH];
     unz_file_info FileInfo; 
     err = unzGetCurrentFileInfo( ZipFile, &FileInfo, filename_inzip, MAX_PATH, NULL, 0, NULL, 0 );
     
     //获取zip内当前文件指针所在的位置。可以用hashmap 记录文件名称对应zip位置,便于以后读写
     int pos;
     unzGetCurrentFileInfoPosition(ZipFile,&pos);
     
    //将zip内文件指针移动到指定的位置
     unzSetCurrentFileInfoPosition(ZipFile, pos);
     
     //移动到zip内下一个文件
     unzGoToNextFile( ZipFile );
     
     //关闭zip当前打开的文件
     unzCloseCurrentFile( ZipFile );
     
     //打开zip当前所在的文件
     unzOpenCurrentFile( ZipFile )
     
     //读取zip当前打开的文件
     char buf[bufsize];
     if( unzReadCurrentFile( ZipFile, buffer, bufsize ) < 0 )
     
     //关闭zip当前打开的文件
     unzCloseCurrentFile( ZipFile );
     
    1 个 window api 函数用法
    Handle = FindFirstFile(FullPath, &FindFile); FullPath 可以有如下形式 e:\quake3\*.pk3 这样将查找所有*.pk3文件

    一个读取zip文件中文本文件的演示程序地址(2007/10/20):
    http://www.91files.com/?QC89XBQFRDPD1WYP8G4J