2019-09-19 22:42:45 +00:00
//-------------------------------------------------------------------------
/*
Copyright ( C ) 2010 - 2019 EDuke32 developers and contributors
Copyright ( C ) 2019 Nuke . YKT
This file is part of NBlood .
NBlood is free software ; you can redistribute it and / or
modify it under the terms of the GNU General Public License version 2
as published by the Free Software Foundation .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE .
See the GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
*/
//-------------------------------------------------------------------------
2019-09-21 18:59:54 +00:00
# include "ns.h" // Must come before everything else!
2019-09-19 22:42:45 +00:00
# include "build.h"
# include "mmulti.h"
# include "compat.h"
2019-10-25 22:32:49 +00:00
# include "gamecontrol.h"
2019-09-19 22:42:45 +00:00
# include "common_game.h"
# include "blood.h"
# include "config.h"
# include "demo.h"
# include "eventq.h"
# include "globals.h"
# include "levels.h"
# include "loadsave.h"
2019-12-01 09:18:38 +00:00
# include "gamemenu.h"
2019-09-19 22:42:45 +00:00
# include "messages.h"
# include "network.h"
# include "player.h"
# include "view.h"
2019-12-09 01:01:30 +00:00
# include "gstrings.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
CPlayerMsg gPlayerMsg ;
CCheatMgr gCheatMgr ;
void sub_5A928 ( void )
{
2020-04-11 22:10:39 +00:00
for ( int i = 0 ; i < buttonMap . NumButtons ( ) ; i + + )
2019-11-04 22:01:50 +00:00
buttonMap . ClearButton ( i ) ;
2019-09-19 22:42:45 +00:00
}
void SetGodMode ( bool god )
{
playerSetGodMode ( gMe , god ) ;
2019-10-21 19:46:41 +00:00
if ( gMe - > godMode )
2019-12-09 01:01:30 +00:00
viewSetMessage ( GStrings ( " TXTB_GODMODE " ) ) ;
2019-09-19 22:42:45 +00:00
else
2019-12-09 01:01:30 +00:00
viewSetMessage ( GStrings ( " TXTB_NOTGODMODE " ) ) ;
2019-09-19 22:42:45 +00:00
}
void SetClipMode ( bool noclip )
{
gNoClip = noclip ;
if ( gNoClip )
2019-12-09 01:01:30 +00:00
viewSetMessage ( GStrings ( " TXTB_NOCLIP " ) ) ;
2019-09-19 22:42:45 +00:00
else
2019-12-09 01:01:30 +00:00
viewSetMessage ( GStrings ( " TXTB_NOCLIPOFF " ) ) ;
2019-09-19 22:42:45 +00:00
}
void packStuff ( PLAYER * pPlayer )
{
for ( int i = 0 ; i < 5 ; i + + )
packAddItem ( pPlayer , i ) ;
}
void packClear ( PLAYER * pPlayer )
{
2019-10-21 19:46:41 +00:00
pPlayer - > packItemId = 0 ;
2019-09-19 22:42:45 +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
}
}
void SetAmmo ( bool stat )
{
if ( stat )
{
for ( int i = 0 ; i < 12 ; i + + )
2019-10-25 20:53:41 +00:00
gMe - > ammoCount [ i ] = gAmmoInfo [ i ] . max ;
2019-12-09 01:01:30 +00:00
viewSetMessage ( GStrings ( " TXTB_FULLAMMO " ) ) ;
2019-09-19 22:42:45 +00:00
}
else
{
for ( int i = 0 ; i < 12 ; i + + )
2019-10-25 20:53:41 +00:00
gMe - > ammoCount [ i ] = 0 ;
2019-12-09 01:01:30 +00:00
viewSetMessage ( GStrings ( " TXTB_NOAMMO " ) ) ;
2019-09-19 22:42:45 +00:00
}
}
void SetWeapons ( bool stat )
{
for ( int i = 0 ; i < 14 ; i + + )
{
2019-10-21 19:46:41 +00:00
gMe - > hasWeapon [ i ] = stat ;
2019-09-19 22:42:45 +00:00
}
SetAmmo ( stat ) ;
if ( stat )
2019-12-09 01:01:30 +00:00
viewSetMessage ( GStrings ( " TXTB_ALLWEAP " ) ) ;
2019-09-19 22:42:45 +00:00
else
{
if ( ! VanillaMode ( ) )
{
// Keep the pitchfork to avoid freeze
2019-10-21 19:46:41 +00:00
gMe - > hasWeapon [ 1 ] = 1 ;
gMe - > curWeapon = 0 ;
gMe - > nextWeapon = 1 ;
2019-09-19 22:42:45 +00:00
}
2019-12-09 01:01:30 +00:00
viewSetMessage ( GStrings ( " TXTB_NOWEAP " ) ) ;
2019-09-19 22:42:45 +00:00
}
}
void SetToys ( bool stat )
{
if ( stat )
{
packStuff ( gMe ) ;
2019-12-09 01:01:30 +00:00
viewSetMessage ( GStrings ( " TXTB_FULLINV " ) ) ;
2019-09-19 22:42:45 +00:00
}
else
{
packClear ( gMe ) ;
2019-12-09 01:01:30 +00:00
viewSetMessage ( GStrings ( " TXTB_NOINV " ) ) ;
2019-09-19 22:42:45 +00:00
}
}
void SetArmor ( bool stat )
{
int nAmount ;
if ( stat )
{
2019-12-09 01:01:30 +00:00
viewSetMessage ( GStrings ( " TXTB_FULLARM " ) ) ;
2019-09-19 22:42:45 +00:00
nAmount = 3200 ;
}
else
{
2019-12-09 01:01:30 +00:00
viewSetMessage ( GStrings ( " TXTB_NOARM " ) ) ;
2019-09-19 22:42:45 +00:00
nAmount = 0 ;
}
for ( int i = 0 ; i < 3 ; i + + )
2019-10-21 19:46:41 +00:00
gMe - > armor [ i ] = nAmount ;
2019-09-19 22:42:45 +00:00
}
void SetKeys ( bool stat )
{
for ( int i = 1 ; i < = 6 ; i + + )
2019-10-21 19:46:41 +00:00
gMe - > hasKey [ i ] = stat ;
2019-09-19 22:42:45 +00:00
if ( stat )
2019-12-09 01:01:30 +00:00
viewSetMessage ( GStrings ( " TXTB_ALLKEYS " ) ) ;
2019-09-19 22:42:45 +00:00
else
2019-12-09 01:01:30 +00:00
viewSetMessage ( GStrings ( " TXTB_NOKEYS " ) ) ;
2019-09-19 22:42:45 +00:00
}
void SetInfiniteAmmo ( bool stat )
{
gInfiniteAmmo = stat ;
if ( gInfiniteAmmo )
2019-12-09 01:01:30 +00:00
viewSetMessage ( GStrings ( " TXTB_INFAMMO " ) ) ;
2019-09-19 22:42:45 +00:00
else
2019-12-09 01:01:30 +00:00
viewSetMessage ( GStrings ( " TXTB_LIMAMMO " ) ) ;
2019-09-19 22:42:45 +00:00
}
void SetMap ( bool stat )
{
gFullMap = stat ;
if ( gFullMap )
2019-12-09 01:01:30 +00:00
viewSetMessage ( GStrings ( " TXTB_ALLMAP " ) ) ;
2019-09-19 22:42:45 +00:00
else
2019-12-09 01:01:30 +00:00
viewSetMessage ( GStrings ( " TXTB_NOALLMAP " ) ) ;
2019-09-19 22:42:45 +00:00
}
void SetWooMode ( bool stat )
{
if ( stat )
{
2019-10-19 19:11:39 +00:00
if ( ! powerupCheck ( gMe , kPwUpTwoGuns ) )
powerupActivate ( gMe , kPwUpTwoGuns ) ;
2019-09-19 22:42:45 +00:00
}
else
{
2019-10-19 19:11:39 +00:00
if ( powerupCheck ( gMe , kPwUpTwoGuns ) )
2019-09-19 22:42:45 +00:00
{
if ( ! VanillaMode ( ) )
2019-10-21 19:46:41 +00:00
gMe - > pwUpTime [ kPwUpTwoGuns ] = 0 ;
2019-10-19 19:11:39 +00:00
powerupDeactivate ( gMe , kPwUpTwoGuns ) ;
2019-09-19 22:42:45 +00:00
}
}
}
void ToggleWooMode ( void )
{
2019-10-19 19:11:39 +00:00
SetWooMode ( ! ( powerupCheck ( gMe , kPwUpTwoGuns ) ! = 0 ) ) ;
2019-09-19 22:42:45 +00:00
}
void ToggleBoots ( void )
{
2019-10-19 19:11:39 +00:00
if ( powerupCheck ( gMe , kPwUpJumpBoots ) )
2019-09-19 22:42:45 +00:00
{
2019-12-09 01:01:30 +00:00
viewSetMessage ( GStrings ( " TXTB_NOJBOOTS " ) ) ;
2019-09-19 22:42:45 +00:00
if ( ! VanillaMode ( ) )
{
2019-10-21 19:46:41 +00:00
gMe - > pwUpTime [ kPwUpJumpBoots ] = 0 ;
gMe - > packSlots [ 4 ] . curAmount = 0 ;
2019-09-19 22:42:45 +00:00
}
2019-10-19 19:11:39 +00:00
powerupDeactivate ( gMe , kPwUpJumpBoots ) ;
2019-09-19 22:42:45 +00:00
}
else
{
2019-12-09 01:01:30 +00:00
viewSetMessage ( GStrings ( " TXTB_JBOOTS " ) ) ;
2019-09-19 22:42:45 +00:00
if ( ! VanillaMode ( ) )
2019-10-21 19:46:41 +00:00
gMe - > pwUpTime [ kPwUpJumpBoots ] = gPowerUpInfo [ kPwUpJumpBoots ] . bonusTime ;
2019-10-19 19:11:39 +00:00
powerupActivate ( gMe , kPwUpJumpBoots ) ;
2019-09-19 22:42:45 +00:00
}
}
void ToggleInvisibility ( void )
{
2019-10-19 19:11:39 +00:00
if ( powerupCheck ( gMe , kPwUpShadowCloak ) )
2019-09-19 22:42:45 +00:00
{
2019-12-09 01:01:30 +00:00
viewSetMessage ( GStrings ( " TXTB_VISIBLE " ) ) ;
2019-09-19 22:42:45 +00:00
if ( ! VanillaMode ( ) )
2019-10-21 19:46:41 +00:00
gMe - > pwUpTime [ kPwUpShadowCloak ] = 0 ;
2019-10-19 19:11:39 +00:00
powerupDeactivate ( gMe , kPwUpShadowCloak ) ;
2019-09-19 22:42:45 +00:00
}
else
{
2019-12-09 01:01:30 +00:00
viewSetMessage ( GStrings ( " TXTB_INVISIBLE " ) ) ;
2019-10-19 19:11:39 +00:00
powerupActivate ( gMe , kPwUpShadowCloak ) ;
2019-09-19 22:42:45 +00:00
}
}
void ToggleInvulnerability ( void )
{
2019-10-19 19:11:39 +00:00
if ( powerupCheck ( gMe , kPwUpDeathMask ) )
2019-09-19 22:42:45 +00:00
{
2019-12-09 01:01:30 +00:00
viewSetMessage ( GStrings ( " TXTB_VULN " ) ) ;
2019-09-19 22:42:45 +00:00
if ( ! VanillaMode ( ) )
2019-10-21 19:46:41 +00:00
gMe - > pwUpTime [ kPwUpDeathMask ] = 0 ;
2019-10-19 19:11:39 +00:00
powerupDeactivate ( gMe , kPwUpDeathMask ) ;
2019-09-19 22:42:45 +00:00
}
else
{
2019-12-09 01:01:30 +00:00
viewSetMessage ( GStrings ( " TXTB_INVULN " ) ) ;
2019-10-19 19:11:39 +00:00
powerupActivate ( gMe , kPwUpDeathMask ) ;
2019-09-19 22:42:45 +00:00
}
}
void ToggleDelirium ( void )
{
2019-10-19 19:11:39 +00:00
if ( powerupCheck ( gMe , kPwUpDeliriumShroom ) )
2019-09-19 22:42:45 +00:00
{
2019-12-09 01:01:30 +00:00
viewSetMessage ( GStrings ( " TXTB_NODELIR " ) ) ;
2019-09-19 22:42:45 +00:00
if ( ! VanillaMode ( ) )
2019-10-21 19:46:41 +00:00
gMe - > pwUpTime [ kPwUpDeliriumShroom ] = 0 ;
2019-10-19 19:11:39 +00:00
powerupDeactivate ( gMe , kPwUpDeliriumShroom ) ;
2019-09-19 22:42:45 +00:00
}
else
{
2019-12-09 01:01:30 +00:00
viewSetMessage ( GStrings ( " TXTB_DELIR " ) ) ;
2019-10-19 19:11:39 +00:00
powerupActivate ( gMe , kPwUpDeliriumShroom ) ;
2019-09-19 22:42:45 +00:00
}
}
void LevelWarp ( int nEpisode , int nLevel )
{
levelSetupOptions ( nEpisode , nLevel ) ;
StartLevel ( & gGameOptions ) ;
viewResizeView ( gViewSize ) ;
}
void LevelWarpAndRecord ( int nEpisode , int nLevel )
{
char buffer [ BMAX_PATH ] ;
levelSetupOptions ( nEpisode , nLevel ) ;
gGameStarted = false ;
strcpy ( buffer , levelGetFilename ( nEpisode , nLevel ) ) ;
ChangeExtension ( buffer , " .DEM " ) ;
gDemo . Create ( buffer ) ;
StartLevel ( & gGameOptions ) ;
viewResizeView ( gViewSize ) ;
}
CGameMessageMgr : : CGameMessageMgr ( )
{
2019-09-19 06:10:18 +00:00
if ( ! VanillaMode ( ) )
Clear ( ) ;
x = 1 ;
y = 0 ;
2019-09-19 22:42:45 +00:00
at9 = 0 ;
atd = 0 ;
2019-09-19 06:10:18 +00:00
nFont = 0 ;
fontHeight = 8 ;
maxNumberOfMessagesToDisplay = 4 ;
visibilityDurationInSecs = 5 ;
messageFlags = 15 ;
numberOfDisplayedMessages = 0 ;
nextMessagesIndex = messagesIndex = 0 ;
2019-09-19 22:42:45 +00:00
}
void CGameMessageMgr : : SetState ( char state )
{
2019-09-19 06:10:18 +00:00
if ( this - > state & & ! state )
2019-09-19 22:42:45 +00:00
{
2019-09-19 06:10:18 +00:00
this - > state = 0 ;
2019-09-19 22:42:45 +00:00
Clear ( ) ;
}
2019-09-19 06:10:18 +00:00
else if ( ! this - > state & & state )
this - > state = 1 ;
2019-09-19 22:42:45 +00:00
}
2019-09-19 06:10:18 +00:00
void CGameMessageMgr : : Add ( const char * pText , char a2 , const int pal , const MESSAGE_PRIORITY priority )
2019-09-19 22:42:45 +00:00
{
2019-12-04 20:35:35 +00:00
if ( a2 & & messageFlags & & hud_messages = = 1 ) // add only if messages are enabled and in native format
2019-09-19 22:42:45 +00:00
{
2019-09-19 06:10:18 +00:00
messageStruct * pMessage = & messages [ nextMessagesIndex ] ;
strncpy ( pMessage - > text , pText , kMaxMessageTextLength - 1 ) ;
pMessage - > text [ kMaxMessageTextLength - 1 ] = 0 ;
pMessage - > lastTickWhenVisible = gFrameClock + visibilityDurationInSecs * kTicRate ;
2019-09-18 10:58:45 +00:00
pMessage - > pal = pal ;
2019-09-19 06:10:18 +00:00
pMessage - > priority = priority ;
pMessage - > deleted = false ;
nextMessagesIndex = ( nextMessagesIndex + 1 ) % kMessageLogSize ;
if ( VanillaMode ( ) )
2019-09-19 22:42:45 +00:00
{
2019-09-19 06:10:18 +00:00
numberOfDisplayedMessages + + ;
if ( numberOfDisplayedMessages > maxNumberOfMessagesToDisplay )
{
messagesIndex = ( messagesIndex + 1 ) % kMessageLogSize ;
atd = 0 ;
numberOfDisplayedMessages = maxNumberOfMessagesToDisplay ;
at9 = fontHeight ;
}
2019-09-19 22:42:45 +00:00
}
}
}
void CGameMessageMgr : : Display ( void )
{
2019-09-19 06:10:18 +00:00
if ( VanillaMode ( ) )
2019-09-19 22:42:45 +00:00
{
2019-10-19 15:20:06 +00:00
if ( numberOfDisplayedMessages & & this - > state & & gInputMode ! = kInputMessage )
2019-09-19 22:42:45 +00:00
{
2019-09-19 06:10:18 +00:00
int initialNrOfDisplayedMsgs = numberOfDisplayedMessages ;
int initialMessagesIndex = messagesIndex ;
int shade = ClipHigh ( initialNrOfDisplayedMsgs * 8 , 48 ) ;
int x = gViewMode = = 3 ? gViewX0S : 0 ;
int y = ( gViewMode = = 3 ? this - > y : 0 ) + ( int ) at9 ;
for ( int i = 0 ; i < initialNrOfDisplayedMsgs ; i + + )
2019-09-19 22:42:45 +00:00
{
2019-09-19 06:10:18 +00:00
messageStruct * pMessage = & messages [ ( initialMessagesIndex + i ) % kMessageLogSize ] ;
if ( pMessage - > lastTickWhenVisible < gFrameClock )
{
messagesIndex = ( messagesIndex + 1 ) % kMessageLogSize ;
numberOfDisplayedMessages - - ;
continue ;
}
viewDrawText ( nFont , pMessage - > text , x , y , shade , pMessage - > pal , 0 , false , 256 ) ;
if ( gViewMode = = 3 )
{
int height ;
2019-12-01 14:31:08 +00:00
viewGetFontInfo ( nFont , pMessage - > text , & height , NULL ) ;
2019-09-19 06:10:18 +00:00
if ( x + height > gViewX1S )
viewUpdatePages ( ) ;
}
y + = fontHeight ;
shade = ClipLow ( shade - 64 / initialNrOfDisplayedMsgs , - 128 ) ;
2019-09-19 22:42:45 +00:00
}
}
2019-09-19 06:10:18 +00:00
}
else
{
2019-10-19 15:20:06 +00:00
if ( this - > state & & gInputMode ! = kInputMessage )
2019-09-19 22:42:45 +00:00
{
2019-09-19 06:10:18 +00:00
messageStruct * currentMessages [ kMessageLogSize ] ;
int currentMessagesCount = 0 ;
for ( int i = 0 ; i < kMessageLogSize ; i + + )
{
messageStruct * pMessage = & messages [ i ] ;
if ( gFrameClock < pMessage - > lastTickWhenVisible & & ! pMessage - > deleted )
{
currentMessages [ currentMessagesCount + + ] = pMessage ;
}
}
SortMessagesByPriority ( currentMessages , currentMessagesCount ) ;
messageStruct * messagesToDisplay [ kMessageLogSize ] ;
int messagesToDisplayCount = 0 ;
for ( int i = 0 ; i < currentMessagesCount & & messagesToDisplayCount < maxNumberOfMessagesToDisplay ; i + + )
{
messagesToDisplay [ messagesToDisplayCount + + ] = currentMessages [ i ] ;
}
SortMessagesByTime ( messagesToDisplay , messagesToDisplayCount ) ;
int shade = ClipHigh ( messagesToDisplayCount * 8 , 48 ) ;
int x = gViewMode = = 3 ? gViewX0S : 0 ;
int y = ( gViewMode = = 3 ? this - > y : 0 ) + ( int ) at9 ;
for ( int i = 0 ; i < messagesToDisplayCount ; i + + )
{
messageStruct * pMessage = messagesToDisplay [ i ] ;
viewDrawText ( nFont , pMessage - > text , x , y , shade , pMessage - > pal , 0 , false , 256 ) ;
if ( gViewMode = = 3 )
{
int height ;
2019-12-01 14:31:08 +00:00
viewGetFontInfo ( nFont , pMessage - > text , & height , NULL ) ;
2019-09-19 06:10:18 +00:00
if ( x + height > gViewX1S )
viewUpdatePages ( ) ;
}
y + = fontHeight ;
shade = ClipLow ( shade - 64 / messagesToDisplayCount , - 128 ) ;
}
2019-09-19 22:42:45 +00:00
}
}
2019-09-19 06:10:18 +00:00
if ( at9 ! = 0 )
{
at9 = fontHeight * at9 / kTicRate ;
atd + = gFrameTicks ;
}
2019-09-19 22:42:45 +00:00
}
void CGameMessageMgr : : Clear ( void )
{
2019-09-19 06:10:18 +00:00
if ( VanillaMode ( ) )
{
messagesIndex = nextMessagesIndex = numberOfDisplayedMessages = 0 ;
}
else
{
for ( int i = 0 ; i < kMessageLogSize ; i + + )
{
messageStruct * pMessage = & messages [ i ] ;
pMessage - > deleted = true ;
}
}
2019-09-19 22:42:45 +00:00
}
void CGameMessageMgr : : SetMaxMessages ( int nMessages )
{
2019-09-19 06:10:18 +00:00
maxNumberOfMessagesToDisplay = ClipRange ( nMessages , 1 , 16 ) ;
2019-09-19 22:42:45 +00:00
}
void CGameMessageMgr : : SetFont ( int nFont )
{
2019-09-19 06:10:18 +00:00
this - > nFont = nFont ;
fontHeight = gFont [ nFont ] . ySize ;
2019-09-19 22:42:45 +00:00
}
void CGameMessageMgr : : SetCoordinates ( int x , int y )
{
2019-09-19 06:10:18 +00:00
this - > x = ClipRange ( x , 0 , gViewX1S ) ;
this - > y = ClipRange ( y , 0 , gViewY1S ) ;
2019-09-19 22:42:45 +00:00
}
void CGameMessageMgr : : SetMessageTime ( int nTime )
{
2019-09-19 06:10:18 +00:00
visibilityDurationInSecs = ClipRange ( nTime , 1 , 8 ) ;
2019-09-19 22:42:45 +00:00
}
void CGameMessageMgr : : SetMessageFlags ( unsigned int nFlags )
{
2019-09-19 06:10:18 +00:00
messageFlags = nFlags & 0xf ;
}
void CGameMessageMgr : : SortMessagesByPriority ( messageStruct * * messages , int count ) {
for ( int i = 1 ; i < count ; i + + )
{
for ( int j = 0 ; j < count - i ; j + + )
{
if ( messages [ j ] - > priority ! = messages [ j + 1 ] - > priority ? messages [ j ] - > priority < messages [ j + 1 ] - > priority : messages [ j ] - > lastTickWhenVisible < messages [ j + 1 ] - > lastTickWhenVisible )
{
messageStruct * temp = messages [ j ] ;
messages [ j ] = messages [ j + 1 ] ;
messages [ j + 1 ] = temp ;
}
}
}
}
void CGameMessageMgr : : SortMessagesByTime ( messageStruct * * messages , int count ) {
for ( int i = 1 ; i < count ; i + + )
{
for ( int j = 0 ; j < count - i ; j + + )
{
if ( messages [ j ] - > lastTickWhenVisible > messages [ j + 1 ] - > lastTickWhenVisible )
{
messageStruct * temp = messages [ j ] ;
messages [ j ] = messages [ j + 1 ] ;
messages [ j + 1 ] = temp ;
}
}
}
2019-09-19 22:42:45 +00:00
}
void CPlayerMsg : : Clear ( void )
{
2019-09-20 10:23:07 +00:00
text [ 0 ] = 0 ;
2019-09-19 22:42:45 +00:00
at0 = 0 ;
}
void CPlayerMsg : : Term ( void )
{
Clear ( ) ;
2019-10-19 15:20:06 +00:00
gInputMode = kInputGame ;
2019-09-19 22:42:45 +00:00
}
void CPlayerMsg : : Draw ( void )
{
char buffer [ 44 ] ;
2019-09-20 10:23:07 +00:00
strcpy ( buffer , text ) ;
2019-09-07 13:15:39 +00:00
if ( ( int ) totalclock & 16 )
2019-09-19 22:42:45 +00:00
strcat ( buffer , " _ " ) ;
int x = gViewMode = = 3 ? gViewX0S : 0 ;
int y = gViewMode = = 3 ? gViewY0S : 0 ;
if ( gViewSize > = 1 )
y + = tilesiz [ 2229 ] . y * ( ( gNetPlayers + 3 ) / 4 ) ;
viewDrawText ( 0 , buffer , x + 1 , y + 1 , - 128 , 0 , 0 , false , 256 ) ;
viewUpdatePages ( ) ;
}
bool CPlayerMsg : : AddChar ( char ch )
{
if ( at0 < 40 )
{
2019-09-20 10:23:07 +00:00
text [ at0 + + ] = ch ;
text [ at0 ] = 0 ;
2019-09-19 22:42:45 +00:00
return true ;
}
return false ;
}
void CPlayerMsg : : DelChar ( void )
{
if ( at0 > 0 )
2019-09-20 10:23:07 +00:00
text [ - - at0 ] = 0 ;
2019-09-19 22:42:45 +00:00
}
void CPlayerMsg : : Set ( const char * pzString )
{
2019-09-20 10:23:07 +00:00
strncpy ( text , pzString , 40 ) ;
2019-09-19 22:42:45 +00:00
at0 = ClipHigh ( strlen ( pzString ) , 40 ) ;
2019-09-20 10:23:07 +00:00
text [ at0 ] = 0 ;
2019-09-19 22:42:45 +00:00
}
void CPlayerMsg : : Send ( void )
{
2019-09-20 10:23:07 +00:00
if ( VanillaMode ( ) | | ! IsWhitespaceOnly ( text ) )
{
netBroadcastMessage ( myconnectindex , text ) ;
if ( ! VanillaMode ( ) )
{
char * myName = gProfile [ myconnectindex ] . name ;
char szTemp [ 128 ] ;
sprintf ( szTemp , " %s: %s " , myName , text ) ;
viewSetMessage ( szTemp , 10 ) ; // 10: dark blue
}
else
viewSetMessage ( text ) ;
}
2019-09-19 22:42:45 +00:00
Term ( ) ;
2019-11-03 23:53:55 +00:00
inputState . keyFlushScans ( ) ;
2019-09-19 22:42:45 +00:00
}
void CPlayerMsg : : ProcessKeys ( void )
{
2019-11-03 23:53:55 +00:00
if ( inputState . GetKeyStatus ( sc_Escape ) ) Term ( ) ;
2019-09-19 22:42:45 +00:00
}
2019-09-20 10:23:07 +00:00
bool CPlayerMsg : : IsWhitespaceOnly ( const char * const pzString )
{
const char * p = pzString ;
while ( * p ! = 0 )
if ( * p + + > 32 )
return false ;
return true ;
}
2019-09-19 22:42:45 +00:00
CCheatMgr : : CHEATINFO CCheatMgr : : s_CheatInfo [ ] = {
{ " NQLGB " , kCheatMpkfa , 0 } , // MPKFA (Invincibility)
{ " DBQJONZBTT " , kCheatCapInMyAss , 0 } , // CAPINMYASS (Disable invincibility )
{ " OPDBQJONZBTT " , kCheatNoCapInMyAss , 0 } , // NOCAPINMYASS (Invincibility)
{ " J!XBOOB!CF!MJLF!LFWJO " , kCheatNoCapInMyAss , 0 } , // I WANNA BE LIKE KEVIN (Invincibility)
{ " JEBIP " , kCheatIdaho , 0 } , // IDAHO (All weapons and full ammo)
{ " NPOUBOB " , kCheatMontana , 0 } , // MONTANA (All weapons, full ammo and all items)
{ " HSJTXPME " , kCheatGriswold , 0 } , // GRISWOLD (Full armor (same effect as getting super armor))
{ " FENBSL " , kCheatEdmark , 0 } , // EDMARK (Does a lot of fire damage to you (if you have 200HP and 200 fire armor then you can survive). Displays the message "THOSE WERE THE DAYS".)
{ " UFRVJMB " , kCheatTequila , 0 } , // TEQUILA (Guns akimbo power-up)
{ " CVO[ " , kCheatBunz , 0 } , // BUNZ (All weapons, full ammo, and guns akimbo power-up)
{ " GVOLZ!TIPFT " , kCheatFunkyShoes , 0 } , // FUNKY SHOES (Gives jump boots item and activates it)
{ " HBUFLFFQFS " , kCheatGateKeeper , 0 } , // GATEKEEPER (Sets the you cheated flag to true, at the end of the level you will see that you have cheated)
{ " LFZNBTUFS " , kCheatKeyMaster , 0 } , // KEYMASTER (All keys)
{ " KPKP " , kCheatJoJo , 0 } , // JOJO (Drunk mode (same effect as getting bitten by red spider))
{ " TBUDIFM " , kCheatSatchel , 0 } , // SATCHEL (Full inventory)
{ " TQPSL " , kCheatSpork , 0 } , // SPORK (200% health (same effect as getting life seed))
{ " POFSJOH " , kCheatOneRing , 0 } , // ONERING (Cloak of invisibility power-up)
{ " NBSJP " , kCheatMario , 1 } , // MARIO (Warp to level E M, e.g.: MARIO 1 3 will take you to Phantom Express)
{ " DBMHPO " , kCheatCalgon , 1 } , // CALGON (Jumps to next level or can be used like MARIO with parameters)
{ " LFWPSLJBO " , kCheatKevorkian , 0 } , // KEVORKIAN (Does a lot of physical damage to you (if you have 200HP and 200 fire armor then you can survive). Displays the message "KEVORKIAN APPROVES".)
{ " NDHFF " , kCheatMcGee , 0 } , // MCGEE (Sets you on fire. Displays the message "YOU'RE FIRED".)
{ " LSVFHFS " , kCheatKrueger , 0 } , // KRUEGER (200% health, but sets you on fire. Displays the message "FLAME RETARDANT".)
{ " DIFFTFIFBE " , kCheatCheeseHead , 0 } , // CHEESEHEAD (100% diving suit)
{ " DPVTUFBV " , kCheatCousteau , 0 } , // COUSTEAU (200% health and diving suit)
{ " WPPSIFFT " , kCheatVoorhees , 0 } , // VOORHEES (Death mask power-up)
{ " MBSB!DSPGU " , kCheatLaraCroft , 0 } , // LARA CROFT (All weapons and infinite ammo. Displays the message "LARA RULES". Typing it the second time will lose all weapons and ammo.)
{ " IPOHLPOH " , kCheatHongKong , 0 } , // HONGKONG (All weapons and infinite ammo)
{ " GSBOLFOTUFJO " , kCheatFrankenstein , 0 } , // FRANKENSTEIN (100% med-kit)
{ " TUFSOP " , kCheatSterno , 0 } , // STERNO (Temporary blindness (same effect as getting bitten by green spider))
{ " DMBSJDF " , kCheatClarice , 0 } , // CLARICE (Gives 100% body armor, 100% fire armor, 100% spirit armor)
{ " GPSL!ZPV " , kCheatForkYou , 0 } , // FORK YOU (Drunk mode, 1HP, no armor, no weapons, no ammo, no items, no keys, no map, guns akimbo power-up)
{ " MJFCFSNBO " , kCheatLieberMan , 0 } , // LIEBERMAN (Sets the you cheated flag to true, at the end of the level you will see that you have cheated)
{ " FWB!HBMMJ " , kCheatEvaGalli , 0 } , // EVA GALLI (Disable/enable clipping (grant the ability to walk through walls))
{ " SBUF " , kCheatRate , 0 } , // RATE (Display frame rate (doesn't count as a cheat))
{ " HPPOJFT " , kCheatGoonies , 0 } , // GOONIES (Enable full map. Displays the message "YOU HAVE THE MAP".)
{ " TQJFMCFSH " , kCheatSpielberg , 1 } , // SPIELBERG (Disables all cheats. If number values corresponding to a level and episode number are entered after the cheat word (i.e. "spielberg 1 3" for Phantom Express), you will be spawned to said level and the game will begin recording a demo from your actions.)
} ;
bool CCheatMgr : : m_bPlayerCheated = false ;
bool CCheatMgr : : Check ( char * pzString )
{
char buffer [ 80 ] ;
strcpy ( buffer , pzString ) ;
for ( size_t i = 0 ; i < strlen ( pzString ) ; i + + )
buffer [ i ] + + ;
for ( int i = 0 ; i < 36 ; i + + )
{
int nCheatLen = strlen ( s_CheatInfo [ i ] . pzString ) ;
if ( s_CheatInfo [ i ] . flags & 1 )
{
2019-12-29 15:35:51 +00:00
if ( ! strnicmp ( buffer , s_CheatInfo [ i ] . pzString , nCheatLen ) )
2019-09-19 22:42:45 +00:00
{
Process ( s_CheatInfo [ i ] . id , buffer + nCheatLen ) ;
return true ;
}
}
if ( ! strcmp ( buffer , s_CheatInfo [ i ] . pzString ) )
{
Process ( s_CheatInfo [ i ] . id , NULL ) ;
return true ;
}
}
return false ;
}
int parseArgs ( char * pzArgs , int * nArg1 , int * nArg2 )
{
if ( ! nArg1 | | ! nArg2 )
return - 1 ;
int nLength = strlen ( pzArgs ) ;
for ( int i = 0 ; i < nLength ; i + + )
pzArgs [ i ] - - ;
int stat = sscanf ( pzArgs , " %d %d " , nArg1 , nArg2 ) ;
if ( stat = = 2 & & ( * nArg1 = = 0 | | * nArg2 = = 0 ) )
return - 1 ;
* nArg1 = ClipRange ( * nArg1 - 1 , 0 , gEpisodeCount - 1 ) ;
* nArg2 = ClipRange ( * nArg2 - 1 , 0 , gEpisodeInfo [ * nArg1 ] . nLevels - 1 ) ;
return stat ;
}
void CCheatMgr : : Process ( CCheatMgr : : CHEATCODE nCheatCode , char * pzArgs )
{
dassert ( nCheatCode > kCheatNone & & nCheatCode < kCheatMax ) ;
if ( gDemo . at0 ) return ;
if ( nCheatCode = = kCheatRate )
{
2019-10-22 23:04:07 +00:00
r_showfps = ! r_showfps ;
2019-09-19 22:42:45 +00:00
return ;
}
if ( gGameOptions . nGameType ! = 0 )
return ;
int nEpisode , nLevel ;
switch ( nCheatCode )
{
case kCheatSpielberg :
if ( parseArgs ( pzArgs , & nEpisode , & nLevel ) = = 2 )
LevelWarpAndRecord ( nEpisode , nLevel ) ;
break ;
case kCheat1 :
SetAmmo ( true ) ;
break ;
case kCheatGriswold :
SetArmor ( true ) ;
break ;
case kCheatSatchel :
SetToys ( true ) ;
break ;
case kCheatEvaGalli :
SetClipMode ( ! gNoClip ) ;
break ;
case kCheatMpkfa :
2019-10-21 19:46:41 +00:00
SetGodMode ( ! gMe - > godMode ) ;
2019-09-19 22:42:45 +00:00
break ;
case kCheatCapInMyAss :
SetGodMode ( false ) ;
break ;
case kCheatNoCapInMyAss :
SetGodMode ( true ) ;
break ;
case kCheatIdaho :
SetWeapons ( true ) ;
break ;
case kCheatKevorkian :
2019-10-21 19:46:41 +00:00
actDamageSprite ( gMe - > nSprite , gMe - > pSprite , DAMAGE_TYPE_2 , 8000 ) ;
2019-12-09 01:01:30 +00:00
viewSetMessage ( GStrings ( " TXTB_KEVORKIAN " ) ) ;
2019-09-19 22:42:45 +00:00
break ;
case kCheatMcGee :
{
if ( ! gMe - > pXSprite - > burnTime )
2019-10-21 19:46:41 +00:00
evPost ( gMe - > nSprite , 3 , 0 , kCallbackFXFlameLick ) ;
actBurnSprite ( actSpriteIdToOwnerId ( gMe - > nSprite ) , gMe - > pXSprite , 2400 ) ;
2019-12-09 01:01:30 +00:00
viewSetMessage ( GStrings ( " TXTB_FIRED " ) ) ;
2019-09-19 22:42:45 +00:00
break ;
}
case kCheatEdmark :
2019-10-21 19:46:41 +00:00
actDamageSprite ( gMe - > nSprite , gMe - > pSprite , DAMAGE_TYPE_3 , 8000 ) ;
2019-12-09 01:01:30 +00:00
viewSetMessage ( GStrings ( " TXTB_THEDAYS " ) ) ;
2019-09-19 22:42:45 +00:00
break ;
case kCheatKrueger :
{
actHealDude ( gMe - > pXSprite , 200 , 200 ) ;
2019-10-21 19:46:41 +00:00
gMe - > armor [ 1 ] = VanillaMode ( ) ? 200 : 3200 ;
2019-09-19 22:42:45 +00:00
if ( ! gMe - > pXSprite - > burnTime )
2019-10-21 19:46:41 +00:00
evPost ( gMe - > nSprite , 3 , 0 , kCallbackFXFlameLick ) ;
actBurnSprite ( actSpriteIdToOwnerId ( gMe - > nSprite ) , gMe - > pXSprite , 2400 ) ;
2019-12-09 01:01:30 +00:00
viewSetMessage ( GStrings ( " TXTB_RETARD " ) ) ;
2019-09-19 22:42:45 +00:00
break ;
}
case kCheatSterno :
2019-10-21 19:46:41 +00:00
gMe - > blindEffect = 250 ;
2019-09-19 22:42:45 +00:00
break ;
2019-10-21 19:46:41 +00:00
case kCheat14 : // quakeEffect (causing a little flickerEffect), not used by any cheat code (dead code)
gMe - > flickerEffect = 360 ;
2019-09-19 22:42:45 +00:00
break ;
case kCheatSpork :
actHealDude ( gMe - > pXSprite , 200 , 200 ) ;
break ;
case kCheatGoonies :
SetMap ( ! gFullMap ) ;
break ;
case kCheatClarice :
if ( ! VanillaMode ( ) )
{
2019-12-09 01:01:30 +00:00
viewSetMessage ( GStrings ( " TXTB_HALFARMOR " ) ) ;
2019-09-19 22:42:45 +00:00
for ( int i = 0 ; i < 3 ; i + + )
2019-10-21 19:46:41 +00:00
gMe - > armor [ i ] = 1600 ;
2019-09-19 22:42:45 +00:00
}
break ;
case kCheatFrankenstein :
2019-10-21 19:46:41 +00:00
gMe - > packSlots [ 0 ] . curAmount = 100 ;
2019-09-19 22:42:45 +00:00
break ;
case kCheatCheeseHead :
2019-10-21 19:46:41 +00:00
gMe - > packSlots [ 1 ] . curAmount = 100 ;
2019-09-19 22:42:45 +00:00
if ( ! VanillaMode ( ) )
2019-10-21 19:46:41 +00:00
gMe - > pwUpTime [ kPwUpDivingSuit ] = gPowerUpInfo [ kPwUpDivingSuit ] . bonusTime ;
2019-09-19 22:42:45 +00:00
break ;
case kCheatTequila :
ToggleWooMode ( ) ;
break ;
case kCheatFunkyShoes :
ToggleBoots ( ) ;
break ;
case kCheatKeyMaster :
SetKeys ( true ) ;
break ;
case kCheatOneRing :
ToggleInvisibility ( ) ;
break ;
case kCheatVoorhees :
ToggleInvulnerability ( ) ;
break ;
case kCheatJoJo :
ToggleDelirium ( ) ;
break ;
case kCheatRate : // show FPS, handled before (dead code), leave here for safety
return ;
case kCheatMario :
if ( parseArgs ( pzArgs , & nEpisode , & nLevel ) = = 2 )
LevelWarp ( nEpisode , nLevel ) ;
break ;
case kCheatCalgon :
if ( parseArgs ( pzArgs , & nEpisode , & nLevel ) = = 2 )
LevelWarp ( nEpisode , nLevel ) ;
else
if ( ! VanillaMode ( ) )
levelEndLevel ( 0 ) ;
break ;
case kCheatLaraCroft :
SetInfiniteAmmo ( ! gInfiniteAmmo ) ;
SetWeapons ( gInfiniteAmmo ) ;
break ;
case kCheatHongKong :
SetWeapons ( true ) ;
SetInfiniteAmmo ( true ) ;
break ;
case kCheatMontana :
SetWeapons ( true ) ;
SetToys ( true ) ;
break ;
case kCheatBunz :
SetWeapons ( true ) ;
SetWooMode ( true ) ;
break ;
case kCheatCousteau :
actHealDude ( gMe - > pXSprite , 200 , 200 ) ;
2019-10-21 19:46:41 +00:00
gMe - > packSlots [ 1 ] . curAmount = 100 ;
2019-09-19 22:42:45 +00:00
if ( ! VanillaMode ( ) )
2019-10-21 19:46:41 +00:00
gMe - > pwUpTime [ kPwUpDivingSuit ] = gPowerUpInfo [ kPwUpDivingSuit ] . bonusTime ;
2019-09-19 22:42:45 +00:00
break ;
case kCheatForkYou :
SetInfiniteAmmo ( false ) ;
SetMap ( false ) ;
SetWeapons ( false ) ;
SetAmmo ( false ) ;
SetArmor ( false ) ;
SetToys ( false ) ;
SetKeys ( false ) ;
SetWooMode ( true ) ;
2019-10-19 19:11:39 +00:00
powerupActivate ( gMe , kPwUpDeliriumShroom ) ;
2019-09-19 22:42:45 +00:00
gMe - > pXSprite - > health = 16 ;
2019-10-21 19:46:41 +00:00
gMe - > hasWeapon [ 1 ] = 1 ;
gMe - > curWeapon = 0 ;
gMe - > nextWeapon = 1 ;
2019-09-19 22:42:45 +00:00
break ;
default :
break ;
}
m_bPlayerCheated = true ;
}
void CCheatMgr : : sub_5BCF4 ( void )
{
m_bPlayerCheated = 0 ;
playerSetGodMode ( gMe , 0 ) ;
gNoClip = 0 ;
packClear ( gMe ) ;
gInfiniteAmmo = 0 ;
gFullMap = 0 ;
}
class MessagesLoadSave : public LoadSave
{
public :
virtual void Load ( ) ;
virtual void Save ( ) ;
} ;
void MessagesLoadSave : : Load ( )
{
Read ( & CCheatMgr : : m_bPlayerCheated , sizeof ( CCheatMgr : : m_bPlayerCheated ) ) ;
}
void MessagesLoadSave : : Save ( )
{
Write ( & CCheatMgr : : m_bPlayerCheated , sizeof ( CCheatMgr : : m_bPlayerCheated ) ) ;
}
static MessagesLoadSave * myLoadSave ;
void MessagesLoadSaveConstruct ( void )
{
myLoadSave = new MessagesLoadSave ( ) ;
}
2019-09-22 06:39:22 +00:00
END_BLD_NS