racing:: track selection; can be now set as a special game mode

This commit is contained in:
Zeno Rogue 2018-11-24 23:52:13 +01:00
parent 6dd14a310f
commit 29c0b899dc
5 changed files with 99 additions and 33 deletions

View File

@ -676,6 +676,7 @@ namespace rg {
static const char princess = 'p'; static const char princess = 'p';
static const char daily = 'd'; static const char daily = 'd';
static const char daily_off = 'D'; static const char daily_off = 'D';
static const char racing = 'R';
// wrongmode only -- marks 'global' achievements not related to the current mode // wrongmode only -- marks 'global' achievements not related to the current mode
static const char global = 'x'; static const char global = 'x';
@ -4680,7 +4681,7 @@ ld sintick(int period, ld phase = 0);
namespace racing { namespace racing {
extern bool on, player_relative, track_ready; extern bool on, player_relative, track_ready;
void generate_track(); void generate_track();
void show(); void configure_race();
void prepare_subscreens(); void prepare_subscreens();
extern vector<cell*> track; extern vector<cell*> track;
extern int current_player; extern int current_player;

View File

@ -494,6 +494,9 @@ void showChangeMode() {
dialog::addBoolItem(XLAT("Yendor Challenge"), (yendor::on), 'y'); dialog::addBoolItem(XLAT("Yendor Challenge"), (yendor::on), 'y');
dialog::addBoolItem(XLAT("%1 Challenge", moPrincess), (princess::challenge), 'P'); dialog::addBoolItem(XLAT("%1 Challenge", moPrincess), (princess::challenge), 'P');
dialog::addBoolItem(XLAT("random pattern mode"), (randomPatternsMode), 'r'); dialog::addBoolItem(XLAT("random pattern mode"), (randomPatternsMode), 'r');
#if CAP_RACING
dialog::addBoolItem(XLAT("racing mode"), racing::on, 'R');
#endif
#if CAP_DAILY #if CAP_DAILY
dialog::addBoolItem(XLAT("Strange Challenge"), daily::on, 'z'); dialog::addBoolItem(XLAT("Strange Challenge"), daily::on, 'z');
#endif #endif
@ -539,6 +542,10 @@ void showChangeMode() {
} }
else if(xuni == 'p') else if(xuni == 'p')
pushScreen(peace::showMenu); pushScreen(peace::showMenu);
#if CAP_RACING
else if(xuni == 'R')
racing::configure_race();
#endif
else if(xuni == 'i') dialog::do_if_confirmed([] { else if(xuni == 'i') dialog::do_if_confirmed([] {
restart_game(rg::inv); restart_game(rg::inv);
}); });

View File

@ -299,6 +299,7 @@ void showMission() {
tour::on ? (canmove ? XLAT("Tutorial") : XLAT("GAME OVER")) : tour::on ? (canmove ? XLAT("Tutorial") : XLAT("GAME OVER")) :
#endif #endif
(cheater && !autocheat)? XLAT("It is a shame to cheat!") : (cheater && !autocheat)? XLAT("It is a shame to cheat!") :
racing::on ? "racing mode" :
showoff ? XLAT("Showoff mode") : showoff ? XLAT("Showoff mode") :
(canmove && princess::challenge) ? XLAT("%1 Challenge", moPrincess) : (canmove && princess::challenge) ? XLAT("%1 Challenge", moPrincess) :
canmove ? XLAT("Quest status") : canmove ? XLAT("Quest status") :
@ -307,9 +308,9 @@ void showMission() {
); );
keyhandler = handleKeyQuit; keyhandler = handleKeyQuit;
if(!peace::on) if(!peace::on && !racing::on)
dialog::addInfo(XLAT("Your score: %1", its(gold()))); dialog::addInfo(XLAT("Your score: %1", its(gold())));
if(!peace::on) if(!peace::on && !racing::on)
dialog::addInfo(XLAT("Enemies killed: %1", its(tkills()))); dialog::addInfo(XLAT("Enemies killed: %1", its(tkills())));
#if CAP_TOUR #if CAP_TOUR
@ -326,6 +327,7 @@ void showMission() {
else if(tour::on) else if(tour::on)
; ;
#endif #endif
else if(racing::on) ;
else if(princess::challenge) else if(princess::challenge)
dialog::addInfo(XLAT("Follow the Mouse and escape with %the1!", moPrincess)); dialog::addInfo(XLAT("Follow the Mouse and escape with %the1!", moPrincess));
else if(gold() < R30) else if(gold() < R30)
@ -354,6 +356,7 @@ void showMission() {
else if(tour::on) ; else if(tour::on) ;
#endif #endif
else if(peace::on) ; else if(peace::on) ;
else if(racing::on) ;
else if(tkills() < R100) else if(tkills() < R100)
dialog::addInfo(XLAT("Defeat %1 enemies to access the Graveyard", its(R100))); dialog::addInfo(XLAT("Defeat %1 enemies to access the Graveyard", its(R100)));
else if(kills[moVizier] == 0 && (items[itFernFlower] < U5 || items[itGold] < U5)) else if(kills[moVizier] == 0 && (items[itFernFlower] < U5 || items[itGold] < U5))
@ -375,7 +378,7 @@ void showMission() {
if(cheater && !autocheat) { if(cheater && !autocheat) {
dialog::addInfo(XLAT("you have cheated %1 times", its(cheater)), 0xFF2020); dialog::addInfo(XLAT("you have cheated %1 times", its(cheater)), 0xFF2020);
} }
else { else if(!racing::on) {
dialog::addInfo(timeline(), dialog::dialogcolor); dialog::addInfo(timeline(), dialog::dialogcolor);
} }
@ -439,6 +442,8 @@ void showMission() {
dialog::addItem(XLAT("restart"), SDLK_F5); dialog::addItem(XLAT("restart"), SDLK_F5);
if(inv::on && items[itInventory]) if(inv::on && items[itInventory])
dialog::addItem(XLAT("inventory"), 'i'); dialog::addItem(XLAT("inventory"), 'i');
if(racing::on)
dialog::addItem(XLAT("racing menu"), 'o');
#if ISMOBILE==0 #if ISMOBILE==0
dialog::addItem(XLAT(quitsaves() ? "save" : "quit"), SDLK_F10); dialog::addItem(XLAT(quitsaves() ? "save" : "quit"), SDLK_F10);
#endif #endif

View File

@ -13,10 +13,13 @@ bool on;
bool player_relative = false; bool player_relative = false;
bool track_ready; bool track_ready;
static const int LENGTH = 50; static const int LENGTH = 250;
static const int TWIDTH = 6; static const int TWIDTH = 6;
static const int DROP = 1; static const int DROP = 1;
int ghosts_to_show = 5;
int ghosts_to_save = 10;
struct race_cellinfo { struct race_cellinfo {
cell *c; cell *c;
int from_track; int from_track;
@ -95,8 +98,9 @@ void hwrite(hstream& hs, const ghost& gh) {
} }
bool read_ghosts(string seed, int mcode) { bool read_ghosts(string seed, int mcode) {
fhstream f; string fname = ghost_filename(seed, mcode);
f.f = fopen(ghost_filename(seed, mcode).c_str(), "rb"); println(hlog, "trying to read ghosts from: ", fname);
fhstream f(fname, "rb");
if(!f.f) return false; if(!f.f) return false;
f.get<int> (); f.get<int> ();
hread(f, race_ghosts[{seed, mcode}]); hread(f, race_ghosts[{seed, mcode}]);
@ -446,9 +450,7 @@ int readArgs() {
else if(argis("-racing")) { else if(argis("-racing")) {
PHASEFROM(2); PHASEFROM(2);
stop_game(); stop_game();
shmup::on = true; switch_game_mode(rg::racing);
racing::on = true;
timerghost = false;
} }
else return 1; else return 1;
return 0; return 0;
@ -580,10 +582,7 @@ void track_chooser(string new_track) {
dialog::addSelItem(XLAT1(linf[l].name), s, let++); dialog::addSelItem(XLAT1(linf[l].name), s, let++);
dialog::add_action([l, new_track] () { dialog::add_action([l, new_track] () {
stop_game(); stop_game();
specialland = l; if(!racing::on) switch_game_mode(rg::racing);
racing::on = true;
shmup::on = true;
track_code = new_track;
start_game(); start_game();
popScreenAll(); popScreenAll();
}); });
@ -626,6 +625,27 @@ struct race_configurer {
dialog::init(XLAT("Racing")); dialog::init(XLAT("Racing"));
dialog::addSelItem("track name", editing_track ? dialog::view_edited_string() : new_track, '/');
dialog::add_action([this] () {
editing_track = !editing_track;
if(editing_track) dialog::start_editing(new_track);
});
dialog::addItem("play the official track", 'o');
dialog::add_action([this] () { new_track = "OFFICIAL"; });
dialog::addItem("play a random track", 'r');
dialog::add_action([this] () { new_track = random_track_name(); });
dialog::addItem(XLAT("select the track and start!"), 's');
dialog::add_action([this] () {
if(race_ghosts[{new_track, modecode()}].empty())
read_ghosts(new_track, modecode());
else
println(hlog, "known ghosts: ", isize(race_ghosts[{new_track, modecode()}]));
pushScreen([this] () { track_chooser(new_track); });
});
dialog::addBreak(100);
dialog::addBoolItem(XLAT("player relative"), player_relative, 'p'); dialog::addBoolItem(XLAT("player relative"), player_relative, 'p');
dialog::add_action([] () { dialog::add_action([] () {
player_relative = !player_relative; player_relative = !player_relative;
@ -674,22 +694,23 @@ struct race_configurer {
} }
else dialog::addBreak(100); else dialog::addBreak(100);
dialog::addSelItem("track name", editing_track ? dialog::view_edited_string() : new_track, '/'); dialog::addBreak(100);
dialog::add_action([this] () {
editing_track = !editing_track; dialog::addSelItem(XLAT("best scores to show as ghosts"), its(ghosts_to_show), 'g');
if(editing_track) dialog::start_editing(new_track); dialog::add_action([]() { dialog::editNumber(ghosts_to_show, 0, 100, 1, 5, "best scores to show as ghosts", ""); });
});
dialog::addItem("play the official track", 'o'); dialog::addSelItem(XLAT("best scores to save"), its(ghosts_to_save), 'b');
dialog::add_action([this] () { new_track = "OFFICIAL"; }); dialog::add_action([]() { dialog::editNumber(ghosts_to_save, 0, 100, 1, 10, "best scores to save", ""); });
dialog::addItem("play a random track", 'r');
dialog::add_action([this] () { new_track = random_track_name(); });
if(racing::on) {
dialog::addItem(XLAT("select the track and start!"), 's'); dialog::addItem(XLAT("disable the racing mode"), 'x');
dialog::add_action([this] () { dialog::add_action([] () {
if(race_ghosts[{new_track, modecode()}].empty()) stop_game();
read_ghosts(new_track, modecode()); switch_game_mode(rg::racing);
pushScreen([this] () { track_chooser(new_track); }); start_game();
}); });
}
dialog::addBack(); dialog::addBack();
dialog::display(); dialog::display();
@ -706,9 +727,13 @@ struct race_configurer {
} }
}; };
void configure_race() {
pushScreen(race_configurer());
}
auto hooks1 = auto hooks1 =
addHook(hooks_o_key, 90, [] { addHook(hooks_o_key, 90, [] {
if(racing::on) return named_dialog("race mode", race_configurer()); if(racing::on) return named_dialog(XLAT("racing menu"), race_configurer());
else return named_functionality(); else return named_functionality();
}); });
@ -745,12 +770,19 @@ void race_won() {
part(*x, 0) >>= 2; part(*x, 0) >>= 2;
} }
race_ghosts[{track_code, modecode()}] [specialland].emplace_back(ghost{gcs, ticks - race_start_tick, time(NULL), current_history[current_player]}); auto &subtrack = race_ghosts[{track_code, modecode()}] [specialland];
write_ghosts(track_code, modecode());
subtrack.emplace_back(ghost{gcs, ticks - race_start_tick, time(NULL), current_history[current_player]});
sort(subtrack.begin(), subtrack.end(), [] (const ghost &g1, const ghost &g2) { return g1.result > g2.result; });
if(isize(subtrack) > ghosts_to_save && ghosts_to_save > 0)
subtrack.resize(ghosts_to_save);
if(ghosts_to_save > 0)
write_ghosts(track_code, modecode());
} }
} }
void markers() { void markers() {
if(!racing::on) return;
if(racing::player_relative) { if(racing::player_relative) {
using namespace racing; using namespace racing;
cell *goal = NULL; cell *goal = NULL;
@ -760,7 +792,10 @@ void markers() {
queuestr(H, vid.fsize, its(celldistance(cwt.at, track.back())), 0x10101 * int(128 - 100 * sintick(150))); queuestr(H, vid.fsize, its(celldistance(cwt.at, track.back())), 0x10101 * int(128 - 100 * sintick(150)));
addauraspecial(H, 0x10100, 0); addauraspecial(H, 0x10100, 0);
} }
int ghosts_left = ghosts_to_show;
for(auto& ghost: race_ghosts[{track_code, modecode()}][specialland]) { for(auto& ghost: race_ghosts[{track_code, modecode()}][specialland]) {
if(!ghosts_left) break;
ghosts_left--;
auto p = std::find_if(ghost.history.begin(), ghost.history.end(), [] (const ghostmoment gm) { return gm.step > ticks - race_start_tick;} ); auto p = std::find_if(ghost.history.begin(), ghost.history.end(), [] (const ghostmoment gm) { return gm.step > ticks - race_start_tick;} );
if(p == ghost.history.end()) p--; if(p == ghost.history.end()) p--;
cell *w = rti[p->where_id].c; cell *w = rti[p->where_id].c;

View File

@ -1192,6 +1192,7 @@ void switch_game_mode(char switchWhat) {
peace::on = !peace::on; peace::on = !peace::on;
tactic::on = yendor::on = princess::challenge = tactic::on = yendor::on = princess::challenge =
randomPatternsMode = inv::on = false; randomPatternsMode = inv::on = false;
racing::on = false;
break; break;
case rg::inv: case rg::inv:
@ -1199,6 +1200,7 @@ void switch_game_mode(char switchWhat) {
if(tactic::on) firstland = laIce; if(tactic::on) firstland = laIce;
tactic::on = yendor::on = princess::challenge = tactic::on = yendor::on = princess::challenge =
randomPatternsMode = peace::on = false; randomPatternsMode = peace::on = false;
racing::on = false;
break; break;
case rg::chaos: case rg::chaos:
@ -1207,6 +1209,7 @@ void switch_game_mode(char switchWhat) {
need_reset_geometry = true; need_reset_geometry = true;
chaosmode = !chaosmode; chaosmode = !chaosmode;
if(bounded) set_geometry(gNormal); if(bounded) set_geometry(gNormal);
racing::on = false;
break; break;
#if CAP_TOUR #if CAP_TOUR
@ -1219,6 +1222,7 @@ void switch_game_mode(char switchWhat) {
shmup::on = false; shmup::on = false;
need_reset_geometry = true; need_reset_geometry = true;
tour::on = !tour::on; tour::on = !tour::on;
racing::on = false;
break; break;
#endif #endif
@ -1230,8 +1234,19 @@ void switch_game_mode(char switchWhat) {
princess::challenge = false; princess::challenge = false;
randomPatternsMode = false; randomPatternsMode = false;
chaosmode = false; chaosmode = false;
racing::on = false;
if(!yendor::on) firstland = laIce; if(!yendor::on) firstland = laIce;
break; break;
case rg::racing:
racing::on = !racing::on;
shmup::on = racing::on;
peace::on = false;
tour::on = false;
inv::on = false;
chaosmode = false;
princess::challenge = false;
break;
case rg::tactic: case rg::tactic:
tactic::on = !tactic::on; tactic::on = !tactic::on;
@ -1240,6 +1255,7 @@ void switch_game_mode(char switchWhat) {
inv::on = false; inv::on = false;
randomPatternsMode = false; randomPatternsMode = false;
princess::challenge = false; princess::challenge = false;
racing::on = false;
chaosmode = false; chaosmode = false;
if(!tactic::on) firstland = laIce; if(!tactic::on) firstland = laIce;
break; break;
@ -1247,6 +1263,7 @@ void switch_game_mode(char switchWhat) {
case rg::shmup: case rg::shmup:
shmup::on = !shmup::on; shmup::on = !shmup::on;
princess::challenge = false; princess::challenge = false;
if(!shmup::on) racing::on = false;
break; break;
case rg::randpattern: case rg::randpattern:
@ -1266,6 +1283,7 @@ void switch_game_mode(char switchWhat) {
yendor::on = false; yendor::on = false;
chaosmode = false; chaosmode = false;
inv::on = false; inv::on = false;
racing::on = false;
break; break;
#if CAP_DAILY #if CAP_DAILY