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 <stdlib.h>
# include <string.h>
2020-09-06 11:39:57 +00:00
# include "automap.h"
2019-09-19 22:42:45 +00:00
# include "compat.h"
# include "build.h"
# include "mmulti.h"
2020-12-09 14:56:32 +00:00
2019-09-19 22:42:45 +00:00
# include "blood.h"
2019-12-09 01:01:30 +00:00
# include "gstrings.h"
2020-09-04 20:23:38 +00:00
# include "gamestate.h"
2020-09-06 10:44:58 +00:00
# include "automap.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
PLAYER gPlayer [ kMaxPlayers ] ;
PLAYER * gMe , * gView ;
2019-09-15 11:59:27 +00:00
bool gBlueFlagDropped = false ;
bool gRedFlagDropped = false ;
2019-10-19 19:11:39 +00:00
// V = has effect in game, X = no effect in game
2019-09-19 22:42:45 +00:00
POWERUPINFO gPowerUpInfo [ kMaxPowerUps ] = {
2019-10-19 19:11:39 +00:00
{ - 1 , 1 , 1 , 1 } , // 00: V keys
{ - 1 , 1 , 1 , 1 } , // 01: V keys
{ - 1 , 1 , 1 , 1 } , // 02: V keys
{ - 1 , 1 , 1 , 1 } , // 03: V keys
{ - 1 , 1 , 1 , 1 } , // 04: V keys
{ - 1 , 1 , 1 , 1 } , // 05: V keys
{ - 1 , 1 , 1 , 1 } , // 06: V keys
{ - 1 , 0 , 100 , 100 } , // 07: V doctor's bag
{ - 1 , 0 , 50 , 100 } , // 08: V medicine pouch
{ - 1 , 0 , 20 , 100 } , // 09: V life essense
{ - 1 , 0 , 100 , 200 } , // 10: V life seed
{ - 1 , 0 , 2 , 200 } , // 11: V red potion
{ 783 , 0 , 3600 , 432000 } , // 12: V feather fall
{ 896 , 0 , 3600 , 432000 } , // 13: V cloak of invisibility
{ 825 , 1 , 3600 , 432000 } , // 14: V death mask (invulnerability)
{ 827 , 0 , 3600 , 432000 } , // 15: V jump boots
{ 828 , 0 , 3600 , 432000 } , // 16: X raven flight
{ 829 , 0 , 3600 , 1728000 } , // 17: V guns akimbo
{ 830 , 0 , 3600 , 432000 } , // 18: V diving suit
{ 831 , 0 , 3600 , 432000 } , // 19: V gas mask
{ - 1 , 0 , 3600 , 432000 } , // 20: X clone
{ 2566 , 0 , 3600 , 432000 } , // 21: V crystal ball
{ 836 , 0 , 3600 , 432000 } , // 22: X decoy
{ 853 , 0 , 3600 , 432000 } , // 23: V doppleganger
{ 2428 , 0 , 3600 , 432000 } , // 24: V reflective shots
{ 839 , 0 , 3600 , 432000 } , // 25: V beast vision
{ 768 , 0 , 3600 , 432000 } , // 26: X cloak of shadow (useless)
{ 840 , 0 , 3600 , 432000 } , // 27: X rage shroom
{ 841 , 0 , 900 , 432000 } , // 28: V delirium shroom
{ 842 , 0 , 3600 , 432000 } , // 29: V grow shroom (gModernMap only)
{ 843 , 0 , 3600 , 432000 } , // 30: V shrink shroom (gModernMap only)
{ - 1 , 0 , 3600 , 432000 } , // 31: X death mask (useless)
{ - 1 , 0 , 3600 , 432000 } , // 32: X wine goblet
{ - 1 , 0 , 3600 , 432000 } , // 33: X wine bottle
{ - 1 , 0 , 3600 , 432000 } , // 34: X skull grail
{ - 1 , 0 , 3600 , 432000 } , // 35: X silver grail
{ - 1 , 0 , 3600 , 432000 } , // 36: X tome
{ - 1 , 0 , 3600 , 432000 } , // 37: X black chest
{ - 1 , 0 , 3600 , 432000 } , // 38: X wooden chest
{ 837 , 1 , 3600 , 432000 } , // 39: V asbestos armor
{ - 1 , 0 , 1 , 432000 } , // 40: V basic armor
{ - 1 , 0 , 1 , 432000 } , // 41: V body armor
{ - 1 , 0 , 1 , 432000 } , // 42: V fire armor
{ - 1 , 0 , 1 , 432000 } , // 43: V spirit armor
{ - 1 , 0 , 1 , 432000 } , // 44: V super armor
{ 0 , 0 , 0 , 0 } , // 45: ? unknown
{ 0 , 0 , 0 , 0 } , // 46: ? unknown
{ 0 , 0 , 0 , 0 } , // 47: ? unknown
{ 0 , 0 , 0 , 0 } , // 48: ? unknown
{ 0 , 0 , 0 , 0 } , // 49: X dummy
{ 833 , 1 , 1 , 1 } // 50: V kModernItemLevelMap (gModernMap only)
2019-09-19 22:42:45 +00:00
} ;
int Handicap [ ] = {
144 , 208 , 256 , 304 , 368
} ;
2020-01-01 20:53:29 +00:00
POSTURE gPostureDefaults [ kModeMax ] [ kPostureMax ] = {
2019-09-19 22:42:45 +00:00
// normal human
{
2020-01-01 20:53:29 +00:00
{ 0x4000 , 0x4000 , 0x4000 , 14 , 17 , 24 , 16 , 32 , 80 , 0x1600 , 0x1200 , 0xc00 , 0x90 , - 0xbaaaa , - 0x175555 } ,
{ 0x1200 , 0x1200 , 0x1200 , 14 , 17 , 24 , 16 , 32 , 80 , 0x1400 , 0x1000 , - 0x600 , 0xb0 , 0x5b05 , 0 } ,
{ 0x2000 , 0x2000 , 0x2000 , 22 , 28 , 24 , 16 , 16 , 40 , 0x800 , 0x600 , - 0x600 , 0xb0 , 0 , 0 } ,
2019-09-19 22:42:45 +00:00
} ,
// normal beast
{
2020-01-01 20:53:29 +00:00
{ 0x4000 , 0x4000 , 0x4000 , 14 , 17 , 24 , 16 , 32 , 80 , 0x1600 , 0x1200 , 0xc00 , 0x90 , - 0xbaaaa , - 0x175555 } ,
{ 0x1200 , 0x1200 , 0x1200 , 14 , 17 , 24 , 16 , 32 , 80 , 0x1400 , 0x1000 , - 0x600 , 0xb0 , 0x5b05 , 0 } ,
{ 0x2000 , 0x2000 , 0x2000 , 22 , 28 , 24 , 16 , 16 , 40 , 0x800 , 0x600 , - 0x600 , 0xb0 , 0 , 0 } ,
2019-09-19 22:42:45 +00:00
} ,
// shrink human
{
2020-01-01 20:53:29 +00:00
{ 10384 , 10384 , 10384 , 14 , 17 , 24 , 16 , 32 , 80 , 5632 , 4608 , 3072 , 144 , - 564586 , - 1329173 } ,
{ 2108 , 2108 , 2108 , 14 , 17 , 24 , 16 , 32 , 80 , 5120 , 4096 , - 1536 , 176 , 0x5b05 , 0 } ,
{ 2192 , 2192 , 2192 , 22 , 28 , 24 , 16 , 16 , 40 , 2048 , 1536 , - 1536 , 176 , 0 , 0 } ,
2019-09-19 22:42:45 +00:00
} ,
// grown human
{
2020-01-01 20:53:29 +00:00
{ 19384 , 19384 , 19384 , 14 , 17 , 24 , 16 , 32 , 80 , 5632 , 4608 , 3072 , 144 , - 1014586 , - 1779173 } ,
{ 5608 , 5608 , 5608 , 14 , 17 , 24 , 16 , 32 , 80 , 5120 , 4096 , - 1536 , 176 , 0x5b05 , 0 } ,
{ 11192 , 11192 , 11192 , 22 , 28 , 24 , 16 , 16 , 40 , 2048 , 1536 , - 1536 , 176 , 0 , 0 } ,
2019-09-19 22:42:45 +00:00
} ,
} ;
AMMOINFO gAmmoInfo [ ] = {
{ 0 , - 1 } ,
{ 100 , - 1 } ,
{ 100 , 4 } ,
{ 500 , 5 } ,
{ 100 , - 1 } ,
{ 50 , - 1 } ,
{ 2880 , - 1 } ,
{ 250 , - 1 } ,
{ 100 , - 1 } ,
{ 100 , - 1 } ,
{ 50 , - 1 } ,
{ 50 , - 1 } ,
} ;
struct ARMORDATA {
2020-11-21 22:40:08 +00:00
int armor0 ;
int armor0max ;
int armor1 ;
int armor1max ;
int armor2 ;
int armor2max ;
2019-09-19 22:42:45 +00:00
} ;
ARMORDATA armorData [ 5 ] = {
{ 0x320 , 0x640 , 0x320 , 0x640 , 0x320 , 0x640 } ,
{ 0x640 , 0x640 , 0 , 0x640 , 0 , 0x640 } ,
{ 0 , 0x640 , 0x640 , 0x640 , 0 , 0x640 } ,
{ 0 , 0x640 , 0 , 0x640 , 0x640 , 0x640 } ,
{ 0xc80 , 0xc80 , 0xc80 , 0xc80 , 0xc80 , 0xc80 }
} ;
struct VICTORY {
2020-11-21 22:40:08 +00:00
const char * message ;
2020-09-01 19:27:32 +00:00
int Kills ;
2019-09-19 22:42:45 +00:00
} ;
VICTORY gVictory [ ] = {
{ " %s boned %s like a fish " , 4100 } ,
{ " %s castrated %s " , 4101 } ,
{ " %s creamed %s " , 4102 } ,
{ " %s destroyed %s " , 4103 } ,
{ " %s diced %s " , 4104 } ,
{ " %s disemboweled %s " , 4105 } ,
{ " %s flattened %s " , 4106 } ,
{ " %s gave %s Anal Justice " , 4107 } ,
{ " %s gave AnAl MaDnEsS to %s " , 4108 } ,
{ " %s hurt %s real bad " , 4109 } ,
{ " %s killed %s " , 4110 } ,
{ " %s made mincemeat out of %s " , 4111 } ,
{ " %s massacred %s " , 4112 } ,
{ " %s mutilated %s " , 4113 } ,
{ " %s reamed %s " , 4114 } ,
{ " %s ripped %s a new orifice " , 4115 } ,
{ " %s slaughtered %s " , 4116 } ,
{ " %s sliced %s " , 4117 } ,
{ " %s smashed %s " , 4118 } ,
{ " %s sodomized %s " , 4119 } ,
{ " %s splattered %s " , 4120 } ,
{ " %s squashed %s " , 4121 } ,
{ " %s throttled %s " , 4122 } ,
{ " %s wasted %s " , 4123 } ,
{ " %s body bagged %s " , 4124 } ,
} ;
struct SUICIDE {
2020-11-21 22:40:08 +00:00
const char * message ;
2020-09-01 19:27:32 +00:00
int Kills ;
2019-09-19 22:42:45 +00:00
} ;
SUICIDE gSuicide [ ] = {
{ " %s is excrement " , 4202 } ,
{ " %s is hamburger " , 4203 } ,
{ " %s suffered scrotum separation " , 4204 } ,
{ " %s volunteered for population control " , 4206 } ,
{ " %s has suicided " , 4207 } ,
} ;
struct DAMAGEINFO {
2020-11-21 22:40:08 +00:00
int armorType ;
2020-09-01 19:27:32 +00:00
int Kills [ 3 ] ;
2019-09-19 22:42:45 +00:00
int at10 [ 3 ] ;
} ;
DAMAGEINFO damageInfo [ 7 ] = {
{ - 1 , 731 , 732 , 733 , 710 , 710 , 710 } ,
{ 1 , 742 , 743 , 744 , 711 , 711 , 711 } ,
{ 0 , 731 , 732 , 733 , 712 , 712 , 712 } ,
{ 1 , 731 , 732 , 733 , 713 , 713 , 713 } ,
{ - 1 , 724 , 724 , 724 , 714 , 714 , 714 } ,
{ 2 , 731 , 732 , 733 , 715 , 715 , 715 } ,
{ 0 , 0 , 0 , 0 , 0 , 0 , 0 }
} ;
2020-01-26 11:19:01 +00:00
int powerupCheck ( PLAYER * pPlayer , int nPowerUp )
{
2020-10-11 10:38:17 +00:00
assert ( pPlayer ! = NULL ) ;
assert ( nPowerUp > = 0 & & nPowerUp < kMaxPowerUps ) ;
2020-01-26 11:19:01 +00:00
int nPack = powerupToPackItem ( nPowerUp ) ;
if ( nPack > = 0 & & ! packItemActive ( pPlayer , nPack ) )
return 0 ;
return pPlayer - > pwUpTime [ nPowerUp ] ;
}
2019-10-19 19:11:39 +00:00
2019-09-19 22:42:45 +00:00
char powerupActivate ( PLAYER * pPlayer , int nPowerUp )
{
2019-10-19 19:11:39 +00:00
if ( powerupCheck ( pPlayer , nPowerUp ) > 0 & & gPowerUpInfo [ nPowerUp ] . pickupOnce )
2019-09-19 22:42:45 +00:00
return 0 ;
2019-10-21 19:46:41 +00:00
if ( ! pPlayer - > pwUpTime [ nPowerUp ] )
pPlayer - > pwUpTime [ nPowerUp ] = gPowerUpInfo [ nPowerUp ] . bonusTime ;
2019-09-19 22:42:45 +00:00
int nPack = powerupToPackItem ( nPowerUp ) ;
if ( nPack > = 0 )
2019-10-21 19:46:41 +00:00
pPlayer - > packSlots [ nPack ] . isActive = 1 ;
2019-10-11 21:59:39 +00:00
switch ( nPowerUp + kItemBase ) {
2020-01-26 11:19:01 +00:00
# ifdef NOONE_EXTENSIONS
2019-10-11 21:59:39 +00:00
case kItemModernMapLevel :
if ( gModernMap ) gFullMap = true ;
break ;
case kItemShroomShrink :
if ( ! gModernMap ) break ;
2020-02-07 19:47:43 +00:00
else if ( isGrown ( pPlayer - > pSprite ) ) playerDeactivateShrooms ( pPlayer ) ;
else playerSizeShrink ( pPlayer , 2 ) ;
2019-10-11 21:59:39 +00:00
break ;
case kItemShroomGrow :
if ( ! gModernMap ) break ;
2020-02-07 19:47:43 +00:00
else if ( isShrinked ( pPlayer - > pSprite ) ) playerDeactivateShrooms ( pPlayer ) ;
2019-10-11 21:59:39 +00:00
else {
2020-02-07 19:47:43 +00:00
playerSizeGrow ( pPlayer , 2 ) ;
2019-10-19 19:11:39 +00:00
if ( powerupCheck ( & gPlayer [ pPlayer - > pSprite - > type - kDudePlayer1 ] , kPwUpShadowCloak ) > 0 ) {
powerupDeactivate ( pPlayer , kPwUpShadowCloak ) ;
2019-10-21 19:46:41 +00:00
pPlayer - > pwUpTime [ kPwUpShadowCloak ] = 0 ;
2019-10-11 21:59:39 +00:00
}
2019-09-19 22:42:45 +00:00
2019-10-11 21:59:39 +00:00
if ( ceilIsTooLow ( pPlayer - > pSprite ) )
2020-02-07 19:47:43 +00:00
actDamageSprite ( pPlayer - > pSprite - > index , pPlayer - > pSprite , DAMAGE_TYPE_3 , 65535 ) ;
2019-10-11 21:59:39 +00:00
}
break ;
2020-01-26 11:19:01 +00:00
# endif
2019-10-11 21:59:39 +00:00
case kItemFeatherFall :
case kItemJumpBoots :
2019-10-21 19:46:41 +00:00
pPlayer - > damageControl [ 0 ] + + ;
2019-10-11 21:59:39 +00:00
break ;
case kItemReflectShots : // reflective shots
if ( pPlayer = = gMe & & gGameOptions . nGameType = = 0 )
sfxSetReverb2 ( 1 ) ;
break ;
case kItemDeathMask :
for ( int i = 0 ; i < 7 ; i + + )
2019-10-21 19:46:41 +00:00
pPlayer - > damageControl [ i ] + + ;
2019-10-11 21:59:39 +00:00
break ;
case kItemDivingSuit : // diving suit
2019-10-21 19:46:41 +00:00
pPlayer - > damageControl [ 4 ] + + ;
2019-10-11 21:59:39 +00:00
if ( pPlayer = = gMe & & gGameOptions . nGameType = = 0 )
sfxSetReverb ( 1 ) ;
break ;
case kItemGasMask :
2019-10-21 19:46:41 +00:00
pPlayer - > damageControl [ 4 ] + + ;
2019-10-11 21:59:39 +00:00
break ;
case kItemArmorAsbest :
2019-10-21 19:46:41 +00:00
pPlayer - > damageControl [ 1 ] + + ;
2019-10-11 21:59:39 +00:00
break ;
case kItemTwoGuns :
2020-08-26 14:48:33 +00:00
pPlayer - > newWeapon = pPlayer - > curWeapon ;
2019-10-11 21:59:39 +00:00
WeaponRaise ( pPlayer ) ;
break ;
2019-09-19 22:42:45 +00:00
}
sfxPlay3DSound ( pPlayer - > pSprite , 776 , - 1 , 0 ) ;
return 1 ;
}
void powerupDeactivate ( PLAYER * pPlayer , int nPowerUp )
{
int nPack = powerupToPackItem ( nPowerUp ) ;
if ( nPack > = 0 )
2019-10-21 19:46:41 +00:00
pPlayer - > packSlots [ nPack ] . isActive = 0 ;
2019-10-11 21:59:39 +00:00
switch ( nPowerUp + kItemBase ) {
2020-01-26 11:19:01 +00:00
# ifdef NOONE_EXTENSIONS
2019-10-11 21:59:39 +00:00
case kItemShroomShrink :
if ( gModernMap ) {
2020-02-07 19:47:43 +00:00
playerSizeReset ( pPlayer ) ;
2019-10-11 21:59:39 +00:00
if ( ceilIsTooLow ( pPlayer - > pSprite ) )
2020-02-07 19:47:43 +00:00
actDamageSprite ( pPlayer - > pSprite - > index , pPlayer - > pSprite , DAMAGE_TYPE_3 , 65535 ) ;
2019-10-11 21:59:39 +00:00
}
break ;
case kItemShroomGrow :
2020-02-07 19:47:43 +00:00
if ( gModernMap ) playerSizeReset ( pPlayer ) ;
2019-10-11 21:59:39 +00:00
break ;
2020-01-26 11:19:01 +00:00
# endif
2019-10-11 21:59:39 +00:00
case kItemFeatherFall :
case kItemJumpBoots :
2019-10-21 19:46:41 +00:00
pPlayer - > damageControl [ 0 ] - - ;
2019-10-11 21:59:39 +00:00
break ;
case kItemDeathMask :
for ( int i = 0 ; i < 7 ; i + + )
2019-10-21 19:46:41 +00:00
pPlayer - > damageControl [ i ] - - ;
2019-10-11 21:59:39 +00:00
break ;
case kItemDivingSuit :
2019-10-21 19:46:41 +00:00
pPlayer - > damageControl [ 4 ] - - ;
if ( pPlayer = = gMe & & VanillaMode ( ) ? true : pPlayer - > pwUpTime [ 24 ] = = 0 )
2019-10-11 21:59:39 +00:00
sfxSetReverb ( 0 ) ;
break ;
case kItemReflectShots :
2019-10-21 19:46:41 +00:00
if ( pPlayer = = gMe & & VanillaMode ( ) ? true : pPlayer - > packSlots [ 1 ] . isActive = = 0 )
2019-10-11 21:59:39 +00:00
sfxSetReverb ( 0 ) ;
break ;
case kItemGasMask :
2019-10-21 19:46:41 +00:00
pPlayer - > damageControl [ 4 ] - - ;
2019-10-11 21:59:39 +00:00
break ;
case kItemArmorAsbest :
2019-10-21 19:46:41 +00:00
pPlayer - > damageControl [ 1 ] - - ;
2019-10-11 21:59:39 +00:00
break ;
case kItemTwoGuns :
2020-08-26 14:48:33 +00:00
pPlayer - > newWeapon = pPlayer - > curWeapon ;
2019-10-11 21:59:39 +00:00
WeaponRaise ( pPlayer ) ;
break ;
2019-09-19 22:42:45 +00:00
}
}
void powerupSetState ( PLAYER * pPlayer , int nPowerUp , char bState )
{
if ( ! bState )
powerupActivate ( pPlayer , nPowerUp ) ;
else
powerupDeactivate ( pPlayer , nPowerUp ) ;
}
void powerupProcess ( PLAYER * pPlayer )
{
2019-10-21 19:46:41 +00:00
pPlayer - > packItemTime = ClipLow ( pPlayer - > packItemTime - 4 , 0 ) ;
2019-09-19 22:42:45 +00:00
for ( int i = kMaxPowerUps - 1 ; i > = 0 ; i - - )
{
int nPack = powerupToPackItem ( i ) ;
if ( nPack > = 0 )
{
2019-10-21 19:46:41 +00:00
if ( pPlayer - > packSlots [ nPack ] . isActive )
2019-09-19 22:42:45 +00:00
{
2019-10-21 19:46:41 +00:00
pPlayer - > pwUpTime [ i ] = ClipLow ( pPlayer - > pwUpTime [ i ] - 4 , 0 ) ;
if ( pPlayer - > pwUpTime [ i ] )
pPlayer - > packSlots [ nPack ] . curAmount = ( 100 * pPlayer - > pwUpTime [ i ] ) / gPowerUpInfo [ i ] . bonusTime ;
2019-09-19 22:42:45 +00:00
else
{
powerupDeactivate ( pPlayer , i ) ;
2019-10-21 19:46:41 +00:00
if ( pPlayer - > packItemId = = nPack )
pPlayer - > packItemId = 0 ;
2019-09-19 22:42:45 +00:00
}
}
}
2019-10-21 19:46:41 +00:00
else if ( pPlayer - > pwUpTime [ i ] > 0 )
2019-09-19 22:42:45 +00:00
{
2019-10-21 19:46:41 +00:00
pPlayer - > pwUpTime [ i ] = ClipLow ( pPlayer - > pwUpTime [ i ] - 4 , 0 ) ;
if ( ! pPlayer - > pwUpTime [ i ] )
2019-09-19 22:42:45 +00:00
powerupDeactivate ( pPlayer , i ) ;
}
}
}
void powerupClear ( PLAYER * pPlayer )
{
for ( int i = kMaxPowerUps - 1 ; i > = 0 ; i - - )
{
2019-10-21 19:46:41 +00:00
pPlayer - > pwUpTime [ i ] = 0 ;
2019-09-19 22:42:45 +00:00
}
}
void powerupInit ( void )
{
}
int packItemToPowerup ( int nPack )
{
int nPowerUp = - 1 ;
2019-10-19 19:11:39 +00:00
switch ( nPack ) {
case 0 :
break ;
case 1 :
nPowerUp = kPwUpDivingSuit ;
break ;
case 2 :
nPowerUp = kPwUpCrystalBall ;
break ;
case 3 :
nPowerUp = kPwUpBeastVision ;
break ;
case 4 :
nPowerUp = kPwUpJumpBoots ;
break ;
default :
2020-10-11 10:22:36 +00:00
I_Error ( " Unhandled pack item %d " , nPack ) ;
2019-10-19 19:11:39 +00:00
break ;
2019-09-19 22:42:45 +00:00
}
return nPowerUp ;
}
int powerupToPackItem ( int nPowerUp )
{
2019-10-19 19:11:39 +00:00
switch ( nPowerUp ) {
case kPwUpDivingSuit :
return 1 ;
case kPwUpCrystalBall :
return 2 ;
case kPwUpBeastVision :
return 3 ;
case kPwUpJumpBoots :
return 4 ;
2019-09-19 22:42:45 +00:00
}
return - 1 ;
}
char packAddItem ( PLAYER * pPlayer , unsigned int nPack )
{
if ( nPack < = 4 )
{
2019-10-21 19:46:41 +00:00
if ( pPlayer - > packSlots [ nPack ] . curAmount > = 100 )
2019-09-19 22:42:45 +00:00
return 0 ;
2019-10-21 19:46:41 +00:00
pPlayer - > packSlots [ nPack ] . curAmount = 100 ;
2019-09-19 22:42:45 +00:00
int nPowerUp = packItemToPowerup ( nPack ) ;
if ( nPowerUp > = 0 )
2019-10-21 19:46:41 +00:00
pPlayer - > pwUpTime [ nPowerUp ] = gPowerUpInfo [ nPowerUp ] . bonusTime ;
if ( pPlayer - > packItemId = = - 1 )
pPlayer - > packItemId = nPack ;
if ( ! pPlayer - > packSlots [ pPlayer - > packItemId ] . curAmount )
pPlayer - > packItemId = nPack ;
2019-09-19 22:42:45 +00:00
}
else
2020-10-11 10:22:36 +00:00
I_Error ( " Unhandled pack item %d " , nPack ) ;
2019-09-19 22:42:45 +00:00
return 1 ;
}
int packCheckItem ( PLAYER * pPlayer , int nPack )
{
2019-10-21 19:46:41 +00:00
return pPlayer - > packSlots [ nPack ] . curAmount ;
2019-09-19 22:42:45 +00:00
}
char packItemActive ( PLAYER * pPlayer , int nPack )
{
2019-10-21 19:46:41 +00:00
return pPlayer - > packSlots [ nPack ] . isActive ;
2019-09-19 22:42:45 +00:00
}
void packUseItem ( PLAYER * pPlayer , int nPack )
{
char v4 = 0 ;
int nPowerUp = - 1 ;
2019-10-21 19:46:41 +00:00
if ( pPlayer - > packSlots [ nPack ] . curAmount > 0 )
2019-09-19 22:42:45 +00:00
{
2020-09-11 17:58:16 +00:00
pPlayer - > packItemId = nPack ;
2019-09-19 22:42:45 +00:00
switch ( nPack )
{
case 0 :
{
XSPRITE * pXSprite = pPlayer - > pXSprite ;
unsigned int health = pXSprite - > health > > 4 ;
if ( health < 100 )
{
2019-10-21 19:46:41 +00:00
int heal = ClipHigh ( 100 - health , pPlayer - > packSlots [ 0 ] . curAmount ) ;
2019-09-19 22:42:45 +00:00
actHealDude ( pXSprite , heal , 100 ) ;
2019-10-21 19:46:41 +00:00
pPlayer - > packSlots [ 0 ] . curAmount - = heal ;
2019-09-19 22:42:45 +00:00
}
break ;
}
case 1 :
v4 = 1 ;
2019-10-19 19:11:39 +00:00
nPowerUp = kPwUpDivingSuit ;
2019-09-19 22:42:45 +00:00
break ;
case 2 :
v4 = 1 ;
2019-10-19 19:11:39 +00:00
nPowerUp = kPwUpCrystalBall ;
2019-09-19 22:42:45 +00:00
break ;
case 3 :
v4 = 1 ;
2019-10-19 19:11:39 +00:00
nPowerUp = kPwUpBeastVision ;
2019-09-19 22:42:45 +00:00
break ;
case 4 :
v4 = 1 ;
2019-10-19 19:11:39 +00:00
nPowerUp = kPwUpJumpBoots ;
2019-09-19 22:42:45 +00:00
break ;
default :
2020-10-11 10:22:36 +00:00
I_Error ( " Unhandled pack item %d " , nPack ) ;
2019-09-19 22:42:45 +00:00
return ;
}
}
2019-10-21 19:46:41 +00:00
pPlayer - > packItemTime = 0 ;
2019-09-19 22:42:45 +00:00
if ( v4 )
2019-10-21 19:46:41 +00:00
powerupSetState ( pPlayer , nPowerUp , pPlayer - > packSlots [ nPack ] . isActive ) ;
2019-09-19 22:42:45 +00:00
}
void packPrevItem ( PLAYER * pPlayer )
{
2019-10-21 19:46:41 +00:00
if ( pPlayer - > packItemTime > 0 )
2019-09-19 22:42:45 +00:00
{
2020-08-27 20:29:45 +00:00
for ( int i = 0 ; i < 2 ; i + + )
2019-09-19 22:42:45 +00:00
{
2020-08-27 20:29:45 +00:00
for ( int nPrev = pPlayer - > packItemId - 1 ; nPrev > = 0 ; nPrev - - )
2019-09-19 22:42:45 +00:00
{
2020-08-27 20:29:45 +00:00
if ( pPlayer - > packSlots [ nPrev ] . curAmount )
{
pPlayer - > packItemId = nPrev ;
pPlayer - > packItemTime = 600 ;
return ;
}
2019-09-19 22:42:45 +00:00
}
2020-08-27 20:29:45 +00:00
pPlayer - > packItemId = 4 ;
if ( pPlayer - > packSlots [ 4 ] . curAmount ) break ;
2019-09-19 22:42:45 +00:00
}
}
2020-08-27 20:29:45 +00:00
2019-10-21 19:46:41 +00:00
pPlayer - > packItemTime = 600 ;
2019-09-19 22:42:45 +00:00
}
2020-08-27 20:29:45 +00:00
void packNextItem ( PLAYER * pPlayer )
2019-09-19 22:42:45 +00:00
{
2019-10-21 19:46:41 +00:00
if ( pPlayer - > packItemTime > 0 )
2019-09-19 22:42:45 +00:00
{
2020-08-27 20:29:45 +00:00
for ( int i = 0 ; i < 2 ; i + + )
2019-09-19 22:42:45 +00:00
{
2020-08-27 20:29:45 +00:00
for ( int nNext = pPlayer - > packItemId + 1 ; nNext < 5 ; nNext + + )
2019-09-19 22:42:45 +00:00
{
2020-08-27 20:29:45 +00:00
if ( pPlayer - > packSlots [ nNext ] . curAmount )
{
pPlayer - > packItemId = nNext ;
pPlayer - > packItemTime = 600 ;
return ;
}
2019-09-19 22:42:45 +00:00
}
2020-08-27 20:29:45 +00:00
pPlayer - > packItemId = 0 ;
if ( pPlayer - > packSlots [ 0 ] . curAmount ) break ;
2019-09-19 22:42:45 +00:00
}
}
2019-10-21 19:46:41 +00:00
pPlayer - > packItemTime = 600 ;
2019-09-19 22:42:45 +00:00
}
char playerSeqPlaying ( PLAYER * pPlayer , int nSeq )
{
int nCurSeq = seqGetID ( 3 , pPlayer - > pSprite - > extra ) ;
if ( pPlayer - > pDudeInfo - > seqStartID + nSeq = = nCurSeq & & seqGetStatus ( 3 , pPlayer - > pSprite - > extra ) > = 0 )
return 1 ;
return 0 ;
}
void playerSetRace ( PLAYER * pPlayer , int nLifeMode )
{
2020-10-11 10:38:17 +00:00
assert ( nLifeMode > = kModeHuman & & nLifeMode < = kModeHumanGrown ) ;
2019-09-19 22:42:45 +00:00
DUDEINFO * pDudeInfo = pPlayer - > pDudeInfo ;
* pDudeInfo = gPlayerTemplate [ nLifeMode ] ;
2019-10-21 19:46:41 +00:00
pPlayer - > lifeMode = nLifeMode ;
2019-09-19 22:42:45 +00:00
// By NoOne: don't forget to change clipdist for grow and shrink modes
pPlayer - > pSprite - > clipdist = pDudeInfo - > clipdist ;
for ( int i = 0 ; i < 7 ; i + + )
2021-01-04 11:36:54 +00:00
pDudeInfo - > at70 [ i ] = MulScale ( Handicap [ gSkill ] , pDudeInfo - > startDamage [ i ] , 8 ) ;
2019-09-19 22:42:45 +00:00
}
2020-09-02 22:29:17 +00:00
void playerSetGodMode ( PLAYER * pPlayer , bool bGodMode )
2019-09-19 22:42:45 +00:00
{
2019-10-21 19:46:41 +00:00
pPlayer - > godMode = bGodMode ;
2019-09-19 22:42:45 +00:00
}
void playerResetInertia ( PLAYER * pPlayer )
{
2020-01-01 20:53:29 +00:00
POSTURE * pPosture = & pPlayer - > pPosture [ pPlayer - > lifeMode ] [ pPlayer - > posture ] ;
2019-10-21 19:46:41 +00:00
pPlayer - > zView = pPlayer - > pSprite - > z - pPosture - > eyeAboveZ ;
pPlayer - > zWeapon = pPlayer - > pSprite - > z - pPosture - > weaponAboveZ ;
viewBackupView ( pPlayer - > nPlayer ) ;
2019-09-19 22:42:45 +00:00
}
2019-09-07 16:39:26 +00:00
void playerCorrectInertia ( PLAYER * pPlayer , vec3_t const * oldpos )
{
2019-10-21 19:46:41 +00:00
pPlayer - > zView + = pPlayer - > pSprite - > z - oldpos - > z ;
pPlayer - > zWeapon + = pPlayer - > pSprite - > z - oldpos - > z ;
viewCorrectViewOffsets ( pPlayer - > nPlayer , oldpos ) ;
2019-09-07 16:39:26 +00:00
}
2019-09-19 22:42:45 +00:00
void playerResetPowerUps ( PLAYER * pPlayer )
{
2019-10-19 19:11:39 +00:00
for ( int i = 0 ; i < kMaxPowerUps ; i + + ) {
if ( ! VanillaMode ( ) & & ( i = = kPwUpJumpBoots | | i = = kPwUpDivingSuit | | i = = kPwUpCrystalBall | | i = = kPwUpBeastVision ) )
2019-09-19 22:42:45 +00:00
continue ;
2019-10-21 19:46:41 +00:00
pPlayer - > pwUpTime [ i ] = 0 ;
2019-09-19 22:42:45 +00:00
}
}
2020-02-07 19:47:43 +00:00
void playerResetPosture ( PLAYER * pPlayer ) {
memcpy ( pPlayer - > pPosture , gPostureDefaults , sizeof ( gPostureDefaults ) ) ;
}
2020-02-10 05:23:49 +00:00
void playerStart ( int nPlayer , int bNewLevel )
2019-09-19 22:42:45 +00:00
{
PLAYER * pPlayer = & gPlayer [ nPlayer ] ;
2020-08-26 15:12:48 +00:00
InputPacket * pInput = & pPlayer - > input ;
2019-09-19 22:42:45 +00:00
ZONE * pStartZone = NULL ;
2020-04-04 19:48:23 +00:00
2019-09-19 22:42:45 +00:00
// normal start position
if ( gGameOptions . nGameType < = 1 )
pStartZone = & gStartZone [ nPlayer ] ;
2020-01-26 11:19:01 +00:00
# ifdef NOONE_EXTENSIONS
// let's check if there is positions of teams is specified
2019-09-19 22:42:45 +00:00
// if no, pick position randomly, just like it works in vanilla.
2019-11-08 19:57:01 +00:00
else if ( gModernMap & & gGameOptions . nGameType = = 3 & & gTeamsSpawnUsed = = true ) {
2019-09-19 22:42:45 +00:00
int maxRetries = 5 ;
while ( maxRetries - - > 0 ) {
2019-10-21 19:46:41 +00:00
if ( pPlayer - > teamId = = 0 ) pStartZone = & gStartZoneTeam1 [ Random ( 3 ) ] ;
2019-09-19 22:42:45 +00:00
else pStartZone = & gStartZoneTeam2 [ Random ( 3 ) ] ;
if ( maxRetries ! = 0 ) {
// check if there is no spawned player in selected zone
2020-10-15 14:48:32 +00:00
int i ;
SectIterator it ( pStartZone - > sectnum ) ;
while ( ( i = it . NextIndex ( ) ) > = 0 )
{
2019-09-19 22:42:45 +00:00
spritetype * pSprite = & sprite [ i ] ;
if ( pStartZone - > x = = pSprite - > x & & pStartZone - > y = = pSprite - > y & & IsPlayerSprite ( pSprite ) ) {
pStartZone = NULL ;
break ;
}
}
}
if ( pStartZone ! = NULL )
break ;
}
2020-01-26 11:19:01 +00:00
}
# endif
else {
2019-09-19 22:42:45 +00:00
pStartZone = & gStartZone [ Random ( 8 ) ] ;
}
spritetype * pSprite = actSpawnSprite ( pStartZone - > sectnum , pStartZone - > x , pStartZone - > y , pStartZone - > z , 6 , 1 ) ;
2020-10-11 10:38:17 +00:00
assert ( pSprite - > extra > 0 & & pSprite - > extra < kMaxXSprites ) ;
2019-09-19 22:42:45 +00:00
XSPRITE * pXSprite = & xsprite [ pSprite - > extra ] ;
pPlayer - > pSprite = pSprite ;
pPlayer - > pXSprite = pXSprite ;
2019-10-21 19:46:41 +00:00
pPlayer - > nSprite = pSprite - > index ;
2019-09-19 22:42:45 +00:00
DUDEINFO * pDudeInfo = & dudeInfo [ kDudePlayer1 + nPlayer - kDudeBase ] ;
pPlayer - > pDudeInfo = pDudeInfo ;
playerSetRace ( pPlayer , kModeHuman ) ;
2020-01-01 20:53:29 +00:00
playerResetPosture ( pPlayer ) ;
2019-09-19 22:42:45 +00:00
seqSpawn ( pDudeInfo - > seqStartID , 3 , pSprite - > extra , - 1 ) ;
if ( pPlayer = = gMe )
2020-09-06 11:39:57 +00:00
show2dsprite . Set ( pSprite - > index ) ;
2019-09-19 22:42:45 +00:00
int top , bottom ;
GetSpriteExtents ( pSprite , & top , & bottom ) ;
pSprite - > z - = bottom - pSprite - > z ;
2019-10-21 19:46:41 +00:00
pSprite - > pal = 11 + ( pPlayer - > teamId & 3 ) ;
2020-11-30 08:57:21 +00:00
pSprite - > ang = pStartZone - > ang ;
2021-01-10 07:17:29 +00:00
pPlayer - > angle . ang = buildang ( pSprite - > ang ) ;
2019-09-19 22:42:45 +00:00
pSprite - > type = kDudePlayer1 + nPlayer ;
pSprite - > clipdist = pDudeInfo - > clipdist ;
2019-09-30 07:18:01 +00:00
pSprite - > flags = 15 ;
2019-09-19 22:42:45 +00:00
pXSprite - > burnTime = 0 ;
pXSprite - > burnSource = - 1 ;
pPlayer - > pXSprite - > health = pDudeInfo - > startHealth < < 4 ;
pPlayer - > pSprite - > cstat & = ( unsigned short ) ~ 32768 ;
2019-10-21 19:46:41 +00:00
pPlayer - > bloodlust = 0 ;
2020-10-07 06:16:58 +00:00
pPlayer - > horizon . horiz = pPlayer - > horizon . horizoff = q16horiz ( 0 ) ;
2019-10-21 19:46:41 +00:00
pPlayer - > slope = 0 ;
pPlayer - > fraggerId = - 1 ;
pPlayer - > underwaterTime = 1200 ;
pPlayer - > bubbleTime = 0 ;
pPlayer - > restTime = 0 ;
pPlayer - > kickPower = 0 ;
pPlayer - > laughCount = 0 ;
2020-10-07 20:55:54 +00:00
pPlayer - > angle . spin = buildlook ( 0 ) ;
2019-10-21 19:46:41 +00:00
pPlayer - > posture = 0 ;
2019-09-19 22:42:45 +00:00
pPlayer - > voodooTarget = - 1 ;
2019-10-21 19:46:41 +00:00
pPlayer - > voodooTargets = 0 ;
pPlayer - > voodooVar1 = 0 ;
pPlayer - > vodooVar2 = 0 ;
2019-09-19 22:42:45 +00:00
playerResetInertia ( pPlayer ) ;
2019-10-21 19:46:41 +00:00
pPlayer - > zWeaponVel = 0 ;
pPlayer - > relAim . dx = 0x4000 ;
pPlayer - > relAim . dy = 0 ;
pPlayer - > relAim . dz = 0 ;
pPlayer - > aimTarget = - 1 ;
pPlayer - > zViewVel = pPlayer - > zWeaponVel ;
2020-02-10 05:23:49 +00:00
if ( ! ( gGameOptions . nGameType = = 1 & & gGameOptions . bKeepKeysOnRespawn & & ! bNewLevel ) )
2019-09-20 10:11:07 +00:00
for ( int i = 0 ; i < 8 ; i + + )
2019-10-21 19:46:41 +00:00
pPlayer - > hasKey [ i ] = gGameOptions . nGameType > = 2 ;
pPlayer - > hasFlag = 0 ;
2019-09-19 22:42:45 +00:00
for ( int i = 0 ; i < 8 ; i + + )
2019-10-21 19:46:41 +00:00
pPlayer - > used2 [ i ] = - 1 ;
2019-09-19 22:42:45 +00:00
for ( int i = 0 ; i < 7 ; i + + )
2019-10-21 19:46:41 +00:00
pPlayer - > damageControl [ i ] = 0 ;
if ( pPlayer - > godMode )
2019-09-19 22:42:45 +00:00
playerSetGodMode ( pPlayer , 1 ) ;
gInfiniteAmmo = 0 ;
gFullMap = 0 ;
2019-10-21 19:46:41 +00:00
pPlayer - > throwPower = 0 ;
pPlayer - > deathTime = 0 ;
pPlayer - > nextWeapon = 0 ;
2019-09-19 22:42:45 +00:00
xvel [ pSprite - > index ] = yvel [ pSprite - > index ] = zvel [ pSprite - > index ] = 0 ;
2020-10-08 03:47:30 +00:00
pInput - > avel = 0 ;
2020-08-28 20:51:05 +00:00
pInput - > actions = 0 ;
2020-08-26 14:54:13 +00:00
pInput - > fvel = 0 ;
pInput - > svel = 0 ;
2020-10-07 07:22:07 +00:00
pInput - > horz = 0 ;
2019-10-21 19:46:41 +00:00
pPlayer - > flickerEffect = 0 ;
pPlayer - > quakeEffect = 0 ;
pPlayer - > tiltEffect = 0 ;
pPlayer - > visibility = 0 ;
pPlayer - > painEffect = 0 ;
pPlayer - > blindEffect = 0 ;
pPlayer - > chokeEffect = 0 ;
pPlayer - > handTime = 0 ;
pPlayer - > weaponTimer = 0 ;
pPlayer - > weaponState = 0 ;
pPlayer - > weaponQav = - 1 ;
2020-01-26 11:19:01 +00:00
# ifdef NOONE_EXTENSIONS
2020-02-07 19:47:43 +00:00
playerQavSceneReset ( pPlayer ) ; // reset qav scene
2020-04-04 19:48:23 +00:00
2020-05-05 18:50:14 +00:00
// assign or update player's sprite index for conditions
if ( gModernMap ) {
2020-04-04 19:48:23 +00:00
2020-10-15 15:15:45 +00:00
int nSprite ;
StatIterator it ( kStatModernPlayerLinker ) ;
while ( ( nSprite = it . NextIndex ( ) ) > = 0 )
{
2020-04-04 19:48:23 +00:00
XSPRITE * pXCtrl = & xsprite [ sprite [ nSprite ] . extra ] ;
2020-05-05 18:50:14 +00:00
if ( pXCtrl - > data1 = = pPlayer - > nPlayer + 1 ) {
int nSpriteOld = pXCtrl - > sysData1 ;
trPlayerCtrlLink ( pXCtrl , pPlayer , ( nSpriteOld < 0 ) ? true : false ) ;
if ( nSpriteOld > 0 )
condUpdateObjectIndex ( OBJ_SPRITE , nSpriteOld , pXCtrl - > sysData1 ) ;
}
2020-04-04 19:48:23 +00:00
}
2020-05-05 18:50:14 +00:00
2020-04-04 19:48:23 +00:00
}
2020-05-05 18:50:14 +00:00
2020-01-26 11:19:01 +00:00
# endif
2019-10-21 19:46:41 +00:00
pPlayer - > hand = 0 ;
2019-09-19 22:42:45 +00:00
pPlayer - > nWaterPal = 0 ;
playerResetPowerUps ( pPlayer ) ;
if ( pPlayer = = gMe )
{
viewInitializePrediction ( ) ;
}
if ( IsUnderwaterSector ( pSprite - > sectnum ) )
{
2019-10-21 19:46:41 +00:00
pPlayer - > posture = 1 ;
2019-10-19 19:11:39 +00:00
pPlayer - > pXSprite - > medium = kMediumWater ;
2019-09-19 22:42:45 +00:00
}
}
void playerReset ( PLAYER * pPlayer )
{
static int dword_136400 [ ] = {
3 , 4 , 2 , 8 , 9 , 10 , 7 , 1 , 1 , 1 , 1 , 1 , 1 , 1
} ;
static int dword_136438 [ ] = {
3 , 4 , 2 , 8 , 9 , 10 , 7 , 1 , 1 , 1 , 1 , 1 , 1 , 1
} ;
2020-10-11 10:38:17 +00:00
assert ( pPlayer ! = NULL ) ;
2019-09-19 22:42:45 +00:00
for ( int i = 0 ; i < 14 ; i + + )
{
2019-10-21 19:46:41 +00:00
pPlayer - > hasWeapon [ i ] = gInfiniteAmmo ;
pPlayer - > weaponMode [ i ] = 0 ;
2019-09-19 22:42:45 +00:00
}
2019-10-21 19:46:41 +00:00
pPlayer - > hasWeapon [ 1 ] = 1 ;
pPlayer - > curWeapon = 0 ;
pPlayer - > qavCallback = - 1 ;
2020-08-26 14:48:33 +00:00
pPlayer - > newWeapon = 1 ;
2019-09-19 22:42:45 +00:00
for ( int i = 0 ; i < 14 ; i + + )
{
2019-10-21 19:46:41 +00:00
pPlayer - > weaponOrder [ 0 ] [ i ] = dword_136400 [ i ] ;
pPlayer - > weaponOrder [ 1 ] [ i ] = dword_136438 [ i ] ;
2019-09-19 22:42:45 +00:00
}
for ( int i = 0 ; i < 12 ; i + + )
{
if ( gInfiniteAmmo )
2019-10-25 20:53:41 +00:00
pPlayer - > ammoCount [ i ] = gAmmoInfo [ i ] . max ;
2019-09-19 22:42:45 +00:00
else
2019-10-25 20:53:41 +00:00
pPlayer - > ammoCount [ i ] = 0 ;
2019-09-19 22:42:45 +00:00
}
for ( int i = 0 ; i < 3 ; i + + )
2019-10-21 19:46:41 +00:00
pPlayer - > armor [ i ] = 0 ;
pPlayer - > weaponTimer = 0 ;
pPlayer - > weaponState = 0 ;
pPlayer - > weaponQav = - 1 ;
pPlayer - > qavLoop = 0 ;
pPlayer - > packItemId = - 1 ;
2019-11-08 19:57:01 +00:00
for ( int i = 0 ; i < 5 ; i + + ) {
2019-10-21 19:46:41 +00:00
pPlayer - > packSlots [ i ] . isActive = 0 ;
pPlayer - > packSlots [ i ] . curAmount = 0 ;
2019-09-19 22:42:45 +00:00
}
2020-02-07 19:47:43 +00:00
# ifdef NOONE_EXTENSIONS
playerQavSceneReset ( pPlayer ) ;
# endif
2020-01-01 20:53:29 +00:00
// reset posture (mainly required for resetting movement speed and jump height)
playerResetPosture ( pPlayer ) ;
2020-01-26 11:19:01 +00:00
2019-11-08 19:57:01 +00:00
}
2020-11-22 12:16:58 +00:00
int team_score [ 8 ] ;
int team_ticker [ 8 ] ;
2019-09-19 22:42:45 +00:00
void playerInit ( int nPlayer , unsigned int a2 )
{
PLAYER * pPlayer = & gPlayer [ nPlayer ] ;
if ( ! ( a2 & 1 ) )
memset ( pPlayer , 0 , sizeof ( PLAYER ) ) ;
2019-10-21 19:46:41 +00:00
pPlayer - > nPlayer = nPlayer ;
pPlayer - > teamId = nPlayer ;
2019-09-19 22:42:45 +00:00
if ( gGameOptions . nGameType = = 3 )
2019-10-21 19:46:41 +00:00
pPlayer - > teamId = nPlayer & 1 ;
pPlayer - > fragCount = 0 ;
2020-11-22 12:16:58 +00:00
memset ( team_score , 0 , sizeof ( team_score ) ) ;
memset ( team_ticker , 0 , sizeof ( team_ticker ) ) ;
2019-10-21 19:46:41 +00:00
memset ( pPlayer - > fragInfo , 0 , sizeof ( pPlayer - > fragInfo ) ) ;
2020-01-01 20:53:29 +00:00
2019-09-19 22:42:45 +00:00
if ( ! ( a2 & 1 ) )
playerReset ( pPlayer ) ;
}
2020-11-21 19:10:45 +00:00
char findDroppedLeech ( PLAYER * a1 , spritetype * a2 )
2019-09-19 22:42:45 +00:00
{
2020-10-15 15:15:45 +00:00
int nSprite ;
StatIterator it ( kStatThing ) ;
while ( ( nSprite = it . NextIndex ( ) ) > = 0 )
2019-09-19 22:42:45 +00:00
{
if ( a2 & & a2 - > index = = nSprite )
continue ;
spritetype * pSprite = & sprite [ nSprite ] ;
2020-12-02 18:56:32 +00:00
if ( pSprite - > type = = kThingDroppedLifeLeech & & pSprite - > owner = = a1 - > nSprite )
2019-09-19 22:42:45 +00:00
return 1 ;
}
return 0 ;
}
2019-10-11 21:59:39 +00:00
char PickupItem ( PLAYER * pPlayer , spritetype * pItem ) {
spritetype * pSprite = pPlayer - > pSprite ; XSPRITE * pXSprite = pPlayer - > pXSprite ;
char buffer [ 80 ] ; int pickupSnd = 775 ; int nType = pItem - > type - kItemBase ;
switch ( pItem - > type ) {
case kItemShadowCloak :
2020-01-26 11:19:01 +00:00
# ifdef NOONE_EXTENSIONS
2019-10-13 22:29:19 +00:00
if ( isGrown ( pPlayer - > pSprite ) | | ! powerupActivate ( pPlayer , nType ) ) return false ;
2020-01-26 11:19:01 +00:00
# else
if ( ! powerupActivate ( pPlayer , nType ) ) return false ;
# endif
2019-10-13 22:29:19 +00:00
break ;
2020-01-26 11:19:01 +00:00
# ifdef NOONE_EXTENSIONS
2019-10-11 21:59:39 +00:00
case kItemShroomShrink :
case kItemShroomGrow :
2020-01-26 11:19:01 +00:00
2019-10-11 21:59:39 +00:00
if ( gModernMap ) {
switch ( pItem - > type ) {
case kItemShroomShrink :
if ( isShrinked ( pSprite ) ) return false ;
break ;
case kItemShroomGrow :
if ( isGrown ( pSprite ) ) return false ;
break ;
}
2019-10-13 22:29:19 +00:00
2019-10-11 21:59:39 +00:00
powerupActivate ( pPlayer , nType ) ;
}
2020-01-26 11:19:01 +00:00
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 kItemFlagABase :
case kItemFlagBBase : {
if ( gGameOptions . nGameType ! = 3 | | pItem - > extra < = 0 ) return 0 ;
XSPRITE * pXItem = & xsprite [ pItem - > extra ] ;
if ( pItem - > type = = kItemFlagABase ) {
2019-10-21 19:46:41 +00:00
if ( pPlayer - > teamId = = 1 ) {
if ( ( pPlayer - > hasFlag & 1 ) = = 0 & & pXItem - > state ) {
pPlayer - > hasFlag | = 1 ;
pPlayer - > used2 [ 0 ] = pItem - > index ;
2020-01-11 21:07:05 +00:00
trTriggerSprite ( pItem - > index , pXItem , kCmdOff ) ;
2020-11-22 12:28:20 +00:00
sprintf ( buffer , " %s stole Blue Flag " , PlayerName ( pPlayer - > nPlayer ) ) ;
2019-09-19 22:42:45 +00:00
sndStartSample ( 8007 , 255 , 2 , 0 ) ;
viewSetMessage ( buffer ) ;
}
}
2019-10-11 21:59:39 +00:00
2019-10-21 19:46:41 +00:00
if ( pPlayer - > teamId = = 0 ) {
2019-10-11 21:59:39 +00:00
2019-10-21 19:46:41 +00:00
if ( ( pPlayer - > hasFlag & 1 ) ! = 0 & & ! pXItem - > state ) {
pPlayer - > hasFlag & = ~ 1 ;
pPlayer - > used2 [ 0 ] = - 1 ;
2020-01-11 21:07:05 +00:00
trTriggerSprite ( pItem - > index , pXItem , kCmdOn ) ;
2020-11-22 12:28:20 +00:00
sprintf ( buffer , " %s returned Blue Flag " , PlayerName ( pPlayer - > nPlayer ) ) ;
2019-09-19 22:42:45 +00:00
sndStartSample ( 8003 , 255 , 2 , 0 ) ;
viewSetMessage ( buffer ) ;
}
2019-10-11 21:59:39 +00:00
2019-10-21 19:46:41 +00:00
if ( ( pPlayer - > hasFlag & 2 ) ! = 0 & & pXItem - > state ) {
pPlayer - > hasFlag & = ~ 2 ;
pPlayer - > used2 [ 1 ] = - 1 ;
2020-11-22 12:16:58 +00:00
team_score [ pPlayer - > teamId ] + = 10 ;
team_ticker [ pPlayer - > teamId ] + = 240 ;
2020-01-11 21:07:05 +00:00
evSend ( 0 , 0 , 81 , kCmdOn ) ;
2020-11-22 12:28:20 +00:00
sprintf ( buffer , " %s captured Red Flag! " , PlayerName ( pPlayer - > nPlayer ) ) ;
2019-09-19 22:42:45 +00:00
sndStartSample ( 8001 , 255 , 2 , 0 ) ;
viewSetMessage ( buffer ) ;
}
}
2019-10-11 21:59:39 +00:00
2019-09-19 22:42:45 +00:00
}
2019-10-11 21:59:39 +00:00
else if ( pItem - > type = = kItemFlagBBase ) {
2019-10-21 19:46:41 +00:00
if ( pPlayer - > teamId = = 0 ) {
if ( ( pPlayer - > hasFlag & 2 ) = = 0 & & pXItem - > state ) {
pPlayer - > hasFlag | = 2 ;
pPlayer - > used2 [ 1 ] = pItem - > index ;
2020-01-11 21:07:05 +00:00
trTriggerSprite ( pItem - > index , pXItem , kCmdOff ) ;
2020-11-22 12:28:20 +00:00
sprintf ( buffer , " %s stole Red Flag " , PlayerName ( pPlayer - > nPlayer ) ) ;
2019-09-19 22:42:45 +00:00
sndStartSample ( 8006 , 255 , 2 , 0 ) ;
viewSetMessage ( buffer ) ;
}
}
2019-10-11 21:59:39 +00:00
2019-10-21 19:46:41 +00:00
if ( pPlayer - > teamId = = 1 ) {
if ( ( pPlayer - > hasFlag & 2 ) ! = 0 & & ! pXItem - > state )
2019-09-19 22:42:45 +00:00
{
2019-10-21 19:46:41 +00:00
pPlayer - > hasFlag & = ~ 2 ;
pPlayer - > used2 [ 1 ] = - 1 ;
2020-01-11 21:07:05 +00:00
trTriggerSprite ( pItem - > index , pXItem , kCmdOn ) ;
2020-11-22 12:28:20 +00:00
sprintf ( buffer , " %s returned Red Flag " , PlayerName ( pPlayer - > nPlayer ) ) ;
2019-09-19 22:42:45 +00:00
sndStartSample ( 8002 , 255 , 2 , 0 ) ;
viewSetMessage ( buffer ) ;
}
2019-10-21 19:46:41 +00:00
if ( ( pPlayer - > hasFlag & 1 ) ! = 0 & & pXItem - > state )
2019-09-19 22:42:45 +00:00
{
2019-10-21 19:46:41 +00:00
pPlayer - > hasFlag & = ~ 1 ;
pPlayer - > used2 [ 0 ] = - 1 ;
2020-11-22 12:16:58 +00:00
team_score [ pPlayer - > teamId ] + = 10 ;
team_ticker [ pPlayer - > teamId ] + = 240 ;
2020-01-11 21:07:05 +00:00
evSend ( 0 , 0 , 80 , kCmdOn ) ;
2020-11-22 12:28:20 +00:00
sprintf ( buffer , " %s captured Blue Flag! " , PlayerName ( pPlayer - > nPlayer ) ) ;
2019-09-19 22:42:45 +00:00
sndStartSample ( 8000 , 255 , 2 , 0 ) ;
viewSetMessage ( buffer ) ;
}
}
}
}
return 0 ;
2019-10-11 21:59:39 +00:00
case kItemFlagA :
if ( gGameOptions . nGameType ! = 3 ) return 0 ;
evKill ( pItem - > index , 3 , kCallbackReturnFlag ) ;
2019-10-21 19:46:41 +00:00
pPlayer - > hasFlag | = 1 ;
pPlayer - > used2 [ 0 ] = pItem - > index ;
2019-10-11 21:59:39 +00:00
gBlueFlagDropped = false ;
break ;
case kItemFlagB :
if ( gGameOptions . nGameType ! = 3 ) return 0 ;
evKill ( pItem - > index , 3 , kCallbackReturnFlag ) ;
2019-10-21 19:46:41 +00:00
pPlayer - > hasFlag | = 2 ;
pPlayer - > used2 [ 1 ] = pItem - > index ;
2019-10-11 21:59:39 +00:00
gRedFlagDropped = false ;
break ;
case kItemArmorBasic :
case kItemArmorBody :
case kItemArmorFire :
case kItemArmorSpirit :
case kItemArmorSuper : {
ARMORDATA * pArmorData = & armorData [ pItem - > type - kItemArmorBasic ] ; bool pickedUp = false ;
2020-11-21 22:40:08 +00:00
if ( pPlayer - > armor [ 1 ] < pArmorData - > armor1max ) {
pPlayer - > armor [ 1 ] = ClipHigh ( pPlayer - > armor [ 1 ] + pArmorData - > armor1 , pArmorData - > armor1max ) ;
2019-10-11 21:59:39 +00:00
pickedUp = true ;
}
2020-11-21 22:40:08 +00:00
if ( pPlayer - > armor [ 0 ] < pArmorData - > armor0max ) {
pPlayer - > armor [ 0 ] = ClipHigh ( pPlayer - > armor [ 0 ] + pArmorData - > armor0 , pArmorData - > armor0max ) ;
2019-10-11 21:59:39 +00:00
pickedUp = true ;
}
2020-11-21 22:40:08 +00:00
if ( pPlayer - > armor [ 2 ] < pArmorData - > armor2max ) {
pPlayer - > armor [ 2 ] = ClipHigh ( pPlayer - > armor [ 2 ] + pArmorData - > armor2 , pArmorData - > armor2max ) ;
2019-10-11 21:59:39 +00:00
pickedUp = true ;
}
if ( ! pickedUp ) return 0 ;
pickupSnd = 779 ;
break ;
2019-09-19 22:42:45 +00:00
}
2019-10-11 21:59:39 +00:00
case kItemCrystalBall :
2019-10-21 19:46:41 +00:00
if ( gGameOptions . nGameType = = 0 | | ! packAddItem ( pPlayer , gItemData [ nType ] . packSlot ) ) return 0 ;
2019-10-11 21:59:39 +00:00
break ;
case kItemKeySkull :
case kItemKeyEye :
case kItemKeyFire :
case kItemKeyDagger :
case kItemKeySpider :
case kItemKeyMoon :
case kItemKeyKey7 :
2019-10-21 19:46:41 +00:00
if ( pPlayer - > hasKey [ pItem - > type - 99 ] ) return 0 ;
pPlayer - > hasKey [ pItem - > type - 99 ] = 1 ;
2019-10-11 21:59:39 +00:00
pickupSnd = 781 ;
break ;
case kItemHealthMedPouch :
case kItemHealthLifeEssense :
case kItemHealthLifeSeed :
case kItemHealthRedPotion : {
2019-10-19 19:11:39 +00:00
int addPower = gPowerUpInfo [ nType ] . bonusTime ;
2020-01-26 11:19:01 +00:00
# ifdef NOONE_EXTENSIONS
// allow custom amount for item
2020-02-07 19:47:43 +00:00
if ( gModernMap & & sprite [ pItem - > index ] . extra > = 0 & & xsprite [ sprite [ pItem - > index ] . extra ] . data1 > 0 )
addPower = xsprite [ sprite [ pItem - > index ] . extra ] . data1 ;
2020-01-26 11:19:01 +00:00
# endif
2019-10-11 21:59:39 +00:00
2019-10-19 19:11:39 +00:00
if ( ! actHealDude ( pXSprite , addPower , gPowerUpInfo [ nType ] . maxTime ) ) return 0 ;
2019-10-11 21:59:39 +00:00
return 1 ;
2019-09-19 22:42:45 +00:00
}
2019-10-11 21:59:39 +00:00
case kItemHealthDoctorBag :
case kItemJumpBoots :
case kItemDivingSuit :
case kItemBeastVision :
2019-10-21 19:46:41 +00:00
if ( ! packAddItem ( pPlayer , gItemData [ nType ] . packSlot ) ) return 0 ;
2019-10-11 21:59:39 +00:00
break ;
default :
if ( ! powerupActivate ( pPlayer , nType ) ) return 0 ;
return 1 ;
2019-09-19 22:42:45 +00:00
}
2019-10-11 21:59:39 +00:00
2019-09-19 22:42:45 +00:00
sfxPlay3DSound ( pSprite - > x , pSprite - > y , pSprite - > z , pickupSnd , pSprite - > sectnum ) ;
return 1 ;
}
2019-10-11 21:59:39 +00:00
char PickupAmmo ( PLAYER * pPlayer , spritetype * pAmmo ) {
2020-02-11 22:15:25 +00:00
const AMMOITEMDATA * pAmmoItemData = & gAmmoItemData [ pAmmo - > type - kItemAmmoBase ] ;
2019-10-21 19:46:41 +00:00
int nAmmoType = pAmmoItemData - > type ;
2019-09-19 22:42:45 +00:00
2019-10-25 20:53:41 +00:00
if ( pPlayer - > ammoCount [ nAmmoType ] > = gAmmoInfo [ nAmmoType ] . max ) return 0 ;
2020-01-26 11:19:01 +00:00
# ifdef NOONE_EXTENSIONS
else if ( gModernMap & & pAmmo - > extra > = 0 & & xsprite [ pAmmo - > extra ] . data1 > 0 ) // allow custom amount for item
2019-10-25 20:53:41 +00:00
pPlayer - > ammoCount [ nAmmoType ] = ClipHigh ( pPlayer - > ammoCount [ nAmmoType ] + xsprite [ pAmmo - > extra ] . data1 , gAmmoInfo [ nAmmoType ] . max ) ;
2020-01-26 11:19:01 +00:00
# endif
else
pPlayer - > ammoCount [ nAmmoType ] = ClipHigh ( pPlayer - > ammoCount [ nAmmoType ] + pAmmoItemData - > count , gAmmoInfo [ nAmmoType ] . max ) ;
2019-09-19 22:42:45 +00:00
2019-10-21 19:46:41 +00:00
if ( pAmmoItemData - > weaponType ) pPlayer - > hasWeapon [ pAmmoItemData - > weaponType ] = 1 ;
2019-09-19 22:42:45 +00:00
sfxPlay3DSound ( pPlayer - > pSprite , 782 , - 1 , 0 ) ;
return 1 ;
}
2019-10-11 21:59:39 +00:00
char PickupWeapon ( PLAYER * pPlayer , spritetype * pWeapon ) {
2020-02-11 22:15:25 +00:00
const WEAPONITEMDATA * pWeaponItemData = & gWeaponItemData [ pWeapon - > type - kItemWeaponBase ] ;
2019-10-21 19:46:41 +00:00
int nWeaponType = pWeaponItemData - > type ;
int nAmmoType = pWeaponItemData - > ammoType ;
if ( ! pPlayer - > hasWeapon [ nWeaponType ] | | gGameOptions . nWeaponSettings = = 2 | | gGameOptions . nWeaponSettings = = 3 ) {
2020-11-21 19:10:45 +00:00
if ( pWeapon - > type = = kItemWeaponLifeLeech & & gGameOptions . nGameType > 1 & & findDroppedLeech ( pPlayer , NULL ) )
2019-09-19 22:42:45 +00:00
return 0 ;
2019-10-21 19:46:41 +00:00
pPlayer - > hasWeapon [ nWeaponType ] = 1 ;
2019-09-19 22:42:45 +00:00
if ( nAmmoType = = - 1 ) return 0 ;
2020-01-26 11:19:01 +00:00
// allow to set custom ammo count for weapon pickups
# ifdef NOONE_EXTENSIONS
else if ( gModernMap & & pWeapon - > extra > = 0 & & xsprite [ pWeapon - > extra ] . data1 > 0 )
2019-10-25 20:53:41 +00:00
pPlayer - > ammoCount [ nAmmoType ] = ClipHigh ( pPlayer - > ammoCount [ nAmmoType ] + xsprite [ pWeapon - > extra ] . data1 , gAmmoInfo [ nAmmoType ] . max ) ;
2020-01-26 11:19:01 +00:00
# endif
else
pPlayer - > ammoCount [ nAmmoType ] = ClipHigh ( pPlayer - > ammoCount [ nAmmoType ] + pWeaponItemData - > count , gAmmoInfo [ nAmmoType ] . max ) ;
2019-09-19 22:42:45 +00:00
int nNewWeapon = WeaponUpgrade ( pPlayer , nWeaponType ) ;
2019-10-21 19:46:41 +00:00
if ( nNewWeapon ! = pPlayer - > curWeapon ) {
pPlayer - > weaponState = 0 ;
pPlayer - > nextWeapon = nNewWeapon ;
2019-09-19 22:42:45 +00:00
}
sfxPlay3DSound ( pPlayer - > pSprite , 777 , - 1 , 0 ) ;
return 1 ;
}
2019-09-21 11:02:17 +00:00
2019-10-25 20:53:41 +00:00
if ( ! actGetRespawnTime ( pWeapon ) | | nAmmoType = = - 1 | | pPlayer - > ammoCount [ nAmmoType ] > = gAmmoInfo [ nAmmoType ] . max ) return 0 ;
2020-01-26 11:19:01 +00:00
# ifdef NOONE_EXTENSIONS
else if ( gModernMap & & pWeapon - > extra > = 0 & & xsprite [ pWeapon - > extra ] . data1 > 0 )
pPlayer - > ammoCount [ nAmmoType ] = ClipHigh ( pPlayer - > ammoCount [ nAmmoType ] + xsprite [ pWeapon - > extra ] . data1 , gAmmoInfo [ nAmmoType ] . max ) ;
# endif
2019-09-21 11:02:17 +00:00
else
2020-01-26 11:19:01 +00:00
pPlayer - > ammoCount [ nAmmoType ] = ClipHigh ( pPlayer - > ammoCount [ nAmmoType ] + pWeaponItemData - > count , gAmmoInfo [ nAmmoType ] . max ) ;
2019-09-21 11:02:17 +00:00
2019-09-19 22:42:45 +00:00
sfxPlay3DSound ( pPlayer - > pSprite , 777 , - 1 , 0 ) ;
return 1 ;
}
void PickUp ( PLAYER * pPlayer , spritetype * pSprite )
{
2019-12-09 01:01:30 +00:00
const char * msg = nullptr ;
2019-09-19 22:42:45 +00:00
int nType = pSprite - > type ;
char pickedUp = 0 ;
int customMsg = - 1 ;
2020-01-26 11:19:01 +00:00
# ifdef NOONE_EXTENSIONS
if ( gModernMap ) { // allow custom INI message instead "Picked up"
XSPRITE * pXSprite = ( pSprite - > extra > = 0 ) ? & xsprite [ pSprite - > extra ] : NULL ;
if ( pXSprite ! = NULL & & pXSprite - > txID ! = 3 & & pXSprite - > lockMsg > 0 )
customMsg = pXSprite - > lockMsg ;
}
# endif
2019-10-11 21:59:39 +00:00
if ( nType > = kItemBase & & nType < = kItemMax ) {
2019-09-21 11:02:17 +00:00
pickedUp = PickupItem ( pPlayer , pSprite ) ;
2019-12-09 01:01:30 +00:00
if ( pickedUp & & customMsg = = - 1 ) msg = GStrings ( FStringf ( " TXTB_ITEM%02d " , int ( nType - kItemBase + 1 ) ) ) ;
2019-10-11 21:59:39 +00:00
} else if ( nType > = kItemAmmoBase & & nType < kItemAmmoMax ) {
2019-09-21 11:02:17 +00:00
pickedUp = PickupAmmo ( pPlayer , pSprite ) ;
2019-12-09 01:01:30 +00:00
if ( pickedUp & & customMsg = = - 1 ) msg = GStrings ( FStringf ( " TXTB_AMMO%02d " , int ( nType - kItemAmmoBase + 1 ) ) ) ;
2019-10-11 21:59:39 +00:00
} else if ( nType > = kItemWeaponBase & & nType < kItemWeaponMax ) {
2019-09-21 11:02:17 +00:00
pickedUp = PickupWeapon ( pPlayer , pSprite ) ;
2019-12-09 01:01:30 +00:00
if ( pickedUp & & customMsg = = - 1 ) msg = GStrings ( FStringf ( " TXTB_WPN%02d " , int ( nType - kItemWeaponBase + 1 ) ) ) ;
2019-09-21 11:02:17 +00:00
}
2019-10-11 21:59:39 +00:00
if ( ! pickedUp ) return ;
else if ( pSprite - > extra > 0 ) {
XSPRITE * pXSprite = & xsprite [ pSprite - > extra ] ;
if ( pXSprite - > Pickup )
2020-01-11 21:07:05 +00:00
trTriggerSprite ( pSprite - > index , pXSprite , kCmdSpritePickup ) ;
2019-10-11 21:59:39 +00:00
}
if ( ! actCheckRespawn ( pSprite ) )
actPostSprite ( pSprite - > index , kStatFree ) ;
2019-10-21 19:46:41 +00:00
pPlayer - > pickupEffect = 30 ;
2019-10-11 21:59:39 +00:00
if ( pPlayer = = gMe ) {
if ( customMsg > 0 ) trTextOver ( customMsg - 1 ) ;
2019-12-09 01:01:30 +00:00
else if ( msg ) viewSetMessage ( msg , 0 , MESSAGE_PRIORITY_PICKUP ) ;
2019-09-19 22:42:45 +00:00
}
}
void CheckPickUp ( PLAYER * pPlayer )
{
spritetype * pSprite = pPlayer - > pSprite ;
int x = pSprite - > x ;
int y = pSprite - > y ;
int z = pSprite - > z ;
int nSector = pSprite - > sectnum ;
int nNextSprite ;
2020-10-15 15:15:45 +00:00
int nSprite ;
StatIterator it ( kStatItem ) ;
while ( ( nSprite = it . NextIndex ( ) ) > = 0 )
{
2019-09-19 22:42:45 +00:00
spritetype * pItem = & sprite [ nSprite ] ;
nNextSprite = nextspritestat [ nSprite ] ;
2019-09-30 07:18:01 +00:00
if ( pItem - > flags & 32 )
2019-09-19 22:42:45 +00:00
continue ;
2021-01-04 12:02:00 +00:00
int dx = abs ( x - pItem - > x ) > > 4 ;
2019-09-19 22:42:45 +00:00
if ( dx > 48 )
continue ;
2021-01-04 12:02:00 +00:00
int dy = abs ( y - pItem - > y ) > > 4 ;
2019-09-19 22:42:45 +00:00
if ( dy > 48 )
continue ;
int top , bottom ;
GetSpriteExtents ( pSprite , & top , & bottom ) ;
int vb = 0 ;
if ( pItem - > z < top )
vb = ( top - pItem - > z ) > > 8 ;
else if ( pItem - > z > bottom )
vb = ( pItem - > z - bottom ) > > 8 ;
if ( vb > 32 )
continue ;
if ( approxDist ( dx , dy ) > 48 )
continue ;
GetSpriteExtents ( pItem , & top , & bottom ) ;
if ( cansee ( x , y , z , nSector , pItem - > x , pItem - > y , pItem - > z , pItem - > sectnum )
| | cansee ( x , y , z , nSector , pItem - > x , pItem - > y , top , pItem - > sectnum )
| | cansee ( x , y , z , nSector , pItem - > x , pItem - > y , bottom , pItem - > sectnum ) )
PickUp ( pPlayer , pItem ) ;
}
}
int ActionScan ( PLAYER * pPlayer , int * a2 , int * a3 )
{
* a2 = 0 ;
* a3 = 0 ;
spritetype * pSprite = pPlayer - > pSprite ;
2020-09-01 13:00:35 +00:00
int x = CosScale16 ( pSprite - > ang ) ;
int y = SinScale16 ( pSprite - > ang ) ;
2019-10-21 19:46:41 +00:00
int z = pPlayer - > slope ;
int hit = HitScan ( pSprite , pPlayer - > zView , x , y , z , 0x10000040 , 128 ) ;
2019-09-19 22:42:45 +00:00
int hitDist = approxDist ( pSprite - > x - gHitInfo . hitx , pSprite - > y - gHitInfo . hity ) > > 4 ;
if ( hitDist < 64 )
{
switch ( hit )
{
case 3 :
* a2 = gHitInfo . hitsprite ;
* a3 = sprite [ * a2 ] . extra ;
2019-10-07 19:29:52 +00:00
if ( * a3 > 0 & & sprite [ * a2 ] . statnum = = kStatThing )
2019-09-19 22:42:45 +00:00
{
spritetype * pSprite = & sprite [ * a2 ] ;
XSPRITE * pXSprite = & xsprite [ * a3 ] ;
2019-10-11 21:59:39 +00:00
if ( pSprite - > type = = kThingDroppedLifeLeech )
2019-09-19 22:42:45 +00:00
{
2020-11-21 19:10:45 +00:00
if ( gGameOptions . nGameType > 1 & & findDroppedLeech ( pPlayer , pSprite ) )
2019-09-19 22:42:45 +00:00
return - 1 ;
2019-10-21 19:46:41 +00:00
pXSprite - > data4 = pPlayer - > nPlayer ;
2019-09-19 22:42:45 +00:00
pXSprite - > isTriggered = 0 ;
}
}
if ( * a3 > 0 & & xsprite [ * a3 ] . Push )
return 3 ;
2019-10-07 19:29:52 +00:00
if ( sprite [ * a2 ] . statnum = = kStatDude )
2019-09-19 22:42:45 +00:00
{
spritetype * pSprite = & sprite [ * a2 ] ;
XSPRITE * pXSprite = & xsprite [ * a3 ] ;
2020-02-05 21:17:05 +00:00
int nMass = getDudeInfo ( pSprite - > type ) - > mass ;
2019-09-19 22:42:45 +00:00
if ( nMass )
{
2021-01-04 11:59:00 +00:00
int t2 = DivScale ( 0xccccc , nMass , 8 ) ;
2021-01-04 11:36:54 +00:00
xvel [ * a2 ] + = MulScale ( x , t2 , 16 ) ;
yvel [ * a2 ] + = MulScale ( y , t2 , 16 ) ;
zvel [ * a2 ] + = MulScale ( z , t2 , 16 ) ;
2019-09-19 22:42:45 +00:00
}
if ( pXSprite - > Push & & ! pXSprite - > state & & ! pXSprite - > isTriggered )
2020-01-11 21:07:05 +00:00
trTriggerSprite ( * a2 , pXSprite , kCmdSpritePush ) ;
2019-09-19 22:42:45 +00:00
}
break ;
case 0 :
case 4 :
* a2 = gHitInfo . hitwall ;
* a3 = wall [ * a2 ] . extra ;
if ( * a3 > 0 & & xwall [ * a3 ] . triggerPush )
return 0 ;
if ( wall [ * a2 ] . nextsector > = 0 )
{
* a2 = wall [ * a2 ] . nextsector ;
* a3 = sector [ * a2 ] . extra ;
if ( * a3 > 0 & & xsector [ * a3 ] . Wallpush )
return 6 ;
}
break ;
case 1 :
case 2 :
* a2 = gHitInfo . hitsect ;
* a3 = sector [ * a2 ] . extra ;
if ( * a3 > 0 & & xsector [ * a3 ] . Push )
return 6 ;
break ;
}
}
* a2 = pSprite - > sectnum ;
* a3 = sector [ * a2 ] . extra ;
if ( * a3 > 0 & & xsector [ * a3 ] . Push )
return 6 ;
return - 1 ;
}
2020-09-16 11:59:19 +00:00
//---------------------------------------------------------------------------
//
2020-09-21 07:00:07 +00:00
// Player's sprite angle function, called in ProcessInput() or from gi->GetInput() as required.
2020-09-16 11:59:19 +00:00
//
//---------------------------------------------------------------------------
2020-09-21 07:00:07 +00:00
void UpdatePlayerSpriteAngle ( PLAYER * pPlayer )
2020-09-16 08:22:01 +00:00
{
2021-01-10 07:17:29 +00:00
pPlayer - > pSprite - > ang = pPlayer - > angle . ang . asbuild ( ) ;
2020-09-16 08:22:01 +00:00
}
2021-01-02 03:40:35 +00:00
//---------------------------------------------------------------------------
//
// Player's slope tilting wrapper function function, called in ProcessInput() or from gi->GetInput() as required.
//
//---------------------------------------------------------------------------
void doslopetilting ( PLAYER * pPlayer , double const scaleAdjust = 1 )
{
auto * const pSprite = pPlayer - > pSprite ;
auto * const pXSprite = pPlayer - > pXSprite ;
int const florhit = gSpriteHit [ pSprite - > extra ] . florhit & 0xc000 ;
char const va = pXSprite - > height < 16 & & ( florhit = = 0x4000 | | florhit = = 0 ) ? 1 : 0 ;
calcviewpitch ( pSprite - > pos . vec2 , & pPlayer - > horizon . horizoff , buildang ( pSprite - > ang ) , va , sector [ pSprite - > sectnum ] . floorstat & 2 , pSprite - > sectnum , scaleAdjust ) ;
}
2019-09-19 22:42:45 +00:00
void ProcessInput ( PLAYER * pPlayer )
{
2020-08-27 19:25:09 +00:00
enum
{
Item_MedKit = 0 ,
Item_CrystalBall = 1 ,
Item_BeastVision = 2 ,
Item_JumpBoots = 3
} ;
2020-10-12 03:42:43 +00:00
pPlayer - > horizon . resetadjustment ( ) ;
pPlayer - > angle . resetadjustment ( ) ;
2020-09-16 12:18:22 +00:00
2019-09-19 22:42:45 +00:00
spritetype * pSprite = pPlayer - > pSprite ;
XSPRITE * pXSprite = pPlayer - > pXSprite ;
2019-10-21 19:46:41 +00:00
int nSprite = pPlayer - > nSprite ;
2020-01-01 20:53:29 +00:00
POSTURE * pPosture = & pPlayer - > pPosture [ pPlayer - > lifeMode ] [ pPlayer - > posture ] ;
2020-08-26 15:12:48 +00:00
InputPacket * pInput = & pPlayer - > input ;
2020-01-30 13:05:34 +00:00
2020-10-08 03:47:30 +00:00
if ( ( pInput - > actions & SB_BUTTON_MASK ) | | pInput - > fvel | | pInput - > svel | | pInput - > avel )
2019-10-21 19:46:41 +00:00
pPlayer - > restTime = 0 ;
else if ( pPlayer - > restTime > = 0 )
pPlayer - > restTime + = 4 ;
2020-12-10 18:23:38 +00:00
2021-04-04 07:35:05 +00:00
// This was just too broken. Every single place in the game depending on 'isRunning' will misbehave if this is set because originally it never worked as intended.
pPlayer - > isRunning = false ; // !!(pInput->actions& SB_RUN) && pPlayer->restTime <= 10;
2020-12-10 18:23:38 +00:00
2019-09-19 22:42:45 +00:00
WeaponProcess ( pPlayer ) ;
if ( pXSprite - > health = = 0 )
{
char bSeqStat = playerSeqPlaying ( pPlayer , 16 ) ;
2019-10-21 19:46:41 +00:00
if ( pPlayer - > fraggerId ! = - 1 )
2019-09-19 22:42:45 +00:00
{
2021-01-10 07:17:29 +00:00
pPlayer - > angle . addadjustment ( getincanglebam ( pPlayer - > angle . ang , bvectangbam ( sprite [ pPlayer - > fraggerId ] . x - pSprite - > x , sprite [ pPlayer - > fraggerId ] . y - pSprite - > y ) ) ) ;
2019-09-19 22:42:45 +00:00
}
2019-10-21 19:46:41 +00:00
pPlayer - > deathTime + = 4 ;
2019-09-19 22:42:45 +00:00
if ( ! bSeqStat )
2021-01-04 11:36:54 +00:00
pPlayer - > horizon . addadjustment ( FixedToFloat ( MulScale ( 0x8000 - ( Cos ( ClipHigh ( pPlayer - > deathTime < < 3 , 1024 ) ) > > 15 ) , gi - > playerHorizMax ( ) , 16 ) - pPlayer - > horizon . horiz . asq16 ( ) ) ) ;
2019-10-21 19:46:41 +00:00
if ( pPlayer - > curWeapon )
2020-08-26 22:53:35 +00:00
pInput - > setNewWeapon ( pPlayer - > curWeapon ) ;
2020-08-28 20:51:05 +00:00
if ( pInput - > actions & SB_OPEN )
2019-09-19 22:42:45 +00:00
{
if ( bSeqStat )
{
2019-10-21 19:46:41 +00:00
if ( pPlayer - > deathTime > 360 )
2019-09-19 22:42:45 +00:00
seqSpawn ( pPlayer - > pDudeInfo - > seqStartID + 14 , 3 , pPlayer - > pSprite - > extra , nPlayerSurviveClient ) ;
}
else if ( seqGetStatus ( 3 , pPlayer - > pSprite - > extra ) < 0 )
{
if ( pPlayer - > pSprite )
2019-10-11 21:59:39 +00:00
pPlayer - > pSprite - > type = kThingBloodChunks ;
2019-10-21 19:46:41 +00:00
actPostSprite ( pPlayer - > nSprite , kStatThing ) ;
2019-09-19 22:42:45 +00:00
seqSpawn ( pPlayer - > pDudeInfo - > seqStartID + 15 , 3 , pPlayer - > pSprite - > extra , - 1 ) ;
playerReset ( pPlayer ) ;
if ( gGameOptions . nGameType = = 0 & & numplayers = = 1 )
{
2020-09-04 20:23:38 +00:00
gameaction = ga_autoloadgame ;
2019-09-19 22:42:45 +00:00
}
else
2019-10-21 19:46:41 +00:00
playerStart ( pPlayer - > nPlayer ) ;
2019-09-19 22:42:45 +00:00
}
2020-08-28 20:51:05 +00:00
pInput - > actions & = ~ SB_OPEN ;
2019-09-19 22:42:45 +00:00
}
return ;
}
2019-10-21 19:46:41 +00:00
if ( pPlayer - > posture = = 1 )
2019-09-19 22:42:45 +00:00
{
int x = Cos ( pSprite - > ang ) ;
int y = Sin ( pSprite - > ang ) ;
2020-08-26 14:54:13 +00:00
if ( pInput - > fvel )
2019-09-19 22:42:45 +00:00
{
2020-08-26 14:54:13 +00:00
int forward = pInput - > fvel ;
2019-09-19 22:42:45 +00:00
if ( forward > 0 )
2021-01-04 11:36:54 +00:00
forward = MulScale ( pPosture - > frontAccel , forward , 8 ) ;
2019-09-19 22:42:45 +00:00
else
2021-01-04 11:36:54 +00:00
forward = MulScale ( pPosture - > backAccel , forward , 8 ) ;
xvel [ nSprite ] + = MulScale ( forward , x , 30 ) ;
yvel [ nSprite ] + = MulScale ( forward , y , 30 ) ;
2019-09-19 22:42:45 +00:00
}
2020-08-26 14:54:13 +00:00
if ( pInput - > svel )
2019-09-19 22:42:45 +00:00
{
2020-08-26 14:54:13 +00:00
int strafe = pInput - > svel ;
2021-01-04 11:36:54 +00:00
strafe = MulScale ( pPosture - > sideAccel , strafe , 8 ) ;
xvel [ nSprite ] + = MulScale ( strafe , y , 30 ) ;
yvel [ nSprite ] - = MulScale ( strafe , x , 30 ) ;
2019-09-19 22:42:45 +00:00
}
}
else if ( pXSprite - > height < 256 )
{
int speed = 0x10000 ;
if ( pXSprite - > height > 0 )
2021-01-04 11:51:41 +00:00
speed - = DivScale ( pXSprite - > height , 256 , 16 ) ;
2019-09-19 22:42:45 +00:00
int x = Cos ( pSprite - > ang ) ;
int y = Sin ( pSprite - > ang ) ;
2020-08-26 14:54:13 +00:00
if ( pInput - > fvel )
2019-09-19 22:42:45 +00:00
{
2020-08-26 14:54:13 +00:00
int forward = pInput - > fvel ;
2019-09-19 22:42:45 +00:00
if ( forward > 0 )
2021-01-04 11:36:54 +00:00
forward = MulScale ( pPosture - > frontAccel , forward , 8 ) ;
2019-09-19 22:42:45 +00:00
else
2021-01-04 11:36:54 +00:00
forward = MulScale ( pPosture - > backAccel , forward , 8 ) ;
2019-09-19 22:42:45 +00:00
if ( pXSprite - > height )
2021-01-04 11:36:54 +00:00
forward = MulScale ( forward , speed , 16 ) ;
xvel [ nSprite ] + = MulScale ( forward , x , 30 ) ;
yvel [ nSprite ] + = MulScale ( forward , y , 30 ) ;
2019-09-19 22:42:45 +00:00
}
2020-08-26 14:54:13 +00:00
if ( pInput - > svel )
2019-09-19 22:42:45 +00:00
{
2020-08-26 14:54:13 +00:00
int strafe = pInput - > svel ;
2021-01-04 11:36:54 +00:00
strafe = MulScale ( pPosture - > sideAccel , strafe , 8 ) ;
2019-09-19 22:42:45 +00:00
if ( pXSprite - > height )
2021-01-04 11:36:54 +00:00
strafe = MulScale ( strafe , speed , 16 ) ;
xvel [ nSprite ] + = MulScale ( strafe , y , 30 ) ;
yvel [ nSprite ] - = MulScale ( strafe , x , 30 ) ;
2019-09-19 22:42:45 +00:00
}
}
2020-09-16 08:22:01 +00:00
2020-11-30 22:40:16 +00:00
if ( SyncInput ( ) )
2019-09-19 22:42:45 +00:00
{
2020-11-07 07:25:06 +00:00
applylook ( & pPlayer - > angle , pInput - > avel , & pInput - > actions ) ;
2019-09-19 22:42:45 +00:00
}
2020-09-16 08:22:01 +00:00
2020-11-30 20:43:12 +00:00
// unconditionally update the player's sprite angle
// in case game is forcing synchronised input.
UpdatePlayerSpriteAngle ( pPlayer ) ;
2020-08-28 20:51:05 +00:00
if ( ! ( pInput - > actions & SB_JUMP ) )
2019-10-25 20:53:41 +00:00
pPlayer - > cantJump = 0 ;
2019-09-19 22:42:45 +00:00
2019-11-08 19:57:01 +00:00
switch ( pPlayer - > posture ) {
2019-09-19 22:42:45 +00:00
case 1 :
2020-08-28 20:51:05 +00:00
if ( pInput - > actions & SB_JUMP )
2019-11-08 19:57:01 +00:00
zvel [ nSprite ] - = pPosture - > normalJumpZ ; //0x5b05;
2020-08-28 20:51:05 +00:00
if ( pInput - > actions & SB_CROUCH )
2019-11-08 19:57:01 +00:00
zvel [ nSprite ] + = pPosture - > normalJumpZ ; //0x5b05;
2019-09-19 22:42:45 +00:00
break ;
case 2 :
2020-08-28 20:51:05 +00:00
if ( ! ( pInput - > actions & SB_CROUCH ) )
2019-10-21 19:46:41 +00:00
pPlayer - > posture = 0 ;
2019-09-19 22:42:45 +00:00
break ;
default :
2020-08-28 20:51:05 +00:00
if ( ! pPlayer - > cantJump & & ( pInput - > actions & SB_JUMP ) & & pXSprite - > height = = 0 ) {
2020-01-26 11:19:01 +00:00
# ifdef NOONE_EXTENSIONS
2020-01-05 13:48:22 +00:00
if ( ( packItemActive ( pPlayer , 4 ) & & pPosture - > pwupJumpZ ! = 0 ) | | pPosture - > normalJumpZ ! = 0 )
2020-01-26 11:19:01 +00:00
# endif
2020-01-04 00:20:41 +00:00
sfxPlay3DSound ( pSprite , 700 , 0 , 0 ) ;
2019-12-11 19:48:42 +00:00
if ( packItemActive ( pPlayer , 4 ) ) zvel [ nSprite ] = pPosture - > pwupJumpZ ; //-0x175555;
else zvel [ nSprite ] = pPosture - > normalJumpZ ; //-0xbaaaa;
2019-10-25 20:53:41 +00:00
pPlayer - > cantJump = 1 ;
2019-09-19 22:42:45 +00:00
}
2020-08-28 20:51:05 +00:00
if ( pInput - > actions & SB_CROUCH )
2019-10-21 19:46:41 +00:00
pPlayer - > posture = 2 ;
2019-09-19 22:42:45 +00:00
break ;
}
2020-08-28 20:51:05 +00:00
if ( pInput - > actions & SB_OPEN )
2019-09-19 22:42:45 +00:00
{
int a2 , a3 ;
int hit = ActionScan ( pPlayer , & a2 , & a3 ) ;
switch ( hit )
{
case 6 :
if ( a3 > 0 & & a3 < = 2048 )
{
XSECTOR * pXSector = & xsector [ a3 ] ;
int key = pXSector - > Key ;
if ( pXSector - > locked & & pPlayer = = gMe )
{
2019-12-09 01:01:30 +00:00
viewSetMessage ( GStrings ( " TXTB_LOCKED " ) ) ;
2020-11-07 04:13:45 +00:00
auto snd = 3062 ;
if ( sndCheckPlaying ( snd ) )
sndStopSample ( snd ) ;
sndStartSample ( snd , 255 , 2 , 0 ) ;
2019-09-19 22:42:45 +00:00
}
2019-10-21 19:46:41 +00:00
if ( ! key | | pPlayer - > hasKey [ key ] )
2020-01-11 21:07:05 +00:00
trTriggerSector ( a2 , pXSector , kCmdSpritePush ) ;
2019-09-19 22:42:45 +00:00
else if ( pPlayer = = gMe )
{
2019-12-09 01:01:30 +00:00
viewSetMessage ( GStrings ( " TXTB_KEY " ) ) ;
2020-11-07 04:13:45 +00:00
auto snd = 3063 ;
if ( sndCheckPlaying ( snd ) )
sndStopSample ( snd ) ;
sndStartSample ( snd , 255 , 2 , 0 ) ;
2019-09-19 22:42:45 +00:00
}
}
break ;
case 0 :
{
XWALL * pXWall = & xwall [ a3 ] ;
int key = pXWall - > key ;
if ( pXWall - > locked & & pPlayer = = gMe )
{
2019-12-09 01:01:30 +00:00
viewSetMessage ( GStrings ( " TXTB_LOCKED " ) ) ;
2020-11-07 04:13:45 +00:00
auto snd = 3062 ;
if ( sndCheckPlaying ( snd ) )
sndStopSample ( snd ) ;
sndStartSample ( snd , 255 , 2 , 0 ) ;
2019-09-19 22:42:45 +00:00
}
2019-10-21 19:46:41 +00:00
if ( ! key | | pPlayer - > hasKey [ key ] )
2020-01-11 21:07:05 +00:00
trTriggerWall ( a2 , pXWall , kCmdWallPush ) ;
2019-09-19 22:42:45 +00:00
else if ( pPlayer = = gMe )
{
2019-12-09 01:01:30 +00:00
viewSetMessage ( GStrings ( " TXTB_KEY " ) ) ;
2020-11-07 04:13:45 +00:00
auto snd = 3063 ;
if ( sndCheckPlaying ( snd ) )
sndStopSample ( snd ) ;
sndStartSample ( snd , 255 , 2 , 0 ) ;
2019-09-19 22:42:45 +00:00
}
break ;
}
case 3 :
{
XSPRITE * pXSprite = & xsprite [ a3 ] ;
int key = pXSprite - > key ;
if ( pXSprite - > locked & & pPlayer = = gMe & & pXSprite - > lockMsg )
trTextOver ( pXSprite - > lockMsg ) ;
2019-10-21 19:46:41 +00:00
if ( ! key | | pPlayer - > hasKey [ key ] )
2020-01-11 21:07:05 +00:00
trTriggerSprite ( a2 , pXSprite , kCmdSpritePush ) ;
2019-09-19 22:42:45 +00:00
else if ( pPlayer = = gMe )
{
2019-12-09 01:01:30 +00:00
viewSetMessage ( GStrings ( " TXTB_KEY " ) ) ;
2019-09-19 22:42:45 +00:00
sndStartSample ( 3063 , 255 , 2 , 0 ) ;
}
break ;
}
}
2019-10-21 19:46:41 +00:00
if ( pPlayer - > handTime > 0 )
pPlayer - > handTime = ClipLow ( pPlayer - > handTime - 4 * ( 6 - gGameOptions . nDifficulty ) , 0 ) ;
if ( pPlayer - > handTime < = 0 & & pPlayer - > hand )
2019-09-19 22:42:45 +00:00
{
2019-10-11 21:59:39 +00:00
spritetype * pSprite2 = actSpawnDude ( pPlayer - > pSprite , kDudeHand , pPlayer - > pSprite - > clipdist < < 1 , 0 ) ;
2019-09-19 22:42:45 +00:00
pSprite2 - > ang = ( pPlayer - > pSprite - > ang + 1024 ) & 2047 ;
int nSprite = pPlayer - > pSprite - > index ;
2020-09-01 13:00:35 +00:00
int x = CosScale16 ( pPlayer - > pSprite - > ang ) ;
int y = SinScale16 ( pPlayer - > pSprite - > ang ) ;
2021-01-04 11:36:54 +00:00
xvel [ pSprite2 - > index ] = xvel [ nSprite ] + MulScale ( 0x155555 , x , 14 ) ;
yvel [ pSprite2 - > index ] = yvel [ nSprite ] + MulScale ( 0x155555 , y , 14 ) ;
2019-09-19 22:42:45 +00:00
zvel [ pSprite2 - > index ] = zvel [ nSprite ] ;
2019-10-21 19:46:41 +00:00
pPlayer - > hand = 0 ;
2019-09-19 22:42:45 +00:00
}
2020-08-28 20:51:05 +00:00
pInput - > actions & = ~ SB_OPEN ;
2019-09-19 22:42:45 +00:00
}
2020-09-16 08:32:39 +00:00
2020-11-30 22:40:16 +00:00
if ( SyncInput ( ) )
2019-09-19 22:42:45 +00:00
{
2021-04-02 11:41:47 +00:00
sethorizon ( & pPlayer - > horizon , pInput - > horz , & pInput - > actions ) ;
2021-01-02 03:54:54 +00:00
doslopetilting ( pPlayer ) ;
2019-09-19 22:42:45 +00:00
}
2020-09-16 08:32:39 +00:00
2020-12-01 11:02:02 +00:00
// disable synchronised input if set by game.
resetForcedSyncInput ( ) ;
2020-10-07 06:16:58 +00:00
pPlayer - > slope = - pPlayer - > horizon . horiz . asq16 ( ) > > 9 ;
2020-08-27 20:19:24 +00:00
if ( pInput - > actions & SB_INVPREV )
2019-09-19 22:42:45 +00:00
{
2020-08-27 20:19:24 +00:00
pInput - > actions & = ~ SB_INVPREV ;
2019-09-19 22:42:45 +00:00
packPrevItem ( pPlayer ) ;
}
2020-08-27 20:19:24 +00:00
if ( pInput - > actions & SB_INVNEXT )
2019-09-19 22:42:45 +00:00
{
2020-08-27 20:19:24 +00:00
pInput - > actions & = ~ SB_INVNEXT ;
2019-09-19 22:42:45 +00:00
packNextItem ( pPlayer ) ;
}
2020-08-27 20:19:24 +00:00
if ( pInput - > actions & SB_INVUSE )
2019-09-19 22:42:45 +00:00
{
2020-08-27 20:19:24 +00:00
pInput - > actions & = ~ SB_INVUSE ;
2019-10-21 19:46:41 +00:00
if ( pPlayer - > packSlots [ pPlayer - > packItemId ] . curAmount > 0 )
packUseItem ( pPlayer , pPlayer - > packItemId ) ;
2019-09-19 22:42:45 +00:00
}
2020-08-27 19:25:09 +00:00
if ( pInput - > isItemUsed ( Item_BeastVision ) )
2019-09-19 22:42:45 +00:00
{
2020-08-27 19:25:09 +00:00
pInput - > clearItemUsed ( Item_BeastVision ) ;
2019-10-21 19:46:41 +00:00
if ( pPlayer - > packSlots [ 3 ] . curAmount > 0 )
2019-09-19 22:42:45 +00:00
packUseItem ( pPlayer , 3 ) ;
}
2020-08-27 19:25:09 +00:00
if ( pInput - > isItemUsed ( Item_CrystalBall ) )
2019-09-19 22:42:45 +00:00
{
2020-08-27 19:25:09 +00:00
pInput - > clearItemUsed ( Item_CrystalBall ) ;
2019-10-21 19:46:41 +00:00
if ( pPlayer - > packSlots [ 2 ] . curAmount > 0 )
2019-09-19 22:42:45 +00:00
packUseItem ( pPlayer , 2 ) ;
}
2020-08-27 19:25:09 +00:00
if ( pInput - > isItemUsed ( Item_JumpBoots ) )
2019-09-19 22:42:45 +00:00
{
2020-08-27 19:25:09 +00:00
pInput - > clearItemUsed ( Item_JumpBoots ) ;
2019-10-21 19:46:41 +00:00
if ( pPlayer - > packSlots [ 4 ] . curAmount > 0 )
2019-09-19 22:42:45 +00:00
packUseItem ( pPlayer , 4 ) ;
}
2020-08-27 19:25:09 +00:00
if ( pInput - > isItemUsed ( Item_MedKit ) )
2019-09-19 22:42:45 +00:00
{
2020-08-27 19:25:09 +00:00
pInput - > clearItemUsed ( Item_MedKit ) ;
2019-10-21 19:46:41 +00:00
if ( pPlayer - > packSlots [ 0 ] . curAmount > 0 )
2019-09-19 22:42:45 +00:00
packUseItem ( pPlayer , 0 ) ;
}
2020-08-28 20:51:05 +00:00
if ( pInput - > actions & SB_HOLSTER )
2019-09-19 22:42:45 +00:00
{
2020-08-28 20:51:05 +00:00
pInput - > actions & = ~ SB_HOLSTER ;
2019-10-21 19:46:41 +00:00
if ( pPlayer - > curWeapon )
2019-09-19 22:42:45 +00:00
{
WeaponLower ( pPlayer ) ;
viewSetMessage ( " Holstering weapon " ) ;
}
}
CheckPickUp ( pPlayer ) ;
}
void playerProcess ( PLAYER * pPlayer )
{
spritetype * pSprite = pPlayer - > pSprite ;
2019-10-21 19:46:41 +00:00
int nSprite = pPlayer - > nSprite ;
2019-09-19 22:42:45 +00:00
int nXSprite = pSprite - > extra ;
XSPRITE * pXSprite = pPlayer - > pXSprite ;
2020-01-01 20:53:29 +00:00
POSTURE * pPosture = & pPlayer - > pPosture [ pPlayer - > lifeMode ] [ pPlayer - > posture ] ;
2019-09-19 22:42:45 +00:00
powerupProcess ( pPlayer ) ;
int top , bottom ;
GetSpriteExtents ( pSprite , & top , & bottom ) ;
int dzb = ( bottom - pSprite - > z ) / 4 ;
int dzt = ( pSprite - > z - top ) / 4 ;
int dw = pSprite - > clipdist < < 2 ;
if ( ! gNoClip )
{
short nSector = pSprite - > sectnum ;
if ( pushmove_old ( & pSprite - > x , & pSprite - > y , & pSprite - > z , & nSector , dw , dzt , dzb , CLIPMASK0 ) = = - 1 )
actDamageSprite ( nSprite , pSprite , DAMAGE_TYPE_0 , 500 < < 4 ) ;
if ( pSprite - > sectnum ! = nSector )
{
if ( nSector = = - 1 )
{
nSector = pSprite - > sectnum ;
actDamageSprite ( nSprite , pSprite , DAMAGE_TYPE_0 , 500 < < 4 ) ;
}
2020-10-11 10:38:17 +00:00
assert ( nSector > = 0 & & nSector < kMaxSectors ) ;
2019-09-19 22:42:45 +00:00
ChangeSpriteSect ( nSprite , nSector ) ;
}
}
ProcessInput ( pPlayer ) ;
int nSpeed = approxDist ( xvel [ nSprite ] , yvel [ nSprite ] ) ;
2019-10-21 19:46:41 +00:00
pPlayer - > zViewVel = interpolate ( pPlayer - > zViewVel , zvel [ nSprite ] , 0x7000 ) ;
int dz = pPlayer - > pSprite - > z - pPosture - > eyeAboveZ - pPlayer - > zView ;
2019-09-19 22:42:45 +00:00
if ( dz > 0 )
2021-01-04 11:36:54 +00:00
pPlayer - > zViewVel + = MulScale ( dz < < 8 , 0xa000 , 16 ) ;
2019-09-19 22:42:45 +00:00
else
2021-01-04 11:36:54 +00:00
pPlayer - > zViewVel + = MulScale ( dz < < 8 , 0x1800 , 16 ) ;
2019-10-21 19:46:41 +00:00
pPlayer - > zView + = pPlayer - > zViewVel > > 8 ;
pPlayer - > zWeaponVel = interpolate ( pPlayer - > zWeaponVel , zvel [ nSprite ] , 0x5000 ) ;
dz = pPlayer - > pSprite - > z - pPosture - > weaponAboveZ - pPlayer - > zWeapon ;
2019-09-19 22:42:45 +00:00
if ( dz > 0 )
2021-01-04 11:36:54 +00:00
pPlayer - > zWeaponVel + = MulScale ( dz < < 8 , 0x8000 , 16 ) ;
2019-09-19 22:42:45 +00:00
else
2021-01-04 11:36:54 +00:00
pPlayer - > zWeaponVel + = MulScale ( dz < < 8 , 0xc00 , 16 ) ;
2019-10-21 19:46:41 +00:00
pPlayer - > zWeapon + = pPlayer - > zWeaponVel > > 8 ;
pPlayer - > bobPhase = ClipLow ( pPlayer - > bobPhase - 4 , 0 ) ;
2020-09-01 13:00:35 +00:00
nSpeed > > = FRACBITS ;
2019-10-21 19:46:41 +00:00
if ( pPlayer - > posture = = 1 )
2019-09-19 22:42:45 +00:00
{
2019-10-21 19:46:41 +00:00
pPlayer - > bobAmp = ( pPlayer - > bobAmp + 17 ) & 2047 ;
pPlayer - > swayAmp = ( pPlayer - > swayAmp + 17 ) & 2047 ;
2021-01-04 11:36:54 +00:00
pPlayer - > bobHeight = MulScale ( pPosture - > bobV * 10 , Sin ( pPlayer - > bobAmp * 2 ) , 30 ) ;
pPlayer - > bobWidth = MulScale ( pPosture - > bobH * pPlayer - > bobPhase , Sin ( pPlayer - > bobAmp - 256 ) , 30 ) ;
pPlayer - > swayHeight = MulScale ( pPosture - > swayV * pPlayer - > bobPhase , Sin ( pPlayer - > swayAmp * 2 ) , 30 ) ;
pPlayer - > swayWidth = MulScale ( pPosture - > swayH * pPlayer - > bobPhase , Sin ( pPlayer - > swayAmp - 0x155 ) , 30 ) ;
2019-09-19 22:42:45 +00:00
}
else
{
if ( pXSprite - > height < 256 )
{
2021-03-01 18:28:47 +00:00
// taking a cue from BloodGDX here. Apparently due to poor coding in the original game this could never be true.
bool running = false ; // pPlayer->isRunning;
2020-12-03 23:06:23 +00:00
pPlayer - > bobAmp = ( pPlayer - > bobAmp + pPosture - > pace [ running ] * 4 ) & 2047 ;
pPlayer - > swayAmp = ( pPlayer - > swayAmp + ( pPosture - > pace [ running ] * 4 ) / 2 ) & 2047 ;
if ( running )
2019-09-19 22:42:45 +00:00
{
2019-10-21 19:46:41 +00:00
if ( pPlayer - > bobPhase < 60 )
pPlayer - > bobPhase = ClipHigh ( pPlayer - > bobPhase + nSpeed , 60 ) ;
2019-09-19 22:42:45 +00:00
}
else
{
2019-10-21 19:46:41 +00:00
if ( pPlayer - > bobPhase < 30 )
pPlayer - > bobPhase = ClipHigh ( pPlayer - > bobPhase + nSpeed , 30 ) ;
2019-09-19 22:42:45 +00:00
}
}
2021-01-04 11:36:54 +00:00
pPlayer - > bobHeight = MulScale ( pPosture - > bobV * pPlayer - > bobPhase , Sin ( pPlayer - > bobAmp * 2 ) , 30 ) ;
pPlayer - > bobWidth = MulScale ( pPosture - > bobH * pPlayer - > bobPhase , Sin ( pPlayer - > bobAmp - 256 ) , 30 ) ;
pPlayer - > swayHeight = MulScale ( pPosture - > swayV * pPlayer - > bobPhase , Sin ( pPlayer - > swayAmp * 2 ) , 30 ) ;
pPlayer - > swayWidth = MulScale ( pPosture - > swayH * pPlayer - > bobPhase , Sin ( pPlayer - > swayAmp - 0x155 ) , 30 ) ;
2019-10-21 19:46:41 +00:00
}
pPlayer - > flickerEffect = 0 ;
pPlayer - > quakeEffect = ClipLow ( pPlayer - > quakeEffect - 4 , 0 ) ;
pPlayer - > tiltEffect = ClipLow ( pPlayer - > tiltEffect - 4 , 0 ) ;
pPlayer - > visibility = ClipLow ( pPlayer - > visibility - 4 , 0 ) ;
pPlayer - > painEffect = ClipLow ( pPlayer - > painEffect - 4 , 0 ) ;
pPlayer - > blindEffect = ClipLow ( pPlayer - > blindEffect - 4 , 0 ) ;
pPlayer - > pickupEffect = ClipLow ( pPlayer - > pickupEffect - 4 , 0 ) ;
2019-09-19 22:42:45 +00:00
if ( pPlayer = = gMe & & gMe - > pXSprite - > health = = 0 )
2019-10-21 19:46:41 +00:00
pPlayer - > hand = 0 ;
2019-09-19 22:42:45 +00:00
if ( ! pXSprite - > health )
return ;
2019-10-21 19:46:41 +00:00
pPlayer - > isUnderwater = 0 ;
if ( pPlayer - > posture = = 1 )
2019-09-19 22:42:45 +00:00
{
2019-10-21 19:46:41 +00:00
pPlayer - > isUnderwater = 1 ;
2019-09-19 22:42:45 +00:00
int nSector = pSprite - > sectnum ;
int nLink = gLowerLink [ nSector ] ;
2019-10-19 19:11:39 +00:00
if ( nLink > 0 & & ( sprite [ nLink ] . type = = kMarkerLowGoo | | sprite [ nLink ] . type = = kMarkerLowWater ) )
2019-09-19 22:42:45 +00:00
{
2019-10-21 19:46:41 +00:00
if ( getceilzofslope ( nSector , pSprite - > x , pSprite - > y ) > pPlayer - > zView )
pPlayer - > isUnderwater = 0 ;
2019-09-19 22:42:45 +00:00
}
}
2019-10-21 19:46:41 +00:00
if ( ! pPlayer - > isUnderwater )
2019-09-19 22:42:45 +00:00
{
2019-10-21 19:46:41 +00:00
pPlayer - > underwaterTime = 1200 ;
pPlayer - > chokeEffect = 0 ;
2019-09-19 22:42:45 +00:00
if ( packItemActive ( pPlayer , 1 ) )
packUseItem ( pPlayer , 1 ) ;
}
int nType = kDudePlayer1 - kDudeBase ;
2019-10-21 19:46:41 +00:00
switch ( pPlayer - > posture )
2019-09-19 22:42:45 +00:00
{
case 1 :
seqSpawn ( dudeInfo [ nType ] . seqStartID + 9 , 3 , nXSprite , - 1 ) ;
break ;
case 2 :
seqSpawn ( dudeInfo [ nType ] . seqStartID + 10 , 3 , nXSprite , - 1 ) ;
break ;
default :
if ( ! nSpeed )
seqSpawn ( dudeInfo [ nType ] . seqStartID , 3 , nXSprite , - 1 ) ;
else
seqSpawn ( dudeInfo [ nType ] . seqStartID + 8 , 3 , nXSprite , - 1 ) ;
break ;
}
}
spritetype * playerFireMissile ( PLAYER * pPlayer , int a2 , int a3 , int a4 , int a5 , int a6 )
{
2019-10-21 19:46:41 +00:00
return actFireMissile ( pPlayer - > pSprite , a2 , pPlayer - > zWeapon - pPlayer - > pSprite - > z , a3 , a4 , a5 , a6 ) ;
2019-09-19 22:42:45 +00:00
}
spritetype * playerFireThing ( PLAYER * pPlayer , int a2 , int a3 , int thingType , int a5 )
{
2020-10-11 10:38:17 +00:00
assert ( thingType > = kThingBase & & thingType < kThingMax ) ;
2019-10-21 19:46:41 +00:00
return actFireThing ( pPlayer - > pSprite , a2 , pPlayer - > zWeapon - pPlayer - > pSprite - > z , pPlayer - > slope + a3 , thingType , a5 ) ;
2019-09-19 22:42:45 +00:00
}
void playerFrag ( PLAYER * pKiller , PLAYER * pVictim )
{
2020-10-11 10:38:17 +00:00
assert ( pKiller ! = NULL ) ;
assert ( pVictim ! = NULL ) ;
2019-09-19 22:42:45 +00:00
char buffer [ 128 ] = " " ;
int nKiller = pKiller - > pSprite - > type - kDudePlayer1 ;
2020-10-11 10:38:17 +00:00
assert ( nKiller > = 0 & & nKiller < kMaxPlayers ) ;
2019-09-19 22:42:45 +00:00
int nVictim = pVictim - > pSprite - > type - kDudePlayer1 ;
2020-10-11 10:38:17 +00:00
assert ( nVictim > = 0 & & nVictim < kMaxPlayers ) ;
2019-09-19 22:42:45 +00:00
if ( nKiller = = nVictim )
{
2019-10-21 19:46:41 +00:00
pVictim - > fraggerId = - 1 ;
2019-09-21 09:54:56 +00:00
if ( VanillaMode ( ) | | gGameOptions . nGameType ! = 1 )
{
2019-10-21 19:46:41 +00:00
pVictim - > fragCount - - ;
pVictim - > fragInfo [ nVictim ] - - ;
2019-09-21 09:54:56 +00:00
}
2019-09-19 22:42:45 +00:00
if ( gGameOptions . nGameType = = 3 )
2020-11-22 12:16:58 +00:00
team_score [ pVictim - > teamId ] - - ;
2019-09-19 22:42:45 +00:00
int nMessage = Random ( 5 ) ;
2020-09-01 19:27:32 +00:00
int nSound = gSuicide [ nMessage ] . Kills ;
2019-10-21 19:46:41 +00:00
if ( pVictim = = gMe & & gMe - > handTime < = 0 )
2019-09-19 22:42:45 +00:00
{
2020-01-07 00:11:19 +00:00
strcpy ( buffer , GStrings ( " TXTB_KILLSELF " ) ) ;
2019-09-19 22:42:45 +00:00
if ( gGameOptions . nGameType > 0 & & nSound > = 0 )
sndStartSample ( nSound , 255 , 2 , 0 ) ;
}
2019-09-17 12:16:05 +00:00
else
{
2020-11-22 12:28:20 +00:00
sprintf ( buffer , gSuicide [ nMessage ] . message , PlayerName ( nVictim ) ) ;
2019-09-17 12:16:05 +00:00
}
2019-09-19 22:42:45 +00:00
}
else
{
2019-09-21 09:54:56 +00:00
if ( VanillaMode ( ) | | gGameOptions . nGameType ! = 1 )
{
2019-10-21 19:46:41 +00:00
pKiller - > fragCount + + ;
pKiller - > fragInfo [ nKiller ] + + ;
2019-09-21 09:54:56 +00:00
}
2019-09-19 22:42:45 +00:00
if ( gGameOptions . nGameType = = 3 )
{
2019-10-21 19:46:41 +00:00
if ( pKiller - > teamId = = pVictim - > teamId )
2020-11-22 12:16:58 +00:00
team_score [ pKiller - > teamId ] - - ;
2019-09-19 22:42:45 +00:00
else
{
2020-11-22 12:16:58 +00:00
team_score [ pKiller - > teamId ] + + ;
team_ticker [ pKiller - > teamId ] + = 120 ;
2019-09-19 22:42:45 +00:00
}
}
int nMessage = Random ( 25 ) ;
2020-09-01 19:27:32 +00:00
int nSound = gVictory [ nMessage ] . Kills ;
2020-11-21 22:40:08 +00:00
const char * pzMessage = gVictory [ nMessage ] . message ;
2020-11-22 12:28:20 +00:00
sprintf ( buffer , pzMessage , PlayerName ( nKiller ) , PlayerName ( nVictim ) ) ;
2019-09-19 22:42:45 +00:00
if ( gGameOptions . nGameType > 0 & & nSound > = 0 & & pKiller = = gMe )
sndStartSample ( nSound , 255 , 2 , 0 ) ;
}
viewSetMessage ( buffer ) ;
}
void FragPlayer ( PLAYER * pPlayer , int nSprite )
{
spritetype * pSprite = NULL ;
if ( nSprite > = 0 )
pSprite = & sprite [ nSprite ] ;
if ( pSprite & & IsPlayerSprite ( pSprite ) )
{
2019-11-08 19:57:01 +00:00
PLAYER * pKiller = & gPlayer [ pSprite - > type - kDudePlayer1 ] ;
2019-09-19 22:42:45 +00:00
playerFrag ( pKiller , pPlayer ) ;
2019-10-21 19:46:41 +00:00
int nTeam1 = pKiller - > teamId & 1 ;
int nTeam2 = pPlayer - > teamId & 1 ;
2019-09-19 22:42:45 +00:00
if ( nTeam1 = = 0 )
{
if ( nTeam1 ! = nTeam2 )
2020-01-11 21:07:05 +00:00
evSend ( 0 , 0 , 15 , kCmdToggle ) ;
2019-09-19 22:42:45 +00:00
else
2020-01-11 21:07:05 +00:00
evSend ( 0 , 0 , 16 , kCmdToggle ) ;
2019-09-19 22:42:45 +00:00
}
else
{
if ( nTeam1 = = nTeam2 )
2020-01-11 21:07:05 +00:00
evSend ( 0 , 0 , 16 , kCmdToggle ) ;
2019-09-19 22:42:45 +00:00
else
2020-01-11 21:07:05 +00:00
evSend ( 0 , 0 , 15 , kCmdToggle ) ;
2019-09-19 22:42:45 +00:00
}
}
}
int playerDamageArmor ( PLAYER * pPlayer , DAMAGE_TYPE nType , int nDamage )
{
DAMAGEINFO * pDamageInfo = & damageInfo [ nType ] ;
2020-11-21 22:40:08 +00:00
int nArmorType = pDamageInfo - > armorType ;
2019-10-21 19:46:41 +00:00
if ( nArmorType > = 0 & & pPlayer - > armor [ nArmorType ] )
2019-09-19 22:42:45 +00:00
{
#if 0
int vbp = ( nDamage * 7 ) / 8 - nDamage / 4 ;
int v8 = pPlayer - > at33e [ nArmorType ] ;
int t = nDamage / 4 + vbp * v8 / 3200 ;
v8 - = t ;
# endif
2019-10-21 19:46:41 +00:00
int v8 = pPlayer - > armor [ nArmorType ] ;
2019-09-19 22:42:45 +00:00
int t = scale ( v8 , 0 , 3200 , nDamage / 4 , ( nDamage * 7 ) / 8 ) ;
v8 - = t ;
nDamage - = t ;
2019-10-21 19:46:41 +00:00
pPlayer - > armor [ nArmorType ] = ClipLow ( v8 , 0 ) ;
2019-09-19 22:42:45 +00:00
}
return nDamage ;
}
2020-11-21 19:10:45 +00:00
spritetype * flagDropped ( PLAYER * pPlayer , int a2 )
2019-09-19 22:42:45 +00:00
{
char buffer [ 80 ] ;
spritetype * pSprite = NULL ;
switch ( a2 )
{
2019-10-11 21:59:39 +00:00
case kItemFlagA :
2019-10-21 19:46:41 +00:00
pPlayer - > hasFlag & = ~ 1 ;
2019-10-11 21:59:39 +00:00
pSprite = actDropObject ( pPlayer - > pSprite , kItemFlagA ) ;
2019-09-19 22:42:45 +00:00
if ( pSprite )
2019-10-21 19:46:41 +00:00
pSprite - > owner = pPlayer - > used2 [ 0 ] ;
2019-09-15 11:59:27 +00:00
gBlueFlagDropped = true ;
2020-11-22 12:28:20 +00:00
sprintf ( buffer , " %s dropped Blue Flag " , PlayerName ( pPlayer - > nPlayer ) ) ;
2019-09-19 22:42:45 +00:00
sndStartSample ( 8005 , 255 , 2 , 0 ) ;
viewSetMessage ( buffer ) ;
break ;
2019-10-11 21:59:39 +00:00
case kItemFlagB :
2019-10-21 19:46:41 +00:00
pPlayer - > hasFlag & = ~ 2 ;
2019-10-11 21:59:39 +00:00
pSprite = actDropObject ( pPlayer - > pSprite , kItemFlagB ) ;
2019-09-19 22:42:45 +00:00
if ( pSprite )
2019-10-21 19:46:41 +00:00
pSprite - > owner = pPlayer - > used2 [ 1 ] ;
2019-09-15 11:59:27 +00:00
gRedFlagDropped = true ;
2020-11-22 12:28:20 +00:00
sprintf ( buffer , " %s dropped Red Flag " , PlayerName ( pPlayer - > nPlayer ) ) ;
2019-09-19 22:42:45 +00:00
sndStartSample ( 8004 , 255 , 2 , 0 ) ;
viewSetMessage ( buffer ) ;
break ;
}
return pSprite ;
}
int playerDamageSprite ( int nSource , PLAYER * pPlayer , DAMAGE_TYPE nDamageType , int nDamage )
{
2020-10-11 10:38:17 +00:00
assert ( nSource < kMaxSprites ) ;
assert ( pPlayer ! = NULL ) ;
2020-12-06 07:36:54 +00:00
if ( pPlayer - > damageControl [ nDamageType ] | | pPlayer - > godMode )
2019-09-19 22:42:45 +00:00
return 0 ;
nDamage = playerDamageArmor ( pPlayer , nDamageType , nDamage ) ;
2019-10-21 19:46:41 +00:00
pPlayer - > painEffect = ClipHigh ( pPlayer - > painEffect + ( nDamage > > 3 ) , 600 ) ;
2019-09-19 22:42:45 +00:00
spritetype * pSprite = pPlayer - > pSprite ;
XSPRITE * pXSprite = pPlayer - > pXSprite ;
int nXSprite = pSprite - > extra ;
int nXSector = sector [ pSprite - > sectnum ] . extra ;
2020-02-05 21:17:05 +00:00
DUDEINFO * pDudeInfo = getDudeInfo ( pSprite - > type ) ;
2019-09-19 22:42:45 +00:00
int nDeathSeqID = - 1 ;
2019-09-20 10:11:07 +00:00
int nKneelingPlayer = - 1 ;
2019-09-19 22:42:45 +00:00
int nSprite = pSprite - > index ;
char va = playerSeqPlaying ( pPlayer , 16 ) ;
if ( ! pXSprite - > health )
{
if ( va )
{
switch ( nDamageType )
{
case DAMAGE_TYPE_5 :
nDeathSeqID = 18 ;
sfxPlay3DSound ( pSprite , 716 , 0 , 0 ) ;
break ;
case DAMAGE_TYPE_3 :
GibSprite ( pSprite , GIBTYPE_7 , NULL , NULL ) ;
GibSprite ( pSprite , GIBTYPE_15 , NULL , NULL ) ;
pPlayer - > pSprite - > cstat | = 32768 ;
nDeathSeqID = 17 ;
break ;
default :
{
int top , bottom ;
GetSpriteExtents ( pSprite , & top , & bottom ) ;
CGibPosition gibPos ( pSprite - > x , pSprite - > y , top ) ;
CGibVelocity gibVel ( xvel [ pSprite - > index ] > > 1 , yvel [ pSprite - > index ] > > 1 , - 0xccccc ) ;
GibSprite ( pSprite , GIBTYPE_27 , & gibPos , & gibVel ) ;
GibSprite ( pSprite , GIBTYPE_7 , NULL , NULL ) ;
fxSpawnBlood ( pSprite , nDamage < < 4 ) ;
fxSpawnBlood ( pSprite , nDamage < < 4 ) ;
nDeathSeqID = 17 ;
break ;
}
}
}
}
else
{
int nHealth = pXSprite - > health - nDamage ;
pXSprite - > health = ClipLow ( nHealth , 0 ) ;
if ( pXSprite - > health > 0 & & pXSprite - > health < 16 )
{
nDamageType = DAMAGE_TYPE_2 ;
pXSprite - > health = 0 ;
nHealth = - 25 ;
}
if ( pXSprite - > health > 0 )
{
DAMAGEINFO * pDamageInfo = & damageInfo [ nDamageType ] ;
int nSound ;
if ( nDamage > = ( 10 < < 4 ) )
2020-09-01 19:27:32 +00:00
nSound = pDamageInfo - > Kills [ 0 ] ;
2019-09-19 22:42:45 +00:00
else
2020-09-01 19:27:32 +00:00
nSound = pDamageInfo - > Kills [ Random ( 3 ) ] ;
2019-10-21 19:46:41 +00:00
if ( nDamageType = = DAMAGE_TYPE_4 & & pXSprite - > medium = = kMediumWater & & ! pPlayer - > hand )
2019-09-19 22:42:45 +00:00
nSound = 714 ;
sfxPlay3DSound ( pSprite , nSound , 0 , 6 ) ;
return nDamage ;
}
sfxKill3DSound ( pPlayer - > pSprite , - 1 , 441 ) ;
2019-10-21 19:46:41 +00:00
if ( gGameOptions . nGameType = = 3 & & pPlayer - > hasFlag ) {
2020-11-21 19:10:45 +00:00
if ( pPlayer - > hasFlag & 1 ) flagDropped ( pPlayer , kItemFlagA ) ;
if ( pPlayer - > hasFlag & 2 ) flagDropped ( pPlayer , kItemFlagB ) ;
2019-09-19 22:42:45 +00:00
}
2019-10-21 19:46:41 +00:00
pPlayer - > deathTime = 0 ;
pPlayer - > qavLoop = 0 ;
pPlayer - > curWeapon = 0 ;
pPlayer - > fraggerId = nSource ;
pPlayer - > voodooTargets = 0 ;
2019-09-19 22:42:45 +00:00
if ( nDamageType = = DAMAGE_TYPE_3 & & nDamage < ( 9 < < 4 ) )
nDamageType = DAMAGE_TYPE_0 ;
switch ( nDamageType )
{
case DAMAGE_TYPE_3 :
sfxPlay3DSound ( pSprite , 717 , 0 , 0 ) ;
GibSprite ( pSprite , GIBTYPE_7 , NULL , NULL ) ;
GibSprite ( pSprite , GIBTYPE_15 , NULL , NULL ) ;
pPlayer - > pSprite - > cstat | = 32768 ;
nDeathSeqID = 2 ;
break ;
case DAMAGE_TYPE_1 :
sfxPlay3DSound ( pSprite , 718 , 0 , 0 ) ;
nDeathSeqID = 3 ;
break ;
case DAMAGE_TYPE_4 :
nDeathSeqID = 1 ;
break ;
default :
if ( nHealth < - 20 & & gGameOptions . nGameType > = 2 & & Chance ( 0x4000 ) )
{
DAMAGEINFO * pDamageInfo = & damageInfo [ nDamageType ] ;
sfxPlay3DSound ( pSprite , pDamageInfo - > at10 [ 0 ] , 0 , 2 ) ;
nDeathSeqID = 16 ;
2019-09-20 10:11:07 +00:00
nKneelingPlayer = nPlayerKneelClient ;
2019-10-19 19:11:39 +00:00
powerupActivate ( pPlayer , kPwUpDeliriumShroom ) ;
2019-09-19 22:42:45 +00:00
pXSprite - > target = nSource ;
2019-10-11 21:59:39 +00:00
evPost ( pSprite - > index , 3 , 15 , kCallbackFinishHim ) ;
2019-09-19 22:42:45 +00:00
}
else
{
sfxPlay3DSound ( pSprite , 716 , 0 , 0 ) ;
nDeathSeqID = 1 ;
}
break ;
}
}
if ( nDeathSeqID < 0 )
return nDamage ;
if ( nDeathSeqID ! = 16 )
{
powerupClear ( pPlayer ) ;
if ( nXSector > 0 & & xsector [ nXSector ] . Exit )
2020-01-11 21:07:05 +00:00
trTriggerSector ( pSprite - > sectnum , & xsector [ nXSector ] , kCmdSectorExit ) ;
2019-09-30 07:18:01 +00:00
pSprite - > flags | = 7 ;
2019-09-19 22:42:45 +00:00
for ( int p = connecthead ; p > = 0 ; p = connectpoint2 [ p ] )
{
2019-10-21 19:46:41 +00:00
if ( gPlayer [ p ] . fraggerId = = nSprite & & gPlayer [ p ] . deathTime > 0 )
gPlayer [ p ] . fraggerId = - 1 ;
2019-09-19 22:42:45 +00:00
}
FragPlayer ( pPlayer , nSource ) ;
2020-01-11 21:07:05 +00:00
trTriggerSprite ( nSprite , pXSprite , kCmdOff ) ;
2019-09-19 22:42:45 +00:00
}
2020-10-11 10:38:17 +00:00
assert ( getSequence ( pDudeInfo - > seqStartID + nDeathSeqID ) ! = NULL ) ;
2019-09-20 10:11:07 +00:00
seqSpawn ( pDudeInfo - > seqStartID + nDeathSeqID , 3 , nXSprite , nKneelingPlayer ) ;
2019-09-19 22:42:45 +00:00
return nDamage ;
}
int UseAmmo ( PLAYER * pPlayer , int nAmmoType , int nDec )
{
if ( gInfiniteAmmo )
return 9999 ;
if ( nAmmoType = = - 1 )
return 9999 ;
2019-10-25 20:53:41 +00:00
pPlayer - > ammoCount [ nAmmoType ] = ClipLow ( pPlayer - > ammoCount [ nAmmoType ] - nDec , 0 ) ;
return pPlayer - > ammoCount [ nAmmoType ] ;
2019-09-19 22:42:45 +00:00
}
2020-11-21 19:10:45 +00:00
void voodooTarget ( PLAYER * pPlayer )
2019-09-19 22:42:45 +00:00
{
2019-10-21 19:46:41 +00:00
int v4 = pPlayer - > aim . dz ;
int dz = pPlayer - > zWeapon - pPlayer - > pSprite - > z ;
2019-09-19 22:42:45 +00:00
if ( UseAmmo ( pPlayer , 9 , 0 ) < 8 )
{
2019-10-21 19:46:41 +00:00
pPlayer - > voodooTargets = 0 ;
2019-09-19 22:42:45 +00:00
return ;
}
for ( int i = 0 ; i < 4 ; i + + )
{
2019-10-21 19:46:41 +00:00
int ang1 = ( pPlayer - > voodooVar1 + pPlayer - > vodooVar2 ) & 2047 ;
2020-09-01 13:00:35 +00:00
actFireVector ( pPlayer - > pSprite , 0 , dz , CosScale16 ( ang1 ) , SinScale16 ( ang1 ) , v4 , VECTOR_TYPE_21 ) ;
2019-10-21 19:46:41 +00:00
int ang2 = ( pPlayer - > voodooVar1 + 2048 - pPlayer - > vodooVar2 ) & 2047 ;
2020-09-01 13:00:35 +00:00
actFireVector ( pPlayer - > pSprite , 0 , dz , CosScale16 ( ang2 ) , SinScale16 ( ang2 ) , v4 , VECTOR_TYPE_21 ) ;
2019-09-19 22:42:45 +00:00
}
2019-10-21 19:46:41 +00:00
pPlayer - > voodooTargets = ClipLow ( pPlayer - > voodooTargets - 1 , 0 ) ;
2019-09-19 22:42:45 +00:00
}
void playerLandingSound ( PLAYER * pPlayer )
{
static int surfaceSound [ ] = {
- 1 ,
600 ,
601 ,
602 ,
603 ,
604 ,
605 ,
605 ,
605 ,
600 ,
605 ,
605 ,
605 ,
604 ,
603
} ;
spritetype * pSprite = pPlayer - > pSprite ;
SPRITEHIT * pHit = & gSpriteHit [ pSprite - > extra ] ;
if ( pHit - > florhit )
{
2019-09-22 07:53:42 +00:00
if ( ! gGameOptions . bFriendlyFire & & IsTargetTeammate ( pPlayer , & sprite [ pHit - > florhit & 0x3fff ] ) )
return ;
2019-09-19 22:42:45 +00:00
char nSurf = tileGetSurfType ( pHit - > florhit ) ;
if ( nSurf )
sfxPlay3DSound ( pSprite , surfaceSound [ nSurf ] , - 1 , 0 ) ;
}
}
2020-11-07 14:16:12 +00:00
void PlayerSurvive ( int , DBloodActor * actor )
2019-09-19 22:42:45 +00:00
{
2020-11-07 14:16:12 +00:00
XSPRITE * pXSprite = & actor - > x ( ) ;
spritetype * pSprite = & actor - > s ( ) ;
2019-09-19 22:42:45 +00:00
char buffer [ 80 ] ;
actHealDude ( pXSprite , 1 , 2 ) ;
if ( gGameOptions . nGameType > 0 & & numplayers > 1 )
{
sfxPlay3DSound ( pSprite , 3009 , 0 , 6 ) ;
if ( IsPlayerSprite ( pSprite ) )
{
PLAYER * pPlayer = & gPlayer [ pSprite - > type - kDudePlayer1 ] ;
if ( pPlayer = = gMe )
2019-12-09 01:01:30 +00:00
viewSetMessage ( GStrings ( " TXT_LIVEAGAIM " ) ) ;
2019-09-19 22:42:45 +00:00
else
{
2020-11-22 12:28:20 +00:00
sprintf ( buffer , " %s lives again! " , PlayerName ( pPlayer - > nPlayer ) ) ;
2019-09-19 22:42:45 +00:00
viewSetMessage ( buffer ) ;
}
2020-08-26 14:48:33 +00:00
pPlayer - > newWeapon = 1 ;
2019-09-19 22:42:45 +00:00
}
}
}
2020-11-07 14:16:12 +00:00
void PlayerKneelsOver ( int , DBloodActor * actor )
2019-09-19 22:42:45 +00:00
{
2020-11-07 14:16:12 +00:00
XSPRITE * pXSprite = & actor - > x ( ) ;
2019-09-19 22:42:45 +00:00
for ( int p = connecthead ; p > = 0 ; p = connectpoint2 [ p ] )
{
if ( gPlayer [ p ] . pXSprite = = pXSprite )
{
PLAYER * pPlayer = & gPlayer [ p ] ;
2019-10-21 19:46:41 +00:00
playerDamageSprite ( pPlayer - > fraggerId , pPlayer , DAMAGE_TYPE_5 , 500 < < 4 ) ;
2019-09-19 22:42:45 +00:00
return ;
}
}
}
2020-11-22 13:24:55 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
FSerializer & Serialize ( FSerializer & arc , const char * keyname , Aim & w , Aim * def )
2019-09-19 22:42:45 +00:00
{
2020-11-22 13:24:55 +00:00
if ( arc . BeginObject ( keyname ) )
{
arc ( " x " , w . dx )
( " y " , w . dx )
( " z " , w . dx )
. EndObject ( ) ;
}
return arc ;
}
FSerializer & Serialize ( FSerializer & arc , const char * keyname , PACKINFO & w , PACKINFO * def )
{
if ( arc . BeginObject ( keyname ) )
{
arc ( " isactive " , w . isActive )
( " curamount " , w . curAmount )
. EndObject ( ) ;
}
return arc ;
}
2019-09-19 22:42:45 +00:00
2020-11-22 13:24:55 +00:00
FSerializer & Serialize ( FSerializer & arc , const char * keyname , POSTURE & w , POSTURE * def )
2019-09-19 22:42:45 +00:00
{
2020-11-22 13:24:55 +00:00
if ( arc . BeginObject ( keyname ) )
{
arc ( " frontaccel " , w . frontAccel , def - > frontAccel )
( " sideaccel " , w . sideAccel , def - > sideAccel )
( " backaccel " , w . backAccel , def - > backAccel )
( " pace0 " , w . pace [ 0 ] , def - > pace [ 0 ] )
( " pace1 " , w . pace [ 1 ] , def - > pace [ 1 ] )
( " bobv " , w . bobV , def - > bobV )
( " bobh " , w . bobH , def - > bobH )
( " swayv " , w . swayV , def - > swayV )
( " swayh " , w . swayH , def - > swayH )
( " eyeabovez " , w . eyeAboveZ , def - > eyeAboveZ )
( " weaponabovez " , w . weaponAboveZ , def - > weaponAboveZ )
( " xoffset " , w . xOffset , def - > xOffset )
( " zoffset " , w . zOffset , def - > zOffset )
( " normaljumpz " , w . normalJumpZ , def - > normalJumpZ )
( " pwupjumpz " , w . pwupJumpZ , def - > pwupJumpZ )
. EndObject ( ) ;
}
return arc ;
}
2020-02-07 19:47:43 +00:00
2020-11-22 13:24:55 +00:00
FSerializer & Serialize ( FSerializer & arc , const char * keyname , PLAYER & w , PLAYER * def )
{
if ( arc . isReading ( ) ) playerResetPosture ( & w ) ;
if ( arc . BeginObject ( keyname ) )
{
arc ( " spritenum " , w . nSprite )
( " horizon " , w . horizon )
( " angle " , w . angle )
( " newweapon " , w . newWeapon )
( " used1 " , w . used1 )
( " weaponqav " , w . weaponQav )
( " qavcallback " , w . qavCallback )
( " isrunning " , w . isRunning )
( " posture " , w . posture )
( " sceneqav " , w . sceneQav )
( " bobphase " , w . bobPhase )
( " bobamp " , w . bobAmp )
( " bobheight " , w . bobHeight )
( " bobwidth " , w . bobWidth )
( " swayphase " , w . swayPhase )
( " swayamp " , w . swayAmp )
( " swayheight " , w . swayHeight )
( " swaywidth " , w . swayWidth )
( " nplayer " , w . nPlayer )
( " lifemode " , w . lifeMode )
( " bloodlust " , w . bloodlust )
( " zview " , w . zView )
( " zviewvel " , w . zViewVel )
( " zweapon " , w . zWeapon )
( " zweaponvel " , w . zWeaponVel )
( " slope " , w . slope )
( " underwater " , w . isUnderwater )
. Array ( " haskey " , w . hasKey , 8 )
( " hasflag " , w . hasFlag )
. Array ( " used2 " , w . used2 , 8 )
. Array ( " dmgcontrol " , w . damageControl , 7 )
( " curweapon " , w . curWeapon )
( " nextweapon " , w . nextWeapon )
( " weapontimer " , w . weaponTimer )
( " weaponstate " , w . weaponState )
( " weaponammo " , w . weaponAmmo )
. Array ( " hasweapon " , w . hasWeapon , countof ( w . hasWeapon ) )
. Array ( " weaponmode " , w . weaponMode , countof ( w . weaponMode ) )
. Array ( " weaponorder " , & w . weaponOrder [ 0 ] [ 0 ] , 14 * 2 )
. Array ( " ammocount " , w . ammoCount , countof ( w . ammoCount ) )
( " qavloop " , w . qavLoop )
( " fusetime " , w . fuseTime )
( " throwtime " , w . throwTime )
( " throwpower " , w . throwPower )
( " aim " , w . aim )
( " relaim " , w . relAim )
( " aimtarget " , w . aimTarget )
( " aimtargetscount " , w . aimTargetsCount )
. Array ( " aimtargets " , w . aimTargets , countof ( w . aimTargets ) )
( " deathtime " , w . deathTime )
. Array ( " pwuptime " , w . pwUpTime , countof ( w . pwUpTime ) )
( " fragcount " , w . fragCount )
. Array ( " fraginfo " , w . fragInfo , countof ( w . fragInfo ) )
( " teamid " , w . teamId )
( " fraggerid " , w . fraggerId )
( " undserwatertime " , w . underwaterTime )
( " bubbletime " , w . bubbleTime )
( " resttime " , w . restTime )
( " kickpower " , w . kickPower )
( " laughcount " , w . laughCount )
( " godmode " , w . godMode )
( " fallscream " , w . fallScream )
( " cantjump " , w . cantJump )
( " packitemtime " , w . packItemTime )
( " packitemid " , w . packItemId )
. Array ( " packslots " , w . packSlots , countof ( w . packSlots ) )
. Array ( " armor " , w . armor , countof ( w . armor ) )
( " voodootarget " , w . voodooTarget )
( " voodootargets " , w . voodooTargets )
( " voodoovar1 " , w . voodooVar1 )
( " voodoovar2 " , w . vodooVar2 )
( " flickereffect " , w . flickerEffect )
( " tilteffect " , w . tiltEffect )
( " visibility " , w . visibility )
( " paineffect " , w . painEffect )
( " blindeffect " , w . blindEffect )
( " chokeeffect " , w . chokeEffect )
( " handtime " , w . handTime )
( " hand " , w . hand )
( " pickupeffect " , w . pickupEffect )
( " flasheffect " , w . flashEffect )
( " quakeeffect " , w . quakeEffect )
( " player_par " , w . player_par )
( " waterpal " , w . nWaterPal )
2020-11-23 09:18:47 +00:00
. Array ( " posturedata " , & w . pPosture [ 0 ] [ 0 ] , & gPostureDefaults [ 0 ] [ 0 ] , kModeMax * kPostureMax ) // only save actual changes in this.
2020-11-22 13:24:55 +00:00
. EndObject ( ) ;
}
return arc ;
}
# ifdef NOONE_EXTENSIONS
FSerializer & Serialize ( FSerializer & arc , const char * keyname , TRPLAYERCTRL & w , TRPLAYERCTRL * def )
{
if ( arc . BeginObject ( keyname ) )
{
arc ( " index " , w . qavScene . index )
( " dummy " , w . qavScene . dummy )
. EndObject ( ) ;
}
if ( arc . isReading ( ) ) w . qavScene . qavResrc = nullptr ;
return arc ;
}
# endif
void SerializePlayers ( FSerializer & arc )
{
if ( arc . BeginObject ( " players " ) )
{
arc ( " numplayers " , gNetPlayers )
. Array ( " teamscore " , team_score , gNetPlayers )
. Array ( " players " , gPlayer , gNetPlayers )
# ifdef NOONE_EXTENSIONS
. Array ( " playerctrl " , gPlayerCtrl , gNetPlayers )
# endif
. EndObject ( ) ;
}
if ( arc . isReading ( ) )
{
for ( int i = 0 ; i < gNetPlayers ; i + + )
{
gPlayer [ i ] . pSprite = & sprite [ gPlayer [ i ] . nSprite ] ;
gPlayer [ i ] . pXSprite = & xsprite [ gPlayer [ i ] . pSprite - > extra ] ;
gPlayer [ i ] . pDudeInfo = & dudeInfo [ gPlayer [ i ] . pSprite - > type - kDudeBase ] ;
# ifdef NOONE_EXTENSIONS
// load qav scene
if ( gPlayer [ i ] . sceneQav ! = - 1 )
{
2020-02-07 19:47:43 +00:00
QAV * pQav = playerQavSceneLoad ( gPlayer [ i ] . sceneQav ) ;
2020-11-22 13:24:55 +00:00
if ( pQav )
{
2019-11-08 19:57:01 +00:00
gPlayerCtrl [ i ] . qavScene . qavResrc = pQav ;
gPlayerCtrl [ i ] . qavScene . qavResrc - > Preload ( ) ;
2020-11-22 13:24:55 +00:00
}
else
{
2019-11-08 19:57:01 +00:00
gPlayer [ i ] . sceneQav = - 1 ;
}
}
2020-11-22 13:24:55 +00:00
# endif
2019-11-08 19:57:01 +00:00
}
2019-09-19 22:42:45 +00:00
}
}
2019-09-22 06:39:22 +00:00
END_BLD_NS