further work for 10.0

This commit is contained in:
Zeno Rogue 2017-07-12 18:03:53 +02:00
parent a22eef683f
commit 94efef5d65
20 changed files with 441 additions and 661 deletions

View File

@ -1003,7 +1003,7 @@ void setvideomode() {
flags = SDL_OPENGL | SDL_HWSURFACE | SDL_GL_DOUBLEBUFFER; flags = SDL_OPENGL | SDL_HWSURFACE | SDL_GL_DOUBLEBUFFER;
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 1); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 1);
if(vid.antialias && AA_MULTI) { if(vid.antialias & AA_MULTI) {
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 16); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 16);
glEnable(GL_MULTISAMPLE); glEnable(GL_MULTISAMPLE);

View File

@ -1703,3 +1703,34 @@
- added a missing russian translation - added a missing russian translation
- [RogueViz] fixed legend in the svg/high quality output - [RogueViz] fixed legend in the svg/high quality output
- more control for text in svg output - more control for text in svg output
2017.07.04 14:40 work in progress
- peaceful mode (work in progress)
- anti-aliased lines, and linewidth setting, option to make lines further from the model center narrower
- rearranged the menus
- '9' key to list all the frames in the current slideshow; better support for multiple slideshows compiled in
- configurable border and foreground color (mostly for presentations, not available in the menus)
- aura effect adjusts to the background color
- nicer text frames
- aura in the spherical geometry
- fixed the Hypersian Rug on some machines (using another OpenGL function), glew used on Linux
- unicode superscript d is now used in the expansion screen instead of "^d"
- some preparation for the Inventory Mode
- texts changed, some minor translation fixes
- fixed the default wsad keys
- [technical] improved the NOGL compilation flag to avoid OpenGL
- [technical] refactoring (gotoHelp, sdltogl)
- [technical] changed #ifdef LOCAL to #ifdef EXTRA_...; extra features are now included by starting the compilation from another file
- [technical] HYPERPATH added, for reaching the files when HyperRogue is called from a different location
- [technical] private source files moved to the "private" dir
- antialiased multisampling
- major refactoring: return to previous menu
- image in the character selection screen
- ignore zero-score games
- do not save zero-score games
- consistency in menu
- multiple selectable columns in scores
- menu -> scores => list the current game if in game over
- yendor hardness fix
- hints shown on the quest status/quit screen

View File

