2018-02-08 23:40:26 +00:00
// Hyperbolic Rogue -- help routines
// Copyright (C) 2011-2018 Zeno Rogue, see 'hyper.cpp' for details
2018-06-10 23:58:31 +00:00
namespace hr {
2017-07-10 18:47:38 +00:00
string help ;
function < void ( ) > help_delegate ;
2018-02-26 12:15:33 +00:00
vector < help_extension > help_extensions ;
vector < string > extra_keys = {
" 1 = orthogonal/Gans model " ,
" 2 = small Poincare model/stereographic projection " ,
" 3 = big Poincare model/stereographic projection " ,
" 4 = Klein model/gnomonic projection " ,
" 5 = change wall display mode " ,
" 6 = change grid " ,
" 7 = change heptagon marking " ,
2018-11-08 20:56:06 +00:00
// "8 = change background color",
// "9 = hyperboloid model",
2018-02-26 12:15:33 +00:00
" qweasdzxc, hjklyubn, numpad = move/skip turn " ,
" arrows = panning " ,
" o = world overview " ,
" v = menu " ,
" F1 = help " ,
" F5 = restart game " ,
" F10 = quit game " ,
" Esc = quest status " ,
" Alt+Enter = full screen " ,
" Alt = highlight interesting stuff " ,
" t = use a ranged Orb (target center of the screen) " ,
" g = drop a Dead Orb " ,
" click left mouse button = move/skip " ,
" shift+click left mouse button = use ranged Orb " ,
" click right mouse button = context help " ,
" mousewheel up = panning " ,
" hold middle mouse button = panning " ,
" mousewheel down = move/skip " ,
" shift + mousewheel = change projection " ,
" ctrl + mousewheel = change zoom " ,
" ctrl + shift + mousewheel = change both projection and zoom " ,
" ctrl + hold middle button = move the screen " ,
2018-07-09 16:10:28 +00:00
" shift + middle button = reset position " ,
" shift + F2 = disable the HUD " ,
" shift + F3 = disable the FPS " ,
" shift + F4 = disable the map "
2018-02-26 12:15:33 +00:00
} ;
void buildHelpText ( ) {
2017-07-10 18:47:38 +00:00
DEBB ( DF_GRAPH , ( debugfile , " buildHelpText \n " ) ) ;
2018-02-26 12:15:33 +00:00
help = XLAT ( " Welcome to HyperRogue " ) ;
2017-07-22 23:33:27 +00:00
# if ISANDROID
2018-02-26 12:15:33 +00:00
help + = XLAT ( " for Android " ) ;
2017-07-10 18:47:38 +00:00
# endif
2017-07-22 23:33:27 +00:00
# if ISIOS
2018-02-26 12:15:33 +00:00
help + = XLAT ( " for iOS " ) ;
2017-07-10 18:47:38 +00:00
# endif
2018-02-26 12:15:33 +00:00
help + = XLAT ( " ! (version %1) \n \n " , VER ) ;
2017-07-10 18:47:38 +00:00
2018-02-26 12:15:33 +00:00
help + = XLAT (
2017-07-10 18:47:38 +00:00
" You have been trapped in a strange, non-Euclidean world. Collect as much treasure as possible "
" before being caught by monsters. The more treasure you collect, the more "
" monsters come to hunt you, as long as you are in the same land type. The "
" Orbs of Yendor are the ultimate treasure; get at least one of them to win the game! "
) ;
2018-02-26 12:15:33 +00:00
help + = XLAT ( " (press ESC for some hints about it). " ) ;
help + = " \n \n " ;
2017-07-10 18:47:38 +00:00
2017-08-06 12:50:16 +00:00
if ( ! shmup : : on & & ! hardcore )
2018-02-26 12:15:33 +00:00
help + = XLAT (
2017-08-06 12:50:16 +00:00
" You can fight most monsters by moving into their location. "
" The monster could also kill you by moving into your location, but the game "
" automatically cancels all moves which result in that. \n \n "
) ;
2018-02-11 20:39:08 +00:00
# if CAP_INV
2017-07-16 21:00:55 +00:00
if ( inv : : on )
2018-02-26 12:15:33 +00:00
help + = XLAT (
2017-07-24 22:21:36 +00:00
inv : : helptext
2017-07-16 21:00:55 +00:00
) ;
else
2018-02-11 20:39:08 +00:00
# endif
2018-02-26 12:15:33 +00:00
help + = XLAT (
2017-07-10 18:47:38 +00:00
" There are many lands in HyperRogue. Collect 10 treasure "
" in the given land type to complete it; this enables you to "
" find the magical Orbs of this land, and in some cases "
" get access to new lands. At 25 treasures "
" this type of Orbs starts appearing in other lands as well. Press 'o' to "
" get the details of all the Lands. \n \n " ) ;
2018-02-26 12:15:33 +00:00
help + = " \n \n " ;
2017-07-10 18:47:38 +00:00
2017-07-22 23:33:27 +00:00
# if ISMOBILE
2018-02-26 12:15:33 +00:00
help + = XLAT (
2017-07-10 18:47:38 +00:00
" Usually, you move by touching somewhere on the map; you can also touch one "
" of the four buttons on the map corners to change this (to scroll the map "
" or get information about map objects). You can also touch the "
" numbers displayed to get their meanings. \n "
) ;
# else
2017-08-06 12:50:16 +00:00
if ( DEFAULTCONTROL )
2018-02-26 12:15:33 +00:00
help + = XLAT (
2017-08-06 12:50:16 +00:00
" Move with mouse, num pad, qweadzxc, or hjklyubn. Wait by pressing 's' or '.'. Spin the world with arrows, PageUp/Down, and Home/Space. "
" To save the game you need an Orb of Safety. Press 'v' for the main menu (configuration, special modes, etc.), ESC for the quest status. \n \n "
) ;
2018-02-26 12:15:33 +00:00
help + = XLAT (
2017-07-10 18:47:38 +00:00
" You can right click any element to get more information about it. \n \n "
) ;
2017-07-22 23:33:27 +00:00
# if ISMAC
2018-02-26 12:15:33 +00:00
help + = XLAT ( " (You can also use right Shift) \n \n " ) ;
2017-07-12 16:03:53 +00:00
# endif
2017-07-10 18:47:38 +00:00
# endif
2018-02-26 12:15:33 +00:00
help + = XLAT ( " See more on the website: " )
2017-07-10 18:47:38 +00:00
+ " http//roguetemple.com/z/hyper/ \n \n " ;
2017-07-22 23:33:27 +00:00
# if CAP_TOUR
2018-02-26 12:15:33 +00:00
help + = XLAT ( " Try the Tutorial to help with understanding the "
2017-07-10 18:47:38 +00:00
" geometry of HyperRogue (menu -> special modes). \n \n " ) ;
# endif
2018-02-26 12:15:33 +00:00
help + = XLAT ( " Still confused? Read the FAQ on the HyperRogue website! \n \n " ) ;
2017-07-10 18:47:38 +00:00
2018-02-26 12:15:33 +00:00
help_extensions . clear ( ) ;
help_extensions . push_back ( help_extension { ' c ' , XLAT ( " credits " ) , [ ] ( ) { buildCredits ( ) ; } } ) ;
# if ISMOBILE == 0
help_extensions . push_back ( help_extension { ' k ' , XLAT ( " advanced keyboard shortcuts " ) , [ ] ( ) {
help = " " ;
for ( string s : extra_keys ) help + = s , help + = " \n \n " ;
} } ) ;
# endif
2017-07-10 18:47:38 +00:00
}
2018-02-26 12:15:33 +00:00
void buildCredits ( ) {
help = " " ;
help + = XLAT ( " game design, programming, texts and graphics by Zeno Rogue <zeno@attnam.com> \n \n " ) ;
2017-07-10 18:47:38 +00:00
if ( lang ( ) ! = 0 )
2018-02-26 12:15:33 +00:00
help + = XLAT ( " add credits for your translation here " ) ;
2019-02-08 23:18:56 +00:00
# if !NOLICENSE
2018-02-26 12:15:33 +00:00
help + = XLAT (
2017-07-10 18:47:38 +00:00
" released under GNU General Public License version 2 and thus "
" comes with absolutely no warranty; see COPYING for details \n \n "
) ;
# endif
2018-02-26 12:15:33 +00:00
help + = XLAT (
2017-07-10 18:47:38 +00:00
" special thanks to the following people for their bug reports, feature requests, porting, and other help: \n \n %1 \n \n " ,
2017-09-30 09:33:39 +00:00
" Konstantin Stupnik, ortoslon, chrysn, Adam Borowski, Damyan Ivanov, Ryan Farnsley, mcobit, Darren Grey, tricosahedron, Maciej Chojecki, Marek Čtrnáct, "
" wonderfullizardofoz, Piotr Migdał, tehora, Michael Heerdegen, Sprite Guard, zelda0x181e, Vipul, snowyowl0, Patashu, phenomist, Alan Malloy, Tom Fryers, Sinquetica, _monad, CtrlAltDestroy, jruderman, "
2019-01-03 01:05:41 +00:00
" Kojiguchi Kazuki, baconcow, Alan, SurelyYouJest, hotdogPi, DivisionByZero, xXxWeedGokuxXx, jpystynen, Dmitry Marakasov, Alexandre Moine, Arthur O'Dwyer, "
" Triple_Agent_AAA, bluetailedgnat "
2017-07-10 18:47:38 +00:00
) ;
# ifdef EXTRALICENSE
2018-02-26 12:15:33 +00:00
help + = EXTRALICENSE ;
2017-07-10 18:47:38 +00:00
# endif
2017-07-22 23:33:27 +00:00
# if !ISMOBILE
2018-02-26 12:15:33 +00:00
help + = XLAT (
2017-07-10 18:47:38 +00:00
" \n \n See sounds/credits.txt for credits for sound effects "
) ;
# endif
2018-02-26 12:15:33 +00:00
if ( musiclicense ! = " " ) help + = musiclicense ;
2017-07-10 18:47:38 +00:00
}
string pushtext ( stringpar p ) {
string s = XLAT (
" \n \n Note: when pushing %the1 off a heptagonal cell, you can control the pushing direction "
" by clicking left or right half of the heptagon. " , p ) ;
2017-07-22 23:33:27 +00:00
# if !ISMOBILE
2017-07-10 18:47:38 +00:00
s + = XLAT ( " With the keyboard, you can rotate the view for a similar effect (Page Up/Down). " ) ;
# endif
return s ;
}
string princedesc ( ) {
if ( princessgender ( ) = = GEN_M )
return XLAT ( " Apparently a prince is kept locked somewhere, but you won't ever find him in this hyperbolic palace. " ) ;
else
return XLAT ( " Apparently a princess is kept locked somewhere, but you won't ever find her in this hyperbolic palace. " ) ;
}
2018-09-04 17:53:42 +00:00
string helptitle ( string s , color_t col ) {
2017-07-10 18:47:38 +00:00
return " @ " + its ( col ) + " \t " + s + " \n " ;
}
string princessReviveHelp ( ) {
2017-07-16 21:00:55 +00:00
if ( inv : : on ) return " " ;
2017-07-10 18:47:38 +00:00
string h = " \n \n " +
XLAT ( " Killed %1 can be revived with Orb of the Love, after you collect 20 more $$$. " , moPrincess ) ;
if ( princess : : reviveAt )
h + = " \n \n " +
XLAT ( " %The1 will be revivable at %2 $$$ " , moPrincess , its ( princess : : reviveAt ) ) ;
return h ;
}
void describeOrb ( string & help , const orbinfo & oi ) {
2017-07-16 21:00:55 +00:00
if ( inv : : on ) return ;
eOrbLandRelation olr = getOLR ( oi . orb , getPrizeLand ( ) ) ;
2017-07-10 18:47:38 +00:00
eItem tr = treasureType ( oi . l ) ;
2018-08-17 22:46:45 +00:00
eItem tt = treasureTypeUnlock ( cwt . at - > land , oi . orb ) ;
2018-08-21 16:24:39 +00:00
if ( olr = = olrGuest ) {
for ( auto & oi1 : orbinfos )
if ( ( oi1 . flags & orbgenflags : : NATIVE ) & & oi1 . orb = = oi . orb )
tr = treasureType ( oi1 . l ) ;
}
2018-08-17 22:46:45 +00:00
help + = " \n \n " + XLAT ( olrDescriptions [ olr ] , cwt . at - > land , tr , tt ) ;
2017-07-10 18:47:38 +00:00
int t = items [ tr ] * landMultiplier ( oi . l ) ;
if ( t > = 25 )
if ( olr = = olrPrize25 | | olr = = olrPrize3 | | olr = = olrGuest | | olr = = olrMonster | | olr = = olrAlways ) {
help + = XLAT ( " \n Spawn rate (as prize Orb): %1%/%2 \n " ,
its ( int ( .5 + 100 * orbprizefun ( t ) ) ) ,
its ( oi . gchance ) ) ;
}
if ( t > = 10 )
if ( olr = = olrHub ) {
help + = XLAT ( " \n Spawn rate (in Hubs): %1%/%2 \n " ,
its ( int ( .5 + 100 * orbcrossfun ( t ) ) ) ,
its ( oi . gchance ) ) ;
}
}
2018-05-26 23:09:34 +00:00
string other_geometry ( ) {
return XLAT ( " Note: the rules above correspond to the standard geometry; actual rules in other geometries may be different. " ) ;
}
string other_land ( ) {
return XLAT ( " Note: the rules refer to colors which are not visible in other lands. " ) ;
}
string other_geometry_land ( ) {
2018-08-28 15:17:34 +00:00
if ( S7 ! = 7 | | ! BITRUNCATED ) return other_geometry ( ) ;
2018-05-26 23:09:34 +00:00
else return other_land ( ) ;
}
string forbidden_marked ( ) {
return XLAT ( " When the 'mark heptagons' option (hotkey '7') is on , forbidden moves are marked . " ) ;
}
string forbidden_unmarked ( ) {
return XLAT ( " When the 'mark heptagons' option (hotkey '7') is on , moves between unmarked cells are forbidden . " ) ;
}
2017-07-10 18:47:38 +00:00
string generateHelpForItem ( eItem it ) {
string help = helptitle ( XLATN ( iinf [ it ] . name ) , iinf [ it ] . color ) ;
2018-12-03 22:15:53 +00:00
if ( it = = itCompass & & geometry = = gCrystal )
help + = crystal : : compass_help ( ) ;
else
help + = XLAT ( iinf [ it ] . help ) ;
2017-07-10 18:47:38 +00:00
2017-07-12 16:03:53 +00:00
if ( it = = itSavedPrincess | | it = = itOrbLove ) if ( ! inv : : on )
2017-07-10 18:47:38 +00:00
help + = princessReviveHelp ( ) ;
if ( it = = itTrollEgg )
help + = XLAT ( " \n \n After the Trolls leave, you have 750 turns to collect %the1, or it gets stolen. " , it ) ;
if ( it = = itIvory | | it = = itAmethyst | | it = = itLotus | | it = = itMutant ) {
help + = XLAT (
" \n \n Easy %1 might disappear when you collect more of its kind. " , it ) ;
if ( it ! = itMutant ) help + = XLAT (
" You need to go deep to collect lots of them. " ) ;
}
2017-07-22 23:33:27 +00:00
# if ISMOBILE==1
2017-07-10 18:47:38 +00:00
if ( it = = itOrbSafety )
help + = XLAT ( " This might be very useful for devices with limited memory. " ) ;
# else
if ( it = = itOrbSafety )
help + = XLAT ( " Thus, it is potentially useful for extremely long games, which would eat all the memory on your system otherwise. \n " ) ;
# endif
if ( isRangedOrb ( it ) ) {
help + = XLAT ( " \n This is a ranged Orb. " ) ;
2017-07-22 23:33:27 +00:00
# if ISMOBILE
2017-07-10 18:47:38 +00:00
if ( vid . shifttarget & 2 )
help + = XLAT ( " \n Ranged Orbs can be targeted by long touching the desired location. " ) ;
else
help + = XLAT ( " \n Ranged Orbs can be targeted by touching the desired location. " ) ;
# else
if ( vid . shifttarget & 1 )
2017-07-22 23:33:27 +00:00
help + = XLAT ( " \n Ranged Orbs can be targeted by shift-clicking the desired location. " ) ;
2017-07-10 18:47:38 +00:00
else
help + = XLAT ( " \n Ranged Orbs can be targeted by clicking the desired location. " ) ;
2017-07-22 23:33:27 +00:00
help + = XLAT ( " You can also scroll to the desired location and then press 't'. " ) ;
2017-07-10 18:47:38 +00:00
# endif
help + = XLAT ( " \n You can never target cells which are adjacent to the player character, or ones out of the sight range. " ) ;
}
2017-07-22 23:33:27 +00:00
# if ISMOBILE
2017-07-10 18:47:38 +00:00
if ( it = = itGreenStone )
help + = XLAT ( " You can touch the Dead Orb in your inventory to drop it. " ) ;
# else
if ( it = = itGreenStone )
help + = XLAT ( " You can press 'g' or click them in the list to drop a Dead Orb. " ) ;
# endif
if ( it = = itOrbLightning | | it = = itOrbFlash )
help + = XLAT ( " \n \n This Orb is triggered on your first attack or illegal move. " ) ;
if ( it = = itOrbShield )
help + = XLAT ( " \n \n This Orb protects you from attacks, scents, and insulates you "
" from electricity. It does not let you go through deadly terrain, but "
" if you are attacked with fire, it lets you stay in place in it. " ) ;
2017-10-14 23:32:16 +00:00
if ( it = = itOrbWinter )
2018-08-01 12:05:03 +00:00
help + = XLAT ( " \n \n This orb also allows you to collect items encased in ice. " ) ;
2017-10-14 23:32:16 +00:00
2017-07-10 18:47:38 +00:00
if ( it = = itOrbEmpathy ) {
int cnt = 0 ;
for ( int i = 0 ; i < ittypes ; i + + ) {
eItem it2 = eItem ( i ) ;
if ( isEmpathyOrb ( it2 ) ) {
help + = XLAT ( cnt ? " , %1 " : " %1 " , it2 ) ;
cnt + + ;
}
}
}
2018-02-11 20:39:08 +00:00
# if CAP_INV
2017-07-16 21:00:55 +00:00
if ( inv : : on ) {
if ( it = = itOrbYendor | | it = = itHell ) {
help + = XLAT (
" \n \n In the Orb Strategy Mode, Orbs of Yendor appear in Hell after "
" you collect 25 Demon Daisies in Hell, in Crossroads/Ocean after you collect 50, "
" and everywhere after you collect 100. " ) ;
}
2017-08-06 12:50:16 +00:00
/* if(it == itBone || it == itGreenStone) {
2017-07-16 21:00:55 +00:00
help + = XLAT (
" \n \n In the Orb Strategy Mode, dead orbs are available once you collect "
" 10 Necromancer Totems in the Graveyard. "
) ;
2017-08-06 12:50:16 +00:00
} */
2017-07-16 21:00:55 +00:00
if ( it = = itFeather | | it = = itOrbSafety ) {
help + = XLAT (
" \n \n In the Orb Strategy Mode, Orbs of Safety can be gained by "
" collecting Phoenix Feathers in the Land of Eternal Motion. "
" You can also find unlimited Orbs of Safety in the Crossroads "
" and the Ocean (after collecting 25 Phoenix Feathers) "
" and in the Prairie. "
) ;
}
if ( it = = itOrbYendor | | it = = itHolyGrail )
help + = XLAT (
" \n \n Collect %the1 to gain an extra Orb of the Mirror. "
" You can gain further Orbs of the Mirror by collecting 2, 4, 8... "
) ;
2017-08-14 19:13:06 +00:00
if ( it = = itPower )
help + = XLAT (
" \n \n The amount of Orbs obtained by using Orbs of Mirroring is "
" multiplied by sqrt(1+p/20), where p is the number of Powerstones "
" collected. This also affects the mirrorings which happened before "
" collecting the Powerstones. "
) ;
2017-07-16 21:00:55 +00:00
if ( it = = itOrbLuck )
help + = XLAT (
" \n \n In the Orb Strategy Mode, the Orb of Luck also "
" significantly increases the frequency of Great Walls, Crossroads IV, "
" and sub-lands. "
) ;
if ( it = = itBone )
help + = XLAT (
" \n \n In the Orb Strategy Mode, each 25 Necromancer's Totems "
" you are given a random offensive Orb. "
) ;
2017-10-10 10:43:41 +00:00
if ( inv : : remaining [ it ] | | inv : : usedup [ it ] ) help + = " \n \n " + inv : : osminfo ( it ) ;
inv : : whichorbinfo = it ;
inv : : compute ( ) ;
if ( inv : : orbinfoline ! = " " ) help + = " \n \n " + inv : : orbinfoline ;
if ( inv : : extra ! = " " ) help + = " \n \n Extras: " + inv : : extra ;
2017-07-16 21:00:55 +00:00
}
2018-02-11 20:39:08 +00:00
# endif
2017-07-16 21:00:55 +00:00
2017-07-10 18:47:38 +00:00
if ( itemclass ( it ) = = IC_ORB | | it = = itGreenStone | | it = = itOrbYendor ) {
2018-12-23 02:13:08 +00:00
for ( auto & oi : orbinfos ) {
2017-12-03 18:01:35 +00:00
if ( oi . orb = = it & & oi . is_native ( ) ) describeOrb ( help , oi ) ;
2017-07-10 18:47:38 +00:00
}
}
if ( itemclass ( it ) = = IC_TREASURE ) {
2018-12-23 02:13:08 +00:00
for ( auto & oi : orbinfos ) {
2017-07-10 18:47:38 +00:00
if ( treasureType ( oi . l ) = = it ) {
if ( oi . gchance > 0 ) {
help + = XLAT ( " \n \n Orb unlocked: %1 " , oi . orb ) ;
describeOrb ( help , oi ) ;
}
2018-08-17 22:46:45 +00:00
else if ( oi . l = = cwt . at - > land | | inv : : on ) {
2017-07-10 18:47:38 +00:00
help + = XLAT ( " \n \n Secondary orb: %1 " , oi . orb ) ;
describeOrb ( help , oi ) ;
}
}
}
}
2018-05-26 23:09:34 +00:00
2018-08-28 15:17:34 +00:00
if ( it = = itOrb37 & & ( S7 ! = 7 | | ! BITRUNCATED ) )
2018-05-26 23:09:34 +00:00
help + = " \n \n " + other_geometry ( ) + forbidden_unmarked ( ) ;
2018-08-28 15:17:34 +00:00
if ( it = = itOrbLava & & ( S7 ! = 7 | | ! BITRUNCATED ) )
2018-05-26 23:09:34 +00:00
help + = " \n \n " + other_geometry ( ) + forbidden_unmarked ( ) ;
if ( among ( it , itOrbSide2 , itOrbSide3 ) & & ! among ( S7 , 6 , 7 ) )
help + = " \n \n " + other_geometry ( ) + XLAT ( " This orb lets you attack adjacent cells %1 steps from the primary target. " , its ( it - itOrbSide1 + 1 ) ) ;
2017-07-10 18:47:38 +00:00
2018-02-11 20:39:08 +00:00
# if CAP_INV
2017-10-14 11:07:13 +00:00
if ( inv : : on & & it = = itInventory )
help + = " \n \n " + XLAT ( inv : : helptext ) ;
2018-02-11 20:39:08 +00:00
# endif
2018-06-12 16:26:20 +00:00
# if CAP_DAILY
if ( daily : : on & & it = = itOrbLove )
help + = " \n \n " + XLAT ( " The Orb of Love gives no bonus score in the Strange Challenge. " ) ;
# endif
2017-07-10 18:47:38 +00:00
return help ;
}
void addMinefieldExplanation ( string & s ) {
s + = XLAT (
2019-02-06 17:03:16 +00:00
" \n \n Once you collect a Bomberbird Egg, "
2017-07-10 18:47:38 +00:00
" stepping on a cell with no adjacent mines also reveals the adjacent cells. "
2019-02-06 17:03:16 +00:00
" Collecting even more Eggs will increase the radius. "
2017-07-10 18:47:38 +00:00
) ;
s + = " \n \n " ;
2019-02-09 20:02:18 +00:00
# if ISMOBILE==0
2017-07-10 18:47:38 +00:00
s + = XLAT ( " Known mines may be marked by pressing 'm'. Your allies won't step on marked mines. " ) ;
# else
s + = XLAT ( " Known mines may be marked by touching while in drag mode. Your allies won't step on marked mines. " ) ;
# endif
}
string generateHelpForWall ( eWall w ) {
string s = helptitle ( XLATN ( winf [ w ] . name ) , winf [ w ] . color ) ;
s + = XLAT ( winf [ w ] . help ) ;
if ( w = = waMineMine | | w = = waMineUnknown | | w = = waMineOpen )
addMinefieldExplanation ( s ) ;
if ( isThumper ( w ) ) s + = pushtext ( w ) ;
2018-08-28 15:17:34 +00:00
if ( ( w = = waClosePlate | | w = = waOpenPlate ) & & PURE )
2017-07-10 18:47:38 +00:00
s + = " \n \n (For the heptagonal mode, the radius has been reduced to 2 for closing plates.) " ;
return s ;
}
void buteol ( string & s , int current , int req ) {
2018-06-22 12:47:24 +00:00
int siz = isize ( s ) ;
2017-07-10 18:47:38 +00:00
if ( s [ siz - 1 ] = = ' \n ' ) s . resize ( siz - 1 ) ;
char buf [ 100 ] ; sprintf ( buf , " (%d/%d) " , current , req ) ;
s + = buf ; s + = " \n " ;
}
string generateHelpForMonster ( eMonster m ) {
string s = helptitle ( XLATN ( minf [ m ] . name ) , minf [ m ] . color ) ;
if ( m = = moPlayer ) {
2017-07-22 23:33:27 +00:00
# if CAP_TOUR
2017-07-24 22:21:36 +00:00
if ( tour : : on | | peace : : on )
2017-07-10 18:47:38 +00:00
return s + XLAT (
" A tourist from another world. They mutter something about the 'tutorial', "
" and claim that they are here just to learn, and to leave without any treasures. "
" Do not kill them! "
) ;
# endif
2017-07-24 22:21:36 +00:00
2017-07-10 18:47:38 +00:00
s + = XLAT (
" This monster has come from another world, presumably to steal our treasures. "
" Not as fast as an Eagle, not as resilient as the guards from the Palace, "
" and not as huge as the Mutant Ivy from the Clearing; however, "
" they are very dangerous because of their intelligence, "
" and access to magical powers. \n \n " ) ;
if ( cheater )
s + = XLAT ( " Actually, their powers appear god-like... \n \n " ) ;
else if ( ! hardcore )
s + = XLAT (
" Rogues will never make moves which result in their immediate death. "
" Even when cornered, they are able to instantly teleport back to their "
" home world at any moment, taking the treasures forever... but "
" at least they will not steal anything further! \n \n "
) ;
if ( ! euclid )
s + = XLAT (
" Despite this intelligence, Rogues appear extremely surprised "
" by the most basic facts about geometry. They must come from "
" some really strange world. \n \n "
) ;
if ( shmup : : on )
s + = XLAT ( " In the Shoot'em Up mode, you are armed with thrown Knives. " ) ;
return s ;
}
s + = XLAT ( minf [ m ] . help ) ;
if ( m = = moPalace | | m = = moSkeleton )
s + = pushtext ( m ) ;
if ( m = = moTroll ) s + = XLAT ( trollhelp2 ) ;
if ( isMonsterPart ( m ) )
s + = XLAT ( " \n \n This is a part of a monster. It does not count for your total kills. " , m ) ;
if ( isFriendly ( m ) )
s + = XLAT ( " \n \n This is a friendly being. It does not count for your total kills. " , m ) ;
if ( m = = moTortoise )
s + = XLAT ( " \n \n Tortoises are not monsters! They are just annoyed. They do not count for your total kills. " , m ) ;
if ( isGhost ( m ) )
s + = XLAT ( " \n \n A Ghost never moves to a cell which is adjacent to another Ghost of the same kind. " , m ) ;
if ( m = = moBat | | m = = moEagle )
s + = XLAT ( " \n \n Fast flying creatures may attack or go against gravity only in their first move. " , m ) ;
2018-05-26 23:09:34 +00:00
if ( m = = moAltDemon )
s + = " \n \n " + other_geometry_land ( ) + forbidden_unmarked ( ) ;
if ( among ( m , moHexDemon , moHexSnake , moHexSnakeTail ) )
s + = " \n \n " + other_geometry_land ( ) + forbidden_marked ( ) ;
2018-08-28 15:17:34 +00:00
if ( among ( m , moKrakenT , moKrakenH ) & & ( S7 ! = 7 | | ! BITRUNCATED ) )
2018-05-26 23:09:34 +00:00
s + = " \n \n " + other_geometry ( ) + XLAT ( " Forbidden cells are marked with a different color. " ) ;
2017-07-10 18:47:38 +00:00
return s ;
}
string generateHelpForLand ( eLand l ) {
string s = helptitle ( XLATN ( linf [ l ] . name ) , linf [ l ] . color ) ;
if ( l = = laPalace ) s + = princedesc ( ) ;
s + = XLAT ( linf [ l ] . help ) ;
if ( l = = laMinefield ) addMinefieldExplanation ( s ) ;
s + = " \n \n " ;
if ( l = = laIce | | l = = laCaves | | l = = laDesert | | l = = laMotion | | l = = laJungle | |
2017-10-13 19:33:06 +00:00
l = = laCrossroads | | l = = laAlchemist | | l = = laHunting )
2017-07-10 18:47:38 +00:00
s + = XLAT ( " Always available. \n " ) ;
# define ACCONLY(z) s += XLAT("Accessible only from %the1.\n", z);
# define ACCONLY2(z,x) s += XLAT("Accessible only from %the1 or %the2.\n", z, x);
# define ACCONLYF(z) s += XLAT("Accessible only from %the1 (until finished).\n", z);
# define TREQ(z) { s += XLAT("Treasure required: %1 $$$.\n", its(z)); buteol(s, gold(), z); }
# define TREQ2(z,x) { s += XLAT("Treasure required: %1 x %2.\n", its(z), x); buteol(s, items[x], z); }
2018-12-23 16:43:08 +00:00
# define TREQ3(z,x) { int now = 0; string t = ""; for(eItem i: x) { if(t!="") t += " + "; t += XLATN(iinf[i].name); now += items[i]; } s += XLAT("Treasure required: %1 x %2.\n", its(z), t); buteol(s, now, z); }
2017-07-10 18:47:38 +00:00
if ( l = = laMirror | | l = = laMinefield | | l = = laPalace | |
l = = laOcean | | l = = laLivefjord | | l = = laZebra | | l = = laWarpCoast | | l = = laWarpSea | |
2018-01-04 19:05:34 +00:00
l = = laReptile | | l = = laIvoryTower | | l = = laSwitch )
2017-07-10 18:47:38 +00:00
TREQ ( R30 )
2017-08-14 19:13:06 +00:00
if ( l = = laPower & & inv : : on )
help + = XLAT (
" \n \n The amount of Orbs obtained by using Orbs of Mirroring is "
" multiplied by sqrt(1+p/20), where p is the number of Powerstones "
" collected. This also affects the mirrorings which happened before "
" collecting the Powerstones. "
) ;
2017-07-10 18:47:38 +00:00
if ( isCoastal ( l ) )
s + = XLAT ( " Coastal region -- connects inland and aquatic regions. \n " ) ;
if ( isPureSealand ( l ) )
s + = XLAT ( " Aquatic region -- accessible only from coastal regions and other aquatic regions. \n " ) ;
if ( l = = laWhirlpool ) ACCONLY ( laOcean )
if ( l = = laRlyeh ) ACCONLYF ( laOcean )
if ( l = = laTemple ) ACCONLY ( laRlyeh )
if ( l = = laClearing ) ACCONLY ( laOvergrown )
if ( l = = laHaunted ) ACCONLY ( laGraveyard )
if ( l = = laPrincessQuest ) ACCONLY ( laPalace )
if ( l = = laMountain ) ACCONLY ( laJungle )
if ( l = = laCamelot ) ACCONLY2 ( laCrossroads , laCrossroads3 )
if ( l = = laDryForest | | l = = laWineyard | | l = = laDeadCaves | | l = = laHive | | l = = laRedRock | |
2017-11-03 21:41:13 +00:00
l = = laOvergrown | | l = = laStorms | | l = = laWhirlwind | |
2017-10-13 19:33:06 +00:00
l = = laCrossroads2 | | l = = laRlyeh | | l = = laVolcano )
2017-07-10 18:47:38 +00:00
TREQ ( R60 )
if ( l = = laReptile ) TREQ2 ( U10 , itElixir )
2017-10-13 19:33:06 +00:00
if ( l = = laVolcano ) TREQ2 ( U10 , itElixir )
2018-01-04 19:05:34 +00:00
if ( l = = laSwitch ) TREQ2 ( U10 , itElixir )
2017-07-10 18:47:38 +00:00
if ( l = = laEndorian ) TREQ2 ( U10 , itIvory )
if ( l = = laKraken ) TREQ2 ( U10 , itFjord )
if ( l = = laBurial ) TREQ2 ( U10 , itKraken )
if ( l = = laDungeon ) TREQ2 ( U5 , itIvory )
if ( l = = laDungeon ) TREQ2 ( U5 , itPalace )
if ( l = = laMountain ) TREQ2 ( U5 , itIvory )
if ( l = = laMountain ) TREQ2 ( U5 , itRuby )
2017-10-13 19:33:06 +00:00
if ( l = = laBlizzard ) TREQ2 ( U5 , itDiamond )
if ( l = = laBlizzard ) TREQ2 ( U5 , itWindstone )
2018-12-23 16:43:08 +00:00
if ( l = = laWestWall ) TREQ2 ( U5 , itIvory )
if ( l = = laWestWall ) TREQ2 ( U5 , itFeather )
if ( l = = laBrownian ) TREQ ( R30 )
if ( l = = laVariant ) {
const auto lst = vector < eItem > { itRuins , itEmerald , itBone } ;
TREQ3 ( variant_unlock_value ( ) , lst )
}
2017-07-10 18:47:38 +00:00
if ( l = = laPrairie ) TREQ ( R90 )
if ( l = = laBull ) TREQ ( R90 )
2017-11-03 21:41:13 +00:00
if ( l = = laRose ) TREQ ( R90 )
2017-10-13 19:33:06 +00:00
if ( l = = laTerracotta ) TREQ ( R90 )
2017-07-10 18:47:38 +00:00
if ( l = = laCrossroads4 ) TREQ ( R200 )
if ( l = = laCrossroads5 ) TREQ ( R300 )
if ( l = = laGraveyard | | l = = laHive ) {
s + = XLAT ( " Kills required: %1. \n " , " 100 " ) ;
buteol ( s , tkills ( ) , R100 ) ;
}
if ( l = = laDragon ) {
s + = XLAT ( " Different kills required: %1. \n " , " 20 " ) ;
buteol ( s , killtypes ( ) , R20 ) ;
}
if ( l = = laTortoise ) ACCONLY ( laDragon )
if ( l = = laTortoise ) s + = XLAT ( " Find a %1 in %the2. " , itBabyTortoise , laDragon ) ;
if ( l = = laHell | | l = = laCrossroads3 ) {
s + = XLAT ( " Finished lands required: %1 (collect %2 treasure) \n " , " 9 " , its ( R10 ) ) ;
buteol ( s , orbsUnlocked ( ) , 9 ) ;
}
if ( l = = laCocytus | | l = = laPower ) TREQ2 ( U10 , itHell )
if ( l = = laRedRock ) TREQ2 ( U10 , itSpice )
if ( l = = laOvergrown ) TREQ2 ( U10 , itRuby )
if ( l = = laClearing ) TREQ2 ( U5 , itMutant )
if ( l = = laCocytus ) TREQ2 ( U10 , itDiamond )
if ( l = = laDeadCaves ) TREQ2 ( U10 , itGold )
if ( l = = laTemple ) TREQ2 ( U5 , itStatue )
if ( l = = laHaunted ) TREQ2 ( U10 , itBone )
if ( l = = laCamelot ) TREQ2 ( U5 , itEmerald )
if ( l = = laEmerald ) {
2017-08-17 23:18:21 +00:00
TREQ2 ( U5 , itFernFlower ) TREQ2 ( U5 , itGold )
2017-07-10 18:47:38 +00:00
s + = XLAT ( " Alternatively: kill a %1 in %the2. \n " , moVizier , laPalace ) ;
buteol ( s , kills [ moVizier ] , 1 ) ;
}
# define KILLREQ(who, where) { s += XLAT("Kills required: %1 (%2).\n", who, where); buteol(s, kills[who], 1); }
if ( l = = laPrincessQuest )
KILLREQ ( moVizier , laPalace ) ;
if ( l = = laElementalWall ) {
KILLREQ ( moFireElemental , laDragon ) ;
KILLREQ ( moEarthElemental , laDeadCaves ) ;
KILLREQ ( moWaterElemental , laLivefjord ) ;
KILLREQ ( moAirElemental , laWhirlwind ) ;
}
2018-01-03 20:51:11 +00:00
if ( l = = laRuins )
2018-01-03 20:49:31 +00:00
KILLREQ ( moSkeleton , laPalace ) ;
2017-07-10 18:47:38 +00:00
if ( l = = laTrollheim ) {
KILLREQ ( moTroll , laCaves ) ;
KILLREQ ( moFjordTroll , laLivefjord ) ;
KILLREQ ( moDarkTroll , laDeadCaves ) ;
KILLREQ ( moStormTroll , laStorms ) ;
KILLREQ ( moForestTroll , laOvergrown ) ;
KILLREQ ( moRedTroll , laRedRock ) ;
}
if ( l = = laZebra ) TREQ2 ( U10 , itFeather )
if ( l = = laCamelot | | l = = laPrincessQuest )
s + = XLAT ( " Completing the quest in this land is not necessary for the Hyperstone Quest. " ) ;
int rl = isRandland ( l ) ;
if ( rl = = 2 )
s + = XLAT ( " Variants of %the1 are always available in the Random Pattern Mode. " , l ) ;
else if ( rl = = 1 )
s + = XLAT (
" Variants of %the1 are available in the Random Pattern Mode after "
" getting a highscore of at least 10 %2. " , l , treasureType ( l ) ) ;
if ( l = = laPrincessQuest ) {
s + = XLAT ( " Unavailable in the shmup mode. \n " ) ;
s + = XLAT ( " Unavailable in the multiplayer mode. \n " ) ;
}
2017-12-21 15:35:19 +00:00
/* if(noChaos(l))
s + = XLAT ( " Unavailable in the Chaos mode. \n " ) ; */
2017-07-10 18:47:38 +00:00
if ( l = = laWildWest )
s + = XLAT ( " Bonus land, available only in some special modes. \n " ) ;
if ( l = = laWhirlpool )
s + = XLAT ( " Orbs of Safety always appear here, and may be used to escape. \n " ) ;
/* if(isHaunted(l) || l == laDungeon)
s + = XLAT ( " You may be unable to leave %the1 if you are not careful! \n " , l ) ; */
if ( l = = laStorms ) {
if ( elec : : lightningfast = = 0 ) s + = XLAT ( " \n Special conduct (still valid) \n " ) ;
else s + = XLAT ( " \n Special conduct failed: \n " ) ;
s + = XLAT (
" Avoid escaping from a discharge ( \" That was close \" ). " ) ;
}
if ( isHaunted ( l ) ) {
if ( survivalist ) s + = XLAT ( " \n Special conduct (still valid) \n " ) ;
else s + = XLAT ( " \n Special conduct failed: \n " ) ;
s + = XLAT (
" Avoid chopping trees, using Orbs, and non-graveyard monsters in the Haunted Woods. "
) ;
}
2018-04-13 11:08:41 +00:00
2018-12-25 22:54:34 +00:00
if ( l = = laCamelot & & geometry = = gCrystal ) {
if ( ! crystal : : used_compass_inside ) s + = XLAT ( " \n Special conduct (still valid) \n " ) ;
else s + = XLAT ( " \n Special conduct failed: \n " ) ;
s + = XLAT (
" Do not use compases. \n \n " ) ;
s + = XLAT ( " Crystal Camelot is an octahedron in 'pure' 3D crystal geometry (and a similar polytope in other pure crystals), "
" and an Euclidean ball in bitruncated/Goldberg crystals. " ) ;
}
2019-01-03 01:06:50 +00:00
auto lv = land_validity ( l ) ;
2018-04-13 11:08:41 +00:00
if ( lv . flags & lv : : display_in_help )
s + = " \n \n " + XLAT ( lv . msg ) ;
2017-07-10 18:47:38 +00:00
2017-07-22 23:33:27 +00:00
# if !ISMOBILE
2017-07-10 18:47:38 +00:00
if ( l = = laCA )
s + = XLAT ( " \n \n Hint: use 'm' to toggle cells quickly " ) ;
# endif
return s ;
}
bool instat ;
string turnstring ( int i ) {
if ( i = = 1 ) return XLAT ( " 1 turn " ) ;
else return XLAT ( " %1 turns " , its ( i ) ) ;
}
2017-10-08 23:40:32 +00:00
reaction_t helpgenerator ;
string bygen ( reaction_t h ) {
helpgenerator = h ;
return " HELPGEN " ;
}
void gotoHelpFor ( eLand l ) ;
void gotoHelpFor ( eItem i ) {
help = generateHelpForItem ( i ) ;
}
void gotoHelpFor ( eWall w ) {
help = generateHelpForWall ( w ) ;
} ;
void gotoHelpFor ( eMonster m ) {
help = generateHelpForMonster ( m ) ;
} ;
2017-11-06 21:01:53 +00:00
void appendHelp ( string s ) {
auto h = helpgenerator ;
if ( help = = " HELPGEN " )
bygen ( [ h , s ] { h ( ) ; help + = s ; } ) ;
else
help + = s ;
}
2017-10-09 11:00:08 +00:00
unsigned char lastval ;
int windtotal ;
2018-07-09 18:09:56 +00:00
hookset < void ( cell * ) > * hooks_mouseover ;
2017-07-10 18:47:38 +00:00
void describeMouseover ( ) {
DEBB ( DF_GRAPH , ( debugfile , " describeMouseover \n " ) ) ;
2018-08-17 22:46:45 +00:00
cell * c = mousing ? mouseover : playermoved ? NULL : centerover . at ;
2017-07-12 16:03:53 +00:00
string & out = mouseovers ;
if ( ! c | | instat | | getcstat ! = ' - ' ) { }
2017-07-10 18:47:38 +00:00
else if ( c - > wall ! = waInvisibleFloor ) {
out = XLAT1 ( linf [ c - > land ] . name ) ;
2017-10-08 23:40:32 +00:00
help = bygen ( [ c ] ( ) { gotoHelpFor ( c - > land ) ; } ) ;
2017-07-16 21:00:55 +00:00
2017-09-30 09:33:39 +00:00
if ( isIcyLand ( c ) )
2017-07-10 18:47:38 +00:00
out + = " ( " + fts ( heat : : celsius ( c ) ) + " °C) " ;
if ( c - > land = = laDryForest & & c - > landparam )
out + = " ( " + its ( c - > landparam ) + " /10) " ;
if ( c - > land = = laOcean & & chaosmode )
out + = " ( " + its ( c - > CHAOSPARAM ) + " S " + its ( c - > SEADIST ) + " L " + its ( c - > LANDDIST ) + " ) " ;
else if ( c - > land = = laOcean & & c - > landparam < = 25 ) {
if ( shmup : : on )
out + = " ( " + its ( c - > landparam ) + " ) " ;
else {
bool b = c - > landparam > = tide [ ( turncount - 1 ) % tidalsize ] ;
int t = 1 ;
for ( ; t < 1000 & & b = = ( c - > landparam > = tide [ ( turncount + t - 1 ) % tidalsize ] ) ; t + + ) ;
if ( b )
out + = " ( " + turnstring ( t ) + XLAT ( " to surface " ) + " ) " ;
else
out + = " ( " + turnstring ( t ) + XLAT ( " to submerge " ) + " ) " ;
}
}
2017-10-09 11:00:08 +00:00
else if ( c - > land = = laVolcano ) {
2017-10-11 20:16:07 +00:00
int id = lavatide ( c , - 1 ) / 4 ;
2017-10-09 11:00:08 +00:00
if ( id < 96 / 4 )
out + = " ( " + turnstring ( 96 / 4 - id ) + XLAT ( " to go cold " ) + " ) " ;
else
out + = " ( " + turnstring ( 256 / 4 - id ) + XLAT ( " to submerge " ) + " ) " ;
}
else if ( c - > land = = laBlizzard ) {
int wm = windmap : : at ( c ) ;
windtotal + = ( signed char ) ( wm - lastval ) ;
lastval = wm ;
2018-08-17 22:46:45 +00:00
if ( c = = cwt . at ) windtotal = 0 ;
2017-10-09 11:00:08 +00:00
out + = " [ " + its ( windtotal ) + " ] " ;
}
2017-07-10 18:47:38 +00:00
if ( c - > land = = laTortoise & & tortoise : : seek ( ) ) out + = " " + tortoise : : measure ( getBits ( c ) ) ;
if ( buggyGeneration ) {
2017-07-16 21:00:55 +00:00
char buf [ 80 ] ; sprintf ( buf , " %p H=%d M=%d " , c , c - > landparam , c - > mpdist ) ; out + = buf ;
2017-07-10 18:47:38 +00:00
}
if ( randomPatternsMode )
out + = " " + describeRPM ( c - > land ) ;
if ( euclid & & cheater ) {
2017-12-28 15:46:10 +00:00
out + = " ( " + its ( cell_to_vec ( c ) ) + " ) " ;
2018-11-27 01:32:11 +00:00
if ( ! fulltorus | | torusconfig : : torus_mode ! = torusconfig : : tmSingle ) {
2017-12-28 15:46:10 +00:00
int x , y ;
tie ( x , y ) = cell_to_pair ( c ) ;
2017-07-10 18:47:38 +00:00
out + = " ( " + its ( short ( x ) ) + " , " + its ( short ( y ) ) + " ) " ;
}
}
2017-10-30 08:12:03 +00:00
if ( c - > wall & & ! ( c - > wall = = waChasm & & c - > land = = laDual & & ctof ( c ) ) & &
2018-01-25 18:49:19 +00:00
! ( c - > land = = laMemory ) & &
2017-09-30 09:33:39 +00:00
! ( ( c - > wall = = waFloorA | | c - > wall = = waFloorB ) & & c - > item ) ) {
2017-07-10 18:47:38 +00:00
out + = " , " ; out + = XLAT1 ( winf [ c - > wall ] . name ) ;
if ( c - > wall = = waRose ) out + = " ( " + its ( 7 - rosephase ) + " ) " ;
if ( ( c - > wall = = waBigTree | | c - > wall = = waSmallTree ) & & c - > land ! = laDryForest )
help =
" Trees in this forest can be chopped down. Big trees take two turns to chop down. " ;
2017-10-08 23:40:32 +00:00
else
if ( c - > wall ! = waSea & & c - > wall ! = waPalace & & c - > wall ! = waDeadfloor )
if ( ! ( ( c - > wall = = waCavefloor | | c - > wall = = waCavewall ) & & ( c - > land = = laEmerald & & c - > land = = laCaves ) ) )
if ( ! ( ( isAlch ( c - > wall ) & & c - > land = = laAlchemist ) ) )
help = bygen ( [ c ] ( ) { gotoHelpFor ( c - > wall ) ; } ) ;
2017-07-10 18:47:38 +00:00
}
if ( isActivable ( c ) ) out + = XLAT ( " (touch to activate) " ) ;
if ( hasTimeout ( c ) ) out + = " [ " + turnstring ( c - > wparam ) + " ] " ;
if ( isReptile ( c - > wall ) )
out + = " [ " + turnstring ( ( unsigned char ) c - > wparam ) + " ] " ;
if ( c - > monst ) {
out + = " , " ; out + = XLAT1 ( minf [ c - > monst ] . name ) ;
if ( hasHitpoints ( c - > monst ) )
out + = " ( " + its ( c - > hitpoints ) + " HP) " ;
if ( isMutantIvy ( c ) )
out + = " ( " + its ( ( c - > stuntime - mutantphase ) & 15 ) + " *) " ;
else if ( c - > stuntime )
out + = " ( " + its ( c - > stuntime ) + " *) " ;
if ( c - > monst = = moTortoise & & tortoise : : seek ( ) )
out + = " " + tortoise : : measure ( tortoise : : getb ( c ) ) ;
2017-10-08 23:40:32 +00:00
help = bygen ( [ c ] ( ) { gotoHelpFor ( c - > monst ) ; } ) ;
2017-07-10 18:47:38 +00:00
}
if ( c - > item & & ! itemHiddenFromSight ( c ) ) {
out + = " , " ;
out + = XLAT1 ( iinf [ c - > item ] . name ) ;
if ( c - > item = = itBarrow ) out + = " (x " + its ( c - > landparam ) + " ) " ;
2017-10-15 21:09:08 +00:00
if ( c - > land = = laHunting ) {
int i = ambushSize ( c , c - > item ) ;
2017-10-17 11:12:19 +00:00
if ( i ) out + = " ( " + XLAT ( " ambush: " ) + " " + its ( i ) + " ) " ;
2017-10-15 21:09:08 +00:00
}
2017-07-10 18:47:38 +00:00
if ( c - > item = = itBabyTortoise & & tortoise : : seek ( ) )
out + = " " + tortoise : : measure ( tortoise : : babymap [ c ] ) ;
2017-10-08 23:40:32 +00:00
if ( ! c - > monst )
2017-10-10 12:04:28 +00:00
help = bygen ( [ c ] ( ) { gotoHelpFor ( c - > item ) ; } ) ;
2017-07-10 18:47:38 +00:00
}
if ( isPlayerOn ( c ) & & ! shmup : : on ) out + = XLAT ( " , you " ) , help = generateHelpForMonster ( moPlayer ) ;
shmup : : addShmupHelp ( out ) ;
if ( rosedist ( c ) = = 1 )
out + = " , wave of scent (front) " ;
if ( rosedist ( c ) = = 2 )
out + = " , wave of scent (back) " ;
if ( sword : : at ( c ) ) out + = " , Energy Sword " ;
if ( rosedist ( c ) | | c - > land = = laRose | | c - > wall = = waRose )
2017-11-06 21:01:53 +00:00
appendHelp ( string ( " \n \n " ) + rosedesc ) ;
2017-07-10 18:47:38 +00:00
if ( isWarped ( c ) & & ! isWarped ( c - > land ) )
out + = " , warped " ;
2018-05-26 23:09:34 +00:00
if ( isWarped ( c ) ) {
appendHelp ( string ( " \n \n " ) + XLAT ( warpdesc ) ) ;
2018-08-28 15:17:34 +00:00
if ( S7 ! = 7 | | ! BITRUNCATED ) if ( c - > item ! = itOrb37 )
2018-05-26 23:09:34 +00:00
help + = " \n \n " + other_geometry ( ) + forbidden_unmarked ( ) ;
}
2017-07-10 18:47:38 +00:00
}
2018-09-27 19:51:48 +00:00
else {
shmup : : addShmupHelp ( out ) ;
}
2017-07-10 18:47:38 +00:00
2018-07-09 18:09:56 +00:00
callhooks ( hooks_mouseover , c ) ;
2017-07-10 18:47:38 +00:00
if ( mousey < vid . fsize * 3 / 2 ) getcstat = SDLK_F1 ;
}
void showHelp ( ) {
2017-07-12 17:50:39 +00:00
cmode = sm : : HELP | sm : : DOTOUR ;
2017-07-10 18:47:38 +00:00
getcstat = SDLK_ESCAPE ;
if ( help = = " HELPFUN " ) {
help_delegate ( ) ;
return ;
}
2018-07-23 21:36:29 +00:00
gamescreen ( 2 ) ;
2017-07-10 18:47:38 +00:00
string help2 ;
if ( help [ 0 ] = = ' @ ' ) {
int iv = help . find ( " \t " ) ;
int id = help . find ( " \n " ) ;
dialog : : init ( help . substr ( iv + 1 , id - iv - 1 ) , atoi ( help . c_str ( ) + 1 ) , 120 , 100 ) ;
dialog : : addHelp ( help . substr ( id + 1 ) ) ;
}
else {
dialog : : init ( " help " , forecolor , 120 , 100 ) ;
dialog : : addHelp ( help ) ;
}
2018-09-05 13:19:51 +00:00
for ( auto & he : help_extensions ) {
if ( he . subtext ! = " " )
dialog : : addSelItem ( he . text , he . subtext , he . key ) ;
else
dialog : : addItem ( he . text , he . key ) ;
dialog : : lastItem ( ) . color = he . color ;
}
2017-07-10 18:47:38 +00:00
dialog : : display ( ) ;
keyhandler = [ ] ( int sym , int uni ) {
dialog : : handleNavigation ( sym , uni ) ;
2017-10-08 23:40:32 +00:00
for ( auto & he : help_extensions )
if ( uni = = he . key ) {
// we need to copy he.action
// as otherwise it could clear the extensions,
// leading to errors
auto act = he . action ;
act ( ) ;
return ;
}
2018-02-26 12:15:33 +00:00
if ( sym = = SDLK_F1 ) {
auto i = help ;
buildHelpText ( ) ;
if ( help = = i ) popScreen ( ) ;
}
2017-07-10 18:47:38 +00:00
else if ( doexiton ( sym , uni ) )
popScreen ( ) ;
} ;
}
2018-07-09 18:09:56 +00:00
hookset < bool ( ) > * hooks_default_help ;
2017-07-10 18:47:38 +00:00
void gotoHelp ( const string & h ) {
help = h ;
2017-10-08 23:40:32 +00:00
help_extensions . clear ( ) ;
2017-07-10 18:47:38 +00:00
pushScreen ( showHelp ) ;
2018-02-26 12:15:33 +00:00
if ( help = = " @ " ) {
2018-07-09 18:09:56 +00:00
if ( callhandlers ( false , hooks_default_help ) ) return ;
2018-02-26 12:15:33 +00:00
# if CAP_RUG
2018-07-09 18:09:56 +00:00
if ( rug : : rugged ) {
help = rug : : makehelp ( ) ;
help_extensions . push_back ( help_extension { ' m ' , XLAT ( " Hypersian Rug menu " ) , [ ] ( ) { popScreen ( ) ; rug : : select ( ) ; } } ) ;
help_extensions . push_back ( help_extension { ' h ' , XLAT ( " HyperRogue help " ) , [ ] ( ) { buildHelpText ( ) ; } } ) ;
return ;
}
2017-12-30 22:47:23 +00:00
# endif
2018-02-26 12:15:33 +00:00
buildHelpText ( ) ;
2017-12-30 16:01:14 +00:00
}
2017-10-08 23:40:32 +00:00
if ( help = = " HELPGEN " ) helpgenerator ( ) ;
}
void subhelp ( const string & h ) {
string oldhelp = help ;
auto ext = help_extensions ;
reaction_t back = [ oldhelp , ext ] ( ) {
help = oldhelp ;
help_extensions = ext ;
} ;
help = h ;
help_extensions . clear ( ) ;
if ( help = = " HELPGEN " ) helpgenerator ( ) ;
help_extensions . push_back ( help_extension { ' z ' , XLAT ( " back " ) , back } ) ;
}
void gotoHelpFor ( eLand l ) {
help = generateHelpForLand ( l ) ;
int beastcount = 0 ;
for ( int m0 = 0 ; m0 < motypes ; m0 + + )
if ( isNative ( l , eMonster ( m0 ) ) & & ! nodisplay ( eMonster ( m0 ) ) ) beastcount + + ;
auto listbeasts = [ l ] ( ) {
char nextmonster = ' a ' ;
for ( int m0 = 0 ; m0 < motypes ; m0 + + ) {
2017-10-14 19:43:21 +00:00
const eMonster m = eMonster ( m0 ) ;
if ( isNative ( l , m ) & & ! nodisplay ( m ) ) {
help_extension hex ;
hex . key = nextmonster + + ;
hex . text = XLATN ( minf [ m ] . name ) ;
hex . action = [ m ] ( ) {
2017-10-08 23:40:32 +00:00
subhelp ( bygen ( [ m ] ( ) { gotoHelpFor ( m ) ; } ) ) ;
2017-10-14 19:43:21 +00:00
} ;
help_extensions . push_back ( hex ) ;
}
2017-10-08 23:40:32 +00:00
}
} ;
if ( beastcount > 3 )
help_extensions . push_back ( help_extension { ' b ' , XLAT ( " bestiary of %the1 " , l ) , [ l , listbeasts ] ( ) {
subhelp ( helptitle ( XLAT ( " bestiary of %the1 " , l ) , 0xC00000 ) ) ;
listbeasts ( ) ;
} } ) ;
else listbeasts ( ) ;
2017-07-10 18:47:38 +00:00
}
2018-06-10 23:58:31 +00:00
}