2020-08-02 17:59:14 +00:00
//-------------------------------------------------------------------------
/*
Copyright ( C ) 2010 - 2019 EDuke32 developers and contributors
Copyright ( C ) 2019 Nuke . YKT
This file is part of NBlood .
NBlood is free software ; you can redistribute it and / or
modify it under the terms of the GNU General Public License version 2
as published by the Free Software Foundation .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE .
See the GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
*/
//-------------------------------------------------------------------------
# include "ns.h" // Must come before everything else!
# include <stdlib.h>
# include <string.h>
# include "build.h"
# include "v_font.h"
2020-12-09 14:56:32 +00:00
# include "blood.h"
2020-08-02 17:59:14 +00:00
# include "zstring.h"
2020-10-04 16:31:48 +00:00
# include "razemenu.h"
2020-08-02 17:59:14 +00:00
# include "gstrings.h"
# include "v_2ddrawer.h"
# include "v_video.h"
# include "v_font.h"
2021-04-05 11:55:36 +00:00
# include "hw_voxels.h"
2021-04-13 18:33:21 +00:00
# include "gamefuncs.h"
2020-08-02 17:59:14 +00:00
BEGIN_BLD_NS
2022-08-27 17:50:43 +00:00
static DAngle gCameraAng ;
2020-08-02 17:59:14 +00:00
int dword_172CE0 [ 16 ] [ 3 ] ;
2021-12-29 19:03:42 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static void RotateYZ ( int * , int * pY , int * pZ , int ang )
2020-08-02 17:59:14 +00:00
{
int oY , oZ , angSin , angCos ;
oY = * pY ;
oZ = * pZ ;
angSin = Sin ( ang ) ;
angCos = Cos ( ang ) ;
2021-12-29 19:03:42 +00:00
* pY = dmulscale30r ( oY , angCos , oZ , - angSin ) ;
* pZ = dmulscale30r ( oY , angSin , oZ , angCos ) ;
2020-08-02 17:59:14 +00:00
}
2021-12-29 19:03:42 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static void RotateXZ ( int * pX , int * , int * pZ , int ang )
2020-08-02 17:59:14 +00:00
{
int oX , oZ , angSin , angCos ;
oX = * pX ;
oZ = * pZ ;
2021-12-29 19:03:42 +00:00
angSin = Sin ( ang ) ;
angCos = Cos ( ang ) ;
* pX = dmulscale30r ( oX , angCos , oZ , - angSin ) ;
* pZ = dmulscale30r ( oX , angSin , oZ , angCos ) ;
2020-08-02 17:59:14 +00:00
}
2021-12-29 19:03:42 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2022-08-07 08:25:15 +00:00
tspritetype * viewInsertTSprite ( tspriteArray & tsprites , sectortype * pSector , int nStatnum , tspritetype const * const parentTSprite )
2020-08-02 17:59:14 +00:00
{
2022-08-07 08:25:15 +00:00
tspritetype * pTSprite = tsprites . newTSprite ( ) ;
2021-12-29 19:03:42 +00:00
memset ( pTSprite , 0 , sizeof ( tspritetype ) ) ;
pTSprite - > cstat = CSTAT_SPRITE_YCENTER ;
pTSprite - > xrepeat = 64 ;
pTSprite - > yrepeat = 64 ;
pTSprite - > ownerActor = nullptr ;
2022-08-07 08:25:15 +00:00
pTSprite - > type = - int ( tsprites . Size ( ) - 1 ) ;
2021-12-29 19:03:42 +00:00
pTSprite - > statnum = nStatnum ;
2021-12-30 15:36:04 +00:00
pTSprite - > sectp = pSector ;
2022-02-02 18:55:11 +00:00
2022-08-10 22:01:00 +00:00
DVector3 pos = { 0 , 0 , 0 } ;
2021-12-29 19:03:42 +00:00
if ( parentTSprite )
{
2022-08-10 22:01:00 +00:00
pos = parentTSprite - > pos ;
2021-12-29 19:03:42 +00:00
pTSprite - > ownerActor = parentTSprite - > ownerActor ;
2022-08-21 10:19:06 +00:00
pTSprite - > angle = parentTSprite - > angle ;
2021-12-29 19:03:42 +00:00
}
2022-08-27 17:50:43 +00:00
pos . X + = gCameraAng . Cos ( ) * 2 ;
pos . Y + = gCameraAng . Sin ( ) * 2 ;
2022-08-10 22:01:00 +00:00
pTSprite - > pos = pos ;
2021-12-29 19:03:42 +00:00
return pTSprite ;
2020-08-02 17:59:14 +00:00
}
2021-07-26 05:59:59 +00:00
static const int effectDetail [ kViewEffectMax ] = {
2021-12-29 19:03:42 +00:00
4 , 4 , 4 , 4 , 0 , 0 , 0 , 0 , 0 , 1 , 4 , 4 , 0 , 0 , 0 , 1 , 0 , 0 , 0
2020-08-02 17:59:14 +00:00
} ;
struct WEAPONICON {
2021-12-29 19:03:42 +00:00
int16_t nTile ;
uint8_t zOffset ;
2020-08-02 17:59:14 +00:00
} ;
static const WEAPONICON gWeaponIcon [ ] = {
2021-12-29 19:03:42 +00:00
{ - 1 , 0 } ,
{ - 1 , 0 } , // 1: pitchfork
{ 524 , 6 } , // 2: flare gun
{ 559 , 6 } , // 3: shotgun
{ 558 , 8 } , // 4: tommy gun
{ 526 , 6 } , // 5: napalm launcher
{ 589 , 11 } , // 6: dynamite
{ 618 , 11 } , // 7: spray can
{ 539 , 6 } , // 8: tesla gun
{ 800 , 0 } , // 9: life leech
{ 525 , 11 } , // 10: voodoo doll
{ 811 , 11 } , // 11: proxy bomb
{ 810 , 11 } , // 12: remote bomb
{ - 1 , 0 } ,
2020-08-02 17:59:14 +00:00
} ;
2021-12-29 19:03:42 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2022-08-07 08:25:15 +00:00
static tspritetype * viewAddEffect ( tspriteArray & tsprites , int nTSprite , VIEW_EFFECT nViewEffect )
2020-08-02 17:59:14 +00:00
{
2021-12-29 19:03:42 +00:00
assert ( nViewEffect > = 0 & & nViewEffect < kViewEffectMax ) ;
2022-08-07 08:25:15 +00:00
auto pTSprite = tsprites . get ( nTSprite ) ;
2021-12-29 19:03:42 +00:00
auto owneractor = static_cast < DBloodActor * > ( pTSprite - > ownerActor ) ;
2022-08-07 08:25:15 +00:00
if ( gDetail < effectDetail [ nViewEffect ] ) return NULL ;
2021-12-29 19:03:42 +00:00
switch ( nViewEffect )
{
case kViewEffectSpotProgress : {
int perc = ( 100 * owneractor - > xspr . data3 ) / kMaxPatrolSpotValue ;
int width = ( 94 * owneractor - > xspr . data3 ) / kMaxPatrolSpotValue ;
int top , bottom ;
GetSpriteExtents ( pTSprite , & top , & bottom ) ;
2022-08-07 08:25:15 +00:00
auto pNSprite2 = viewInsertTSprite ( tsprites , pTSprite - > sectp , 32767 , pTSprite ) ;
2021-12-29 19:03:42 +00:00
if ( ! pNSprite2 )
break ;
pNSprite2 - > picnum = 2203 ;
pNSprite2 - > xrepeat = width ;
pNSprite2 - > yrepeat = 20 ;
pNSprite2 - > pal = 10 ;
if ( perc > = 75 ) pNSprite2 - > pal = 0 ;
else if ( perc > = 50 ) pNSprite2 - > pal = 6 ;
2022-02-02 19:03:02 +00:00
pNSprite2 - > set_int_z ( top - 2048 ) ;
2021-12-29 19:03:42 +00:00
pNSprite2 - > shade = - 128 ;
break ;
}
case kViewEffectAtom :
for ( int i = 0 ; i < 16 ; i + + )
{
2022-08-07 08:25:15 +00:00
auto pNSprite = viewInsertTSprite ( tsprites , pTSprite - > sectp , 32767 , pTSprite ) ;
2021-12-29 19:03:42 +00:00
if ( ! pNSprite )
break ;
int ang = ( PlayClock * 2048 ) / 120 ;
int nRand1 = dword_172CE0 [ i ] [ 0 ] ;
int nRand2 = dword_172CE0 [ i ] [ 1 ] ;
int nRand3 = dword_172CE0 [ i ] [ 2 ] ;
ang + = nRand3 ;
int x = MulScale ( 512 , Cos ( ang ) , 30 ) ;
int y = MulScale ( 512 , Sin ( ang ) , 30 ) ;
int z = 0 ;
RotateYZ ( & x , & y , & z , nRand1 ) ;
RotateXZ ( & x , & y , & z , nRand2 ) ;
2022-02-02 18:55:11 +00:00
pNSprite - > set_int_pos ( { pTSprite - > int_pos ( ) . X + x , pTSprite - > int_pos ( ) . Y + y , pTSprite - > int_pos ( ) . Z + ( z < < 4 ) } ) ;
2021-12-29 19:03:42 +00:00
pNSprite - > picnum = 1720 ;
pNSprite - > shade = - 128 ;
}
break ;
case kViewEffectFlag :
case kViewEffectBigFlag :
{
int top , bottom ;
GetSpriteExtents ( pTSprite , & top , & bottom ) ;
2022-08-07 08:25:15 +00:00
auto pNSprite = viewInsertTSprite ( tsprites , pTSprite - > sectp , 32767 , pTSprite ) ;
2021-12-29 19:03:42 +00:00
if ( ! pNSprite )
break ;
pNSprite - > shade = - 128 ;
pNSprite - > pal = 0 ;
2022-02-02 19:03:02 +00:00
pNSprite - > set_int_z ( top ) ;
2021-12-29 19:03:42 +00:00
if ( nViewEffect = = kViewEffectFlag )
pNSprite - > xrepeat = pNSprite - > yrepeat = 24 ;
else
pNSprite - > xrepeat = pNSprite - > yrepeat = 64 ;
pNSprite - > picnum = 3558 ;
return pNSprite ;
}
case kViewEffectTesla :
{
2022-08-07 08:25:15 +00:00
auto pNSprite = viewInsertTSprite ( tsprites , pTSprite - > sectp , 32767 , pTSprite ) ;
2021-12-29 19:03:42 +00:00
if ( ! pNSprite )
break ;
2022-02-07 07:47:18 +00:00
pNSprite - > pos . Z = pTSprite - > pos . Z ;
2021-12-29 19:03:42 +00:00
pNSprite - > cstat | = CSTAT_SPRITE_TRANSLUCENT ;
pNSprite - > shade = - 128 ;
pNSprite - > xrepeat = pTSprite - > xrepeat ;
pNSprite - > yrepeat = pTSprite - > yrepeat ;
pNSprite - > picnum = 2135 ;
break ;
}
case kViewEffectShoot :
{
2022-08-07 08:25:15 +00:00
auto pNSprite = viewInsertTSprite ( tsprites , pTSprite - > sectp , 32767 , pTSprite ) ;
2021-12-29 19:03:42 +00:00
if ( ! pNSprite )
break ;
pNSprite - > shade = - 128 ;
pNSprite - > pal = 0 ;
pNSprite - > xrepeat = pNSprite - > yrepeat = 64 ;
pNSprite - > picnum = 2605 ;
return pNSprite ;
}
case kViewEffectReflectiveBall :
{
2022-08-07 08:25:15 +00:00
auto pNSprite = viewInsertTSprite ( tsprites , pTSprite - > sectp , 32767 , pTSprite ) ;
2021-12-29 19:03:42 +00:00
if ( ! pNSprite )
break ;
pNSprite - > shade = 26 ;
pNSprite - > pal = 0 ;
pNSprite - > cstat | = CSTAT_SPRITE_TRANSLUCENT ;
pNSprite - > xrepeat = pNSprite - > yrepeat = 64 ;
pNSprite - > picnum = 2089 ;
break ;
}
case kViewEffectPhase :
{
2022-08-07 08:25:15 +00:00
auto pNSprite = viewInsertTSprite ( tsprites , pTSprite - > sectp , 32767 , pTSprite ) ;
2021-12-29 19:03:42 +00:00
if ( ! pNSprite )
break ;
int top , bottom ;
GetSpriteExtents ( pTSprite , & top , & bottom ) ;
pNSprite - > shade = 26 ;
pNSprite - > pal = 0 ;
pNSprite - > cstat | = CSTAT_SPRITE_TRANSLUCENT ;
pNSprite - > xrepeat = pNSprite - > yrepeat = 24 ;
pNSprite - > picnum = 626 ;
2022-02-02 19:03:02 +00:00
pNSprite - > set_int_z ( top ) ;
2021-12-29 19:03:42 +00:00
break ;
}
case kViewEffectTrail :
{
2022-08-16 21:17:01 +00:00
int nAng = pTSprite - > int_ang ( ) ;
2021-12-29 19:03:42 +00:00
if ( pTSprite - > cstat & CSTAT_SPRITE_ALIGNMENT_WALL )
{
nAng = ( nAng + 512 ) & 2047 ;
}
else
{
nAng = ( nAng + 1024 ) & 2047 ;
}
2022-08-07 08:25:15 +00:00
for ( int i = 0 ; i < 5 ; i + + )
2021-12-29 19:03:42 +00:00
{
2021-12-30 15:58:48 +00:00
auto pSector = pTSprite - > sectp ;
2022-08-07 08:25:15 +00:00
auto pNSprite = viewInsertTSprite ( tsprites , pSector , 32767 , NULL ) ;
2021-12-29 19:03:42 +00:00
if ( ! pNSprite )
break ;
int nLen = 128 + ( i < < 7 ) ;
int x = MulScale ( nLen , Cos ( nAng ) , 30 ) ;
int y = MulScale ( nLen , Sin ( nAng ) , 30 ) ;
2022-02-02 18:55:11 +00:00
pNSprite - > set_int_pos ( { pTSprite - > int_pos ( ) . X + x , pTSprite - > int_pos ( ) . Y + y , pTSprite - > int_pos ( ) . Z } ) ;
2021-12-29 19:03:42 +00:00
assert ( pSector ) ;
2022-08-22 16:27:03 +00:00
FindSector ( pNSprite - > pos , & pSector ) ;
2021-12-30 15:36:04 +00:00
pNSprite - > sectp = pSector ;
2021-12-29 19:03:42 +00:00
pNSprite - > ownerActor = pTSprite - > ownerActor ;
pNSprite - > picnum = pTSprite - > picnum ;
pNSprite - > cstat | = CSTAT_SPRITE_TRANSLUCENT ;
if ( i < 2 )
pNSprite - > cstat | = CSTAT_SPRITE_TRANSLUCENT | CSTAT_SPRITE_TRANS_FLIP ;
pNSprite - > shade = ClipLow ( pTSprite - > shade - 16 , - 128 ) ;
pNSprite - > xrepeat = pTSprite - > xrepeat ;
pNSprite - > yrepeat = pTSprite - > yrepeat ;
pNSprite - > picnum = pTSprite - > picnum ;
}
break ;
}
case kViewEffectFlame :
{
2022-08-07 08:25:15 +00:00
auto pNSprite = viewInsertTSprite ( tsprites , pTSprite - > sectp , 32767 , pTSprite ) ;
2021-12-29 19:03:42 +00:00
if ( ! pNSprite )
break ;
pNSprite - > shade = - 128 ;
2022-02-07 07:47:18 +00:00
pNSprite - > pos . Z = pTSprite - > pos . Z ;
2021-12-29 19:03:42 +00:00
pNSprite - > picnum = 908 ;
pNSprite - > statnum = kStatDecoration ;
pNSprite - > xrepeat = pNSprite - > yrepeat = ( tileWidth ( pTSprite - > picnum ) * pTSprite - > xrepeat ) / 64 ;
break ;
}
case kViewEffectSmokeHigh :
{
2022-08-07 08:25:15 +00:00
auto pNSprite = viewInsertTSprite ( tsprites , pTSprite - > sectp , 32767 , pTSprite ) ;
2021-12-29 19:03:42 +00:00
if ( ! pNSprite )
break ;
int top , bottom ;
GetSpriteExtents ( pTSprite , & top , & bottom ) ;
2022-02-02 19:03:02 +00:00
pNSprite - > set_int_z ( top ) ;
2021-12-29 19:03:42 +00:00
if ( IsDudeSprite ( pTSprite ) )
pNSprite - > picnum = 672 ;
else
pNSprite - > picnum = 754 ;
pNSprite - > cstat | = CSTAT_SPRITE_TRANSLUCENT ;
pNSprite - > shade = 8 ;
pNSprite - > xrepeat = pTSprite - > xrepeat ;
pNSprite - > yrepeat = pTSprite - > yrepeat ;
break ;
}
case kViewEffectSmokeLow :
{
2022-08-07 08:25:15 +00:00
auto pNSprite = viewInsertTSprite ( tsprites , pTSprite - > sectp , 32767 , pTSprite ) ;
2021-12-29 19:03:42 +00:00
if ( ! pNSprite )
break ;
int top , bottom ;
GetSpriteExtents ( pTSprite , & top , & bottom ) ;
2022-02-02 19:03:02 +00:00
pNSprite - > set_int_z ( bottom ) ;
2021-12-29 19:03:42 +00:00
if ( pTSprite - > type > = kDudeBase & & pTSprite - > type < kDudeMax )
pNSprite - > picnum = 672 ;
else
pNSprite - > picnum = 754 ;
pNSprite - > cstat | = CSTAT_SPRITE_TRANSLUCENT ;
pNSprite - > shade = 8 ;
pNSprite - > xrepeat = pTSprite - > xrepeat ;
pNSprite - > yrepeat = pTSprite - > yrepeat ;
break ;
}
case kViewEffectTorchHigh :
{
2022-08-07 08:25:15 +00:00
auto pNSprite = viewInsertTSprite ( tsprites , pTSprite - > sectp , 32767 , pTSprite ) ;
2021-12-29 19:03:42 +00:00
if ( ! pNSprite )
break ;
int top , bottom ;
GetSpriteExtents ( pTSprite , & top , & bottom ) ;
2022-02-02 19:03:02 +00:00
pNSprite - > set_int_z ( top ) ;
2021-12-29 19:03:42 +00:00
pNSprite - > picnum = 2101 ;
pNSprite - > shade = - 128 ;
pNSprite - > xrepeat = pNSprite - > yrepeat = ( tileWidth ( pTSprite - > picnum ) * pTSprite - > xrepeat ) / 32 ;
break ;
}
case kViewEffectTorchLow :
{
2022-08-07 08:25:15 +00:00
auto pNSprite = viewInsertTSprite ( tsprites , pTSprite - > sectp , 32767 , pTSprite ) ;
2021-12-29 19:03:42 +00:00
if ( ! pNSprite )
break ;
int top , bottom ;
GetSpriteExtents ( pTSprite , & top , & bottom ) ;
2022-02-02 19:03:02 +00:00
pNSprite - > set_int_z ( bottom ) ;
2021-12-29 19:03:42 +00:00
pNSprite - > picnum = 2101 ;
pNSprite - > shade = - 128 ;
pNSprite - > xrepeat = pNSprite - > yrepeat = ( tileWidth ( pTSprite - > picnum ) * pTSprite - > xrepeat ) / 32 ;
break ;
}
case kViewEffectShadow :
{
2022-08-07 08:25:15 +00:00
auto pNSprite = viewInsertTSprite ( tsprites , pTSprite - > sectp , 32767 , pTSprite ) ;
2022-05-05 22:22:39 +00:00
if ( ! pNSprite )
break ;
2022-08-08 22:33:57 +00:00
pNSprite - > set_int_z ( getflorzofslopeptr ( pTSprite - > sectp , pNSprite - > int_pos ( ) . X , pNSprite - > int_pos ( ) . Y ) ) ;
2022-05-05 22:22:39 +00:00
if ( ( pNSprite - > sectp - > floorpicnum > = 4080 ) & & ( pNSprite - > sectp - > floorpicnum < = 4095 ) & & ! VanillaMode ( ) ) // if floor has ror, find actual floor
2021-12-29 19:03:42 +00:00
{
2022-08-08 22:33:57 +00:00
int cX = pNSprite - > int_pos ( ) . X , cY = pNSprite - > int_pos ( ) . Y , cZ = pNSprite - > int_pos ( ) . Z , cZrel = pNSprite - > int_pos ( ) . Z ;
2022-05-05 22:22:39 +00:00
auto cSect = pNSprite - > sectp ;
for ( int i = 0 ; i < 16 ; i + + ) // scan through max stacked sectors
{
if ( ! CheckLink ( & cX , & cY , & cZ , & cSect ) ) // if no more floors underneath, abort
break ;
const int newFloorZ = getflorzofslopeptr ( cSect , cX , cZ ) ;
cZrel + = newFloorZ - cZ ; // get height difference for next sector's ceiling/floor, and add to relative height for shadow
if ( ( cSect - > floorpicnum < 4080 ) | | ( cSect - > floorpicnum > 4095 ) ) // if current sector is not open air, use as floor for shadow casting, otherwise continue to next sector
break ;
cZ = newFloorZ ;
}
pNSprite - > sectp = cSect ;
2022-08-08 22:33:57 +00:00
pNSprite - > set_int_z ( cZrel ) ;
2021-12-29 19:03:42 +00:00
}
2022-05-05 22:22:39 +00:00
pNSprite - > shade = 127 ;
pNSprite - > cstat | = CSTAT_SPRITE_TRANSLUCENT ;
pNSprite - > xrepeat = pTSprite - > xrepeat ;
pNSprite - > yrepeat = pTSprite - > yrepeat > > 2 ;
pNSprite - > picnum = pTSprite - > picnum ;
if ( ! VanillaMode ( ) & & ( pTSprite - > type = = kThingDroppedLifeLeech ) ) // fix shadow for thrown lifeleech
pNSprite - > picnum = 800 ;
pNSprite - > pal = 5 ;
int height = tileHeight ( pNSprite - > picnum ) ;
int center = height / 2 + tileTopOffset ( pNSprite - > picnum ) ;
2022-08-08 22:33:57 +00:00
pNSprite - > add_int_z ( - ( pNSprite - > yrepeat < < 2 ) * ( height - center ) ) ;
2021-12-29 19:03:42 +00:00
break ;
}
case kViewEffectFlareHalo :
{
2022-08-07 08:25:15 +00:00
auto pNSprite = viewInsertTSprite ( tsprites , pTSprite - > sectp , 32767 , pTSprite ) ;
2021-12-29 19:03:42 +00:00
if ( ! pNSprite )
break ;
pNSprite - > shade = - 128 ;
pNSprite - > pal = 2 ;
pNSprite - > cstat | = CSTAT_SPRITE_TRANSLUCENT ;
2022-02-07 07:47:18 +00:00
pNSprite - > pos . Z = pTSprite - > pos . Z ;
2021-12-29 19:03:42 +00:00
pNSprite - > xrepeat = pTSprite - > xrepeat ;
pNSprite - > yrepeat = pTSprite - > yrepeat ;
pNSprite - > picnum = 2427 ;
break ;
}
case kViewEffectCeilGlow :
{
2022-08-07 08:25:15 +00:00
auto pNSprite = viewInsertTSprite ( tsprites , pTSprite - > sectp , 32767 , pTSprite ) ;
2021-12-29 19:03:42 +00:00
if ( ! pNSprite )
break ;
2021-12-30 15:58:48 +00:00
sectortype * pSector = pTSprite - > sectp ;
2022-08-16 21:46:18 +00:00
pNSprite - > pos = { pTSprite - > pos . X , pTSprite - > pos . Y , pSector - > ceilingz } ;
2022-02-02 18:55:11 +00:00
2021-12-29 19:03:42 +00:00
pNSprite - > picnum = 624 ;
2022-02-02 23:46:04 +00:00
pNSprite - > shade = ( ( pTSprite - > int_pos ( ) . Z - pSector - > int_ceilingz ( ) ) > > 8 ) - 64 ;
2021-12-29 19:03:42 +00:00
pNSprite - > pal = 2 ;
pNSprite - > xrepeat = pNSprite - > yrepeat = 64 ;
pNSprite - > cstat | = CSTAT_SPRITE_ONE_SIDE | CSTAT_SPRITE_ALIGNMENT_FLOOR | CSTAT_SPRITE_YFLIP | CSTAT_SPRITE_TRANSLUCENT ;
2022-08-21 10:19:06 +00:00
pNSprite - > angle = pTSprite - > angle ;
2021-12-29 19:03:42 +00:00
pNSprite - > ownerActor = pTSprite - > ownerActor ;
break ;
}
case kViewEffectFloorGlow :
{
2022-08-07 08:25:15 +00:00
auto pNSprite = viewInsertTSprite ( tsprites , pTSprite - > sectp , 32767 , pTSprite ) ;
2021-12-29 19:03:42 +00:00
if ( ! pNSprite )
break ;
2021-12-30 15:58:48 +00:00
sectortype * pSector = pTSprite - > sectp ;
2022-08-16 21:46:18 +00:00
pNSprite - > pos = { pTSprite - > pos . X , pTSprite - > pos . Y , pSector - > floorz } ;
2021-12-29 19:03:42 +00:00
pNSprite - > picnum = 624 ;
2022-08-20 17:40:23 +00:00
uint8_t nShade = ( uint8_t ) clamp ( pSector - > floorz - pTSprite - > pos . Z , 0. , 255. ) ;
2021-12-29 19:03:42 +00:00
pNSprite - > shade = nShade - 32 ;
pNSprite - > pal = 2 ;
pNSprite - > xrepeat = pNSprite - > yrepeat = nShade ;
pNSprite - > cstat | = CSTAT_SPRITE_ONE_SIDE | CSTAT_SPRITE_ALIGNMENT_FLOOR | CSTAT_SPRITE_TRANSLUCENT ;
2022-08-21 10:19:06 +00:00
pNSprite - > angle = pTSprite - > angle ;
2021-12-29 19:03:42 +00:00
pNSprite - > ownerActor = pTSprite - > ownerActor ;
break ;
}
case kViewEffectSpear :
{
2022-08-07 08:25:15 +00:00
auto pNSprite = viewInsertTSprite ( tsprites , pTSprite - > sectp , 32767 , pTSprite ) ;
2021-12-29 19:03:42 +00:00
if ( ! pNSprite )
break ;
2022-02-07 07:47:18 +00:00
pNSprite - > pos . Z = pTSprite - > pos . Z ;
2021-12-29 19:03:42 +00:00
if ( gDetail > 1 )
pNSprite - > cstat | = CSTAT_SPRITE_TRANSLUCENT | CSTAT_SPRITE_TRANS_FLIP ;
pNSprite - > shade = ClipLow ( pTSprite - > shade - 32 , - 128 ) ;
pNSprite - > xrepeat = pTSprite - > xrepeat ;
pNSprite - > yrepeat = 64 ;
pNSprite - > picnum = 775 ;
break ;
}
case kViewEffectShowWeapon :
{
assert ( pTSprite - > type > = kDudePlayer1 & & pTSprite - > type < = kDudePlayer8 ) ;
PLAYER * pPlayer = & gPlayer [ pTSprite - > type - kDudePlayer1 ] ;
WEAPONICON weaponIcon = gWeaponIcon [ pPlayer - > curWeapon ] ;
auto & nTile = weaponIcon . nTile ;
if ( nTile < 0 ) break ;
2022-08-07 08:25:15 +00:00
auto pNSprite = viewInsertTSprite ( tsprites , pTSprite - > sectp , 32767 , pTSprite ) ;
2021-12-29 19:03:42 +00:00
if ( ! pNSprite )
break ;
2022-08-16 21:46:18 +00:00
pNSprite - > pos = pTSprite - > pos . plusZ ( - 32 - weaponIcon . zOffset ) ;
2021-12-29 19:03:42 +00:00
pNSprite - > picnum = nTile ;
pNSprite - > shade = pTSprite - > shade ;
pNSprite - > xrepeat = 32 ;
pNSprite - > yrepeat = 32 ;
auto & nVoxel = voxelIndex [ nTile ] ;
if ( cl_showweapon = = 2 & & r_voxels & & nVoxel ! = - 1 )
{
2022-08-16 21:25:11 +00:00
pNSprite - > set_int_ang ( ( gView - > actor - > int_ang ( ) + 512 ) & 2047 ) ; // always face viewer
2021-12-29 19:03:42 +00:00
pNSprite - > cstat | = CSTAT_SPRITE_ALIGNMENT_SLAB ;
pNSprite - > cstat & = ~ CSTAT_SPRITE_YFLIP ;
pNSprite - > picnum = nVoxel ;
if ( pPlayer - > curWeapon = = kWeapLifeLeech ) // position lifeleech behind player
{
2022-08-16 21:17:01 +00:00
pNSprite - > add_int_x ( MulScale ( 128 , Cos ( gView - > actor - > int_ang ( ) ) , 30 ) ) ;
pNSprite - > add_int_y ( MulScale ( 128 , Sin ( gView - > actor - > int_ang ( ) ) , 30 ) ) ;
2021-12-29 19:03:42 +00:00
}
if ( ( pPlayer - > curWeapon = = kWeapLifeLeech ) | | ( pPlayer - > curWeapon = = kWeapVoodooDoll ) ) // make lifeleech/voodoo doll always face viewer like sprite
2022-08-16 21:25:11 +00:00
pNSprite - > set_int_ang ( ( pNSprite - > int_ang ( ) + 512 ) & 2047 ) ; // offset angle 90 degrees
2021-12-29 19:03:42 +00:00
}
break ;
}
}
return NULL ;
2020-08-02 17:59:14 +00:00
}
2021-12-29 19:03:42 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static void viewApplyDefaultPal ( tspritetype * pTSprite , sectortype const * pSector )
2020-08-02 17:59:14 +00:00
{
2021-12-29 19:03:42 +00:00
XSECTOR const * pXSector = pSector - > hasX ( ) ? & pSector - > xs ( ) : nullptr ;
if ( pXSector & & pXSector - > color & & ( VanillaMode ( ) | | pSector - > floorpal ! = 0 ) )
{
copyfloorpal ( pTSprite , pSector ) ;
}
2020-08-02 17:59:14 +00:00
}
2021-12-29 19:03:42 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2022-08-27 17:50:43 +00:00
void viewProcessSprites ( tspriteArray & tsprites , int32_t cX , int32_t cY , int32_t cZ , DAngle cA , int32_t smoothratio )
2020-08-02 17:59:14 +00:00
{
2022-08-07 08:25:15 +00:00
int nViewSprites = tsprites . Size ( ) ;
2020-09-01 18:02:37 +00:00
// shift before interpolating to increase precision.
2021-12-29 19:03:42 +00:00
int myclock = ( PlayClock < < 3 ) + MulScale ( 4 < < 3 , smoothratio , 16 ) ;
gCameraAng = cA ;
2022-08-07 08:25:15 +00:00
for ( int nTSprite = int ( tsprites . Size ( ) ) - 1 ; nTSprite > = 0 ; nTSprite - - )
2021-12-29 19:03:42 +00:00
{
2022-08-07 08:25:15 +00:00
tspritetype * pTSprite = tsprites . get ( nTSprite ) ;
2021-12-29 19:03:42 +00:00
auto owneractor = static_cast < DBloodActor * > ( pTSprite - > ownerActor ) ;
if ( owneractor - > spr . detail > gDetail )
{
pTSprite - > xrepeat = 0 ;
continue ;
}
int nTile = pTSprite - > picnum ;
if ( nTile < 0 | | nTile > = kMaxTiles )
{
pTSprite - > xrepeat = 0 ;
continue ;
}
// skip picnum 0 on face sprites. picnum 0 is a simple wall texture in Blood,
// but there are maps that use 0 on some operator sprites that may show up in potals as a result.
// Since the wall texture is perfectly fine for wall and floor sprites, these will be allowed to pass.
if ( nTile = = 0 & & ( pTSprite - > cstat & CSTAT_SPRITE_ALIGNMENT_MASK ) = = CSTAT_SPRITE_ALIGNMENT_FACING )
{
pTSprite - > xrepeat = 0 ;
continue ;
}
if ( cl_interpolate & & owneractor - > interpolated & & ! ( pTSprite - > flags & 512 ) )
{
2022-02-03 23:04:45 +00:00
pTSprite - > pos = owneractor - > interpolatedvec3 ( gInterpolate ) ;
2022-08-28 00:17:59 +00:00
pTSprite - > angle = owneractor - > interpolatedang ( gInterpolate ) ;
2021-12-29 19:03:42 +00:00
}
int nAnim = 0 ;
switch ( picanm [ nTile ] . extra & 7 ) {
case 0 :
if ( ! owneractor - > hasX ( ) ) break ;
switch ( pTSprite - > type ) {
2022-05-06 16:27:44 +00:00
# ifdef NOONE_EXTENSIONS
case kModernCondition :
case kModernConditionFalse :
if ( ! gModernMap ) break ;
[[fallthrough]] ;
# endif
2021-12-29 19:03:42 +00:00
case kSwitchToggle :
case kSwitchOneWay :
if ( owneractor - > xspr . state ) nAnim = 1 ;
break ;
case kSwitchCombo :
nAnim = owneractor - > xspr . data1 ;
break ;
}
break ;
case 1 :
{
2022-01-23 18:03:14 +00:00
if ( tilehasmodelorvoxel ( pTSprite - > picnum , pTSprite - > pal ) & & ! ( owneractor - > sprext . renderflags & SPREXT_NOTMD ) )
2021-12-29 19:03:42 +00:00
{
pTSprite - > cstat & = ~ CSTAT_SPRITE_XFLIP ;
break ;
}
2022-02-02 18:55:11 +00:00
int dX = cX - pTSprite - > int_pos ( ) . X ;
int dY = cY - pTSprite - > int_pos ( ) . Y ;
2022-08-16 21:15:49 +00:00
RotateVector ( & dX , & dY , 128 - pTSprite - > int_ang ( ) ) ;
2021-12-29 19:03:42 +00:00
nAnim = GetOctant ( dX , dY ) ;
if ( nAnim < = 4 )
{
pTSprite - > cstat & = ~ CSTAT_SPRITE_XFLIP ;
}
else
{
nAnim = 8 - nAnim ;
pTSprite - > cstat | = CSTAT_SPRITE_XFLIP ;
}
break ;
}
case 2 :
{
2022-01-23 18:03:14 +00:00
if ( tilehasmodelorvoxel ( pTSprite - > picnum , pTSprite - > pal ) & & ! ( owneractor - > sprext . renderflags & SPREXT_NOTMD ) )
2021-12-29 19:03:42 +00:00
{
pTSprite - > cstat & = ~ CSTAT_SPRITE_XFLIP ;
break ;
}
2022-02-02 18:55:11 +00:00
int dX = cX - pTSprite - > int_pos ( ) . X ;
int dY = cY - pTSprite - > int_pos ( ) . Y ;
2022-08-16 21:15:49 +00:00
RotateVector ( & dX , & dY , 128 - pTSprite - > int_ang ( ) ) ;
2021-12-29 19:03:42 +00:00
nAnim = GetOctant ( dX , dY ) ;
break ;
}
case 3 :
{
if ( owneractor - > hasX ( ) )
{
if ( owneractor - > hit . florhit . type = = kHitNone )
nAnim = 1 ;
}
else
{
int top , bottom ;
GetSpriteExtents ( pTSprite , & top , & bottom ) ;
2022-02-02 18:55:11 +00:00
if ( getflorzofslopeptr ( pTSprite - > sectp , pTSprite - > int_pos ( ) . X , pTSprite - > int_pos ( ) . Y ) > bottom )
2021-12-29 19:03:42 +00:00
nAnim = 1 ;
}
break ;
}
case 6 :
case 7 :
{
2022-01-23 18:03:14 +00:00
if ( hw_models & & md_tilehasmodel ( pTSprite - > picnum , pTSprite - > pal ) > = 0 & & ! ( owneractor - > sprext . renderflags & SPREXT_NOTMD ) )
2021-12-29 19:03:42 +00:00
break ;
// Can be overridden by def script
2022-01-23 18:03:14 +00:00
if ( r_voxels & & tiletovox [ pTSprite - > picnum ] = = - 1 & & voxelIndex [ pTSprite - > picnum ] ! = - 1 & & ! ( owneractor - > sprext . renderflags & SPREXT_NOTMD ) )
2021-12-29 19:03:42 +00:00
{
if ( ( pTSprite - > flags & kHitagRespawn ) = = 0 )
{
pTSprite - > cstat | = CSTAT_SPRITE_ALIGNMENT_SLAB ;
pTSprite - > cstat & = ~ ( CSTAT_SPRITE_XFLIP | CSTAT_SPRITE_YFLIP ) ;
pTSprite - > yoffset + = tileTopOffset ( pTSprite - > picnum ) ;
pTSprite - > picnum = voxelIndex [ pTSprite - > picnum ] ;
if ( ( picanm [ nTile ] . extra & 7 ) = = 7 )
{
2022-08-16 21:25:11 +00:00
pTSprite - > set_int_ang ( myclock & 2047 ) ;
2021-12-29 19:03:42 +00:00
}
}
}
break ;
}
}
while ( nAnim > 0 )
{
pTSprite - > picnum + = picanm [ pTSprite - > picnum ] . num + 1 ;
nAnim - - ;
}
2022-01-23 18:03:14 +00:00
if ( ( pTSprite - > cstat & CSTAT_SPRITE_ALIGNMENT_MASK ) ! = CSTAT_SPRITE_ALIGNMENT_SLAB & & r_voxels & & ! ( owneractor - > sprext . renderflags & SPREXT_NOTMD ) )
2021-12-29 19:03:42 +00:00
{
int const nRootTile = pTSprite - > picnum ;
2022-08-05 16:47:35 +00:00
int nAnimTile = pTSprite - > picnum + tileAnimateOfs ( pTSprite - > picnum , ( pTSprite - > ownerActor - > GetIndex ( ) & 16383 ) ) ;
2020-08-02 17:59:14 +00:00
#if 0
2021-12-29 19:03:42 +00:00
if ( tiletovox [ nAnimTile ] ! = - 1 )
{
pTSprite - > yoffset + = tileTopOffset ( nAnimTile ) ;
pTSprite - > xoffset + = tileLeftOffset ( nAnimTile ) ;
}
2020-08-02 17:59:14 +00:00
# endif
2021-12-29 19:03:42 +00:00
int const nVoxel = tiletovox [ pTSprite - > picnum ] ;
if ( nVoxel ! = - 1 & & ( picanm [ nRootTile ] . extra & 7 ) = = 7 )
2021-12-30 18:00:35 +00:00
pTSprite - > clipdist | = TSPR_MDLROTATE ; // per-sprite rotation setting.
2021-12-29 19:03:42 +00:00
}
2022-01-23 18:03:14 +00:00
if ( ( pTSprite - > cstat & CSTAT_SPRITE_ALIGNMENT_MASK ) ! = CSTAT_SPRITE_ALIGNMENT_SLAB & & hw_models & & ! ( owneractor - > sprext . renderflags & SPREXT_NOTMD ) )
2021-12-29 19:03:42 +00:00
{
int const nRootTile = pTSprite - > picnum ;
2022-08-05 16:47:35 +00:00
int nAnimTile = pTSprite - > picnum + tileAnimateOfs ( pTSprite - > picnum , ( pTSprite - > ownerActor - > GetIndex ( ) & 16383 ) ) ;
2021-12-29 19:03:42 +00:00
if ( tile2model [ Ptile2tile ( nAnimTile , pTSprite - > pal ) ] . modelid > = 0 & &
tile2model [ Ptile2tile ( nAnimTile , pTSprite - > pal ) ] . framenum > = 0 )
{
pTSprite - > yoffset + = tileTopOffset ( nAnimTile ) ;
pTSprite - > xoffset + = tileLeftOffset ( nAnimTile ) ;
if ( ( picanm [ nRootTile ] . extra & 7 ) = = 7 )
2021-12-30 18:00:35 +00:00
pTSprite - > clipdist | = TSPR_MDLROTATE ; // per-sprite rotation setting.
2021-12-29 19:03:42 +00:00
}
}
2021-12-30 15:58:48 +00:00
sectortype * pSector = pTSprite - > sectp ;
2021-12-29 19:03:42 +00:00
XSECTOR const * pXSector = pSector - > hasX ( ) ? & pSector - > xs ( ) : nullptr ;
int nShade = pTSprite - > shade ;
if ( ( pSector - > ceilingstat & CSTAT_SECTOR_SKY ) & & ( pSector - > floorstat & CSTAT_SECTOR_NO_CEILINGSHADE ) = = 0 )
{
nShade + = tileShade [ pSector - > ceilingpicnum ] + pSector - > ceilingshade ;
}
else
{
nShade + = tileShade [ pSector - > floorpicnum ] + pSector - > floorshade ;
}
nShade + = tileShade [ pTSprite - > picnum ] ;
pTSprite - > shade = ClipRange ( nShade , - 128 , 127 ) ;
2022-05-23 22:30:41 +00:00
if ( ( pTSprite - > flags & kHitagRespawn ) & & pTSprite - > ownerActor - > spr . intowner = = 3 & & owneractor - > hasX ( ) ) // Where does this 3 come from? Nothing sets it.
2021-12-29 19:03:42 +00:00
{
pTSprite - > xrepeat = 48 ;
pTSprite - > yrepeat = 48 ;
pTSprite - > shade = - 128 ;
pTSprite - > picnum = 2272 + 2 * owneractor - > xspr . respawnPending ;
pTSprite - > cstat & = ~ ( CSTAT_SPRITE_TRANSLUCENT | CSTAT_SPRITE_TRANS_FLIP ) ;
if ( ( ( IsItemSprite ( pTSprite ) | | IsAmmoSprite ( pTSprite ) ) & & gGameOptions . nItemSettings = = 2 )
| | ( IsWeaponSprite ( pTSprite ) & & gGameOptions . nWeaponSettings = = 3 ) )
{
pTSprite - > xrepeat = pTSprite - > yrepeat = 48 ;
}
else
{
pTSprite - > xrepeat = pTSprite - > yrepeat = 0 ;
}
}
if ( owneractor - > hasX ( ) & & owneractor - > xspr . burnTime > 0 )
{
pTSprite - > shade = ClipRange ( pTSprite - > shade - 16 - QRandom ( 8 ) , - 128 , 127 ) ;
}
if ( pTSprite - > flags & 256 )
{
2022-08-07 08:25:15 +00:00
viewAddEffect ( tsprites , nTSprite , kViewEffectSmokeHigh ) ;
2021-12-29 19:03:42 +00:00
}
if ( pTSprite - > flags & 1024 )
{
pTSprite - > cstat | = CSTAT_SPRITE_XFLIP ;
}
if ( pTSprite - > flags & 2048 )
{
pTSprite - > cstat | = CSTAT_SPRITE_YFLIP ;
}
switch ( pTSprite - > statnum ) {
case kStatDecoration : {
switch ( pTSprite - > type ) {
case kDecorationCandle :
if ( ! owneractor - > hasX ( ) | | owneractor - > xspr . state = = 1 ) {
pTSprite - > shade = - 128 ;
2022-08-07 08:25:15 +00:00
viewAddEffect ( tsprites , nTSprite , kViewEffectPhase ) ;
2021-12-29 19:03:42 +00:00
}
else {
pTSprite - > shade = - 8 ;
}
break ;
case kDecorationTorch :
if ( ! owneractor - > hasX ( ) | | owneractor - > xspr . state = = 1 ) {
pTSprite - > picnum + + ;
2022-08-07 08:25:15 +00:00
viewAddEffect ( tsprites , nTSprite , kViewEffectTorchHigh ) ;
2021-12-29 19:03:42 +00:00
}
else {
2022-08-07 08:25:15 +00:00
viewAddEffect ( tsprites , nTSprite , kViewEffectSmokeHigh ) ;
2021-12-29 19:03:42 +00:00
}
break ;
default :
viewApplyDefaultPal ( pTSprite , pSector ) ;
break ;
}
}
break ;
case kStatItem : {
switch ( pTSprite - > type ) {
case kItemFlagABase :
if ( owneractor - > hasX ( ) & & owneractor - > xspr . state > 0 & & gGameOptions . nGameType = = 3 ) {
2022-08-07 08:25:15 +00:00
auto pNTSprite = viewAddEffect ( tsprites , nTSprite , kViewEffectBigFlag ) ;
2021-12-29 19:03:42 +00:00
if ( pNTSprite ) pNTSprite - > pal = 10 ;
}
break ;
case kItemFlagBBase :
if ( owneractor - > hasX ( ) & & owneractor - > xspr . state > 0 & & gGameOptions . nGameType = = 3 ) {
2022-08-07 08:25:15 +00:00
auto pNTSprite = viewAddEffect ( tsprites , nTSprite , kViewEffectBigFlag ) ;
2021-12-29 19:03:42 +00:00
if ( pNTSprite ) pNTSprite - > pal = 7 ;
}
break ;
case kItemFlagA :
pTSprite - > pal = 10 ;
pTSprite - > cstat | = CSTAT_SPRITE_BLOOD_BIT2 ;
break ;
case kItemFlagB :
pTSprite - > pal = 7 ;
pTSprite - > cstat | = CSTAT_SPRITE_BLOOD_BIT2 ;
break ;
default :
if ( pTSprite - > type > = kItemKeySkull & & pTSprite - > type < kItemKeyMax )
pTSprite - > shade = - 128 ;
viewApplyDefaultPal ( pTSprite , pSector ) ;
break ;
}
}
break ;
case kStatProjectile : {
switch ( pTSprite - > type ) {
case kMissileTeslaAlt :
pTSprite - > yrepeat = 128 ;
pTSprite - > cstat | = CSTAT_SPRITE_ALIGNMENT_FLOOR ;
break ;
case kMissileTeslaRegular :
2022-08-07 08:25:15 +00:00
viewAddEffect ( tsprites , nTSprite , kViewEffectTesla ) ;
2021-12-29 19:03:42 +00:00
break ;
case kMissileButcherKnife :
2022-08-07 08:25:15 +00:00
viewAddEffect ( tsprites , nTSprite , kViewEffectTrail ) ;
2021-12-29 19:03:42 +00:00
break ;
case kMissileFlareRegular :
case kMissileFlareAlt :
if ( pTSprite - > statnum = = kStatFlare ) {
if ( owneractor - > GetTarget ( ) = = gView - > actor )
{
pTSprite - > xrepeat = 0 ;
break ;
}
}
2022-08-07 08:25:15 +00:00
viewAddEffect ( tsprites , nTSprite , kViewEffectFlareHalo ) ;
2021-12-29 19:03:42 +00:00
if ( pTSprite - > type ! = kMissileFlareRegular ) break ;
2021-12-30 15:58:48 +00:00
sectortype * pSector1 = pTSprite - > sectp ;
2021-12-29 19:03:42 +00:00
2022-08-20 17:40:23 +00:00
double zDiff = pTSprite - > pos . Z - pSector1 - > ceilingz ;
if ( ( pSector1 - > ceilingstat & CSTAT_SECTOR_SKY ) = = 0 & & zDiff < 64 )
{
2022-08-07 08:25:15 +00:00
viewAddEffect ( tsprites , nTSprite , kViewEffectCeilGlow ) ;
2021-12-29 19:03:42 +00:00
}
2022-08-20 17:40:23 +00:00
zDiff = ( pSector1 - > floorz - pTSprite - > pos . Z ) ;
if ( ( pSector1 - > floorstat & CSTAT_SECTOR_SKY ) = = 0 & & zDiff < 64 )
{
2022-08-07 08:25:15 +00:00
viewAddEffect ( tsprites , nTSprite , kViewEffectFloorGlow ) ;
2021-12-29 19:03:42 +00:00
}
break ;
}
break ;
}
case kStatDude :
{
if ( pTSprite - > type = = kDudeHand & & owneractor - > hasX ( ) & & owneractor - > xspr . aiState = = & hand13A3B4 )
{
auto target = owneractor - > GetTarget ( ) ;
if ( target & & target - > IsPlayerActor ( ) )
{
pTSprite - > xrepeat = 0 ;
break ;
}
}
if ( pXSector & & pXSector - > color ) copyfloorpal ( pTSprite , pSector ) ;
if ( powerupCheck ( gView , kPwUpBeastVision ) > 0 ) pTSprite - > shade = - 128 ;
if ( IsPlayerSprite ( pTSprite ) ) {
PLAYER * pPlayer = & gPlayer [ pTSprite - > type - kDudePlayer1 ] ;
if ( powerupCheck ( pPlayer , kPwUpShadowCloak ) & & ! powerupCheck ( gView , kPwUpBeastVision ) ) {
pTSprite - > cstat | = CSTAT_SPRITE_TRANSLUCENT ;
pTSprite - > pal = 5 ;
}
else if ( powerupCheck ( pPlayer , kPwUpDeathMask ) ) {
pTSprite - > shade = - 128 ;
pTSprite - > pal = 5 ;
}
else if ( powerupCheck ( pPlayer , kPwUpDoppleganger ) ) {
pTSprite - > pal = 11 + ( gView - > teamId & 3 ) ;
}
if ( powerupCheck ( pPlayer , kPwUpReflectShots ) ) {
2022-08-07 08:25:15 +00:00
viewAddEffect ( tsprites , nTSprite , kViewEffectReflectiveBall ) ;
2021-12-29 19:03:42 +00:00
}
if ( cl_showweapon & & gGameOptions . nGameType > 0 & & gView ) {
2022-08-07 08:25:15 +00:00
viewAddEffect ( tsprites , nTSprite , kViewEffectShowWeapon ) ;
2021-12-29 19:03:42 +00:00
}
if ( pPlayer - > flashEffect & & ( gView ! = pPlayer | | gViewPos ! = VIEWPOS_0 ) ) {
2022-08-07 08:25:15 +00:00
auto pNTSprite = viewAddEffect ( tsprites , nTSprite , kViewEffectShoot ) ;
2021-12-29 19:03:42 +00:00
if ( pNTSprite ) {
POSTURE * pPosture = & pPlayer - > pPosture [ pPlayer - > lifeMode ] [ pPlayer - > posture ] ;
2022-08-16 21:17:01 +00:00
pNTSprite - > add_int_x ( MulScale ( pPosture - > zOffset , Cos ( pTSprite - > int_ang ( ) ) , 28 ) ) ;
pNTSprite - > add_int_y ( MulScale ( pPosture - > zOffset , Sin ( pTSprite - > int_ang ( ) ) , 28 ) ) ;
2022-02-02 19:03:02 +00:00
pNTSprite - > set_int_z ( pPlayer - > actor - > int_pos ( ) . Z - pPosture - > xOffset ) ;
2021-12-29 19:03:42 +00:00
}
}
if ( pPlayer - > hasFlag > 0 & & gGameOptions . nGameType = = 3 ) {
if ( pPlayer - > hasFlag & 1 ) {
2022-08-07 08:25:15 +00:00
auto pNTSprite = viewAddEffect ( tsprites , nTSprite , kViewEffectFlag ) ;
2021-12-29 19:03:42 +00:00
if ( pNTSprite )
{
pNTSprite - > pal = 10 ;
pNTSprite - > cstat | = CSTAT_SPRITE_XFLIP ;
}
}
if ( pPlayer - > hasFlag & 2 ) {
2022-08-07 08:25:15 +00:00
auto pNTSprite = viewAddEffect ( tsprites , nTSprite , kViewEffectFlag ) ;
2021-12-29 19:03:42 +00:00
if ( pNTSprite )
{
pNTSprite - > pal = 7 ;
pNTSprite - > cstat | = CSTAT_SPRITE_XFLIP ;
}
}
}
}
if ( pTSprite - > ownerActor ! = gView - > actor | | gViewPos ! = VIEWPOS_0 ) {
2022-02-02 18:55:11 +00:00
if ( getflorzofslopeptr ( pTSprite - > sectp , pTSprite - > int_pos ( ) . X , pTSprite - > int_pos ( ) . Y ) > = cZ )
2021-12-29 19:03:42 +00:00
{
2022-08-07 08:25:15 +00:00
viewAddEffect ( tsprites , nTSprite , kViewEffectShadow ) ;
2021-12-29 19:03:42 +00:00
}
}
if ( gModernMap & & owneractor - > hasX ( ) ) { // add target spot indicator for patrol dudes
if ( owneractor - > xspr . dudeFlag4 & & aiInPatrolState ( owneractor - > xspr . aiState ) & & owneractor - > xspr . data3 > 0 & & owneractor - > xspr . data3 < = kMaxPatrolSpotValue )
2022-08-07 08:25:15 +00:00
viewAddEffect ( tsprites , nTSprite , kViewEffectSpotProgress ) ;
2021-12-29 19:03:42 +00:00
}
break ;
}
case kStatTraps : {
if ( pTSprite - > type = = kTrapSawCircular ) {
if ( owneractor - > xspr . state ) {
if ( owneractor - > xspr . data1 ) {
pTSprite - > picnum = 772 ;
if ( owneractor - > xspr . data2 )
2022-08-07 08:25:15 +00:00
viewAddEffect ( tsprites , nTSprite , kViewEffectSpear ) ;
2021-12-29 19:03:42 +00:00
}
}
else if ( owneractor - > xspr . data1 ) pTSprite - > picnum = 773 ;
else pTSprite - > picnum = 656 ;
}
break ;
}
case kStatThing : {
viewApplyDefaultPal ( pTSprite , pSector ) ;
if ( pTSprite - > type < kThingBase | | pTSprite - > type > = kThingMax | | owneractor - > hit . florhit . type = = kHitNone )
{
2022-02-02 18:55:11 +00:00
if ( ( pTSprite - > flags & kPhysMove ) & & getflorzofslopeptr ( pTSprite - > sectp , pTSprite - > int_pos ( ) . X , pTSprite - > int_pos ( ) . Y ) > = cZ )
2022-08-07 08:25:15 +00:00
viewAddEffect ( tsprites , nTSprite , kViewEffectShadow ) ;
2021-12-29 19:03:42 +00:00
}
}
break ;
}
}
2022-08-07 08:25:15 +00:00
for ( int nTSprite = int ( tsprites . Size ( ) - 1 ) ; nTSprite > = nViewSprites ; nTSprite - - )
2021-12-29 19:03:42 +00:00
{
2022-08-07 08:25:15 +00:00
tspritetype * pTSprite = tsprites . get ( nTSprite ) ;
2021-12-29 19:03:42 +00:00
int nAnim = 0 ;
switch ( picanm [ pTSprite - > picnum ] . extra & 7 )
{
case 1 :
{
2022-02-02 18:55:11 +00:00
int dX = cX - pTSprite - > int_pos ( ) . X ;
int dY = cY - pTSprite - > int_pos ( ) . Y ;
2022-08-16 21:15:49 +00:00
RotateVector ( & dX , & dY , 128 - pTSprite - > int_ang ( ) ) ;
2021-12-29 19:03:42 +00:00
nAnim = GetOctant ( dX , dY ) ;
if ( nAnim < = 4 )
{
pTSprite - > cstat & = ~ CSTAT_SPRITE_XFLIP ;
}
else
{
nAnim = 8 - nAnim ;
pTSprite - > cstat | = CSTAT_SPRITE_XFLIP ;
}
break ;
}
case 2 :
{
2022-02-02 18:55:11 +00:00
int dX = cX - pTSprite - > int_pos ( ) . X ;
int dY = cY - pTSprite - > int_pos ( ) . Y ;
2022-08-16 21:15:49 +00:00
RotateVector ( & dX , & dY , 128 - pTSprite - > int_ang ( ) ) ;
2021-12-29 19:03:42 +00:00
nAnim = GetOctant ( dX , dY ) ;
break ;
}
}
while ( nAnim > 0 )
{
pTSprite - > picnum + = picanm [ pTSprite - > picnum ] . num + 1 ;
nAnim - - ;
}
}
2020-08-02 17:59:14 +00:00
}
2021-12-29 19:03:42 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2022-08-27 08:49:41 +00:00
void GameInterface : : processSprites ( tspriteArray & tsprites , int viewx , int viewy , int viewz , DAngle viewang , double smoothRatio )
2021-03-20 22:01:16 +00:00
{
2022-08-27 17:50:43 +00:00
viewProcessSprites ( tsprites , viewx , viewy , viewz , viewang , int ( smoothRatio ) ) ;
2021-03-20 22:01:16 +00:00
}
2021-03-29 19:48:23 +00:00
int display_mirror ;
2021-12-22 22:27:32 +00:00
void GameInterface : : EnterPortal ( DCoreActor * viewer , int type )
2021-03-29 19:48:23 +00:00
{
2021-12-29 19:03:42 +00:00
if ( type = = PORTAL_WALL_MIRROR )
{
display_mirror + + ;
if ( viewer ) viewer - > spr . cstat & = ~ CSTAT_SPRITE_INVISIBLE ;
}
2021-03-29 19:48:23 +00:00
}
2021-12-22 22:27:32 +00:00
void GameInterface : : LeavePortal ( DCoreActor * viewer , int type )
2021-03-29 19:48:23 +00:00
{
2021-12-29 19:03:42 +00:00
if ( type = = PORTAL_WALL_MIRROR )
{
display_mirror - - ;
if ( viewer & & display_mirror = = 0 & & ! ( viewer - > spr . cstat & CSTAT_SPRITE_TRANSLUCENT ) ) viewer - > spr . cstat | = CSTAT_SPRITE_INVISIBLE ;
}
2021-03-29 19:48:23 +00:00
}
2020-08-02 17:59:14 +00:00
END_BLD_NS