@ -736,7 +736,7 @@ enum eMonster {
// shmup specials // shmup specials
moPlayer, moBullet, moFlailBullet, moFireball, moTongue, moAirball, moPlayer, moBullet, moFlailBullet, moFireball, moTongue, moAirball,
// temporary // temporary
moDeadBug, moLightningBolt, moDeadBird, moEnergySword, moWarning, moDeadBug, moLightningBolt, moDeadBird, moEnergySword, moWarning,
moRogueviz moRogueviz
}; };
@ -767,7 +767,7 @@ genderswitch_t genderswitch[NUM_GS] = {
// --- items --- // --- items ---
const int ittypes = 111; const int ittypes = 112;
struct itemtype { struct itemtype {
char glyph; char glyph;
@ -1153,6 +1153,7 @@ itemtype iinf[ittypes] = {
"with this Orb." }, "with this Orb." },
{ '$', 0xC060C0, "Spinel", bulldashdesc }, { '$', 0xC060C0, "Spinel", bulldashdesc },
{ 'o', 0xC0C0FF, "Orb of the Mirror", NODESCYET }, { 'o', 0xC0C0FF, "Orb of the Mirror", NODESCYET },
{ 'O', 0xF0F0F0, "your orbs", NODESC},
}; };
enum eItem { itNone, itDiamond, itGold, itSpice, itRuby, itElixir, itShard, itBone, itHell, itStatue, enum eItem { itNone, itDiamond, itGold, itSpice, itRuby, itElixir, itShard, itBone, itHell, itStatue,
@ -1185,7 +1186,8 @@ enum eItem { itNone, itDiamond, itGold, itSpice, itRuby, itElixir, itShard, itBo
itOrbSword, itKraken, itOrbSword2, itBarrow, itOrbSword, itKraken, itOrbSword2, itBarrow,
itTrollEgg, itWarning, itOrbStone, itOrbNature, itTreat, itTrollEgg, itWarning, itOrbStone, itOrbNature, itTreat,
itSlime, itAmethyst, itOrbRecall, itDodeca, itOrbDash, itGreenGrass, itOrbHorns, itSlime, itAmethyst, itOrbRecall, itDodeca, itOrbDash, itGreenGrass, itOrbHorns,
itOrbBull, itBull, itOrbMirror itOrbBull, itBull, itOrbMirror,
itInventory
}; };
// --- wall types --- // --- wall types ---

View File

@ -589,6 +589,8 @@ namespace princess {
achievement_gain("PRINCESS1"); achievement_gain("PRINCESS1");
princess::saved = true; princess::saved = true;
princess::everSaved = true; princess::everSaved = true;
if(inv::on && !princess::reviveAt)
princess::reviveAt = gold(NO_LOVE);
items[itSavedPrincess]++; items[itSavedPrincess]++;
} }
if(newdist == OUT_OF_PRISON && princess::challenge) { if(newdist == OUT_OF_PRISON && princess::challenge) {

View File

@ -407,6 +407,8 @@ void showAllConfig() {
dialog::addItem(XLAT("exit configuration"), 'v'); dialog::addItem(XLAT("exit configuration"), 'v');
#ifndef NOCONFIG #ifndef NOCONFIG
dialog::addItem(XLAT("save the current config"), 's'); dialog::addItem(XLAT("save the current config"), 's');
if(getcstat == 's')
mouseovers = XLAT("Config file: %1", conffile);
#endif #endif
} }
@ -448,6 +450,8 @@ void showGraphConfig() {
#ifndef MOBWEB #ifndef MOBWEB
dialog::addSelItem(XLAT("framerate limit"), its(vid.framelimit), 'l'); dialog::addSelItem(XLAT("framerate limit"), its(vid.framelimit), 'l');
if(getcstat == 'l')
mouseovers = XLAT("Reduce the framerate limit to conserve CPU energy");
#endif #endif
#ifndef IOS #ifndef IOS
@ -455,6 +459,7 @@ void showGraphConfig() {
#endif #endif
dialog::addSelItem(XLAT("scrolling speed"), fts(vid.sspeed), 'a'); dialog::addSelItem(XLAT("scrolling speed"), fts(vid.sspeed), 'a');
dialog::addSelItem(XLAT("movement animation speed"), fts(vid.mspeed), 'm'); dialog::addSelItem(XLAT("movement animation speed"), fts(vid.mspeed), 'm');
dialog::addBoolItem(XLAT("extra graphical effects"), (vid.particles), 'u'); dialog::addBoolItem(XLAT("extra graphical effects"), (vid.particles), 'u');
@ -508,7 +513,9 @@ void showGraphConfig() {
if(xuni == 'a') dialog::editNumber(vid.sspeed, -5, 5, 1, 0, if(xuni == 'a') dialog::editNumber(vid.sspeed, -5, 5, 1, 0,
XLAT("scrolling speed"), XLAT("scrolling speed"),
XLAT("+5 = center instantly, -5 = do not center the map")); XLAT("+5 = center instantly, -5 = do not center the map")
+ "\n\n" +
XLAT("press Space or Home to center on the PC"));
if(xuni == 'm') dialog::editNumber(vid.mspeed, -5, 5, 1, 0, if(xuni == 'm') dialog::editNumber(vid.mspeed, -5, 5, 1, 0,
XLAT("movement animation speed"), XLAT("movement animation speed"),
@ -613,6 +620,8 @@ void showBasicConfig() {
dialog::addSelItem(XLAT("language"), XLAT("EN"), 'l'); dialog::addSelItem(XLAT("language"), XLAT("EN"), 'l');
#endif #endif
dialog::addSelItem(XLAT("player character"), numplayers() > 1 ? "" : csname(vid.cs), 'g'); dialog::addSelItem(XLAT("player character"), numplayers() > 1 ? "" : csname(vid.cs), 'g');
if(getcstat == 'g')
mouseovers = XLAT("Affects looks and grammar");
#ifndef NOAUDIO #ifndef NOAUDIO
dialog::addSelItem(XLAT("background music volume"), its(musicvolume), 'b'); dialog::addSelItem(XLAT("background music volume"), its(musicvolume), 'b');
@ -719,6 +728,12 @@ void showJoyConfig() {
#ifndef MOBWEB #ifndef MOBWEB
dialog::addSelItem(XLAT("joystick mode"), XLAT(autojoy ? "automatic" : "manual"), 'p'); dialog::addSelItem(XLAT("joystick mode"), XLAT(autojoy ? "automatic" : "manual"), 'p');
if(getcstat == 'p') {
if(autojoy)
mouseovers = XLAT("joystick mode: automatic (release the joystick to move)");
if(!autojoy)
mouseovers = XLAT("joystick mode: manual (press a button to move)");
}
dialog::addSelItem(XLAT("first joystick: movement threshold"), its(vid.joyvalue), 'a'); dialog::addSelItem(XLAT("first joystick: movement threshold"), its(vid.joyvalue), 'a');
dialog::addSelItem(XLAT("first joystick: execute movement threshold"), its(vid.joyvalue2), 'b'); dialog::addSelItem(XLAT("first joystick: execute movement threshold"), its(vid.joyvalue2), 'b');

View File

@ -10,7 +10,7 @@ bool gtouched;
int getcstat, lgetcstat; ld getcshift; bool inslider; int getcstat, lgetcstat; ld getcshift; bool inslider;
int andmode = 0; function <void(int sym, int uni)> keyhandler;
// is the player using mouse? (used for auto-cross) // is the player using mouse? (used for auto-cross)
bool mousing = true; bool mousing = true;
@ -32,12 +32,6 @@ int lastt;
Uint8 *SDL_GetKeyState(void *v) { static Uint8 tab[1024]; return tab; } Uint8 *SDL_GetKeyState(void *v) { static Uint8 tab[1024]; return tab; }
#endif #endif
bool quitsaves() { return (items[itOrbSafety] && havesave); }
bool needConfirmation() {
return canmove && (gold() >= 30 || tkills() >= 50) && !cheater && !quitsaves();
}
bool mouseout() { bool mouseout() {
if((getcstat != '-' && getcstat) || (lgetcstat && lgetcstat != '-')) return true; if((getcstat != '-' && getcstat) || (lgetcstat && lgetcstat != '-')) return true;
return outofmap(mouseh); return outofmap(mouseh);
@ -210,52 +204,6 @@ bool doexiton(int sym, int uni) {
return false; return false;
} }
void handleKeyQuit(int sym, int uni) {
dialog::handleNavigation(sym, uni);
// ignore the camera movement keys
#ifndef NORUG
if(rug::rugged && (sym == SDLK_UP || sym == SDLK_DOWN || sym == SDLK_PAGEUP || sym == SDLK_PAGEDOWN ||
sym == SDLK_RIGHT || sym == SDLK_LEFT))
sym = 0;
#endif
if(sym == SDLK_RETURN || sym == SDLK_KP_ENTER || sym == SDLK_F10) quitmainloop = true;
else if(uni == 'r' || sym == SDLK_F5) {
restartGame(), popScreen();
msgs.clear();
}
else if(sym == SDLK_UP || sym == SDLK_KP8 || sym == PSEUDOKEY_WHEELUP) msgscroll++;
else if(sym == SDLK_DOWN || sym == SDLK_KP2 || sym == PSEUDOKEY_WHEELDOWN) msgscroll--;
else if(sym == SDLK_PAGEUP || sym == SDLK_KP9) msgscroll+=5;
else if(sym == SDLK_PAGEDOWN || sym == SDLK_KP3) msgscroll-=5;
else if(uni == 'v') popScreenAll(), pushScreen(showMainMenu);
else if(sym == SDLK_F3 || (sym == ' ' || sym == SDLK_HOME))
fullcenter();
else if(uni == 'o' && DEFAULTNOR(sym)) setAppropriateOverview();
#ifdef INV
else if(uni == 'i' && DEFAULTNOR(sym) && inv::on)
pushScreen(inv::show);
#endif
#ifndef NOSAVE
else if(uni == 't') {
if(!canmove) restartGame();
loadScores();
msgs.clear();
}
#endif
else if(doexiton(sym, uni) && !didsomething) {
popScreen();
msgscroll = 0;
msgs.clear();
if(!canmove) {
addMessage(XLAT("GAME OVER"));
addMessage(timeline());
}
}
}
bool didsomething; bool didsomething;
#ifdef MOBILE #ifdef MOBILE
@ -396,24 +344,6 @@ void handleKeyNormal(int sym, int uni) {
else quitmainloop = true; else quitmainloop = true;
} }
if(!canmove) {
if(sym == SDLK_RETURN || sym == SDLK_KP_ENTER) quitmainloop = true;
else if(uni == 'r') restartGame();
#ifndef NOSAVE
else if(uni == 't') {
restartGame();
loadScores();
}
#endif
#ifndef NORUG
else if(rug::rugged) ;
#endif
else if(sym == SDLK_UP || sym == SDLK_KP8) msgscroll++;
else if(sym == SDLK_DOWN || sym == SDLK_KP2) msgscroll--;
else if(sym == SDLK_PAGEUP || sym == SDLK_KP9) msgscroll+=5;
else if(sym == SDLK_PAGEDOWN || sym == SDLK_KP3) msgscroll-=5;
}
if(uni == 'o' && DEFAULTNOR(sym)) setAppropriateOverview(); if(uni == 'o' && DEFAULTNOR(sym)) setAppropriateOverview();
#ifdef INV #ifdef INV
if(uni == 'i' && DEFAULTNOR(sym) && inv::on) if(uni == 'i' && DEFAULTNOR(sym) && inv::on)
@ -776,3 +706,17 @@ void displayabutton(int px, int py, string s, int col) {
} }
#endif #endif
void gmodekeys(int sym, int uni) {
if(uni == '1') { vid.alpha = 999; vid.scale = 998; }
if(uni == '2') { vid.alpha = 1; vid.scale = 0.4; }
if(uni == '3') { vid.alpha = 1; vid.scale = 1; }
if(uni == '4') { vid.alpha = 0; vid.scale = 1; }
if(uni == '5') { vid.wallmode += 60 + (shiftmul > 0 ? 1 : -1); vid.wallmode %= 6; }
if(uni == '6') vid.grid = !vid.grid;
if(uni == '7') { vid.darkhepta = !vid.darkhepta; }
if(uni == '%' && sym == '5') {
if(vid.wallmode == 0) vid.wallmode = 6;
vid.wallmode--;
}
}

View File

@ -267,7 +267,7 @@ int itemclass(eItem i) {
if(i == itSavedPrincess || i == itStrongWind || i == itWarning) if(i == itSavedPrincess || i == itStrongWind || i == itWarning)
return IC_NAI; return IC_NAI;
if(i == itKey || i == itOrbYendor || i == itGreenStone || i == itHolyGrail || i == itCompass || if(i == itKey || i == itOrbYendor || i == itGreenStone || i == itHolyGrail || i == itCompass ||
isElementalShard(i) || i == itRevolver) isElementalShard(i) || i == itRevolver || i == itInventory)
return IC_OTHER; return IC_OTHER;
return IC_ORB; return IC_ORB;
} }

112
game.cpp
View File

@ -189,15 +189,6 @@ bool itemHiddenFromSight(cell *c) {
&& !(shmup::on && shmup::boatAt(c)); && !(shmup::on && shmup::boatAt(c));
} }
int puregold() {
int i = items[itOrbYendor] * 50 + items[itHolyGrail] * 10;
if(items[itOrbLove]) i += 30;
for(int t=0; t<ittypes; t++)
if(itemclass(eItem(t)) == IC_TREASURE)
i += items[t];
return i;
}
int numplayers() { int numplayers() {
return multi::players; return multi::players;
} }
@ -273,8 +264,24 @@ void countLocalTreasure() {
} }
} }
int gold() { int gold(int no) {
return puregold(); int i = 0;
if(!(no & NO_YENDOR)) i += items[itOrbYendor] * 50;
if(!(no & NO_GRAIL)) i += items[itHolyGrail] * 10;
if(!(no & NO_LOVE)) {
bool love = items[itOrbLove];
#ifdef INV
if(inv::on && inv::remaining[itOrbLove])
love = true;
#endif
if(love) i += 30;
}
if(!(no & NO_TREASURE))
for(int t=0; t<ittypes; t++)
if(itemclass(eItem(t)) == IC_TREASURE)
i += items[t];
return i;
} }
int maxgold() { int maxgold() {
@ -1721,9 +1728,9 @@ void killMonster(cell *c, eMonster who, flagtype deathflags) {
i->princess = NULL; i->princess = NULL;
if(i->bestdist == OUT_OF_PALACE) { if(i->bestdist == OUT_OF_PALACE) {
items[itSavedPrincess]--; items[itSavedPrincess]--;
if(items[itSavedPrincess] == 0) { if(items[itSavedPrincess] == 0 && !inv::on) {
items[itOrbLove] = 0; items[itOrbLove] = 0;
princess::reviveAt = gold() + 20; princess::reviveAt = gold(NO_LOVE) + 20;
} }
} }
if(princess::challenge) showMissionScreen(); if(princess::challenge) showMissionScreen();
@ -2154,13 +2161,13 @@ bool attackMonster(cell *c, flagtype flags, eMonster killer) {
addMessage(XLAT("That was easy, but groups could be dangerous.")); addMessage(XLAT("That was easy, but groups could be dangerous."));
} }
if(tk < 10 && ntk >= 10 && !tactic::on && !euclid && !sphere) if(tk < 10 && ntk >= 10 && !tactic::on && !euclid && !sphere && !inv::on)
addMessage(XLAT("Good to know that your fighting skills serve you well in this strange world.")); addMessage(XLAT("Good to know that your fighting skills serve you well in this strange world."));
if(tk < 50 && ntk >= 50 && !euclid && !sphere) if(tk < R100/2 && ntk >= R100/2 && !euclid && !sphere)
addMessage(XLAT("You wonder where all these monsters go, after their death...")); addMessage(XLAT("You wonder where all these monsters go, after their death..."));
if(tk < 100 && ntk >= 100 && !euclid && !sphere) if(tk < R100 && ntk >= R100 && !euclid && !sphere)
addMessage(XLAT("You feel that the souls of slain enemies pull you to the Graveyard...")); addMessage(XLAT("You feel that the souls of slain enemies pull you to the Graveyard..."));
if(!tu && trollUnlocked()) { if(!tu && trollUnlocked()) {
@ -5429,6 +5436,10 @@ void checkmove() {
for(int i=0; i<ittypes; i++) orbused[i] = orbusedbak[i]; for(int i=0; i<ittypes; i++) orbused[i] = orbusedbak[i];
if(recallCell && !markOrb(itOrbRecall)) activateRecall(); if(recallCell && !markOrb(itOrbRecall)) activateRecall();
#ifdef INV
if(inv::on) inv::compute();
#endif
} }
// move the PC. Warning: a very long function! todo: refactor // move the PC. Warning: a very long function! todo: refactor
@ -5586,48 +5597,55 @@ void collectMessage(cell *c2, eItem which) {
addMessage(XLAT("Prove yourself here, then find new lands, with new quests...")); addMessage(XLAT("Prove yourself here, then find new lands, with new quests..."));
else if(!items[which] && itemclass(which) == IC_TREASURE) else if(!items[which] && itemclass(which) == IC_TREASURE)
addMessage(XLAT("You collect your first %1!", which)); addMessage(XLAT("You collect your first %1!", which));
else if(items[which] == 4 && maxgold() == 4 && !specialmode) { else if(items[which] == 4 && maxgold() == U5-1 && !specialmode) {
addMessage(XLAT("You feel that %the2 become%s2 more dangerous.", which, c2->land)); addMessage(XLAT("You feel that %the2 become%s2 more dangerous.", which, c2->land));
addMessage(XLAT("With each %1 you collect...", which, c2->land)); addMessage(XLAT("With each %1 you collect...", which, c2->land));
} }
else if(items[which] == 9 && maxgold() == 9 && !specialmode) else if(items[which] == 9 && maxgold() == 9 && !specialmode) {
addMessage(XLAT("Are there any magical orbs in %the1?...", c2->land)); if(inv::on) {
else if(items[which] == 10 && maxgold() == 10 && !specialmode) { addMessage(XLAT("The treasure gives your magical powers!", c2->land));
if(!ISMOBILE)
addMessage(XLAT("Press 'i' to access your magical powers.", c2->land));
}
else
addMessage(XLAT("Are there any magical orbs in %the1?...", c2->land));
}
else if(items[which] == R10 && maxgold() == R10 && !specialmode && !inv::on) {
addMessage(XLAT("You feel that %the1 slowly become%s1 dangerous...", c2->land)); addMessage(XLAT("You feel that %the1 slowly become%s1 dangerous...", c2->land));
addMessage(XLAT("Better find some other place.")); addMessage(XLAT("Better find some other place."));
} }
else if(which == itSpice && items[itSpice] == 7 && !specialmode) else if(which == itSpice && items[itSpice] == U10*7/10 && !specialmode)
addMessage(XLAT("You have a vision of the future, fighting demons in Hell...")); addMessage(XLAT("You have a vision of the future, fighting demons in Hell..."));
else if(which == itSpice && items[itSpice] == 9 && !specialmode) else if(which == itSpice && items[itSpice] == U10-1 && !specialmode)
addMessage(XLAT("You will be fighting red rock snakes, too...")); addMessage(XLAT("You will be fighting red rock snakes, too..."));
else if(which == itKraken && items[itKraken] == 9 && !specialmode) else if(which == itKraken && items[itKraken] == U10-1 && !specialmode)
addMessage(XLAT("You feel that a magical weapon is waiting for you...")); addMessage(XLAT("You feel that a magical weapon is waiting for you..."));
// else if(which == itFeather && items[itFeather] == 10) // else if(which == itFeather && items[itFeather] == 10)
// addMessage(XLAT("There should be a Palace somewhere nearby...")); // addMessage(XLAT("There should be a Palace somewhere nearby..."));
else if(which == itElixir && items[itElixir] == 4 && !specialmode) else if(which == itElixir && items[itElixir] == U5-1 && !specialmode)
addMessage(XLAT("With this Elixir, your life should be long and prosperous...")); addMessage(XLAT("With this Elixir, your life should be long and prosperous..."));
else if(which == itRuby && items[itRuby] == 4 && !specialmode) { else if(which == itRuby && items[itRuby] == U5-1 && !specialmode) {
addMessage(XLAT("You feel something strange about gravity here...")); addMessage(XLAT("You feel something strange about gravity here..."));
} }
else if(which == itPalace && items[itPalace] == 4 && !specialmode) { else if(which == itPalace && items[itPalace] == U5-1 && !specialmode) {
addMessage(XLAT("The rug depicts a man in a deep dungeon, unable to leave.")); addMessage(XLAT("The rug depicts a man in a deep dungeon, unable to leave."));
} }
else if(which == itIvory && items[itIvory] == 4 && !specialmode) { else if(which == itIvory && items[itIvory] == U5-1 && !specialmode) {
addMessage(XLAT("You feel attuned to gravity, ready to face mountains and dungeons.")); addMessage(XLAT("You feel attuned to gravity, ready to face mountains and dungeons."));
} }
else if(which == itBone && items[itBone] == 6 && !specialmode) else if(which == itBone && items[itBone] == U5+1 && !specialmode)
addMessage(XLAT("The Necromancer's Totem contains hellish incantations...")); addMessage(XLAT("The Necromancer's Totem contains hellish incantations..."));
else if(which == itStatue && items[itStatue] == 6 && !specialmode) else if(which == itStatue && items[itStatue] == U5+1 && !specialmode)
addMessage(XLAT("The inscriptions on the Statue of Cthulhu point you toward your destiny...")); addMessage(XLAT("The inscriptions on the Statue of Cthulhu point you toward your destiny..."));
else if(which == itStatue && items[itStatue] == 4 && !specialmode) else if(which == itStatue && items[itStatue] == U5-1 && !specialmode)
addMessage(XLAT("There must be some temples of Cthulhu in R'Lyeh...")); addMessage(XLAT("There must be some temples of Cthulhu in R'Lyeh..."));
else if(which == itDiamond && items[itDiamond] == 8 && !specialmode) else if(which == itDiamond && items[itDiamond] == U10-2 && !specialmode)
addMessage(XLAT("Still, even greater treasures lie ahead...")); addMessage(XLAT("Still, even greater treasures lie ahead..."));
else if(which == itFernFlower && items[itFernFlower] == 4 && !specialmode) else if(which == itFernFlower && items[itFernFlower] == U5-1 && !specialmode)
addMessage(XLAT("You overheard Hedgehog Warriors talking about emeralds...")); addMessage(XLAT("You overheard Hedgehog Warriors talking about emeralds..."));
else if(which == itEmerald && items[itEmerald] == 4 && !specialmode && !chaosmode) else if(which == itEmerald && items[itEmerald] == U5-1 && !specialmode && !chaosmode)
addMessage(XLAT("You overhear miners talking about a castle...")); addMessage(XLAT("You overhear miners talking about a castle..."));
else if(which == itEmerald && items[itEmerald] == 5 && !specialmode && !chaosmode) else if(which == itEmerald && items[itEmerald] == U5 && !specialmode && !chaosmode)
addMessage(XLAT("A castle in the Crossroads...")); addMessage(XLAT("A castle in the Crossroads..."));
else if(which == itShard) ; else if(which == itShard) ;
else { else {
@ -5983,21 +6001,23 @@ bool collectItem(cell *c2, bool telekinesis) {
} }
#ifdef MOBILE #ifdef MOBILE
if(pg < lastsafety + 45 && g2 >= lastsafety + 45) if(pg < lastsafety + R30*3/2 && g2 >= lastsafety + R30*3/2)
addMessage(XLAT("The Orb of Safety from the Land of Eternal Motion might save you.")); addMessage(XLAT("The Orb of Safety from the Land of Eternal Motion might save you."));
#endif #endif
if(pg < 15 && g2 >= 15) #define IF(x) if(pg < (x) && g2 >= x)
IF(R60/4)
addMessage(XLAT("Collect treasure to access more different lands...")); addMessage(XLAT("Collect treasure to access more different lands..."));
if(pg < 30 && g2 >= 30) IF(R30)
addMessage(XLAT("You feel that you have enough treasure to access new lands!")); addMessage(XLAT("You feel that you have enough treasure to access new lands!"));
if(pg < 45 && g2 >= 45) IF(R30*3/2)
addMessage(XLAT("Collect more treasures, there are still more lands waiting...")); addMessage(XLAT("Collect more treasures, there are still more lands waiting..."));
if(pg < 60 && g2 >= 60) IF(R60)
addMessage(XLAT("You feel that the stars are right, and you can access R'Lyeh!")); addMessage(XLAT("You feel that the stars are right, and you can access R'Lyeh!"));
if(pg < 75 && g2 >= 75) IF(R30*5/2)
addMessage(XLAT("Kill monsters and collect treasures, and you may get access to Hell...")); addMessage(XLAT("Kill monsters and collect treasures, and you may get access to Hell..."));
if(pg < 90 && g2 >= 90) IF(R10 * 9)
addMessage(XLAT("To access Hell, collect %1 treasures each of 9 kinds...", its(R10))); addMessage(XLAT("To access Hell, collect %1 treasures each of 9 kinds...", its(R10)));
if(hellUnlocked() && !lhu) { if(hellUnlocked() && !lhu) {
addMessage(XLAT("Abandon all hope, the gates of Hell are opened!")); addMessage(XLAT("Abandon all hope, the gates of Hell are opened!"));
@ -6021,7 +6041,7 @@ bool collectItem(cell *c2, bool telekinesis) {
numOrb++; numOrb++;
if(numOrb) achievement_count("ORB", numOrb, 0); if(numOrb) achievement_count("ORB", numOrb, 0);
if(princess::reviveAt && gold() >= princess::reviveAt) { if(princess::reviveAt && gold(NO_LOVE) >= princess::reviveAt && !inv::on) {
princess::reviveAt = 0, princess::reviveAt = 0,
items[itSavedPrincess] = 1; items[itSavedPrincess] = 1;
addMessage("You have enough treasure now to revive the Princess!"); addMessage("You have enough treasure now to revive the Princess!");
@ -6095,8 +6115,12 @@ void roundTableMessage(cell *c2) {
} }
long long circlesize[100], disksize[100]; long long circlesize[100], disksize[100];
ld circlesizeD[10000];
int lastsize;
void computeSizes() { void computeSizes() {
lastsize = purehepta ? 44 : 76;
circlesize[0] = 1; circlesize[0] = 1;
if(!purehepta) { if(!purehepta) {
@ -6168,12 +6192,12 @@ void knightFlavorMessage(cell *c2) {
addMessage(XLAT("\"Train in the Desert first!\"")); addMessage(XLAT("\"Train in the Desert first!\""));
} }
else if(msgid == 8) { else if(msgid == 8) {
if(rad <= 76) if(rad <= lastsize)
addMessage(XLAT("\"Our Table seats %1 Knights!\"", llts(circlesize[rad]))); addMessage(XLAT("\"Our Table seats %1 Knights!\"", llts(circlesize[rad])));
else else
addMessage(XLAT("\"By now, you should have your own formula, you know?\"")); addMessage(XLAT("\"By now, you should have your own formula, you know?\""));
} }
else if(msgid == 9 && rad <= 76) { else if(msgid == 9 && rad <= lastsize) {
addMessage(XLAT("\"There are %1 floor tiles inside our Table!\"", llts(disksize[rad]))); addMessage(XLAT("\"There are %1 floor tiles inside our Table!\"", llts(disksize[rad])));
} }
else if(msgid == 10 && !items[itPirate] && !items[itWhirlpool]) { else if(msgid == 10 && !items[itPirate] && !items[itWhirlpool]) {

View File

@ -602,7 +602,7 @@ bool drawItemType(eItem it, cell *c, const transmatrix& V, int icol, int ticks,
queuepolyat(V * spin(ticks / 1500. + M_PI/(ct6+6)), *xsh, darkena(0x202020, 0, hidden ? 0x40 : 0xF0), PPR_ITEMb); queuepolyat(V * spin(ticks / 1500. + M_PI/(ct6+6)), *xsh, darkena(0x202020, 0, hidden ? 0x40 : 0xF0), PPR_ITEMb);
} }
else if(xch == 'o') { else if(xch == 'o' || it == itInventory) {
if(it == itOrbFire) icol = firecolor(100); if(it == itOrbFire) icol = firecolor(100);
queuepoly(V, shDisk, darkena(icol, 0, hidden ? 0x20 : 0xC0)); queuepoly(V, shDisk, darkena(icol, 0, hidden ? 0x20 : 0xC0));
if(it == itOrbFire) icol = firecolor(200); if(it == itOrbFire) icol = firecolor(200);
@ -4330,13 +4330,7 @@ void drawthemap() {
mapeditor::ewsearch.dist = 1e30; mapeditor::ewsearch.dist = 1e30;
modist = 1e20; mouseover = NULL; modist = 1e20; mouseover = NULL;
modist2 = 1e20; mouseover2 = NULL; modist2 = 1e20; mouseover2 = NULL;
mouseovers = XLAT("Press F1 or right click for help");
#ifdef ROGUEVIZ
if(rogueviz::on) mouseovers = " ";
#endif
#ifdef TOUR
if(tour::on) mouseovers = tour::tourhelp;
#endif
centdist = 1e20; centdist = 1e20;
if(!torus) centerover = NULL; if(!torus) centerover = NULL;
@ -4643,6 +4637,16 @@ void gamescreen(int _darken) {
void normalscreen() { void normalscreen() {
help = "@"; help = "@";
#ifdef ROGUEVIZ
if(!rogueviz::on)
#endif
mouseovers = XLAT("Press F1 or right click for help");
#ifdef TOUR
if(tour::on) mouseovers = tour::tourhelp;
#endif
if(!outofmap(mouseh)) getcstat = '-'; if(!outofmap(mouseh)) getcstat = '-';
cmode2 = smNormal; cmode2 = smNormal;
gamescreen(hiliteclick && mmmon ? 1 : 0); drawStats(); gamescreen(hiliteclick && mmmon ? 1 : 0); drawStats();
@ -4655,6 +4659,8 @@ void normalscreen() {
#endif #endif
displayButton(vid.xres-8, vid.yres-vid.fsize, XLAT("(v) menu"), 'v', 16); displayButton(vid.xres-8, vid.yres-vid.fsize, XLAT("(v) menu"), 'v', 16);
keyhandler = handleKeyNormal; keyhandler = handleKeyNormal;
describeMouseover();
} }
vector< function<void()> > screens = { normalscreen }; vector< function<void()> > screens = { normalscreen };
@ -4689,14 +4695,21 @@ void drawscreen() {
lgetcstat = getcstat; lgetcstat = getcstat;
getcstat = 0; inslider = false; getcstat = 0; inslider = false;
mouseovers = " ";
cmode2 = smMenu; cmode2 = smMenu;
keyhandler = [] (int sym, int uni) { return false; }; keyhandler = [] (int sym, int uni) { return false; };
screens.back()(); screens.back()();
int col = linf[cwt.c->land].color;
if(cwt.c->land == laRedRock) col = 0xC00000;
#ifndef MOBILE
displayfr(vid.xres/2, vid.fsize, 2, vid.fsize, mouseovers, col, 8);
#endif
drawmessages(); drawmessages();
describeMouseover();
if((havewhat&HF_BUG) && darken == 0 && cmode2 == smNormal) for(int k=0; k<3; k++) if((havewhat&HF_BUG) && darken == 0 && cmode2 == smNormal) for(int k=0; k<3; k++)
displayfr(vid.xres/2 + vid.fsize * 5 * (k-1), vid.fsize*2, 2, vid.fsize, displayfr(vid.xres/2 + vid.fsize * 5 * (k-1), vid.fsize*2, 2, vid.fsize,
its(hive::bugcount[k]), minf[moBug0+k].color, 8); its(hive::bugcount[k]), minf[moBug0+k].color, 8);

113
help.cpp
View File

@ -60,7 +60,9 @@ string buildHelpText() {
h += XLAT( h += XLAT(
"You can right click any element to get more information about it.\n\n" "You can right click any element to get more information about it.\n\n"
); );
#ifdef MAC
h += XLAT("(You can also use right Shift)\n\n"); h += XLAT("(You can also use right Shift)\n\n");
#endif
#endif #endif
h += XLAT("See more on the website: ") h += XLAT("See more on the website: ")
+ "http//roguetemple.com/z/hyper/\n\n"; + "http//roguetemple.com/z/hyper/\n\n";
@ -158,7 +160,7 @@ string generateHelpForItem(eItem it) {
help += XLAT(iinf[it].help); help += XLAT(iinf[it].help);
if(it == itSavedPrincess || it == itOrbLove) if(it == itSavedPrincess || it == itOrbLove) if(!inv::on)
help += princessReviveHelp(); help += princessReviveHelp();
if(it == itTrollEgg) if(it == itTrollEgg)
@ -530,16 +532,12 @@ void describeMouseover() {
DEBB(DF_GRAPH, (debugfile,"describeMouseover\n")); DEBB(DF_GRAPH, (debugfile,"describeMouseover\n"));
cell *c = mousing ? mouseover : playermoved ? NULL : centerover; cell *c = mousing ? mouseover : playermoved ? NULL : centerover;
string out = mouseovers; string& out = mouseovers;
if(!c || instat || getcstat) { } if(!c || instat || getcstat != '-') { }
else if(c->wall != waInvisibleFloor) { else if(c->wall != waInvisibleFloor) {
out = XLAT1(linf[c->land].name); out = XLAT1(linf[c->land].name);
help = generateHelpForLand(c->land); help = generateHelpForLand(c->land);
// Celsius
// if(c->land == laIce) out = "Icy Lands (" + fts(60 * (c->heat - .4)) + " C)";
if(c->land == laIce || c->land == laCocytus) if(c->land == laIce || c->land == laCocytus)
out += " (" + fts(heat::celsius(c)) + " °C)"; out += " (" + fts(heat::celsius(c)) + " °C)";
if(c->land == laDryForest && c->landparam) if(c->land == laDryForest && c->landparam)
@ -562,29 +560,10 @@ void describeMouseover() {
if(c->land == laTortoise && tortoise::seek()) out += " " + tortoise::measure(getBits(c)); if(c->land == laTortoise && tortoise::seek()) out += " " + tortoise::measure(getBits(c));
/* if(c->land == laGraveyard || c->land == laHauntedBorder || c->land == laHaunted)
out += " (" + its(c->landparam)+")"; */
if(buggyGeneration) { if(buggyGeneration) {
char buf[20]; sprintf(buf, " H=%d M=%d", c->landparam, c->mpdist); out += buf; char buf[20]; sprintf(buf, " H=%d M=%d", c->landparam, c->mpdist); out += buf;
} }
// if(c->land == laBarrier)
// out += "(" + string(linf[c->barleft].name) + " / " + string(linf[c->barright].name) + ")";
// out += "(" + its(c->bardir) + ":" + string(linf[c->barleft].name) + " / " + string(linf[c->barright].name) + ")";
// out += " MD"+its(c->mpdist);
// out += " WP:" + its(c->wparam);
// out += " rose:" + its(rosemap[c]/4) + "." + its(rosemap[c]%4);
// out += " MP:" + its(c->mpdist);
// out += " cda:" + its(celldistAlt(c));
/* out += " DP=" + its(celldistance(c, cwt.c));
out += " DO=" + its(celldist(c));
out += " PD=" + its(c->pathdist); */
if(false) { if(false) {
out += " LP:" + itsh(c->landparam)+"/"+its(turncount); out += " LP:" + itsh(c->landparam)+"/"+its(turncount);
@ -594,33 +573,17 @@ void describeMouseover() {
out += " D:" + its(c->mpdist); out += " D:" + its(c->mpdist);
char zz[64]; sprintf(zz, " P%p", c); out += zz; char zz[64]; sprintf(zz, " P%p", c); out += zz;
// out += " rv" + its(rosedist(c));
// if(rosemap.count(c))
// out += " rv " + its(rosemap[c]/8) + "." + its(rosemap[c]%8);
// out += " ai" + its(c->aitmp);
if(euclid) { if(euclid) {
for(int i=0; i<4; i++) out += " " + its(getEuclidCdata(c->master)->val[i]); for(int i=0; i<4; i++) out += " " + its(getEuclidCdata(c->master)->val[i]);
out += " " + itsh(getBits(c)); out += " " + itsh(getBits(c));
} }
else { else {
for(int i=0; i<4; i++) out += " " + its(getHeptagonCdata(c->master)->val[i]); for(int i=0; i<4; i++) out += " " + its(getHeptagonCdata(c->master)->val[i]);
// out += " " + itsh(getHeptagonCdata(c->master)->bits);
out += " " + fts(tortoise::getScent(getBits(c))); out += " " + fts(tortoise::getScent(getBits(c)));
} }
// itsh(getHeptagonCdata(c->master)->bits);
// out += " barleft: " + s0 + dnameof(c->barleft);
// out += " barright: " + s0 + dnameof(c->barright);
} }
// char zz[64]; sprintf(zz, " P%p", c); out += zz;
/* whirlwind::calcdirs(c);
for(int i=0; i<whirlwind::qdirs; i++)
out += " " + its(whirlwind::dfrom[i]) + ":" + its(whirlwind::dto[i]); */
// out += " : " + its(whirlwinddir(c));
if(randomPatternsMode) if(randomPatternsMode)
out += " " + describeRPM(c->land); out += " " + describeRPM(c->land);
@ -635,26 +598,6 @@ void describeMouseover() {
} }
} }
// char zz[64]; sprintf(zz, " P%d", princess::dist(c)); out += zz;
// out += " MD"+its(c->mpdist);
// out += " H "+its(c->heat);
// if(c->type != 6) out += " Z"+its(c->master->zebraval);
// out += " H"+its(c->heat);
/* // Hive debug
if(c->land == laHive) {
out += " [" + its(c->tmp) + " H" + its(int(c->heat));
if(c->tmp >= 0 && c->tmp < size(buginfo) && buginfo[c->tmp].where == c) {
buginfo_t b(buginfo[c->tmp]);
for(int k=0; k<3; k++) out += ":" + its(b.dist[k]);
for(int k=0; k<3; k++)
for(int i=0; i<size(bugqueue[k]); i++)
if(bugqueue[k][i] == c->tmp)
out += " B"+its(k)+":"+its(i);
}
out += "]";
} */
if(c->wall && if(c->wall &&
!((c->wall == waFloorA || c->wall == waFloorB || c->wall == waFloorC || c->wall == waFloorD) && c->item)) { !((c->wall == waFloorA || c->wall == waFloorB || c->wall == waFloorC || c->wall == waFloorD) && c->item)) {
out += ", "; out += XLAT1(winf[c->wall].name); out += ", "; out += XLAT1(winf[c->wall].name);
@ -721,55 +664,11 @@ void describeMouseover() {
if(isWarped(c)) if(isWarped(c))
help += s0 + "\n\n" + warpdesc; help += s0 + "\n\n" + warpdesc;
} }
/*
else if(cmode == emGraphConfig) {
if(getcstat == 'a' && vid.sspeed > -4.99)
out = XLAT("+5 = center instantly, -5 = do not center the map");
else if(getcstat == 'a')
out = XLAT("press Space or Home to center on the PC");
else if(getcstat == 'w')
out = XLAT("also hold Alt during the game to toggle high contrast");
else if(getcstat == 'f')
out = XLAT("Reduce the framerate limit to conserve CPU energy");
}
else if(cmode == emBasicConfig) {
if(getcstat == 'c')
out = XLAT("The axes help with keyboard movement");
else if(getcstat == 'g')
out = XLAT("Affects looks and grammar");
#ifndef MOBILE
else if(getcstat == 's')
out = XLAT("Config file: %1", conffile);
#endif
else out = "";
}
else if(cmode == emDisplayMode) {
if(getcstat == 'p') {
if(autojoy)
out = XLAT("joystick mode: automatic (release the joystick to move)");
if(!autojoy)
out = XLAT("joystick mode: manual (press a button to move)");
}
}
else if(cmode == emChangeMode) {
if(getcstat == 'h')
out = XLAT("One wrong move and it is game over!");
}
*/
mouseovers = out;
#ifdef ROGUEVIZ #ifdef ROGUEVIZ
rogueviz::describe(c); rogueviz::describe(c);
#endif #endif
int col = linf[cwt.c->land].color;
if(cwt.c->land == laRedRock) col = 0xC00000;
#ifndef MOBILE
displayfr(vid.xres/2, vid.fsize, 2, vid.fsize, out, col, 8);
#endif
if(mousey < vid.fsize * 3/2) getcstat = SDLK_F1; if(mousey < vid.fsize * 3/2) getcstat = SDLK_F1;
} }

View File

@ -231,6 +231,10 @@ void displayglyph2(int cx, int cy, int buttonsize, int i) {
mouseovers += XLAT(" (click to drop)"); mouseovers += XLAT(" (click to drop)");
getcstat = 'g'; getcstat = 'g';
} }
if(it == itInventory) {
mouseovers += XLAT(" (click to use)");
getcstat = 'i';
}
if(imp & GLYPH_LOCAL) mouseovers += XLAT(" (local treasure)"); if(imp & GLYPH_LOCAL) mouseovers += XLAT(" (local treasure)");
help = generateHelpForItem(it); help = generateHelpForItem(it);
} }

27
hyper.h
View File

@ -559,7 +559,12 @@ bool isFriendly(eMonster m);
bool isFriendly(cell *c); bool isFriendly(cell *c);
bool isChild(cell *w, cell *killed); // is w killed if killed is killed? bool isChild(cell *w, cell *killed); // is w killed if killed is killed?
int gold(); static const int NO_TREASURE = 1;
static const int NO_YENDOR = 2;
static const int NO_GRAIL = 4;
static const int NO_LOVE = 8;
int gold(int no = 0);
int tkills(); int tkills();
bool hellUnlocked(); bool hellUnlocked();
@ -1037,10 +1042,6 @@ void checkmove();
transmatrix eumove(int x, int y); transmatrix eumove(int x, int y);
transmatrix eumovedir(int d); transmatrix eumovedir(int d);
#ifndef NOSAVE
void loadScores();
#endif
int reptilemax(); int reptilemax();
extern bool mousing; extern bool mousing;
@ -1289,7 +1290,9 @@ eLand getNewSealand(eLand old);
bool createOnSea(eLand old); bool createOnSea(eLand old);
namespace inv { namespace inv {
bool on; extern bool on;
extern int remaining[ittypes];
void compute();
} }
bool drawItemType(eItem it, cell *c, const transmatrix& V, int icol, int ticks, bool hidden); bool drawItemType(eItem it, cell *c, const transmatrix& V, int icol, int ticks, bool hidden);
@ -1315,7 +1318,7 @@ template<class T, class U> int addHook(hookset<T>*& m, int prio, const U& hook)
return 0; return 0;
} }
extern purehookset hooks_frame, hooks_stats, clearmemory; extern purehookset hooks_frame, hooks_stats, clearmemory, hooks_config;
template<class T, class... U> void callhooks(hookset<T> *h, U... args) { template<class T, class... U> void callhooks(hookset<T> *h, U... args) {
if(h) for(auto& p: *h) p.second(args...); if(h) for(auto& p: *h) p.second(args...);
@ -1429,10 +1432,10 @@ void switchGL();
void switchFullscreen(); void switchFullscreen();
extern screenmode cmode2; extern screenmode cmode2;
namespace scores { void load(); }
void gotoHelp(const string& h); void gotoHelp(const string& h);
void showCustomizeChar(); void showCustomizeChar();
void showScores();
void showPickScores();
void showCheatMenu(); void showCheatMenu();
void showDisplayMode(); void showDisplayMode();
void showChangeMode(); void showChangeMode();
@ -1445,3 +1448,9 @@ void gamescreen(int darken);
void showMission(); void showMission();
void handleKeyQuit(int sym, int uni); void handleKeyQuit(int sym, int uni);
void handlePanning(int sym, int uni); void handlePanning(int sym, int uni);
#ifdef MOBILE
namespace leader { void showMenu(); void handleKey(int sym, int uni); }
#endif
bool needConfirmation();

View File

@ -1,6 +1,6 @@
#define VER "9.4n2" #define VER "9.4n3"
#define VERNUM 9416 #define VERNUM 9417
#define VERNUM_HEX 0x9416 #define VERNUM_HEX 0x9417
#define GEN_M 0 #define GEN_M 0
#define GEN_F 1 #define GEN_F 1
@ -264,7 +264,7 @@ const char *loadlevel = NULL;
#include "landgen.cpp" #include "landgen.cpp"
#include "orbs.cpp" #include "orbs.cpp"
#ifdef INV #ifdef INV
#include "inventory.cpp" #include "closed/inventory.cpp"
#endif #endif
#include "system.cpp" #include "system.cpp"
#include "geometry.cpp" #include "geometry.cpp"
@ -281,6 +281,7 @@ const char *loadlevel = NULL;
#include "config.cpp" #include "config.cpp"
#include "scores.cpp" #include "scores.cpp"
#include "menus.cpp" #include "menus.cpp"
#include "quit.cpp"
#ifdef FIXEDSIZE #ifdef FIXEDSIZE
#include "nofont.cpp" #include "nofont.cpp"
#endif #endif

View File

@ -361,7 +361,7 @@ void run(const char *fname, int _perdist, double _maxfac) {
} }
void describe(cell *c) { void describe(cell *c) {
if(cmode == emHelp) return; if(cmode2 == smHelp) return;
neuron *n = getNeuronSlow(c); neuron *n = getNeuronSlow(c);
if(!n) return; if(!n) return;
help += "cell number: " + its(n - &net[0]) + "\n"; help += "cell number: " + its(n - &net[0]) + "\n";

View File

@ -1721,7 +1721,7 @@ namespace mapeditor {
if(mapeditor::painttype == 4) if(mapeditor::painttype == 4)
mapeditor::painttype = 0, mapeditor::paintwhat = 0, mapeditor::painttype = 0, mapeditor::paintwhat = 0,
mapeditor::paintwhat_str = "clear monster"; mapeditor::paintwhat_str = "clear monster";
mapeditor::copywhat = NULL; mapeditor::copywhat = NULL;
mapeditor::undo.clear(); mapeditor::undo.clear();
if(!cheater) mapeditor::displaycodes = 0; if(!cheater) mapeditor::displaycodes = 0;
if(!cheater) mapeditor::whichShape = 0; if(!cheater) mapeditor::whichShape = 0;

258
menus.cpp
View File

@ -3,6 +3,8 @@
#include "dialogs.cpp" #include "dialogs.cpp"
// -- overview --
#define BLACKISH 0x404040 #define BLACKISH 0x404040
#define REDDISH 0x400000 #define REDDISH 0x400000
@ -159,6 +161,8 @@ void showOverview() {
}; };
} }
// -- main menu --
bool checkHalloweenDate() { bool checkHalloweenDate() {
time_t t = time(NULL); time_t t = time(NULL);
struct tm tm = *localtime(&t); struct tm tm = *localtime(&t);
@ -241,7 +245,7 @@ void showMainMenu() {
else if(sym == 'd') pushScreen(showDisplayMode); else if(sym == 'd') pushScreen(showDisplayMode);
else if(sym == 'm') pushScreen(showChangeMode); else if(sym == 'm') pushScreen(showChangeMode);
#ifndef NOSAVE #ifndef NOSAVE
else if(sym == 't') loadScores(); else if(sym == 't') scores::load();
#endif #endif
else if(uni == 'y'-96) { else if(uni == 'y'-96) {
if(!sphere) { if(!sphere) {
@ -271,7 +275,7 @@ void showMainMenu() {
#ifdef INV #ifdef INV
else if(sym == 'i') { else if(sym == 'i') {
clearMessages(); clearMessages();
pushScreen(inv::show()); pushScreen(inv::show);
} }
#endif #endif
else if(sym == SDLK_ESCAPE) else if(sym == SDLK_ESCAPE)
@ -294,6 +298,8 @@ void showMainMenu() {
}; };
} }
// -- display modes --
void showDisplayMode() { void showDisplayMode() {
gamescreen(3); gamescreen(3);
@ -308,6 +314,8 @@ void showDisplayMode() {
dialog::addBoolItem(XLAT("big Poincaré model"), vid.alpha == 1 && vid.scale >= 1, '3'); dialog::addBoolItem(XLAT("big Poincaré model"), vid.alpha == 1 && vid.scale >= 1, '3');
dialog::addBoolItem(XLAT("Klein-Beltrami model"), vid.alpha == 0, '4'); dialog::addBoolItem(XLAT("Klein-Beltrami model"), vid.alpha == 0, '4');
dialog::addSelItem(XLAT("wall display mode"), XLAT(wdmodes[vid.wallmode]), '5'); dialog::addSelItem(XLAT("wall display mode"), XLAT(wdmodes[vid.wallmode]), '5');
if(getcstat == '5')
mouseovers = XLAT("also hold Alt during the game to toggle high contrast");
dialog::addBoolItem(XLAT("draw the grid"), (vid.grid), '6'); dialog::addBoolItem(XLAT("draw the grid"), (vid.grid), '6');
dialog::addBoolItem(XLAT("mark heptagons"), (vid.darkhepta), '7'); dialog::addBoolItem(XLAT("mark heptagons"), (vid.darkhepta), '7');
dialog::addSelItem(XLAT("3D configuration"), "", '9'); dialog::addSelItem(XLAT("3D configuration"), "", '9');
@ -383,19 +391,7 @@ void showDisplayMode() {
}; };
} }
void gmodekeys(int sym, int uni) { // -- game modes --
if(uni == '1') { vid.alpha = 999; vid.scale = 998; }
if(uni == '2') { vid.alpha = 1; vid.scale = 0.4; }
if(uni == '3') { vid.alpha = 1; vid.scale = 1; }
if(uni == '4') { vid.alpha = 0; vid.scale = 1; }
if(uni == '5') { vid.wallmode += 60 + (shiftmul > 0 ? 1 : -1); vid.wallmode %= 6; }
if(uni == '6') vid.grid = !vid.grid;
if(uni == '7') { vid.darkhepta = !vid.darkhepta; }
if(uni == '%' && sym == '5') {
if(vid.wallmode == 0) vid.wallmode = 6;
vid.wallmode--;
}
}
void switchHardcore() { void switchHardcore() {
if(hardcore && !canmove) { if(hardcore && !canmove) {
@ -426,16 +422,18 @@ void showChangeMode() {
dialog::addBoolItem(XLAT(SHMUPTITLE), (shmup::on || multi::players > 1), 's'); dialog::addBoolItem(XLAT(SHMUPTITLE), (shmup::on || multi::players > 1), 's');
if(!shmup::on) dialog::addSelItem(XLAT("hardcore mode"), if(!shmup::on) dialog::addSelItem(XLAT("hardcore mode"),
hardcore && !pureHardcore() ? XLAT("PARTIAL") : ONOFF(hardcore), 'h'); hardcore && !pureHardcore() ? XLAT("PARTIAL") : ONOFF(hardcore), 'h');
if(getcstat == 'h')
mouseovers = XLAT("One wrong move and it is game over!");
multi::cpid = 0; multi::cpid = 0;
dialog::addBoolItem(XLAT("%1 Challenge", moPrincess), (princess::challenge), 'p');
dialog::addBoolItem(XLAT("random pattern mode"), (randomPatternsMode), 'r');
dialog::addBoolItem(XLAT("Yendor Challenge"), (yendor::on), 'y');
dialog::addBoolItem(XLAT("pure tactics mode"), (tactic::on), 't');
dialog::addBoolItem(XLAT("heptagonal mode"), (purehepta), '7'); dialog::addBoolItem(XLAT("heptagonal mode"), (purehepta), '7');
dialog::addBoolItem(XLAT("Chaos mode"), (chaosmode), 'C'); dialog::addBoolItem(XLAT("Chaos mode"), (chaosmode), 'C');
dialog::addBoolItem(XLAT("peaceful mode"), (chaosmode), 'P'); dialog::addBoolItem(XLAT("peaceful mode"), (chaosmode), 'p');
dialog::addBoolItem(XLAT("inventory mode"), (inv::on), 'i'); dialog::addBoolItem(XLAT("inventory mode"), (inv::on), 'i');
dialog::addBoolItem(XLAT("pure tactics mode"), (tactic::on), 't');
dialog::addBoolItem(XLAT("Yendor Challenge"), (yendor::on), 'y');
dialog::addBoolItem(XLAT("%1 Challenge", moPrincess), (princess::challenge), 'P');
dialog::addBoolItem(XLAT("random pattern mode"), (randomPatternsMode), 'r');
dialog::addBreak(50); dialog::addBreak(50);
// cheating and map editor // cheating and map editor
@ -489,7 +487,7 @@ void showChangeMode() {
} }
else if(xuni == '7') else if(xuni == '7')
restartGame('7'); restartGame('7');
else if(xuni == 'P') else if(xuni == 'p')
pushScreen(peace::showMenu); pushScreen(peace::showMenu);
else if(xuni == 'i') { else if(xuni == 'i') {
restartGame('i'); restartGame('i');
@ -512,7 +510,7 @@ void showChangeMode() {
if(!princess::everSaved) if(!princess::everSaved)
addMessage(XLAT("Save %the1 first to unlock this challenge!", moPrincess)); addMessage(XLAT("Save %the1 first to unlock this challenge!", moPrincess));
else else
restartGame('p'); restartGame('P');
} }
#ifndef NOEDIT #ifndef NOEDIT
else if(xuni == 'm') { else if(xuni == 'm') {
@ -545,6 +543,8 @@ void showChangeMode() {
}; };
} }
// -- cheat menu --
void showCheatMenu() { void showCheatMenu() {
gamescreen(1); gamescreen(1);
dialog::init("cheat menu"); dialog::init("cheat menu");
@ -592,6 +592,8 @@ void showCheatMenu() {
}; };
} }
// -- geometry menu --
int eupage = 0; int eupage = 0;
int euperpage = 21; int euperpage = 21;
@ -698,27 +700,7 @@ void showEuclideanMenu() {
}; };
} }
#ifdef MOBILE // -- demo --
namespace leader { void showMenu(); void handleKey(int sym, int uni); }
#endif
void handleQuit(int sym, int uni) {
if(uni == 'r' || sym == SDLK_F5) {
restartGame(), popScreen();
msgs.clear();
}
else if(uni == 'v') pushScreen(showMainMenu);
else if(uni == SDLK_ESCAPE) popScreen();
else if(uni == 'o') setAppropriateOverview();
#ifndef NOSAVE
else if(uni == 't') {
if(!canmove) restartGame();
loadScores();
msgs.clear();
}
#endif
}
#ifdef DEMO #ifdef DEMO
bool demoanim; bool demoanim;
@ -804,188 +786,8 @@ void handleDemoKey(int sym, int uni) {
} }
} }
#endif #endif
function <void(int sym, int uni)> keyhandler; // -- overview --
#ifndef MOBILE
void quitOrAgain() {
int y = vid.yres * (618) / 1000;
displayButton(vid.xres/2, y + vid.fsize*1/2,
(items[itOrbSafety] && havesave) ?
XLAT("Press Enter or F10 to save") :
XLAT("Press Enter or F10 to quit"),
SDLK_RETURN, 8, 2);
displayButton(vid.xres/2, y + vid.fsize*2, XLAT("or 'r' or F5 to restart"), 'r', 8, 2);
displayButton(vid.xres/2, y + vid.fsize*7/2, XLAT("or 't' to see the top scores"), 't', 8, 2);
displayButton(vid.xres/2, y + vid.fsize*10/2, XLAT("or 'v' to see the main menu"), 'v', 8, 2);
displayButton(vid.xres/2, y + vid.fsize*13/2, XLAT("or 'o' to see the world overview"), 'o', 8, 2);
}
#endif
int msgscroll = 0;
string timeline() {
int timespent = (int) (savetime + (timerstopped ? 0 : (time(NULL) - timerstart)));
char buf[20];
sprintf(buf, "%d:%02d", timespent/60, timespent % 60);
return
shmup::on ?
XLAT("%1 knives (%2)", its(turncount), buf)
:
XLAT("%1 turns (%2)", its(turncount), buf);
}
void showMission() {
cmode2 = smMission;
gamescreen(1); drawStats();
keyhandler = handleKeyQuit;
dialog::init(
#ifdef TOUR
tour::on ? (canmove ? XLAT("Tutorial") : XLAT("GAME OVER")) :
#endif
cheater ? XLAT("It is a shame to cheat!") :
showoff ? XLAT("Showoff mode") :
canmove && princess::challenge ? XLAT("%1 Challenge", moPrincess) :
canmove ? XLAT("Quest status") :
XLAT("GAME OVER"),
0xC00000, 200, 100
);
dialog::addInfo(XLAT("Your score: %1", its(gold())));
dialog::addInfo(XLAT("Enemies killed: %1", its(tkills())));
#ifdef TOUR
if(tour::on) ; else
#endif
if(items[itOrbYendor]) {
dialog::addInfo(XLAT("Orbs of Yendor found: %1", its(items[itOrbYendor])), iinf[itOrbYendor].color);
dialog::addInfo(XLAT("CONGRATULATIONS!"), iinf[itOrbYendor].color);
}
else {
if(princess::challenge)
dialog::addInfo(XLAT("Follow the Mouse and escape with %the1!", moPrincess));
else if(gold() < R30)
dialog::addInfo(XLAT("Collect %1 $$$ to access more worlds", its(R30)));
else if(gold() < R60)
dialog::addInfo(XLAT("Collect %1 $$$ to access even more lands", its(R60)));
else if(!hellUnlocked())
dialog::addInfo(XLAT("Collect at least %1 treasures in each of 9 types to access Hell", its(R10)));
else if(items[itHell] < R10)
dialog::addInfo(XLAT("Collect at least %1 Demon Daisies to find the Orbs of Yendor", its(R10)));
else if(size(yendor::yi) == 0)
dialog::addInfo(XLAT("Look for the Orbs of Yendor in Hell or in the Crossroads!"));
else
dialog::addInfo(XLAT("Unlock the Orb of Yendor!"));
}
if(!timerstopped && !canmove) {
savetime += time(NULL) - timerstart;
timerstopped = true;
}
if(canmove && !timerstart)
timerstart = time(NULL);
if(princess::challenge) ;
#ifdef TOUR
else if(tour::on) ;
#endif
else if(tkills() < R100)
dialog::addInfo(XLAT("Defeat %1 enemies to access the Graveyard", its(R100)));
else if(kills[moVizier] == 0 && (items[itFernFlower] < U5 || items[itGold] < U5))
dialog::addInfo(XLAT("Kill a Vizier in the Palace to access Emerald Mine"));
else if(items[itEmerald] < U5)
dialog::addInfo(XLAT("Collect 5 Emeralds to access Camelot"));
else if(hellUnlocked() && !chaosmode) {
bool b = true;
for(int i=0; i<LAND_HYP; i++)
if(b && items[treasureType(land_hyp[i])] < R10) {
dialog::addInfo(
XLAT(
land_hyp[i] == laTortoise ? "Hyperstone Quest: collect at least %3 points in %the2" :
"Hyperstone Quest: collect at least %3 %1 in %the2",
treasureType(land_hyp[i]), land_hyp[i], its(R10)));
b = false;
}
if(b)
dialog::addInfo(XLAT("Hyperstone Quest completed!"), iinf[itHyperstone].color);
}
else dialog::addInfo(XLAT("Some lands unlock at specific treasures or kills"));
if(cheater) {
dialog::addInfo(XLAT("you have cheated %1 times", its(cheater)), 0xFF2020);
}
if(!cheater) {
dialog::addInfo(timeline(), 0xC0C0C0);
}
msgs.clear();
if(msgscroll < 0) msgscroll = 0;
int gls = size(gamelog) - msgscroll;
int mnum = 0;
for(int i=gls-5; i<gls; i++)
if(i>=0) {
msginfo m;
m.spamtype = 0;
m.flashout = true;
m.stamp = ticks-128*vid.flashtime-128*(gls-i);
m.msg = gamelog[i].msg;
m.quantity = gamelog[i].quantity;
mnum++,
msgs.push_back(m);
}
dialog::addBreak(100);
bool intour = false;
#ifdef TOUR
intour = tour::on;
#endif
if(intour) {
#ifdef TOUR
if(canmove) {
dialog::addItem(XLAT("spherical geometry"), '1');
dialog::addItem(XLAT("Euclidean geometry"), '2');
dialog::addItem(XLAT("more curved hyperbolic geometry"), '3');
}
if(!items[itOrbTeleport])
dialog::addItem(XLAT("teleport away"), '4');
else if(!items[itOrbAether])
dialog::addItem(XLAT("move through walls"), '4');
else
dialog::addItem(XLAT("flash"), '4');
if(canmove) {
if(tour::slidecommand != "")
dialog::addItem(tour::slidecommand, '5');
dialog::addItem(XLAT("static mode"), '6');
dialog::addItem(XLAT("enable/disable texts"), '7');
dialog::addItem(XLAT("next slide"), SDLK_RETURN);
dialog::addItem(XLAT("previous slide"), SDLK_BACKSPACE);
dialog::addItem(XLAT("list of slides"), '9');
}
else
dialog::addBreak(200);
dialog::addItem(XLAT("main menu"), 'v');
#endif
}
else {
dialog::addItem(XLAT(canmove ? "continue" : "see how it ended"), SDLK_ESCAPE);
dialog::addItem(XLAT("main menu"), 'v');
dialog::addItem(XLAT("restart"), SDLK_F5);
#ifndef MOBILE
dialog::addItem(XLAT(quitsaves() ? "save" : "quit"), SDLK_F10);
#endif
#ifdef ANDROIDSHARE
dialog::addItem(XLAT("SHARE"), 's'-96);
#endif
}
dialog::display();
if(mnum)
displayfr(vid.xres/2, vid.yres-vid.fsize*(mnum+1), 2, vid.fsize/2, XLAT("last messages:"), 0xC0C0C0, 8);
}
void setAppropriateOverview() { void setAppropriateOverview() {
clearMessages(); clearMessages();
@ -1001,9 +803,3 @@ void setAppropriateOverview() {
pushScreen(showOverview); pushScreen(showOverview);
} }
void showMissionScreen() {
popScreenAll();
pushScreen(showMission);
achievement_final(false);
msgscroll = 0;
}

View File

@ -1987,8 +1987,8 @@ slide rvslides[] = {
auto hooks = auto hooks =
addHook(hooks_frame, 0, drawExtra) + addHook(hooks_frame, 0, drawExtra) +
addHook(hooks_args, 100, readArgs) + addHook(hooks_args, 100, readArgs) +
addHook(clearmemory, 0, clear) + addHook(clearmemory, 0, close) +
addHook(hooks_config, 0, [] () { ss::list(rogueviz::rvtour::rvslides); }); addHook(hooks_config, 0, [] () { tour::ss::list(rogueviz::rvtour::rvslides); });
}; };

View File

@ -1,5 +1,9 @@
#ifndef NOSAVE #ifndef NOSAVE
namespace scores {
vector<score> scores; vector<score> scores;
score *currentgame;
int scoresort = 2; int scoresort = 2;
int scoredisplay = 1; int scoredisplay = 1;
@ -15,14 +19,37 @@ bool fakescore() {
return fakebox[scoredisplay]; return fakebox[scoredisplay];
} }
string displayfor(score* S) { int colwidth() {
if(scoredisplay == 0) return 5;
if(scoredisplay == 1) return 16;
if(scoredisplay == 5) return 8;
return 4;
}
string displayfor(score* S, bool shorten = false) {
// printf("S=%p, scoredisplay = %d\n", S, scoredisplay); // printf("S=%p, scoredisplay = %d\n", S, scoredisplay);
if(S == NULL) { if(S == NULL) {
return XLATN(boxname[scoredisplay]); string str = XLATN(boxname[scoredisplay]);
if(!shorten) return str;
if(scoredisplay == 0 || scoredisplay == 65) return XLAT("time");
if(scoredisplay == 2) return "$$$";
if(scoredisplay == 3) return XLAT("kills");
if(scoredisplay == 4) return XLAT("turns");
if(scoredisplay == 5) return XLAT("cells");
if(scoredisplay == 67) return XLAT("cheats");
if(scoredisplay == 66) return XLAT("saves");
if(scoredisplay == 197) return XLAT("players");
int i = 0;
for(int j=0; j<5; j++) if(i < size(str)) getnext(str.c_str(), i);
return str.substr(0, i);
} }
if(scoredisplay == 0) { if(scoredisplay == 0 || scoredisplay == 65) {
char buf[10]; char buf[20];
snprintf(buf, 10, "%d:%02d", S->box[0]/60, S->box[0]%60); int t = S->box[0];
if(t >= 3600)
snprintf(buf, 20, "%d:%02d:%02d", t/3600, (t/60)%60, t%60);
else
snprintf(buf, 20, "%d:%02d", t/60, t%60);
return buf; return buf;
} }
if(scoredisplay == 1) { if(scoredisplay == 1) {
@ -33,58 +60,6 @@ string displayfor(score* S) {
return its(S->box[scoredisplay]); return its(S->box[scoredisplay]);
} }
void loadScores() {
scores.clear();
FILE *f = fopen(scorefile, "rt");
if(!f) {
printf("Could not open the score file '%s'!\n", scorefile);
addMessage(s0 + "Could not open the score file: " + scorefile);
return;
}
while(!feof(f)) {
char buf[120];
if(fgets(buf, 120, f) == NULL) break;
if(buf[0] == 'H' && buf[1] == 'y') {
score sc; bool ok = true;
{if(fscanf(f, "%s", buf) <= 0) break;} sc.ver = buf;
for(int i=0; i<MAXBOX; i++) {
if(fscanf(f, "%d", &sc.box[i]) <= 0) { boxid = i; break; }
}
for(int i=boxid; i<MAXBOX; i++) sc.box[i] = 0;
if(sc.ver >= "4.4") {
sc.box[0] = sc.box[65];
// the first executable on Steam included a corruption
if(sc.box[65] > 1420000000 && sc.box[65] < 1430000000) {
sc.box[0] = sc.box[65] - sc.box[1];
sc.box[65] = sc.box[0];
}
// do not include saves
if(sc.box[65 + 4 + itOrbSafety - itOrbLightning]) ok = false;
}
else
sc.box[0] = sc.box[1] - sc.box[0]; // could not save then
if(ok && boxid > 20) scores.push_back(sc);
}
}
fclose(f);
addMessage(its(size(scores))+" games have been recorded in "+scorefile);
pushScreen(showScores);
boxid = 0; applyBoxes();
scoresort = 2; reverse(scores.begin(), scores.end());
scoremode = 0;
if(shmup::on) scoremode = 1;
else if(hardcore) scoremode = 2;
scorefrom = 0;
stable_sort(scores.begin(), scores.end(), scorecompare);
#ifdef MOBILE
extern int andmode;
andmode = 2;
#endif
}
vector<pair<string, int> > pickscore_options; vector<pair<string, int> > pickscore_options;
void sortScores() { void sortScores() {
@ -101,28 +76,84 @@ void shiftScoreDisplay(int delta) {
if(fakescore()) shiftScoreDisplay(delta); if(fakescore()) shiftScoreDisplay(delta);
} }
void showScores() { int curcol;
int y = vid.fsize * 7/2;
int bx = vid.fsize; vector<int> columns;
getcstat = 1;
bool monsterpage = false;
void showPickScores() {
int d = scoredisplay = columns[curcol];
string modes = pickscore_options.clear();
scoremode == 0 ? XLAT(", m - mode: normal") :
scoremode == 1 ? XLAT(", m - mode: shoot'em up") :
scoremode == 2 ? XLAT(", m - mode: hardcore only") :
"?";
if(euclid) modes += XLAT(" (E:%1)", euclidland); scorerev = false;
for(int i=0; i<POSSCORE; i++) {
scoredisplay = i;
if(!fakescore()) {
string s = displayfor(NULL);
if(mapeditor::hasInfix(s))
if(monsbox[scoredisplay] == monsterpage)
pickscore_options.push_back(make_pair(s, i));
}
}
sort(pickscore_options.begin(), pickscore_options.end());
int q = (int) pickscore_options.size();
int percolumn = vid.yres / (vid.fsize+3) - 4;
int qcolumns = 1 + (q-1) / percolumn;
for(int i=0; i<q; i++) {
int x = 16 + (vid.xres * (i/percolumn)) / qcolumns;
int y = (vid.fsize+3) * (i % percolumn) + vid.fsize*2;
scoredisplay = pickscore_options[i].second;
if(q <= 9)
pickscore_options[i].first = pickscore_options[i].first + " [" + its(i+1) + "]";
if(!fakescore())
displayButton(x, y, pickscore_options[i].first, 1000+i, 0);
}
displayButton(vid.xres/2, vid.yres - vid.fsize*2, "kills", 'm', 8);
mouseovers = XLAT("t/left/right - change display, up/down - scroll, s - sort by") + modes; scoredisplay = d;
displaystr(bx*4, vid.fsize*2, 0, vid.fsize, "#", forecolor, 16); mouseovers = mapeditor::infix;
displaystr(bx*8, vid.fsize*2, 0, vid.fsize, "$$$", forecolor, 16); keyhandler = [] (int sym, int uni) {
displaystr(bx*12, vid.fsize*2, 0, vid.fsize, XLAT("kills"), forecolor, 16); if(uni == 'm') monsterpage = !monsterpage; else
displaystr(bx*18, vid.fsize*2, 0, vid.fsize, XLAT("time"), forecolor, 16); if(uni >= '1' && uni <= '9') uni = uni + 1000 - '1';
displaystr(bx*22, vid.fsize*2, 0, vid.fsize, XLAT("ver"), forecolor, 16); else if(uni >= 1000 && uni < 1000 + size(pickscore_options)) {
displaystr(bx*23, vid.fsize*2, 0, vid.fsize, displayfor(NULL), forecolor, 0); scoredisplay = pickscore_options[uni - 1000].second;
for(int i=0; i<POSSCORE; i++)
if(columns[i] == scoredisplay) swap(columns[i], columns[curcol]);
popScreen();
}
else if(mapeditor::editInfix(uni)) ;
else if(doexiton(sym, uni)) popScreen();
};
}
void show() {
if(columns.size() == 0) for(int i=0; i<POSSCORE; i++) columns.push_back(i);
int y = vid.fsize * 5/2;
int bx = vid.fsize;
getcstat = 0;
displaystr(bx*4, vid.fsize, 0, vid.fsize, "#", forecolor, 16);
displaystr(bx*8, vid.fsize, 0, vid.fsize, XLAT("ver"), forecolor, 16);
int at = 9;
for(int i=0; i<POSSCORE; i++) {
scoredisplay = columns[i];
if(bx*at > vid.xres) break;
if(displaystr(bx*at, vid.fsize, 0, vid.fsize, displayfor(NULL, true), i == curcol ? 0xFFD500 : forecolor, 0))
getcstat = 1000+i;
at += colwidth();
}
if(scorefrom < 0) scorefrom = 0; if(scorefrom < 0) scorefrom = 0;
int id = 0; int id = 0;
int omit = scorefrom; int omit = scorefrom;
@ -144,41 +175,58 @@ void showScores() {
if(wrongtype) { id++; continue; } if(wrongtype) { id++; continue; }
if(omit) { omit--; rank++; id++; continue; } if(omit) { omit--; rank++; id++; continue; }
char buf[16];
rank++; sprintf(buf, "%d", rank); bool cur = S.box[MAXBOX-1];
displaystr(bx*4, y, 0, vid.fsize, buf, 0xC0C0C0, 16); if(cur) {
saveBox();
for(int i=0; i<POSSCORE; i++) S.box[i] = savebox[i];
S.box[0] = S.box[65];
}
int col = cur ? 0xFFD500 : 0xC0C0C0;
sprintf(buf, "%d", S.box[2]);
displaystr(bx*8, y, 0, vid.fsize, buf, 0xC0C0C0, 16); rank++;
displaystr(bx*4, y, 0, vid.fsize, its(rank), col, 16);
sprintf(buf, "%d", S.box[3]); displaystr(bx*8, y, 0, vid.fsize, S.ver, col, 16);
displaystr(bx*12, y, 0, vid.fsize, buf, 0xC0C0C0, 16);
sprintf(buf, "%d:%02d", S.box[0]/60, S.box[0] % 60); int at = 9;
displaystr(bx*18, y, 0, vid.fsize, buf, 0xC0C0C0, 16); for(int i=0; i<POSSCORE; i++) {
scoredisplay = columns[i];
if(bx*at > vid.xres) break;
at += colwidth();
if(displaystr(bx*(at-1), y, 0, vid.fsize, displayfor(&S), col, 16))
getcstat = 1000+i;
}
displaystr(bx*22, y, 0, vid.fsize, S.ver, 0xC0C0C0, 16);
displaystr(bx*23, y, 0, vid.fsize, displayfor(&S), 0xC0C0C0, 0);
y += vid.fsize*5/4; id++; y += vid.fsize*5/4; id++;
} }
#ifdef MOBILE int i0 = vid.yres - vid.fsize;
buttonclicked = false; int xr = vid.xres / 80;
displayabutton(-1, +1, XLAT("SORT"), BTON);
displayabutton( 0, +1, XLAT("PICK"), BTON); string modes =
displayabutton(+1, +1, XLAT("PLAY"), BTON); scoremode == 0 ? XLAT(", m - mode: normal") :
#endif scoremode == 1 ? XLAT(", m - mode: shoot'em up") :
scoremode == 2 ? XLAT(", m - mode: hardcore only") :
"?";
if(euclid) modes += XLAT(" (E:%1)", euclidland);
displayButton(xr*10, i0, IFM("s - ") + XLAT("sort"), 's', 8);
displayButton(xr*25, i0, IFM("t - ") + XLAT("choose"), 't', 8);
displayButton(xr*40, i0, IFM("0 - ") + XLAT("play"), '0', 8);
displayButton(xr*65, i0, IFM("m - ") + modes.substr(6), 'm', 8);
keyhandler = [] (int sym, int uni) { keyhandler = [] (int sym, int uni) {
#ifndef MOBILE if(sym == SDLK_LEFT || sym == SDLK_KP4 || sym == 'h' || sym == 'a') {
if(sym == SDLK_LEFT || sym == SDLK_KP4 || sym == 'h' || sym == 'a') if(curcol > 0) curcol--;
shiftScoreDisplay(-1); }
else if(sym == SDLK_RIGHT || sym == SDLK_KP6 || sym == 'l' || sym == 'd') else if(sym == SDLK_RIGHT || sym == SDLK_KP6 || sym == 'l' || sym == 'd') {
shiftScoreDisplay(1); if(curcol < POSSCORE-1) curcol++;
}
else if(sym >= 1000 && sym < 1000+POSSCORE)
curcol = sym - 1000;
else if(sym == 't') { mapeditor::infix = ""; pushScreen(showPickScores); } else if(sym == 't') { mapeditor::infix = ""; pushScreen(showPickScores); }
else if(sym == SDLK_UP || sym == 'k' || sym == 'w') else if(sym == SDLK_UP || sym == 'k' || sym == 'w')
scorefrom -= 5; scorefrom -= 5;
@ -191,98 +239,88 @@ void showScores() {
else if(sym == 's') sortScores(); else if(sym == 's') sortScores();
else if(sym == 'm') { scoremode++; scoremode %= 3; } else if(sym == 'm') { scoremode++; scoremode %= 3; }
else if(doexiton(sym, uni)) popScreen(); else if(doexiton(sym, uni)) popScreen();
#else
static int scoredragx, scoredragy; static int scoredragy;
extern bool clicked, lclicked; static bool lclicked;
extern int andmode;
if(andmode) { if(mousepressed) {
if(!clicked && !lclicked) { if(!lclicked) {
andmode = 0; // scoredragx = mousex;
scoredragx = mousex;
scoredragy = mousey; scoredragy = mousey;
} }
}
else { else {
if(clicked && !lclicked)
scoredragx = mousex, scoredragy = mousey;
else if(lclicked && !clicked) {
if(mousey > vid.ycenter - 2 * vid.fsize) {
if(mousex < vid.xcenter*2/3) sortScores();
else if(mousex < vid.xcenter*4/3)
cmode = emPickScores;
else andmode = 0, popScreen();
}
}
else if(clicked && lclicked) {
// if(mousex > scoredragx + 80) scoredragx += 80, shiftScoreDisplay(1);
// if(mousex < scoredragx - 80) scoredragx -= 80, shiftScoreDisplay(-1);
while(mousey > scoredragy + vid.fsize) scoredragy += vid.fsize, scorefrom--; while(mousey > scoredragy + vid.fsize) scoredragy += vid.fsize, scorefrom--;
while(mousey < scoredragy - vid.fsize) scoredragy -= vid.fsize, scorefrom++; while(mousey < scoredragy - vid.fsize) scoredragy -= vid.fsize, scorefrom++;
} }
lclicked = mousepressed;
} }
#endif
}; };
} }
bool monsterpage = false; void load() {
scores.clear();
void showPickScores() { FILE *f = fopen(scorefile, "rt");
if(!f) {
getcstat = '0'; printf("Could not open the score file '%s'!\n", scorefile);
int d = scoredisplay; addMessage(s0 + "Could not open the score file: " + scorefile);
return;
pickscore_options.clear();
scorerev = false;
for(int i=0; i<POSSCORE; i++) {
scoredisplay = i;
if(!fakescore()) {
string s = displayfor(NULL);
if(mapeditor::hasInfix(s))
if(monsbox[scoredisplay] == monsterpage)
pickscore_options.push_back(make_pair(s, i));
}
} }
sort(pickscore_options.begin(), pickscore_options.end()); while(!feof(f)) {
char buf[120];
int q = (int) pickscore_options.size(); if(fgets(buf, 120, f) == NULL) break;
int percolumn = vid.yres / (vid.fsize+3) - 4; if(buf[0] == 'H' && buf[1] == 'y') {
int columns = 1 + (q-1) / percolumn; score sc; bool ok = true;
sc.box[MAXBOX-1] = 0;
for(int i=0; i<q; i++) { {if(fscanf(f, "%s", buf) <= 0) break;} sc.ver = buf;
int x = 16 + (vid.xres * (i/percolumn)) / columns;
int y = (vid.fsize+3) * (i % percolumn) + vid.fsize*2;
scoredisplay = pickscore_options[i].second;
if(q <= 9)
pickscore_options[i].first = pickscore_options[i].first + " [" + its(i+1) + "]";
if(!fakescore())
displayButton(x, y, pickscore_options[i].first, 1000+i, 0);
}
displayButton(vid.xres/2, vid.yres - vid.fsize*2, "kills", 'm', 8);
scoredisplay = d; for(int i=0; i<MAXBOX; i++) {
if(fscanf(f, "%d", &sc.box[i]) <= 0) { boxid = i; break; }
}
for(int i=boxid; i<MAXBOX; i++) sc.box[i] = 0;
mouseovers = mapeditor::infix; if(sc.ver >= "4.4") {
keyhandler = [] (int sym, int uni) { sc.box[0] = sc.box[65];
extern int andmode; // the first executable on Steam included a corruption
andmode = 2; if(sc.box[65] > 1420000000 && sc.box[65] < 1430000000) {
if(uni == 'm') monsterpage = !monsterpage; else sc.box[0] = sc.box[65] - sc.box[1];
if(uni >= '1' && uni <= '9') uni = uni + 1000 - '1'; sc.box[65] = sc.box[0];
else if(uni >= 1000 && uni < 1000 + size(pickscore_options)) { }
scoredisplay = pickscore_options[uni - 1000].second; // do not include saves
popScreen(); if(sc.box[65 + 4 + itOrbSafety - itOrbLightning]) ok = false;
}
else
sc.box[0] = sc.box[1] - sc.box[0]; // could not save then
if(sc.box[2] == 0) continue; // do not list zero scores
if(ok && boxid > 20) scores.push_back(sc);
} }
else if(mapeditor::editInfix(uni)) ; }
else if(doexiton(sym, uni)) popScreen();
}; saveBox();
score sc;
for(int i=0; i<POSSCORE; i++) sc.box[i] = savebox[i];
sc.box[MAXBOX-1] = 1; sc.ver = "NOW";
scores.push_back(sc);
fclose(f);
clearMessages();
// addMessage(its(size(scores))+" games have been recorded in "+scorefile);
pushScreen(show);
boxid = 0; applyBoxes();
scoresort = 2; reverse(scores.begin(), scores.end());
scoremode = 0;
if(shmup::on) scoremode = 1;
else if(hardcore) scoremode = 2;
scorefrom = 0;
stable_sort(scores.begin(), scores.end(), scorecompare);
} }
}
#endif #endif

View File

@ -645,6 +645,7 @@ void saveStats(bool emergency = false) {
#endif #endif
if(randomPatternsMode) return; if(randomPatternsMode) return;
if(peace::on) return; if(peace::on) return;
if(!gold()) return;
remove_emergency_save(); remove_emergency_save();

View File

@ -154,6 +154,7 @@ namespace yendor {
int hardness() { int hardness() {
if(peace::on) return 15; // just to generate monsters if(peace::on) return 15; // just to generate monsters
if(!yendor::generating && !yendor::path && !yendor::on) return 0;
int thf = 0; int thf = 0;
for(int i=0; i<size(yi); i++) { for(int i=0; i<size(yi); i++) {
yendorinfo& ye ( yi[i] ); yendorinfo& ye ( yi[i] );