mirror of
				https://github.com/zenorogue/hyperrogue.git
				synced 2025-10-31 05:52:59 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			797 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			797 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // HyperRogue menus
 | |
| // Copyright (C) 2011-2016 Zeno Rogue, see 'hyper.cpp' for details
 | |
| 
 | |
| void showOverview() {
 | |
|   DEBB(DF_GRAPH, (debugfile,"show overview\n"));
 | |
|   mouseovers = XLAT("world overview");
 | |
|   mouseovers += "       ";
 | |
|   mouseovers += XLAT(" kills: %1/%2", its(tkills()), its(killtypes()));
 | |
|   mouseovers += XLAT(" $$$: %1", its(gold()));
 | |
|   if(hellUnlocked()) {
 | |
|     int i1, i2; countHyperstoneQuest(i1, i2);
 | |
|     mouseovers += XLAT(" Hyperstone: %1/%2", its(i1), its(i2));
 | |
|     }
 | |
|   else
 | |
|     mouseovers += XLAT(" Hell: %1/9", its(orbsUnlocked()));
 | |
|   
 | |
|   int nl = LAND_OVER; eLand *landtab = land_over;
 | |
|   if(randomPatternsMode) { nl = RANDLANDS; landtab = randlands; }
 | |
|   
 | |
|   int vf = min((vid.yres-64) / nl, vid.xres/40);
 | |
|   
 | |
|   eLand curland = cwt.c->land;
 | |
|   if(curland == laPalace && princess::dist(cwt.c) < OUT_OF_PRISON)
 | |
|     curland = laPrincessQuest;
 | |
|   if(isElemental(curland)) curland = laElementalWall;
 | |
|   
 | |
|   getcstat = '0';
 | |
|   
 | |
|   for(int i=0; i<nl; i++) {
 | |
|     eLand l = landtab[i];
 | |
|     int xr = vid.xres / 64;
 | |
|     int i0 = 56 + i * vf;
 | |
|     int col;
 | |
|     if(landUnlocked(l)) col = linf[l].color; else col = 0x202020;
 | |
|     if(chaosmode && noChaos(l)) col = 0x200000;
 | |
|     if(l == curland)
 | |
|       displayfr(1, i0, 1, vf-4, "*", 0xFFFFFF, 0);
 | |
|     if(displayfr(xr*1, i0, 1, vf-4, XLAT1(linf[l].name), col, 0))
 | |
|       getcstat = 1000 + l;
 | |
|     eItem it = treasureType(l);
 | |
|     int lv = items[it] * landMultiplier(l);
 | |
|     if(lv >= 25) col = 0xFFD500;
 | |
|     else if(lv >= 10) col = 0x00D500;
 | |
|     else if(items[it]) col = 0xC0C0C0;
 | |
|     else col = 0x202020;
 | |
|     if(chaosmode && noChaos(l)) col = 0x200000;
 | |
|     if(displayfr(xr*24-48, i0, 1, vf-4, its(items[it]), col, 16))
 | |
|       getcstat = 2000+it;
 | |
|     if(!cheater)
 | |
|     if(displayfr(xr*24, i0, 1, vf-4, its(hiitems[modecode()][it]), col, 16))
 | |
|       getcstat = 2000+it;
 | |
|     if(items[it]) col = iinf[it].color; else col = 0x202020;
 | |
|     if(chaosmode && noChaos(l)) col = 0x200000;
 | |
|     if(displayfr(xr*24+32, i0, 1, vf-4, s0 + iinf[it].glyph, col, 16))
 | |
|       getcstat = 2000+it;
 | |
|     if(displayfr(xr*24+40, i0, 1, vf-4, XLAT1(iinf[it].name), col, 0))
 | |
|       getcstat = 2000+it;
 | |
|     eItem io = orbType(l);
 | |
|     if(io == itShard) {
 | |
|       if(items[it] >= 10) col = winf[waMirror].color; else col = 0x202020;
 | |
|       if(chaosmode && noChaos(l)) col = 0x200000;
 | |
|       if(displayfr(xr*46, i0, 1, vf-4, XLAT1(winf[waMirror].name), col, 0))
 | |
|         getcstat = 3000+waMirror;
 | |
|       if(getcstat == 3000+waMirror)
 | |
|         mouseovers = XLAT(
 | |
|           olrDescriptions[getOLR(io, cwt.c->land)], cwt.c->land, it, treasureType(cwt.c->land));
 | |
|       }
 | |
|     else if(io) {
 | |
|       if(lv >= 25) col = 0xFFD500;
 | |
|       else if(lv >= 10) col = 0xC0C0C0;
 | |
|       else col = 0x202020;
 | |
|       if(chaosmode && noChaos(l)) col = 0x200000;
 | |
|       if(displayfr(xr*46-32, i0, 1, vf-4, its(items[io]), col, 16))
 | |
|         getcstat = 2000+io;
 | |
|       if(lv >= 10) col = iinf[io].color; else col = 0x202020;
 | |
|       if(chaosmode && noChaos(l)) col = 0x200000;
 | |
|       if(displayfr(xr*46-8, i0, 1, vf-4, s0 + iinf[io].glyph, col, 16))
 | |
|         getcstat = 2000+io;
 | |
|       if(displayfr(xr*46, i0, 1, vf-4, XLAT1(iinf[io].name), col, 0))
 | |
|         getcstat = 2000+io;
 | |
|       if(getcstat == 2000+io)
 | |
|         mouseovers = XLAT(
 | |
|           olrDescriptions[getOLR(io, curland)], curland, it, treasureType(curland));
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
| void handleOverview(int uni) {
 | |
|   int umod = uni % 1000;
 | |
|   int udiv = uni / 1000;
 | |
|   if(udiv == 1 && umod < landtypes) {
 | |
|     if(cheater) {
 | |
|       eLand l = eLand(umod);
 | |
|       cheater++;
 | |
|       if(l == laPrincessQuest) {
 | |
|         if(kills[moVizier] == 0) kills[moVizier] = 1;
 | |
|         princess::forceMouse = true;
 | |
|         princess::gotoPrincess = true;
 | |
|         l = laPalace;
 | |
|         }
 | |
|       activateSafety(l);
 | |
|       cmode = emNormal;
 | |
|       canmove = true;
 | |
|       }
 | |
|     else {
 | |
|       lastmode = cmode;
 | |
|       cmode = emHelp; help = generateHelpForLand(eLand(umod));
 | |
|       }
 | |
|     }
 | |
|   else if(udiv == 2 && umod < ittypes) {
 | |
|     if(cheater) {
 | |
|       cheater++;
 | |
|       double shiftmul = 1.001;
 | |
|       if(anyshiftclick) shiftmul *= -1;
 | |
|       if(rightclick) shiftmul /= 10;
 | |
|       int ic = itemclass(eItem(umod));
 | |
|       if(ic == IC_TREASURE) items[umod] += int(10*shiftmul);
 | |
|       if(ic == IC_ORB) items[umod] += int(60*shiftmul);
 | |
|       if(umod == itGreenStone) items[umod] += int(100*shiftmul);
 | |
|       else if(ic == IC_OTHER) items[umod] += (shiftmul>0?1:-1);
 | |
|       if(items[umod] < 0) items[umod] = 0;
 | |
|       if(hardcore) canmove = true;
 | |
|       else checkmove();
 | |
|       }
 | |
|     else {
 | |
|       lastmode = cmode;
 | |
|       cmode = emHelp; help = generateHelpForItem(eItem(umod));
 | |
|       if(hardcore) canmove = true;
 | |
|       else checkmove();
 | |
|       }
 | |
|     }
 | |
|   else if(udiv == 3 && umod < walltypes) {
 | |
|     lastmode = cmode;
 | |
|     cmode = emHelp; help = generateHelpForWall(eWall(umod));
 | |
|     }
 | |
|   else if(uni) cmode = emNormal;
 | |
|   }
 | |
| 
 | |
| void showMainMenu() {
 | |
|   int y = vid.yres * .5 - vid.fsize * 10.5;
 | |
|   displayfr(vid.xres/2, y-vid.fsize * 2, 4, vid.fsize*2, 
 | |
|     XLAT("HyperRogue %1", VER), 0xC00000, 8
 | |
|     );
 | |
| 
 | |
|   displayButton(vid.xres/2, y + vid.fsize*2, ifMousing("b", "basic configuration"), 'b', 8, 2);
 | |
|   displayButton(vid.xres/2, y + vid.fsize*4, ifMousing("a", "advanced configuration"), 'a', 8, 2);
 | |
|                                              
 | |
| #ifndef ANDROID
 | |
|   displayButton(vid.xres/2, y + vid.fsize*6, ifMousing("t", "local highscores"), 't', 8, 2);
 | |
| #endif
 | |
|   displayButton(vid.xres/2, y + vid.fsize*8, ifMousing("h, F1", "help"), 'h', 8, 2);
 | |
|   if(cheater)
 | |
|      displayButton(vid.xres/2, y + vid.fsize*10, ifMousing("c", "cheats"), 'c', 8, 2);
 | |
| 
 | |
|   displayButton(vid.xres/2, y + vid.fsize*12, ifMousing("r, F5", "restart game"), 'r', 8, 2);
 | |
|   displayButton(vid.xres/2, y + vid.fsize*14, ifMousing("m", "special game modes"), 'm', 8, 2);
 | |
|   
 | |
|   string q;
 | |
|   
 | |
| #ifndef ANDROID
 | |
|   q = (items[itOrbSafety] && havesave) ? "save" : "quit"; 
 | |
| #ifdef IOS
 | |
|   q = q + " and visit the website";
 | |
| #else
 | |
|   q = q + " the game";
 | |
| #endif
 | |
|   displayButton(vid.xres/2, y + vid.fsize*17, ifMousing("q, F10", q), 'q', 8, 2);
 | |
| #endif
 | |
| 
 | |
|   if(canmove)
 | |
|     q = "review your quest";
 | |
|   else
 | |
|     q = "review the scene";
 | |
|   
 | |
|   displayButton(vid.xres/2, y + vid.fsize*20, ifMousing("ESC", q), SDLK_ESCAPE, 8, 2);
 | |
| 
 | |
|   displayButton(vid.xres/2, y + vid.fsize*22, ifMousing("o", "world overview"), 'o', 8, 2);
 | |
|   
 | |
|   if(!canmove) q = "game over screen";
 | |
|   else if(turncount > 0) q = "continue game";
 | |
|   else q = "play the game!";
 | |
|   
 | |
|   displayButton(vid.xres/2, y + vid.fsize*25, ifMousing(XLAT("other"), q), ' ', 8, 2);
 | |
|   }
 | |
| 
 | |
| void loadScores();
 | |
| 
 | |
| bool handleMenuKey(int sym, bool mdown) {
 | |
|   if(sym == SDLK_F1 || sym == 'h') {
 | |
|     lastmode = cmode;
 | |
|     cmode = emHelp;
 | |
|     }
 | |
|   else if(sym == 'c' && cheater)
 | |
|     cmode = emCheatMenu;
 | |
|   else if(sym == 'b') cmode = emVisual1;
 | |
|   else if(sym == 'a') cmode = emVisual2;
 | |
|   else if(sym == 'm') cmode = emChangeMode;
 | |
| #ifndef ANDROID
 | |
|   else if(sym == 't') loadScores();
 | |
| #endif
 | |
|   else if(sym == 'r' || sym == SDLK_F5) {
 | |
|     restartGame();
 | |
|     cmode = emNormal;
 | |
|     }
 | |
|   else if(sym == 'q' || sym == SDLK_F10) return true;
 | |
|   else if(sym == 'o') cmode = emOverview;
 | |
|   else if(sym == SDLK_ESCAPE) cmode = emQuit;
 | |
|   else if((sym != 0 && sym != SDLK_F12) || mdown) {
 | |
|     cmode = emNormal;
 | |
|     msgs.clear();
 | |
|     }
 | |
|   return false;
 | |
|   }
 | |
| 
 | |
| void showVisual1() {
 | |
| #ifndef MOBILE
 | |
|   displayStat(2, XLAT("video resolution"), its(vid.xres) + "x"+its(vid.yres), 'r');
 | |
|   displayStat(3, XLAT("fullscreen mode"), ONOFF(vid.full), 'f');
 | |
| #endif
 | |
|   displayStat(4, XLAT("animation speed"), fts(vid.aspeed), 'a');
 | |
|   displayStat(5, XLAT("dist from hyperboloid ctr"), fts(vid.alpha), 'p');
 | |
|   displayStat(6, XLAT("scale factor"), fts(vid.scale), 'z');
 | |
| 
 | |
|   const char *wdmodes[4] = {"ASCII", "black", "plain", "Escher"};
 | |
|   const char *mdmodes[4] = {"ASCII", "items only", "items and monsters", "high contrast"};
 | |
| 
 | |
|   displayStat(7, XLAT("draw the heptagons darker"), ONOFF(vid.darkhepta), '7');
 | |
|   
 | |
|   displayStat(8, XLAT("wall display mode"), 
 | |
|     XLAT(wdmodes[vid.wallmode]), 'w');
 | |
|   displayStat(9, XLAT("monster display mode"), 
 | |
|     XLAT(mdmodes[vid.monmode]), 'm');
 | |
| #ifndef MOBILE
 | |
|   const char *axmodes[4] = {"no axes", "auto", "light", "heavy"};
 | |
|   displayStat(10, XLAT("cross display mode"), 
 | |
|     XLAT(axmodes[vid.axes]), 'c');
 | |
| #endif
 | |
| #ifndef MOBILE
 | |
|   displayStat(11, XLAT("background music volume"), 
 | |
|     its(audiovolume), 'b');
 | |
| #endif
 | |
|   if(lang() != 0) {
 | |
|     string s = XLAT("TRANSLATIONWARNING");
 | |
|     if(s != "" && s != "TRANSLATIONWARNING") {
 | |
|       int dy = vid.fsize * 23 + vid.yres/4;
 | |
|       int dx = vid.xres/2;
 | |
|       displaystr(dx, dy, 0, vid.fsize, s, 0xFF0000, 8);
 | |
|       }
 | |
|     s = XLAT("TRANSLATIONWARNING2");
 | |
|     if(s != "" && s != "TRANSLATIONWARNING2") {
 | |
|       int dy = vid.fsize * 24 + vid.yres/4;
 | |
|       int dx = vid.xres/2;
 | |
|       displaystr(dx, dy, 0, vid.fsize, s, 0xFF0000, 8);
 | |
|       }
 | |
|       }
 | |
|   displayStat(13, XLAT("language"), XLAT("EN"), 'l');
 | |
|   displayStat(14, XLAT("player character"), 
 | |
|   numplayers() > 1 ? "" : csname(vid.cs), 'g');
 | |
|   }
 | |
| 
 | |
| void handleVisual1(int sym, int uni) {
 | |
|     
 | |
|   char xuni = uni | 96;
 | |
|   
 | |
|   if(uni >= 32 && uni < 64) xuni = uni;
 | |
|   
 | |
|   if(xuni == 'p') vid.alpha += shiftmul * 0.1;
 | |
|   if(xuni == 'z') vid.scale += shiftmul * 0.1;
 | |
|   
 | |
|   if(xuni == 'i') {
 | |
|     double d = exp(shiftmul/10);
 | |
|     vid.alpha *= d;
 | |
|     vid.scale *= d;
 | |
|     }
 | |
|   
 | |
|   if(xuni == 'a') vid.aspeed += shiftmul;
 | |
| #ifndef MOBILE
 | |
|   if(xuni == 'f') {
 | |
|     vid.full = !vid.full;
 | |
|     if(shiftmul > 0) {
 | |
|       vid.xres = vid.full ? vid.xscr : 9999;
 | |
|       vid.yres = vid.full ? vid.yscr : 9999;
 | |
|       extern bool setfsize;
 | |
|       setfsize = true;
 | |
|       }
 | |
|     setvideomode();
 | |
|     }
 | |
| #endif
 | |
|   
 | |
|   if(xuni == 'v' || sym == SDLK_F2) cmode = emNormal;
 | |
| #ifndef ANDROID
 | |
|   if(xuni == 's') saveConfig();
 | |
| #endif
 | |
|   
 | |
|   if(xuni == '7') { vid.darkhepta = !vid.darkhepta; }
 | |
|   if(xuni == 'w') { vid.wallmode += 60 + (shiftmul > 0 ? 1 : -1); vid.wallmode %= 4; }
 | |
|   if(xuni == 'm') { vid.monmode += 60 + (shiftmul > 0 ? 1 : -1); vid.monmode %= 4; }
 | |
|   if(xuni == 'c') { vid.axes += 60 + (shiftmul > 0 ? 1 : -1); vid.axes %= 4; }
 | |
| #ifndef MOBILE
 | |
|   if(xuni == 'b') {
 | |
|     audiovolume += int(10.5 * shiftmul);
 | |
|     if(audiovolume < 0) audiovolume = 0;
 | |
|     if(audiovolume > MIX_MAX_VOLUME) audiovolume = MIX_MAX_VOLUME;
 | |
|     Mix_VolumeMusic(audiovolume);
 | |
|     }
 | |
| #endif
 | |
|   
 | |
|   if(sym == SDLK_ESCAPE) cmode = emNormal;
 | |
|   
 | |
|   if(xuni == 'l') {
 | |
|     vid.language += (shiftmul>0?1:-1);
 | |
|     vid.language %= NUMLAN;
 | |
|     if(vid.language < 0) vid.language += NUMLAN;
 | |
|     }
 | |
|   
 | |
|   if(xuni == 'g') cmode = emCustomizeChar;
 | |
|   }
 | |
| 
 | |
| void showVisual2() {
 | |
|   #ifndef MOBILE
 | |
|   #ifdef GL
 | |
|   displayStat(2, XLAT("openGL & antialiasing mode"), vid.usingGL ? "OpenGL" : vid.usingAA ? "AA" : "OFF", 'o');
 | |
|   #endif
 | |
|   #endif
 | |
|   displayStat(3, XLAT("distance between eyes"), fts(vid.eye * 10), 'e');
 | |
|   #ifndef MOBILE
 | |
|   displayStat(4, XLAT("framerate limit"), its(vid.framelimit), 'f');
 | |
|   #endif
 | |
| 
 | |
| #ifndef MOBILE
 | |
|   displayStat(6, XLAT("joystick mode"), XLAT(autojoy ? "automatic" : "manual"), 'p');
 | |
|     
 | |
|   displayStat(7, XLAT("first joystick: movement threshold"), its(vid.joyvalue), 'a');
 | |
|   displayStat(8, XLAT("first joystick: execute movement threshold"), its(vid.joyvalue2), 'b');
 | |
|   displayStat(9, XLAT("second joystick: pan threshold"), its(vid.joypanthreshold), 'c');
 | |
|   displayStat(10, XLAT("second joystick: panning speed"), fts(vid.joypanspeed * 1000), 'd');
 | |
| #endif
 | |
| 
 | |
| #ifdef MOBILE
 | |
|   displayStat(6, XLAT("sight range"), its(sightrange), 'a');
 | |
|   extern int fontscale;
 | |
|   displayStat(7, XLAT("font scale"), its(fontscale), 'b');
 | |
| #endif
 | |
|   
 | |
|   displayStat(12, XLAT("message flash time"), its(vid.flashtime), 't');
 | |
| #ifndef MOBILE
 | |
|   displayStat(13, XLAT("targetting ranged Orbs Shift+click only"), ONOFF(vid.shifttarget), 'i');
 | |
| #endif
 | |
| #ifdef STEAM
 | |
|   displayStat(14, XLAT("send scores to Steam leaderboards"), ONOFF(vid.steamscore), 'l');
 | |
| #endif
 | |
|   }
 | |
| 
 | |
| void handleVisual2(int sym, int uni) {
 | |
|   char xuni = uni | 96;
 | |
|   
 | |
|   if(xuni == 'v' || sym == SDLK_F2 || sym == SDLK_ESCAPE) cmode = emNormal;
 | |
| #ifndef ANDROID
 | |
|   if(xuni == 's') saveConfig();
 | |
| #endif
 | |
|   
 | |
|   if(sym == SDLK_F1 || sym == 'h')
 | |
|     lastmode = cmode, cmode = emHelp;
 | |
| #ifdef GL
 | |
|   
 | |
| #ifndef MOBILE
 | |
|   if(xuni == 'o' && shiftmul > 0) {
 | |
|     vid.usingGL = !vid.usingGL;
 | |
|     if(vid.usingGL) addMessage(XLAT("openGL mode enabled"));
 | |
|     if(!vid.usingGL) addMessage(XLAT("openGL mode disabled"));
 | |
|     setvideomode();
 | |
|     }
 | |
| #endif
 | |
|   
 | |
|   if(xuni == 'o' && shiftmul < 0 && !vid.usingGL) {
 | |
|     vid.usingAA = !vid.usingAA;
 | |
|     if(vid.usingAA) addMessage(XLAT("anti-aliasing enabled"));
 | |
|     if(!vid.usingAA) addMessage(XLAT("anti-aliasing disabled"));
 | |
|     }
 | |
| #endif
 | |
|   
 | |
|   if(xuni == 'f') {
 | |
|     vid.framelimit += int(10.5 * shiftmul);
 | |
|     if(vid.framelimit < 5) vid.framelimit = 5;
 | |
|     }
 | |
|   
 | |
| #ifdef MOBILE
 | |
|   if(xuni == 'a') {
 | |
|     sightrange += shiftmul>0?1:-1;
 | |
|     if(sightrange < 4) sightrange = 4;
 | |
|     if(sightrange > 7) sightrange = 7;
 | |
|     }
 | |
| 
 | |
|   if(xuni =='b') {
 | |
|     extern int fontscale;
 | |
|     fontscale += int(shiftmul * 10);
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|   if(xuni == 'a') vid.joyvalue += int(shiftmul * 100);
 | |
|   if(xuni == 'b') vid.joyvalue2 += int(shiftmul * 100);
 | |
|   if(xuni == 'c') vid.joypanthreshold += int(shiftmul * 100);
 | |
|   if(xuni == 'd') vid.joypanspeed += shiftmul / 50000;
 | |
|   if(xuni == 'e') vid.eye += shiftmul * 0.01;
 | |
| #ifdef STEAM
 | |
|   if(xuni == 'l') vid.steamscore = !vid.steamscore;
 | |
| #endif
 | |
|   if(xuni == 't') vid.flashtime += shiftmul>0?1:-1;
 | |
|   
 | |
|   if(xuni == 'p') autojoy = !autojoy;
 | |
|   if(xuni == 'i') { vid.shifttarget = !vid.shifttarget; }
 | |
|   }
 | |
| 
 | |
| void showChangeMode() {
 | |
| #ifndef MOBILE
 | |
|   displayStat(2, XLAT("vector graphics editor"), "", 'g');
 | |
|   displayStat(3, XLAT("map editor"), ONOFF(false), 'm');
 | |
| #endif
 | |
|   displayStat(4, XLAT("cheat mode"), ONOFF(cheater), 'c');
 | |
|   
 | |
|   displayStat(6, XLAT("Euclidean mode"), ONOFF(euclid), 'e');
 | |
| #ifndef MOBILE
 | |
|   displayStat(7, 
 | |
|     XLAT("shoot'em up mode") + " " + XLAT("(includes co-op)"), 
 | |
|     ONOFF(shmup::on), 's');
 | |
| #endif
 | |
|   if(!shmup::on) displayStat(8, XLAT("hardcore mode"),
 | |
|     hardcore && !pureHardcore() ? XLAT("PARTIAL") : ONOFF(hardcore), 'h');
 | |
|   
 | |
|   displayStat(9, XLAT("%1 Challenge", moPrincess), ONOFF(princess::challenge), 'p');
 | |
|   displayStat(10, XLAT("random pattern mode"), ONOFF(randomPatternsMode), 'r');
 | |
|   displayStat(11, XLAT("Yendor Challenge"), ONOFF(yendor::on), 'y');
 | |
| #ifndef ANDROID
 | |
|   displayStat(12, XLAT("pure tactics mode"), ONOFF(tactic::on), 't');
 | |
| #endif
 | |
| #ifndef MOBILE
 | |
|   displayStat(13, XLAT("hypersian rug mode"), ONOFF(rug::rugged), 'u');
 | |
| #endif
 | |
|   displayStat(14, XLAT("heptagonal mode"), ONOFF(purehepta), '7');
 | |
|   displayStat(15, XLAT("Chaos mode"), ONOFF(chaosmode), 'C');
 | |
|   
 | |
| #ifndef MOBILE
 | |
|   displayStat(16, XLAT("paper model creator"), ONOFF(false), 'n');
 | |
| #endif
 | |
|   displayStat(17, XLAT("conformal/history mode"), ONOFF(conformal::on), 'a');
 | |
|   
 | |
|   displayStat(19, XLAT("return to the game"), "", 'v');
 | |
|   }
 | |
| 
 | |
| void handleChangeMode(int sym, int uni) {
 | |
|     
 | |
|   char xuni = uni;
 | |
|   
 | |
|   if((uni >= 'A' && uni <= 'Z') || (uni >= 1 && uni <= 26)) xuni |= 96;
 | |
|   
 | |
|   if(xuni == 'v' || sym == SDLK_F2 || sym == SDLK_ESCAPE) cmode = emNormal;
 | |
|   
 | |
|   if(uni == 'c') {
 | |
|     if(tactic::on && gold()) {
 | |
|       addMessage(XLAT("Not available in the pure tactics mode!"));
 | |
|       }
 | |
|     else if(!cheater) {
 | |
|       cheater++;
 | |
|       addMessage(XLAT("You activate your demonic powers!"));
 | |
| #ifndef MOBILE
 | |
|       addMessage(XLAT("Shift+F, Shift+O, Shift+T, Shift+L, Shift+U, etc."));
 | |
| #endif
 | |
|       cmode = emNormal;
 | |
|       }
 | |
|     else {
 | |
|       cmode = emNormal;
 | |
|       firstland = princess::challenge ? laPalace : laIce;
 | |
|       restartGame();
 | |
|       }
 | |
|     }
 | |
|   
 | |
| #ifndef MOBILE
 | |
|   if(xuni == 'g') {
 | |
|     cmode = emDraw;
 | |
|     mapeditor::drawcell = cwt.c;
 | |
|   }
 | |
| #endif
 | |
|   if(xuni == 'e') {
 | |
|     cmode = emPickEuclidean;
 | |
|   }
 | |
|   if(xuni == 't') {
 | |
|     cmode = emTactic;
 | |
|   }
 | |
| #ifndef MOBILE
 | |
|   if(xuni == 'u')
 | |
|     rug::select();
 | |
| #endif
 | |
|   if(xuni == 'y') {
 | |
|     if(yendor::everwon)
 | |
|         cmode = emYendor;
 | |
|     else {
 | |
|       cmode = emHelp;
 | |
|       help = yendor::chelp;
 | |
|       lastmode = emChangeMode;
 | |
|       }
 | |
|     }
 | |
|   if(xuni == '7')
 | |
|       restartGame('7');
 | |
|   if(uni == 'a')
 | |
|       cmode = emConformal;
 | |
|   if(uni == 'C') {
 | |
|     if(!chaosmode) {
 | |
|       cmode = emHelp;
 | |
|       help =
 | |
|       "In the Chaos mode, lands change very often, and "
 | |
|       "there are no walls between them. "
 | |
|       "Some lands are incompatible with this."
 | |
|       "\n\nYou need to reach Crossroads IV to unlock the Chaos mode.";
 | |
|       lastmode = chaosUnlocked ? emNormal : emChangeMode;
 | |
|       }
 | |
|     if(chaosUnlocked) restartGame('C');
 | |
|     }
 | |
|   if(xuni == 'p') {
 | |
|     if(!princess::everSaved)
 | |
|       addMessage(XLAT("Save %the1 first to unlock this challenge!", moPrincess));
 | |
|     else {
 | |
|       restartGame('p');
 | |
|       cmode = emNormal;
 | |
|       }
 | |
|     }
 | |
| #ifndef MOBILE
 | |
|   if(xuni == 'm') {
 | |
|     if(tactic::on) 
 | |
|       addMessage(XLAT("Not available in the pure tactics mode!"));
 | |
|     else {
 | |
|       cheater++;
 | |
|       cmode = emMapEditor;
 | |
|       lastexplore = turncount;
 | |
|       addMessage(XLAT("You activate your terraforming powers!"));
 | |
|       }
 | |
|     }
 | |
| #endif
 | |
|   if(xuni == 's')
 | |
|     cmode = emShmupConfig;
 | |
|   if(xuni == 'n')
 | |
|     cmode = emNetgen;
 | |
|   if(xuni == 'h' && !shmup::on) {
 | |
|     if(hardcore && !canmove) { }
 | |
|     else if(hardcore && canmove) { hardcore = false; }
 | |
|     else { hardcore = true; canmove = true; hardcoreAt = turncount; }
 | |
|     if(hardcore)
 | |
|         addMessage("One wrong move, and it is game over!");
 | |
|     else
 | |
|         addMessage("Not so hardcore?");
 | |
|     if(pureHardcore()) cmode = emNormal;
 | |
|     }
 | |
|   if(xuni == 'r') {
 | |
|     firstland = laIce;
 | |
|     restartGame('r');
 | |
|     cmode = emNormal;
 | |
|     }
 | |
|   }
 | |
| 
 | |
| void showCheatMenu() {
 | |
|   displayStat(0, XLAT("gain orb powers"), "", 'F');
 | |
|   displayStat(1, XLAT("summon treasure"), "", 'T');
 | |
|   displayStat(2, XLAT("summon dead orbs"), "", 'D');
 | |
|   displayStat(3, XLAT("lose all treasure"), "", 'J');
 | |
|   displayStat(4, XLAT("gain kills"), "", 'K');
 | |
|   displayStat(5, XLAT("Hyperstone Quest"), "", 'C');
 | |
|   displayStat(6, XLAT("summon orbs"), "", 'O');
 | |
|   displayStat(7, XLAT("gain Orb of Yendor"), "", 'Y');
 | |
|   displayStat(8, XLAT("summon lots of treasure"), "", 'T'-64);
 | |
|   displayStat(9, XLAT("Safety (quick save)"), "", 'S');
 | |
|   displayStat(10, XLAT("Select the land ---"), "", 'L');
 | |
|   displayStat(11, XLAT("--- and teleport there"), "", 'U');
 | |
|   displayStat(12, XLAT("rotate the character"), "", 'Z');
 | |
|   displayStat(13, XLAT("summon a Golem"), "", 'G');
 | |
|   displayStat(14, XLAT("summon Sandworm"), "", 'W');
 | |
|   displayStat(15, XLAT("summon Ivy"), "", 'I');
 | |
|   displayStat(16, XLAT("summon a Monster"), "", 'E');
 | |
|   displayStat(17, XLAT("summon Thumpers"), "", 'H');
 | |
|   displayStat(18, XLAT("summon Bonfire"), "", 'B');
 | |
|   displayStat(19, XLAT("summon Mimics"), "", 'M');
 | |
|   displayStat(20, XLAT("deplete orb powers"), "", 'P');
 | |
|   displayStat(21, XLAT("summon Orb of Yendor"), "", 'Y'-64);
 | |
|   displayStat(22, XLAT("switch ghost timer"), "", 'G'-64);
 | |
|   displayStat(23, XLAT("switch web display"), "", 'W'-64);
 | |
|   displayStat(-2, XLAT("return to the game"), "", ' ');
 | |
|   }
 | |
| 
 | |
| void handleCheatMenu(int uni) {
 | |
|   if(uni != 0) {
 | |
|     applyCheat(uni);
 | |
|     if(uni == 'F' || uni == 'C' || uni == 'O' ||
 | |
|       uni == 'S' || uni == 'U' || uni == 'G' ||
 | |
|       uni == 'W' || uni == 'I' || uni == 'E' ||
 | |
|       uni == 'H' || uni == 'B' || uni == 'M' ||
 | |
|       uni == 'P' || uni == 'Y'-64 || uni == 'G'-64 ||
 | |
|       uni == ' ') 
 | |
|       cmode = emNormal;
 | |
|     }
 | |
|   }
 | |
| 
 | |
| void showCustomizeChar() {
 | |
|   displayStatHelp(0, XLAT("Customize character"));
 | |
|   
 | |
|   if(shmup::on) shmup::cpid = shmup::cpid_edit % shmup::players;
 | |
|   charstyle& cs = getcs();
 | |
|   
 | |
|   displayStat(2, XLAT("character"), csname(cs), 'g');
 | |
|   displayStat(3, XLAT("skin color"), "?", 's');
 | |
|   displayStat(4, XLAT("weapon color"), "?", 'w');
 | |
|   displayStat(5, XLAT("hair color"), "?", 'h');
 | |
| 
 | |
|   if(cs.charid >= 1) displayStat(6, XLAT("dress color"), "?", 'd');
 | |
|   if(cs.charid == 3) displayStat(7, XLAT("dress color II"), "?", 'f');
 | |
|   
 | |
|   if(!shmup::on) displayStat(8, XLAT("save whom"), XLAT1(minf[moPrincess].name), 'p');
 | |
|   
 | |
|   if(numplayers() > 1) displayStat(8, XLAT("player"), its(shmup::cpid+1), 'a');
 | |
|   
 | |
|   displayStatHelp(16, XLAT("Shift=random, Ctrl=mix"));
 | |
|   
 | |
|   displayStat(19, XLAT("return to the game"), "", 'v');
 | |
|   }
 | |
| 
 | |
| void switchcolor(int& c, unsigned int* cs, int mod) {
 | |
|   int id = 0;
 | |
|   int q = cs[0]; cs++;
 | |
|   for(int i=0; i<q; i++) if(c == (int) cs[i]) id = i;
 | |
|   if(mod == 1)
 | |
|     c = ((rand() % 0x1000000) << 8) | 0xFF;
 | |
|   else if(mod == 2)
 | |
|     c = (gradient(cs[rand() % q] >> 8, cs[rand() % q] >> 8, 0, rand() % 101, 100) << 8) + 0xFF;
 | |
|   else
 | |
|     c = cs[(id+1) % q];
 | |
|   }
 | |
| 
 | |
| void handleCustomizeChar(int sym, int uni, int mod) {
 | |
| 
 | |
|   char xuni = uni | 96;
 | |
|   if(shiftmul < -.5) mod = 1;
 | |
|   else if(shiftmul > -.2 && shiftmul < .2) mod = 2;
 | |
|   else mod = 0;
 | |
| 
 | |
|   if(shmup::on) shmup::cpid = shmup::cpid_edit % shmup::players;
 | |
|   charstyle& cs = getcs();
 | |
|   if(xuni == 'a') { shmup::cpid_edit++; shmup::cpid_edit %= 60; }
 | |
|   if(xuni == 'g') {
 | |
|     cs.charid++;
 | |
|     if(cs.charid == 2 && !princess::everSaved) cs.charid = 4;
 | |
|     cs.charid %= 8;
 | |
|     }
 | |
|   if(xuni == 'p') vid.samegender = !vid.samegender;
 | |
|   bool cat = cs.charid >= 4;
 | |
|   if(xuni == 's') switchcolor(cs.skincolor, cat ? haircolors : skincolors, mod);
 | |
|   if(xuni == 'h') switchcolor(cs.haircolor, haircolors, mod);
 | |
|   if(xuni == 'w') switchcolor(cs.swordcolor, cat ? eyecolors : swordcolors, mod);
 | |
|   if(xuni == 'd') switchcolor(cs.dresscolor, cat ? haircolors : dresscolors, mod);
 | |
|   if(xuni == 'f') switchcolor(cs.dresscolor2, dresscolors2, mod);
 | |
|   if(xuni == 'v' || sym == SDLK_F2 || sym == SDLK_ESCAPE) cmode = emNormal;
 | |
|   }
 | |
| 
 | |
| int eupage = 0;
 | |
| int euperpage = 21;
 | |
| 
 | |
| void showEuclideanMenu() {
 | |
|   int s = vid.fsize;
 | |
|   vid.fsize = vid.fsize * 4/5;
 | |
|   displayStatHelp(-8, XLAT("Euclidean mode"));
 | |
|   if(cheater) for(int i=0; i<landtypes; i++) landvisited[i] = true;
 | |
|   for(int i=0; i<landtypes; i++)
 | |
|     if(hiitemsMax(treasureType(eLand(i))) >= 25) landvisited[i] = true;
 | |
|   landvisited[laCrossroads] = true;
 | |
|   landvisited[laIce] = true;
 | |
|   landvisited[laMirror] = true;
 | |
|   landvisited[laPrincessQuest] = princess::everSaved;
 | |
|   landvisited[laWildWest] = true;
 | |
|   // for(int i=2; i<lt; i++) landvisited[i] = true;
 | |
|   for(int i=0; i<euperpage; i++) {
 | |
|     if(euperpage * eupage + i >= LAND_EUC) break;
 | |
|     eLand l = land_euc[euperpage * eupage + i];
 | |
|     if(landvisited[l]) {
 | |
|       char ch;
 | |
|       if(i < 26) ch = 'a' + i;
 | |
|       else ch = 'A' + (i-26);
 | |
|       displayStat(i-6, XLAT1(linf[l].name), "", ch);
 | |
|       }
 | |
|     }
 | |
|   displayStat(euperpage+1-6, XLAT("Return to the hyperbolic world"), "", '0');
 | |
|   displayStat(euperpage+2-6, XLAT("Next page"), "", '-');
 | |
|   displayStatHelp(euperpage+4-6, XLAT("Choose from the lands visited this game."));
 | |
| #ifdef HAVE_ACHIEVEMENTS
 | |
|   displayStatHelp(euperpage+6-6, XLAT("Scores and achievements are not"));
 | |
|   displayStatHelp(euperpage+7-6, XLAT("saved in the Euclidean mode!"));
 | |
| #endif
 | |
|   vid.fsize = s;
 | |
|   }
 | |
| 
 | |
| void handleEuclidean(int sym, int uni) {
 | |
|   int lid;
 | |
|   if(uni >= 'a' && uni <= 'z') lid = uni - 'a';
 | |
|   else if(uni >= 'A' && uni <= 'Z') lid = 26 + uni - 'A';
 | |
|   else lid = -1;
 | |
|   
 | |
|   if(lid >= 0) lid += euperpage * eupage;
 | |
|   
 | |
|   if(uni == '0') {
 | |
|     if(euclid) restartGame('e');
 | |
|     cmode = emNormal;
 | |
|     }
 | |
|   else if(uni == '-') {
 | |
|     eupage++;
 | |
|     if(eupage * euperpage >= LAND_EUC) eupage = 0;
 | |
|     }
 | |
|   else if(lid >= 0 && lid < LAND_EUC) {
 | |
|     euclidland = land_euc[lid];
 | |
|     if(landvisited[euclidland] && euclidland != laOceanWall) {
 | |
|       if(euclid) restartGame();
 | |
|       else restartGame('e');
 | |
|       cmode = emNormal;
 | |
|       }
 | |
|     else euclidland = laIce;
 | |
|     }
 | |
|   else if(uni == '2' || sym == SDLK_F1) {
 | |
|     help =
 | |
|     "If you want to know how much the gameplay is affected by the "
 | |
|     "hyperbolic geometry in HyperRogue, this mode is for you!\n\n"
 | |
|     
 | |
|     "You can play an Euclidean version of each of the lands in "
 | |
|     "HyperRogue. Lands which include horocycles (Temple, Caribbean, "
 | |
|     "Whirlpool), infinite trees (Zebra, Emerald), or networks of "
 | |
|     "ultraparallel lines (Crossroads, Vineyard, Palace) cannot be "
 | |
|     "faithfully represented in Euclidean, so yo get more "
 | |
|     "or less simplified versions of them. Choose Crossroads to play a game "
 | |
|     "where many different lands appear.";
 | |
|     cmode = emHelp;
 | |
|     lastmode = emPickEuclidean;
 | |
|     }
 | |
|   else if(uni) cmode = emNormal;
 | |
|   }
 | |
| 
 | |
| void showConfig() {
 | |
|   displayStatHelp(0, XLAT("Configuration:"));
 | |
|   
 | |
|   if(cmode == emVisual1) showVisual1(); else showVisual2();
 | |
| 
 | |
| #ifndef MOBILE
 | |
|   displayStatHelp(16, XLAT("use Shift to decrease and Ctrl to fine tune "));
 | |
|   displayStatHelp(17, XLAT("(e.g. Shift+Ctrl+Z)"));
 | |
| #endif
 | |
|     
 | |
|   displayStat(19, XLAT("exit configuration"), "", 'v');
 | |
| #ifdef ANDROID
 | |
|   displayStat(16, XLAT("settings set here won't be saved"), "", 's');
 | |
|   displayStat(17, XLAT("-- use the Android menu instead"), "", 's');
 | |
| #else
 | |
|   displayStat(21, XLAT("save the current config"), "", 's');
 | |
| #endif
 | |
|   }
 | |
| 
 | |
| void handleMenus(int sym, int uni, int mod) {
 | |
|   if(cmode == emOverview) handleOverview(uni);
 | |
|   else if(cmode == emYendor) yendor::handleKey(uni, sym);
 | |
|   else if(cmode == emChangeMode) handleChangeMode(uni, sym);
 | |
|   else if(cmode == emVisual1) handleVisual1(uni, sym);
 | |
|   else if(cmode == emMenu) handleMenuKey(uni, false);
 | |
|   else if(cmode == emCheatMenu) handleCheatMenu(uni);
 | |
|   else if(cmode == emVisual2) handleVisual2(uni, sym);
 | |
|   else if(cmode == emPickEuclidean) handleEuclidean(uni, sym);
 | |
|   else if(cmode == emCustomizeChar) handleCustomizeChar(uni, sym, 0);
 | |
|   else if(cmode == emTactic) tactic::handleKey(uni, sym);
 | |
|   else if(cmode == emConformal) conformal::handleKey(uni, sym);
 | |
|   }
 | |
| 
 | |
| void displayMenus() {
 | |
|   if(cmode == emOverview) showOverview();
 | |
|   if(cmode == emYendor) yendor::showMenu();
 | |
|   if(cmode == emChangeMode) showChangeMode();
 | |
|   if(cmode == emCustomizeChar) showCustomizeChar();
 | |
|   if(cmode == emShmupConfig) shmup::showShmupConfig();
 | |
|   if(cmode == emConformal) conformal::show();
 | |
|   if(cmode == emTactic) tactic::showMenu();
 | |
|   if(cmode == emPickEuclidean) showEuclideanMenu();
 | |
|   if(cmode == emMenu) showMainMenu();
 | |
|   if(cmode == emCheatMenu) showCheatMenu();
 | |
|   if(cmode == emVisual1 || cmode == emVisual2) showConfig();    
 | |
| 
 | |
| #ifndef MOBILE
 | |
|   if(cmode == emNetgen) netgen::show();
 | |
|   if(cmode == emRugConfig) rug::show();
 | |
|   if(cmode == emMapEditor) mapeditor::showMapEditor();
 | |
|   if(cmode == emDraw) mapeditor::showDrawEditor();
 | |
| #endif
 | |
| 
 | |
| #ifndef ANDROID
 | |
|   if(cmode == emScores) showScores();
 | |
|   if(cmode == emPickScores) showPickScores();
 | |
| #endif
 | |
|   }
 | 
