diff --git a/include/modify.hpp b/include/modify.hpp index 8f1d1f2..96f5369 100644 --- a/include/modify.hpp +++ b/include/modify.hpp @@ -25,8 +25,8 @@ void parse_action(int command, char *string, DescriptorData *d); /* PAGING */ /* page_string and page_string_desc will also start paging */ -void page_string(CharData *ch, const char *str); -void page_string_desc(DescriptorData *d, const char *str); +void page_string(CharData *ch, std::string_view str); +void page_string_desc(DescriptorData *d, std::string_view str); /* paging_printf will collect data, but you must then call start_paging */ template void paging_printf(CharData *ch, std::string_view messg, Args &&...args) { diff --git a/include/string_utils.hpp b/include/string_utils.hpp index 6e3c60f..33c5997 100644 --- a/include/string_utils.hpp +++ b/include/string_utils.hpp @@ -37,4 +37,6 @@ bool is_equals(const std::string_view &lhs, const std::string_view &rhs); // [[nodiscard]] bool matches_end(std::string_view lhs, std::string_view rhs); // // Is 'needle' contained inside 'haystack' case insensitively? -// [[nodiscard]] bool matches_inside(std::string_view needle, std::string_view haystack); \ No newline at end of file +// [[nodiscard]] bool matches_inside(std::string_view needle, std::string_view haystack); + +[[nodiscard]] std::string progress_bar(int current, int wall = 0, int max = 1000); \ No newline at end of file diff --git a/src/act.informative.cpp b/src/act.informative.cpp index 8be1f0a..592a3ec 100644 --- a/src/act.informative.cpp +++ b/src/act.informative.cpp @@ -3476,25 +3476,25 @@ ACMD(do_score) { const char *proficiency_message(int proficiency) { if (proficiency == 0) - return "not learned"; + return "(not learned)"; else if (proficiency <= 100) - return "awful"; + return "(awful)"; else if (proficiency <= 200) - return "bad"; + return "(bad)"; else if (proficiency <= 400) - return "poor"; + return "(poor)"; else if (proficiency <= 550) - return "average"; + return "(average)"; else if (proficiency <= 700) - return "fair"; + return "(fair)"; else if (proficiency <= 800) - return "good"; + return "(good)"; else if (proficiency <= 850) - return "very good"; + return "(very good)"; else if (proficiency <= 999) - return "superb"; + return "(superb)"; else - return "mastered"; + return "(mastered)"; } #define MAX_CIRCLE 14 @@ -3773,14 +3773,11 @@ ACMD(do_listspells) { ACMD(do_skills) { int level_max_skill(CharData * ch, int level, int skill); - const char *fullmastered = " &7-&b*&0&7-&0"; - const char *mastered = " * "; - const char *normal = " "; - const char *mastery; int i, x; CharData *tch; char points[MAX_INPUT_LENGTH]; bool godpeek; + std::string result; one_argument(argument, arg); @@ -3794,17 +3791,14 @@ ACMD(do_skills) { char_printf(ch, "There's nobody here by that name.\n"); return; } - sprintf(buf, "%s knows of the following skills:\n", GET_NAME(tch)); + result = fmt::format("{} knows of the following skills:\n", GET_NAME(tch)); godpeek = true; } else { - strcpy(buf, "You know of the following skills:\n"); + result = "You know of the following skills:\n"; tch = ch; godpeek = false; } - strcpy(buf2, buf); - points[0] = '\0'; - /* do_skills crashes when performed by non-switched mobs. */ if (IS_NPC(ch) && !ch->desc) return; @@ -3818,28 +3812,20 @@ ACMD(do_skills) { if (GET_SKILL(tch, i) <= 0) continue; - if (godpeek) - sprintf(points, " (%4d/%4d/%4d)", GET_ISKILL(tch, i), return_max_skill(tch, i), - level_max_skill(tch, LVL_MAX_MORT, i)); - - /* Show a star if the skill is as good as possible. */ - if (GET_ISKILL(tch, i) >= level_max_skill(tch, LVL_MAX_MORT, i)) - mastery = fullmastered; - else if (GET_ISKILL(tch, i) >= return_max_skill(tch, i)) - mastery = mastered; - else - mastery = normal; - /* Show exact skill numbers of mobs when switched. */ - sprintf(buf1, "(%s)", proficiency_message(GET_ISKILL(tch, i))); + result += fmt::format("{:<22} {:<15} ", skills[i].name, proficiency_message(GET_ISKILL(tch, i))); if (POSSESSED(tch) && GET_LEVEL(POSSESSOR(tch)) >= LVL_IMMORT) { - sprintf(buf, "%-22s %15s [%4d]%s%s\n", skills[i].name, buf1, GET_ISKILL(tch, i), mastery, points); + result += fmt::format("[{:4d}]", GET_ISKILL(tch, i)); } else { - sprintf(buf, "%-22s %15s%s%s\n", skills[i].name, buf1, mastery, points); + result += progress_bar(GET_ISKILL(tch, i), return_max_skill(tch, i)); + } + if (godpeek) { + result += fmt::format("({:4d}/{:4d}/{:4d})", GET_ISKILL(tch, i), return_max_skill(tch, i), + level_max_skill(tch, LVL_MAX_MORT, i)); } - strcat(buf2, buf); + result += "\n"; } - page_string(ch, buf2); + page_string(ch, result); } static int scan_chars(CharData *ch, int room, int dis, int dir, int seen_any) { diff --git a/src/modify.cpp b/src/modify.cpp index be64055..0f1260d 100644 --- a/src/modify.cpp +++ b/src/modify.cpp @@ -958,12 +958,12 @@ void start_paging(CharData *ch) { start_paging_desc(ch->desc); } -void page_string(CharData *ch, const char *str) { +void page_string(CharData *ch, std::string_view str) { if (ch->desc) page_string_desc(ch->desc, str); } -void page_string_desc(DescriptorData *d, const char *str) { +void page_string_desc(DescriptorData *d, std::string_view str) { paging_addstr(d, str); if (!d->page_outbuf->empty()) start_paging_desc(d); diff --git a/src/string_utils.cpp b/src/string_utils.cpp index 612b4ee..67f1565 100644 --- a/src/string_utils.cpp +++ b/src/string_utils.cpp @@ -183,3 +183,30 @@ bool matches_start(std::string_view lhs, std::string_view rhs) { // auto haystack_low = haystack | std::ranges::views::transform(tolower); // return !std::ranges::search(haystack_low, needle_low).empty(); // } + +std::string progress_bar(int current, int wall, int max) { + double percentage = static_cast(current) / max * 100; + double level_percentage = static_cast(current) / wall * 100; + + if (level_percentage < percentage || max < wall) + return ""; + + // Define progress bar lengths + const int bar_length = 40; + + if (current >= max) { + return fmt::format("[{:#^{}}]", " MASTERED ", bar_length); + } + + // Calculate filled portion for each bar + int fill = static_cast(percentage / 100 * bar_length); + int wall_position = static_cast(level_percentage / 100 * bar_length); + + // Create progress bars + std::string progress_bar = "[" + std::string(fill, '#') + std::string(wall_position - fill, '='); + if (bar_length - wall_position > 0) + progress_bar += std::string(bar_length - wall_position, '-'); + progress_bar += "]"; + + return progress_bar; +}