diff --git a/achievement.cpp b/achievement.cpp index 6cdd3c5e..5ca7bc0f 100644 --- a/achievement.cpp +++ b/achievement.cpp @@ -104,6 +104,7 @@ EX vector achievementsReceived; */ EX bool wrongMode(char flags) { if(cheater) return true; + if(casual) return true; if(flags == rg::global) return false; if(flags != rg::special_geometry) { @@ -214,6 +215,7 @@ EX void achievement_collection(eItem it) { EX void achievement_collection2(eItem it, int q) { if(cheater && !test_achievements) return; + if(casual && !test_achievements) return; if(randomPatternsMode) return; LATE( achievement_collection2(it, q); ) @@ -544,6 +546,7 @@ EX void achievement_collection2(eItem it, int q) { EX void achievement_count(const string& s, int current, int prev) { if(cheater && !test_achievements) return; + if(casual && !test_achievements) return; if(shmup::on) return; if(randomPatternsMode) return; LATE( achievement_count(s, current, prev); ) @@ -610,6 +613,7 @@ EX void achievement_score(int cat, int number) { if(offlineMode) return; #ifdef HAVE_ACHIEVEMENTS if(cheater) return; + if(casual) return; LATE( achievement_score(cat, number); ) if(cat == LB_HALLOWEEN) { if(geometry != gSphere && geometry != gElliptic) @@ -713,6 +717,7 @@ EX void achievement_final(bool really_final) { next_stat_tick = ticks + 600000; } if(cheater) return; + if(casual) return; #if CAP_TOUR if(tour::on) return; @@ -831,6 +836,7 @@ EX void achievement_victory(bool hyper) { if(offlineMode) return; #ifdef HAVE_ACHIEVEMENTS if(cheater) return; + if(casual) return; if(geometry) return; if(CHANGED_VARIATION) return; if(randomPatternsMode) return; @@ -921,6 +927,7 @@ EX string get_rich_presence_text() { if(randomPatternsMode) res += "random "; if(inv::on) res += "OSM "; if(multi::players > 1) res += "multi "; + if(casual) res += "casual "; if(cheater || among(cwt.at->land, laCanvas, laCA)) return res + "(?)"; diff --git a/checkmove.cpp b/checkmove.cpp index dc537da5..57e42b6a 100644 --- a/checkmove.cpp +++ b/checkmove.cpp @@ -17,6 +17,8 @@ namespace hr { EX bool hardcore = false; /** when did we switch to the hardcore mode */ EX int hardcoreAt; +/** are we in the casual mode */ +EX bool casual = false; EX bool pureHardcore() { return hardcore && hardcoreAt < PUREHARDCORE_LEVEL; } diff --git a/dialogs.cpp b/dialogs.cpp index acc02a13..4d13a481 100644 --- a/dialogs.cpp +++ b/dialogs.cpp @@ -164,6 +164,7 @@ EX namespace dialog { if(k == SDLK_ESCAPE) return "Esc"; if(k == SDLK_F5) return "F5"; if(k == SDLK_F10) return "F10"; + if(k == SDLK_F9) return "F9"; if(k == SDLK_F1) return "F1"; if(k == SDLK_HOME) return "Home"; if(k == SDLK_BACKSPACE) return "Backspace"; diff --git a/game.cpp b/game.cpp index 9d1865f0..662514eb 100644 --- a/game.cpp +++ b/game.cpp @@ -259,6 +259,11 @@ EX void teleportToLand(eLand l, bool make_it_safe) { EX void activateSafety(eLand l) { teleportToLand(l, true); + if(casual) { + saveStats(); + savecount++; + save_turns = turncount; + } } EX void placeGolem(cell *on, cell *moveto, eMonster m) { diff --git a/menus.cpp b/menus.cpp index 0a9c9168..d84df4f8 100644 --- a/menus.cpp +++ b/menus.cpp @@ -404,6 +404,23 @@ EX void switchHardcore() { if(pureHardcore()) popScreenAll(); } +EX void switch_casual() { + if(savecount > 0) { + dialog::push_confirm_dialog([] { + restart_game(); + casual = !casual; + }, XLAT("Switching casual allowed only before saving the game. Do you want to restart?")); + return; + } + else + casual = !casual; + if(casual) { + addMessage(XLAT("You are in the Casual mode! Achievements are disabled.")); + addMessage(XLAT("Collect an Orb of Safety to save a checkpoint.")); + } + popScreenAll(); + } + EX void showCreative() { cmode = sm::SIDE | sm::MAYDARK; gamescreen(3); @@ -531,6 +548,7 @@ EX void show_chaos() { else dialog::addInfo("not eligible for achievements"); if(cheater) dialog::addInfo("(but the cheat mode is on)"); + if(casual) dialog::addInfo("(but the casual mode is on)"); dialog::addBreak(100); dialog::addBack(); @@ -724,6 +742,9 @@ EX void showChangeMode() { dialog::addBoolItem(XLAT("multiplayer"), multi::players > 1, 'm'); dialog::add_action_push(multi::showConfigureMultiplayer); + dialog::addSelItem(XLAT("casual mode"), ONOFF(casual), 'C'); + dialog::add_action(switch_casual); + if(!shmup::on) { dialog::addSelItem(XLAT("hardcore mode"), hardcore && !pureHardcore() ? XLAT("PARTIAL") : ONOFF(hardcore), 'h'); diff --git a/quit.cpp b/quit.cpp index b24894d7..fb9cb76b 100644 --- a/quit.cpp +++ b/quit.cpp @@ -8,14 +8,18 @@ #include "hyper.h" namespace hr { -EX bool quitsaves() { return (items[itOrbSafety] && CAP_SAVE && !arcm::in()); } +EX bool quitsaves() { + if(casual) return false; + return (items[itOrbSafety] && CAP_SAVE && !arcm::in()); + } EX bool needConfirmationEvenIfSaved() { return canmove && (gold() >= 30 || tkills() >= 50) && !cheater; } EX bool needConfirmation() { - return needConfirmationEvenIfSaved() && !quitsaves(); + if(casual) return needConfirmationEvenIfSaved() && turncount > save_turns + 10; + else return needConfirmationEvenIfSaved() && quitsaves(); } EX int getgametime() { @@ -498,6 +502,8 @@ EX void showMission() { #if !ISMOBILE dialog::addItem(quitsaves() ? XLAT("save") : XLAT("quit"), SDLK_F10); #endif + if(casual && savecount) + dialog::addItem(XLAT("load (%1 turns passed)", its(turncount - save_turns)), SDLK_F9); #if CAP_ANDROIDSHARE dialog::addItem(XLAT("SHARE"), 's'-96); #endif @@ -534,6 +540,11 @@ EX void handleKeyQuit(int sym, int uni) { else if(uni == 'v') popScreenAll(), pushScreen(showMainMenu); else if(uni == 'l') popScreenAll(), pushScreen(showMessageLog), messagelogpos = isize(gamelog); else if(uni == 'z') hints[hinttoshow].action(); + else if(sym == SDLK_F9 && casual && savecount) { + stop_game(); + load_last_save(); + start_game(); + } else if(sym == SDLK_F3 || (sym == ' ' || sym == SDLK_HOME)) fullcenter(); else if(uni == 'o') get_o_key().second(); diff --git a/system.cpp b/system.cpp index 236a7eb9..ad8a6847 100644 --- a/system.cpp +++ b/system.cpp @@ -53,6 +53,7 @@ EX int asteroids_generated, asteroid_orbs_generated; EX time_t timerstart, savetime; EX bool timerstopped; EX int savecount; +EX int save_turns; EX bool doCross = false; EX bool gamegen_failure; @@ -419,7 +420,7 @@ EX namespace scores { /** \brief the amount of boxes reserved for each hr::score item */ #define MAXBOX 500 /** \brief currently used boxes in hr::score */ -#define POSSCORE 389 +#define POSSCORE 391 /** \brief a struct to keep local score from an earlier game */ struct score { /** \brief version used */ @@ -893,6 +894,9 @@ EX void applyBoxes() { applyBoxNum(saved_modecode, "modecode"); applyBoxBool(ineligible_starting_land, "ineligible_starting_land"); + + applyBoxNum(yasc_code, "YASC code"); + applyBoxBool(casual, "casual mode"); if(POSSCORE != boxid) printf("ERROR: %d boxes\n", boxid); if(isize(invorb)) { println(hlog, "ERROR: Orbs not taken into account"); exit(1); } @@ -981,6 +985,8 @@ EX void remove_emergency_save() { #endif } +scores::score scorebox; + EX void saveStats(bool emergency IS(false)) { DEBBI(DF_INIT, ("saveStats [", scorefile, "]")); @@ -1064,6 +1070,7 @@ EX void saveStats(bool emergency IS(false)) { scores::saveBox(); for(int i=0; i(peace::explore_other); f.write(multi::players); f.write(xcheat); + if(casual) { + f.write(1); + } } EX modecode_t modecode(int mode) {