casual mode

This commit is contained in:
Zeno Rogue 2021-05-27 12:57:12 +02:00
parent 7fc91b1eaf
commit b65e5f603f
8 changed files with 101 additions and 36 deletions

View File

@ -104,6 +104,7 @@ EX vector<string> 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 + "(?)";

View File

@ -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; }

View File

@ -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";

View File

@ -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) {

View File

@ -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');

View File

@ -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();

View File

@ -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<scores::boxid; i++) fprintf(f, " %d", scores::save.box[i]);
scorebox = scores::save;
anticheat::save(f);
fprintf(f, "\n");
@ -1106,6 +1113,8 @@ EX void saveStats(bool emergency IS(false)) {
fclose(f);
}
bool tamper = false;
// load the save
EX void loadsave() {
if(autocheat) return;
@ -1117,10 +1126,9 @@ EX void loadsave() {
FILE *f = fopen(scorefile, "rt");
havesave = f;
if(!f) return;
scores::score sc;
bool ok = false;
bool tamper = false;
int coh = counthints();
auto& sc = scorebox;
while(!feof(f)) {
char buf[12000];
if(fgets(buf, 12000, f) == NULL) break;
@ -1215,40 +1223,45 @@ EX void loadsave() {
}
fclose(f);
if(ok && sc.box[65 + 4 + itOrbSafety - itOrbLightning]) {
anticheat::tampered = tamper;
if(ok && sc.box[65 + 4 + itOrbSafety - itOrbLightning])
load_last_save();
}
EX void load_last_save() {
auto& sc = scorebox;
anticheat::tampered = tamper;
// printf("box = %d (%d)\n", sc.box[65 + 4 + itOrbSafety - itOrbLightning], boxid);
// printf("boxid = %d\n", boxid);
using namespace scores;
for(int i=0; i<boxid; i++) save.box[i] = sc.box[i];
for(int i=boxid; i<MAXBOX; i++) save.box[i] = 0;
using namespace scores;
for(int i=0; i<boxid; i++) save.box[i] = sc.box[i];
for(int i=boxid; i<MAXBOX; i++) save.box[i] = 0;
// for(int i=160; i<200; i++) printf("%d: %d ", i, save.box[i]);
if(meaning.count(sc.box[MODECODE_BOX])) {
shstream ss;
ss.s = meaning[sc.box[MODECODE_BOX]];
ss.read(ss.vernum);
mapstream::load_geometry(ss);
}
loadBox();
// printf("boxid = %d\n", boxid);
if(items[itHolyGrail]) {
items[itHolyGrail]--;
camelot::knighted = newRoundTableRadius();
items[itHolyGrail]++;
}
else camelot::knighted = 0;
safety = true;
if(items[itSavedPrincess] < 0) items[itSavedPrincess] = 0;
addMessage(XLAT("Game loaded."));
showstartmenu = false;
// reset unsavable special modes just in case
peace::on = false;
randomPatternsMode = false;
yendor::on = false;
tour::on = false;
if(meaning.count(sc.box[MODECODE_BOX])) {
shstream ss;
ss.s = meaning[sc.box[MODECODE_BOX]];
ss.read(ss.vernum);
mapstream::load_geometry(ss);
}
loadBox();
// printf("boxid = %d\n", boxid);
if(items[itHolyGrail]) {
items[itHolyGrail]--;
camelot::knighted = newRoundTableRadius();
items[itHolyGrail]++;
}
else camelot::knighted = 0;
safety = true;
if(items[itSavedPrincess] < 0) items[itSavedPrincess] = 0;
addMessage(XLAT("Game loaded."));
showstartmenu = false;
// reset unsavable special modes just in case
peace::on = false;
randomPatternsMode = false;
yendor::on = false;
tour::on = false;
save_turns = turncount;
}
#endif
@ -1258,7 +1271,8 @@ EX void stop_game() {
DEBBI(DF_INIT, ("stop_game"));
achievement_final(true);
#if CAP_SAVE
saveStats();
if(!casual)
saveStats();
#endif
for(int i=0; i<ittypes; i++) items[i] = 0;
lastkills = 0; for(int i=0; i<motypes; i++) kills[i] = 0;
@ -1604,7 +1618,8 @@ EX void finishAll() {
achievement_final(!items[itOrbSafety]);
#if CAP_SAVE
saveStats();
if(!casual)
saveStats();
#endif
clearMemory();
#if !ISMOBILE

View File

@ -1085,6 +1085,9 @@ void save_mode_data(hstream& f) {
f.write<char>(peace::explore_other);
f.write<char>(multi::players);
f.write<char>(xcheat);
if(casual) {
f.write<char>(1);
}
}
EX modecode_t modecode(int mode) {