2020-12-02 11:46:44 +00:00
# pragma once
BEGIN_BLD_NS
2020-12-04 22:21:42 +00:00
2020-11-06 21:48:22 +00:00
// Due to the messed up array storage of all the game data we cannot do any direct references here yet. We have to access everything via wrapper functions for now.
2020-12-02 11:46:44 +00:00
// Note that the indexing is very inconsistent - partially by sprite index, partially by xsprite index.
class DBloodActor
{
2020-11-07 15:26:14 +00:00
int index ;
2021-05-05 08:12:31 +00:00
DBloodActor * base ( ) ;
2020-12-02 11:46:44 +00:00
public :
2021-05-05 08:12:31 +00:00
int dudeSlope ;
2020-12-04 22:21:42 +00:00
DUDEEXTRA dudeExtra ;
2021-09-01 19:53:33 +00:00
SPRITEMASS spriteMass ;
2021-09-16 18:49:25 +00:00
int cumulDamage ;
2020-11-07 15:26:14 +00:00
2021-05-05 08:12:31 +00:00
DBloodActor ( ) : index ( int ( this - base ( ) ) ) { /*assert(index >= 0 && index < kMaxSprites);*/ }
DBloodActor & operator = ( const DBloodActor & other ) = default ;
2020-12-02 19:22:13 +00:00
void Clear ( )
{
dudeSlope = 0 ;
2020-12-04 22:21:42 +00:00
dudeExtra = { } ;
2021-09-01 19:53:33 +00:00
spriteMass = { } ;
2020-12-02 19:22:13 +00:00
}
2021-05-05 08:12:31 +00:00
bool hasX ( ) { return sprite [ index ] . extra > 0 ; }
2020-12-02 22:39:38 +00:00
void addX ( )
{
if ( s ( ) . extra = = - 1 ) dbInsertXSprite ( s ( ) . index ) ;
}
2020-12-02 11:46:44 +00:00
spritetype & s ( ) { return sprite [ index ] ; }
XSPRITE & x ( ) { return xsprite [ sprite [ index ] . extra ] ; } // calling this does not validate the xsprite!
2021-05-05 08:12:31 +00:00
SPRITEHIT & hit ( ) { return gSpriteHit [ sprite [ index ] . extra ] ; }
int & xvel ( ) { return Blood : : xvel [ index ] ; }
int & yvel ( ) { return Blood : : yvel [ index ] ; }
int & zvel ( ) { return Blood : : zvel [ index ] ; }
2021-09-01 19:54:23 +00:00
int GetIndex ( ) { return s ( ) . index ; } // this is for error printing only!
2020-12-02 11:46:44 +00:00
2021-05-05 08:12:31 +00:00
GENDUDEEXTRA & genDudeExtra ( ) { return Blood : : gGenDudeExtra [ index ] ; }
POINT3D & basePoint ( ) { return Blood : : baseSprite [ index ] ; }
2020-12-02 19:22:13 +00:00
void SetOwner ( DBloodActor * own )
{
2021-05-05 08:12:31 +00:00
s ( ) . owner = own ? own - > s ( ) . index : - 1 ;
2020-12-02 19:22:13 +00:00
}
DBloodActor * GetOwner ( )
{
2021-05-05 08:12:31 +00:00
if ( s ( ) . owner = = - 1 | | s ( ) . owner = = kMaxSprites - 1 ) return nullptr ;
2020-12-02 19:22:13 +00:00
return base ( ) + s ( ) . owner ;
}
2020-12-03 17:00:07 +00:00
void SetTarget ( DBloodActor * own )
{
2021-09-15 22:40:09 +00:00
x ( ) . target_i = own ? own - > s ( ) . index : - 1 ;
2020-12-03 17:00:07 +00:00
}
DBloodActor * GetTarget ( )
{
2021-05-05 08:12:31 +00:00
if ( x ( ) . target_i < = - 1 | | x ( ) . target_i = = kMaxSprites - 1 ) return nullptr ;
2021-09-15 22:40:09 +00:00
return base ( ) + x ( ) . target_i ;
2020-12-03 17:00:07 +00:00
}
2021-05-05 08:12:31 +00:00
bool ValidateTarget ( const char * func )
{
if ( GetTarget ( ) = = nullptr )
{
Printf ( PRINT_HIGH | PRINT_NOTIFY , " %s: invalid target in calling actor \n " , func ) ;
return false ;
}
return true ;
}
2020-12-03 19:30:30 +00:00
void SetBurnSource ( DBloodActor * own )
{
x ( ) . burnSource = own ? own - > s ( ) . index : - 1 ;
}
DBloodActor * GetBurnSource ( )
{
if ( x ( ) . burnSource = = - 1 | | x ( ) . burnSource = = kMaxSprites - 1 ) return nullptr ;
return base ( ) + x ( ) . burnSource ;
}
2020-12-02 23:30:19 +00:00
void SetSpecialOwner ( ) // nnext hackery
{
s ( ) . owner = kMaxSprites - 1 ;
}
bool GetSpecialOwner ( )
{
return ( s ( ) . owner = = kMaxSprites - 1 ) ;
}
2020-12-02 19:22:13 +00:00
bool IsPlayerActor ( )
{
return s ( ) . type > = kDudePlayer1 & & s ( ) . type < = kDudePlayer8 ;
}
bool IsDudeActor ( )
{
return s ( ) . type > = kDudeBase & & s ( ) . type < kDudeMax ;
}
bool IsItemActor ( )
{
return s ( ) . type > = kItemBase & & s ( ) . type < kItemMax ;
}
bool IsWeaponActor ( )
{
return s ( ) . type > = kItemWeaponBase & & s ( ) . type < kItemWeaponMax ;
}
bool IsAmmoActor ( )
{
return s ( ) . type > = kItemAmmoBase & & s ( ) . type < kItemAmmoMax ;
}
2020-12-03 19:30:30 +00:00
bool isActive ( )
{
if ( ! hasX ( ) )
return false ;
switch ( x ( ) . aiState - > stateType )
{
case kAiStateIdle :
case kAiStateGenIdle :
case kAiStateSearch :
case kAiStateMove :
case kAiStateOther :
return false ;
default :
return true ;
}
}
2020-12-05 16:24:27 +00:00
void addExtra ( )
{
if ( s ( ) . extra < = 0 ) s ( ) . extra = dbInsertXSprite ( index ) ;
}
2020-12-02 11:46:44 +00:00
} ;
extern DBloodActor bloodActors [ kMaxSprites ] ;
inline DBloodActor * DBloodActor : : base ( ) { return bloodActors ; }
2020-12-02 16:10:00 +00:00
// Iterator wrappers that return an actor pointer, not an index.
class BloodStatIterator : public StatIterator
{
public :
BloodStatIterator ( int stat ) : StatIterator ( stat )
{
}
DBloodActor * Next ( )
{
int n = NextIndex ( ) ;
return n > = 0 ? & bloodActors [ n ] : nullptr ;
}
DBloodActor * Peek ( )
{
int n = PeekIndex ( ) ;
return n > = 0 ? & bloodActors [ n ] : nullptr ;
}
} ;
class BloodSectIterator : public SectIterator
{
public :
BloodSectIterator ( int stat ) : SectIterator ( stat )
{
}
DBloodActor * Next ( )
{
int n = NextIndex ( ) ;
return n > = 0 ? & bloodActors [ n ] : nullptr ;
}
DBloodActor * Peek ( )
{
int n = PeekIndex ( ) ;
return n > = 0 ? & bloodActors [ n ] : nullptr ;
}
} ;
2020-12-02 19:05:53 +00:00
inline int DeleteSprite ( DBloodActor * nSprite )
{
if ( nSprite ) return DeleteSprite ( nSprite - > s ( ) . index ) ;
return 0 ;
}
2020-12-02 20:39:37 +00:00
inline void actBurnSprite ( DBloodActor * pSource , DBloodActor * pTarget , int nTime )
{
auto pXSprite = & pTarget - > x ( ) ;
pXSprite - > burnTime = ClipHigh ( pXSprite - > burnTime + nTime , sprite [ pXSprite - > reference ] . statnum = = kStatDude ? 2400 : 1200 ) ;
2021-05-10 22:02:01 +00:00
pXSprite - > burnSource = pSource ? pSource - > s ( ) . index : - 1 ;
2020-12-02 20:39:37 +00:00
}
2020-12-02 16:10:00 +00:00
2020-12-02 22:39:38 +00:00
inline void GetActorExtents ( DBloodActor * actor , int * top , int * bottom )
{
GetSpriteExtents ( & actor - > s ( ) , top , bottom ) ;
}
2020-12-02 23:20:14 +00:00
inline DBloodActor * PLAYER : : fragger ( )
{
return fraggerId = = - 1 ? nullptr : & bloodActors [ fraggerId ] ;
}
inline void PLAYER : : setFragger ( DBloodActor * actor )
{
fraggerId = actor = = nullptr ? - 1 : actor - > s ( ) . index ;
}
2020-12-05 22:49:51 +00:00
inline DBloodActor * PLAYER : : actor ( )
{
return & bloodActors [ pSprite - > index ] ;
}
2020-12-03 19:30:30 +00:00
// Wrapper around the insane collision info mess from Build.
struct Collision
{
int type ;
int index ;
int legacyVal ; // should be removed later, but needed for converting back for unadjusted code.
DBloodActor * actor ;
Collision ( ) = default ;
Collision ( int legacyval ) { setFromEngine ( legacyval ) ; }
int setNone ( )
{
type = kHitNone ;
index = - 1 ;
legacyVal = 0 ;
actor = nullptr ;
return kHitNone ;
}
int setSector ( int num )
{
type = kHitSector ;
index = num ;
legacyVal = type | index ;
actor = nullptr ;
return kHitSector ;
}
int setWall ( int num )
{
type = kHitWall ;
index = num ;
legacyVal = type | index ;
actor = nullptr ;
return kHitWall ;
}
int setSprite ( DBloodActor * num )
{
type = kHitSprite ;
index = - 1 ;
legacyVal = type | int ( num - bloodActors ) ;
actor = num ;
return kHitSprite ;
}
int setFromEngine ( int value )
{
legacyVal = value ;
type = value & kHitTypeMask ;
if ( type = = 0 ) { index = - 1 ; actor = nullptr ; }
else if ( type ! = kHitSprite ) { index = value & kHitIndexMask ; actor = nullptr ; }
else { index = - 1 ; actor = & bloodActors [ value & kHitIndexMask ] ; }
return type ;
}
} ;
2020-12-04 23:08:51 +00:00
inline DBloodActor * getUpperLink ( int sect )
{
auto l = gUpperLink [ sect ] ;
return l = = - 1 ? nullptr : & bloodActors [ l ] ;
}
inline DBloodActor * getLowerLink ( int sect )
{
auto l = gLowerLink [ sect ] ;
return l = = - 1 ? nullptr : & bloodActors [ l ] ;
}
2020-12-05 11:54:26 +00:00
inline void viewBackupSpriteLoc ( DBloodActor * actor )
{
viewBackupSpriteLoc ( actor - > s ( ) . index , & actor - > s ( ) ) ;
}
2021-08-30 18:12:19 +00:00
inline FSerializer & Serialize ( FSerializer & arc , const char * keyname , DBloodActor * & w , DBloodActor * * def )
{
int index = w ? int ( w - bloodActors ) : - 1 ;
Serialize ( arc , keyname , index , nullptr ) ;
if ( arc . isReading ( ) ) w = index = = - 1 ? nullptr : & bloodActors [ index ] ;
return arc ;
}
2021-09-15 22:12:28 +00:00
inline void sfxPlay3DSound ( DBloodActor * pSprite , int soundId , int a3 = - 1 , int a4 = 0 )
{
sfxPlay3DSound ( & pSprite - > s ( ) , soundId , a3 , a4 ) ;
}
inline void sfxPlay3DSoundCP ( DBloodActor * pSprite , int soundId , int a3 = - 1 , int a4 = 0 , int pitch = 0 , int volume = 0 )
{
sfxPlay3DSoundCP ( & pSprite - > s ( ) , soundId , a3 , a4 , pitch , volume ) ;
}
inline void sfxKill3DSound ( DBloodActor * pSprite , int a2 = - 1 , int a3 = - 1 )
{
sfxKill3DSound ( & pSprite - > s ( ) , a2 , a3 ) ;
}
2020-12-02 11:46:44 +00:00
END_BLD_NS