2020-07-15 19:11:23 +00:00
//-------------------------------------------------------------------------
/*
Copyright ( C ) 1996 , 2003 - 3 D Realms Entertainment
Copyright ( C ) 2020 - Christoph Oelckers
This file is part of Duke Nukem 3 D version 1.5 - Atomic Edition
Duke Nukem 3 D is free software ; you can redistribute it and / or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation ; either version 2
of the License , or ( at your option ) any later version .
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 . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
Original Source : 1996 - Todd Replogle
Prepared for public release : 03 / 21 / 2003 - Charlie Wiederhold , 3 D Realms
Modifications for JonoF ' s port by Jonathon Fowler ( jf @ jonof . id . au )
*/
//-------------------------------------------------------------------------
// all code related to startup, up to entering the main loop.
# include "ns.h" // Must come before everything else!
# include "duke3d.h"
# include "m_argv.h"
# include "mapinfo.h"
# include "texturemanager.h"
# include "statusbar.h"
# include "st_start.h"
# include "i_interface.h"
# include "prediction.h"
2020-07-21 20:46:26 +00:00
# include "gamestate.h"
2021-06-01 09:05:26 +00:00
# include "razefont.h"
2022-01-12 22:33:44 +00:00
# include "psky.h"
2022-01-23 23:10:25 +00:00
# include "vm.h"
2022-01-25 23:36:34 +00:00
# include "thingdef.h"
2022-12-07 16:10:27 +00:00
# include "tilesetbuilder.h"
2022-12-21 21:06:34 +00:00
# include "concmd.h"
2020-07-15 19:11:23 +00:00
BEGIN_DUKE_NS
void SetDispatcher ( ) ;
void InitCheats ( ) ;
int registerosdcommands ( void ) ;
2022-12-08 22:09:46 +00:00
FTextureID mirrortex , foftex ;
2021-12-05 13:00:22 +00:00
//---------------------------------------------------------------------------
//
// DObject stuff - everything GC related.
//
//---------------------------------------------------------------------------
2021-12-05 19:55:19 +00:00
IMPLEMENT_CLASS ( DDukeActor , false , true )
IMPLEMENT_POINTERS_START ( DDukeActor )
IMPLEMENT_POINTER ( ownerActor )
IMPLEMENT_POINTER ( hitOwnerActor )
IMPLEMENT_POINTER ( temp_actor )
IMPLEMENT_POINTER ( seek_actor )
IMPLEMENT_POINTERS_END
size_t DDukeActor : : PropagateMark ( )
{
for ( auto & var : uservars )
{
var . Mark ( ) ;
}
2021-12-06 16:00:15 +00:00
return Super : : PropagateMark ( ) ;
2021-12-05 19:55:19 +00:00
}
2021-12-05 13:00:22 +00:00
static void markgcroots ( )
{
GC : : Mark ( camsprite ) ;
2022-11-28 18:55:28 +00:00
GC : : MarkArray ( spriteq , 1024 ) ;
2021-12-05 13:00:22 +00:00
GC : : Mark ( currentCommentarySprite ) ;
GC : : Mark ( ud . cameraactor ) ;
for ( auto & pl : ps )
{
GC : : Mark ( pl . actor ) ;
GC : : Mark ( pl . actorsqu ) ;
GC : : Mark ( pl . wackedbyactor ) ;
GC : : Mark ( pl . on_crane ) ;
GC : : Mark ( pl . holoduke_on ) ;
GC : : Mark ( pl . somethingonplayer ) ;
GC : : Mark ( pl . access_spritenum ) ;
GC : : Mark ( pl . dummyplayersprite ) ;
GC : : Mark ( pl . newOwner ) ;
for ( auto & var : pl . uservars )
{
var . Mark ( ) ;
}
}
}
2020-07-15 19:11:23 +00:00
//---------------------------------------------------------------------------
//
// game specific command line args go here.
//
//---------------------------------------------------------------------------
static void checkcommandline ( )
{
2020-09-05 14:31:01 +00:00
#if 0
2020-07-15 19:11:23 +00:00
val = Args - > CheckValue ( " -respawn " ) ;
if ( ! val ) val = Args - > CheckValue ( " -t " ) ;
if ( val )
{
if ( * val = = ' 1 ' ) ud . m_respawn_monsters = 1 ;
else if ( * val = = ' 2 ' ) ud . m_respawn_items = 1 ;
else if ( * val = = ' 3 ' ) ud . m_respawn_inventory = 1 ;
else
{
ud . m_respawn_monsters = 1 ;
ud . m_respawn_items = 1 ;
ud . m_respawn_inventory = 1 ;
}
Printf ( " Respawn on. \n " ) ;
}
2020-09-05 14:31:01 +00:00
# endif
2020-07-15 19:11:23 +00:00
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static void genspriteremaps ( void )
{
int j ;
auto fr = fileSystem . OpenFileReader ( " lookup.dat " ) ;
if ( ! fr . isOpen ( ) )
2020-07-20 21:21:27 +00:00
return ;
2020-07-15 19:11:23 +00:00
j = lookups . loadTable ( fr ) ;
if ( j < 0 )
{
if ( j = = - 1 )
Printf ( " ERROR loading \" lookup.dat \" : failed reading enough data. \n " ) ;
return ;
}
uint8_t paldata [ 768 ] ;
2020-07-20 21:21:27 +00:00
for ( j = 1 ; j < = 5 ; j + + )
2020-07-15 19:11:23 +00:00
{
if ( fr . Read ( paldata , 768 ) ! = 768 )
return ;
for ( int k = 0 ; k < 768 ; k + + ) // Build uses 6 bit VGA palettes.
paldata [ k ] = ( paldata [ k ] < < 2 ) | ( paldata [ k ] > > 6 ) ;
2020-07-26 15:55:22 +00:00
paletteSetColorTable ( j , paldata , j = = DREALMSPAL | | j = = ENDINGPAL , j > SLIMEPAL ) ;
2020-07-15 19:11:23 +00:00
}
for ( int i = 0 ; i < 256 ; i + + )
{
// swap red and blue channels.
paldata [ i * 3 ] = GPalette . BaseColors [ i ] . b ;
2020-07-20 21:21:27 +00:00
paldata [ i * 3 + 1 ] = GPalette . BaseColors [ i ] . g ;
paldata [ i * 3 + 2 ] = GPalette . BaseColors [ i ] . r ;
2020-07-15 19:11:23 +00:00
}
paletteSetColorTable ( DRUGPAL , paldata , false , false ) ; // todo: implement this as a shader effect (swap R and B in postprocessing.)
if ( isRR ( ) )
{
uint8_t table [ 256 ] ;
for ( j = 0 ; j < 256 ; j + + )
table [ j ] = j ;
for ( j = 0 ; j < 32 ; j + + )
table [ j ] = j + 32 ;
lookups . makeTable ( 7 , table , 0 , 0 , 0 , 0 ) ;
for ( j = 0 ; j < 256 ; j + + )
table [ j ] = j ;
lookups . makeTable ( 30 , table , 0 , 0 , 0 , 0 ) ;
lookups . makeTable ( 31 , table , 0 , 0 , 0 , 0 ) ;
lookups . makeTable ( 32 , table , 0 , 0 , 0 , 0 ) ;
lookups . makeTable ( 33 , table , 0 , 0 , 0 , 0 ) ;
if ( isRRRA ( ) )
lookups . makeTable ( 105 , table , 0 , 0 , 0 , 0 ) ;
int unk = 63 ;
for ( j = 64 ; j < 80 ; j + + )
{
unk - - ;
table [ j ] = unk ;
table [ j + 16 ] = j - 24 ;
}
table [ 80 ] = 80 ;
table [ 81 ] = 81 ;
for ( j = 0 ; j < 32 ; j + + )
{
table [ j ] = j + 32 ;
}
lookups . makeTable ( 34 , table , 0 , 0 , 0 , 0 ) ;
for ( j = 0 ; j < 256 ; j + + )
table [ j ] = j ;
for ( j = 0 ; j < 16 ; j + + )
table [ j ] = j + 129 ;
for ( j = 16 ; j < 32 ; j + + )
table [ j ] = j + 192 ;
lookups . makeTable ( 35 , table , 0 , 0 , 0 , 0 ) ;
if ( isRRRA ( ) )
{
lookups . makeTable ( 50 , nullptr , 12 * 4 , 12 * 4 , 12 * 4 , 0 ) ;
lookups . makeTable ( 51 , nullptr , 12 * 4 , 12 * 4 , 12 * 4 , 0 ) ;
lookups . makeTable ( 54 , lookups . getTable ( 8 ) , 32 * 4 , 32 * 4 , 32 * 4 , 0 ) ;
}
}
}
//---------------------------------------------------------------------------
//
// Define sky layouts.
//
//---------------------------------------------------------------------------
static void setupbackdrop ( )
{
2022-01-12 22:33:44 +00:00
static const int16_t moonoff [ 8 ] = { 0 , 2 , 3 , 0 , 2 , 0 , 1 , 0 } ;
static const int16_t orbitoff [ 8 ] = { 0 , 0 , 4 , 0 , 0 , 1 , 2 , 3 } ;
static const int16_t laoff [ 8 ] = { 1 , 2 , 1 , 3 , 4 , 0 , 2 , 3 } ;
static const int16_t defoff [ 8 ] = { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 } ;
static const int16_t defoff1 [ 8 ] = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 0 } ;
static const int16_t defoff4 [ 8 ] = { 4 , 5 , 6 , 7 , 0 , 1 , 2 , 3 } ;
static const int16_t defoff7 [ 8 ] = { 7 , 0 , 1 , 2 , 3 , 4 , 5 , 6 } ;
2022-12-09 11:53:16 +00:00
defineSky ( nullptr , 3 , nullptr ) ;
2022-11-30 13:56:56 +00:00
defineSky ( " CLOUDYOCEAN " , 3 , nullptr ) ;
defineSky ( " MOONSKY12 " , 3 , moonoff ) ;
defineSky ( " BIGORBIT1 " , 3 , orbitoff ) ;
defineSky ( " LA " , 3 , laoff ) ;
2020-07-15 19:11:23 +00:00
if ( isWorldTour ( ) )
{
2022-12-09 11:53:16 +00:00
defineSky ( " SPACESKY " , 3 , defoff ) ;
defineSky ( " PARISSKY " , 3 , defoff , 80 ) ;
defineSky ( " LONDONSKY " , 3 , defoff , 80 ) ;
defineSky ( " MOSCOWSKY " , 3 , defoff7 , 80 ) ;
defineSky ( " DESERTSKY " , 3 , defoff , 80 ) ;
defineSky ( " AMSTERDAMSKY " , 3 , defoff , 80 ) ;
defineSky ( " HOLLYWOODSKY " , 3 , defoff1 , 80 ) ;
defineSky ( " FRISCOSKY " , 3 , defoff4 , 80 ) ;
defineSky ( " ROMESKY " , 3 , defoff , 80 ) ;
2020-07-15 19:11:23 +00:00
}
2021-05-08 20:08:05 +00:00
if ( isNam ( ) )
{
2022-12-09 11:53:16 +00:00
defineSky ( " NAMSKY1 " , 3 , nullptr , 0 , 1 , 140 ) ;
defineSky ( " NAMSKY2 " , 3 , nullptr , 0 , 1 , 140 ) ;
2021-05-08 20:08:05 +00:00
}
2022-01-04 15:36:34 +00:00
if ( isWW2GI ( ) & & ( g_gameType & GAMEFLAG_ADDON ) )
{
2022-12-09 11:53:16 +00:00
defineSky ( " PLATOONSKY " , 3 , nullptr , 0 , 1 , 140 ) ;
2022-01-04 15:36:34 +00:00
}
2022-01-13 14:57:25 +00:00
// this sky isn't actually placed wrong - it's just so poorly designed that it needs to be shifted down to hide its shortcomings as good as possible.
if ( isDuke ( ) & & ( g_gameType & GAMEFLAG_DUKEDC ) )
{
2022-12-09 11:53:16 +00:00
defineSky ( " DUKEDCSKY " , 3 , nullptr , 0 , 1 , - 40 ) ;
2022-01-13 14:57:25 +00:00
}
2020-07-15 19:11:23 +00:00
}
2022-12-07 16:10:27 +00:00
void GameInterface : : SetupSpecialTextures ( TilesetBuildInfo & info )
2022-12-05 19:04:31 +00:00
{
// set up all special tiles here, before we fully hook up with the texture manager.
2022-12-07 16:10:27 +00:00
info . Delete ( FOF ) ; // portal marker
FImageSource * viewscreen ;
2022-12-05 19:04:31 +00:00
if ( ! isRR ( ) )
{
2022-12-08 22:09:46 +00:00
info . Delete ( MIRROR_DUKE ) ; // the mirror tile.
2023-01-01 12:58:54 +00:00
viewscreen = info . tile [ VIEWSCREEN_DUKE ] . tileimage ;
2022-12-05 19:04:31 +00:00
}
else
{
2022-12-08 22:09:46 +00:00
info . Delete ( MIRROR_RR ) ; // the mirror tile.
2022-12-07 16:10:27 +00:00
info . Delete ( 0 ) ; // RR uses this as an empty texture
2023-01-01 12:58:54 +00:00
info . MakeWritable ( BOWLINGLANE ) ; // bowling lane pin displays
info . MakeWritable ( BOWLINGLANE + 1 ) ;
info . MakeWritable ( BOWLINGLANE + 2 ) ;
info . MakeWritable ( BOWLINGLANE + 3 ) ;
viewscreen = info . tile [ VIEWSCREEN_RR ] . tileimage ;
2022-12-05 19:04:31 +00:00
}
2022-12-07 16:10:27 +00:00
info . MakeCanvas ( TILE_VIEWSCR , viewscreen ? viewscreen - > GetWidth ( ) : 128 , viewscreen ? viewscreen - > GetHeight ( ) : 128 ) ;
2022-12-05 19:04:31 +00:00
}
2020-10-06 17:26:22 +00:00
2021-06-01 09:05:26 +00:00
void GameInterface : : loadPalette ( )
{
paletteLoadFromDisk ( ) ;
genspriteremaps ( ) ;
}
2021-07-20 08:50:46 +00:00
int GameInterface : : GetCurrentSkill ( )
{
return ud . player_skill - 1 ;
}
2022-12-08 22:09:46 +00:00
//---------------------------------------------------------------------------
//
// IDs for non-textures that need direct checking
//
//---------------------------------------------------------------------------
void setTextureIDs ( )
{
mirrortex = tileGetTextureID ( isRR ( ) ? MIRROR_RR : MIRROR_DUKE ) ;
foftex = tileGetTextureID ( FOF ) ;
}
2023-01-01 15:16:17 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void initactorflags ( )
{
if ( ! isRR ( ) )
{
gs . weaponsandammosprites [ 0 ] = DukeRPGSpriteClass ;
gs . weaponsandammosprites [ 1 ] = DukeChaingunSpriteClass ;
gs . weaponsandammosprites [ 2 ] = DukeDevastatorAmmoClass ;
gs . weaponsandammosprites [ 3 ] = DukeRPGAmmoClass ;
gs . weaponsandammosprites [ 4 ] = DukeRPGAmmoClass ;
gs . weaponsandammosprites [ 5 ] = DukeJetpackClass ;
gs . weaponsandammosprites [ 6 ] = DukeShieldClass ;
gs . weaponsandammosprites [ 7 ] = DukeFirstAidClass ;
gs . weaponsandammosprites [ 8 ] = DukeSteroidsClass ;
gs . weaponsandammosprites [ 9 ] = DukeRPGAmmoClass ;
gs . weaponsandammosprites [ 10 ] = DukeRPGAmmoClass ;
gs . weaponsandammosprites [ 11 ] = DukeRPGSpriteClass ;
gs . weaponsandammosprites [ 12 ] = DukeRPGAmmoClass ;
gs . weaponsandammosprites [ 13 ] = DukeFreezeSpriteClass ;
gs . weaponsandammosprites [ 14 ] = DukeFreezeAmmoClass ;
}
else
{
gs . weaponsandammosprites [ 0 ] = RedneckCrossbowClass ;
gs . weaponsandammosprites [ 1 ] = RedneckRiflegunClass ;
gs . weaponsandammosprites [ 2 ] = RedneckBlasterammoClass ;
gs . weaponsandammosprites [ 3 ] = RedneckDynamiteAmmoClass ;
gs . weaponsandammosprites [ 4 ] = RedneckDynamiteAmmoClass ;
gs . weaponsandammosprites [ 5 ] = RedneckCowpieClass ;
gs . weaponsandammosprites [ 6 ] = RedneckWhiskeyClass ;
gs . weaponsandammosprites [ 7 ] = RedneckPorkRindsClass ;
gs . weaponsandammosprites [ 8 ] = RedneckMoonshineClass ;
gs . weaponsandammosprites [ 9 ] = RedneckDynamiteAmmoClass ;
gs . weaponsandammosprites [ 10 ] = RedneckDynamiteAmmoClass ;
gs . weaponsandammosprites [ 11 ] = RedneckCrossbowClass ;
gs . weaponsandammosprites [ 12 ] = RedneckDynamiteAmmoClass ;
gs . weaponsandammosprites [ 13 ] = RedneckTitgunClass ;
gs . weaponsandammosprites [ 14 ] = RedneckTitAmmoClass ;
gs . gutsscale = 0.125 ;
}
}
2020-07-15 19:11:23 +00:00
//---------------------------------------------------------------------------
//
// set up the game module's state
//
//---------------------------------------------------------------------------
2020-08-30 10:49:21 +00:00
void GameInterface : : app_init ( )
2020-07-15 19:11:23 +00:00
{
2022-12-29 08:56:14 +00:00
RegisterClasses ( ) ;
2021-12-05 13:00:22 +00:00
GC : : AddMarkerFunc ( markgcroots ) ;
2021-11-25 21:33:55 +00:00
2020-08-26 12:33:19 +00:00
if ( isRR ( ) ) C_SetNotifyFontScale ( 0.5 ) ;
2020-07-20 21:21:27 +00:00
ud . god = 0 ;
ud . m_respawn_items = 0 ;
ud . m_respawn_monsters = 0 ;
ud . m_respawn_inventory = 0 ;
ud . cashman = 0 ;
2020-09-05 14:31:01 +00:00
ud . player_skill = 2 ;
2020-07-20 21:21:27 +00:00
ud . wchoice [ 0 ] [ 0 ] = 3 ;
ud . wchoice [ 0 ] [ 1 ] = 4 ;
ud . wchoice [ 0 ] [ 2 ] = 5 ;
ud . wchoice [ 0 ] [ 3 ] = 7 ;
ud . wchoice [ 0 ] [ 4 ] = 8 ;
ud . wchoice [ 0 ] [ 5 ] = 6 ;
ud . wchoice [ 0 ] [ 6 ] = 0 ;
ud . wchoice [ 0 ] [ 7 ] = 2 ;
ud . wchoice [ 0 ] [ 8 ] = 9 ;
ud . wchoice [ 0 ] [ 9 ] = 1 ;
ud . multimode = 1 ;
2020-07-15 19:11:23 +00:00
ud . m_monsters_off = userConfig . nomonsters ;
2020-07-20 21:21:27 +00:00
ps [ 0 ] . aim_mode = 1 ;
2020-11-02 22:53:55 +00:00
ud . cameraactor = nullptr ;
2022-12-21 12:32:00 +00:00
moves . Push ( { } ) ; // make sure the first entry in 'moves' is a null move.
2022-12-21 12:20:14 +00:00
actions . Push ( { } ) ; // make sure the first entry in 'actions' is a null action.
2022-12-17 14:41:53 +00:00
ais . Push ( { } ) ; // make sure the first entry in 'actions' is a null action.
2020-07-15 19:11:23 +00:00
2020-07-19 19:04:22 +00:00
if ( fileSystem . FileExists ( " DUKESW.BIN " ) )
g_gameType | = GAMEFLAG_SHAREWARE ;
2020-07-15 19:11:23 +00:00
2020-07-20 21:21:27 +00:00
numplayers = 1 ;
playerswhenstarted = ud . multimode ;
connectpoint2 [ 0 ] = - 1 ;
2020-07-15 19:11:23 +00:00
2020-07-20 21:21:27 +00:00
SetDispatcher ( ) ;
2022-11-24 20:27:08 +00:00
2020-07-20 21:21:27 +00:00
loadcons ( ) ;
2023-01-01 15:16:17 +00:00
initactorflags ( ) ;
2022-12-08 22:09:46 +00:00
setTextureIDs ( ) ; // sets a few texture IDs needed for map checking.
2022-10-21 22:12:17 +00:00
duke_menufont - > Callback ( ) ; // depends on the .CON files so it must be after loadcons
2020-07-15 19:11:23 +00:00
2020-07-20 21:21:27 +00:00
OnEvent ( EVENT_INIT ) ;
2020-07-15 19:11:23 +00:00
2020-07-20 21:21:27 +00:00
//Net_SendClientInfo();
2020-07-15 19:11:23 +00:00
2021-04-03 19:06:02 +00:00
setupbackdrop ( ) ;
2020-07-20 21:21:27 +00:00
InitCheats ( ) ;
checkcommandline ( ) ;
registerosdcommands ( ) ;
screenpeek = myconnectindex ;
2020-10-25 14:06:06 +00:00
C_InitConback ( TexMan . CheckForTexture ( " MENUSCREEN " , ETextureType : : Any ) , false , 0.75 ) ;
2020-07-20 21:21:27 +00:00
if ( ud . multimode > 1 )
{
ud . m_monsters_off = 1 ;
2020-09-05 14:31:01 +00:00
//ud.player_skill = 0;
2020-07-20 21:21:27 +00:00
}
ud . last_level = - 1 ;
2020-08-23 15:47:05 +00:00
enginecompatibility_mode = ENGINECOMPATIBILITY_19961112 ; //bVanilla;
2020-09-26 14:18:44 +00:00
S_ParseDeveloperCommentary ( ) ;
2020-07-15 19:11:23 +00:00
}
2020-07-20 21:21:27 +00:00
2022-12-21 21:06:34 +00:00
void GameInterface : : FinalizeSetup ( )
{
for ( int i = 0 ; i < MAXTILES ; i + + )
{
auto & actinf = gs . actorinfo [ i ] ;
if ( actinf . scriptaddress ! = 0 )
{
int act = ScriptCode [ actinf . scriptaddress + 1 ] ;
int cmd = ScriptCode [ actinf . scriptaddress + 4 ] ;
auto info = spawnMap . CheckKey ( i ) ;
PClassActor * cls = nullptr ;
2022-12-31 16:58:14 +00:00
if ( info ! = nullptr & & ! info - > basetex . isValid ( ) )
2022-12-21 21:06:34 +00:00
{
cls = info - > cls ;
}
2022-12-31 16:58:14 +00:00
else if ( info = = nullptr | | ! info - > basetex . isValid ( ) )
2022-12-21 21:06:34 +00:00
{
2023-01-01 11:48:01 +00:00
// No unique actor class exists here. Since we need one, create a new class here, directly derived from DDukeActor.
2022-12-21 21:06:34 +00:00
auto newcls = ( PClassActor * ) RUNTIME_CLASS ( DDukeActor ) - > CreateDerivedClass ( FStringf ( " NewConActor%d " , i ) , RUNTIME_CLASS ( DDukeActor ) - > Size ) ;
newcls - > InitializeDefaults ( ) ;
2023-01-01 11:48:01 +00:00
insertSpawnType ( i , { newcls , FNullTextureID ( ) , FNullTextureID ( ) , NO_SOUND , int8_t ( 0 ) , int8_t ( 0 ) , int16_t ( 0x8000 ) } ) ;
2022-12-21 21:06:34 +00:00
cls = newcls ;
2022-12-31 17:32:05 +00:00
GetDefaultByType ( newcls ) - > spr . setspritetexture ( tileGetTextureID ( i ) ) ; // make it show the right pic.
2022-12-21 21:06:34 +00:00
}
else
{
// the ugly case: This tries to replace a variant of a special actor.
// All of Duke's entries falling in this category are coded to not execute scripts at all with no possible override.
// this means that none of these actors can ever run its scripts.
}
// now copy all data over so that we don't have to do double maintenance.
if ( cls )
{
cls - > ActorInfo ( ) - > TypeNum = i ;
GetDefaultByType ( cls ) - > IntVar ( NAME_strength ) = ScriptCode [ actinf . scriptaddress ] ;
if ( actinf . enemyflags & EDukeFlags1 : : FromInt ( 1 ) )
{
auto def = static_cast < DDukeActor * > ( GetDefaultByType ( cls ) ) ;
auto fb = ( SFLAG_BADGUY | SFLAG_KILLCOUNT | SFLAG_BADGUYSTAYPUT ) ;
auto check = ( def - > flags1 & ( SFLAG_BADGUY | SFLAG_KILLCOUNT ) ) ;
// do not enable KILLCOUNT if it the base is a non-counting badguy. This is needed for RR's animals.
if ( check = = EDukeFlags1 : : FromInt ( SFLAG_BADGUY ) ) fb & = ~ SFLAG_KILLCOUNT ;
def - > flags1 = ( def - > flags1 & ~ fb ) | ( actinf . enemyflags & fb ) ;
}
}
}
//ScriptCode[actinf.scriptaddress] = 0; // ignore strength values for hashing the script code. (later, we still need this.)
// todo: hash the entire script code and compare against precalculated value for the current game.
// If identical, remove all ScriptAddresses from the class list.
}
}
2022-01-25 23:36:34 +00:00
2022-12-28 21:46:13 +00:00
int LookupAction ( DDukeActor * self , FName name )
{
// todo
return 0 ;
}
int LookupMove ( DDukeActor * self , FName name )
{
// todo
return 0 ;
}
int LookupAI ( DDukeActor * self , FName name )
{
// todo
return 0 ;
}
2022-02-20 23:19:26 +00:00
void CallInitialize ( DDukeActor * actor )
{
2022-01-16 23:51:40 +00:00
IFVIRTUALPTR ( actor , DDukeActor , Initialize )
2022-02-20 23:19:26 +00:00
{
2023-01-05 09:56:04 +00:00
VMValue val = actor ;
VMCall ( func , & val , 1 , nullptr , 0 ) ;
2022-02-20 23:19:26 +00:00
}
}
void CallTick ( DDukeActor * actor )
{
IFVIRTUALPTR ( actor , DDukeActor , Tick )
{
VMValue val = actor ;
VMCall ( func , & val , 1 , nullptr , 0 ) ;
}
}
void CallAction ( DDukeActor * actor )
{
IFVIRTUALPTR ( actor , DDukeActor , RunState )
{
VMValue val = actor ;
VMCall ( func , & val , 1 , nullptr , 0 ) ;
}
}
2022-12-22 09:50:48 +00:00
void checkhitsprite ( DDukeActor * actor , DDukeActor * hitter )
2022-01-17 23:30:43 +00:00
{
IFVIRTUALPTR ( actor , DDukeActor , onHit )
{
VMValue val [ 2 ] = { actor , hitter } ;
VMCall ( func , val , 2 , nullptr , 0 ) ;
}
}
2022-11-15 09:17:23 +00:00
void CallOnHurt ( DDukeActor * actor , player_struct * hitter )
{
IFVIRTUALPTR ( actor , DDukeActor , onHurt )
{
VMValue val [ 2 ] = { actor , hitter } ;
VMCall ( func , val , 2 , nullptr , 0 ) ;
}
}
2022-11-21 20:33:27 +00:00
void CallOnTouch ( DDukeActor * actor , player_struct * hitter )
{
IFVIRTUALPTR ( actor , DDukeActor , onTouch )
{
VMValue val [ 2 ] = { actor , hitter } ;
VMCall ( func , val , 2 , nullptr , 0 ) ;
}
}
2022-11-15 09:17:23 +00:00
2022-01-21 00:04:08 +00:00
bool CallOnUse ( DDukeActor * actor , player_struct * user )
2022-11-14 09:22:22 +00:00
{
2022-01-21 00:04:08 +00:00
int nval = false ;
2022-11-14 09:22:22 +00:00
IFVIRTUALPTR ( actor , DDukeActor , onUse )
{
VMValue val [ 2 ] = { actor , user } ;
2022-01-21 00:04:08 +00:00
VMReturn ret ( & nval ) ;
VMCall ( func , val , 2 , & ret , 1 ) ;
2022-11-14 09:22:22 +00:00
}
2022-01-21 00:04:08 +00:00
return nval ;
2022-11-14 09:22:22 +00:00
}
2022-01-17 23:30:43 +00:00
2022-11-22 16:53:46 +00:00
void CallOnMotoSmash ( DDukeActor * actor , player_struct * hitter )
{
IFVIRTUALPTR ( actor , DDukeActor , onMotoSmash )
{
VMValue val [ 2 ] = { actor , hitter } ;
VMCall ( func , val , 2 , nullptr , 0 ) ;
}
}
2022-11-20 10:58:19 +00:00
void CallOnRespawn ( DDukeActor * actor , int low )
{
IFVIRTUALPTR ( actor , DDukeActor , onRespawn )
{
VMValue val [ 2 ] = { actor , low } ;
VMCall ( func , val , 2 , nullptr , 0 ) ;
}
}
2022-01-19 17:52:52 +00:00
bool CallAnimate ( DDukeActor * actor , tspritetype * tspr )
{
int nval = false ;
IFVIRTUALPTR ( actor , DDukeActor , animate )
{
VMReturn ret ( & nval ) ;
2022-12-24 04:41:37 +00:00
VMValue val [ 2 ] = { actor , tspr } ;
2022-12-23 09:33:22 +00:00
VMCall ( func , val , 2 , & ret , 1 ) ;
2022-01-19 17:52:52 +00:00
}
return nval ;
}
2022-11-20 12:57:51 +00:00
void CallStaticSetup ( DDukeActor * actor )
{
IFVIRTUALPTR ( actor , DDukeActor , StaticSetup )
{
VMValue val = actor ;
VMCall ( func , & val , 1 , nullptr , 0 ) ;
}
}
2022-01-19 17:52:52 +00:00
2022-11-29 12:06:42 +00:00
bool CallShootThis ( DDukeActor * clsdef , DDukeActor * actor , int pn , const DVector3 & spos , DAngle sang )
{
int rv = 0 ;
VMReturn ret ( & rv ) ;
IFVIRTUALPTR ( clsdef , DDukeActor , ShootThis )
{
VMValue val [ ] = { clsdef , actor , pn > = 0 ? & ps [ pn ] : nullptr , spos . X , spos . Y , spos . Z , sang . Degrees ( ) } ;
VMCall ( func , val , 7 , & ret , 1 ) ;
}
return rv ;
}
2022-12-31 14:21:03 +00:00
void CallPlayFTASound ( DDukeActor * actor , int mode )
2022-11-30 18:39:06 +00:00
{
IFVIRTUALPTR ( actor , DDukeActor , PlayFTASound )
{
2022-12-31 14:21:03 +00:00
VMValue val [ ] = { actor , mode } ;
VMCall ( func , val , 2 , nullptr , 0 ) ;
2022-11-30 18:39:06 +00:00
}
}
2022-12-02 22:26:55 +00:00
void CallStandingOn ( DDukeActor * actor , player_struct * p )
{
IFVIRTUALPTR ( actor , DDukeActor , StandingOn )
{
VMValue val [ ] = { actor , p } ;
VMCall ( func , val , 2 , nullptr , 0 ) ;
}
}
2022-12-29 12:55:59 +00:00
int CallTriggerSwitch ( DDukeActor * actor , player_struct * p )
2022-12-10 22:40:58 +00:00
{
int nval = false ;
IFVIRTUALPTR ( actor , DDukeActor , TriggerSwitch )
{
VMReturn ret ( & nval ) ;
VMValue val [ ] = { actor , p } ;
VMCall ( func , val , 2 , & ret , 1 ) ;
}
return nval ;
}
2022-12-16 15:56:47 +00:00
PClassActor * CallGetRadiusDamageType ( DDukeActor * actor , int targhealth )
{
PClassActor * nval = nullptr ;
IFVIRTUALPTR ( actor , DDukeActor , GetRadiusDamageType )
{
VMReturn ret ;
ret . PointerAt ( ( void * * ) & nval ) ;
VMValue val [ ] = { actor , targhealth } ;
VMCall ( func , val , 2 , & ret , 1 ) ;
}
return nval ;
}
2022-11-30 18:39:06 +00:00
2022-12-21 23:07:38 +00:00
//==========================================================================
//
// Sets up the flag defaults which differ between RR and Duke.
//
//==========================================================================
2022-12-23 21:32:37 +00:00
DEFINE_PROPERTY ( setgamedefaults , 0 , DukeActor )
2022-12-21 23:07:38 +00:00
{
2022-12-23 21:32:37 +00:00
if ( ! isRR ( ) )
{
defaults - > flags1 | = SFLAG_LOOKALLAROUND ; // feature comes from RR, but we want the option in Duke as well, so this fake property sets the default
defaults - > FloatVar ( NAME_shootzoffset ) = - 7 ;
}
2022-12-21 23:07:38 +00:00
else
{
defaults - > flags1 | = SFLAG_MOVEFTA_WAKEUPCHECK ; // Animals were not supposed to have this, but due to a coding bug the logic was unconditional for everything in the game.
defaults - > flags2 | = SFLAG2_NODAMAGEPUSH ; // RR does not have this feature, so set the flag for everything, this allows disabling it if wanted later.
2022-12-29 18:12:35 +00:00
defaults - > flags3 | = SFLAG3_RANDOMANGLEONWATER ; // RR does this for all badguys, Duke only for the LizMan.
2022-12-21 23:07:38 +00:00
}
}
//==========================================================================
//
// The 3 major CPN related properties - moves, actions, ais.
//
//==========================================================================
DEFINE_PROPERTY ( move , Sii , DukeActor )
{
2023-01-01 15:16:17 +00:00
if ( info - > ActorInfo ( ) - > NumMoves + + = = 0 ) info - > ActorInfo ( ) - > FirstMove = moves . Size ( ) ;
2022-12-21 23:07:38 +00:00
auto move = & moves [ moves . Reserve ( 1 ) ] ;
move - > movex = move - > movez = 0 ;
PROP_STRING_PARM ( n , 0 ) ;
move - > name = n ;
move - > qualifiedName = FStringf ( " %s.%s " , info - > TypeName . GetChars ( ) , n ) ;
if ( PROP_PARM_COUNT > 1 )
{
PROP_INT_PARM ( v , 1 ) ;
move - > movex = v / 16.f ;
if ( PROP_PARM_COUNT > 2 )
{
PROP_INT_PARM ( v2 , 2 ) ;
move - > movex = v2 / 16.f ;
}
}
}
DEFINE_PROPERTY ( movef , Sff , DukeActor )
{
2023-01-01 15:16:17 +00:00
if ( info - > ActorInfo ( ) - > NumMoves + + = = 0 ) info - > ActorInfo ( ) - > FirstMove = moves . Size ( ) ;
2022-12-21 23:07:38 +00:00
auto move = & moves [ moves . Reserve ( 1 ) ] ;
move - > movex = move - > movez = 0 ;
PROP_STRING_PARM ( n , 0 ) ;
move - > name = n ;
move - > qualifiedName = FStringf ( " %s.%s " , info - > TypeName . GetChars ( ) , n ) ;
if ( PROP_PARM_COUNT > 1 )
{
PROP_FLOAT_PARM ( v , 1 ) ;
move - > movex = v ;
if ( PROP_PARM_COUNT > 2 )
{
PROP_FLOAT_PARM ( v2 , 2 ) ;
move - > movex = v2 ;
}
}
}
DEFINE_PROPERTY ( action , SZIiiii , DukeActor )
{
2023-01-01 15:16:17 +00:00
if ( info - > ActorInfo ( ) - > NumActions + + = = 0 ) info - > ActorInfo ( ) - > FirstAction = actions . Size ( ) ;
2022-12-21 23:07:38 +00:00
auto action = & actions [ actions . Reserve ( 1 ) ] ;
2022-12-28 21:46:13 +00:00
memset ( action , 0 , sizeof ( * action ) ) ;
2022-12-21 23:07:38 +00:00
PROP_STRING_PARM ( n , 0 ) ;
action - > name = n ;
action - > qualifiedName = FStringf ( " %s.%s " , info - > TypeName . GetChars ( ) , n ) ;
PROP_STRING_PARM ( b , 1 ) ;
action - > base = b = = nullptr ? FNullTextureID ( ) : TexMan . CheckForTexture ( b , ETextureType : : Any , FTextureManager : : TEXMAN_ReturnAll | FTextureManager : : TEXMAN_TryAny | FTextureManager : : TEXMAN_ForceLookup ) ;
PROP_INT_PARM ( v2 , 2 ) ;
action - > offset = v2 ;
if ( PROP_PARM_COUNT > 3 )
{
PROP_INT_PARM ( v3 , 3 ) ;
action - > numframes = v3 ;
if ( PROP_PARM_COUNT > 4 )
{
PROP_INT_PARM ( v4 , 4 ) ;
action - > rotationtype = v4 ;
if ( PROP_PARM_COUNT > 5 )
{
PROP_INT_PARM ( v5 , 5 ) ;
action - > increment = v5 ;
if ( PROP_PARM_COUNT > 6 )
{
PROP_INT_PARM ( v6 , 6 ) ;
action - > delay = v6 ;
}
}
}
}
}
DEFINE_PROPERTY ( ai , SSSi , DukeActor )
{
2023-01-01 15:16:17 +00:00
if ( info - > ActorInfo ( ) - > NumAIs + + = = 0 ) info - > ActorInfo ( ) - > FirstAI = ais . Size ( ) ;
2022-12-21 23:07:38 +00:00
auto ai = & ais [ ais . Reserve ( 1 ) ] ;
ai - > moveflags = 0 ;
PROP_STRING_PARM ( n , 0 ) ;
ai - > name = n ;
PROP_STRING_PARM ( a , 1 ) ;
ai - > action = FName ( a ) . GetIndex ( ) | 0x80000000 ; // don't look it up yet.
PROP_STRING_PARM ( m , 2 ) ;
2023-01-01 15:16:17 +00:00
ai - > move = FName ( m ) . GetIndex ( ) | 0x80000000 ; // don't look it up yet.
2022-12-21 23:07:38 +00:00
if ( PROP_PARM_COUNT > 3 )
{
PROP_INT_PARM ( v3 , 3 ) ;
ai - > moveflags = v3 ;
}
}
2022-12-28 21:46:13 +00:00
DEFINE_PROPERTY ( startaction , S , DukeActor )
{
PROP_STRING_PARM ( n , 0 ) ;
bag . DefaultAction = n ;
}
DEFINE_PROPERTY ( startmove , S , DukeActor )
{
PROP_STRING_PARM ( n , 0 ) ;
bag . DefaultMove = n ;
}
DEFINE_PROPERTY ( moveflags , I , DukeActor )
{
PROP_INT_PARM ( n , 0 ) ;
bag . moveflags = n ;
}
2022-12-04 08:18:57 +00:00
CCMD ( changewalltexture )
{
if ( argv . argc ( ) < 2 ) return ;
2022-12-09 23:29:25 +00:00
FTextureID tile = TexMan . CheckForTexture ( argv [ 1 ] , ETextureType : : Any ) ;
if ( ! tile . isValid ( ) ) tile = tileGetTextureID ( ( int ) strtol ( argv [ 1 ] , nullptr , 10 ) ) ;
2022-12-04 08:18:57 +00:00
HitInfoBase hit ;
hitscan ( ps [ 0 ] . actor - > spr . pos , ps [ 0 ] . cursector , DVector3 ( ps [ 0 ] . actor - > spr . Angles . Yaw . ToVector ( ) , 0 ) * 1024 , hit , CLIPMASK1 ) ;
if ( hit . hitWall )
{
2022-12-09 23:29:25 +00:00
hit . hitWall - > setwalltexture ( tile ) ;
2022-12-04 08:18:57 +00:00
}
}
2022-12-21 23:07:38 +00:00
2020-07-15 19:11:23 +00:00
END_DUKE_NS