Minor notes refactoring. Added a basic notes browser on '_'.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@528 c06c8d41-db1a-0410-9941-cceddc491573
43ZTEB57FU7KE5EVMYWZONNVJBZCGF3JEAJZIY25LC4LGE65PG5QC
void get_full_detail(char* buffer, bool calc_unid)
{
#define CUR_AD &buffer[++lines*45],44
#define BUF_SIZE 24*3*45
int lines = -1;
memset(buffer, 0, BUF_SIZE);
static const char* determine_color_string( int level ) {
switch ( level ) {
case 3:
case 2:
return "<lightgreen>";
case 1:
return "<green>";
case -1:
return "<red>";
case -2:
case -3:
return "<lightred>";
default:
return "<lightgrey>";
}
}
snprintf(CUR_AD, "%s the %s", you.your_name, player_title());
lines++;
snprintf(CUR_AD, "Race : %s", species_name(you.species,you.experience_level) );
snprintf(CUR_AD, "Class : %s", you.class_name);
snprintf(CUR_AD, "Worship : %s",
you.religion == GOD_NO_GOD? "" : god_name(you.religion) );
snprintf(CUR_AD, "Level : %7d", you.experience_level);
snprintf(CUR_AD, "Exp : %7lu", you.experience);
std::vector<formatted_string> get_full_detail(bool calc_unid)
{
char buf[1000];
// 3 columns, splits at columns 32, 52
column_composer cols(3, 32, 52);
snprintf(buf, sizeof buf,
"<red>%s the %s</red>\n\n"
"Race : %s\n"
"Class : %s\n"
"Worship : %s\n"
"Level : %7d\n"
"Exp : %7lu\n",
you.your_name, player_title(),
species_name(you.species,you.experience_level),
you.class_name,
you.religion == GOD_NO_GOD? "" : god_name(you.religion),
you.experience_level,
you.experience);
cols.add_formatted(0, buf, false);
int xp_needed = (exp_needed(you.experience_level+2) - you.experience) + 1;
snprintf(CUR_AD, "Next Level : %7lu", exp_needed(you.experience_level + 2) + 1);
snprintf(CUR_AD, "Exp Needed : %7d", xp_needed);
int xp_needed = (exp_needed(you.experience_level+2)-you.experience)+1;
snprintf(buf, sizeof buf,
"Next Level : %7lu\n"
"Exp Needed : %7d\n",
exp_needed(you.experience_level + 2) + 1,
xp_needed);
cols.add_formatted(0, buf, false);
{
snprintf(CUR_AD, " ");
snprintf(CUR_AD, " ");
}
snprintf(CUR_AD, "Spls.Left : %7d", player_spell_levels() );
snprintf(CUR_AD, "Gold : %7d", you.gold );
lines++;
cols.add_formatted(0, "\n\n", false);
snprintf(buf, sizeof buf,
"Spls.Left : %7d\n"
"Gold : %7d\n",
player_spell_levels(),
you.gold);
cols.add_formatted(0, buf, false);
snprintf(CUR_AD, "HP : %3d/%d (%d)",
you.hp, you.hp_max, you.hp_max + player_rotted() );
snprintf(buf, sizeof buf, "HP : %3d/%d (%d)",
you.hp, you.hp_max, you.hp_max + player_rotted() );
snprintf(CUR_AD, "AC : %3d", player_AC() );
snprintf(CUR_AD, "Evasion : %3d", player_evasion() );
snprintf(CUR_AD, "Shield : %3d", player_shield_class() );
lines++;
snprintf(buf, sizeof buf,
"AC : %3d\n"
"Evasion : %3d\n"
"Shield : %3d\n",
player_AC(),
player_evasion(),
player_shield_class());
cols.add_formatted(0, buf, false);
lines = 24 + 1;
const int rfire = player_res_fire(calc_unid);
const int rcold = player_res_cold(calc_unid);
const int rlife = player_prot_life(calc_unid);
const int rpois = player_res_poison(calc_unid);
const int relec = player_res_electricity(calc_unid);
snprintf(buf, sizeof buf, "\n\n"
"Res.Fire : %s%s\n"
"Res.Cold : %s%s\n"
"Life Prot.: %s%s\n"
"Res.Poison: %s%s\n"
"Res.Elec. : %s%s\n",
determine_color_string(rfire), itosym3(rfire),
determine_color_string(rcold), itosym3(rcold),
determine_color_string(rlife), itosym3(rlife),
determine_color_string(rpois), itosym1(rpois),
determine_color_string(relec), itosym1(relec));
cols.add_formatted(1, buf, false);
snprintf(CUR_AD, "Res.Fire : %s",
itosym3( player_res_fire(calc_unid) ) );
snprintf(CUR_AD, "Res.Cold : %s",
itosym3( player_res_cold(calc_unid) ) );
snprintf(CUR_AD, "Life Prot.: %s",
itosym3( player_prot_life(calc_unid) ) );
snprintf(CUR_AD, "Res.Poison: %s",
itosym1( player_res_poison(calc_unid) ) );
snprintf(CUR_AD, "Res.Elec. : %s",
itosym1( player_res_electricity(calc_unid) ) );
lines++;
snprintf(CUR_AD, "Sust.Abil.: %s",
itosym1( player_sust_abil(calc_unid) ) );
snprintf(CUR_AD, "Res.Mut. : %s",
itosym1( wearing_amulet( AMU_RESIST_MUTATION, calc_unid) ) );
snprintf(CUR_AD, "Res.Slow : %s",
itosym1( wearing_amulet( AMU_RESIST_SLOW, calc_unid) ) );
snprintf(CUR_AD, "Clarity : %s",
itosym1( wearing_amulet( AMU_CLARITY, calc_unid) ) );
lines++;
lines++;
const int rsust = player_sust_abil(calc_unid);
const int rmuta = wearing_amulet(AMU_RESIST_MUTATION, calc_unid);
const int rslow = wearing_amulet(AMU_RESIST_SLOW, calc_unid);
const int rclar = wearing_amulet(AMU_CLARITY, calc_unid);
snprintf(buf, sizeof buf,
"Sust.Abil.: %s%s\n"
"Res.Mut. : %s%s\n"
"Res.Slow : %s%s\n"
"Clarity : %s%s\n \n",
determine_color_string(rsust), itosym1(rsust),
determine_color_string(rmuta), itosym1(rmuta),
determine_color_string(rslow), itosym1(rslow),
determine_color_string(rclar), itosym1(rclar));
cols.add_formatted(1, buf, true);
in_name( you.equip[ e_order[i] ], DESC_PLAIN,
str_pass, true );
snprintf(CUR_AD, "%-7s: %s", slot, str_pass);
const int inum = you.equip[e_order[i]];
in_name( inum, DESC_PLAIN, str_pass, true );
str_pass[38] = 0; // truncate
const char* colname = colour_to_str(you.inv[inum].colour);
snprintf(buf, sizeof buf, "%-7s: <%s>%s</%s>",
slot, colname, str_pass, colname);
lines = 24 * 2 + 1;
snprintf(CUR_AD, "See Invis. : %s",
itosym1( player_see_invis(calc_unid) ) );
snprintf(CUR_AD, "Warding : %s",
itosym1( wearing_amulet(AMU_WARDING, calc_unid)
|| (you.religion == GOD_VEHUMET &&
you.duration[DUR_PRAYER] &&
!player_under_penance() &&
you.piety >= 75) ) );
snprintf(CUR_AD, "Conserve : %s",
itosym1( wearing_amulet( AMU_CONSERVATION, calc_unid) ) );
snprintf(CUR_AD, "Res.Corr. : %s",
itosym1( wearing_amulet( AMU_RESIST_CORROSION, calc_unid) ) );
if ( !wearing_amulet( AMU_THE_GOURMAND, calc_unid) )
{
switch (you.species)
{
case SP_GHOUL:
snprintf(CUR_AD, "Saprovore : %s", itosym3(3) );
break;
const int rinvi = player_see_invis(calc_unid);
const int rward = wearing_amulet(AMU_WARDING, calc_unid) ||
(you.religion == GOD_VEHUMET && you.duration[DUR_PRAYER] &&
!player_under_penance() && you.piety >= 75);
const int rcons = wearing_amulet(AMU_CONSERVATION, calc_unid);
const int rcorr = wearing_amulet(AMU_RESIST_CORROSION, calc_unid);
case SP_KOBOLD:
case SP_TROLL:
snprintf(CUR_AD, "Saprovore : %s", itosym3(2) );
break;
snprintf(buf, sizeof buf, "\n\n"
"See Invis. : %s%s\n"
"Warding : %s%s\n"
"Conserve : %s%s\n"
"Res.Corr. : %s%s\n",
determine_color_string(rinvi), itosym1(rinvi),
determine_color_string(rward), itosym1(rward),
determine_color_string(rcons), itosym1(rcons),
determine_color_string(rcorr), itosym1(rcorr));
cols.add_formatted(2, buf, false);
int saplevel = 0;
switch (you.species)
{
case SP_GHOUL:
saplevel = 3;
snprintf(buf, sizeof buf, "Saprovore : %s%s",
determine_color_string(3), itosym3(3) );
break;
default:
snprintf(CUR_AD, "Gourmand : %s", itosym1(0) );
break;
}
case SP_HILL_ORC:
case SP_OGRE:
saplevel = 1;
break;
default:
saplevel = 0;
break;
}
const char* pregourmand;
const char* postgourmand;
if ( wearing_amulet(AMU_THE_GOURMAND, calc_unid) )
{
pregourmand = "Gourmand : ";
postgourmand = itosym1(1);
saplevel = 1;
snprintf(CUR_AD, "Rnd.Telep. : %s",
itosym1( player_teleport(calc_unid) ) );
snprintf(CUR_AD, "Ctrl.Telep.: %s",
itosym1( player_control_teleport(calc_unid) ) );
snprintf(CUR_AD, "Levitation : %s", itosym1( player_is_levitating() ) );
snprintf(CUR_AD, "Ctrl.Flight: %s",
itosym1( wearing_amulet(AMU_CONTROLLED_FLIGHT, calc_unid) ) );
lines++;
{
const int rrtel = player_teleport(calc_unid);
snprintf(buf, sizeof buf, "Rnd.Telep. : %s%s",
determine_color_string(rrtel), itosym1(rrtel));
}
cols.add_formatted(2, buf, false);
const int rctel = player_control_teleport(calc_unid);
const int rlevi = player_is_levitating();
const int rcfli = wearing_amulet(AMU_CONTROLLED_FLIGHT, calc_unid);
snprintf(buf, sizeof buf,
"Ctrl.Telep.: %s%s\n"
"Levitation : %s%s\n"
"Ctrl.Flight: %s%s\n",
determine_color_string(rctel), itosym1(rctel),
determine_color_string(rlevi), itosym1(rlevi),
determine_color_string(rcfli), itosym1(rcfli));
cols.add_formatted(2, buf, false);
switch ( note.type ) {
case NOTE_HP_CHANGE:
// [ds] Shortened HP change note from "Had X hitpoints" to accommodate
// the cause for the loss of hitpoints.
snprintf(buf, sizeof buf, "HP: %d/%d [%s]",
note.first, note.second, note.name.c_str());
break;
case NOTE_MP_CHANGE:
snprintf(buf, sizeof buf, "Mana: %d/%d", note.first, note.second);
break;
case NOTE_MAXHP_CHANGE:
snprintf(buf, sizeof buf, "Reached %d max hit points", note.first);
break;
case NOTE_MAXMP_CHANGE:
snprintf(buf, sizeof buf, "Reached %d max mana", note.first);
break;
case NOTE_XP_LEVEL_CHANGE:
snprintf(buf, sizeof buf, "Reached XP level %d. %s", note.first,
note.name.c_str());
break;
case NOTE_DUNGEON_LEVEL_CHANGE:
snprintf(buf, sizeof buf, "Entered %s",
place_name(note.packed_place, true, true).c_str());
break;
case NOTE_LEARN_SPELL:
snprintf(buf, sizeof buf, "Learned a level %d spell: %s",
spell_difficulty(note.first), spell_title(note.first));
break;
case NOTE_GET_GOD:
snprintf(buf, sizeof buf, "Became a worshipper of %s",
god_name(note.first, true));
break;
case NOTE_LOSE_GOD:
snprintf(buf, sizeof buf, "Fell from the grace of %s",
god_name(note.first));
break;
case NOTE_GOD_GIFT:
snprintf(buf, sizeof buf, "Received a gift from %s",
god_name(note.first));
break;
case NOTE_ID_ITEM:
if (note.desc.length() > 0)
snprintf(buf, sizeof buf, "Identified %s (%s)", note.name.c_str(),
note.desc.c_str());
else
snprintf(buf, sizeof buf, "Identified %s", note.name.c_str());
break;
case NOTE_GET_ITEM:
snprintf(buf, sizeof buf, "Got %s", note.name.c_str());
break;
case NOTE_GAIN_SKILL:
snprintf(buf, sizeof buf, "Reached skill %d in %s",
note.second, skill_name(note.first));
break;
case NOTE_SEEN_MONSTER:
snprintf(buf, sizeof buf, "Noticed %s", note.name.c_str() );
break;
case NOTE_KILL_MONSTER:
snprintf(buf, sizeof buf, "Defeated %s", note.name.c_str());
break;
case NOTE_POLY_MONSTER:
snprintf(buf, sizeof buf, "%s changed form", note.name.c_str() );
break;
case NOTE_GOD_POWER:
snprintf(buf, sizeof buf, "Acquired %s's %s power",
god_name(note.first),
number_to_ordinal(real_god_power(note.first, note.second)+1));
break;
case NOTE_GET_MUTATION:
snprintf(buf, sizeof buf, "Gained mutation: %s",
mutation_name(note.first, note.second == 0 ? 1 : note.second));
break;
case NOTE_LOSE_MUTATION:
snprintf(buf, sizeof buf, "Lost mutation: %s",
mutation_name(note.first,
note.second == 3 ? 3 : note.second+1));
break;
case NOTE_USER_NOTE:
snprintf(buf, sizeof buf, "%s", note.name.c_str());
break;
case NOTE_MESSAGE:
snprintf(buf, sizeof buf, "%s", note.name.c_str());
break;
default:
snprintf(buf, sizeof buf, "Buggy note description: unknown note type");
break;
std::string result;
if ( when )
{
char buf[20];
snprintf(buf, sizeof buf, "| %5ld ", turn );
result += buf;
snprintf(buf2, sizeof buf2, "| %5ld | ", note.turn );
std::string placename = short_place_name(note.packed_place);
while ( placename.length() < 7 )
placename += ' ';
return std::string(buf2) + placename + std::string(" | ") +
std::string(buf);
if ( where )
{
result += "| ";
std::string placename = short_place_name(packed_place);
while ( placename.length() < 7 )
placename += ' ';
result += placename;
result += " | ";
}
if ( what )
{
char buf[200];
switch ( type ) {
case NOTE_HP_CHANGE:
// [ds] Shortened HP change note from "Had X hitpoints" to
// accommodate the cause for the loss of hitpoints.
snprintf(buf, sizeof buf, "HP: %d/%d [%s]",
first, second, name.c_str());
break;
case NOTE_MP_CHANGE:
snprintf(buf, sizeof buf, "Mana: %d/%d", first, second);
break;
case NOTE_MAXHP_CHANGE:
snprintf(buf, sizeof buf, "Reached %d max hit points", first);
break;
case NOTE_MAXMP_CHANGE:
snprintf(buf, sizeof buf, "Reached %d max mana", first);
break;
case NOTE_XP_LEVEL_CHANGE:
snprintf(buf, sizeof buf, "Reached XP level %d. %s", first,
name.c_str());
break;
case NOTE_DUNGEON_LEVEL_CHANGE:
snprintf(buf, sizeof buf, "Entered %s",
place_name(packed_place, true, true).c_str());
break;
case NOTE_LEARN_SPELL:
snprintf(buf, sizeof buf, "Learned a level %d spell: %s",
spell_difficulty(first), spell_title(first));
break;
case NOTE_GET_GOD:
snprintf(buf, sizeof buf, "Became a worshipper of %s",
god_name(first, true));
break;
case NOTE_LOSE_GOD:
snprintf(buf, sizeof buf, "Fell from the grace of %s",
god_name(first));
break;
case NOTE_GOD_GIFT:
snprintf(buf, sizeof buf, "Received a gift from %s",
god_name(first));
break;
case NOTE_ID_ITEM:
if (desc.length() > 0)
snprintf(buf, sizeof buf, "Identified %s (%s)",
name.c_str(), desc.c_str());
else
snprintf(buf, sizeof buf, "Identified %s", name.c_str());
break;
case NOTE_GET_ITEM:
snprintf(buf, sizeof buf, "Got %s", name.c_str());
break;
case NOTE_GAIN_SKILL:
snprintf(buf, sizeof buf, "Reached skill %d in %s",
second, skill_name(first));
break;
case NOTE_SEEN_MONSTER:
snprintf(buf, sizeof buf, "Noticed %s", name.c_str() );
break;
case NOTE_KILL_MONSTER:
snprintf(buf, sizeof buf, "Defeated %s", name.c_str());
break;
case NOTE_POLY_MONSTER:
snprintf(buf, sizeof buf, "%s changed form", name.c_str() );
break;
case NOTE_GOD_POWER:
snprintf(buf, sizeof buf, "Acquired %s's %s power",
god_name(first),
number_to_ordinal(real_god_power(first, second)+1));
break;
case NOTE_GET_MUTATION:
snprintf(buf, sizeof buf, "Gained mutation: %s",
mutation_name(first, second == 0 ? 1 : second));
break;
case NOTE_LOSE_MUTATION:
snprintf(buf, sizeof buf, "Lost mutation: %s",
mutation_name(first, second == 3 ? 3 : second+1));
break;
case NOTE_USER_NOTE:
snprintf(buf, sizeof buf, "%s", name.c_str());
break;
case NOTE_MESSAGE:
snprintf(buf, sizeof buf, "%s", name.c_str());
break;
default:
snprintf(buf, sizeof buf,
"Buggy note description: unknown note type");
break;
}
result += buf;
}
return result;
const size_t newpos = s.find( EOL, eolpos );
add_entry(new MenuEntry(std::string(s, eolpos, newpos-eolpos)));
const size_t newpos = s.find( "\n", eolpos );
add_item_formatted_string(formatted_string::parse_string(std::string(s, eolpos, newpos-eolpos)));
eolpos = newpos + strlen(EOL);
}
eolpos = newpos + 1;
}
}
void formatted_scroller::add_item_formatted_string(const formatted_string& fs)
{
MenuEntry* me = new MenuEntry;
me->data = new formatted_string(fs);
add_entry(me);
}
void formatted_scroller::add_item_string(const std::string& s)
{
add_entry( new MenuEntry(s) );
formatted_string::parse_string(me->text).display();
if ( me->data == NULL )
Menu::draw_index_item(index, me);
else
static_cast<formatted_string*>(me->data)->display();
}
formatted_scroller::~formatted_scroller()
{
// very important: this destructor is called *before* the
// base (Menu) class destructor...which is at it should be.
for ( unsigned i = 0; i < items.size(); ++i )
if ( items[i]->data != NULL )
delete static_cast<formatted_string*>(items[i]->data);
}
const std::string cols[16] =
{
"black", "blue", "green", "cyan", "red", "magenta", "brown",
"lightgrey", "darkgrey", "lightblue", "lightgreen", "lightcyan",
"lightred", "lightmagenta", "yellow", "white"
};
const char* colour_to_str(unsigned char colour)
{
if ( colour >= 16 )
return "lightgrey";
else
return cols[colour].c_str();
ptr_n = &buffer[i][0];
if (buffer[i+24][0] == 0 && buffer[i+24*2][0] == 0)
snprintf(&str_pass[0], 45, "%s", ptr_n);
else
snprintf(&str_pass[0], 45, "%-32s", ptr_n);
text += str_pass;
ptr_n = &buffer[i+24][0];
if (buffer[i+24*2][0] == 0)
snprintf(&str_pass[0], 45, "%s", ptr_n);
else
snprintf(&str_pass[0], 45, "%-20s", ptr_n);
text += str_pass;
ptr_n = &buffer[i+24*2][0];
if (buffer[i+24*2][0] != 0)
{
snprintf(&str_pass[0], 45, "%s", ptr_n);
text += str_pass;
}
text += "\n";
text += vfs[i];
text += '\n';
static void set_resist_dump_color( const char* data ) {
while ( *data && *data != ':' )
++data;
if ( *data == 0 )
return;
++data;
int pluscount = 0;
while ( *data ) {
if ( *data == '+' )
++pluscount;
if ( *data == 'x' )
--pluscount;
++data;
void display_notes()
{
#ifdef DOS_TERM
char dosbuffer[4000];
gettext( 1, 1, 80, 25, dosbuffer );
window( 1, 1, 80, 25 );
#endif
Menu scr;
scr.set_title( new MenuEntry("| Turn |Location | Note"));
for ( unsigned int i = 0; i < note_list.size(); ++i )
{
std::string prefix = note_list[i].describe(true, true, false);
std::string suffix = note_list[i].describe(false, false, true);
if ( suffix.empty() )
continue;
int spaceleft = get_number_of_cols() - prefix.length() - 1;
if ( spaceleft <= 0 )
return;
linebreak_string(suffix, spaceleft - 4, spaceleft);
std::vector<std::string> parts = split_string("\n", suffix);
scr.add_entry(new MenuEntry(prefix + parts[0]));
for ( unsigned int j = 1; j < parts.size(); ++j )
scr.add_entry(new MenuEntry(std::string(prefix.length()-2, ' ') +
std::string("| ") + parts[j]));
switch ( pluscount ) {
case 3:
case 2:
textcolor(LIGHTGREEN);
break;
case 1:
textcolor(GREEN);
break;
case -1:
textcolor(RED);
break;
case -2:
case -3:
textcolor(LIGHTRED);
break;
default:
textcolor(LIGHTGREY);
break;
}
scr.show();
#ifdef DOS_TERM
puttext(1, 1, 80, 25, dosbuffer);
window(1, 1, 80, 25);
#endif
redraw_screen();
get_full_detail(&buffer[0][0], false);
for (int line = 0; line < 24; ++line ) {
for ( int block = 0; block < 3; ++block ) {
const int idx = block * 24 + line;
if ( buffer[idx][0] ) {
gotoxy( block == 2 ? 53 : block * 32 + 1, line+1 );
/* FIXME - hack - magic number 14 */
if ( block != 0 && line < 14 )
set_resist_dump_color(buffer[idx]);
cprintf("%s", buffer[idx] );
textcolor(LIGHTGREY);
}
}
formatted_scroller scr;
for ( unsigned i = 0; i < vfs.size(); ++i )
{
scr.add_item_formatted_string(vfs[i]);