2020-12-02 11:46:44 +00:00
# pragma once
BEGIN_BLD_NS
2021-09-02 18:23:51 +00:00
class DBloodActor ;
// 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 ) ; }
// need forward declarations of these.
int actorIndex ( DBloodActor * ) ;
DBloodActor * Actor ( int ) ;
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 | actorIndex ( num ) ;
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 = Actor ( value & kHitIndexMask ) ; }
return type ;
}
walltype * wall ( )
{
assert ( type = = kHitWall ) ;
return & : : wall [ index ] ;
}
sectortype * sector ( )
{
assert ( type = = kHitSector ) ;
return & : : sector [ index ] ;
}
} ;
struct SPRITEHIT
{
Collision hit , ceilhit , florhit ;
} ;
2021-08-28 13:43:34 +00:00
struct ConditionElement
{
int type ;
int index ;
DBloodActor * actor ;
bool operator = = ( const ConditionElement & other ) const
{
if ( type ! = other . type ) return false ;
if ( type = = kCondSerialSprite & & actor ! = other . actor ) return false ;
if ( type ! = kCondSerialSprite & & index ! = other . index ) return false ;
return true ;
}
bool operator ! = ( const ConditionElement & other ) const
{
return ! ( operator = = ( other ) ) ;
}
} ;
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 ;
2021-09-05 08:09:59 +00:00
int xvel , yvel , zvel ;
bool hasx ;
XSPRITE xsprite ;
2021-08-29 17:09:29 +00:00
SPRITEHIT hit ;
2020-12-04 22:21:42 +00:00
DUDEEXTRA dudeExtra ;
2021-09-01 19:53:33 +00:00
SPRITEMASS spriteMass ;
2021-08-29 07:27:03 +00:00
GENDUDEEXTRA genDudeExtra ;
2021-08-29 13:57:42 +00:00
DBloodActor * prevmarker ; // needed by the nnext marker code. This originally hijacked targetX in XSPRITE
2021-11-19 20:19:18 +00:00
DBloodActor * ownerActor ; // was previously stored in the sprite's owner field.
2021-09-04 10:23:36 +00:00
POINT3D basePoint ;
2021-09-05 08:09:59 +00:00
ConditionElement condition [ 2 ] ;
bool explosionhackflag ; // this originally hijacked the target field which is not safe when working with pointers.
2021-09-01 19:53:33 +00:00
2021-08-28 13:43:34 +00:00
// transient data (not written to savegame)
int cumulDamage ;
2021-09-05 10:35:13 +00:00
bool interpolated ;
2020-11-07 15:26:14 +00:00
2021-09-05 10:35:13 +00:00
DBloodActor ( ) : index ( int ( this - base ( ) ) ) { }
2021-05-05 08:12:31 +00:00
DBloodActor & operator = ( const DBloodActor & other ) = default ;
2020-12-02 19:22:13 +00:00
void Clear ( )
{
dudeSlope = 0 ;
2021-09-04 17:53:31 +00:00
hit = { } ;
2020-12-04 22:21:42 +00:00
dudeExtra = { } ;
2021-09-01 19:53:33 +00:00
spriteMass = { } ;
2021-09-04 17:53:31 +00:00
genDudeExtra = { } ;
prevmarker = nullptr ;
2021-09-04 10:23:36 +00:00
basePoint = { } ;
2021-09-05 08:09:59 +00:00
xsprite = { } ;
hasx = false ;
2021-09-05 10:35:13 +00:00
interpolated = false ;
2021-09-04 10:52:02 +00:00
xvel = yvel = zvel = 0 ;
2021-09-04 17:53:31 +00:00
explosionhackflag = false ;
interpolated = false ;
2020-12-02 19:22:13 +00:00
}
2021-09-05 08:09:59 +00:00
bool hasX ( ) { return hasx ; }
void addX ( ) { hasx = true ; }
2020-12-02 11:46:44 +00:00
spritetype & s ( ) { return sprite [ index ] ; }
2021-09-05 08:09:59 +00:00
XSPRITE & x ( ) { return xsprite ; } // calling this does not validate the xsprite!
2021-10-24 07:11:43 +00:00
int GetIndex ( ) { return s ( ) . time ; } // For error printing only! This is only identical with the sprite index for items spawned at map start.
2021-09-05 17:05:06 +00:00
int GetSpriteIndex ( ) { return index ; } // this is only here to mark places that need changing later!
2020-12-02 11:46:44 +00:00
2020-12-02 19:22:13 +00:00
void SetOwner ( DBloodActor * own )
{
2021-11-19 20:19:18 +00:00
ownerActor = own ;
2020-12-02 19:22:13 +00:00
}
DBloodActor * GetOwner ( )
{
2021-11-19 20:19:18 +00:00
return ownerActor ;
2020-12-02 19:22:13 +00:00
}
2020-12-03 17:00:07 +00:00
void SetTarget ( DBloodActor * own )
{
2021-11-19 19:54:13 +00:00
x ( ) . target = own ;
2020-12-03 17:00:07 +00:00
}
DBloodActor * GetTarget ( )
{
2021-11-19 19:54:13 +00:00
return x ( ) . target ;
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 )
{
2021-09-05 17:05:06 +00:00
x ( ) . burnSource = own ? own - > GetSpriteIndex ( ) : - 1 ;
2020-12-03 19:30:30 +00:00
}
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
{
2021-11-19 20:19:18 +00:00
ownerActor = nullptr ;
2020-12-02 23:30:19 +00:00
s ( ) . owner = kMaxSprites - 1 ;
}
bool GetSpecialOwner ( )
{
2021-11-19 20:19:18 +00:00
return ownerActor = = nullptr & & ( s ( ) . owner = = kMaxSprites - 1 ) ;
2020-12-02 23:30:19 +00:00
}
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 ;
}
}
2021-11-19 16:29:49 +00:00
sectortype * sector ( )
{
return s ( ) . sector ( ) ;
}
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 ;
}
} ;
2021-08-29 18:47:51 +00:00
// An iterator to iterate over all sprites.
class BloodSpriteIterator
{
BloodStatIterator it ;
int stat = kStatDecoration ;
public :
BloodSpriteIterator ( ) : it ( kStatDecoration ) { }
DBloodActor * Next ( )
{
while ( stat < kStatFree )
{
auto ac = it . Next ( ) ;
if ( ac ) return ac ;
stat + + ;
if ( stat < kStatFree ) it . Reset ( stat ) ;
}
return nullptr ;
}
} ;
// For iterating linearly over map spawned sprites.
class BloodLinearSpriteIterator
{
int index = 0 ;
public :
2021-09-05 06:27:34 +00:00
void Reset ( )
{
index = 0 ;
}
2021-08-29 18:47:51 +00:00
DBloodActor * Next ( )
{
while ( index < MAXSPRITES )
{
auto p = & bloodActors [ index + + ] ;
if ( p - > s ( ) . statnum ! = kStatFree ) return p ;
}
return nullptr ;
}
} ;
2020-12-02 19:05:53 +00:00
inline int DeleteSprite ( DBloodActor * nSprite )
{
2021-09-05 17:05:06 +00:00
if ( nSprite ) return DeleteSprite ( nSprite - > GetSpriteIndex ( ) ) ;
2020-12-02 19:05:53 +00:00
return 0 ;
}
2020-12-02 22:39:38 +00:00
inline void GetActorExtents ( DBloodActor * actor , int * top , int * bottom )
{
GetSpriteExtents ( & actor - > s ( ) , top , bottom ) ;
}
2020-12-04 23:08:51 +00:00
inline DBloodActor * getUpperLink ( int sect )
{
2021-11-20 17:42:19 +00:00
auto pSect = & sector [ sect ] ;
return pSect - > upperLink ;
2020-12-04 23:08:51 +00:00
}
inline DBloodActor * getLowerLink ( int sect )
{
2021-11-20 17:42:19 +00:00
auto pSect = & sector [ sect ] ;
return pSect - > lowerLink ;
2020-12-04 23:08:51 +00:00
}
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 ) ;
}
2021-09-02 18:23:51 +00:00
inline void ChangeActorStat ( DBloodActor * actor , int stat )
2021-08-27 14:38:53 +00:00
{
2021-09-05 17:05:06 +00:00
ChangeSpriteStat ( actor - > GetSpriteIndex ( ) , stat ) ;
2021-08-27 14:38:53 +00:00
}
2021-09-02 18:23:51 +00:00
inline void ChangeActorSect ( DBloodActor * actor , int stat )
2021-08-27 14:38:53 +00:00
{
2021-09-05 17:05:06 +00:00
ChangeSpriteSect ( actor - > GetSpriteIndex ( ) , stat ) ;
2021-08-27 14:38:53 +00:00
}
2021-09-02 18:23:51 +00:00
inline int Collision : : actorIndex ( DBloodActor * actor )
{
return int ( actor - bloodActors ) ;
}
inline DBloodActor * Collision : : Actor ( int a )
{
return & bloodActors [ a ] ;
}
2021-08-28 11:59:29 +00:00
inline void setActorPos ( DBloodActor * actor , vec3_t * pos )
{
2021-09-05 17:05:06 +00:00
setsprite ( actor - > GetSpriteIndex ( ) , pos ) ;
2021-08-28 11:59:29 +00:00
}
2020-12-02 11:46:44 +00:00
END_BLD_NS