From 5a761c43c5ff0ba5a0e88df4409fbbb30b334443 Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Sun, 4 May 2025 22:37:00 +0200 Subject: [PATCH] ru:: stats, redefine keys in the inventory screen --- rogueviz/ru/classes.cpp | 23 ++++++++++++++++++++- rogueviz/ru/entity.cpp | 2 +- rogueviz/ru/globals.cpp | 6 ++++-- rogueviz/ru/man.cpp | 2 ++ rogueviz/ru/powers.cpp | 33 ++++++++++++++++++++++++----- rogueviz/ru/ru.cpp | 19 +++++++---------- rogueviz/ru/stats.cpp | 46 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 110 insertions(+), 21 deletions(-) create mode 100644 rogueviz/ru/stats.cpp diff --git a/rogueviz/ru/classes.cpp b/rogueviz/ru/classes.cpp index e98b56c3..53eed51e 100644 --- a/rogueviz/ru/classes.cpp +++ b/rogueviz/ru/classes.cpp @@ -132,6 +132,17 @@ struct xy { xy& operator /= (ld s) { x /= s; y /= s; return self; } }; +enum class stat { str, con, wis, dex }; + +constexpr stat allstats[] = { stat::str, stat::con, stat::wis, stat::dex }; +constexpr int qstat = 4; + +template struct statarray : array { + statarray() {}; + T& operator [] (stat s) { return array::operator[] ((int) s); }; + const T& operator [] (stat s) const { return array::operator[] ((int) s); }; + }; + struct entity { virtual xy siz() = 0; xy where, vel; @@ -232,7 +243,17 @@ struct man : public entity { int last_action; - man() { facing = 1; attack_facing = 1; postfix(); } + int experience; + statarray base_stats, current_stats, next_stats; + + virtual int max_hp() { return 10 * current_stats[stat::con]; } + + man() { + facing = 1; attack_facing = 1; + for(auto s: allstats) base_stats[s] = 10; + next_stats = base_stats; current_stats = base_stats; + postfix(); + } xy siz() override { return {12, 12}; } string glyph() override { return hallucinating ? "f" : "@"; } color_t color() override { return hallucinating ? 0x808080FF : 0xFF8080FF; } diff --git a/rogueviz/ru/entity.cpp b/rogueviz/ru/entity.cpp index b3a3a663..0182f1b5 100644 --- a/rogueviz/ru/entity.cpp +++ b/rogueviz/ru/entity.cpp @@ -246,7 +246,7 @@ void npc::act() { kino(); if(gframeid > m.last_action + 300 && intersect(extend_all(get_pixel_bbox(), get_scale()*12), m.get_pixel_bbox()) && talk_on != m.last_action) { talk_on = m.last_action = gframeid; - cmode = mode::talking; + cmode = mode::menu; pushScreen([&] { cmode = mode::playing; popScreen(); }); pushScreen([&] { dialog::init(name, col >> 8); diff --git a/rogueviz/ru/globals.cpp b/rogueviz/ru/globals.cpp index 719f39cc..69ae86d4 100644 --- a/rogueviz/ru/globals.cpp +++ b/rogueviz/ru/globals.cpp @@ -124,14 +124,14 @@ extern array, 256> all_locations; enum class mapmode { standard, poincare, klein }; -enum class mode { editmap, menu, playing, paused, inventory, talking }; +enum class mode { editmap, menu, playing, paused }; mode cmode = mode::playing; mapmode cmapmode = mapmode::standard; void switch_mapmode_to(mapmode m); -bool should_apply_fov() { return among(cmode, mode::playing, mode::paused, mode::inventory); } +bool should_apply_fov() { return among(cmode, mode::playing, mode::paused, mode::menu); } void enable(); @@ -146,4 +146,6 @@ void render_room_objects(room *r); void asciiletter(ld minx, ld miny, ld maxx, ld maxy, const string& ch, color_t col); +void render_the_map(); + } diff --git a/rogueviz/ru/man.cpp b/rogueviz/ru/man.cpp index aac443f3..d076572d 100644 --- a/rogueviz/ru/man.cpp +++ b/rogueviz/ru/man.cpp @@ -5,6 +5,8 @@ void handle_powers(data& d); void man::act() { kino(); + current_stats = next_stats; + next_stats = base_stats; auto dat = get_dat(); coyote_time = next_coyote_time; next_coyote_time = 0; diff --git a/rogueviz/ru/powers.cpp b/rogueviz/ru/powers.cpp index 364fd2f6..9054b385 100644 --- a/rogueviz/ru/powers.cpp +++ b/rogueviz/ru/powers.cpp @@ -117,7 +117,7 @@ void gen_powers() { m.attack_facing = m.facing; m.attack_when = gframeid; auto pb = m.get_pixel_bbox_at(xy{m.where.x + m.attack_facing * m.dsiz().x, m.where.y}); auto bb = pixel_to_block(pb); - for(auto& e: current_room->entities) if(e->existing && intersect(e->get_pixel_bbox(), pb)) e->attacked(15); + for(auto& e: current_room->entities) if(e->existing && intersect(e->get_pixel_bbox(), pb)) e->attacked((m.current_stats[stat::str] + 1) * 3 / 2); for(int y=bb.miny; yat(x, y); @@ -207,6 +207,8 @@ void gen_powers() { "Is it safe to put this ring on?", "=", 0xC04040FF, [] (data& d) { + if(d.p->flags & ACTIVE) + m.next_stats[stat::str] += d.p->qty_filled; if(d.keystate == 1) { d.p->flags ^= ACTIVE; d.p->flags |= IDENTIFIED; @@ -239,23 +241,44 @@ void handle_powers(data& d) { } } -void draw_inventory() { +void draw_inventory_frame() { flat_model_enabler fme; initquickqueue(); for(int a: {0, 1, 3, 2, 0}) curvepoint(eupoint((a&1)?16:vid.xres-16, (a&2)?16:vid.yres-16)); queuecurve(atscreenpos(0, 0), 0xFFFFFFFF, 0x000000E0, PPR::LINE); quickqueue(); + } + +void draw_inventory() { + render_the_map(); + draw_inventory_frame(); + dialog::init(); int next_y = 48; int st = vid.fsize * 1.2; displaystr(32, next_y, 0, vid.fsize, "Your inventory:", 0xC0C0C0, 0); next_y += st * 1.5; for(auto& p: powers) if(p.qty_owned) { string key = p.key == ' ' ? "␣" : dialog::keyname(p.key); - displaystr(100, next_y, 0, vid.fsize, key, p.color >> 8, 16); - displaystr(130, next_y, 0, vid.fsize, p.get_glyph(), p.color >> 8, 8); - displaystr(160, next_y, 0, vid.fsize, p.get_name(), p.color >> 8, 0); + if(displaystr(100, next_y, 0, vid.fsize, key, p.color >> 8, 16)) getcstat = p.key; + if(displaystr(130, next_y, 0, vid.fsize, p.get_glyph(), p.color >> 8, 8)) getcstat = p.key; + if(displaystr(160, next_y, 0, vid.fsize, p.get_name(), p.color >> 8, 0)) getcstat = p.key; next_y += st; + dialog::add_key_action(p.key, [&p] { pushScreen([&p] { + render_the_map(); + draw_inventory_frame(); + dialog::init(p.get_name(), p.color); + dialog::addHelp(p.get_desc()); + dialog::addItem("press a key to redefine", SDLK_ESCAPE); + dialog::display(); + dialog::addBack(); + keyhandler = [&p] (int sym, int uni) { + if(sym == 0) return; + if(sym == SDLK_ESCAPE) return popScreen(); + for(auto& p1: powers) if(p1.key == sym) p1.key = p.key; + p.key = sym; + }; + }); }); } } diff --git a/rogueviz/ru/ru.cpp b/rogueviz/ru/ru.cpp index 74ad877b..3f17b99e 100644 --- a/rogueviz/ru/ru.cpp +++ b/rogueviz/ru/ru.cpp @@ -33,6 +33,7 @@ Have fun! #include "portals.cpp" #include "powers.cpp" #include "save.cpp" +#include "stats.cpp" namespace rogue_unlike { @@ -298,25 +299,19 @@ void run() { draw_pentagon(); break; - case mode::inventory: - render_the_map(); - draw_inventory(); - dialog::add_key_action('v', [] { cmode = mode::menu; }); - break; - - case mode::talking: - break; - case mode::menu: - nomap = true; - emptyscreen(); + render_the_map(); + draw_inventory_frame(); dialog::init(); dialog::addTitle("Fountains of Alchemy", 0x4040C0, 150); dialog::addItem("return to game", 'v'); dialog::add_action([] { cmode = mode::playing; }); dialog::addItem("inventory", 'i'); - dialog::add_action([] { clearMessages(); cmode = mode::inventory; }); + dialog::add_action_push(draw_inventory); + + dialog::addItem("character", 'k'); + dialog::add_action_push(draw_stats); dialog::addItem("map editor", 'e'); dialog::add_action([] { cmode = mode::editmap; }); diff --git a/rogueviz/ru/stats.cpp b/rogueviz/ru/stats.cpp new file mode 100644 index 00000000..ef6f4f3a --- /dev/null +++ b/rogueviz/ru/stats.cpp @@ -0,0 +1,46 @@ +namespace rogue_unlike { + +struct statinfo { + char key; + string name; + string desc; + }; + +statarray statdata; + +void draw_stats() { + + statdata[stat::str] = {'s', "Strength", "Affects the strength of your mundane melee attacks."}; + statdata[stat::con] = {'t', "Toughness", "Affects the amount of hitpoints you have."}; + statdata[stat::wis] = {'w', "Wisdom", "Affects the power of your alchemy."}; + statdata[stat::dex] = {'d', "Dexterity", "Affects the strength of your mundane missile attacks."}; + + render_the_map(); + draw_inventory_frame(); + dialog::init("the Alchemist", 0xC000C0); + + dialog::addSelItem("free experience", its(m.experience), 'x'); + + for(auto st: allstats) { + string s = its(m.base_stats[st]); + if(m.current_stats[st] != m.base_stats[st]) s += " (" + its(m.current_stats[st]) + ")"; + dialog::addSelItem(statdata[st].name, s, statdata[st].key); + dialog::add_action_push([st] { + render_the_map(); + draw_inventory_frame(); + dialog::init(statdata[st].name, 0xC000C0); + dialog::addHelp(statdata[st].desc); + dialog::addBreak(100); + dialog::addSelItem("base value", its(m.base_stats[st]), 0); + dialog::addSelItem("current value", its(m.current_stats[st]), 0); + dialog::addBreak(100); + dialog::addBack(); + dialog::display(); + }); + } + + dialog::addBack(); + dialog::display(); + } + +}