diff --git a/rogueviz/ru/classes.cpp b/rogueviz/ru/classes.cpp index 1b309388..7958e2f1 100644 --- a/rogueviz/ru/classes.cpp +++ b/rogueviz/ru/classes.cpp @@ -357,6 +357,8 @@ struct man : public entity { int experience; stat profession; + string backstory; + namedcolor hair, eye; statarray base_stats; statdata current, next; @@ -510,15 +512,10 @@ struct vtrap : public located_entity { string get_help() override { return "A deadly but invisible trap."; } }; -struct cat_color { - string name; - color_t col; - }; - -void sact(stater& s, string t, cat_color co) { s.act(t+".name", co.name, "black").act(t+".col", co.col, 0xFFFFFFFF); } +void sact(stater& s, string t, namedcolor co) { s.act(t+".name", co.name, "black").act(t+".col", co.col, 0xFFFFFFFF); } struct cat : public enemy { - cat_color col; + namedcolor col; cat(); xy siz() override { return {5, 5}; } string glyph() override { return "f"; } diff --git a/rogueviz/ru/entity.cpp b/rogueviz/ru/entity.cpp index 1549e8ad..6597e5f1 100644 --- a/rogueviz/ru/entity.cpp +++ b/rogueviz/ru/entity.cpp @@ -774,12 +774,6 @@ void bat::attacked(int dmg) { if(where.y > m.where.y) vel.y = +abs(vel.y); } -vector cat_colors = { - cat_color{"red", 0xC04040FF}, - cat_color{"black", 0x505060FF}, - cat_color{"white", 0xF0F0F0FF} - }; - cat::cat() { col = hrand_elt(cat_colors); } diff --git a/rogueviz/ru/namedcolors.cpp b/rogueviz/ru/namedcolors.cpp new file mode 100644 index 00000000..b3a7d9ff --- /dev/null +++ b/rogueviz/ru/namedcolors.cpp @@ -0,0 +1,22 @@ +namespace rogue_unlike { + +struct namedcolor { + string name; + color_t col; + }; + +namedcolor + // cat colors + nc_red{"red", 0xC04040FF}, + nc_black{"red", 0x505060FF}, + nc_white{"white", 0xF0F0F0FF}, + // hair colors + nc_blonde{"blonde", 0xF0F0D0FF}, + nc_brownhair{"brown", 0x706030FF}, + // eye colors + nc_green{"green", 0x40F040FF}, + nc_browneye{"brown", 0xA07030FF}; + +vector cat_colors = { nc_red, nc_black, nc_white }; + +} diff --git a/rogueviz/ru/randeff.cpp b/rogueviz/ru/randeff.cpp index 634a5736..a2330e32 100644 --- a/rogueviz/ru/randeff.cpp +++ b/rogueviz/ru/randeff.cpp @@ -122,7 +122,7 @@ randeff fire_weapon("Fiery Weapon", "Attacks with your [weapon] set things on fi m.next.mods.emplace_back(d.re->which_weapon, mod::burning, 2 * m.current.stats[stat::wis] + 1e-6); }); -cat_color morph_cat_color; +namedcolor morph_cat_color; // morph powers randeff morph_cat("Cat", "Turns you into a cat.", "You turn into a cat!", [] (data &d) { diff --git a/rogueviz/ru/ru.cpp b/rogueviz/ru/ru.cpp index 82c59860..22064e66 100644 --- a/rogueviz/ru/ru.cpp +++ b/rogueviz/ru/ru.cpp @@ -24,6 +24,7 @@ Have fun! */ #include "globals.cpp" +#include "namedcolors.cpp" #include "classes.cpp" #include "staters.cpp" #include "geometry.cpp" @@ -485,9 +486,10 @@ void add_platf_hooks() { void start_new_game() { enable(); - randomize_stats(); + generate_character(); cmode = mode::menu; pushScreen(initial_stats); + clearMessages(); } auto chk = arg::add3("-ru", enable) diff --git a/rogueviz/ru/stats.cpp b/rogueviz/ru/stats.cpp index 5715310f..28f7f847 100644 --- a/rogueviz/ru/stats.cpp +++ b/rogueviz/ru/stats.cpp @@ -1,27 +1,75 @@ namespace rogue_unlike { +struct backstory_element { + string text; + reaction_t effect; + }; + +struct backstory_choice { + string part; + vector elts; + }; + +stat mainstat; + +extern vector backstories; + +int statseed; +vector story_choices; + // -1 to downgrade int stat_upgrade_cost(stat s, int bonus = 0) { return 10 * (m.base_stats[s] + bonus); } +void randomize_stories() { + story_choices = {}; + for(auto& v: backstories) + story_choices.push_back(hrand(isize(v.elts))); + } + +void upgrade(stat s) { + auto uc = stat_upgrade_cost(s); + if(uc <= m.experience) { + m.experience -= uc; + m.base_stats[s]++; + if(m.base_stats[s] > m.base_stats[mainstat]) mainstat = s; + } + } + void randomize_stats() { for(auto s: allstats) while(m.base_stats[s] > 1) { m.base_stats[s]--; m.experience += stat_upgrade_cost(s); } - auto mainstat = stat::str; + + std::mt19937 statgen; + statgen.seed(statseed); + swap(statgen, hrngen); + + mainstat = stat::str; + + m.backstory = ""; + for(int i=0; i m.base_stats[mainstat]) mainstat = s; - } + upgrade(s); } m.profession = mainstat; for(auto s: allstats) m.current.stats[s] = m.base_stats[s]; + + swap(statgen, hrngen); + } + +void generate_character() { + statseed = time(NULL); + randomize_stories(); + randomize_stats(); } struct statinfo { @@ -65,6 +113,28 @@ void stat_screen(bool editable) { draw_inventory_frame(); dialog::init("the Alchemist", 0xC000C0); + dialog::addHelp(m.backstory); + + if(editable) { + dialog::addItem("customize the character", 'e'); + dialog::add_action_push([] { + dialog::init("the Alchemist backstory", 0xC000C0); + dialog::addItem("randomize all", 'r'); + dialog::add_action([] { randomize_stories(); randomize_stats(); popScreen(); }); + char key = 'a'; + for(int i=0; i backstories = { + + backstory_choice{ "family", + { + {"You are the only child from a family of workers. ", [] { upgrade(stat::str); upgrade(stat::str); }}, + + {"You come from a family with long traditions in alchemy. ", [] { upgrade(stat::wis); upgrade(stat::wis); }} + } + }, + + backstory_choice{ "hair", + { + {"You have blonde hair ", [] {}}, + + {"You have red hair ", [] {}}, + + {"You have dark hair ", [] {}}, + } + }, + + backstory_choice{ "eyes", + { + {"and green eyes. ", [] {}}, + + {"and blue eyes. ", [] {}}, + + {"and brown eyes. ", [] {}}, + } + }, + + backstory_choice{ "childhood stories", + { + {"As a child, you loved to listen to your grandfather's stories about how he battled demons to find a cure for your mother's illness when she was a child.\n\n", + [] { upgrade(stat::wis); upgrade(stat::wis); }}, + + {"As a child, you loved to listen to your grandfather's stories about how he found your grandmother, a princess from another world.\n\n", + [] { upgrade(stat::str); upgrade(stat::str); }}, + + {"As a child, you loved to listen to your grandmother's stories. The coolest one was about how she almost died from a mad magician's scythe attack.\n\n", + [] { upgrade(stat::con); upgrade(stat::con); }} + + } + }, + + backstory_choice{ "motivation for studying alchemy", + { + {"You chose to study alchemy, believing it may help to cure the sick. ", + [] { upgrade(stat::con); upgrade(stat::con); }}, + + {"You chose to study alchemy, believing that the more people know, the better for them. ", + [] { upgrade(stat::wis); upgrade(stat::wis); }}, + + {"You chose to study alchemy. Good alchemists earn lots of money, after all. ", + [] { upgrade(stat::dex); upgrade(stat::dex); }}, + + {"You chose to study alchemy. Some potions can make you stronger. ", + [] { upgrade(stat::str); upgrade(stat::str); }}, + } + }, + + backstory_choice{ "motivation for Second Life", + { + {"During your studies, you started to question the inevitability of death. You started to work on a potion of second life.\n\n", + [] { upgrade(stat::con); upgrade(stat::con); }}, + + {"But you were bored by your fellow alchemists creating mundane stuff, such as potions of love and dyes. You realized that it should be possible to create a potion of second life.\n\n", + [] { upgrade(stat::wis); upgrade(stat::wis); }}, + + {"You realized that your potions are easier to sell when more people want them, and started researching something that everyone would want: a potion of second life.\n\n", + [] { upgrade(stat::dex); upgrade(stat::dex); }} + } + }, + + backstory_choice{ "motivation for adventuring", + { + {"But some ingredients could be found only in the magic fountains in Dungeons of Rogorama. The dungeons are full of dangerous creatures that you are eager to fight. ", + [] { upgrade(stat::str); }}, + + {"But some ingredients could be found only in the magic fountains in the Dungeons of Rogorama. The dungeons are full of legendary artifacts that you are eager to study. ", + [] { upgrade(stat::wis); }} + } + }, + + backstory_choice{ "", + { + {"While almost nobody has ever returned from these dungeons, the fountains are rumored to be easy to find, so you should be able to create a potion of second life quite easily. " + "And then, nothing would be able to stop you!\n\nYou wake up in the last inn before entering the dungeons...", + [] { }} + } + } + + }; + }