2019-09-19 22:42:45 +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 .
*/
//-------------------------------------------------------------------------
2019-09-21 18:59:54 +00:00
# include "ns.h" // Must come before everything else!
2019-09-19 22:42:45 +00:00
# include "build.h"
# include "pragmas.h"
2020-11-21 22:40:33 +00:00
# include "savegamehelp.h"
2019-09-19 22:42:45 +00:00
# include "mmulti.h"
# include "common_game.h"
# include "actor.h"
# include "ai.h"
2020-07-25 15:56:39 +00:00
# include "aistate.h"
2020-01-26 11:19:01 +00:00
# include "aiunicult.h"
2019-09-19 22:42:45 +00:00
# include "blood.h"
# include "db.h"
# include "dude.h"
# include "eventq.h"
# include "fx.h"
# include "gameutil.h"
# include "gib.h"
# include "globals.h"
# include "levels.h"
# include "loadsave.h"
# include "player.h"
# include "seq.h"
# include "sound.h"
# include "triggers.h"
2019-11-08 19:57:01 +00:00
# include "view.h"
2020-02-07 19:47:43 +00:00
# include "nnexts.h"
2019-09-19 22:42:45 +00:00
2019-09-22 06:39:22 +00:00
BEGIN_BLD_NS
2019-09-19 22:42:45 +00:00
int cumulDamage [ kMaxXSprites ] ;
int gDudeSlope [ kMaxXSprites ] ;
DUDEEXTRA gDudeExtra [ kMaxXSprites ] ;
AISTATE genIdle = { kAiStateGenIdle , 0 , - 1 , 0 , NULL , NULL , NULL , NULL } ;
AISTATE genRecoil = { kAiStateRecoil , 5 , - 1 , 20 , NULL , NULL , NULL , & genIdle } ;
2020-02-11 23:22:11 +00:00
const int dword_138BB0 [ 5 ] = { 0x2000 , 0x4000 , 0x8000 , 0xa000 , 0xe000 } ;
2019-09-19 22:42:45 +00:00
2020-11-21 17:33:31 +00:00
bool dudeIsPlayingSeq ( spritetype * pSprite , int nSeq )
2019-09-19 22:42:45 +00:00
{
2019-10-07 19:29:52 +00:00
if ( pSprite - > statnum = = kStatDude & & pSprite - > type > = kDudeBase & & pSprite - > type < kDudeMax )
2019-09-19 22:42:45 +00:00
{
2020-02-05 21:17:05 +00:00
DUDEINFO * pDudeInfo = getDudeInfo ( pSprite - > type ) ;
2019-09-19 22:42:45 +00:00
if ( seqGetID ( 3 , pSprite - > extra ) = = pDudeInfo - > seqStartID + nSeq & & seqGetStatus ( 3 , pSprite - > extra ) > = 0 )
return true ;
}
return false ;
}
void aiPlay3DSound ( spritetype * pSprite , int a2 , AI_SFX_PRIORITY a3 , int a4 )
{
DUDEEXTRA * pDudeExtra = & gDudeExtra [ pSprite - > extra ] ;
if ( a3 = = AI_SFX_PRIORITY_0 )
sfxPlay3DSound ( pSprite , a2 , a4 , 2 ) ;
2020-11-21 22:40:33 +00:00
else if ( a3 > pDudeExtra - > prio | | pDudeExtra - > time < = gFrameClock )
2019-09-19 22:42:45 +00:00
{
sfxKill3DSound ( pSprite , - 1 , - 1 ) ;
sfxPlay3DSound ( pSprite , a2 , a4 , 0 ) ;
2020-11-21 22:40:33 +00:00
pDudeExtra - > prio = a3 ;
pDudeExtra - > time = gFrameClock + 120 ;
2019-09-19 22:42:45 +00:00
}
}
void aiNewState ( spritetype * pSprite , XSPRITE * pXSprite , AISTATE * pAIState )
{
2020-02-05 21:17:05 +00:00
DUDEINFO * pDudeInfo = getDudeInfo ( pSprite - > type ) ;
2019-11-24 20:53:51 +00:00
pXSprite - > stateTimer = pAIState - > stateTicks ;
2019-09-19 22:42:45 +00:00
pXSprite - > aiState = pAIState ;
int seqStartId = pDudeInfo - > seqStartID ;
2019-11-24 20:53:51 +00:00
if ( pAIState - > seqId > = 0 ) {
seqStartId + = pAIState - > seqId ;
2020-07-25 20:47:46 +00:00
if ( getSequence ( seqStartId ) )
2019-11-24 20:53:51 +00:00
seqSpawn ( seqStartId , 3 , pSprite - > extra , pAIState - > funcId ) ;
2019-09-19 22:42:45 +00:00
}
2019-11-24 20:53:51 +00:00
if ( pAIState - > enterFunc )
pAIState - > enterFunc ( pSprite , pXSprite ) ;
2019-09-19 22:42:45 +00:00
}
2019-11-24 20:53:51 +00:00
2020-02-15 21:53:21 +00:00
bool isImmune ( spritetype * pSprite , int dmgType , int minScale ) {
2020-02-07 19:47:43 +00:00
if ( dmgType > = kDmgFall & & dmgType < kDmgMax & & pSprite - > extra > = 0 & & xsprite [ pSprite - > extra ] . locked ! = 1 ) {
if ( pSprite - > type > = kThingBase & & pSprite - > type < kThingMax )
return ( thingInfo [ pSprite - > type - kThingBase ] . dmgControl [ dmgType ] < = minScale ) ;
else if ( IsDudeSprite ( pSprite ) ) {
if ( IsPlayerSprite ( pSprite ) ) return ( gPlayer [ pSprite - > type - kDudePlayer1 ] . damageControl [ dmgType ] < = minScale ) ;
else return ( dudeInfo [ pSprite - > type - kDudeBase ] . at70 [ dmgType ] < = minScale ) ;
}
}
return true ;
}
2019-09-19 22:42:45 +00:00
bool CanMove ( spritetype * pSprite , int a2 , int nAngle , int nRange )
{
int top , bottom ;
GetSpriteExtents ( pSprite , & top , & bottom ) ;
int x = pSprite - > x ;
int y = pSprite - > y ;
int z = pSprite - > z ;
2020-09-01 13:00:35 +00:00
HitScan ( pSprite , z , CosScale16 ( nAngle ) , SinScale16 ( nAngle ) , 0 , CLIPMASK0 , nRange ) ;
2019-09-19 22:42:45 +00:00
int nDist = approxDist ( x - gHitInfo . hitx , y - gHitInfo . hity ) ;
if ( nDist - ( pSprite - > clipdist < < 2 ) < nRange )
{
if ( gHitInfo . hitsprite < 0 | | a2 ! = gHitInfo . hitsprite )
return false ;
return true ;
}
x + = mulscale30 ( nRange , Cos ( nAngle ) ) ;
y + = mulscale30 ( nRange , Sin ( nAngle ) ) ;
int nSector = pSprite - > sectnum ;
2020-10-11 10:38:17 +00:00
assert ( nSector > = 0 & & nSector < kMaxSectors ) ;
2019-09-19 22:42:45 +00:00
if ( ! FindSector ( x , y , z , & nSector ) )
return false ;
int floorZ = getflorzofslope ( nSector , x , y ) ;
int nXSector = sector [ nSector ] . extra ;
char Underwater = 0 ; char Water = 0 ; char Depth = 0 ; char Crusher = 0 ;
XSECTOR * pXSector = NULL ;
if ( nXSector > 0 )
{
pXSector = & xsector [ nXSector ] ;
if ( pXSector - > Underwater )
Underwater = 1 ;
if ( pXSector - > Depth )
Depth = 1 ;
2020-02-07 19:47:43 +00:00
if ( sector [ nSector ] . type = = kSectorDamage | | pXSector - > damageType > 0 )
Crusher = 1 ;
2019-09-19 22:42:45 +00:00
}
int nUpper = gUpperLink [ nSector ] ;
int nLower = gLowerLink [ nSector ] ;
if ( nUpper > = 0 )
{
if ( sprite [ nUpper ] . type = = kMarkerUpWater | | sprite [ nUpper ] . type = = kMarkerUpGoo )
Water = Depth = 1 ;
}
if ( nLower > = 0 )
{
if ( sprite [ nLower ] . type = = kMarkerLowWater | | sprite [ nLower ] . type = = kMarkerLowGoo )
Depth = 1 ;
}
2019-10-11 21:59:39 +00:00
switch ( pSprite - > type ) {
case kDudeGargoyleFlesh :
case kDudeGargoyleStone :
case kDudeBat :
2019-09-19 22:42:45 +00:00
if ( pSprite - > clipdist > nDist )
return 0 ;
if ( Depth )
{
// Ouch...
if ( Depth )
return false ;
if ( Crusher )
return false ;
}
break ;
2019-10-11 21:59:39 +00:00
case kDudeBoneEel :
2019-09-19 22:42:45 +00:00
if ( Water )
return false ;
if ( ! Underwater )
return false ;
if ( Underwater )
return true ;
break ;
2020-02-07 19:47:43 +00:00
case kDudeCerberusTwoHead :
case kDudeCerberusOneHead :
// by NoOne: a quick fix for Cerberus spinning in E3M7-like maps, where damage sectors is used.
// It makes ignore danger if enemy immune to N damageType. As result Cerberus start acting like
// in Blood 1.0 so it can move normally to player. It's up to you for adding rest of enemies here as
// i don't think it will broke something in game.
2020-02-15 21:53:21 +00:00
if ( ! VanillaMode ( ) & & Crusher & & isImmune ( pSprite , pXSector - > damageType , 16 ) ) return true ;
2020-02-07 19:47:43 +00:00
fallthrough__ ;
2019-10-11 21:59:39 +00:00
case kDudeZombieButcher :
case kDudeSpiderBrown :
case kDudeSpiderRed :
case kDudeSpiderBlack :
case kDudeSpiderMother :
case kDudeHellHound :
case kDudeRat :
case kDudeInnocent :
2019-09-19 22:42:45 +00:00
if ( Crusher )
return false ;
if ( Depth | | Underwater )
return false ;
if ( floorZ - bottom > 0x2000 )
return false ;
break ;
2020-01-26 11:19:01 +00:00
# ifdef NOONE_EXTENSIONS
2019-10-11 21:59:39 +00:00
case kDudeModernCustom :
case kDudeModernCustomBurning :
2020-02-15 21:53:21 +00:00
if ( ( Crusher & & ! nnExtIsImmune ( pSprite , pXSector - > damageType ) ) | | ( ( Water | | Underwater ) & & ! canSwim ( pSprite ) ) ) return false ;
2019-09-19 22:42:45 +00:00
return true ;
2019-07-23 16:09:21 +00:00
fallthrough__ ;
2020-01-26 11:19:01 +00:00
# endif
2019-10-11 21:59:39 +00:00
case kDudeZombieAxeNormal :
case kDudePhantasm :
case kDudeGillBeast :
2019-09-19 22:42:45 +00:00
default :
if ( Crusher )
return false ;
if ( ( nXSector < 0 | | ( ! xsector [ nXSector ] . Underwater & & ! xsector [ nXSector ] . Depth ) ) & & floorZ - bottom > 0x2000 )
return false ;
break ;
}
return 1 ;
}
void aiChooseDirection ( spritetype * pSprite , XSPRITE * pXSprite , int a3 )
{
int nSprite = pSprite - > index ;
2020-10-11 10:38:17 +00:00
assert ( pSprite - > type > = kDudeBase & & pSprite - > type < kDudeMax ) ;
2019-09-19 22:42:45 +00:00
int vc = ( ( a3 + 1024 - pSprite - > ang ) & 2047 ) - 1024 ;
int nCos = Cos ( pSprite - > ang ) ;
int nSin = Sin ( pSprite - > ang ) ;
int dx = xvel [ nSprite ] ;
int dy = yvel [ nSprite ] ;
int t1 = dmulscale30 ( dx , nCos , dy , nSin ) ;
int vsi = ( ( t1 * 15 ) > > 12 ) / 2 ;
int v8 = 341 ;
if ( vc < 0 )
v8 = - 341 ;
if ( CanMove ( pSprite , pXSprite - > target , pSprite - > ang + vc , vsi ) )
pXSprite - > goalAng = pSprite - > ang + vc ;
else if ( CanMove ( pSprite , pXSprite - > target , pSprite - > ang + vc / 2 , vsi ) )
pXSprite - > goalAng = pSprite - > ang + vc / 2 ;
else if ( CanMove ( pSprite , pXSprite - > target , pSprite - > ang - vc / 2 , vsi ) )
pXSprite - > goalAng = pSprite - > ang - vc / 2 ;
else if ( CanMove ( pSprite , pXSprite - > target , pSprite - > ang + v8 , vsi ) )
pXSprite - > goalAng = pSprite - > ang + v8 ;
else if ( CanMove ( pSprite , pXSprite - > target , pSprite - > ang , vsi ) )
pXSprite - > goalAng = pSprite - > ang ;
else if ( CanMove ( pSprite , pXSprite - > target , pSprite - > ang - v8 , vsi ) )
pXSprite - > goalAng = pSprite - > ang - v8 ;
2020-02-07 19:47:43 +00:00
//else if (pSprite->flags&2)
//pXSprite->goalAng = pSprite->ang+341;
2019-09-19 22:42:45 +00:00
else // Weird..
pXSprite - > goalAng = pSprite - > ang + 341 ;
if ( Chance ( 0x8000 ) )
pXSprite - > dodgeDir = 1 ;
else
pXSprite - > dodgeDir = - 1 ;
if ( ! CanMove ( pSprite , pXSprite - > target , pSprite - > ang + pXSprite - > dodgeDir * 512 , 512 ) )
{
pXSprite - > dodgeDir = - pXSprite - > dodgeDir ;
if ( ! CanMove ( pSprite , pXSprite - > target , pSprite - > ang + pXSprite - > dodgeDir * 512 , 512 ) )
pXSprite - > dodgeDir = 0 ;
}
}
void aiMoveForward ( spritetype * pSprite , XSPRITE * pXSprite )
{
int nSprite = pSprite - > index ;
2020-10-11 10:38:17 +00:00
assert ( pSprite - > type > = kDudeBase & & pSprite - > type < kDudeMax ) ;
2020-02-05 21:17:05 +00:00
DUDEINFO * pDudeInfo = getDudeInfo ( pSprite - > type ) ;
2019-09-19 22:42:45 +00:00
int nAng = ( ( pXSprite - > goalAng + 1024 - pSprite - > ang ) & 2047 ) - 1024 ;
int nTurnRange = ( pDudeInfo - > angSpeed < < 2 ) > > 4 ;
pSprite - > ang = ( pSprite - > ang + ClipRange ( nAng , - nTurnRange , nTurnRange ) ) & 2047 ;
if ( klabs ( nAng ) > 341 )
return ;
xvel [ nSprite ] + = mulscale30 ( pDudeInfo - > frontSpeed , Cos ( pSprite - > ang ) ) ;
yvel [ nSprite ] + = mulscale30 ( pDudeInfo - > frontSpeed , Sin ( pSprite - > ang ) ) ;
}
void aiMoveTurn ( spritetype * pSprite , XSPRITE * pXSprite )
{
2020-10-11 10:38:17 +00:00
assert ( pSprite - > type > = kDudeBase & & pSprite - > type < kDudeMax ) ;
2020-02-05 21:17:05 +00:00
DUDEINFO * pDudeInfo = getDudeInfo ( pSprite - > type ) ;
2019-09-19 22:42:45 +00:00
int nAng = ( ( pXSprite - > goalAng + 1024 - pSprite - > ang ) & 2047 ) - 1024 ;
int nTurnRange = ( pDudeInfo - > angSpeed < < 2 ) > > 4 ;
pSprite - > ang = ( pSprite - > ang + ClipRange ( nAng , - nTurnRange , nTurnRange ) ) & 2047 ;
}
void aiMoveDodge ( spritetype * pSprite , XSPRITE * pXSprite )
{
int nSprite = pSprite - > index ;
2020-10-11 10:38:17 +00:00
assert ( pSprite - > type > = kDudeBase & & pSprite - > type < kDudeMax ) ;
2020-02-05 21:17:05 +00:00
DUDEINFO * pDudeInfo = getDudeInfo ( pSprite - > type ) ;
2019-09-19 22:42:45 +00:00
int nAng = ( ( pXSprite - > goalAng + 1024 - pSprite - > ang ) & 2047 ) - 1024 ;
int nTurnRange = ( pDudeInfo - > angSpeed < < 2 ) > > 4 ;
pSprite - > ang = ( pSprite - > ang + ClipRange ( nAng , - nTurnRange , nTurnRange ) ) & 2047 ;
if ( pXSprite - > dodgeDir )
{
int nCos = Cos ( pSprite - > ang ) ;
int nSin = Sin ( pSprite - > ang ) ;
int dx = xvel [ nSprite ] ;
int dy = yvel [ nSprite ] ;
int t1 = dmulscale30 ( dx , nCos , dy , nSin ) ;
int t2 = dmulscale30 ( dx , nSin , - dy , nCos ) ;
if ( pXSprite - > dodgeDir > 0 )
t2 + = pDudeInfo - > sideSpeed ;
else
t2 - = pDudeInfo - > sideSpeed ;
xvel [ nSprite ] = dmulscale30 ( t1 , nCos , t2 , nSin ) ;
yvel [ nSprite ] = dmulscale30 ( t1 , nSin , - t2 , nCos ) ;
}
}
void aiActivateDude ( spritetype * pSprite , XSPRITE * pXSprite )
{
2020-10-11 10:38:17 +00:00
assert ( pSprite - > type > = kDudeBase & & pSprite - > type < kDudeMax ) ;
2019-10-11 21:59:39 +00:00
if ( ! pXSprite - > state ) {
2019-09-19 22:42:45 +00:00
aiChooseDirection ( pSprite , pXSprite , getangle ( pXSprite - > targetX - pSprite - > x , pXSprite - > targetY - pSprite - > y ) ) ;
pXSprite - > state = 1 ;
}
2019-10-11 21:59:39 +00:00
switch ( pSprite - > type ) {
case kDudePhantasm :
2019-09-19 22:42:45 +00:00
{
DUDEEXTRA_at6_u1 * pDudeExtraE = & gDudeExtra [ pSprite - > extra ] . at6 . u1 ;
2020-11-21 22:40:33 +00:00
pDudeExtraE - > xval2 = 0 ;
pDudeExtraE - > xval3 = 1 ;
pDudeExtraE - > xval1 = 0 ;
2019-09-19 22:42:45 +00:00
if ( pXSprite - > target = = - 1 )
aiNewState ( pSprite , pXSprite , & ghostSearch ) ;
else
{
aiPlay3DSound ( pSprite , 1600 , AI_SFX_PRIORITY_1 , - 1 ) ;
aiNewState ( pSprite , pXSprite , & ghostChase ) ;
}
break ;
}
2019-10-11 21:59:39 +00:00
case kDudeCultistTommy :
case kDudeCultistShotgun :
case kDudeCultistTesla :
case kDudeCultistTNT :
case kDudeCultistBeast :
2019-09-19 22:42:45 +00:00
{
DUDEEXTRA_at6_u1 * pDudeExtraE = & gDudeExtra [ pSprite - > extra ] . at6 . u1 ;
2020-11-21 22:40:33 +00:00
pDudeExtraE - > xval3 = 1 ;
pDudeExtraE - > xval1 = 0 ;
2019-10-11 21:59:39 +00:00
if ( pXSprite - > target = = - 1 ) {
switch ( pXSprite - > medium ) {
2019-10-19 19:11:39 +00:00
case kMediumNormal :
2019-10-11 21:59:39 +00:00
aiNewState ( pSprite , pXSprite , & cultistSearch ) ;
if ( Chance ( 0x8000 ) ) {
if ( pSprite - > type = = kDudeCultistTommy ) aiPlay3DSound ( pSprite , 4008 + Random ( 5 ) , AI_SFX_PRIORITY_1 , - 1 ) ;
else aiPlay3DSound ( pSprite , 1008 + Random ( 5 ) , AI_SFX_PRIORITY_1 , - 1 ) ;
}
break ;
2019-10-19 19:11:39 +00:00
case kMediumWater :
case kMediumGoo :
2019-10-11 21:59:39 +00:00
aiNewState ( pSprite , pXSprite , & cultistSwimSearch ) ;
break ;
2019-09-19 22:42:45 +00:00
}
2019-10-11 21:59:39 +00:00
} else {
if ( Chance ( 0x8000 ) ) {
if ( pSprite - > type = = kDudeCultistTommy ) aiPlay3DSound ( pSprite , 4003 + Random ( 4 ) , AI_SFX_PRIORITY_1 , - 1 ) ;
else aiPlay3DSound ( pSprite , 1003 + Random ( 4 ) , AI_SFX_PRIORITY_1 , - 1 ) ;
2019-09-19 22:42:45 +00:00
}
2019-10-11 21:59:39 +00:00
switch ( pXSprite - > medium ) {
2019-10-19 19:11:39 +00:00
case kMediumNormal :
2019-10-11 21:59:39 +00:00
if ( pSprite - > type = = kDudeCultistTommy ) aiNewState ( pSprite , pXSprite , & fanaticChase ) ;
else aiNewState ( pSprite , pXSprite , & cultistChase ) ;
break ;
2019-10-19 19:11:39 +00:00
case kMediumWater :
case kMediumGoo :
2019-10-11 21:59:39 +00:00
aiNewState ( pSprite , pXSprite , & cultistSwimChase ) ;
break ;
2019-09-19 22:42:45 +00:00
}
}
break ;
}
2020-01-26 11:19:01 +00:00
# ifdef NOONE_EXTENSIONS
2019-10-11 21:59:39 +00:00
case kDudeModernCustom :
2019-09-19 22:42:45 +00:00
{
DUDEEXTRA_at6_u1 * pDudeExtraE = & gDudeExtra [ pSprite - > extra ] . at6 . u1 ;
2020-11-21 22:40:33 +00:00
pDudeExtraE - > xval3 = 1 ;
pDudeExtraE - > xval1 = 0 ;
2019-09-19 22:42:45 +00:00
if ( pXSprite - > target = = - 1 ) {
2019-11-24 20:53:51 +00:00
if ( spriteIsUnderwater ( pSprite , false ) ) aiGenDudeNewState ( pSprite , & genDudeSearchW ) ;
else aiGenDudeNewState ( pSprite , & genDudeSearchL ) ;
} else {
if ( Chance ( 0x4000 ) ) playGenDudeSound ( pSprite , kGenDudeSndTargetSpot ) ;
if ( spriteIsUnderwater ( pSprite , false ) ) aiGenDudeNewState ( pSprite , & genDudeChaseW ) ;
else aiGenDudeNewState ( pSprite , & genDudeChaseL ) ;
2019-09-19 22:42:45 +00:00
}
break ;
}
2019-10-11 21:59:39 +00:00
case kDudeModernCustomBurning :
2019-11-24 20:53:51 +00:00
if ( pXSprite - > target = = - 1 ) aiGenDudeNewState ( pSprite , & genDudeBurnSearch ) ;
else aiGenDudeNewState ( pSprite , & genDudeBurnChase ) ;
2019-09-19 22:42:45 +00:00
break ;
2020-01-26 11:19:01 +00:00
# endif
2019-10-11 21:59:39 +00:00
case kDudeCultistTommyProne : {
2019-09-19 22:42:45 +00:00
DUDEEXTRA_at6_u1 * pDudeExtraE = & gDudeExtra [ pSprite - > extra ] . at6 . u1 ;
2020-11-21 22:40:33 +00:00
pDudeExtraE - > xval3 = 1 ; pDudeExtraE - > xval1 = 0 ;
2019-10-11 21:59:39 +00:00
pSprite - > type = kDudeCultistTommy ;
if ( pXSprite - > target = = - 1 ) {
switch ( pXSprite - > medium ) {
case 0 :
aiNewState ( pSprite , pXSprite , & cultistSearch ) ;
if ( Chance ( 0x8000 ) )
aiPlay3DSound ( pSprite , 4008 + Random ( 5 ) , AI_SFX_PRIORITY_1 , - 1 ) ;
break ;
2019-10-19 19:11:39 +00:00
case kMediumWater :
case kMediumGoo :
2019-10-11 21:59:39 +00:00
aiNewState ( pSprite , pXSprite , & cultistSwimSearch ) ;
break ;
2019-09-19 22:42:45 +00:00
}
2019-10-11 21:59:39 +00:00
} else {
2019-09-19 22:42:45 +00:00
if ( Chance ( 0x8000 ) )
aiPlay3DSound ( pSprite , 4008 + Random ( 5 ) , AI_SFX_PRIORITY_1 , - 1 ) ;
2019-10-11 21:59:39 +00:00
switch ( pXSprite - > medium ) {
2019-10-19 19:11:39 +00:00
case kMediumNormal :
2019-10-11 21:59:39 +00:00
aiNewState ( pSprite , pXSprite , & cultistProneChase ) ;
break ;
2019-10-19 19:11:39 +00:00
case kMediumWater :
case kMediumGoo :
2019-10-11 21:59:39 +00:00
aiNewState ( pSprite , pXSprite , & cultistSwimChase ) ;
break ;
2019-09-19 22:42:45 +00:00
}
}
break ;
}
2019-10-11 21:59:39 +00:00
case kDudeCultistShotgunProne :
2019-09-19 22:42:45 +00:00
{
DUDEEXTRA_at6_u1 * pDudeExtraE = & gDudeExtra [ pSprite - > extra ] . at6 . u1 ;
2020-11-21 22:40:33 +00:00
pDudeExtraE - > xval3 = 1 ;
pDudeExtraE - > xval1 = 0 ;
2019-10-11 21:59:39 +00:00
pSprite - > type = kDudeCultistShotgun ;
2019-09-19 22:42:45 +00:00
if ( pXSprite - > target = = - 1 )
{
switch ( pXSprite - > medium )
{
2019-10-19 19:11:39 +00:00
case kMediumNormal :
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & cultistSearch ) ;
if ( Chance ( 0x8000 ) )
aiPlay3DSound ( pSprite , 1008 + Random ( 5 ) , AI_SFX_PRIORITY_1 , - 1 ) ;
break ;
2019-10-19 19:11:39 +00:00
case kMediumWater :
case kMediumGoo :
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & cultistSwimSearch ) ;
break ;
}
}
else
{
if ( Chance ( 0x8000 ) )
aiPlay3DSound ( pSprite , 1003 + Random ( 4 ) , AI_SFX_PRIORITY_1 , - 1 ) ;
switch ( pXSprite - > medium )
{
2019-10-19 19:11:39 +00:00
case kMediumNormal :
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & cultistProneChase ) ;
break ;
2019-10-19 19:11:39 +00:00
case kMediumWater :
case kMediumGoo :
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & cultistSwimChase ) ;
break ;
}
}
break ;
}
2019-10-11 21:59:39 +00:00
case kDudeBurningCultist :
2019-09-19 22:42:45 +00:00
if ( pXSprite - > target = = - 1 )
aiNewState ( pSprite , pXSprite , & cultistBurnSearch ) ;
else
aiNewState ( pSprite , pXSprite , & cultistBurnChase ) ;
break ;
2019-10-11 21:59:39 +00:00
case kDudeBat :
2019-09-19 22:42:45 +00:00
{
DUDEEXTRA_at6_u1 * pDudeExtraE = & gDudeExtra [ pSprite - > extra ] . at6 . u1 ;
2020-11-21 22:40:33 +00:00
pDudeExtraE - > xval2 = 0 ;
pDudeExtraE - > xval3 = 1 ;
pDudeExtraE - > xval1 = 0 ;
2019-09-30 07:18:01 +00:00
if ( ! pSprite - > flags )
pSprite - > flags = 9 ;
2019-09-19 22:42:45 +00:00
if ( pXSprite - > target = = - 1 )
aiNewState ( pSprite , pXSprite , & batSearch ) ;
else
{
if ( Chance ( 0xa000 ) )
aiPlay3DSound ( pSprite , 2000 , AI_SFX_PRIORITY_1 , - 1 ) ;
aiNewState ( pSprite , pXSprite , & batChase ) ;
}
break ;
}
2019-10-11 21:59:39 +00:00
case kDudeBoneEel :
2019-09-19 22:42:45 +00:00
{
DUDEEXTRA_at6_u1 * pDudeExtraE = & gDudeExtra [ pSprite - > extra ] . at6 . u1 ;
2020-11-21 22:40:33 +00:00
pDudeExtraE - > xval2 = 0 ;
pDudeExtraE - > xval3 = 1 ;
pDudeExtraE - > xval1 = 0 ;
2019-09-19 22:42:45 +00:00
if ( pXSprite - > target = = - 1 )
aiNewState ( pSprite , pXSprite , & eelSearch ) ;
else
{
if ( Chance ( 0x8000 ) )
aiPlay3DSound ( pSprite , 1501 , AI_SFX_PRIORITY_1 , - 1 ) ;
else
aiPlay3DSound ( pSprite , 1500 , AI_SFX_PRIORITY_1 , - 1 ) ;
aiNewState ( pSprite , pXSprite , & eelChase ) ;
}
break ;
}
2019-10-11 21:59:39 +00:00
case kDudeGillBeast : {
2019-09-19 22:42:45 +00:00
DUDEEXTRA_at6_u1 * pDudeExtraE = & gDudeExtra [ pSprite - > extra ] . at6 . u1 ;
XSECTOR * pXSector = NULL ;
if ( sector [ pSprite - > sectnum ] . extra > 0 )
pXSector = & xsector [ sector [ pSprite - > sectnum ] . extra ] ;
2020-11-21 22:40:33 +00:00
pDudeExtraE - > xval1 = 0 ;
pDudeExtraE - > xval2 = 0 ;
pDudeExtraE - > xval3 = 1 ;
2019-09-19 22:42:45 +00:00
if ( pXSprite - > target = = - 1 )
{
if ( pXSector & & pXSector - > Underwater )
aiNewState ( pSprite , pXSprite , & gillBeastSwimSearch ) ;
else
aiNewState ( pSprite , pXSprite , & gillBeastSearch ) ;
}
else
{
if ( Chance ( 0x4000 ) )
aiPlay3DSound ( pSprite , 1701 , AI_SFX_PRIORITY_1 , - 1 ) ;
else
aiPlay3DSound ( pSprite , 1700 , AI_SFX_PRIORITY_1 , - 1 ) ;
if ( pXSector & & pXSector - > Underwater )
aiNewState ( pSprite , pXSprite , & gillBeastSwimChase ) ;
else
aiNewState ( pSprite , pXSprite , & gillBeastChase ) ;
}
break ;
}
2019-10-11 21:59:39 +00:00
case kDudeZombieAxeNormal : {
2019-09-19 22:42:45 +00:00
DUDEEXTRA_at6_u2 * pDudeExtraE = & gDudeExtra [ pSprite - > extra ] . at6 . u2 ;
2020-11-21 22:40:33 +00:00
pDudeExtraE - > xval2 = 1 ;
pDudeExtraE - > xval1 = 0 ;
2019-09-19 22:42:45 +00:00
if ( pXSprite - > target = = - 1 )
aiNewState ( pSprite , pXSprite , & zombieASearch ) ;
else
{
if ( Chance ( 0xa000 ) )
{
switch ( Random ( 3 ) )
{
default :
case 0 :
case 3 :
aiPlay3DSound ( pSprite , 1103 , AI_SFX_PRIORITY_1 , - 1 ) ;
break ;
case 1 :
aiPlay3DSound ( pSprite , 1104 , AI_SFX_PRIORITY_1 , - 1 ) ;
break ;
case 2 :
aiPlay3DSound ( pSprite , 1105 , AI_SFX_PRIORITY_1 , - 1 ) ;
break ;
}
}
aiNewState ( pSprite , pXSprite , & zombieAChase ) ;
}
break ;
}
2019-10-11 21:59:39 +00:00
case kDudeZombieAxeBuried :
2019-09-19 22:42:45 +00:00
{
DUDEEXTRA_at6_u2 * pDudeExtraE = & gDudeExtra [ pSprite - > extra ] . at6 . u2 ;
2020-11-21 22:40:33 +00:00
pDudeExtraE - > xval2 = 1 ;
pDudeExtraE - > xval1 = 0 ;
2019-09-19 22:42:45 +00:00
if ( pXSprite - > aiState = = & zombieEIdle )
aiNewState ( pSprite , pXSprite , & zombieEUp ) ;
break ;
}
2019-10-11 21:59:39 +00:00
case kDudeZombieAxeLaying :
2019-09-19 22:42:45 +00:00
{
DUDEEXTRA_at6_u2 * pDudeExtraE = & gDudeExtra [ pSprite - > extra ] . at6 . u2 ;
2020-11-21 22:40:33 +00:00
pDudeExtraE - > xval2 = 1 ;
pDudeExtraE - > xval1 = 0 ;
2019-09-19 22:42:45 +00:00
if ( pXSprite - > aiState = = & zombieSIdle )
aiNewState ( pSprite , pXSprite , & zombie13AC2C ) ;
break ;
}
2019-10-11 21:59:39 +00:00
case kDudeZombieButcher : {
2019-09-19 22:42:45 +00:00
DUDEEXTRA_at6_u2 * pDudeExtraE = & gDudeExtra [ pSprite - > extra ] . at6 . u2 ;
2020-11-21 22:40:33 +00:00
pDudeExtraE - > xval2 = 1 ;
pDudeExtraE - > xval1 = 0 ;
2019-09-19 22:42:45 +00:00
if ( pXSprite - > target = = - 1 )
aiNewState ( pSprite , pXSprite , & zombieFSearch ) ;
else
{
if ( Chance ( 0x4000 ) )
aiPlay3DSound ( pSprite , 1201 , AI_SFX_PRIORITY_1 , - 1 ) ;
else
aiPlay3DSound ( pSprite , 1200 , AI_SFX_PRIORITY_1 , - 1 ) ;
aiNewState ( pSprite , pXSprite , & zombieFChase ) ;
}
break ;
}
2019-10-11 21:59:39 +00:00
case kDudeBurningZombieAxe :
2019-09-19 22:42:45 +00:00
if ( pXSprite - > target = = - 1 )
aiNewState ( pSprite , pXSprite , & zombieABurnSearch ) ;
else
aiNewState ( pSprite , pXSprite , & zombieABurnChase ) ;
break ;
2019-10-11 21:59:39 +00:00
case kDudeBurningZombieButcher :
2019-09-19 22:42:45 +00:00
if ( pXSprite - > target = = - 1 )
aiNewState ( pSprite , pXSprite , & zombieFBurnSearch ) ;
else
aiNewState ( pSprite , pXSprite , & zombieFBurnChase ) ;
break ;
2019-10-11 21:59:39 +00:00
case kDudeGargoyleFlesh : {
2019-09-19 22:42:45 +00:00
DUDEEXTRA_at6_u1 * pDudeExtraE = & gDudeExtra [ pSprite - > extra ] . at6 . u1 ;
2020-11-21 22:40:33 +00:00
pDudeExtraE - > xval2 = 0 ;
pDudeExtraE - > xval3 = 1 ;
pDudeExtraE - > xval1 = 0 ;
2019-09-19 22:42:45 +00:00
if ( pXSprite - > target = = - 1 )
aiNewState ( pSprite , pXSprite , & gargoyleFSearch ) ;
else
{
if ( Chance ( 0x4000 ) )
aiPlay3DSound ( pSprite , 1401 , AI_SFX_PRIORITY_1 , - 1 ) ;
else
aiPlay3DSound ( pSprite , 1400 , AI_SFX_PRIORITY_1 , - 1 ) ;
aiNewState ( pSprite , pXSprite , & gargoyleFChase ) ;
}
break ;
}
2019-10-11 21:59:39 +00:00
case kDudeGargoyleStone :
2019-09-19 22:42:45 +00:00
{
DUDEEXTRA_at6_u1 * pDudeExtraE = & gDudeExtra [ pSprite - > extra ] . at6 . u1 ;
2020-11-21 22:40:33 +00:00
pDudeExtraE - > xval2 = 0 ;
pDudeExtraE - > xval3 = 1 ;
pDudeExtraE - > xval1 = 0 ;
2019-09-19 22:42:45 +00:00
if ( pXSprite - > target = = - 1 )
aiNewState ( pSprite , pXSprite , & gargoyleFSearch ) ;
else
{
if ( Chance ( 0x4000 ) )
aiPlay3DSound ( pSprite , 1451 , AI_SFX_PRIORITY_1 , - 1 ) ;
else
aiPlay3DSound ( pSprite , 1450 , AI_SFX_PRIORITY_1 , - 1 ) ;
aiNewState ( pSprite , pXSprite , & gargoyleFChase ) ;
}
break ;
}
2019-10-11 21:59:39 +00:00
case kDudeGargoyleStatueFlesh :
case kDudeGargoyleStatueStone :
2020-01-26 11:19:01 +00:00
# ifdef NOONE_EXTENSIONS
// play gargoyle statue breaking animation if data1 = 1.
2019-10-11 21:59:39 +00:00
if ( gModernMap & & pXSprite - > data1 = = 1 ) {
if ( pSprite - > type = = kDudeGargoyleStatueFlesh ) aiNewState ( pSprite , pXSprite , & statueFBreakSEQ ) ;
else aiNewState ( pSprite , pXSprite , & statueSBreakSEQ ) ;
2019-09-19 22:42:45 +00:00
} else {
if ( Chance ( 0x4000 ) ) aiPlay3DSound ( pSprite , 1401 , AI_SFX_PRIORITY_1 , - 1 ) ;
else aiPlay3DSound ( pSprite , 1400 , AI_SFX_PRIORITY_1 , - 1 ) ;
2019-10-11 21:59:39 +00:00
if ( pSprite - > type = = kDudeGargoyleStatueFlesh ) aiNewState ( pSprite , pXSprite , & gargoyleFMorph ) ;
2019-09-19 22:42:45 +00:00
else aiNewState ( pSprite , pXSprite , & gargoyleSMorph ) ;
}
2020-01-26 11:19:01 +00:00
# else
if ( Chance ( 0x4000 ) ) aiPlay3DSound ( pSprite , 1401 , AI_SFX_PRIORITY_1 , - 1 ) ;
else aiPlay3DSound ( pSprite , 1400 , AI_SFX_PRIORITY_1 , - 1 ) ;
if ( pSprite - > type = = kDudeGargoyleStatueFlesh ) aiNewState ( pSprite , pXSprite , & gargoyleFMorph ) ;
else aiNewState ( pSprite , pXSprite , & gargoyleSMorph ) ;
# endif
2019-09-19 22:42:45 +00:00
break ;
2019-10-11 21:59:39 +00:00
case kDudeCerberusTwoHead :
2019-09-19 22:42:45 +00:00
if ( pXSprite - > target = = - 1 )
aiNewState ( pSprite , pXSprite , & cerberusSearch ) ;
else
{
aiPlay3DSound ( pSprite , 2300 , AI_SFX_PRIORITY_1 , - 1 ) ;
aiNewState ( pSprite , pXSprite , & cerberusChase ) ;
}
break ;
2019-10-11 21:59:39 +00:00
case kDudeCerberusOneHead :
2019-09-19 22:42:45 +00:00
if ( pXSprite - > target = = - 1 )
aiNewState ( pSprite , pXSprite , & cerberus2Search ) ;
else
{
aiPlay3DSound ( pSprite , 2300 , AI_SFX_PRIORITY_1 , - 1 ) ;
aiNewState ( pSprite , pXSprite , & cerberus2Chase ) ;
}
break ;
2019-10-11 21:59:39 +00:00
case kDudeHellHound :
2019-09-19 22:42:45 +00:00
if ( pXSprite - > target = = - 1 )
aiNewState ( pSprite , pXSprite , & houndSearch ) ;
else
{
aiPlay3DSound ( pSprite , 1300 , AI_SFX_PRIORITY_1 , - 1 ) ;
aiNewState ( pSprite , pXSprite , & houndChase ) ;
}
break ;
2019-10-11 21:59:39 +00:00
case kDudeHand :
2019-09-19 22:42:45 +00:00
if ( pXSprite - > target = = - 1 )
aiNewState ( pSprite , pXSprite , & handSearch ) ;
else
{
aiPlay3DSound ( pSprite , 1900 , AI_SFX_PRIORITY_1 , - 1 ) ;
aiNewState ( pSprite , pXSprite , & handChase ) ;
}
break ;
2019-10-11 21:59:39 +00:00
case kDudeRat :
2019-09-19 22:42:45 +00:00
if ( pXSprite - > target = = - 1 )
aiNewState ( pSprite , pXSprite , & ratSearch ) ;
else
{
aiPlay3DSound ( pSprite , 2100 , AI_SFX_PRIORITY_1 , - 1 ) ;
aiNewState ( pSprite , pXSprite , & ratChase ) ;
}
break ;
2019-10-11 21:59:39 +00:00
case kDudeInnocent :
2019-09-19 22:42:45 +00:00
if ( pXSprite - > target = = - 1 )
aiNewState ( pSprite , pXSprite , & innocentSearch ) ;
else
{
if ( pXSprite - > health > 0 )
aiPlay3DSound ( pSprite , 7000 + Random ( 6 ) , AI_SFX_PRIORITY_1 , - 1 ) ;
aiNewState ( pSprite , pXSprite , & innocentChase ) ;
}
break ;
2019-10-11 21:59:39 +00:00
case kDudeTchernobog :
2019-09-19 22:42:45 +00:00
if ( pXSprite - > target = = - 1 )
aiNewState ( pSprite , pXSprite , & tchernobogSearch ) ;
else
{
aiPlay3DSound ( pSprite , 2350 + Random ( 7 ) , AI_SFX_PRIORITY_1 , - 1 ) ;
aiNewState ( pSprite , pXSprite , & tchernobogChase ) ;
}
break ;
2019-10-11 21:59:39 +00:00
case kDudeSpiderBrown :
case kDudeSpiderRed :
case kDudeSpiderBlack :
2019-09-30 07:18:01 +00:00
pSprite - > flags | = 2 ;
2019-09-19 22:42:45 +00:00
pSprite - > cstat & = ~ 8 ;
if ( pXSprite - > target = = - 1 )
aiNewState ( pSprite , pXSprite , & spidSearch ) ;
else
{
aiPlay3DSound ( pSprite , 1800 , AI_SFX_PRIORITY_1 , - 1 ) ;
aiNewState ( pSprite , pXSprite , & spidChase ) ;
}
break ;
2019-10-11 21:59:39 +00:00
case kDudeSpiderMother : {
2019-09-19 22:42:45 +00:00
DUDEEXTRA_at6_u1 * pDudeExtraE = & gDudeExtra [ pSprite - > extra ] . at6 . u1 ;
2020-11-21 22:40:33 +00:00
pDudeExtraE - > xval3 = 1 ;
pDudeExtraE - > xval1 = 0 ;
2019-09-30 07:18:01 +00:00
pSprite - > flags | = 2 ;
2019-09-19 22:42:45 +00:00
pSprite - > cstat & = ~ 8 ;
2019-10-11 21:59:39 +00:00
if ( pXSprite - > target = = - 1 )
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & spidSearch ) ;
else
{
aiPlay3DSound ( pSprite , 1853 + Random ( 1 ) , AI_SFX_PRIORITY_1 , - 1 ) ;
aiNewState ( pSprite , pXSprite , & spidChase ) ;
}
break ;
}
2019-10-11 21:59:39 +00:00
case kDudeTinyCaleb :
2019-09-19 22:42:45 +00:00
{
DUDEEXTRA_at6_u2 * pDudeExtraE = & gDudeExtra [ pSprite - > extra ] . at6 . u2 ;
2020-11-21 22:40:33 +00:00
pDudeExtraE - > xval2 = 1 ;
pDudeExtraE - > xval1 = 0 ;
2019-09-19 22:42:45 +00:00
if ( pXSprite - > target = = - 1 )
{
switch ( pXSprite - > medium )
{
2019-10-19 19:11:39 +00:00
case kMediumNormal :
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & tinycalebSearch ) ;
break ;
2019-10-19 19:11:39 +00:00
case kMediumWater :
case kMediumGoo :
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & tinycalebSwimSearch ) ;
break ;
}
}
else
{
switch ( pXSprite - > medium )
{
2019-10-19 19:11:39 +00:00
case kMediumNormal :
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & tinycalebChase ) ;
break ;
2019-10-19 19:11:39 +00:00
case kMediumWater :
case kMediumGoo :
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & tinycalebSwimChase ) ;
break ;
}
}
break ;
}
2019-10-11 21:59:39 +00:00
case kDudeBeast :
2019-09-19 22:42:45 +00:00
{
DUDEEXTRA_at6_u2 * pDudeExtraE = & gDudeExtra [ pSprite - > extra ] . at6 . u2 ;
2020-11-21 22:40:33 +00:00
pDudeExtraE - > xval2 = 1 ;
pDudeExtraE - > xval1 = 0 ;
2019-09-19 22:42:45 +00:00
if ( pXSprite - > target = = - 1 )
{
switch ( pXSprite - > medium )
{
2019-10-19 19:11:39 +00:00
case kMediumNormal :
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & beastSearch ) ;
break ;
2019-10-19 19:11:39 +00:00
case kMediumWater :
case kMediumGoo :
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & beastSwimSearch ) ;
break ;
}
}
else
{
aiPlay3DSound ( pSprite , 9009 + Random ( 2 ) , AI_SFX_PRIORITY_1 , - 1 ) ;
switch ( pXSprite - > medium )
{
2019-10-19 19:11:39 +00:00
case kMediumNormal :
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & beastChase ) ;
break ;
2019-10-19 19:11:39 +00:00
case kMediumWater :
case kMediumGoo :
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & beastSwimChase ) ;
break ;
}
}
break ;
}
2019-10-11 21:59:39 +00:00
case kDudePodGreen :
case kDudePodFire :
2019-09-19 22:42:45 +00:00
if ( pXSprite - > target = = - 1 )
aiNewState ( pSprite , pXSprite , & podSearch ) ;
else
{
2019-10-11 21:59:39 +00:00
if ( pSprite - > type = = kDudePodFire )
2019-09-19 22:42:45 +00:00
aiPlay3DSound ( pSprite , 2453 , AI_SFX_PRIORITY_1 , - 1 ) ;
else
aiPlay3DSound ( pSprite , 2473 , AI_SFX_PRIORITY_1 , - 1 ) ;
aiNewState ( pSprite , pXSprite , & podChase ) ;
}
break ;
2019-10-11 21:59:39 +00:00
case kDudeTentacleGreen :
case kDudeTentacleFire :
2019-09-19 22:42:45 +00:00
if ( pXSprite - > target = = - 1 )
aiNewState ( pSprite , pXSprite , & tentacleSearch ) ;
else
{
aiPlay3DSound ( pSprite , 2503 , AI_SFX_PRIORITY_1 , - 1 ) ;
aiNewState ( pSprite , pXSprite , & tentacleChase ) ;
}
break ;
}
}
void aiSetTarget ( XSPRITE * pXSprite , int x , int y , int z )
{
pXSprite - > target = - 1 ;
pXSprite - > targetX = x ;
pXSprite - > targetY = y ;
pXSprite - > targetZ = z ;
}
void aiSetTarget ( XSPRITE * pXSprite , int nTarget )
{
2020-10-11 10:38:17 +00:00
assert ( nTarget > = 0 & & nTarget < kMaxSprites ) ;
2019-09-19 22:42:45 +00:00
spritetype * pTarget = & sprite [ nTarget ] ;
if ( pTarget - > type > = kDudeBase & & pTarget - > type < kDudeMax )
{
if ( actSpriteOwnerToSpriteId ( & sprite [ pXSprite - > reference ] ) ! = nTarget )
{
pXSprite - > target = nTarget ;
2020-02-05 21:17:05 +00:00
DUDEINFO * pDudeInfo = getDudeInfo ( pTarget - > type ) ;
2019-09-19 22:42:45 +00:00
pXSprite - > targetX = pTarget - > x ;
pXSprite - > targetY = pTarget - > y ;
pXSprite - > targetZ = pTarget - > z - ( ( pDudeInfo - > eyeHeight * pTarget - > yrepeat ) < < 2 ) ;
}
}
}
int aiDamageSprite ( spritetype * pSprite , XSPRITE * pXSprite , int nSource , DAMAGE_TYPE nDmgType , int nDamage )
{
2020-10-11 10:38:17 +00:00
assert ( nSource < kMaxSprites ) ;
2019-09-19 22:42:45 +00:00
if ( ! pXSprite - > health )
return 0 ;
pXSprite - > health = ClipLow ( pXSprite - > health - nDamage , 0 ) ;
cumulDamage [ pSprite - > extra ] + = nDamage ;
2020-02-05 21:17:05 +00:00
DUDEINFO * pDudeInfo = getDudeInfo ( pSprite - > type ) ;
2019-09-19 22:42:45 +00:00
int nSprite = pXSprite - > reference ;
if ( nSource > = 0 )
{
spritetype * pSource = & sprite [ nSource ] ;
if ( pSprite = = pSource )
return 0 ;
if ( pXSprite - > target = = - 1 | | ( nSource ! = pXSprite - > target & & Chance ( pSprite - > type = = pSource - > type ? nDamage * pDudeInfo - > changeTargetKin : nDamage * pDudeInfo - > changeTarget ) ) )
{
aiSetTarget ( pXSprite , nSource ) ;
aiActivateDude ( pSprite , pXSprite ) ;
}
if ( nDmgType = = DAMAGE_TYPE_6 )
{
DUDEEXTRA * pDudeExtra = & gDudeExtra [ pSprite - > extra ] ;
2020-11-21 22:40:33 +00:00
pDudeExtra - > recoil = 1 ;
2019-09-19 22:42:45 +00:00
}
switch ( pSprite - > type )
{
2019-10-11 21:59:39 +00:00
case kDudeCultistTommy :
case kDudeCultistShotgun :
case kDudeCultistTesla :
case kDudeCultistTNT :
2019-09-19 22:42:45 +00:00
if ( nDmgType ! = DAMAGE_TYPE_1 )
{
2020-11-21 17:33:31 +00:00
if ( ! dudeIsPlayingSeq ( pSprite , 14 ) & & ! pXSprite - > medium )
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & cultistDodge ) ;
2020-11-21 17:33:31 +00:00
else if ( dudeIsPlayingSeq ( pSprite , 14 ) & & ! pXSprite - > medium )
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & cultistProneDodge ) ;
2020-11-21 17:33:31 +00:00
else if ( dudeIsPlayingSeq ( pSprite , 13 ) & & ( pXSprite - > medium = = kMediumWater | | pXSprite - > medium = = kMediumGoo ) )
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & cultistSwimDodge ) ;
}
else if ( nDmgType = = DAMAGE_TYPE_1 & & pXSprite - > health < = ( unsigned int ) pDudeInfo - > fleeHealth /* && (pXSprite->at17_6 != 1 || pXSprite->at17_6 != 2)*/ )
{
2019-10-11 21:59:39 +00:00
pSprite - > type = kDudeBurningCultist ;
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & cultistBurnGoto ) ;
aiPlay3DSound ( pSprite , 361 , AI_SFX_PRIORITY_0 , - 1 ) ;
aiPlay3DSound ( pSprite , 1031 + Random ( 2 ) , AI_SFX_PRIORITY_2 , - 1 ) ;
2020-11-21 22:40:33 +00:00
gDudeExtra [ pSprite - > extra ] . time = gFrameClock + 360 ;
2019-09-19 22:42:45 +00:00
actHealDude ( pXSprite , dudeInfo [ 40 ] . startHealth , dudeInfo [ 40 ] . startHealth ) ;
2019-10-11 21:59:39 +00:00
evKill ( nSprite , 3 , kCallbackFXFlameLick ) ;
2019-09-19 22:42:45 +00:00
}
break ;
2019-12-21 02:15:17 +00:00
case kDudeInnocent :
2019-09-19 22:42:45 +00:00
if ( nDmgType = = DAMAGE_TYPE_1 & & pXSprite - > health < = ( unsigned int ) pDudeInfo - > fleeHealth /* && (pXSprite->at17_6 != 1 || pXSprite->at17_6 != 2)*/ )
{
2019-10-11 21:59:39 +00:00
pSprite - > type = kDudeBurningInnocent ;
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & cultistBurnGoto ) ;
aiPlay3DSound ( pSprite , 361 , AI_SFX_PRIORITY_0 , - 1 ) ;
2020-11-21 22:40:33 +00:00
gDudeExtra [ pSprite - > extra ] . time = gFrameClock + 360 ;
2019-09-19 22:42:45 +00:00
actHealDude ( pXSprite , dudeInfo [ 39 ] . startHealth , dudeInfo [ 39 ] . startHealth ) ;
2019-10-11 21:59:39 +00:00
evKill ( nSprite , 3 , kCallbackFXFlameLick ) ;
2019-09-19 22:42:45 +00:00
}
break ;
2019-10-11 21:59:39 +00:00
case kDudeBurningCultist :
2020-11-21 22:40:33 +00:00
if ( Chance ( 0x4000 ) & & gDudeExtra [ pSprite - > extra ] . time < gFrameClock )
2019-09-19 22:42:45 +00:00
{
aiPlay3DSound ( pSprite , 1031 + Random ( 2 ) , AI_SFX_PRIORITY_2 , - 1 ) ;
2020-11-21 22:40:33 +00:00
gDudeExtra [ pSprite - > extra ] . time = gFrameClock + 360 ;
2019-09-19 22:42:45 +00:00
}
2019-10-19 19:11:39 +00:00
if ( Chance ( 0x600 ) & & ( pXSprite - > medium = = kMediumWater | | pXSprite - > medium = = kMediumGoo ) )
2019-09-19 22:42:45 +00:00
{
2019-10-11 21:59:39 +00:00
pSprite - > type = kDudeCultistTommy ;
2019-09-19 22:42:45 +00:00
pXSprite - > burnTime = 0 ;
aiNewState ( pSprite , pXSprite , & cultistSwimGoto ) ;
}
2019-10-19 19:11:39 +00:00
else if ( pXSprite - > medium = = kMediumWater | | pXSprite - > medium = = kMediumGoo )
2019-09-19 22:42:45 +00:00
{
2019-10-11 21:59:39 +00:00
pSprite - > type = kDudeCultistShotgun ;
2019-09-19 22:42:45 +00:00
pXSprite - > burnTime = 0 ;
aiNewState ( pSprite , pXSprite , & cultistSwimGoto ) ;
}
break ;
2019-10-11 21:59:39 +00:00
case kDudeGargoyleFlesh :
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & gargoyleFChase ) ;
break ;
2019-10-11 21:59:39 +00:00
case kDudeZombieButcher :
if ( nDmgType = = DAMAGE_TYPE_1 & & pXSprite - > health < = ( unsigned int ) pDudeInfo - > fleeHealth ) {
2019-09-19 22:42:45 +00:00
aiPlay3DSound ( pSprite , 361 , AI_SFX_PRIORITY_0 , - 1 ) ;
aiPlay3DSound ( pSprite , 1202 , AI_SFX_PRIORITY_2 , - 1 ) ;
2019-10-11 21:59:39 +00:00
pSprite - > type = kDudeBurningZombieButcher ;
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & zombieFBurnGoto ) ;
actHealDude ( pXSprite , dudeInfo [ 42 ] . startHealth , dudeInfo [ 42 ] . startHealth ) ;
2019-10-11 21:59:39 +00:00
evKill ( nSprite , 3 , kCallbackFXFlameLick ) ;
2019-09-19 22:42:45 +00:00
}
break ;
2019-12-21 02:15:17 +00:00
case kDudeTinyCaleb :
2019-09-19 22:42:45 +00:00
if ( nDmgType = = DAMAGE_TYPE_1 & & pXSprite - > health < = ( unsigned int ) pDudeInfo - > fleeHealth /* && (pXSprite->at17_6 != 1 || pXSprite->at17_6 != 2)*/ )
{
2019-10-11 21:59:39 +00:00
pSprite - > type = kDudeBurningInnocent ;
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & cultistBurnGoto ) ;
aiPlay3DSound ( pSprite , 361 , AI_SFX_PRIORITY_0 , - 1 ) ;
2020-11-21 22:40:33 +00:00
gDudeExtra [ pSprite - > extra ] . time = gFrameClock + 360 ;
2019-09-19 22:42:45 +00:00
actHealDude ( pXSprite , dudeInfo [ 39 ] . startHealth , dudeInfo [ 39 ] . startHealth ) ;
2019-10-11 21:59:39 +00:00
evKill ( nSprite , 3 , kCallbackFXFlameLick ) ;
2019-09-19 22:42:45 +00:00
}
break ;
2020-01-26 11:19:01 +00:00
# ifdef NOONE_EXTENSIONS
2019-10-11 21:59:39 +00:00
case kDudeModernCustomBurning :
2020-11-21 22:40:33 +00:00
if ( Chance ( 0x2000 ) & & gDudeExtra [ pSprite - > extra ] . time < gFrameClock ) {
2019-11-24 20:53:51 +00:00
playGenDudeSound ( pSprite , kGenDudeSndBurning ) ;
2020-11-21 22:40:33 +00:00
gDudeExtra [ pSprite - > extra ] . time = gFrameClock + 360 ;
2019-09-19 22:42:45 +00:00
}
if ( pXSprite - > burnTime = = 0 ) pXSprite - > burnTime = 2400 ;
if ( spriteIsUnderwater ( pSprite , false ) ) {
2019-10-11 21:59:39 +00:00
pSprite - > type = kDudeModernCustom ;
2019-09-19 22:42:45 +00:00
pXSprite - > burnTime = 0 ;
pXSprite - > health = 1 ; // so it can be killed with flame weapons while underwater and if already was burning dude before.
2019-11-24 20:53:51 +00:00
aiGenDudeNewState ( pSprite , & genDudeGotoW ) ;
2019-09-19 22:42:45 +00:00
}
break ;
2019-11-24 20:53:51 +00:00
case kDudeModernCustom : {
GENDUDEEXTRA * pExtra = genDudeExtra ( pSprite ) ;
2019-09-19 22:42:45 +00:00
if ( nDmgType = = DAMAGE_TYPE_1 ) {
2019-11-24 20:53:51 +00:00
if ( pXSprite - > health > pDudeInfo - > fleeHealth ) break ;
else if ( pXSprite - > txID < = 0 | | getNextIncarnation ( pXSprite ) = = NULL ) {
removeDudeStuff ( pSprite ) ;
2019-12-05 20:42:35 +00:00
if ( pExtra - > weaponType = = kGenDudeWeaponKamikaze )
2019-11-24 20:53:51 +00:00
doExplosion ( pSprite , pXSprite - > data1 - kTrapExploder ) ;
2019-09-19 22:42:45 +00:00
2019-11-24 20:53:51 +00:00
if ( spriteIsUnderwater ( pSprite , false ) ) {
pXSprite - > health = 0 ;
break ;
}
2019-09-19 22:42:45 +00:00
2019-11-24 20:53:51 +00:00
if ( pXSprite - > burnTime < = 0 )
pXSprite - > burnTime = 1200 ;
2019-09-19 22:42:45 +00:00
2019-11-24 20:53:51 +00:00
if ( pExtra - > canBurn & & pExtra - > availDeaths [ DAMAGE_TYPE_1 ] > 0 ) {
2019-09-19 22:42:45 +00:00
2019-11-24 20:53:51 +00:00
aiPlay3DSound ( pSprite , 361 , AI_SFX_PRIORITY_0 , - 1 ) ;
playGenDudeSound ( pSprite , kGenDudeSndBurning ) ;
pSprite - > type = kDudeModernCustomBurning ;
2019-09-19 22:42:45 +00:00
2019-11-24 20:53:51 +00:00
if ( pXSprite - > data2 = = kGenDudeDefaultSeq ) // don't inherit palette for burning if using default animation
pSprite - > pal = 0 ;
2019-09-19 22:42:45 +00:00
2019-11-24 20:53:51 +00:00
aiGenDudeNewState ( pSprite , & genDudeBurnGoto ) ;
actHealDude ( pXSprite , dudeInfo [ 55 ] . startHealth , dudeInfo [ 55 ] . startHealth ) ;
2020-11-21 22:40:33 +00:00
gDudeExtra [ pSprite - > extra ] . time = gFrameClock + 360 ;
2019-11-24 20:53:51 +00:00
evKill ( nSprite , 3 , kCallbackFXFlameLick ) ;
2019-09-19 22:42:45 +00:00
}
2019-11-24 20:53:51 +00:00
} else {
actKillDude ( nSource , pSprite , DAMAGE_TYPE_0 , 65535 ) ;
2019-09-19 22:42:45 +00:00
}
2019-11-24 20:53:51 +00:00
} else if ( canWalk ( pSprite ) & & ! inDodge ( pXSprite - > aiState ) & & ! inRecoil ( pXSprite - > aiState ) ) {
2020-01-01 20:53:29 +00:00
if ( ! dudeIsMelee ( pXSprite ) ) {
if ( inIdle ( pXSprite - > aiState ) | | Chance ( getDodgeChance ( pSprite ) ) ) {
if ( ! spriteIsUnderwater ( pSprite , false ) ) {
2020-11-21 17:33:31 +00:00
if ( ! canDuck ( pSprite ) | | ! dudeIsPlayingSeq ( pSprite , 14 ) ) aiGenDudeNewState ( pSprite , & genDudeDodgeShortL ) ;
2020-01-01 20:53:29 +00:00
else aiGenDudeNewState ( pSprite , & genDudeDodgeShortD ) ;
2019-09-21 11:02:17 +00:00
2020-01-01 20:53:29 +00:00
if ( Chance ( 0x0200 ) )
playGenDudeSound ( pSprite , kGenDudeSndGotHit ) ;
2019-11-24 20:53:51 +00:00
2020-11-21 17:33:31 +00:00
} else if ( dudeIsPlayingSeq ( pSprite , 13 ) ) {
2020-01-01 20:53:29 +00:00
aiGenDudeNewState ( pSprite , & genDudeDodgeShortW ) ;
}
2019-09-19 22:42:45 +00:00
}
2020-01-01 20:53:29 +00:00
} else if ( Chance ( 0x0200 ) ) {
playGenDudeSound ( pSprite , kGenDudeSndGotHit ) ;
2019-09-19 22:42:45 +00:00
}
}
break ;
}
2020-01-26 11:19:01 +00:00
# endif
2019-10-11 21:59:39 +00:00
case kDudeCultistBeast :
2019-09-19 22:42:45 +00:00
if ( pXSprite - > health < = ( unsigned int ) pDudeInfo - > fleeHealth )
{
2019-10-11 21:59:39 +00:00
pSprite - > type = kDudeBeast ;
2019-09-19 22:42:45 +00:00
aiPlay3DSound ( pSprite , 9008 , AI_SFX_PRIORITY_1 , - 1 ) ;
aiNewState ( pSprite , pXSprite , & beastMorphFromCultist ) ;
actHealDude ( pXSprite , dudeInfo [ 51 ] . startHealth , dudeInfo [ 51 ] . startHealth ) ;
}
break ;
2019-10-11 21:59:39 +00:00
case kDudeZombieAxeNormal :
case kDudeZombieAxeBuried :
2019-09-19 22:42:45 +00:00
if ( nDmgType = = DAMAGE_TYPE_1 & & pXSprite - > health < = ( unsigned int ) pDudeInfo - > fleeHealth )
{
aiPlay3DSound ( pSprite , 361 , AI_SFX_PRIORITY_0 , - 1 ) ;
aiPlay3DSound ( pSprite , 1106 , AI_SFX_PRIORITY_2 , - 1 ) ;
2019-10-11 21:59:39 +00:00
pSprite - > type = kDudeBurningZombieAxe ;
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & zombieABurnGoto ) ;
actHealDude ( pXSprite , dudeInfo [ 41 ] . startHealth , dudeInfo [ 41 ] . startHealth ) ;
2019-10-11 21:59:39 +00:00
evKill ( nSprite , 3 , kCallbackFXFlameLick ) ;
2019-09-19 22:42:45 +00:00
}
break ;
}
}
return nDamage ;
}
void RecoilDude ( spritetype * pSprite , XSPRITE * pXSprite )
{
char v4 = Chance ( 0x8000 ) ;
DUDEEXTRA * pDudeExtra = & gDudeExtra [ pSprite - > extra ] ;
2019-11-24 20:53:51 +00:00
if ( pSprite - > statnum = = kStatDude & & ( pSprite - > type > = kDudeBase & & pSprite - > type < kDudeMax ) ) {
2020-02-05 21:17:05 +00:00
DUDEINFO * pDudeInfo = getDudeInfo ( pSprite - > type ) ;
2019-11-24 20:53:51 +00:00
switch ( pSprite - > type ) {
2020-01-26 11:19:01 +00:00
# ifdef NOONE_EXTENSIONS
2019-11-24 20:53:51 +00:00
case kDudeModernCustom : {
GENDUDEEXTRA * pExtra = genDudeExtra ( pSprite ) ; int rChance = getRecoilChance ( pSprite ) ;
2020-11-21 22:40:33 +00:00
if ( pExtra - > canElectrocute & & pDudeExtra - > recoil & & ! spriteIsUnderwater ( pSprite , false ) ) {
2019-09-19 22:42:45 +00:00
2019-11-24 20:53:51 +00:00
if ( Chance ( rChance < < 3 ) | | ( dudeIsMelee ( pXSprite ) & & Chance ( rChance < < 4 ) ) ) aiGenDudeNewState ( pSprite , & genDudeRecoilTesla ) ;
else if ( pExtra - > canRecoil & & Chance ( rChance ) ) aiGenDudeNewState ( pSprite , & genDudeRecoilL ) ;
else if ( canWalk ( pSprite ) ) {
if ( Chance ( rChance > > 2 ) ) aiGenDudeNewState ( pSprite , & genDudeDodgeL ) ;
else if ( Chance ( rChance > > 1 ) ) aiGenDudeNewState ( pSprite , & genDudeDodgeShortL ) ;
2019-09-21 11:02:17 +00:00
}
2019-09-19 22:42:45 +00:00
2019-11-24 20:53:51 +00:00
} else if ( pExtra - > canRecoil & & Chance ( rChance ) ) {
if ( inDuck ( pXSprite - > aiState ) & & Chance ( rChance > > 2 ) ) aiGenDudeNewState ( pSprite , & genDudeRecoilD ) ;
else if ( spriteIsUnderwater ( pSprite , false ) ) aiGenDudeNewState ( pSprite , & genDudeRecoilW ) ;
else aiGenDudeNewState ( pSprite , & genDudeRecoilL ) ;
2019-09-19 22:42:45 +00:00
}
2019-11-24 20:53:51 +00:00
short rState = inRecoil ( pXSprite - > aiState ) ;
if ( rState > 0 ) {
if ( ! canWalk ( pSprite ) ) {
if ( rState = = 1 ) pXSprite - > aiState - > nextState = & genDudeChaseNoWalkL ;
else if ( rState = = 2 ) pXSprite - > aiState - > nextState = & genDudeChaseNoWalkD ;
else pXSprite - > aiState - > nextState = & genDudeChaseNoWalkW ;
2019-09-19 22:42:45 +00:00
2019-11-24 20:53:51 +00:00
} else if ( ! dudeIsMelee ( pXSprite ) | | Chance ( rChance > > 2 ) ) {
if ( rState = = 1 ) pXSprite - > aiState - > nextState = ( Chance ( rChance ) ? & genDudeDodgeL : & genDudeDodgeShortL ) ;
else if ( rState = = 2 ) pXSprite - > aiState - > nextState = ( Chance ( rChance ) ? & genDudeDodgeD : & genDudeDodgeShortD ) ;
2019-12-05 20:42:35 +00:00
else if ( rState = = 3 ) pXSprite - > aiState - > nextState = ( Chance ( rChance ) ? & genDudeDodgeW : & genDudeDodgeShortW ) ;
2019-09-19 22:42:45 +00:00
2019-11-24 20:53:51 +00:00
}
else if ( rState = = 1 ) pXSprite - > aiState - > nextState = & genDudeChaseL ;
else if ( rState = = 2 ) pXSprite - > aiState - > nextState = & genDudeChaseD ;
else pXSprite - > aiState - > nextState = & genDudeChaseW ;
2019-09-19 22:42:45 +00:00
2019-11-24 20:53:51 +00:00
playGenDudeSound ( pSprite , kGenDudeSndGotHit ) ;
2019-09-19 22:42:45 +00:00
}
2020-11-21 22:40:33 +00:00
pDudeExtra - > recoil = 0 ;
2019-09-19 22:42:45 +00:00
break ;
}
2020-01-26 11:19:01 +00:00
# endif
2019-10-11 21:59:39 +00:00
case kDudeCultistTommy :
case kDudeCultistShotgun :
case kDudeCultistTesla :
case kDudeCultistTNT :
case kDudeCultistBeast :
if ( pSprite - > type = = kDudeCultistTommy ) aiPlay3DSound ( pSprite , 4013 + Random ( 2 ) , AI_SFX_PRIORITY_2 , - 1 ) ;
else aiPlay3DSound ( pSprite , 1013 + Random ( 2 ) , AI_SFX_PRIORITY_2 , - 1 ) ;
2019-10-19 19:11:39 +00:00
if ( ! v4 & & pXSprite - > medium = = kMediumNormal ) {
2020-11-21 22:40:33 +00:00
if ( pDudeExtra - > recoil ) aiNewState ( pSprite , pXSprite , & cultistTeslaRecoil ) ;
2019-10-11 21:59:39 +00:00
else aiNewState ( pSprite , pXSprite , & cultistRecoil ) ;
2019-10-19 19:11:39 +00:00
} else if ( v4 & & pXSprite - > medium = = kMediumNormal ) {
2020-11-21 22:40:33 +00:00
if ( pDudeExtra - > recoil ) aiNewState ( pSprite , pXSprite , & cultistTeslaRecoil ) ;
2019-10-11 21:59:39 +00:00
else if ( gGameOptions . nDifficulty > 0 ) aiNewState ( pSprite , pXSprite , & cultistProneRecoil ) ;
else aiNewState ( pSprite , pXSprite , & cultistRecoil ) ;
2019-09-19 22:42:45 +00:00
}
2019-10-19 19:11:39 +00:00
else if ( pXSprite - > medium = = kMediumWater | | pXSprite - > medium = = kMediumGoo )
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & cultistSwimRecoil ) ;
else
{
2020-11-21 22:40:33 +00:00
if ( pDudeExtra - > recoil )
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & cultistTeslaRecoil ) ;
else
aiNewState ( pSprite , pXSprite , & cultistRecoil ) ;
}
break ;
2019-10-11 21:59:39 +00:00
case kDudeBurningCultist :
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & cultistBurnGoto ) ;
break ;
2020-01-26 11:19:01 +00:00
# ifdef NOONE_EXTENSIONS
2019-10-11 21:59:39 +00:00
case kDudeModernCustomBurning :
2019-11-24 20:53:51 +00:00
aiGenDudeNewState ( pSprite , & genDudeBurnGoto ) ;
2019-09-19 22:42:45 +00:00
break ;
2020-01-26 11:19:01 +00:00
# endif
2019-10-11 21:59:39 +00:00
case kDudeZombieButcher :
2019-09-19 22:42:45 +00:00
aiPlay3DSound ( pSprite , 1202 , AI_SFX_PRIORITY_2 , - 1 ) ;
2020-11-21 22:40:33 +00:00
if ( pDudeExtra - > recoil )
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & zombieFTeslaRecoil ) ;
else
aiNewState ( pSprite , pXSprite , & zombieFRecoil ) ;
break ;
2019-10-11 21:59:39 +00:00
case kDudeZombieAxeNormal :
case kDudeZombieAxeBuried :
2019-09-19 22:42:45 +00:00
aiPlay3DSound ( pSprite , 1106 , AI_SFX_PRIORITY_2 , - 1 ) ;
2020-11-21 22:40:33 +00:00
if ( pDudeExtra - > recoil & & pXSprite - > data3 > pDudeInfo - > startHealth / 3 )
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & zombieATeslaRecoil ) ;
2019-09-21 11:02:17 +00:00
else if ( pXSprite - > data3 > pDudeInfo - > startHealth / 3 )
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & zombieARecoil2 ) ;
else
aiNewState ( pSprite , pXSprite , & zombieARecoil ) ;
break ;
2019-10-11 21:59:39 +00:00
case kDudeBurningZombieAxe :
2019-09-19 22:42:45 +00:00
aiPlay3DSound ( pSprite , 1106 , AI_SFX_PRIORITY_2 , - 1 ) ;
aiNewState ( pSprite , pXSprite , & zombieABurnGoto ) ;
break ;
2019-10-11 21:59:39 +00:00
case kDudeBurningZombieButcher :
2019-09-19 22:42:45 +00:00
aiPlay3DSound ( pSprite , 1202 , AI_SFX_PRIORITY_2 , - 1 ) ;
aiNewState ( pSprite , pXSprite , & zombieFBurnGoto ) ;
break ;
2019-10-11 21:59:39 +00:00
case kDudeGargoyleFlesh :
case kDudeGargoyleStone :
2019-09-19 22:42:45 +00:00
aiPlay3DSound ( pSprite , 1402 , AI_SFX_PRIORITY_2 , - 1 ) ;
aiNewState ( pSprite , pXSprite , & gargoyleFRecoil ) ;
break ;
2019-10-11 21:59:39 +00:00
case kDudeCerberusTwoHead :
2019-09-19 22:42:45 +00:00
aiPlay3DSound ( pSprite , 2302 + Random ( 2 ) , AI_SFX_PRIORITY_2 , - 1 ) ;
2020-11-21 22:40:33 +00:00
if ( pDudeExtra - > recoil & & pXSprite - > data3 > pDudeInfo - > startHealth / 3 )
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & cerberusTeslaRecoil ) ;
else
aiNewState ( pSprite , pXSprite , & cerberusRecoil ) ;
break ;
2019-10-11 21:59:39 +00:00
case kDudeCerberusOneHead :
2019-09-19 22:42:45 +00:00
aiPlay3DSound ( pSprite , 2302 + Random ( 2 ) , AI_SFX_PRIORITY_2 , - 1 ) ;
aiNewState ( pSprite , pXSprite , & cerberus2Recoil ) ;
break ;
2019-10-11 21:59:39 +00:00
case kDudeHellHound :
2019-09-19 22:42:45 +00:00
aiPlay3DSound ( pSprite , 1302 , AI_SFX_PRIORITY_2 , - 1 ) ;
2020-11-21 22:40:33 +00:00
if ( pDudeExtra - > recoil )
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & houndTeslaRecoil ) ;
else
aiNewState ( pSprite , pXSprite , & houndRecoil ) ;
break ;
2019-10-11 21:59:39 +00:00
case kDudeTchernobog :
2019-09-19 22:42:45 +00:00
aiPlay3DSound ( pSprite , 2370 + Random ( 2 ) , AI_SFX_PRIORITY_2 , - 1 ) ;
aiNewState ( pSprite , pXSprite , & tchernobogRecoil ) ;
break ;
2019-10-11 21:59:39 +00:00
case kDudeHand :
2019-09-19 22:42:45 +00:00
aiPlay3DSound ( pSprite , 1902 , AI_SFX_PRIORITY_2 , - 1 ) ;
aiNewState ( pSprite , pXSprite , & handRecoil ) ;
break ;
2019-10-11 21:59:39 +00:00
case kDudeRat :
2019-09-19 22:42:45 +00:00
aiPlay3DSound ( pSprite , 2102 , AI_SFX_PRIORITY_2 , - 1 ) ;
aiNewState ( pSprite , pXSprite , & ratRecoil ) ;
break ;
2019-10-11 21:59:39 +00:00
case kDudeBat :
2019-09-19 22:42:45 +00:00
aiPlay3DSound ( pSprite , 2002 , AI_SFX_PRIORITY_2 , - 1 ) ;
aiNewState ( pSprite , pXSprite , & batRecoil ) ;
break ;
2019-10-11 21:59:39 +00:00
case kDudeBoneEel :
2019-09-19 22:42:45 +00:00
aiPlay3DSound ( pSprite , 1502 , AI_SFX_PRIORITY_2 , - 1 ) ;
aiNewState ( pSprite , pXSprite , & eelRecoil ) ;
break ;
2019-10-11 21:59:39 +00:00
case kDudeGillBeast : {
2019-09-19 22:42:45 +00:00
XSECTOR * pXSector = NULL ;
if ( sector [ pSprite - > sectnum ] . extra > 0 )
pXSector = & xsector [ sector [ pSprite - > sectnum ] . extra ] ;
aiPlay3DSound ( pSprite , 1702 , AI_SFX_PRIORITY_2 , - 1 ) ;
if ( pXSector & & pXSector - > Underwater )
aiNewState ( pSprite , pXSprite , & gillBeastSwimRecoil ) ;
else
aiNewState ( pSprite , pXSprite , & gillBeastRecoil ) ;
break ;
}
2019-10-11 21:59:39 +00:00
case kDudePhantasm :
2019-09-19 22:42:45 +00:00
aiPlay3DSound ( pSprite , 1602 , AI_SFX_PRIORITY_2 , - 1 ) ;
2020-11-21 22:40:33 +00:00
if ( pDudeExtra - > recoil )
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & ghostTeslaRecoil ) ;
else
aiNewState ( pSprite , pXSprite , & ghostRecoil ) ;
break ;
2019-10-11 21:59:39 +00:00
case kDudeSpiderBrown :
case kDudeSpiderRed :
case kDudeSpiderBlack :
2019-09-19 22:42:45 +00:00
aiPlay3DSound ( pSprite , 1802 + Random ( 1 ) , AI_SFX_PRIORITY_2 , - 1 ) ;
aiNewState ( pSprite , pXSprite , & spidDodge ) ;
break ;
2019-10-11 21:59:39 +00:00
case kDudeSpiderMother :
2019-09-19 22:42:45 +00:00
aiPlay3DSound ( pSprite , 1851 + Random ( 1 ) , AI_SFX_PRIORITY_2 , - 1 ) ;
aiNewState ( pSprite , pXSprite , & spidDodge ) ;
break ;
2019-10-11 21:59:39 +00:00
case kDudeInnocent :
2019-09-19 22:42:45 +00:00
aiPlay3DSound ( pSprite , 7007 + Random ( 2 ) , AI_SFX_PRIORITY_2 , - 1 ) ;
2020-11-21 22:40:33 +00:00
if ( pDudeExtra - > recoil )
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & innocentTeslaRecoil ) ;
else
aiNewState ( pSprite , pXSprite , & innocentRecoil ) ;
break ;
2019-10-11 21:59:39 +00:00
case kDudeTinyCaleb :
2019-10-19 19:11:39 +00:00
if ( pXSprite - > medium = = kMediumNormal )
2019-09-19 22:42:45 +00:00
{
2020-11-21 22:40:33 +00:00
if ( pDudeExtra - > recoil )
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & tinycalebTeslaRecoil ) ;
else
aiNewState ( pSprite , pXSprite , & tinycalebRecoil ) ;
}
2019-10-19 19:11:39 +00:00
else if ( pXSprite - > medium = = kMediumWater | | pXSprite - > medium = = kMediumGoo )
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & tinycalebSwimRecoil ) ;
else
{
2020-11-21 22:40:33 +00:00
if ( pDudeExtra - > recoil )
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & tinycalebTeslaRecoil ) ;
else
aiNewState ( pSprite , pXSprite , & tinycalebRecoil ) ;
}
break ;
2019-10-11 21:59:39 +00:00
case kDudeBeast :
2019-09-19 22:42:45 +00:00
aiPlay3DSound ( pSprite , 9004 + Random ( 2 ) , AI_SFX_PRIORITY_2 , - 1 ) ;
2019-10-19 19:11:39 +00:00
if ( pXSprite - > medium = = kMediumNormal )
2019-09-19 22:42:45 +00:00
{
2020-11-21 22:40:33 +00:00
if ( pDudeExtra - > recoil )
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & beastTeslaRecoil ) ;
else
aiNewState ( pSprite , pXSprite , & beastRecoil ) ;
}
2019-10-19 19:11:39 +00:00
else if ( pXSprite - > medium = = kMediumWater | | pXSprite - > medium = = kMediumGoo )
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & beastSwimRecoil ) ;
else
{
2020-11-21 22:40:33 +00:00
if ( pDudeExtra - > recoil )
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & beastTeslaRecoil ) ;
else
aiNewState ( pSprite , pXSprite , & beastRecoil ) ;
}
break ;
2019-10-11 21:59:39 +00:00
case kDudePodGreen :
case kDudePodFire :
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & podRecoil ) ;
break ;
2019-10-11 21:59:39 +00:00
case kDudeTentacleGreen :
case kDudeTentacleFire :
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & tentacleRecoil ) ;
break ;
default :
aiNewState ( pSprite , pXSprite , & genRecoil ) ;
break ;
}
2020-11-21 22:40:33 +00:00
pDudeExtra - > recoil = 0 ;
2019-09-19 22:42:45 +00:00
}
}
void aiThinkTarget ( spritetype * pSprite , XSPRITE * pXSprite )
{
2020-10-11 10:38:17 +00:00
assert ( pSprite - > type > = kDudeBase & & pSprite - > type < kDudeMax ) ;
2020-02-05 21:17:05 +00:00
DUDEINFO * pDudeInfo = getDudeInfo ( pSprite - > type ) ;
2019-09-19 22:42:45 +00:00
if ( Chance ( pDudeInfo - > alertChance ) )
{
for ( int p = connecthead ; p > = 0 ; p = connectpoint2 [ p ] )
{
PLAYER * pPlayer = & gPlayer [ p ] ;
2019-10-21 19:46:41 +00:00
if ( pSprite - > owner = = pPlayer - > nSprite | | pPlayer - > pXSprite - > health = = 0 | | powerupCheck ( pPlayer , kPwUpShadowCloak ) > 0 )
2019-09-19 22:42:45 +00:00
continue ;
int x = pPlayer - > pSprite - > x ;
int y = pPlayer - > pSprite - > y ;
int z = pPlayer - > pSprite - > z ;
int nSector = pPlayer - > pSprite - > sectnum ;
int dx = x - pSprite - > x ;
int dy = y - pSprite - > y ;
int nDist = approxDist ( dx , dy ) ;
if ( nDist > pDudeInfo - > seeDist & & nDist > pDudeInfo - > hearDist )
continue ;
if ( ! cansee ( x , y , z , nSector , pSprite - > x , pSprite - > y , pSprite - > z - ( ( pDudeInfo - > eyeHeight * pSprite - > yrepeat ) < < 2 ) , pSprite - > sectnum ) )
continue ;
int nDeltaAngle = ( ( getangle ( dx , dy ) + 1024 - pSprite - > ang ) & 2047 ) - 1024 ;
if ( nDist < pDudeInfo - > seeDist & & klabs ( nDeltaAngle ) < = pDudeInfo - > periphery )
{
2019-10-21 19:46:41 +00:00
aiSetTarget ( pXSprite , pPlayer - > nSprite ) ;
2019-09-19 22:42:45 +00:00
aiActivateDude ( pSprite , pXSprite ) ;
return ;
}
else if ( nDist < pDudeInfo - > hearDist )
{
aiSetTarget ( pXSprite , x , y , z ) ;
aiActivateDude ( pSprite , pXSprite ) ;
return ;
}
}
}
}
void sub_5F15C ( spritetype * pSprite , XSPRITE * pXSprite )
{
2020-10-11 10:38:17 +00:00
assert ( pSprite - > type > = kDudeBase & & pSprite - > type < kDudeMax ) ;
2020-02-05 21:17:05 +00:00
DUDEINFO * pDudeInfo = getDudeInfo ( pSprite - > type ) ;
2019-09-19 22:42:45 +00:00
if ( Chance ( pDudeInfo - > alertChance ) )
{
for ( int p = connecthead ; p > = 0 ; p = connectpoint2 [ p ] )
{
PLAYER * pPlayer = & gPlayer [ p ] ;
2019-10-21 19:46:41 +00:00
if ( pSprite - > owner = = pPlayer - > nSprite | | pPlayer - > pXSprite - > health = = 0 | | powerupCheck ( pPlayer , kPwUpShadowCloak ) > 0 )
2019-09-19 22:42:45 +00:00
continue ;
int x = pPlayer - > pSprite - > x ;
int y = pPlayer - > pSprite - > y ;
int z = pPlayer - > pSprite - > z ;
int nSector = pPlayer - > pSprite - > sectnum ;
int dx = x - pSprite - > x ;
int dy = y - pSprite - > y ;
int nDist = approxDist ( dx , dy ) ;
if ( nDist > pDudeInfo - > seeDist & & nDist > pDudeInfo - > hearDist )
continue ;
if ( ! cansee ( x , y , z , nSector , pSprite - > x , pSprite - > y , pSprite - > z - ( ( pDudeInfo - > eyeHeight * pSprite - > yrepeat ) < < 2 ) , pSprite - > sectnum ) )
continue ;
int nDeltaAngle = ( ( getangle ( dx , dy ) + 1024 - pSprite - > ang ) & 2047 ) - 1024 ;
if ( nDist < pDudeInfo - > seeDist & & klabs ( nDeltaAngle ) < = pDudeInfo - > periphery )
{
2019-10-21 19:46:41 +00:00
aiSetTarget ( pXSprite , pPlayer - > nSprite ) ;
2019-09-19 22:42:45 +00:00
aiActivateDude ( pSprite , pXSprite ) ;
return ;
}
else if ( nDist < pDudeInfo - > hearDist )
{
aiSetTarget ( pXSprite , x , y , z ) ;
aiActivateDude ( pSprite , pXSprite ) ;
return ;
}
}
if ( pXSprite - > state )
{
2020-10-15 15:08:21 +00:00
uint8_t va4 [ ( kMaxSectors + 7 ) > > 3 ] ;
2020-11-21 20:31:50 +00:00
GetClosestSpriteSectors ( pSprite - > sectnum , pSprite - > x , pSprite - > y , 400 , va4 ) ;
2020-10-15 15:15:45 +00:00
int nSprite2 ;
StatIterator it ( kStatDude ) ;
while ( ( nSprite2 = it . NextIndex ( ) ) > = 0 )
2019-09-19 22:42:45 +00:00
{
spritetype * pSprite2 = & sprite [ nSprite2 ] ;
int dx = pSprite2 - > x - pSprite - > x ;
int dy = pSprite2 - > y - pSprite - > y ;
int nDist = approxDist ( dx , dy ) ;
2019-10-11 21:59:39 +00:00
if ( pSprite2 - > type = = kDudeInnocent )
2019-09-19 22:42:45 +00:00
{
2020-02-05 21:17:05 +00:00
DUDEINFO * pDudeInfo = getDudeInfo ( pSprite2 - > type ) ;
2019-09-19 22:42:45 +00:00
if ( nDist > pDudeInfo - > seeDist & & nDist > pDudeInfo - > hearDist )
continue ;
aiSetTarget ( pXSprite , pSprite2 - > index ) ;
aiActivateDude ( pSprite , pXSprite ) ;
return ;
}
}
}
}
}
2019-11-24 20:53:51 +00:00
void aiProcessDudes ( void ) {
2020-10-15 15:15:45 +00:00
int nSprite ;
StatIterator it ( kStatDude ) ;
while ( ( nSprite = it . NextIndex ( ) ) > = 0 )
{
2019-09-19 22:42:45 +00:00
spritetype * pSprite = & sprite [ nSprite ] ;
2019-11-08 19:57:01 +00:00
if ( pSprite - > flags & 32 ) continue ;
2019-09-19 22:42:45 +00:00
int nXSprite = pSprite - > extra ;
2020-02-05 21:17:05 +00:00
XSPRITE * pXSprite = & xsprite [ nXSprite ] ; DUDEINFO * pDudeInfo = getDudeInfo ( pSprite - > type ) ;
2019-10-11 21:59:39 +00:00
if ( IsPlayerSprite ( pSprite ) | | pXSprite - > health = = 0 ) continue ;
2019-09-19 22:42:45 +00:00
pXSprite - > stateTimer = ClipLow ( pXSprite - > stateTimer - 4 , 0 ) ;
2020-02-07 19:47:43 +00:00
if ( pXSprite - > aiState - > moveFunc )
pXSprite - > aiState - > moveFunc ( pSprite , pXSprite ) ;
2020-08-26 10:55:46 +00:00
if ( pXSprite - > aiState - > thinkFunc & & ( gFrameCount & 3 ) = = ( nSprite & 3 ) )
2020-02-07 19:47:43 +00:00
pXSprite - > aiState - > thinkFunc ( pSprite , pXSprite ) ;
switch ( pSprite - > type ) {
2020-01-26 11:19:01 +00:00
# ifdef NOONE_EXTENSIONS
case kDudeModernCustom :
2020-02-07 19:47:43 +00:00
case kDudeModernCustomBurning : {
GENDUDEEXTRA * pExtra = & gGenDudeExtra [ pSprite - > index ] ;
if ( pExtra - > slaveCount > 0 ) updateTargetOfSlaves ( pSprite ) ;
if ( pExtra - > nLifeLeech > = 0 ) updateTargetOfLeech ( pSprite ) ;
if ( pXSprite - > stateTimer = = 0 & & pXSprite - > aiState - > nextState
& & ( pXSprite - > aiState - > stateTicks > 0 | | seqGetStatus ( 3 , pSprite - > extra ) < 0 ) ) {
aiGenDudeNewState ( pSprite , pXSprite - > aiState - > nextState ) ;
}
int hinder = ( ( pExtra - > isMelee ) ? 25 : 5 ) < < 4 ;
if ( pXSprite - > health < = 0 | | hinder > cumulDamage [ pSprite - > extra ] ) break ;
pXSprite - > data3 = cumulDamage [ pSprite - > extra ] ;
RecoilDude ( pSprite , pXSprite ) ;
2020-01-26 11:19:01 +00:00
break ;
2020-02-07 19:47:43 +00:00
}
2020-01-26 11:19:01 +00:00
# endif
default :
if ( pXSprite - > stateTimer = = 0 & & pXSprite - > aiState - > nextState ) {
if ( pXSprite - > aiState - > stateTicks > 0 )
aiNewState ( pSprite , pXSprite , pXSprite - > aiState - > nextState ) ;
else if ( seqGetStatus ( 3 , nXSprite ) < 0 )
aiNewState ( pSprite , pXSprite , pXSprite - > aiState - > nextState ) ;
}
2019-11-08 19:57:01 +00:00
2020-01-26 11:19:01 +00:00
if ( pXSprite - > health > 0 & & ( ( pDudeInfo - > hinderDamage < < 4 ) < = cumulDamage [ nXSprite ] ) ) {
pXSprite - > data3 = cumulDamage [ nXSprite ] ;
RecoilDude ( pSprite , pXSprite ) ;
}
break ;
2019-11-24 20:53:51 +00:00
}
2019-09-19 22:42:45 +00:00
}
memset ( cumulDamage , 0 , sizeof ( cumulDamage ) ) ;
}
void aiInit ( void )
{
2020-10-15 15:15:45 +00:00
int nSprite ;
StatIterator it ( kStatDude ) ;
while ( ( nSprite = it . NextIndex ( ) ) > = 0 )
2019-09-19 22:42:45 +00:00
{
aiInitSprite ( & sprite [ nSprite ] ) ;
}
}
void aiInitSprite ( spritetype * pSprite )
{
int nXSprite = pSprite - > extra ;
XSPRITE * pXSprite = & xsprite [ nXSprite ] ;
int nSector = pSprite - > sectnum ;
int nXSector = sector [ nSector ] . extra ;
XSECTOR * pXSector = NULL ;
if ( nXSector > 0 )
pXSector = & xsector [ nXSector ] ;
DUDEEXTRA * pDudeExtra = & gDudeExtra [ pSprite - > extra ] ;
2020-11-21 22:40:33 +00:00
pDudeExtra - > recoil = 0 ;
pDudeExtra - > time = 0 ;
2020-04-04 19:48:23 +00:00
2019-10-11 21:59:39 +00:00
switch ( pSprite - > type ) {
2020-04-04 19:48:23 +00:00
# ifdef NOONE_EXTENSIONS
case kDudeModernCustom :
aiGenDudeInitSprite ( pSprite , pXSprite ) ;
genDudePrepare ( pSprite , kGenDudePropertyAll ) ;
return ;
2019-10-11 21:59:39 +00:00
case kDudeModernCustomBurning :
2020-04-04 19:48:23 +00:00
aiGenDudeInitSprite ( pSprite , pXSprite ) ;
return ;
# endif
2019-10-11 21:59:39 +00:00
case kDudeCultistTommy :
case kDudeCultistShotgun :
case kDudeCultistTesla :
case kDudeCultistTNT :
case kDudeCultistBeast :
2019-09-19 22:42:45 +00:00
{
DUDEEXTRA_at6_u1 * pDudeExtraE = & gDudeExtra [ nXSprite ] . at6 . u1 ;
2020-11-21 22:40:33 +00:00
pDudeExtraE - > xval3 = 0 ;
pDudeExtraE - > xval1 = 0 ;
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & cultistIdle ) ;
break ;
}
2019-10-11 21:59:39 +00:00
case kDudeCultistTommyProne :
2019-09-19 22:42:45 +00:00
{
DUDEEXTRA_at6_u1 * pDudeExtraE = & gDudeExtra [ nXSprite ] . at6 . u1 ;
2020-11-21 22:40:33 +00:00
pDudeExtraE - > xval3 = 0 ;
pDudeExtraE - > xval1 = 0 ;
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & fanaticProneIdle ) ;
break ;
}
2019-10-11 21:59:39 +00:00
case kDudeCultistShotgunProne :
2019-09-19 22:42:45 +00:00
{
DUDEEXTRA_at6_u1 * pDudeExtraE = & gDudeExtra [ nXSprite ] . at6 . u1 ;
2020-11-21 22:40:33 +00:00
pDudeExtraE - > xval3 = 0 ;
pDudeExtraE - > xval1 = 0 ;
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & cultistProneIdle ) ;
break ;
}
2019-10-11 21:59:39 +00:00
case kDudeZombieButcher : {
2019-09-19 22:42:45 +00:00
DUDEEXTRA_at6_u2 * pDudeExtraE = & gDudeExtra [ nXSprite ] . at6 . u2 ;
2020-11-21 22:40:33 +00:00
pDudeExtraE - > xval2 = 0 ;
pDudeExtraE - > xval1 = 0 ;
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & zombieFIdle ) ;
break ;
}
2019-10-11 21:59:39 +00:00
case kDudeZombieAxeNormal : {
2019-09-19 22:42:45 +00:00
DUDEEXTRA_at6_u2 * pDudeExtraE = & gDudeExtra [ nXSprite ] . at6 . u2 ;
2020-11-21 22:40:33 +00:00
pDudeExtraE - > xval2 = 0 ;
pDudeExtraE - > xval1 = 0 ;
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & zombieAIdle ) ;
break ;
}
2019-10-11 21:59:39 +00:00
case kDudeZombieAxeLaying :
2019-09-19 22:42:45 +00:00
{
DUDEEXTRA_at6_u2 * pDudeExtraE = & gDudeExtra [ nXSprite ] . at6 . u2 ;
2020-11-21 22:40:33 +00:00
pDudeExtraE - > xval2 = 0 ;
pDudeExtraE - > xval1 = 0 ;
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & zombieSIdle ) ;
2019-09-30 07:18:01 +00:00
pSprite - > flags & = ~ 1 ;
2019-09-19 22:42:45 +00:00
break ;
}
2019-10-11 21:59:39 +00:00
case kDudeZombieAxeBuried : {
2019-09-19 22:42:45 +00:00
DUDEEXTRA_at6_u2 * pDudeExtraE = & gDudeExtra [ nXSprite ] . at6 . u2 ;
2020-11-21 22:40:33 +00:00
pDudeExtraE - > xval2 = 0 ;
pDudeExtraE - > xval1 = 0 ;
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & zombieEIdle ) ;
break ;
}
2019-10-11 21:59:39 +00:00
case kDudeGargoyleFlesh :
case kDudeGargoyleStone : {
2019-09-19 22:42:45 +00:00
DUDEEXTRA_at6_u1 * pDudeExtraE = & gDudeExtra [ nXSprite ] . at6 . u1 ;
2020-11-21 22:40:33 +00:00
pDudeExtraE - > xval2 = 0 ;
pDudeExtraE - > xval3 = 0 ;
pDudeExtraE - > xval1 = 0 ;
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & gargoyleFIdle ) ;
break ;
}
2019-10-11 21:59:39 +00:00
case kDudeGargoyleStatueFlesh :
case kDudeGargoyleStatueStone :
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & gargoyleStatueIdle ) ;
break ;
2019-10-11 21:59:39 +00:00
case kDudeCerberusTwoHead : {
2019-09-19 22:42:45 +00:00
DUDEEXTRA_at6_u2 * pDudeExtraE = & gDudeExtra [ nXSprite ] . at6 . u2 ;
2020-11-21 22:40:33 +00:00
pDudeExtraE - > xval2 = 0 ;
pDudeExtraE - > xval1 = 0 ;
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & cerberusIdle ) ;
break ;
}
2019-10-11 21:59:39 +00:00
case kDudeHellHound :
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & houndIdle ) ;
break ;
2019-10-11 21:59:39 +00:00
case kDudeHand :
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & handIdle ) ;
break ;
2019-10-11 21:59:39 +00:00
case kDudePhantasm :
2019-09-19 22:42:45 +00:00
{
DUDEEXTRA_at6_u1 * pDudeExtraE = & gDudeExtra [ nXSprite ] . at6 . u1 ;
2020-11-21 22:40:33 +00:00
pDudeExtraE - > xval2 = 0 ;
pDudeExtraE - > xval3 = 0 ;
pDudeExtraE - > xval1 = 0 ;
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & ghostIdle ) ;
break ;
}
2019-10-11 21:59:39 +00:00
case kDudeInnocent :
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & innocentIdle ) ;
break ;
2019-10-11 21:59:39 +00:00
case kDudeRat :
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & ratIdle ) ;
break ;
2019-10-11 21:59:39 +00:00
case kDudeBoneEel :
2019-09-19 22:42:45 +00:00
{
DUDEEXTRA_at6_u1 * pDudeExtraE = & gDudeExtra [ nXSprite ] . at6 . u1 ;
2020-11-21 22:40:33 +00:00
pDudeExtraE - > xval2 = 0 ;
pDudeExtraE - > xval3 = 0 ;
pDudeExtraE - > xval1 = 0 ;
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & eelIdle ) ;
break ;
}
2019-10-11 21:59:39 +00:00
case kDudeGillBeast :
2019-12-05 20:42:35 +00:00
aiNewState ( pSprite , pXSprite , & gillBeastIdle ) ;
2019-09-19 22:42:45 +00:00
break ;
2019-10-11 21:59:39 +00:00
case kDudeBat :
2019-09-19 22:42:45 +00:00
{
DUDEEXTRA_at6_u1 * pDudeExtraE = & gDudeExtra [ nXSprite ] . at6 . u1 ;
2020-11-21 22:40:33 +00:00
pDudeExtraE - > xval2 = 0 ;
pDudeExtraE - > xval3 = 0 ;
pDudeExtraE - > xval1 = 0 ;
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & batIdle ) ;
break ;
}
2019-10-11 21:59:39 +00:00
case kDudeSpiderBrown :
case kDudeSpiderRed :
case kDudeSpiderBlack :
2019-09-19 22:42:45 +00:00
{
DUDEEXTRA_at6_u1 * pDudeExtraE = & gDudeExtra [ nXSprite ] . at6 . u1 ;
2020-11-21 22:40:33 +00:00
pDudeExtraE - > xval3 = 0 ;
pDudeExtraE - > xval2 = 0 ;
pDudeExtraE - > xval1 = 0 ;
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & spidIdle ) ;
break ;
}
2019-10-11 21:59:39 +00:00
case kDudeSpiderMother :
2019-09-19 22:42:45 +00:00
{
DUDEEXTRA_at6_u1 * pDudeExtraE = & gDudeExtra [ nXSprite ] . at6 . u1 ;
2020-11-21 22:40:33 +00:00
pDudeExtraE - > xval3 = 0 ;
pDudeExtraE - > xval2 = 0 ;
pDudeExtraE - > xval1 = 0 ;
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & spidIdle ) ;
break ;
}
2019-10-11 21:59:39 +00:00
case kDudeTchernobog :
2019-09-19 22:42:45 +00:00
{
DUDEEXTRA_at6_u2 * pDudeExtraE = & gDudeExtra [ nXSprite ] . at6 . u2 ;
2020-11-21 22:40:33 +00:00
pDudeExtraE - > xval2 = 0 ;
pDudeExtraE - > xval1 = 0 ;
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & tchernobogIdle ) ;
break ;
}
2019-10-11 21:59:39 +00:00
case kDudeTinyCaleb :
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & tinycalebIdle ) ;
break ;
2019-10-11 21:59:39 +00:00
case kDudeBeast :
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & beastIdle ) ;
break ;
2019-10-11 21:59:39 +00:00
case kDudePodGreen :
case kDudePodFire :
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & podIdle ) ;
break ;
2019-10-11 21:59:39 +00:00
case kDudeTentacleGreen :
case kDudeTentacleFire :
2019-09-19 22:42:45 +00:00
aiNewState ( pSprite , pXSprite , & tentacleIdle ) ;
break ;
default :
aiNewState ( pSprite , pXSprite , & genIdle ) ;
break ;
}
aiSetTarget ( pXSprite , 0 , 0 , 0 ) ;
pXSprite - > stateTimer = 0 ;
switch ( pSprite - > type )
{
2019-10-11 21:59:39 +00:00
case kDudeSpiderBrown :
case kDudeSpiderRed :
case kDudeSpiderBlack :
if ( pSprite - > cstat & 8 ) pSprite - > flags | = 9 ;
else pSprite - > flags = 15 ;
break ;
case kDudeGargoyleFlesh :
case kDudeGargoyleStone :
case kDudePhantasm :
case kDudeBoneEel :
case kDudeBat :
2019-09-30 07:18:01 +00:00
pSprite - > flags | = 9 ;
2019-09-19 22:42:45 +00:00
break ;
2019-10-11 21:59:39 +00:00
case kDudeGillBeast :
if ( pXSector & & pXSector - > Underwater ) pSprite - > flags | = 9 ;
else pSprite - > flags = 15 ;
2019-09-19 22:42:45 +00:00
break ;
2019-10-11 21:59:39 +00:00
case kDudeZombieAxeBuried :
case kDudeZombieAxeLaying :
2019-09-30 07:18:01 +00:00
pSprite - > flags = 7 ;
2019-09-19 22:42:45 +00:00
break ;
2020-01-26 11:19:01 +00:00
# ifdef NOONE_EXTENSIONS
case kDudePodMother : // FakeDude type
2019-10-11 21:59:39 +00:00
if ( gModernMap ) break ;
fallthrough__ ;
2020-01-26 11:19:01 +00:00
// Allow put pods and tentacles on ceilings if sprite is y-flipped.
2019-10-11 21:59:39 +00:00
case kDudePodGreen :
case kDudeTentacleGreen :
case kDudePodFire :
case kDudeTentacleFire :
case kDudeTentacleMother :
if ( gModernMap & & ( pSprite - > cstat & CSTAT_SPRITE_YFLIP ) ) {
2019-09-30 07:18:01 +00:00
if ( ! ( pSprite - > flags & kModernTypeFlag1 ) ) // don't add autoaim for player if hitag 1 specified in editor.
pSprite - > flags = kHitagAutoAim ;
2019-09-19 22:42:45 +00:00
break ;
}
fallthrough__ ;
// go default
2020-01-26 11:19:01 +00:00
# endif
2019-09-19 22:42:45 +00:00
default :
2019-09-30 07:18:01 +00:00
pSprite - > flags = 15 ;
2019-09-19 22:42:45 +00:00
break ;
}
}
2020-11-21 22:40:33 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2019-09-19 22:42:45 +00:00
2020-11-21 22:40:33 +00:00
FSerializer & Serialize ( FSerializer & arc , const char * keyname , DUDEEXTRA & w , DUDEEXTRA * def )
2019-09-19 22:42:45 +00:00
{
2020-11-22 11:48:01 +00:00
int empty = 0 ;
char empty2 = 0 ;
if ( arc . isReading ( ) ) w = { } ;
2020-11-21 22:40:33 +00:00
if ( arc . BeginObject ( keyname ) )
{
2020-11-22 11:48:01 +00:00
arc ( " time " , w . time , & empty )
( " recoil " , w . recoil , & empty )
( " prio " , w . prio , & empty )
( " x1 " , w . at6 . u1 . xval1 , & empty )
( " x2 " , w . at6 . u1 . xval2 , & empty )
( " x3 " , w . at6 . u1 . xval3 , & empty2 )
2020-11-21 22:40:33 +00:00
. EndObject ( ) ;
}
return arc ;
2019-09-19 22:42:45 +00:00
}
2020-11-21 22:40:33 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
FSerializer & Serialize ( FSerializer & arc , const char * keyname , GENDUDEEXTRA & w , GENDUDEEXTRA * def )
2019-09-19 22:42:45 +00:00
{
2020-11-21 22:40:33 +00:00
if ( arc . BeginObject ( keyname ) )
{
arc . Array ( " initvals " , w . initVals , 3 )
. Array ( " availdeaths " , w . availDeaths , kDamageMax )
( " movespeed " , w . moveSpeed )
( " firedist " , w . fireDist )
( " throwdist " , w . throwDist )
( " curweapon " , w . curWeapon )
( " weapontype " , w . weaponType )
( " basedispersion " , w . baseDispersion )
( " slavecount " , w . slaveCount )
( " lifeleech " , w . nLifeLeech )
. Array ( " slaves " , w . slave , w . slaveCount )
. Array ( " dmgcontrol " , w . dmgControl , kDamageMax )
. Array ( " updreq " , w . updReq , kGenDudePropertyMax )
( " flags " , w . flags )
. EndObject ( ) ;
}
return arc ;
2019-09-19 22:42:45 +00:00
}
2020-11-21 22:40:33 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void SerializeAI ( FSerializer & arc )
2019-09-19 22:42:45 +00:00
{
2020-11-21 22:40:33 +00:00
if ( arc . BeginObject ( " ai " ) )
{
arc . SparseArray ( " dudeslope " , gDudeSlope , kMaxSprites , activeXSprites )
. SparseArray ( " dudeextra " , gDudeExtra , kMaxSprites , activeXSprites ) ;
// the GenDudeArray only contains valid info for kDudeModernCustom and kDudeModernCustomBurning so only save the relevant entries as these are not small.
bool foundsome = false ;
for ( int i = 0 ; i < kMaxSprites ; i + + )
{
if ( activeSprites [ i ] & & ( sprite [ i ] . type = = kDudeModernCustom | | sprite [ i ] . type = = kDudeModernCustomBurning ) )
{
if ( ! foundsome ) arc . BeginArray ( " gendudeextra " ) ;
foundsome = true ;
arc ( nullptr , gGenDudeExtra [ i ] ) ;
}
}
if ( foundsome ) arc . EndArray ( ) ;
arc . EndObject ( ) ;
}
2019-09-19 22:42:45 +00:00
}
2020-11-21 22:40:33 +00:00
2019-09-22 06:39:22 +00:00
END_BLD_NS