1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2024-11-27 14:37:16 +00:00

shmup:: rewritten shmup configuration in OOP style

This commit is contained in:
Zeno Rogue 2018-11-18 03:18:11 +01:00
parent 97c405fc87
commit 8e2727882e
7 changed files with 254 additions and 229 deletions

View File

@ -364,7 +364,7 @@ bool have_current_settings() {
return true; return true;
if(pmodel != mdDisk || vid.monmode != DEFAULT_MONMODE || vid.wallmode != DEFAULT_WALLMODE) if(pmodel != mdDisk || vid.monmode != DEFAULT_MONMODE || vid.wallmode != DEFAULT_WALLMODE)
return true; return true;
if(firstland != laIce || vid.scfg.players != 1 || rug::rugged) if(firstland != laIce || multi::players != 1 || rug::rugged)
return true; return true;
if(modecount > 1) if(modecount > 1)
return true; return true;
@ -384,8 +384,8 @@ void resetModes(char leave) {
if(yendor::on != (leave == rg::yendor)) stop_game_and_switch_mode(rg::yendor); if(yendor::on != (leave == rg::yendor)) stop_game_and_switch_mode(rg::yendor);
if(tactic::on != (leave == rg::tactic)) stop_game_and_switch_mode(rg::tactic); if(tactic::on != (leave == rg::tactic)) stop_game_and_switch_mode(rg::tactic);
if(randomPatternsMode != (leave == rg::randpattern)) stop_game_and_switch_mode(rg::randpattern); if(randomPatternsMode != (leave == rg::randpattern)) stop_game_and_switch_mode(rg::randpattern);
if(vid.scfg.players != 1) { if(multi::players != 1) {
vid.scfg.players = 1; stop_game_and_switch_mode(); stop_game_and_switch_mode(); multi::players = 1;
} }
if(firstland != laIce || specialland != laIce) { if(firstland != laIce || specialland != laIce) {
stop_game(); stop_game();
@ -997,10 +997,8 @@ void showBasicConfig() {
if(xuni == 'g') pushScreen(showCustomizeChar); if(xuni == 'g') pushScreen(showCustomizeChar);
#if CAP_SHMUP #if CAP_SHMUP
if(xuni == 'p') { if(xuni == 'p')
pushScreen(shmup::showShmupConfig); shmup::configure();
multi::shmupcfg = shmup::on;
}
#endif #endif
if(uni == 'r') vid.revcontrol = !vid.revcontrol; if(uni == 'r') vid.revcontrol = !vid.revcontrol;
@ -1777,8 +1775,8 @@ int read_gamemode_args() {
if(argis("-P")) { if(argis("-P")) {
PHASE(2); shift(); PHASE(2); shift();
vid.scfg.players = argi();
stop_game_and_switch_mode(rg::nothing); stop_game_and_switch_mode(rg::nothing);
multi::players = argi();
} }
TOGGLE('C', chaosmode, stop_game_and_switch_mode(rg::chaos)) TOGGLE('C', chaosmode, stop_game_and_switch_mode(rg::chaos))
TOGGLE('S', shmup::on, stop_game_and_switch_mode(rg::shmup)) TOGGLE('S', shmup::on, stop_game_and_switch_mode(rg::shmup))

View File

@ -18,6 +18,8 @@ bool holdmouse;
int getcstat, lgetcstat; ld getcshift; bool inslider; int getcstat, lgetcstat; ld getcshift; bool inslider;
function <void(int sym, int uni)> keyhandler = [] (int sym, int uni) {}; function <void(int sym, int uni)> keyhandler = [] (int sym, int uni) {};
function <bool(SDL_Event &ev)> joyhandler = [] (SDL_Event &ev) {return false;};
// is the player using mouse? (used for auto-cross) // is the player using mouse? (used for auto-cross)
bool mousing = true; bool mousing = true;
@ -613,30 +615,7 @@ void handle_event(SDL_Event& ev) {
} }
} }
bool shmupconf = cmode & sm::SHMUPCONFIG; if(joyhandler && joyhandler(ev)) ;
if(ev.type == SDL_JOYBUTTONDOWN && shmupconf && vid.scfg.setwhat) {
int joyid = ev.jbutton.which;
int button = ev.jbutton.button;
if(joyid < 8 && button < 32)
vid.scfg.joyaction[joyid][button] = vid.scfg.setwhat;
vid.scfg.setwhat = 0;
}
else if(ev.type == SDL_JOYHATMOTION && shmupconf && vid.scfg.setwhat) {
int joyid = ev.jhat.which;
int hat = ev.jhat.hat;
int dir = 4;
if(ev.jhat.value == SDL_HAT_UP) dir = 0;
if(ev.jhat.value == SDL_HAT_RIGHT) dir = 1;
if(ev.jhat.value == SDL_HAT_DOWN) dir = 2;
if(ev.jhat.value == SDL_HAT_LEFT) dir = 3;
printf("%d %d %d\n", joyid, hat, dir);
if(joyid < 8 && hat < 4 && dir < 4) {
vid.scfg.hataction[joyid][hat][dir] = vid.scfg.setwhat;
vid.scfg.setwhat = 0;
}
}
else if(ev.type == SDL_JOYHATMOTION && !normal) { else if(ev.type == SDL_JOYHATMOTION && !normal) {
if(ev.jhat.value == SDL_HAT_UP) sym = SDLK_UP; if(ev.jhat.value == SDL_HAT_UP) sym = SDLK_UP;

View File

@ -5720,6 +5720,9 @@ void drawscreen() {
cmode = 0; cmode = 0;
keyhandler = [] (int sym, int uni) { return false; }; keyhandler = [] (int sym, int uni) { return false; };
#if CAP_SDL
joyhandler = [] (SDL_Event& ev) { return false; };
#endif
if(!isize(screens)) pushScreen(normalscreen); if(!isize(screens)) pushScreen(normalscreen);
screens.back()(); screens.back()();

View File

@ -766,7 +766,6 @@ void loadcs(FILE *f, charstyle& cs, int vernum);
namespace multi { namespace multi {
extern bool shmupcfg;
extern bool alwaysuse; extern bool alwaysuse;
void recall(); void recall();
extern cell *origpos[MAXPLAYER], *origtarget[MAXPLAYER]; extern cell *origpos[MAXPLAYER], *origtarget[MAXPLAYER];
@ -786,9 +785,6 @@ namespace multi {
extern int treasures[MAXPLAYER], kills[MAXPLAYER], deaths[MAXPLAYER]; extern int treasures[MAXPLAYER], kills[MAXPLAYER], deaths[MAXPLAYER];
struct config { struct config {
int players;
int subconfig;
int setwhat;
char keyaction[512]; char keyaction[512];
char joyaction[MAXJOY][MAXBUTTON]; char joyaction[MAXJOY][MAXBUTTON];
char axeaction[MAXJOY][MAXAXE]; char axeaction[MAXJOY][MAXAXE];
@ -807,7 +803,7 @@ namespace multi {
cell *multiPlayerTarget(int i); cell *multiPlayerTarget(int i);
void checklastmove(); void checklastmove();
void leaveGame(int i); void leaveGame(int i);
void showShmupConfig(); void configure();
} }
template<class T> class hookset : public map<int, function<T>> {}; template<class T> class hookset : public map<int, function<T>> {};
@ -2474,6 +2470,9 @@ extern bool leftclick;
void clearMemory(); void clearMemory();
extern function <void(int sym, int uni)> keyhandler; extern function <void(int sym, int uni)> keyhandler;
#if CAP_SDL
extern function <bool(SDL_Event &ev)> joyhandler;
#endif
void gmodekeys(int sym, int uni); void gmodekeys(int sym, int uni);
void switchGL(); void switchGL();

View File

@ -557,8 +557,7 @@ void showChangeMode() {
#if ISMOBILE==1 #if ISMOBILE==1
restart_game(rg::shmup); restart_game(rg::shmup);
#else #else
multi::shmupcfg = shmup::on; shmup::configure();
pushScreen(shmup::showShmupConfig);
#endif #endif
} }
else if(xuni == 'h' && !shmup::on) else if(xuni == 'h' && !shmup::on)
@ -762,10 +761,8 @@ void showStartMenu() {
clearMessages(); clearMessages();
welcomeMessage(); welcomeMessage();
stampbase = ticks; stampbase = ticks;
if(uni == 's') { if(uni == 's')
multi::shmupcfg = shmup::on; shmup::configure();
pushScreen(multi::showShmupConfig);
}
} }
else if(uni == 'Z') { else if(uni == 'Z') {
popScreenAll(); popScreenAll();
@ -931,7 +928,7 @@ int read_menu_args() {
PHASEFROM(2); launch_dialog(showChangeMode); PHASEFROM(2); launch_dialog(showChangeMode);
} }
else if(argis("-d:shmup")) { else if(argis("-d:shmup")) {
PHASEFROM(2); launch_dialog(shmup::showShmupConfig); PHASEFROM(2); launch_dialog(); shmup::configure();
} }
else return 1; else return 1;
return 0; return 0;

506
shmup.cpp
View File

@ -69,7 +69,7 @@ namespace multi {
static const int CMDS = 15; static const int CMDS = 15;
static const int CMDS_PAN = 11; static const int CMDS_PAN = 11;
const char* playercmds_shmup[15] = { vector<string> playercmds_shmup = {
"forward", "backward", "turn left", "turn right", "forward", "backward", "turn left", "turn right",
"move up", "move right", "move down", "move left", "move up", "move right", "move down", "move left",
"throw a knife", "face the pointer", "throw at the pointer", "throw a knife", "face the pointer", "throw at the pointer",
@ -77,7 +77,7 @@ namespace multi {
"Orb power (target: facing)" "Orb power (target: facing)"
}; };
const char* playercmds_turn[15] = { vector<string> playercmds_turn = {
"move up-right", "move up-left", "move down-right", "move down-left", "move up-right", "move up-left", "move down-right", "move down-left",
"move up", "move right", "move down", "move left", "move up", "move right", "move down", "move left",
"stay in place (left + right)", "cancel move", "leave the game", "stay in place (left + right)", "cancel move", "leave the game",
@ -85,7 +85,7 @@ namespace multi {
"" ""
}; };
const char* pancmds[11] = { vector<string> pancmds = {
"pan up", "pan right", "pan down", "pan left", "pan up", "pan right", "pan down", "pan left",
"rotate left", "rotate right", "home", "rotate left", "rotate right", "home",
"world overview", "review your quest", "inventory", "main menu" "world overview", "review your quest", "inventory", "main menu"
@ -93,7 +93,7 @@ namespace multi {
#define SHMUPAXES_BASE 4 #define SHMUPAXES_BASE 4
#define SHMUPAXES ((SHMUPAXES_BASE) + 4 * (MAXPLAYER)) #define SHMUPAXES ((SHMUPAXES_BASE) + 4 * (MAXPLAYER))
#define SHMUPAXES_CUR ((SHMUPAXES_BASE) + 4 * vid.scfg.players) #define SHMUPAXES_CUR ((SHMUPAXES_BASE) + 4 * playercfg)
const char* axemodes[SHMUPAXES] = { const char* axemodes[SHMUPAXES] = {
"do nothing", "do nothing",
@ -132,9 +132,6 @@ const char* axemodes[SHMUPAXES] = {
int centerplayer = -1; int centerplayer = -1;
int shmupnumkeys;
const char** shmupcmdtable;
char* axeconfigs[24]; int numaxeconfigs; char* axeconfigs[24]; int numaxeconfigs;
int* dzconfigs[24]; int* dzconfigs[24];
@ -178,28 +175,112 @@ void resetScores() {
multi::treasures[i] = multi::kills[i] = multi::deaths[i] = 0; multi::treasures[i] = multi::kills[i] = multi::deaths[i] = 0;
} }
bool shmupcfg;
bool configdead; bool configdead;
void handleConfig(int sym, int uni); void handleConfig(int sym, int uni);
void showShmupConfig() { string player_count_name(int p) {
#if CAP_SDL return XLAT(
cmode = sm::SHMUPCONFIG; p == 2 ? "two players" :
p == 3 ? "three players" :
int sc = vid.scfg.subconfig; p == 4 ? "four players" :
p == 5 ? "five players" :
if(sc == 1 || sc == 2 || sc == 4 || sc == 5 || sc == 6 || sc == 7 || sc == 8) { p == 6 ? "six players" :
shmupnumkeys = CMDS; p == 7 ? "seven players" :
shmupcmdtable = shmup::on ? playercmds_shmup : playercmds_turn; "one player");
} }
else if(sc == 3) {
shmupnumkeys = CMDS_PAN; struct key_configurer {
shmupcmdtable = pancmds;
int sc;
vector<string>& shmupcmdtable;
int setwhat;
key_configurer(int sc, vector<string>& sct) : sc(sc), shmupcmdtable(sct), setwhat(0) {}
void operator() () {
dialog::init(
XLAT(sc == 1 ? "configure player 1" :
sc == 2 ? "configure player 2" :
sc == 3 ? "configure panning" :
sc == 4 ? "configure player 3" :
sc == 5 ? "configure player 4" :
sc == 6 ? "configure player 5" :
sc == 7 ? "configure player 6" :
sc == 8 ? "configure player 7" : ""
));
getcstat = ' ';
for(int i=0; i<isize(shmupcmdtable); i++) if(shmupcmdtable[i][0])
dialog::addSelItem(XLAT(shmupcmdtable[i]), listkeys(16*sc+i),
setwhat ? (setwhat>1 && i == (setwhat&15) ? '?' : 0) : 'a'+i);
else dialog::addBreak(100);
if(setwhat == 1)
dialog::addItem(XLAT("press a key to unassign"), 0);
else if(setwhat)
dialog::addItem(XLAT("press a key for '%1'", XLAT(shmupcmdtable[setwhat&15])), 0);
else
dialog::addItem(XLAT("unassign a key"), 'z');
dialog::display();
keyhandler = [this] (int sym, int uni) {
if(!setwhat) dialog::handleNavigation(sym, uni);
if(sym) {
if(setwhat) {
vid.scfg.keyaction[sym] = setwhat;
setwhat = 0;
} }
else if(uni >= 'a' && uni < 'a' + isize(shmupcmdtable) && shmupcmdtable[uni-'a'][0])
setwhat = 16*sc+uni - 'a';
else if(uni == 'z')
setwhat = 1;
else if(doexiton(sym, uni))
popScreen();
}
};
joyhandler = [this] (SDL_Event& ev) {
if(ev.type == SDL_JOYBUTTONDOWN && setwhat) {
int joyid = ev.jbutton.which;
int button = ev.jbutton.button;
if(joyid < 8 && button < 32)
vid.scfg.joyaction[joyid][button] = setwhat;
setwhat = 0;
return true;
}
else if(ev.type == SDL_JOYHATMOTION && setwhat) {
int joyid = ev.jhat.which;
int hat = ev.jhat.hat;
int dir = 4;
if(ev.jhat.value == SDL_HAT_UP) dir = 0;
if(ev.jhat.value == SDL_HAT_RIGHT) dir = 1;
if(ev.jhat.value == SDL_HAT_DOWN) dir = 2;
if(ev.jhat.value == SDL_HAT_LEFT) dir = 3;
printf("%d %d %d\n", joyid, hat, dir);
if(joyid < 8 && hat < 4 && dir < 4) {
vid.scfg.hataction[joyid][hat][dir] = setwhat;
setwhat = 0;
return true;
}
}
return false;
};
}
};
#if CAP_SDLJOY #if CAP_SDLJOY
else if(sc == SCJOY) { struct joy_configurer {
bool shmupcfg, racecfg;
int playercfg;
joy_configurer(int playercfg) : playercfg(playercfg) {}
void operator() () {
dialog::init(); dialog::init();
getcstat = ' '; getcstat = ' ';
numaxeconfigs = 0; numaxeconfigs = 0;
@ -227,193 +308,9 @@ void showShmupConfig() {
dialog::addBoolItem(XLAT("Configure dead zones"), (configdead), 'z'); dialog::addBoolItem(XLAT("Configure dead zones"), (configdead), 'z');
dialog::display(); dialog::display();
}
#endif
else if(sc == 0) {
dialog::init(SHMUPTITLE); keyhandler = [this] (int sym, int uni) {
dialog::handleNavigation(sym, uni);
dialog::addItem(XLAT(
vid.scfg.players == 2 ? "two players" :
vid.scfg.players == 3 ? "three players" :
vid.scfg.players == 4 ? "four players" :
vid.scfg.players == 5 ? "five players" :
vid.scfg.players == 6 ? "six players" :
vid.scfg.players == 7 ? "seven players" :
"one player"), 'n');
dialog::addItem(XLAT(shmupcfg ? "shoot'em up mode" : "turn-based mode"), 's');
dialog::addItem(XLAT(shmup::on == shmupcfg && players == vid.scfg.players ?
"continue playing"
: "start a new game"), '0');
if(shmupcfg || multi::alwaysuse || vid.scfg.players > 1)
dialog::addItem(XLAT("configure player 1") + dsc(0), '1');
else
dialog::addBreak(100);
if(vid.scfg.players > 1)
dialog::addItem(XLAT("configure player 2") + dsc(1), '2');
else if(vid.scfg.players == 1 && !shmupcfg)
dialog::addSelItem(XLAT("input"), XLAT(multi::alwaysuse ? "config" : "default"), 'a');
else
dialog::addBreak(100);
if(vid.scfg.players > 2)
dialog::addItem(XLAT("configure player 3") + dsc(2), '3');
#if CAP_SDLJOY
else if(vid.scfg.players == 1 && !shmupcfg && !shmupcfg && !multi::alwaysuse)
dialog::addItem(XLAT("old style joystick configuration"), 'b');
#endif
else dialog::addBreak(100);
if(vid.scfg.players > 3)
dialog::addItem(XLAT("configure player 4") + dsc(3), '4');
else dialog::addBreak(100);
if(vid.scfg.players > 4)
dialog::addItem(XLAT("configure player 5") + dsc(4), '5');
else dialog::addBreak(100);
if(vid.scfg.players > 5)
dialog::addItem(XLAT("configure player 6") + dsc(5), '6');
else dialog::addBreak(100);
if(vid.scfg.players > 6)
dialog::addItem(XLAT("configure player 7") + dsc(6), '7');
else dialog::addBreak(100);
if(shmupcfg || multi::alwaysuse || vid.scfg.players > 1)
dialog::addItem(XLAT("configure panning and general keys"), 'p');
else dialog::addBreak(100);
#if CAP_SDLJOY
if(numsticks > 0) {
if(shmupcfg || multi::alwaysuse || vid.scfg.players > 1)
dialog::addItem(XLAT("configure joystick axes"), 'j');
else dialog::addBreak(100);
}
#endif
if(multi::players > 1)
dialog::addItem(XLAT("reset per-player statistics"), 'r');
else dialog::addBreak(100);
dialog::addBreak(50);
#if CAP_CONFIG
dialog::addItem(XLAT("save the configuration"), 'c');
#endif
dialog::addHelp();
dialog::addBack();
dialog::display();
}
if(sc >= 1 && sc <= MAXPLAYER + 1) {
dialog::init(
XLAT(sc == 1 ? "configure player 1" :
sc == 2 ? "configure player 2" :
sc == 3 ? "configure panning" :
sc == 4 ? "configure player 3" :
sc == 5 ? "configure player 4" :
sc == 6 ? "configure player 5" :
sc == 7 ? "configure player 6" :
sc == 8 ? "configure player 7" : ""
));
getcstat = ' ';
for(int i=0; i<shmupnumkeys; i++) if(shmupcmdtable[i][0])
dialog::addSelItem(XLAT(shmupcmdtable[i]), listkeys(16*sc+i),
vid.scfg.setwhat ? (vid.scfg.setwhat>1 && i == (vid.scfg.setwhat&15) ? '?' : 0) : 'a'+i);
else dialog::addBreak(100);
if(vid.scfg.setwhat == 1)
dialog::addItem(XLAT("press a key to unassign"), 0);
else if(vid.scfg.setwhat)
dialog::addItem(XLAT("press a key for '%1'", XLAT(shmupcmdtable[vid.scfg.setwhat&15])), 0);
else
dialog::addItem(XLAT("unassign a key"), 'z');
dialog::display();
}
keyhandler = handleConfig;
#endif
}
void handleConfig(int sym, int uni) {
#if CAP_SDL
if(!vid.scfg.setwhat) dialog::handleNavigation(sym, uni);
int sc = vid.scfg.subconfig;
if(sc == 0) {
if(uni == '1') vid.scfg.subconfig = 1;
else if(uni == '2') vid.scfg.subconfig = 2;
else if(uni == 'p') vid.scfg.subconfig = 3;
else if(uni == '3') vid.scfg.subconfig = 4;
else if(uni == '4') vid.scfg.subconfig = 5;
else if(uni == '5') vid.scfg.subconfig = 6;
else if(uni == '6') vid.scfg.subconfig = 7;
else if(uni == '7') vid.scfg.subconfig = 8;
#if CAP_SDLJOY
else if(uni == 'j') vid.scfg.subconfig = SCJOY;
#endif
else if(uni == 'a') multi::alwaysuse = !multi::alwaysuse;
#if CAP_SDLJOY
else if(uni == 'b') pushScreen(showJoyConfig);
#endif
else if(uni == 'r')
for(int i=0; i<MAXPLAYER; i++)
kills[i] = deaths[i] = treasures[i] = 0;
else if(uni == 's' || uni == 't')
shmupcfg = !shmupcfg;
#if CAP_CONFIG
else if(uni == 'c')
hr::saveConfig();
#endif
else if(uni == 'n' || uni == 'N') {
vid.scfg.players += shiftmul > 0 ? 1 : -1;
vid.scfg.players %= MAXPLAYER;
if(vid.scfg.players <= 0) vid.scfg.players += MAXPLAYER;
}
else if(sym == SDLK_F1 || uni == '?' || uni == 'h') {
gotoHelp("");
help =
XLAT(
"Shmup (shoot'em up) mode: You can play a hyperbolic shoot'em up game. The game is based "
"on the usual turn-based grid-based HyperRogue, but there are some changes. You fight by "
"throwing knives, and you have three extra lives. There are no allies, so all Orbs "
"related to allies give you extra lives instead (up to 5). Some other rules have been "
"adapted too.\n\n");
help += XLAT(
"Multiplayer: Play cooperatively (locally); treasures, kills, and deaths are calculated "
"for each player too, for more competitive play. Orbs and treasures are shared, orbs drain "
"faster, knives recharge slower, and player characters are not allowed to separate.\n\n");
help += XLAT(
"Turn-based multiplayer: Turns are executed in parallel. A player can leave the game "
"by pressing a designated key (useful when about to get killed or lost). The following "
"Orbs work to bring such players back: ");
help += XLATN(iinf[itOrbLife].name); help += ", ";
help += XLATN(iinf[itOrbFriend].name); help += ", ";
help += XLATN(iinf[itOrbUndeath].name); help += ", ";
help += XLATN(iinf[itOrbTeleport].name); help += ", ";
help += XLATN(iinf[itOrbSafety].name); help += "\n\n";
help += XLAT("This menu can be also used to configure keys.\n\n");
}
else if(doexiton(sym, uni)) {
popScreen();
if(shmup::on != shmupcfg) { restart_game(rg::shmup); resetScores(); }
else if(vid.scfg.players != players) { restart_game(); resetScores(); }
}
}
else if(sc == SCJOY) {
if(sym) { if(sym) {
char xuni = uni | 96; char xuni = uni | 96;
if(xuni >= 'a' && xuni < 'a' + numaxeconfigs) { if(xuni >= 'a' && xuni < 'a' + numaxeconfigs) {
@ -434,24 +331,178 @@ help += XLAT("This menu can be also used to configure keys.\n\n");
else if(xuni == 'z') else if(xuni == 'z')
configdead = !configdead; configdead = !configdead;
else if(doexiton(sym, uni)) else if(doexiton(sym, uni))
vid.scfg.subconfig = 0; popScreen();
}
}
else {
if(sym) {
if(vid.scfg.setwhat) {
vid.scfg.keyaction[sym] = vid.scfg.setwhat;
vid.scfg.setwhat = 0;
}
else if(uni >= 'a' && uni < 'a' + shmupnumkeys && shmupcmdtable[uni-'a'][0])
vid.scfg.setwhat = 16*sc+uni - 'a';
else if(uni == 'z')
vid.scfg.setwhat = 1;
else if(uni || sym == SDLK_F10)
vid.scfg.subconfig = 0;
} }
};
} }
};
#endif #endif
struct shmup_configurer {
bool shmupcfg;
int playercfg;
shmup_configurer() { shmupcfg = shmup::on; players = multi::players; }
void operator()() {
#if CAP_SDL
cmode = sm::SHMUPCONFIG;
dialog::init(SHMUPTITLE);
dialog::addItem(player_count_name(playercfg), 'n');
dialog::addItem(XLAT(shmupcfg ? "shoot'em up mode" : "turn-based mode"), 's');
dialog::addItem(XLAT(shmup::on == shmupcfg && players == playercfg ?
"continue playing"
: "start a new game"), '0');
if(shmupcfg || multi::alwaysuse || playercfg > 1)
dialog::addItem(XLAT("configure player 1") + dsc(0), '1');
else
dialog::addBreak(100);
if(playercfg > 1)
dialog::addItem(XLAT("configure player 2") + dsc(1), '2');
else if(playercfg == 1 && !shmupcfg)
dialog::addSelItem(XLAT("input"), XLAT(multi::alwaysuse ? "config" : "default"), 'a');
else
dialog::addBreak(100);
if(playercfg > 2)
dialog::addItem(XLAT("configure player 3") + dsc(2), '3');
#if CAP_SDLJOY
else if(playercfg == 1 && !shmupcfg && !shmupcfg && !multi::alwaysuse)
dialog::addItem(XLAT("old style joystick configuration"), 'b');
#endif
else dialog::addBreak(100);
if(playercfg > 3)
dialog::addItem(XLAT("configure player 4") + dsc(3), '4');
else dialog::addBreak(100);
if(playercfg > 4)
dialog::addItem(XLAT("configure player 5") + dsc(4), '5');
else dialog::addBreak(100);
if(playercfg > 5)
dialog::addItem(XLAT("configure player 6") + dsc(5), '6');
else dialog::addBreak(100);
if(playercfg > 6)
dialog::addItem(XLAT("configure player 7") + dsc(6), '7');
else dialog::addBreak(100);
if(shmupcfg || multi::alwaysuse || playercfg > 1)
dialog::addItem(XLAT("configure panning and general keys"), 'p');
else dialog::addBreak(100);
#if CAP_SDLJOY
if(numsticks > 0) {
if(shmupcfg || multi::alwaysuse || playercfg > 1)
dialog::addItem(XLAT("configure joystick axes"), 'j');
else dialog::addBreak(100);
}
#endif
if(multi::players > 1)
dialog::addItem(XLAT("reset per-player statistics"), 'r');
else dialog::addBreak(100);
dialog::addBreak(50);
#if CAP_CONFIG
dialog::addItem(XLAT("save the configuration"), 'c');
#endif
dialog::addHelp();
dialog::addBack();
dialog::display();
keyhandler = [this] (int sym, int uni) { return handleConfig(sym, uni); };
#endif
}
void handleConfig(int sym, int uni) {
auto& cmdlist = shmupcfg ? playercmds_shmup : playercmds_turn;
#if CAP_SDL
if(uni == '1') pushScreen(key_configurer(1, cmdlist));
else if(uni == '2') pushScreen(key_configurer(2, cmdlist));
else if(uni == 'p') pushScreen(key_configurer(3, pancmds));
else if(uni == '3') pushScreen(key_configurer(4, cmdlist));
else if(uni == '4') pushScreen(key_configurer(5, cmdlist));
else if(uni == '5') pushScreen(key_configurer(6, cmdlist));
else if(uni == '6') pushScreen(key_configurer(7, cmdlist));
else if(uni == '7') pushScreen(key_configurer(8, cmdlist));
#if CAP_SDLJOY
else if(uni == 'j') pushScreen(joy_configurer(playercfg));
#endif
else if(uni == 'a') multi::alwaysuse = !multi::alwaysuse;
#if CAP_SDLJOY
else if(uni == 'b') pushScreen(showJoyConfig);
#endif
else if(uni == 'r')
for(int i=0; i<MAXPLAYER; i++)
kills[i] = deaths[i] = treasures[i] = 0;
else if(uni == 's' || uni == 't')
shmupcfg = !shmupcfg;
#if CAP_CONFIG
else if(uni == 'c')
hr::saveConfig();
#endif
else if(uni == 'n' || uni == 'N') {
playercfg += shiftmul > 0 ? 1 : -1;
playercfg %= MAXPLAYER;
if(playercfg <= 0) playercfg += MAXPLAYER;
}
else if(sym == SDLK_F1 || uni == '?' || uni == 'h') {
gotoHelp("");
help = XLAT(
"Shmup (shoot'em up) mode: You can play a hyperbolic shoot'em up game. The game is based "
"on the usual turn-based grid-based HyperRogue, but there are some changes. You fight by "
"throwing knives, and you have three extra lives. There are no allies, so all Orbs "
"related to allies give you extra lives instead (up to 5). Some other rules have been "
"adapted too.\n\n");
help += XLAT(
"Multiplayer: Play cooperatively (locally); treasures, kills, and deaths are calculated "
"for each player too, for more competitive play. Orbs and treasures are shared, orbs drain "
"faster, knives recharge slower, and player characters are not allowed to separate.\n\n");
help += XLAT(
"Turn-based multiplayer: Turns are executed in parallel. A player can leave the game "
"by pressing a designated key (useful when about to get killed or lost). The following "
"Orbs work to bring such players back: ");
help += XLATN(iinf[itOrbLife].name); help += ", ";
help += XLATN(iinf[itOrbFriend].name); help += ", ";
help += XLATN(iinf[itOrbUndeath].name); help += ", ";
help += XLATN(iinf[itOrbTeleport].name); help += ", ";
help += XLATN(iinf[itOrbSafety].name); help += "\n\n";
help += XLAT("This menu can be also used to configure keys.\n\n");
}
else if(doexiton(sym, uni)) {
popScreen();
if(shmup::on != shmupcfg) {
stop_game();
switch_game_mode(rg::shmup);
resetScores();
}
if(playercfg != players) {
stop_game();
players = playercfg;
resetScores();
}
start_game();
}
#endif
}
};
void configure() {
pushScreen(shmup_configurer());
} }
#define NUMACT 128 #define NUMACT 128
@ -479,7 +530,6 @@ bool notremapped(int sym) {
} }
void initConfig() { void initConfig() {
vid.scfg.players = 1;
char* t = vid.scfg.keyaction; char* t = vid.scfg.keyaction;
@ -577,7 +627,7 @@ void initConfig() {
multi::scs[5].uicolor = 0x00C0C0FF; multi::scs[5].uicolor = 0x00C0C0FF;
multi::scs[6].uicolor = 0xC0C0C0FF; multi::scs[6].uicolor = 0xC0C0C0FF;
addsaver(vid.scfg.players, "mode-number of players"); addsaver(multi::players, "mode-number of players");
addsaver(alwaysuse, "use configured keys"); addsaver(alwaysuse, "use configured keys");
// unfortunately we cannot use key names here because SDL is not yet initialized // unfortunately we cannot use key names here because SDL is not yet initialized
for(int i=0; i<512; i++) for(int i=0; i<512; i++)
@ -606,9 +656,9 @@ void scanchar(FILE *f, char& c) {
void loadConfig(FILE *f) { void loadConfig(FILE *f) {
int xvernum; int xvernum;
int err = fscanf(f, "%d %d", &xvernum, &vid.scfg.players); int err = fscanf(f, "%d %d", &xvernum, &multi::players);
if(vid.scfg.players < 1 || vid.scfg.players > MAXPLAYER) if(multi::players < 1 || multi::players > MAXPLAYER)
vid.scfg.players = 1; multi::players = 1;
if(err != 2) return; if(err != 2) return;
if(xvernum >= 8990) { int b=alwaysuse; err=fscanf(f, " %d", &b); alwaysuse = b; } if(xvernum >= 8990) { int b=alwaysuse; err=fscanf(f, " %d", &b); alwaysuse = b; }
for(int i=0; i<512; i++) scanchar(f, vid.scfg.keyaction[i]); for(int i=0; i<512; i++) scanchar(f, vid.scfg.keyaction[i]);

View File

@ -97,7 +97,6 @@ void initgame() {
DEBB(DF_INIT, (debugfile,"initGame\n")); DEBB(DF_INIT, (debugfile,"initGame\n"));
callhooks(hooks_initgame); callhooks(hooks_initgame);
if(!safety) multi::players = vid.scfg.players;
if(multi::players < 1 || multi::players > MAXPLAYER) if(multi::players < 1 || multi::players > MAXPLAYER)
multi::players = 1; multi::players = 1;
multi::whereto[0].d = MD_UNDECIDED; multi::whereto[0].d = MD_UNDECIDED;