2019-11-01 18:25:42 +00:00
# include <filesystem>
2019-10-25 22:32:49 +00:00
# include "gamecontrol.h"
# include "tarray.h"
# include "zstring.h"
# include "name.h"
# include "control.h"
# include "keyboard.h"
# include "sc_man.h"
2019-10-26 11:16:32 +00:00
# include "c_cvars.h"
2019-10-26 17:24:46 +00:00
# include "gameconfigfile.h"
2019-10-26 21:45:55 +00:00
# include "gamecvars.h"
2019-10-26 11:16:32 +00:00
# include "build.h"
2019-10-28 05:47:49 +00:00
# include "inputstate.h"
2019-10-28 16:50:08 +00:00
# include "_control.h"
# include "control.h"
2019-10-28 21:19:50 +00:00
# include "m_argv.h"
# include "rts.h"
2019-11-01 18:25:42 +00:00
# include "printf.h"
2019-10-25 22:32:49 +00:00
2019-10-27 23:24:09 +00:00
InputState inputState ;
2019-10-28 21:19:50 +00:00
void SetClipshapes ( ) ;
2019-10-31 22:25:21 +00:00
int ShowStartupWindow ( TArray < GrpEntry > & ) ;
2019-11-01 18:25:42 +00:00
void InitFileSystem ( TArray < GrpEntry > & ) ;
2019-10-31 22:25:21 +00:00
int globalShadeDiv ;
2019-10-27 23:24:09 +00:00
2019-10-25 22:32:49 +00:00
struct GameFuncNameDesc
{
int index ;
const char * name ;
} ;
static const GameFuncNameDesc gamefuncs [ ] = {
{ gamefunc_Move_Forward , " Move_Forward " } ,
{ gamefunc_Move_Backward , " Move_Backward " } ,
{ gamefunc_Turn_Left , " Turn_Left " } ,
{ gamefunc_Turn_Right , " Turn_Right " } ,
{ gamefunc_Strafe , " Strafe " } ,
{ gamefunc_Fire , " Fire " } ,
{ gamefunc_Open , " Open " } ,
{ gamefunc_Run , " Run " } ,
{ gamefunc_Alt_Fire , " Alt_Fire " } ,
{ gamefunc_Jump , " Jump " } ,
{ gamefunc_Crouch , " Crouch " } ,
{ gamefunc_Look_Up , " Look_Up " } ,
{ gamefunc_Look_Down , " Look_Down " } ,
{ gamefunc_Look_Left , " Look_Left " } ,
{ gamefunc_Look_Right , " Look_Right " } ,
{ gamefunc_Strafe_Left , " Strafe_Left " } ,
{ gamefunc_Strafe_Right , " Strafe_Right " } ,
{ gamefunc_Aim_Up , " Aim_Up " } ,
{ gamefunc_Aim_Down , " Aim_Down " } ,
{ gamefunc_Weapon_1 , " Weapon_1 " } ,
{ gamefunc_Weapon_2 , " Weapon_2 " } ,
{ gamefunc_Weapon_3 , " Weapon_3 " } ,
{ gamefunc_Weapon_4 , " Weapon_4 " } ,
{ gamefunc_Weapon_5 , " Weapon_5 " } ,
{ gamefunc_Weapon_6 , " Weapon_6 " } ,
{ gamefunc_Weapon_7 , " Weapon_7 " } ,
{ gamefunc_Weapon_8 , " Weapon_8 " } ,
{ gamefunc_Weapon_9 , " Weapon_9 " } ,
{ gamefunc_Weapon_10 , " Weapon_10 " } ,
{ gamefunc_Inventory , " Inventory " } ,
{ gamefunc_Inventory_Left , " Inventory_Left " } ,
{ gamefunc_Inventory_Right , " Inventory_Right " } ,
{ gamefunc_Holo_Duke , " Holo_Duke " } ,
{ gamefunc_Jetpack , " Jetpack " } ,
{ gamefunc_NightVision , " NightVision " } ,
{ gamefunc_MedKit , " MedKit " } ,
{ gamefunc_TurnAround , " TurnAround " } ,
{ gamefunc_SendMessage , " SendMessage " } ,
{ gamefunc_Map , " Map " } ,
{ gamefunc_Shrink_Screen , " Shrink_Screen " } ,
{ gamefunc_Enlarge_Screen , " Enlarge_Screen " } ,
{ gamefunc_Center_View , " Center_View " } ,
{ gamefunc_Holster_Weapon , " Holster_Weapon " } ,
{ gamefunc_Show_Opponents_Weapon , " Show_Opponents_Weapon " } ,
{ gamefunc_Map_Follow_Mode , " Map_Follow_Mode " } ,
{ gamefunc_See_Coop_View , " See_Coop_View " } ,
{ gamefunc_Mouse_Aiming , " Mouse_Aiming " } ,
{ gamefunc_Toggle_Crosshair , " Toggle_Crosshair " } ,
{ gamefunc_Steroids , " Steroids " } ,
{ gamefunc_Quick_Kick , " Quick_Kick " } ,
{ gamefunc_Next_Weapon , " Next_Weapon " } ,
{ gamefunc_Previous_Weapon , " Previous_Weapon " } ,
{ gamefunc_Show_Console , " Show_Console " } ,
{ gamefunc_Show_DukeMatch_Scores , " Show_DukeMatch_Scores " } ,
{ gamefunc_Dpad_Select , " Dpad_Select " } ,
{ gamefunc_Dpad_Aiming , " Dpad_Aiming " } ,
{ gamefunc_AutoRun , " AutoRun " } ,
{ gamefunc_Last_Weapon , " Last_Used_Weapon " } ,
{ gamefunc_Quick_Save , " Quick_Save " } ,
{ gamefunc_Quick_Load , " Quick_Load " } ,
2019-10-26 11:16:32 +00:00
{ gamefunc_Alt_Weapon , " Alt_Weapon " } ,
2019-10-25 22:32:49 +00:00
{ gamefunc_Third_Person_View , " Third_Person_View " } ,
{ gamefunc_Toggle_Crouch , " Toggle_Crouch " } ,
{ gamefunc_See_Chase_View , " See_Chase_View " } , // the following were added by Blood
{ gamefunc_Turn_Around , " Turn_Around " } ,
{ gamefunc_Weapon_Fire , " Weapon_Fire " } ,
{ gamefunc_Weapon_Special_Fire , " Weapon_Special_Fire " } ,
{ gamefunc_Aim_Center , " Aim_Center " } ,
{ gamefunc_Tilt_Left , " Tilt_Left " } ,
{ gamefunc_Tilt_Right , " Tilt_Right " } ,
{ gamefunc_Send_Message , " Send_Message " } ,
{ gamefunc_BeastVision , " BeastVision " } ,
{ gamefunc_CrystalBall , " CrystalBall " } ,
{ gamefunc_JumpBoots , " JumpBoots " } ,
{ gamefunc_ProximityBombs , " ProximityBombs " } ,
{ gamefunc_RemoteBombs , " RemoteBombs " } ,
2019-10-26 11:16:32 +00:00
{ gamefunc_Smoke_Bomb , " Smoke_Bomb " } ,
{ gamefunc_Gas_Bomb , " Gas_Bomb " } ,
{ gamefunc_Flash_Bomb , " Flash_Bomb " } ,
{ gamefunc_Caltrops , " Calitrops " } ,
2019-10-25 22:32:49 +00:00
} ;
2019-10-31 23:32:56 +00:00
FString currentGame ;
2019-10-28 22:46:15 +00:00
FString LumpFilter ;
2019-10-26 17:24:46 +00:00
2019-10-25 22:32:49 +00:00
static TMap < FName , int > GF_NameToNum ;
2019-10-26 11:16:32 +00:00
static FString GF_NumToName [ NUMGAMEFUNCTIONS ] ; // This one will preserve the original name for writing to the config (which must be loaded before CON scripts can hack around with the alias array.)
static FString GF_NumToAlias [ NUMGAMEFUNCTIONS ] ; // This is for CON scripts to hack apart.
2019-10-25 22:32:49 +00:00
uint8_t KeyboardKeys [ NUMGAMEFUNCTIONS ] [ 2 ] ;
2019-10-26 11:16:32 +00:00
static FString stringStore [ 2 * NUMGAMEFUNCTIONS ] ; // toss all persistent strings from the OSDCMDs in here so that they stick around until shutdown.
CVAR ( Int , cl_defaultconfiguration , 2 , CVAR_ARCHIVE | CVAR_GLOBALCONFIG )
2019-10-25 22:32:49 +00:00
2019-10-27 07:14:58 +00:00
2019-10-26 11:16:32 +00:00
static int osdcmd_button ( osdcmdptr_t parm )
2019-10-25 22:32:49 +00:00
{
2019-10-26 11:16:32 +00:00
static char const s_gamefunc_ [ ] = " gamefunc_ " ;
int constexpr strlen_gamefunc_ = ARRAY_SIZE ( s_gamefunc_ ) - 1 ;
char const * p = parm - > name + strlen_gamefunc_ ;
//if (gInputMode == kInputGame) // only trigger these if in game (fixme: Ensure it works for all games!)
CONTROL_ButtonFlags [ CONFIG_FunctionNameToNum ( p ) ] = 1 ; // FIXME
return OSDCMD_OK ;
}
2019-10-26 17:24:46 +00:00
//==========================================================================
//
//
//
//==========================================================================
2019-10-26 11:16:32 +00:00
void SetupButtonFunctions ( )
{
unsigned index = 0 ;
for ( auto & func : GF_NumToAlias )
{
if ( func [ 0 ] = = ' \0 ' )
continue ;
}
}
2019-10-28 21:19:50 +00:00
UserConfig userConfig ;
void UserConfig : : ProcessOptions ( )
{
// -help etc are omitted
// -cfg / -setupfile refer to Build style config which are not supported.
if ( Args - > CheckParm ( " -cfg " ) | | Args - > CheckParm ( " -setupfile " ) )
{
initprintf ( " Build-format config files not supported and will be ignored \n " ) ;
}
auto v = Args - > CheckValue ( " -port " ) ;
if ( v ) netPort = strtol ( v , nullptr , 0 ) ;
netServerMode = Args - > CheckParm ( " -server " ) ;
netServerAddress = Args - > CheckValue ( " -connect " ) ;
netPassword = Args - > CheckValue ( " -password " ) ;
v = Args - > CheckValue ( " -addon " ) ;
if ( v )
{
auto val = strtol ( v , nullptr , 0 ) ;
static const char * const addons [ ] = { " DUKE3D.GRP " , " DUKEDC.GRP " , " NWINTER.GRP " , " VACATION.GRP " } ;
if ( val > 0 & & val < 4 ) gamegrp = addons [ val ] ;
else initprintf ( " %s: Unknown Addon \n " , v ) ;
}
else if ( Args - > CheckParm ( " -nam " ) )
{
gamegrp = " NAM.GRP " ;
}
else if ( Args - > CheckParm ( " -napalm " ) )
{
gamegrp = " NAPALM.GRP " ;
}
else if ( Args - > CheckParm ( " -ww2gi " ) )
{
gamegrp = " WW2GI.GRP " ;
}
2019-11-01 18:25:42 +00:00
v = Args - > CheckValue ( " -gamegrp " ) ;
2019-10-28 21:19:50 +00:00
if ( v )
{
gamegrp = v ;
}
else
{
// This is to enable the use of Doom launchers. that are limited to -iwad for specifying the game's main resource.
v = Args - > CheckValue ( " -iwad " ) ;
if ( v )
{
gamegrp = v ;
}
}
Args - > CollectFiles ( " -rts " , " .rts " ) ;
auto rts = Args - > CheckValue ( " -rts " ) ;
if ( rts ) RTS_Init ( rts ) ;
Args - > CollectFiles ( " -map " , " .map " ) ;
CommandMap = Args - > CheckValue ( " -map " ) ;
static const char * defs [ ] = { " -def " , " -h " , nullptr } ;
Args - > CollectFiles ( " -def " , defs , " .def " ) ;
DefaultDef = Args - > CheckValue ( " -def " ) ;
static const char * cons [ ] = { " -con " , " -x " , nullptr } ;
Args - > CollectFiles ( " -con " , cons , " .con " ) ;
DefaultCon = Args - > CheckValue ( " -con " ) ;
static const char * demos [ ] = { " -playback " , " -d " , " -demo " , nullptr } ;
Args - > CollectFiles ( " -demo " , demos , " .dmo " ) ;
CommandDemo = Args - > CheckValue ( " -demo " ) ;
static const char * names [ ] = { " -pname " , " -name " , nullptr } ;
Args - > CollectFiles ( " -name " , names , " .--- " ) ; // this shouldn't collect any file names at all so use a nonsense extension
CommandName = Args - > CheckValue ( " -name " ) ;
static const char * nomos [ ] = { " -nomonsters " , " -nodudes " , nullptr } ;
Args - > CollectFiles ( " -nomonsters " , nomos , " .--- " ) ; // this shouldn't collect any file names at all so use a nonsense extension
nomonsters = Args - > CheckParm ( " -nomonsters " ) ;
static const char * acons [ ] = { " -addcon " , " -mx " , nullptr } ;
Args - > CollectFiles ( " -addcon " , acons , " .con " ) ;
AddCons . reset ( Args - > GatherFiles ( " -addcon " ) ) ;
static const char * adefs [ ] = { " -adddef " , " -mh " , nullptr } ;
Args - > CollectFiles ( " -adddef " , adefs , " .def " ) ;
AddDefs . reset ( Args - > GatherFiles ( " -adddef " ) ) ;
Args - > CollectFiles ( " -art " , " .art " ) ;
AddArt . reset ( Args - > GatherFiles ( " -art " ) ) ;
CommandIni = Args - > CheckValue ( " -ini " ) ;
nologo = Args - > CheckParm ( " -nologo " ) | | Args - > CheckParm ( " -quick " ) ;
nomusic = Args - > CheckParm ( " -nomusic " ) ;
nosound = Args - > CheckParm ( " -nosfx " ) ;
if ( Args - > CheckParm ( " -nosound " ) ) nomusic = nosound = true ;
if ( Args - > CheckParm ( " -setup " ) ) setupstate = 1 ;
else if ( Args - > CheckParm ( " -nosetup " ) ) setupstate = 0 ;
if ( Args - > CheckParm ( " -file " ) )
{
// For file loading there's two modes:
// If -file is given, all content will be processed in order and the legacy options be ignored entirely.
//This allows mixing directories and GRP files in arbitrary order.
Args - > CollectFiles ( " -file " , NULL ) ;
AddFiles . reset ( Args - > GatherFiles ( " -file " ) ) ;
}
else
{
2019-11-01 18:25:42 +00:00
// Trying to emulate Build. This means to treat RFF files as lowest priority, then all GRPs and then all directories.
2019-10-28 21:19:50 +00:00
// This is only for people depending on lauchers. Since the semantics are so crappy it is strongly recommended to
2019-11-01 18:25:42 +00:00
// use -file instead which gives the user full control over the order in which things are added.
2019-10-28 21:19:50 +00:00
// For single mods this is no problem but don't even think about loading more stuff consistently...
static const char * grps [ ] = { " -g " , " -grp " , nullptr } ;
static const char * dirs [ ] = { " -game_dir " , " -j " , nullptr } ;
static const char * rffs [ ] = { " -rff " , " -snd " , nullptr } ;
static const char * twostep [ ] = { " -rff " , " -grp " , nullptr } ;
// Abuse the inner workings to get the files into proper order. This is not 100% accurate but should work fine for everything that doesn't intentionally fuck things up.
Args - > CollectFiles ( " -rff " , rffs , " .rff " ) ;
Args - > CollectFiles ( " -grp " , grps , nullptr ) ;
Args - > CollectFiles ( " -grp " , twostep , nullptr ) ; // The two previous calls have already brought the content in order so collecting it again gives us one list with everything.
AddFilesPre . reset ( Args - > GatherFiles ( " -grp " ) ) ;
Args - > CollectFiles ( " -game_dir " , dirs , nullptr ) ;
AddFiles . reset ( Args - > GatherFiles ( " -game_dir " ) ) ;
}
}
2019-10-31 22:25:21 +00:00
//==========================================================================
//
//
//
//==========================================================================
namespace Duke
{
extern GameInterface Interface ;
}
namespace Redneck
{
extern GameInterface Interface ;
}
namespace Blood
{
extern GameInterface Interface ;
}
namespace ShadowWarrior
{
extern GameInterface Interface ;
}
void CheckFrontend ( int flags )
{
if ( flags & GAMEFLAG_BLOOD )
{
gi = & Blood : : Interface ;
globalShadeDiv = 62 ;
}
else if ( flags & GAMEFLAG_RR )
{
gi = & Redneck : : Interface ;
globalShadeDiv = 30 ;
}
else if ( flags & GAMEFLAG_FURY )
{
gi = & Duke : : Interface ;
globalShadeDiv = 26 ; // This is different from all other games which need a value two less than the amount of shades.
}
else if ( flags & GAMEFLAG_SW )
{
gi = & ShadowWarrior : : Interface ;
globalShadeDiv = 30 ;
}
else
{
gi = & Duke : : Interface ;
globalShadeDiv = 30 ;
}
}
2019-10-26 17:24:46 +00:00
//==========================================================================
//
//
//
//==========================================================================
2019-10-31 23:32:56 +00:00
int CONFIG_Init ( )
2019-10-26 11:16:32 +00:00
{
2019-10-28 21:19:50 +00:00
SetClipshapes ( ) ;
2019-10-26 11:16:32 +00:00
// This must be done before initializing any data, so doing it late in the startup process won't work.
2019-11-01 18:25:42 +00:00
if ( CONTROL_Startup ( controltype_keyboardandmouse , BGetTime , 120 ) )
2019-10-26 11:16:32 +00:00
{
2019-10-31 23:32:56 +00:00
return 1 ;
2019-10-26 11:16:32 +00:00
}
2019-10-28 21:19:50 +00:00
userConfig . ProcessOptions ( ) ;
2019-10-29 18:53:46 +00:00
G_LoadConfig ( ) ;
2019-10-31 22:25:21 +00:00
2019-10-29 18:53:46 +00:00
// Startup dialog must be presented here so that everything can be set up before reading the keybinds.
2019-10-30 23:41:56 +00:00
auto groups = GrpScan ( ) ;
2019-11-01 18:25:42 +00:00
if ( groups . Size ( ) = = 0 )
{
// Abort if no game data found.
I_Error ( " Unable to find any game data. Please verify your settings. " ) ;
}
decltype ( groups ) usedgroups ;
int groupno = - 1 ;
// If the user has specified a file name, let's see if we know it.
//
if ( userConfig . gamegrp )
2019-10-31 23:32:56 +00:00
{
2019-11-01 18:25:42 +00:00
std : : filesystem : : path gpath = std : : filesystem : : u8path ( userConfig . gamegrp . GetChars ( ) ) ;
int g = 0 ;
for ( auto & grp : groups )
2019-10-31 23:32:56 +00:00
{
2019-11-01 18:25:42 +00:00
std : : filesystem : : path fpath = std : : filesystem : : u8path ( grp . FileName . GetChars ( ) ) ;
std : : error_code err ;
if ( std : : filesystem : : equivalent ( gpath , fpath , err ) )
2019-10-31 23:32:56 +00:00
{
break ;
}
2019-11-01 18:25:42 +00:00
g + + ;
}
groupno = g ;
}
if ( groupno = = - 1 | | userConfig . setupstate = = 1 )
groupno = ShowStartupWindow ( groups ) ;
if ( groupno = = - 1 ) return 0 ;
auto & group = groups [ groupno ] ;
// Now filter out the data we actually need and delete the rest.
usedgroups . Push ( group ) ;
auto crc = group . FileInfo . dependencyCRC ;
for ( auto & dep : groups )
{
if ( dep . FileInfo . CRC = = crc )
{
usedgroups . Insert ( 0 , dep ) ; // Order from least dependent to most dependent, which is the loading order of data.
2019-10-31 23:32:56 +00:00
}
}
2019-11-01 18:25:42 +00:00
groups . Reset ( ) ;
FString selectedScript ;
FString selectedDef ;
for ( auto & ugroup : usedgroups )
{
// For CONs the command line has priority, aside from that, the last one wins. For Blood this handles INIs - the rules are the same.
if ( ugroup . FileInfo . scriptname . IsNotEmpty ( ) ) selectedScript = ugroup . FileInfo . scriptname ;
if ( ugroup . FileInfo . defname . IsNotEmpty ( ) ) selectedDef = ugroup . FileInfo . defname ;
// CVAR has priority. This also overwrites the global variable each time. Init here is lazy so this is ok.
if ( ugroup . FileInfo . rtsname . IsNotEmpty ( ) & & * * rtsname = = 0 ) RTS_Init ( ugroup . FileInfo . rtsname ) ;
// For the game filter the last non-empty one wins.
if ( ugroup . FileInfo . gamefilter . IsNotEmpty ( ) ) LumpFilter = ugroup . FileInfo . gamefilter ;
g_gameType | = ugroup . FileInfo . flags ;
}
if ( userConfig . DefaultCon . IsEmpty ( ) ) userConfig . DefaultCon = selectedScript ;
if ( userConfig . DefaultDef . IsEmpty ( ) ) userConfig . DefaultDef = selectedDef ;
// This can only happen with a custom game that does not define any filter.
// In this case take the display name and strip all whitespace and invaliid path characters from it.
if ( LumpFilter . IsEmpty ( ) )
{
LumpFilter = usedgroups . Last ( ) . FileInfo . name ;
LumpFilter . StripChars ( " .:/ \\ <>? \" *| \t \r \n " ) ;
}
2019-10-29 18:53:46 +00:00
2019-10-31 23:32:56 +00:00
currentGame = LumpFilter ;
currentGame . Truncate ( currentGame . IndexOf ( " . " ) ) ;
2019-11-01 18:25:42 +00:00
CheckFrontend ( g_gameType ) ;
2019-10-28 21:19:50 +00:00
2019-10-31 23:32:56 +00:00
G_ReadConfig ( currentGame ) ;
if ( ! GameConfig - > IsInitialized ( ) )
{
CONFIG_ReadCombatMacros ( ) ;
CONFIG_SetDefaultKeys ( cl_defaultconfiguration = = 1 ? " demolition/origbinds.txt " : cl_defaultconfiguration = = 2 ? " demolition/leftbinds.txt " : " demolition/defbinds.txt " ) ;
}
2019-10-28 21:19:50 +00:00
if ( userConfig . CommandName . IsNotEmpty ( ) )
{
playername = userConfig . CommandName ;
}
2019-10-26 11:16:32 +00:00
int index = 0 ;
2019-10-25 22:32:49 +00:00
for ( auto & gf : gamefuncs )
{
GF_NameToNum . Insert ( gf . name , gf . index ) ;
GF_NumToAlias [ gf . index ] = GF_NumToName [ gf . index ] = gf . name ;
2019-10-26 11:16:32 +00:00
stringStore [ index ] . Format ( " gamefunc_%s " , gf . name ) ;
stringStore [ index ] . ToLower ( ) ;
stringStore [ index + 1 ] = stringStore [ index ] ;
stringStore [ index + 1 ] + = " : game button " ;
OSD_RegisterFunction ( stringStore [ index ] , stringStore [ index + 1 ] , osdcmd_button ) ;
index + = 2 ;
2019-10-25 22:32:49 +00:00
}
2019-10-26 17:24:46 +00:00
SetupButtonFunctions ( ) ;
2019-10-26 11:16:32 +00:00
CONTROL_ClearAssignments ( ) ;
2019-10-26 21:45:55 +00:00
CONFIG_InitMouseAndController ( ) ;
CONFIG_SetGameControllerDefaultsStandard ( ) ;
2019-11-01 18:25:42 +00:00
InitFileSystem ( usedgroups ) ;
2019-10-31 23:32:56 +00:00
return gi - > app_main ( ) ;
2019-10-25 22:32:49 +00:00
}
2019-10-26 17:24:46 +00:00
//==========================================================================
//
//
//
//==========================================================================
2019-10-25 22:32:49 +00:00
int32_t CONFIG_FunctionNameToNum ( const char * func )
{
if ( ! func ) return - 1 ;
FName name ( func , true ) ;
if ( name = = NAME_None ) return - 1 ;
auto res = GF_NameToNum . CheckKey ( name ) ;
if ( ! res ) return - 1 ;
return * res ;
}
const char * CONFIG_FunctionNumToName ( int32_t func )
{
if ( ( unsigned ) func > = ( unsigned ) NUMGAMEFUNCTIONS )
return NULL ;
return GF_NumToAlias [ func ] ;
}
const char * CONFIG_FunctionNumToRealName ( int32_t func )
{
if ( ( unsigned ) func > = ( unsigned ) NUMGAMEFUNCTIONS )
return NULL ;
return GF_NumToName [ func ] ;
}
void CONFIG_ReplaceButtonName ( int num , const char * text )
{
if ( ( unsigned ) num > = ( unsigned ) NUMGAMEFUNCTIONS )
return ;
GF_NumToAlias [ num ] = text ;
GF_NameToNum . Insert ( text , num ) ;
}
void CONFIG_DeleteButtonName ( int num )
{
if ( ( unsigned ) num > = ( unsigned ) NUMGAMEFUNCTIONS )
return ;
GF_NumToAlias [ num ] = " " ;
}
2019-10-26 17:24:46 +00:00
//==========================================================================
//
2019-10-25 22:32:49 +00:00
// wrapper for CONTROL_MapKey(), generates key bindings to reflect changes to keyboard setup
2019-10-26 17:24:46 +00:00
//
//==========================================================================
2019-10-25 22:32:49 +00:00
void CONFIG_MapKey ( int which , kb_scancode key1 , kb_scancode oldkey1 , kb_scancode key2 , kb_scancode oldkey2 )
{
int const keys [ ] = { key1 , key2 , oldkey1 , oldkey2 } ;
if ( which = = gamefunc_Show_Console )
OSD_CaptureKey ( key1 ) ;
for ( int k = 0 ; ( unsigned ) k < ARRAY_SIZE ( keys ) ; k + + )
{
if ( keys [ k ] = = 0xff | | ! keys [ k ] )
continue ;
int match = 0 ;
for ( ; sctokeylut [ match ] . key ; match + + )
{
if ( keys [ k ] = = sctokeylut [ match ] . sc )
break ;
}
FString tempbuf ;
for ( int i = NUMGAMEFUNCTIONS - 1 ; i > = 0 ; i - - )
{
if ( KeyboardKeys [ i ] [ 0 ] = = keys [ k ] | | KeyboardKeys [ i ] [ 1 ] = = keys [ k ] )
{
tempbuf . AppendFormat ( " gamefunc_%s; " , CONFIG_FunctionNumToName ( i ) ) ;
}
}
auto len = tempbuf . Len ( ) ;
if ( len > = 2 )
{
tempbuf . Truncate ( len - 2 ) ; // cut off the trailing "; "
CONTROL_BindKey ( keys [ k ] , tempbuf , 1 , sctokeylut [ match ] . key ? sctokeylut [ match ] . key : " <?> " ) ;
}
else
{
CONTROL_FreeKeyBind ( keys [ k ] ) ;
}
}
}
2019-10-26 17:24:46 +00:00
//==========================================================================
//
//
//
//==========================================================================
2019-10-25 22:32:49 +00:00
void CONFIG_SetDefaultKeys ( const char * defbinds , bool lazy /*=false*/ )
{
FScanner sc ;
sc . Open ( defbinds ) ;
if ( ! lazy )
{
memset ( KeyboardKeys , 0xff , sizeof ( KeyboardKeys ) ) ;
CONTROL_ClearAllBinds ( ) ;
}
while ( sc . GetToken ( ) )
{
sc . TokenMustBe ( TK_StringConst ) ;
int num = CONFIG_FunctionNameToNum ( sc . String ) ;
int default0 = - 1 ;
int default1 = - 1 ;
if ( sc . CheckToken ( ' , ' ) )
{
sc . MustGetToken ( TK_StringConst ) ;
default0 = KB_StringToScanCode ( sc . String ) ;
if ( sc . CheckToken ( ' , ' ) )
{
sc . MustGetToken ( TK_StringConst ) ;
default1 = KB_StringToScanCode ( sc . String ) ;
2019-10-26 19:16:23 +00:00
}
if ( num > = 0 & & num < NUMGAMEFUNCTIONS )
{
auto & key = KeyboardKeys [ num ] ;
2019-10-25 22:32:49 +00:00
#if 0
2019-10-26 19:16:23 +00:00
// skip the function if the default key is already used
// or the function is assigned to another key
if ( lazy & & ( key [ 0 ] ! = 0xff | | ( CONTROL_KeyIsBound ( default0 ) & & Bstrlen ( CONTROL_KeyBinds [ default0 ] . cmdstr ) > strlen_gamefunc_
& & CONFIG_FunctionNameToNum ( CONTROL_KeyBinds [ default0 ] . cmdstr + strlen_gamefunc_ ) > = 0 ) ) )
{
continue ;
}
2019-10-25 22:32:49 +00:00
# endif
2019-10-26 19:16:23 +00:00
key [ 0 ] = default0 ;
key [ 1 ] = default1 ;
2019-10-25 22:32:49 +00:00
2019-10-26 19:16:23 +00:00
if ( key [ 0 ] ) CONTROL_FreeKeyBind ( key [ 0 ] ) ;
if ( key [ 1 ] ) CONTROL_FreeKeyBind ( key [ 1 ] ) ;
2019-10-25 22:32:49 +00:00
2019-10-26 19:16:23 +00:00
if ( num = = gamefunc_Show_Console )
OSD_CaptureKey ( key [ 0 ] ) ;
else
CONFIG_MapKey ( num , key [ 0 ] , 0 , key [ 1 ] , 0 ) ;
2019-10-25 22:32:49 +00:00
}
}
}
}
2019-10-26 17:24:46 +00:00
2019-10-27 07:14:58 +00:00
//==========================================================================
//
//
//
//==========================================================================
CVAR ( String , combatmacro0 , " " , CVAR_ARCHIVE | CVAR_USERINFO )
CVAR ( String , combatmacro1 , " " , CVAR_ARCHIVE | CVAR_USERINFO )
CVAR ( String , combatmacro2 , " " , CVAR_ARCHIVE | CVAR_USERINFO )
CVAR ( String , combatmacro3 , " " , CVAR_ARCHIVE | CVAR_USERINFO )
CVAR ( String , combatmacro4 , " " , CVAR_ARCHIVE | CVAR_USERINFO )
CVAR ( String , combatmacro5 , " " , CVAR_ARCHIVE | CVAR_USERINFO )
CVAR ( String , combatmacro6 , " " , CVAR_ARCHIVE | CVAR_USERINFO )
CVAR ( String , combatmacro7 , " " , CVAR_ARCHIVE | CVAR_USERINFO )
CVAR ( String , combatmacro8 , " " , CVAR_ARCHIVE | CVAR_USERINFO )
CVAR ( String , combatmacro9 , " " , CVAR_ARCHIVE | CVAR_USERINFO )
FStringCVar * const CombatMacros [ ] = { & combatmacro0 , & combatmacro1 , & combatmacro2 , & combatmacro3 , & combatmacro4 , & combatmacro5 , & combatmacro6 , & combatmacro7 , & combatmacro8 , & combatmacro9 } ;
void CONFIG_ReadCombatMacros ( )
{
FScanner sc ;
sc . Open ( " demolition/combatmacros.txt " ) ;
for ( auto s : CombatMacros )
{
sc . MustGetToken ( TK_StringConst ) ;
if ( strlen ( * s ) = = 0 )
* s = sc . String ;
}
}
2019-10-26 19:50:49 +00:00
//==========================================================================
//
//
//
//==========================================================================
2019-10-27 12:40:24 +00:00
static FString CONFIG_GetMD4EntryName ( uint8_t const * const md4 )
{
return FStringf ( " MD4_%08x%08x%08x%08x " ,
B_BIG32 ( B_UNBUF32 ( & md4 [ 0 ] ) ) , B_BIG32 ( B_UNBUF32 ( & md4 [ 4 ] ) ) ,
B_BIG32 ( B_UNBUF32 ( & md4 [ 8 ] ) ) , B_BIG32 ( B_UNBUF32 ( & md4 [ 12 ] ) ) ) ;
}
int32_t CONFIG_GetMapBestTime ( char const * const mapname , uint8_t const * const mapmd4 )
{
auto m = CONFIG_GetMD4EntryName ( mapmd4 ) ;
if ( GameConfig - > SetSection ( " MapTimes " ) )
{
auto s = GameConfig - > GetValueForKey ( m ) ;
if ( s ) ( int ) strtoull ( s , nullptr , 0 ) ;
}
return - 1 ;
}
int CONFIG_SetMapBestTime ( uint8_t const * const mapmd4 , int32_t tm )
{
FStringf t ( " %d " , tm ) ;
auto m = CONFIG_GetMD4EntryName ( mapmd4 ) ;
if ( GameConfig - > SetSection ( " MapTimes " ) )
{
GameConfig - > SetValueForKey ( m , t ) ;
}
return 0 ;
}
//==========================================================================
//
//
//
//==========================================================================
2019-10-26 19:50:49 +00:00
int32_t MouseFunctions [ MAXMOUSEBUTTONS ] [ 2 ] ;
int32_t MouseDigitalFunctions [ MAXMOUSEAXES ] [ 2 ] ;
int32_t MouseAnalogueAxes [ MAXMOUSEAXES ] ;
int32_t MouseAnalogueScale [ MAXMOUSEAXES ] ;
int32_t JoystickFunctions [ MAXJOYBUTTONSANDHATS ] [ 2 ] ;
int32_t JoystickDigitalFunctions [ MAXJOYAXES ] [ 2 ] ;
int32_t JoystickAnalogueAxes [ MAXJOYAXES ] ;
int32_t JoystickAnalogueScale [ MAXJOYAXES ] ;
int32_t JoystickAnalogueDead [ MAXJOYAXES ] ;
int32_t JoystickAnalogueSaturate [ MAXJOYAXES ] ;
int32_t JoystickAnalogueInvert [ MAXJOYAXES ] ;
2019-10-26 21:45:55 +00:00
static const char * mousedefaults [ MAXMOUSEBUTTONS ] =
{
" Weapon_Fire " ,
" Weapon_Special_Fire " ,
" " ,
" " ,
" Previous_Weapon " ,
" Next_Weapon " ,
} ;
static const char * mouseclickeddefaults [ MAXMOUSEBUTTONS ] =
{
} ;
static const char * mouseanalogdefaults [ MAXMOUSEAXES ] =
{
" analog_turning " ,
" analog_moving " ,
} ;
static const char * mousedigitaldefaults [ MAXMOUSEDIGITAL ] =
{
} ;
static const char * joystickdefaults [ MAXJOYBUTTONSANDHATS ] =
{
" Fire " ,
" Strafe " ,
" Run " ,
" Open " ,
" " ,
" " ,
" " ,
" " ,
" " ,
" " ,
" " ,
" " ,
" " ,
" " ,
" " ,
" " ,
" " ,
" " ,
" " ,
" " ,
" " ,
" " ,
" " ,
" " ,
" " ,
" " ,
" " ,
" " ,
" " ,
" " ,
" " ,
" " ,
" Aim_Down " ,
" Look_Right " ,
" Aim_Up " ,
" Look_Left " ,
} ;
static const char * joystickclickeddefaults [ MAXJOYBUTTONSANDHATS ] =
{
" " ,
" Inventory " ,
" Jump " ,
" Crouch " ,
} ;
static const char * joystickanalogdefaults [ MAXJOYAXES ] =
{
" analog_turning " ,
" analog_moving " ,
" analog_strafing " ,
} ;
static const char * joystickdigitaldefaults [ MAXJOYDIGITAL ] =
{
" " ,
" " ,
" " ,
" " ,
" " ,
" " ,
" Run " ,
} ;
2019-10-26 19:50:49 +00:00
//==========================================================================
//
//
//
//==========================================================================
int32_t CONFIG_AnalogNameToNum ( const char * func )
{
if ( ! func )
return - 1 ;
if ( ! Bstrcasecmp ( func , " analog_turning " ) )
{
return analog_turning ;
}
if ( ! Bstrcasecmp ( func , " analog_strafing " ) )
{
return analog_strafing ;
}
if ( ! Bstrcasecmp ( func , " analog_moving " ) )
{
return analog_moving ;
}
if ( ! Bstrcasecmp ( func , " analog_lookingupanddown " ) )
{
return analog_lookingupanddown ;
}
return - 1 ;
}
//==========================================================================
//
//
//
//==========================================================================
const char * CONFIG_AnalogNumToName ( int32_t func )
{
switch ( func )
{
case analog_turning :
return " analog_turning " ;
case analog_strafing :
return " analog_strafing " ;
case analog_moving :
return " analog_moving " ;
case analog_lookingupanddown :
return " analog_lookingupanddown " ;
}
return NULL ;
}
2019-10-26 21:45:55 +00:00
void CONFIG_SetupMouse ( void )
{
const char * val ;
FString section = currentGame + " .MouseSettings " ;
if ( ! GameConfig - > SetSection ( section ) ) return ;
for ( int i = 0 ; i < MAXMOUSEBUTTONS ; i + + )
{
section . Format ( " MouseButton%d " , i ) ;
val = GameConfig - > GetValueForKey ( section ) ;
if ( val )
MouseFunctions [ i ] [ 0 ] = CONFIG_FunctionNameToNum ( val ) ;
section . Format ( " MouseButtonClicked%d " , i ) ;
val = GameConfig - > GetValueForKey ( section ) ;
if ( val )
MouseFunctions [ i ] [ 1 ] = CONFIG_FunctionNameToNum ( val ) ;
}
// map over the axes
for ( int i = 0 ; i < MAXMOUSEAXES ; i + + )
{
section . Format ( " MouseAnalogAxes%d " , i ) ;
val = GameConfig - > GetValueForKey ( section ) ;
if ( val )
MouseAnalogueAxes [ i ] = CONFIG_AnalogNameToNum ( val ) ;
section . Format ( " MouseDigitalAxes%d_0 " , i ) ;
val = GameConfig - > GetValueForKey ( section ) ;
if ( val )
MouseDigitalFunctions [ i ] [ 0 ] = CONFIG_FunctionNameToNum ( val ) ;
section . Format ( " MouseDigitalAxes%d_1 " , i ) ;
val = GameConfig - > GetValueForKey ( section ) ;
if ( val )
MouseDigitalFunctions [ i ] [ 1 ] = CONFIG_FunctionNameToNum ( val ) ;
section . Format ( " MouseAnalogScale%d " , i ) ;
val = GameConfig - > GetValueForKey ( section ) ;
if ( val )
MouseAnalogueScale [ i ] = ( int32_t ) strtoull ( val , nullptr , 0 ) ;
}
for ( int i = 0 ; i < MAXMOUSEBUTTONS ; i + + )
{
CONTROL_MapButton ( MouseFunctions [ i ] [ 0 ] , i , 0 , controldevice_mouse ) ;
CONTROL_MapButton ( MouseFunctions [ i ] [ 1 ] , i , 1 , controldevice_mouse ) ;
}
for ( int i = 0 ; i < MAXMOUSEAXES ; i + + )
{
CONTROL_MapAnalogAxis ( i , MouseAnalogueAxes [ i ] , controldevice_mouse ) ;
CONTROL_MapDigitalAxis ( i , MouseDigitalFunctions [ i ] [ 0 ] , 0 , controldevice_mouse ) ;
CONTROL_MapDigitalAxis ( i , MouseDigitalFunctions [ i ] [ 1 ] , 1 , controldevice_mouse ) ;
CONTROL_SetAnalogAxisScale ( i , MouseAnalogueScale [ i ] , controldevice_mouse ) ;
}
2019-10-28 06:05:32 +00:00
CONTROL_MouseEnabled = ( in_mouse & & CONTROL_MousePresent ) ;
2019-10-26 21:45:55 +00:00
}
void CONFIG_SetupJoystick ( void )
{
const char * val ;
FString section = currentGame + " .ControllerSettings " ;
if ( ! GameConfig - > SetSection ( section ) ) return ;
for ( int i = 0 ; i < MAXJOYBUTTONSANDHATS ; i + + )
{
section . Format ( " ControllerButton%d " , i ) ;
val = GameConfig - > GetValueForKey ( section ) ;
if ( val )
JoystickFunctions [ i ] [ 0 ] = CONFIG_FunctionNameToNum ( val ) ;
section . Format ( " ControllerButtonClicked%d " , i ) ;
val = GameConfig - > GetValueForKey ( section ) ;
if ( val )
JoystickFunctions [ i ] [ 1 ] = CONFIG_FunctionNameToNum ( val ) ;
}
// map over the axes
for ( int i = 0 ; i < MAXJOYAXES ; i + + )
{
section . Format ( " ControllerAnalogAxes%d " , i ) ;
val = GameConfig - > GetValueForKey ( section ) ;
if ( val )
JoystickAnalogueAxes [ i ] = CONFIG_AnalogNameToNum ( val ) ;
section . Format ( " ControllerDigitalAxes%d_0 " , i ) ;
val = GameConfig - > GetValueForKey ( section ) ;
if ( val )
JoystickDigitalFunctions [ i ] [ 0 ] = CONFIG_FunctionNameToNum ( val ) ;
section . Format ( " ControllerDigitalAxes%d_1 " , i ) ;
val = GameConfig - > GetValueForKey ( section ) ;
if ( val )
JoystickDigitalFunctions [ i ] [ 1 ] = CONFIG_FunctionNameToNum ( val ) ;
section . Format ( " ControllerAnalogScale%d " , i ) ;
val = GameConfig - > GetValueForKey ( section ) ;
if ( val )
JoystickAnalogueScale [ i ] = ( int32_t ) strtoull ( val , nullptr , 0 ) ;
section . Format ( " ControllerAnalogInvert%d " , i ) ;
val = GameConfig - > GetValueForKey ( section ) ;
if ( val )
JoystickAnalogueInvert [ i ] = ( int32_t ) strtoull ( val , nullptr , 0 ) ;
section . Format ( " ControllerAnalogDead%d " , i ) ;
val = GameConfig - > GetValueForKey ( section ) ;
if ( val )
JoystickAnalogueDead [ i ] = ( int32_t ) strtoull ( val , nullptr , 0 ) ;
section . Format ( " ControllerAnalogSaturate%d " , i ) ;
val = GameConfig - > GetValueForKey ( section ) ;
if ( val )
JoystickAnalogueSaturate [ i ] = ( int32_t ) strtoull ( val , nullptr , 0 ) ;
}
for ( int i = 0 ; i < MAXJOYBUTTONSANDHATS ; i + + )
{
CONTROL_MapButton ( JoystickFunctions [ i ] [ 0 ] , i , 0 , controldevice_joystick ) ;
CONTROL_MapButton ( JoystickFunctions [ i ] [ 1 ] , i , 1 , controldevice_joystick ) ;
}
for ( int i = 0 ; i < MAXJOYAXES ; i + + )
{
CONTROL_MapAnalogAxis ( i , JoystickAnalogueAxes [ i ] , controldevice_joystick ) ;
CONTROL_MapDigitalAxis ( i , JoystickDigitalFunctions [ i ] [ 0 ] , 0 , controldevice_joystick ) ;
CONTROL_MapDigitalAxis ( i , JoystickDigitalFunctions [ i ] [ 1 ] , 1 , controldevice_joystick ) ;
CONTROL_SetAnalogAxisScale ( i , JoystickAnalogueScale [ i ] , controldevice_joystick ) ;
CONTROL_SetAnalogAxisInvert ( i , JoystickAnalogueInvert [ i ] , controldevice_joystick ) ;
}
2019-10-28 06:05:32 +00:00
CONTROL_JoystickEnabled = ( in_joystick & & CONTROL_JoyPresent ) ;
// JBF 20040215: evil and nasty place to do this, but joysticks are evil and nasty too
for ( int i = 0 ; i < joystick . numAxes ; i + + )
joySetDeadZone ( i , JoystickAnalogueDead [ i ] , JoystickAnalogueSaturate [ i ] ) ;
2019-10-26 21:45:55 +00:00
}
static void CONFIG_SetJoystickButtonFunction ( int i , int j , int function )
{
JoystickFunctions [ i ] [ j ] = function ;
CONTROL_MapButton ( function , i , j , controldevice_joystick ) ;
}
static void CONFIG_SetJoystickAnalogAxisScale ( int i , int scale )
{
JoystickAnalogueScale [ i ] = scale ;
CONTROL_SetAnalogAxisScale ( i , scale , controldevice_joystick ) ;
}
static void CONFIG_SetJoystickAnalogAxisInvert ( int i , int invert )
{
JoystickAnalogueInvert [ i ] = invert ;
CONTROL_SetAnalogAxisInvert ( i , invert , controldevice_joystick ) ;
}
static void CONFIG_SetJoystickAnalogAxisDeadSaturate ( int i , int dead , int saturate )
{
JoystickAnalogueDead [ i ] = dead ;
JoystickAnalogueSaturate [ i ] = saturate ;
joySetDeadZone ( i , dead , saturate ) ;
}
static void CONFIG_SetJoystickDigitalAxisFunction ( int i , int j , int function )
{
JoystickDigitalFunctions [ i ] [ j ] = function ;
CONTROL_MapDigitalAxis ( i , function , j , controldevice_joystick ) ;
}
static void CONFIG_SetJoystickAnalogAxisFunction ( int i , int function )
{
JoystickAnalogueAxes [ i ] = function ;
CONTROL_MapAnalogAxis ( i , function , controldevice_joystick ) ;
}
struct GameControllerButtonSetting
{
GameControllerButton button ;
int function ;
void apply ( ) const
{
CONFIG_SetJoystickButtonFunction ( button , 0 , function ) ;
}
} ;
struct GameControllerAnalogAxisSetting
{
GameControllerAxis axis ;
int function ;
void apply ( ) const
{
CONFIG_SetJoystickAnalogAxisFunction ( axis , function ) ;
}
} ;
struct GameControllerDigitalAxisSetting
{
GameControllerAxis axis ;
int polarity ;
int function ;
void apply ( ) const
{
CONFIG_SetJoystickDigitalAxisFunction ( axis , polarity , function ) ;
}
} ;
void CONFIG_SetGameControllerDefaultsClear ( )
{
for ( int i = 0 ; i < MAXJOYBUTTONSANDHATS ; i + + )
{
CONFIG_SetJoystickButtonFunction ( i , 0 , - 1 ) ;
CONFIG_SetJoystickButtonFunction ( i , 1 , - 1 ) ;
}
for ( int i = 0 ; i < MAXJOYAXES ; i + + )
{
CONFIG_SetJoystickAnalogAxisScale ( i , DEFAULTJOYSTICKANALOGUESCALE ) ;
CONFIG_SetJoystickAnalogAxisInvert ( i , 0 ) ;
CONFIG_SetJoystickAnalogAxisDeadSaturate ( i , DEFAULTJOYSTICKANALOGUEDEAD , DEFAULTJOYSTICKANALOGUESATURATE ) ;
CONFIG_SetJoystickDigitalAxisFunction ( i , 0 , - 1 ) ;
CONFIG_SetJoystickDigitalAxisFunction ( i , 1 , - 1 ) ;
CONFIG_SetJoystickAnalogAxisFunction ( i , - 1 ) ;
}
}
static void CONFIG_SetGameControllerAxesModern ( )
{
static GameControllerAnalogAxisSetting const analogAxes [ ] =
{
{ GAMECONTROLLER_AXIS_LEFTX , analog_strafing } ,
{ GAMECONTROLLER_AXIS_LEFTY , analog_moving } ,
{ GAMECONTROLLER_AXIS_RIGHTX , analog_turning } ,
{ GAMECONTROLLER_AXIS_RIGHTY , analog_lookingupanddown } ,
} ;
CONFIG_SetJoystickAnalogAxisScale ( GAMECONTROLLER_AXIS_RIGHTX , 32768 + 16384 ) ;
CONFIG_SetJoystickAnalogAxisScale ( GAMECONTROLLER_AXIS_RIGHTY , 32768 + 16384 ) ;
for ( auto const & analogAxis : analogAxes )
analogAxis . apply ( ) ;
}
void CONFIG_SetGameControllerDefaultsStandard ( )
{
CONFIG_SetGameControllerDefaultsClear ( ) ;
CONFIG_SetGameControllerAxesModern ( ) ;
static GameControllerButtonSetting const buttons [ ] =
{
{ GAMECONTROLLER_BUTTON_A , gamefunc_Jump } ,
{ GAMECONTROLLER_BUTTON_B , gamefunc_Toggle_Crouch } ,
{ GAMECONTROLLER_BUTTON_BACK , gamefunc_Map } ,
{ GAMECONTROLLER_BUTTON_LEFTSTICK , gamefunc_Run } ,
{ GAMECONTROLLER_BUTTON_RIGHTSTICK , gamefunc_Quick_Kick } ,
{ GAMECONTROLLER_BUTTON_LEFTSHOULDER , gamefunc_Crouch } ,
{ GAMECONTROLLER_BUTTON_RIGHTSHOULDER , gamefunc_Jump } ,
{ GAMECONTROLLER_BUTTON_DPAD_UP , gamefunc_Previous_Weapon } ,
{ GAMECONTROLLER_BUTTON_DPAD_DOWN , gamefunc_Next_Weapon } ,
} ;
static GameControllerButtonSetting const buttonsDuke [ ] =
{
{ GAMECONTROLLER_BUTTON_X , gamefunc_Open } ,
{ GAMECONTROLLER_BUTTON_Y , gamefunc_Inventory } ,
{ GAMECONTROLLER_BUTTON_DPAD_LEFT , gamefunc_Inventory_Left } ,
{ GAMECONTROLLER_BUTTON_DPAD_RIGHT , gamefunc_Inventory_Right } ,
} ;
static GameControllerButtonSetting const buttonsFury [ ] =
{
{ GAMECONTROLLER_BUTTON_X , gamefunc_Steroids } , // Reload
{ GAMECONTROLLER_BUTTON_Y , gamefunc_Open } ,
{ GAMECONTROLLER_BUTTON_DPAD_LEFT , gamefunc_MedKit } ,
{ GAMECONTROLLER_BUTTON_DPAD_RIGHT , gamefunc_NightVision } , // Radar
} ;
static GameControllerDigitalAxisSetting const digitalAxes [ ] =
{
{ GAMECONTROLLER_AXIS_TRIGGERLEFT , 1 , gamefunc_Alt_Fire } ,
{ GAMECONTROLLER_AXIS_TRIGGERRIGHT , 1 , gamefunc_Fire } ,
} ;
for ( auto const & button : buttons )
button . apply ( ) ;
/*
if ( FURY )
{
for ( auto const & button : buttonsFury )
button . apply ( ) ;
}
else
*/
{
for ( auto const & button : buttonsDuke )
button . apply ( ) ;
}
for ( auto const & digitalAxis : digitalAxes )
digitalAxis . apply ( ) ;
}
void CONFIG_SetGameControllerDefaultsPro ( )
{
CONFIG_SetGameControllerDefaultsClear ( ) ;
CONFIG_SetGameControllerAxesModern ( ) ;
static GameControllerButtonSetting const buttons [ ] =
{
{ GAMECONTROLLER_BUTTON_A , gamefunc_Open } ,
{ GAMECONTROLLER_BUTTON_B , gamefunc_Third_Person_View } ,
{ GAMECONTROLLER_BUTTON_Y , gamefunc_Quick_Kick } ,
{ GAMECONTROLLER_BUTTON_BACK , gamefunc_Map } ,
{ GAMECONTROLLER_BUTTON_LEFTSTICK , gamefunc_Run } ,
{ GAMECONTROLLER_BUTTON_RIGHTSTICK , gamefunc_Crouch } ,
{ GAMECONTROLLER_BUTTON_DPAD_UP , gamefunc_Previous_Weapon } ,
{ GAMECONTROLLER_BUTTON_DPAD_DOWN , gamefunc_Next_Weapon } ,
} ;
static GameControllerButtonSetting const buttonsDuke [ ] =
{
{ GAMECONTROLLER_BUTTON_X , gamefunc_Inventory } ,
{ GAMECONTROLLER_BUTTON_LEFTSHOULDER , gamefunc_Previous_Weapon } ,
{ GAMECONTROLLER_BUTTON_RIGHTSHOULDER , gamefunc_Next_Weapon } ,
{ GAMECONTROLLER_BUTTON_DPAD_LEFT , gamefunc_Inventory_Left } ,
{ GAMECONTROLLER_BUTTON_DPAD_RIGHT , gamefunc_Inventory_Right } ,
} ;
static GameControllerButtonSetting const buttonsFury [ ] =
{
{ GAMECONTROLLER_BUTTON_X , gamefunc_Steroids } , // Reload
{ GAMECONTROLLER_BUTTON_LEFTSHOULDER , gamefunc_Crouch } ,
{ GAMECONTROLLER_BUTTON_RIGHTSHOULDER , gamefunc_Alt_Fire } ,
{ GAMECONTROLLER_BUTTON_DPAD_LEFT , gamefunc_MedKit } ,
{ GAMECONTROLLER_BUTTON_DPAD_RIGHT , gamefunc_NightVision } , // Radar
} ;
static GameControllerDigitalAxisSetting const digitalAxes [ ] =
{
{ GAMECONTROLLER_AXIS_TRIGGERLEFT , 1 , gamefunc_Jump } ,
{ GAMECONTROLLER_AXIS_TRIGGERRIGHT , 1 , gamefunc_Fire } ,
} ;
for ( auto const & button : buttons )
button . apply ( ) ;
#if 0 // ouch...
if ( FURY )
{
for ( auto const & button : buttonsFury )
button . apply ( ) ;
}
else
# endif
{
for ( auto const & button : buttonsDuke )
button . apply ( ) ;
}
for ( auto const & digitalAxis : digitalAxes )
digitalAxis . apply ( ) ;
}
char const * CONFIG_GetGameFuncOnKeyboard ( int gameFunc )
{
const char * string0 = KB_ScanCodeToString ( KeyboardKeys [ gameFunc ] [ 0 ] ) ;
return string0 [ 0 ] = = ' \0 ' ? KB_ScanCodeToString ( KeyboardKeys [ gameFunc ] [ 1 ] ) : string0 ;
}
char const * CONFIG_GetGameFuncOnMouse ( int gameFunc )
{
for ( int j = 0 ; j < 2 ; + + j )
for ( int i = 0 ; i < joystick . numButtons ; + + i )
if ( JoystickFunctions [ i ] [ j ] = = gameFunc )
return joyGetName ( 1 , i ) ;
for ( int i = 0 ; i < joystick . numAxes ; + + i )
for ( int j = 0 ; j < 2 ; + + j )
if ( JoystickDigitalFunctions [ i ] [ j ] = = gameFunc )
return joyGetName ( 0 , i ) ;
return " " ;
}
char const * CONFIG_GetGameFuncOnJoystick ( int gameFunc )
{
for ( int j = 0 ; j < 2 ; + + j )
for ( int i = 0 ; i < joystick . numButtons ; + + i )
if ( JoystickFunctions [ i ] [ j ] = = gameFunc )
return joyGetName ( 1 , i ) ;
for ( int i = 0 ; i < joystick . numAxes ; + + i )
for ( int j = 0 ; j < 2 ; + + j )
if ( JoystickDigitalFunctions [ i ] [ j ] = = gameFunc )
2019-10-28 16:50:08 +00:00
return joyGetName ( 0 , i ) ;
return " " ;
}
// FIXME: Consider the mouse as well!
FString CONFIG_GetBoundKeyForLastInput ( int gameFunc )
{
if ( CONTROL_LastSeenInput = = LastSeenInput : : Joystick )
{
char const * joyname = CONFIG_GetGameFuncOnJoystick ( gameFunc ) ;
if ( joyname ! = nullptr & & joyname [ 0 ] ! = ' \0 ' )
{
return joyname ;
}
char const * keyname = CONFIG_GetGameFuncOnKeyboard ( gameFunc ) ;
if ( keyname ! = nullptr & & keyname [ 0 ] ! = ' \0 ' )
{
return keyname ;
}
}
else
{
char const * keyname = CONFIG_GetGameFuncOnKeyboard ( gameFunc ) ;
if ( keyname ! = nullptr & & keyname [ 0 ] ! = ' \0 ' )
{
return keyname ;
}
char const * joyname = CONFIG_GetGameFuncOnJoystick ( gameFunc ) ;
if ( joyname ! = nullptr & & joyname [ 0 ] ! = ' \0 ' )
{
return joyname ;
}
}
2019-10-28 21:19:50 +00:00
return " UNBOUND " ;
2019-10-28 16:50:08 +00:00
}
2019-10-26 21:45:55 +00:00
void CONFIG_InitMouseAndController ( )
{
memset ( MouseFunctions , - 1 , sizeof ( MouseFunctions ) ) ;
memset ( MouseDigitalFunctions , - 1 , sizeof ( MouseDigitalFunctions ) ) ;
memset ( JoystickFunctions , - 1 , sizeof ( JoystickFunctions ) ) ;
memset ( JoystickDigitalFunctions , - 1 , sizeof ( JoystickDigitalFunctions ) ) ;
for ( int i = 0 ; i < MAXMOUSEBUTTONS ; i + + )
{
MouseFunctions [ i ] [ 0 ] = CONFIG_FunctionNameToNum ( mousedefaults [ i ] ) ;
CONTROL_MapButton ( MouseFunctions [ i ] [ 0 ] , i , 0 , controldevice_mouse ) ;
if ( i > = 4 ) continue ;
MouseFunctions [ i ] [ 1 ] = CONFIG_FunctionNameToNum ( mouseclickeddefaults [ i ] ) ;
CONTROL_MapButton ( MouseFunctions [ i ] [ 1 ] , i , 1 , controldevice_mouse ) ;
}
for ( int i = 0 ; i < MAXMOUSEAXES ; i + + )
{
MouseAnalogueScale [ i ] = DEFAULTMOUSEANALOGUESCALE ;
CONTROL_SetAnalogAxisScale ( i , MouseAnalogueScale [ i ] , controldevice_mouse ) ;
MouseDigitalFunctions [ i ] [ 0 ] = CONFIG_FunctionNameToNum ( mousedigitaldefaults [ i * 2 ] ) ;
MouseDigitalFunctions [ i ] [ 1 ] = CONFIG_FunctionNameToNum ( mousedigitaldefaults [ i * 2 + 1 ] ) ;
CONTROL_MapDigitalAxis ( i , MouseDigitalFunctions [ i ] [ 0 ] , 0 , controldevice_mouse ) ;
CONTROL_MapDigitalAxis ( i , MouseDigitalFunctions [ i ] [ 1 ] , 1 , controldevice_mouse ) ;
MouseAnalogueAxes [ i ] = CONFIG_AnalogNameToNum ( mouseanalogdefaults [ i ] ) ;
CONTROL_MapAnalogAxis ( i , MouseAnalogueAxes [ i ] , controldevice_mouse ) ;
}
CONFIG_SetupMouse ( ) ;
CONFIG_SetupJoystick ( ) ;
2019-10-28 16:50:08 +00:00
KB_ClearKeysDown ( ) ;
KB_FlushKeyboardQueue ( ) ;
KB_FlushKeyboardQueueScans ( ) ;
2019-10-26 21:45:55 +00:00
}
2019-10-28 16:50:08 +00:00
2019-10-26 21:45:55 +00:00
void CONFIG_PutNumber ( const char * key , int number )
{
FStringf str ( " %d " , number ) ;
GameConfig - > SetValueForKey ( key , str ) ;
}
void CONFIG_WriteControllerSettings ( )
{
FString buf ;
if ( in_mouse )
{
FString section = currentGame + " .MouseSettings " ;
GameConfig - > SetSection ( section ) ;
for ( int i = 0 ; i < MAXMOUSEBUTTONS ; i + + )
{
if ( CONFIG_FunctionNumToName ( MouseFunctions [ i ] [ 0 ] ) )
{
buf . Format ( " MouseButton%d " , i ) ;
GameConfig - > SetValueForKey ( buf , CONFIG_FunctionNumToName ( MouseFunctions [ i ] [ 0 ] ) ) ;
}
if ( i > = ( MAXMOUSEBUTTONS - 2 ) ) continue ;
if ( CONFIG_FunctionNumToName ( MouseFunctions [ i ] [ 1 ] ) )
{
buf . Format ( " MouseButtonClicked%d " , i ) ;
GameConfig - > SetValueForKey ( buf , CONFIG_FunctionNumToName ( MouseFunctions [ i ] [ 1 ] ) ) ;
}
}
for ( int i = 0 ; i < MAXMOUSEAXES ; i + + )
{
if ( CONFIG_AnalogNumToName ( MouseAnalogueAxes [ i ] ) )
{
buf . Format ( " MouseAnalogAxes%d " , i ) ;
GameConfig - > SetValueForKey ( buf , CONFIG_AnalogNumToName ( MouseAnalogueAxes [ i ] ) ) ;
}
if ( CONFIG_FunctionNumToName ( MouseDigitalFunctions [ i ] [ 0 ] ) )
{
buf . Format ( " MouseDigitalAxes%d_0 " , i ) ;
GameConfig - > SetValueForKey ( buf , CONFIG_FunctionNumToName ( MouseDigitalFunctions [ i ] [ 0 ] ) ) ;
}
if ( CONFIG_FunctionNumToName ( MouseDigitalFunctions [ i ] [ 1 ] ) )
{
buf . Format ( " MouseDigitalAxes%d_1 " , i ) ;
GameConfig - > SetValueForKey ( buf , CONFIG_FunctionNumToName ( MouseDigitalFunctions [ i ] [ 1 ] ) ) ;
}
buf . Format ( " MouseAnalogScale%d " , i ) ;
CONFIG_PutNumber ( buf , MouseAnalogueScale [ i ] ) ;
}
}
if ( in_joystick )
{
FString section = currentGame + " .ControllerSettings " ;
GameConfig - > SetSection ( section ) ;
for ( int dummy = 0 ; dummy < MAXJOYBUTTONSANDHATS ; dummy + + )
{
if ( CONFIG_FunctionNumToName ( JoystickFunctions [ dummy ] [ 0 ] ) )
{
buf . Format ( " ControllerButton%d " , dummy ) ;
GameConfig - > SetValueForKey ( buf , CONFIG_FunctionNumToName ( JoystickFunctions [ dummy ] [ 0 ] ) ) ;
}
if ( CONFIG_FunctionNumToName ( JoystickFunctions [ dummy ] [ 1 ] ) )
{
buf . Format ( " ControllerButtonClicked%d " , dummy ) ;
GameConfig - > SetValueForKey ( buf , CONFIG_FunctionNumToName ( JoystickFunctions [ dummy ] [ 1 ] ) ) ;
}
}
for ( int dummy = 0 ; dummy < MAXJOYAXES ; dummy + + )
{
if ( CONFIG_AnalogNumToName ( JoystickAnalogueAxes [ dummy ] ) )
{
buf . Format ( " ControllerAnalogAxes%d " , dummy ) ;
GameConfig - > SetValueForKey ( buf , CONFIG_AnalogNumToName ( JoystickAnalogueAxes [ dummy ] ) ) ;
}
if ( CONFIG_FunctionNumToName ( JoystickDigitalFunctions [ dummy ] [ 0 ] ) )
{
buf . Format ( " ControllerDigitalAxes%d_0 " , dummy ) ;
GameConfig - > SetValueForKey ( buf , CONFIG_FunctionNumToName ( JoystickDigitalFunctions [ dummy ] [ 0 ] ) ) ;
}
if ( CONFIG_FunctionNumToName ( JoystickDigitalFunctions [ dummy ] [ 1 ] ) )
{
buf . Format ( " ControllerDigitalAxes%d_1 " , dummy ) ;
GameConfig - > SetValueForKey ( buf , CONFIG_FunctionNumToName ( JoystickDigitalFunctions [ dummy ] [ 1 ] ) ) ;
}
buf . Format ( " ControllerAnalogScale%d " , dummy ) ;
CONFIG_PutNumber ( buf , JoystickAnalogueScale [ dummy ] ) ;
buf . Format ( " ControllerAnalogInvert%d " , dummy ) ;
CONFIG_PutNumber ( buf , JoystickAnalogueInvert [ dummy ] ) ;
buf . Format ( " ControllerAnalogDead%d " , dummy ) ;
CONFIG_PutNumber ( buf , JoystickAnalogueDead [ dummy ] ) ;
buf . Format ( " ControllerAnalogSaturate%d " , dummy ) ;
CONFIG_PutNumber ( buf , JoystickAnalogueSaturate [ dummy ] ) ;
}
}
}
2019-10-28 05:47:49 +00:00
const char * const ConsoleButtons [ ] =
{
" mouse1 " , " mouse2 " , " mouse3 " , " mouse4 " , " mwheelup " ,
" mwheeldn " , " mouse5 " , " mouse6 " , " mouse7 " , " mouse8 "
} ;
int osdcmd_bind ( osdcmdptr_t parm )
{
char tempbuf [ 256 ] ;
if ( parm - > numparms = = 1 & & ! Bstrcasecmp ( parm - > parms [ 0 ] , " showkeys " ) )
{
for ( auto & s : sctokeylut )
OSD_Printf ( " %s \n " , s . key ) ;
for ( auto ConsoleButton : ConsoleButtons )
OSD_Printf ( " %s \n " , ConsoleButton ) ;
return OSDCMD_OK ;
}
if ( parm - > numparms = = 0 )
{
int j = 0 ;
OSD_Printf ( " Current key bindings: \n " ) ;
for ( int i = 0 ; i < NUMKEYS + MAXMOUSEBUTTONS ; i + + )
if ( CONTROL_KeyIsBound ( i ) )
{
j + + ;
OSD_Printf ( " %-9s %s \" %s \" \n " , CONTROL_KeyBinds [ i ] . key , CONTROL_KeyBinds [ i ] . repeat ? " " : " norepeat " ,
CONTROL_KeyBinds [ i ] . cmdstr ) ;
}
if ( j = = 0 )
OSD_Printf ( " No binds found. \n " ) ;
return OSDCMD_OK ;
}
int i , j , repeat ;
for ( i = 0 ; i < ARRAY_SSIZE ( sctokeylut ) ; i + + )
{
if ( ! Bstrcasecmp ( parm - > parms [ 0 ] , sctokeylut [ i ] . key ) )
break ;
}
// didn't find the key
if ( i = = ARRAY_SSIZE ( sctokeylut ) )
{
for ( i = 0 ; i < MAXMOUSEBUTTONS ; i + + )
if ( ! Bstrcasecmp ( parm - > parms [ 0 ] , ConsoleButtons [ i ] ) )
break ;
if ( i > = MAXMOUSEBUTTONS )
return OSDCMD_SHOWHELP ;
if ( parm - > numparms < 2 )
{
if ( CONTROL_KeyBinds [ NUMKEYS + i ] . cmdstr & & CONTROL_KeyBinds [ NUMKEYS + i ] . key )
OSD_Printf ( " %-9s %s \" %s \" \n " , ConsoleButtons [ i ] , CONTROL_KeyBinds [ NUMKEYS + i ] . repeat ? " " : " norepeat " ,
CONTROL_KeyBinds [ NUMKEYS + i ] . cmdstr ) ;
else OSD_Printf ( " %s is unbound \n " , ConsoleButtons [ i ] ) ;
return OSDCMD_OK ;
}
j = 1 ;
repeat = 1 ;
if ( ! Bstrcasecmp ( parm - > parms [ j ] , " norepeat " ) )
{
repeat = 0 ;
j + + ;
}
Bstrcpy ( tempbuf , parm - > parms [ j + + ] ) ;
for ( ; j < parm - > numparms ; j + + )
{
Bstrcat ( tempbuf , " " ) ;
Bstrcat ( tempbuf , parm - > parms [ j + + ] ) ;
}
CONTROL_BindMouse ( i , tempbuf , repeat , ConsoleButtons [ i ] ) ;
if ( ! OSD_ParsingScript ( ) )
OSD_Printf ( " %s \n " , parm - > raw ) ;
return OSDCMD_OK ;
}
if ( parm - > numparms < 2 )
{
if ( CONTROL_KeyIsBound ( sctokeylut [ i ] . sc ) )
OSD_Printf ( " %-9s %s \" %s \" \n " , sctokeylut [ i ] . key , CONTROL_KeyBinds [ sctokeylut [ i ] . sc ] . repeat ? " " : " norepeat " ,
CONTROL_KeyBinds [ sctokeylut [ i ] . sc ] . cmdstr ) ;
else OSD_Printf ( " %s is unbound \n " , sctokeylut [ i ] . key ) ;
return OSDCMD_OK ;
}
j = 1 ;
repeat = 1 ;
if ( ! Bstrcasecmp ( parm - > parms [ j ] , " norepeat " ) )
{
repeat = 0 ;
j + + ;
}
Bstrcpy ( tempbuf , parm - > parms [ j + + ] ) ;
for ( ; j < parm - > numparms ; j + + )
{
Bstrcat ( tempbuf , " " ) ;
Bstrcat ( tempbuf , parm - > parms [ j + + ] ) ;
}
CONTROL_BindKey ( sctokeylut [ i ] . sc , tempbuf , repeat , sctokeylut [ i ] . key ) ;
char * cp = tempbuf ;
// Populate the keyboard config menu based on the bind.
// Take care of processing one-to-many bindings properly, too.
static char const s_gamefunc_ [ ] = " gamefunc_ " ;
int constexpr strlen_gamefunc_ = ARRAY_SIZE ( s_gamefunc_ ) - 1 ;
while ( ( cp = Bstrstr ( cp , s_gamefunc_ ) ) )
{
cp + = strlen_gamefunc_ ;
char * semi = Bstrchr ( cp , ' ; ' ) ;
if ( semi )
* semi = 0 ;
j = CONFIG_FunctionNameToNum ( cp ) ;
if ( semi )
cp = semi + 1 ;
if ( j ! = - 1 )
{
KeyboardKeys [ j ] [ 1 ] = KeyboardKeys [ j ] [ 0 ] ;
KeyboardKeys [ j ] [ 0 ] = sctokeylut [ i ] . sc ;
// CONTROL_MapKey(j, sctokeylut[i].sc, KeyboardKeys[j][0]);
if ( j = = gamefunc_Show_Console )
OSD_CaptureKey ( sctokeylut [ i ] . sc ) ;
}
}
if ( ! OSD_ParsingScript ( ) )
OSD_Printf ( " %s \n " , parm - > raw ) ;
return OSDCMD_OK ;
}
int osdcmd_unbindall ( osdcmdptr_t UNUSED ( parm ) )
{
UNREFERENCED_CONST_PARAMETER ( parm ) ;
for ( int i = 0 ; i < NUMKEYS ; + + i )
CONTROL_FreeKeyBind ( i ) ;
for ( int i = 0 ; i < MAXMOUSEBUTTONS ; + + i )
CONTROL_FreeMouseBind ( i ) ;
for ( auto & KeyboardKey : KeyboardKeys )
KeyboardKey [ 0 ] = KeyboardKey [ 1 ] = 0xff ;
if ( ! OSD_ParsingScript ( ) )
OSD_Printf ( " unbound all controls \n " ) ;
return OSDCMD_OK ;
}
int osdcmd_unbind ( osdcmdptr_t parm )
{
if ( parm - > numparms ! = 1 )
return OSDCMD_SHOWHELP ;
for ( auto & ConsoleKey : sctokeylut )
{
if ( ConsoleKey . key & & ! Bstrcasecmp ( parm - > parms [ 0 ] , ConsoleKey . key ) )
{
CONTROL_FreeKeyBind ( ConsoleKey . sc ) ;
OSD_Printf ( " unbound key %s \n " , ConsoleKey . key ) ;
return OSDCMD_OK ;
}
}
for ( int i = 0 ; i < MAXMOUSEBUTTONS ; i + + )
{
if ( ! Bstrcasecmp ( parm - > parms [ 0 ] , ConsoleButtons [ i ] ) )
{
CONTROL_FreeMouseBind ( i ) ;
OSD_Printf ( " unbound %s \n " , ConsoleButtons [ i ] ) ;
return OSDCMD_OK ;
}
}
return OSDCMD_SHOWHELP ;
}
2019-11-01 18:25:42 +00:00