Advertisement
Guest User

Untitled

a guest
Sep 26th, 2016
341
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 46.69 KB | None | 0 0
  1. // Emacs style mode select   -*- C++ -*-
  2. //-----------------------------------------------------------------------------
  3. //
  4. // $Id:$
  5. //
  6. // Copyright (C) 1993-1996 by id Software, Inc.
  7. //
  8. // This source is available for distribution and/or modification
  9. // only under the terms of the DOOM Source Code License as
  10. // published by id Software. All rights reserved.
  11. //
  12. // The source is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
  15. // for more details.
  16. //
  17. // $Log:$
  18. //
  19. // DESCRIPTION:
  20. //      Refresh of things, i.e. objects represented by sprites.
  21. //
  22. //-----------------------------------------------------------------------------
  23.  
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26.  
  27. #include "templates.h"
  28. #include "m_alloc.h"
  29. #include "doomdef.h"
  30. #include "m_swap.h"
  31. #include "m_argv.h"
  32. #include "i_system.h"
  33. #include "z_zone.h"
  34. #include "w_wad.h"
  35. #include "r_local.h"
  36. #include "p_effect.h"
  37. #include "c_console.h"
  38. #include "c_cvars.h"
  39. #include "c_dispatch.h"
  40. #include "doomstat.h"
  41. #include "v_video.h"
  42. #include "sc_man.h"
  43. #include "s_sound.h"
  44. #include "sbar.h"
  45. #include "gi.h"
  46.  
  47. extern fixed_t globaluclip, globaldclip;
  48.  
  49.  
  50. #define MINZ            (2048*4)
  51. #define BASEYCENTER     (100)
  52.  
  53. EXTERN_CVAR (Bool, st_scale)
  54. CVAR (Bool, r_drawfuzz, true, CVAR_ARCHIVE)
  55.  
  56.  
  57. //
  58. // Sprite rotation 0 is facing the viewer,
  59. //  rotation 1 is one angle turn CLOCKWISE around the axis.
  60. // This is not the same as the angle,
  61. //  which increases counter clockwise (protractor).
  62. //
  63. fixed_t         pspritexscale;
  64. fixed_t         pspriteyscale;
  65. fixed_t         pspritexiscale;
  66. fixed_t         sky1scale;          // [RH] Sky 1 scale factor
  67. fixed_t         sky2scale;          // [RH] Sky 2 scale factor
  68.  
  69. static int      spriteshade;
  70.  
  71. TArray<WORD>    ParticlesInSubsec;
  72.  
  73. // constant arrays
  74. //  used for psprite clipping and initializing clipping
  75. short           negonearray[MAXWIDTH];
  76. short           screenheightarray[MAXWIDTH];
  77.  
  78. #define MAX_SPRITE_FRAMES   29      // [RH] Macro-ized as in BOOM.
  79.  
  80.  
  81. CVAR (Bool, r_drawplayersprites, true, 0)   // [RH] Draw player sprites?
  82.  
  83. //
  84. // INITIALIZATION FUNCTIONS
  85. //
  86.  
  87. // variables used to look up
  88. //  and range check thing_t sprites patches
  89. TArray<spritedef_t> sprites;
  90.  
  91. spriteframe_t   sprtemp[MAX_SPRITE_FRAMES];
  92. int             maxframe;
  93. char*           spritename;
  94.  
  95. // [RH] skin globals
  96. FPlayerSkin     *skins;
  97. size_t          numskins;
  98.  
  99. // [RH] particle globals
  100. int             NumParticles;
  101. int             ActiveParticles;
  102. int             InactiveParticles;
  103. particle_t      *Particles;
  104.  
  105. CVAR (Bool, r_particles, true, 0);
  106.  
  107.  
  108. //
  109. // R_InstallSpriteLump
  110. // Local function for R_InitSprites.
  111. //
  112. // [RH] Removed checks for coexistance of rotation 0 with other
  113. //      rotations and made it look more like BOOM's version.
  114. //
  115. static void R_InstallSpriteLump (int lump, unsigned frame, char rot, BOOL flipped)
  116. {
  117.     unsigned rotation;
  118.  
  119.     if (rot >= '0' && rot <= '9')
  120.     {
  121.         rotation = rot - '0';
  122.     }
  123.     else if (rot >= 'A')
  124.     {
  125.         rotation = rot - 'A' + 10;
  126.     }
  127.     else
  128.     {
  129.         rotation = 17;
  130.     }
  131.  
  132.     if (frame >= MAX_SPRITE_FRAMES || rotation > 16)
  133.         I_FatalError ("R_InstallSpriteLump: Bad frame characters in lump %i", lump);
  134.  
  135.     if ((int)frame > maxframe)
  136.         maxframe = frame;
  137.                
  138.     if (rotation == 0)
  139.     {
  140.         // the lump should be used for all rotations
  141.         // false=0, true=1, but array initialised to -1
  142.         // allows doom to have a "no value set yet" boolean value!
  143.         int r;
  144.  
  145.         for (r = 14; r >= 0; r -= 2)
  146.         {
  147.             if (sprtemp[frame].lump[r] == -1)
  148.             {
  149.                 sprtemp[frame].lump[r] = (short)(lump);
  150.                 if (flipped)
  151.                 {
  152.                     sprtemp[frame].flip |= 1 << r;
  153.                 }
  154.                 sprtemp[frame].rotate = false;
  155.             }
  156.         }
  157.     }
  158.     else
  159.     {
  160.         if (rotation <= 8)
  161.         {
  162.             rotation = (rotation - 1) * 2;
  163.         }
  164.         else
  165.         {
  166.             rotation = (rotation - 9) * 2 + 1;
  167.         }
  168.  
  169.         if (sprtemp[frame].lump[rotation] == -1)
  170.         {
  171.             // the lump is only used for one rotation
  172.             sprtemp[frame].lump[rotation] = (short)(lump);
  173.             if (flipped)
  174.             {
  175.                 sprtemp[frame].flip |= 1 << rotation;
  176.             }
  177.             sprtemp[frame].rotate = true;
  178.         }
  179.     }
  180. }
  181.  
  182.  
  183. // [RH] Seperated out of R_InitSpriteDefs()
  184. static void R_InstallSprite (int num)
  185. {
  186.     int frame;
  187.  
  188.     if (maxframe == -1)
  189.     {
  190.         sprites[num].numframes = 0;
  191.         return;
  192.     }
  193.  
  194.     maxframe++;
  195.    
  196.     for (frame = 0; frame < maxframe; frame++)
  197.     {
  198.         switch ((int)sprtemp[frame].rotate)
  199.         {
  200.         case -1:
  201.             // no rotations were found for that frame at all
  202.             I_FatalError ("R_InstallSprite: No patches found for %s frame %c", sprites[num].name, frame+'A');
  203.             break;
  204.            
  205.         case 0:
  206.             // only the first rotation is needed
  207.             break;
  208.                    
  209.         case 1:
  210.             // must have all 8 frame pairs
  211.             {
  212.                 int rot;
  213.  
  214.                 for (rot = 0; rot < 8; ++rot)
  215.                 {
  216.                     if (sprtemp[frame].lump[rot*2+1] == -1)
  217.                     {
  218.                         sprtemp[frame].lump[rot*2+1] = sprtemp[frame].lump[rot*2];
  219.                         if (sprtemp[frame].flip & (1 << (rot*2)))
  220.                         {
  221.                             sprtemp[frame].flip |= 1 << (rot*2+1);
  222.                         }
  223.                     }
  224.                     if (sprtemp[frame].lump[rot*2] == -1)
  225.                     {
  226.                         sprtemp[frame].lump[rot*2] = sprtemp[frame].lump[rot*2+1];
  227.                         if (sprtemp[frame].flip & (1 << (rot*2+1)))
  228.                         {
  229.                             sprtemp[frame].flip |= 1 << (rot*2);
  230.                         }
  231.                     }
  232.  
  233.                 }
  234.                 for (rot = 0; rot < 16; ++rot)
  235.                 {
  236.                     if (sprtemp[frame].lump[rot] == -1)
  237.                         I_FatalError ("R_InstallSprite: Sprite %c%c%c%c frame %c is missing rotations",
  238.                                       sprites[num].name[0],
  239.                                       sprites[num].name[1],
  240.                                       sprites[num].name[2],
  241.                                       sprites[num].name[3], frame+'A');
  242.                 }
  243.             }
  244.             break;
  245.         }
  246.     }
  247.    
  248.     // allocate space for the frames present and copy sprtemp to it
  249.     sprites[num].numframes = maxframe;
  250.     sprites[num].spriteframes = (spriteframe_t *)
  251.         Z_Malloc (maxframe * sizeof(spriteframe_t), PU_STATIC, NULL);
  252.     memcpy (sprites[num].spriteframes, sprtemp, maxframe * sizeof(spriteframe_t));
  253. }
  254.  
  255.  
  256. //
  257. // R_InitSpriteDefs
  258. // Pass a null terminated list of sprite names
  259. //  (4 chars exactly) to be used.
  260. // Builds the sprite rotation matrices to account
  261. //  for horizontally flipped sprites.
  262. // Will report an error if the lumps are inconsistant.
  263. // Only called at startup.
  264. //
  265. // Sprite lump names are 4 characters for the actor,
  266. //  a letter for the frame, and a number for the rotation.
  267. // A sprite that is flippable will have an additional
  268. //  letter/number appended.
  269. // The rotation character can be 0 to signify no rotations.
  270. //
  271. void R_InitSpriteDefs ()
  272. {
  273.     size_t i;
  274.     int l;
  275.     int intname;
  276.     int start;
  277.     int end;
  278.                
  279.     start = firstspritelump - 1;
  280.     end = lastspritelump + 1;
  281.        
  282.     // scan all the lump names for each of the names,
  283.     //  noting the highest frame letter.
  284.     // Just compare 4 characters as ints
  285.     for (i = 0; i < sprites.Size (); i++)
  286.     {
  287.         spritename = sprites[i].name;
  288.         memset (sprtemp, -1, sizeof(sprtemp));
  289.         for (int j = 0; j < MAX_SPRITE_FRAMES; ++j)
  290.         {
  291.             sprtemp[j].flip = 0;
  292.         }
  293.                
  294.         maxframe = -1;
  295.         intname = *(int *)spritename;
  296.        
  297.         // scan the lumps,
  298.         //  filling in the frames for whatever is found
  299.         for (l = lastspritelump; l >= firstspritelump; l--)
  300.         {
  301.             if (*(int *)lumpinfo[l].name == intname)
  302.             {
  303.                 R_InstallSpriteLump (l,
  304.                                      lumpinfo[l].name[4] - 'A',
  305.                                      lumpinfo[l].name[5],
  306.                                      false);
  307.  
  308.                 if (lumpinfo[l].name[6])
  309.                     R_InstallSpriteLump (l,
  310.                                      lumpinfo[l].name[6] - 'A',
  311.                                      lumpinfo[l].name[7],
  312.                                      true);
  313.             }
  314.         }
  315.        
  316.         R_InstallSprite (i);
  317.     }
  318. }
  319.  
  320. // [RH]
  321. // R_InitSkins
  322. // Reads in everything applicable to a skin. The skins should have already
  323. // been counted and had their identifiers assigned to namespaces.
  324. //
  325. #define NUMSKINSOUNDS 9
  326. static const char *skinsoundnames[NUMSKINSOUNDS][2] = {
  327.     { "dsplpain",   "*pain100" },
  328.     { "dspldeth",   "*death" },
  329.     { "dspdiehi",   "*xdeath" },
  330.     { "dsoof",      "*land" },
  331.     { "dsoof",      "*grunt" },
  332.     { "dsnoway",    "*usefail" },
  333.     { "dsslop",     "*gibbed" },
  334.     { "dspunch",    "*fist" },
  335.     { "dsjump",     "*jump" }
  336. };
  337. static const char painname[3][8] = { "*pain25", "*pain50", "*pain75" };
  338. static WORD playersoundrefs[NUMSKINSOUNDS+3];
  339.  
  340. static int STACK_ARGS skinsorter (const void *a, const void *b)
  341. {
  342.     return stricmp (((FPlayerSkin *)a)->name, ((FPlayerSkin *)b)->name);
  343. }
  344.  
  345. void R_InitSkins (void)
  346. {
  347.     spritedef_t temp;
  348.     int sndlumps[NUMSKINSOUNDS];
  349.     char key[10];
  350.     int intname;
  351.     size_t i;
  352.     int j, k, base;
  353.     int lastlump;
  354.  
  355.     key[9] = 0;
  356.     i = 0;
  357.     lastlump = 0;
  358.  
  359.     for (j = 0; j < NUMSKINSOUNDS; ++j)
  360.     {
  361.         playersoundrefs[j] = S_FindSound (skinsoundnames[j][1]);
  362.     }
  363.     for (j = 0; j < 3; ++j)
  364.     {
  365.         playersoundrefs[j+NUMSKINSOUNDS] = S_FindSound (painname[j]);
  366.     }
  367.  
  368.     while ((base = W_FindLump ("S_SKIN", &lastlump)) != -1)
  369.     {
  370.         // The player sprite has 23 frames. This means that the S_SKIN
  371.         // marker needs a minimum of 23 lumps after it.
  372.         if (base >= numlumps - 23 || base == -1)
  373.             continue;
  374.  
  375.         i++;
  376.         for (j = 0; j < NUMSKINSOUNDS; j++)
  377.             sndlumps[j] = -1;
  378.         skins[i].namespc = lumpinfo[base].namespc;
  379.  
  380.         SC_OpenLumpNum (base, "S_SKIN");
  381.         intname = 0;
  382.  
  383.         // Data is stored as "key = data".
  384.         while (SC_GetString ())
  385.         {
  386.             strncpy (key, sc_String, 9);
  387.             if (!SC_GetString() || sc_String[0] != '=')
  388.             {
  389.                 Printf_Bold ("Bad format for skin %d: %s\n", i, key);
  390.                 break;
  391.             }
  392.             SC_GetString ();
  393.             if (0 == stricmp (key, "name"))
  394.             {
  395.                 strncpy (skins[i].name, sc_String, 16);
  396.                 for (j = 0; (size_t)j < i; j++)
  397.                 {
  398.                     if (stricmp (skins[i].name, skins[j].name) == 0)
  399.                     {
  400.                         sprintf (skins[i].name, "skin%d", i);
  401.                         Printf_Bold ("Skin %s duplicated as %s\n",
  402.                             skins[j].name, skins[i].name);
  403.                         break;
  404.                     }
  405.                 }
  406.             }
  407.             else if (0 == stricmp (key, "sprite"))
  408.             {
  409.                 for (j = 3; j >= 0; j--)
  410.                     sc_String[j] = toupper (sc_String[j]);
  411.                 intname = *((int *)sc_String);
  412.             }
  413.             else if (0 == stricmp (key, "face"))
  414.             {
  415.                 for (j = 2; j >= 0; j--)
  416.                     skins[i].face[j] = toupper (sc_String[j]);
  417.             }
  418.             else if (0 == stricmp (key, "gender"))
  419.             {
  420.                 skins[i].gender = D_GenderToInt (sc_String);
  421.             }
  422.             else
  423.             {
  424.                 for (j = 0; j < NUMSKINSOUNDS; j++)
  425.                 {
  426.                     if (stricmp (key, skinsoundnames[j][0]) == 0)
  427.                     {
  428.                         sndlumps[j] = W_CheckNumForName (sc_String, skins[i].namespc);
  429.                         if (sndlumps[j] == -1)
  430.                         { // Replacement not found, try finding it in the global namespace
  431.                             sndlumps[j] = W_CheckNumForName (sc_String);
  432.                         }
  433.                     }
  434.                 }
  435.                 //if (j == 8)
  436.                 //  Printf ("Funny info for skin %i: %s = %s\n", i, key, sc_String);
  437.             }
  438.         }
  439.  
  440.         if (skins[i].name[0] == 0)
  441.             sprintf (skins[i].name, "skin%d", i);
  442.  
  443.         // Now collect the sprite frames for this skin. If the sprite name was not
  444.         // specified, use whatever immediately follows the specifier lump.
  445.         if (intname == 0)
  446.         {
  447.             intname = *(int *)(lumpinfo[base+1].name);
  448.         }
  449.  
  450.         memset (sprtemp, -1, sizeof(sprtemp));
  451.         for (k = 0; k < MAX_SPRITE_FRAMES; ++k)
  452.         {
  453.             sprtemp[k].flip = 0;
  454.         }
  455.         maxframe = -1;
  456.  
  457.         for (k = base + 1; lumpinfo[k].wadnum == lumpinfo[base].wadnum; k++)
  458.         {
  459.             if (*(int *)lumpinfo[k].name == intname)
  460.             {
  461.                 R_InstallSpriteLump (k,
  462.                                      lumpinfo[k].name[4] - 'A',
  463.                                      lumpinfo[k].name[5],
  464.                                      false);
  465.  
  466.                 if (lumpinfo[k].name[6])
  467.                     R_InstallSpriteLump (k,
  468.                                      lumpinfo[k].name[6] - 'A',
  469.                                      lumpinfo[k].name[7],
  470.                                      true);
  471.             }
  472.         }
  473.  
  474.         if (maxframe <= 0)
  475.         {
  476.             Printf_Bold ("Skin %s (#%d) has no frames. Removing.\n", skins[i].name, i);
  477.             if (i < numskins-1)
  478.                 memmove (&skins[i], &skins[i+1], sizeof(skins[0])*(numskins-i-1));
  479.             i--;
  480.             continue;
  481.         }
  482.  
  483.         strncpy (temp.name, lumpinfo[base+1].name, 4);
  484.         skins[i].sprite = sprites.Push (temp);
  485.         R_InstallSprite (skins[i].sprite);
  486.  
  487.         // Register any sounds this skin provides
  488.         for (j = 0; j < NUMSKINSOUNDS; j++)
  489.         {
  490.             if (sndlumps[j] != -1)
  491.             {
  492.                 int aliasid;
  493.  
  494.                 aliasid = S_AddPlayerSound (skins[i].name, skins[i].gender,
  495.                     playersoundrefs[j], sndlumps[j]);
  496.                 if (j == 0)
  497.                 {
  498.                     for (int l = 3; l > 0; --l)
  499.                     {
  500.                         S_AddPlayerSoundExisting (skins[i].name, skins[i].gender,
  501.                             playersoundrefs[NUMSKINSOUNDS-1+l], aliasid);
  502.                     }
  503.                 }
  504.             }
  505.         }
  506.  
  507.         SC_Close ();
  508.  
  509.         // Make sure face prefix is a full 3 chars
  510.         if (skins[i].face[1] == 0 || skins[i].face[2] == 0)
  511.         {
  512.             skins[i].face[0] = 0;
  513.         }
  514.     }
  515.  
  516.     if (numskins > 1)
  517.     { // The sound table may have changed, so rehash it.
  518.         S_HashSounds ();
  519.         S_ShrinkPlayerSoundLists ();
  520.     }
  521. }
  522.  
  523. // [RH] Find a skin by name
  524. int R_FindSkin (const char *name)
  525. {
  526.     int min, max, mid;
  527.     int lexx;
  528.  
  529.   if (stricmp ("base", name) == 0)
  530.     {
  531.         return 0;
  532.     }
  533.  
  534.     min = 1;
  535.     max = numskins-1;
  536.  
  537.     while (min <= max)
  538.     {
  539.         mid = (min + max)/2;
  540.         lexx = strnicmp (skins[mid].name, name, 16);
  541.         if (lexx == 0)
  542.             return mid;
  543.         else if (lexx < 0)
  544.             min = mid + 1;
  545.         else
  546.             max = mid - 1;
  547.     }
  548.     return 0;
  549. }
  550.  
  551. // [RH] List the names of all installed skins
  552. CCMD (skins)
  553. {
  554.     int i;
  555.  
  556.     for (i = 0; i < (int)numskins; i++)
  557.         Printf ("%3d %s\n", i, skins[i].name);
  558. }
  559.  
  560. //
  561. // GAME FUNCTIONS
  562. //
  563. int             MaxVisSprites;
  564. vissprite_t     *vissprites;
  565. vissprite_t     *firstvissprite;
  566. vissprite_t     *vissprite_p;
  567. vissprite_t     *lastvissprite;
  568. int             newvissprite;
  569.  
  570.  
  571.  
  572. //
  573. // R_InitSprites
  574. // Called at program start.
  575. //
  576. void R_InitSprites ()
  577. {
  578.     byte rangestart, rangeend;
  579.     int lump, lastlump;
  580.     size_t i;
  581.  
  582.     for (i = 0; i < MAXWIDTH; i++)
  583.     {
  584.         negonearray[i] = 0;
  585.     }
  586.  
  587.     MaxVisSprites = 128;    // [RH] This is the initial default value. It grows as needed.
  588.     firstvissprite = vissprites = (vissprite_t *)Malloc (MaxVisSprites * sizeof(vissprite_t));
  589.     lastvissprite = &vissprites[MaxVisSprites];
  590.  
  591.     if (gameinfo.gametype == GAME_Doom)
  592.     {
  593.         rangestart = 112;
  594.         rangeend = 127;
  595.     }
  596.     else if (gameinfo.gametype == GAME_Heretic)
  597.     {
  598.         rangestart = 225;
  599.         rangeend = 240;
  600.     }
  601.     else // Hexen
  602.     {
  603.         rangestart = 146;
  604.         rangeend = 163;
  605.     }
  606.  
  607.     // [RH] Count the number of skins.
  608.     numskins = 1;
  609.     lastlump = 0;
  610.     while ((lump = W_FindLump ("S_SKIN", &lastlump)) != -1)
  611.     {
  612.         numskins++;
  613.     }
  614.  
  615.     // [RH] Do some preliminary setup
  616.     skins = (FPlayerSkin *)Z_Malloc (sizeof(*skins) * numskins, PU_STATIC, 0);
  617.     memset (skins, 0, sizeof(*skins) * numskins);
  618.     for (i = 0; i < numskins; i++)
  619.     {
  620.         skins[i].range0start = rangestart;
  621.         skins[i].range0end = rangeend;
  622.     }
  623.  
  624.     R_InitSpriteDefs ();
  625.     R_InitSkins ();     // [RH] Finish loading skin data
  626.  
  627.     // [RH] Set up base skin
  628.     strcpy (skins[0].name, "Base");
  629.     skins[0].face[0] = 'S';
  630.     skins[0].face[1] = 'T';
  631.     skins[0].face[2] = 'F';
  632.     skins[0].namespc = ns_global;
  633.  
  634.     for (i = 0; i < sprites.Size (); i++)
  635.     {
  636.         if (memcmp (sprites[i].name, deh.PlayerSprite, 4) == 0)
  637.         {
  638.             skins[0].sprite = i;
  639.             break;
  640.         }
  641.     }
  642.  
  643.     // [RH] Sort the skins, but leave base as skin 0
  644.     qsort (&skins[1], numskins-1, sizeof(FPlayerSkin), skinsorter);
  645. }
  646.  
  647.  
  648.  
  649. //
  650. // R_ClearSprites
  651. // Called at frame start.
  652. //
  653. void R_ClearSprites (void)
  654. {
  655.     vissprite_p = firstvissprite;
  656. }
  657.  
  658.  
  659. //
  660. // R_NewVisSprite
  661. //
  662. vissprite_t *R_NewVisSprite (void)
  663. {
  664.     if (vissprite_p == lastvissprite)
  665.     {
  666.         ptrdiff_t firstvisspritenum = firstvissprite - vissprites;
  667.         ptrdiff_t prevvisspritenum = vissprite_p - vissprites;
  668.  
  669.         MaxVisSprites *= 2;
  670.         vissprites = (vissprite_t *)Realloc (vissprites, MaxVisSprites * sizeof(vissprite_t));
  671.         lastvissprite = &vissprites[MaxVisSprites];
  672.         firstvissprite = &vissprites[firstvisspritenum];
  673.         vissprite_p = &vissprites[prevvisspritenum];
  674.         DPrintf ("MaxVisSprites increased to %d\n", MaxVisSprites);
  675.     }
  676.    
  677.     vissprite_p++;
  678.     return vissprite_p-1;
  679. }
  680.  
  681.  
  682. //
  683. // R_DrawMaskedColumn
  684. // Used for sprites and masked mid textures.
  685. // Masked means: partly transparent, i.e. stored
  686. //  in posts/runs of opaque pixels.
  687. //
  688. short*          mfloorclip;
  689. short*          mceilingclip;
  690.  
  691. fixed_t         spryscale;
  692. fixed_t         sprtopscreen;
  693.  
  694. bool            sprflipvert;
  695.  
  696. void R_DrawMaskedColumn (column_t *column)
  697. {
  698.     int top = -1;
  699.  
  700.     while (column->topdelta != 0xff)
  701.     {
  702.         if (column->topdelta <= top)
  703.         {
  704.             top += column->topdelta;
  705.         }
  706.         else
  707.         {
  708.             top = column->topdelta;
  709.         }
  710.  
  711.         if (column->length == 0)
  712.         {
  713.             goto nextpost;
  714.         }
  715.  
  716.         // calculate unclipped screen coordinates for post
  717.         dc_yl = (sprtopscreen + spryscale * top) >> FRACBITS;
  718.         dc_yh = (sprtopscreen + spryscale * (top + column->length) - FRACUNIT) >> FRACBITS;
  719.  
  720.         if (sprflipvert)
  721.         {
  722.             swap (dc_yl, dc_yh);
  723.         }
  724.  
  725.         if (dc_yh >= mfloorclip[dc_x])
  726.         {
  727.             dc_yh = mfloorclip[dc_x] - 1;
  728.         }
  729.         if (dc_yl < mceilingclip[dc_x])
  730.         {
  731.             dc_yl = mceilingclip[dc_x];
  732.         }
  733.  
  734.         if (dc_yl <= dc_yh)
  735.         {
  736.             if (sprflipvert)
  737.             {
  738.                 dc_texturefrac = (dc_yl*dc_iscale) - (top << FRACBITS)
  739.                     - FixedMul (centeryfrac, dc_iscale) - dc_texturemid;
  740.                 const fixed_t maxfrac = column->length << FRACBITS;
  741.                 while (dc_texturefrac >= maxfrac)
  742.                 {
  743.                     if (++dc_yl > dc_yh)
  744.                         goto nextpost;
  745.                     dc_texturefrac += dc_iscale;
  746.                 }
  747.                 fixed_t endfrac = dc_texturefrac + (dc_yh-dc_yl)*dc_iscale;
  748.                 while (endfrac < 0)
  749.                 {
  750.                     if (--dc_yh < dc_yl)
  751.                         goto nextpost;
  752.                     endfrac -= dc_iscale;
  753.                 }
  754.             }
  755.             else
  756.             {
  757.                 dc_texturefrac = dc_texturemid - (top << FRACBITS)
  758.                     + (dc_yl*dc_iscale) - FixedMul (centeryfrac-FRACUNIT, dc_iscale);
  759.                 while (dc_texturefrac < 0)
  760.                 {
  761.                     if (++dc_yl > dc_yh)
  762.                         goto nextpost;
  763.                     dc_texturefrac += dc_iscale;
  764.                 }
  765.                 fixed_t endfrac = dc_texturefrac + (dc_yh-dc_yl)*dc_iscale;
  766.                 const fixed_t maxfrac = column->length << FRACBITS;
  767.                 while (endfrac >= maxfrac)
  768.                 {
  769.                     if (--dc_yh < dc_yl)
  770.                         goto nextpost;
  771.                     endfrac -= dc_iscale;
  772.                 }
  773.             }
  774.             dc_source = (byte *)column + 3;
  775.             colfunc ();
  776.         }
  777. nextpost:
  778.         column = (column_t *)((byte *)column + column->length + 4);
  779.     }
  780. }
  781.  
  782. void R_DrawMaskedColumn2 (column2_t *column)
  783. {
  784.     while (column->Length != 0)
  785.     {
  786.         const int length = column->Length;
  787.         const int top = column->TopDelta;
  788.  
  789.         // calculate unclipped screen coordinates for post
  790.         dc_yl = (sprtopscreen + spryscale * top) >> FRACBITS;
  791.         dc_yh = (sprtopscreen + spryscale * (top + length) - FRACUNIT) >> FRACBITS;
  792.  
  793.         if (sprflipvert)
  794.         {
  795.             swap (dc_yl, dc_yh);
  796.         }
  797.  
  798.         if (dc_yh >= mfloorclip[dc_x])
  799.         {
  800.             dc_yh = mfloorclip[dc_x] - 1;
  801.         }
  802.         if (dc_yl < mceilingclip[dc_x])
  803.         {
  804.             dc_yl = mceilingclip[dc_x];
  805.         }
  806.  
  807.         if (dc_yl <= dc_yh)
  808.         {
  809.             if (sprflipvert)
  810.             {
  811.                 dc_texturefrac = (dc_yl*dc_iscale) - (top << FRACBITS)
  812.                     - FixedMul (centeryfrac, dc_iscale) - dc_texturemid;
  813.                 const fixed_t maxfrac = length << FRACBITS;
  814.                 while (dc_texturefrac >= maxfrac)
  815.                 {
  816.                     if (++dc_yl > dc_yh)
  817.                         goto nextpost;
  818.                     dc_texturefrac += dc_iscale;
  819.                 }
  820.                 fixed_t endfrac = dc_texturefrac + (dc_yh-dc_yl)*dc_iscale;
  821.                 while (endfrac < 0)
  822.                 {
  823.                     if (--dc_yh < dc_yl)
  824.                         goto nextpost;
  825.                     endfrac -= dc_iscale;
  826.                 }
  827.             }
  828.             else
  829.             {
  830.                 dc_texturefrac = dc_texturemid - (top << FRACBITS)
  831.                     + (dc_yl*dc_iscale) - FixedMul (centeryfrac-FRACUNIT, dc_iscale);
  832.                 while (dc_texturefrac < 0)
  833.                 {
  834.                     if (++dc_yl > dc_yh)
  835.                         goto nextpost;
  836.                     dc_texturefrac += dc_iscale;
  837.                 }
  838.                 fixed_t endfrac = dc_texturefrac + (dc_yh-dc_yl)*dc_iscale;
  839.                 const fixed_t maxfrac = length << FRACBITS;
  840.                 while (endfrac >= maxfrac)
  841.                 {
  842.                     if (--dc_yh < dc_yl)
  843.                         goto nextpost;
  844.                     endfrac -= dc_iscale;
  845.                 }
  846.             }
  847.             dc_source = (byte *)column + 4;
  848.             colfunc ();
  849.         }
  850. nextpost:
  851.         column = (column2_t *)((byte *)column + length + 4);
  852.     }
  853. }
  854.  
  855. //
  856. // R_DrawVisSprite
  857. //  mfloorclip and mceilingclip should also be set.
  858. //
  859. void R_DrawVisSprite (vissprite_t *vis, int x1, int x2)
  860. {
  861. #ifdef RANGECHECK
  862.     unsigned int    patchwidth;
  863. #endif
  864.     fixed_t         frac;
  865.     patch_t*        patch;
  866.  
  867.     patch = TileCache[R_CacheTileNum (vis->picnum, PU_CACHE)];
  868.  
  869.     dc_colormap = vis->colormap;
  870.     spryscale = vis->yscale;
  871.     sprflipvert = false;
  872.     dc_iscale = 0xffffffffu / (unsigned)vis->yscale;
  873.     dc_texturemid = vis->texturemid;
  874.     frac = vis->startfrac;
  875.  
  876.     sprtopscreen = centeryfrac - FixedMul (dc_texturemid, spryscale);
  877.  
  878. #ifdef RANGECHECK
  879.     patchwidth = (unsigned)SHORT(patch->width);
  880. #endif
  881.  
  882.     switch (R_SetPatchStyle (vis->RenderStyle, vis->alpha,
  883.         vis->Translation, vis->AlphaColor))
  884.     {
  885.     case DontDraw:
  886.         break;
  887.  
  888.     case DoDraw0:
  889.         // One column at a time
  890.         {
  891.         int x1 = vis->x1, x2 = vis->x2;
  892.         fixed_t xiscale = vis->xiscale;
  893.  
  894.         for (dc_x = x1; dc_x <= x2; dc_x++, frac += xiscale)
  895.         {
  896.             unsigned int texturecolumn = frac>>FRACBITS;
  897.  
  898. #ifdef RANGECHECK
  899.             if (texturecolumn >= patchwidth)
  900.             {
  901.                 DPrintf ("R_DrawSpriteRange: bad texturecolumn (%d)\n", texturecolumn);
  902.                 continue;
  903.             }
  904. #endif
  905.  
  906.             R_DrawMaskedColumn ((column_t *)((byte *)patch + LONG(patch->columnofs[texturecolumn])));
  907.         }
  908.         }
  909.         break;
  910.  
  911.     case DoDraw1:
  912.         // Up to four columns at a time
  913.         {
  914.         int x1 = vis->x1, x2 = vis->x2 + 1;
  915.         fixed_t xiscale = vis->xiscale;
  916.         int stop = x2 & ~3;
  917.  
  918.         if (x1 < x2)
  919.         {
  920.             dc_x = x1;
  921.  
  922.             while ((dc_x < stop) && (dc_x & 3))
  923.             {
  924.                 R_DrawMaskedColumn ((column_t *)((byte *)patch + LONG(patch->columnofs[frac>>FRACBITS])));
  925.                 dc_x++;
  926.                 frac += xiscale;
  927.             }
  928.  
  929.             while (dc_x < stop)
  930.             {
  931.                 rt_initcols();
  932.                 R_DrawMaskedColumnHoriz ((column_t *)((byte *)patch + LONG(patch->columnofs[frac>>FRACBITS])));
  933.                 dc_x++;
  934.                 frac += xiscale;
  935.                 R_DrawMaskedColumnHoriz ((column_t *)((byte *)patch + LONG(patch->columnofs[frac>>FRACBITS])));
  936.                 dc_x++;
  937.                 frac += xiscale;
  938.                 R_DrawMaskedColumnHoriz ((column_t *)((byte *)patch + LONG(patch->columnofs[frac>>FRACBITS])));
  939.                 dc_x++;
  940.                 frac += xiscale;
  941.                 R_DrawMaskedColumnHoriz ((column_t *)((byte *)patch + LONG(patch->columnofs[frac>>FRACBITS])));
  942.                 rt_draw4cols (dc_x - 3);
  943.                 dc_x++;
  944.                 frac += xiscale;
  945.             }
  946.  
  947.             while (dc_x < x2)
  948.             {
  949.                 R_DrawMaskedColumn ((column_t *)((byte *)patch + LONG(patch->columnofs[frac>>FRACBITS])));
  950.                 dc_x++;
  951.                 frac += xiscale;
  952.             }
  953.         }
  954.         }
  955.         break;
  956.     }
  957.  
  958.     R_FinishSetPatchStyle ();
  959. }
  960.  
  961. //
  962. // R_ProjectSprite
  963. // Generates a vissprite for a thing if it might be visible.
  964. //
  965. void R_ProjectSprite (AActor *thing, int fakeside)
  966. {
  967.     fixed_t             fx, fy, fz;
  968.     fixed_t             tr_x;
  969.     fixed_t             tr_y;
  970.    
  971.     fixed_t             gzt;                // killough 3/27/98
  972.     fixed_t             gzb;                // [RH] use bottom of sprite, not actor
  973.     fixed_t             tx, tx2;
  974.     fixed_t             tz;
  975.  
  976.     fixed_t             xscale;
  977.    
  978.     int                 x1;
  979.     int                 x2;
  980.  
  981.     spritedef_t*        sprdef;
  982.     spriteframe_t*      sprframe;
  983.     int                 lump;
  984.    
  985.     WORD                flip;
  986.    
  987.     vissprite_t*        vis;
  988.    
  989.     fixed_t             iscale;
  990.  
  991.     sector_t*           heightsec;          // killough 3/27/98
  992.  
  993.     if ((thing->renderflags & RF_INVISIBLE) ||
  994.         thing->RenderStyle == STYLE_None ||
  995.         (thing->RenderStyle >= STYLE_Translucent && thing->alpha == 0))
  996.     {
  997.         return;
  998.     }
  999.  
  1000.     // [RH] Interpolate the sprite's position to make it look smooth
  1001.     fx = thing->PrevX + FixedMul (r_TicFrac, thing->x - thing->PrevX);
  1002.     fy = thing->PrevY + FixedMul (r_TicFrac, thing->y - thing->PrevY);
  1003.     fz = thing->PrevZ + FixedMul (r_TicFrac, thing->z - thing->PrevZ);
  1004.  
  1005.     // transform the origin point
  1006.     //tr_x = thing->x - viewx;
  1007.     //tr_y = thing->y - viewy;
  1008.     tr_x = fx - viewx;
  1009.     tr_y = fy - viewy;
  1010.  
  1011.     tz = DMulScale20 (tr_x, viewtancos, tr_y, viewtansin);
  1012.  
  1013.     // thing is behind view plane?
  1014.     if (tz < MINZ)
  1015.         return;
  1016.  
  1017.     tx = DMulScale16 (tr_x, viewsin, -tr_y, viewcos);
  1018.  
  1019.     // [RH] Flip for mirrors
  1020.     if (MirrorFlags & RF_XFLIP)
  1021.     {
  1022.         tx = viewwidth - tx - 1;
  1023.     }
  1024.     tx2 = tx >> 4;
  1025.  
  1026.     // too far off the side?
  1027.     if ((abs (tx) >> 6) > tz)
  1028.     {
  1029.         return;
  1030.     }
  1031.  
  1032.     xscale = Scale (centerxfrac, (thing->xscale+1)<<6, tz);
  1033.  
  1034.     // decide which patch to use for sprite relative to player
  1035. #ifdef RANGECHECK
  1036.     if ((unsigned)thing->sprite >= (unsigned)sprites.Size ())
  1037.     {
  1038.         DPrintf ("R_ProjectSprite: invalid sprite number %i\n", thing->sprite);
  1039.         return;
  1040.     }
  1041. #endif
  1042.     sprdef = &sprites[thing->sprite];
  1043.     if (thing->frame >= sprdef->numframes)
  1044.     {
  1045.         DPrintf ("R_ProjectSprite: invalid sprite frame %c%c%c%c: %c (max %c)\n",
  1046.             sprdef->name[0], sprdef->name[1], sprdef->name[2], sprdef->name[3],
  1047.             thing->frame + 'A', sprdef->numframes + 'A' - 1);
  1048.         return;
  1049.     }
  1050.     sprframe = &sprdef->spriteframes[thing->frame];
  1051.  
  1052.     if (sprframe->rotate)
  1053.     {
  1054.         // choose a different rotation based on player view
  1055.         angle_t ang = R_PointToAngle (thing->x, thing->y);
  1056.         unsigned rot = (ang-thing->angle+(unsigned)(ANG45/2)*9)>>28;
  1057.         lump = sprframe->lump[rot];
  1058.         flip = sprframe->flip & (1 << rot);
  1059.     }
  1060.     else
  1061.     {
  1062.         // use single rotation for all views
  1063.         lump = sprframe->lump[0];
  1064.         flip = sprframe->flip & 1;
  1065.     }
  1066.  
  1067.     if (TileSizes[lump].Width == 0xffff)
  1068.     {
  1069.         R_CacheTileNum (lump, PU_CACHE);    // [RH] get sprite's size
  1070.     }
  1071.    
  1072.     // [RH] Added scaling
  1073.     gzt = thing->z + (TileSizes[lump].TopOffset << (FRACBITS-6)) * (thing->yscale+1);
  1074.     gzb = thing->z + ((TileSizes[lump].TopOffset - TileSizes[lump].Height) << (FRACBITS-6)) * (thing->yscale+1);
  1075.  
  1076.     // [RH] Reject sprites that are off the top or bottom of the screen
  1077.     if (MulScale12 (globaluclip, tz) > viewz - gzb ||
  1078.         MulScale12 (globaldclip, tz) < viewz - gzt)
  1079.     {
  1080.         return;
  1081.     }
  1082.  
  1083.     // calculate edges of the shape
  1084.     tx -= TileSizes[lump].LeftOffset << 16;
  1085.     x1 = (centerxfrac + MulScale16 (tx, xscale)) >> FRACBITS;
  1086.  
  1087.     // off the right side?
  1088.     if (x1 > WindowRight)
  1089.         return;
  1090.    
  1091.     tx += TileSizes[lump].Width << 16;
  1092.     x2 = ((centerxfrac + MulScale16 (tx, xscale)) >> FRACBITS) - 1;
  1093.  
  1094.     // off the left side or too small?
  1095.     if (x2 < WindowLeft || x2 < x1)
  1096.         return;
  1097.  
  1098.     // killough 3/27/98: exclude things totally separated
  1099.     // from the viewer, by either water or fake ceilings
  1100.     // killough 4/11/98: improve sprite clipping for underwater/fake ceilings
  1101.  
  1102.     heightsec = thing->Sector->heightsec;
  1103.  
  1104.     if (heightsec != NULL && heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC)
  1105.     {
  1106.         heightsec = NULL;
  1107.     }
  1108.  
  1109.     if (heightsec)  // only clip things which are in special sectors
  1110.     {
  1111.         if (fakeside == FAKED_AboveCeiling)
  1112.         {
  1113.             if (gzt < heightsec->ceilingplane.ZatPoint (thing->x, thing->y))
  1114.                 return;
  1115.         }
  1116.         else if (fakeside == FAKED_BelowFloor)
  1117.         {
  1118.             if (gzb >= heightsec->floorplane.ZatPoint (thing->x, thing->y))
  1119.                 return;
  1120.         }
  1121.         else
  1122.         {
  1123.             if (gzt < heightsec->floorplane.ZatPoint (thing->x, thing->y))
  1124.                 return;
  1125.             if (gzb >= heightsec->ceilingplane.ZatPoint (thing->x, thing->y))
  1126.                 return;
  1127.         }
  1128.     }
  1129.  
  1130.     // [RH] Flip for mirrors and renderflags
  1131.     if ((MirrorFlags ^ thing->renderflags) & RF_XFLIP)
  1132.     {
  1133.         flip = !flip;
  1134.     }
  1135.  
  1136.     // store information in a vissprite
  1137.     vis = R_NewVisSprite ();
  1138.  
  1139.     // killough 3/27/98: save sector for special clipping later
  1140.     vis->heightsec = heightsec;
  1141.  
  1142.     vis->renderflags = thing->renderflags;
  1143.     vis->RenderStyle = thing->RenderStyle;
  1144.     vis->AlphaColor = thing->alphacolor;
  1145.     vis->xscale = xscale;
  1146.     vis->yscale = Scale (InvZtoScale, (thing->yscale+1)<<6, tz);
  1147.     vis->depth = tz;
  1148.     vis->cx = tx2;
  1149.     vis->gx = thing->x;
  1150.     vis->gy = thing->y;
  1151.     vis->gz = gzb;      // [RH] use gzb, not thing->z
  1152.     vis->gzt = gzt;     // killough 3/27/98
  1153.     vis->floorclip = thing->floorclip;
  1154.     vis->texturemid = (TileSizes[lump].TopOffset << FRACBITS)
  1155.         - SafeDivScale6 (viewz-thing->z, thing->yscale+1) - vis->floorclip;
  1156.     vis->x1 = x1 < WindowLeft ? WindowLeft : x1;
  1157.     vis->x2 = x2 > WindowRight ? WindowRight : x2;
  1158.     vis->Translation = thing->Translation;      // [RH] thing translation table
  1159.     vis->FakeFlatStat = fakeside;
  1160.     vis->alpha = thing->alpha;
  1161.     vis->picnum = lump;
  1162.     iscale = DivScale32 (1, xscale);
  1163.  
  1164.     if (flip)
  1165.     {
  1166.         vis->startfrac = (TileSizes[lump].Width << FRACBITS) - 1;
  1167.         vis->xiscale = -iscale;
  1168.     }
  1169.     else
  1170.     {
  1171.         vis->startfrac = 0;
  1172.         vis->xiscale = iscale;
  1173.     }
  1174.  
  1175.     if (vis->x1 > x1)
  1176.         vis->startfrac += vis->xiscale*(vis->x1-x1);
  1177.    
  1178.     // get light level
  1179.     if (fixedlightlev)
  1180.     {
  1181.         vis->colormap = basecolormap + fixedlightlev;
  1182.     }
  1183.     else if (fixedcolormap)
  1184.     {
  1185.         // fixed map
  1186.         vis->colormap = fixedcolormap;
  1187.     }
  1188.     else if (!foggy && (thing->renderflags & RF_FULLBRIGHT))
  1189.     {
  1190.         // full bright
  1191.         vis->colormap = basecolormap;   // [RH] Use basecolormap
  1192.     }
  1193.     else
  1194.     {
  1195.         // diminished light
  1196.         vis->colormap = basecolormap + (GETPALOOKUP (
  1197.             (fixed_t)DivScale12 (r_SpriteVisibility, tz), spriteshade) << COLORMAPSHIFT);
  1198.     }
  1199. }
  1200.  
  1201.  
  1202. //
  1203. // R_AddSprites
  1204. // During BSP traversal, this adds sprites by sector.
  1205. //
  1206. // killough 9/18/98: add lightlevel as parameter, fixing underwater lighting
  1207. // [RH] Save which side of heightsec sprite is on here.
  1208. void R_AddSprites (sector_t *sec, int lightlevel, int fakeside)
  1209. {
  1210.     AActor *thing;
  1211.  
  1212.     // BSP is traversed by subsector.
  1213.     // A sector might have been split into several
  1214.     //  subsectors during BSP building.
  1215.     // Thus we check whether it was already added.
  1216.     if (sec->thinglist == NULL || sec->validcount == validcount)
  1217.         return;
  1218.  
  1219.     // Well, now it will be done.
  1220.     sec->validcount = validcount;
  1221.  
  1222.     spriteshade = LIGHT2SHADE(lightlevel + r_actualextralight);
  1223.  
  1224.     // Handle all things in sector.
  1225.     for (thing = sec->thinglist; thing; thing = thing->snext)
  1226.     {
  1227.         R_ProjectSprite (thing, fakeside);
  1228.     }
  1229. }
  1230.  
  1231.  
  1232. //
  1233. // R_DrawPSprite
  1234. //
  1235. void R_DrawPSprite (pspdef_t* psp, AActor *owner)
  1236. {
  1237.     fixed_t             tx;
  1238.     int                 x1;
  1239.     int                 x2;
  1240.     spritedef_t*        sprdef;
  1241.     spriteframe_t*      sprframe;
  1242.     int                 lump;
  1243.     BOOL                flip;
  1244.     vissprite_t*        vis;
  1245.     vissprite_t         avis;
  1246.    
  1247.     // decide which patch to use
  1248. #ifdef RANGECHECK
  1249.     if ( (unsigned)psp->state->sprite.index >= (unsigned)sprites.Size ())
  1250.     {
  1251.         DPrintf ("R_DrawPSprite: invalid sprite number %i\n", psp->state->sprite.index);
  1252.         return;
  1253.     }
  1254. #endif
  1255.     sprdef = &sprites[psp->state->sprite.index];
  1256. #ifdef RANGECHECK
  1257.     if (psp->state->GetFrame() >= sprdef->numframes)
  1258.     {
  1259.         DPrintf ("R_DrawPSprite: invalid sprite frame %i : %i\n", psp->state->sprite.index, psp->state->GetFrame());
  1260.         return;
  1261.     }
  1262. #endif
  1263.     sprframe = &sprdef->spriteframes[psp->state->GetFrame()];
  1264.  
  1265.     lump = sprframe->lump[0];
  1266.     flip = (BOOL)sprframe->flip & 1;
  1267.  
  1268.     if (TileSizes[lump].Width == 0xffff)
  1269.     {
  1270.         R_CacheTileNum (lump, PU_CACHE);
  1271.     }
  1272.  
  1273.     // calculate edges of the shape
  1274.     tx = psp->sx-((320/2)<<FRACBITS);
  1275.        
  1276.     tx -= TileSizes[lump].LeftOffset << FRACBITS;
  1277.     x1 = (centerxfrac + FixedMul (tx, pspritexscale)) >>FRACBITS;
  1278.  
  1279.     // off the right side
  1280.     if (x1 > viewwidth)
  1281.         return;
  1282.  
  1283.     tx += TileSizes[lump].Width << FRACBITS;
  1284.     x2 = ((centerxfrac + FixedMul (tx, pspritexscale)) >>FRACBITS) - 1;
  1285.  
  1286.     // off the left side
  1287.     if (x2 < 0)
  1288.         return;
  1289.    
  1290.     // store information in a vissprite
  1291.     vis = &avis;
  1292.     vis->renderflags = owner->renderflags;
  1293.     vis->floorclip = 0;
  1294.     vis->texturemid = (BASEYCENTER<<FRACBITS) -
  1295.         (psp->sy - (TileSizes[lump].TopOffset << FRACBITS));
  1296.     if (camera->player && (RenderTarget != screen ||
  1297.         realviewheight == RenderTarget->GetHeight() ||
  1298.         (RenderTarget->GetWidth() > 320 && !st_scale)))
  1299.     {   // Adjust PSprite for fullscreen views
  1300.         FWeaponInfo *weapon;
  1301.         if (camera->player->powers[pw_weaponlevel2])
  1302.             weapon = wpnlev2info[camera->player->readyweapon];
  1303.         else
  1304.             weapon = wpnlev1info[camera->player->readyweapon];
  1305.         if (weapon && weapon->yadjust)
  1306.         {
  1307.             if (RenderTarget != screen || realviewheight == RenderTarget->GetHeight())
  1308.             {
  1309.                 vis->texturemid -= weapon->yadjust;
  1310.             }
  1311.             else
  1312.             {
  1313.                 vis->texturemid -= FixedMul (StatusBar->GetDisplacement (),
  1314.                     weapon->yadjust);
  1315.             }
  1316.         }
  1317.     }
  1318.     vis->x1 = x1 < 0 ? 0 : x1;
  1319.     vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2;
  1320.     vis->xscale = pspritexscale;
  1321.     vis->yscale = pspriteyscale;
  1322.     vis->Translation = 0;       // [RH] Use default colors
  1323.     vis->alpha = owner->alpha;
  1324.     vis->RenderStyle = owner->RenderStyle;
  1325.     vis->picnum = lump;
  1326.  
  1327.     if (flip)
  1328.     {
  1329.         vis->xiscale = -pspritexiscale;
  1330.         vis->startfrac = (TileSizes[lump].Width << FRACBITS) - 1;
  1331.     }
  1332.     else
  1333.     {
  1334.         vis->xiscale = pspritexiscale;
  1335.         vis->startfrac = 0;
  1336.     }
  1337.  
  1338.     if (vis->x1 > x1)
  1339.         vis->startfrac += vis->xiscale*(vis->x1-x1);
  1340.  
  1341.     if (fixedlightlev)
  1342.     {
  1343.         vis->colormap = basecolormap + fixedlightlev;
  1344.     }
  1345.     else if (fixedcolormap)
  1346.     {
  1347.         // fixed color
  1348.         vis->colormap = fixedcolormap;
  1349.     }
  1350.     else if (psp->state->GetFullbright())
  1351.     {
  1352.         // full bright
  1353.         vis->colormap = basecolormap;   // [RH] use basecolormap
  1354.     }
  1355.     else
  1356.     {
  1357.         // local light
  1358.         vis->colormap = basecolormap + (GETPALOOKUP (0, spriteshade) << COLORMAPSHIFT);
  1359.     }
  1360.     if (camera->player &&
  1361.         camera->player->powers[pw_invisibility] < 4*32 &&
  1362.         !(camera->player->powers[pw_invisibility] & 8))
  1363.     {
  1364.         // shadow draw
  1365.         vis->RenderStyle = STYLE_Normal;
  1366.     }
  1367.        
  1368.     R_DrawVisSprite (vis, vis->x1, vis->x2);
  1369. }
  1370.  
  1371.  
  1372.  
  1373. //
  1374. // R_DrawPlayerSprites
  1375. //
  1376. void R_DrawPlayerSprites (void)
  1377. {
  1378.     int         i;
  1379.     int         lightnum;
  1380.     pspdef_t*   psp;
  1381.     sector_t*   sec;
  1382.     static sector_t tempsec;
  1383.     int         floorlight, ceilinglight;
  1384.    
  1385.     if (!r_drawplayersprites ||
  1386.         !camera->player ||
  1387.         (players[consoleplayer].cheats & CF_CHASECAM))
  1388.         return;
  1389.  
  1390.     sec = R_FakeFlat (camera->Sector, &tempsec, &floorlight,
  1391.         &ceilinglight, false);
  1392.  
  1393.     // [RH] set foggy flag
  1394.     foggy = (level.fadeto || sec->floorcolormap->Fade || sec->ceilingcolormap->Fade);
  1395.     r_actualextralight = foggy ? 0 : extralight << 4;
  1396.  
  1397.     // [RH] set basecolormap
  1398.     basecolormap = sec->floorcolormap->Maps;
  1399.  
  1400.     // get light level
  1401.     lightnum = ((floorlight + ceilinglight) >> 1) + r_actualextralight;
  1402.     spriteshade = LIGHT2SHADE(lightnum) - 24*FRACUNIT;
  1403.  
  1404.     // clip to screen bounds
  1405.     mfloorclip = screenheightarray;
  1406.     mceilingclip = negonearray;
  1407.  
  1408.     if (camera->player != NULL)
  1409.     {
  1410.         fixed_t centerhack = centeryfrac;
  1411.  
  1412.         centery = viewheight >> 1;
  1413.         centeryfrac = centery << FRACBITS;
  1414.  
  1415.         // add all active psprites
  1416.         for (i = 0, psp = camera->player->psprites;
  1417.              i < NUMPSPRITES;
  1418.              i++, psp++)
  1419.         {
  1420.             if (psp->state)
  1421.                 R_DrawPSprite (psp, camera);
  1422.         }
  1423.  
  1424.         centeryfrac = centerhack;
  1425.         centery = centerhack >> FRACBITS;
  1426.     }
  1427. }
  1428.  
  1429.  
  1430.  
  1431.  
  1432. //
  1433. // R_SortVisSprites
  1434. //
  1435. // [RH] The old code for this function used a bubble sort, which was far less
  1436. //      than optimal with large numbers of sprites. I changed it to use the
  1437. //      stdlib qsort() function instead, and now it is a *lot* faster; the
  1438. //      more vissprites that need to be sorted, the better the performance
  1439. //      gain compared to the old function.
  1440. //
  1441. static vissprite_t **spritesorter;
  1442. static int spritesortersize = 0;
  1443. static int vsprcount;
  1444.  
  1445. static int STACK_ARGS sv_compare (const void *arg1, const void *arg2)
  1446. {
  1447.     int diff = (*(vissprite_t **)arg1)->depth - (*(vissprite_t **)arg2)->depth;
  1448.     if (diff == 0)
  1449.         return (*(vissprite_t **)arg2)->gzt - (*(vissprite_t **)arg1)->gzt;
  1450.     return diff;
  1451. }
  1452.  
  1453. void R_SortVisSprites (void)
  1454. {
  1455.     int i;
  1456.     vissprite_t *spr;
  1457.  
  1458.     vsprcount = vissprite_p - firstvissprite;
  1459.  
  1460.     if (!vsprcount)
  1461.         return;
  1462.  
  1463.     if (spritesortersize < MaxVisSprites)
  1464.     {
  1465.         if (spritesorter != NULL)
  1466.             delete[] spritesorter;
  1467.         spritesorter = new vissprite_t *[MaxVisSprites];
  1468.         spritesortersize = MaxVisSprites;
  1469.     }
  1470.  
  1471.     for (i = 0, spr = firstvissprite; i < vsprcount; i++, spr++)
  1472.     {
  1473.         spritesorter[i] = spr;
  1474.     }
  1475.  
  1476.     qsort (spritesorter, vsprcount, sizeof (vissprite_t *), sv_compare);
  1477. }
  1478.  
  1479.  
  1480. //
  1481. // R_DrawSprite
  1482. //
  1483. void R_DrawSprite (vissprite_t *spr)
  1484. {
  1485.     static short clipbot[MAXWIDTH];
  1486.     static short cliptop[MAXWIDTH];
  1487.     drawseg_t *ds;
  1488.     int i;
  1489.     int r1, r2;
  1490.     short topclip, botclip;
  1491.     short *clip1, *clip2;
  1492.  
  1493.     // [RH] Check for particles
  1494.     if (spr->picnum == -1)
  1495.     {
  1496.         R_DrawParticle (spr);
  1497.         return;
  1498.     }
  1499.  
  1500.     // [RH] Quickly reject sprites with bad x ranges.
  1501.     if (spr->x1 > spr->x2)
  1502.         return;
  1503.  
  1504.     // [RH] Initialize the clipping arrays to their largest possible range
  1505.     // instead of using a special "not clipped" value. This eliminates
  1506.     // visual anomalies when looking down and should be faster, too.
  1507.     topclip = 0;
  1508.     botclip = viewheight;
  1509.  
  1510.     // killough 3/27/98:
  1511.     // Clip the sprite against deep water and/or fake ceilings.
  1512.     // [RH] rewrote this to be based on which part of the sector is really visible
  1513.  
  1514.     if (spr->heightsec &&
  1515.         !(spr->heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC))
  1516.     { // only things in specially marked sectors
  1517.         if (spr->FakeFlatStat != FAKED_AboveCeiling)
  1518.         {
  1519.             fixed_t h = spr->heightsec->floorplane.ZatPoint (spr->gx, spr->gy);
  1520.             h = (centeryfrac - FixedMul (h-viewz, spr->yscale)) >> FRACBITS;
  1521.  
  1522.             if (spr->FakeFlatStat == FAKED_BelowFloor)
  1523.             { // seen below floor: clip top
  1524.                 if (h > topclip)
  1525.                 {
  1526.                     topclip = MIN<short> (h, viewheight);
  1527.                 }
  1528.             }
  1529.             else
  1530.             { // seen in the middle: clip bottom
  1531.                 if (h < botclip)
  1532.                 {
  1533.                     botclip = MAX<short> (0, h);
  1534.                 }
  1535.             }
  1536.         }
  1537.         if (spr->FakeFlatStat != FAKED_BelowFloor)
  1538.         {
  1539.             fixed_t h = spr->heightsec->ceilingplane.ZatPoint (spr->gx, spr->gy);
  1540.             h = (centeryfrac - FixedMul (h-viewz, spr->yscale)) >> FRACBITS;
  1541.  
  1542.             if (spr->FakeFlatStat == FAKED_AboveCeiling)
  1543.             { // seen above ceiling: clip bottom
  1544.                 if (h < botclip)
  1545.                 {
  1546.                     botclip = MAX<short> (0, h);
  1547.                 }
  1548.             }
  1549.             else
  1550.             { // seen in the middle: clip top
  1551.                 if (h > topclip)
  1552.                 {
  1553.                     topclip = MIN<short> (h, viewheight);
  1554.                 }
  1555.             }
  1556.         }
  1557.     }
  1558.     // killough 3/27/98: end special clipping for deep water / fake ceilings
  1559.     else if (spr->floorclip)
  1560.     { // [RH] Move floorclip stuff from R_DrawVisSprite to here
  1561.         if (TileSizes[spr->picnum].Width == 0xffff)
  1562.         {
  1563.             R_CacheTileNum (spr->picnum, PU_CACHE);
  1564.         }
  1565.         int clip = ((centeryfrac - FixedMul (spr->texturemid -
  1566.             (TileSizes[spr->picnum].Height<<FRACBITS) +
  1567.             spr->floorclip, spr->yscale)) >> FRACBITS);
  1568.         if (clip < botclip)
  1569.         {
  1570.             botclip = MAX<short> (0, clip);
  1571.         }
  1572.     }
  1573.  
  1574.     i = spr->x2 - spr->x1 + 1;
  1575.     clip1 = clipbot + spr->x1;
  1576.     clip2 = cliptop + spr->x1;
  1577.     do
  1578.     {
  1579.         *clip1++ = botclip;
  1580.         *clip2++ = topclip;
  1581.     } while (--i);
  1582.    
  1583.     // Scan drawsegs from end to start for obscuring segs.
  1584.     // The first drawseg that is closer than the sprite is the clip seg.
  1585.  
  1586.     // Modified by Lee Killough:
  1587.     // (pointer check was originally nonportable
  1588.     // and buggy, by going past LEFT end of array):
  1589.  
  1590.     //      for (ds=ds_p-1 ; ds >= drawsegs ; ds--)    old buggy code
  1591.  
  1592.     for (ds = ds_p; ds-- > firstdrawseg; )  // new -- killough
  1593.     {
  1594.         // determine if the drawseg obscures the sprite
  1595.         if (ds->x1 > spr->x2 || ds->x2 < spr->x1 ||
  1596.             (!(ds->silhouette & SIL_BOTH) && ds->maskedtexturecol == -1 &&
  1597.              !ds->bFogBoundary) )
  1598.         {
  1599.             // does not cover sprite
  1600.             continue;
  1601.         }
  1602.  
  1603.         r1 = MAX<int> (ds->x1, spr->x1);
  1604.         r2 = MIN<int> (ds->x2, spr->x2);
  1605.  
  1606.         if (ds->neardepth > spr->depth || (ds->fardepth > spr->depth &&
  1607.             // Check if sprite is in front of draw seg:
  1608.             DMulScale24 (spr->depth - ds->cy, ds->cdx,
  1609.                          ds->cdy, ds->cx - spr->cx) < 0))
  1610.         {
  1611.             // seg is behind sprite, so draw the mid texture if it has one
  1612.             if (ds->maskedtexturecol != -1 || ds->bFogBoundary)
  1613.                 R_RenderMaskedSegRange (ds, r1, r2);
  1614.             continue;
  1615.         }
  1616.  
  1617.         // clip this piece of the sprite
  1618.         // killough 3/27/98: optimized and made much shorter
  1619.         // [RH] Optimized further (at least for VC++;
  1620.         // other compilers should be at least as good as before)
  1621.  
  1622.         if (ds->silhouette & SIL_BOTTOM) //bottom sil
  1623.         {
  1624.             clip1 = clipbot + r1;
  1625.             clip2 = openings + ds->sprbottomclip + r1 - ds->x1;
  1626.             i = r2 - r1 + 1;
  1627.             do
  1628.             {
  1629.                 if (*clip1 > *clip2)
  1630.                     *clip1 = *clip2;
  1631.                 clip1++;
  1632.                 clip2++;
  1633.             } while (--i);
  1634.         }
  1635.  
  1636.         if (ds->silhouette & SIL_TOP)   // top sil
  1637.         {
  1638.             clip1 = cliptop + r1;
  1639.             clip2 = openings + ds->sprtopclip + r1 - ds->x1;
  1640.             i = r2 - r1 + 1;
  1641.             do
  1642.             {
  1643.                 if (*clip1 < *clip2)
  1644.                     *clip1 = *clip2;
  1645.                 clip1++;
  1646.                 clip2++;
  1647.             } while (--i);
  1648.         }
  1649.     }
  1650.  
  1651.     // all clipping has been performed, so draw the sprite
  1652.  
  1653.     mfloorclip = clipbot;
  1654.     mceilingclip = cliptop;
  1655.     R_DrawVisSprite (spr, spr->x1, spr->x2);
  1656. }
  1657.  
  1658. //
  1659. // R_DrawMasked
  1660. //
  1661. void R_DrawMasked (void)
  1662. {
  1663.     drawseg_t *ds;
  1664.     int i;
  1665.  
  1666.     R_SortVisSprites ();
  1667.  
  1668.     for (i = vsprcount; i > 0; i--)
  1669.     {
  1670.         R_DrawSprite (spritesorter[i-1]);
  1671.     }
  1672.  
  1673.     // render any remaining masked mid textures
  1674.  
  1675.     // Modified by Lee Killough:
  1676.     // (pointer check was originally nonportable
  1677.     // and buggy, by going past LEFT end of array):
  1678.  
  1679.     //      for (ds=ds_p-1 ; ds >= drawsegs ; ds--)    old buggy code
  1680.  
  1681.     for (ds = ds_p; ds-- > firstdrawseg; )  // new -- killough
  1682.     {
  1683.         if (ds->maskedtexturecol != -1 || ds->bFogBoundary)
  1684.         {
  1685.             R_RenderMaskedSegRange (ds, ds->x1, ds->x2);
  1686.         }
  1687.     }
  1688.    
  1689.     // draw the psprites on top of everything
  1690.     //  but does not draw on side views
  1691.     if (!viewangleoffset)
  1692.     {
  1693.         R_DrawPlayerSprites ();
  1694.     }
  1695. }
  1696.  
  1697.  
  1698. //
  1699. // [RH] Particle functions
  1700. //
  1701.  
  1702. void R_InitParticles ()
  1703. {
  1704.     char *i;
  1705.  
  1706.     if ((i = Args.CheckValue ("-numparticles")))
  1707.         NumParticles = atoi (i);
  1708.     if (NumParticles == 0)
  1709.         NumParticles = 4000;
  1710.     else if (NumParticles < 100)
  1711.         NumParticles = 100;
  1712.  
  1713.     Particles = new particle_t[NumParticles * sizeof(particle_t)];
  1714.     R_ClearParticles ();
  1715. }
  1716.  
  1717. void R_ClearParticles ()
  1718. {
  1719.     int i;
  1720.  
  1721.     memset (Particles, 0, NumParticles * sizeof(particle_t));
  1722.     ActiveParticles = NO_PARTICLE;
  1723.     InactiveParticles = 0;
  1724.     for (i = 0; i < NumParticles-1; i++)
  1725.         Particles[i].tnext = i + 1;
  1726.     Particles[i].tnext = NO_PARTICLE;
  1727. }
  1728.  
  1729. // Group particles by subsectors. Because particles are always
  1730. // in motion, there is little benefit to caching this information
  1731. // from one frame to the next.
  1732.  
  1733. WORD filt = 0xffff;
  1734.  
  1735. CCMD (pfilt)
  1736. {
  1737.     if (argv.argc() == 1)
  1738.     {
  1739.         filt = R_PointInSubsector (players[0].mo->x, players[0].mo->y) - subsectors;
  1740.         Printf ("filtering %d\n", filt);
  1741.     }
  1742.     else
  1743.     {
  1744.         filt = 0xffff;
  1745.     }
  1746. }
  1747.  
  1748. void R_FindParticleSubsectors ()
  1749. {
  1750.     if (ParticlesInSubsec.Size() < numsubsectors)
  1751.     {
  1752.         ParticlesInSubsec.Reserve (numsubsectors - ParticlesInSubsec.Size());
  1753.     }
  1754.  
  1755.     clearbufshort (&ParticlesInSubsec[0], numsubsectors, NO_PARTICLE);
  1756.  
  1757.     if (!r_particles)
  1758.     {
  1759.         return;
  1760.     }
  1761.     for (WORD i = ActiveParticles; i != NO_PARTICLE; i = Particles[i].tnext)
  1762.     {
  1763.         subsector_t *ssec = R_PointInSubsector (Particles[i].x, Particles[i].y);
  1764.         int ssnum = ssec-subsectors;
  1765.         if (filt == 0xffff || ssnum == filt)
  1766.         {
  1767.             Particles[i].snext = ParticlesInSubsec[ssnum];
  1768.             ParticlesInSubsec[ssnum] = i;
  1769.         }
  1770.     }
  1771. }
  1772.  
  1773. void R_ProjectParticle (particle_t *particle, const sector_t *sector, int shade, int fakeside)
  1774. {
  1775.     fixed_t             tr_x;
  1776.     fixed_t             tr_y;
  1777.     fixed_t             tx, ty;
  1778.     fixed_t             tz, tiz;
  1779.     fixed_t             xscale, yscale;
  1780.     int                 x1, x2, y1, y2;
  1781.     vissprite_t*        vis;
  1782.     sector_t*           heightsec = NULL;
  1783.     byte*               map;
  1784.  
  1785.     // transform the origin point
  1786.     tr_x = particle->x - viewx;
  1787.     tr_y = particle->y - viewy;
  1788.  
  1789.     tz = DMulScale20 (tr_x, viewtancos, tr_y, viewtansin);
  1790.  
  1791.     // particle is behind view plane?
  1792.     if (tz < MINZ)
  1793.         return;
  1794.  
  1795.     tx = DMulScale20 (tr_x, viewsin, -tr_y, viewcos);
  1796.  
  1797.     // Flip for mirrors
  1798.     if (MirrorFlags & RF_XFLIP)
  1799.     {
  1800.         tx = viewwidth - tx - 1;
  1801.     }
  1802.  
  1803.     // too far off the side?
  1804.     if (tz <= abs (tx))
  1805.         return;
  1806.  
  1807.     tiz = 268435456 / tz;
  1808.     xscale = centerx * tiz;
  1809.  
  1810.     // calculate edges of the shape
  1811.     int psize = particle->size << (12-3);
  1812.  
  1813.     x1 = MAX<int> (WindowLeft, (centerxfrac + MulScale12 (tx-psize, xscale)) >> FRACBITS);
  1814.     x2 = MIN<int> (WindowRight, (centerxfrac + MulScale12 (tx+psize, xscale)) >> FRACBITS);
  1815.  
  1816.     if (x1 >= x2)
  1817.         return;
  1818.  
  1819.     yscale = MulScale16 (yaspectmul, xscale);
  1820.     ty = particle->z - viewz;
  1821.     psize <<= 4;
  1822.     y1 = (centeryfrac - FixedMul (ty+psize, yscale)) >> FRACBITS;
  1823.     y2 = (centeryfrac - FixedMul (ty-psize, yscale)) >> FRACBITS;
  1824.  
  1825.     // Clip the particle now. Because it's a point and projected as its subsector is
  1826.     // entered, we don't need to clip it to drawsegs like a normal sprite.
  1827.  
  1828.     // Clip particles behind walls.
  1829.     if (y1 <  ceilingclip[x1])      y1 = ceilingclip[x1];
  1830.     if (y1 <  ceilingclip[x2-1])    y1 = ceilingclip[x2-1];
  1831.     if (y2 >= floorclip[x1])        y2 = floorclip[x1] - 1;
  1832.     if (y2 >= floorclip[x2-1])      y2 = floorclip[x2-1] - 1;
  1833.  
  1834.     if (y1 >= y2)
  1835.         return;
  1836.  
  1837.     // Clip particles above the ceiling or below the floor.
  1838.     heightsec = sector->heightsec;
  1839.  
  1840.     if (heightsec != NULL && heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC)
  1841.     {
  1842.         heightsec = NULL;
  1843.     }
  1844.  
  1845.     const secplane_t *topplane;
  1846.     const secplane_t *botplane;
  1847.     int toppic;
  1848.     int botpic;
  1849.  
  1850.     if (heightsec)  // only clip things which are in special sectors
  1851.     {
  1852.         if (fakeside == FAKED_AboveCeiling)
  1853.         {
  1854.             topplane = &sector->ceilingplane;
  1855.             botplane = &heightsec->ceilingplane;
  1856.             toppic = sector->ceilingpic;
  1857.             botpic = heightsec->ceilingpic;
  1858.             map = heightsec->floorcolormap->Maps;
  1859.         }
  1860.         else if (fakeside == FAKED_BelowFloor)
  1861.         {
  1862.             topplane = &heightsec->floorplane;
  1863.             botplane = &sector->floorplane;
  1864.             toppic = heightsec->floorpic;
  1865.             botpic = sector->floorpic;
  1866.             map = heightsec->floorcolormap->Maps;
  1867.         }
  1868.         else
  1869.         {
  1870.             topplane = &heightsec->ceilingplane;
  1871.             botplane = &heightsec->floorplane;
  1872.             toppic = heightsec->ceilingpic;
  1873.             botpic = heightsec->floorpic;
  1874.             map = sector->floorcolormap->Maps;
  1875.         }
  1876.     }
  1877.     else
  1878.     {
  1879.         topplane = &sector->ceilingplane;
  1880.         botplane = &sector->floorplane;
  1881.         toppic = sector->ceilingpic;
  1882.         botpic = sector->floorpic;
  1883.         map = sector->floorcolormap->Maps;
  1884.     }
  1885.  
  1886.     if (botpic != skyflatnum && particle->z < botplane->ZatPoint (particle->x, particle->y))
  1887.         return;
  1888.     if (toppic != skyflatnum && particle->z >= topplane->ZatPoint (particle->x, particle->y))
  1889.         return;
  1890.  
  1891.     // store information in a vissprite
  1892.     vis = R_NewVisSprite ();
  1893.     vis->heightsec = heightsec;
  1894.     vis->xscale = xscale;
  1895. //  vis->yscale = FixedMul (xscale, InvZtoScale);
  1896.     vis->yscale = xscale;
  1897.     vis->depth = tz;
  1898.     vis->cx = tx;
  1899.     vis->gx = particle->x;
  1900.     vis->gy = particle->y;
  1901.     vis->gz = y1;
  1902.     vis->gzt = y2;
  1903.     vis->x1 = x1;
  1904.     vis->x2 = x2;
  1905.     vis->Translation = 0;
  1906.     vis->startfrac = particle->color;
  1907.     vis->picnum = -1;
  1908.     vis->renderflags = particle->trans;
  1909.     vis->FakeFlatStat = fakeside;
  1910.     vis->floorclip = 0;
  1911.     vis->heightsec = heightsec;
  1912.  
  1913.     if (fixedcolormap)
  1914.     {
  1915.         vis->colormap = fixedcolormap;
  1916.     }
  1917.     else if (fixedlightlev)
  1918.     {
  1919.         vis->colormap = map + fixedlightlev;
  1920.     }
  1921.     else
  1922.     {
  1923.         vis->colormap = map + (GETPALOOKUP (FixedMul (tiz, r_ParticleVisibility),
  1924.             shade) << COLORMAPSHIFT);
  1925.     }
  1926. }
  1927.  
  1928. static void R_DrawMaskedSegsBehindParticle (const vissprite_t *vis)
  1929. {
  1930.     const int x1 = vis->x1;
  1931.     const int x2 = vis->x2;
  1932.  
  1933.     // Draw any masked textures behind this particle so that when the
  1934.     // particle is drawn, it will be in front of them.
  1935.     for (int p = InterestingDrawsegs.Size(); p-- > FirstInterestingDrawseg; )
  1936.     {
  1937.         drawseg_t *ds = &drawsegs[InterestingDrawsegs[p]];
  1938.         if (ds->x1 >= x2 || ds->x2 < x1)
  1939.         {
  1940.             continue;
  1941.         }
  1942.         if ((//ds->neardepth > vis->depth || (ds->fardepth > vis->depth &&
  1943.             DMulScale24 (vis->depth - ds->cy, ds->cdx,
  1944.                          ds->cdy, ds->cx - vis->cx) < 0))
  1945.         {
  1946.             R_RenderMaskedSegRange (ds, MAX<int> (ds->x1, x1), MIN<int> (ds->x2, x2-1));
  1947.         }
  1948.     }
  1949. }
  1950.  
  1951. void R_DrawParticle (vissprite_t *vis)
  1952. {
  1953.     DWORD *bg2rgb;
  1954.     int spacing;
  1955.     byte *dest;
  1956.     DWORD fg;
  1957.     byte color = vis->colormap[vis->startfrac];
  1958.     int yl = vis->gz;
  1959.     int ycount = vis->gzt - yl;
  1960.     int x1 = vis->x1;
  1961.     int countbase = vis->x2 - x1;
  1962.  
  1963.     R_DrawMaskedSegsBehindParticle (vis);
  1964.  
  1965.     // vis->renderflags holds translucency level (0-255)
  1966.     {
  1967.         fixed_t fglevel, bglevel;
  1968.         DWORD *fg2rgb;
  1969.  
  1970.         fglevel = ((vis->renderflags + 1) << 8) & ~0x3ff;
  1971.         bglevel = FRACUNIT-fglevel;
  1972.         fg2rgb = Col2RGB8[fglevel>>10];
  1973.         bg2rgb = Col2RGB8[bglevel>>10];
  1974.         fg = fg2rgb[color];
  1975.     }
  1976.  
  1977.     spacing = (RenderTarget->GetPitch()<<detailyshift) - countbase;
  1978.     dest = ylookup[yl] + x1;
  1979.  
  1980.     do
  1981.     {
  1982.         int count = countbase;
  1983.         do
  1984.         {
  1985.             DWORD bg = bg2rgb[*dest];
  1986.             bg = (fg+bg) | 0x1f07c1f;
  1987.             *dest++ = RGB32k[0][0][bg & (bg>>15)];
  1988.         } while (--count);
  1989.         dest += spacing;
  1990.     } while (--ycount);
  1991. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement