2019-11-20 16:21:32 +00:00
//-------------------------------------------------------------------------
/*
Copyright ( C ) 2010 - 2019 EDuke32 developers and contributors
Copyright ( C ) 2019 sirlemonhead , Nuke . YKT
This file is part of PCExhumed .
PCExhumed 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-11-22 23:11:37 +00:00
# include "ns.h"
2019-08-26 03:59:14 +00:00
# include "player.h"
2020-08-18 07:52:08 +00:00
# include "aistuff.h"
2019-08-26 03:59:14 +00:00
# include "exhumed.h"
# include "names.h"
# include "engine.h"
# include "sequence.h"
# include "view.h"
# include "status.h"
# include "sound.h"
# include "sound.h"
2020-05-24 05:58:56 +00:00
# include "buildtiles.h"
2020-08-22 18:14:00 +00:00
# include "gstrings.h"
2020-08-23 10:26:52 +00:00
# include "gamestate.h"
2020-08-23 14:24:54 +00:00
# include "mapinfo.h"
2020-09-06 18:49:43 +00:00
# include "automap.h"
2021-01-04 19:44:46 +00:00
# include "interpolate.h"
2020-09-06 18:49:43 +00:00
2019-08-26 03:59:14 +00:00
# include <assert.h>
# include <stdio.h>
# include <string.h>
2019-11-22 23:11:37 +00:00
BEGIN_PS_NS
2023-03-23 09:50:08 +00:00
void doPlayerItemPickups ( Player * const pPlayer ) ;
2019-08-26 03:59:14 +00:00
2020-10-11 09:33:28 +00:00
static actionSeq PlayerSeq [ ] = {
2019-08-31 07:47:15 +00:00
{ 18 , 0 } , { 0 , 0 } , { 9 , 0 } , { 27 , 0 } , { 63 , 0 } ,
2019-11-20 16:21:32 +00:00
{ 72 , 0 } , { 54 , 0 } , { 45 , 0 } , { 54 , 0 } , { 81 , 0 } ,
{ 90 , 0 } , { 99 , 0 } , { 108 , 0 } , { 8 , 0 } , { 0 , 0 } ,
{ 139 , 0 } , { 117 , 1 } , { 119 , 1 } , { 120 , 1 } , { 121 , 1 } ,
2019-08-31 07:47:15 +00:00
{ 122 , 1 }
2019-08-26 03:59:14 +00:00
} ;
2021-11-21 18:24:46 +00:00
static const uint8_t nHeightTemplate [ ] = { 0 , 0 , 0 , 0 , 0 , 0 , 7 , 7 , 7 , 9 , 9 , 9 , 9 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ;
2019-08-26 03:59:14 +00:00
2022-09-07 05:25:34 +00:00
static constexpr double nActionEyeLevel [ ] = {
- 55.0 , - 55.0 , - 55.0 , - 55.0 , - 55.0 , - 55.0 , - 32.5 ,
- 32.5 , - 32.5 , - 32.5 , - 32.5 , - 32.5 , - 32.5 , - 55.0 ,
- 55.0 , - 55.0 , - 55.0 , - 55.0 , - 55.0 , - 55.0 , - 55.0
2019-08-26 03:59:14 +00:00
} ;
2021-11-21 18:24:46 +00:00
static const uint16_t nGunLotag [ ] = { 52 , 53 , 54 , 55 , 56 , 57 } ;
static const uint16_t nGunPicnum [ ] = { 57 , 488 , 490 , 491 , 878 , 899 , 3455 } ;
2019-08-26 03:59:14 +00:00
2021-11-21 18:24:46 +00:00
static const int16_t nItemText [ ] = {
2019-08-31 07:47:15 +00:00
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , 18 , 20 , 19 , 13 , - 1 , 10 , 1 , 0 , 2 , - 1 , 3 ,
- 1 , 4 , 5 , 9 , 6 , 7 , 8 , - 1 , 11 , - 1 , 13 , 12 , 14 , 15 , - 1 , 16 , 17 ,
- 1 , - 1 , - 1 , 21 , 22 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , 23 , 24 , 25 , 26 , 27 ,
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1
2019-08-26 03:59:14 +00:00
} ;
2023-03-23 09:50:08 +00:00
extern int nStatusSeqOffset ;
int obobangle = 0 , bobangle = 0 ;
2019-08-26 03:59:14 +00:00
int nLocalPlayer = 0 ;
Player PlayerList [ kMaxPlayers ] ;
2021-12-07 17:53:02 +00:00
TObjPtr < DExhumedActor * > nNetStartSprite [ kMaxPlayers ] = { } ;
2022-09-10 17:18:09 +00:00
double nStandHeight ;
2021-11-21 20:09:27 +00:00
int PlayerCount ;
int nNetStartSprites ;
int nCurStartSprite ;
2019-08-26 03:59:14 +00:00
2021-12-07 17:53:02 +00:00
2022-09-11 06:09:26 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2021-12-07 17:53:02 +00:00
size_t MarkPlayers ( )
{
for ( auto & p : PlayerList )
{
GC : : Mark ( p . pActor ) ;
GC : : Mark ( p . pDoppleSprite ) ;
GC : : Mark ( p . pPlayerFloorSprite ) ;
GC : : Mark ( p . pPlayerGrenade ) ;
2023-03-13 09:10:47 +00:00
GC : : Mark ( p . pTarget ) ;
2021-12-07 17:53:02 +00:00
}
GC : : MarkArray ( nNetStartSprite , kMaxPlayers ) ;
2023-03-13 09:10:47 +00:00
return 6 * kMaxPlayers ;
2021-12-07 17:53:02 +00:00
}
2022-09-11 06:09:26 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2022-09-07 07:48:05 +00:00
void SetSavePoint ( int nPlayer , const DVector3 & pos , sectortype * pSector , DAngle nAngle )
2019-08-26 03:59:14 +00:00
{
2022-08-23 21:36:23 +00:00
PlayerList [ nPlayer ] . sPlayerSave . pos = pos ;
2021-11-22 23:20:15 +00:00
PlayerList [ nPlayer ] . sPlayerSave . pSector = pSector ;
2021-10-21 10:51:16 +00:00
PlayerList [ nPlayer ] . sPlayerSave . nAngle = nAngle ;
2019-08-26 03:59:14 +00:00
}
2022-09-11 06:09:26 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2019-08-26 03:59:14 +00:00
void InitPlayer ( )
{
2019-08-31 07:47:15 +00:00
for ( int i = 0 ; i < kMaxPlayers ; i + + ) {
2021-10-21 20:39:17 +00:00
PlayerList [ i ] . pActor = nullptr ;
2022-12-09 06:55:13 +00:00
PlayerList [ i ] . Angles = { } ;
2022-01-03 21:13:45 +00:00
PlayerList [ i ] . pPlayerPushSect = nullptr ;
PlayerList [ i ] . pPlayerViewSect = nullptr ;
2019-08-31 07:47:15 +00:00
}
2019-08-26 03:59:14 +00:00
}
2021-11-16 17:50:02 +00:00
void InitPlayerKeys ( int nPlayer )
2019-08-26 03:59:14 +00:00
{
2019-08-31 07:47:15 +00:00
PlayerList [ nPlayer ] . keys = 0 ;
2019-08-26 03:59:14 +00:00
}
2022-09-11 06:09:26 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2021-11-16 17:50:02 +00:00
void InitPlayerInventory ( int nPlayer )
2019-08-26 03:59:14 +00:00
{
2019-08-31 07:47:15 +00:00
memset ( & PlayerList [ nPlayer ] , 0 , sizeof ( Player ) ) ;
2019-08-26 03:59:14 +00:00
2021-05-13 11:44:58 +00:00
PlayerList [ nPlayer ] . nItem = - 1 ;
2021-10-21 10:51:16 +00:00
PlayerList [ nPlayer ] . nPlayerSwear = 4 ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
ResetPlayerWeapons ( nPlayer ) ;
2019-08-26 03:59:14 +00:00
2021-05-13 17:06:38 +00:00
PlayerList [ nPlayer ] . nLives = kDefaultLives ;
2019-08-26 03:59:14 +00:00
2021-10-21 20:39:17 +00:00
PlayerList [ nPlayer ] . pActor = nullptr ;
2022-12-09 06:55:13 +00:00
PlayerList [ nPlayer ] . Angles = { } ;
2019-08-31 07:47:15 +00:00
PlayerList [ nPlayer ] . nRun = - 1 ;
2019-08-26 03:59:14 +00:00
2021-10-21 10:51:16 +00:00
PlayerList [ nPlayer ] . nPistolClip = 6 ;
PlayerList [ nPlayer ] . nPlayerClip = 0 ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
PlayerList [ nPlayer ] . nCurrentWeapon = 0 ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
if ( nPlayer = = nLocalPlayer ) {
2020-08-24 17:54:26 +00:00
automapMode = am_off ;
2019-08-31 07:47:15 +00:00
}
2019-08-26 03:59:14 +00:00
2021-10-21 10:51:16 +00:00
PlayerList [ nPlayer ] . nPlayerScore = 0 ;
2019-08-26 03:59:14 +00:00
2022-12-06 17:30:57 +00:00
auto pixels = GetRawPixels ( tileGetTextureID ( kTile3571 + nPlayer ) ) ;
2019-08-26 03:59:14 +00:00
2021-10-21 10:51:16 +00:00
PlayerList [ nPlayer ] . nPlayerColor = pixels [ tileWidth ( nPlayer + kTile3571 ) * tileHeight ( nPlayer + kTile3571 ) / 2 ] ;
2019-08-26 03:59:14 +00:00
}
2022-09-11 06:09:26 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2021-11-21 19:48:11 +00:00
int GetPlayerFromActor ( DExhumedActor * pActor )
2019-08-26 03:59:14 +00:00
{
2022-05-23 22:30:41 +00:00
return RunData [ pActor - > spr . intowner ] . nObjIndex ;
2019-08-26 03:59:14 +00:00
}
2022-09-11 06:09:26 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2021-11-16 17:50:02 +00:00
void RestartPlayer ( int nPlayer )
2019-08-26 03:59:14 +00:00
{
2020-10-13 22:19:39 +00:00
auto plr = & PlayerList [ nPlayer ] ;
2021-12-26 07:47:54 +00:00
auto pActor = plr - > pActor ;
2021-12-07 17:53:02 +00:00
DExhumedActor * pDopSprite = plr - > pDoppleSprite ;
2020-10-13 22:19:39 +00:00
2021-10-21 17:44:53 +00:00
DExhumedActor * floorsprt ;
2020-10-13 22:19:39 +00:00
2023-03-23 08:14:26 +00:00
plr - > nPlayer = nPlayer ;
2021-10-21 19:20:54 +00:00
if ( pActor )
2020-10-13 22:19:39 +00:00
{
2022-05-23 22:30:41 +00:00
runlist_DoSubRunRec ( pActor - > spr . intowner ) ;
2021-12-23 18:01:43 +00:00
runlist_FreeRun ( pActor - > spr . lotag - 1 ) ;
2020-10-13 22:19:39 +00:00
2021-10-21 19:20:54 +00:00
ChangeActorStat ( pActor , 0 ) ;
2020-10-13 22:19:39 +00:00
2021-10-21 20:39:17 +00:00
plr - > pActor = nullptr ;
2022-12-09 06:55:13 +00:00
plr - > Angles = { } ;
2020-10-13 22:19:39 +00:00
2021-12-07 17:53:02 +00:00
DExhumedActor * pFloorSprite = plr - > pPlayerFloorSprite ;
2021-10-21 17:44:53 +00:00
if ( pFloorSprite ! = nullptr ) {
DeleteActor ( pFloorSprite ) ;
2020-10-13 22:19:39 +00:00
}
2021-10-21 17:54:39 +00:00
if ( pDopSprite )
2020-10-13 22:19:39 +00:00
{
2022-05-23 22:30:41 +00:00
runlist_DoSubRunRec ( pDopSprite - > spr . intowner ) ;
2021-12-23 18:01:43 +00:00
runlist_FreeRun ( pDopSprite - > spr . lotag - 1 ) ;
2021-10-21 17:54:39 +00:00
DeleteActor ( pDopSprite ) ;
2020-10-13 22:19:39 +00:00
}
}
2021-10-21 19:20:54 +00:00
pActor = GrabBody ( ) ;
2020-10-13 22:19:39 +00:00
2021-11-22 23:20:15 +00:00
ChangeActorSect ( pActor , plr - > sPlayerSave . pSector ) ;
2021-10-21 19:20:54 +00:00
ChangeActorStat ( pActor , 100 ) ;
2020-10-13 22:19:39 +00:00
2021-12-30 15:51:56 +00:00
auto pDActor = insertActor ( pActor - > sector ( ) , 100 ) ;
2021-10-21 19:20:54 +00:00
plr - > pDoppleSprite = pDActor ;
2020-10-13 22:19:39 +00:00
if ( nTotalPlayers > 1 )
{
2021-12-07 17:53:02 +00:00
DExhumedActor * nNStartSprite = nNetStartSprite [ nCurStartSprite ] ;
2020-10-13 22:19:39 +00:00
nCurStartSprite + + ;
if ( nCurStartSprite > = nNetStartSprites ) {
nCurStartSprite = 0 ;
}
2022-10-05 15:38:44 +00:00
pActor - > spr . pos = nNStartSprite - > spr . pos ;
2021-12-30 15:51:56 +00:00
ChangeActorSect ( pActor , nNStartSprite - > sector ( ) ) ;
2022-11-27 00:34:39 +00:00
pActor - > spr . Angles . Yaw = nNStartSprite - > spr . Angles . Yaw ;
2021-12-23 18:01:43 +00:00
2021-12-30 15:51:56 +00:00
floorsprt = insertActor ( pActor - > sector ( ) , 0 ) ;
2021-12-23 18:01:43 +00:00
2022-10-05 15:38:44 +00:00
floorsprt - > spr . pos = pActor - > spr . pos ;
2022-10-07 21:52:29 +00:00
floorsprt - > spr . scale = DVector2 ( 1 , 1 ) ;
2021-12-23 18:01:43 +00:00
floorsprt - > spr . cstat = CSTAT_SPRITE_ALIGNMENT_FLOOR ;
floorsprt - > spr . picnum = nPlayer + kTile3571 ;
2020-10-13 22:19:39 +00:00
}
else
{
2022-08-23 21:36:23 +00:00
pActor - > spr . pos . XY ( ) = plr - > sPlayerSave . pos . XY ( ) ;
pActor - > spr . pos . Z = plr - > sPlayerSave . pSector - > floorz ;
2022-11-27 00:34:39 +00:00
pActor - > spr . Angles . Yaw = plr - > sPlayerSave . nAngle ;
2020-10-13 22:19:39 +00:00
2021-10-21 17:44:53 +00:00
floorsprt = nullptr ;
2020-10-13 22:19:39 +00:00
}
2022-11-27 00:34:39 +00:00
pActor - > backuploc ( ) ;
2020-10-13 22:19:39 +00:00
2021-10-21 19:20:54 +00:00
plr - > pPlayerFloorSprite = floorsprt ;
2020-10-13 22:19:39 +00:00
2021-12-23 18:01:43 +00:00
pActor - > spr . cstat = CSTAT_SPRITE_BLOCK_ALL ;
pActor - > spr . shade = - 12 ;
2022-10-04 17:13:26 +00:00
pActor - > clipdist = 14.5 ;
2021-12-23 18:01:43 +00:00
pActor - > spr . pal = 0 ;
2022-10-07 21:52:29 +00:00
pActor - > spr . scale = DVector2 ( 0.625 , 0.625 ) ;
2021-12-23 18:01:43 +00:00
pActor - > spr . xoffset = 0 ;
pActor - > spr . yoffset = 0 ;
pActor - > spr . picnum = seq_GetSeqPicnum ( kSeqJoe , 18 , 0 ) ;
2020-10-13 22:19:39 +00:00
2022-09-03 08:02:25 +00:00
pActor - > vel . X = 0 ;
pActor - > vel . Y = 0 ;
pActor - > vel . Z = 0 ;
2019-08-31 07:47:15 +00:00
2022-09-10 19:24:40 +00:00
nStandHeight = GetActorHeight ( pActor ) ;
2019-08-31 07:47:15 +00:00
2021-12-23 18:01:43 +00:00
pActor - > spr . hitag = 0 ;
pActor - > spr . extra = - 1 ;
pActor - > spr . lotag = runlist_HeadRun ( ) + 1 ;
2020-10-13 22:19:39 +00:00
2022-10-05 15:38:44 +00:00
pDActor - > spr . pos = pActor - > spr . pos ;
2022-10-07 21:41:15 +00:00
pDActor - > spr . scale = pActor - > spr . scale ;
2021-12-23 18:01:43 +00:00
pDActor - > spr . xoffset = 0 ;
pDActor - > spr . yoffset = 0 ;
pDActor - > spr . shade = pActor - > spr . shade ;
2022-11-25 12:13:50 +00:00
pDActor - > spr . Angles . Yaw = pActor - > spr . Angles . Yaw ;
2021-12-23 18:01:43 +00:00
pDActor - > spr . cstat = pActor - > spr . cstat ;
2019-08-26 03:59:14 +00:00
2021-12-23 18:01:43 +00:00
pDActor - > spr . lotag = runlist_HeadRun ( ) + 1 ;
2019-08-26 03:59:14 +00:00
2020-10-13 22:19:39 +00:00
plr - > nAction = 0 ;
plr - > nHealth = 800 ; // TODO - define
2019-08-26 03:59:14 +00:00
2020-10-13 22:19:39 +00:00
if ( nNetPlayerCount ) {
plr - > nHealth = 1600 ; // TODO - define
}
2019-08-26 03:59:14 +00:00
2021-11-21 18:33:51 +00:00
plr - > nSeqSize = 0 ;
2021-10-21 20:39:17 +00:00
plr - > pActor = pActor ;
2022-12-09 06:55:13 +00:00
plr - > Angles = { } ;
plr - > Angles . initialize ( plr - > pActor ) ;
2020-10-13 22:19:39 +00:00
plr - > bIsMummified = false ;
2019-08-31 07:47:15 +00:00
2020-10-13 22:19:39 +00:00
if ( plr - > invincibility > = 0 ) {
plr - > invincibility = 0 ;
}
2021-10-21 19:20:54 +00:00
plr - > nTorch = 0 ;
2020-10-13 22:19:39 +00:00
plr - > nMaskAmount = 0 ;
SetTorch ( nPlayer , 0 ) ;
2021-10-21 19:20:54 +00:00
plr - > nInvisible = 0 ;
2020-10-13 22:19:39 +00:00
plr - > bIsFiring = 0 ;
2021-11-21 18:33:51 +00:00
plr - > nSeqSize2 = 0 ;
2021-11-22 23:20:15 +00:00
plr - > pPlayerViewSect = plr - > sPlayerSave . pSector ;
2021-11-21 18:33:51 +00:00
plr - > nState = 0 ;
2020-10-13 22:19:39 +00:00
2021-10-21 19:20:54 +00:00
plr - > nDouble = 0 ;
2019-08-31 07:47:15 +00:00
2020-10-13 22:19:39 +00:00
plr - > nSeq = kSeqJoe ;
2021-10-21 19:20:54 +00:00
plr - > nPlayerPushSound = - 1 ;
2019-08-31 07:47:15 +00:00
2021-11-21 18:33:51 +00:00
plr - > nNextWeapon = - 1 ;
2019-08-26 03:59:14 +00:00
2020-10-13 22:19:39 +00:00
if ( plr - > nCurrentWeapon = = 7 ) {
2021-11-21 18:33:51 +00:00
plr - > nCurrentWeapon = plr - > nLastWeapon ;
2020-10-13 22:19:39 +00:00
}
2019-08-31 07:47:15 +00:00
2021-11-21 18:33:51 +00:00
plr - > nLastWeapon = 0 ;
2020-10-13 22:19:39 +00:00
plr - > nAir = 100 ;
2019-08-26 03:59:14 +00:00
2021-05-02 13:54:19 +00:00
if ( ! ( currentLevel - > gameflags & LEVEL_EX_MULTI ) )
2020-10-13 22:19:39 +00:00
{
RestoreMinAmmo ( nPlayer ) ;
}
else
{
ResetPlayerWeapons ( nPlayer ) ;
plr - > nMagic = 0 ;
}
2019-08-26 03:59:14 +00:00
2021-10-21 19:20:54 +00:00
plr - > pPlayerGrenade = nullptr ;
2022-11-23 09:47:45 +00:00
pActor - > oviewzoffset = pActor - > viewzoffset = - 55. ;
2023-03-23 06:22:28 +00:00
plr - > dVertPan = 0 ;
2019-08-26 03:59:14 +00:00
2020-10-13 22:19:39 +00:00
nTemperature [ nPlayer ] = 0 ;
2019-08-26 03:59:14 +00:00
2022-09-09 20:59:16 +00:00
plr - > nThrust . Zero ( ) ;
2019-08-26 03:59:14 +00:00
2022-11-25 11:32:28 +00:00
plr - > nDestVertPan = plr - > pActor - > PrevAngles . Pitch = plr - > pActor - > spr . Angles . Pitch = nullAngle ;
2021-10-21 19:20:54 +00:00
plr - > nBreathTimer = 90 ;
2019-08-26 03:59:14 +00:00
2021-10-21 19:20:54 +00:00
plr - > nTauntTimer = RandomSize ( 3 ) + 3 ;
2019-08-26 03:59:14 +00:00
2022-05-23 22:30:41 +00:00
pDActor - > spr . intowner = runlist_AddRunRec ( pDActor - > spr . lotag - 1 , nPlayer , 0xA0000 ) ;
pActor - > spr . intowner = runlist_AddRunRec ( pActor - > spr . lotag - 1 , nPlayer , 0xA0000 ) ;
2019-08-26 03:59:14 +00:00
2020-10-13 22:19:39 +00:00
if ( plr - > nRun < 0 ) {
2021-10-15 16:37:39 +00:00
plr - > nRun = runlist_AddRunRec ( NewRun , nPlayer , 0xA0000 ) ;
2020-10-13 22:19:39 +00:00
}
2019-08-26 03:59:14 +00:00
2020-10-13 22:19:39 +00:00
BuildRa ( nPlayer ) ;
2019-08-26 03:59:14 +00:00
2020-10-13 22:19:39 +00:00
if ( nPlayer = = nLocalPlayer )
{
RestoreGreenPal ( ) ;
2021-04-13 11:56:01 +00:00
plr - > bPlayerPan = plr - > bLockPan = false ;
2020-10-13 22:19:39 +00:00
}
2019-08-26 03:59:14 +00:00
2021-10-21 19:20:54 +00:00
plr - > ototalvel = plr - > totalvel = 0 ;
2019-08-26 03:59:14 +00:00
2023-03-13 09:29:04 +00:00
PlayerList [ nPlayer ] . nCurrentItem = - 1 ;
2019-08-26 03:59:14 +00:00
2021-10-21 19:20:54 +00:00
plr - > nDeathType = 0 ;
2023-03-23 06:32:26 +00:00
plr - > nQuake = 0 ;
2019-08-26 03:59:14 +00:00
}
2021-01-19 08:44:16 +00:00
2022-09-11 06:09:26 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2019-08-26 03:59:14 +00:00
int GrabPlayer ( )
{
2019-08-31 07:47:15 +00:00
if ( PlayerCount > = kMaxPlayers ) {
return - 1 ;
}
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
return PlayerCount + + ;
2019-08-26 03:59:14 +00:00
}
2022-09-11 06:09:26 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2019-08-26 03:59:14 +00:00
void StartDeathSeq ( int nPlayer , int nVal )
{
2019-08-31 07:47:15 +00:00
FreeRa ( nPlayer ) ;
2021-12-26 07:47:54 +00:00
auto pActor = PlayerList [ nPlayer ] . pActor ;
2019-08-31 07:47:15 +00:00
PlayerList [ nPlayer ] . nHealth = 0 ;
2021-12-30 15:51:56 +00:00
int nLotag = pActor - > sector ( ) - > lotag ;
2019-08-31 07:47:15 +00:00
if ( nLotag > 0 ) {
2021-10-28 16:57:50 +00:00
runlist_SignalRun ( nLotag - 1 , nPlayer , & ExhumedAI : : EnterSector ) ;
2019-08-31 07:47:15 +00:00
}
2021-10-21 17:44:53 +00:00
if ( PlayerList [ nPlayer ] . pPlayerGrenade )
2019-08-31 07:47:15 +00:00
{
2022-09-10 20:39:40 +00:00
ThrowGrenade ( nPlayer , 0 , - 10000 ) ;
2019-08-31 07:47:15 +00:00
}
else
{
if ( nNetPlayerCount )
{
int nWeapon = PlayerList [ nPlayer ] . nCurrentWeapon ;
if ( nWeapon > kWeaponSword & & nWeapon < = kWeaponRing )
{
2021-12-30 15:51:56 +00:00
auto pSector = pActor - > sector ( ) ;
2021-11-22 22:05:48 +00:00
if ( pSector - > pBelow ! = nullptr ) {
pSector = pSector - > pBelow ;
2019-08-31 07:47:15 +00:00
}
2021-09-17 13:33:07 +00:00
auto pGunActor = GrabBodyGunSprite ( ) ;
2021-11-22 22:05:48 +00:00
ChangeActorSect ( pGunActor , pSector ) ;
2019-08-31 07:47:15 +00:00
2022-10-05 15:38:44 +00:00
pGunActor - > spr . pos = { pActor - > spr . pos . X , pActor - > spr . pos . Y , pSector - > floorz - 2 } ;
2019-08-31 07:47:15 +00:00
2021-09-17 13:33:07 +00:00
ChangeActorStat ( pGunActor , nGunLotag [ nWeapon ] + 900 ) ;
2019-08-31 07:47:15 +00:00
2021-12-23 18:01:43 +00:00
pGunActor - > spr . picnum = nGunPicnum [ nWeapon ] ;
2019-08-31 07:47:15 +00:00
2021-10-21 07:50:00 +00:00
BuildItemAnim ( pGunActor ) ;
2019-08-31 07:47:15 +00:00
}
}
}
2023-03-24 08:38:10 +00:00
PlayerList [ nPlayer ] . bIsFiring = false ;
2019-08-31 07:47:15 +00:00
2022-11-25 11:32:28 +00:00
PlayerList [ nPlayer ] . pActor - > PrevAngles . Pitch = PlayerList [ nPlayer ] . pActor - > spr . Angles . Pitch = nullAngle ;
2022-11-23 09:47:45 +00:00
pActor - > oviewzoffset = pActor - > viewzoffset = - 55 ;
2021-05-13 17:15:53 +00:00
PlayerList [ nPlayer ] . nInvisible = 0 ;
2023-03-23 06:22:28 +00:00
PlayerList [ nPlayer ] . dVertPan = 15 ;
2019-08-31 07:47:15 +00:00
2021-12-23 21:51:26 +00:00
pActor - > spr . cstat & = ~ CSTAT_SPRITE_INVISIBLE ;
2019-08-31 07:47:15 +00:00
SetNewWeaponImmediate ( nPlayer , - 2 ) ;
2021-12-30 15:51:56 +00:00
if ( pActor - > sector ( ) - > Damage < = 0 )
2019-08-31 07:47:15 +00:00
{
2021-10-21 10:51:16 +00:00
PlayerList [ nPlayer ] . nDeathType = nVal ;
2019-08-31 07:47:15 +00:00
}
else
{
2021-10-21 10:51:16 +00:00
PlayerList [ nPlayer ] . nDeathType = 2 ;
2019-08-31 07:47:15 +00:00
}
nVal * = 2 ;
2021-12-30 15:51:56 +00:00
if ( nVal | | ! ( pActor - > sector ( ) - > Flag & kSectUnderwater ) )
2019-08-31 07:47:15 +00:00
{
PlayerList [ nPlayer ] . nAction = nVal + 17 ;
}
else {
PlayerList [ nPlayer ] . nAction = 16 ;
}
2021-11-21 18:33:51 +00:00
PlayerList [ nPlayer ] . nSeqSize = 0 ;
2019-08-31 07:47:15 +00:00
2021-12-23 16:05:32 +00:00
pActor - > spr . cstat & = ~ CSTAT_SPRITE_BLOCK_ALL ;
2019-11-20 16:21:32 +00:00
2019-08-31 07:47:15 +00:00
if ( nTotalPlayers = = 1 )
{
2021-05-02 13:54:19 +00:00
if ( ! ( currentLevel - > gameflags & LEVEL_EX_TRAINING ) ) { // if not on the training level
2021-05-13 17:06:38 +00:00
PlayerList [ nPlayer ] . nLives - - ;
2019-08-31 07:47:15 +00:00
}
2021-05-13 17:06:38 +00:00
if ( PlayerList [ nPlayer ] . nLives < 0 ) {
PlayerList [ nPlayer ] . nLives = 0 ;
2019-08-31 07:47:15 +00:00
}
}
2021-10-21 10:51:16 +00:00
PlayerList [ nPlayer ] . ototalvel = PlayerList [ nPlayer ] . totalvel = 0 ;
2019-08-26 03:59:14 +00:00
}
2022-09-11 06:09:26 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2019-08-26 03:59:14 +00:00
int AddAmmo ( int nPlayer , int nWeapon , int nAmmoAmount )
{
2019-08-31 07:47:15 +00:00
if ( ! nAmmoAmount ) {
nAmmoAmount = 1 ;
}
2021-11-21 19:48:11 +00:00
int nCurAmmo = PlayerList [ nPlayer ] . nAmmo [ nWeapon ] ;
2019-08-31 07:47:15 +00:00
if ( nCurAmmo > = 300 & & nAmmoAmount > 0 ) {
return 0 ;
}
nAmmoAmount = nCurAmmo + nAmmoAmount ;
if ( nAmmoAmount > 300 ) {
nAmmoAmount = 300 ;
}
PlayerList [ nPlayer ] . nAmmo [ nWeapon ] = nAmmoAmount ;
if ( nWeapon = = 1 )
{
2021-10-21 10:51:16 +00:00
if ( ! PlayerList [ nPlayer ] . nPistolClip ) {
PlayerList [ nPlayer ] . nPistolClip = 6 ;
2019-08-31 07:47:15 +00:00
}
}
return 1 ;
2019-08-26 03:59:14 +00:00
}
2022-09-11 06:09:26 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2019-08-26 03:59:14 +00:00
void SetPlayerMummified ( int nPlayer , int bIsMummified )
{
2021-12-07 17:53:02 +00:00
DExhumedActor * pActor = PlayerList [ nPlayer ] . pActor ;
2019-08-26 03:59:14 +00:00
2022-09-03 08:02:25 +00:00
pActor - > vel . Y = 0 ;
pActor - > vel . X = 0 ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
PlayerList [ nPlayer ] . bIsMummified = bIsMummified ;
2019-08-26 03:59:14 +00:00
2019-08-31 07:47:15 +00:00
if ( bIsMummified )
{
PlayerList [ nPlayer ] . nAction = 13 ;
PlayerList [ nPlayer ] . nSeq = kSeqMummy ;
}
else
{
PlayerList [ nPlayer ] . nAction = 0 ;
PlayerList [ nPlayer ] . nSeq = kSeqJoe ;
}
2019-08-26 03:59:14 +00:00
2021-11-21 18:33:51 +00:00
PlayerList [ nPlayer ] . nSeqSize = 0 ;
2019-08-26 03:59:14 +00:00
}
2022-09-11 06:09:26 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2019-08-26 03:59:14 +00:00
void ShootStaff ( int nPlayer )
{
2019-08-31 07:47:15 +00:00
PlayerList [ nPlayer ] . nAction = 15 ;
2021-11-21 18:33:51 +00:00
PlayerList [ nPlayer ] . nSeqSize = 0 ;
2019-08-31 07:47:15 +00:00
PlayerList [ nPlayer ] . nSeq = kSeqJoe ;
2019-08-26 03:59:14 +00:00
}
2022-09-11 06:09:26 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2019-08-31 07:47:15 +00:00
void PlayAlert ( const char * str )
2019-08-26 03:59:14 +00:00
{
2019-08-31 07:47:15 +00:00
StatusMessage ( 300 , str ) ;
PlayLocalSound ( StaticSound [ kSound63 ] , 0 ) ;
2019-08-26 03:59:14 +00:00
}
2022-09-11 06:09:26 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2020-08-22 18:14:00 +00:00
static void pickupMessage ( int no )
{
no = nItemText [ no ] ;
if ( no ! = - 1 )
{
FStringf label ( " TXT_EX_PICKUP%d " , no + 1 ) ;
auto str = GStrings [ label ] ;
if ( str ) Printf ( PRINT_NOTIFY , " %s \n " , str ) ;
}
}
2022-09-11 06:09:26 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2021-10-15 20:19:07 +00:00
void AIPlayer : : Draw ( RunListEvent * ev )
2019-08-26 03:59:14 +00:00
{
2021-11-16 17:50:02 +00:00
int nPlayer = RunData [ ev - > nRun ] . nObjIndex ;
2021-10-15 20:19:07 +00:00
assert ( nPlayer > = 0 & & nPlayer < kMaxPlayers ) ;
2021-11-21 19:48:11 +00:00
int nAction = PlayerList [ nPlayer ] . nAction ;
2021-10-15 20:19:07 +00:00
2021-11-21 18:33:51 +00:00
seq_PlotSequence ( ev - > nParam , SeqOffsets [ PlayerList [ nPlayer ] . nSeq ] + PlayerSeq [ nAction ] . a , PlayerList [ nPlayer ] . nSeqSize , PlayerSeq [ nAction ] . b ) ;
2021-10-15 20:19:07 +00:00
}
2019-08-31 07:47:15 +00:00
2022-09-11 06:09:26 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2021-10-15 20:19:07 +00:00
void AIPlayer : : RadialDamage ( RunListEvent * ev )
{
2021-11-16 17:50:02 +00:00
int nPlayer = RunData [ ev - > nRun ] . nObjIndex ;
2019-08-31 07:47:15 +00:00
assert ( nPlayer > = 0 & & nPlayer < kMaxPlayers ) ;
2021-12-26 07:47:54 +00:00
auto pPlayerActor = PlayerList [ nPlayer ] . pActor ;
2019-08-31 07:47:15 +00:00
2021-10-15 20:19:07 +00:00
if ( PlayerList [ nPlayer ] . nHealth < = 0 )
{
return ;
}
2019-08-31 07:47:15 +00:00
2021-10-21 20:39:17 +00:00
ev - > nDamage = runlist_CheckRadialDamage ( pPlayerActor ) ;
2021-10-15 20:19:07 +00:00
Damage ( ev ) ;
}
2019-08-31 07:47:15 +00:00
2022-09-11 06:09:26 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2021-10-15 20:19:07 +00:00
void AIPlayer : : Damage ( RunListEvent * ev )
{
int nDamage = ev - > nDamage ;
2021-11-16 17:50:02 +00:00
int nPlayer = RunData [ ev - > nRun ] . nObjIndex ;
2021-12-26 07:47:54 +00:00
auto pPlayerActor = PlayerList [ nPlayer ] . pActor ;
2021-11-21 19:48:11 +00:00
int nAction = PlayerList [ nPlayer ] . nAction ;
2021-12-07 17:53:02 +00:00
DExhumedActor * pDopple = PlayerList [ nPlayer ] . pDoppleSprite ;
2019-08-31 07:47:15 +00:00
2021-10-15 20:19:07 +00:00
if ( ! nDamage ) {
return ;
}
2019-11-03 17:20:05 +00:00
2021-12-07 17:53:02 +00:00
DExhumedActor * pActor2 = ( ! ev - > isRadialEvent ( ) ) ? ev - > pOtherActor : ev - > pRadialActor - > pTarget . Get ( ) ;
2019-08-31 07:47:15 +00:00
2021-10-15 20:19:07 +00:00
// ok continue case 0x80000 as normal, loc_1C57C
if ( ! PlayerList [ nPlayer ] . nHealth ) {
return ;
}
2019-08-31 07:47:15 +00:00
2021-10-15 20:19:07 +00:00
if ( ! PlayerList [ nPlayer ] . invincibility )
{
PlayerList [ nPlayer ] . nHealth - = nDamage ;
if ( nPlayer = = nLocalPlayer )
{
TintPalette ( nDamage , 0 , 0 ) ;
2019-08-31 07:47:15 +00:00
}
2021-10-15 20:19:07 +00:00
}
2019-08-31 07:47:15 +00:00
2021-10-15 20:19:07 +00:00
if ( PlayerList [ nPlayer ] . nHealth > 0 )
{
if ( nDamage > 40 | | ( totalmoves & 0xF ) < 2 )
2019-08-31 07:47:15 +00:00
{
2021-10-15 20:19:07 +00:00
if ( PlayerList [ nPlayer ] . invincibility ) {
2019-08-31 07:47:15 +00:00
return ;
}
2021-12-30 15:51:56 +00:00
if ( pPlayerActor - > sector ( ) - > Flag & kSectUnderwater )
2019-08-31 07:47:15 +00:00
{
2021-10-15 20:19:07 +00:00
if ( nAction ! = 12 )
2019-08-31 07:47:15 +00:00
{
2021-11-21 18:33:51 +00:00
PlayerList [ nPlayer ] . nSeqSize = 0 ;
2021-10-15 20:19:07 +00:00
PlayerList [ nPlayer ] . nAction = 12 ;
return ;
2019-08-31 07:47:15 +00:00
}
}
2021-10-15 20:19:07 +00:00
else
2019-08-31 07:47:15 +00:00
{
2021-10-15 20:19:07 +00:00
if ( nAction ! = 4 )
2019-08-31 07:47:15 +00:00
{
2021-11-21 18:33:51 +00:00
PlayerList [ nPlayer ] . nSeqSize = 0 ;
2021-10-15 20:19:07 +00:00
PlayerList [ nPlayer ] . nAction = 4 ;
2019-08-31 07:47:15 +00:00
2021-10-21 16:22:14 +00:00
if ( pActor2 )
2019-08-31 07:47:15 +00:00
{
2021-10-21 10:51:16 +00:00
PlayerList [ nPlayer ] . nPlayerSwear - - ;
if ( PlayerList [ nPlayer ] . nPlayerSwear < = 0 )
2019-08-31 07:47:15 +00:00
{
2021-10-21 17:54:39 +00:00
D3PlayFX ( StaticSound [ kSound52 ] , pDopple ) ;
2021-10-21 10:51:16 +00:00
PlayerList [ nPlayer ] . nPlayerSwear = RandomSize ( 3 ) + 4 ;
2019-08-31 07:47:15 +00:00
}
}
}
2021-10-15 20:19:07 +00:00
}
}
2019-08-31 07:47:15 +00:00
2021-10-15 20:19:07 +00:00
return ;
}
else
{
// player has died
2021-12-21 22:18:23 +00:00
if ( pActor2 & & pActor2 - > spr . statnum = = 100 )
2021-10-15 20:19:07 +00:00
{
2021-11-21 19:48:11 +00:00
int nPlayer2 = GetPlayerFromActor ( pActor2 ) ;
2021-10-15 20:19:07 +00:00
if ( nPlayer2 = = nPlayer ) // player caused their own death
{
2021-10-21 10:51:16 +00:00
PlayerList [ nPlayer ] . nPlayerScore - - ;
2019-08-31 07:47:15 +00:00
}
else
{
2021-10-21 10:51:16 +00:00
PlayerList [ nPlayer ] . nPlayerScore + + ;
2021-10-15 20:19:07 +00:00
}
}
2021-10-21 16:22:14 +00:00
else if ( pActor2 = = nullptr )
2021-10-15 20:19:07 +00:00
{
2021-10-21 10:51:16 +00:00
PlayerList [ nPlayer ] . nPlayerScore - - ;
2021-10-15 20:19:07 +00:00
}
2019-08-31 07:47:15 +00:00
2021-10-28 16:08:03 +00:00
if ( ev - > isRadialEvent ( ) )
2021-10-15 20:19:07 +00:00
{
for ( int i = 122 ; i < = 131 ; i + + )
{
2021-10-21 19:10:17 +00:00
BuildCreatureChunk ( pPlayerActor , seq_GetSeqPicnum ( kSeqJoe , i , 0 ) ) ;
2021-10-15 20:19:07 +00:00
}
2019-08-31 07:47:15 +00:00
2021-10-15 20:19:07 +00:00
StartDeathSeq ( nPlayer , 1 ) ;
}
else
{
StartDeathSeq ( nPlayer , 0 ) ;
}
}
}
2019-08-31 07:47:15 +00:00
2022-09-11 06:09:26 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2023-03-24 13:12:52 +00:00
static void doPlayerCounters ( Player * const pPlayer )
2023-03-23 08:34:53 +00:00
{
2023-03-24 23:08:55 +00:00
const auto pPlayerActor = pPlayer - > pActor ;
2023-03-24 13:12:52 +00:00
if ( pPlayer - > nCurrentItem > - 1 )
2023-03-23 08:46:18 +00:00
{
2023-03-24 13:12:52 +00:00
UseItem ( pPlayer - > nPlayer , pPlayer - > nCurrentItem ) ;
pPlayer - > nCurrentItem = - 1 ;
2023-03-23 08:46:18 +00:00
}
2023-03-24 13:12:52 +00:00
if ( pPlayer - > nTorch > 0 )
2023-03-23 08:46:18 +00:00
{
2023-03-24 13:12:52 +00:00
pPlayer - > nTorch - - ;
if ( pPlayer - > nTorch = = 0 )
{
SetTorch ( pPlayer - > nPlayer , 0 ) ;
}
else if ( pPlayer - > nPlayer ! = nLocalPlayer )
{
nFlashDepth = 5 ;
2023-03-24 23:08:55 +00:00
AddFlash ( pPlayerActor - > sector ( ) , pPlayerActor - > spr . pos , 0 ) ;
2023-03-24 13:12:52 +00:00
}
2023-03-23 08:46:18 +00:00
}
2023-03-24 13:12:52 +00:00
if ( pPlayer - > nDouble > 0 )
{
pPlayer - > nDouble - - ;
2023-03-23 08:46:45 +00:00
2023-03-24 13:12:52 +00:00
if ( pPlayer - > nDouble = = 150 & & pPlayer - > nPlayer = = nLocalPlayer )
{
PlayAlert ( GStrings ( " TXT_EX_WEAPONEX " ) ) ;
}
}
2023-03-23 08:46:45 +00:00
2023-03-24 13:12:52 +00:00
if ( pPlayer - > nInvisible > 0 )
2023-03-23 08:46:45 +00:00
{
2023-03-24 13:12:52 +00:00
pPlayer - > nInvisible - - ;
2023-03-23 08:46:45 +00:00
2023-03-24 13:12:52 +00:00
if ( pPlayer - > nInvisible = = 0 )
{
2023-03-24 23:08:55 +00:00
pPlayerActor - > spr . cstat & = ~ CSTAT_SPRITE_INVISIBLE ; // set visible
2023-03-23 08:47:11 +00:00
2023-03-24 13:12:52 +00:00
if ( pPlayer - > pPlayerFloorSprite )
{
pPlayer - > pPlayerFloorSprite - > spr . cstat & = ~ CSTAT_SPRITE_INVISIBLE ; // set visible
}
}
else if ( pPlayer - > nInvisible = = 150 & & pPlayer - > nPlayer = = nLocalPlayer )
{
PlayAlert ( GStrings ( " TXT_EX_INVISEX " ) ) ;
}
}
2023-03-23 08:47:11 +00:00
2023-03-24 13:12:52 +00:00
if ( pPlayer - > invincibility > 0 )
2023-03-23 08:47:11 +00:00
{
2023-03-24 13:12:52 +00:00
pPlayer - > invincibility - - ;
2023-03-23 08:47:11 +00:00
2023-03-24 13:12:52 +00:00
if ( pPlayer - > invincibility = = 150 & & pPlayer - > nPlayer = = nLocalPlayer )
2023-03-23 08:47:11 +00:00
{
2023-03-24 13:12:52 +00:00
PlayAlert ( GStrings ( " TXT_EX_INVINCEX " ) ) ;
2023-03-23 08:47:11 +00:00
}
}
2023-03-24 22:42:37 +00:00
if ( pPlayer - > nMaskAmount > 0 & & pPlayer - > nHealth > 0 )
{
pPlayer - > nMaskAmount - - ;
if ( pPlayer - > nMaskAmount = = 150 & & pPlayer - > nPlayer = = nLocalPlayer )
{
PlayAlert ( GStrings ( " TXT_EX_MASKEX " ) ) ;
}
}
2023-03-24 13:12:52 +00:00
if ( pPlayer - > nQuake ! = 0 )
{
pPlayer - > nQuake = - pPlayer - > nQuake ;
2023-03-23 08:47:41 +00:00
2023-03-24 13:12:52 +00:00
if ( pPlayer - > nQuake > 0 )
{
pPlayer - > nQuake - = 2. ;
2023-03-23 08:47:41 +00:00
2023-03-24 13:12:52 +00:00
if ( pPlayer - > nQuake < 0 )
{
pPlayer - > nQuake = 0 ;
}
}
2023-03-23 08:47:41 +00:00
}
}
2023-03-23 08:48:26 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2023-03-24 08:01:10 +00:00
static void doPlayerBreath ( Player * const pPlayer )
{
const auto pPlayerActor = pPlayer - > pActor ;
pPlayer - > nBreathTimer - - ;
if ( pPlayer - > nBreathTimer < = 0 )
{
pPlayer - > nBreathTimer = 90 ;
if ( pPlayer - > pPlayerViewSect - > Flag & kSectUnderwater )
{
if ( pPlayer - > nMaskAmount > 0 )
{
D3PlayFX ( StaticSound [ kSound30 ] , pPlayerActor ) ;
pPlayer - > nAir = 100 ;
}
else
{
pPlayer - > nAir - = 25 ;
if ( pPlayer - > nAir > 0 )
{
D3PlayFX ( StaticSound [ kSound25 ] , pPlayerActor ) ;
}
else
{
pPlayer - > nHealth + = ( pPlayer - > nAir < < 2 ) ;
if ( pPlayer - > nHealth < = 0 )
{
pPlayer - > nHealth = 0 ;
StartDeathSeq ( pPlayer - > nPlayer , 0 ) ;
}
pPlayer - > nAir = 0 ;
D3PlayFX ( StaticSound [ ( pPlayer - > nHealth < 300 ) ? kSound79 : kSound19 ] , pPlayerActor ) ;
}
}
DoBubbles ( pPlayer - > nPlayer ) ;
}
}
if ( pPlayerActor - > sector ( ) - > Flag & kSectUnderwater )
{
if ( pPlayer - > nAir < 50 )
D3PlayFX ( StaticSound [ kSound14 ] , pPlayerActor ) ;
pPlayer - > nBreathTimer = 1 ;
}
pPlayer - > nBreathTimer - - ;
if ( pPlayer - > nBreathTimer < = 0 )
pPlayer - > nBreathTimer = 90 ;
if ( pPlayer - > nAir < 100 )
pPlayer - > nAir = 100 ;
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2023-03-24 08:52:36 +00:00
static void doPlayerRamses ( Player * const pPlayer )
{
setForcedSyncInput ( pPlayer - > nPlayer ) ;
if ( nTotalPlayers < = 1 )
{
const auto pPlayerActor = pPlayer - > pActor ;
pPlayerActor - > spr . Angles = DRotator ( nullAngle , ( pSpiritSprite - > spr . pos . XY ( ) - pPlayerActor - > spr . pos . XY ( ) ) . Angle ( ) , nullAngle ) ;
pPlayerActor - > backupang ( ) ;
pPlayerActor - > vel . Zero ( ) ;
pPlayer - > vel . Zero ( ) ;
if ( nFreeze < 1 )
{
nFreeze = 1 ;
StopAllSounds ( ) ;
StopLocalSound ( ) ;
InitSpiritHead ( ) ;
pPlayerActor - > spr . Angles . Pitch = currentLevel - > ex_ramses_horiz ;
pPlayer - > nDestVertPan = nullAngle ;
}
}
else
{
LevelFinished ( ) ;
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2023-03-24 06:51:33 +00:00
static void doPlayerGravity ( DExhumedActor * const pPlayerActor )
{
// Z vel is modified within Gravity() and needs backing up.
const double zVel = pPlayerActor - > vel . Z ;
Gravity ( pPlayerActor ) ;
if ( pPlayerActor - > vel . Z > = 6500 / 256. & & zVel < 6500 / 256. )
{
D3PlayFX ( StaticSound [ kSound17 ] , pPlayerActor ) ;
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2023-03-24 08:01:35 +00:00
static void updatePlayerFloorActor ( Player * const pPlayer )
{
if ( nTotalPlayers > 1 )
{
if ( DExhumedActor * const pFloorActor = pPlayer - > pPlayerFloorSprite )
{
const auto pPlayerActor = pPlayer - > pActor ;
pFloorActor - > spr . pos . XY ( ) = pPlayerActor - > spr . pos . XY ( ) ;
pFloorActor - > spr . pos . Z = pPlayerActor - > sector ( ) - > floorz ;
if ( pFloorActor - > sector ( ) ! = pPlayerActor - > sector ( ) )
{
ChangeActorSect ( pFloorActor , pPlayerActor - > sector ( ) ) ;
}
}
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2023-03-24 09:12:27 +00:00
static void updatePlayerDoppleActor ( Player * const pPlayer )
{
const auto pPlayerActor = pPlayer - > pActor ;
DExhumedActor * const pDopple = pPlayer - > pDoppleSprite ;
pDopple - > spr . pos = pPlayerActor - > spr . pos ;
if ( pPlayerActor - > sector ( ) - > pAbove ! = nullptr )
{
pDopple - > spr . Angles . Yaw = pPlayerActor - > spr . Angles . Yaw ;
ChangeActorSect ( pDopple , pPlayerActor - > sector ( ) - > pAbove ) ;
pDopple - > spr . cstat = CSTAT_SPRITE_BLOCK_ALL ;
}
else
{
pDopple - > spr . cstat = CSTAT_SPRITE_INVISIBLE ;
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2023-03-24 10:13:40 +00:00
static void updatePlayerViewSector ( Player * const pPlayer , const Collision & nMove , const DVector3 & spr_pos , const DVector3 & spr_vel , const bool bUnderwater )
{
const auto pPlayerActor = pPlayer - > pActor ;
const double EyeZ = pPlayerActor - > getOffsetZ ( ) + pPlayer - > nQuake ;
auto pViewSect = pPlayerActor - > sector ( ) ;
while ( 1 )
{
double nCeilZ = pViewSect - > ceilingz ;
if ( EyeZ > = nCeilZ )
break ;
if ( pViewSect - > pAbove = = nullptr )
break ;
pViewSect = pViewSect - > pAbove ;
}
// Do underwater sector check
if ( bUnderwater & & pViewSect ! = pPlayerActor - > sector ( ) & & nMove . type = = kHitWall )
{
auto pos = pPlayerActor - > spr . pos ;
ChangeActorSect ( pPlayerActor , pViewSect ) ;
double fz = pViewSect - > floorz - 20 ;
pPlayerActor - > spr . pos = DVector3 ( spr_pos . XY ( ) , fz ) ;
auto coll = movesprite ( pPlayerActor , spr_vel . XY ( ) , 0 , 0 , CLIPMASK0 ) ;
if ( coll . type = = kHitWall )
{
ChangeActorSect ( pPlayerActor , pPlayerActor - > sector ( ) ) ;
pPlayerActor - > spr . pos = pos ;
}
else
{
pPlayerActor - > spr . pos . Z = fz - 1 ;
D3PlayFX ( StaticSound [ kSound42 ] , pPlayerActor ) ;
}
}
pPlayer - > pPlayerViewSect = pViewSect ;
if ( nLocalPlayer = = pPlayer - > nPlayer )
{
pLocalEyeSect = pPlayer - > pPlayerViewSect ;
CheckAmbience ( pLocalEyeSect ) ;
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2023-03-24 08:24:13 +00:00
static void doPlayerFloorDamage ( Player * const pPlayer )
{
const auto pPlayerActor = pPlayer - > pActor ;
pPlayer - > nThrust / = 2 ;
if ( pPlayer - > nPlayer = = nLocalPlayer & & abs ( pPlayerActor - > vel . Z ) > 2 & & ! pPlayerActor - > spr . Angles . Pitch . Sgn ( ) & & cl_slopetilting )
pPlayer - > nDestVertPan = nullAngle ;
if ( pPlayerActor - > vel . Z > = 6500 / 256. )
{
pPlayerActor - > vel . XY ( ) * = 0.25 ;
runlist_DamageEnemy ( pPlayerActor , nullptr , int ( ( ( pPlayerActor - > vel . Z * 256 ) - 6500 ) * ( 1. / 128. ) ) + 10 ) ;
if ( pPlayer - > nHealth < = 0 )
{
pPlayerActor - > vel . X = 0 ;
pPlayerActor - > vel . Y = 0 ;
StopActorSound ( pPlayerActor ) ;
PlayFXAtXYZ ( StaticSound [ kSoundJonFDie ] , pPlayerActor - > spr . pos , CHANF_NONE , 1 ) ; // CHECKME
}
else
{
D3PlayFX ( StaticSound [ kSound27 ] | 0x2000 , pPlayerActor ) ;
}
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2023-03-24 08:16:56 +00:00
static void doPlayerMovingBlocks ( Player * const pPlayer , const Collision & nMove , const DVector3 & spr_pos , const DVector3 & spr_vel , sectortype * const spr_sect )
{
const auto pPlayerActor = pPlayer - > pActor ;
sectortype * sect ;
DAngle nNormal = nullAngle ;
if ( nMove . type = = kHitSector )
{
sect = nMove . hitSector ;
// Hm... Normal calculation here was broken.
}
else //if (nMove.type == kHitWall)
{
sect = nMove . hitWall - > nextSector ( ) ;
nNormal = nMove . hitWall - > normalAngle ( ) ;
}
// moving blocks - move this to a separate function!
if ( sect ! = nullptr )
{
const auto nDiff = absangle ( nNormal , pPlayerActor - > spr . Angles . Yaw + DAngle180 ) ;
if ( ( sect - > hitag = = 45 ) & & bTouchFloor & & nDiff < = DAngle45 )
{
pPlayer - > pPlayerPushSect = sect ;
DVector2 vel = pPlayer - > vel ;
auto nMyAngle = vel . Angle ( ) . Normalized360 ( ) ;
setsectinterpolate ( sect ) ;
MoveSector ( sect , nMyAngle , vel ) ;
if ( pPlayer - > nPlayerPushSound = = - 1 )
{
const int nBlock = pPlayer - > pPlayerPushSect - > extra ;
pPlayer - > nPlayerPushSound = nBlock ;
DExhumedActor * pBlockActor = sBlockInfo [ nBlock ] . pActor ;
D3PlayFX ( StaticSound [ kSound23 ] , pBlockActor , 0x4000 ) ;
}
else
{
pPlayerActor - > spr . pos = spr_pos ;
ChangeActorSect ( pPlayerActor , spr_sect ) ;
}
movesprite ( pPlayerActor , vel , spr_vel . Z , - 20 , CLIPMASK0 ) ;
}
else if ( pPlayer - > nPlayerPushSound ! = - 1 )
{
if ( pPlayer - > pPlayerPushSect ! = nullptr )
{
StopActorSound ( sBlockInfo [ pPlayer - > pPlayerPushSect - > extra ] . pActor ) ;
}
pPlayer - > nPlayerPushSound = - 1 ;
}
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2023-03-24 09:11:01 +00:00
static bool doPlayerMovement ( Player * const pPlayer )
{
const auto pPlayerActor = pPlayer - > pActor ;
const auto spr_vel = DVector3 ( pPlayerActor - > vel . XY ( ) * ( pPlayer - > bIsMummified ? 0.5 : 1. ) , pPlayerActor - > vel . Z ) ;
const auto spr_pos = pPlayerActor - > spr . pos ;
const auto spr_sect = pPlayerActor - > sector ( ) ;
if ( pPlayerActor - > vel . Z > 32 )
pPlayerActor - > vel . Z = 32 ;
Collision nMove ;
nMove . setNone ( ) ;
if ( bSlipMode )
{
SetActor ( pPlayerActor , pPlayerActor - > spr . pos + spr_vel . XY ( ) ) ;
pPlayerActor - > spr . pos . Z = pPlayerActor - > sector ( ) - > floorz ;
}
else
{
nMove = movesprite ( pPlayerActor , spr_vel . XY ( ) , spr_vel . Z , - 20 , CLIPMASK0 ) ;
auto pPlayerSect = pPlayerActor - > sector ( ) ;
pushmove ( pPlayerActor - > spr . pos , & pPlayerSect , pPlayerActor - > clipdist , 20 , - 20 , CLIPMASK0 ) ;
if ( pPlayerSect ! = pPlayerActor - > sector ( ) )
ChangeActorSect ( pPlayerActor , pPlayerSect ) ;
}
if ( inside ( pPlayerActor - > spr . pos . X , pPlayerActor - > spr . pos . Y , pPlayerActor - > sector ( ) ) ! = 1 )
{
ChangeActorSect ( pPlayerActor , spr_sect ) ;
pPlayerActor - > spr . pos . XY ( ) = spr_pos . XY ( ) ;
}
const bool bUnderwater = pPlayerActor - > sector ( ) - > Flag & kSectUnderwater ;
if ( bUnderwater )
pPlayer - > nThrust / = 2 ;
// Trigger Ramses?
if ( ( pPlayerActor - > sector ( ) - > Flag & 0x8000 ) & & bTouchFloor )
return false ;
if ( nMove . type | | nMove . exbits )
{
if ( bTouchFloor )
{
2023-03-24 08:24:13 +00:00
doPlayerFloorDamage ( pPlayer ) ;
2023-03-24 09:11:01 +00:00
}
if ( nMove . type = = kHitSector | | nMove . type = = kHitWall )
{
2023-03-24 08:16:56 +00:00
doPlayerMovingBlocks ( pPlayer , nMove , spr_pos , spr_vel , spr_sect ) ;
2023-03-24 09:11:01 +00:00
}
}
if ( ! pPlayer - > bPlayerPan & & ! pPlayer - > bLockPan )
{
pPlayer - > nDestVertPan = maphoriz ( ( pPlayerActor - > spr . pos . Z - spr_pos . Z ) * 2. ) ;
}
pPlayer - > ototalvel = pPlayer - > totalvel ;
pPlayer - > totalvel = int ( ( spr_pos . XY ( ) - pPlayerActor - > spr . pos . XY ( ) ) . Length ( ) * worldtoint ) ;
2023-03-24 10:13:40 +00:00
updatePlayerViewSector ( pPlayer , nMove , spr_pos , spr_vel , bUnderwater ) ;
2023-03-24 09:11:01 +00:00
pPlayer - > nPlayerD = ( pPlayerActor - > spr . pos - spr_pos ) ;
return true ;
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2023-03-24 08:36:43 +00:00
static void updatePlayerAction ( Player * const pPlayer )
2021-10-15 20:19:07 +00:00
{
2023-03-24 08:36:43 +00:00
const auto pPlayerActor = pPlayer - > pActor ;
2023-03-24 08:49:38 +00:00
const auto pPlayerSect = pPlayerActor - > sector ( ) ;
const bool bUnderwater = pPlayerSect - > Flag & kSectUnderwater ;
int nextAction = pPlayer - > nAction ;
2021-10-15 20:19:07 +00:00
2023-03-24 08:36:43 +00:00
if ( ! pPlayer - > bIsMummified )
{
if ( pPlayer - > input . actions & SB_JUMP )
{
if ( bUnderwater )
{
pPlayerActor - > vel . Z = - 8 ;
2023-03-24 08:49:38 +00:00
nextAction = 10 ;
2023-03-24 08:36:43 +00:00
}
2023-03-24 08:49:38 +00:00
else if ( bTouchFloor & & ( pPlayer - > nAction < 6 | | pPlayer - > nAction > 8 ) )
2023-03-24 08:36:43 +00:00
{
2023-03-24 08:49:38 +00:00
pPlayerActor - > vel . Z = - 14 ;
nextAction = 3 ;
2023-03-24 08:36:43 +00:00
}
}
else if ( pPlayer - > input . actions & SB_CROUCH )
{
if ( bUnderwater )
{
pPlayerActor - > vel . Z = 8 ;
2023-03-24 08:49:38 +00:00
nextAction = 10 ;
2023-03-24 08:36:43 +00:00
}
else
{
2023-03-24 08:49:38 +00:00
if ( pPlayerActor - > viewzoffset < - 32.5 )
{
2023-03-24 08:36:43 +00:00
pPlayerActor - > viewzoffset + = ( ( - 32.5 - pPlayerActor - > viewzoffset ) * 0.5 ) ;
}
2023-03-24 08:49:38 +00:00
nextAction = 7 - ( pPlayer - > totalvel < 1 ) ;
2023-03-24 08:36:43 +00:00
}
}
else
{
if ( pPlayer - > nHealth > 0 )
{
pPlayerActor - > viewzoffset + = ( nActionEyeLevel [ pPlayer - > nAction ] - pPlayerActor - > viewzoffset ) * 0.5 ;
if ( bUnderwater )
{
2023-03-24 08:49:38 +00:00
nextAction = 10 - ( pPlayer - > totalvel < = 1 ) ;
2023-03-24 08:36:43 +00:00
}
2023-03-24 08:49:38 +00:00
else if ( nStandHeight > ( pPlayerSect - > floorz - pPlayerSect - > ceilingz ) )
2023-03-24 08:36:43 +00:00
{
// CHECKME - confirm branching in this area is OK
2023-03-24 08:49:38 +00:00
// CHECKME - are we finished with 'nSector' variable at this point? if so, maybe set it to pPlayerActor->sector() so we can make this code a bit neater. Don't assume pPlayerActor->sector() == nSector here!!
2023-03-24 08:50:11 +00:00
nextAction = 7 - ( pPlayer - > totalvel < 1 ) ;
2023-03-24 08:49:38 +00:00
}
else
{
const auto totalvel = pPlayer - > totalvel ;
nextAction = ( totalvel < = 1 ) ? 0 : ( totalvel < = 30 ) ? 2 : 1 ;
2023-03-24 08:36:43 +00:00
}
}
2023-03-24 08:49:38 +00:00
2023-03-24 08:36:43 +00:00
if ( pPlayer - > input . actions & SB_FIRE ) // was var_38
{
if ( bUnderwater )
{
2023-03-24 08:49:38 +00:00
nextAction = 11 ;
2023-03-24 08:36:43 +00:00
}
2023-03-24 08:49:38 +00:00
else if ( nextAction ! = 2 & & nextAction ! = 1 )
2023-03-24 08:36:43 +00:00
{
2023-03-24 08:49:38 +00:00
nextAction = 5 ;
2023-03-24 08:36:43 +00:00
}
}
}
// Handle player pressing number keys to change weapon
2023-03-24 08:49:38 +00:00
if ( auto newWeap = pPlayer - > input . getNewWeapon ( ) )
2023-03-24 08:36:43 +00:00
{
2023-03-24 08:49:38 +00:00
if ( pPlayer - > nPlayerWeapons & ( 1 < < ( newWeap - - ) ) )
2023-03-24 08:36:43 +00:00
{
2023-03-24 08:49:38 +00:00
SetNewWeapon ( pPlayer - > nPlayer , newWeap ) ;
2023-03-24 08:36:43 +00:00
}
}
}
else // player is mummified
{
if ( pPlayer - > input . actions & SB_FIRE )
{
2023-03-24 08:49:38 +00:00
pPlayer - > bIsFiring = true ;
2023-03-24 08:36:43 +00:00
}
if ( pPlayer - > nAction ! = 15 )
{
2023-03-24 08:49:38 +00:00
nextAction = 14 - ( pPlayer - > totalvel < = 1 ) ;
2023-03-24 08:36:43 +00:00
}
}
2023-03-24 08:49:38 +00:00
if ( nextAction ! = pPlayer - > nAction & & pPlayer - > nAction ! = 4 )
2023-03-24 08:36:43 +00:00
{
2023-03-24 08:49:38 +00:00
pPlayer - > nAction = nextAction ;
2023-03-24 08:36:43 +00:00
pPlayer - > nSeqSize = 0 ;
}
}
2023-03-24 04:53:37 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2023-03-24 05:15:14 +00:00
static void doPlayerYaw ( Player * const pPlayer )
{
const auto pInput = & pPlayer - > input ;
if ( SyncInput ( ) )
{
pPlayer - > pActor - > spr . Angles . Yaw + = DAngle : : fromDeg ( pInput - > avel ) ;
}
pPlayer - > Angles . doYawKeys ( pInput ) ;
pPlayer - > Angles . doViewYaw ( pInput ) ;
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2023-03-24 04:53:37 +00:00
static void doPlayerPitch ( Player * const pPlayer )
{
const auto pPlayerActor = pPlayer - > pActor ;
const auto pInput = & pPlayer - > input ;
if ( SyncInput ( ) )
{
pPlayerActor - > spr . Angles . Pitch + = DAngle : : fromDeg ( pInput - > horz ) ;
}
pPlayer - > Angles . doPitchKeys ( pInput ) ;
if ( pInput - > actions & ( SB_AIM_UP | SB_AIM_DOWN ) | | pInput - > horz )
{
pPlayer - > nDestVertPan = pPlayerActor - > spr . Angles . Pitch ;
pPlayer - > bPlayerPan = pPlayer - > bLockPan = true ;
}
else if ( pInput - > actions & ( SB_LOOK_UP | SB_LOOK_DOWN | SB_CENTERVIEW ) )
{
pPlayer - > nDestVertPan = pPlayerActor - > spr . Angles . Pitch ;
pPlayer - > bPlayerPan = pPlayer - > bLockPan = false ;
}
if ( pPlayer - > totalvel > 20 )
{
pPlayer - > bPlayerPan = false ;
}
if ( cl_slopetilting & & ! pPlayer - > bPlayerPan & & ! pPlayer - > bLockPan )
{
if ( double nVertPan = deltaangle ( pPlayerActor - > spr . Angles . Pitch , pPlayer - > nDestVertPan ) . Tan ( ) * 32. )
{
pPlayerActor - > spr . Angles . Pitch + = maphoriz ( abs ( nVertPan ) > = 4 ? clamp ( nVertPan , - 4. , 4. ) : nVertPan * 2. ) ;
}
}
}
2023-03-24 05:32:58 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2023-03-24 09:11:27 +00:00
static void doPlayerActionSequence ( Player * const pPlayer )
{
const auto pPlayerActor = pPlayer - > pActor ;
const auto nSeq = SeqOffsets [ pPlayer - > nSeq ] + PlayerSeq [ pPlayer - > nAction ] . a ;
seq_MoveSequence ( pPlayerActor , nSeq , pPlayer - > nSeqSize ) ;
pPlayer - > nSeqSize + + ;
if ( pPlayer - > nSeqSize > = SeqSize [ nSeq ] )
{
pPlayer - > nSeqSize = 0 ;
switch ( pPlayer - > nAction )
{
default :
break ;
case 3 :
pPlayer - > nSeqSize = SeqSize [ nSeq ] - 1 ;
break ;
case 4 :
pPlayer - > nAction = 0 ;
break ;
case 16 :
pPlayer - > nSeqSize = SeqSize [ nSeq ] - 1 ;
if ( pPlayerActor - > spr . pos . Z < pPlayerActor - > sector ( ) - > floorz )
pPlayerActor - > spr . pos . Z + + ;
if ( ! RandomSize ( 5 ) )
{
sectortype * mouthSect ;
const auto pos = WheresMyMouth ( pPlayer - > nPlayer , & mouthSect ) ;
BuildAnim ( nullptr , 71 , 0 , DVector3 ( pos . XY ( ) , pPlayerActor - > spr . pos . Z + 15 ) , mouthSect , 1.171875 , 128 ) ;
}
break ;
case 17 :
pPlayer - > nAction = 18 ;
break ;
case 19 :
pPlayerActor - > spr . cstat | = CSTAT_SPRITE_INVISIBLE ;
pPlayer - > nAction = 20 ;
break ;
}
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2023-03-24 05:32:58 +00:00
static void doPlayerDeathPitch ( Player * const pPlayer )
{
const auto pPlayerActor = pPlayer - > pActor ;
pPlayer - > nThrust . Zero ( ) ;
if ( pPlayerActor - > viewzoffset > = - 11 )
{
pPlayerActor - > viewzoffset = - 11 ;
pPlayer - > dVertPan = 0 ;
}
else
{
if ( pPlayerActor - > spr . Angles . Pitch . Sgn ( ) > 0 )
{
pPlayerActor - > spr . Angles . Pitch = nullAngle ;
pPlayerActor - > viewzoffset - = pPlayer - > dVertPan ;
}
else
{
pPlayerActor - > spr . Angles . Pitch - = maphoriz ( pPlayer - > dVertPan ) ;
if ( pPlayerActor - > spr . Angles . Pitch . Degrees ( ) < = - 38 )
{
pPlayerActor - > spr . Angles . Pitch = DAngle : : fromDeg ( - 37.72 ) ;
}
else if ( pPlayerActor - > spr . Angles . Pitch . Sgn ( ) > = 0 )
{
if ( ! ( pPlayerActor - > sector ( ) - > Flag & kSectUnderwater ) )
{
SetNewWeapon ( pPlayer - > nPlayer , pPlayer - > nDeathType + 8 ) ;
}
}
pPlayer - > dVertPan - - ;
}
}
}
2023-03-24 08:36:43 +00:00
//---------------------------------------------------------------------------
//
2023-03-24 09:39:09 +00:00
// this function is (no longer) pure spaghetti madness... :)
2023-03-24 08:36:43 +00:00
//
//---------------------------------------------------------------------------
void AIPlayer : : Tick ( RunListEvent * ev )
{
2023-03-23 07:50:30 +00:00
const int nPlayer = RunData [ ev - > nRun ] . nObjIndex ;
2021-10-15 20:19:07 +00:00
assert ( nPlayer > = 0 & & nPlayer < kMaxPlayers ) ;
2023-03-23 07:50:30 +00:00
const auto pPlayer = & PlayerList [ nPlayer ] ;
const auto pPlayerActor = pPlayer - > pActor ;
2023-03-24 09:11:01 +00:00
const auto pStartSect = pPlayerActor - > sector ( ) ;
2021-10-15 20:19:07 +00:00
2023-03-24 09:12:27 +00:00
pPlayer - > pDoppleSprite - > spr . picnum = pPlayerActor - > spr . picnum ;
2023-03-24 08:36:43 +00:00
pPlayerActor - > spr . picnum = seq_GetSeqPicnum ( pPlayer - > nSeq , PlayerSeq [ nHeightTemplate [ pPlayer - > nAction ] ] . a , pPlayer - > nSeqSize ) ;
pPlayerActor - > vel . XY ( ) = pPlayer - > vel ;
2021-10-15 20:19:07 +00:00
2023-03-24 13:12:52 +00:00
doPlayerCounters ( pPlayer ) ;
2023-03-24 05:15:14 +00:00
doPlayerYaw ( pPlayer ) ;
2023-03-24 06:51:33 +00:00
doPlayerGravity ( pPlayerActor ) ;
2019-08-31 07:47:15 +00:00
2021-10-15 20:19:07 +00:00
// Trigger Ramses?
2023-03-24 09:11:01 +00:00
if ( ! doPlayerMovement ( pPlayer ) )
2021-10-15 20:19:07 +00:00
{
2023-03-24 08:52:36 +00:00
doPlayerRamses ( pPlayer ) ;
2021-10-15 20:19:07 +00:00
return ;
}
2023-03-23 07:50:30 +00:00
if ( pPlayer - > nHealth > 0 )
2021-10-15 20:19:07 +00:00
{
2023-03-23 07:50:30 +00:00
if ( ! pPlayer - > invincibility )
2023-03-24 08:01:10 +00:00
doPlayerBreath ( pPlayer ) ;
2019-08-31 07:47:15 +00:00
2023-03-24 08:01:10 +00:00
if ( pPlayer - > pPlayerViewSect - > Flag & kSectUnderwater )
2021-10-15 20:19:07 +00:00
{
2023-03-23 07:50:30 +00:00
if ( pPlayer - > nTorch > 0 )
2021-10-15 20:19:07 +00:00
{
2023-03-23 07:50:30 +00:00
pPlayer - > nTorch = 0 ;
2021-10-15 20:19:07 +00:00
SetTorch ( nPlayer , 0 ) ;
}
}
else
{
2023-03-24 08:01:10 +00:00
const auto pTmpSect = pPlayerActor - > sector ( ) ;
const bool highvel = pPlayer - > totalvel > 25 ;
const bool belowfloor = pPlayerActor - > spr . pos . Z > pTmpSect - > floorz ;
2019-08-31 07:47:15 +00:00
2023-03-24 08:01:10 +00:00
if ( highvel & & belowfloor & & pTmpSect - > Depth & & ! pTmpSect - > Speed & & ! pTmpSect - > Damage )
D3PlayFX ( StaticSound [ kSound42 ] , pPlayerActor ) ;
2021-10-15 20:19:07 +00:00
}
2019-10-29 15:17:43 +00:00
2023-03-24 08:01:35 +00:00
updatePlayerFloorActor ( pPlayer ) ;
2023-03-23 09:50:08 +00:00
doPlayerItemPickups ( pPlayer ) ;
2021-10-15 20:19:07 +00:00
2023-03-24 08:01:35 +00:00
if ( bTouchFloor & & pPlayerActor - > sector ( ) - > lotag > 0 )
runlist_SignalRun ( pPlayerActor - > sector ( ) - > lotag - 1 , nPlayer , & ExhumedAI : : TouchFloor ) ;
2021-10-15 20:19:07 +00:00
2023-03-24 09:11:01 +00:00
if ( pStartSect ! = pPlayerActor - > sector ( ) )
2021-10-15 20:19:07 +00:00
{
2023-03-24 09:11:01 +00:00
if ( pStartSect - > lotag > 0 )
runlist_SignalRun ( pStartSect - > lotag - 1 , nPlayer , & ExhumedAI : : EnterSector ) ;
2019-08-31 07:47:15 +00:00
2021-12-30 15:51:56 +00:00
if ( pPlayerActor - > sector ( ) - > lotag > 0 )
runlist_SignalRun ( pPlayerActor - > sector ( ) - > lotag - 1 , nPlayer , & ExhumedAI : : LeaveSector ) ;
2021-10-15 20:19:07 +00:00
}
2023-03-23 07:50:30 +00:00
if ( ! pPlayer - > bIsMummified )
2021-10-15 20:19:07 +00:00
{
2023-03-24 01:01:36 +00:00
if ( pPlayer - > input . actions & SB_OPEN )
2021-10-15 20:19:07 +00:00
{
2023-03-24 01:01:36 +00:00
pPlayer - > input . actions & = ~ SB_OPEN ;
2021-10-15 20:19:07 +00:00
2023-03-24 01:56:57 +00:00
// neartag finds the nearest sector, wall, and sprite which has its hitag and/or lotag set to a value.
2023-03-24 09:39:09 +00:00
HitInfo near ;
2023-03-24 01:56:57 +00:00
neartag ( pPlayerActor - > spr . pos , pPlayerActor - > sector ( ) , pPlayerActor - > spr . Angles . Yaw , near , 128. , NT_Hitag | NT_NoSpriteCheck ) ;
2021-11-22 21:20:53 +00:00
int tag ;
2021-11-26 18:30:32 +00:00
if ( near . hitWall ! = nullptr & & ( tag = near . hitWall - > lotag ) > 0 )
2021-11-22 21:20:53 +00:00
runlist_SignalRun ( tag - 1 , nPlayer , & ExhumedAI : : Use ) ;
2020-09-21 10:37:09 +00:00
2021-11-26 18:30:32 +00:00
if ( near . hitSector ! = nullptr & & ( tag = near . hitSector - > lotag ) > 0 )
2021-11-22 21:20:53 +00:00
runlist_SignalRun ( tag - 1 , nPlayer , & ExhumedAI : : Use ) ;
2021-10-15 20:19:07 +00:00
}
2023-03-24 08:38:10 +00:00
pPlayer - > bIsFiring = ! ! ( pPlayer - > input . actions & SB_FIRE ) ;
2021-10-15 20:19:07 +00:00
}
2019-08-31 07:47:15 +00:00
2023-03-24 08:36:43 +00:00
updatePlayerAction ( pPlayer ) ;
2023-03-24 04:53:37 +00:00
doPlayerPitch ( pPlayer ) ;
2021-10-15 20:19:07 +00:00
}
else // else, player's health is less than 0
{
2023-03-23 06:09:02 +00:00
setForcedSyncInput ( nPlayer ) ;
2023-03-23 04:37:06 +00:00
2023-03-24 01:01:36 +00:00
if ( pPlayer - > input . actions & SB_OPEN )
2021-10-15 20:19:07 +00:00
{
2023-03-24 01:01:36 +00:00
pPlayer - > input . actions & = ~ SB_OPEN ;
2019-08-31 07:47:15 +00:00
2023-03-24 04:14:07 +00:00
if ( pPlayer - > nAction > = 16 )
2019-08-31 07:47:15 +00:00
{
2021-10-15 20:19:07 +00:00
if ( nPlayer = = nLocalPlayer )
2019-08-31 07:47:15 +00:00
{
2021-10-15 20:19:07 +00:00
StopAllSounds ( ) ;
StopLocalSound ( ) ;
GrabPalette ( ) ;
2019-08-31 07:47:15 +00:00
}
2021-10-15 20:19:07 +00:00
2023-03-23 07:50:30 +00:00
pPlayer - > nCurrentWeapon = pPlayer - > nPlayerOldWeapon ;
2021-10-15 20:19:07 +00:00
2023-03-23 07:50:30 +00:00
if ( pPlayer - > nLives & & nNetTime )
2019-08-31 07:47:15 +00:00
{
2023-03-24 04:14:07 +00:00
if ( pPlayer - > nAction ! = 20 )
2019-08-31 07:47:15 +00:00
{
2021-12-23 18:01:43 +00:00
pPlayerActor - > spr . picnum = seq_GetSeqPicnum ( kSeqJoe , 120 , 0 ) ;
pPlayerActor - > spr . cstat = 0 ;
2022-08-20 14:44:30 +00:00
pPlayerActor - > spr . pos . Z = pPlayerActor - > sector ( ) - > floorz ;
2019-08-31 07:47:15 +00:00
}
2020-09-21 09:28:39 +00:00
2021-10-15 20:19:07 +00:00
// will invalidate nPlayerSprite
RestartPlayer ( nPlayer ) ;
}
else
{
2022-01-22 22:11:34 +00:00
DoGameOverScene ( currentLevel - > levelNumber = = 20 ) ;
2021-10-15 20:19:07 +00:00
return ;
2019-08-31 07:47:15 +00:00
}
}
2021-10-15 20:19:07 +00:00
}
}
2023-03-24 09:11:27 +00:00
doPlayerActionSequence ( pPlayer ) ;
2021-10-15 20:19:07 +00:00
2023-03-23 07:50:30 +00:00
if ( ! pPlayer - > nHealth )
2023-03-24 05:32:58 +00:00
doPlayerDeathPitch ( pPlayer ) ;
2021-10-15 20:19:07 +00:00
2023-03-24 09:12:27 +00:00
updatePlayerDoppleActor ( pPlayer ) ;
2021-10-15 20:19:07 +00:00
MoveWeapons ( nPlayer ) ;
}
2022-09-11 06:09:26 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2021-10-15 20:19:07 +00:00
2020-11-29 23:47:53 +00:00
FSerializer & Serialize ( FSerializer & arc , const char * keyname , Player & w , Player * def )
{
if ( arc . BeginObject ( keyname ) )
{
arc ( " health " , w . nHealth )
2021-11-21 18:33:51 +00:00
( " at2 " , w . nSeqSize )
2020-11-29 23:47:53 +00:00
( " action " , w . nAction )
2021-10-21 20:39:17 +00:00
( " sprite " , w . pActor )
2020-11-29 23:47:53 +00:00
( " mummy " , w . bIsMummified )
( " invincible " , w . invincibility )
( " air " , w . nAir )
( " seq " , w . nSeq )
2021-05-13 11:44:58 +00:00
( " item " , w . nItem )
2020-11-29 23:47:53 +00:00
( " maskamount " , w . nMaskAmount )
( " keys " , w . keys )
( " magic " , w . nMagic )
. Array ( " items " , w . items , countof ( w . items ) )
. Array ( " ammo " , w . nAmmo , countof ( w . nAmmo ) )
( " weapon " , w . nCurrentWeapon )
( " isfiring " , w . bIsFiring )
2021-11-21 18:33:51 +00:00
( " field3f " , w . nSeqSize2 )
( " field38 " , w . nNextWeapon )
( " field3a " , w . nState )
( " field3c " , w . nLastWeapon )
2020-11-29 23:47:53 +00:00
( " seq " , w . nSeq )
2022-11-25 06:09:11 +00:00
( " horizon " , w . Angles )
( " angle " , w . Angles )
2021-05-13 17:06:38 +00:00
( " lives " , w . nLives )
2021-05-13 17:15:53 +00:00
( " double " , w . nDouble )
( " invisible " , w . nInvisible )
( " torch " , w . nTorch )
2021-10-21 10:51:16 +00:00
( " breathtimer " , w . nBreathTimer )
( " playerswear " , w . nPlayerSwear )
2021-11-22 20:09:24 +00:00
( " pushsect " , w . pPlayerPushSect )
2021-10-21 10:51:16 +00:00
( " deathtype " , w . nDeathType )
( " score " , w . nPlayerScore )
( " color " , w . nPlayerColor )
2021-12-30 12:10:12 +00:00
( " dx " , w . nPlayerD . X )
( " dy " , w . nPlayerD . Y )
2021-10-21 10:51:16 +00:00
( " pistolclip " , w . nPistolClip )
2022-09-09 20:08:53 +00:00
( " thrustx " , w . nThrust . X )
( " thrusty " , w . nThrust . Y )
2021-10-21 17:54:39 +00:00
( " dopplesprite " , w . pDoppleSprite )
2021-10-21 10:51:16 +00:00
( " oldweapon " , w . nPlayerOldWeapon )
( " clip " , w . nPlayerClip )
( " pushsound " , w . nPlayerPushSound )
( " taunttimer " , w . nTauntTimer )
( " weapons " , w . nPlayerWeapons )
2021-11-22 23:20:15 +00:00
( " viewsect " , w . pPlayerViewSect )
2021-10-21 17:44:53 +00:00
( " floorspr " , w . pPlayerFloorSprite )
2021-10-21 10:51:16 +00:00
( " save " , w . sPlayerSave )
( " totalvel " , w . totalvel )
2021-10-21 17:44:53 +00:00
( " grenade " , w . pPlayerGrenade )
2021-10-21 10:51:16 +00:00
2020-11-29 23:47:53 +00:00
. EndObject ( ) ;
}
return arc ;
}
FSerializer & Serialize ( FSerializer & arc , const char * keyname , PlayerSave & w , PlayerSave * def )
{
if ( arc . BeginObject ( keyname ) )
{
2022-08-23 21:36:23 +00:00
arc ( " pos " , w . pos )
2021-11-22 23:20:15 +00:00
( " sector " , w . pSector )
2020-11-29 23:47:53 +00:00
( " angle " , w . nAngle )
. EndObject ( ) ;
}
return arc ;
}
void SerializePlayer ( FSerializer & arc )
{
if ( arc . BeginObject ( " player " ) )
{
2022-09-11 11:21:00 +00:00
arc ( " bobangle " , bobangle )
2020-11-29 23:47:53 +00:00
( " standheight " , nStandHeight )
( " playercount " , PlayerCount )
( " netstartsprites " , nNetStartSprites )
( " localplayer " , nLocalPlayer )
2021-10-21 08:41:41 +00:00
( " curstartsprite " , nCurStartSprite )
2021-10-21 10:51:16 +00:00
. Array ( " netstartsprite " , nNetStartSprite , kMaxPlayers )
. Array ( " list " , PlayerList , PlayerCount ) ;
2021-10-15 20:19:07 +00:00
arc . EndObject ( ) ;
2020-11-29 23:47:53 +00:00
}
}
2019-12-26 21:00:04 +00:00
2022-09-11 06:09:26 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2021-05-13 20:28:02 +00:00
DEFINE_FIELD_X ( ExhumedPlayer , Player , nHealth ) ;
DEFINE_FIELD_X ( ExhumedPlayer , Player , nLives ) ;
DEFINE_FIELD_X ( ExhumedPlayer , Player , nDouble ) ;
DEFINE_FIELD_X ( ExhumedPlayer , Player , nInvisible ) ;
DEFINE_FIELD_X ( ExhumedPlayer , Player , nTorch ) ;
2021-11-21 18:33:51 +00:00
DEFINE_FIELD_X ( ExhumedPlayer , Player , nSeqSize ) ;
2021-05-13 20:28:02 +00:00
DEFINE_FIELD_X ( ExhumedPlayer , Player , nAction ) ;
2021-10-21 20:39:17 +00:00
DEFINE_FIELD_X ( ExhumedPlayer , Player , pActor ) ;
2021-05-13 20:28:02 +00:00
DEFINE_FIELD_X ( ExhumedPlayer , Player , bIsMummified ) ;
DEFINE_FIELD_X ( ExhumedPlayer , Player , invincibility ) ;
DEFINE_FIELD_X ( ExhumedPlayer , Player , nAir ) ;
DEFINE_FIELD_X ( ExhumedPlayer , Player , nSeq ) ;
DEFINE_FIELD_X ( ExhumedPlayer , Player , nMaskAmount ) ;
2021-10-15 20:19:07 +00:00
DEFINE_FIELD_X ( ExhumedPlayer , Player , keys ) ;
2021-05-13 20:28:02 +00:00
DEFINE_FIELD_X ( ExhumedPlayer , Player , nMagic ) ;
DEFINE_FIELD_X ( ExhumedPlayer , Player , nItem ) ;
DEFINE_FIELD_X ( ExhumedPlayer , Player , items ) ;
2022-10-17 19:22:13 +00:00
DEFINE_FIELD_X ( ExhumedPlayer , Player , nAmmo ) ; // TODO - kMaxWeapons?
DEFINE_FIELD_X ( ExhumedPlayer , Player , nPlayerWeapons ) ;
2021-05-13 20:28:02 +00:00
DEFINE_FIELD_X ( ExhumedPlayer , Player , nCurrentWeapon ) ;
2021-11-21 18:33:51 +00:00
DEFINE_FIELD_X ( ExhumedPlayer , Player , nSeqSize2 ) ;
2021-05-13 20:28:02 +00:00
DEFINE_FIELD_X ( ExhumedPlayer , Player , bIsFiring ) ;
2021-11-21 18:33:51 +00:00
DEFINE_FIELD_X ( ExhumedPlayer , Player , nNextWeapon ) ;
DEFINE_FIELD_X ( ExhumedPlayer , Player , nState ) ;
DEFINE_FIELD_X ( ExhumedPlayer , Player , nLastWeapon ) ;
2021-05-13 20:28:02 +00:00
DEFINE_FIELD_X ( ExhumedPlayer , Player , nRun ) ;
DEFINE_FIELD_X ( ExhumedPlayer , Player , bPlayerPan ) ;
DEFINE_FIELD_X ( ExhumedPlayer , Player , bLockPan ) ;
DEFINE_ACTION_FUNCTION ( _Exhumed , GetViewPlayer )
{
ACTION_RETURN_POINTER ( & PlayerList [ nLocalPlayer ] ) ;
}
2021-07-16 13:52:56 +00:00
DEFINE_ACTION_FUNCTION ( _Exhumed , GetPistolClip )
{
2023-01-21 13:37:57 +00:00
ACTION_RETURN_INT ( PlayerList [ nLocalPlayer ] . nPistolClip ) ;
2021-07-16 13:52:56 +00:00
}
2021-07-17 04:57:43 +00:00
DEFINE_ACTION_FUNCTION ( _Exhumed , GetPlayerClip )
{
2023-01-21 13:37:57 +00:00
ACTION_RETURN_INT ( PlayerList [ nLocalPlayer ] . nPlayerClip ) ;
2021-07-17 04:57:43 +00:00
}
2021-05-13 20:28:02 +00:00
DEFINE_ACTION_FUNCTION ( _ExhumedPlayer , IsUnderwater )
{
PARAM_SELF_STRUCT_PROLOGUE ( Player ) ;
auto nLocalPlayer = self - PlayerList ;
2021-11-22 23:20:15 +00:00
ACTION_RETURN_BOOL ( PlayerList [ nLocalPlayer ] . pPlayerViewSect - > Flag & kSectUnderwater ) ;
2021-05-13 20:28:02 +00:00
}
DEFINE_ACTION_FUNCTION ( _ExhumedPlayer , GetAngle )
{
PARAM_SELF_STRUCT_PROLOGUE ( Player ) ;
2022-11-25 12:13:50 +00:00
ACTION_RETURN_INT ( self - > pActor - > spr . Angles . Yaw . Buildang ( ) ) ;
2021-05-13 20:28:02 +00:00
}
2019-11-22 23:11:37 +00:00
END_PS_NS