2018-02-08 23:40:26 +00:00
// Hyperbolic Rogue -- help routines
// Copyright (C) 2011-2018 Zeno Rogue, see 'hyper.cpp' for details
2019-08-10 11:43:24 +00:00
/** \file help.cpp
* \ brief Building and displaying help text
*/
2019-09-05 07:15:40 +00:00
# include "hyper.h"
2018-06-10 23:58:31 +00:00
namespace hr {
2019-08-09 19:00:52 +00:00
EX string help ;
2017-07-10 18:47:38 +00:00
2019-08-09 19:00:52 +00:00
EX function < void ( ) > help_delegate ;
2017-07-10 18:47:38 +00:00
2019-08-09 19:18:13 +00:00
# if HDR
struct help_extension {
2022-12-04 13:49:06 +00:00
int key ;
2019-08-09 19:18:13 +00:00
string text ;
string subtext ;
color_t color ;
reaction_t action ;
help_extension ( ) { color = forecolor ; }
help_extension ( char k , string t , reaction_t a ) : key ( k ) , text ( t ) , action ( a ) { color = forecolor ; }
} ;
# endif
2019-08-09 19:00:52 +00:00
EX vector < help_extension > help_extensions ;
2018-02-26 12:15:33 +00:00
2020-04-19 20:54:40 +00:00
vector < string > quick_keys = {
" 1 = orthogonal/Gans model/FPP " ,
" 2 = small Poincare model/stereographic projection/SPP " ,
" 3 = big Poincare model/stereographic projection/TPP " ,
2018-02-26 12:15:33 +00:00
" 4 = Klein model/gnomonic projection " ,
" 5 = change wall display mode " ,
" 6 = change grid " ,
" 7 = change heptagon marking " ,
2020-04-19 20:54:40 +00:00
" 8 = monster display mode "
} ;
vector < string > normal_keys = {
2018-02-26 12:15:33 +00:00
" qweasdzxc, hjklyubn, numpad = move/skip turn " ,
2020-04-19 20:54:40 +00:00
" g = drop a Dead Orb " ,
" t = use a ranged Orb (target center of the screen) "
} ;
vector < string > extra_keys = {
" o = world overview (or another meaning in special modes) " ,
2018-02-26 12:15:33 +00:00
" v = menu " ,
" F1 = help " ,
" F5 = restart game " ,
" F10 = quit game " ,
" Esc = quest status " ,
" Alt+Enter = full screen " ,
" Alt = highlight interesting stuff " ,
" click left mouse button = move/skip " ,
2020-04-19 20:54:40 +00:00
" [shift+]click left mouse button = use ranged Orb (depending on mouse settings) " ,
2018-02-26 12:15:33 +00:00
" click right mouse button = context help " ,
" mousewheel up = panning " ,
" hold middle mouse button = panning " ,
2020-04-19 20:54:40 +00:00
" lctrl + hold middle button = move the screen " ,
2018-02-26 12:15:33 +00:00
" mousewheel down = move/skip " ,
2020-04-19 20:54:40 +00:00
" rshift + mousewheel = change projection " ,
" lshift + mousewheel = change zoom (lctrl to keep center) " ,
" lctrl + mousewheel = reset the map center " ,
2018-07-09 16:10:28 +00:00
" shift + F2 = disable the HUD " ,
" shift + F3 = disable the FPS " ,
2020-04-19 20:54:40 +00:00
" shift + F4 = disable the map " ,
" space = recenter " ,
" ctrl + <key> = more precision "
} ;
vector < string > extra_keys_2d = {
" arrows = panning " ,
" PageUp/Down = rotate the screen " ,
} ;
vector < string > extra_keys_3d = {
" arrows = rotate the camera " ,
" rshift+arrows = strafe " ,
" lshift+arrows = rotate the model (in rug mode) " ,
" end = move camera forward " ,
" home = move camera backward " ,
2020-04-19 20:58:45 +00:00
" shift+Home/End = zoom " ,
2020-04-19 20:54:40 +00:00
" PageUp/Down = rotate the screen " ,
" move mouse = rotate camera (in rug, only with lctrl) " ,
2018-02-26 12:15:33 +00:00
} ;
2022-07-05 09:51:32 +00:00
EX void buildHelpText ( ) {
2019-05-12 23:57:40 +00:00
DEBBI ( DF_GRAPH , ( " buildHelpText " ) ) ;
2017-07-10 18:47:38 +00:00
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
2022-08-05 20:51:56 +00:00
if ( ! game_keys_scroll ) 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! "
) ;
2022-08-05 20:51:56 +00:00
if ( ! game_keys_scroll ) help + = XLAT ( " (press ESC for some hints about it). " ) ;
if ( ! game_keys_scroll ) help + = " \n \n " ;
2017-07-10 18:47:38 +00:00
2022-08-05 20:51:56 +00:00
if ( ! shmup : : on & & ! hardcore & & ! game_keys_scroll )
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 "
) ;
2019-03-30 22:45:28 +00:00
2022-08-05 20:51:56 +00:00
if ( shmup : : on & & ! game_keys_scroll ) {
2019-03-30 22:45:28 +00:00
help + = XLAT (
" Shmup (shoot'em up) mode: You can play a hyperbolic shoot'em up game. The game is based "
" on the usual turn-based grid-based HyperRogue, but there are some changes. You fight by "
" throwing knives, and you have three extra lives. There are no allies, so all Orbs "
" related to allies give you extra lives instead (up to 5). Some other rules have been "
" adapted too. \n \n " ) ;
}
2022-08-05 20:51:56 +00:00
if ( shmup : : on & & multi : : players > 1 & & ! game_keys_scroll ) {
2019-03-30 22:45:28 +00:00
help + = XLAT (
" Multiplayer: Play cooperatively (locally); treasures, kills, and deaths are calculated "
" for each player too, for more competitive play. Orbs and treasures are shared, orbs drain "
" faster, knives recharge slower, and player characters are not allowed to separate. \n \n " ) ;
}
2022-08-05 20:51:56 +00:00
if ( multi : : players > 1 & & ! shmup : : on & & ! game_keys_scroll ) {
2019-03-30 22:45:28 +00:00
help + = XLAT (
" Turn-based multiplayer: Turns are executed in parallel. A player can leave the game "
" by pressing a designated key (useful when about to get killed or lost). The following "
" Orbs work to bring such players back: " ) ;
help + = XLATN ( iinf [ itOrbLife ] . name ) ; help + = " , " ;
help + = XLATN ( iinf [ itOrbFriend ] . name ) ; help + = " , " ;
help + = XLATN ( iinf [ itOrbUndeath ] . name ) ; help + = " , " ;
help + = XLATN ( iinf [ itOrbTeleport ] . name ) ; help + = " , " ;
help + = XLATN ( iinf [ itOrbSafety ] . name ) ; help + = " \n \n " ;
}
2018-02-11 20:39:08 +00:00
# if CAP_INV
2022-08-05 20:51:56 +00:00
if ( inv : : on & & ! game_keys_scroll )
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
) ;
2022-08-05 20:51:56 +00:00
else if ( ! game_keys_scroll )
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 " ) ;
2022-08-05 20:51:56 +00:00
if ( ! game_keys_scroll ) 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
2022-08-05 20:51:56 +00:00
if ( DEFAULTCONTROL & & ! game_keys_scroll )
2018-02-26 12:15:33 +00:00
help + = XLAT (
2020-04-19 13:30:45 +00:00
" Move with mouse, num pad, qweadzxc, or hjklyubn. Wait by pressing 's' or '.'. Spin the world with arrows, PageUp/Down, and Space. "
2017-08-06 12:50:16 +00:00
" 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 "
) ;
2022-08-05 20:51:56 +00:00
else if ( DEFAULTCONTROL & & WDIM = = 2 )
help + = XLAT (
" You are currently in a visualization. Press wasd to scroll, qe to rotate. You can also use the arrow keys. ESC for menu. \n \n " ) ;
else if ( DEFAULTCONTROL & & WDIM = = 3 )
help + = XLAT (
" You are currently in a visualization. Press wasdqe to rotate the camera, ijklyh to move. You can also use the arrow keys and Home/End and PgUp/PgDn. ESC for menu. \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: " )
2022-11-04 15:06:02 +00:00
+ " https://roguetemple.com/z/hyper/ \n \n " ;
2017-07-10 18:47:38 +00:00
2017-07-22 23:33:27 +00:00
# if CAP_TOUR
2022-08-05 20:52:16 +00:00
if ( ! tour : : on )
2019-09-13 16:01:28 +00:00
help + = XLAT ( " Try the Guided Tour 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 = " " ;
2020-04-19 20:54:40 +00:00
for ( string s : normal_keys ) help + = s , help + = " \n " ;
for ( string s : extra_keys ) help + = s , help + = " \n " ;
help + = " \n \n Quick keys: \n " ;
for ( string s : quick_keys ) help + = s , help + = " \n " ;
if ( GDIM = = 3 | | rug : : rugged ) {
help + = " \n \n In 3D modes: \n " ;
for ( string s : extra_keys_3d ) help + = s , help + = " \n " ;
}
else {
help + = " \n \n In 2D modes: \n " ;
for ( string s : extra_keys_2d ) help + = s , help + = " \n " ;
}
2018-02-26 12:15:33 +00:00
} } ) ;
# endif
2017-07-10 18:47:38 +00:00
}
2019-12-25 10:53:50 +00:00
EX string standard_help ( ) {
2023-03-25 08:24:47 +00:00
if ( nohelp = = 2 ) return " " ;
2019-12-25 10:53:50 +00:00
return XLAT ( " Press F1 or right click for help " ) ;
}
2019-08-10 00:16:48 +00:00
EX void buildCredits ( ) {
2018-02-26 12:15:33 +00:00
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, "
2019-09-27 15:34:16 +00:00
" Triple_Agent_AAA, bluetailedgnat, Allalinor, Shitford, KittyTac, Christopher King, KosGD, TravelDemon, Bubbles, rdococ, frozenlake, MagmaMcFry, "
2020-09-15 18:00:53 +00:00
" Snakebird Priestess, roaringdragon2, Stopping Dog, bengineer8, Sir Light IJIJ, ShadeBlade, Saplou, shnourok, Ralith, madasa, 6% remaining, Chimera245, Remik Pi, alien foxcat thing, "
2023-12-02 10:34:51 +00:00
" Piotr Grochowski, Ann, still-flow, tyzone, Paradoxica, LottieRatWorld, aismallard, albatross, EncodedSpirit, Jacob Mandelson, CrashTuvai, cvoight, jennlbw, Kali Ranya, spiritbackup, Dylan, L_Lord, AntiRogue "
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. " ) ;
}
2019-09-06 06:17:02 +00:00
EX 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 " +
2021-12-12 19:41:11 +00:00
XLAT ( " Killed %1 can be revived with an Orb of Love, after you collect 20 more $$$. " , moPrincess ) ;
2017-07-10 18:47:38 +00:00
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 ) {
2019-10-05 15:06:48 +00:00
for ( auto & oi1 : orbinfos )
if ( ( oi1 . flags & orbgenflags : : NATIVE ) & & oi1 . orb = = oi . orb ) {
help + = XLAT ( " \n Spawn rate (as prize Orb): %1%/%2 \n " ,
its ( int ( .5 + 100 * orbprizefun ( t ) ) ) ,
its ( oi1 . gchance ) ) ;
}
2017-07-10 18:47:38 +00:00
}
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 . " ) ;
}
2019-11-27 23:39:27 +00:00
string hyperstone_optional = " Completing the quest in this land is not necessary for the Hyperstone Quest. " ;
2019-11-27 23:45:13 +00:00
string power_help =
" 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. " ;
2019-08-09 21:39:36 +00:00
EX string generateHelpForItem ( eItem it ) {
2017-07-10 18:47:38 +00:00
string help = helptitle ( XLATN ( iinf [ it ] . name ) , iinf [ it ] . color ) ;
2022-06-17 07:09:53 +00:00
if ( shmup : : on & & isShmupLifeOrb ( it ) ) {
int cnt = 0 ;
help + = XLAT (
" The following Orbs act an extra lives in the shmup mode: " ) ;
for ( int i = 0 ; i < ittypes ; i + + ) {
eItem it2 = eItem ( i ) ;
if ( isShmupLifeOrb ( it2 ) ) help + = cnt + + ? XLAT ( " , %1 " , it2 ) : XLAT ( " %1 " , it2 ) ;
}
}
2017-07-10 18:47:38 +00:00
2022-06-17 07:09:53 +00:00
else
2019-02-17 17:28:20 +00:00
# if CAP_CRYSTAL
2019-08-22 10:14:39 +00:00
if ( it = = itCompass & & cryst )
2018-12-03 22:15:53 +00:00
help + = crystal : : compass_help ( ) ;
else
2019-02-17 17:28:20 +00:00
# endif
2018-12-03 22:15:53 +00:00
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. " ) ;
}
2020-05-03 18:56:41 +00:00
# if ISMOBILE
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 )
2023-12-02 10:05:28 +00:00
help + = XLAT ( " \n \n This Orb is triggered on your first direct melee attack or illegal move. " ) ;
2017-07-10 18:47:38 +00:00
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. " ) ;
2019-11-27 23:14:22 +00:00
if ( it = = itOrbIntensity & & inv : : on )
help + = XLAT ( " \n \n In the Orb Strategy Mode, the effect is increased to +100%. " ) ;
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 ) ) {
2021-05-23 12:33:25 +00:00
help + = cnt ? XLAT ( " , %1 " , it2 ) : XLAT ( " %1 " , it2 ) ;
2017-07-10 18:47:38 +00:00
cnt + + ;
}
}
2020-03-02 19:35:15 +00:00
help + = XLAT ( " \n \n Additionally, your allies are protected from your indirect attacks. " ) ;
2017-07-10 18:47:38 +00:00
}
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. "
2020-09-16 18:20:50 +00:00
" You can gain further Orbs of the Mirror by collecting 2, 4, 8... " ,
it
2017-07-16 21:00:55 +00:00
) ;
2017-08-14 19:13:06 +00:00
if ( it = = itPower )
2019-11-27 23:45:13 +00:00
help + = " \n \n " + XLAT ( power_help ) ;
2017-08-14 19:13:06 +00:00
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
2021-05-27 14:36:19 +00:00
if ( it = = itOrbLuck ) {
help + = XLAT ( " \n \n Additionally, the probabilities of generating terrain features are subtly changed in the following lands: " ) ;
int cnt = 0 ;
for ( int i = 0 ; i < landtypes ; i + + ) {
eLand land = eLand ( i ) ;
if ( isLuckyLand ( land ) ) {
help + = cnt ? XLAT ( " , %1 " , land ) : XLAT ( " %1 " , land ) ;
cnt + + ;
}
}
}
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 ) {
2021-06-29 10:47:12 +00:00
help + = " \n \n " ;
2017-07-10 18:47:38 +00:00
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 ) {
2021-06-29 10:47:12 +00:00
help + = " \n \n " ;
help + = XLAT ( " Secondary orb: %1 " , oi . orb ) ;
2017-07-10 18:47:38 +00:00
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
2019-11-27 23:39:27 +00:00
if ( in_full_game ( ) & & ! required_for_hyperstones ( it ) & & it ! = itHyperstone )
help + = " \n \n " + XLAT ( hyperstone_optional ) ;
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 " ;
2020-05-03 18:56:41 +00:00
# if !ISMOBILE
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
2022-05-21 15:10:04 +00:00
help_extensions . push_back ( help_extension { ' n ' , XLAT ( " toggle numerical display " ) , [ ] ( ) { numerical_minefield = ! numerical_minefield ; } } ) ;
2017-07-10 18:47:38 +00:00
}
2019-09-06 06:17:02 +00:00
EX string generateHelpForWall ( eWall w ) {
2017-07-10 18:47:38 +00:00
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 ) ;
2023-08-21 17:14:19 +00:00
s + = hr : : format ( " (%d/%d) \n " , current , req ) ;
2017-07-10 18:47:38 +00:00
}
2019-09-06 06:17:02 +00:00
EX string generateHelpForMonster ( eMonster m ) {
2017-07-10 18:47:38 +00:00
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 ) ;
2019-12-25 10:53:50 +00:00
if ( m = = moMutant ) {
using namespace clearing ;
if ( direct )
2019-12-25 13:44:41 +00:00
s + = XLAT ( " \n \n Leaves cut directly: %1 " , its ( direct ) ) ;
2019-12-25 10:53:50 +00:00
if ( kills [ moMutant ] )
2019-12-25 13:44:41 +00:00
s + = XLAT ( " \n \n Leaves cut onscreen: %1 " , its ( kills [ moMutant ] ) ) ;
2019-12-25 10:53:50 +00:00
if ( imputed . nonzero ( ) )
2019-12-25 13:44:41 +00:00
s + = XLAT ( " \n \n Leaves cut offscreen (approximately): %1 " , imputed . get_str ( 10000 ) ) ;
2019-12-25 10:53:50 +00:00
}
2020-03-01 01:58:09 +00:00
eItem it = frog_power ( m ) ;
if ( it )
s + = XLAT ( " \n \n This Frog uses the power of %the1. You get 5 charges yourself for killing it. " , it ) ;
2019-12-25 10:53:50 +00:00
2017-07-10 18:47:38 +00:00
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 ;
}
2019-04-11 19:33:17 +00:00
void add_reqs ( eLand l , string & s ) {
back :
switch ( l ) {
# define LAND(a,b,c,d,e,f,g) case c:
# define REQ(x) x return;
# define REQAS(x,y) y l = x; goto back;
# define GOLD(x) NUMBER(gold(), x, XLAT("Treasure required: %1 $$$.\n", its(x)))
# define KILL(who, where) NUMBER(kills[who], 1, XLAT("Kills required: %1 (%2).\n", who, where))
# define ITEMS(kind, number) NUMBER(items[kind], number, XLAT("Treasure required: %1 x %2.\n", its(number), kind))
# define NEVER ;
# define ALWAYS s += XLAT("Always available.\n");
# define KILLS(x) NUMBER(tkills(), x, XLAT("Kills required: %1.\n", its(x)))
# define AKILL(who, where) s += XLAT("Alternatively: kill a %1 in %the2.\n", who, where); buteol(s, kills[who], 1);
# define ORD(a, b) b a
# define ALT(x) // if([&] { x return true; } ()) return true;
# define NUMBER(val, required, description) s += description; buteol(s, val, required);
# define COND(x,y) s += (y);
# define ITEMS_TOTAL(list, z) \
2020-11-14 14:08:16 +00:00
{ int now = 0 ; string t = " ( " ; for ( eItem i : list ) { if ( t ! = " ( " ) t + = " | " ; t + = XLATN ( iinf [ i ] . name ) ; now + = items [ i ] ; } t + = " ) " ; s + = XLAT ( " Treasure required: %1 x %2. \n " , its ( z ) , t ) ; buteol ( s , now , z ) ; }
2019-04-11 19:33:17 +00:00
# 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);
2022-11-04 16:12:08 +00:00
# define ACCONLY3(z,y,x) s += XLAT("Accessible only from %the1, %2, or %3.\n", z, y, x);
2019-04-11 19:33:17 +00:00
# define ACCONLYF(z) s += XLAT("Accessible only from %the1 (until finished).\n", z);
# include "content.cpp"
case landtypes : return ;
}
}
2019-11-30 14:05:50 +00:00
EX string generateHelpForLand ( eLand l ) {
2017-07-10 18:47:38 +00:00
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 " ;
2019-04-11 19:33:17 +00:00
add_reqs ( l , s ) ;
2017-07-10 18:47:38 +00:00
2017-08-14 19:13:06 +00:00
if ( l = = laPower & & inv : : on )
2019-11-27 23:45:13 +00:00
help + = XLAT ( power_help ) + " \n \n " ;
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 " ) ;
2019-11-27 23:39:27 +00:00
if ( in_full_game ( ) & & ! required_for_hyperstones ( treasureType ( l ) ) & & ! isCrossroads ( l ) )
s + = XLAT ( hyperstone_optional ) ;
2017-07-10 18:47:38 +00:00
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
2019-02-17 17:28:20 +00:00
# if CAP_CRYSTAL
2019-08-22 10:14:39 +00:00
if ( l = = laCamelot & & cryst ) {
2018-12-25 22:54:34 +00:00
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-02-17 17:28:20 +00:00
# endif
2018-12-25 22:54:34 +00:00
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
2019-12-07 10:12:46 +00:00
if ( l = = laCA ) {
s + = XLAT ( " \n \n Option -mineadj 1 can be added for Moore neighborhoods. " ) ;
2017-07-10 18:47:38 +00:00
s + = XLAT ( " \n \n Hint: use 'm' to toggle cells quickly " ) ;
2019-12-07 10:12:46 +00:00
}
2017-07-10 18:47:38 +00:00
# endif
return s ;
}
2019-09-06 06:17:02 +00:00
EX bool instat ;
2017-07-10 18:47:38 +00:00
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 ;
2019-09-06 06:17:02 +00:00
EX string bygen ( reaction_t h ) {
2017-10-08 23:40:32 +00:00
helpgenerator = h ;
return " HELPGEN " ;
}
void gotoHelpFor ( eLand l ) ;
void gotoHelpFor ( eItem i ) {
help = generateHelpForItem ( i ) ;
}
void gotoHelpFor ( eWall w ) {
help = generateHelpForWall ( w ) ;
2020-02-23 01:51:27 +00:00
}
2017-10-08 23:40:32 +00:00
void gotoHelpFor ( eMonster m ) {
help = generateHelpForMonster ( m ) ;
2020-02-23 01:51:27 +00:00
}
2017-10-08 23:40:32 +00:00
2019-09-06 06:17:02 +00:00
EX void appendHelp ( string s ) {
2017-11-06 21:01:53 +00:00
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 ;
2020-04-11 18:47:14 +00:00
EX hookset < void ( cell * ) > hooks_mouseover ;
2018-07-09 18:09:56 +00:00
2020-09-11 09:16:02 +00:00
template < class T > void set_help_to ( T t ) {
2022-08-05 20:52:39 +00:00
help = bygen ( [ t ] {
gotoHelpFor ( t ) ;
help_extensions . push_back ( help_extension { ' h ' , XLAT ( " HyperRogue help " ) , [ ] ( ) { buildHelpText ( ) ; } } ) ;
} ) ;
2020-09-11 09:16:02 +00:00
}
2019-08-09 19:00:52 +00:00
EX void describeMouseover ( ) {
2019-05-12 23:57:40 +00:00
DEBBI ( DF_GRAPH , ( " describeMouseover " ) ) ;
2017-07-10 18:47:38 +00:00
2019-11-13 23:26:50 +00:00
cell * c = mousing ? mouseover : playermoved ? NULL : centerover ;
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 ) ;
2020-09-11 09:16:02 +00:00
set_help_to ( c - > land ) ;
2017-07-16 21:00:55 +00:00
2019-05-08 16:33:08 +00:00
if ( WDIM = = 3 & & isGravityLand ( c - > land ) ) out + = " [ " + its ( gravityLevel ( c ) ) + " ] " ;
2019-03-23 15:31:12 +00:00
2020-01-28 14:21:39 +00:00
if ( c - > land = = laTemple & & c - > master - > alt ) {
int lev = - celldistAlt ( c ) ;
int ts = temple_layer_size ( ) ;
out + = " ( " + its ( lev / ts + 1 ) + " : " + its ( lev % ts ) + " ) " ;
}
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) " ;
2019-01-16 23:56:32 +00:00
if ( c - > land = = laBrownian & & c - > wall = = waNone )
out + = XLAT ( " (level %1) " , its ( snakelevel ( c ) ) ) ;
2017-07-10 18:47:38 +00:00
if ( c - > land = = laDryForest & & c - > landparam )
out + = " ( " + its ( c - > landparam ) + " /10) " ;
2021-04-11 20:15:40 +00:00
if ( c - > land = = laOcean & & ls : : any_chaos ( ) )
2017-07-10 18:47:38 +00:00
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 " ) + " ) " ;
}
}
2019-02-17 17:28:20 +00:00
# if CAP_FIELD
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 ) + " ] " ;
}
2019-02-17 17:28:20 +00:00
# endif
2017-07-10 18:47:38 +00:00
if ( c - > land = = laTortoise & & tortoise : : seek ( ) ) out + = " " + tortoise : : measure ( getBits ( c ) ) ;
2021-05-22 21:02:35 +00:00
// describe the shadow path
if ( among ( c - > land , laGraveyard , laCursed ) & & shpos . size ( ) ) {
string shadowtimes ;
vector < cell * > route ;
for ( int s = 1 ; s < SHSIZE ; s + + ) {
bool shadow = false ;
for ( int p : player_indices ( ) )
if ( shpos [ ( cshpos + s ) % SHSIZE ] [ p ] = = c )
shadow = true ;
if ( shadow ) {
if ( shadowtimes = = " " )
shadowtimes = its ( s ) ;
else
shadowtimes + = " " + its ( s ) ;
}
}
if ( shadowtimes ! = " " )
out + = XLAT ( " (shadow in %1) " , shadowtimes ) ;
}
2017-07-10 18:47:38 +00:00
if ( buggyGeneration ) {
2023-08-21 17:14:19 +00:00
out + = hr : : format ( " %p H=%d M=%d " , hr : : voidp ( c ) , c - > landparam , c - > mpdist ) ;
2017-07-10 18:47:38 +00:00
}
if ( randomPatternsMode )
out + = " " + describeRPM ( c - > land ) ;
2019-12-14 10:26:03 +00:00
if ( cheater & & euc : : in ( 2 ) ) {
2019-11-27 00:01:20 +00:00
auto co = euc2_coordinates ( c ) ;
out + = " ( " + its ( co . first ) ;
for ( int i = 1 ; i < WDIM ; i + + ) out + = " , " + its ( co . second ) ;
out + = " ) " ;
}
2021-02-18 14:53:21 +00:00
if ( cheater & & euc : : in ( 3 ) & & ! ( cgflags & qPORTALSPACE ) ) {
2019-12-08 10:01:28 +00:00
auto co = euc : : get_ispacemap ( ) [ c - > master ] ;
2019-11-27 00:01:20 +00:00
out + = " ( " + its ( co [ 0 ] ) ;
for ( int i = 1 ; i < WDIM ; i + + ) out + = " , " + its ( co [ i ] ) ;
out + = " ) " ;
2017-07-10 18:47:38 +00:00
}
2019-10-12 11:15:46 +00:00
# if CAP_CRYSTAL
if ( geometry = = gCrystal344 & & cheater & & crystal : : view_coordinates ) {
out + = " ( " ;
auto co = crystal : : get_coord ( c - > master ) ;
for ( int i = 0 ; i < 4 ; i + + ) {
if ( i ) out + = " , " ;
out + = its ( co [ i ] ) ;
}
out + = " ) " ;
}
# endif
2017-07-10 18:47:38 +00:00
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 ) ) {
2023-12-22 00:14:41 +00:00
eWall w = c - > wall ;
if ( isAlch ( w ) )
w = conditional_flip_slime ( mousing ? det ( mouseoverV . T ) < 0 : det ( View ) < 0 , w ) ;
out + = " , " ; out + = XLAT1 ( winf [ w ] . name ) ;
2017-07-10 18:47:38 +00:00
if ( c - > wall = = waRose ) out + = " ( " + its ( 7 - rosephase ) + " ) " ;
2021-08-04 00:15:53 +00:00
if ( c - > wall = = waTerraWarrior ) out + = " ( " + its ( c - > wparam ) + " ) " ;
2021-07-20 14:00:48 +00:00
# if CAP_COMPLEX2
if ( isDie ( c - > wall ) ) out + = " ( " + dice : : describe ( c ) + " ) " ;
# endif
2017-07-10 18:47:38 +00:00
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 )
2020-03-23 18:48:56 +00:00
if ( ! ( ( c - > wall = = waCavefloor | | c - > wall = = waCavewall ) & & ( c - > land = = laEmerald | | c - > land = = laCaves ) ) )
2017-10-08 23:40:32 +00:00
if ( ! ( ( isAlch ( c - > wall ) & & c - > land = = laAlchemist ) ) )
2020-09-11 09:16:02 +00:00
set_help_to ( 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 ) + " ] " ;
2020-03-06 14:17:25 +00:00
2020-10-15 14:33:52 +00:00
# if CAP_COMPLEX2
2020-03-06 14:17:25 +00:00
if ( c - > monst = = moKnight )
out + = XLAT ( " , %1 the Knight " , camelot : : knight_name ( c ) ) ;
2020-10-15 14:33:52 +00:00
# else
if ( 0 ) ;
# endif
2017-07-10 18:47:38 +00:00
2020-03-06 14:17:25 +00:00
else if ( c - > monst ) {
2017-07-10 18:47:38 +00:00
out + = " , " ; out + = XLAT1 ( minf [ c - > monst ] . name ) ;
2021-07-20 14:00:48 +00:00
# if CAP_COMPLEX2
if ( isDie ( c - > monst ) )
out + = " ( " + dice : : describe ( c ) + " ) " ;
# endif
2017-07-10 18:47:38 +00:00
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 ) ) ;
2020-09-11 09:16:02 +00:00
set_help_to ( 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 ) + " ) " ;
2020-10-15 14:33:52 +00:00
# if CAP_COMPLEX2
if ( c - > land = = laHunting ) {
2019-12-08 18:17:28 +00:00
int i = ambush : : size ( 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
}
2020-10-15 14:33:52 +00:00
# endif
2017-07-10 18:47:38 +00:00
if ( c - > item = = itBabyTortoise & & tortoise : : seek ( ) )
out + = " " + tortoise : : measure ( tortoise : : babymap [ c ] ) ;
2020-09-11 09:16:02 +00:00
if ( ! c - > monst ) set_help_to ( 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
2019-04-16 22:42:51 +00:00
if ( isWarped ( c ) & & ! isWarpedType ( c - > land ) )
2017-07-10 18:47:38 +00:00
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 )
2020-03-01 01:34:27 +00:00
appendHelp ( " \n \n " + other_geometry ( ) + forbidden_unmarked ( ) ) ;
}
if ( isElectricLand ( c ) | | isElectricLand ( cwt . at - > land ) ) {
using namespace elec ;
eCharge ch = getCharge ( c ) ;
if ( ch = = ecCharged ) appendHelp ( " \n \n This cell is charged. " ) ;
if ( ch = = ecGrounded ) appendHelp ( " \n \n This cell is grounded. " ) ;
if ( ch = = ecConductor ) appendHelp ( " \n \n This cell is currently conductive. " ) ;
if ( ch = = ecIsolator ) appendHelp ( " \n \n This cell is currently not conductive. " ) ;
2018-05-26 23:09:34 +00:00
}
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
2019-09-03 06:27:02 +00:00
if ( mousey < vid . fsize * 3 / 2 & & getcstat = = ' - ' & & ! instat ) getcstat = SDLK_F1 ;
2020-10-15 14:33:52 +00:00
# if CAP_TOUR
2020-09-15 17:14:24 +00:00
if ( tour : : on & & ! tour : : texts ) {
if ( tour : : slides [ tour : : currentslide ] . flags & tour : : NOTITLE )
mouseovers = " " ;
else
mouseovers = XLAT ( tour : : slides [ tour : : currentslide ] . name ) ;
}
2020-10-15 14:33:52 +00:00
# endif
2017-07-10 18:47:38 +00:00
}
2019-08-09 19:00:52 +00:00
EX void showHelp ( ) {
2022-07-05 09:51:06 +00:00
cmode = sm : : HELP | sm : : DOTOUR | sm : : DARKEN ;
2017-07-10 18:47:38 +00:00
getcstat = SDLK_ESCAPE ;
if ( help = = " HELPFUN " ) {
help_delegate ( ) ;
return ;
}
2022-07-05 09:51:06 +00:00
gamescreen ( ) ;
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 ) ;
}
2022-12-04 13:49:06 +00:00
bool in_list = false ;
2018-09-05 13:19:51 +00:00
for ( auto & he : help_extensions ) {
2022-12-04 13:49:06 +00:00
if ( ! in_list & & he . key = = dialog : : first_list_fake_key ) {
dialog : : start_list ( 1000 , 1000 , ' a ' ) ;
in_list = true ;
}
if ( in_list & & ( he . key < dialog : : first_list_fake_key | | he . key > dialog : : first_list_fake_key + 1000 ) ) {
in_list = false ;
dialog : : end_list ( ) ;
}
2018-09-05 13:19:51 +00:00
if ( he . subtext ! = " " )
dialog : : addSelItem ( he . text , he . subtext , he . key ) ;
else
dialog : : addItem ( he . text , he . key ) ;
2022-12-04 13:49:06 +00:00
dialog : : add_action ( he . action ) ;
2018-09-05 13:19:51 +00:00
dialog : : lastItem ( ) . color = he . color ;
}
2022-12-04 13:49:06 +00:00
if ( in_list ) dialog : : end_list ( ) ;
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
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 ( ) ;
} ;
}
2020-04-11 18:47:14 +00:00
EX hookset < bool ( ) > hooks_default_help ;
2018-07-09 18:09:56 +00:00
2019-08-09 19:00:52 +00:00
EX void gotoHelp ( const string & h ) {
2017-07-10 18:47:38 +00:00
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 ( ) ;
2020-04-19 20:54:40 +00:00
help + = " \n \n " ;
for ( string s : extra_keys_3d ) help + = s , help + = " \n " ;
help + = " \n \n " ;
2018-07-09 18:09:56 +00:00
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 ( ) ;
}
2019-08-09 19:00:52 +00:00
EX void subhelp ( const string & h ) {
2017-10-08 23:40:32 +00:00
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 } ) ;
}
2019-08-09 19:00:52 +00:00
EX void gotoHelpFor ( eLand l ) {
2017-10-08 23:40:32 +00:00
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 ( ) ;
2020-03-22 08:46:13 +00:00
if ( l = = laTortoise )
2021-07-03 10:05:23 +00:00
help_extensions . push_back ( help_extension { ' s ' , XLAT ( " Galápagos shading " ) , [ ] ( ) {
2020-03-22 08:46:13 +00:00
tortoise : : shading_enabled = ! tortoise : : shading_enabled ;
} } ) ;
2021-07-04 02:38:20 +00:00
help_extensions . push_back ( help_extension { ' w ' , XLAT ( " wiki " ) , [ l ] ( ) {
open_wiki ( linf [ l ] . name ) ;
} } ) ;
2017-07-10 18:47:38 +00:00
}
2018-06-10 23:58:31 +00:00
}