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

  1. // char.c
  2.  
  3. // Egoboo, Copyright (C) 2000 Aaron Bishop
  4.  
  5. #include "egoboo.h"
  6.  
  7. //--------------------------------------------------------------------------------------------
  8. //--------------------------------------------------------------------------------------------
  9. //--------------------------------------------------------------------------------------------
  10. void flash_character_height(int character, unsigned char valuelow, signed short low,
  11.     unsigned char valuehigh, signed short high)
  12. {
  13.     // ZZ> This function sets a character's lighting depending on vertex height...
  14.     //     Can make feet dark and head light...
  15.     int cnt;
  16.     unsigned short frame;
  17.     signed short z;
  18.  
  19.  
  20.     frame = chrframe[character];
  21.     cnt = 0;
  22.     while(cnt < madtransvertices[chrmodel[character]])
  23.     {
  24.         z = madvrtz[frame][cnt];
  25.         if(z < low)
  26.         {
  27.             chrvrta[character][cnt] = valuelow;
  28.         }
  29.         else
  30.         {
  31.             if(z > high)
  32.             {
  33.                 chrvrta[character][cnt] = valuehigh;
  34.             }
  35.             else
  36.             {
  37.                 chrvrta[character][cnt] = (valuehigh * (z - low) / (high - low)) +
  38.                                           (valuelow * (high - z) / (high - low));
  39.             }
  40.         }
  41.         cnt++;
  42.     }
  43. }
  44.  
  45. //--------------------------------------------------------------------------------------------
  46. void flash_character(int character, unsigned char value)
  47. {
  48.     // ZZ> This function sets a character's lighting
  49.     int cnt;
  50.  
  51.     cnt = 0;
  52.     while(cnt < madtransvertices[chrmodel[character]])
  53.     {
  54.         chrvrta[character][cnt] = value;
  55.         cnt++;
  56.     }
  57. }
  58.  
  59. //--------------------------------------------------------------------------------------------
  60. void flash_select()
  61. {
  62.     // ZZ> This function makes the selected characters blink
  63.     int cnt;
  64.     unsigned char value;
  65.  
  66.     if((wldframe&31)==0 && allselect==FALSE)
  67.     {
  68.         value = ((wldframe&32)<<3) - ((wldframe&32)>>5);
  69.         cnt = 0;
  70.         while(cnt < numrtsselect)
  71.         {
  72.             flash_character(rtsselect[cnt], value);
  73.             cnt++;
  74.         }
  75.     }
  76. }
  77.  
  78. //--------------------------------------------------------------------------------------------
  79. void add_to_dolist(int cnt)
  80. {
  81.     // This function puts a character in the list
  82.     int fan;
  83.  
  84.  
  85.     if(!chrindolist[cnt])
  86.     {
  87.         fan = chronwhichfan[cnt];
  88.         if(meshinrenderlist[fan])
  89.         {
  90.             chrlightlevel[cnt] = meshvrtl[meshvrtstart[fan]];
  91.             dolist[numdolist] = cnt;
  92.             chrindolist[cnt] = TRUE;
  93.             numdolist++;
  94.  
  95.  
  96.             // Do flashing
  97.             if((allframe&chrflashand[cnt]) == 0 && chrflashand[cnt]!=DONTFLASH)
  98.             {
  99.                 flash_character(cnt, 255);
  100.             }
  101.             // Do blacking
  102.             if((allframe&SEEKURSEAND) == 0 && localseekurse && chriskursed[cnt])
  103.             {
  104.                 flash_character(cnt, 0);
  105.             }
  106.         }
  107.         else
  108.         {
  109.             // Double check for large/special objects
  110.             if(capalwaysdraw[chrmodel[cnt]])
  111.             {
  112.                 dolist[numdolist] = cnt;
  113.                 chrindolist[cnt] = TRUE;
  114.                 numdolist++;
  115.             }
  116.         }
  117.         // Add its weapons too
  118.         if(chrholdingwhich[cnt][0] != MAXCHR)
  119.             add_to_dolist(chrholdingwhich[cnt][0]);
  120.         if(chrholdingwhich[cnt][1] != MAXCHR)
  121.             add_to_dolist(chrholdingwhich[cnt][1]);
  122.     }
  123. }
  124.  
  125. //--------------------------------------------------------------------------------------------
  126. void order_dolist(void)
  127. {
  128.     // ZZ> This function orders the dolist based on distance from camera,
  129.     //     which is needed for reflections to properly clip themselves.
  130.     //     Order from closest to farthest
  131.     int cnt, tnc, character, order;
  132.     int dist[MAXCHR];
  133.     unsigned short olddolist[MAXCHR];
  134.  
  135.  
  136.     // Figure the distance of each
  137.     cnt = 0;
  138.     while(cnt < numdolist)
  139.     {
  140.         character = dolist[cnt];  olddolist[cnt] = character;
  141.         if(chrlight[character] != 255 || chralpha[character] != 255)
  142.         {
  143.             // This makes stuff inside an invisible character visible...
  144.             // A key inside a Jellcube, for example
  145.             dist[cnt] = 0x7fffffff;
  146.         }
  147.         else
  148.         {
  149.             dist[cnt] = ABS(chrxpos[character]-camx)+ABS(chrypos[character]-camy);
  150.         }
  151.         cnt++;
  152.     }
  153.  
  154.  
  155.     // Put em in the right order
  156.     cnt = 0;
  157.     while(cnt < numdolist)
  158.     {
  159.         character = olddolist[cnt];
  160.         order = 0;  // Assume this character is closest
  161.         tnc = 0;
  162.         while(tnc < numdolist)
  163.         {
  164.             // For each one closer, increment the order
  165.             order += (dist[cnt] > dist[tnc]);
  166.             order += (dist[cnt] == dist[tnc]) && (cnt < tnc);
  167.             tnc++;
  168.         }
  169.         dolist[order] = character;
  170.         cnt++;
  171.     }
  172. }
  173.  
  174. //--------------------------------------------------------------------------------------------
  175. void make_dolist(void)
  176. {
  177.     // ZZ> This function finds the characters that need to be drawn and puts them in the list
  178.     int cnt, character;
  179.  
  180.  
  181.     // Remove everyone from the dolist
  182.     cnt = 0;
  183.     while(cnt < numdolist)
  184.     {
  185.         character = dolist[cnt];
  186.         chrindolist[character] = FALSE;
  187.         cnt++;
  188.     }
  189.     numdolist = 0;
  190.  
  191.  
  192.     // Now fill it up again
  193.     cnt = 0;
  194.     while(cnt < MAXCHR)
  195.     {
  196.         if(chron[cnt]&&(!chrinpack[cnt]))
  197.         {
  198.             // Add the character
  199.             add_to_dolist(cnt);
  200.         }
  201.         cnt++;
  202.     }
  203. }
  204.  
  205. //--------------------------------------------------------------------------------------------
  206. void keep_weapons_with_holders()
  207. {
  208.     // ZZ> This function keeps weapons near their holders
  209.     int cnt, character;
  210.  
  211.  
  212.     // !!!BAD!!!  May need to do 3 levels of attachment...
  213.     cnt = 0;
  214.     while(cnt < MAXCHR)
  215.     {
  216.         if(chron[cnt])
  217.         {
  218.             character = chrattachedto[cnt];
  219.             if(character == MAXCHR)
  220.             {
  221.                 // Keep inventory with character
  222.                 if(chrinpack[cnt] == FALSE)
  223.                 {
  224.                     character = chrnextinpack[cnt];
  225.                     while(character != MAXCHR)
  226.                     {
  227.                         chrxpos[character] = chrxpos[cnt];
  228.                         chrypos[character] = chrypos[cnt];
  229.                         chrzpos[character] = chrzpos[cnt];
  230.                         // Copy olds to make SendMessageNear work
  231.                         chroldx[character] = chrxpos[cnt];
  232.                         chroldy[character] = chrypos[cnt];
  233.                         chroldz[character] = chrzpos[cnt];
  234.                         character = chrnextinpack[character];
  235.                     }
  236.                 }
  237.             }
  238.             else
  239.             {
  240.                 // Keep in hand weapons with character
  241.                 if(chrmatrixvalid[character] && chrmatrixvalid[cnt])
  242.                 {
  243.                     chrxpos[cnt] = chrmatrix[cnt]_CNV(3,0);
  244.                     chrypos[cnt] = chrmatrix[cnt]_CNV(3,1);
  245.                     chrzpos[cnt] = chrmatrix[cnt]_CNV(3,2);
  246.                 }
  247.                 else
  248.                 {
  249.                     chrxpos[cnt] = chrxpos[character];
  250.                     chrypos[cnt] = chrypos[character];
  251.                     chrzpos[cnt] = chrzpos[character];
  252.                 }
  253.                 chrturnleftright[cnt] = chrturnleftright[character];
  254.                 // Copy this stuff ONLY if it's a weapon, not for mounts
  255.                 if(chrtransferblend[character]&&chrisitem[cnt])
  256.                 {
  257.                     if(chralpha[character]!=255)
  258.                     {
  259.                         chralpha[cnt] = chralpha[character];
  260.                     }
  261.                     if(chrlight[character]!=255)
  262.                     {
  263.                         chrlight[cnt] = chrlight[character];
  264.                     }
  265.                 }
  266.             }
  267.         }
  268.         cnt++;
  269.     }
  270. }
  271.  
  272. //--------------------------------------------------------------------------------------------
  273. void make_turntosin(void)
  274. {
  275.     // ZZ> This function makes the lookup table for chrturn...
  276.     int cnt;
  277.  
  278.     cnt = 0;
  279.     while(cnt < 16384)
  280.     {
  281.         turntosin[cnt] = sin((float) (2*PI*cnt/16384.0));
  282.         cnt++;
  283.     }
  284. }
  285.  
  286. //--------------------------------------------------------------------------------------------
  287. void make_one_character_matrix(unsigned short cnt)
  288. {
  289.    // ZZ> This function sets one character's matrix
  290.    unsigned short tnc;
  291.    chrmatrixvalid[cnt] = TRUE;
  292.    if(chroverlay[cnt])
  293.    {
  294.        // Overlays are kept with their target...
  295.        tnc = chraitarget[cnt];
  296.        chrxpos[cnt] = chrxpos[tnc];
  297.        chrypos[cnt] = chrypos[tnc];
  298.        chrzpos[cnt] = chrzpos[tnc];
  299.        chrmatrix[cnt]_CNV(0,0) = chrmatrix[tnc]_CNV(0,0);
  300.        chrmatrix[cnt]_CNV(0,1) = chrmatrix[tnc]_CNV(0,1);
  301.        chrmatrix[cnt]_CNV(0,2) = chrmatrix[tnc]_CNV(0,2);
  302.        chrmatrix[cnt]_CNV(0,3) = chrmatrix[tnc]_CNV(0,3);
  303.        chrmatrix[cnt]_CNV(1,0) = chrmatrix[tnc]_CNV(1,0);
  304.        chrmatrix[cnt]_CNV(1,1) = chrmatrix[tnc]_CNV(1,1);
  305.        chrmatrix[cnt]_CNV(1,2) = chrmatrix[tnc]_CNV(1,2);
  306.        chrmatrix[cnt]_CNV(1,3) = chrmatrix[tnc]_CNV(1,3);
  307.        chrmatrix[cnt]_CNV(2,0) = chrmatrix[tnc]_CNV(2,0);
  308.        chrmatrix[cnt]_CNV(2,1) = chrmatrix[tnc]_CNV(2,1);
  309.        chrmatrix[cnt]_CNV(2,2) = chrmatrix[tnc]_CNV(2,2);
  310.        chrmatrix[cnt]_CNV(2,3) = chrmatrix[tnc]_CNV(2,3);
  311.        chrmatrix[cnt]_CNV(3,0) = chrmatrix[tnc]_CNV(3,0);
  312.        chrmatrix[cnt]_CNV(3,1) = chrmatrix[tnc]_CNV(3,1);
  313.        chrmatrix[cnt]_CNV(3,2) = chrmatrix[tnc]_CNV(3,2);
  314.        chrmatrix[cnt]_CNV(3,3) = chrmatrix[tnc]_CNV(3,3);
  315.    }
  316.    else
  317.    {
  318.        chrmatrix[cnt] = ScaleXYZRotateXYZTranslate(chrscale[cnt], chrscale[cnt], chrscale[cnt],
  319.                                     chrturnleftright[cnt]>>2,
  320.                                     ((unsigned short) (chrturnmapud[cnt]+32768))>>2,
  321.                                     ((unsigned short) (chrturnmaplr[cnt]+32768))>>2,
  322.                                     chrxpos[cnt], chrypos[cnt], chrzpos[cnt]);
  323.    }
  324. }
  325.  
  326. //--------------------------------------------------------------------------------------------
  327. void free_one_character(int character)
  328. {
  329.     // ZZ> This function sticks a character back on the free character stack
  330.     int cnt;
  331.  
  332.     freechrlist[numfreechr]=character;
  333.     numfreechr++;
  334.     // Remove from stat list
  335.     if(chrstaton[character])
  336.     {
  337.         chrstaton[character] = FALSE;
  338.         cnt = 0;
  339.         while(cnt < numstat)
  340.         {
  341.             if(statlist[cnt] == character)
  342.             {
  343.                 cnt++;
  344.                 while(cnt < numstat)
  345.                 {
  346.                     statlist[cnt-1] = statlist[cnt];
  347.                     cnt++;
  348.                 }
  349.                 numstat--;
  350.             }
  351.             cnt++;
  352.         }
  353.     }
  354.     // Make sure everyone knows it died
  355.     if(chralive[character] && capinvictus[chrmodel[character]]==FALSE)
  356.     {
  357.         teammorale[chrbaseteam[character]]--;
  358.     }
  359.     cnt = 0;
  360.     while(cnt < MAXCHR)
  361.     {
  362.         if(chron[cnt])
  363.         {
  364.             if(chraitarget[cnt] == character)
  365.             {
  366.                 chralert[cnt]|=ALERTIFTARGETKILLED;
  367.                 chraitarget[cnt] = cnt;
  368.             }
  369.             if(teamleader[chrteam[cnt]] == character)
  370.             {
  371.                 chralert[cnt]|=ALERTIFLEADERKILLED;
  372.             }
  373.         }
  374.         cnt++;
  375.     }
  376.     if(teamleader[chrteam[character]]==character)
  377.     {
  378.         teamleader[chrteam[character]] = NOLEADER;
  379.     }
  380.     chron[character]=FALSE;
  381.     chralive[character]=FALSE;
  382.     chrinpack[character]=FALSE;
  383. }
  384.  
  385. //--------------------------------------------------------------------------------------------
  386. void free_inventory(int character)
  387. {
  388.     // ZZ> This function frees every item in the character's inventory
  389.     int cnt, next;
  390.  
  391.     cnt = chrnextinpack[character];
  392.     while(cnt < MAXCHR)
  393.     {
  394.         next = chrnextinpack[cnt];
  395.         free_one_character(cnt);
  396.         cnt = next;
  397.     }
  398. }
  399.  
  400. //--------------------------------------------------------------------------------------------
  401. void attach_particle_to_character(int particle, int character, int grip)
  402. {
  403.     // ZZ> This function sets one particle's position to be attached to a character.
  404.     //     It will kill the particle if the character is no longer around
  405.     unsigned short vertex, model, frame, lastframe;
  406.     unsigned char lip;
  407.     float pointx;
  408.     float pointy;
  409.     float pointz;
  410.     int temp;
  411.  
  412.  
  413.     // Check validity of attachment
  414.     if(chron[character]==FALSE || chrinpack[character])
  415.     {
  416.         prttime[particle] = 1;
  417.         return;
  418.     }
  419.  
  420.  
  421.     // Do we have a matrix???
  422.     if(chrmatrixvalid[character])//meshinrenderlist[chronwhichfan[character]])
  423.     {
  424.         // Transform the weapon grip from model to world space
  425.         model = chrmodel[character];
  426.         frame = chrframe[character];
  427.         lastframe = chrlastframe[character];
  428.         lip = chrlip[character]>>6;
  429.         if(grip == SPAWNORIGIN)
  430.         {
  431.             prtxpos[particle] = chrmatrix[character]_CNV(3,0);
  432.             prtypos[particle] = chrmatrix[character]_CNV(3,1);
  433.             prtzpos[particle] = chrmatrix[character]_CNV(3,2);
  434.             return;
  435.         }
  436.         vertex = madvertices[model] - grip;
  437.  
  438.  
  439.         // Calculate grip point locations with linear interpolation and other silly things
  440.         switch(lip)
  441.         {
  442.             case 0:  // 25% this frame
  443.                 temp = madvrtx[lastframe][vertex];
  444.                 temp = temp+temp+temp+madvrtx[frame][vertex]>>2;
  445.                 pointx = temp;///chrscale[cnt];
  446.                 temp = madvrty[lastframe][vertex];
  447.                 temp = temp+temp+temp+madvrty[frame][vertex]>>2;
  448.                 pointy = temp;///chrscale[cnt];
  449.                 temp = madvrtz[lastframe][vertex];
  450.                 temp = temp+temp+temp+madvrtz[frame][vertex]>>2;
  451.                 pointz = temp;///chrscale[cnt];
  452.                 break;
  453.             case 1:  // 50% this frame
  454.                 pointx = (madvrtx[frame][vertex]+madvrtx[lastframe][vertex]>>1);///chrscale[cnt];
  455.                 pointy = (madvrty[frame][vertex]+madvrty[lastframe][vertex]>>1);///chrscale[cnt];
  456.                 pointz = (madvrtz[frame][vertex]+madvrtz[lastframe][vertex]>>1);///chrscale[cnt];
  457.                 break;
  458.             case 2:  // 75% this frame
  459.                 temp = madvrtx[frame][vertex];
  460.                 temp = temp+temp+temp+madvrtx[lastframe][vertex]>>2;
  461.                 pointx = temp;///chrscale[cnt];
  462.                 temp = madvrty[frame][vertex];
  463.                 temp = temp+temp+temp+madvrty[lastframe][vertex]>>2;
  464.                 pointy = temp;///chrscale[cnt];
  465.                 temp = madvrtz[frame][vertex];
  466.                 temp = temp+temp+temp+madvrtz[lastframe][vertex]>>2;
  467.                 pointz = temp;///chrscale[cnt];
  468.                 break;
  469.             case 3:  // 100% this frame...  This is the legible one
  470.                 pointx = madvrtx[frame][vertex];///chrscale[cnt];
  471.                 pointy = madvrty[frame][vertex];///chrscale[cnt];
  472.                 pointz = madvrtz[frame][vertex];///chrscale[cnt];
  473.                 break;
  474.         }
  475.  
  476.  
  477.  
  478.  
  479.  
  480.         // Do the transform
  481.         prtxpos[particle] = (pointx*chrmatrix[character]_CNV(0,0) +
  482.                              pointy*chrmatrix[character]_CNV(1,0) +
  483.                              pointz*chrmatrix[character]_CNV(2,0));
  484.         prtypos[particle] = (pointx*chrmatrix[character]_CNV(0,1) +
  485.                              pointy*chrmatrix[character]_CNV(1,1) +
  486.                              pointz*chrmatrix[character]_CNV(2,1));
  487.         prtzpos[particle] = (pointx*chrmatrix[character]_CNV(0,2) +
  488.                              pointy*chrmatrix[character]_CNV(1,2) +
  489.                              pointz*chrmatrix[character]_CNV(2,2));
  490.         prtxpos[particle] += chrmatrix[character]_CNV(3,0);
  491.         prtypos[particle] += chrmatrix[character]_CNV(3,1);
  492.         prtzpos[particle] += chrmatrix[character]_CNV(3,2);
  493.     }
  494.     else
  495.     {
  496.         // No matrix, so just wing it...
  497.         prtxpos[particle] = chrxpos[character];
  498.         prtypos[particle] = chrypos[character];
  499.         prtzpos[particle] = chrzpos[character];
  500.     }
  501. }
  502.  
  503. //--------------------------------------------------------------------------------------------
  504. void make_one_weapon_matrix(unsigned short cnt)
  505. {
  506.     // ZZ> This function sets one weapon's matrix, based on who it's attached to
  507.     #define POINTS 4
  508.     int tnc;
  509.     unsigned short character, vertex, model, frame, lastframe;
  510.     unsigned char lip;
  511.     float pointx[POINTS];
  512.     float pointy[POINTS];
  513.     float pointz[POINTS];
  514.     float nupointx[POINTS];
  515.     float nupointy[POINTS];
  516.     float nupointz[POINTS];
  517.     int temp;
  518.  
  519.  
  520.     // Transform the weapon grip from model to world space
  521.     character = chrattachedto[cnt];
  522.     model = chrmodel[character];
  523.     frame = chrframe[character];
  524.     lastframe = chrlastframe[character];
  525.     lip = chrlip[character]>>6;
  526.     chrmatrixvalid[cnt] = TRUE;
  527.  
  528.  
  529.     // Calculate grip point locations with linear interpolation and other silly things
  530.     switch(lip)
  531.     {
  532.         case 0:  // 25% this frame
  533.             vertex = chrweapongrip[cnt][0];
  534.             temp = madvrtx[lastframe][vertex];
  535.             temp = temp+temp+temp+madvrtx[frame][vertex]>>2;
  536.             pointx[0] = temp;
  537.             temp = madvrty[lastframe][vertex];
  538.             temp = temp+temp+temp+madvrty[frame][vertex]>>2;
  539.             pointy[0] = temp;
  540.             temp = madvrtz[lastframe][vertex];
  541.             temp = temp+temp+temp+madvrtz[frame][vertex]>>2;
  542.             pointz[0] = temp;
  543.  
  544.             vertex = chrweapongrip[cnt][1];
  545.             temp = madvrtx[lastframe][vertex];
  546.             temp = temp+temp+temp+madvrtx[frame][vertex]>>2;
  547.             pointx[1] = temp;
  548.             temp = madvrty[lastframe][vertex];
  549.             temp = temp+temp+temp+madvrty[frame][vertex]>>2;
  550.             pointy[1] = temp;
  551.             temp = madvrtz[lastframe][vertex];
  552.             temp = temp+temp+temp+madvrtz[frame][vertex]>>2;
  553.             pointz[1] = temp;
  554.  
  555.             vertex = chrweapongrip[cnt][2];
  556.             temp = madvrtx[lastframe][vertex];
  557.             temp = temp+temp+temp+madvrtx[frame][vertex]>>2;
  558.             pointx[2] = temp;
  559.             temp = madvrty[lastframe][vertex];
  560.             temp = temp+temp+temp+madvrty[frame][vertex]>>2;
  561.             pointy[2] = temp;
  562.             temp = madvrtz[lastframe][vertex];
  563.             temp = temp+temp+temp+madvrtz[frame][vertex]>>2;
  564.             pointz[2] = temp;
  565.  
  566.             vertex = chrweapongrip[cnt][3];
  567.             temp = madvrtx[lastframe][vertex];
  568.             temp = temp+temp+temp+madvrtx[frame][vertex]>>2;
  569.             pointx[3] = temp;
  570.             temp = madvrty[lastframe][vertex];
  571.             temp = temp+temp+temp+madvrty[frame][vertex]>>2;
  572.             pointy[3] = temp;
  573.             temp = madvrtz[lastframe][vertex];
  574.             temp = temp+temp+temp+madvrtz[frame][vertex]>>2;
  575.             pointz[3] = temp;
  576.             break;
  577.         case 1:  // 50% this frame
  578.             vertex = chrweapongrip[cnt][0];
  579.             pointx[0] = (madvrtx[frame][vertex]+madvrtx[lastframe][vertex]>>1);
  580.             pointy[0] = (madvrty[frame][vertex]+madvrty[lastframe][vertex]>>1);
  581.             pointz[0] = (madvrtz[frame][vertex]+madvrtz[lastframe][vertex]>>1);
  582.             vertex = chrweapongrip[cnt][1];
  583.             pointx[1] = (madvrtx[frame][vertex]+madvrtx[lastframe][vertex]>>1);
  584.             pointy[1] = (madvrty[frame][vertex]+madvrty[lastframe][vertex]>>1);
  585.             pointz[1] = (madvrtz[frame][vertex]+madvrtz[lastframe][vertex]>>1);
  586.             vertex = chrweapongrip[cnt][2];
  587.             pointx[2] = (madvrtx[frame][vertex]+madvrtx[lastframe][vertex]>>1);
  588.             pointy[2] = (madvrty[frame][vertex]+madvrty[lastframe][vertex]>>1);
  589.             pointz[2] = (madvrtz[frame][vertex]+madvrtz[lastframe][vertex]>>1);
  590.             vertex = chrweapongrip[cnt][3];
  591.             pointx[3] = (madvrtx[frame][vertex]+madvrtx[lastframe][vertex]>>1);
  592.             pointy[3] = (madvrty[frame][vertex]+madvrty[lastframe][vertex]>>1);
  593.             pointz[3] = (madvrtz[frame][vertex]+madvrtz[lastframe][vertex]>>1);
  594.             break;
  595.         case 2:  // 75% this frame
  596.             vertex = chrweapongrip[cnt][0];
  597.             temp = madvrtx[frame][vertex];
  598.             temp = temp+temp+temp+madvrtx[lastframe][vertex]>>2;
  599.             pointx[0] = temp;
  600.             temp = madvrty[frame][vertex];
  601.             temp = temp+temp+temp+madvrty[lastframe][vertex]>>2;
  602.             pointy[0] = temp;
  603.             temp = madvrtz[frame][vertex];
  604.             temp = temp+temp+temp+madvrtz[lastframe][vertex]>>2;
  605.             pointz[0] = temp;
  606.  
  607.  
  608.             vertex = chrweapongrip[cnt][1];
  609.             temp = madvrtx[frame][vertex];
  610.             temp = temp+temp+temp+madvrtx[lastframe][vertex]>>2;
  611.             pointx[1] = temp;
  612.             temp = madvrty[frame][vertex];
  613.             temp = temp+temp+temp+madvrty[lastframe][vertex]>>2;
  614.             pointy[1] = temp;
  615.             temp = madvrtz[frame][vertex];
  616.             temp = temp+temp+temp+madvrtz[lastframe][vertex]>>2;
  617.             pointz[1] = temp;
  618.  
  619.  
  620.             vertex = chrweapongrip[cnt][2];
  621.             temp = madvrtx[frame][vertex];
  622.             temp = temp+temp+temp+madvrtx[lastframe][vertex]>>2;
  623.             pointx[2] = temp;
  624.             temp = madvrty[frame][vertex];
  625.             temp = temp+temp+temp+madvrty[lastframe][vertex]>>2;
  626.             pointy[2] = temp;
  627.             temp = madvrtz[frame][vertex];
  628.             temp = temp+temp+temp+madvrtz[lastframe][vertex]>>2;
  629.             pointz[2] = temp;
  630.  
  631.  
  632.             vertex = chrweapongrip[cnt][3];
  633.             temp = madvrtx[frame][vertex];
  634.             temp = temp+temp+temp+madvrtx[lastframe][vertex]>>2;
  635.             pointx[3] = temp;
  636.             temp = madvrty[frame][vertex];
  637.             temp = temp+temp+temp+madvrty[lastframe][vertex]>>2;
  638.             pointy[3] = temp;
  639.             temp = madvrtz[frame][vertex];
  640.             temp = temp+temp+temp+madvrtz[lastframe][vertex]>>2;
  641.             pointz[3] = temp;
  642.  
  643.             break;
  644.         case 3:  // 100% this frame...  This is the legible one
  645.             vertex = chrweapongrip[cnt][0];
  646.             pointx[0] = madvrtx[frame][vertex];
  647.             pointy[0] = madvrty[frame][vertex];
  648.             pointz[0] = madvrtz[frame][vertex];
  649.             vertex = chrweapongrip[cnt][1];
  650.             pointx[1] = madvrtx[frame][vertex];
  651.             pointy[1] = madvrty[frame][vertex];
  652.             pointz[1] = madvrtz[frame][vertex];
  653.             vertex = chrweapongrip[cnt][2];
  654.             pointx[2] = madvrtx[frame][vertex];
  655.             pointy[2] = madvrty[frame][vertex];
  656.             pointz[2] = madvrtz[frame][vertex];
  657.             vertex = chrweapongrip[cnt][3];
  658.             pointx[3] = madvrtx[frame][vertex];
  659.             pointy[3] = madvrty[frame][vertex];
  660.             pointz[3] = madvrtz[frame][vertex];
  661.             break;
  662.     }
  663.  
  664.  
  665.  
  666.  
  667.  
  668.     tnc = 0;
  669.     while(tnc < POINTS)
  670.     {
  671.         // Do the transform
  672.         nupointx[tnc] = (pointx[tnc]*chrmatrix[character]_CNV(0,0) +
  673.                        pointy[tnc]*chrmatrix[character]_CNV(1,0) +
  674.                        pointz[tnc]*chrmatrix[character]_CNV(2,0));
  675.         nupointy[tnc] = (pointx[tnc]*chrmatrix[character]_CNV(0,1) +
  676.                        pointy[tnc]*chrmatrix[character]_CNV(1,1) +
  677.                        pointz[tnc]*chrmatrix[character]_CNV(2,1));
  678.         nupointz[tnc] = (pointx[tnc]*chrmatrix[character]_CNV(0,2) +
  679.                        pointy[tnc]*chrmatrix[character]_CNV(1,2) +
  680.                        pointz[tnc]*chrmatrix[character]_CNV(2,2));
  681.  
  682.         nupointx[tnc] += chrmatrix[character]_CNV(3,0);
  683.         nupointy[tnc] += chrmatrix[character]_CNV(3,1);
  684.         nupointz[tnc] += chrmatrix[character]_CNV(3,2);
  685.  
  686.         tnc++;
  687.     }
  688.  
  689.  
  690.  
  691.  
  692.     // Calculate weapon's matrix based on positions of grip points
  693.     // chrscale is recomputed at time of attachment
  694.     chrmatrix[cnt] = FourPoints(nupointx[0], nupointy[0], nupointz[0],
  695.                                 nupointx[1], nupointy[1], nupointz[1],
  696.                                 nupointx[2], nupointy[2], nupointz[2],
  697.                                 nupointx[3], nupointy[3], nupointz[3],
  698.                                 chrscale[cnt]);
  699. }
  700.  
  701. //--------------------------------------------------------------------------------------------
  702. void make_character_matrices()
  703. {
  704.     // ZZ> This function makes all of the character's matrices
  705.     int cnt, tnc;
  706.  
  707.     // Forget about old matrices
  708.     cnt = 0;
  709.     while(cnt < MAXCHR)
  710.     {
  711.         chrmatrixvalid[cnt] = FALSE;
  712.         cnt++;
  713.     }
  714.  
  715.  
  716.     // Do base characters
  717.     tnc = 0;
  718.     while(tnc < MAXCHR)
  719.     {
  720.         if(chrattachedto[tnc] == MAXCHR && chron[tnc])  // Skip weapons for now
  721.         {
  722.             make_one_character_matrix(tnc);
  723.         }
  724.         tnc++;
  725.     }
  726.  
  727.  
  728.  
  729.     // Do first level of attachments
  730.     tnc = 0;
  731.     while(tnc < MAXCHR)
  732.     {
  733.         if(chrattachedto[tnc] != MAXCHR && chron[tnc])
  734.         {
  735.             if(chrattachedto[chrattachedto[tnc]] == MAXCHR)
  736.             {
  737.                 make_one_weapon_matrix(tnc);
  738.             }
  739.         }
  740.         tnc++;
  741.     }
  742.  
  743.  
  744.     // Do second level of attachments
  745.     tnc = 0;
  746.     while(tnc < MAXCHR)
  747.     {
  748.         if(chrattachedto[tnc] != MAXCHR && chron[tnc])
  749.         {
  750.             if(chrattachedto[chrattachedto[tnc]] != MAXCHR)
  751.             {
  752.                 make_one_weapon_matrix(tnc);
  753.             }
  754.         }
  755.         tnc++;
  756.     }
  757. }
  758.  
  759. //--------------------------------------------------------------------------------------------
  760. int get_free_character()
  761. {
  762.     // ZZ> This function gets an unused character and returns its index
  763.     int character;
  764.  
  765.  
  766.     if(numfreechr==0)
  767.     {
  768.         // Return MAXCHR if we can't find one
  769.         return MAXCHR;
  770.     }
  771.     else
  772.     {
  773.         // Just grab the next one
  774.         numfreechr--;
  775.         character=freechrlist[numfreechr];
  776.     }
  777.     return character;
  778. }
  779.  
  780. //--------------------------------------------------------------------------------------------
  781. unsigned char find_target_in_block(int x, int y, float chrx, float chry, unsigned short facing, 
  782.   unsigned char onlyfriends, unsigned char anyone, unsigned char team,
  783.   unsigned short donttarget, unsigned short oldtarget)
  784. {
  785.     // ZZ> This function helps find a target, returning TRUE if it found a decent target
  786.     int cnt;
  787.     unsigned short angle;
  788.     unsigned short charb;
  789.     unsigned char enemies, returncode;
  790.     unsigned int fanblock;
  791.     int distance;
  792.  
  793.  
  794.  
  795.     returncode = FALSE;
  796.  
  797.  
  798.     // Current fanblock
  799.     if(x >= 0 && x < (meshsizex>>2) && y >= 0 && y < (meshsizey>>2))
  800.     {
  801.         fanblock = x+meshblockstart[y];
  802.  
  803.  
  804.         enemies = FALSE;
  805.         if(onlyfriends==FALSE) enemies = TRUE;
  806.  
  807.  
  808.         charb = meshbumplistchr[fanblock];
  809.         cnt = 0;
  810.         while(cnt < meshbumplistchrnum[fanblock])
  811.         {
  812.             if(chralive[charb] && chrinvictus[charb]==FALSE && charb != donttarget && charb != oldtarget)
  813.             {
  814.                 if(anyone || (chrteam[charb]==team && onlyfriends) || (teamhatesteam[team][chrteam[charb]] && enemies))
  815.                 {
  816.                     distance = ABS(chrxpos[charb]-chrx) + ABS(chrypos[charb]-chry);
  817.                     if(distance < globestdistance)
  818.                     {
  819.                         angle = (atan2(chrypos[charb]-chry, chrxpos[charb]-chrx)+PI)*65535/(2*PI);
  820.                         angle = facing-angle;
  821.                         if(angle < globestangle || angle > (65535-globestangle))
  822.                         {
  823.                             returncode = TRUE;
  824.                             globesttarget = charb;
  825.                             globestdistance = distance;
  826.                             glouseangle = angle;
  827.                             if(angle  > 32767)
  828.                                 globestangle = -angle;
  829.                             else
  830.                                 globestangle = angle;
  831.                         }
  832.                     }
  833.                 }
  834.             }
  835.             charb = chrbumpnext[charb];
  836.             cnt++;
  837.         }
  838.     }
  839.     return returncode;
  840. }
  841.  
  842. //--------------------------------------------------------------------------------------------
  843. unsigned short find_target(float chrx, float chry, unsigned short facing, 
  844.   unsigned short targetangle, unsigned char onlyfriends, unsigned char anyone,
  845.   unsigned char team, unsigned short donttarget, unsigned short oldtarget)
  846. {
  847.     // This function finds the best target for the given parameters
  848.     unsigned char done;
  849.     int x, y;
  850.  
  851.     x = chrx;
  852.     y = chry;
  853.     x = x>>9;
  854.     y = y>>9;
  855.     globestdistance = 9999;
  856.     globestangle = targetangle;
  857.     done = find_target_in_block(x, y, chrx, chry, facing, onlyfriends, anyone, team, donttarget, oldtarget);
  858.     done |= find_target_in_block(x+1, y, chrx, chry, facing, onlyfriends, anyone, team, donttarget, oldtarget);
  859.     done |= find_target_in_block(x-1, y, chrx, chry, facing, onlyfriends, anyone, team, donttarget, oldtarget);
  860.     done |= find_target_in_block(x, y+1, chrx, chry, facing, onlyfriends, anyone, team, donttarget, oldtarget);
  861.     done |= find_target_in_block(x, y-1, chrx, chry, facing, onlyfriends, anyone, team, donttarget, oldtarget);
  862.     if(done) return globesttarget;
  863.  
  864.  
  865.     done = find_target_in_block(x+1, y+1, chrx, chry, facing, onlyfriends, anyone, team, donttarget, oldtarget);
  866.     done |= find_target_in_block(x+1, y-1, chrx, chry, facing, onlyfriends, anyone, team, donttarget, oldtarget);
  867.     done |= find_target_in_block(x-1, y+1, chrx, chry, facing, onlyfriends, anyone, team, donttarget, oldtarget);
  868.     done |= find_target_in_block(x-1, y-1, chrx, chry, facing, onlyfriends, anyone, team, donttarget, oldtarget);
  869.     if(done) return globesttarget;
  870.  
  871.  
  872.     return MAXCHR;
  873. }
  874.  
  875. //--------------------------------------------------------------------------------------------
  876. void free_all_characters()
  877. {
  878.     // ZZ> This function resets the character allocation list
  879.     nolocalplayers = TRUE;
  880.     numfreechr = 0;
  881.     while(numfreechr<MAXCHR)
  882.     {
  883.         chron[numfreechr] = FALSE;
  884.         chralive[numfreechr] = FALSE;
  885.         chrinpack[numfreechr] = FALSE;
  886.         chrnuminpack[numfreechr] = 0;
  887.         chrnextinpack[numfreechr] = MAXCHR;
  888.         chrstaton[numfreechr] = FALSE;
  889.         chrmatrixvalid[numfreechr] = FALSE;
  890.         freechrlist[numfreechr] = numfreechr;
  891.         numfreechr++;
  892.     }
  893.     numpla = 0;
  894.     numlocalpla = 0;
  895.     numstat = 0;
  896. }
  897.  
  898. //--------------------------------------------------------------------------------------------
  899. unsigned char __chrhitawall(int character)
  900. {
  901.     // ZZ> This function returns nonzero if the character hit a wall that the
  902.     //     character is not allowed to cross
  903.     unsigned char passtl, passtr, passbr, passbl;
  904.     int x, y, bs;
  905.  
  906.  
  907.     y = chrypos[character];  x = chrxpos[character];  bs = chrbumpsize[character]>>1;
  908.     // !!!BAD!!! Should really do bound checking...
  909.     passtl = meshfx[meshfanstart[y-bs>>7]+(x-bs>>7)];
  910.     passtr = meshfx[meshfanstart[y-bs>>7]+(x+bs>>7)];
  911.     passbr = meshfx[meshfanstart[y+bs>>7]+(x+bs>>7)];
  912.     passbl = meshfx[meshfanstart[y+bs>>7]+(x-bs>>7)];
  913.     passtl = (passtl|passtr|passbr|passbl)&chrstoppedby[character];
  914.     return passtl;
  915. }
  916.  
  917. //--------------------------------------------------------------------------------------------
  918. void reset_character_accel(unsigned short character)
  919. {
  920.     // ZZ> This function fixes a character's max acceleration
  921.     unsigned short enchant;
  922.  
  923.     if(character != MAXCHR)
  924.     {
  925.         if(chron[character])
  926.         {
  927.             // Okay, remove all acceleration enchants
  928.             enchant = chrfirstenchant[character];
  929.             while(enchant < MAXENCHANT)
  930.             {
  931.                 remove_enchant_value(enchant, ADDACCEL);
  932.                 enchant = encnextenchant[enchant];
  933.             }
  934.             // Set the starting value
  935.             chrmaxaccel[character] = capmaxaccel[chrmodel[character]][chrtexture[character]-madskinstart[chrmodel[character]]];
  936.             // Put the acceleration enchants back on
  937.             enchant = chrfirstenchant[character];
  938.             while(enchant < MAXENCHANT)
  939.             {
  940.                 add_enchant_value(enchant, ADDACCEL, enceve[enchant]);
  941.                 enchant = encnextenchant[enchant];
  942.             }
  943.         }
  944.     }
  945. }
  946.  
  947. //--------------------------------------------------------------------------------------------
  948. void detach_character_from_mount(unsigned short character, unsigned char ignorekurse,
  949.   unsigned char doshop)
  950. {
  951.     // ZZ> This function drops an item
  952.     unsigned short mount, hand, enchant, cnt, passage, owner, price;
  953.     unsigned char inshop;
  954.     int loc;
  955.  
  956.  
  957.     // Make sure the character is valid
  958.     if(character==MAXCHR)
  959.         return;
  960.  
  961.  
  962.     // Make sure the character is mounted
  963.     mount = chrattachedto[character];
  964.     if(mount>=MAXCHR)
  965.         return;
  966.  
  967.  
  968.     // Make sure both are still around
  969.     if(!chron[character] || !chron[mount])
  970.         return;
  971.  
  972.  
  973.     // Don't allow living characters to drop kursed weapons
  974.     if(ignorekurse==FALSE && chriskursed[character] && chralive[mount] && chrisitem[character])
  975.     {
  976.         chralert[character] = chralert[character]|ALERTIFNOTDROPPED;
  977.         return;
  978.     }
  979.  
  980.  
  981.     // Figure out which hand it's in
  982.     hand = 0;
  983.     if(chrinwhichhand[character] == GRIPRIGHT)
  984.     {
  985.         hand = 1;
  986.     }
  987.  
  988.  
  989.     // Rip 'em apart
  990.     chrattachedto[character] = MAXCHR;
  991.     if(chrholdingwhich[mount][0] == character)
  992.         chrholdingwhich[mount][0] = MAXCHR;
  993.     if(chrholdingwhich[mount][1] == character)
  994.         chrholdingwhich[mount][1] = MAXCHR;
  995.     chrscale[character] = chrfat[character]*madscale[chrmodel[character]]*4;
  996.  
  997.  
  998.     // Run the falling animation...
  999.     play_action(character, ACTIONJB+hand, FALSE);
  1000.  
  1001.  
  1002.  
  1003.     // Set the positions
  1004.     if(chrmatrixvalid[character])
  1005.     {
  1006.       chrxpos[character] = chrmatrix[character]_CNV(3,0);
  1007.       chrypos[character] = chrmatrix[character]_CNV(3,1);
  1008.       chrzpos[character] = chrmatrix[character]_CNV(3,2);
  1009.     }
  1010.     else
  1011.     {
  1012.       chrxpos[character] = chrxpos[mount];
  1013.       chrypos[character] = chrypos[mount];
  1014.       chrzpos[character] = chrzpos[mount];
  1015.     }
  1016.  
  1017.  
  1018.  
  1019.     // Make sure it's not dropped in a wall...
  1020.     if(__chrhitawall(character))
  1021.     {
  1022.         chrxpos[character] = chrxpos[mount];
  1023.         chrypos[character] = chrypos[mount];
  1024.     }
  1025.  
  1026.  
  1027.     // Check for shop passages
  1028.     inshop = FALSE;
  1029.     if(chrisitem[character] && numshoppassage != 0 && doshop)
  1030.     {
  1031.         cnt = 0;
  1032.         while(cnt < numshoppassage)
  1033.         {
  1034.             passage = shoppassage[cnt];
  1035.             loc = chrxpos[character];
  1036.             loc = loc >> 7;
  1037.             if(loc >= passtlx[passage] && loc <= passbrx[passage])
  1038.             {
  1039.                 loc = chrypos[character];
  1040.                 loc = loc >> 7;
  1041.                 if(loc >= passtly[passage] && loc <= passbry[passage])
  1042.                 {
  1043.                     inshop = TRUE;
  1044.                     owner = shopowner[passage];
  1045.                     cnt = numshoppassage;  // Finish loop
  1046.                     if(owner == NOOWNER)
  1047.                     {
  1048.                         // The owner has died!!!
  1049.                         inshop = FALSE;
  1050.                     }
  1051.                 }
  1052.             }
  1053.             cnt++;
  1054.         }
  1055.         if(inshop)
  1056.         {
  1057.             // Give the mount its money back, alert the shop owner
  1058.             price = capskincost[chrmodel[character]][0];
  1059.             if(capisstackable[chrmodel[character]])
  1060.             {
  1061.                 price = price * chrammo[character];
  1062.             }
  1063.             chrmoney[mount] += price;
  1064.             chrmoney[owner] -= price;
  1065.             if(chrmoney[owner] < 0)  chrmoney[owner] = 0;
  1066.             if(chrmoney[mount] > MAXMONEY)  chrmoney[mount] = MAXMONEY;
  1067.             chralert[owner] |= ALERTIFORDERED;
  1068.             chrorder[owner] = price;  // Tell owner how much...
  1069.             chrcounter[owner] = 0;  // 0 for buying an item
  1070.         }
  1071.     }
  1072.  
  1073.  
  1074.  
  1075.     // Make sure it works right
  1076.     chrhitready[character]=TRUE;
  1077.     if(inshop)
  1078.     {
  1079.       // Drop straight down to avoid theft
  1080.       chrxvel[character]=0;
  1081.       chryvel[character]=0;
  1082.     }
  1083.     else
  1084.     {
  1085.       chrxvel[character]=chrxvel[mount];
  1086.       chryvel[character]=chryvel[mount];
  1087.     }
  1088.     chrzvel[character]=DROPZVEL;
  1089.  
  1090.  
  1091.     // Turn looping off
  1092.     chrloopaction[character]=FALSE;
  1093.  
  1094.  
  1095.     // Reset the team if it is a mount
  1096.     if(chrismount[mount])
  1097.     {
  1098.         chrteam[mount] = chrbaseteam[mount];
  1099.         chralert[mount] |= ALERTIFDROPPED;
  1100.     }
  1101.     chrteam[character] = chrbaseteam[character];
  1102.     chralert[character] |= ALERTIFDROPPED;
  1103.  
  1104.  
  1105.     // Reset transparency
  1106.     if(chrisitem[character] && chrtransferblend[mount])
  1107.     {
  1108.         // Okay, reset transparency
  1109.         enchant = chrfirstenchant[character];
  1110.         while(enchant < MAXENCHANT)
  1111.         {
  1112.             unset_enchant_value(enchant, SETALPHABLEND);
  1113.             unset_enchant_value(enchant, SETLIGHTBLEND);
  1114.             enchant = encnextenchant[enchant];
  1115.         }
  1116.         chralpha[character] = capalpha[chrmodel[character]];
  1117.         chrlight[character] = caplight[chrmodel[character]];
  1118.         enchant = chrfirstenchant[character];
  1119.         while(enchant < MAXENCHANT)
  1120.         {
  1121.             set_enchant_value(enchant, SETALPHABLEND, enceve[enchant]);
  1122.             set_enchant_value(enchant, SETLIGHTBLEND, enceve[enchant]);
  1123.             enchant = encnextenchant[enchant];
  1124.         }
  1125.     }
  1126.  
  1127.  
  1128.     // Set twist
  1129.     chrturnmaplr[character] = 32768;
  1130.     chrturnmapud[character] = 32768;
  1131. }
  1132.  
  1133. //--------------------------------------------------------------------------------------------
  1134. void attach_character_to_mount(unsigned short character, unsigned short mount,
  1135.     unsigned short grip)
  1136. {
  1137.     // ZZ> This function attaches one character to another ( the mount )
  1138.     //     at either the left or right grip
  1139.     int tnc, hand;
  1140.  
  1141.  
  1142.     // Make sure both are still around
  1143.     if(!chron[character] || !chron[mount] || chrinpack[character] || chrinpack[mount])
  1144.         return;
  1145.  
  1146.     // Figure out which hand this grip relates to
  1147.     hand = 1;
  1148.     if(grip == GRIPLEFT)
  1149.         hand = 0;
  1150.  
  1151.  
  1152.     // Make sure the the hand is valid
  1153.     if(capgripvalid[chrmodel[mount]][hand]==FALSE)
  1154.         return;
  1155.  
  1156.  
  1157.     // Put 'em together
  1158.     chrinwhichhand[character] = grip;
  1159.     chrattachedto[character] = mount;
  1160.     chrholdingwhich[mount][hand] = character;
  1161.     tnc = madvertices[chrmodel[mount]] - grip;
  1162.     chrweapongrip[character][0] = tnc;
  1163.     chrweapongrip[character][1] = tnc+1;
  1164.     chrweapongrip[character][2] = tnc+2;
  1165.     chrweapongrip[character][3] = tnc+3;
  1166.     chrscale[character] = chrfat[character]/(chrfat[mount]*1280);
  1167.     chrinwater[character] = FALSE;
  1168.     chrjumptime[character]=JUMPDELAY*4;
  1169.  
  1170.  
  1171.     // Run the held animation
  1172.     if(chrismount[mount] && grip == GRIPONLY)
  1173.     {
  1174.         // Riding mount
  1175.         play_action(character, ACTIONMI, TRUE);
  1176.         chrloopaction[character]=TRUE;
  1177.     }
  1178.     else
  1179.     {
  1180.         play_action(character, ACTIONMM+hand, FALSE);
  1181.         if(chrisitem[character])
  1182.         {
  1183.             // Item grab
  1184.             chrkeepaction[character]=TRUE;
  1185.         }
  1186.     }
  1187.  
  1188.  
  1189.  
  1190.  
  1191.     // Set the team
  1192.     if(chrisitem[character])
  1193.     {
  1194.         chrteam[character]=chrteam[mount];
  1195.         // Set the alert
  1196.         chralert[character] = chralert[character]|ALERTIFGRABBED;
  1197.     }
  1198.     if(chrismount[mount])
  1199.     {
  1200.         chrteam[mount]=chrteam[character];
  1201.         // Set the alert
  1202.         if(chrisitem[mount]==FALSE)
  1203.         {
  1204.             chralert[mount] = chralert[mount]|ALERTIFGRABBED;
  1205.         }
  1206.     }
  1207.  
  1208.  
  1209.     // It's not gonna hit the floor
  1210.     chrhitready[character]=FALSE;
  1211. }
  1212.  
  1213. //--------------------------------------------------------------------------------------------
  1214. unsigned short stack_in_pack(unsigned short item, unsigned short character)
  1215. {
  1216.     // ZZ> This function looks in the character's pack for an item similar
  1217.     //     to the one given.  If it finds one, it returns the similar item's
  1218.     //     index number, otherwise it returns MAXCHR.
  1219.     unsigned short inpack, id;
  1220.     unsigned char allok;
  1221.  
  1222.  
  1223.     if(capisstackable[chrmodel[item]]==TRUE)
  1224.     {
  1225.         inpack = chrnextinpack[character];
  1226.         allok = FALSE;
  1227.         while(inpack != MAXCHR && allok == FALSE)
  1228.         {
  1229.             allok = TRUE;
  1230.             if(chrmodel[inpack]!=chrmodel[item])
  1231.             {
  1232.                 if(capisstackable[chrmodel[inpack]]==FALSE)
  1233.                 {
  1234.                     allok = FALSE;
  1235.                 }
  1236.  
  1237.                 if(chrammomax[inpack]!=chrammomax[item])
  1238.                 {
  1239.                     allok = FALSE;
  1240.                 }
  1241.  
  1242.                 id = 0;
  1243.                 while(id < MAXIDSZ && allok == TRUE)
  1244.                 {
  1245.                     if(capidsz[chrmodel[inpack]][id]!=capidsz[chrmodel[item]][id])
  1246.                     {
  1247.                         allok = FALSE;
  1248.                     }
  1249.                     id++;
  1250.                 }
  1251.             }
  1252.             if(allok == FALSE)
  1253.             {
  1254.                 inpack = chrnextinpack[inpack];
  1255.             }
  1256.         }
  1257.         if(allok == TRUE)
  1258.         {
  1259.             return inpack;
  1260.         }
  1261.     }
  1262.     return MAXCHR;
  1263. }
  1264.  
  1265. //--------------------------------------------------------------------------------------------
  1266. void add_item_to_character_pack(unsigned short item, unsigned short character)
  1267. {
  1268.     // ZZ> This function puts one character inside the other's pack
  1269.     unsigned short oldfirstitem, newammo, stack;
  1270.  
  1271.  
  1272.     // Make sure everything is hunkydori
  1273.     if((!chron[item]) || (!chron[character]) || chrinpack[item] || chrinpack[character] ||
  1274.        chrisitem[character])
  1275.         return;
  1276.  
  1277.  
  1278.     stack = stack_in_pack(item, character);
  1279.     if(stack != MAXCHR)
  1280.     {
  1281.         // We found a similar, stackable item in the pack
  1282.         if(chrnameknown[item] || chrnameknown[stack])
  1283.         {
  1284.             chrnameknown[item] = TRUE;
  1285.             chrnameknown[stack] = TRUE;
  1286.         }
  1287.         if(capusageknown[chrmodel[item]] || capusageknown[chrmodel[stack]])
  1288.         {
  1289.             capusageknown[chrmodel[item]] = TRUE;
  1290.             capusageknown[chrmodel[stack]] = TRUE;
  1291.         }
  1292.         newammo = chrammo[item] + chrammo[stack];
  1293.         if(newammo <= chrammomax[stack])
  1294.         {
  1295.             // All transfered, so kill the in hand item
  1296.             chrammo[stack] = newammo;
  1297.             if(chrattachedto[item] != MAXCHR)
  1298.             {
  1299.                 detach_character_from_mount(item, TRUE, FALSE);
  1300.             }
  1301.             free_one_character(item);
  1302.         }
  1303.         else
  1304.         {
  1305.             // Only some were transfered, 
  1306.             chrammo[item] = chrammo[item]+chrammo[stack]-chrammomax[stack];
  1307.             chrammo[stack] = chrammomax[stack];
  1308.             chralert[character]|=ALERTIFTOOMUCHBAGGAGE;
  1309.         }
  1310.     }
  1311.     else
  1312.     {
  1313.         // Make sure we have room for another item
  1314.         if(chrnuminpack[character] >= MAXNUMINPACK)
  1315.         {
  1316.             chralert[character]|=ALERTIFTOOMUCHBAGGAGE;
  1317.             return;
  1318.         }
  1319.  
  1320.  
  1321.         // Take the item out of hand
  1322.         if(chrattachedto[item] != MAXCHR)
  1323.         {
  1324.             detach_character_from_mount(item, TRUE, FALSE);
  1325.             chralert[item] &= (~ALERTIFDROPPED);
  1326.         }
  1327.  
  1328.  
  1329.         // Remove the item from play
  1330.         chrhitready[item] = FALSE;
  1331.         chrinpack[item] = TRUE;
  1332.  
  1333.  
  1334.         // Insert the item into the pack as the first one
  1335.         oldfirstitem = chrnextinpack[character];
  1336.         chrnextinpack[character] = item;
  1337.         chrnextinpack[item] = oldfirstitem;
  1338.         chrnuminpack[character]++;
  1339.         if(capisequipment[chrmodel[item]])
  1340.         {
  1341.             // AtLastWaypoint doubles as PutAway
  1342.             chralert[item]|=ALERTIFATLASTWAYPOINT;
  1343.         }
  1344.     }
  1345.     return;
  1346. }
  1347.  
  1348. //--------------------------------------------------------------------------------------------
  1349. unsigned short get_item_from_character_pack(unsigned short character, unsigned short grip, unsigned char ignorekurse)
  1350. {
  1351.     // ZZ> This function takes the last item in the character's pack and puts
  1352.     //     it into the designated hand.  It returns the item number or MAXCHR.
  1353.     unsigned short item, nexttolastitem;
  1354.  
  1355.  
  1356.     // Make sure everything is hunkydori
  1357.     if((!chron[character]) || chrinpack[character] || chrisitem[character] || chrnextinpack[character]==MAXCHR)
  1358.         return MAXCHR;
  1359.     if(chrnuminpack[character] == 0)
  1360.         return MAXCHR;
  1361.  
  1362.  
  1363.     // Find the last item in the pack
  1364.     nexttolastitem = character;
  1365.     item = chrnextinpack[character];
  1366.     while(chrnextinpack[item] != MAXCHR)
  1367.     {
  1368.         nexttolastitem = item;
  1369.         item = chrnextinpack[item];
  1370.     }
  1371.  
  1372.  
  1373.     // Figure out what to do with it
  1374.     if(chriskursed[item] && chrisequipped[item] && ignorekurse == FALSE)
  1375.     {
  1376.         // Flag the last item as not removed
  1377.         chralert[item] |= ALERTIFNOTPUTAWAY;  // Doubles as IfNotTakenOut
  1378.         // Cycle it to the front
  1379.         chrnextinpack[item] = chrnextinpack[character];
  1380.         chrnextinpack[nexttolastitem] = MAXCHR;
  1381.         chrnextinpack[character] = item;
  1382.         if(character == nexttolastitem)
  1383.         {
  1384.             chrnextinpack[item] = MAXCHR;
  1385.         }
  1386.         return MAXCHR;
  1387.     }
  1388.     else
  1389.     {
  1390.         // Remove the last item from the pack
  1391.         chrinpack[item] = FALSE;
  1392.         chrisequipped[item] = FALSE;
  1393.         chrnextinpack[nexttolastitem] = MAXCHR;
  1394.         chrnuminpack[character]--;
  1395.         chrteam[item]=chrteam[character];
  1396.  
  1397.  
  1398.         // Attach the item to the character's hand
  1399.         attach_character_to_mount(item, character, grip);
  1400.         chralert[item]&=(~ALERTIFGRABBED);
  1401.         chralert[item]|=(ALERTIFTAKENOUT);
  1402.     }
  1403.     return item;
  1404. }
  1405.  
  1406. //--------------------------------------------------------------------------------------------
  1407. void drop_keys(unsigned short character)
  1408. {
  1409.     // ZZ> This function drops all keys ( [KEYA] to [KEYZ] ) that are in a character's
  1410.     //     inventory ( Not hands ).
  1411.     unsigned short item, lastitem, nextitem, direction, cosdir;
  1412.     int testa, testz;
  1413.  
  1414.  
  1415.     if(character < MAXCHR)
  1416.     {
  1417.         if(chron[character])
  1418.         {
  1419.             if(chrzpos[character] > -2) // Don't lose keys in pits...
  1420.             {
  1421.                 // The IDSZs to find
  1422.                 testa = ('K'-'A'<<15)|('E'-'A'<<10)|('Y'-'A'<<5)|('A'-'A');  // [KEYA]
  1423.                 testz = ('K'-'A'<<15)|('E'-'A'<<10)|('Y'-'A'<<5)|('Z'-'A');  // [KEYZ]
  1424.  
  1425.  
  1426.                 lastitem = character;
  1427.                 item = chrnextinpack[character];
  1428.                 while(item != MAXCHR)
  1429.                 {
  1430.                     nextitem = chrnextinpack[item];
  1431.                     if(item != character)  // Should never happen...
  1432.                     {
  1433.                         if((capidsz[chrmodel[item]][IDSZPARENT]>=(unsigned int) testa &&
  1434.                             capidsz[chrmodel[item]][IDSZPARENT]<=(unsigned int) testz) ||
  1435.                            (capidsz[chrmodel[item]][IDSZTYPE]>=(unsigned int) testa &&
  1436.                             capidsz[chrmodel[item]][IDSZTYPE]<=(unsigned int) testz))
  1437.                         {
  1438.                             // We found a key...
  1439.                             chrinpack[item] = FALSE;
  1440.                             chrisequipped[item] = FALSE;
  1441.                             chrnextinpack[lastitem] = nextitem;
  1442.                             chrnextinpack[item] = MAXCHR;
  1443.                             chrnuminpack[character]--;
  1444.                             chrattachedto[item] = MAXCHR;
  1445.                             chralert[item] |= ALERTIFDROPPED;
  1446.                             chrhitready[item]=TRUE;
  1447.  
  1448.  
  1449.                             direction = RANDIE;
  1450.                             chrturnleftright[item] = direction+32768;
  1451.                             cosdir = direction + 16384;
  1452.                             chrlevel[item] = chrlevel[character];
  1453.                             chrxpos[item] = chrxpos[character];
  1454.                             chrypos[item] = chrypos[character];
  1455.                             chrzpos[item] = chrzpos[character];
  1456.                             chrxvel[item] = turntosin[cosdir>>2]*DROPXYVEL;
  1457.                             chryvel[item] = turntosin[direction>>2]*DROPXYVEL;
  1458.                             chrzvel[item] = DROPZVEL;
  1459.                             chrteam[item] = chrbaseteam[item];
  1460.                         }
  1461.                         else
  1462.                         {
  1463.                             lastitem = item;
  1464.                         }
  1465.                     }
  1466.                     item = nextitem;
  1467.                 }
  1468.             }
  1469.         }
  1470.     }
  1471. }
  1472.  
  1473. //--------------------------------------------------------------------------------------------
  1474. void drop_all_items(unsigned short character)
  1475. {
  1476.     // ZZ> This function drops all of a character's items
  1477.     unsigned short item, direction, cosdir, diradd;
  1478.  
  1479.  
  1480.     if(character < MAXCHR)
  1481.     {
  1482.         if(chron[character])
  1483.         {
  1484.             detach_character_from_mount(chrholdingwhich[character][0], TRUE, FALSE);
  1485.             detach_character_from_mount(chrholdingwhich[character][1], TRUE, FALSE);
  1486.             if(chrnuminpack[character] > 0)
  1487.             {
  1488.                 direction = chrturnleftright[character]+32768;
  1489.                 diradd = 65535 / chrnuminpack[character];
  1490.                 while(chrnuminpack[character] > 0)
  1491.                 {
  1492.                     item = get_item_from_character_pack(character, GRIPLEFT, FALSE);
  1493.                     if(item < MAXCHR)
  1494.                     {
  1495.                         detach_character_from_mount(item, TRUE, TRUE);
  1496.                         chrhitready[item]=TRUE;
  1497.                         chralert[item]|=ALERTIFDROPPED;
  1498.                         chrxpos[item] = chrxpos[character];
  1499.                         chrypos[item] = chrypos[character];
  1500.                         chrzpos[item] = chrzpos[character];
  1501.                         chrlevel[item] = chrlevel[character];
  1502.                         chrturnleftright[item] = direction+32768;
  1503.                         cosdir = direction + 16384;
  1504.                         chrxvel[item] = turntosin[cosdir>>2]*DROPXYVEL;
  1505.                         chryvel[item] = turntosin[direction>>2]*DROPXYVEL;
  1506.                         chrzvel[item] = DROPZVEL;
  1507.                         chrteam[item] = chrbaseteam[item];
  1508.                     } 
  1509.                     direction += diradd;
  1510.                 }
  1511.             }
  1512.         }
  1513.     }
  1514. }
  1515.  
  1516. //--------------------------------------------------------------------------------------------
  1517. void character_grab_stuff(int chara, int grip, unsigned char people)
  1518. {
  1519.     // ZZ> This function makes the character pick up an item if there's one around
  1520.     float xa, ya, za, xb, yb, zb, dist;
  1521.     int charb, hand;
  1522.     unsigned short vertex, model, frame, owner, passage, cnt, price;
  1523.     float pointx, pointy, pointz;
  1524.     unsigned char inshop;
  1525.     int loc;
  1526.  
  1527.  
  1528.     // Make life easier
  1529.     model = chrmodel[chara];
  1530.     hand = (grip-4)>>2;  // 0 is left, 1 is right
  1531.  
  1532.  
  1533.     // Make sure the character doesn't have something already, and that it has hands
  1534.     if(chrholdingwhich[chara][hand]!=MAXCHR || capgripvalid[model][hand] == FALSE)
  1535.         return;
  1536.  
  1537.  
  1538.     // Do we have a matrix???
  1539.     if(chrmatrixvalid[chara])//meshinrenderlist[chronwhichfan[chara]])
  1540.     {
  1541.         // Transform the weapon grip from model to world space
  1542.         frame = chrframe[chara];
  1543.         vertex = madvertices[model] - grip;
  1544.  
  1545.  
  1546.         // Calculate grip point locations
  1547.         pointx = madvrtx[frame][vertex];///chrscale[cnt];
  1548.         pointy = madvrty[frame][vertex];///chrscale[cnt];
  1549.         pointz = madvrtz[frame][vertex];///chrscale[cnt];
  1550.  
  1551.  
  1552.         // Do the transform
  1553.         xa = (pointx*chrmatrix[chara]_CNV(0,0) +
  1554.               pointy*chrmatrix[chara]_CNV(1,0) +
  1555.               pointz*chrmatrix[chara]_CNV(2,0));
  1556.         ya = (pointx*chrmatrix[chara]_CNV(0,1) +
  1557.               pointy*chrmatrix[chara]_CNV(1,1) +
  1558.               pointz*chrmatrix[chara]_CNV(2,1));
  1559.         za = (pointx*chrmatrix[chara]_CNV(0,2) +
  1560.               pointy*chrmatrix[chara]_CNV(1,2) +
  1561.               pointz*chrmatrix[chara]_CNV(2,2));
  1562.         xa += chrmatrix[chara]_CNV(3,0);
  1563.         ya += chrmatrix[chara]_CNV(3,1);
  1564.         za += chrmatrix[chara]_CNV(3,2);
  1565.     }
  1566.     else
  1567.     {
  1568.         // Just wing it
  1569.         xa = chrxpos[chara];
  1570.         ya = chrypos[chara];
  1571.         za = chrzpos[chara];
  1572.     }
  1573.  
  1574.  
  1575.  
  1576.     // Go through all characters to find the best match
  1577.     charb = 0;
  1578.     while(charb < MAXCHR)
  1579.     {
  1580.         if(chron[charb] && (!chrinpack[charb]) && chrweight[charb]<chrweight[chara] && chralive[charb] && chrattachedto[charb]==MAXCHR && ((people==FALSE&&chrisitem[charb]) || (people==TRUE&&chrisitem[charb]==FALSE)))
  1581.         {
  1582.             xb = chrxpos[charb];
  1583.             yb = chrypos[charb];
  1584.             zb = chrzpos[charb];
  1585.             // First check absolute value diamond
  1586.             xb = ABS(xa-xb);
  1587.             yb = ABS(ya-yb);
  1588.             zb = ABS(za-zb);
  1589.             dist = xb+yb;
  1590.             if(dist < GRABSIZE && zb < GRABSIZE)
  1591.             {
  1592.                 // Don't grab your mount
  1593.                 if(chrholdingwhich[charb][0]!=chara && chrholdingwhich[charb][1]!=chara)
  1594.                 {
  1595.                     // Check for shop
  1596.                     inshop = FALSE;
  1597.                     if(chrisitem[charb] && numshoppassage != 0)
  1598.                     {
  1599.                         cnt = 0;
  1600.                         while(cnt < numshoppassage)
  1601.                         {
  1602.                             passage = shoppassage[cnt];
  1603.                             loc = chrxpos[charb];
  1604.                             loc = loc >> 7;
  1605.                             if(loc >= passtlx[passage] && loc <= passbrx[passage])
  1606.                             {
  1607.                                 loc = chrypos[charb];
  1608.                                 loc = loc >> 7;
  1609.                                 if(loc >= passtly[passage] && loc <= passbry[passage])
  1610.                                 {
  1611.                                     inshop = TRUE;
  1612.                                     owner = shopowner[passage];
  1613.                                     cnt = numshoppassage;  // Finish loop
  1614.                                     if(owner == NOOWNER)
  1615.                                     {
  1616.                                         // The owner has died!!!
  1617.                                         inshop = FALSE;
  1618.                                     }
  1619.                                 }
  1620.                             }
  1621.                             cnt++;
  1622.                         }
  1623.                         if(inshop)
  1624.                         {
  1625.                             // Pay the shop owner, or don't allow grab...
  1626.                             if(chrisitem[chara])
  1627.                             {
  1628.                                 // Pets can shop for free =]
  1629.                                 inshop = FALSE;
  1630.                             }
  1631.                             else
  1632.                             {
  1633.                                 chralert[owner] |= ALERTIFORDERED;
  1634.                                 price = capskincost[chrmodel[charb]][0];
  1635.                                 if(capisstackable[chrmodel[charb]])
  1636.                                 {
  1637.                                     price = price * chrammo[charb];
  1638.                                 }
  1639.                                 chrorder[owner] = price;  // Tell owner how much...
  1640.                                 if(chrmoney[chara] >= price)
  1641.                                 {
  1642.                                     // Okay to buy
  1643.                                     chrcounter[owner] = 1;  // 1 for selling an item
  1644.                                     chrmoney[chara] -= price;  // Skin 0 cost is price
  1645.                                     chrmoney[owner] += price;
  1646.                                     if(chrmoney[owner] > MAXMONEY)  chrmoney[owner] = MAXMONEY;
  1647.                                     inshop = FALSE;
  1648.                                 }
  1649.                                 else
  1650.                                 {
  1651.                                     // Don't allow purchase
  1652.                                     chrcounter[owner] = 2;  // 2 for "you can't afford that"
  1653.                                     inshop = TRUE;
  1654.                                 }
  1655.                             }
  1656.                         }
  1657.                     }
  1658.  
  1659.  
  1660.                     if(inshop == FALSE)
  1661.                     {
  1662.                         // Stick 'em together and quit
  1663.                         attach_character_to_mount(charb, chara, grip);
  1664.                         charb=MAXCHR;
  1665.                         if(people==TRUE)
  1666.                         {
  1667.                             // Do a slam animation...  ( Be sure to drop!!! )
  1668.                             play_action(chara, ACTIONMC+hand, FALSE);
  1669.                         }
  1670.                     }
  1671.                     else
  1672.                     {
  1673.                         // Lift the item a little and quit...
  1674.                         chrzvel[charb] = DROPZVEL;
  1675.                         chrhitready[charb]=TRUE;
  1676.                         chralert[charb] |= ALERTIFDROPPED;
  1677.                         charb=MAXCHR;
  1678.                     }
  1679.                 }
  1680.             }
  1681.         }
  1682.         charb++;
  1683.     }
  1684. }
  1685.  
  1686. //--------------------------------------------------------------------------------------------
  1687. void character_swipe(unsigned short cnt, unsigned char grip)
  1688. {
  1689.     // ZZ> This function spawns an attack particle
  1690.     int weapon, particle, spawngrip, thrown;
  1691.     unsigned char action;
  1692.     unsigned short tTmp;
  1693.     float dampen;
  1694.     float x, y, z, velocity;
  1695.  
  1696.  
  1697.     weapon = chrholdingwhich[cnt][grip];
  1698.     spawngrip = SPAWNLAST;
  1699.     action = chraction[cnt];
  1700.     // See if it's an unarmed attack...
  1701.     if(weapon==MAXCHR)
  1702.     {
  1703.         weapon = cnt;
  1704.         spawngrip = 4+(grip<<2);  // 0 = GRIPLEFT, 1 = GRIPRIGHT
  1705.     }
  1706.  
  1707.  
  1708.     if(weapon!=cnt && ((capisstackable[chrmodel[weapon]] && chrammo[weapon]>1) || (action >= ACTIONFA && action <= ACTIONFD)))
  1709.     {
  1710.         // Throw the weapon if it's stacked or a hurl animation
  1711.         x = chrxpos[cnt];
  1712.         y = chrypos[cnt];
  1713.         z = chrzpos[cnt];
  1714.         thrown = spawn_one_character(x, y, z, chrmodel[weapon], chrteam[cnt], 0, chrturnleftright[cnt], chrname[weapon], MAXCHR);
  1715.         if(thrown < MAXCHR)
  1716.         {
  1717.             chriskursed[thrown] = FALSE;
  1718.             chrammo[thrown] = 1;
  1719.             chralert[thrown]|=ALERTIFTHROWN;
  1720.             velocity = chrstrength[cnt]/(chrweight[thrown]*THROWFIX);
  1721.             velocity += MINTHROWVELOCITY;
  1722.             if(velocity > MAXTHROWVELOCITY)
  1723.             {
  1724.                 velocity = MAXTHROWVELOCITY;
  1725.             }
  1726.             tTmp = chrturnleftright[cnt]>>2;
  1727.             chrxvel[thrown]+=turntosin[(tTmp+12288)&16383]*velocity;
  1728.             chryvel[thrown]+=turntosin[(tTmp+8192)&16383]*velocity;
  1729.             chrzvel[thrown] = DROPZVEL;
  1730.             if(chrammo[weapon]<=1)
  1731.             {
  1732.                 // Poof the item
  1733.                 detach_character_from_mount(weapon, TRUE, FALSE);
  1734.                 free_one_character(weapon);
  1735.             }
  1736.             else
  1737.             {
  1738.                 chrammo[weapon]--;
  1739.             }
  1740.         }
  1741.     }
  1742.     else
  1743.     {
  1744.         // Spawn an attack particle
  1745.         if(chrammomax[weapon]==0||chrammo[weapon]!=0)
  1746.         {
  1747.             if(chrammo[weapon]>0 && capisstackable[chrmodel[weapon]]==FALSE)
  1748.             {
  1749.                 chrammo[weapon]--;  // Ammo usage
  1750.             }
  1751.             if(capattackprttype[chrmodel[weapon]]!=-1)
  1752.             {
  1753.                 particle = spawn_one_particle(chrxpos[weapon], chrypos[weapon], chrzpos[weapon], chrturnleftright[cnt], chrmodel[weapon], capattackprttype[chrmodel[weapon]], weapon, spawngrip, chrteam[cnt], cnt, 0, MAXCHR);
  1754.                 if(particle!=MAXPRT)
  1755.                 {
  1756.                     if(capattackattached[chrmodel[weapon]]==FALSE)
  1757.                     {
  1758.                         // Detach the particle
  1759.                         if(pipstartontarget[prtpip[particle]]==FALSE || prttarget[particle]==MAXCHR)
  1760.                         {
  1761.                             attach_particle_to_character(particle, weapon, spawngrip);
  1762.                             // Correct Z spacing base, but nothing else...
  1763.                             prtzpos[particle]+=pipzspacingbase[prtpip[particle]];
  1764.                         }
  1765.                         prtattachedtocharacter[particle]=MAXCHR;
  1766.                         // Don't spawn in walls
  1767.                         if(__prthitawall(particle))
  1768.                         {
  1769.                             prtxpos[particle] = chrxpos[weapon];
  1770.                             prtypos[particle] = chrypos[weapon];
  1771.                             if(__prthitawall(particle))
  1772.                             {
  1773.                                 prtxpos[particle] = chrxpos[cnt];
  1774.                                 prtypos[particle] = chrypos[cnt];
  1775.                             }
  1776.                         }
  1777.                     }
  1778.                     else
  1779.                     {
  1780.                         // Attached particles get a strength bonus for reeling...
  1781.                         dampen = REELBASE+(chrstrength[cnt]/REEL);
  1782.                         prtxvel[particle] = prtxvel[particle]*dampen;
  1783.                         prtyvel[particle] = prtyvel[particle]*dampen;
  1784.                         prtzvel[particle] = prtzvel[particle]*dampen;
  1785.                     }
  1786.                     // Initial particles get a strength bonus, which may be 0.00
  1787.                     prtdamagebase[particle]+=(chrstrength[cnt]*capstrengthdampen[chrmodel[weapon]]);
  1788.                     // Initial particles get an enchantment bonus
  1789.                     prtdamagebase[particle]+=chrdamageboost[weapon];
  1790.                     // Initial particles inherit damage type of weapon
  1791.                     prtdamagetype[particle] = chrdamagetargettype[weapon];
  1792.                 }
  1793.             }
  1794.         }
  1795.         else
  1796.         {
  1797.             chrammoknown[weapon] = TRUE;
  1798.         }
  1799.     }
  1800. }
  1801.  
  1802. //--------------------------------------------------------------------------------------------
  1803. void move_characters(void)
  1804. {
  1805.     // ZZ> This function handles character physics
  1806.     int cnt;
  1807.     unsigned int mapud, maplr;
  1808.     unsigned char twist, actionready;
  1809.     unsigned char speed, framelip, allowedtoattack;
  1810.     float level, friction;
  1811.     float dvx, dvy, dvmax;
  1812.     unsigned short action, weapon, mount, item;
  1813.     int distance, volume;
  1814.     unsigned char watchtarget, grounded;
  1815.  
  1816.  
  1817.     // Move every character
  1818.     cnt = 0;
  1819.     while(cnt < MAXCHR)
  1820.     {
  1821.         if(chron[cnt] && (!chrinpack[cnt]))
  1822.         {
  1823.             grounded = FALSE;
  1824.             valuegopoof = FALSE;
  1825.             // Down that ol' damage timer
  1826.             chrdamagetime[cnt]-=(chrdamagetime[cnt] != 0);
  1827.  
  1828.  
  1829.             // Character's old location
  1830.             chroldx[cnt] = chrxpos[cnt];
  1831.             chroldy[cnt] = chrypos[cnt];
  1832.             chroldz[cnt] = chrzpos[cnt];
  1833.             chroldturn[cnt] = chrturnleftright[cnt];
  1834. //            if(chrattachedto[cnt]!=MAXCHR)
  1835. //            {
  1836. //                chrturnleftright[cnt] = chrturnleftright[chrattachedto[cnt]];
  1837. //                if(chrindolist[cnt]==FALSE)
  1838. //                {
  1839. //                    chrxpos[cnt] = chrxpos[chrattachedto[cnt]];
  1840. //                    chrypos[cnt] = chrypos[chrattachedto[cnt]];
  1841. //                    chrzpos[cnt] = chrzpos[chrattachedto[cnt]];
  1842. //                }
  1843. //            }
  1844.  
  1845.  
  1846.             // Texture movement
  1847.             chruoffset[cnt]+=chruoffvel[cnt];
  1848.             chrvoffset[cnt]+=chrvoffvel[cnt];
  1849.  
  1850.  
  1851.             if(chralive[cnt])
  1852.             {
  1853.                 if(chrattachedto[cnt]==MAXCHR)
  1854.                 {
  1855.                     // Character latches for generalized movement
  1856.                     dvx = chrlatchx[cnt];
  1857.                     dvy = chrlatchy[cnt];
  1858.  
  1859.  
  1860.                     // Reverse movements for daze
  1861.                     if(chrdazetime[cnt] > 0)
  1862.                     {
  1863.                         dvx=-dvx;
  1864.                         dvy=-dvy;
  1865.                     }
  1866.                     // Switch x and y for daze
  1867.                     if(chrgrogtime[cnt] > 0)
  1868.                     {
  1869.                         dvmax = dvx;
  1870.                         dvx=dvy;
  1871.                         dvy=dvmax;
  1872.                     }
  1873.  
  1874.  
  1875.  
  1876.                     // Get direction from the DESIRED change in velocity
  1877.                     if(chrturnmode[cnt]==TURNMODEWATCH)
  1878.                     {
  1879.                         if((ABS(dvx) > WATCHMIN || ABS(dvy) > WATCHMIN))
  1880.                         {
  1881.                             chrturnleftright[cnt] = terp_dir(chrturnleftright[cnt],(atan2(dvy, dvx)+PI)*65535/(2*PI));
  1882.                         }
  1883.                     }
  1884.                     // Face the target
  1885.                     watchtarget = (chrturnmode[cnt]==TURNMODEWATCHTARGET);
  1886.                     if(watchtarget)
  1887.                     {
  1888.                         if(cnt != chraitarget[cnt])
  1889.                             chrturnleftright[cnt] = terp_dir(chrturnleftright[cnt],(atan2(chrypos[chraitarget[cnt]]-chrypos[cnt], chrxpos[chraitarget[cnt]]-chrxpos[cnt])+PI)*65535/(2*PI));
  1890.                     }
  1891.  
  1892.  
  1893.  
  1894.                     if(madframefx[chrframe[cnt]]&MADFXSTOP)
  1895.                     {
  1896.                         dvx = 0;
  1897.                         dvy = 0;
  1898.                     }
  1899.                     else
  1900.                     {
  1901.                         // Limit to max acceleration
  1902.                         dvmax = chrmaxaccel[cnt];
  1903.                         if(dvx < -dvmax) dvx=-dvmax;
  1904.                         if(dvx > dvmax) dvx=dvmax;
  1905.                         if(dvy < -dvmax) dvy=-dvmax;
  1906.                         if(dvy > dvmax) dvy=dvmax;
  1907.                         chrxvel[cnt]+=dvx;
  1908.                         chryvel[cnt]+=dvy;
  1909.                     }
  1910.  
  1911.  
  1912.                     // Get direction from ACTUAL change in velocity
  1913.                     if(chrturnmode[cnt]==TURNMODEVELOCITY)
  1914.                     {
  1915.                         if(dvx<-TURNSPD||dvx>TURNSPD||dvy<-TURNSPD||dvy>TURNSPD)
  1916.                         {
  1917.                             if(chrisplayer[cnt])
  1918.                             {
  1919.                                 // Players turn quickly
  1920.                                 chrturnleftright[cnt] = terp_dir_fast(chrturnleftright[cnt],(atan2(dvy, dvx)+PI)*65535/(2*PI));
  1921.                             }
  1922.                             else
  1923.                             {
  1924.                                 // AI turn slowly
  1925.                                 chrturnleftright[cnt] = terp_dir(chrturnleftright[cnt],(atan2(dvy, dvx)+PI)*65535/(2*PI));
  1926.                             }
  1927.                         }
  1928.                     }
  1929.                     // Otherwise make it spin
  1930.                     else if(chrturnmode[cnt]==TURNMODESPIN)
  1931.                     {
  1932.                         chrturnleftright[cnt]+=SPINRATE;
  1933.                     }
  1934.                 }
  1935.  
  1936.  
  1937.                 // Character latches for generalized buttons
  1938.                 if(chrlatchbutton[cnt]!=0)
  1939.                 {
  1940.                     if(chrlatchbutton[cnt]&LATCHBUTTONJUMP)
  1941.                     {
  1942.                         if(chrattachedto[cnt]!=MAXCHR && chrjumptime[cnt]==0)
  1943.                         {
  1944.                             detach_character_from_mount(cnt, TRUE, TRUE);
  1945.                             chrjumptime[cnt]=JUMPDELAY;
  1946.                             chrzvel[cnt]=DISMOUNTZVEL;
  1947.                             if(chrflyheight[cnt] != 0)
  1948.                                 chrzvel[cnt]=DISMOUNTZVELFLY;
  1949.                             chrzpos[cnt]+=chrzvel[cnt];
  1950.                             if(chrjumpnumberreset[cnt]!=JUMPINFINITE && chrjumpnumber[cnt] != 0)
  1951.                               chrjumpnumber[cnt]--;
  1952.                             // Play the sound
  1953.                             distance = ABS(camtrackx-chrxpos[cnt])+ABS(camtracky-chrypos[cnt]);
  1954.                             volume = -distance;
  1955.  
  1956.                             volume = volume<<VOLSHIFT;
  1957.                             if(volume > VOLMIN)
  1958.                             {
  1959.                                 if(capwavejump[chrmodel[cnt]] != -1)
  1960.                                     play_sound_pvf(capwaveindex[chrmodel[cnt]][capwavejump[chrmodel[cnt]]], PANMID, volume, FRQRANDOM);
  1961.                             }
  1962.  
  1963.                         }
  1964.                         if(chrjumptime[cnt]==0 && chrjumpnumber[cnt]!=0 && chrflyheight[cnt] == 0)
  1965.                         {
  1966.                             if(chrjumpnumberreset[cnt]!=1 || chrjumpready[cnt])
  1967.                             {
  1968.                                 // Make the character jump
  1969.                                 chrhitready[cnt]=TRUE;
  1970.                                 if(chrinwater[cnt])
  1971.                                 {
  1972.                                     chrzvel[cnt]=WATERJUMP;
  1973.                                 }
  1974.                                 else
  1975.                                 {
  1976.                                     chrzvel[cnt]=chrjump[cnt];
  1977.                                 }
  1978.                                 chrjumptime[cnt]=JUMPDELAY;
  1979.                                 chrjumpready[cnt]=FALSE;
  1980.                                 if(chrjumpnumberreset[cnt]!=JUMPINFINITE) chrjumpnumber[cnt]--;
  1981.                                 // Set to jump animation if not doing anything better
  1982.                                 if(chractionready[cnt])    play_action(cnt, ACTIONJA, TRUE);
  1983.                                 // Play the sound
  1984.                                 distance = ABS(camtrackx-chrxpos[cnt])+ABS(camtracky-chrypos[cnt]);
  1985.                                 volume = -distance;
  1986.  
  1987.                                 volume = volume<<VOLSHIFT;
  1988.                                 if(volume > VOLMIN)
  1989.                                 {
  1990.                                     if(capwavejump[chrmodel[cnt]] != -1)
  1991.                                         play_sound_pvf(capwaveindex[chrmodel[cnt]][capwavejump[chrmodel[cnt]]], PANMID, volume, FRQRANDOM);
  1992.                                 }
  1993.  
  1994.                             }
  1995.                         }
  1996.                     }
  1997.                     if((chrlatchbutton[cnt]&LATCHBUTTONALTLEFT)&&chractionready[cnt]&&chrreloadtime[cnt]==0)
  1998.                     {
  1999.                         chrreloadtime[cnt] = GRABDELAY;
  2000.                         if(chrholdingwhich[cnt][0]==MAXCHR)
  2001.                         {
  2002.                             // Grab left
  2003.                             play_action(cnt, ACTIONME, FALSE);
  2004.                         }
  2005.                         else
  2006.                         {
  2007.                             // Drop left
  2008.                             play_action(cnt, ACTIONMA, FALSE);
  2009.                         }
  2010.                     }
  2011.                     if((chrlatchbutton[cnt]&LATCHBUTTONALTRIGHT)&&chractionready[cnt]&&chrreloadtime[cnt]==0)
  2012.                     {
  2013.                         chrreloadtime[cnt] = GRABDELAY;
  2014.                         if(chrholdingwhich[cnt][1]==MAXCHR)
  2015.                         {
  2016.                             // Grab right
  2017.                             play_action(cnt, ACTIONMF, FALSE);
  2018.                         }
  2019.                         else
  2020.                         {
  2021.                             // Drop right
  2022.                             play_action(cnt, ACTIONMB, FALSE);
  2023.                         }
  2024.                     }
  2025.                     if((chrlatchbutton[cnt]&LATCHBUTTONPACKLEFT)&&chractionready[cnt]&&chrreloadtime[cnt]==0)
  2026.                     {
  2027.                         chrreloadtime[cnt] = PACKDELAY;
  2028.                         item = chrholdingwhich[cnt][0];
  2029.                         if(item!=MAXCHR)
  2030.                         {
  2031.                             if((chriskursed[item] || capistoobig[chrmodel[item]]) && capisequipment[chrmodel[item]]==FALSE)
  2032.                             {
  2033.                                 // The item couldn't be put away
  2034.                                 chralert[item]|=ALERTIFNOTPUTAWAY;
  2035.                             }
  2036.                             else
  2037.                             {
  2038.                                 // Put the item into the pack
  2039.                                 add_item_to_character_pack(item, cnt);
  2040.                             }
  2041.                         }
  2042.                         else
  2043.                         {
  2044.                             // Get a new one out and put it in hand
  2045.                             get_item_from_character_pack(cnt, GRIPLEFT, FALSE);
  2046.                         }
  2047.                         // Make it take a little time
  2048.                         play_action(cnt, ACTIONMG, FALSE);
  2049.                     }
  2050.                     if((chrlatchbutton[cnt]&LATCHBUTTONPACKRIGHT)&&chractionready[cnt]&&chrreloadtime[cnt]==0)
  2051.                     {
  2052.                         chrreloadtime[cnt] = PACKDELAY;
  2053.                         item = chrholdingwhich[cnt][1];
  2054.                         if(item!=MAXCHR)
  2055.                         {
  2056.                             if((chriskursed[item] || capistoobig[chrmodel[item]]) && capisequipment[chrmodel[item]]==FALSE)
  2057.                             {
  2058.                                 // The item couldn't be put away
  2059.                                 chralert[item]|=ALERTIFNOTPUTAWAY;
  2060.                             }
  2061.                             else
  2062.                             {
  2063.                                 // Put the item into the pack
  2064.                                 add_item_to_character_pack(item, cnt);
  2065.                             }
  2066.                         }
  2067.                         else
  2068.                         {
  2069.                             // Get a new one out and put it in hand
  2070.                             get_item_from_character_pack(cnt, GRIPRIGHT, FALSE);
  2071.                         }
  2072.                         // Make it take a little time
  2073.                         play_action(cnt, ACTIONMG, FALSE);
  2074.                     }
  2075.                     if(chrlatchbutton[cnt]&LATCHBUTTONLEFT&&chrreloadtime[cnt]==0)
  2076.                     {
  2077.                         // Which weapon?
  2078.                         weapon = chrholdingwhich[cnt][0];
  2079.                         if(weapon == MAXCHR)
  2080.                         {
  2081.                             // Unarmed means character itself is the weapon
  2082.                             weapon = cnt;
  2083.                         }
  2084.                         action = capweaponaction[chrmodel[weapon]];
  2085.  
  2086.  
  2087.                         // Can it do it?
  2088.                         allowedtoattack = TRUE;
  2089.                         if(madactionvalid[chrmodel[cnt]][action]==FALSE || chrreloadtime[weapon] > 0 ||
  2090.                            (capneedskillidtouse[chrmodel[weapon]] && capidsz[chrmodel[cnt]][IDSZSKILL] != capidsz[chrmodel[weapon]][IDSZSKILL]))
  2091.                         {
  2092.                             allowedtoattack = FALSE;
  2093.                             if(chrreloadtime[weapon] == 0)
  2094.                             {
  2095.                                 // This character can't use this weapon
  2096.                                 chrreloadtime[weapon] = 50;
  2097.                                 if(chrstaton[cnt])
  2098.                                 {
  2099.                                     // Tell the player that they can't use this weapon
  2100.                                     sprintf(generictext, "%s can't use this item...", chrname[cnt]);
  2101.                                     debug_message(generictext);
  2102.                                 }
  2103.                             }
  2104.                         }
  2105.                         if(action==ACTIONDA)
  2106.                         {
  2107.                             allowedtoattack = FALSE;
  2108.                             if(chrreloadtime[weapon]==0)
  2109.                             {
  2110.                                 chralert[weapon]=chralert[weapon]|ALERTIFUSED;
  2111.                             }
  2112.                         }
  2113.  
  2114.  
  2115.                         if(allowedtoattack)
  2116.                         {
  2117.                             // Rearing mount
  2118.                             mount = chrattachedto[cnt];
  2119.                             if(mount!=MAXCHR)
  2120.                             {
  2121.                                 allowedtoattack = capridercanattack[chrmodel[mount]];
  2122.                                 if(chrismount[mount]&&chralive[mount]&&chrisplayer[mount]==FALSE&&chractionready[mount])
  2123.                                 {
  2124.                                     if((action != ACTIONPA || allowedtoattack == FALSE) && chractionready[cnt])
  2125.                                     {
  2126.                                         play_action(chrattachedto[cnt], ACTIONUA+(rand()&1), FALSE);
  2127.                                         chralert[chrattachedto[cnt]]|=ALERTIFUSED;
  2128.                                     }
  2129.                                     else
  2130.                                     {
  2131.                                         allowedtoattack = FALSE;
  2132.                                     }
  2133.                                 }
  2134.                             }
  2135.  
  2136.  
  2137.                             // Attack button
  2138.                             if(allowedtoattack)
  2139.                             {
  2140.                                 if(chractionready[cnt] && madactionvalid[chrmodel[cnt]][action])
  2141.                                 {
  2142.                                     // Check mana cost
  2143.                                     if(chrmana[cnt] >= chrmanacost[weapon] || chrcanchannel[cnt])
  2144.                                     {
  2145.                                         cost_mana(cnt, chrmanacost[weapon], weapon);
  2146.                                         // Check life healing
  2147.                                         chrlife[cnt]+=chrlifeheal[weapon];
  2148.                                         if(chrlife[cnt] > chrlifemax[cnt])  chrlife[cnt] = chrlifemax[cnt];
  2149.                                         actionready = FALSE;
  2150.                                         if(action == ACTIONPA)
  2151.                                             actionready = TRUE;
  2152.                                         action+=rand()&1;
  2153.                                         play_action(cnt, action, actionready);
  2154.                                         if(weapon!=cnt)
  2155.                                         {
  2156.                                             // Make the weapon attack too
  2157.                                             play_action(weapon, ACTIONMJ, FALSE);
  2158.                                             chralert[weapon]=chralert[weapon]|ALERTIFUSED;
  2159.                                         }
  2160.                                         else
  2161.                                         {
  2162.                                             // Flag for unarmed attack
  2163.                                             chralert[cnt]|=ALERTIFUSED;
  2164.                                         }
  2165.                                     }
  2166.                                 }
  2167.                             }
  2168.                         }
  2169.                     }
  2170.                     else if(chrlatchbutton[cnt]&LATCHBUTTONRIGHT&&chrreloadtime[cnt]==0)
  2171.                     {
  2172.                         // Which weapon?
  2173.                         weapon = chrholdingwhich[cnt][1];
  2174.                         if(weapon == MAXCHR)
  2175.                         {
  2176.                             // Unarmed means character itself is the weapon
  2177.                             weapon = cnt;
  2178.                         }
  2179.                         action = capweaponaction[chrmodel[weapon]]+2;
  2180.  
  2181.  
  2182.                         // Can it do it?
  2183.                         allowedtoattack = TRUE;
  2184.                         if(madactionvalid[chrmodel[cnt]][action]==FALSE || chrreloadtime[weapon] > 0 ||
  2185.                            (capneedskillidtouse[chrmodel[weapon]] && capidsz[chrmodel[cnt]][IDSZSKILL] != capidsz[chrmodel[weapon]][IDSZSKILL]))
  2186.                         {
  2187.                             allowedtoattack = FALSE;
  2188.                             if(chrreloadtime[weapon] == 0)
  2189.                             {
  2190.                                 // This character can't use this weapon
  2191.                                 chrreloadtime[weapon] = 50;
  2192.                                 if(chrstaton[cnt])
  2193.                                 {
  2194.                                     // Tell the player that they can't use this weapon
  2195.                                     sprintf(generictext, "%s can't use this item...", chrname[cnt]);
  2196.                                     debug_message(generictext);
  2197.                                 }
  2198.                             }
  2199.                         }
  2200.                         if(action==ACTIONDC)
  2201.                         {
  2202.                             allowedtoattack = FALSE;
  2203.                             if(chrreloadtime[weapon]==0)
  2204.                             {
  2205.                                 chralert[weapon]=chralert[weapon]|ALERTIFUSED;
  2206.                             }
  2207.                         }
  2208.  
  2209.  
  2210.                         if(allowedtoattack)
  2211.                         {
  2212.                             // Rearing mount
  2213.                             mount = chrattachedto[cnt];
  2214.                             if(mount!=MAXCHR)
  2215.                             {
  2216.                                 allowedtoattack = capridercanattack[chrmodel[mount]];
  2217.                                 if(chrismount[mount]&&chralive[mount]&&chrisplayer[mount]==FALSE&&chractionready[mount])
  2218.                                 {
  2219.                                     if((action != ACTIONPC || allowedtoattack == FALSE) && chractionready[cnt])
  2220.                                     {
  2221.                                         play_action(chrattachedto[cnt], ACTIONUC+(rand()&1), FALSE);
  2222.                                         chralert[chrattachedto[cnt]]|=ALERTIFUSED;
  2223.                                     }
  2224.                                     else
  2225.                                     {
  2226.                                         allowedtoattack = FALSE;
  2227.                                     }
  2228.                                 }
  2229.                             }
  2230.  
  2231.  
  2232.                             // Attack button
  2233.                             if(allowedtoattack)
  2234.                             {
  2235.                                 if(chractionready[cnt] && madactionvalid[chrmodel[cnt]][action])
  2236.                                 {
  2237.                                     // Check mana cost
  2238.                                     if(chrmana[cnt] >= chrmanacost[weapon] || chrcanchannel[cnt])
  2239.                                     {
  2240.                                         cost_mana(cnt, chrmanacost[weapon], weapon);
  2241.                                         // Check life healing
  2242.                                         chrlife[cnt]+=chrlifeheal[weapon];
  2243.                                         if(chrlife[cnt] > chrlifemax[cnt])  chrlife[cnt] = chrlifemax[cnt];
  2244.                                         actionready = FALSE;
  2245.                                         if(action == ACTIONPC)
  2246.                                             actionready = TRUE;
  2247.                                         action+=rand()&1;
  2248.                                         play_action(cnt, action, actionready);
  2249.                                         if(weapon!=cnt)
  2250.                                         {
  2251.                                             // Make the weapon attack too
  2252.                                             play_action(weapon, ACTIONMJ, FALSE);
  2253.                                             chralert[weapon]=chralert[weapon]|ALERTIFUSED;
  2254.                                         }
  2255.                                         else
  2256.                                         {
  2257.                                             // Flag for unarmed attack
  2258.                                             chralert[cnt]|=ALERTIFUSED;
  2259.                                         }
  2260.                                     }
  2261.                                 }
  2262.                             }
  2263.                         }
  2264.                     }
  2265.                 }
  2266.             }
  2267.  
  2268.  
  2269.  
  2270.  
  2271.             // Is the character in the air?
  2272.             level = chrlevel[cnt];
  2273.             if(chrflyheight[cnt]==0)
  2274.             {
  2275.                 chrzpos[cnt]+=chrzvel[cnt];
  2276.                 if(chrzpos[cnt] > level || (chrzvel[cnt] > STOPBOUNCING && chrzpos[cnt] > level-STOPBOUNCING))
  2277.                 {
  2278.                     // Character is in the air
  2279.                     chrjumpready[cnt]=FALSE;
  2280.                     chrzvel[cnt]+=gravity;
  2281.  
  2282.  
  2283.                     // Down jump timers for flapping characters
  2284.                     if(chrjumptime[cnt]!=0) chrjumptime[cnt]--;
  2285.  
  2286.  
  2287.                     // Airborne characters still get friction to make control easier
  2288.                     friction = airfriction;
  2289.                 }
  2290.                 else
  2291.                 {
  2292.                     // Character is on the ground
  2293.                     chrzpos[cnt] = level;
  2294.                     grounded = TRUE;
  2295.                     if(chrhitready[cnt])
  2296.                     {
  2297.                         chralert[cnt]|=ALERTIFHITGROUND;
  2298.                         chrhitready[cnt] = FALSE;
  2299.                     }
  2300.  
  2301.  
  2302.                     // Make the characters slide
  2303.                     twist = meshtwist[chronwhichfan[cnt]];
  2304.                     friction = noslipfriction;
  2305.                     if(meshfx[chronwhichfan[cnt]]&MESHFXSLIPPY)
  2306.                     {
  2307.                         if(wateriswater && (meshfx[chronwhichfan[cnt]]&MESHFXWATER) && chrlevel[cnt] < watersurfacelevel+RAISE+1)
  2308.                         {
  2309.                             // It says it's slippy, but the water is covering it...
  2310.                             // Treat exactly as normal
  2311.                             chrjumpready[cnt]=TRUE;
  2312.                             chrjumpnumber[cnt] = chrjumpnumberreset[cnt];
  2313.                             if(chrjumptime[cnt] > 0) chrjumptime[cnt]--;
  2314.                             chrzvel[cnt] = -chrzvel[cnt]*chrdampen[cnt];
  2315.                             chrzvel[cnt]+=gravity;
  2316.                         }
  2317.                         else
  2318.                         {
  2319.                             // It's slippy all right...
  2320.                             friction = slippyfriction;
  2321.                             chrjumpready[cnt]=TRUE;
  2322.                             if(chrjumptime[cnt] > 0) chrjumptime[cnt]--;
  2323.                             if(chrweight[cnt]!=65535)
  2324.                             {
  2325.                                 // Slippy hills make characters slide
  2326.                                 chrxvel[cnt]+=vellrtwist[twist];
  2327.                                 chryvel[cnt]+=veludtwist[twist];
  2328.                                 chrzvel[cnt]=-SLIDETOLERANCE;
  2329.                             }
  2330.                             if(flattwist[twist])
  2331.                             {
  2332.                                 // Reset jumping on flat areas of slippiness
  2333.                                 chrjumpnumber[cnt] = chrjumpnumberreset[cnt];
  2334.                             }
  2335.                         }
  2336.                     }
  2337.                     else
  2338.                     {
  2339.                         // Reset jumping
  2340.                         chrjumpready[cnt]=TRUE;
  2341.                         chrjumpnumber[cnt] = chrjumpnumberreset[cnt];
  2342.                         if(chrjumptime[cnt] > 0) chrjumptime[cnt]--;
  2343.                         chrzvel[cnt] = -chrzvel[cnt]*chrdampen[cnt];
  2344.                         chrzvel[cnt]+=gravity;
  2345.                     }
  2346.  
  2347.  
  2348.  
  2349.  
  2350.                     // Characters with sticky butts lie on the surface of the mesh
  2351.                     if(chrstickybutt[cnt]||chralive[cnt]==FALSE)
  2352.                     {
  2353.                         maplr = chrturnmaplr[cnt];
  2354.                         maplr = (maplr<<6)-maplr+maplrtwist[twist];
  2355.                         mapud = chrturnmapud[cnt];
  2356.                         mapud = (mapud<<6)-mapud+mapudtwist[twist];
  2357.                         chrturnmaplr[cnt] = maplr>>6;
  2358.                         chrturnmapud[cnt] = mapud>>6;
  2359.                     }
  2360.                 }
  2361.             }
  2362.             else
  2363.             {
  2364.                 //  Flying
  2365.                 chrjumpready[cnt]=FALSE;
  2366.                 chrzpos[cnt]+=chrzvel[cnt];
  2367.                 if(level < 0) level = 0;  // Don't fall in pits...
  2368.                 chrzvel[cnt]+=(level+chrflyheight[cnt]-chrzpos[cnt])*FLYDAMPEN;
  2369.                 if(chrzpos[cnt] < level)
  2370.                 {
  2371.                     chrzpos[cnt] = level;
  2372.                     chrzvel[cnt] = 0;
  2373.                 }
  2374.                 // Airborne characters still get friction to make control easier
  2375.                 friction = airfriction;
  2376.             }
  2377.             // Move the character
  2378.             chrxpos[cnt]+=chrxvel[cnt];
  2379.             if(__chrhitawall(cnt)) { chrxpos[cnt]=chroldx[cnt]; chrxvel[cnt]=-chrxvel[cnt]; }
  2380.             chrypos[cnt]+=chryvel[cnt];
  2381.             if(__chrhitawall(cnt)) { chrypos[cnt]=chroldy[cnt]; chryvel[cnt]=-chryvel[cnt]; }
  2382.             // Apply friction for next time
  2383.             chrxvel[cnt]=chrxvel[cnt]*friction;
  2384.             chryvel[cnt]=chryvel[cnt]*friction;
  2385.  
  2386.  
  2387.             // Animate the character
  2388.             chrlip[cnt] = (chrlip[cnt] + 64);
  2389.             if(chrlip[cnt] == 192)
  2390.             {
  2391.                 // Check frame effects
  2392.                 if(madframefx[chrframe[cnt]]&MADFXACTLEFT)
  2393.                     character_swipe(cnt, 0);
  2394.                 if(madframefx[chrframe[cnt]]&MADFXACTRIGHT)
  2395.                     character_swipe(cnt, 1);
  2396.                 if(madframefx[chrframe[cnt]]&MADFXGRABLEFT)
  2397.                     character_grab_stuff(cnt, GRIPLEFT, FALSE);
  2398.                 if(madframefx[chrframe[cnt]]&MADFXGRABRIGHT)
  2399.                     character_grab_stuff(cnt, GRIPRIGHT, FALSE);
  2400.                 if(madframefx[chrframe[cnt]]&MADFXCHARLEFT)
  2401.                     character_grab_stuff(cnt, GRIPLEFT, TRUE);
  2402.                 if(madframefx[chrframe[cnt]]&MADFXCHARRIGHT)
  2403.                     character_grab_stuff(cnt, GRIPRIGHT, TRUE);
  2404.                 if(madframefx[chrframe[cnt]]&MADFXDROPLEFT)
  2405.                     detach_character_from_mount(chrholdingwhich[cnt][0], FALSE, TRUE);
  2406.                 if(madframefx[chrframe[cnt]]&MADFXDROPRIGHT)
  2407.                     detach_character_from_mount(chrholdingwhich[cnt][1], FALSE, TRUE);
  2408.                 if(madframefx[chrframe[cnt]]&MADFXPOOF && chrisplayer[cnt]==FALSE)
  2409.                     valuegopoof = TRUE;
  2410.                 if(madframefx[chrframe[cnt]]&MADFXFOOTFALL)
  2411.                 {
  2412.                     if(capwavefootfall[chrmodel[cnt]] != -1)
  2413.                     {
  2414.                         distance = ABS(camtrackx-chrxpos[cnt])+ABS(camtracky-chrypos[cnt]);
  2415.                         volume = -distance;
  2416.  
  2417.                         volume = volume<<VOLSHIFT;
  2418.                         if(volume > VOLMIN)
  2419.                         {
  2420.                             play_sound_pvf(capwaveindex[chrmodel[cnt]][capwavefootfall[chrmodel[cnt]]], PANMID, volume, FRQRANDOM);
  2421.                         }
  2422.  
  2423.                     }
  2424.                 }
  2425.             }
  2426.             if(chrlip[cnt] == 0)
  2427.             {
  2428.                 // Change frames
  2429.                 chrlastframe[cnt] = chrframe[cnt];
  2430.                 chrframe[cnt]++;
  2431.                 if(chrframe[cnt] == madactionend[chrmodel[cnt]][chraction[cnt]])
  2432.                 {
  2433.                     // Action finished
  2434.                     if(chrkeepaction[cnt])
  2435.                     {
  2436.                         // Keep the last frame going
  2437.                         chrframe[cnt] = chrlastframe[cnt];
  2438.                     }
  2439.                     else
  2440.                     {
  2441.                         if(chrloopaction[cnt]==FALSE)
  2442.                         {
  2443.                             // Go on to the next action
  2444.                             chraction[cnt] = chrnextaction[cnt];
  2445.                             chrnextaction[cnt] = ACTIONDA;
  2446.                         }
  2447.                         else
  2448.                         {
  2449.                             // See if the character is mounted...
  2450.                             if(chrattachedto[cnt]!=MAXCHR)
  2451.                             {
  2452.                                 chraction[cnt] = ACTIONMI;
  2453.                             }
  2454.                         }
  2455.                         chrframe[cnt] = madactionstart[chrmodel[cnt]][chraction[cnt]];
  2456.                     }
  2457.                     chractionready[cnt] = TRUE;
  2458.                 }
  2459.             }
  2460.  
  2461.  
  2462.  
  2463.             // Do "Be careful!" delay
  2464.             if(chrcarefultime[cnt] != 0)
  2465.             {
  2466.                 chrcarefultime[cnt]--;
  2467.             }
  2468.  
  2469.  
  2470.             // Get running, walking, sneaking, or dancing, from speed
  2471.             if((chrkeepaction[cnt]|chrloopaction[cnt])==FALSE)
  2472.             {
  2473.                 framelip = madframelip[chrframe[cnt]];  // 0 - 15...  Way through animation
  2474.                 if(chractionready[cnt]&&chrlip[cnt]==0&&grounded&&chrflyheight[cnt]==0&&(framelip&7)<2)
  2475.                 {
  2476.                     // Do the motion stuff
  2477.                     speed = ABS((int) chrxvel[cnt])+ABS((int) chryvel[cnt]);
  2478.                     if(speed < chrsneakspd[cnt])
  2479.                     {
  2480. //                        chrnextaction[cnt] = ACTIONDA;
  2481.                         // Do boredom
  2482.                         chrboretime[cnt]--;
  2483.                         if(chrboretime[cnt] < 0)
  2484.                         {
  2485.                             chralert[cnt]|=ALERTIFBORED;
  2486.                             chrboretime[cnt] = BORETIME;
  2487.                         }
  2488.                         else
  2489.                         {
  2490.                             // Do standstill
  2491.                             if(chraction[cnt]>ACTIONDD)
  2492.                             {
  2493.                                 chraction[cnt] = ACTIONDA;
  2494.                                 chrframe[cnt] = madactionstart[chrmodel[cnt]][chraction[cnt]];
  2495.                             }
  2496.                         }
  2497.                     }
  2498.                     else
  2499.                     {
  2500.                         chrboretime[cnt] = BORETIME;
  2501.                         if(speed < chrwalkspd[cnt])
  2502.                         {
  2503.                             chrnextaction[cnt] = ACTIONWA;
  2504.                             if(chraction[cnt]!=ACTIONWA)
  2505.                             {
  2506.                                 chrframe[cnt] = madframeliptowalkframe[chrmodel[cnt]][LIPWA][framelip];
  2507.                                 chraction[cnt] = ACTIONWA;
  2508.                             }
  2509.                         }
  2510.                         else
  2511.                         {
  2512.                             if(speed < chrrunspd[cnt])
  2513.                             {
  2514.                                 chrnextaction[cnt] = ACTIONWB;
  2515.                                 if(chraction[cnt]!=ACTIONWB)
  2516.                                 {
  2517.                                     chrframe[cnt] = madframeliptowalkframe[chrmodel[cnt]][LIPWB][framelip];
  2518.                                     chraction[cnt] = ACTIONWB;
  2519.                                 }
  2520.                             }
  2521.                             else
  2522.                             {
  2523.                                 chrnextaction[cnt] = ACTIONWC;
  2524.                                 if(chraction[cnt]!=ACTIONWC)
  2525.                                 {
  2526.                                     chrframe[cnt] = madframeliptowalkframe[chrmodel[cnt]][LIPWC][framelip];
  2527.                                     chraction[cnt] = ACTIONWC;
  2528.                                 }
  2529.                             }
  2530.                         }
  2531.                     }
  2532.                 }
  2533.             }
  2534.             // Do poofing
  2535.             if(valuegopoof)
  2536.             {
  2537.                 if(chrattachedto[cnt] != MAXCHR)
  2538.                     detach_character_from_mount(cnt, TRUE, FALSE);
  2539.                 if(chrholdingwhich[cnt][0] != MAXCHR)
  2540.                     detach_character_from_mount(chrholdingwhich[cnt][0], TRUE, FALSE);
  2541.                 if(chrholdingwhich[cnt][1] != MAXCHR)
  2542.                     detach_character_from_mount(chrholdingwhich[cnt][1], TRUE, FALSE);
  2543.                 free_inventory(cnt);
  2544.                 free_one_character(cnt);
  2545.             }
  2546.         }
  2547.         cnt++;
  2548.     }
  2549. }
  2550.  
  2551. //--------------------------------------------------------------------------------------------
  2552. void setup_characters(char *modname)
  2553. {
  2554.     // ZZ> This function sets up character data, loaded from "SPAWN.TXT"
  2555.     int currentcharacter=0, lastcharacter, passage, content, money, level, skin, cnt, tnc, localnumber;
  2556.     unsigned char ghost, team, stat, cTmp;
  2557.     char *name;
  2558.     char itislocal;
  2559.     char myname[256], newloadname[256];
  2560.     unsigned short facing, slot, grip, attach;
  2561.     float x, y, z;
  2562.     FILE *fileread;
  2563.  
  2564.  
  2565.     // Turn all characters off
  2566.     free_all_characters();
  2567.  
  2568.  
  2569.     // Turn some back on
  2570.     make_newloadname(modname, "gamedat/spawn.txt", newloadname);
  2571.     fileread = fopen( FILENAME( newloadname ), "r");
  2572.     currentcharacter = MAXCHR;
  2573.     if(fileread)
  2574.     {
  2575.         while(goto_colon_yesno(fileread))
  2576.         {
  2577.             fscanf(fileread, "%s", myname);
  2578.             name = myname;
  2579.             if(myname[0] == 'N' && myname[1] == 'O' && myname[2] == 'N' &&
  2580.                 myname[3] == 'E' && myname[4] == 0)
  2581.             {
  2582.                 // Random name
  2583.                 name = NULL;
  2584.             }
  2585.             cnt = 0;
  2586.             while(cnt < 256)
  2587.             {
  2588.                 if(myname[cnt]=='_')  myname[cnt] = ' ';
  2589.                 cnt++;
  2590.             }
  2591.             fscanf(fileread, "%d", &slot);
  2592.             fscanf(fileread, "%f%f%f", &x, &y, &z); x = x*128;  y = y*128;  z = z*128;
  2593.             cTmp = get_first_letter(fileread);
  2594.                 attach = MAXCHR;
  2595.                 facing = NORTH;
  2596.                 if(cTmp == 'S' || cTmp == 's')  facing = SOUTH;
  2597.                 if(cTmp == 'E' || cTmp == 'e')  facing = EAST;
  2598.                 if(cTmp == 'W' || cTmp == 'w')  facing = WEST;
  2599.                 if(cTmp == 'L' || cTmp == 'l')  { attach = currentcharacter; grip = GRIPLEFT;   }
  2600.                 if(cTmp == 'R' || cTmp == 'r')  { attach = currentcharacter; grip = GRIPRIGHT;  }
  2601.                 if(cTmp == 'I' || cTmp == 'i')  { attach = currentcharacter; grip = INVENTORY;  }
  2602.             fscanf(fileread, "%d%d%d%d%d", &money, &skin, &passage, &content, &level);
  2603.             cTmp = get_first_letter(fileread);
  2604.                 stat = FALSE;
  2605.                 if(cTmp == 'T' || cTmp == 't') stat = TRUE;
  2606.             cTmp = get_first_letter(fileread);
  2607.                 ghost = FALSE;
  2608.                 if(cTmp == 'T' || cTmp == 't') ghost = TRUE;
  2609.             team = (get_first_letter(fileread)-'A')%MAXTEAM;
  2610.  
  2611.  
  2612.             // Spawn the character
  2613.             if(team < numplayer || rtscontrol==FALSE || team >= MAXPLAYER)
  2614.             {
  2615.                 lastcharacter = spawn_one_character(x, y, z, slot, team, skin, facing, name, MAXCHR);
  2616.                 if(lastcharacter < MAXCHR)
  2617.                 {
  2618.                     if(allselect && team == rtslocalteam)
  2619.                         add_select(lastcharacter);
  2620.                     chrmoney[lastcharacter]+=money;
  2621.                     if(chrmoney[lastcharacter] > MAXMONEY)  chrmoney[lastcharacter] = MAXMONEY;
  2622.                     if(chrmoney[lastcharacter] < 0)  chrmoney[lastcharacter] = 0;
  2623.                     chraicontent[lastcharacter] = content;
  2624.                     chrpassage[lastcharacter] = passage;
  2625.                     if(attach==MAXCHR)
  2626.                     {
  2627.                         // Free character
  2628.                         currentcharacter = lastcharacter;
  2629.                     }
  2630.                     else
  2631.                     {
  2632.                         // Attached character
  2633.                         if(grip != INVENTORY)
  2634.                         {
  2635.                             // Wielded character
  2636.                             attach_character_to_mount(lastcharacter, currentcharacter, grip);
  2637.                             let_character_think(lastcharacter);  // Empty the grabbed messages
  2638.                         }
  2639.                         else
  2640.                         {
  2641.                             // Inventory character
  2642.                             add_item_to_character_pack(lastcharacter, currentcharacter);
  2643.                             chralert[lastcharacter] |= ALERTIFGRABBED;  // Make spellbooks change
  2644.                             chrattachedto[lastcharacter] = currentcharacter;  // Make grab work
  2645.                             let_character_think(lastcharacter);  // Empty the grabbed messages
  2646.                             chrattachedto[lastcharacter] = MAXCHR;  // Fix grab
  2647.                         }
  2648.                     }
  2649.                     // Turn on player input devices
  2650.                     if(stat)
  2651.                     {
  2652.                         if(importamount == 0)
  2653.                         {
  2654.                             if(playeramount < 2)
  2655.                             {
  2656.                                 if(numstat == 0)
  2657.                                 {
  2658.                                     // Single player module
  2659.                                     add_player(lastcharacter, numstat, INPUTMOUSE|INPUTKEY|INPUTJOYA|INPUTJOYB);
  2660.                                 }
  2661.                             }
  2662.                             else
  2663.                             {
  2664.                                 if(networkon == FALSE)
  2665.                                 {
  2666.                                     if(playeramount == 2)
  2667.                                     {
  2668.                                         // Two player hack
  2669.                                         if(numstat == 0)
  2670.                                         {
  2671.                                             // First player
  2672.                                             add_player(lastcharacter, numstat, INPUTMOUSE|INPUTKEY|INPUTJOYB);
  2673.                                         }
  2674.                                         if(numstat == 1)
  2675.                                         {
  2676.                                             // Second player
  2677.                                             add_player(lastcharacter, numstat, INPUTJOYA);
  2678.                                         }
  2679.                                     }
  2680.                                     else
  2681.                                     {
  2682.                                         // Three player hack
  2683.                                         if(numstat == 0)
  2684.                                         {
  2685.                                             // First player
  2686.                                             add_player(lastcharacter, numstat, INPUTKEY);
  2687.                                         }
  2688.                                         if(numstat == 1)
  2689.                                         {
  2690.                                             // Second player
  2691.                                             add_player(lastcharacter, numstat, INPUTJOYA);
  2692.                                         }
  2693.                                         if(numstat == 2)
  2694.                                         {
  2695.                                             // Third player
  2696.                                             add_player(lastcharacter, numstat, INPUTJOYB|INPUTMOUSE);
  2697.                                         }
  2698.                                     }
  2699.                                 }
  2700.                                 else
  2701.                                 {
  2702.                                     // One player per machine hack
  2703.                                     if(localmachine == numstat)
  2704.                                     {
  2705.                                         add_player(lastcharacter, numstat, INPUTMOUSE|INPUTKEY|INPUTJOYA|INPUTJOYB);
  2706.                                     }
  2707.                                 }
  2708.                             }
  2709.                         }
  2710.                         if(numstat < importamount)
  2711.                         {
  2712.                             // Multiplayer import module
  2713.                             itislocal = FALSE;
  2714.                             tnc = 0;
  2715.                             while(tnc < numimport)
  2716.                             {
  2717.                                 if(capimportslot[chrmodel[lastcharacter]] == localslot[tnc])
  2718.                                 {
  2719.                                     itislocal = TRUE;
  2720.                                     localnumber = tnc;
  2721.                                     tnc = numimport;
  2722.                                 }
  2723.                                 tnc++;
  2724.                             }
  2725.  
  2726.  
  2727.                             if(itislocal)
  2728.                             {
  2729.                                 // It's a local player
  2730.                                 add_player(lastcharacter, numstat, localcontrol[localnumber]);
  2731.                             }
  2732.                             else
  2733.                             {
  2734.                                 // It's a remote player
  2735.                                 add_player(lastcharacter, numstat, INPUTNONE);
  2736.                             }
  2737.                         }
  2738.                         // Turn on the stat display
  2739.                         add_stat(lastcharacter);
  2740.                     }
  2741.  
  2742.                     // Set the starting level
  2743.                     if(chrisplayer[lastcharacter]==FALSE)
  2744.                     {
  2745.                         // Let the character gain levels
  2746.                         level = level - 1;
  2747.                         while(chrexperiencelevel[lastcharacter] < level && chrexperience[lastcharacter] < MAXXP)
  2748.                         {
  2749.                             give_experience(lastcharacter, MAXXP, XPDIRECT);
  2750.                         }
  2751.                     }
  2752.                     if(ghost)
  2753.                     {
  2754.                         // Make the character a ghost !!!BAD!!!  Can do with enchants
  2755.                         chralpha[lastcharacter] = 128;
  2756.                         chrlight[lastcharacter] = 255;
  2757.                     }
  2758.                 }
  2759.             }
  2760.         }
  2761.         fclose(fileread);
  2762.     }
  2763.     else
  2764.     {
  2765.         general_error(0, 0, newloadname);
  2766.     }
  2767.     clear_messages();
  2768.  
  2769.  
  2770.     // Make sure local players are displayed first
  2771.     sort_stat();
  2772.  
  2773.  
  2774.     // Fix tilting trees problem
  2775.     tilt_characters_to_terrain();
  2776.  
  2777.     // Assume RTS mode always has players...  So it doesn't quit
  2778.     if(rtscontrol)  nolocalplayers = FALSE;
  2779. }
  2780.  
  2781. //--------------------------------------------------------------------------------------------
  2782. void set_one_player_latch(unsigned short player)
  2783. {
  2784.     // ZZ> This function converts input readings to latch settings, so players can
  2785.     //     move around
  2786.     float newx, newy;
  2787.     unsigned short turnsin, turncos, character;
  2788.     unsigned char device;
  2789.     float dist, scale;
  2790.     float inputx, inputy;
  2791.  
  2792.  
  2793.     // Check to see if we need to bother
  2794.     if(plavalid[player] && pladevice[player] != INPUTNONE)
  2795.     {
  2796.         // Make life easier
  2797.         character = plaindex[player];
  2798.         device = pladevice[player];
  2799.  
  2800.         // Clear the player's latch buffers
  2801.         plalatchbutton[player] = 0;
  2802.         plalatchx[player] = 0;
  2803.         plalatchy[player] = 0;
  2804.  
  2805.         // Mouse routines
  2806.         if((device & INPUTMOUSE) && mouseon)
  2807.         {
  2808.             // Movement
  2809.             newx = 0;
  2810.             newy = 0;
  2811.             if((autoturncamera==255 && numlocalpla == 1) ||
  2812.                !control_mouse_is_pressed(MOS_CAMERA))  // Don't allow movement in camera control mode
  2813.             {
  2814.                 dist = sqrt(mousex*mousex+mousey*mousey);
  2815.                 if(dist > 0)
  2816.                 {
  2817.                     scale = mousesense/dist;
  2818.                     if(dist < mousesense)
  2819.                     {
  2820.                         scale = dist/mousesense;
  2821.                     }
  2822.                     scale = scale/mousesense;
  2823.                     if(chrattachedto[character]!=MAXCHR)
  2824.                     {
  2825.                         // Mounted
  2826.                         inputx = mousex*chrmaxaccel[chrattachedto[character]]*scale;
  2827.                         inputy = mousey*chrmaxaccel[chrattachedto[character]]*scale;
  2828.                     }
  2829.                     else
  2830.                     {
  2831.                         // Unmounted
  2832.                         inputx = mousex*chrmaxaccel[character]*scale;
  2833.                         inputy = mousey*chrmaxaccel[character]*scale;
  2834.                     }
  2835.                     turnsin = (camturnleftrightone*16383);
  2836.                     turnsin = turnsin&16383;
  2837.                     turncos = (turnsin+4096)&16383;
  2838.                     if(autoturncamera==255 &&
  2839.                        numlocalpla == 1 &&
  2840.                        control_mouse_is_pressed(MOS_CAMERA)==0)  inputx = 0;
  2841.                     newx = (inputx*turntosin[turncos]+inputy*turntosin[turnsin]);
  2842.                     newy = (-inputx*turntosin[turnsin]+inputy*turntosin[turncos]);
  2843. //                    plalatchx[player]+=newx;
  2844. //                    plalatchy[player]+=newy;
  2845.                 }
  2846.             }
  2847.             plalatchx[player]+=newx*mousecover+mouselatcholdx*mousesustain;
  2848.             plalatchy[player]+=newy*mousecover+mouselatcholdy*mousesustain;
  2849.             mouselatcholdx = plalatchx[player];
  2850.             mouselatcholdy = plalatchy[player];
  2851.             // Sustain old movements to ease mouse play
  2852. //            plalatchx[player]+=mouselatcholdx*mousesustain;
  2853. //            plalatchy[player]+=mouselatcholdy*mousesustain;
  2854. //            mouselatcholdx = plalatchx[player];
  2855. //            mouselatcholdy = plalatchy[player];
  2856.             // Read buttons
  2857.             if(control_mouse_is_pressed(MOS_JUMP))
  2858.                 plalatchbutton[player] |= LATCHBUTTONJUMP;
  2859.             if(control_mouse_is_pressed(MOS_LEFT_USE))
  2860.                 plalatchbutton[player] |= LATCHBUTTONLEFT;
  2861.             if(control_mouse_is_pressed(MOS_LEFT_GET))
  2862.                 plalatchbutton[player] |= LATCHBUTTONALTLEFT;
  2863.             if(control_mouse_is_pressed(MOS_LEFT_PACK))
  2864.                 plalatchbutton[player] |= LATCHBUTTONPACKLEFT;
  2865.             if(control_mouse_is_pressed(MOS_RIGHT_USE))
  2866.                 plalatchbutton[player] |= LATCHBUTTONRIGHT;
  2867.             if(control_mouse_is_pressed(MOS_RIGHT_GET))
  2868.                 plalatchbutton[player] |= LATCHBUTTONALTRIGHT;
  2869.             if(control_mouse_is_pressed(MOS_RIGHT_PACK))
  2870.                 plalatchbutton[player] |= LATCHBUTTONPACKRIGHT;
  2871.         }
  2872.  
  2873.  
  2874.         // Joystick A routines
  2875.         if((device & INPUTJOYA) && joyaon)
  2876.         {
  2877.             // Movement
  2878.             if((autoturncamera==255 && numlocalpla == 1) ||
  2879.                !control_joya_is_pressed(JOA_CAMERA))
  2880.             {
  2881.                 newx = 0;
  2882.                 newy = 0;
  2883.                 inputx = 0;
  2884.                 inputy = 0;
  2885.                 dist = sqrt(joyax*joyax+joyay*joyay);
  2886.                 if(dist > 0)
  2887.                 {
  2888.                     scale = 1.0/dist;
  2889.                     if(chrattachedto[character]!=MAXCHR)
  2890.                     {
  2891.                         // Mounted
  2892.                         inputx = joyax*chrmaxaccel[chrattachedto[character]]*scale;
  2893.                         inputy = joyay*chrmaxaccel[chrattachedto[character]]*scale;
  2894.                     }
  2895.                     else
  2896.                     {
  2897.                         // Unmounted
  2898.                         inputx = joyax*chrmaxaccel[character]*scale;
  2899.                         inputy = joyay*chrmaxaccel[character]*scale;
  2900.                     }
  2901.                 }
  2902.                 turnsin = (camturnleftrightone*16383);
  2903.                 turnsin = turnsin&16383;
  2904.                 turncos = (turnsin+4096)&16383;
  2905.                 if(autoturncamera==255 &&
  2906.                    numlocalpla == 1 &&
  2907.                    !control_joya_is_pressed(JOA_CAMERA))  inputx = 0;
  2908.                 newx = (inputx*turntosin[turncos]+inputy*turntosin[turnsin]);
  2909.                 newy = (-inputx*turntosin[turnsin]+inputy*turntosin[turncos]);
  2910.                 plalatchx[player]+=newx;
  2911.                 plalatchy[player]+=newy;
  2912.             }
  2913.             // Read buttons
  2914.             if(control_joya_is_pressed(JOA_JUMP))
  2915.                 plalatchbutton[player] |= LATCHBUTTONJUMP;
  2916.             if(control_joya_is_pressed(JOA_LEFT_USE))
  2917.                 plalatchbutton[player] |= LATCHBUTTONLEFT;
  2918.             if(control_joya_is_pressed(JOA_LEFT_GET))
  2919.                 plalatchbutton[player] |= LATCHBUTTONALTLEFT;
  2920.             if(control_joya_is_pressed(JOA_LEFT_PACK))
  2921.                 plalatchbutton[player] |= LATCHBUTTONPACKLEFT;
  2922.             if(control_joya_is_pressed(JOA_RIGHT_USE))
  2923.                 plalatchbutton[player] |= LATCHBUTTONRIGHT;
  2924.             if(control_joya_is_pressed(JOA_RIGHT_GET))
  2925.                 plalatchbutton[player] |= LATCHBUTTONALTRIGHT;
  2926.             if(control_joya_is_pressed(JOA_RIGHT_PACK))
  2927.                 plalatchbutton[player] |= LATCHBUTTONPACKRIGHT;
  2928.         }
  2929.  
  2930.  
  2931.         // Joystick B routines
  2932.         if((device & INPUTJOYB) && joybon)
  2933.         {
  2934.             // Movement
  2935.             if((autoturncamera==255 && numlocalpla == 1) ||
  2936.                !control_joyb_is_pressed(JOB_CAMERA))
  2937.             {
  2938.                 newx = 0;
  2939.                 newy = 0;
  2940.                 inputx = 0;
  2941.                 inputy = 0;
  2942.                 dist = sqrt(joybx*joybx+joyby*joyby);
  2943.                 if(dist > 0)
  2944.                 {
  2945.                     scale = 1.0/dist;
  2946.                     if(chrattachedto[character]!=MAXCHR)
  2947.                     {
  2948.                         // Mounted
  2949.                         inputx = joybx*chrmaxaccel[chrattachedto[character]]*scale;
  2950.                         inputy = joyby*chrmaxaccel[chrattachedto[character]]*scale;
  2951.                     }
  2952.                     else
  2953.                     {
  2954.                         // Unmounted
  2955.                         inputx = joybx*chrmaxaccel[character]*scale;
  2956.                         inputy = joyby*chrmaxaccel[character]*scale;
  2957.                     }
  2958.                 }
  2959.                 turnsin = (camturnleftrightone*16383);
  2960.                 turnsin = turnsin&16383;
  2961.                 turncos = (turnsin+4096)&16383;
  2962.                 if(autoturncamera==255 &&
  2963.                    numlocalpla == 1 &&
  2964.                    !control_joyb_is_pressed(JOB_CAMERA))  inputx = 0;
  2965.                 newx = (inputx*turntosin[turncos]+inputy*turntosin[turnsin]);
  2966.                 newy = (-inputx*turntosin[turnsin]+inputy*turntosin[turncos]);
  2967.                 plalatchx[player]+=newx;
  2968.                 plalatchy[player]+=newy;
  2969.             }
  2970.             // Read buttons
  2971.             if(control_joyb_is_pressed(JOB_JUMP))
  2972.                 plalatchbutton[player] |= LATCHBUTTONJUMP;
  2973.             if(control_joyb_is_pressed(JOB_LEFT_USE))
  2974.                 plalatchbutton[player] |= LATCHBUTTONLEFT;
  2975.             if(control_joyb_is_pressed(JOB_LEFT_GET))
  2976.                 plalatchbutton[player] |= LATCHBUTTONALTLEFT;
  2977.             if(control_joyb_is_pressed(JOB_LEFT_PACK))
  2978.                 plalatchbutton[player] |= LATCHBUTTONPACKLEFT;
  2979.             if(control_joyb_is_pressed(JOB_RIGHT_USE))
  2980.                 plalatchbutton[player] |= LATCHBUTTONRIGHT;
  2981.             if(control_joyb_is_pressed(JOB_RIGHT_GET))
  2982.                 plalatchbutton[player] |= LATCHBUTTONALTRIGHT;
  2983.             if(control_joyb_is_pressed(JOB_RIGHT_PACK))
  2984.                 plalatchbutton[player] |= LATCHBUTTONPACKRIGHT;
  2985.         }
  2986.  
  2987.         // Keyboard routines
  2988.         if((device & INPUTKEY) && keyon)
  2989.         {
  2990.             // Movement
  2991.             if(chrattachedto[character]!=MAXCHR)
  2992.             {
  2993.                 // Mounted
  2994.                 inputx = (control_key_is_pressed(KEY_RIGHT)-control_key_is_pressed(KEY_LEFT))*chrmaxaccel[chrattachedto[character]];
  2995.                 inputy = (control_key_is_pressed(KEY_DOWN)-control_key_is_pressed(KEY_UP))*chrmaxaccel[chrattachedto[character]];
  2996.             }
  2997.             else
  2998.             {
  2999.                 // Unmounted
  3000.                 inputx = (control_key_is_pressed(KEY_RIGHT)-control_key_is_pressed(KEY_LEFT))*chrmaxaccel[character];
  3001.                 inputy = (control_key_is_pressed(KEY_DOWN)-control_key_is_pressed(KEY_UP))*chrmaxaccel[character];
  3002.             }
  3003.             turnsin = (camturnleftrightone*16383);
  3004.             turnsin = turnsin&16383;
  3005.             turncos = (turnsin+4096)&16383;
  3006.             if(autoturncamera==255 && numlocalpla == 1)  inputx = 0;
  3007.             newx = (inputx*turntosin[turncos]+inputy*turntosin[turnsin]);
  3008.             newy = (-inputx*turntosin[turnsin]+inputy*turntosin[turncos]);
  3009.             plalatchx[player]+=newx;
  3010.             plalatchy[player]+=newy;
  3011.             // Read buttons
  3012.             if(control_key_is_pressed(KEY_JUMP))
  3013.                 plalatchbutton[player] |= LATCHBUTTONJUMP;
  3014.             if(control_key_is_pressed(KEY_LEFT_USE))
  3015.                 plalatchbutton[player] |= LATCHBUTTONLEFT;
  3016.             if(control_key_is_pressed(KEY_LEFT_GET))
  3017.                 plalatchbutton[player] |= LATCHBUTTONALTLEFT;
  3018.             if(control_key_is_pressed(KEY_LEFT_PACK))
  3019.                 plalatchbutton[player] |= LATCHBUTTONPACKLEFT;
  3020.             if(control_key_is_pressed(KEY_RIGHT_USE))
  3021.                 plalatchbutton[player] |= LATCHBUTTONRIGHT;
  3022.             if(control_key_is_pressed(KEY_RIGHT_GET))
  3023.                 plalatchbutton[player] |= LATCHBUTTONALTRIGHT;
  3024.             if(control_key_is_pressed(KEY_RIGHT_PACK))
  3025.                 plalatchbutton[player] |= LATCHBUTTONPACKRIGHT;
  3026.         }
  3027.     }
  3028. }
  3029.  
  3030. //--------------------------------------------------------------------------------------------
  3031. void set_local_latches(void)
  3032. {
  3033.     // ZZ> This function emulates AI thinkin' by setting latches from input devices
  3034.     int cnt;
  3035.  
  3036.     cnt = 0;
  3037.     while(cnt < MAXPLAYER)
  3038.     {
  3039.         set_one_player_latch(cnt);
  3040.         cnt++;
  3041.     }
  3042. }
  3043.  
  3044. //--------------------------------------------------------------------------------------------
  3045. void make_onwhichfan(void)
  3046. {
  3047.     // ZZ> This function figures out which fan characters are on and sets their level
  3048.     unsigned short character;
  3049.     int x, y, ripand, distance;
  3050.     //int volume;
  3051.     float level;
  3052.  
  3053.  
  3054.  
  3055.  
  3056.     // First figure out which fan each character is in
  3057.     character = 0;
  3058.     while(character < MAXCHR)
  3059.     {
  3060.         if(chron[character] && (!chrinpack[character]))
  3061.         {
  3062.             x = chrxpos[character];
  3063.             y = chrypos[character];
  3064.             x = x>>7;
  3065.             y = y>>7;
  3066.             chronwhichfan[character] = meshfanstart[y]+x;
  3067.         }
  3068.         character++;
  3069.     }
  3070.  
  3071.     // Get levels every update
  3072.     character = 0;
  3073.     while(character < MAXCHR)
  3074.     {
  3075.         if(chron[character] && (!chrinpack[character]))
  3076.         {
  3077.             level = get_level(chrxpos[character], chrypos[character], chronwhichfan[character], chrwaterwalk[character])+RAISE;
  3078.             if(chralive[character])
  3079.             {
  3080.                 if(meshfx[chronwhichfan[character]]&MESHFXDAMAGE && chrzpos[character]<=chrlevel[character]+DAMAGERAISE && chrattachedto[character]==MAXCHR)
  3081.                 {
  3082.                     if((chrdamagemodifier[character][damagetiletype]&DAMAGESHIFT) != 3 && !chrinvictus[character]) // 3 means they're pretty well immune
  3083.                     {
  3084.                         distance = ABS(camtrackx-chrxpos[character])+ABS(camtracky-chrypos[character]);
  3085.                         if(distance < damagetilemindistance)
  3086.                         {
  3087.                            damagetilemindistance = distance;
  3088.                         }
  3089.                         if(distance < damagetilemindistance + 256)
  3090.                         {
  3091.                            damagetilesoundtime = 0;
  3092.                         }
  3093.                         if(chrdamagetime[character] == 0)
  3094.                         {
  3095.                             damage_character(character, 32768, damagetileamount, 1, damagetiletype, DAMAGETEAM, chrbumplast[character], DAMFXBLOC|DAMFXARMO);
  3096.                             chrdamagetime[character] = DAMAGETILETIME;
  3097.                         }
  3098.                         if(damagetileparttype != -1 && (wldframe&damagetilepartand)==0)
  3099.                         {
  3100.                             spawn_one_particle(chrxpos[character], chrypos[character], chrzpos[character],
  3101.                                                0, MAXMODEL, damagetileparttype, MAXCHR, SPAWNLAST, NULLTEAM, MAXCHR, 0, MAXCHR);
  3102.                         }
  3103.                     }
  3104.                     if(chrreaffirmdamagetype[character]==damagetiletype)
  3105.                     {
  3106.                         if((wldframe&TILEREAFFIRMAND)==0)
  3107.                             reaffirm_attached_particles(character);
  3108.                     }
  3109.                 }
  3110.             }
  3111.             if(chrzpos[character] < watersurfacelevel && (meshfx[chronwhichfan[character]]&MESHFXWATER))
  3112.             {
  3113.                 if(chrinwater[character]==FALSE)
  3114.                 {
  3115.                     // Splash
  3116.                     if(chrattachedto[character]==MAXCHR)
  3117.                     {
  3118.                         spawn_one_particle(chrxpos[character], chrypos[character], watersurfacelevel+RAISE,
  3119.                                            0, MAXMODEL, SPLASH, MAXCHR, SPAWNLAST, NULLTEAM, MAXCHR, 0, MAXCHR);
  3120.                     }
  3121.                     chrinwater[character] = TRUE;
  3122.                     if(wateriswater)
  3123.                     {
  3124.                         chralert[character]|=ALERTIFINWATER;
  3125.                     }
  3126.                 }
  3127.                 else
  3128.                 {
  3129.                     if(chrzpos[character]>watersurfacelevel-RIPPLETOLERANCE && capripple[chrmodel[character]])
  3130.                     {
  3131.                         // Ripples
  3132.                         ripand = ((int)chrxvel[character]!=0)|((int)chryvel[character]!=0);
  3133.                         ripand = RIPPLEAND>>ripand;
  3134.                         if((wldframe&ripand)==0&&chrzpos[character]<watersurfacelevel&&chralive[character])
  3135.                         {
  3136.                             spawn_one_particle(chrxpos[character], chrypos[character], watersurfacelevel,
  3137.                                                0, MAXMODEL, RIPPLE, MAXCHR, SPAWNLAST, NULLTEAM, MAXCHR, 0, MAXCHR);
  3138.                         }
  3139.                     }
  3140.                     if(wateriswater && (wldframe&7) == 0)
  3141.                     {
  3142.                         chrjumpready[character] = TRUE;
  3143.                         chrjumpnumber[character]=1; //chrjumpnumberreset[character];
  3144.                     }
  3145.                 }
  3146.                 chrxvel[character]=chrxvel[character]*waterfriction;
  3147.                 chryvel[character]=chryvel[character]*waterfriction;
  3148.                 chrzvel[character]=chrzvel[character]*waterfriction;
  3149.             }
  3150.             else
  3151.             {
  3152.                 chrinwater[character] = FALSE;
  3153.             }
  3154.             chrlevel[character] = level;
  3155.         }
  3156.         character++;
  3157.     }
  3158.  
  3159.  
  3160.     // Play the damage tile sound
  3161.     if(damagetilesound >= 0)
  3162.     {
  3163.         if((wldframe & 3)==0)
  3164.         {
  3165.             // Change the volume...
  3166. /*PORT
  3167.             volume = -(damagetilemindistance + (damagetilesoundtime<<8));
  3168.             volume = volume<<VOLSHIFT;
  3169.             if(volume > VOLMIN)
  3170.             {
  3171.                 lpDSBuffer[damagetilesound]->SetVolume(volume);
  3172.             }
  3173.             if(damagetilesoundtime < TILESOUNDTIME)  damagetilesoundtime++;
  3174.             else damagetilemindistance = 9999;
  3175. */
  3176.         }
  3177.     }
  3178. }
  3179.  
  3180. //--------------------------------------------------------------------------------------------
  3181. void bump_characters(void)
  3182. {
  3183.     // ZZ> This function sets handles characters hitting other characters or particles
  3184.     unsigned short character, particle, entry, pip, direction;
  3185.     unsigned int chara, charb, fanblock, prtidparent, prtidtype, chridvulnerability, eveidremove;
  3186.     signed char hide;
  3187.     int cnt, tnc, dist, chrinblock, prtinblock, enchant, temp;
  3188.     float xa, ya, za, xb, yb, zb;
  3189.     float ax, ay, nx, ny, scale;  // For deflection
  3190.     unsigned short facing;
  3191.  
  3192.  
  3193.     // Clear the lists
  3194.     fanblock = 0;
  3195.     while(fanblock < numfanblock)
  3196.     {
  3197.         meshbumplistchrnum[fanblock] = 0;
  3198.         meshbumplistprtnum[fanblock] = 0;
  3199.         fanblock++;
  3200.     }
  3201.  
  3202.  
  3203.  
  3204.     // Fill 'em back up
  3205.     character = 0;
  3206.     while(character < MAXCHR)
  3207.     {
  3208.         if(chron[character]&&(!chrinpack[character])&&(chrattachedto[character]==MAXCHR||chrreaffirmdamagetype[character]!=DAMAGENULL))
  3209.         {
  3210.             hide = caphidestate[chrmodel[character]];
  3211.             if(hide == NOHIDE || hide != chraistate[character])
  3212.             {
  3213.                 chrholdingweight[character] = 0;
  3214.                 fanblock = (((int)chrxpos[character])>>9)+meshblockstart[((int)chrypos[character])>>9];
  3215.                 // Insert before any other characters on the block
  3216.                 entry = meshbumplistchr[fanblock];
  3217.                 chrbumpnext[character] = entry;
  3218.                 meshbumplistchr[fanblock] = character;
  3219.                 meshbumplistchrnum[fanblock]++;
  3220.             }
  3221.         }
  3222.         character++;
  3223.     }
  3224.     particle = 0;
  3225.     while(particle < MAXPRT)
  3226.     {
  3227.         if(prton[particle]&&prtbumpsize[particle])
  3228.         {
  3229.             fanblock = (((int)prtxpos[particle])>>9)+meshblockstart[((int)prtypos[particle])>>9];
  3230.             // Insert before any other particles on the block
  3231.             entry = meshbumplistprt[fanblock];
  3232.             prtbumpnext[particle] = entry;
  3233.             meshbumplistprt[fanblock] = particle;
  3234.             meshbumplistprtnum[fanblock]++;
  3235.         }
  3236.         particle++;
  3237.     }
  3238.  
  3239.  
  3240.  
  3241.     // Check collisions with other characters and bump particles
  3242.     // Only check each pair once
  3243.     fanblock = 0;
  3244.     while(fanblock < numfanblock)
  3245.     {
  3246.         chara = meshbumplistchr[fanblock];
  3247.         chrinblock = meshbumplistchrnum[fanblock];
  3248.         prtinblock = meshbumplistprtnum[fanblock];
  3249.         cnt = 0;
  3250.         while(cnt < chrinblock)
  3251.         {
  3252.             xa = chrxpos[chara];
  3253.             ya = chrypos[chara];
  3254.             za = chrzpos[chara];
  3255.             chridvulnerability = capidsz[chrmodel[chara]][IDSZVULNERABILITY];
  3256.             // Don't let items bump
  3257.             if(chrbumpheight[chara])//chrisitem[chara]==FALSE)
  3258.             {
  3259.                 charb = chrbumpnext[chara];  // Don't collide with self
  3260.                 tnc = cnt+1;
  3261.                 while(tnc < chrinblock)
  3262.                 {
  3263.                     if(chrbumpheight[charb])//chrisitem[charb]==FALSE)
  3264.                     {
  3265.                         xb = chrxpos[charb];
  3266.                         yb = chrypos[charb];
  3267.                         zb = chrzpos[charb];
  3268.                         // First check absolute value diamond
  3269.                         xb = ABS(xa-xb);
  3270.                         yb = ABS(ya-yb);
  3271.                         dist = xb+yb;
  3272.                         if(dist < chrbumpsizebig[chara] || dist < chrbumpsizebig[charb])
  3273.                         {
  3274.                             // Then check bounding box square...  Square+Diamond=Octagon
  3275.                             if((xb<chrbumpsize[chara] || xb<chrbumpsize[charb])&&
  3276.                             (yb<chrbumpsize[chara] || yb<chrbumpsize[charb]))
  3277.                             {
  3278.                                // Pretend that they collided
  3279.                                 chrbumplast[chara]=charb;
  3280.                                 chrbumplast[charb]=chara;
  3281.                                 // Now see if either is on top the other like a platform
  3282.                                 if(za>zb+chrbumpheight[charb]-PLATTOLERANCE+chrzvel[chara]-chrzvel[charb]&&(capcanuseplatforms[chrmodel[chara]]||za>zb+chrbumpheight[charb]))
  3283.                                 {
  3284.                                     // Is A falling on B?
  3285.                                     if(za<zb+chrbumpheight[charb]&&chrplatform[charb])//&&chrflyheight[chara]==0)
  3286.                                     {
  3287.                                         // A is inside, coming from above
  3288.                                         chrzpos[chara]=(chrzpos[chara])*PLATKEEP+(chrzpos[charb]+chrbumpheight[charb]+PLATADD)*PLATASCEND;
  3289.                                         chrxvel[chara]+=(chrxvel[charb])*platstick;
  3290.                                         chryvel[chara]+=(chryvel[charb])*platstick;
  3291.                                         if(chrzvel[chara]<chrzvel[charb])
  3292.                                             chrzvel[chara]=chrzvel[charb];
  3293.                                         chrturnleftright[chara]+=(chrturnleftright[charb]-chroldturn[charb]);
  3294.                                         chrjumpready[chara]=TRUE;
  3295.                                         chrjumpnumber[chara]=chrjumpnumberreset[chara];
  3296.                                         chrholdingweight[charb]=chrweight[chara];
  3297.                                     }
  3298.                                 }
  3299.                                 else
  3300.                                 {
  3301.                                     if(zb>za+chrbumpheight[chara]-PLATTOLERANCE+chrzvel[charb]-chrzvel[chara]&&(capcanuseplatforms[chrmodel[charb]]||zb>za+chrbumpheight[chara]))
  3302.                                     {
  3303.                                         // Is B falling on A?
  3304.                                         if(zb<za+chrbumpheight[chara]&&chrplatform[chara])//&&chrflyheight[charb]==0)
  3305.                                         {
  3306.                                             // B is inside, coming from above
  3307.                                             chrzpos[charb]=(chrzpos[charb])*PLATKEEP+(chrzpos[chara]+chrbumpheight[chara]+PLATADD)*PLATASCEND;
  3308.                                             chrxvel[charb]+=(chrxvel[chara])*platstick;
  3309.                                             chryvel[charb]+=(chryvel[chara])*platstick;
  3310.                                             if(chrzvel[charb]<chrzvel[chara])
  3311.                                                 chrzvel[charb]=chrzvel[chara];
  3312.                                             chrturnleftright[charb]+=(chrturnleftright[chara]-chroldturn[chara]);
  3313.                                             chrjumpready[charb]=TRUE;
  3314.                                             chrjumpnumber[charb]=chrjumpnumberreset[charb];
  3315.                                             chrholdingweight[chara]=chrweight[charb];
  3316.                                         }
  3317.                                     }
  3318.                                     else
  3319.                                     {
  3320.                                         // They are inside each other, which ain't good
  3321.                                         // Only collide if moving toward the other
  3322.                                         if(chrxvel[chara]>0)
  3323.                                         {
  3324.                                             if(chrxpos[chara]<chrxpos[charb]) { chrxvel[charb]+=chrxvel[chara]*chrbumpdampen[charb];  chrxvel[chara]=-chrxvel[chara]*chrbumpdampen[chara];  chrxpos[chara]=chroldx[chara]; }
  3325.                                         }
  3326.                                         else
  3327.                                         {
  3328.                                             if(chrxpos[chara]>chrxpos[charb]) { chrxvel[charb]+=chrxvel[chara]*chrbumpdampen[charb];  chrxvel[chara]=-chrxvel[chara]*chrbumpdampen[chara];  chrxpos[chara]=chroldx[chara]; }
  3329.                                         }
  3330.                                         if(chryvel[chara]>0)
  3331.                                         {
  3332.                                             if(chrypos[chara]<chrypos[charb]) { chryvel[charb]+=chryvel[chara]*chrbumpdampen[charb];  chryvel[chara]=-chryvel[chara]*chrbumpdampen[chara];  chrypos[chara]=chroldy[chara]; }
  3333.                                         }
  3334.                                         else
  3335.                                         {
  3336.                                             if(chrypos[chara]>chrypos[charb]) { chryvel[charb]+=chryvel[chara]*chrbumpdampen[charb];  chryvel[chara]=-chryvel[chara]*chrbumpdampen[chara];  chrypos[chara]=chroldy[chara]; }
  3337.                                         }
  3338.                                         if(chrxvel[charb]>0)
  3339.                                         {
  3340.                                             if(chrxpos[charb]<chrxpos[chara]) { chrxvel[chara]+=chrxvel[charb]*chrbumpdampen[chara];  chrxvel[charb]=-chrxvel[charb]*chrbumpdampen[charb];  chrxpos[charb]=chroldx[charb]; }
  3341.                                         }
  3342.                                         else
  3343.                                         {
  3344.                                             if(chrxpos[charb]>chrxpos[chara]) { chrxvel[chara]+=chrxvel[charb]*chrbumpdampen[chara];  chrxvel[charb]=-chrxvel[charb]*chrbumpdampen[charb];  chrxpos[charb]=chroldx[charb]; }
  3345.                                         }
  3346.                                         if(chryvel[charb]>0)
  3347.                                         {
  3348.                                             if(chrypos[charb]<chrypos[chara]) { chryvel[chara]+=chryvel[charb]*chrbumpdampen[chara];  chryvel[charb]=-chryvel[charb]*chrbumpdampen[charb];  chrypos[charb]=chroldy[charb]; }
  3349.                                         }
  3350.                                         else
  3351.                                         {
  3352.                                             if(chrypos[charb]>chrypos[chara]) { chryvel[chara]+=chryvel[charb]*chrbumpdampen[chara];  chryvel[charb]=-chryvel[charb]*chrbumpdampen[charb];  chrypos[charb]=chroldy[charb]; }
  3353.                                         }
  3354.                                         xa=chrxpos[chara];
  3355.                                         ya=chrypos[chara];
  3356.                                         chralert[chara]=chralert[chara]|ALERTIFBUMPED;
  3357.                                         chralert[charb]=chralert[charb]|ALERTIFBUMPED;
  3358.                                     }
  3359.                                 }
  3360.                             }
  3361.                         }
  3362.                     }
  3363.                     charb = chrbumpnext[charb];
  3364.                     tnc++;
  3365.                 }
  3366.                 // Now double check the last character we bumped into, in case it's a platform
  3367.                 charb = chrbumplast[chara];
  3368.                 if(chron[charb]&&(!chrinpack[charb])&&charb!=chara&&chrattachedto[charb]==MAXCHR&&chrbumpheight[chara]&&chrbumpheight[charb])
  3369.                 {
  3370.                     xb = chrxpos[charb];
  3371.                     yb = chrypos[charb];
  3372.                     zb = chrzpos[charb];
  3373.                     // First check absolute value diamond
  3374.                     xb = ABS(xa-xb);
  3375.                     yb = ABS(ya-yb);
  3376.                     dist = xb+yb;
  3377.                     if(dist < chrbumpsizebig[chara] || dist < chrbumpsizebig[charb])
  3378.                     {
  3379.                         // Then check bounding box square...  Square+Diamond=Octagon
  3380.                         if((xb<chrbumpsize[chara] || xb<chrbumpsize[charb])&&
  3381.                            (yb<chrbumpsize[chara] || yb<chrbumpsize[charb]))
  3382.                         {
  3383.                             // Now see if either is on top the other like a platform
  3384.                             if(za>zb+chrbumpheight[charb]-PLATTOLERANCE+chrzvel[chara]-chrzvel[charb]&&(capcanuseplatforms[chrmodel[chara]]||za>zb+chrbumpheight[charb]))
  3385.                             {
  3386.                                 // Is A falling on B?
  3387.                                 if(za<zb+chrbumpheight[charb]&&chrplatform[charb]&&chralive[chara])//&&chrflyheight[chara]==0)
  3388.                                 {
  3389.                                     // A is inside, coming from above
  3390.                                     chrzpos[chara]=(chrzpos[chara])*PLATKEEP+(chrzpos[charb]+chrbumpheight[charb]+PLATADD)*PLATASCEND;
  3391.                                     chrxvel[chara]+=(chrxvel[charb])*platstick;
  3392.                                     chryvel[chara]+=(chryvel[charb])*platstick;
  3393.                                     if(chrzvel[chara]<chrzvel[charb])
  3394.                                         chrzvel[chara]=chrzvel[charb];
  3395.                                     chrturnleftright[chara]+=(chrturnleftright[charb]-chroldturn[charb]);
  3396.                                     chrjumpready[chara]=TRUE;
  3397.                                     chrjumpnumber[chara]=chrjumpnumberreset[chara];
  3398.                                     if(madactionvalid[chrmodel[chara]][ACTIONMI]&&chralive[chara]&&chralive[charb]&&chrismount[charb]&&chrisitem[chara]==FALSE&&chrholdingwhich[charb][0]==MAXCHR&&chrattachedto[chara]==MAXCHR&&chrjumptime[chara]==0&&chrflyheight[chara]==0)
  3399.                                     {
  3400.                                         attach_character_to_mount(chara, charb, GRIPONLY);
  3401.                                         chrbumplast[chara]=chara;
  3402.                                         chrbumplast[charb]=charb;
  3403.                                     }
  3404.                                     chrholdingweight[charb]=chrweight[chara];
  3405.                                 }
  3406.                             }
  3407.                             else
  3408.                             {
  3409.                                 if(zb>za+chrbumpheight[chara]-PLATTOLERANCE+chrzvel[charb]-chrzvel[chara]&&(capcanuseplatforms[chrmodel[charb]]||zb>za+chrbumpheight[chara]))
  3410.                                 {
  3411.                                     // Is B falling on A?
  3412.                                     if(zb<za+chrbumpheight[chara]&&chrplatform[chara]&&chralive[charb])//&&chrflyheight[charb]==0)
  3413.                                     {
  3414.                                         // B is inside, coming from above
  3415.                                         chrzpos[charb]=(chrzpos[charb])*PLATKEEP+(chrzpos[chara]+chrbumpheight[chara]+PLATADD)*PLATASCEND;
  3416.                                         chrxvel[charb]+=(chrxvel[chara])*platstick;
  3417.                                         chryvel[charb]+=(chryvel[chara])*platstick;
  3418.                                         if(chrzvel[charb]<chrzvel[chara])
  3419.                                             chrzvel[charb]=chrzvel[chara];
  3420.                                         chrturnleftright[charb]+=(chrturnleftright[chara]-chroldturn[chara]);
  3421.                                         chrjumpready[charb]=TRUE;
  3422.                                         chrjumpnumber[charb]=chrjumpnumberreset[charb];
  3423.                                         if(madactionvalid[chrmodel[charb]][ACTIONMI]&&chralive[chara]&&chralive[charb]&&chrismount[chara]&&chrisitem[charb]==FALSE&&chrholdingwhich[chara][0]==MAXCHR&&chrattachedto[charb]==MAXCHR&&chrjumptime[charb]==0&&chrflyheight[charb]==0)
  3424.                                         {
  3425.                                             attach_character_to_mount(charb, chara, GRIPONLY);
  3426.                                             chrbumplast[chara]=chara;
  3427.                                             chrbumplast[charb]=charb;
  3428.                                         }
  3429.                                         chrholdingweight[chara]=chrweight[charb];
  3430.                                     }
  3431.                                 }
  3432.                                 else
  3433.                                 {
  3434.                                     // They are inside each other, which ain't good
  3435.                                     // Only collide if moving toward the other
  3436.                                     if(chrxvel[chara]>0)
  3437.                                     {
  3438.                                         if(chrxpos[chara]<chrxpos[charb]) { chrxvel[charb]+=chrxvel[chara]*chrbumpdampen[charb];  chrxvel[chara]=-chrxvel[chara]*chrbumpdampen[chara];  chrxpos[chara]=chroldx[chara]; }
  3439.                                     }
  3440.                                     else
  3441.                                     {
  3442.                                         if(chrxpos[chara]>chrxpos[charb]) { chrxvel[charb]+=chrxvel[chara]*chrbumpdampen[charb];  chrxvel[chara]=-chrxvel[chara]*chrbumpdampen[chara];  chrxpos[chara]=chroldx[chara]; }
  3443.                                     }
  3444.                                     if(chryvel[chara]>0)
  3445.                                     {
  3446.                                         if(chrypos[chara]<chrypos[charb]) { chryvel[charb]+=chryvel[chara]*chrbumpdampen[charb];  chryvel[chara]=-chryvel[chara]*chrbumpdampen[chara];  chrypos[chara]=chroldy[chara]; }
  3447.                                     }
  3448.                                     else
  3449.                                     {
  3450.                                         if(chrypos[chara]>chrypos[charb]) { chryvel[charb]+=chryvel[chara]*chrbumpdampen[charb];  chryvel[chara]=-chryvel[chara]*chrbumpdampen[chara];  chrypos[chara]=chroldy[chara]; }
  3451.                                     }
  3452.                                     if(chrxvel[charb]>0)
  3453.                                     {
  3454.                                         if(chrxpos[charb]<chrxpos[chara]) { chrxvel[chara]+=chrxvel[charb]*chrbumpdampen[chara];  chrxvel[charb]=-chrxvel[charb]*chrbumpdampen[charb];  chrxpos[charb]=chroldx[charb]; }
  3455.                                     }
  3456.                                     else
  3457.                                     {
  3458.                                         if(chrxpos[charb]>chrxpos[chara]) { chrxvel[chara]+=chrxvel[charb]*chrbumpdampen[chara];  chrxvel[charb]=-chrxvel[charb]*chrbumpdampen[charb];  chrxpos[charb]=chroldx[charb]; }
  3459.                                     }
  3460.                                     if(chryvel[charb]>0)
  3461.                                     {
  3462.                                         if(chrypos[charb]<chrypos[chara]) { chryvel[chara]+=chryvel[charb]*chrbumpdampen[chara];  chryvel[charb]=-chryvel[charb]*chrbumpdampen[charb];  chrypos[charb]=chroldy[charb]; }
  3463.                                     }
  3464.                                     else
  3465.                                     {
  3466.                                         if(chrypos[charb]>chrypos[chara]) { chryvel[chara]+=chryvel[charb]*chrbumpdampen[chara];  chryvel[charb]=-chryvel[charb]*chrbumpdampen[charb];  chrypos[charb]=chroldy[charb]; }
  3467.                                     }
  3468.                                     xa=chrxpos[chara];
  3469.                                     ya=chrypos[chara];
  3470.                                     chralert[chara]=chralert[chara]|ALERTIFBUMPED;
  3471.                                     chralert[charb]=chralert[charb]|ALERTIFBUMPED;
  3472.                                 }
  3473.                             }
  3474.                         }
  3475.                     }
  3476.                 }
  3477.             }
  3478.             // Now check collisions with every bump particle in same area
  3479.             if(chralive[chara])
  3480.             {
  3481.                 particle = meshbumplistprt[fanblock];
  3482.                 tnc = 0;
  3483.                 while(tnc < prtinblock)
  3484.                 {
  3485.                     xb = prtxpos[particle];
  3486.                     yb = prtypos[particle];
  3487.                     zb = prtzpos[particle];
  3488.                     // First check absolute value diamond
  3489.                     xb = ABS(xa-xb);
  3490.                     yb = ABS(ya-yb);
  3491.                     dist = xb+yb;
  3492.                     if(dist < chrbumpsizebig[chara] || dist < prtbumpsizebig[particle])
  3493.                     {
  3494.                         // Then check bounding box square...  Square+Diamond=Octagon
  3495.                         if((xb<chrbumpsize[chara]  ||xb<prtbumpsize[particle])&&
  3496.                            (yb<chrbumpsize[chara]  ||yb<prtbumpsize[particle])&&
  3497.                            (zb>za-prtbumpheight[particle]&&zb<za+chrbumpheight[chara]+prtbumpheight[particle]))
  3498.                         {
  3499.                             pip = prtpip[particle];
  3500.                             if(zb>za+chrbumpheight[chara]+prtzvel[particle]&&prtzvel[particle]<0&&chrplatform[chara]&&prtattachedtocharacter[particle]==MAXCHR)
  3501.                             {
  3502.                                 // Particle is falling on A
  3503.                                 prtzpos[particle]=za+chrbumpheight[chara];
  3504.                                 prtzvel[particle]=-prtzvel[particle]*pipdampen[pip];
  3505.                                 prtxvel[particle]+=(chrxvel[chara])*platstick;
  3506.                                 prtyvel[particle]+=(chryvel[chara])*platstick;
  3507.                             }
  3508.                             // Check reaffirmation of particles
  3509.                             if(prtattachedtocharacter[particle]!=chara)
  3510.                             {
  3511.                                 if(chrreloadtime[chara]==0)
  3512.                                 {
  3513.                                     if(chrreaffirmdamagetype[chara]==prtdamagetype[particle]&&chrdamagetime[chara]==0)
  3514.                                     {
  3515.                                         reaffirm_attached_particles(chara);
  3516.                                     }
  3517.                                 }
  3518.                             }
  3519.                             // Check for missile treatment
  3520.                             if((chrdamagemodifier[chara][prtdamagetype[particle]]&3) < 2 ||
  3521.                                chrmissiletreatment[chara] == MISNORMAL ||
  3522.                                prtattachedtocharacter[particle] != MAXCHR ||
  3523.                                (prtchr[particle] == chara && pipfriendlyfire[pip]==FALSE) ||
  3524.                                (chrmana[chrmissilehandler[chara]] < (chrmissilecost[chara]<<4) && chrcanchannel[chrmissilehandler[chara]] == FALSE))
  3525.                             {
  3526.                                 if((teamhatesteam[prtteam[particle]][chrteam[chara]]||(pipfriendlyfire[pip]&&((chara!=prtchr[particle]&&chara!=chrattachedto[prtchr[particle]])||piponlydamagefriendly[pip])))&&chrinvictus[chara]==FALSE)
  3527.                                 {
  3528.                                     spawn_bump_particles(chara, particle); // Catch on fire
  3529.                                     if((prtdamagebase[particle]|prtdamagerand[particle])>1)
  3530.                                     {
  3531.                                         prtidparent = capidsz[prtmodel[particle]][IDSZPARENT];
  3532.                                         prtidtype = capidsz[prtmodel[particle]][IDSZTYPE];
  3533.                                         if(chrdamagetime[chara]==0 && prtattachedtocharacter[particle]!=chara && (pipdamfx[pip]&DAMFXARRO) == 0)
  3534.                                         {
  3535.                                             // Normal particle damage
  3536.                                             if(pipallowpush[pip])
  3537.                                             {
  3538.                                                 chrxvel[chara]=prtxvel[particle]*chrbumpdampen[chara];
  3539.                                                 chryvel[chara]=prtyvel[particle]*chrbumpdampen[chara];
  3540.                                                 chrzvel[chara]=prtzvel[particle]*chrbumpdampen[chara];
  3541.                                             }
  3542.                                             direction = (atan2(prtyvel[particle], prtxvel[particle])+PI)*65535/(2*PI);
  3543.                                             direction = chrturnleftright[chara]-direction+32768;
  3544.                                             // Check all enchants to see if they are removed
  3545.                                             enchant = chrfirstenchant[chara];
  3546.                                             while(enchant != MAXENCHANT)
  3547.                                             {
  3548.                                                 eveidremove = everemovedbyidsz[enceve[enchant]];
  3549.                                                 temp = encnextenchant[enchant];
  3550.                                                 if(eveidremove != IDSZNONE && (eveidremove == prtidtype || eveidremove == prtidparent))
  3551.                                                 {
  3552.                                                     remove_enchant(enchant);
  3553.                                                 }
  3554.                                                 enchant = temp;
  3555.                                             }
  3556.                                             // Damage the character
  3557.                                             if(chridvulnerability != IDSZNONE && (chridvulnerability == prtidtype || chridvulnerability == prtidparent))
  3558.                                             {
  3559.                                                 damage_character(chara, direction, prtdamagebase[particle]<<1, prtdamagerand[particle]<<1, prtdamagetype[particle], prtteam[particle], prtchr[particle], pipdamfx[pip]);
  3560.                                                 chralert[chara]|=ALERTIFHITVULNERABLE;
  3561.                                             }
  3562.                                             else
  3563.                                             {
  3564.                                                 damage_character(chara, direction, prtdamagebase[particle], prtdamagerand[particle], prtdamagetype[particle], prtteam[particle], prtchr[particle], pipdamfx[pip]);
  3565.                                             }
  3566.                                             // Do confuse effects
  3567.                                             if((madframefx[chrframe[chara]]&MADFXINVICTUS)==FALSE || pipdamfx[pip]&DAMFXBLOC)
  3568.                                             {
  3569.                                                 if(pipgrogtime[pip] != 0 && capcanbegrogged[chrmodel[chara]])
  3570.                                                 {
  3571.                                                     chrgrogtime[chara]+=pipgrogtime[pip];
  3572.                                                     if(chrgrogtime[chara]<0)  chrgrogtime[chara] = 32767;
  3573.                                                     chralert[chara] = chralert[chara]|ALERTIFGROGGED;
  3574.                                                 }
  3575.                                                 if(pipdazetime[pip] != 0 && capcanbedazed[chrmodel[chara]])
  3576.                                                 {
  3577.                                                     chrdazetime[chara]+=pipdazetime[pip];
  3578.                                                     if(chrdazetime[chara]<0)  chrdazetime[chara] = 32767;
  3579.                                                     chralert[chara] = chralert[chara]|ALERTIFDAZED;
  3580.                                                 }
  3581.                                             }
  3582.                                             // Notify the attacker of a scored hit
  3583.                                             if(prtchr[particle]!=MAXCHR)
  3584.                                             {
  3585.                                                 chralert[prtchr[particle]]=chralert[prtchr[particle]]|ALERTIFSCOREDAHIT;
  3586.                                                 chrhitlast[prtchr[particle]]=chara;
  3587.                                             }
  3588.                                         }
  3589.                                         if((wldframe&31)==0 && prtattachedtocharacter[particle]==chara)
  3590.                                         {
  3591.                                             // Attached particle damage ( Burning )
  3592.                                             if(pipxyvelbase[pip]==0)
  3593.                                             {
  3594.                                                 // Make character limp
  3595.                                                 chrxvel[chara]=0;
  3596.                                                 chryvel[chara]=0;
  3597.                                             }
  3598.                                             damage_character(chara, 32768, prtdamagebase[particle], prtdamagerand[particle], prtdamagetype[particle], prtteam[particle], prtchr[particle], pipdamfx[pip]);
  3599.                                         }
  3600.                                     }
  3601.                                     if(pipendbump[pip])
  3602.                                     {
  3603.                                         if(pipbumpmoney[pip])
  3604.                                         {
  3605.                                             if(chrcangrabmoney[chara]&&chralive[chara]&&chrdamagetime[chara]==0)
  3606.                                             {
  3607.                                                 if(chrismount[chara])
  3608.                                                 {
  3609.                                                     // Let mounts collect money for their riders
  3610.                                                     if(chrholdingwhich[chara][0] != MAXCHR)
  3611.                                                     {
  3612.                                                         chrmoney[chrholdingwhich[chara][0]]+=pipbumpmoney[pip];
  3613.                                                         if(chrmoney[chrholdingwhich[chara][0]] > MAXMONEY) chrmoney[chrholdingwhich[chara][0]] = 0;
  3614.                                                         if(chrmoney[chrholdingwhich[chara][0]] < 0) chrmoney[chrholdingwhich[chara][0]] = 0;
  3615.                                                         prttime[particle]=1;
  3616.                                                     }
  3617.                                                 }
  3618.                                                 else
  3619.                                                 {
  3620.                                                     // Normal money collection
  3621.                                                     chrmoney[chara]+=pipbumpmoney[pip];
  3622.                                                     if(chrmoney[chara] > MAXMONEY) chrmoney[chara] = 0;
  3623.                                                     if(chrmoney[chara] < 0) chrmoney[chara] = 0;
  3624.                                                     prttime[particle]=1;
  3625.                                                 }
  3626.                                             }
  3627.                                         }
  3628.                                         else
  3629.                                         {
  3630.                                             prttime[particle]=1;
  3631.                                             // Only hit one character, not several
  3632.                                             prtdamagebase[particle] = 0;
  3633.                                             prtdamagerand[particle] = 1;
  3634.                                         }
  3635.                                     }
  3636.                                 }
  3637.                             }
  3638.                             else
  3639.                             {
  3640.                                 if(prtchr[particle] != chara)
  3641.                                 {
  3642.                                     cost_mana(chrmissilehandler[chara], (chrmissilecost[chara]<<4), prtchr[particle]);
  3643.                                     // Treat the missile
  3644.                                     if(chrmissiletreatment[chara] == MISDEFLECT)
  3645.                                     {
  3646.                                         // Use old position to find normal
  3647.                                         ax = prtxpos[particle] - prtxvel[particle];
  3648.                                         ay = prtypos[particle] - prtyvel[particle];
  3649.                                         ax = chrxpos[chara] - ax;
  3650.                                         ay = chrypos[chara] - ay;
  3651.                                         // Find size of normal
  3652.                                         scale = ax*ax + ay*ay;
  3653.                                         if(scale > 0)
  3654.                                         {
  3655.                                             // Make the normal a unit normal
  3656.                                             scale = sqrt(scale);
  3657.                                             nx = ax/scale;
  3658.                                             ny = ay/scale;
  3659.                                             // Deflect the incoming ray off the normal
  3660.                                             scale = (prtxvel[particle]*nx + prtyvel[particle]*ny)*2;
  3661.                                             ax = scale*nx;
  3662.                                             ay = scale*ny;
  3663.                                             prtxvel[particle] = prtxvel[particle] - ax;
  3664.                                             prtyvel[particle] = prtyvel[particle] - ay;
  3665.                                         }
  3666.                                     }
  3667.                                     else
  3668.                                     {
  3669.                                         // Reflect it back in the direction it came
  3670.                                         prtxvel[particle] = -prtxvel[particle];
  3671.                                         prtyvel[particle] = -prtyvel[particle];
  3672.                                     }
  3673.                                     // Change the owner of the missile
  3674.                                     if(piphoming[pip] == FALSE)
  3675.                                     {
  3676.                                         prtteam[particle] = chrteam[chara];
  3677.                                         prtchr[particle] = chara;
  3678.                                     }
  3679.                                     // Change the direction of the particle
  3680.                                     if(piprotatetoface[pip])
  3681.                                     {
  3682.                                         // Turn to face new direction
  3683.                                         facing = atan2(prtyvel[particle], prtxvel[particle])*65535/(2*PI);
  3684.                                         facing+=32768;
  3685.                                         prtfacing[particle] = facing;
  3686.                                     }
  3687.                                 }
  3688.                             }
  3689.                         }
  3690.                     }
  3691.                     particle = prtbumpnext[particle];
  3692.                     tnc++;
  3693.                 }
  3694.             }
  3695.             chara = chrbumpnext[chara];
  3696.             cnt++;
  3697.         }
  3698.         fanblock++;
  3699.     }
  3700. }
  3701.  
  3702.  
  3703. //--------------------------------------------------------------------------------------------
  3704. void stat_return()
  3705. {
  3706.     // ZZ> This function brings mana and life back
  3707.     int cnt, owner, target, eve;
  3708.  
  3709.  
  3710.     // Do reload time
  3711.     cnt = 0;
  3712.     while(cnt < MAXCHR)
  3713.     {
  3714.         if(chrreloadtime[cnt] > 0)
  3715.         {
  3716.             chrreloadtime[cnt]--;
  3717.         }
  3718.         cnt++;
  3719.     }
  3720.  
  3721.  
  3722.  
  3723.     // Do stats
  3724.     if(statclock==ONESECOND)
  3725.     {
  3726.         // Reset the clock
  3727.         statclock = 0;
  3728.  
  3729.  
  3730.         // Do all the characters
  3731.         cnt = 0;
  3732.         while(cnt < MAXCHR)
  3733.         {
  3734.             if(chron[cnt]&&(!chrinpack[cnt])&&chralive[cnt])
  3735.             {
  3736.                 chrmana[cnt]+=chrmanareturn[cnt];
  3737.                 if(chrmana[cnt] < 0)
  3738.                     chrmana[cnt] = 0;
  3739.                 if(chrmana[cnt] > chrmanamax[cnt])
  3740.                     chrmana[cnt] = chrmanamax[cnt];
  3741.                 chrlife[cnt]+=chrlifereturn[cnt];
  3742.                 if(chrlife[cnt] < 1)
  3743.                     chrlife[cnt] = 1;
  3744.                 if(chrlife[cnt] > chrlifemax[cnt])
  3745.                     chrlife[cnt] = chrlifemax[cnt];
  3746.                 if(chrgrogtime[cnt] > 0)
  3747.                 {
  3748.                     chrgrogtime[cnt]--;
  3749.                     if(chrgrogtime[cnt] < 0)
  3750.                         chrgrogtime[cnt] = 0;
  3751.                 }
  3752.                 if(chrdazetime[cnt] > 0)
  3753.                 {
  3754.                     chrdazetime[cnt]--;
  3755.                     if(chrdazetime[cnt] < 0)
  3756.                         chrdazetime[cnt] = 0;
  3757.                 }
  3758.             }
  3759.             cnt++;
  3760.         }
  3761.  
  3762.  
  3763.         // Run through all the enchants as well
  3764.         cnt = 0;
  3765.         while(cnt < MAXENCHANT)
  3766.         {
  3767.             if(encon[cnt])
  3768.             {
  3769.                 if(enctime[cnt] != 0)
  3770.                 {
  3771.                     if(enctime[cnt] > 0)
  3772.                     {
  3773.                         enctime[cnt]--;
  3774.                     }
  3775.                     owner = encowner[cnt];
  3776.                     target = enctarget[cnt];
  3777.                     eve = enceve[cnt];
  3778.  
  3779.  
  3780.                     // Do drains
  3781.                     if(chralive[owner])
  3782.                     {
  3783.                         // Change life
  3784.                         chrlife[owner]+=encownerlife[cnt];
  3785.                         if(chrlife[owner] < 1)
  3786.                         {
  3787.                             chrlife[owner] = 1;
  3788.                             kill_character(owner, target);
  3789.                         }
  3790.                         if(chrlife[owner] > chrlifemax[owner])
  3791.                         {
  3792.                             chrlife[owner] = chrlifemax[owner];
  3793.                         }
  3794.                         // Change mana
  3795.                         if(cost_mana(owner, -encownermana[cnt], target)==FALSE && eveendifcantpay[eve])
  3796.                         {
  3797.                             remove_enchant(cnt);
  3798.                         }
  3799.                     }
  3800.                     else
  3801.                     {
  3802.                         if(evestayifnoowner[eve]==FALSE)
  3803.                         {
  3804.                             remove_enchant(cnt);
  3805.                         }
  3806.                     }
  3807.                     if(encon[cnt])
  3808.                     {
  3809.                         if(chralive[target])
  3810.                         {
  3811.                             // Change life
  3812.                             chrlife[target]+=enctargetlife[cnt];
  3813.                             if(chrlife[target] < 1)
  3814.                             {
  3815.                                 chrlife[target] = 1;
  3816.                                 kill_character(target, owner);
  3817.                             }
  3818.                             if(chrlife[target] > chrlifemax[target])
  3819.                             {
  3820.                                 chrlife[target] = chrlifemax[target];
  3821.                             }
  3822.                             // Change mana
  3823.                             if(cost_mana(target, -enctargetmana[cnt], owner)==FALSE && eveendifcantpay[eve])
  3824.                             {
  3825.                                 remove_enchant(cnt);
  3826.                             }
  3827.                         }
  3828.                         else
  3829.                         {
  3830.                             remove_enchant(cnt);
  3831.                         }
  3832.                     }
  3833.                 }
  3834.                 else
  3835.                 {
  3836.                     remove_enchant(cnt);
  3837.                 }
  3838.             }
  3839.             cnt++;
  3840.         }
  3841.     }
  3842. }
  3843.  
  3844. //--------------------------------------------------------------------------------------------
  3845. void pit_kill()
  3846. {
  3847.     // ZZ> This function kills any character in a deep pit...
  3848.     int cnt;
  3849.  
  3850.     if(pitskill)
  3851.     {
  3852.         if(pitclock > 19)
  3853.         {
  3854.             pitclock = 0;
  3855.  
  3856.  
  3857.             // Kill any particles that fell in a pit, if they die in water...
  3858.             cnt = 0;
  3859.             while(cnt < MAXPRT)
  3860.             {
  3861.                 if(prton[cnt])
  3862.                 {
  3863.                     if(prtzpos[cnt] < PITDEPTH && pipendwater[prtpip[cnt]])
  3864.                     {
  3865.                         prttime[cnt] = 1;
  3866.                     }
  3867.                 }
  3868.                 cnt++;
  3869.             }
  3870.  
  3871.  
  3872.  
  3873.             // Kill any characters that fell in a pit...
  3874.             cnt = 0;
  3875.             while(cnt < MAXCHR)
  3876.             {
  3877.                 if(chron[cnt] && chralive[cnt] && chrinpack[cnt] == FALSE)
  3878.                 {
  3879.                     if(chrinvictus[cnt] == FALSE && chrzpos[cnt] < PITDEPTH && chrattachedto[cnt]==MAXCHR)
  3880.                     {
  3881.                         // Got one!
  3882.                         kill_character(cnt, MAXCHR);
  3883.                         chrxvel[cnt] = 0;
  3884.                         chryvel[cnt] = 0;
  3885.                     }
  3886.                 }
  3887.                 cnt++;
  3888.             }
  3889.         }
  3890.         else
  3891.         {
  3892.             pitclock++;
  3893.         }
  3894.     }
  3895. }
  3896.  
  3897. //--------------------------------------------------------------------------------------------
  3898. void reset_players()
  3899. {
  3900.     // ZZ> This function clears the player list data
  3901.     int cnt, tnc;
  3902.  
  3903.  
  3904.     // Reset the local data stuff
  3905.     localseekurse = FALSE;
  3906.     localseeinvisible = FALSE;
  3907.     alllocalpladead = FALSE;
  3908.  
  3909.  
  3910.     // Reset the initial player data and latches
  3911.     cnt = 0;
  3912.     while(cnt < MAXPLAYER)
  3913.     {
  3914.         plavalid[cnt] = FALSE;
  3915.         plaindex[cnt] = 0;
  3916.         plalatchx[cnt] = 0;
  3917.         plalatchy[cnt] = 0;
  3918.         plalatchbutton[cnt] = 0;
  3919.         tnc = 0;
  3920.         while(tnc < MAXLAG)
  3921.         {
  3922.             platimelatchx[cnt][tnc] = 0;
  3923.             platimelatchy[cnt][tnc] = 0;
  3924.             platimelatchbutton[cnt][tnc] = 0;
  3925.             tnc++;
  3926.         }
  3927.         pladevice[cnt] = INPUTNONE;
  3928.         cnt++;
  3929.     }
  3930.     numpla = 0;
  3931.     nexttimestamp = -1;
  3932.     numplatimes = STARTTALK+1;
  3933.     if(hostactive) numplatimes++;
  3934. }
  3935.  
  3936. //--------------------------------------------------------------------------------------------
  3937. void resize_characters()
  3938. {
  3939.     // ZZ> This function makes the characters get bigger or smaller, depending
  3940.     //     on their sizegoto and sizegototime
  3941.     int cnt, item, mount;
  3942.     unsigned char willgetcaught;
  3943.     float newsize;
  3944.  
  3945.  
  3946.     cnt = 0;
  3947.     while(cnt < MAXCHR)
  3948.     {
  3949.         if(chron[cnt] && chrsizegototime[cnt])
  3950.         {
  3951.             // Make sure it won't get caught in a wall
  3952.             willgetcaught = FALSE;
  3953.             if(chrsizegoto[cnt] > chrfat[cnt])
  3954.             {
  3955.                 chrbumpsize[cnt] += 10;
  3956.                 if(__chrhitawall(cnt))
  3957.                 {
  3958.                     willgetcaught = TRUE;
  3959.                 }
  3960.                 chrbumpsize[cnt] -= 10;
  3961.             }
  3962.  
  3963.  
  3964.             // If it is getting caught, simply halt growth until later
  3965.             if(willgetcaught==FALSE)
  3966.             {
  3967.                 // Figure out how big it is
  3968.                 chrsizegototime[cnt]--;
  3969.                 newsize = chrsizegoto[cnt];
  3970.                 if(chrsizegototime[cnt] != 0)
  3971.                 {
  3972.                     newsize = (chrfat[cnt] * .90) + (newsize * .10);
  3973.                 }
  3974.  
  3975.  
  3976.                 // Make it that big...
  3977.                 chrfat[cnt] = newsize;
  3978.                 chrshadowsize[cnt] = chrshadowsizesave[cnt]*newsize;
  3979.                 chrbumpsize[cnt] = chrbumpsizesave[cnt]*newsize;
  3980.                 chrbumpsizebig[cnt] = chrbumpsizebigsave[cnt]*newsize;
  3981.                 chrbumpheight[cnt] = chrbumpheightsave[cnt]*newsize;
  3982.                 chrweight[cnt] = capweight[chrmodel[cnt]]*newsize;
  3983.                 if(capweight[chrmodel[cnt]]==255) chrweight[cnt] = 65535;
  3984.  
  3985.  
  3986.                 // Now come up with the magic number
  3987.                 mount = chrattachedto[cnt];
  3988.                 if(mount == MAXCHR)
  3989.                 {
  3990.                     chrscale[cnt] = newsize*madscale[chrmodel[cnt]]*4;
  3991.                 }
  3992.                 else
  3993.                 {
  3994.                     chrscale[cnt] = newsize/(chrfat[mount]*1280);
  3995.                 }
  3996.  
  3997.  
  3998.                 // Make in hand items stay the same size...
  3999.                 newsize = newsize*1280;
  4000.                 item = chrholdingwhich[cnt][0];
  4001.                 if(item != MAXCHR)
  4002.                     chrscale[item] = chrfat[item]/newsize;
  4003.                 item = chrholdingwhich[cnt][1];
  4004.                 if(item != MAXCHR)
  4005.                     chrscale[item] = chrfat[item]/newsize;
  4006.             }
  4007.         }
  4008.         cnt++;
  4009.     }
  4010. }
  4011.  
  4012. //--------------------------------------------------------------------------------------------
  4013. void export_one_character_name(char *szSaveName, unsigned short character)
  4014. {
  4015.     // ZZ> This function makes the naming.txt file for the character
  4016.     FILE* filewrite;
  4017.     int profile;
  4018.     char cTmp;
  4019.     int cnt, tnc;
  4020.  
  4021.  
  4022.     // Can it export?
  4023.     profile = chrmodel[character];
  4024.     filewrite = fopen(szSaveName, "w");
  4025.     if(filewrite)
  4026.     {
  4027.         cnt = 0;
  4028.         cTmp = chrname[character][0];
  4029.         cnt++;
  4030.         while(cnt < MAXCAPNAMESIZE && cTmp != 0)
  4031.         {
  4032.             fprintf(filewrite, ":");
  4033.             tnc = 0;
  4034.             while(tnc < 8 && cTmp != 0)
  4035.             {
  4036.                 if(cTmp == ' ')
  4037.                 {
  4038.                     fprintf(filewrite, "_");
  4039.                 }
  4040.                 else
  4041.                 {
  4042.                     fprintf(filewrite, "%c", cTmp);
  4043.                 }
  4044.                 cTmp = chrname[character][cnt];
  4045.                 tnc++;
  4046.                 cnt++;
  4047.             }
  4048.             fprintf(filewrite, "\n");
  4049.             fprintf(filewrite, ":STOP\n\n");
  4050.         }
  4051.         fclose(filewrite);
  4052.     }
  4053. }
  4054.  
  4055. //--------------------------------------------------------------------------------------------
  4056. void export_one_character_profile(char *szSaveName, unsigned short character)
  4057. {
  4058.     // ZZ> This function creates a data.txt file for the given character.
  4059.     //     it is assumed that all enchantments have been done away with
  4060.     FILE* filewrite;
  4061.     int profile;
  4062.     int damagetype, skin;
  4063.     char types[10] = "SCPHEFIZ";
  4064.     char codes[4];
  4065.  
  4066.  
  4067.     // General stuff
  4068.     profile = chrmodel[character];
  4069.  
  4070.  
  4071.     // Open the file
  4072.     filewrite = fopen(szSaveName, "w");
  4073.     if(filewrite)
  4074.     {
  4075.         // Real general data
  4076.         fprintf(filewrite, "Slot number    : -1\n");  // -1 signals a flexible load thing
  4077.         funderf(filewrite, "Class name     : ", capclassname[profile]);
  4078.         ftruthf(filewrite, "Uniform light  : ", capuniformlit[profile]);
  4079.         fprintf(filewrite, "Maximum ammo   : %d\n", capammomax[profile]);
  4080.         fprintf(filewrite, "Current ammo   : %d\n", chrammo[character]);
  4081.         fgendef(filewrite, "Gender         : ", chrgender[character]);
  4082.         fprintf(filewrite, "\n");
  4083.  
  4084.  
  4085.  
  4086.         // Object stats
  4087.         fprintf(filewrite, "Life color     : %d\n", chrlifecolor[character]);
  4088.         fprintf(filewrite, "Mana color     : %d\n", chrmanacolor[character]);
  4089.         fprintf(filewrite, "Life           : %4.2f\n", chrlifemax[character]/256.0);
  4090.         fpairof(filewrite, "Life up        : ", caplifeperlevelbase[profile], caplifeperlevelrand[profile]);
  4091.         fprintf(filewrite, "Mana           : %4.2f\n", chrmanamax[character]/256.0);
  4092.         fpairof(filewrite, "Mana up        : ", capmanaperlevelbase[profile], capmanaperlevelrand[profile]);
  4093.         fprintf(filewrite, "Mana return    : %4.2f\n", chrmanareturn[character]/16.0);
  4094.         fpairof(filewrite, "Mana return up : ", capmanareturnperlevelbase[profile], capmanareturnperlevelrand[profile]);
  4095.         fprintf(filewrite, "Mana flow      : %4.2f\n", chrmanaflow[character]/256.0);
  4096.         fpairof(filewrite, "Mana flow up   : ", capmanaflowperlevelbase[profile], capmanaflowperlevelrand[profile]);
  4097.         fprintf(filewrite, "STR            : %4.2f\n", chrstrength[character]/256.0);
  4098.         fpairof(filewrite, "STR up         : ", capstrengthperlevelbase[profile], capstrengthperlevelrand[profile]);
  4099.         fprintf(filewrite, "WIS            : %4.2f\n", chrwisdom[character]/256.0);
  4100.         fpairof(filewrite, "WIS up         : ", capwisdomperlevelbase[profile], capwisdomperlevelrand[profile]);
  4101.         fprintf(filewrite, "INT            : %4.2f\n", chrintelligence[character]/256.0);
  4102.         fpairof(filewrite, "INT up         : ", capintelligenceperlevelbase[profile], capintelligenceperlevelrand[profile]);
  4103.         fprintf(filewrite, "DEX            : %4.2f\n", chrdexterity[character]/256.0);
  4104.         fpairof(filewrite, "DEX up         : ", capdexterityperlevelbase[profile], capdexterityperlevelrand[profile]);
  4105.         fprintf(filewrite, "\n");
  4106.  
  4107.  
  4108.  
  4109.         // More physical attributes
  4110.         fprintf(filewrite, "Size           : %4.2f\n", chrsizegoto[character]);
  4111.         fprintf(filewrite, "Size up        : %4.2f\n", capsizeperlevel[profile]);
  4112.         fprintf(filewrite, "Shadow size    : %d\n", capshadowsize[profile]);
  4113.         fprintf(filewrite, "Bump size      : %d\n", capbumpsize[profile]);
  4114.         fprintf(filewrite, "Bump height    : %d\n", capbumpheight[profile]);
  4115.         fprintf(filewrite, "Bump dampen    : %4.2f\n", capbumpdampen[profile]);
  4116.         fprintf(filewrite, "Weight         : %d\n", capweight[profile]);
  4117.         fprintf(filewrite, "Jump power     : %4.2f\n", capjump[profile]);
  4118.         fprintf(filewrite, "Jump number    : %d\n", capjumpnumber[profile]);
  4119.         fprintf(filewrite, "Sneak speed    : %d\n", capsneakspd[profile]);
  4120.         fprintf(filewrite, "Walk speed     : %d\n", capwalkspd[profile]);
  4121.         fprintf(filewrite, "Run speed      : %d\n", caprunspd[profile]);
  4122.         fprintf(filewrite, "Fly to height  : %d\n", capflyheight[profile]);
  4123.         fprintf(filewrite, "Flashing AND   : %d\n", capflashand[profile]);
  4124.         fprintf(filewrite, "Alpha blending : %d\n", capalpha[profile]);
  4125.         fprintf(filewrite, "Light blending : %d\n", caplight[profile]);
  4126.         ftruthf(filewrite, "Transfer blend : ", captransferblend[profile]);
  4127.         fprintf(filewrite, "Sheen          : %d\n", capsheen[profile]);
  4128.         ftruthf(filewrite, "Phong mapping  : ", capenviro[profile]);
  4129.         fprintf(filewrite, "Texture X add  : %4.2f\n", capuoffvel[profile]/65535.0);
  4130.         fprintf(filewrite, "Texture Y add  : %4.2f\n", capvoffvel[profile]/65535.0);
  4131.         ftruthf(filewrite, "Sticky butt    : ", capstickybutt[profile]);
  4132.         fprintf(filewrite, "\n");
  4133.  
  4134.  
  4135.  
  4136.         // Invulnerability data
  4137.         ftruthf(filewrite, "Invictus       : ", capinvictus[profile]);
  4138.         fprintf(filewrite, "NonI facing    : %d\n", capnframefacing[profile]);
  4139.         fprintf(filewrite, "NonI angle     : %d\n", capnframeangle[profile]);
  4140.         fprintf(filewrite, "I facing       : %d\n", capiframefacing[profile]);
  4141.         fprintf(filewrite, "I angle        : %d\n", capiframeangle[profile]);
  4142.         fprintf(filewrite, "\n");
  4143.  
  4144.  
  4145.  
  4146.         // Skin defenses
  4147.         fprintf(filewrite, "Base defense   : %3d %3d %3d %3d\n", 255-capdefense[profile][0], 255-capdefense[profile][1],
  4148.                                                                  255-capdefense[profile][2], 255-capdefense[profile][3]);
  4149.         damagetype = 0;
  4150.         while(damagetype < MAXDAMAGETYPE)
  4151.         {
  4152.             fprintf(filewrite, "%c damage shift : %3d %3d %3d %3d\n", types[damagetype],
  4153.                                                                       capdamagemodifier[profile][damagetype][0]&DAMAGESHIFT,
  4154.                                                                       capdamagemodifier[profile][damagetype][1]&DAMAGESHIFT,
  4155.                                                                       capdamagemodifier[profile][damagetype][2]&DAMAGESHIFT,
  4156.                                                                       capdamagemodifier[profile][damagetype][3]&DAMAGESHIFT);
  4157.             damagetype++;
  4158.         }
  4159.         damagetype = 0;
  4160.         while(damagetype < MAXDAMAGETYPE)
  4161.         {
  4162.             skin = 0;
  4163.             while(skin < 4)
  4164.             {
  4165.                 codes[skin] = 'F';
  4166.                 if(capdamagemodifier[profile][damagetype][skin]&DAMAGEINVERT)
  4167.                     codes[skin] = 'T';
  4168.                 if(capdamagemodifier[profile][damagetype][skin]&DAMAGECHARGE)
  4169.                     codes[skin] = 'C';
  4170.                 skin++;
  4171.             }
  4172.             fprintf(filewrite, "%c damage code  : %3c %3c %3c %3c\n", types[damagetype], codes[0], codes[1], codes[2], codes[3]);
  4173.             damagetype++;
  4174.         }
  4175.         fprintf(filewrite, "Acceleration   : %3.0f %3.0f %3.0f %3.0f\n", capmaxaccel[profile][0]*80,
  4176.                                                                          capmaxaccel[profile][1]*80, 
  4177.                                                                          capmaxaccel[profile][2]*80,
  4178.                                                                          capmaxaccel[profile][3]*80);
  4179.         fprintf(filewrite, "\n");
  4180.  
  4181.  
  4182.  
  4183.         // Experience and level data
  4184.         fprintf(filewrite, "EXP for 2nd    : %d\n", capexperienceforlevel[profile][1]);
  4185.         fprintf(filewrite, "EXP for 3rd    : %d\n", capexperienceforlevel[profile][2]);
  4186.         fprintf(filewrite, "EXP for 4th    : %d\n", capexperienceforlevel[profile][3]);
  4187.         fprintf(filewrite, "EXP for 5th    : %d\n", capexperienceforlevel[profile][4]);
  4188.         fprintf(filewrite, "EXP for 6th    : %d\n", capexperienceforlevel[profile][5]);
  4189.         fprintf(filewrite, "Starting EXP   : %d\n", chrexperience[character]);
  4190.         fprintf(filewrite, "EXP worth      : %d\n", capexperienceworth[profile]);
  4191.         fprintf(filewrite, "EXP exchange   : %5.3f\n", capexperienceexchange[profile]);
  4192.         fprintf(filewrite, "EXPSECRET      : %4.2f\n", capexperiencerate[profile][0]);
  4193.         fprintf(filewrite, "EXPQUEST       : %4.2f\n", capexperiencerate[profile][1]);
  4194.         fprintf(filewrite, "EXPDARE        : %4.2f\n", capexperiencerate[profile][2]);
  4195.         fprintf(filewrite, "EXPKILL        : %4.2f\n", capexperiencerate[profile][3]);
  4196.         fprintf(filewrite, "EXPMURDER      : %4.2f\n", capexperiencerate[profile][4]);
  4197.         fprintf(filewrite, "EXPREVENGE     : %4.2f\n", capexperiencerate[profile][5]);
  4198.         fprintf(filewrite, "EXPTEAMWORK    : %4.2f\n", capexperiencerate[profile][6]);
  4199.         fprintf(filewrite, "EXPROLEPLAY    : %4.2f\n", capexperiencerate[profile][7]);
  4200.         fprintf(filewrite, "\n");
  4201.  
  4202.  
  4203.  
  4204.         // IDSZ identification tags
  4205.         undo_idsz(capidsz[profile][0]);
  4206.         fprintf(filewrite, "IDSZ Parent    : [%s]\n", valueidsz);
  4207.         undo_idsz(capidsz[profile][1]);
  4208.         fprintf(filewrite, "IDSZ Type      : [%s]\n", valueidsz);
  4209.         undo_idsz(capidsz[profile][2]);
  4210.         fprintf(filewrite, "IDSZ Skill     : [%s]\n", valueidsz);
  4211.         undo_idsz(capidsz[profile][3]);
  4212.         fprintf(filewrite, "IDSZ Special   : [%s]\n", valueidsz);
  4213.         undo_idsz(capidsz[profile][4]);
  4214.         fprintf(filewrite, "IDSZ Hate      : [%s]\n", valueidsz);
  4215.         undo_idsz(capidsz[profile][5]);
  4216.         fprintf(filewrite, "IDSZ Vulnie    : [%s]\n", valueidsz);
  4217.         fprintf(filewrite, "\n");
  4218.  
  4219.  
  4220.  
  4221.         // Item and damage flags
  4222.         ftruthf(filewrite, "Is an item     : ", capisitem[profile]);
  4223.         ftruthf(filewrite, "Is a mount     : ", capismount[profile]);
  4224.         ftruthf(filewrite, "Is stackable   : ", capisstackable[profile]);
  4225.         ftruthf(filewrite, "Name known     : ", chrnameknown[character]);
  4226.         ftruthf(filewrite, "Usage known    : ", capusageknown[profile]);
  4227.         ftruthf(filewrite, "Is exportable  : ", capcancarrytonextmodule[profile]);
  4228.         ftruthf(filewrite, "Requires skill : ", capneedskillidtouse[profile]);
  4229.         ftruthf(filewrite, "Is platform    : ", capplatform[profile]);
  4230.         ftruthf(filewrite, "Collects money : ", capcangrabmoney[profile]);
  4231.         ftruthf(filewrite, "Can open stuff : ", capcanopenstuff[profile]);
  4232.         fprintf(filewrite, "\n");
  4233.  
  4234.  
  4235.  
  4236.         // Other item and damage stuff
  4237.         fdamagf(filewrite, "Damage type    : ", capdamagetargettype[profile]);
  4238.         factiof(filewrite, "Attack type    : ", capweaponaction[profile]);
  4239.         fprintf(filewrite, "\n");
  4240.  
  4241.  
  4242.  
  4243.         // Particle attachments
  4244.         fprintf(filewrite, "Attached parts : %d\n", capattachedprtamount[profile]);
  4245.         fdamagf(filewrite, "Reaffirm type  : ", capattachedprtreaffirmdamagetype[profile]);
  4246.         fprintf(filewrite, "Particle type  : %d\n", capattachedprttype[profile]);
  4247.         fprintf(filewrite, "\n");
  4248.  
  4249.  
  4250.  
  4251.         // Character hands
  4252.         ftruthf(filewrite, "Left valid     : ", capgripvalid[profile][0]);
  4253.         ftruthf(filewrite, "Right valid    : ", capgripvalid[profile][1]);
  4254.         fprintf(filewrite, "\n");
  4255.  
  4256.  
  4257.  
  4258.         // Particle spawning on attack
  4259.         ftruthf(filewrite, "Part on weapon : ", capattackattached[profile]);
  4260.         fprintf(filewrite, "Part type      : %d\n", capattackprttype[profile]);
  4261.         fprintf(filewrite, "\n");
  4262.  
  4263.  
  4264.  
  4265.         // Particle spawning for GoPoof
  4266.         fprintf(filewrite, "Poof amount    : %d\n", capgopoofprtamount[profile]);
  4267.         fprintf(filewrite, "Facing add     : %d\n", capgopoofprtfacingadd[profile]);
  4268.         fprintf(filewrite, "Part type      : %d\n", capgopoofprttype[profile]);
  4269.         fprintf(filewrite, "\n");
  4270.  
  4271.  
  4272.  
  4273.         // Particle spawning for blood
  4274.         ftruthf(filewrite, "Blood valid    : ", capbloodvalid[profile]);
  4275.         fprintf(filewrite, "Part type      : %d\n", capbloodprttype[profile]);
  4276.         fprintf(filewrite, "\n");
  4277.  
  4278.  
  4279.  
  4280.         // Extra stuff
  4281.         ftruthf(filewrite, "Waterwalking   : ", capwaterwalk[profile]);
  4282.         fprintf(filewrite, "Bounce dampen  : %5.3f\n", capdampen[profile]);
  4283.         fprintf(filewrite, "\n");
  4284.  
  4285.  
  4286.  
  4287.         // More stuff
  4288.         fprintf(filewrite, "Life healing   : %5.3f\n", caplifeheal[profile]/256.0);
  4289.         fprintf(filewrite, "Mana cost      : %5.3f\n", capmanacost[profile]/256.0);
  4290.         fprintf(filewrite, "Life return    : %d\n", caplifereturn[profile]);
  4291.         fprintf(filewrite, "Stopped by     : %d\n", capstoppedby[profile]);
  4292.         funderf(filewrite, "Skin 0 name    : ", capskinname[profile][0]);
  4293.         funderf(filewrite, "Skin 1 name    : ", capskinname[profile][1]);
  4294.         funderf(filewrite, "Skin 2 name    : ", capskinname[profile][2]);
  4295.         funderf(filewrite, "Skin 3 name    : ", capskinname[profile][3]);
  4296.         fprintf(filewrite, "Skin 0 cost    : %d\n", capskincost[profile][0]);
  4297.         fprintf(filewrite, "Skin 1 cost    : %d\n", capskincost[profile][1]);
  4298.         fprintf(filewrite, "Skin 2 cost    : %d\n", capskincost[profile][2]);
  4299.         fprintf(filewrite, "Skin 3 cost    : %d\n", capskincost[profile][3]);
  4300.         fprintf(filewrite, "STR dampen     : %5.3f\n", capstrengthdampen[profile]);
  4301.         fprintf(filewrite, "\n");
  4302.  
  4303.  
  4304.  
  4305.         // Another memory lapse
  4306.         ftruthf(filewrite, "No rider attak : ", TRUE-capridercanattack[profile]);
  4307.         ftruthf(filewrite, "Can be dazed   : ", capcanbedazed[profile]);
  4308.         ftruthf(filewrite, "Can be grogged : ", capcanbegrogged[profile]);
  4309.         fprintf(filewrite, "NOT USED       : 0\n");
  4310.         fprintf(filewrite, "NOT USED       : 0\n");
  4311.         ftruthf(filewrite, "Can see invisi : ", capcanseeinvisible[profile]);
  4312.         fprintf(filewrite, "Kursed chance  : %d\n", chriskursed[character]*100);
  4313.         fprintf(filewrite, "Footfall sound : %d\n", capwavefootfall[profile]);
  4314.         fprintf(filewrite, "Jump sound     : %d\n", capwavejump[profile]);
  4315.         fprintf(filewrite, "\n");
  4316.  
  4317.  
  4318.         // Expansions
  4319.         fprintf(filewrite, ":[GOLD] %d\n", chrmoney[character]);
  4320.         if(capskindressy[profile]&1)
  4321.             fprintf(filewrite, ":[DRES] 0\n");
  4322.         if(capskindressy[profile]&2)
  4323.             fprintf(filewrite, ":[DRES] 1\n");
  4324.         if(capskindressy[profile]&4)
  4325.             fprintf(filewrite, ":[DRES] 2\n");
  4326.         if(capskindressy[profile]&8)
  4327.             fprintf(filewrite, ":[DRES] 3\n");
  4328.         if(capresistbumpspawn[profile])
  4329.             fprintf(filewrite, ":[STUK] 0\n");
  4330.         if(capistoobig[profile])
  4331.             fprintf(filewrite, ":[PACK] 0\n");
  4332.         if(capreflect[profile]==FALSE)
  4333.             fprintf(filewrite, ":[VAMP] 1\n");
  4334.         if(capalwaysdraw[profile])
  4335.             fprintf(filewrite, ":[DRAW] 1\n");
  4336.         if(capisranged[profile])
  4337.             fprintf(filewrite, ":[RANG] 1\n");
  4338.         if(caphidestate[profile]!=NOHIDE)
  4339.             fprintf(filewrite, ":[HIDE] %d\n", caphidestate[profile]);
  4340.         if(capisequipment[profile])
  4341.             fprintf(filewrite, ":[EQUI] 1\n");
  4342.         if(capbumpsizebig[profile]==(capbumpsize[profile]<<1))
  4343.             fprintf(filewrite, ":[SQUA] 1\n");
  4344.         if(capicon[profile] != capusageknown[profile])
  4345.             fprintf(filewrite, ":[ICON] %d\n", capicon[profile]);
  4346.         if(capforceshadow[profile])
  4347.             fprintf(filewrite, ":[SHAD] 1\n");
  4348.         if(capcanseekurse[profile])
  4349.             fprintf(filewrite, ":[CKUR] 1\n");
  4350.         if(capripple[profile] == capisitem[profile])
  4351.             fprintf(filewrite, ":[RIPP] %d\n", capripple[profile]);
  4352.         fprintf(filewrite, ":[PLAT] %d\n", capcanuseplatforms[profile]);
  4353.         fprintf(filewrite, ":[SKIN] %d\n", chrtexture[character]-madskinstart[profile]);
  4354.         fprintf(filewrite, ":[CONT] %d\n", chraicontent[character]);
  4355.         fprintf(filewrite, ":[STAT] %d\n", chraistate[character]);
  4356.         fprintf(filewrite, ":[LEVL] %d\n", chrexperiencelevel[character]);
  4357.         fclose(filewrite);
  4358.     }
  4359. }
  4360.  
  4361. //--------------------------------------------------------------------------------------------
  4362. void export_one_character_skin(char *szSaveName, unsigned short character)
  4363. {
  4364.     // ZZ> This function creates a skin.txt file for the given character.
  4365.     FILE* filewrite;
  4366.     int profile;
  4367.  
  4368.  
  4369.     // General stuff
  4370.     profile = chrmodel[character];
  4371.  
  4372.  
  4373.     // Open the file
  4374.     filewrite = fopen(szSaveName, "w");
  4375.     if(filewrite)
  4376.     {
  4377.         fprintf(filewrite, "This file is used only by the import menu\n");
  4378.         fprintf(filewrite, ": %d\n", (chrtexture[character]-madskinstart[profile])&3);
  4379.         fclose(filewrite);
  4380.     }
  4381. }
  4382.  
  4383. //--------------------------------------------------------------------------------------------
  4384. int load_one_character_profile(char *szLoadName)
  4385. {
  4386.     // ZZ> This function fills a character profile with data from data.txt, returning
  4387.     // the object slot that the profile was stuck into.  It may cause the program
  4388.     // to abort if bad things happen.
  4389.     FILE* fileread;
  4390.     int object;
  4391.     char szTmp[256];
  4392.     int iTmp;
  4393.     float fTmp;
  4394.     char cTmp;
  4395.     int damagetype, level, xptype, idsz;
  4396.     int test;
  4397.  
  4398.     // Open the file
  4399.     fileread = fopen(FILENAME(szLoadName), "r");
  4400.     //printf(" DIAG: trying to read %s\n",szLoadName);
  4401.     if(fileread!=NULL)
  4402.     {
  4403.         globalname = szLoadName;
  4404.         // Read in the object slot
  4405.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp); object=iTmp;
  4406.         if(object < 0)
  4407.         {
  4408.             if(importobject < 0)
  4409.             {
  4410.                 sprintf(szTmp, "-1 OBJECT SLOT (%s)", szLoadName);
  4411.                 general_error(object, object, szTmp);
  4412.             }
  4413.             else
  4414.             {
  4415.                 object = importobject;
  4416.             }
  4417.         }
  4418.  
  4419.  
  4420.  
  4421.         // Read in the real general data
  4422.         goto_colon(fileread);  get_name(fileread, capclassname[object]);
  4423.  
  4424.  
  4425.         // Make sure we don't load over an existing model
  4426.         if(madused[object])
  4427.         {
  4428.             sprintf(szTmp, "<--MODEL SLOT USED TWICE (%s)", capclassname[object]);
  4429.             general_error(object, object, szTmp);
  4430.         }
  4431.         madused[object] = TRUE;
  4432.  
  4433.  
  4434.         // Light cheat
  4435.         goto_colon(fileread);  cTmp = get_first_letter(fileread);
  4436.             capuniformlit[object] = FALSE;
  4437. /*PORT
  4438.             if(cTmp=='T' || cTmp=='t' || shading == D3DSHADE_FLAT)  capuniformlit[object] = TRUE;
  4439. */
  4440.         // Ammo
  4441.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  capammomax[object] = iTmp;
  4442.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  capammo[object] = iTmp;
  4443.         // Gender
  4444.         goto_colon(fileread);  cTmp = get_first_letter(fileread);
  4445.             capgender[object] = GENOTHER;
  4446.             if(cTmp=='F' || cTmp=='f')  capgender[object] = GENFEMALE;
  4447.             if(cTmp=='M' || cTmp=='m')  capgender[object] = GENMALE;
  4448.             if(cTmp=='R' || cTmp=='r')  capgender[object] = GENRANDOM;
  4449.         // Read in the object stats
  4450.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  caplifecolor[object] = iTmp;
  4451.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  capmanacolor[object] = iTmp;
  4452.         goto_colon(fileread);  read_pair(fileread);
  4453.             caplifebase[object] = pairbase;  capliferand[object] = pairrand;
  4454.         goto_colon(fileread);  read_pair(fileread);
  4455.             caplifeperlevelbase[object] = pairbase;  caplifeperlevelrand[object] = pairrand;
  4456.         goto_colon(fileread);  read_pair(fileread);
  4457.             capmanabase[object] = pairbase;  capmanarand[object] = pairrand;
  4458.         goto_colon(fileread);  read_pair(fileread);
  4459.             capmanaperlevelbase[object] = pairbase;  capmanaperlevelrand[object] = pairrand;
  4460.         goto_colon(fileread);  read_pair(fileread);
  4461.             capmanareturnbase[object] = pairbase;  capmanareturnrand[object] = pairrand;
  4462.         goto_colon(fileread);  read_pair(fileread);
  4463.             capmanareturnperlevelbase[object] = pairbase;  capmanareturnperlevelrand[object] = pairrand;
  4464.         goto_colon(fileread);  read_pair(fileread);
  4465.             capmanaflowbase[object] = pairbase;  capmanaflowrand[object] = pairrand;
  4466.         goto_colon(fileread);  read_pair(fileread);
  4467.             capmanaflowperlevelbase[object] = pairbase;  capmanaflowperlevelrand[object] = pairrand;
  4468.         goto_colon(fileread);  read_pair(fileread);
  4469.             capstrengthbase[object] = pairbase;  capstrengthrand[object] = pairrand;
  4470.         goto_colon(fileread);  read_pair(fileread);
  4471.             capstrengthperlevelbase[object] = pairbase;  capstrengthperlevelrand[object] = pairrand;
  4472.         goto_colon(fileread);  read_pair(fileread);
  4473.             capwisdombase[object] = pairbase;  capwisdomrand[object] = pairrand;
  4474.         goto_colon(fileread);  read_pair(fileread);
  4475.             capwisdomperlevelbase[object] = pairbase;  capwisdomperlevelrand[object] = pairrand;
  4476.         goto_colon(fileread);  read_pair(fileread);
  4477.             capintelligencebase[object] = pairbase;  capintelligencerand[object] = pairrand;
  4478.         goto_colon(fileread);  read_pair(fileread);
  4479.             capintelligenceperlevelbase[object] = pairbase;  capintelligenceperlevelrand[object] = pairrand;
  4480.         goto_colon(fileread);  read_pair(fileread);
  4481.             capdexteritybase[object] = pairbase;  capdexterityrand[object] = pairrand;
  4482.         goto_colon(fileread);  read_pair(fileread);
  4483.             capdexterityperlevelbase[object] = pairbase;  capdexterityperlevelrand[object] = pairrand;
  4484.  
  4485.         // More physical attributes
  4486.         goto_colon(fileread);  fscanf(fileread, "%f", &fTmp);  capsize[object] = fTmp;
  4487.         goto_colon(fileread);  fscanf(fileread, "%f", &fTmp);  capsizeperlevel[object] = fTmp;
  4488.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  capshadowsize[object] = iTmp;
  4489.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  capbumpsize[object] = iTmp;
  4490.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  capbumpheight[object] = iTmp;
  4491.         goto_colon(fileread);  fscanf(fileread, "%f", &fTmp);  capbumpdampen[object] = fTmp;
  4492.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  capweight[object] = iTmp;
  4493.         goto_colon(fileread);  fscanf(fileread, "%f", &fTmp);  capjump[object] = fTmp;
  4494.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  capjumpnumber[object] = iTmp;
  4495.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  capsneakspd[object] = iTmp;
  4496.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  capwalkspd[object] = iTmp;
  4497.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  caprunspd[object] = iTmp;
  4498.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  capflyheight[object] = iTmp;
  4499.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  capflashand[object] = iTmp;
  4500.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  capalpha[object] = iTmp;
  4501.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  caplight[object] = iTmp;
  4502.         goto_colon(fileread);  cTmp = get_first_letter(fileread);
  4503.             captransferblend[object] = FALSE;
  4504.             if(cTmp=='T' || cTmp=='t')  captransferblend[object] = TRUE;
  4505.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  capsheen[object] = iTmp;
  4506.         goto_colon(fileread);  cTmp = get_first_letter(fileread);
  4507.             capenviro[object] = FALSE;
  4508.             if(cTmp=='T' || cTmp=='t')  capenviro[object] = TRUE;
  4509.         goto_colon(fileread);  fscanf(fileread, "%f", &fTmp);  capuoffvel[object] = fTmp*65535;
  4510.         goto_colon(fileread);  fscanf(fileread, "%f", &fTmp);  capvoffvel[object] = fTmp*65535;
  4511.         goto_colon(fileread);  cTmp = get_first_letter(fileread);
  4512.             capstickybutt[object] = FALSE;
  4513.             if(cTmp=='T' || cTmp=='t')  capstickybutt[object] = TRUE;
  4514.  
  4515.  
  4516.         // Invulnerability data
  4517.         goto_colon(fileread);  cTmp = get_first_letter(fileread);
  4518.             capinvictus[object] = FALSE;
  4519.             if(cTmp=='T' || cTmp=='t')  capinvictus[object] = TRUE;
  4520.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  capnframefacing[object] = iTmp;
  4521.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  capnframeangle[object] = iTmp;
  4522.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  capiframefacing[object] = iTmp;
  4523.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  capiframeangle[object] = iTmp;
  4524.         // Resist burning and stuck arrows with nframe angle of 1 or more
  4525.         if(capnframeangle[object] > 0)
  4526.         {
  4527.             if(capnframeangle[object] == 1)
  4528.             {
  4529.                 capnframeangle[object] = 0;
  4530.             }
  4531.         }
  4532.  
  4533.  
  4534.         // Skin defenses ( 4 skins )
  4535.         goto_colon(fileread);
  4536.             fscanf(fileread, "%d", &iTmp);  capdefense[object][0] = 255-iTmp;
  4537.             fscanf(fileread, "%d", &iTmp);  capdefense[object][1] = 255-iTmp;
  4538.             fscanf(fileread, "%d", &iTmp);  capdefense[object][2] = 255-iTmp;
  4539.             fscanf(fileread, "%d", &iTmp);  capdefense[object][3] = 255-iTmp;
  4540.         damagetype = 0;
  4541.         while(damagetype < MAXDAMAGETYPE)
  4542.         {
  4543.             goto_colon(fileread);
  4544.                 fscanf(fileread, "%d", &iTmp);  capdamagemodifier[object][damagetype][0] = iTmp;
  4545.                 fscanf(fileread, "%d", &iTmp);  capdamagemodifier[object][damagetype][1] = iTmp;
  4546.                 fscanf(fileread, "%d", &iTmp);  capdamagemodifier[object][damagetype][2] = iTmp;
  4547.                 fscanf(fileread, "%d", &iTmp);  capdamagemodifier[object][damagetype][3] = iTmp;
  4548.             damagetype++;
  4549.         }
  4550.         damagetype = 0;
  4551.         while(damagetype < MAXDAMAGETYPE)
  4552.         {
  4553.             goto_colon(fileread);
  4554.                 cTmp = get_first_letter(fileread);  if(cTmp=='T' || cTmp=='t')  capdamagemodifier[object][damagetype][0]|=DAMAGEINVERT;
  4555.                                                     if(cTmp=='C' || cTmp=='c')  capdamagemodifier[object][damagetype][0]|=DAMAGECHARGE;
  4556.                 cTmp = get_first_letter(fileread);  if(cTmp=='T' || cTmp=='t')  capdamagemodifier[object][damagetype][1]|=DAMAGEINVERT;
  4557.                                                     if(cTmp=='C' || cTmp=='c')  capdamagemodifier[object][damagetype][1]|=DAMAGECHARGE;
  4558.                 cTmp = get_first_letter(fileread);  if(cTmp=='T' || cTmp=='t')  capdamagemodifier[object][damagetype][2]|=DAMAGEINVERT;
  4559.                                                     if(cTmp=='C' || cTmp=='c')  capdamagemodifier[object][damagetype][2]|=DAMAGECHARGE;
  4560.                 cTmp = get_first_letter(fileread);  if(cTmp=='T' || cTmp=='t')  capdamagemodifier[object][damagetype][3]|=DAMAGEINVERT;
  4561.                                                     if(cTmp=='C' || cTmp=='c')  capdamagemodifier[object][damagetype][3]|=DAMAGECHARGE;
  4562.             damagetype++;
  4563.         }
  4564.         goto_colon(fileread);
  4565.             fscanf(fileread, "%f", &fTmp);  capmaxaccel[object][0] = fTmp/80.0;
  4566.             fscanf(fileread, "%f", &fTmp);  capmaxaccel[object][1] = fTmp/80.0;
  4567.             fscanf(fileread, "%f", &fTmp);  capmaxaccel[object][2] = fTmp/80.0;
  4568.             fscanf(fileread, "%f", &fTmp);  capmaxaccel[object][3] = fTmp/80.0;
  4569.  
  4570.  
  4571.         // Experience and level data
  4572.         capexperienceforlevel[object][0] = 0;
  4573.         level = 1;
  4574.         while(level < MAXLEVEL)
  4575.         {
  4576.             goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  capexperienceforlevel[object][level] = iTmp;
  4577.             level++;
  4578.         }
  4579.         goto_colon(fileread);  read_pair(fileread);
  4580.             pairbase = pairbase>>8;
  4581.             pairrand = pairrand>>8;
  4582.             if(pairrand < 1)  pairrand = 1;
  4583.             capexperiencebase[object] = pairbase;
  4584.             capexperiencerand[object] = pairrand;
  4585.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  capexperienceworth[object] = iTmp;
  4586.         goto_colon(fileread);  fscanf(fileread, "%f", &fTmp);  capexperienceexchange[object] = fTmp;
  4587.         xptype = 0;
  4588.         while(xptype < MAXEXPERIENCETYPE)
  4589.         {
  4590.             goto_colon(fileread);  fscanf(fileread, "%f", &fTmp);  capexperiencerate[object][xptype] = fTmp+0.001;
  4591.             xptype++;
  4592.         }
  4593.  
  4594.  
  4595.         // IDSZ tags
  4596.         idsz = 0;
  4597.         while(idsz < MAXIDSZ)
  4598.         {
  4599.             goto_colon(fileread);  iTmp = get_idsz(fileread);  capidsz[object][idsz] = iTmp;
  4600.             idsz++;
  4601.         }
  4602.  
  4603.  
  4604.         // Item and damage flags
  4605.         goto_colon(fileread);  cTmp = get_first_letter(fileread);
  4606.             capisitem[object] = FALSE;  capripple[object] = TRUE;
  4607.             if(cTmp=='T' || cTmp=='t')  { capisitem[object] = TRUE; capripple[object] = FALSE; }
  4608.         goto_colon(fileread);  cTmp = get_first_letter(fileread);
  4609.             capismount[object] = FALSE;
  4610.             if(cTmp=='T' || cTmp=='t')  capismount[object] = TRUE;
  4611.         goto_colon(fileread);  cTmp = get_first_letter(fileread);
  4612.             capisstackable[object] = FALSE;
  4613.             if(cTmp=='T' || cTmp=='t')  capisstackable[object] = TRUE;
  4614.         goto_colon(fileread);  cTmp = get_first_letter(fileread);
  4615.             capnameknown[object] = FALSE;
  4616.             if(cTmp=='T' || cTmp=='t')  capnameknown[object] = TRUE;
  4617.         goto_colon(fileread);  cTmp = get_first_letter(fileread);
  4618.             capusageknown[object] = FALSE;
  4619.             if(cTmp=='T' || cTmp=='t')  capusageknown[object] = TRUE;
  4620.         goto_colon(fileread);  cTmp = get_first_letter(fileread);
  4621.             capcancarrytonextmodule[object] = FALSE;
  4622.             if(cTmp=='T' || cTmp=='t')  capcancarrytonextmodule[object] = TRUE;
  4623.         goto_colon(fileread);  cTmp = get_first_letter(fileread);
  4624.             capneedskillidtouse[object] = FALSE;
  4625.             if(cTmp=='T' || cTmp=='t')  capneedskillidtouse[object] = TRUE;
  4626.         goto_colon(fileread);  cTmp = get_first_letter(fileread);
  4627.             capplatform[object] = FALSE;
  4628.             if(cTmp=='T' || cTmp=='t')  capplatform[object] = TRUE;
  4629.         goto_colon(fileread);  cTmp = get_first_letter(fileread);
  4630.             capcangrabmoney[object] = FALSE;
  4631.             if(cTmp=='T' || cTmp=='t')  capcangrabmoney[object] = TRUE;
  4632.         goto_colon(fileread);  cTmp = get_first_letter(fileread);
  4633.             capcanopenstuff[object] = FALSE;
  4634.             if(cTmp=='T' || cTmp=='t')  capcanopenstuff[object] = TRUE;
  4635.  
  4636.  
  4637.  
  4638.         // More item and damage stuff
  4639.         goto_colon(fileread);  cTmp = get_first_letter(fileread);
  4640.             if(cTmp=='S' || cTmp=='s')  capdamagetargettype[object] = DAMAGESLASH;
  4641.             if(cTmp=='C' || cTmp=='c')  capdamagetargettype[object] = DAMAGECRUSH;
  4642.             if(cTmp=='P' || cTmp=='p')  capdamagetargettype[object] = DAMAGEPOKE;
  4643.             if(cTmp=='H' || cTmp=='h')  capdamagetargettype[object] = DAMAGEHOLY;
  4644.             if(cTmp=='E' || cTmp=='e')  capdamagetargettype[object] = DAMAGEEVIL;
  4645.             if(cTmp=='F' || cTmp=='f')  capdamagetargettype[object] = DAMAGEFIRE;
  4646.             if(cTmp=='I' || cTmp=='i')  capdamagetargettype[object] = DAMAGEICE;
  4647.             if(cTmp=='Z' || cTmp=='z')  capdamagetargettype[object] = DAMAGEZAP;
  4648.         goto_colon(fileread);  cTmp = get_first_letter(fileread);
  4649.             capweaponaction[object] = what_action(cTmp);
  4650.  
  4651.  
  4652.         // Particle attachments
  4653.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  capattachedprtamount[object] = iTmp;
  4654.         goto_colon(fileread);  cTmp = get_first_letter(fileread);
  4655.             if(cTmp=='N' || cTmp=='n')  capattachedprtreaffirmdamagetype[object] = DAMAGENULL;
  4656.             if(cTmp=='S' || cTmp=='s')  capattachedprtreaffirmdamagetype[object] = DAMAGESLASH;
  4657.             if(cTmp=='C' || cTmp=='c')  capattachedprtreaffirmdamagetype[object] = DAMAGECRUSH;
  4658.             if(cTmp=='P' || cTmp=='p')  capattachedprtreaffirmdamagetype[object] = DAMAGEPOKE;
  4659.             if(cTmp=='H' || cTmp=='h')  capattachedprtreaffirmdamagetype[object] = DAMAGEHOLY;
  4660.             if(cTmp=='E' || cTmp=='e')  capattachedprtreaffirmdamagetype[object] = DAMAGEEVIL;
  4661.             if(cTmp=='F' || cTmp=='f')  capattachedprtreaffirmdamagetype[object] = DAMAGEFIRE;
  4662.             if(cTmp=='I' || cTmp=='i')  capattachedprtreaffirmdamagetype[object] = DAMAGEICE;
  4663.             if(cTmp=='Z' || cTmp=='z')  capattachedprtreaffirmdamagetype[object] = DAMAGEZAP;
  4664.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  capattachedprttype[object] = iTmp;
  4665.  
  4666.  
  4667.         // Character hands
  4668.         capgripvalid[object][0] = FALSE;
  4669.         capgripvalid[object][1] = FALSE;
  4670.         goto_colon(fileread);  cTmp = get_first_letter(fileread);
  4671.             if(cTmp=='T' || cTmp=='t')  capgripvalid[object][0] = TRUE;
  4672.         goto_colon(fileread);  cTmp = get_first_letter(fileread);
  4673.             if(cTmp=='T' || cTmp=='t')  capgripvalid[object][1] = TRUE;
  4674.  
  4675.  
  4676.  
  4677.  
  4678.         // Attack order ( weapon )
  4679.         goto_colon(fileread);  cTmp = get_first_letter(fileread);
  4680.             capattackattached[object] = FALSE;
  4681.             if(cTmp=='T' || cTmp=='t')  capattackattached[object] = TRUE;
  4682.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  capattackprttype[object] = iTmp;
  4683.  
  4684.  
  4685.         // GoPoof
  4686.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  capgopoofprtamount[object] = iTmp;
  4687.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  capgopoofprtfacingadd[object] = iTmp;
  4688.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  capgopoofprttype[object] = iTmp;
  4689.  
  4690.  
  4691.         // Blood
  4692.         goto_colon(fileread);  cTmp = get_first_letter(fileread);
  4693.             capbloodvalid[object] = FALSE;
  4694.             if(cTmp=='T' || cTmp=='t')  capbloodvalid[object] = TRUE;
  4695.             if(cTmp=='U' || cTmp=='u')  capbloodvalid[object] = ULTRABLOODY;
  4696.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  capbloodprttype[object] = iTmp;
  4697.  
  4698.  
  4699.         // Stuff I forgot
  4700.         goto_colon(fileread);  cTmp = get_first_letter(fileread);
  4701.             capwaterwalk[object] = FALSE;
  4702.             if(cTmp=='T' || cTmp=='t')  capwaterwalk[object] = TRUE;
  4703.         goto_colon(fileread);  fscanf(fileread, "%f", &fTmp);  capdampen[object] = fTmp;
  4704.  
  4705.  
  4706.         // More stuff I forgot
  4707.         goto_colon(fileread);  fscanf(fileread, "%f", &fTmp);  caplifeheal[object] = fTmp*256;
  4708.         goto_colon(fileread);  fscanf(fileread, "%f", &fTmp);  capmanacost[object] = fTmp*256;
  4709.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  caplifereturn[object] = iTmp;
  4710.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  capstoppedby[object] = iTmp|MESHFXIMPASS;
  4711.         goto_colon(fileread);  get_name(fileread, capskinname[object][0]);
  4712.         goto_colon(fileread);  get_name(fileread, capskinname[object][1]);
  4713.         goto_colon(fileread);  get_name(fileread, capskinname[object][2]);
  4714.         goto_colon(fileread);  get_name(fileread, capskinname[object][3]);
  4715.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  capskincost[object][0] = iTmp;
  4716.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  capskincost[object][1] = iTmp;
  4717.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  capskincost[object][2] = iTmp;
  4718.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);  capskincost[object][3] = iTmp;
  4719.         goto_colon(fileread);  fscanf(fileread, "%f", &fTmp);  capstrengthdampen[object] = fTmp;
  4720.  
  4721.  
  4722.  
  4723.         // Another memory lapse
  4724.         goto_colon(fileread);  cTmp = get_first_letter(fileread);
  4725.             capridercanattack[object] = TRUE;
  4726.             if(cTmp=='T' || cTmp=='t')  capridercanattack[object] = FALSE;
  4727.         goto_colon(fileread);  cTmp = get_first_letter(fileread);  // Can be dazed
  4728.             capcanbedazed[object] = FALSE;
  4729.             if(cTmp=='T' || cTmp=='t')  capcanbedazed[object] = TRUE;
  4730.         goto_colon(fileread);  cTmp = get_first_letter(fileread);  // Can be grogged
  4731.             capcanbegrogged[object] = FALSE;
  4732.             if(cTmp=='T' || cTmp=='t')  capcanbegrogged[object] = TRUE;
  4733.         goto_colon(fileread);  // !!!BAD!!! Life add
  4734.         goto_colon(fileread);  // !!!BAD!!! Mana add
  4735.         goto_colon(fileread);  cTmp = get_first_letter(fileread);  // Can see invisible
  4736.             capcanseeinvisible[object] = FALSE;
  4737.             if(cTmp=='T' || cTmp=='t')  capcanseeinvisible[object] = TRUE;
  4738.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);      // Chance of kursed
  4739.             capkursechance[object] = iTmp;
  4740.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);      // Footfall sound
  4741.             if(iTmp < -1) iTmp = -1;
  4742.             if(iTmp > MAXWAVE-1) iTmp = MAXWAVE-1;
  4743.             capwavefootfall[object] = iTmp;
  4744.         goto_colon(fileread);  fscanf(fileread, "%d", &iTmp);      // Jump sound
  4745.             if(iTmp < -1) iTmp = -1;
  4746.             if(iTmp > MAXWAVE-1) iTmp = MAXWAVE-1;
  4747.             capwavejump[object] = iTmp;
  4748.  
  4749.  
  4750.         // Clear expansions...
  4751.         capskindressy[object] = FALSE;
  4752.         capresistbumpspawn[object] = FALSE;
  4753.         capistoobig[object] = FALSE;
  4754.         capreflect[object] = TRUE;
  4755.         capalwaysdraw[object] = FALSE;
  4756.         capisranged[object] = FALSE;
  4757.         caphidestate[object] = NOHIDE;
  4758.         capisequipment[object] = FALSE;
  4759.         capbumpsizebig[object] = capbumpsize[object]+(capbumpsize[object]>>1);
  4760.         capcanseekurse[object] = FALSE;
  4761.         capmoney[object] = 0;
  4762.         capicon[object] = capusageknown[object];
  4763.         capforceshadow[object] = FALSE;
  4764.         capskinoverride[object] = NOSKINOVERRIDE;
  4765.         capcontentoverride[object] = 0;
  4766.         capstateoverride[object] = 0;
  4767.         capleveloverride[object] = 0;
  4768.         capcanuseplatforms[object] = !capplatform[object];
  4769.         // Read expansions
  4770.         while(goto_colon_yesno(fileread))
  4771.         {
  4772.             idsz = get_idsz(fileread);
  4773.             fscanf(fileread, "%c%d", &cTmp, &iTmp);
  4774.             test = ('D'-'A'<<15)|('R'-'A'<<10)|('E'-'A'<<5)|('S'-'A');  // [DRES]
  4775.             if(idsz == test)  capskindressy[object]|= 1<<iTmp;
  4776.             test = ('G'-'A'<<15)|('O'-'A'<<10)|('L'-'A'<<5)|('D'-'A');  // [GOLD]
  4777.             if(idsz == test)  capmoney[object] = iTmp;
  4778.             test = ('S'-'A'<<15)|('T'-'A'<<10)|('U'-'A'<<5)|('K'-'A');  // [STUK]
  4779.             if(idsz == test)  capresistbumpspawn[object] = 1-iTmp;
  4780.             test = ('P'-'A'<<15)|('A'-'A'<<10)|('C'-'A'<<5)|('K'-'A');  // [PACK]
  4781.             if(idsz == test)  capistoobig[object] = 1-iTmp;
  4782.             test = ('V'-'A'<<15)|('A'-'A'<<10)|('M'-'A'<<5)|('P'-'A');  // [VAMP]
  4783.             if(idsz == test)  capreflect[object] = 1-iTmp;
  4784.             test = ('D'-'A'<<15)|('R'-'A'<<10)|('A'-'A'<<5)|('W'-'A');  // [DRAW]
  4785.             if(idsz == test)  capalwaysdraw[object] = iTmp;
  4786.             test = ('R'-'A'<<15)|('A'-'A'<<10)|('N'-'A'<<5)|('G'-'A');  // [RANG]
  4787.             if(idsz == test)  capisranged[object] = iTmp;
  4788.             test = ('H'-'A'<<15)|('I'-'A'<<10)|('D'-'A'<<5)|('E'-'A');  // [HIDE]
  4789.             if(idsz == test)  caphidestate[object] = iTmp;
  4790.             test = ('E'-'A'<<15)|('Q'-'A'<<10)|('U'-'A'<<5)|('I'-'A');  // [EQUI]
  4791.             if(idsz == test)  capisequipment[object] = iTmp;
  4792.             test = ('S'-'A'<<15)|('Q'-'A'<<10)|('U'-'A'<<5)|('A'-'A');  // [SQUA]
  4793.             if(idsz == test)  capbumpsizebig[object] = capbumpsize[object]<<1;
  4794.             test = ('I'-'A'<<15)|('C'-'A'<<10)|('O'-'A'<<5)|('N'-'A');  // [ICON]
  4795.             if(idsz == test)  capicon[object] = iTmp;
  4796.             test = ('S'-'A'<<15)|('H'-'A'<<10)|('A'-'A'<<5)|('D'-'A');  // [SHAD]
  4797.             if(idsz == test)  capforceshadow[object] = iTmp;
  4798.             test = ('C'-'A'<<15)|('K'-'A'<<10)|('U'-'A'<<5)|('R'-'A');  // [CKUR]
  4799.             if(idsz == test)  capcanseekurse[object] = iTmp;
  4800.             test = ('S'-'A'<<15)|('K'-'A'<<10)|('I'-'A'<<5)|('N'-'A');  // [SKIN]
  4801.             if(idsz == test)  capskinoverride[object] = iTmp&3;
  4802.             test = ('C'-'A'<<15)|('O'-'A'<<10)|('N'-'A'<<5)|('T'-'A');  // [CONT]
  4803.             if(idsz == test)  capcontentoverride[object] = iTmp;
  4804.             test = ('S'-'A'<<15)|('T'-'A'<<10)|('A'-'A'<<5)|('T'-'A');  // [STAT]
  4805.             if(idsz == test)  capstateoverride[object] = iTmp;
  4806.             test = ('L'-'A'<<15)|('E'-'A'<<10)|('V'-'A'<<5)|('L'-'A');  // [LEVL]
  4807.             if(idsz == test)  capleveloverride[object] = iTmp;
  4808.             test = ('P'-'A'<<15)|('L'-'A'<<10)|('A'-'A'<<5)|('T'-'A');  // [PLAT]
  4809.             if(idsz == test)  capcanuseplatforms[object] = iTmp;
  4810.             test = ('R'-'A'<<15)|('I'-'A'<<10)|('P'-'A'<<5)|('P'-'A');  // [RIPP]
  4811.             if(idsz == test)  capripple[object] = iTmp;
  4812.         }
  4813.         fclose(fileread);
  4814.     }
  4815.     else
  4816.     {
  4817.         // The data file wasn't found
  4818.         general_error(0, 0, "DATA.TXT NOT FOUND");
  4819.     }
  4820.  
  4821.     return object;
  4822. }
  4823.  
  4824. //--------------------------------------------------------------------------------------------
  4825. int get_skin(char *filename)
  4826. {
  4827.     // ZZ> This function reads the skin.txt file...
  4828.     FILE*   fileread;
  4829.     int skin;
  4830.  
  4831.  
  4832.     skin = 0;
  4833.     fileread = fopen(FILENAME(filename), "r");
  4834.     if(fileread)
  4835.     {
  4836.         goto_colon_yesno(fileread);
  4837.         fscanf(fileread, "%d", &skin);
  4838.         skin = skin & 3;
  4839.         fclose(fileread);
  4840.     }
  4841.     return skin;
  4842. }
  4843.  
  4844. //--------------------------------------------------------------------------------------------
  4845. void check_player_import(char *dirname)
  4846. {
  4847.     // ZZ> This function figures out which players may be imported, and loads basic
  4848.     //     data for each
  4849.     char searchname[128];
  4850.     char filename[128];
  4851.     int skin;
  4852.     BOOL keeplooking;
  4853.     char *foundfile;
  4854.  
  4855.  
  4856.     // Set up...
  4857.     numloadplayer = 0;
  4858.  
  4859.     // Search for all objects
  4860.     sprintf(searchname, FILENAME("%s/*.obj"), dirname);
  4861.     foundfile = DirGetFirst(searchname);
  4862.     keeplooking = 1;
  4863.     if(foundfile != NULL)
  4864.     {
  4865.         while(keeplooking && numloadplayer < MAXLOADPLAYER)
  4866.         {
  4867.             //fprintf(stderr,"foundfile=%s keeplooking=%d numload=%d/%d\n",foundfile,keeplooking,numloadplayer,MAXLOADPLAYER);
  4868.             prime_names();
  4869.             sprintf(loadplayerdir[numloadplayer], "%s", foundfile);
  4870.             sprintf(filename, FILENAME("%s/%s/skin.txt"), dirname, foundfile);
  4871.             skin = get_skin(filename);
  4872.             sprintf(filename, FILENAME("%s/%s/icon%d.bmp"), dirname, foundfile, skin);
  4873.             load_one_icon(filename);
  4874.             sprintf(filename, FILENAME("%s/%s/naming.txt"), dirname, foundfile);
  4875.             read_naming(0, filename);
  4876.             naming_names(0);
  4877.             sprintf(loadplayername[numloadplayer], "%s", namingnames);
  4878.             numloadplayer++;
  4879.             foundfile=DirGetNext();
  4880.             if(foundfile==NULL) keeplooking=0; else keeplooking=1;
  4881.         }
  4882.     }
  4883.     DirClose();
  4884.     nullicon = globalnumicon;
  4885.     load_one_icon("basicdat/nullicon.bmp");
  4886.     keybicon = globalnumicon;
  4887.     load_one_icon("basicdat/keybicon.bmp");
  4888.     mousicon = globalnumicon;
  4889.     load_one_icon("basicdat/mousicon.bmp");
  4890.     joyaicon = globalnumicon;
  4891.     load_one_icon("basicdat/joyaicon.bmp");
  4892.     joybicon = globalnumicon;
  4893.     load_one_icon("basicdat/joybicon.bmp");
  4894.     keybplayer = 0;
  4895.     mousplayer = 0;
  4896.     joyaplayer = 0;
  4897.     joybplayer = 0;
  4898. }
  4899.  
  4900.