home *** CD-ROM | disk | FTP | other *** search
/ Launch & Play / spustahrej2.iso / Egoboo / code / graphic.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-12-03  |  135.1 KB  |  4,188 lines

  1.  
  2. // Egoboo, Copyright (C) 2000 Aaron Bishop
  3.  
  4. #include "egoboo.h"
  5.  
  6.  
  7. BOOL    gTextureOn = FALSE;
  8.  
  9. void EnableTexturing()
  10. {
  11.     if ( !gTextureOn )
  12.     {
  13.         glEnable( GL_TEXTURE_2D );
  14.         gTextureOn = TRUE;
  15.     }
  16. }
  17.  
  18. void DisableTexturing()
  19. {
  20.     if ( gTextureOn )
  21.     {
  22.         glDisable( GL_TEXTURE_2D );
  23.         gTextureOn = FALSE;
  24.     }
  25. }
  26.  
  27.  
  28.  
  29. // This needs work
  30. void Begin3DMode()
  31. {
  32.     glMatrixMode(GL_PROJECTION);
  33.     glLoadMatrixf(mProjection.v);
  34.  
  35.     glMatrixMode(GL_MODELVIEW);
  36.     glLoadMatrixf(mView.v);
  37.     glMultMatrixf(mWorld.v);
  38. }
  39.  
  40. void End3DMode()
  41. {
  42. }
  43.  
  44. /********************> Begin2DMode() <*****/
  45. void Begin2DMode( void )
  46. {
  47.   glMatrixMode(GL_PROJECTION);
  48.   glLoadIdentity();                                    // Reset The Projection Matrix
  49.   glOrtho(0, scrx, 0, scry, 1, -1);                    // Set up an orthogonal projection
  50.  
  51.   glMatrixMode(GL_MODELVIEW);
  52.   glLoadIdentity();
  53.  
  54.   glDisable(GL_DEPTH_TEST);
  55.   glDisable(GL_CULL_FACE);
  56. }    
  57.  
  58. /********************> End2DMode() <*****/
  59. void End2DMode( void )
  60. {
  61.   glEnable(GL_CULL_FACE);
  62.   glEnable(GL_DEPTH_TEST);
  63. }
  64.  
  65. //---------------------------------------------------------------------------------------------
  66. int get_level(unsigned char x, unsigned char y, unsigned int fan, unsigned char waterwalk)
  67. {
  68.     // ZZ> This function returns the height of a point within a mesh fan, precise
  69.     //     If waterwalk is nonzero and the fan is watery, then the level returned is the
  70.     //     level of the water.
  71.     int z0, z1, z2, z3;         // Height of each fan corner
  72.     int zleft, zright,zdone;    // Weighted height of each side
  73.  
  74.     x = x&127;
  75.     y = y&127;
  76.     z0 = meshvrtz[meshvrtstart[fan]+0];
  77.     z1 = meshvrtz[meshvrtstart[fan]+1];
  78.     z2 = meshvrtz[meshvrtstart[fan]+2];
  79.     z3 = meshvrtz[meshvrtstart[fan]+3];
  80.  
  81.     zleft = (z0*(128-y)+z3*y)>>7;
  82.     zright = (z1*(128-y)+z2*y)>>7;
  83.     zdone = (zleft*(128-x)+zright*x)>>7;
  84.     if(waterwalk)
  85.     {
  86.         if(watersurfacelevel>zdone && (meshfx[fan]&MESHFXWATER) && wateriswater)
  87.         {
  88.             return watersurfacelevel;
  89.         }
  90.     }
  91.     return zdone;
  92. }
  93.  
  94. //---------------------------------------------------------------------------------------------
  95. void release_all_textures()
  96. {
  97.     // ZZ> This function clears out all of the textures
  98.     int cnt;
  99.     
  100.     for (cnt = 0; cnt < MAXTEXTURE; cnt++)
  101.         GLTexture_Release(&txTexture[cnt]);
  102. }
  103.  
  104. //--------------------------------------------------------------------------------------------
  105. void load_one_icon(char *szLoadName)
  106. {
  107.     // ZZ> This function is used to load an icon.  Most icons are loaded
  108.     //     without this function though...
  109.     
  110.     GLTexture_Load( &TxIcon[globalnumicon], szLoadName );//lpDDSIcon[globalnumicon] = DDLoadBitmap(lpDD, szLoadName, 0, 0, FALSE);
  111.     if ( GLTexture_GetTextureID( &TxIcon[globalnumicon] ) != 0 )//if(lpDDSIcon[globalnumicon]!=NULL)
  112.     {
  113.         /* PORT
  114.         DDSetColorKey(lpDDSIcon[globalnumicon], 0); */
  115.     }
  116.     globalnumicon++;
  117.     
  118. }
  119.  
  120. //---------------------------------------------------------------------------------------------
  121. void prime_titleimage()
  122. {
  123.     // ZZ> This function sets the title image pointers to NULL
  124.     int cnt;
  125.  
  126.     for (cnt = 0; cnt < MAXMODULE; cnt++)
  127.         TxTitleImage[cnt].textureID=0;
  128.     
  129.     //titlerect.x = 0;
  130.     //titlerect.w = TITLESIZE;
  131.     //titlerect.y = 0;
  132.     //titlerect.h = TITLESIZE;
  133. }
  134.  
  135. //---------------------------------------------------------------------------------------------
  136. void prime_icons()
  137. {
  138.     // ZZ> This function sets the icon pointers to NULL
  139.     int cnt;
  140.  
  141.     for (cnt = 0; cnt < MAXTEXTURE+1; cnt++)
  142.     {
  143.         //lpDDSIcon[cnt]=NULL;
  144.         TxIcon[cnt].textureID=-1;
  145.         madskintoicon[cnt]=0;
  146.     }
  147.     iconrect.left = 0;
  148.     iconrect.right = 32;
  149.     iconrect.top = 0;
  150.     iconrect.bottom = 32;
  151.     globalnumicon=0;
  152. }
  153.  
  154. //---------------------------------------------------------------------------------------------
  155. void release_all_icons()
  156. {
  157.     // ZZ> This function clears out all of the icons
  158.     int cnt;
  159.     
  160.     for (cnt = 0; cnt < MAXTEXTURE+1; cnt++)
  161.         GLTexture_Release( &TxIcon[cnt] );
  162.  
  163.     prime_icons();    /* Do we need this? */
  164. }
  165.  
  166. //---------------------------------------------------------------------------------------------
  167. void release_all_titleimages()
  168. {
  169.     // ZZ> This function clears out all of the title images
  170.     int cnt;
  171.     
  172.     for (cnt = 0; cnt < MAXMODULE; cnt++)
  173.         GLTexture_Release( &TxTitleImage[cnt] );
  174. }
  175.  
  176. //---------------------------------------------------------------------------------------------
  177. void release_all_models()
  178. {
  179.     // ZZ> This function clears out all of the models
  180.     int cnt;
  181.     for (cnt = 0; cnt < MAXMODEL; cnt++)
  182.     {
  183.         capclassname[cnt][0] = 0;
  184.         madused[cnt] = FALSE;
  185.         madname[cnt][0] = '*';
  186.         madname[cnt][1] = 'N';
  187.         madname[cnt][2] = 'O';
  188.         madname[cnt][3] = 'N';
  189.         madname[cnt][4] = 'E';
  190.         madname[cnt][5] = '*';
  191.         madname[cnt][6] = 0;
  192.     }
  193.     madloadframe=0;
  194. }
  195.  
  196.  
  197. //--------------------------------------------------------------------------------------------
  198. void release_grfx(void)
  199. {
  200.     // ZZ> This function frees up graphics/input/sound resources.
  201.  
  202.     SDL_Quit ();
  203. }
  204.  
  205. //--------------------------------------------------------------------------------------------
  206. void release_map()
  207. {
  208.     // ZZ> This function releases all the map images
  209.     
  210.     GLTexture_Release( &TxMap );
  211. }
  212.  
  213. //--------------------------------------------------------------------------------------------
  214. void debug_message(char *text)
  215. {
  216.     // ZZ> This function sticks a message in the display queue and sets its timer
  217.     int slot = get_free_message();
  218.     // Copy the message
  219.     int write = 0;
  220.     int read = 0;
  221.     char cTmp = text[read];  read++;
  222.     msgtime[slot] = MESSAGETIME;
  223.     
  224.     while(cTmp != 0)
  225.     {
  226.         msgtextdisplay[slot][write] = cTmp;
  227.         write++;
  228.         cTmp = text[read];  read++;
  229.     }
  230.     msgtextdisplay[slot][write] = 0;
  231. }
  232.  
  233. //--------------------------------------------------------------------------------------------
  234. void reset_end_text()
  235. {
  236.     // ZZ> This function resets the end-module text
  237.     if(numpla > 1)
  238.     {
  239.         sprintf(endtext, "Sadly, they were never heard from again...");
  240.         endtextwrite = 42;  // Where to append further text
  241.     }
  242.     else
  243.     {
  244.         if(numpla == 0)
  245.         {
  246.             // No players???  RTS module???
  247.             sprintf(endtext, "The game has ended...");
  248.             endtextwrite = 21;
  249.         }
  250.         else
  251.         {
  252.             // One player
  253.             sprintf(endtext, "Sadly, no trace was ever found...");
  254.             endtextwrite = 33;  // Where to append further text
  255.         }
  256.     }
  257. }
  258.  
  259. //--------------------------------------------------------------------------------------------
  260. void append_end_text(int message, unsigned short character)
  261. {
  262.     // ZZ> This function appends a message to the end-module text
  263.     int read, cnt;
  264.     char *eread;
  265.     char szTmp[256];
  266.     char cTmp, lTmp;
  267.     unsigned short target, owner;
  268.  
  269.     target = chraitarget[character];
  270.     owner = chraiowner[character];
  271.     if(message<msgtotal)
  272.     {
  273.         // Copy the message
  274.         read = msgindex[message];
  275.         cnt=0;
  276.         cTmp = msgtext[read];  read++;
  277.         while(cTmp != 0)
  278.         {
  279.             if(cTmp == '%')
  280.             {
  281.                 // Escape sequence
  282.                 eread = szTmp;
  283.                 szTmp[0] = 0;
  284.                 cTmp = msgtext[read];  read++;
  285.                 if(cTmp == 'n')  // Name
  286.                 {
  287.                     if(chrnameknown[character])
  288.                         sprintf(szTmp, "%s", chrname[character]);
  289.                     else
  290.                     {
  291.                         lTmp = capclassname[chrmodel[character]][0];
  292.                         if(lTmp == 'A' || lTmp == 'E' || lTmp == 'I' || lTmp == 'O' || lTmp == 'U')
  293.                             sprintf(szTmp, "an %s", capclassname[chrmodel[character]]);
  294.                         else
  295.                             sprintf(szTmp, "a %s", capclassname[chrmodel[character]]);
  296.                     }
  297.                     if(cnt == 0 && szTmp[0] == 'a')  szTmp[0] = 'A';
  298.                 }
  299.                 if(cTmp == 'c')  // Class name
  300.                 {
  301.                     eread = capclassname[chrmodel[character]];
  302.                 }
  303.                 if(cTmp == 't')  // Target name
  304.                 {
  305.                     if(chrnameknown[target])
  306.                         sprintf(szTmp, "%s", chrname[target]);
  307.                     else
  308.                     {
  309.                         lTmp = capclassname[chrmodel[target]][0];
  310.                         if(lTmp == 'A' || lTmp == 'E' || lTmp == 'I' || lTmp == 'O' || lTmp == 'U')
  311.                             sprintf(szTmp, "an %s", capclassname[chrmodel[target]]);
  312.                         else
  313.                             sprintf(szTmp, "a %s", capclassname[chrmodel[target]]);
  314.                     }
  315.                     if(cnt == 0 && szTmp[0] == 'a')  szTmp[0] = 'A';
  316.                 }
  317.                 if(cTmp == 'o')  // Owner name
  318.                 {
  319.                     if(chrnameknown[owner])
  320.                         sprintf(szTmp, "%s", chrname[owner]);
  321.                     else
  322.                     {
  323.                         lTmp = capclassname[chrmodel[owner]][0];
  324.                         if(lTmp == 'A' || lTmp == 'E' || lTmp == 'I' || lTmp == 'O' || lTmp == 'U')
  325.                             sprintf(szTmp, "an %s", capclassname[chrmodel[owner]]);
  326.                         else
  327.                             sprintf(szTmp, "a %s", capclassname[chrmodel[owner]]);
  328.                     }
  329.                     if(cnt == 0 && szTmp[0] == 'a')  szTmp[0] = 'A';
  330.                 }
  331.                 if(cTmp == 's')  // Target class name
  332.                 {
  333.                     eread = capclassname[chrmodel[target]];
  334.                 }
  335.                 if(cTmp >= '0' && cTmp <= '3')  // Target's skin name
  336.                 {
  337.                     eread = capskinname[chrmodel[target]][cTmp-'0'];
  338.                 }
  339.                 if(cTmp == 'd')  // tmpdistance value
  340.                 {
  341.                     sprintf(szTmp, "%d", valuetmpdistance);
  342.                 }
  343.                 if(cTmp == 'x')  // tmpx value
  344.                 {
  345.                     sprintf(szTmp, "%d", valuetmpx);
  346.                 }
  347.                 if(cTmp == 'y')  // tmpy value
  348.                 {
  349.                     sprintf(szTmp, "%d", valuetmpy);
  350.                 }
  351.                 if(cTmp == 'D')  // tmpdistance value
  352.                 {
  353.                     sprintf(szTmp, "%2d", valuetmpdistance);
  354.                 }
  355.                 if(cTmp == 'X')  // tmpx value
  356.                 {
  357.                     sprintf(szTmp, "%2d", valuetmpx);
  358.                 }
  359.                 if(cTmp == 'Y')  // tmpy value
  360.                 {
  361.                     sprintf(szTmp, "%2d", valuetmpy);
  362.                 }
  363.                 if(cTmp == 'a')  // Character's ammo
  364.                 {
  365.                     if(chrammoknown[character])
  366.                         sprintf(szTmp, "%d", chrammo[character]);
  367.                     else
  368.                         sprintf(szTmp, "?");
  369.                 }
  370.                 if(cTmp == 'k')  // Kurse state
  371.                 {
  372.                     if(chriskursed[character])
  373.                         sprintf(szTmp, "kursed");
  374.                     else
  375.                         sprintf(szTmp, "unkursed");
  376.                 }
  377.                 if(cTmp == 'p')  // Character's possessive
  378.                 {
  379.                     if(chrgender[character] == GENFEMALE)
  380.                     {
  381.                         sprintf(szTmp, "her");
  382.                     }
  383.                     else
  384.                     {
  385.                         if(chrgender[character] == GENMALE)
  386.                         {
  387.                             sprintf(szTmp, "his");
  388.                         }
  389.                         else
  390.                         {
  391.                             sprintf(szTmp, "its");
  392.                         }
  393.                     }
  394.                 }
  395.                 if(cTmp == 'm')  // Character's gender
  396.                 {
  397.                     if(chrgender[character] == GENFEMALE)
  398.                     {
  399.                         sprintf(szTmp, "female ");
  400.                     }
  401.                     else
  402.                     {
  403.                         if(chrgender[character] == GENMALE)
  404.                         {
  405.                             sprintf(szTmp, "male ");
  406.                         }
  407.                         else
  408.                         {
  409.                             sprintf(szTmp, " ");
  410.                         }
  411.                     }
  412.                 }
  413.                 if(cTmp == 'g')  // Target's possessive
  414.                 {
  415.                     if(chrgender[target] == GENFEMALE)
  416.                     {
  417.                         sprintf(szTmp, "her");
  418.                     }
  419.                     else
  420.                     {
  421.                         if(chrgender[target] == GENMALE)
  422.                         {
  423.                             sprintf(szTmp, "his");
  424.                         }
  425.                         else
  426.                         {
  427.                             sprintf(szTmp, "its");
  428.                         }
  429.                     }
  430.                 }
  431.                 // Copy the generated text
  432.                 cTmp = *eread;  eread++;
  433.                 while(cTmp != 0 && endtextwrite < MAXENDTEXT-1)
  434.                 {
  435.                     endtext[endtextwrite] = cTmp;
  436.                     cTmp = *eread;  eread++;
  437.                     endtextwrite++;
  438.                 }
  439.             }
  440.             else
  441.             {
  442.                 // Copy the letter
  443.                 if(endtextwrite < MAXENDTEXT-1)
  444.                 {
  445.                     endtext[endtextwrite] = cTmp;
  446.                     endtextwrite++;
  447.                 }
  448.             }
  449.             cTmp = msgtext[read];  read++;
  450.             cnt++;
  451.         }
  452.     }
  453.     endtext[endtextwrite] = 0;
  454. }
  455.  
  456. //--------------------------------------------------------------------------------------------
  457. void make_textureoffset(void)
  458. {
  459.     // ZZ> This function sets up for moving textures
  460.     int cnt;
  461.     for (cnt = 0; cnt < 256; cnt++)
  462.         textureoffset[cnt] = cnt*1.0/256;
  463. }
  464.  
  465. //--------------------------------------------------------------------------------------------
  466. void create_szfpstext(int frames)
  467. {
  468.     // ZZ> This function fills in the number of frames in "000 Frames per Second"
  469.     frames = frames&511;
  470.     szfpstext[0] = '0'+(frames/100);
  471.     szfpstext[1] = '0'+((frames/10)%10);
  472.     szfpstext[2] = '0'+(frames%10);
  473. }
  474.  
  475. //--------------------------------------------------------------------------------------------
  476. void make_renderlist()
  477. {
  478.     // ZZ> This function figures out which mesh fans to draw
  479.     int cnt, fan, fanx, fany;
  480.     int row, run, numrow;
  481.     int xlist[4], ylist[4];
  482.     int leftnum, leftlist[4];
  483.     int rightnum, rightlist[4];
  484.     int fanrowstart[128], fanrowrun[128];
  485.     int x, stepx, divx, basex;
  486.     int from, to;
  487.  
  488.  
  489.     // Clear old render lists
  490.     cnt = 0;
  491.     while(cnt < nummeshrenderlist)
  492.     {
  493.         fan = meshrenderlist[cnt];
  494.         meshinrenderlist[fan] = FALSE;
  495.         cnt++;
  496.     }
  497.     nummeshrenderlist = 0;
  498.     nummeshrenderlistref = 0;
  499.     nummeshrenderlistsha = 0;
  500.  
  501.     // Make sure it doesn't die ugly !!!BAD!!!
  502.  
  503.     // It works better this way...
  504.     cornery[cornerlistlowtohighy[3]]+=256;
  505.  
  506.     // Make life simpler
  507.     xlist[0] = cornerx[cornerlistlowtohighy[0]];
  508.     xlist[1] = cornerx[cornerlistlowtohighy[1]];
  509.     xlist[2] = cornerx[cornerlistlowtohighy[2]];
  510.     xlist[3] = cornerx[cornerlistlowtohighy[3]];
  511.     ylist[0] = cornery[cornerlistlowtohighy[0]];
  512.     ylist[1] = cornery[cornerlistlowtohighy[1]];
  513.     ylist[2] = cornery[cornerlistlowtohighy[2]];
  514.     ylist[3] = cornery[cornerlistlowtohighy[3]];
  515.  
  516.     // Find the center line
  517.     divx = ylist[3]-ylist[0]; if(divx < 1) return;
  518.     stepx = xlist[3]-xlist[0];
  519.     basex = xlist[0];
  520.  
  521.  
  522.     // Find the points in each edge
  523.     leftlist[0] = 0;  leftnum = 1;
  524.     rightlist[0] = 0;  rightnum = 1;
  525.     if(xlist[1] < (stepx*(ylist[1]-ylist[0])/divx)+basex)
  526.     {
  527.         leftlist[leftnum] = 1;  leftnum++;
  528.         cornerx[1]-=512;
  529.     }
  530.     else
  531.     {
  532.         rightlist[rightnum] = 1;  rightnum++;
  533.         cornerx[1]+=512;
  534.     }
  535.     if(xlist[2] < (stepx*(ylist[2]-ylist[0])/divx)+basex)
  536.     {
  537.         leftlist[leftnum] = 2;  leftnum++;
  538.         cornerx[2]-=512;
  539.     }
  540.     else
  541.     {
  542.         rightlist[rightnum] = 2;  rightnum++;
  543.         cornerx[2]+=512;
  544.     }
  545.     leftlist[leftnum] = 3;  leftnum++;
  546.     rightlist[rightnum] = 3;  rightnum++;
  547.  
  548.  
  549.     // Make the left edge ( rowstart )
  550.     fany = ylist[0]>>7;
  551.     row = 0;
  552.     cnt = 1;
  553.     while(cnt < leftnum)
  554.     {
  555.         from = leftlist[cnt-1];  to = leftlist[cnt];
  556.         x = xlist[from];
  557.         divx = ylist[to]-ylist[from];
  558.         stepx = 0;
  559.         if(divx > 0)
  560.         {
  561.             stepx = ((xlist[to]-xlist[from])<<7)/divx;
  562.         }
  563.         x-=256;
  564.         run = ylist[to]>>7;
  565.         while(fany < run)
  566.         {
  567.             if(fany >= 0 && fany < meshsizey)
  568.             {
  569.                 fanx = x>>7;
  570.                 if(fanx < 0)  fanx = 0;
  571.                 if(fanx >= meshsizex)  fanx = meshsizex-1;
  572.                 fanrowstart[row] = fanx;
  573.                 row++;
  574.             }
  575.             x+=stepx;
  576.             fany++;
  577.         }
  578.         cnt++;
  579.     }
  580.     numrow = row;
  581.  
  582.  
  583.     // Make the right edge ( rowrun )
  584.     fany = ylist[0]>>7;
  585.     row = 0;
  586.     cnt = 1;
  587.     while(cnt < rightnum)
  588.     {
  589.         from = rightlist[cnt-1];  to = rightlist[cnt];
  590.         x = xlist[from];
  591.         //x+=128;
  592.         divx = ylist[to]-ylist[from];
  593.         stepx = 0;
  594.         if(divx > 0)
  595.         {
  596.             stepx = ((xlist[to]-xlist[from])<<7)/divx;
  597.         }
  598.         run = ylist[to]>>7;
  599.         while(fany < run)
  600.         {
  601.             if(fany >= 0 && fany < meshsizey)
  602.             {
  603.                 fanx = x>>7;
  604.                 if(fanx < 0)  fanx = 0;
  605.                 if(fanx >= meshsizex-1)  fanx = meshsizex-1;//-2
  606.                 fanrowrun[row] = ABS(fanx-fanrowstart[row])+1;
  607.                 row++;
  608.             }
  609.             x+=stepx;
  610.             fany++;
  611.         }
  612.         cnt++;
  613.     }
  614.  
  615.     if(numrow != row)
  616.     {
  617.         general_error(numrow, row, "ROW");
  618.     }
  619.  
  620.     // Fill 'em up again
  621.     fany = ylist[0]>>7;
  622.     if(fany < 0) fany = 0;
  623.     if(fany >= meshsizey) fany = meshsizey-1;
  624.     row = 0;
  625.     while(row < numrow)
  626.     {
  627.         cnt = meshfanstart[fany]+fanrowstart[row];
  628.         run = fanrowrun[row];
  629.         fanx = 0;
  630.         while(fanx < run)
  631.         {
  632.             if(nummeshrenderlist < MAXMESHRENDER)
  633.             {
  634.                 // Put each tile in basic list
  635.                 meshinrenderlist[cnt] = TRUE;
  636.                 meshrenderlist[nummeshrenderlist] = cnt;
  637.                 nummeshrenderlist++;
  638.                 // Put each tile in one other list, for shadows and relections
  639.                 if(meshfx[cnt]&MESHFXSHA)
  640.                 {
  641.                     meshrenderlistsha[nummeshrenderlistsha] = cnt;
  642.                     nummeshrenderlistsha++;
  643.                 }
  644.                 else
  645.                 {
  646.                     meshrenderlistref[nummeshrenderlistref] = cnt;
  647.                     nummeshrenderlistref++;
  648.                 }
  649.             }
  650.             cnt++;
  651.             fanx++;
  652.         }
  653.         row++;
  654.         fany++;
  655.     }
  656. }
  657.  
  658. //--------------------------------------------------------------------------------------------
  659. void figure_out_what_to_draw()
  660. {
  661.     // ZZ> This function determines the things that need to be drawn
  662.  
  663.     // Find the render area corners
  664.     project_view();
  665.     // Make the render list for the mesh
  666.     make_renderlist();
  667.  
  668.     camturnleftrightone = (camturnleftright)/(2*PI);
  669.     camturnleftrightshort = camturnleftrightone*65536;
  670.  
  671.     // Request matrices needed for local machine
  672.     make_dolist();
  673.     order_dolist();
  674. }
  675.  
  676. //--------------------------------------------------------------------------------------------
  677. void animate_tiles()
  678. {
  679.     // This function changes the animated tile frame
  680.     if((wldframe & animtileupdateand)==0)
  681.     {
  682.         animtileframeadd = (animtileframeadd + 1) & animtileframeand;
  683.     }
  684. }
  685.  
  686. //--------------------------------------------------------------------------------------------
  687. void load_basic_textures( char *modname )
  688. {
  689.     // ZZ> This function loads the standard textures for a module
  690.     char newloadname[256];
  691.     
  692.     // Particle sprites
  693.     GLTexture_LoadA( &txTexture[0], FILENAME( "basicdat/particle.bmp" ), TRANSCOLOR );
  694.     /* PORT
  695.     txTexture[0].SetColorKey(TRANSCOLOR); */
  696.     
  697.     // Module background tiles
  698.     make_newloadname( modname, FILENAME( "gamedat/tile0.bmp" ), newloadname );
  699.     GLTexture_LoadA( &txTexture[1], newloadname, TRANSCOLOR );
  700.     /* PORT        txTexture[1].SetColorKey(TRANSCOLOR); */
  701.     make_newloadname( modname, FILENAME( "gamedat/tile1.bmp" ), newloadname );
  702.     GLTexture_LoadA(  &txTexture[2], newloadname, TRANSCOLOR );
  703.     /* PORT        txTexture[2].SetColorKey(TRANSCOLOR); */
  704.     make_newloadname( modname, FILENAME( "gamedat/tile2.bmp" ), newloadname );
  705.     GLTexture_LoadA( &txTexture[3], newloadname, TRANSCOLOR );
  706.     /* PORT        txTexture[3].SetColorKey(TRANSCOLOR); */
  707.     make_newloadname( modname, FILENAME( "gamedat/tile3.bmp" ), newloadname );
  708.     GLTexture_LoadA( &txTexture[4], newloadname, TRANSCOLOR );
  709.     /* PORT        txTexture[4].SetColorKey(TRANSCOLOR); */
  710.     
  711.     // Water textures
  712.     make_newloadname( modname, FILENAME( "gamedat/watertop.bmp" ), newloadname );
  713.     GLTexture_Load( &txTexture[5], newloadname);
  714.     make_newloadname( modname, FILENAME( "gamedat/waterlow.bmp" ), newloadname );
  715.     GLTexture_Load( &txTexture[6], newloadname );// This is also used as far background
  716.     
  717.     
  718.     // Texture 7 is the phong map
  719.     if ( phongon )
  720.     {
  721.         make_newloadname( modname, FILENAME( "gamedat/phong.bmp" ), newloadname );
  722.         GLTexture_Load( &txTexture[7], newloadname );
  723.     }
  724.     
  725. }
  726.  
  727. //--------------------------------------------------------------------------------------------
  728. unsigned short action_number()
  729. {
  730.     // ZZ> This function returns the number of the action in cFrameName, or
  731.     //     it returns NOACTION if it could not find a match
  732.     int cnt;
  733.     char first, second;
  734.  
  735.  
  736.     first = cFrameName[0];
  737.     second = cFrameName[1];
  738.     for (cnt = 0; cnt < MAXACTION; cnt++)
  739.     {
  740.         if(first == cActionName[cnt][0] && second == cActionName[cnt][1])
  741.             return cnt;
  742.     }
  743.  
  744.     return NOACTION;
  745. }
  746.  
  747. //--------------------------------------------------------------------------------------------
  748. unsigned short action_frame()
  749. {
  750.     // ZZ> This function returns the frame number in the third and fourth characters
  751.     //     of cFrameName
  752.     int number;
  753.     sscanf(&cFrameName[2], "%d", &number);
  754.     return number;
  755. }
  756.  
  757. //--------------------------------------------------------------------------------------------
  758. unsigned short test_frame_name(char letter)
  759. {
  760.     // ZZ> This function returns TRUE if the 4th, 5th, 6th, or 7th letters
  761.     //     of the frame name matches the input argument
  762.     if(cFrameName[4]==letter) return TRUE;
  763.     if(cFrameName[4]==0) return FALSE;
  764.     if(cFrameName[5]==letter) return TRUE;
  765.     if(cFrameName[5]==0) return FALSE;
  766.     if(cFrameName[6]==letter) return TRUE;
  767.     if(cFrameName[6]==0) return FALSE;
  768.     if(cFrameName[7]==letter) return TRUE;
  769.     return FALSE;
  770. }
  771.  
  772. //--------------------------------------------------------------------------------------------
  773. void action_copy_correct(int object, unsigned short actiona, unsigned short actionb)
  774. {
  775.     // ZZ> This function makes sure both actions are valid if either of them
  776.     //     are valid.  It will copy start and ends to mirror the valid action.
  777.     if(madactionvalid[object][actiona]==madactionvalid[object][actionb])
  778.     {
  779.         // They are either both valid or both invalid, in either case we can't help
  780.     }
  781.     else
  782.     {
  783.         // Fix the invalid one
  784.         if(madactionvalid[object][actiona]==FALSE)
  785.         {
  786.             // Fix actiona
  787.             madactionvalid[object][actiona] = TRUE;
  788.             madactionstart[object][actiona] = madactionstart[object][actionb];
  789.             madactionend[object][actiona] = madactionend[object][actionb];
  790.         }
  791.         else
  792.         {
  793.             // Fix actionb
  794.             madactionvalid[object][actionb] = TRUE;
  795.             madactionstart[object][actionb] = madactionstart[object][actiona];
  796.             madactionend[object][actionb] = madactionend[object][actiona];
  797.         }
  798.     }
  799. }
  800.  
  801. //--------------------------------------------------------------------------------------------
  802. void get_walk_frame(int object, int lip, int action)
  803. {
  804.     // ZZ> This helps make walking look right
  805.     int frame = 0;
  806.     int framesinaction = madactionend[object][action]-madactionstart[object][action];
  807.     
  808.     while(frame < 16)
  809.     {
  810.         int framealong = 0;
  811.         if(framesinaction > 0)
  812.         {
  813.             framealong = ((frame*framesinaction/16) + 2)%framesinaction;
  814.         }
  815.         madframeliptowalkframe[object][lip][frame]=madactionstart[object][action]+framealong;
  816.         frame++;
  817.     }
  818. }
  819.  
  820. //--------------------------------------------------------------------------------------------
  821. void get_framefx(int frame)
  822. {
  823.     // ZZ> This function figures out the IFrame invulnerability, and Attack, Grab, and
  824.     //     Drop timings
  825.     unsigned short fx = 0;
  826.  
  827.     if(test_frame_name('I'))
  828.         fx=fx|MADFXINVICTUS;
  829.     if(test_frame_name('L'))
  830.     {
  831.         if(test_frame_name('A'))
  832.             fx=fx|MADFXACTLEFT;
  833.         if(test_frame_name('G'))
  834.             fx=fx|MADFXGRABLEFT;
  835.         if(test_frame_name('D'))
  836.             fx=fx|MADFXDROPLEFT;
  837.         if(test_frame_name('C'))
  838.             fx=fx|MADFXCHARLEFT;
  839.     }
  840.     if(test_frame_name('R'))
  841.     {
  842.         if(test_frame_name('A'))
  843.             fx=fx|MADFXACTRIGHT;
  844.         if(test_frame_name('G'))
  845.             fx=fx|MADFXGRABRIGHT;
  846.         if(test_frame_name('D'))
  847.             fx=fx|MADFXDROPRIGHT;
  848.         if(test_frame_name('C'))
  849.             fx=fx|MADFXCHARRIGHT;
  850.     }
  851.     if(test_frame_name('S'))
  852.         fx=fx|MADFXSTOP;
  853.     if(test_frame_name('F'))
  854.         fx=fx|MADFXFOOTFALL;
  855.     if(test_frame_name('P'))
  856.         fx=fx|MADFXPOOF;
  857.     madframefx[frame] = fx;
  858. }
  859.  
  860. //--------------------------------------------------------------------------------------------
  861. void make_framelip(int object, int action)
  862. {
  863.     // ZZ> This helps make walking look right
  864.     int frame, framesinaction;
  865.  
  866.     if(madactionvalid[object][action])
  867.     {
  868.         framesinaction = madactionend[object][action]-madactionstart[object][action];
  869.         frame = madactionstart[object][action];
  870.         while(frame < madactionend[object][action])
  871.         {
  872.             madframelip[frame] = (frame-madactionstart[object][action])*15/framesinaction;
  873.             madframelip[frame] = (madframelip[frame])&15;
  874.             frame++;
  875.         }
  876.     }
  877. }
  878.  
  879. //--------------------------------------------------------------------------------------------
  880. void get_actions(int object)
  881. {
  882.     // ZZ> This function creates the frame lists for each action based on the
  883.     //     name of each md2 frame in the model
  884.     int frame, framesinaction;
  885.     int action, lastaction;
  886.  
  887.  
  888.     // Clear out all actions and reset to invalid
  889.     action = 0;
  890.     while(action < MAXACTION)
  891.     {
  892.         madactionvalid[object][action]=FALSE;
  893.         action++;
  894.     }
  895.  
  896.  
  897.     // Set the primary dance action to be the first frame, just as a default
  898.     madactionvalid[object][ACTIONDA]=TRUE;
  899.     madactionstart[object][ACTIONDA]=madframestart[object];
  900.     madactionend[object][ACTIONDA]=madframestart[object]+1;
  901.  
  902.  
  903.     // Now go huntin' to see what each frame is, look for runs of same action
  904.     //printf("DIAG: ripping md2\n");
  905.     rip_md2_frame_name(0);
  906.     //printf("DIAG: done ripping md2\n");
  907.     lastaction = action_number();  framesinaction = 0;
  908.     frame = 0;
  909.     while(frame < madframes[object])
  910.     {
  911.         rip_md2_frame_name(frame);
  912.         action = action_number();
  913.         if(lastaction == action)
  914.         {
  915.             framesinaction++;
  916.         }
  917.         else
  918.         {
  919.             // Write the old action
  920.             if(lastaction < MAXACTION)
  921.             {
  922.                 madactionvalid[object][lastaction]=TRUE;
  923.                 madactionstart[object][lastaction]=madframestart[object]+frame-framesinaction;
  924.                 madactionend[object][lastaction]=madframestart[object]+frame;
  925.             }
  926.             framesinaction = 1;
  927.             lastaction = action;
  928.         }
  929.         get_framefx(madframestart[object]+frame);
  930.         frame++;
  931.     }
  932.     // Write the old action
  933.     if(lastaction < MAXACTION)
  934.     {
  935.         madactionvalid[object][lastaction]=TRUE;
  936.         madactionstart[object][lastaction]=madframestart[object]+frame-framesinaction;
  937.         madactionend[object][lastaction]=madframestart[object]+frame;
  938.     }
  939.  
  940.     // Make sure actions are made valid if a similar one exists
  941.     action_copy_correct(object, ACTIONDA, ACTIONDB);  // All dances should be safe
  942.     action_copy_correct(object, ACTIONDB, ACTIONDC);
  943.     action_copy_correct(object, ACTIONDC, ACTIONDD);
  944.     action_copy_correct(object, ACTIONDB, ACTIONDC);
  945.     action_copy_correct(object, ACTIONDA, ACTIONDB);
  946.         action_copy_correct(object, ACTIONUA, ACTIONUB);
  947.         action_copy_correct(object, ACTIONUB, ACTIONUC);
  948.         action_copy_correct(object, ACTIONUC, ACTIONUD);
  949.     action_copy_correct(object, ACTIONTA, ACTIONTB);
  950.     action_copy_correct(object, ACTIONTC, ACTIONTD);
  951.         action_copy_correct(object, ACTIONCA, ACTIONCB);
  952.         action_copy_correct(object, ACTIONCC, ACTIONCD);
  953.     action_copy_correct(object, ACTIONSA, ACTIONSB);
  954.     action_copy_correct(object, ACTIONSC, ACTIONSD);
  955.         action_copy_correct(object, ACTIONBA, ACTIONBB);
  956.         action_copy_correct(object, ACTIONBC, ACTIONBD);
  957.     action_copy_correct(object, ACTIONLA, ACTIONLB);
  958.     action_copy_correct(object, ACTIONLC, ACTIONLD);
  959.         action_copy_correct(object, ACTIONXA, ACTIONXB);
  960.         action_copy_correct(object, ACTIONXC, ACTIONXD);
  961.     action_copy_correct(object, ACTIONFA, ACTIONFB);
  962.     action_copy_correct(object, ACTIONFC, ACTIONFD);
  963.         action_copy_correct(object, ACTIONPA, ACTIONPB);
  964.         action_copy_correct(object, ACTIONPC, ACTIONPD);
  965.     action_copy_correct(object, ACTIONZA, ACTIONZB);
  966.     action_copy_correct(object, ACTIONZC, ACTIONZD);
  967.         action_copy_correct(object, ACTIONWA, ACTIONWB);
  968.         action_copy_correct(object, ACTIONWB, ACTIONWC);
  969.         action_copy_correct(object, ACTIONWC, ACTIONWD);
  970.         action_copy_correct(object, ACTIONDA, ACTIONWD);  // All walks should be safe
  971.         action_copy_correct(object, ACTIONWC, ACTIONWD);
  972.         action_copy_correct(object, ACTIONWB, ACTIONWC);
  973.         action_copy_correct(object, ACTIONWA, ACTIONWB);
  974.     action_copy_correct(object, ACTIONJA, ACTIONJB);
  975.     action_copy_correct(object, ACTIONJB, ACTIONJC);
  976.     action_copy_correct(object, ACTIONDA, ACTIONJC);    // All jumps should be safe
  977.     action_copy_correct(object, ACTIONJB, ACTIONJC);
  978.     action_copy_correct(object, ACTIONJA, ACTIONJB);
  979.         action_copy_correct(object, ACTIONHA, ACTIONHB);
  980.         action_copy_correct(object, ACTIONHB, ACTIONHC);
  981.         action_copy_correct(object, ACTIONHC, ACTIONHD);
  982.         action_copy_correct(object, ACTIONHB, ACTIONHC);
  983.         action_copy_correct(object, ACTIONHA, ACTIONHB);
  984.     action_copy_correct(object, ACTIONKA, ACTIONKB);
  985.     action_copy_correct(object, ACTIONKB, ACTIONKC);
  986.     action_copy_correct(object, ACTIONKC, ACTIONKD);
  987.     action_copy_correct(object, ACTIONKB, ACTIONKC);
  988.     action_copy_correct(object, ACTIONKA, ACTIONKB);
  989.         action_copy_correct(object, ACTIONMH, ACTIONMI);
  990.     action_copy_correct(object, ACTIONDA, ACTIONMM);
  991.     action_copy_correct(object, ACTIONMM, ACTIONMN);
  992.  
  993.     
  994.     // Create table for doing transition from one type of walk to another...
  995.     // Clear 'em all to start
  996.     for (frame = 0; frame < madframes[object]; frame++)
  997.         madframelip[frame+madframestart[object]] = 0;
  998.  
  999.     // Need to figure out how far into action each frame is
  1000.     make_framelip(object, ACTIONWA);
  1001.     make_framelip(object, ACTIONWB);
  1002.     make_framelip(object, ACTIONWC);
  1003.     // Now do the same, in reverse, for walking animations
  1004.     get_walk_frame(object, LIPDA, ACTIONDA);
  1005.     get_walk_frame(object, LIPWA, ACTIONWA);
  1006.     get_walk_frame(object, LIPWB, ACTIONWB);
  1007.     get_walk_frame(object, LIPWC, ACTIONWC);
  1008. }
  1009.  
  1010. //--------------------------------------------------------------------------------------------
  1011. void make_mad_equally_lit(int model)
  1012. {
  1013.     // ZZ> This function makes ultra low poly models look better
  1014.     int frame, cnt, vert;
  1015.  
  1016.     if(madused[model])
  1017.     {
  1018.         frame = madframestart[model];
  1019.         for (cnt = 0; cnt < madframes[model]; cnt++)
  1020.         {
  1021.             vert = 0;
  1022.             while(vert < MAXVERTICES)
  1023.             {
  1024.                 madvrta[frame][vert]=EQUALLIGHTINDEX;
  1025.                 vert++;
  1026.             }
  1027.             frame++;
  1028.         }
  1029.     }
  1030. }
  1031.  
  1032. //--------------------------------------------------------------------------------------------
  1033. void check_copy(char* loadname, int object)
  1034. {
  1035.     // ZZ> This function copies a model's actions
  1036.     FILE *fileread;
  1037.     int actiona, actionb;
  1038.     char szOne[16], szTwo[16];
  1039.  
  1040.  
  1041.     madmsgstart[object] = 0;
  1042.     fileread = fopen(loadname, "r");
  1043.     if(fileread)
  1044.     {
  1045.         while(goto_colon_yesno(fileread))
  1046.         {
  1047.             fscanf(fileread, "%s%s", szOne, szTwo);
  1048.             actiona = what_action(szOne[0]);
  1049.             actionb = what_action(szTwo[0]);
  1050.             action_copy_correct(object, actiona, actionb);
  1051.             action_copy_correct(object, actiona+1, actionb+1);
  1052.             action_copy_correct(object, actiona+2, actionb+2);
  1053.             action_copy_correct(object, actiona+3, actionb+3);
  1054.         }
  1055.         fclose(fileread);
  1056.     }
  1057. }
  1058.  
  1059. //--------------------------------------------------------------------------------------------
  1060. int load_one_object(int skin, char* tmploadname)
  1061. {
  1062.     // ZZ> This function loads one object and returns the number of skins
  1063.     int object;
  1064.     int numskins, numicon;
  1065.     char newloadname[256];
  1066.     char wavename[256];
  1067.     int cnt;
  1068.     char ctmp;
  1069.  
  1070.     //printf(" DIAG: entered load_one_object\n");
  1071.     // Load the object data file and get the object number
  1072.     make_newloadname(tmploadname, "/data.txt", newloadname);
  1073.     object = load_one_character_profile(newloadname);
  1074.  
  1075.  
  1076.     //printf(" DIAG: making up model name\n");
  1077.     // Make up a name for the model...  IMPORT\TEMP0000.OBJ
  1078.     cnt = 0;
  1079.     ctmp = tmploadname[cnt];
  1080.     while(ctmp != 0 && cnt < 127)
  1081.     {
  1082.         madname[object][cnt] = ctmp;
  1083.         cnt++;
  1084.         ctmp = tmploadname[cnt];
  1085.     }
  1086.     madname[object][cnt]=0;
  1087.  
  1088.  
  1089.     //printf(" DIAG: appending slash\n");
  1090.     // Append a slash to the tmploadname
  1091.     sprintf(newloadname, "%s", tmploadname);
  1092.     sprintf(tmploadname, "%s/", newloadname);
  1093.  
  1094.  
  1095.     // Load the AI script for this object
  1096.     make_newloadname(tmploadname, "script.txt", newloadname);
  1097.     //printf(" DIAG: load ai script %s\n",newloadname);
  1098.     if(load_ai_script(newloadname))
  1099.     {
  1100.         // Create a reference to the one we just loaded
  1101.         madai[object]=iNumAis-1;
  1102.     }
  1103.  
  1104.  
  1105.     //printf(" DIAG: load object model\n");
  1106.     // Load the object model
  1107.     make_newloadname(tmploadname, "tris.md2", newloadname);
  1108.     load_one_md2(newloadname, object);
  1109.  
  1110.  
  1111.     //printf(" DIAG: fixing lighting\n");
  1112.     // Fix lighting if need be
  1113.     if(capuniformlit[object])
  1114.     {
  1115.         make_mad_equally_lit(object);
  1116.     }
  1117.  
  1118.  
  1119.     //printf(" DIAG: creating actions\n");
  1120.     // Create the actions table for this object
  1121.     get_actions(object);
  1122.  
  1123.  
  1124.     //printf(" DIAG: copy actions\n");
  1125.     // Copy entire actions to save frame space COPY.TXT
  1126.     make_newloadname(tmploadname, "copy.txt", newloadname);
  1127.     check_copy(newloadname, object);
  1128.  
  1129.  
  1130.     //printf(" DIAG: loading messages\n");
  1131.     // Load the messages for this object
  1132.     make_newloadname(tmploadname, "message.txt", newloadname);
  1133.     load_all_messages(newloadname, object);
  1134.  
  1135.  
  1136.     //printf(" DIAG: doing random naming\n");
  1137.     // Load the random naming table for this object
  1138.     make_newloadname(tmploadname, "naming.txt", newloadname);
  1139.     read_naming(object, newloadname);
  1140.  
  1141.  
  1142.     //printf(" DIAG: loading particles\n");
  1143.     // Load the particles for this object
  1144.     for (cnt = 0; cnt < MAXPRTPIPPEROBJECT; cnt++)
  1145.     {
  1146.         sprintf(newloadname, "%spart%d.txt", tmploadname, cnt);
  1147.         load_one_particle(newloadname, object, cnt);
  1148.     }
  1149.  
  1150.  
  1151.     //printf(" DIAG: loading waves\n");
  1152.     // Load the waves for this object
  1153.     for (cnt = 0; cnt < MAXWAVE; cnt++)
  1154.     {
  1155.         sprintf(wavename, "sound%d.wav", cnt);
  1156.         make_newloadname(tmploadname, wavename, newloadname);
  1157.         capwaveindex[object][cnt] = load_one_wave(newloadname);
  1158.     }
  1159.  
  1160.  
  1161.     //printf(" DIAG: loading enchantments\n");
  1162.     // Load the enchantment for this object
  1163.     make_newloadname(tmploadname, "enchant.txt", newloadname);
  1164.     load_one_enchant_type(newloadname, object);
  1165.  
  1166.  
  1167.     //printf(" DIAG: loading skins and icons (PORTED EXCEPT ALPHA)\n");
  1168.     // Load the skins and icons
  1169.     madskinstart[object] = skin;
  1170.     numskins = 0;
  1171.     numicon = 0;
  1172.     make_newloadname(tmploadname, "tris0.bmp", newloadname);
  1173.     
  1174.     /*PORT ALPHA STUFF*/
  1175.     GLTexture_LoadA( &txTexture[skin+numskins], newloadname, TRANSCOLOR );
  1176.     if ( GLTexture_GetTextureID( &txTexture[skin+numskins] ) != 0 )
  1177.     {
  1178.         //txTexture[skin+numskins].SetColorKey(TRANSCOLOR);  // Port to new alpha code
  1179.         numskins++;
  1180.         make_newloadname(tmploadname, "icon0.bmp", newloadname);
  1181.         GLTexture_Load( &TxIcon[globalnumicon], newloadname );
  1182.         if ( GLTexture_GetTextureID( &TxIcon[globalnumicon] ) != 0 )
  1183.         {
  1184.             //DDSetColorKey(lpDDSIcon[globalnumicon], 0);    // Port to new alpha code
  1185.             while( numicon < numskins )
  1186.             {
  1187.                 madskintoicon[skin+numicon]=globalnumicon;
  1188.                 if(object==SPELLBOOK)  bookicon = globalnumicon;
  1189.                 numicon++;
  1190.             }
  1191.             globalnumicon++;
  1192.         }
  1193.     }
  1194.     make_newloadname(tmploadname, "tris1.bmp", newloadname);
  1195.     GLTexture_LoadA( &txTexture[skin+numskins], newloadname, TRANSCOLOR );
  1196.     if ( GLTexture_GetTextureID( &txTexture[skin+numskins] ) != 0 )
  1197.     {
  1198.         //txTexture[skin+numskins].SetColorKey(TRANSCOLOR);    // Port to new alpha code
  1199.         numskins++;
  1200.         make_newloadname(tmploadname, "icon1.bmp", newloadname);
  1201.         GLTexture_Load( &TxIcon[globalnumicon], newloadname );
  1202.         if ( GLTexture_GetTextureID( &TxIcon[globalnumicon] ) != 0 )
  1203.         {
  1204.             //DDSetColorKey(lpDDSIcon[globalnumicon], 0);    // Port to new alpha code
  1205.             while(numicon<numskins)
  1206.             {
  1207.                 madskintoicon[skin+numicon]=globalnumicon;
  1208.                 numicon++;
  1209.             }
  1210.             globalnumicon++;
  1211.         }
  1212.     }
  1213.     make_newloadname(tmploadname, "tris2.bmp", newloadname);
  1214.     GLTexture_LoadA( &txTexture[skin+numskins], newloadname, TRANSCOLOR );
  1215.     if ( GLTexture_GetTextureID( &txTexture[skin+numskins] ) != 0 )
  1216.     {
  1217.         //txTexture[skin+numskins].SetColorKey(TRANSCOLOR);    // port to new alpha code
  1218.         numskins++;
  1219.         make_newloadname(tmploadname, "icon2.bmp", newloadname);
  1220.         GLTexture_Load( &TxIcon[globalnumicon], newloadname );
  1221.         if ( GLTexture_GetTextureID( &TxIcon[globalnumicon] ) != 0 )
  1222.         {
  1223.             //DDSetColorKey(lpDDSIcon[globalnumicon], 0);    // port to new alpha code
  1224.             while(numicon<numskins)
  1225.             {
  1226.                 madskintoicon[skin+numicon]=globalnumicon;
  1227.                 numicon++;
  1228.             }
  1229.             globalnumicon++;
  1230.         }
  1231.     }
  1232.     make_newloadname(tmploadname, "tris3.bmp", newloadname);
  1233.     GLTexture_LoadA( &txTexture[skin+numskins], newloadname, TRANSCOLOR );
  1234.     if ( GLTexture_GetTextureID( &txTexture[skin+numskins] ) != 0 )
  1235.     {
  1236.         //txTexture[skin+numskins].SetColorKey(TRANSCOLOR);    // port to new alpha code
  1237.         numskins++;
  1238.         make_newloadname(tmploadname, "icon3.bmp", newloadname);
  1239.         GLTexture_Load( &TxIcon[globalnumicon], newloadname );
  1240.         if ( GLTexture_GetTextureID( &TxIcon[globalnumicon] ) != 0 )
  1241.         {
  1242.             //DDSetColorKey(lpDDSIcon[globalnumicon], 0);    // port to new alpha code
  1243.             while(numicon<numskins)
  1244.             {
  1245.                 madskintoicon[skin+numicon]=globalnumicon;
  1246.                 numicon++;
  1247.             }
  1248.             globalnumicon++;
  1249.         }
  1250.     }
  1251.     /* FINISH PORTING */
  1252.     
  1253.     madskins[object] = numskins;
  1254.     if(numskins == 0)
  1255.     {
  1256.         // If we didn't get a skin, set it to the water texture
  1257.         madskinstart[object] = 5;
  1258.         madskins[object] = 1;
  1259.     }
  1260.  
  1261.  
  1262.     //printf(" DIAG: leaving load_one_obj\n");
  1263.     return numskins;
  1264. }
  1265.  
  1266. //--------------------------------------------------------------------------------------------
  1267. void load_all_objects(char *modname)
  1268. {
  1269.     // ZZ> This function loads a module's objects
  1270.     char *filehandle;
  1271.     BOOL keeplooking;
  1272.     FILE* fileread;
  1273.     char newloadname[256];
  1274.     char filename[256];
  1275.     int cnt;
  1276.     int skin;
  1277.     int importplayer;
  1278.  
  1279.  
  1280.     // Log all of the script errors
  1281.     //printf(" DIAG: opening ParseErr\n");
  1282.     globalparseerr = fopen(FILENAME("basicdat/ParseErr.txt"), "w");
  1283.     parseerror = FALSE;
  1284.     fprintf(globalparseerr, "This file documents typos found in the AI scripts...\n");
  1285.  
  1286.     // Clear the import slots...
  1287.     //printf(" DIAG: Clearing import slots\n");
  1288.     for (cnt = 0; cnt < MAXMODEL; cnt++)
  1289.         capimportslot[cnt] = 10000;
  1290.     
  1291.     // Load the import directory
  1292.     //printf(" DIAG: loading inport dir\n");
  1293.     importplayer = -1;
  1294.     skin = 8;  // Character skins start at 8...  Trust me
  1295.     if(importvalid)
  1296.     {
  1297.         for (cnt = 0; cnt < MAXIMPORT; cnt++)
  1298.         {
  1299.             sprintf(filename, "import/temp%04d.obj", cnt);
  1300.             // Make sure the object exists...
  1301.             sprintf(newloadname, "%s/data.txt", filename);
  1302.             fileread = fopen( FILENAME(newloadname), "r");
  1303.             if(fileread)
  1304.             {
  1305.           //printf("Found import slot %04d\n", cnt);
  1306.  
  1307.                 fclose(fileread);
  1308.                 // Load it...
  1309.                 if((cnt % 9) == 0)
  1310.                 {
  1311.                     importplayer++;
  1312.                 }
  1313.                 importobject = ((importplayer)*9)+(cnt%9);
  1314.                 capimportslot[importobject] = cnt;
  1315.                 skin += load_one_object(skin, filename);
  1316.             }
  1317.         }
  1318.     }
  1319.     //printf(" DIAG: emptying directory\n");
  1320.     //empty_import_directory();  // Free up that disk space...
  1321.  
  1322.     // Search for .obj directories and load them
  1323.     //printf(" DIAG: Searching for .objs\n");
  1324.     importobject = -100;
  1325.     make_newloadname(modname, "objects/*.obj", newloadname);
  1326.     filehandle= DirGetFirst( FILENAME(newloadname) );
  1327.     make_newloadname(modname, "objects/", newloadname);
  1328.     keeplooking = 1;
  1329.     if(filehandle!= NULL)
  1330.     {
  1331.         while(keeplooking)
  1332.         {
  1333.             //printf(" DIAG: keeplooking\n");
  1334.             sprintf(filename, "%s%s", newloadname, filehandle);
  1335.             skin += load_one_object(skin, filename);
  1336.             keeplooking = (DirGetNext()!=NULL);
  1337.         }
  1338.     }
  1339.     //printf(" DIAG: Done Searching for .objs\n");
  1340.     fclose(globalparseerr);
  1341. }
  1342.  
  1343. //--------------------------------------------------------------------------------------------
  1344. void load_bars(char* szBitmap)
  1345. {
  1346.     // ZZ> This function loads the status bar bitmap
  1347.     int cnt;
  1348.     
  1349.     GLTexture_LoadA(&TxBars, szBitmap, 0);
  1350.     if (&TxBars == NULL)
  1351.         general_error(0, 0, "NO BARS!!!");
  1352.  
  1353.     
  1354.     // Make the blit rectangles
  1355.     for (cnt = 0; cnt < NUMBAR; cnt++)
  1356.     {
  1357.         tabrect[cnt].left = 0;
  1358.         tabrect[cnt].right = TABX;
  1359.         tabrect[cnt].top = cnt*BARY;
  1360.         tabrect[cnt].bottom = (cnt+1)*BARY;
  1361.         barrect[cnt].left = TABX;
  1362.         barrect[cnt].right = BARX;  // This is reset whenever a bar is drawn
  1363.         barrect[cnt].top = tabrect[cnt].top;
  1364.         barrect[cnt].bottom = tabrect[cnt].bottom;
  1365.     }
  1366.  
  1367.     // Set the transparent color
  1368.     //DDSetColorKey(lpDDSBars, 0); port to new alpha code
  1369. }
  1370.  
  1371. //--------------------------------------------------------------------------------------------
  1372. void load_map(char* szModule, int sysmem)
  1373. {
  1374.     // ZZ> This function loads the map bitmap and the blip bitmap
  1375.     char szMap[256];
  1376.     
  1377.     // Turn it all off
  1378.     mapon = FALSE;
  1379.     youarehereon = FALSE;
  1380.     numblip = 0;
  1381.  
  1382.     // Load the images
  1383.     sprintf(szMap, "%sgamedat/plan.bmp", szModule);
  1384.     GLTexture_Load(&TxMap, FILENAME( szMap ));
  1385.     if (GLTexture_GetTextureID == 0)
  1386.         general_error(0, 0, "NO MAP!!!");
  1387.     
  1388.     // Set up the rectangles
  1389.     maprect.left   = 0;
  1390.     maprect.right  = MAPSIZE;
  1391.     maprect.top    = 0;
  1392.     maprect.bottom = MAPSIZE;
  1393.     
  1394. }
  1395.  
  1396. //--------------------------------------------------------------------------------------------
  1397. void load_font(char* szBitmap, char* szSpacing, int sysmem)
  1398. {
  1399.     // ZZ> This function loads the font bitmap and sets up the coordinates
  1400.     //     of each font on that bitmap...  Bitmap must have 16x6 fonts
  1401.     int cnt, i, x, y, xsize, ysize, xdiv, ydiv;
  1402.     int xstt, ystt;
  1403.     int xspacing, yspacing;
  1404.     unsigned char cTmp;
  1405.     FILE *fileread;
  1406.  
  1407.  
  1408.     GLTexture_LoadA(&TxFont, szBitmap, 0);
  1409.     if(GLTexture_GetTextureID(&TxFont) == 0)
  1410.          general_error(0, 0, "NO FONTS!!!");
  1411.  
  1412.  
  1413.     // Clear out the conversion table
  1414.     for (cnt = 0; cnt < 256; cnt++)
  1415.         asciitofont[cnt] = 0;
  1416.     
  1417.  
  1418.     // Get the size of the bitmap
  1419.     xsize = GLTexture_GetImageWidth(&TxFont);
  1420.     ysize = GLTexture_GetImageHeight(&TxFont);
  1421.     if(xsize == 0 || ysize == 0)
  1422.          general_error(xsize, ysize, "BAD FONT SIZE!!!");
  1423.     
  1424.  
  1425.     // Figure out the general size of each font
  1426.     ydiv = ysize/NUMFONTY;
  1427.     xdiv = xsize/NUMFONTX;
  1428.  
  1429.  
  1430.     // Figure out where each font is and its spacing
  1431.     fileread = fopen(FILENAME(szSpacing), "r");
  1432.     if(fileread==NULL)
  1433.          general_error(xsize, ysize, "FONT SPACING NOT AVAILABLE!!!");
  1434.     
  1435.     globalname = szSpacing;
  1436.     cnt = 0;
  1437.     y = 0;
  1438.     
  1439.     xstt = 0;
  1440.     ystt = 0;
  1441.  
  1442.     // Uniform font height is at the top
  1443.     goto_colon(fileread);
  1444.     fscanf(fileread, "%d", &yspacing);
  1445.     fontoffset = scry - yspacing;
  1446.  
  1447.     // Mark all as unused
  1448.     for (i=0; i < 255; i++) 
  1449.         asciitofont[i] = 255;
  1450.  
  1451.     for (i=0; i < 96; i++) 
  1452.     {
  1453.         goto_colon(fileread);
  1454.         fscanf(fileread, "%c%d", &cTmp, &xspacing);
  1455.         if (asciitofont[cTmp] == 255) asciitofont[cTmp] = cnt;
  1456.         if (xstt+xspacing+1 > 255) 
  1457.         {
  1458.           xstt = 0;
  1459.           ystt += yspacing;
  1460.         }
  1461.         fontrect[cnt].x = xstt;
  1462.         fontrect[cnt].w = xspacing;
  1463.         fontrect[cnt].y = ystt;
  1464.         fontrect[cnt].h = yspacing-2;
  1465.         fontxspacing[cnt] = xspacing+1;
  1466.         xstt += xspacing+1;
  1467.         cnt++;
  1468.         x++;
  1469.     }
  1470.     fclose(fileread);
  1471.  
  1472.  
  1473.     // Space between lines
  1474.     fontyspacing = (yspacing>>1)+FONTADD;
  1475. }
  1476.  
  1477. //--------------------------------------------------------------------------------------------
  1478. void make_water()
  1479. {
  1480.     // ZZ> This function sets up water movements
  1481.     int layer, frame, point, mode, cnt;
  1482.     float temp;
  1483.     unsigned char spek;
  1484.  
  1485.  
  1486.     layer = 0;
  1487.         while(layer < numwaterlayer)
  1488.     {
  1489.         if(waterlight)  waterlayeralpha[layer] = 255;  // Some cards don't support alpha lights...
  1490.         waterlayeru[layer] = 0;
  1491.         waterlayerv[layer] = 0;
  1492.         frame = 0;
  1493.         while(frame < MAXWATERFRAME)
  1494.         {
  1495.             // Do first mode
  1496.             mode = 0;
  1497.             for (point = 0; point < WATERPOINTS; point++)
  1498.             {
  1499.                 temp = sin((frame*2*PI/MAXWATERFRAME)+(2*PI*point/WATERPOINTS)+(2*PI*layer/MAXWATERLAYER));
  1500.                 waterlayerzadd[layer][frame][mode][point] = temp*waterlayeramp[layer];
  1501.                 waterlayercolor[layer][frame][mode][point] = (waterlightlevel[layer]*(temp+1.0))+waterlightadd[layer];
  1502.             }
  1503.             
  1504.             // Now mirror and copy data to other three modes
  1505.             mode++;
  1506.             waterlayerzadd[layer][frame][mode][0] = waterlayerzadd[layer][frame][0][1];
  1507.             waterlayercolor[layer][frame][mode][0] = waterlayercolor[layer][frame][0][1];
  1508.             waterlayerzadd[layer][frame][mode][1] = waterlayerzadd[layer][frame][0][0];
  1509.             waterlayercolor[layer][frame][mode][1] = waterlayercolor[layer][frame][0][0];
  1510.             waterlayerzadd[layer][frame][mode][2] = waterlayerzadd[layer][frame][0][3];
  1511.             waterlayercolor[layer][frame][mode][2] = waterlayercolor[layer][frame][0][3];
  1512.             waterlayerzadd[layer][frame][mode][3] = waterlayerzadd[layer][frame][0][2];
  1513.             waterlayercolor[layer][frame][mode][3] = waterlayercolor[layer][frame][0][2];
  1514.             mode++;
  1515.             waterlayerzadd[layer][frame][mode][0] = waterlayerzadd[layer][frame][0][3];
  1516.             waterlayercolor[layer][frame][mode][0] = waterlayercolor[layer][frame][0][3];
  1517.             waterlayerzadd[layer][frame][mode][1] = waterlayerzadd[layer][frame][0][2];
  1518.             waterlayercolor[layer][frame][mode][1] = waterlayercolor[layer][frame][0][2];
  1519.             waterlayerzadd[layer][frame][mode][2] = waterlayerzadd[layer][frame][0][1];
  1520.             waterlayercolor[layer][frame][mode][2] = waterlayercolor[layer][frame][0][1];
  1521.             waterlayerzadd[layer][frame][mode][3] = waterlayerzadd[layer][frame][0][0];
  1522.             waterlayercolor[layer][frame][mode][3] = waterlayercolor[layer][frame][0][0];
  1523.             mode++;
  1524.             waterlayerzadd[layer][frame][mode][0] = waterlayerzadd[layer][frame][0][2];
  1525.             waterlayercolor[layer][frame][mode][0] = waterlayercolor[layer][frame][0][2];
  1526.             waterlayerzadd[layer][frame][mode][1] = waterlayerzadd[layer][frame][0][3];
  1527.             waterlayercolor[layer][frame][mode][1] = waterlayercolor[layer][frame][0][3];
  1528.             waterlayerzadd[layer][frame][mode][2] = waterlayerzadd[layer][frame][0][0];
  1529.             waterlayercolor[layer][frame][mode][2] = waterlayercolor[layer][frame][0][0];
  1530.             waterlayerzadd[layer][frame][mode][3] = waterlayerzadd[layer][frame][0][1];
  1531.             waterlayercolor[layer][frame][mode][3] = waterlayercolor[layer][frame][0][1];
  1532.             frame++;
  1533.         }
  1534.         layer++;
  1535.     }
  1536.  
  1537.  
  1538.     // Calculate specular highlights
  1539.     spek = 0;
  1540.     for (cnt = 0; cnt < 256; cnt++)
  1541.     {
  1542.         spek = 0;
  1543.         if(cnt > waterspekstart)
  1544.         {
  1545.             temp = cnt-waterspekstart;
  1546.             temp = temp/(256-waterspekstart);
  1547.             temp = temp*temp;
  1548.             spek = temp*waterspeklevel;
  1549.         }
  1550.  
  1551.         // [claforte] Probably need to replace this with a 
  1552.         //            glColor4f(spek/256.0f, spek/256.0f, spek/256.0f, 1.0f) call:
  1553.  
  1554.         if(1) // PORT: if(shading == D3DSHADE_FLAT)
  1555.           waterspek[cnt] = 0;
  1556.         else
  1557.           waterspek[cnt] = 0xff000000|(spek<<16)|(spek<<8)|(spek);
  1558.     }
  1559. }
  1560.  
  1561. //--------------------------------------------------------------------------------------------
  1562. void read_wawalite(char *modname)
  1563. {
  1564.     // ZZ> This function sets up water and lighting for the module
  1565.     char newloadname[256];
  1566.     FILE* fileread;
  1567.     float lx, ly, lz, la;
  1568.     float fTmp;
  1569.     char cTmp;
  1570.     int iTmp;
  1571.  
  1572.     make_newloadname(modname, "gamedat/wawalite.txt", newloadname);
  1573.     fileread = fopen(FILENAME(newloadname), "r");
  1574.     if(fileread)
  1575.     {
  1576.         goto_colon(fileread);
  1577.         //  !!!BAD!!!
  1578.         //  Random map...
  1579.         //  If someone else wants to handle this, here are some thoughts for approaching
  1580.         //  it.  The .MPD file for the level should give the basic size of the map.  Use
  1581.         //  a standard tile set like the Palace modules.  Only use objects that are in
  1582.         //  the module's object directory, and only use some of them.  Imagine several Rock
  1583.         //  Moles eating through a stone filled level to make a path from the entrance to
  1584.         //  the exit.  Door placement will be difficult.
  1585.         //  !!!BAD!!!
  1586.  
  1587.  
  1588.         // Read water data first
  1589.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  numwaterlayer = iTmp;
  1590.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  waterspekstart = iTmp;
  1591.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  waterspeklevel = iTmp;
  1592.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  waterdouselevel = iTmp;
  1593.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  watersurfacelevel = iTmp;
  1594.         goto_colon(fileread);  cTmp = get_first_letter(fileread);
  1595.             if(cTmp=='T' || cTmp=='t')  waterlight = TRUE;
  1596.             else waterlight = FALSE;
  1597.         goto_colon(fileread);  cTmp = get_first_letter(fileread);
  1598.             wateriswater = FALSE;
  1599.             if(cTmp=='T' || cTmp=='t')  wateriswater = TRUE;
  1600.         goto_colon(fileread);  cTmp = get_first_letter(fileread);
  1601.             if((cTmp=='T' || cTmp=='t') && overlayvalid)  overlayon = TRUE;
  1602.             else overlayon = FALSE;
  1603.         goto_colon(fileread);  cTmp = get_first_letter(fileread);
  1604.             if((cTmp=='T' || cTmp=='t') && backgroundvalid)  clearson = FALSE;
  1605.             else clearson = TRUE;
  1606.         goto_colon(fileread);  fscanf(fileread, "%f", &fTmp);  waterlayerdistx[0] = fTmp;
  1607.         goto_colon(fileread);  fscanf(fileread, "%f", &fTmp);  waterlayerdisty[0] = fTmp;
  1608.         goto_colon(fileread);  fscanf(fileread, "%f", &fTmp);  waterlayerdistx[1] = fTmp;
  1609.         goto_colon(fileread);  fscanf(fileread, "%f", &fTmp);  waterlayerdisty[1] = fTmp;
  1610.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  foregroundrepeat = iTmp;
  1611.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  backgroundrepeat = iTmp;
  1612.  
  1613.  
  1614.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  waterlayerz[0] = iTmp;
  1615.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  waterlayeralpha[0] = iTmp;
  1616.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  waterlayerframeadd[0] = iTmp;
  1617.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  waterlightlevel[0] = iTmp;
  1618.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  waterlightadd[0] = iTmp;
  1619.         goto_colon(fileread);  fscanf(fileread, "%f", &fTmp);  waterlayeramp[0] = fTmp;
  1620.         goto_colon(fileread);  fscanf(fileread, "%f", &fTmp);  waterlayeruadd[0] = fTmp;
  1621.         goto_colon(fileread);  fscanf(fileread, "%f", &fTmp);  waterlayervadd[0] = fTmp;
  1622.  
  1623.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  waterlayerz[1] = iTmp;
  1624.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  waterlayeralpha[1] = iTmp;
  1625.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  waterlayerframeadd[1] = iTmp;
  1626.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  waterlightlevel[1] = iTmp;
  1627.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  waterlightadd[1] = iTmp;
  1628.         goto_colon(fileread);  fscanf(fileread, "%f", &fTmp);  waterlayeramp[1] = fTmp;
  1629.         goto_colon(fileread);  fscanf(fileread, "%f", &fTmp);  waterlayeruadd[1] = fTmp;
  1630.         goto_colon(fileread);  fscanf(fileread, "%f", &fTmp);  waterlayervadd[1] = fTmp;
  1631.  
  1632.         waterlayeru[0] = 0;
  1633.         waterlayerv[0] = 0;
  1634.         waterlayeru[1] = 0;
  1635.         waterlayerv[1] = 0;
  1636.         waterlayerframe[0] = rand()&WATERFRAMEAND;
  1637.         waterlayerframe[1] = rand()&WATERFRAMEAND;
  1638.         // Read light data second
  1639.         goto_colon(fileread);  fscanf(fileread, "%f", &fTmp);  lx = fTmp;
  1640.         goto_colon(fileread);  fscanf(fileread, "%f", &fTmp);  ly = fTmp;
  1641.         goto_colon(fileread);  fscanf(fileread, "%f", &fTmp);  lz = fTmp;
  1642.         goto_colon(fileread);  fscanf(fileread, "%f", &fTmp);  la = fTmp;
  1643.         // Read tile data third
  1644.         goto_colon(fileread);  fscanf(fileread, "%f", &fTmp);  hillslide = fTmp;
  1645.         goto_colon(fileread);  fscanf(fileread, "%f", &fTmp);  slippyfriction = fTmp;
  1646.         goto_colon(fileread);  fscanf(fileread, "%f", &fTmp);  airfriction = fTmp;
  1647.         goto_colon(fileread);  fscanf(fileread, "%f", &fTmp);  waterfriction = fTmp;
  1648.         goto_colon(fileread);  fscanf(fileread, "%f", &fTmp);  noslipfriction = fTmp;
  1649.         goto_colon(fileread);  fscanf(fileread, "%f", &fTmp);  gravity = fTmp;
  1650.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  animtileupdateand = iTmp;
  1651.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  animtileframeand = iTmp;
  1652.                                                                biganimtileframeand = (iTmp<<1)+1;
  1653.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  damagetileamount = iTmp;
  1654.         goto_colon(fileread);  cTmp = get_first_letter(fileread);
  1655.             if(cTmp=='S' || cTmp=='s')  damagetiletype = DAMAGESLASH;
  1656.             if(cTmp=='C' || cTmp=='c')  damagetiletype = DAMAGECRUSH;
  1657.             if(cTmp=='P' || cTmp=='p')  damagetiletype = DAMAGEPOKE;
  1658.             if(cTmp=='H' || cTmp=='h')  damagetiletype = DAMAGEHOLY;
  1659.             if(cTmp=='E' || cTmp=='e')  damagetiletype = DAMAGEEVIL;
  1660.             if(cTmp=='F' || cTmp=='f')  damagetiletype = DAMAGEFIRE;
  1661.             if(cTmp=='I' || cTmp=='i')  damagetiletype = DAMAGEICE;
  1662.             if(cTmp=='Z' || cTmp=='z')  damagetiletype = DAMAGEZAP;
  1663.         // Read weather data fourth
  1664.         goto_colon(fileread);  cTmp = get_first_letter(fileread);
  1665.             weatheroverwater = FALSE;
  1666.             if(cTmp=='T' || cTmp=='t')  weatheroverwater = TRUE;
  1667.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  weathertimereset = iTmp;
  1668.         weathertime = weathertimereset;
  1669.         weatherplayer = 0;
  1670.         // Read extra data
  1671.         goto_colon(fileread);  cTmp = get_first_letter(fileread);
  1672.             meshexploremode = FALSE;
  1673.             if(cTmp=='T' || cTmp=='t')  meshexploremode = TRUE;
  1674.         goto_colon(fileread);  cTmp = get_first_letter(fileread);
  1675.             usefaredge = FALSE;
  1676.             if(cTmp=='T' || cTmp=='t')  usefaredge = TRUE;
  1677.         camswing = 0;
  1678.         goto_colon(fileread);  fscanf(fileread, "%f", &fTmp);  camswingrate = fTmp;
  1679.         goto_colon(fileread);  fscanf(fileread, "%f", &fTmp);  camswingamp = fTmp;
  1680.  
  1681.  
  1682.         // Read unnecessary data...  Only read if it exists...
  1683.         fogon = FALSE;
  1684.         fogaffectswater = TRUE;
  1685.         fogtop = 100;
  1686.         fogbottom = 0;
  1687.         fogdistance = 100;
  1688.         fogred = 255;
  1689.         foggrn = 255;
  1690.         fogblu = 255;
  1691.         damagetileparttype = -1;
  1692.         damagetilepartand = 255;
  1693.         damagetilesound = -1;
  1694.         damagetilesoundtime = TILESOUNDTIME;
  1695.         damagetilemindistance = 9999;
  1696.         if(goto_colon_yesno(fileread))
  1697.         {
  1698.             fogon = fogallowed;
  1699.             fscanf(fileread, "%f", &fTmp);  fogtop = fTmp;
  1700.             goto_colon(fileread);  fscanf(fileread, "%f", &fTmp);  fogbottom = fTmp;
  1701.             goto_colon(fileread);  fscanf(fileread, "%f", &fTmp);  fogred = fTmp*255;
  1702.             goto_colon(fileread);  fscanf(fileread, "%f", &fTmp);  foggrn = fTmp*255;
  1703.             goto_colon(fileread);  fscanf(fileread, "%f", &fTmp);  fogblu = fTmp*255;
  1704.             goto_colon(fileread);  cTmp = get_first_letter(fileread);
  1705.               if(cTmp == 'F' || cTmp == 'f')  fogaffectswater = FALSE;
  1706.             fogdistance = (fogtop-fogbottom);
  1707.             if(fogdistance < 1.0)  fogon = FALSE;
  1708.  
  1709.  
  1710.             // Read extra stuff for damage tile particles...
  1711.             if(goto_colon_yesno(fileread))
  1712.             {
  1713.                 fscanf(fileread, "%d", &iTmp);  damagetileparttype = iTmp;
  1714.                 goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);
  1715.                 damagetilepartand = iTmp;
  1716.                 goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);
  1717.                 damagetilesound = iTmp;
  1718.             }
  1719.         }
  1720.  
  1721.         // Allow slow machines to ignore the fancy stuff
  1722.         if(twolayerwateron == FALSE && numwaterlayer > 1)
  1723.         {
  1724.             numwaterlayer = 1;
  1725.             iTmp = waterlayeralpha[0];
  1726.             iTmp = ((waterlayeralpha[1]*iTmp)>>8) + iTmp;
  1727.             if(iTmp > 255) iTmp = 255;
  1728.             waterlayeralpha[0] = iTmp;
  1729.         }
  1730.  
  1731.  
  1732.         fclose(fileread);
  1733.         // Do it
  1734.         //printf("entering light stuff\n");
  1735.         make_lighttable(lx, ly, lz, la);
  1736.         make_lighttospek();
  1737.         make_water();
  1738.     }
  1739.     else
  1740.     {
  1741.         general_error(0, 0, "WAWALITE.TXT NOT READ");
  1742.     }
  1743. }
  1744.  
  1745. //--------------------------------------------------------------------------------------------
  1746. void render_background(unsigned short texture)
  1747. {
  1748.     // ZZ> This function draws the large background
  1749.     GLVERTEX vtlist[4];    
  1750.     DWORD light;
  1751.     float size;
  1752.     unsigned short rotate;
  1753.     float sinsize, cossize;
  1754.     float x, y, z, u, v;
  1755.     int i;
  1756.  
  1757.  
  1758.     // Flat shade this
  1759.     //if(shading != D3DSHADE_FLAT)
  1760.     //    lpD3DDDevice->SetRenderState(D3DRENDERSTATE_SHADEMODE, D3DSHADE_FLAT);
  1761.     // Wait until there's a way to check current - DDOI
  1762. //    glShadeModel (GL_FLAT);
  1763.  
  1764.     glBindTexture ( GL_TEXTURE_2D, GLTexture_GetTextureID ( &txTexture[texture] ));    
  1765.  
  1766.     // Figure out the screen coordinates of its corners
  1767.     x = scrx/2.0;
  1768.     y = scry/2.0;
  1769.     z = .99999;
  1770.     u = waterlayeru[1];
  1771.     v = waterlayerv[1];
  1772.     rotate=16384+8192-camturnleftrightshort;
  1773.     rotate = rotate>>2;
  1774.     size = x + y + 1;
  1775.     sinsize = turntosin[rotate]*size;
  1776.     cossize = turntosin[(rotate+4096)&16383]*size;
  1777.  
  1778.     light = (0xffffffff);
  1779.     glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
  1780.  
  1781.     vtlist[0].x = x + cossize;
  1782.     vtlist[0].y = y - sinsize;
  1783.     vtlist[0].z = z;
  1784.     //vtlist[0].dcSpecular = 0;
  1785.     vtlist[0].s = 0+u;
  1786.     vtlist[0].t = 0+v;
  1787.  
  1788.     vtlist[1].x = x + sinsize;
  1789.     vtlist[1].y = y + cossize;
  1790.     vtlist[1].z = z;
  1791.     //vtlist[1].dcSpecular = 0;
  1792.     vtlist[1].s = backgroundrepeat+u;
  1793.     vtlist[1].t = 0+v;
  1794.  
  1795.     vtlist[2].x = x - cossize;
  1796.     vtlist[2].y = y + sinsize;
  1797.     vtlist[2].z = z;
  1798.     //vtlist[2].dcSpecular = 0;
  1799.     vtlist[2].s = backgroundrepeat+u;
  1800.     vtlist[2].t = backgroundrepeat+v;
  1801.  
  1802.     vtlist[3].x = x - sinsize;
  1803.     vtlist[3].y = y - cossize;
  1804.     vtlist[3].z = z;
  1805.     //vtlist[3].dcSpecular = 0;
  1806.     vtlist[3].s = 0+u;
  1807.     vtlist[3].t = backgroundrepeat+v;
  1808.  
  1809.     glBegin (GL_TRIANGLE_FAN);
  1810.     for (i = 0; i < 4; i++)
  1811.     {
  1812.         glTexCoord2f (vtlist[i].s, vtlist[i].t);
  1813.         glVertex3f (vtlist[i].x, vtlist[i].y, vtlist[i].z);
  1814.     }
  1815.     glEnd ();   
  1816. }
  1817.  
  1818.  
  1819. //--------------------------------------------------------------------------------------------
  1820. void render_shadow(int character)
  1821. {
  1822.     // ZZ> This function draws a NIFTY shadow
  1823.     GLVERTEX v[4];
  1824.     //GLVERTEX vt[4];
  1825.     //GLVERTEX vtlist[4];
  1826.     
  1827.     float size, x, y;
  1828.     DWORD light = 0x00ffffff;
  1829.     DWORD spek = 0xff000000;
  1830.     float level; //, z;
  1831.     int height;
  1832.     unsigned char alpha;
  1833.     signed char hide;
  1834.     int i;
  1835.  
  1836.     glColor4f(1.0, 1.0, 1.0, 1.0);
  1837.  
  1838.     hide = caphidestate[chrmodel[character]];
  1839.     if(hide == NOHIDE || hide != chraistate[character])
  1840.     {
  1841.         // Original points
  1842.         level = chrlevel[character];
  1843.         level += SHADOWRAISE;
  1844.         height = chrmatrix[character]_CNV(3,2)-level;
  1845.         if (height > 255)  return;
  1846.         if (height < 0) height = 0;
  1847.         size = chrshadowsize[character]-((height*chrshadowsize[character])>>8);
  1848.         if (size < 1) return;
  1849.         alpha = (height>>1) + 64;
  1850.  
  1851. /* PORT:if(fogon)
  1852.         {
  1853.             alpha = (alpha>>1) + 64;
  1854.             z = (chrlevel[character]);
  1855.             if(z < fogtop)
  1856.             {
  1857.                 if(z < fogbottom)
  1858.                 {
  1859.                     alpha += 80;
  1860.                 }
  1861.                 else
  1862.                 {
  1863.                     z = 1.0 - ((z-fogbottom)/fogdistance);
  1864.                     alpha = alpha + (80 * z);
  1865.                 }
  1866.             }
  1867.         }*/
  1868.         spek = spek | (alpha<<16) | (alpha<<8) | (alpha);
  1869.         x = chrmatrix[character]_CNV(3,0);
  1870.         y = chrmatrix[character]_CNV(3,1);
  1871.         v[0].x = (float) x+size;
  1872.         v[0].y = (float) y-size;
  1873.         v[0].z = (float) level;
  1874.  
  1875.         v[1].x = (float) x+size;
  1876.         v[1].y = (float) y+size;
  1877.         v[1].z = (float) level;
  1878.         
  1879.         v[2].x = (float) x-size;
  1880.         v[2].y = (float) y+size;
  1881.         v[2].z = (float) level;
  1882.         
  1883.         v[3].x = (float) x-size;
  1884.         v[3].y = (float) y-size;
  1885.         v[3].z = (float) level;
  1886.         
  1887.         // Choose texture.
  1888.         glBindTexture ( GL_TEXTURE_2D, GLTexture_GetTextureID( &txTexture[particletexture] ));
  1889.  
  1890.         //vt[0].dcSpecular = spek;
  1891.         v[0].s = particleimageu[238][0];
  1892.         v[0].t = particleimagev[238][0];
  1893.  
  1894.         //vt[1].dcSpecular = spek;
  1895.         v[1].s = particleimageu[255][1];
  1896.         v[1].t = particleimagev[238][0];
  1897.  
  1898.         //vt[2].dcSpecular = spek;
  1899.         v[2].s = particleimageu[255][1];
  1900.         v[2].t = particleimagev[255][1];
  1901.  
  1902.         //vt[3].dcSpecular = spek;
  1903.         v[3].s = particleimageu[238][0];
  1904.         v[3].t = particleimagev[255][1];
  1905.  
  1906.         glBegin(GL_TRIANGLE_FAN);
  1907.         for (i = 0; i < 4; i++) 
  1908.         {
  1909.             glTexCoord2f (v[i].s, v[i].t);
  1910.             glVertex3f (v[i].x, v[i].y, v[i].z);
  1911.         }
  1912.         glEnd();
  1913.     }
  1914. }
  1915.  
  1916. //--------------------------------------------------------------------------------------------
  1917. void render_bad_shadow(int character)
  1918. {
  1919.     // ZZ> This function draws a sprite shadow
  1920.     GLVERTEX v[4];
  1921.     float size, x, y;
  1922.     unsigned char ambi;
  1923.     //DWORD light;
  1924.     float level; //, z;
  1925.     int height;
  1926.     signed char hide;
  1927.     unsigned char trans;
  1928.     int i;
  1929.  
  1930.  
  1931.     hide = caphidestate[chrmodel[character]];
  1932.     if(hide == NOHIDE || hide != chraistate[character])
  1933.     {
  1934.         // Original points
  1935.         level = chrlevel[character];
  1936.         level+=SHADOWRAISE;
  1937.         height = chrmatrix[character]_CNV(3,2)-level;
  1938.         if(height > 255)  return;
  1939.         if(height < 0) height = 0;
  1940.         size = chrshadowsize[character]-((height*chrshadowsize[character])>>8);
  1941.         if(size < 1) return;
  1942.         ambi = chrlightlevel[character]>>4;  // LUL >>3;
  1943.         trans = ((255-height)>>1)+64;
  1944. /*      if(fogon)
  1945.         {
  1946.             z = (chrlevel[character]);
  1947.             if(z < fogtop)
  1948.             {
  1949.                 if(z > fogbottom)
  1950.                 {
  1951.                     z = ((z-fogbottom)/fogdistance);
  1952.                     trans = (trans * z);
  1953.                     if(trans < 64)  trans = 64;
  1954.                 }
  1955.                 else
  1956.                 {
  1957.                     trans = 64;
  1958.                 }
  1959.             }
  1960.         }*/
  1961.         //light = (trans<<24) | (ambi<<16) | (ambi<<8) | ambi;
  1962.         glColor4f(ambi/255.0, ambi/255.0, ambi/255.0, trans/255.0);
  1963.         
  1964.         x = chrmatrix[character]_CNV(3,0);
  1965.         y = chrmatrix[character]_CNV(3,1);
  1966.         v[0].x = (float) x+size;
  1967.         v[0].y = (float) y-size;
  1968.         v[0].z = (float) level;
  1969.  
  1970.         v[1].x = (float) x+size;
  1971.         v[1].y = (float) y+size;
  1972.         v[1].z = (float) level;
  1973.         
  1974.         v[2].x = (float) x-size;
  1975.         v[2].y = (float) y+size;
  1976.         v[2].z = (float) level;
  1977.         
  1978.         v[3].x = (float) x-size;
  1979.         v[3].y = (float) y-size;
  1980.         v[3].z = (float) level;
  1981.         
  1982.         // Choose texture and matrix
  1983.         glBindTexture ( GL_TEXTURE_2D, GLTexture_GetTextureID( &txTexture[particletexture] ));
  1984.         
  1985.         v[0].s = particleimageu[236][0];
  1986.         v[0].t = particleimagev[236][0];
  1987.  
  1988.         v[1].s = particleimageu[253][1];
  1989.         v[1].t = particleimagev[236][0];
  1990.  
  1991.         v[2].s = particleimageu[253][1];
  1992.         v[2].t = particleimagev[253][1];
  1993.  
  1994.         v[3].s = particleimageu[236][0];
  1995.         v[3].t = particleimagev[253][1];
  1996.  
  1997.         glBegin(GL_TRIANGLE_FAN);
  1998.         for (i = 0; i < 4; i++) 
  1999.         {
  2000.             glTexCoord2f (v[i].s, v[i].t);
  2001.             glVertex3f (v[i].x, v[i].y, v[i].z);
  2002.         }
  2003.         glEnd();           
  2004.     }
  2005. }
  2006.  
  2007.  
  2008.  
  2009.  
  2010. //--------------------------------------------------------------------------------------------
  2011. void light_characters()
  2012. {
  2013.     // ZZ> This function figures out character lighting
  2014.     int cnt, tnc, x, y;
  2015.     unsigned short tl, tr, bl, br;
  2016.     unsigned short light;
  2017.  
  2018.     cnt = 0;
  2019.     while(cnt < numdolist)
  2020.     {
  2021.         tnc = dolist[cnt];
  2022.         x = chrxpos[tnc];
  2023.         y = chrypos[tnc];
  2024.         x = (x&127)>>5;  // From 0 to 3
  2025.         y = (y&127)>>5;  // From 0 to 3
  2026.         light = 0;
  2027.         tl = meshvrtl[meshvrtstart[chronwhichfan[tnc]]+0];
  2028.         tr = meshvrtl[meshvrtstart[chronwhichfan[tnc]]+1];
  2029.         br = meshvrtl[meshvrtstart[chronwhichfan[tnc]]+2];
  2030.         bl = meshvrtl[meshvrtstart[chronwhichfan[tnc]]+3];
  2031.  
  2032.         // Interpolate lighting level using tile corners
  2033.         switch(x)
  2034.         {
  2035.             case 0:
  2036.                 light+=tl<<1;
  2037.                 light+=bl<<1;
  2038.                 break;
  2039.             case 1:
  2040.             case 2:
  2041.                 light+=tl;
  2042.                 light+=tr;
  2043.                 light+=bl;
  2044.                 light+=br;
  2045.                 break;
  2046.             case 3:
  2047.                 light+=tr<<1;
  2048.                 light+=br<<1;
  2049.                 break;
  2050.         }
  2051.         switch(y)
  2052.         {
  2053.             case 0:
  2054.                 light+=tl<<1;
  2055.                 light+=tr<<1;
  2056.                 break;
  2057.             case 1:
  2058.             case 2:
  2059.                 light+=tl;
  2060.                 light+=tr;
  2061.                 light+=bl;
  2062.                 light+=br;
  2063.                 break;
  2064.             case 3:
  2065.                 light+=bl<<1;
  2066.                 light+=br<<1;
  2067.                 break;
  2068.         }
  2069.         light=light>>3;
  2070.         chrlightlevel[tnc] = light;
  2071.  
  2072.  
  2073.         if(meshexploremode==FALSE)
  2074.         {
  2075.             // Look up light direction using corners again
  2076.             tl = (tl<<8)&0xf000;
  2077.             tr = (tr<<4)&0x0f00;
  2078.             br = (br)&0x00f0;
  2079.             bl = bl>>4;
  2080.             tl = tl|tr|br|bl;
  2081.             chrlightturnleftright[tnc] = (lightdirectionlookup[tl]<<8);
  2082.         }
  2083.         else
  2084.         {
  2085.             chrlightturnleftright[tnc] = 0;
  2086.         }
  2087.         cnt++;
  2088.     }
  2089. }
  2090.  
  2091. //--------------------------------------------------------------------------------------------
  2092. void light_particles()
  2093. {
  2094.     // ZZ> This function figures out particle lighting
  2095.     int cnt;
  2096.     int character;
  2097.  
  2098.     cnt = 0;
  2099.     while(cnt < MAXPRT)
  2100.     {
  2101.         if(prton[cnt])
  2102.         {
  2103.             character = prtattachedtocharacter[cnt];
  2104.             if(character != MAXCHR)
  2105.             {
  2106.                 prtlight[cnt] = chrlightlevel[character];
  2107.             }
  2108.             else
  2109.             {
  2110.                 prtlight[cnt] = meshvrtl[meshvrtstart[prtonwhichfan[cnt]]];
  2111.             }
  2112.         }
  2113.         cnt++;
  2114.     }
  2115. }
  2116.  
  2117. //--------------------------------------------------------------------------------------------
  2118. void set_fan_light(int fanx, int fany, unsigned short particle)
  2119. {
  2120.     // ZZ> This function is a little helper, lighting the selected fan
  2121.     //     with the chosen particle
  2122.     float x, y;
  2123.     int fan, vertex, lastvertex;
  2124.     float level;
  2125.     float light;
  2126.  
  2127.  
  2128.     if(fanx >= 0 && fanx < meshsizex && fany >= 0 && fany < meshsizey)
  2129.     {
  2130.         fan = fanx+meshfanstart[fany];
  2131.         vertex = meshvrtstart[fan];
  2132.         lastvertex = vertex + meshcommandnumvertices[meshtype[fan]];
  2133.         while(vertex < lastvertex)
  2134.         {
  2135.             light = meshvrta[vertex];
  2136.             x = prtxpos[particle]-meshvrtx[vertex];
  2137.             y = prtypos[particle]-meshvrty[vertex];
  2138.             level = (x*x + y*y)/prtdynalightfalloff[particle];
  2139.             level = 255-level;
  2140.             level=level*prtdynalightlevel[particle];
  2141.             if(level > light)
  2142.             {
  2143.                 if(level > 255) level = 255;
  2144.                 meshvrtl[vertex] = level;
  2145.                 meshvrta[vertex] = level;
  2146.             }
  2147.             vertex++;
  2148.         }
  2149.     }
  2150. }
  2151.  
  2152. //--------------------------------------------------------------------------------------------
  2153. void do_dynalight()
  2154. {
  2155.     // ZZ> This function does dynamic lighting of visible fans
  2156.  
  2157.     int cnt, lastvertex, vertex, fan, entry, fanx, fany, addx, addy;
  2158.     float x, y;
  2159.     float level;
  2160.     float light;
  2161.  
  2162.  
  2163.     // Do each floor tile
  2164.     if(meshexploremode)
  2165.     {
  2166.         // Set base light level in explore mode...  Don't need to do every frame
  2167.         if((allframe & 7) == 0)
  2168.         {
  2169.             cnt = 0;
  2170.             while(cnt < MAXPRT)
  2171.             {
  2172.                 if(prton[cnt] && prtdynalighton[cnt])
  2173.                 {
  2174.                     fanx = prtxpos[cnt];
  2175.                     fany = prtypos[cnt];
  2176.                     fanx = fanx>>7;
  2177.                     fany = fany>>7;
  2178.                     addy = -DYNAFANS;
  2179.                     while(addy <= DYNAFANS)
  2180.                     {
  2181.                         addx = -DYNAFANS;
  2182.                         while(addx <= DYNAFANS)
  2183.                         {
  2184.                             set_fan_light(fanx+addx, fany+addy, cnt);
  2185.                             addx++;
  2186.                         }
  2187.                         addy++;
  2188.                     }
  2189.                 }
  2190.                 cnt++;
  2191.             }
  2192.         }
  2193.     }
  2194.     else
  2195.     {
  2196.         //if(shading != D3DSHADE_FLAT)
  2197.         //GS - if(shading == shading)
  2198.         {
  2199.             // Add to base light level in normal mode
  2200.             entry = 0;
  2201.             while(entry < nummeshrenderlist)
  2202.             {
  2203.                 fan = meshrenderlist[entry];
  2204.                 vertex = meshvrtstart[fan];
  2205.                 lastvertex = vertex + meshcommandnumvertices[meshtype[fan]];
  2206.                 while(vertex < lastvertex)
  2207.                 {
  2208.                     // Do light particles
  2209.                     light = meshvrta[vertex];
  2210.                     cnt = 0;
  2211.                     while(cnt < numdynalight)
  2212.                     {
  2213.                         x = dynalightlistx[cnt]-meshvrtx[vertex];
  2214.                         y = dynalightlisty[cnt]-meshvrty[vertex];
  2215.                         level = (x*x + y*y)/dynalightfalloff[cnt];
  2216.                         level = 255-level;
  2217.                         if(level > 0)
  2218.                         {
  2219.                             light+=level*dynalightlevel[cnt];
  2220.                         }
  2221.                         cnt++;
  2222.                     }
  2223.                     if(light > 255) light = 255;
  2224.                     if(light < 0) light = 0;
  2225.                     meshvrtl[vertex] = light;
  2226.                     vertex++;
  2227.                 }
  2228.                 entry++;
  2229.             }
  2230.         }
  2231.     }
  2232. }
  2233.  
  2234. //--------------------------------------------------------------------------------------------
  2235. void render_water()
  2236. {
  2237.     // ZZ> This function draws all of the water fans
  2238.  
  2239.     int cnt;
  2240.  
  2241.     // Set the transformation thing
  2242.     glLoadMatrixf(mView.v);
  2243.     glMultMatrixf(mWorld.v);
  2244.  
  2245.  
  2246.     // Bottom layer first
  2247.     if(numwaterlayer > 1 && waterlayerz[1] > -waterlayeramp[1])
  2248.     {
  2249.         cnt = 0;
  2250.         while(cnt < nummeshrenderlist)
  2251.         {
  2252.             if(meshfx[meshrenderlist[cnt]]&MESHFXWATER)
  2253.             {
  2254.                 // !!!BAD!!! Water will get screwed up if meshsizex is odd
  2255.                 render_water_fan(meshrenderlist[cnt], 1, ((meshrenderlist[cnt]>>watershift)&2)+(meshrenderlist[cnt]&1));
  2256.             }
  2257.             cnt++;
  2258.         }
  2259.     }
  2260.     // Top layer second
  2261.     if(numwaterlayer > 0 && waterlayerz[0] > -waterlayeramp[0])
  2262.     {
  2263.         cnt = 0;
  2264.         while(cnt < nummeshrenderlist)
  2265.         {
  2266.             if(meshfx[meshrenderlist[cnt]]&MESHFXWATER)
  2267.             {
  2268.                 // !!!BAD!!! Water will get screwed up if meshsizex is odd
  2269.                 render_water_fan(meshrenderlist[cnt], 0, ((meshrenderlist[cnt]>>watershift)&2)+(meshrenderlist[cnt]&1));
  2270.             }
  2271.             cnt++;
  2272.         }
  2273.     }
  2274.     // Foreground overlay
  2275.     if(overlayon)
  2276.     {
  2277.         //render_foreground_overlay(5);  // Texture 5 is watertop.bmp
  2278.     }
  2279. }
  2280.  
  2281. //--------------------------------------------------------------------------------------------
  2282. void draw_scene_sadreflection()
  2283. {
  2284.     // ZZ> This function draws 3D objects
  2285.     unsigned short cnt, tnc;
  2286.     unsigned char trans;
  2287.     RECT rect;// = {0, 0, scrx, scry};    // Don't know why this isn't working on the Mac, it should
  2288.     
  2289.     rect.left = 0;
  2290.     rect.right = 0;
  2291.     rect.top = scrx;
  2292.     rect.bottom = scry;
  2293.  
  2294.     // ZB> Clear the z-buffer
  2295.     glClear(GL_DEPTH_BUFFER_BIT);
  2296.     
  2297.     // Clear the image if need be
  2298.     if (clearson)
  2299.         glClear(GL_COLOR_BUFFER_BIT);
  2300.     else
  2301.     {
  2302.         // Render the background
  2303.         render_background(6);  // 6 is the texture for waterlow.bmp
  2304.     }
  2305.  
  2306.  
  2307.     // Render the reflective floors
  2308.     meshlasttexture = 0;
  2309.     for (cnt = 0; cnt < nummeshrenderlistref; cnt++)
  2310.         render_fan(meshrenderlistref[cnt]);
  2311.     
  2312.     if(refon)
  2313.     {
  2314.         // Render reflections of characters
  2315.     
  2316.         glEnable(GL_CULL_FACE);
  2317.         glFrontFace(GL_CCW);
  2318.  
  2319.         glDisable(GL_DEPTH_TEST);
  2320.         glDepthMask(GL_FALSE);
  2321.  
  2322.         glEnable(GL_BLEND);
  2323.         glBlendFunc(GL_SRC_ALPHA, GL_ONE);
  2324.  
  2325.         for (cnt = 0; cnt < numdolist; cnt++)
  2326.         {
  2327.             tnc = dolist[cnt];
  2328.             if((meshfx[chronwhichfan[tnc]]&MESHFXDRAWREF))
  2329.             {
  2330.                 render_refmad(tnc, chralpha[tnc]&chrlight[tnc]);
  2331.             }
  2332.         }
  2333.         
  2334.         // Render the reflected sprites
  2335.         glFrontFace(GL_CW);
  2336.         render_refprt();
  2337.         
  2338.         glDisable(GL_BLEND);
  2339.         glEnable(GL_DEPTH_TEST);
  2340.         glDepthMask(GL_TRUE);
  2341.     }
  2342.  
  2343.     // Render the shadow floors
  2344.     meshlasttexture = 0;
  2345.     for (cnt = 0; cnt < nummeshrenderlistsha; cnt++)
  2346.         render_fan(meshrenderlistsha[cnt]);
  2347.     
  2348.     // Render the shadows
  2349.     if(shaon)
  2350.     {
  2351.         if(shasprite)
  2352.         {
  2353.             // Bad shadows
  2354.             glDepthMask(GL_FALSE);
  2355.             glEnable(GL_BLEND);
  2356.             glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
  2357.             
  2358.             for (cnt = 0; cnt < numdolist; cnt++)
  2359.             {
  2360.                 tnc = dolist[cnt];
  2361.                 if(chrattachedto[tnc] == MAXCHR)
  2362.                 {
  2363.                     if(((chrlight[tnc]==255 && chralpha[tnc]==255) || capforceshadow[chrmodel[tnc]]) && chrshadowsize[tnc]!=0)
  2364.                     {
  2365.                         render_bad_shadow(tnc);
  2366.                     }
  2367.                 }
  2368.             }
  2369.         
  2370.             glDisable(GL_BLEND);
  2371.             glDepthMask(GL_TRUE);
  2372.         }
  2373.         else
  2374.         {
  2375.             // Good shadows for me
  2376.             glDepthMask(GL_FALSE);
  2377.             glEnable(GL_BLEND);
  2378.             glBlendFunc(GL_SRC_COLOR, GL_ZERO);
  2379.             for (cnt = 0; cnt < numdolist; cnt++)
  2380.             {
  2381.                 tnc = dolist[cnt];
  2382.                 if(chrattachedto[tnc] == MAXCHR)
  2383.                 {
  2384.                     if(((chrlight[tnc]==255 && chralpha[tnc]==255) || capforceshadow[chrmodel[tnc]]) && chrshadowsize[tnc]!=0)
  2385.                     {
  2386.                         render_shadow(tnc);
  2387.                     }
  2388.                 }
  2389.             }
  2390.             glDisable(GL_BLEND);
  2391.             glDepthMask(GL_TRUE);
  2392.         }
  2393.     }
  2394.  
  2395.     glAlphaFunc(GL_GREATER, 0);
  2396.     glEnable(GL_ALPHA_TEST);
  2397.  
  2398.     // Render the normal characters
  2399.     for (cnt = 0; cnt < numdolist; cnt++)
  2400.     {
  2401.         tnc = dolist[cnt];
  2402.         if(chralpha[tnc]==255 && chrlight[tnc]==255)
  2403.             render_mad(tnc, 255);
  2404.     }
  2405.  
  2406.     // Render the sprites
  2407.     glDepthMask(GL_FALSE);
  2408.     glEnable(GL_BLEND);
  2409.  
  2410.     // Now render the transparent characters
  2411.     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  2412.     for (cnt = 0; cnt < numdolist; cnt++)
  2413.     {
  2414.         tnc = dolist[cnt];
  2415.         if(chralpha[tnc]!=255 && chrlight[tnc]==255)
  2416.         {
  2417.             trans = chralpha[tnc];
  2418.             if(trans < SEEINVISIBLE && (localseeinvisible || chrislocalplayer[tnc]))  trans = SEEINVISIBLE;
  2419.             render_mad(tnc, trans);
  2420.         }
  2421.     }
  2422.     
  2423.     // Alpha water
  2424.     if(!waterlight)  render_water();
  2425.     
  2426.     // Then do the light characters
  2427.     glBlendFunc(GL_SRC_ALPHA, GL_ONE);
  2428.     for (cnt = 0; cnt < numdolist; cnt++)
  2429.     {
  2430.         tnc = dolist[cnt];
  2431.         if(chrlight[tnc]!=255)
  2432.         {
  2433.             trans = chrlight[tnc];
  2434.             if(trans < SEEINVISIBLE && (localseeinvisible || chrislocalplayer[tnc]))  trans = SEEINVISIBLE;
  2435.             render_mad(tnc, trans);
  2436.         }
  2437.     
  2438.         // Do phong highlights
  2439.         if(phongon && chralpha[tnc]==255 && chrlight[tnc]==255 && chrenviro[tnc]==FALSE && chrsheen[tnc] > 0)
  2440.         {
  2441.             unsigned short texturesave;
  2442.             chrenviro[tnc] = TRUE;
  2443.             texturesave = chrtexture[tnc];
  2444.             chrtexture[tnc] = 7;  // The phong map texture...
  2445.             render_mad(tnc, chrsheen[tnc]<<4);
  2446.             chrtexture[tnc] = texturesave;
  2447.             chrenviro[tnc] = FALSE;
  2448.         }
  2449.     }
  2450.  
  2451.     // Light water
  2452.     if(waterlight)  render_water();
  2453.  
  2454.     // Turn Z buffer back on, alphablend off
  2455.     glDepthMask(GL_TRUE);
  2456.     glDisable(GL_BLEND);
  2457.     glEnable(GL_ALPHA_TEST);
  2458.     render_prt();
  2459.     glDisable(GL_ALPHA_TEST);
  2460.     
  2461.     glDepthMask(GL_TRUE);
  2462.     glDisable(GL_BLEND);
  2463.  
  2464.     // Done rendering
  2465. }
  2466.  
  2467. //--------------------------------------------------------------------------------------------
  2468. void draw_scene_zreflection()
  2469. {
  2470.     // ZZ> This function draws 3D objects
  2471.     unsigned short cnt, tnc;
  2472.     unsigned char trans;
  2473.  
  2474.     // Clear the image if need be
  2475.     // PORT: I don't think this is needed if(clearson) { clear_surface(lpDDSBack); }
  2476.     // Zbuffer is cleared later
  2477.  
  2478.     // Render the reflective floors
  2479.     glDisable(GL_DEPTH_TEST);
  2480.     glDepthMask(GL_FALSE);
  2481.  
  2482.     // Render the background
  2483.     if (clearson == FALSE)
  2484.         render_background(6);  // 6 is the texture for waterlow.bmp
  2485.  
  2486.     meshlasttexture = 0;
  2487.  
  2488.     for (cnt = 0; cnt < nummeshrenderlistref; cnt++)
  2489.         render_fan(meshrenderlistref[cnt]);
  2490.  
  2491.     // BAD: DRAW SHADOW STUFF TOO
  2492.     for (cnt = 0; cnt < nummeshrenderlistsha; cnt++)
  2493.         render_fan(meshrenderlistsha[cnt]);
  2494.  
  2495.     glEnable(GL_DEPTH_TEST);
  2496.     glDepthMask(GL_TRUE);
  2497.     if(refon)
  2498.     {
  2499.         // Render reflections of characters
  2500.         glFrontFace(GL_CCW);
  2501.         glEnable(GL_BLEND);
  2502.         glBlendFunc(GL_SRC_ALPHA, GL_ONE);
  2503.         glDepthFunc(GL_LEQUAL);
  2504.  
  2505.         for (cnt = 0; cnt < numdolist; cnt++)
  2506.         {
  2507.             tnc = dolist[cnt];
  2508.             if((meshfx[chronwhichfan[tnc]]&MESHFXDRAWREF))
  2509.                 render_refmad(tnc, chralpha[tnc]&chrlight[tnc]);
  2510.         }
  2511.         
  2512.         // [claforte] I think this is wrong... I think we should choose some other depth func.
  2513.         glDepthFunc(GL_ALWAYS);
  2514.  
  2515.         // Render the reflected sprites
  2516.         glDisable(GL_DEPTH_TEST);
  2517.         glDepthMask(GL_FALSE);
  2518.         glFrontFace(GL_CW);
  2519.         render_refprt();
  2520.         
  2521.         glDisable(GL_BLEND);
  2522.         glDepthFunc(GL_LEQUAL);
  2523.         glEnable(GL_DEPTH_TEST);
  2524.         glDepthMask(GL_TRUE);
  2525.     }
  2526.     
  2527.     // Clear the Zbuffer at a bad time...  But hey, reflections work with Voodoo
  2528.     //lpD3DVViewport->Clear(1, &rect, D3DCLEAR_ZBUFFER);
  2529.     // Not sure if this is cool or not - DDOI
  2530.     // glClear ( GL_DEPTH_BUFFER_BIT );
  2531.  
  2532.     // Render the shadow floors
  2533.     meshlasttexture = 0;
  2534.  
  2535.     for (cnt = 0; cnt < nummeshrenderlistsha; cnt++)
  2536.         render_fan(meshrenderlistsha[cnt]);
  2537.  
  2538.     // Render the shadows
  2539.     if (shaon)
  2540.     {
  2541.         if (shasprite)
  2542.         {
  2543.             // Bad shadows
  2544.             glDepthMask(GL_FALSE);
  2545.             glEnable(GL_BLEND);
  2546.             glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  2547.             
  2548.             for (cnt = 0; cnt < numdolist; cnt++)
  2549.             {
  2550.                 tnc = dolist[cnt];
  2551.                 if(chrattachedto[tnc] == MAXCHR)
  2552.                 {
  2553.                     if(((chrlight[tnc]==255 && chralpha[tnc]==255) || capforceshadow[chrmodel[tnc]]) && chrshadowsize[tnc]!=0)
  2554.                         render_bad_shadow(tnc);
  2555.                 }
  2556.             }
  2557.             glDisable(GL_BLEND);
  2558.             glDepthMask(GL_TRUE);
  2559.         }
  2560.         else
  2561.         {
  2562.             // Good shadows for me
  2563.             glDepthMask(GL_FALSE);
  2564.             glEnable(GL_BLEND);
  2565.             glBlendFunc(GL_SRC_COLOR, GL_ZERO);
  2566.  
  2567.             for (cnt = 0; cnt < numdolist; cnt++)
  2568.             {
  2569.                 tnc = dolist[cnt];
  2570.                 if(chrattachedto[tnc] == MAXCHR)
  2571.                 {
  2572.                     if(((chrlight[tnc]==255 && chralpha[tnc]==255) || capforceshadow[chrmodel[tnc]]) && chrshadowsize[tnc]!=0)
  2573.                         render_shadow(tnc);
  2574.                 }
  2575.             }
  2576.  
  2577.             glDisable(GL_BLEND);
  2578.             glDepthMask ( GL_TRUE );
  2579.         }
  2580.     }
  2581.  
  2582.     glAlphaFunc(GL_GREATER, 0);
  2583.     glEnable(GL_ALPHA_TEST);
  2584.  
  2585.     // Render the normal characters
  2586.     for (cnt = 0; cnt < numdolist; cnt++)
  2587.     {
  2588.         tnc = dolist[cnt];
  2589.         if(chralpha[tnc]==255 && chrlight[tnc]==255)
  2590.             render_mad(tnc, 255);
  2591.     }
  2592.  
  2593.     // Render the sprites
  2594.     glDepthMask ( GL_FALSE );
  2595.     glEnable(GL_BLEND);
  2596.  
  2597.     // Now render the transparent characters
  2598.     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  2599.  
  2600.     for (cnt = 0; cnt < numdolist; cnt++)
  2601.     {
  2602.         tnc = dolist[cnt];
  2603.         if(chralpha[tnc]!=255 && chrlight[tnc]==255)
  2604.         {
  2605.             trans = chralpha[tnc];
  2606.             if(trans < SEEINVISIBLE && (localseeinvisible || chrislocalplayer[tnc]))  trans = SEEINVISIBLE;
  2607.             render_mad(tnc, trans);
  2608.         }
  2609.     }
  2610.  
  2611.     // And alpha water floors
  2612.     if(!waterlight)  
  2613.         render_water();
  2614.     
  2615.     // Then do the light characters
  2616.     glBlendFunc(GL_SRC_ALPHA, GL_ONE);
  2617.     
  2618.     for (cnt = 0; cnt < numdolist; cnt++)
  2619.     {
  2620.         tnc = dolist[cnt];
  2621.         if(chrlight[tnc]!=255)
  2622.         {
  2623.             trans = chrlight[tnc];
  2624.             if(trans < SEEINVISIBLE && (localseeinvisible || chrislocalplayer[tnc]))  trans = SEEINVISIBLE;
  2625.             render_mad(tnc, trans);
  2626.         }
  2627.  
  2628.         // Do phong highlights
  2629.         if(phongon && chralpha[tnc]==255 && chrlight[tnc]==255 && chrenviro[tnc]==FALSE && chrsheen[tnc] > 0)
  2630.         {
  2631.             unsigned short texturesave;
  2632.             chrenviro[tnc] = TRUE;
  2633.             texturesave = chrtexture[tnc];
  2634.             chrtexture[tnc] = 7;  // The phong map texture...
  2635.             render_mad(tnc, chrsheen[tnc]<<4);
  2636.             chrtexture[tnc] = texturesave;
  2637.             chrenviro[tnc] = FALSE;
  2638.         }
  2639.     }
  2640.  
  2641.     // Do light water
  2642.     if(waterlight)  
  2643.         render_water();
  2644.  
  2645.     // Turn Z buffer back on, alphablend off
  2646.     glDepthMask(GL_TRUE);
  2647.     glDisable(GL_BLEND);
  2648.     glEnable(GL_ALPHA_TEST);
  2649.     render_prt();
  2650.     glDisable(GL_ALPHA_TEST);
  2651.  
  2652.     glDepthMask(GL_TRUE);
  2653.     
  2654.     glDisable(GL_BLEND);
  2655.  
  2656.     // Done rendering
  2657. }
  2658.  
  2659. //--------------------------------------------------------------------------------------------
  2660. BOOL get_mesh_memory()
  2661. {
  2662.     // ZZ> This function gets a load of memory for the terrain mesh
  2663.     floatmemory = (float *) malloc(maxtotalmeshvertices*BYTESFOREACHVERTEX);
  2664.     if(floatmemory == NULL)
  2665.         return FALSE;
  2666.  
  2667.     meshvrtx = &floatmemory[0];
  2668.     meshvrty = &floatmemory[1*maxtotalmeshvertices];
  2669.     meshvrtz = &floatmemory[2*maxtotalmeshvertices];
  2670.     meshvrta = (unsigned char *) &floatmemory[3*maxtotalmeshvertices];
  2671.     meshvrtl = &meshvrta[maxtotalmeshvertices];
  2672.     return TRUE;
  2673. }
  2674.  
  2675. //--------------------------------------------------------------------------------------------
  2676. void draw_blip(unsigned char color, int x, int y)
  2677. {
  2678.     float xl,xr,yt,yb;
  2679.     int width, height;
  2680.  
  2681.     // ZZ> This function draws a blip
  2682.     if(x > 0 && y > 0)
  2683.     {
  2684.         EnableTexturing();
  2685.         glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
  2686.         glNormal3f(0.0f, 0.0f, 1.0f);
  2687.  
  2688.         glBindTexture(GL_TEXTURE_2D, GLTexture_GetTextureID( &TxBlip ));
  2689.         xl = ((float)bliprect[color].left)/32;
  2690.         xr = ((float)bliprect[color].right)/32;
  2691.         yt = ((float)bliprect[color].top)/4;
  2692.         yb = ((float)bliprect[color].bottom)/4;
  2693.         width = bliprect[color].right-bliprect[color].left; height=bliprect[color].bottom-bliprect[color].top;
  2694.  
  2695.         glBegin(GL_QUADS);
  2696.             glTexCoord2f( xl, yb );   glVertex2i( x-1,       scry-y-1-height );
  2697.             glTexCoord2f( xr, yb );   glVertex2i( x-1+width, scry-y-1-height );
  2698.             glTexCoord2f( xr, yt );   glVertex2i( x-1+width, scry-y-1 );
  2699.             glTexCoord2f( xl, yt );   glVertex2i( x-1,       scry-y-1 );
  2700.         glEnd();
  2701.  
  2702.     }
  2703. }
  2704.  
  2705. //--------------------------------------------------------------------------------------------
  2706. void draw_one_icon(int icontype, int x, int y, unsigned char sparkle)
  2707. {
  2708.     // ZZ> This function draws an icon
  2709.     int position, blipx, blipy;
  2710.     float xl,xr,yt,yb;
  2711.     int width, height;
  2712.  
  2713.     if(TxIcon[icontype].textureID>=0) //if(lpDDSIcon[icontype])
  2714.     {
  2715.         EnableTexturing();        // Enable texture mapping
  2716.         glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
  2717.  
  2718.         //lpDDSBack->BltFast(x, y, lpDDSIcon[icontype], &iconrect, DDBLTFAST_NOCOLORKEY);
  2719.         glBindTexture( GL_TEXTURE_2D, GLTexture_GetTextureID( &TxIcon[icontype] ) );
  2720.         xl=((float)iconrect.left)/32;
  2721.         xr=((float)iconrect.right)/32;
  2722.         yt=((float)iconrect.top)/32;
  2723.         yb=((float)iconrect.bottom)/32;
  2724.         width=iconrect.right-iconrect.left; height=iconrect.bottom-iconrect.top;
  2725.         glBegin(GL_QUADS);
  2726.             glTexCoord2f( xl, yb );   glVertex2i( x,       scry-y-height );
  2727.             glTexCoord2f( xr, yb );   glVertex2i( x+width, scry-y-height );
  2728.             glTexCoord2f( xr, yt );   glVertex2i( x+width, scry-y );
  2729.             glTexCoord2f( xl, yt );   glVertex2i( x,       scry-y );
  2730.         glEnd();
  2731.     }
  2732.  
  2733.     if(sparkle != NOSPARKLE)
  2734.     {
  2735.         position = wldframe&31;
  2736.         position = (SPARKLESIZE * position >> 5);
  2737.  
  2738.         blipx = x + SPARKLEADD + position;
  2739.         blipy = y + SPARKLEADD;
  2740.         draw_blip(sparkle, blipx, blipy);
  2741.  
  2742.         blipx = x + SPARKLEADD + SPARKLESIZE;
  2743.         blipy = y + SPARKLEADD + position;
  2744.         draw_blip(sparkle, blipx, blipy);
  2745.  
  2746.         blipx = blipx - position;
  2747.         blipy = y + SPARKLEADD + SPARKLESIZE;
  2748.         draw_blip(sparkle, blipx, blipy);
  2749.  
  2750.         blipx = x + SPARKLEADD;
  2751.         blipy = blipy - position;
  2752.         draw_blip(sparkle, blipx, blipy);
  2753.     }
  2754. }
  2755.  
  2756. //--------------------------------------------------------------------------------------------
  2757. void draw_one_font(int fonttype, int x, int y)
  2758. {
  2759.     // ZZ> This function draws a letter or number
  2760.     // GAC> Very nasty version for starters.  Lots of room for improvement.
  2761.     GLfloat dx,dy,fx1,fx2,fy1,fy2;
  2762.     GLuint x2,y2;
  2763.  
  2764.     y = fontoffset - y;
  2765.     x2 = x + fontrect[fonttype].w;
  2766.     y2 = y + fontrect[fonttype].h;
  2767.     dx = 2.0/512;
  2768.     dy = 1.0/256;
  2769.     fx1 = fontrect[fonttype].x*dx + 0.001;
  2770.     fx2 = (fontrect[fonttype].x+fontrect[fonttype].w)*dx - 0.001;
  2771.     fy1 = fontrect[fonttype].y*dy + 0.001;
  2772.     fy2 = (fontrect[fonttype].y+fontrect[fonttype].h)*dy;
  2773.  
  2774.     glBegin(GL_QUADS);
  2775.         glTexCoord2f(fx1,fy2);   glVertex2i( x, y);
  2776.         glTexCoord2f(fx2,fy2);   glVertex2i(x2, y);
  2777.         glTexCoord2f(fx2,fy1);   glVertex2i(x2,y2);
  2778.         glTexCoord2f(fx1,fy1);   glVertex2i( x,y2);
  2779.     glEnd();
  2780. }
  2781.  
  2782. //--------------------------------------------------------------------------------------------
  2783. void draw_map(int x, int y)
  2784. {
  2785.     // ZZ> This function draws the map
  2786.  
  2787.     //printf("draw map getting called\n");
  2788.     
  2789.     EnableTexturing();
  2790.     glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
  2791.     //glNormal3f( 0, 0, 1 );
  2792.  
  2793.     glBindTexture( GL_TEXTURE_2D, GLTexture_GetTextureID( &TxMap ) );
  2794.     glBegin(GL_QUADS);
  2795.         glTexCoord2f (0.0, 1.0); glVertex2i (x,     scry-y-MAPSIZE);
  2796.         glTexCoord2f (1.0, 1.0); glVertex2i (x+MAPSIZE, scry-y-MAPSIZE);
  2797.         glTexCoord2f (1.0, 0.0); glVertex2i (x+MAPSIZE, scry-y);
  2798.         glTexCoord2f (0.0, 0.0); glVertex2i (x,     scry-y);
  2799.     glEnd();    
  2800. }
  2801.  
  2802. //--------------------------------------------------------------------------------------------
  2803. int draw_one_bar(int bartype, int x, int y, int ticks, int maxticks)
  2804. {
  2805.     // ZZ> This function draws a bar and returns the y position for the next one
  2806.     int noticks;
  2807.     float xl, xr, yt, yb;
  2808.     int width, height;
  2809.  
  2810.     EnableTexturing();               // Enable texture mapping
  2811.     glColor4f( 1, 1, 1, 1 );
  2812.  
  2813.     if(maxticks>0 && ticks >= 0)
  2814.     {
  2815.         // Draw the tab
  2816.         glBindTexture( GL_TEXTURE_2D, GLTexture_GetTextureID( &TxBars ) );
  2817.         xl=((float)tabrect[bartype].left)/128;
  2818.         xr=((float)tabrect[bartype].right)/128;
  2819.         yt=((float)tabrect[bartype].top)/128;
  2820.         yb=((float)tabrect[bartype].bottom)/128;
  2821.         width=tabrect[bartype].right-tabrect[bartype].left; height=tabrect[bartype].bottom-tabrect[bartype].top;
  2822.         glBegin( GL_QUADS );
  2823.                 glTexCoord2f( xl, yb );   glVertex2i( x,       scry-y-height );
  2824.                 glTexCoord2f( xr, yb );   glVertex2i( x+width, scry-y-height );
  2825.                 glTexCoord2f( xr, yt );   glVertex2i( x+width, scry-y );
  2826.                 glTexCoord2f( xl, yt );   glVertex2i( x,       scry-y );
  2827.         glEnd();
  2828.  
  2829.         // Error check
  2830.         if(maxticks>MAXTICK) maxticks = MAXTICK;
  2831.         if(ticks>maxticks) ticks = maxticks;
  2832.  
  2833.         // Draw the full rows of ticks
  2834.         x+=TABX;
  2835.         while(ticks >= NUMTICK)
  2836.         {
  2837.             barrect[bartype].right = BARX;
  2838.             glBindTexture( GL_TEXTURE_2D, GLTexture_GetTextureID( &TxBars ) );
  2839.             xl=((float)barrect[bartype].left)/128;
  2840.             xr=((float)barrect[bartype].right)/128;
  2841.             yt=((float)barrect[bartype].top)/128;
  2842.             yb=((float)barrect[bartype].bottom)/128;
  2843.             width=barrect[bartype].right-barrect[bartype].left; height=barrect[bartype].bottom-barrect[bartype].top;
  2844.             glBegin( GL_QUADS );
  2845.                 glTexCoord2f( xl, yb );   glVertex2i( x,       scry-y-height );
  2846.                 glTexCoord2f( xr, yb );   glVertex2i( x+width, scry-y-height );
  2847.                 glTexCoord2f( xr, yt );   glVertex2i( x+width, scry-y );
  2848.                 glTexCoord2f( xl, yt );   glVertex2i( x,       scry-y );
  2849.             glEnd();
  2850.             y+=BARY;
  2851.             ticks-=NUMTICK;
  2852.             maxticks-=NUMTICK;
  2853.         }
  2854.  
  2855.  
  2856.         // Draw any partial rows of ticks
  2857.         if(maxticks > 0)
  2858.         {
  2859.             // Draw the filled ones
  2860.             barrect[bartype].right = (ticks<<3)+TABX;
  2861.             glBindTexture( GL_TEXTURE_2D, GLTexture_GetTextureID( &TxBars ) );
  2862.             xl=((float)barrect[bartype].left)/128;
  2863.             xr=((float)barrect[bartype].right)/128;
  2864.             yt=((float)barrect[bartype].top)/128;
  2865.             yb=((float)barrect[bartype].bottom)/128;
  2866.             width=barrect[bartype].right-barrect[bartype].left; height=barrect[bartype].bottom-barrect[bartype].top;
  2867.             glBegin( GL_QUADS );
  2868.                 glTexCoord2f( xl, yb );   glVertex2i( x,       scry-y-height );
  2869.                 glTexCoord2f( xr, yb );   glVertex2i( x+width, scry-y-height );
  2870.                 glTexCoord2f( xr, yt );   glVertex2i( x+width, scry-y );
  2871.                 glTexCoord2f( xl, yt );   glVertex2i( x,       scry-y );
  2872.             glEnd();
  2873.  
  2874.             // Draw the empty ones
  2875.             noticks = maxticks-ticks;
  2876.             if(noticks > (NUMTICK-ticks)) noticks = (NUMTICK-ticks);
  2877.             barrect[0].right = (noticks<<3)+TABX;
  2878.             glBindTexture( GL_TEXTURE_2D, GLTexture_GetTextureID( &TxBars ) );
  2879.             xl=((float)barrect[0].left)/128;
  2880.             xr=((float)barrect[0].right)/128;
  2881.             yt=((float)barrect[0].top)/128;
  2882.             yb=((float)barrect[0].bottom)/128;
  2883.             width=barrect[0].right-barrect[0].left; height=barrect[0].bottom-barrect[0].top;
  2884.             glBegin( GL_QUADS );
  2885.                 glTexCoord2f( xl, yb );   glVertex2i( (ticks<<3)+x,       scry-y-height );
  2886.                 glTexCoord2f( xr, yb );   glVertex2i( (ticks<<3)+x+width, scry-y-height );
  2887.                 glTexCoord2f( xr, yt );   glVertex2i( (ticks<<3)+x+width, scry-y );
  2888.                 glTexCoord2f( xl, yt );   glVertex2i( (ticks<<3)+x,       scry-y );
  2889.             glEnd();
  2890.             maxticks-=NUMTICK;
  2891.             y+=BARY;
  2892.         }
  2893.  
  2894.  
  2895.         // Draw full rows of empty ticks
  2896.         while(maxticks >= NUMTICK)
  2897.         {
  2898.             barrect[0].right = BARX;
  2899.             glBindTexture( GL_TEXTURE_2D, GLTexture_GetTextureID( &TxBars ) );
  2900.             xl=((float)barrect[0].left)/128;
  2901.             xr=((float)barrect[0].right)/128;
  2902.             yt=((float)barrect[0].top)/128;
  2903.             yb=((float)barrect[0].bottom)/128;
  2904.             width=barrect[0].right-barrect[0].left; height=barrect[0].bottom-barrect[0].top;
  2905.             glBegin( GL_QUADS );
  2906.                 glTexCoord2f( xl, yb );   glVertex2i( x,       scry-y-height );
  2907.                 glTexCoord2f( xr, yb );   glVertex2i( x+width, scry-y-height );
  2908.                 glTexCoord2f( xr, yt );   glVertex2i( x+width, scry-y );
  2909.                 glTexCoord2f( xl, yt );   glVertex2i( x,       scry-y );
  2910.             glEnd();
  2911.             y+=BARY;
  2912.             maxticks-=NUMTICK;
  2913.         }
  2914.  
  2915.  
  2916.         // Draw the last of the empty ones
  2917.         if(maxticks > 0)
  2918.         {
  2919.             barrect[0].right = (maxticks<<3)+TABX;
  2920.             glBindTexture( GL_TEXTURE_2D, GLTexture_GetTextureID( &TxBars ) );
  2921.             xl=((float)barrect[0].left)/128;
  2922.             xr=((float)barrect[0].right)/128;
  2923.             yt=((float)barrect[0].top)/128;
  2924.             yb=((float)barrect[0].bottom)/128;
  2925.             width=barrect[0].right-barrect[0].left; height=barrect[0].bottom-barrect[0].top;
  2926.             glBegin( GL_QUADS );
  2927.                 glTexCoord2f( xl, yb );   glVertex2i( x,       scry-y-height );
  2928.                 glTexCoord2f( xr, yb );   glVertex2i( x+width, scry-y-height );
  2929.                 glTexCoord2f( xr, yt );   glVertex2i( x+width, scry-y );
  2930.                 glTexCoord2f( xl, yt );   glVertex2i( x,       scry-y );
  2931.             glEnd();
  2932.             y+=BARY;
  2933.         }
  2934.     }
  2935.  
  2936.     return y;
  2937. }
  2938.  
  2939. //--------------------------------------------------------------------------------------------
  2940. void BeginText(void)
  2941. {
  2942.     EnableTexturing();        // Enable texture mapping
  2943.     glBindTexture( GL_TEXTURE_2D, GLTexture_GetTextureID( &TxFont ) );
  2944.     glAlphaFunc(GL_GREATER,0);
  2945.     glEnable(GL_ALPHA_TEST);
  2946.     glDisable(GL_DEPTH_TEST);
  2947.     glDisable(GL_CULL_FACE);
  2948. }
  2949.  
  2950. //--------------------------------------------------------------------------------------------
  2951. void EndText()
  2952. {
  2953.     glDisable(GL_BLEND);
  2954.     glDisable(GL_ALPHA_TEST);
  2955. }
  2956.  
  2957. //--------------------------------------------------------------------------------------------
  2958. void draw_string(char *szText, int x, int y)
  2959. {
  2960.     // ZZ> This function spits a line of null terminated text onto the backbuffer
  2961.     unsigned char cTmp = szText[0];
  2962.     int cnt = 1;
  2963.  
  2964.     BeginText();
  2965.  
  2966.     while(cTmp != 0)
  2967.     {
  2968.         // Convert ASCII to our own little font
  2969.         if(cTmp == '~')
  2970.         {
  2971.             // Use squiggle for tab
  2972.             x = x & (~TABAND);
  2973.             x+=TABAND+1;
  2974.         }
  2975.         else
  2976.         {
  2977.             // Normal letter
  2978.             cTmp = asciitofont[cTmp];
  2979.             draw_one_font(cTmp, x, y);
  2980.             x+=fontxspacing[cTmp];
  2981.         }
  2982.         cTmp=szText[cnt];
  2983.         cnt++;
  2984.     }
  2985.     EndText();
  2986. }
  2987.  
  2988. //--------------------------------------------------------------------------------------------
  2989. int length_of_word(char *szText)
  2990. {
  2991.     // ZZ> This function returns the number of pixels the
  2992.     //     next word will take on screen in the x direction
  2993.     
  2994.     // Count all preceeding spaces
  2995.     int x = 0;
  2996.     int cnt = 0;
  2997.     unsigned char cTmp = szText[cnt];
  2998.  
  2999.     while(cTmp == ' ' || cTmp == '~')
  3000.     {
  3001.         if(cTmp == ' ')
  3002.         {
  3003.             x+=fontxspacing[asciitofont[cTmp]];
  3004.         }
  3005.         else
  3006.         {
  3007.             x+=TABAND+1;
  3008.         }
  3009.         cnt++;
  3010.         cTmp = szText[cnt];
  3011.     }
  3012.  
  3013.  
  3014.     while(cTmp != ' ' && cTmp != '~' && cTmp != 0)
  3015.     {
  3016.         x += fontxspacing[asciitofont[cTmp]];
  3017.         cnt++;
  3018.         cTmp = szText[cnt];
  3019.     }
  3020.     return x;
  3021. }
  3022.  
  3023. //--------------------------------------------------------------------------------------------
  3024. int draw_wrap_string(char *szText, int x, int y, int maxx)
  3025. {
  3026.     // ZZ> This function spits a line of null terminated text onto the backbuffer,
  3027.     //     wrapping over the right side and returning the new y value
  3028.     int sttx = x;
  3029.     unsigned char cTmp = szText[0];
  3030.     int newy = y+fontyspacing;
  3031.     unsigned char newword = TRUE;
  3032.     int cnt = 1;
  3033.  
  3034.     BeginText();
  3035.  
  3036.     maxx = maxx+sttx;
  3037.  
  3038.     while(cTmp != 0)
  3039.     {
  3040.         // Check each new word for wrapping
  3041.         if(newword)
  3042.         {
  3043.             int endx = x + length_of_word(szText + cnt - 1);
  3044.             
  3045.             newword = FALSE;
  3046.             if(endx > maxx)
  3047.             {
  3048.                 // Wrap the end and cut off spaces and tabs
  3049.                 x = sttx+fontyspacing;
  3050.                 y+=fontyspacing;
  3051.                 newy+=fontyspacing;
  3052.                 while(cTmp == ' ' || cTmp == '~')
  3053.                 {
  3054.                     cTmp=szText[cnt];
  3055.                     cnt++;
  3056.                 }
  3057.             }
  3058.         }
  3059.         else
  3060.         {
  3061.             if(cTmp == '~')
  3062.             {
  3063.                 // Use squiggle for tab
  3064.                 x = x & (~TABAND);
  3065.                 x+=TABAND+1;
  3066.             }
  3067.             else
  3068.             {
  3069.                 // Normal letter
  3070.                 cTmp = asciitofont[cTmp];
  3071.                 draw_one_font(cTmp, x, y);
  3072.                 x+=fontxspacing[cTmp];
  3073.             }
  3074.             cTmp=szText[cnt];
  3075.             if(cTmp == '~' || cTmp == ' ')
  3076.             {
  3077.                 newword = TRUE;
  3078.             }
  3079.             cnt++;
  3080.         }
  3081.     }
  3082.     EndText();
  3083.     return newy;
  3084. }
  3085.  
  3086. //--------------------------------------------------------------------------------------------
  3087. int draw_status(unsigned short character, int x, int y)
  3088. {
  3089.     // ZZ> This function shows a character's icon, status and inventory
  3090.     //     The x,y coordinates are the top left point of the image to draw
  3091.     unsigned short item;
  3092.     char cTmp;
  3093.     char *readtext;
  3094.  
  3095.     int life = chrlife[character]>>8;
  3096.     int lifemax = chrlifemax[character]>>8;
  3097.     int mana = chrmana[character]>>8;
  3098.     int manamax = chrmanamax[character]>>8;
  3099.     int cnt = lifemax;
  3100.     
  3101.     /* [claforte] This can be removed
  3102.         Note: This implies that the status line assumes that the max life and mana
  3103.               representable is 50.
  3104.       
  3105.     if(cnt > 50) cnt = 50;
  3106.     if(cnt == 0) cnt = -9;
  3107.     cnt = manamax;
  3108.     if(cnt > 50) cnt = 50;
  3109.     if(cnt == 0) cnt = -9;
  3110.     */
  3111.  
  3112.     // Write the character's first name
  3113.     if(chrnameknown[character])
  3114.       readtext = chrname[character];
  3115.     else
  3116.       readtext = capclassname[chrmodel[character]];
  3117.  
  3118.     for (cnt = 0; cnt < 6; cnt++)
  3119.     {
  3120.         cTmp = readtext[cnt];
  3121.         if(cTmp == ' ' || cTmp == 0)
  3122.         {
  3123.             generictext[cnt] = 0;
  3124.             break;
  3125.         }
  3126.         else
  3127.             generictext[cnt] = cTmp;
  3128.     }
  3129.     generictext[6] = 0;
  3130.     draw_string(generictext, x+8, y); y+=fontyspacing;
  3131.  
  3132.  
  3133.     // Write the character's money
  3134.     sprintf(generictext, "$%4d", chrmoney[character]);
  3135.     draw_string(generictext, x+8, y); y+=fontyspacing+8;
  3136.  
  3137.  
  3138.     // Draw the icons
  3139.     draw_one_icon(madskintoicon[chrtexture[character]], x+40, y, chrsparkle[character]);
  3140.     item = chrholdingwhich[character][0];
  3141.     if(item!=MAXCHR)
  3142.     {
  3143.         if(chricon[item])
  3144.         {
  3145.             draw_one_icon(madskintoicon[chrtexture[item]], x+8, y, chrsparkle[item]);
  3146.             if(chrammomax[item]!=0 && chrammoknown[item])
  3147.             {
  3148.                 if(capisstackable[chrmodel[item]]==FALSE || chrammo[item]>1)
  3149.                 {
  3150.                     // Show amount of ammo left
  3151.                     sprintf(generictext, "%2d", chrammo[item]);
  3152.                     draw_string(generictext, x+8, y-8);
  3153.                 }
  3154.             }
  3155.         }
  3156.         else
  3157.             draw_one_icon(bookicon+(chrmoney[item]&3), x+8, y, chrsparkle[item]);
  3158.     }
  3159.     else
  3160.         draw_one_icon(NULLICON, x+8, y, NOSPARKLE);
  3161.  
  3162.     item = chrholdingwhich[character][1];
  3163.     if(item!=MAXCHR)
  3164.     {
  3165.         if(chricon[item])
  3166.         {
  3167.             draw_one_icon(madskintoicon[chrtexture[item]], x+72, y, chrsparkle[item]);
  3168.             if(chrammomax[item]!=0 && chrammoknown[item])
  3169.             {
  3170.                 if(capisstackable[chrmodel[item]]==FALSE || chrammo[item]>1)
  3171.                 {
  3172.                     // Show amount of ammo left
  3173.                     sprintf(generictext, "%2d", chrammo[item]);
  3174.                     draw_string(generictext, x+72, y-8);
  3175.                 }
  3176.             }
  3177.         }
  3178.         else
  3179.             draw_one_icon(bookicon+(chrmoney[item]&3), x+72, y, chrsparkle[item]);
  3180.     }
  3181.     else
  3182.         draw_one_icon(NULLICON, x+72, y, NOSPARKLE);
  3183.  
  3184.     y+=32;
  3185.  
  3186.     // Draw the bars
  3187.     if(chralive[character])
  3188.         y = draw_one_bar(chrlifecolor[character], x, y, life, lifemax);
  3189.     else
  3190.         y = draw_one_bar(0, x, y, 0, lifemax);  // Draw a black bar
  3191.  
  3192.     y = draw_one_bar(chrmanacolor[character], x, y, mana, manamax);
  3193.     return y;
  3194. }
  3195.  
  3196. //--------------------------------------------------------------------------------------------
  3197. void draw_text()
  3198. {
  3199.     // ZZ> This function spits out some words
  3200.     char text[512];
  3201.     int y, cnt, tnc, fifties, seconds, minutes;
  3202.  
  3203.  
  3204.     Begin2DMode();
  3205.     // Status bars
  3206.     y = 0;
  3207.     if(staton)
  3208.     {
  3209.         for (cnt = 0; cnt < numstat && y < scry; cnt++)
  3210.             y = draw_status(statlist[cnt], scrx-BARX, y);
  3211.     }
  3212.  
  3213.     // Map display
  3214.     if(mapon)
  3215.     {
  3216.         draw_map(0, scry-MAPSIZE);
  3217.         
  3218.         for (cnt = 0; cnt < numblip; cnt++)
  3219.             draw_blip(blipc[cnt], blipx[cnt], blipy[cnt]+scry-MAPSIZE);
  3220.         
  3221.         if(youarehereon && (wldframe&8))
  3222.         {
  3223.             for (cnt = 0; cnt < MAXPLAYER; cnt++)
  3224.             {
  3225.                 if(plavalid[cnt] && pladevice[cnt] != INPUTNONE)
  3226.                 {
  3227.                     tnc = plaindex[cnt];
  3228.                     if(chralive[tnc])
  3229.                         draw_blip(0, chrxpos[tnc]*MAPSIZE/meshedgex, (chrypos[tnc]*MAPSIZE/meshedgey)+scry-MAPSIZE);
  3230.                 }
  3231.             }
  3232.         }
  3233.     }
  3234.  
  3235.  
  3236.     // FPS text
  3237.     y = 0;
  3238.     if(outofsync)
  3239.     {
  3240.         sprintf(text, "OUT OF SYNC, TRY RTS...");
  3241.         draw_string(text, 0, y);  y+=fontyspacing;
  3242.     }
  3243.  
  3244.     if(parseerror)
  3245.     {
  3246.         sprintf(text, "SCRIPT ERROR ( SEE PARSEERR.TXT )");
  3247.         draw_string(text, 0, y);  
  3248.         y+=fontyspacing;
  3249.     }
  3250.     
  3251.     if(fpson)
  3252.     {
  3253.         draw_string(szfpstext, 0, y);  
  3254.         y+=fontyspacing;
  3255.     }
  3256.  
  3257.  
  3258.     if(SDLKEYDOWN(SDLK_F1))
  3259.     {
  3260.         // In-Game help
  3261.         sprintf(text, "!!!MOUSE HELP!!!");
  3262.         draw_string(text, 0, y);  y+=fontyspacing;
  3263.         if(rtscontrol)
  3264.         {
  3265.             if(allselect)
  3266.             {
  3267.                 sprintf(text, "  Left Click to order units");
  3268.                 draw_string(text, 0, y);  y+=fontyspacing;
  3269.             }
  3270.             else
  3271.             {
  3272.                 sprintf(text, "  Left Drag to select units");
  3273.                 draw_string(text, 0, y);  y+=fontyspacing;
  3274.                 sprintf(text, "  Left Click to order them");
  3275.                 draw_string(text, 0, y);  y+=fontyspacing;
  3276.             }
  3277.         }
  3278.         else
  3279.         {
  3280.             sprintf(text, "  Edit CONTROLS.TXT to change");
  3281.             draw_string(text, 0, y);  y+=fontyspacing;
  3282.             sprintf(text, "  Left Click to use an item");
  3283.             draw_string(text, 0, y);  y+=fontyspacing;
  3284.             sprintf(text, "  Left and Right Click to grab");
  3285.             draw_string(text, 0, y);  y+=fontyspacing;
  3286.             sprintf(text, "  Middle Click to jump");
  3287.             draw_string(text, 0, y);  y+=fontyspacing;
  3288.             sprintf(text, "  A and S keys do stuff");
  3289.             draw_string(text, 0, y);  y+=fontyspacing;
  3290.         }
  3291.         sprintf(text, "  Right Drag to move camera");
  3292.         draw_string(text, 0, y);  y+=fontyspacing;
  3293.     }
  3294.     if(SDLKEYDOWN(SDLK_F2))
  3295.     {
  3296.         // In-Game help
  3297.         sprintf(text, "!!!JOYSTICK HELP!!!");
  3298.         draw_string(text, 0, y);  y+=fontyspacing;
  3299.         if(rtscontrol)
  3300.         {
  3301.             sprintf(text, "  Joystick not available");
  3302.             draw_string(text, 0, y);  y+=fontyspacing;
  3303.         }
  3304.         else
  3305.         {
  3306.             sprintf(text, "  Edit CONTROLS.TXT to change");
  3307.             draw_string(text, 0, y);  y+=fontyspacing;
  3308.             sprintf(text, "  Hit the buttons");
  3309.             draw_string(text, 0, y);  y+=fontyspacing;
  3310.             sprintf(text, "  You'll figure it out");
  3311.             draw_string(text, 0, y);  y+=fontyspacing;
  3312.         }
  3313.     }
  3314.     if(SDLKEYDOWN(SDLK_F3))
  3315.     {
  3316.         // In-Game help
  3317.         sprintf(text, "!!!KEYBOARD HELP!!!");
  3318.         draw_string(text, 0, y);  y+=fontyspacing;
  3319.         if(rtscontrol)
  3320.         {
  3321.             sprintf(text, "  Keyboard not available");
  3322.             draw_string(text, 0, y);  y+=fontyspacing;
  3323.         }
  3324.         else
  3325.         {
  3326.             sprintf(text, "  Edit CONTROLS.TXT to change");
  3327.             draw_string(text, 0, y);  y+=fontyspacing;
  3328.             sprintf(text, "  TGB control one hand");
  3329.             draw_string(text, 0, y);  y+=fontyspacing;
  3330.             sprintf(text, "  YHN control the other");
  3331.             draw_string(text, 0, y);  y+=fontyspacing;
  3332.             sprintf(text, "  Keypad to move and jump");
  3333.             draw_string(text, 0, y);  y+=fontyspacing;
  3334.             sprintf(text, "  Number keys for stats");
  3335.             draw_string(text, 0, y);  y+=fontyspacing;
  3336.         }
  3337.     }
  3338.     if(SDLKEYDOWN(SDLK_F5))
  3339.     {
  3340.         // Debug information
  3341.         sprintf(text, "!!!DEBUG MODE-5!!!");
  3342.         draw_string(text, 0, y);  y+=fontyspacing;
  3343.         sprintf(text, "  CAM %f %f", camx, camy);
  3344.         draw_string(text, 0, y);  y+=fontyspacing;
  3345.         tnc = plaindex[0];
  3346.         sprintf(text, "  PLA0DEF %d %d %d %d %d %d %d %d", 
  3347.                             chrdamagemodifier[tnc][0]&3,
  3348.                             chrdamagemodifier[tnc][1]&3,
  3349.                             chrdamagemodifier[tnc][2]&3,
  3350.                             chrdamagemodifier[tnc][3]&3,
  3351.                             chrdamagemodifier[tnc][4]&3,
  3352.                             chrdamagemodifier[tnc][5]&3,
  3353.                             chrdamagemodifier[tnc][6]&3,
  3354.                             chrdamagemodifier[tnc][7]&3);
  3355.         draw_string(text, 0, y);  y+=fontyspacing;
  3356.         tnc = plaindex[0];
  3357.         sprintf(text, "  PLA0 %5.1f %5.1f", chrxpos[tnc]/128.0, chrypos[tnc]/128.0);
  3358.         draw_string(text, 0, y);  y+=fontyspacing;
  3359.         tnc = plaindex[1];
  3360.         sprintf(text, "  PLA1 %5.1f %5.1f", chrxpos[tnc]/128.0, chrypos[tnc]/128.0);
  3361.         draw_string(text, 0, y);  y+=fontyspacing;
  3362.     }
  3363.     if(SDLKEYDOWN(SDLK_F6))
  3364.     {
  3365.         // More debug information
  3366.         sprintf(text, "!!!DEBUG MODE-6!!!");
  3367.         draw_string(text, 0, y);  y+=fontyspacing;
  3368.         sprintf(text, "  FREEPRT %d", numfreeprt);
  3369.         draw_string(text, 0, y);  y+=fontyspacing;
  3370.         sprintf(text, "  FREECHR %d",  numfreechr);
  3371.         draw_string(text, 0, y);  y+=fontyspacing;
  3372.         sprintf(text, "  MACHINE %d", localmachine);
  3373.         draw_string(text, 0, y);  y+=fontyspacing;
  3374.         sprintf(text, "  EXPORT %d", exportvalid);
  3375.         draw_string(text, 0, y);  y+=fontyspacing;
  3376.         sprintf(text, "  FOGAFF %d", fogaffectswater);
  3377.         draw_string(text, 0, y);  y+=fontyspacing;
  3378.         sprintf(text, "  PASS %d/%d", numshoppassage, numpassage);
  3379.         draw_string(text, 0, y);  y+=fontyspacing;
  3380.         sprintf(text, "  NETPLAYERS %d", numplayer);
  3381.         draw_string(text, 0, y);  y+=fontyspacing;
  3382.         sprintf(text, "  DAMAGEPART %d", damagetileparttype);
  3383.         draw_string(text, 0, y);  y+=fontyspacing;
  3384.     }
  3385.     if(SDLKEYDOWN(SDLK_F7))
  3386.     {
  3387.         // White debug mode
  3388.         sprintf(text, "!!!DEBUG MODE-7!!!");
  3389.         draw_string(text, 0, y);  y+=fontyspacing;
  3390.         sprintf(text, "CAM %f %f %f %f", (mView)_CNV(0,0), (mView)_CNV(1,0), (mView)_CNV(2,0), (mView)_CNV(3,0));
  3391.         draw_string(text, 0, y);  y+=fontyspacing;
  3392.         sprintf(text, "CAM %f %f %f %f", (mView)_CNV(0,1), (mView)_CNV(1,1), (mView)_CNV(2,1), (mView)_CNV(3,1));
  3393.         draw_string(text, 0, y);  y+=fontyspacing;
  3394.         sprintf(text, "CAM %f %f %f %f", (mView)_CNV(0,2), (mView)_CNV(1,2), (mView)_CNV(2,2), (mView)_CNV(3,2));
  3395.         draw_string(text, 0, y);  y+=fontyspacing;
  3396.         sprintf(text, "CAM %f %f %f %f", (mView)_CNV(0,3), (mView)_CNV(1,3), (mView)_CNV(2,3), (mView)_CNV(3,3));
  3397.         draw_string(text, 0, y);  y+=fontyspacing;
  3398.         sprintf(text, "x %f", camcenterx);
  3399.         draw_string(text, 0, y);  y+=fontyspacing;
  3400.         sprintf(text, "y %f", camcentery);
  3401.         draw_string(text, 0, y);  y+=fontyspacing;
  3402.         sprintf(text, "turn %d %d", autoturncamera, doturntime);
  3403.         draw_string(text, 0, y);  y+=fontyspacing;
  3404.     }
  3405.     if(SDLKEYDOWN(SDLK_F8) && networkon==FALSE)
  3406.     {
  3407.         // Pause debug mode...  Don't show text, so screen captures look better
  3408. //        sprintf(text, "!!!DEBUG MODE-8!!!");
  3409. //        draw_string(text, 0, y);  y+=fontyspacing;
  3410.     }
  3411.     if(timeron)
  3412.     {
  3413.         fifties = (timervalue%50)<<1;
  3414.         seconds = ((timervalue/50)%60);
  3415.         minutes = (timervalue/3000);
  3416.         sprintf(text, "=%d:%02d:%02d=", minutes, seconds, fifties);
  3417.         draw_string(text, 0, y);  
  3418.         y+=fontyspacing;
  3419.     }
  3420.     if(waitingforplayers)
  3421.     {
  3422.         sprintf(text, "Waiting for players...");
  3423.         draw_string(text, 0, y);  
  3424.         y+=fontyspacing;
  3425.     }
  3426.     if(!rtscontrol)
  3427.     {
  3428.         if(alllocalpladead || respawnanytime)
  3429.         {
  3430.             if(respawnvalid)
  3431.             {
  3432.                 sprintf(text, "PRESS SPACE TO RESPAWN");
  3433.             }
  3434.             else
  3435.             {
  3436.                 sprintf(text, "PRESS ESCAPE TO QUIT");
  3437.             }
  3438.             draw_string(text, 0, y);  
  3439.             y+=fontyspacing;
  3440.         }
  3441.         else
  3442.         {
  3443.             if(beatmodule)
  3444.             {
  3445.                 sprintf(text, "VICTORY!  PRESS ESCAPE");
  3446.                 draw_string(text, 0, y);  
  3447.                 y+=fontyspacing;
  3448.             }
  3449.         }
  3450.     }
  3451.  
  3452.  
  3453.     // Network message input
  3454.     if(netmessagemode)
  3455.     {
  3456.         y = draw_wrap_string(netmessage, 0, y, scrx-wraptolerance);
  3457.     }
  3458.  
  3459.  
  3460.     // Messages
  3461.     if(messageon)
  3462.     {
  3463.         // Display the messages
  3464.         tnc = msgstart;
  3465.         
  3466.         for (cnt = 0; cnt < maxmessage; cnt++)
  3467.         {
  3468.             if(msgtime[tnc]>0)
  3469.             {
  3470.                 y = draw_wrap_string(msgtextdisplay[tnc], 0, y, scrx-wraptolerance);
  3471.                 msgtime[tnc] -= msgtimechange;
  3472.             }
  3473.             tnc++;
  3474.             tnc = tnc % maxmessage;
  3475.         }
  3476.     }
  3477.     End2DMode();
  3478. }
  3479.  
  3480. //--------------------------------------------------------------------------------------------
  3481. void flip_pages()
  3482.     SDL_GL_SwapBuffers(); 
  3483. }
  3484.  
  3485. //--------------------------------------------------------------------------------------------
  3486. void draw_scene()
  3487. {
  3488.     Begin3DMode();
  3489.  
  3490.     make_prtlist();
  3491.     do_dynalight();
  3492.     light_characters();
  3493.     light_particles();
  3494.     
  3495.     if(zreflect) //DO REFLECTIONS
  3496.         draw_scene_zreflection();
  3497.     else
  3498.         draw_scene_sadreflection();
  3499.     
  3500.     End3DMode();
  3501. }
  3502.  
  3503. //--------------------------------------------------------------------------------------------
  3504. void build_select(float tlx, float tly, float brx, float bry, unsigned char team)
  3505. {
  3506.     // ZZ> This function checks which characters are in the selection rectangle
  3507. /*PORT
  3508.     D3DLVERTEX v[MAXPRT];
  3509.     D3DTLVERTEX vt[MAXPRT];
  3510.     int numbertocheck, character, cnt, first, sound;
  3511.  
  3512.  
  3513.     // Unselect old ones
  3514.     clear_select();
  3515.  
  3516.  
  3517.     // Figure out who to check
  3518.     numbertocheck = 0;
  3519.     cnt = 0;
  3520.     while(cnt < MAXCHR)
  3521.     {
  3522.         if(chrteam[cnt] == team && chron[cnt] && !chrinpack[cnt])
  3523.         {
  3524.             v[numbertocheck].x = (D3DVALUE) chrxpos[cnt];
  3525.             v[numbertocheck].y = (D3DVALUE) chrypos[cnt];
  3526.             v[numbertocheck].z = (D3DVALUE) chrzpos[cnt];
  3527.             v[numbertocheck].color = cnt;  // Store an index in the color slot...
  3528.             v[numbertocheck].dwReserved = 0;
  3529.             numbertocheck++;
  3530.         }
  3531.         cnt++;
  3532.     }
  3533.  
  3534.  
  3535.     // Figure out where the points go onscreen
  3536.     lpD3DDDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mWorld);
  3537.     transform_vertices(numbertocheck, v, vt);
  3538.  
  3539.  
  3540.     first = TRUE;
  3541.     cnt = 0;
  3542.     while(cnt < numbertocheck)
  3543.     {
  3544.         // Only check if in front of camera
  3545.         if(vt[cnt].dvRHW > 0)
  3546.         {
  3547.             // Check the rectangle
  3548.             if(vt[cnt].dvSX > tlx && vt[cnt].dvSX < brx)
  3549.             {
  3550.                 if(vt[cnt].dvSY > tly && vt[cnt].dvSY < bry)
  3551.                 {
  3552.                     // Select the character
  3553.                     character = v[cnt].color;
  3554.                     add_select(character);
  3555.                     if(first)
  3556.                     {
  3557.                         // Play the select speech for the first one picked
  3558.                         sound = chrwavespeech[character][SPEECHSELECT];
  3559.                         if(sound >= 0 && sound < MAXWAVE)
  3560.                         play_sound_pvf(capwaveindex[chrmodel[character]][sound], PANMID, VOLMAX, 11025);
  3561.                         first = FALSE;
  3562.                     }
  3563.                 }
  3564.             }
  3565.         }
  3566.         cnt++;
  3567.     }
  3568. */
  3569. }
  3570.  
  3571. //--------------------------------------------------------------------------------------------
  3572. unsigned short build_select_target(float tlx, float tly, float brx, float bry, unsigned char team)
  3573. {
  3574.     // ZZ> This function checks which characters are in the selection rectangle,
  3575.     //     and returns the first one found
  3576. /*PORT
  3577.     D3DLVERTEX v[MAXPRT];
  3578.     D3DTLVERTEX vt[MAXPRT];
  3579.     int numbertocheck, character, cnt;
  3580.  
  3581.  
  3582.     // Figure out who to check
  3583.     numbertocheck = 0;
  3584.     // Add enemies first
  3585.     cnt = 0;
  3586.     while(cnt < MAXCHR)
  3587.     {
  3588.         if(teamhatesteam[team][chrteam[cnt]] && chron[cnt] && !chrinpack[cnt])
  3589.         {
  3590.             v[numbertocheck].x = (D3DVALUE) chrxpos[cnt];
  3591.             v[numbertocheck].y = (D3DVALUE) chrypos[cnt];
  3592.             v[numbertocheck].z = (D3DVALUE) chrzpos[cnt];
  3593.             v[numbertocheck].color = cnt;  // Store an index in the color slot...
  3594.             v[numbertocheck].dwReserved = 0;
  3595.             numbertocheck++;
  3596.         }
  3597.         cnt++;
  3598.     }
  3599.     // Add allies next
  3600.     cnt = 0;
  3601.     while(cnt < MAXCHR)
  3602.     {
  3603.         if(teamhatesteam[team][chrteam[cnt]] == FALSE && chron[cnt] && !chrinpack[cnt])
  3604.         {
  3605.             v[numbertocheck].x = (D3DVALUE) chrxpos[cnt];
  3606.             v[numbertocheck].y = (D3DVALUE) chrypos[cnt];
  3607.             v[numbertocheck].z = (D3DVALUE) chrzpos[cnt];
  3608.             v[numbertocheck].color = cnt;  // Store an index in the color slot...
  3609.             v[numbertocheck].dwReserved = 0;
  3610.             numbertocheck++;
  3611.         }
  3612.         cnt++;
  3613.     }
  3614.  
  3615.  
  3616.     // Figure out where the points go onscreen
  3617.     lpD3DDDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mWorld);
  3618.     transform_vertices(numbertocheck, v, vt);
  3619.  
  3620.  
  3621.     cnt = 0;
  3622.     while(cnt < numbertocheck)
  3623.     {
  3624.         // Only check if in front of camera
  3625.         if(vt[cnt].dvRHW > 0)
  3626.         {
  3627.             // Check the rectangle
  3628.             if(vt[cnt].dvSX > tlx && vt[cnt].dvSX < brx)
  3629.             {
  3630.                 if(vt[cnt].dvSY > tly && vt[cnt].dvSY < bry)
  3631.                 {
  3632.                     // Select the character
  3633.                     character = v[cnt].color;
  3634.                     return character;
  3635.                 }
  3636.             }
  3637.         }
  3638.         cnt++;
  3639.     }
  3640.     return MAXCHR;
  3641. */
  3642. return 0;
  3643. }
  3644.  
  3645. //--------------------------------------------------------------------------------------------
  3646. void move_rtsxy()
  3647. {
  3648.     // ZZ> This function iteratively transforms the cursor back to world coordinates
  3649. /*PORT
  3650.     D3DLVERTEX v[1];
  3651.     D3DTLVERTEX vt[1];
  3652.     int numbertocheck, x, y, fan;
  3653.     float sin, cos, trailrate, level;
  3654.  
  3655.  
  3656.  
  3657.     // Figure out where the rtsxy is at on the screen
  3658.     x = rtsx;
  3659.     y = rtsy;
  3660.     fan = meshfanstart[y>>7]+(x>>7);
  3661.     level = get_level(rtsx, rtsy, fan, FALSE);
  3662.     v[0].x = (D3DVALUE) rtsx;
  3663.     v[0].y = (D3DVALUE) rtsy;
  3664.     v[0].z = level;
  3665.     v[0].color = 0;
  3666.     v[0].dwReserved = 0;
  3667.     numbertocheck = 1;
  3668.  
  3669.  
  3670.     // Figure out where the points go onscreen
  3671.     lpD3DDDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mWorld);
  3672.     transform_vertices(numbertocheck, v, vt);
  3673.  
  3674.  
  3675.     if(vt[0].dvRHW < 0)
  3676.     {
  3677.         // Move it to camtrackxy if behind the camera
  3678.         rtsx = camtrackx;
  3679.         rtsy = camtracky;
  3680.     }
  3681.     else
  3682.     {
  3683.         // Move it to closer to the onscreen cursor
  3684.         trailrate = ABS(cursorx-vt[0].dvSX) + ABS(cursory-vt[0].dvSY);
  3685.         trailrate *= rtstrailrate;
  3686.         sin = turntosin[camturnleftrightshort>>2]*trailrate;
  3687.         cos = turntosin[((camturnleftrightshort>>2)+4096)&16383]*trailrate;
  3688.         if(vt[0].dvSX < cursorx)
  3689.         {
  3690.             rtsx += cos;
  3691.             rtsy -= sin;
  3692.         }
  3693.         else
  3694.         {
  3695.             rtsx -= cos;
  3696.             rtsy += sin;
  3697.         }
  3698.  
  3699.  
  3700.  
  3701.         if(vt[0].dvSY < cursory)
  3702.         {
  3703.             rtsx += sin;
  3704.             rtsy += cos;
  3705.         }
  3706.         else
  3707.         {
  3708.             rtsx -= sin;
  3709.             rtsy -= cos;
  3710.         }
  3711.     }
  3712. */
  3713. }
  3714.  
  3715. //--------------------------------------------------------------------------------------------
  3716. void do_cursor_rts()
  3717. {
  3718.     // This function implements the RTS mouse cursor
  3719.     int sttx, stty, endx, endy, target, leader;
  3720.     signed short sound;
  3721.  
  3722.  
  3723.     if(mousebutton[1] == 0)
  3724.     {
  3725.         cursorx+=mousex;
  3726.         cursory+=mousey;
  3727.     }
  3728.     if(cursorx < 6)  cursorx = 6;  if (cursorx > scrx-16)  cursorx = scrx-16;
  3729.     if(cursory < 8)  cursory = 8;  if (cursory > scry-24)  cursory = scry-24;
  3730.     move_rtsxy();
  3731.     if(mousebutton[0])
  3732.     {
  3733.         // Moving the end select point
  3734.         pressed = TRUE;
  3735.         rtsendx = cursorx+5;
  3736.         rtsendy = cursory+7;
  3737.  
  3738.         // Draw the selection rectangle
  3739.         if(allselect == FALSE)
  3740.         {
  3741.             sttx = rtssttx;  endx = rtsendx;  if(sttx > endx)  {  sttx = rtsendx;  endx = rtssttx; }
  3742.             stty = rtsstty;  endy = rtsendy;  if(stty > endy)  {  stty = rtsendy;  endy = rtsstty; }
  3743.             draw_trim_box(sttx, stty, endx, endy);
  3744.         }
  3745.     }
  3746.     else
  3747.     {
  3748.         if(pressed)
  3749.         {
  3750.             // See if we selected anyone
  3751.             if((ABS(rtssttx - rtsendx) + ABS(rtsstty - rtsendy)) > 10 && allselect == FALSE)
  3752.             {
  3753.                 // We drew a box alright
  3754.                 sttx = rtssttx;  endx = rtsendx;  if(sttx > endx)  {  sttx = rtsendx;  endx = rtssttx; }
  3755.                 stty = rtsstty;  endy = rtsendy;  if(stty > endy)  {  stty = rtsendy;  endy = rtsstty; }
  3756.                 build_select(sttx, stty, endx, endy, rtslocalteam);
  3757.             }
  3758.             else
  3759.             {
  3760.                 // We want to issue an order
  3761.                 if(numrtsselect > 0)
  3762.                 {
  3763.                     leader = rtsselect[0];
  3764.                     sttx = rtssttx-20;  endx = rtssttx+20;
  3765.                     stty = rtsstty-20;  endy = rtsstty+20;
  3766.                     target = build_select_target(sttx, stty, endx, endy, rtslocalteam);
  3767.                     if(target == MAXCHR)
  3768.                     {
  3769.                         // No target...
  3770.                         if(SDLKEYDOWN(SDLK_LSHIFT) || SDLKEYDOWN(SDLK_RSHIFT))
  3771.                         {
  3772.                             send_rts_order(rtsx, rtsy, RTSTERRAIN, target);
  3773.                             sound = chrwavespeech[leader][SPEECHTERRAIN];
  3774.                         }
  3775.                         else
  3776.                         {
  3777.                             send_rts_order(rtsx, rtsy, RTSMOVE, target);
  3778.                             sound = wldframe&1;  // Move or MoveAlt
  3779.                             sound = chrwavespeech[leader][sound];
  3780.                         }
  3781.                     }
  3782.                     else
  3783.                     {
  3784.                         if(teamhatesteam[rtslocalteam][chrteam[target]])
  3785.                         {
  3786.                             // Target is an enemy, so issue an attack order
  3787.                             send_rts_order(rtsx, rtsy, RTSATTACK, target);
  3788.                             sound = chrwavespeech[leader][SPEECHATTACK];
  3789.                         }
  3790.                         else
  3791.                         {
  3792.                             // Target is a friend, so issue an assist order
  3793.                             send_rts_order(rtsx, rtsy, RTSASSIST, target);
  3794.                             sound = chrwavespeech[leader][SPEECHASSIST];
  3795.                         }
  3796.                     }
  3797.                     // Do unit speech at 11025 KHz
  3798.                     if(sound >= 0 && sound < MAXWAVE)
  3799.                     {
  3800.                         play_sound_pvf(capwaveindex[chrmodel[leader]][sound], PANMID, VOLMAX, 11025);
  3801.                     }
  3802.                 }
  3803.             }
  3804.             pressed = FALSE;
  3805.         }
  3806.  
  3807.  
  3808.         // Moving the select point
  3809.         rtssttx = cursorx+5;
  3810.         rtsstty = cursory+7;
  3811.         rtsendx = cursorx+5;
  3812.         rtsendy = cursory+7;
  3813.     }
  3814.  
  3815.     // GAC - Don't forget to BeginText() and EndText();
  3816.     BeginText();
  3817.     draw_one_font(11, cursorx-5, cursory-7);
  3818.     EndText ();
  3819. }
  3820.  
  3821. //--------------------------------------------------------------------------------------------
  3822. void draw_main()
  3823. {
  3824.     // ZZ> This function does all the drawing stuff
  3825.     //printf("DIAG: Drawing scene nummeshrenderlistref=%d\n",nummeshrenderlistref);
  3826.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  3827.  
  3828.     draw_scene();
  3829.     draw_text();
  3830.     if(rtscontrol)  
  3831.         do_cursor_rts();
  3832.     
  3833.     flip_pages();
  3834.     allframe++;
  3835.     fpsframe++;
  3836. }
  3837.  
  3838. //--------------------------------------------------------------------------------------------
  3839. int load_one_title_image(int titleimage, char *szLoadName)
  3840. {
  3841.     // ZZ> This function loads a title in the specified image slot, forcing it into
  3842.     //     system memory.  Returns TRUE if it worked
  3843.     GLTexture_Load( &TxTitleImage[titleimage], szLoadName );
  3844.     if ( GLTexture_GetTextureID != 0 )
  3845.     {
  3846.         /* PORT
  3847.         // Set the transparent color
  3848.         DDSetColorKey(lpDDSTitleImage[titleimage], 0); */
  3849.         return TRUE;
  3850.     }
  3851.     return FALSE;
  3852.     
  3853. }
  3854.  
  3855. //--------------------------------------------------------------------------------------------
  3856. void load_all_menu_images()
  3857. {
  3858.     // ZZ> This function loads the title image for each module.  Modules without a
  3859.     //     title are marked as invalid
  3860.  
  3861.     char searchname[15];
  3862.     char loadname[256];
  3863.     char *FileName;
  3864.     FILE* filesave;
  3865.  
  3866.     // Convert searchname
  3867.     strcpy(searchname, "modules/*.mod");
  3868.  
  3869.     // Log a directory list
  3870.     filesave = fopen(FILENAME("basicdat/modules.txt"), "w");
  3871.     if ( filesave != NULL )
  3872.     {
  3873.         fprintf(filesave, "This file logs all of the modules found\n");
  3874.         fprintf(filesave, "** Denotes an invalid module\n\n");
  3875.     }
  3876.  
  3877.     // Search for .mod directories
  3878.     FileName = DirGetFirst(FILENAME(searchname));
  3879.     globalnummodule = 0;
  3880.     while(FileName && globalnummodule < MAXMODULE)
  3881.     {
  3882.         sprintf(modloadname[globalnummodule], "%s", FileName);
  3883.         sprintf(loadname, "modules/%s/gamedat/menu.txt", FileName);
  3884.         if(get_module_data(globalnummodule, loadname))
  3885.         {
  3886.             sprintf(loadname, "modules/%s/gamedat/title.bmp", FileName);
  3887.             if(load_one_title_image(globalnummodule, loadname))
  3888.             {
  3889.                 fprintf(filesave, "%02d.  %s\n", globalnummodule, modlongname[globalnummodule]);
  3890.                 globalnummodule++;
  3891.             }
  3892.             else
  3893.             {
  3894.                 fprintf(filesave, "**.  %s\n", FileName);
  3895.             }
  3896.         }
  3897.         else
  3898.         {
  3899.             fprintf(filesave, "**.  %s\n", FileName);
  3900.         }
  3901.         FileName = DirGetNext();
  3902.     }
  3903.     DirClose();
  3904.     if ( filesave != NULL ) fclose(filesave);
  3905. }
  3906.  
  3907. //--------------------------------------------------------------------------------------------
  3908. void load_menu_trim()
  3909. {
  3910.     // ZZ> This function loads the trim bitmaps
  3911.     int cnt;
  3912.     
  3913.     GLTexture_Load( &TxBlip, "basicdat/blip.bmp" );
  3914.     GLTexture_Load( &TxTrim, "basicdat/trim.bmp" );
  3915.     
  3916.     // Set up the rectangles
  3917.     for (cnt = 0; cnt < NUMBAR; cnt++)
  3918.     {
  3919.         bliprect[cnt].left   = cnt * BLIPSIZE;
  3920.         bliprect[cnt].right  = (cnt * BLIPSIZE) + BLIPSIZE;
  3921.         bliprect[cnt].top    = 0;
  3922.         bliprect[cnt].bottom = BLIPSIZE;
  3923.     }
  3924.     trimrect.left = 0;
  3925.     trimrect.top = 0;
  3926. }
  3927.  
  3928. //--------------------------------------------------------------------------------------------
  3929. void draw_trimx(int x, int y, int length)
  3930. {
  3931.     // ZZ> This function draws a horizontal trim bar
  3932.     GLfloat    txWidth, txHeight, txLength;
  3933.     
  3934.     if ( GLTexture_GetTextureID( &TxTrim ) != 0 )//if( lpDDSTrimX )
  3935.     {
  3936.         /*while( length > 0 )
  3937.         {
  3938.             trimrect.right = length;
  3939.             if(length > TRIMX)  trimrect.right = TRIMX;
  3940.             trimrect.bottom = 4;
  3941.             lpDDSBack->BltFast(x, y, lpDDSTrimX, &trimrect, DDBLTFAST_NOCOLORKEY);
  3942.             length-=TRIMX;
  3943.             x+=TRIMX;
  3944.         }*/
  3945.         
  3946.         /* Calculate the texture width, height, and length */
  3947.         txWidth = ( GLfloat )( GLTexture_GetImageWidth( &TxTrim )/GLTexture_GetDimensions( &TxTrim ) );
  3948.         txHeight = ( GLfloat )( GLTexture_GetImageHeight( &TxTrim )/GLTexture_GetDimensions( &TxTrim ) );
  3949.         txLength = ( GLfloat )( length/GLTexture_GetImageWidth( &TxTrim ) );
  3950.         
  3951.         
  3952.         /* Bind our texture */
  3953.         glBindTexture( GL_TEXTURE_2D, GLTexture_GetTextureID( &TxTrim ) );
  3954.         
  3955.         /* Draw the trim */
  3956.         glColor4f( 1, 1, 1, 1 );
  3957.         glBegin( GL_QUADS );
  3958.             glTexCoord2f( 0, 1 );    glVertex2f( x, scry - y );
  3959.             glTexCoord2f( 0, 1 - txHeight );    glVertex2f( x, scry - y - GLTexture_GetImageHeight( &TxTrim ) );
  3960.             glTexCoord2f( txWidth*txLength, 1 - txHeight );    glVertex2f( x + length, scry - y - GLTexture_GetImageHeight( &TxTrim ) );
  3961.             glTexCoord2f( txWidth*txLength, 1 );    glVertex2f( x + length, scry - y );
  3962.         glEnd();
  3963.     }
  3964. }
  3965.  
  3966. //--------------------------------------------------------------------------------------------
  3967. void draw_trimy(int x, int y, int length)
  3968. {
  3969.     // ZZ> This function draws a vertical trim bar
  3970.     GLfloat    txWidth, txHeight, txLength;
  3971.     
  3972.     if ( GLTexture_GetTextureID( &TxTrim ) != 0 )//if(lpDDSTrimY)
  3973.     {
  3974.         /*while(length > 0)
  3975.         {
  3976.             trimrect.bottom = length;
  3977.             if(length > TRIMY)  trimrect.bottom = TRIMY;
  3978.             trimrect.right = 4;
  3979.             lpDDSBack->BltFast(x, y, lpDDSTrimY, &trimrect, DDBLTFAST_NOCOLORKEY);
  3980.             length-=TRIMY;
  3981.             y+=TRIMY;
  3982.         }*/
  3983.         
  3984.         /* Calculate the texture width, height, and length */
  3985.         txWidth = ( GLfloat )( GLTexture_GetImageWidth( &TxTrim )/GLTexture_GetDimensions( &TxTrim ) );
  3986.         txHeight = ( GLfloat )( GLTexture_GetImageHeight( &TxTrim )/GLTexture_GetDimensions( &TxTrim ) );
  3987.         txLength = ( GLfloat )( length/GLTexture_GetImageHeight( &TxTrim ) );
  3988.         
  3989.         /* Bind our texture */
  3990.         glBindTexture( GL_TEXTURE_2D, GLTexture_GetTextureID( &TxTrim ) );
  3991.         
  3992.         /* Draw the trim */
  3993.         glColor4f( 1, 1, 1, 1 );
  3994.         glBegin( GL_QUADS );
  3995.             glTexCoord2f( 0, 1 );    glVertex2f( x, scry - y );
  3996.             glTexCoord2f( 0, 1 - txHeight*txLength );    glVertex2f( x, scry - y - length );
  3997.             glTexCoord2f( txWidth, 1 - txHeight*txLength );    glVertex2f( x + GLTexture_GetImageWidth( &TxTrim ), scry - y - length );
  3998.             glTexCoord2f( txWidth, 1 );    glVertex2f( x + GLTexture_GetImageWidth( &TxTrim ), scry - y );            
  3999.         glEnd();
  4000.     }
  4001. }
  4002.  
  4003. //--------------------------------------------------------------------------------------------
  4004. void draw_trim_box(int left, int top, int right, int bottom)
  4005. {
  4006.     // ZZ> This function draws a trim rectangle
  4007.     float l,t,r,b;
  4008.     l=((float)left)/scrx;
  4009.     r=((float)right)/scrx;
  4010.     t=((float)top)/scry;
  4011.     b=((float)bottom)/scry;
  4012.  
  4013.     Begin2DMode();
  4014.     
  4015.     draw_trimx(left, top, right-left);
  4016.     draw_trimx(left, bottom-4, right-left);
  4017.     draw_trimy(left, top, bottom-top);
  4018.     draw_trimy(right-4, top, bottom-top);
  4019.  
  4020.     End2DMode();
  4021. }
  4022.  
  4023. //--------------------------------------------------------------------------------------------
  4024. void draw_trim_box_opening(int left, int top, int right, int bottom, float amount)
  4025. {
  4026.     // ZZ> This function draws a trim rectangle, scaled around its center
  4027.     int x = (left + right)>>1;
  4028.     int y = (top + bottom)>>1;
  4029.     left   = (x * (1.0-amount)) + (left * amount);
  4030.     right  = (x * (1.0-amount)) + (right * amount);
  4031.     top    = (y * (1.0-amount)) + (top * amount);
  4032.     bottom = (y * (1.0-amount)) + (bottom * amount);
  4033.     draw_trim_box(left, top, right, bottom);
  4034. }
  4035.  
  4036. //--------------------------------------------------------------------------------------------
  4037. void load_menu()
  4038. {
  4039.     // ZZ> This function loads all of the menu data...  Images are loaded into system
  4040.     // memory
  4041.  
  4042.     load_font( "basicdat/font.bmp", "basicdat/font.txt", TRUE );
  4043.     load_all_menu_images();
  4044. }
  4045.  
  4046. //--------------------------------------------------------------------------------------------
  4047. void draw_titleimage(int image, int x, int y)
  4048. {
  4049.     // ZZ> This function draws a title image on the backbuffer
  4050.     GLfloat    txWidth, txHeight;
  4051.     
  4052.     if ( GLTexture_GetTextureID( &TxTitleImage[image] ) != 0 )//if(lpDDSTitleImage[image])
  4053.     {
  4054.         glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
  4055.         Begin2DMode();
  4056.         glNormal3f( 0, 0, 1 );    // glNormal3f( 0, 1, 0 );
  4057.         
  4058.         /* Calculate the texture width & height */
  4059.         txWidth = ( GLfloat )( GLTexture_GetImageWidth( &TxTitleImage[image] )/GLTexture_GetDimensions( &TxTitleImage[image] ) );
  4060.         txHeight = ( GLfloat )( GLTexture_GetImageHeight( &TxTitleImage[image] )/GLTexture_GetDimensions( &TxTitleImage[image] ) );
  4061.  
  4062.         /* Bind the texture */
  4063.         glBindTexture( GL_TEXTURE_2D, GLTexture_GetTextureID( &TxTitleImage[image] ) );
  4064.         
  4065.         /* Draw the quad */
  4066.         glBegin( GL_QUADS );
  4067.             glTexCoord2f( 0, 1 );    glVertex2f( x, scry - y - GLTexture_GetImageHeight( &TxTitleImage[image] ) );
  4068.             glTexCoord2f( txWidth, 1 );    glVertex2f( x + GLTexture_GetImageWidth( &TxTitleImage[image] ), scry - y - GLTexture_GetImageHeight( &TxTitleImage[image] ) );
  4069.             glTexCoord2f( txWidth, 1-txHeight );    glVertex2f( x + GLTexture_GetImageWidth( &TxTitleImage[image] ), scry - y );
  4070.             glTexCoord2f( 0, 1-txHeight );    glVertex2f( x, scry - y );
  4071.         glEnd();
  4072.         
  4073.         End2DMode();
  4074.     }
  4075. }
  4076.  
  4077. //--------------------------------------------------------------------------------------------
  4078. void do_cursor()
  4079. {
  4080.     // This function implements a mouse cursor
  4081.     read_input();
  4082.     cursorx=mousex;  if(cursorx < 6)  cursorx = 6;  if (cursorx > scrx-16)  cursorx = scrx-16;
  4083.     cursory=mousey;  if(cursory < 8)  cursory = 8;  if (cursory > scry-24)  cursory = scry-24;
  4084.     clicked = FALSE;
  4085.     if(mousebutton[0] && pressed == FALSE)
  4086.     {
  4087.         clicked = TRUE;
  4088.     }
  4089.     pressed = mousebutton[0];
  4090.     BeginText();  // Needed to setup text mode
  4091.     //draw_one_font(11, cursorx-5, cursory-7);
  4092.     draw_one_font(95, cursorx-5, cursory-7);
  4093.     EndText();    // Needed when done with text mode
  4094. }
  4095.  
  4096. /********************> Reshape3D() <*****/
  4097. void Reshape3D( int w, int h )
  4098. {
  4099.     glViewport( 0, 0, w, h );
  4100. }
  4101.  
  4102. int glinit(int argc, char **argv)
  4103. {
  4104.     GLfloat intensity[] = {1.0,1.0,1.0,1.0};
  4105.     
  4106.     /* Depth testing stuff */
  4107.     glClearDepth( 1.0 );
  4108.     glDepthFunc( GL_LESS );
  4109.     glEnable( GL_DEPTH_TEST );
  4110.     
  4111.     /* Enable a single OpenGL light. */
  4112.     //glLightfv(GL_LIGHT0, GL_SPECULAR, light_diffuse);
  4113.     //glLightfv(GL_LIGHT0, GL_POSITION, light_position);
  4114.     //glEnable(GL_LIGHT0);
  4115.     glDisable(GL_LIGHTING);
  4116.     //glLightModelfv(GL_LIGHT_MODEL_AMBIENT,intensity);
  4117.     
  4118.     /* Backface culling */
  4119.     glEnable (GL_CULL_FACE);   // This seems implied - DDOI 
  4120.     glCullFace( GL_BACK );
  4121.     
  4122.     glEnable(GL_COLOR_MATERIAL);    // Need this for color + lighting
  4123.     EnableTexturing();        // Enable texture mapping
  4124.     glShadeModel( GL_SMOOTH );
  4125.     
  4126.     Reshape3D( scrx, scry );
  4127.     
  4128.     return 1;
  4129. }
  4130.  
  4131. void sdlinit(int argc, char **argv)
  4132. {
  4133.     SDL_Surface    *theSurface;
  4134.     int         colordepth;
  4135.     
  4136.     if ( SDL_Init( SDL_INIT_VIDEO|SDL_INIT_AUDIO|SDL_INIT_JOYSTICK) < 0 )
  4137.     {
  4138.         fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError());
  4139.         exit(1);
  4140.     }
  4141.     
  4142.     atexit(SDL_Quit);
  4143.  
  4144.     colordepth=scrd/3;
  4145.  
  4146.     /* Setup the cute windows manager icon */
  4147.     theSurface=SDL_LoadBMP(FILENAME("basicdat/icon.bmp"));
  4148.     if ( theSurface == NULL )
  4149.     {
  4150.         fprintf(stderr, "Unable to load icon\n");
  4151.         exit(1);
  4152.     }
  4153.      SDL_WM_SetIcon(theSurface, NULL);
  4154.     
  4155.     /* Set the OpenGL Attributes */
  4156.     SDL_GL_SetAttribute( SDL_GL_RED_SIZE, colordepth );
  4157.     SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, colordepth  );
  4158.     SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE,  colordepth );
  4159.     SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, scrd );
  4160.     SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
  4161.     
  4162.     theSurface = SDL_SetVideoMode( scrx, scry, scrd, SDL_DOUBLEBUF | SDL_OPENGL | (fullscreen ? SDL_FULLSCREEN : 0));
  4163.     if ( theSurface == NULL )
  4164.     {
  4165.         fprintf(stderr, "Unable to set video mode: %s\n", SDL_GetError());
  4166.         exit(1);
  4167.     }
  4168.     
  4169.     // Set the window name
  4170.     SDL_WM_SetCaption( "Egoboo", "Egoboo" );
  4171.  
  4172.     if ( gGrabMouse )
  4173.     {
  4174.         SDL_WM_GrabInput ( SDL_GRAB_ON );
  4175.     }
  4176.  
  4177.     if ( gHideMouse )
  4178.     {
  4179.         SDL_ShowCursor(0);    // Hide the mouse cursor
  4180.     }
  4181.     
  4182.     if(SDL_NumJoysticks() > 0) {
  4183.         sdljoya = SDL_JoystickOpen(0);
  4184.         joyaon = TRUE;
  4185.     }
  4186. }
  4187.