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 "compat.h"
# include "baselayer.h"
2019-08-31 09:08:38 +00:00
# include "common.h"
2019-08-26 03:59:14 +00:00
# include "engine.h"
# include "exhumed.h"
# include "sequence.h"
# include "names.h"
# include "menu.h"
# include "player.h"
2019-11-24 09:03:19 +00:00
# include "ps_input.h"
2019-08-26 03:59:14 +00:00
# include "sound.h"
# include "view.h"
# include "status.h"
# include "version.h"
2020-08-18 07:52:08 +00:00
# include "aistuff.h"
2019-12-27 09:52:40 +00:00
# include "mapinfo.h"
2019-08-26 03:59:14 +00:00
# include <string.h>
# include <cstdio> // for printf
# include <cstdlib>
# include <stdarg.h>
# include <ctype.h>
# include <time.h>
# include <assert.h>
2019-12-12 23:19:34 +00:00
# include "gamecvars.h"
2019-12-26 22:17:11 +00:00
# include "savegamehelp.h"
2019-12-27 19:05:58 +00:00
# include "c_dispatch.h"
2020-04-12 06:09:38 +00:00
# include "raze_sound.h"
2020-08-20 19:05:14 +00:00
# include "gamestate.h"
# include "screenjob.h"
2020-08-22 19:13:11 +00:00
# include "c_console.h"
# include "cheathandler.h"
2020-04-11 21:38:30 +00:00
# include "core/menu/menu.h"
2019-08-26 03:59:14 +00:00
2019-11-22 23:11:37 +00:00
BEGIN_PS_NS
2019-08-27 06:08:18 +00:00
extern const char * s_buildRev ;
extern const char * s_buildTimestamp ;
2019-08-31 09:08:38 +00:00
2020-08-18 07:52:08 +00:00
void uploadCinemaPalettes ( ) ;
2020-08-18 08:28:19 +00:00
int32_t registerosdcommands ( void ) ;
2020-08-19 22:55:31 +00:00
void InitFonts ( ) ;
2019-08-26 03:59:14 +00:00
int htimer = 0 ;
2020-08-23 10:26:52 +00:00
int EndLevel = false ;
2019-08-26 03:59:14 +00:00
2019-10-31 17:22:12 +00:00
2020-04-04 04:31:27 +00:00
PlayerInput localInput ;
2019-10-31 17:22:12 +00:00
////////
2020-08-18 07:52:08 +00:00
void ResetEngine ( )
{
EraseScreen ( - 1 ) ;
resettiming ( ) ;
totalclock = 0 ;
ototalclock = totalclock ;
localclock = ( int ) totalclock ;
numframes = 0 ;
}
void InstallEngine ( )
{
TileFiles . LoadArtSet ( " tiles%03d.art " ) ;
if ( engineInit ( ) )
{
G_FatalEngineError ( ) ;
}
uploadCinemaPalettes ( ) ;
LoadPaletteLookups ( ) ;
2020-08-19 22:55:31 +00:00
InitFonts ( ) ;
2020-08-18 07:52:08 +00:00
videoInit ( ) ;
enginecompatibility_mode = ENGINECOMPATIBILITY_19950829 ;
}
void RemoveEngine ( )
{
engineUnInit ( ) ;
}
2019-08-26 03:59:14 +00:00
void CopyTileToBitmap ( short nSrcTile , short nDestTile , int xPos , int yPos ) ;
// void TestSaveLoad();
void EraseScreen ( int nVal ) ;
void LoadStatus ( ) ;
void MySetView ( int x1 , int y1 , int x2 , int y2 ) ;
void mysetbrightness ( char al ) ;
char sHollyStr [ 40 ] ;
short nFontFirstChar ;
short nBackgroundPic ;
short nShadowPic ;
short nCreaturesLeft = 0 ;
short nFreeze ;
short nSnakeCam = - 1 ;
short nLocalSpr ;
int nNetPlayerCount = 0 ;
short nClockVal ;
short fps ;
short nRedTicks ;
2020-08-22 20:40:22 +00:00
short bInMove ;
2019-08-26 03:59:14 +00:00
short nAlarmTicks ;
short nButtonColor ;
short nEnergyChan ;
2020-08-18 08:28:19 +00:00
short bModemPlay = false ;
2019-08-26 03:59:14 +00:00
int lCountDown = 0 ;
short nEnergyTowers = 0 ;
short nCfgNetPlayers = 0 ;
FILE * vcrfp = NULL ;
int lLocalButtons = 0 ;
int lLocalCodes = 0 ;
2020-08-18 08:28:19 +00:00
short bCoordinates = false ;
2019-08-26 03:59:14 +00:00
int nNetTime = - 1 ;
short nCodeMin = 0 ;
short nCodeMax = 0 ;
short nCodeIndex = 0 ;
short levelnum = - 1 ;
2019-08-27 06:08:18 +00:00
//short nScreenWidth = 320;
//short nScreenHeight = 200;
2019-08-26 03:59:14 +00:00
int moveframes ;
int flash ;
int localclock ;
int totalmoves ;
short nCurBodyNum = 0 ;
short nBodyTotal = 0 ;
short lastfps ;
2019-11-18 20:31:08 +00:00
short nMapMode = 0 ;
2019-08-26 03:59:14 +00:00
short nTotalPlayers = 1 ;
2019-11-13 21:34:11 +00:00
// TODO: Rename this (or make it static) so it doesn't conflict with library function
//short socket = 0;
2019-08-26 03:59:14 +00:00
short nFirstPassword = 0 ;
short nFirstPassInfo = 0 ;
short nPasswordCount = 0 ;
2020-08-18 08:28:19 +00:00
short bSnakeCam = false ;
short bRecord = false ;
short bPlayback = false ;
short bInDemo = false ;
short bSlipMode = false ;
short bDoFlashes = true ;
2019-08-26 03:59:14 +00:00
2020-08-19 22:55:31 +00:00
short besttarget ;
2019-08-26 03:59:14 +00:00
short scan_char = 0 ;
int nStartLevel ;
int nTimeLimit ;
2019-10-27 16:36:25 +00:00
int bVanilla = 0 ;
2020-08-22 20:40:22 +00:00
ClockTicks tclocks ;
2019-08-26 03:59:14 +00:00
void DebugOut ( const char * fmt , . . . )
{
# ifdef _DEBUG
2019-08-27 06:08:18 +00:00
va_list args ;
2019-08-26 03:59:14 +00:00
va_start ( args , fmt ) ;
2019-11-24 09:03:19 +00:00
VPrintf ( PRINT_HIGH , fmt , args ) ;
2019-08-26 03:59:14 +00:00
# endif
}
2019-08-27 06:08:18 +00:00
void ShutDown ( void )
{
StopCD ( ) ;
RemoveEngine ( ) ;
2019-12-25 22:37:16 +00:00
//UnInitFX();
2019-08-27 06:08:18 +00:00
}
2019-08-31 07:47:15 +00:00
void timerhandler ( )
{
2019-12-27 19:05:58 +00:00
UpdateSounds ( ) ;
2019-08-27 06:08:18 +00:00
scan_char + + ;
if ( scan_char = = kTimerTicks )
{
scan_char = 0 ;
lastfps = fps ;
fps = 0 ;
}
2019-11-28 20:40:17 +00:00
if ( ! bInMove ) {
2020-07-14 12:00:27 +00:00
C_RunDelayedCommands ( ) ;
2019-11-28 20:40:17 +00:00
}
2019-08-26 03:59:14 +00:00
}
2019-08-31 15:04:06 +00:00
void HandleAsync ( )
{
handleevents ( ) ;
2020-03-01 15:32:41 +00:00
2019-08-31 15:04:06 +00:00
}
2020-08-22 19:13:11 +00:00
static bool HollyCheat ( cheatseq_t * c )
2019-08-26 03:59:14 +00:00
{
2020-08-22 19:13:11 +00:00
// Do the closest thing to this cheat that's available.
C_ToggleConsole ( ) ;
return true ;
}
2019-08-27 06:08:18 +00:00
2020-08-22 19:13:11 +00:00
static bool KimberlyCheat ( cheatseq_t * c )
{
Printf ( PRINT_NOTIFY , " %s \n " , GStrings ( " TXT_EX_SWEETIE " ) ) ;
return true ;
}
2019-08-27 06:08:18 +00:00
2020-08-22 19:13:11 +00:00
static bool CopCheat ( cheatseq_t * c )
{
lLocalCodes | = kButtonCheatGuns ;
return true ;
}
2019-08-27 06:08:18 +00:00
2020-08-22 19:13:11 +00:00
static bool GodCheat ( cheatseq_t * c )
{
lLocalCodes | = kButtonCheatGodMode ;
return true ;
}
2019-08-27 06:08:18 +00:00
2020-08-22 19:13:11 +00:00
static bool LiteCheat ( cheatseq_t * c )
{
Printf ( PRINT_NOTIFY , " %s \n " , GStrings ( " TXT_EX_FLASHES " ) ) ;
bDoFlashes = ! bDoFlashes ;
return true ;
}
2020-06-09 23:08:47 +00:00
2020-08-22 19:13:11 +00:00
static bool KeyCheat ( cheatseq_t * c )
{
lLocalCodes | = kButtonCheatKeys ;
return true ;
}
2019-08-27 06:08:18 +00:00
2020-08-22 19:13:11 +00:00
bool SlipCheat ( cheatseq_t * c )
{
if ( ! nNetPlayerCount )
{
if ( bSlipMode = = false )
2019-08-27 06:08:18 +00:00
{
2020-08-22 19:13:11 +00:00
bSlipMode = true ;
Printf ( PRINT_NOTIFY , " %s \n " , GStrings ( " TXT_EX_SLIPON " ) ) ;
2019-08-27 06:08:18 +00:00
}
2020-08-22 19:13:11 +00:00
else {
bSlipMode = false ;
Printf ( PRINT_NOTIFY , " %s \n " , GStrings ( " TXT_EX_SLIPOFF " ) ) ;
2019-08-27 06:08:18 +00:00
}
2020-08-22 19:13:11 +00:00
}
return true ;
}
2019-08-27 06:08:18 +00:00
2020-08-22 19:13:11 +00:00
static bool SnakeCheat ( cheatseq_t * c )
{
if ( ! nNetPlayerCount )
{
if ( bSnakeCam = = false )
2019-08-27 06:08:18 +00:00
{
2020-08-22 19:13:11 +00:00
bSnakeCam = true ;
Printf ( PRINT_NOTIFY , " %s \n " , GStrings ( " TXT_EX_SNAKEON " ) ) ;
2019-08-27 06:08:18 +00:00
}
2020-08-22 19:13:11 +00:00
else {
bSnakeCam = false ;
Printf ( PRINT_NOTIFY , " %s \n " , GStrings ( " TXT_EX_SNAKEOFF " ) ) ;
2019-08-27 06:08:18 +00:00
}
2020-08-22 19:13:11 +00:00
}
return true ;
}
2019-08-27 06:08:18 +00:00
2020-08-22 19:13:11 +00:00
static bool SphereCheat ( cheatseq_t * c )
{
Printf ( PRINT_NOTIFY , " %s \n " , GStrings ( " TXT_EX_FULLMAP " ) ) ;
GrabMap ( ) ;
bShowTowers = true ;
return true ;
}
2019-08-27 06:08:18 +00:00
2020-08-22 19:13:11 +00:00
static bool SwagCheat ( cheatseq_t * c )
{
lLocalCodes | = kButtonCheatItems ;
return true ;
}
2019-08-27 06:08:18 +00:00
2020-08-22 19:13:11 +00:00
static bool CoordCheat ( cheatseq_t * c )
{
C_DoCommand ( " stat printcoords " ) ;
return true ;
}
2019-08-27 06:08:18 +00:00
2020-08-22 19:13:11 +00:00
static cheatseq_t excheats [ ] = {
{ " holly " , HollyCheat , 0 } ,
{ " kimberly " , KimberlyCheat , 0 } ,
{ " lobocop " , CopCheat , 0 } ,
{ " lobodeity " , GodCheat , 0 } ,
{ " lobolite " , LiteCheat , 0 } ,
{ " lobopick " , KeyCheat , 0 } ,
{ " loboslip " , SlipCheat , 0 } ,
{ " lobosnake " , SnakeCheat , 0 } ,
{ " lobosphere " , SphereCheat , 0 } ,
{ " loboswag " , SwagCheat , 0 } ,
{ " loboxy " , CoordCheat , true } ,
} ;
2019-08-26 03:59:14 +00:00
void mysetbrightness ( char nBrightness )
{
2019-08-27 06:08:18 +00:00
g_visibility = 2048 - ( nBrightness < < 9 ) ;
2019-08-26 03:59:14 +00:00
}
2020-01-05 19:20:33 +00:00
// Replicate original DOS EXE behaviour when pointer is null
static const char * safeStrtok ( char * s , const char * d )
{
const char * r = strtok ( s , d ) ;
return r ? r : " " ;
}
2020-01-22 15:14:01 +00:00
2019-08-26 03:59:14 +00:00
void DoClockBeep ( )
{
2019-08-27 06:08:18 +00:00
for ( int i = headspritestat [ 407 ] ; i ! = - 1 ; i = nextspritestat [ i ] ) {
2019-09-21 15:47:55 +00:00
PlayFX2 ( StaticSound [ kSound74 ] , i ) ;
2019-08-27 06:08:18 +00:00
}
2019-08-26 03:59:14 +00:00
}
void DoRedAlert ( int nVal )
{
2019-08-27 06:08:18 +00:00
if ( nVal )
{
nAlarmTicks = 69 ;
nRedTicks = 30 ;
}
for ( int i = headspritestat [ 405 ] ; i ! = - 1 ; i = nextspritestat [ i ] )
{
if ( nVal )
{
2019-09-21 15:47:55 +00:00
PlayFXAtXYZ ( StaticSound [ kSoundAlarm ] , sprite [ i ] . x , sprite [ i ] . y , sprite [ i ] . z , sprite [ i ] . sectnum ) ;
2019-08-27 06:08:18 +00:00
AddFlash ( sprite [ i ] . sectnum , sprite [ i ] . x , sprite [ i ] . y , sprite [ i ] . z , 192 ) ;
}
}
2019-08-26 03:59:14 +00:00
}
void DrawClock ( )
{
2019-08-27 06:08:18 +00:00
int ebp = 49 ;
2019-08-26 03:59:14 +00:00
2019-11-24 12:59:36 +00:00
auto pixels = TileFiles . tileMakeWritable ( kTile3603 ) ;
2019-08-26 03:59:14 +00:00
2020-04-11 22:04:02 +00:00
memset ( pixels , TRANSPARENT_INDEX , 4096 ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
if ( lCountDown / 30 ! = nClockVal )
{
nClockVal = lCountDown / 30 ;
DoClockBeep ( ) ;
}
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
int nVal = nClockVal ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
while ( nVal )
{
int v2 = nVal & 0xF ;
2020-02-04 21:45:10 +00:00
int yPos = 32 - tilesiz [ v2 + kClockSymbol1 ] . y / 2 ;
2019-08-26 03:59:14 +00:00
2020-02-04 21:45:10 +00:00
CopyTileToBitmap ( v2 + kClockSymbol1 , kTile3603 , ebp - tilesiz [ v2 + kClockSymbol1 ] . x / 2 , yPos ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
ebp - = 15 ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
nVal / = 16 ;
}
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
DoEnergyTile ( ) ;
2019-08-26 03:59:14 +00:00
}
2020-08-22 20:40:22 +00:00
int32_t calc_smoothratio ( ClockTicks totalclk , ClockTicks ototalclk )
2019-11-03 17:20:05 +00:00
{
2020-05-29 01:15:01 +00:00
if ( bRecord | | bPlayback | | nFreeze ! = 0 | | bCamera | | paused )
2019-11-03 17:20:05 +00:00
return 65536 ;
2020-02-02 09:27:47 +00:00
return CalcSmoothRatio ( totalclk , ototalclk , 30 ) ;
2019-11-03 17:20:05 +00:00
}
2019-12-25 23:21:04 +00:00
FString GameInterface : : statFPS ( )
2019-11-15 06:48:40 +00:00
{
2019-12-25 23:21:04 +00:00
FString out ;
2019-11-15 06:48:40 +00:00
static int32_t frameCount ;
static double cumulativeFrameDelay ;
static double lastFrameTime ;
2019-12-02 16:34:59 +00:00
static float lastFPS ; // , minFPS = std::numeric_limits<float>::max(), maxFPS;
//static double minGameUpdate = std::numeric_limits<double>::max(), maxGameUpdate;
2019-11-15 06:48:40 +00:00
double frameTime = timerGetHiTicks ( ) ;
double frameDelay = frameTime - lastFrameTime ;
cumulativeFrameDelay + = frameDelay ;
if ( frameDelay > = 0 )
{
2019-12-25 23:21:04 +00:00
out . Format ( " %.1f ms, %5.1f fps " , frameDelay , lastFPS ) ;
2019-11-15 06:48:40 +00:00
if ( cumulativeFrameDelay > = 1000.0 )
{
lastFPS = 1000.f * frameCount / cumulativeFrameDelay ;
// g_frameRate = Blrintf(lastFPS);
frameCount = 0 ;
cumulativeFrameDelay = 0.0 ;
}
frameCount + + ;
}
lastFrameTime = frameTime ;
2019-12-25 23:21:04 +00:00
return out ;
2019-11-15 06:48:40 +00:00
}
2020-08-22 20:40:22 +00:00
void GameMove ( void )
2019-11-03 17:20:05 +00:00
{
FixPalette ( ) ;
if ( levelnum = = kMap20 )
{
if ( lCountDown < = 0 )
{
2020-08-23 10:26:52 +00:00
DoGameOverScene ( true ) ;
2019-11-03 17:20:05 +00:00
return ;
}
// Pink section
lCountDown - - ;
DrawClock ( ) ;
if ( nRedTicks )
{
nRedTicks - - ;
if ( nRedTicks < = 0 ) {
DoRedAlert ( 0 ) ;
}
2019-11-18 22:15:48 +00:00
}
2019-11-03 17:20:05 +00:00
2019-11-18 22:15:48 +00:00
nAlarmTicks - - ;
nButtonColor - - ;
2019-11-03 17:20:05 +00:00
2019-11-18 22:15:48 +00:00
if ( nAlarmTicks < = 0 ) {
DoRedAlert ( 1 ) ;
2019-11-03 17:20:05 +00:00
}
}
// YELLOW SECTION
MoveThings ( ) ;
2019-11-08 16:55:26 +00:00
obobangle = bobangle ;
2019-11-03 17:20:05 +00:00
if ( totalvel [ nLocalPlayer ] = = 0 )
{
bobangle = 0 ;
}
else
{
bobangle + = 56 ;
bobangle & = kAngleMask ;
}
2019-11-03 17:32:02 +00:00
UpdateCreepySounds ( ) ;
2019-11-03 17:20:05 +00:00
// loc_120E9:
totalmoves + + ;
moveframes - - ;
}
2020-08-23 05:49:58 +00:00
void GameTicker ( )
{
2020-08-23 07:11:32 +00:00
bInMove = true ;
if ( paused )
{
tclocks = totalclock - 4 ;
buttonMap . ResetButtonStates ( ) ;
}
else
2020-08-23 05:49:58 +00:00
{
2020-08-23 07:11:32 +00:00
while ( ( totalclock - ototalclock ) > = 1 | | ! bInMove )
{
ototalclock = ototalclock + 1 ;
2020-08-23 05:49:58 +00:00
2020-08-23 07:11:32 +00:00
if ( ! ( ( int ) ototalclock & 3 ) & & moveframes < 4 )
moveframes + + ;
2020-08-23 05:49:58 +00:00
2020-08-23 07:11:32 +00:00
GetLocalInput ( ) ;
PlayerInterruptKeys ( ) ;
2020-08-23 05:49:58 +00:00
2020-08-23 07:11:32 +00:00
nPlayerDAng = fix16_sadd ( nPlayerDAng , localInput . nAngle ) ;
inita & = kAngleMask ;
2020-08-23 05:49:58 +00:00
2020-08-23 07:11:32 +00:00
lPlayerXVel + = localInput . yVel * Cos ( inita ) + localInput . xVel * Sin ( inita ) ;
lPlayerYVel + = localInput . yVel * Sin ( inita ) - localInput . xVel * Cos ( inita ) ;
lPlayerXVel - = ( lPlayerXVel > > 5 ) + ( lPlayerXVel > > 6 ) ;
lPlayerYVel - = ( lPlayerYVel > > 5 ) + ( lPlayerYVel > > 6 ) ;
2020-08-23 05:49:58 +00:00
2020-08-23 07:11:32 +00:00
sPlayerInput [ nLocalPlayer ] . xVel = lPlayerXVel ;
sPlayerInput [ nLocalPlayer ] . yVel = lPlayerYVel ;
sPlayerInput [ nLocalPlayer ] . buttons = lLocalButtons | lLocalCodes ;
sPlayerInput [ nLocalPlayer ] . nAngle = nPlayerDAng ;
sPlayerInput [ nLocalPlayer ] . nTarget = besttarget ;
2020-08-23 05:49:58 +00:00
2020-08-23 07:11:32 +00:00
Ra [ nLocalPlayer ] . nTarget = besttarget ;
2020-08-23 05:49:58 +00:00
2020-08-23 07:11:32 +00:00
lLocalCodes = 0 ;
nPlayerDAng = 0 ;
2020-08-23 05:49:58 +00:00
2020-08-23 07:11:32 +00:00
sPlayerInput [ nLocalPlayer ] . horizon = PlayerList [ nLocalPlayer ] . q16horiz ;
2020-08-23 05:49:58 +00:00
2020-08-23 07:11:32 +00:00
while ( ! EndLevel & & totalclock > = tclocks + 4 )
{
tclocks + = 4 ;
GameMove ( ) ;
}
}
if ( nPlayerLives [ nLocalPlayer ] < = 0 ) {
startmainmenu ( ) ;
2020-08-23 05:49:58 +00:00
}
2020-08-23 07:11:32 +00:00
}
bInMove = false ;
2020-08-23 05:49:58 +00:00
}
2019-11-03 17:20:05 +00:00
int32_t r_maxfpsoffset = 0 ;
2019-12-14 00:33:26 +00:00
void ExitGame ( )
{
ShutDown ( ) ;
2020-04-11 21:50:43 +00:00
throw CExitEvent ( 0 ) ;
2019-12-14 00:33:26 +00:00
}
2020-08-22 20:40:22 +00:00
void InitTimer ( )
{
htimer = 1 ;
timerInit ( kTimerTicks ) ;
timerSetCallback ( timerhandler ) ;
}
2019-11-18 20:31:08 +00:00
2020-04-11 22:10:39 +00:00
static const char * actions [ ] =
{
" Move_Forward " ,
" Move_Backward " ,
" Turn_Left " ,
" Turn_Right " ,
" Strafe " ,
" Fire " ,
" Open " ,
" Run " ,
" Alt_Fire " , // Duke3D", Blood
" Jump " ,
" Crouch " ,
" Look_Up " ,
" Look_Down " ,
" Look_Left " ,
" Look_Right " ,
" Strafe_Left " ,
" Strafe_Right " ,
" Aim_Up " ,
" Aim_Down " ,
" Weapon_1 " ,
" Weapon_2 " ,
" Weapon_3 " ,
" Weapon_4 " ,
" Weapon_5 " ,
" Weapon_6 " ,
" Weapon_7 " ,
" Weapon_8 " ,
" Weapon_9 " ,
" Weapon_10 " ,
" Inventory " ,
" Inventory_Left " ,
" Inventory_Right " ,
" TurnAround " ,
" SendMessage " ,
" Map " ,
" Shrink_Screen " ,
" Enlarge_Screen " ,
" Center_View " ,
" Holster_Weapon " ,
" Show_Opponents_Weapon " ,
" Map_Follow_Mode " ,
" See_Coop_View " ,
" Mouse_Aiming " ,
" Toggle_Crosshair " ,
" Next_Weapon " ,
" Previous_Weapon " ,
" Dpad_Select " ,
" Dpad_Aiming " ,
" Last_Weapon " ,
" Alt_Weapon " ,
" Third_Person_View " ,
" Toggle_Crouch " , // This is the last one used by EDuke32.
} ;
2019-12-27 19:05:58 +00:00
2020-08-18 07:52:08 +00:00
2020-08-20 19:05:14 +00:00
2020-08-22 20:40:22 +00:00
void InitGame ( )
2019-11-24 12:59:36 +00:00
{
int i ;
//int esi = 1;
//int edi = esi;
2020-04-11 22:10:39 +00:00
buttonMap . SetButtons ( actions , NUM_ACTIONS ) ;
2020-02-29 11:55:12 +00:00
help_disabled = true ;
2019-12-27 09:52:40 +00:00
// Create the global level table. Parts of the engine need it, even though the game itself does not.
for ( int i = 0 ; i < = 32 ; i + + )
{
2020-08-23 10:26:52 +00:00
auto mi = AllocateMap ( ) ;
2019-12-27 09:52:40 +00:00
mi - > fileName . Format ( " LEV%d.MAP " , i ) ;
mi - > labelName . Format ( " LEV%d " , i ) ;
mi - > name . Format ( " $TXT_EX_MAP%02d " , i ) ;
2020-08-23 10:26:52 +00:00
mi - > levelNumber = i ;
2019-12-27 09:52:40 +00:00
int nTrack = i ;
if ( nTrack ! = 0 ) nTrack - - ;
mi - > cdSongId = ( nTrack % 8 ) + 11 ;
}
2020-08-22 19:13:11 +00:00
SetCheats ( excheats , countof ( excheats ) ) ;
2019-08-31 09:08:38 +00:00
registerosdcommands ( ) ;
2019-08-27 06:08:18 +00:00
if ( nNetPlayerCount = = - 1 )
{
nNetPlayerCount = nCfgNetPlayers - 1 ;
nTotalPlayers + = nNetPlayerCount ;
}
// temp - moving InstallEngine(); before FadeOut as we use nextpage() in FadeOut
InstallEngine ( ) ;
2020-08-22 20:40:22 +00:00
const char * defsfile = G_DefFile ( ) ;
2019-11-21 12:51:27 +00:00
uint32_t stime = timerGetTicks ( ) ;
if ( ! loaddefinitionsfile ( defsfile ) )
{
uint32_t etime = timerGetTicks ( ) ;
2020-08-22 20:40:22 +00:00
Printf ( " Definitions file \" %s \" loaded in %d ms. \n " , defsfile , etime - stime ) ;
2019-11-21 12:51:27 +00:00
}
2020-02-01 22:05:43 +00:00
enginePostInit ( ) ;
2019-08-31 14:07:47 +00:00
2019-08-27 06:08:18 +00:00
InitView ( ) ;
2019-09-19 13:38:28 +00:00
InitFX ( ) ;
2019-08-27 06:08:18 +00:00
seq_LoadSequences ( ) ;
InitStatus ( ) ;
InitTimer ( ) ;
for ( i = 0 ; i < kMaxPlayers ; i + + ) {
nPlayerLives [ i ] = kDefaultLives ;
}
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
ResetEngine ( ) ;
ResetView ( ) ;
GrabPalette ( ) ;
2019-08-26 03:59:14 +00:00
}
void mychangespritesect ( int nSprite , int nSector )
{
2019-08-27 06:08:18 +00:00
DoKenTest ( ) ;
changespritesect ( nSprite , nSector ) ;
DoKenTest ( ) ;
2019-08-26 03:59:14 +00:00
}
void mydeletesprite ( int nSprite )
{
2019-08-27 06:08:18 +00:00
if ( nSprite < 0 | | nSprite > kMaxSprites ) {
2019-11-24 09:03:19 +00:00
I_Error ( " bad sprite value %d handed to mydeletesprite " , nSprite ) ;
2019-08-27 06:08:18 +00:00
}
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
deletesprite ( nSprite ) ;
2019-08-26 03:59:14 +00:00
2019-08-27 06:08:18 +00:00
if ( nSprite = = besttarget ) {
besttarget = - 1 ;
}
2019-08-26 03:59:14 +00:00
}
void CopyTileToBitmap ( short nSrcTile , short nDestTile , int xPos , int yPos )
{
2019-08-27 06:08:18 +00:00
int nOffs = tilesiz [ nDestTile ] . y * xPos ;
2019-11-24 12:59:36 +00:00
auto pixels = TileFiles . tileMakeWritable ( nDestTile ) ;
uint8_t * pDest = pixels + nOffs + yPos ;
2019-08-31 07:47:15 +00:00
uint8_t * pDestB = pDest ;
2019-08-27 06:08:18 +00:00
tileLoad ( nSrcTile ) ;
int destYSize = tilesiz [ nDestTile ] . y ;
int srcYSize = tilesiz [ nSrcTile ] . y ;
2019-11-20 16:21:32 +00:00
2019-11-24 12:59:36 +00:00
const uint8_t * pSrc = tilePtr ( nSrcTile ) ;
2019-11-20 16:21:32 +00:00
2019-08-27 06:08:18 +00:00
for ( int x = 0 ; x < tilesiz [ nSrcTile ] . x ; x + + )
{
pDest + = destYSize ;
for ( int y = 0 ; y < srcYSize ; y + + )
{
2019-08-31 07:47:15 +00:00
uint8_t val = * pSrc ;
2020-04-11 22:04:02 +00:00
if ( val ! = TRANSPARENT_INDEX ) {
2019-08-27 06:08:18 +00:00
* pDestB = val ;
}
pDestB + + ;
pSrc + + ;
}
// reset pDestB
pDestB = pDest ;
}
2019-11-05 06:15:21 +00:00
2020-08-22 16:12:19 +00:00
TileFiles . InvalidateTile ( nDestTile ) ;
2019-08-26 03:59:14 +00:00
}
void EraseScreen ( int nVal )
{
2020-04-12 05:44:55 +00:00
// There's no other values than 0 ever coming through here.
2020-06-12 18:52:01 +00:00
twod - > ClearScreen ( ) ;
2019-08-26 03:59:14 +00:00
}
2019-12-26 18:41:42 +00:00
bool GameInterface : : CanSave ( )
{
2020-05-29 01:15:01 +00:00
return ! bRecord & & ! bPlayback & & ! paused & & ! bInDemo & & nTotalPlayers = = 1 ;
2019-12-26 18:41:42 +00:00
}
2019-12-27 09:52:40 +00:00
2019-12-12 23:19:34 +00:00
: : GameInterface * CreateInterface ( )
{
return new GameInterface ;
}
2019-12-26 21:00:04 +00:00
// This is only the static global data.
static SavegameHelper sgh ( " exhumed " ,
2020-08-19 22:55:31 +00:00
SV ( besttarget ) ,
2019-12-26 21:00:04 +00:00
SV ( nCreaturesLeft ) , // todo: also maintain a total counter.
SV ( nFreeze ) ,
SV ( nSnakeCam ) ,
SV ( nLocalSpr ) ,
SV ( nClockVal ) , // kTile3603
SV ( nRedTicks ) ,
SV ( nAlarmTicks ) ,
SV ( nButtonColor ) ,
SV ( nEnergyChan ) ,
SV ( lCountDown ) ,
SV ( nEnergyTowers ) ,
SV ( levelnum ) ,
SV ( moveframes ) ,
SV ( totalmoves ) ,
SV ( nCurBodyNum ) ,
SV ( nBodyTotal ) ,
SV ( bSnakeCam ) ,
SV ( bSlipMode ) ,
2019-12-26 22:17:11 +00:00
SV ( localclock ) ,
SV ( tclocks ) ,
SV ( totalclock ) ,
2019-12-26 21:00:04 +00:00
nullptr ) ;
2020-08-22 19:39:14 +00:00
extern short cPupData [ 300 ] ;
extern uint8_t * Worktile ;
extern int lHeadStartClock ;
extern short * pPupData ;
2019-12-26 21:00:04 +00:00
2019-12-26 22:17:11 +00:00
void SaveTextureState ( )
{
auto fw = WriteSavegameChunk ( " texture " ) ;
int pupOffset = pPupData ? int ( pPupData - cPupData ) : - 1 ;
2019-12-27 09:52:40 +00:00
// There is really no good way to restore these tiles, so it's probably best to save them as well, so that they can be reloaded with the exact state they were left in
2019-12-26 22:17:11 +00:00
fw - > Write ( & pupOffset , 4 ) ;
uint8_t loaded = ! ! Worktile ;
fw - > Write ( & loaded , 1 ) ;
if ( Worktile ) fw - > Write ( Worktile , WorktileSize ) ;
auto pixels = TileFiles . tileMakeWritable ( kTile3603 ) ;
fw - > Write ( pixels , tilesiz [ kTile3603 ] . x * tilesiz [ kTile3603 ] . y ) ;
2019-12-27 09:52:40 +00:00
pixels = TileFiles . tileMakeWritable ( kEnergy1 ) ;
fw - > Write ( pixels , tilesiz [ kEnergy1 ] . x * tilesiz [ kEnergy1 ] . y ) ;
pixels = TileFiles . tileMakeWritable ( kEnergy2 ) ;
fw - > Write ( pixels , tilesiz [ kEnergy2 ] . x * tilesiz [ kEnergy2 ] . y ) ;
2019-12-26 22:17:11 +00:00
}
void LoadTextureState ( )
{
auto fr = ReadSavegameChunk ( " texture " ) ;
int pofs ;
fr . Read ( & pofs , 4 ) ;
pPupData = pofs = = - 1 ? nullptr : cPupData + pofs ;
uint8_t loaded ;
fr . Read ( & loaded , 1 ) ;
if ( loaded )
{
Worktile = TileFiles . tileCreate ( kTileRamsesWorkTile , kSpiritX * 2 , kSpiritY * 2 ) ;
fr . Read ( Worktile , WorktileSize ) ;
}
auto pixels = TileFiles . tileMakeWritable ( kTile3603 ) ;
fr . Read ( pixels , tilesiz [ kTile3603 ] . x * tilesiz [ kTile3603 ] . y ) ;
2019-12-27 09:52:40 +00:00
pixels = TileFiles . tileMakeWritable ( kEnergy1 ) ;
fr . Read ( pixels , tilesiz [ kEnergy1 ] . x * tilesiz [ kEnergy1 ] . y ) ;
pixels = TileFiles . tileMakeWritable ( kEnergy2 ) ;
fr . Read ( pixels , tilesiz [ kEnergy2 ] . x * tilesiz [ kEnergy2 ] . y ) ;
2019-12-26 22:17:11 +00:00
TileFiles . InvalidateTile ( kTileRamsesWorkTile ) ;
TileFiles . InvalidateTile ( kTile3603 ) ;
2019-12-27 09:52:40 +00:00
TileFiles . InvalidateTile ( kEnergy1 ) ;
TileFiles . InvalidateTile ( kEnergy2 ) ;
2019-12-26 22:17:11 +00:00
}
2019-12-26 21:00:04 +00:00
2019-11-22 23:11:37 +00:00
END_PS_NS