From 83920a57bc2a96e34fb0a84cedb3700d59b30e6e Mon Sep 17 00:00:00 2001 From: bgiraudr Date: Mon, 16 May 2022 23:57:25 +0200 Subject: [PATCH] Types have color + can now change player's type --- CMakeLists.txt | 1 + assets-cg/converters.py | 13 ++++- assets-cg/fxconv-metadata.txt | 2 +- assets-cg/maps/inside/fxconv-metadata.txt | 2 +- assets-cg/maps/testCarte.tmx | 2 +- assets-cg/table_type.csv | 10 ++-- include/draw_util.h | 5 ++ include/player.h | 4 +- include/talkable.h | 1 - include/type.h | 2 + include/util.h | 6 ++- src/battle.c | 13 ++--- src/capacite.c | 5 +- src/draw_util.c | 43 ++++++++++++++++ src/event.c | 10 ++++ src/inventory.c | 5 +- src/player.c | 62 +++++++++++++++++++++-- src/talkable.c | 59 +-------------------- src/type.c | 27 +++++----- src/util.c | 51 ++++++++++++++++++- 20 files changed, 220 insertions(+), 103 deletions(-) create mode 100644 include/draw_util.h create mode 100644 src/draw_util.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 407673b..0ddbfb4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,6 +48,7 @@ set(SOURCES src/inventory.c src/item.c src/type.c + src/draw_util.c ) set(ASSETS_cg diff --git a/assets-cg/converters.py b/assets-cg/converters.py index fb41748..e3bf888 100644 --- a/assets-cg/converters.py +++ b/assets-cg/converters.py @@ -22,6 +22,8 @@ def convert(input, output, params, target): elif params["custom-type"] == "table_type": convert_table_type(input, output, params, target) return 0 + elif params["custom-type"] == "test": + test(input, output, params, target) else: return 1 @@ -331,21 +333,28 @@ def convert_table_type(input, output, params, target): type = fxconv.Structure() type += fxconv.string(i["type"]) type += fxconv.u32(list(i).index(i["type"])) - - taille = len(i) + taille = len(i)-1 #-1 because of the "color" column b,l,n = [],[],[] for j in i: id = list(i).index(j) if(i[j]=="2"): b.append(id) if(i[j]=="0,5"): l.append(id) if(i[j]=="0"): n.append(id) + if(j=="Couleur"): color=i[j] for a in range(len(b),taille):b.append(0) for a in range(len(l),taille):l.append(0) for a in range(len(n),taille):n.append(0) + if(color == None): + raise Exception(f"Pas de couleur pour le type: {i['type']}") + if(len(color.strip()) != 5): + raise Exception(f"Mauvaise couleur pour le type {i['type']} : {color}") + + color = int(color.strip()[1:], 16) type += b"".join(fxconv.u32(value) for value in b) type += b"".join(fxconv.u32(value) for value in l) type += b"".join(fxconv.u32(value) for value in n) + type += fxconv.u16(color) table_type += fxconv.ptr(type) diff --git a/assets-cg/fxconv-metadata.txt b/assets-cg/fxconv-metadata.txt index c6cf87f..09a0baa 100644 --- a/assets-cg/fxconv-metadata.txt +++ b/assets-cg/fxconv-metadata.txt @@ -33,7 +33,7 @@ categories.png: battle_ui.png: type: bopti-image name: img_battle - profile: p4 + profile: p8 player_moves.txt: custom-type: player_moves diff --git a/assets-cg/maps/inside/fxconv-metadata.txt b/assets-cg/maps/inside/fxconv-metadata.txt index 1f4c3f3..7ff8236 100644 --- a/assets-cg/maps/inside/fxconv-metadata.txt +++ b/assets-cg/maps/inside/fxconv-metadata.txt @@ -5,4 +5,4 @@ tileset_in.png: type: bopti-image name: img_tileset_in - profile: p4 + profile: p8 diff --git a/assets-cg/maps/testCarte.tmx b/assets-cg/maps/testCarte.tmx index 9d307ca..373e8cb 100644 --- a/assets-cg/maps/testCarte.tmx +++ b/assets-cg/maps/testCarte.tmx @@ -188,7 +188,7 @@ - + diff --git a/assets-cg/table_type.csv b/assets-cg/table_type.csv index 330c3cb..ddf99b3 100644 --- a/assets-cg/table_type.csv +++ b/assets-cg/table_type.csv @@ -1,5 +1,5 @@ -type,Administrateur,Modérateur,Rédacteur,Labélisateur -Administrateur,0,1,1,2 -Modérateur,0,"0,5",2,2 -Rédacteur,2,1,"0,5",1 -Labélisateur,2,"0,5",1,0 +type,Administrateur,Modérateur,Rédacteur,Labélisateur,Couleur +Administrateur,0,1,1,2,#F800 +Modérateur,0,"0,5",2,2,#3D65 +Rédacteur,2,1,"0,5",1,#341B +Labélisateur,2,"0,5",1,0,#FBA0 diff --git a/include/draw_util.h b/include/draw_util.h new file mode 100644 index 0000000..f9ea74d --- /dev/null +++ b/include/draw_util.h @@ -0,0 +1,5 @@ +#pragma once + +void draw_text(int x, int y, const int color, char const *format, ...); +void draw_change_one_color(int x, int y, bopti_image_t *image, uint16_t from, uint16_t to); +void draw_change_one_color_index(int x, int y, bopti_image_t *image, int index, uint16_t color); \ No newline at end of file diff --git a/include/player.h b/include/player.h index b15f7cd..f975fe6 100644 --- a/include/player.h +++ b/include/player.h @@ -56,4 +56,6 @@ void reset_pp(struct Player *player); void check_level(struct Player *player, int prec_level); void add_xp(struct Player *player, int xp); int select_capacity(struct Player *player, char* context, bool allow_back); -void add_pp(struct Player *player, int amount); \ No newline at end of file +void add_pp(struct Player *player, int amount); +void change_type(struct Player *player, struct Type type); +int yes_no_question(char const *format, ...); \ No newline at end of file diff --git a/include/talkable.h b/include/talkable.h index e07cffb..df201e2 100644 --- a/include/talkable.h +++ b/include/talkable.h @@ -17,5 +17,4 @@ void draw_dialog(struct Game *game); struct Talkable* get_dialog_xy(struct Map *map, int x, int y); char *word_boundary_before(char *str, char *limit); char *skip_spaces(char *str); -void format_text(int x, int y, const int color, char const *format, ...); void format_text_opt(int x, int y, int width, int height, const int color, char const *format, ...); \ No newline at end of file diff --git a/include/type.h b/include/type.h index ca000cc..d6028bc 100644 --- a/include/type.h +++ b/include/type.h @@ -1,5 +1,6 @@ #pragma once #include "define.h" +#include struct Type { char* name; @@ -7,6 +8,7 @@ struct Type { int buff[NB_TYPES+1]; int less[NB_TYPES+1]; int null[NB_TYPES+1]; + const uint16_t color; }; struct Types { diff --git a/include/util.h b/include/util.h index b431c80..f8a00c7 100644 --- a/include/util.h +++ b/include/util.h @@ -2,5 +2,7 @@ /*wait for a specified input key*/ void wait_for_input(int input); - -int rand_range(int low, int high); \ No newline at end of file +int rand_range(int low, int high); +void format_text_opt(int x, int y, int width, int height, const int color, char const *format, ...); +char *word_boundary_before(char *str, char *limit); +char *skip_spaces(char *str); \ No newline at end of file diff --git a/src/battle.c b/src/battle.c index 2882cdd..489e5a9 100644 --- a/src/battle.c +++ b/src/battle.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "engine.h" #include "battle.h" @@ -9,7 +10,7 @@ #include "player.h" #include "monster.h" #include "talkable.h" -#include +#include "draw_util.h" extern bopti_image_t img_dialogue; @@ -115,7 +116,7 @@ void finish_battle(int status, struct Game *game, struct Monster *monster) { //gain d'xp int xp = ceil((monster->stats->xp*monster->stats->level*1.5)/7); - format_text(50, DHEIGHT-47, C_BLACK, "Vous remportez %d points d'experience", xp); + draw_text(50, DHEIGHT-47, C_BLACK, "Vous remportez %d points d'experience", xp); dupdate(); wait_for_input(KEY_SHIFT); @@ -123,7 +124,7 @@ void finish_battle(int status, struct Game *game, struct Monster *monster) { } else if(status == LOSE) { draw_battle(game->player, monster); - format_text(50, DHEIGHT-47, C_BLACK, "%s a eu raison de vous !", monster->name); + draw_text(50, DHEIGHT-47, C_BLACK, "%s a eu raison de vous !", monster->name); dupdate(); wait_for_input(KEY_SHIFT); game->player->stats.pv = 0; @@ -218,12 +219,12 @@ void draw_battle(struct Player *player, struct Monster *monster) { void draw_executed_move(struct Move *move, struct Monster *monster, int is_monster) { if(is_monster) { - format_text(50, DHEIGHT-47, C_BLACK, "%s lance %s !", monster->name, move->name); + draw_text(50, DHEIGHT-47, C_BLACK, "%s lance %s !", monster->name, move->name); } else { - format_text(50, DHEIGHT-47, C_BLACK, "Vous lancez %s !", move->name); + draw_text(50, DHEIGHT-47, C_BLACK, "Vous lancez %s !", move->name); } } void draw_status(char *name, char *message) { - format_text(50, DHEIGHT-47, C_BLACK, "%s %s", name, message); + draw_text(50, DHEIGHT-47, C_BLACK, "%s %s", name, message); } \ No newline at end of file diff --git a/src/capacite.c b/src/capacite.c index 2abd4a9..5c60ff9 100644 --- a/src/capacite.c +++ b/src/capacite.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -8,6 +9,7 @@ #include "capacite.h" #include "util.h" #include "type.h" +#include "draw_util.h" extern struct Capacities capacities; @@ -52,7 +54,7 @@ void draw_move(int x, int y, int x2, int y2, struct Move *move) { extern bopti_image_t img_categories; const int font_size = 8; - dimage(x, y, &img_capacite); + draw_change_one_color(x, y, &img_capacite, 0xE6D6, getTypeFromName(move->type).color); dsubimage(x+96, y+7, &img_categories, 20*move->categorie, 0, 20, 10, DIMAGE_NONE); int color = move->pp > 0 ? C_BLACK : C_RED; @@ -69,7 +71,6 @@ void draw_move(int x, int y, int x2, int y2, struct Move *move) { dprint(x+15, y2-17, C_BLACK, "ATK : %d", move->atk); dprint(x+70, y2-17, C_BLACK, "PRE : %d", move->precision); } - dtext(x+50, y+15, C_BLUE, move->type); } void draw_classic_move(int x, int y, struct Move *move) { diff --git a/src/draw_util.c b/src/draw_util.c new file mode 100644 index 0000000..af27592 --- /dev/null +++ b/src/draw_util.c @@ -0,0 +1,43 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "draw_util.h" +#include "util.h" + +void draw_text(int x, int y, const int color, char const *format, ...) { + int const DIALOG_WIDTH = 295, LINE_HEIGHT = 13; + extern bopti_image_t img_dialogue; + dimage(x-7,y-26,&img_dialogue); + + char text_arg[512]; + va_list args; + va_start(args, format); + vsnprintf(text_arg, 512, format, args); + va_end(args); + + format_text_opt(x, y, DIALOG_WIDTH, LINE_HEIGHT, color, text_arg); +} + +void draw_change_one_color(int x, int y, bopti_image_t *image, uint16_t from, uint16_t to) { + for (int i = 0; i < image->color_count; i++) { + if(image->palette[i] == from) { + image->palette[i] = to; + dimage(x, y, image); + image->palette[i] = from; + return; + } + } +} + +void draw_change_one_color_index(int x, int y, bopti_image_t *image, int index, uint16_t color) { + if(index >= image->color_count) return; + uint16_t init_color = image->palette[index]; + image->palette[index] = color; + dimage(x, y, image); + image->palette[index] = init_color; +} \ No newline at end of file diff --git a/src/event.c b/src/event.c index 898cada..414c7d9 100644 --- a/src/event.c +++ b/src/event.c @@ -7,6 +7,7 @@ #include "capacite.h" #include "inventory.h" #include "item.h" +#include "type.h" bool handle_event(struct Game *game, char const *event) { @@ -45,6 +46,15 @@ bool handle_event(struct Game *game, char const *event) add_pp(game->player, atoi(event)); return true; } + else if(!strncmp(event, "type:", 5)) { + event += 5; + int len=strlen(event); + char name[20]; + strncpy(name,event,len); + name[len] = '\0'; + change_type(game->player, getTypeFromName(name)); + return true; + } else if(!strncmp(event, "move:", 5)) { event += 5; add_move(game->player, get_move_id(atoi(event))); diff --git a/src/inventory.c b/src/inventory.c index 7c02b34..1b36fd9 100644 --- a/src/inventory.c +++ b/src/inventory.c @@ -10,6 +10,7 @@ #include "talkable.h" #include "event.h" #include "item.h" +#include "draw_util.h" #include "game.h" int get_first_free_space(struct Inventory *inventory) { @@ -25,14 +26,14 @@ bool add_item_to_inventory(struct Game *game, struct Inventory *inventory, struc int index = get_first_free_space(inventory); if(index < NB_PLAYER_ITEMS) { - format_text(50, DHEIGHT-47, C_BLACK, "Vous ajoutez %s à votre inventaire !", item->name); + draw_text(50, DHEIGHT-47, C_BLACK, "Vous ajoutez %s à votre inventaire !", item->name); dupdate(); wait_for_input(KEY_SHIFT); inventory->items[index] = item; inventory->nbItems++; return true; } else { - format_text(50, DHEIGHT-47, C_BLACK, "Plus de place pour ajouter %s à votre inventaire !", item->name); + draw_text(50, DHEIGHT-47, C_BLACK, "Plus de place pour ajouter %s à votre inventaire !", item->name); dupdate(); wait_for_input(KEY_SHIFT); int pos = open_inventory(game, inventory, "Remplacer", false); diff --git a/src/player.c b/src/player.c index 576cf95..57e2bcc 100644 --- a/src/player.c +++ b/src/player.c @@ -2,6 +2,8 @@ #include #include #include +#include +#include #include "player.h" #include "define.h" @@ -10,6 +12,7 @@ #include "capacite.h" #include "util.h" #include "talkable.h" +#include "draw_util.h" extern struct LevelUpPlayer levelupplayer; @@ -98,12 +101,12 @@ int get_nb_moves(struct Player *player) { void add_move(struct Player *player, struct Move move) { int index = get_nb_moves(player); if(index != NB_PLAYER_MOVES) { - format_text(50, DHEIGHT-47, C_BLACK, "Vous apprenez %s !", move.name); + draw_text(50, DHEIGHT-47, C_BLACK, "Vous apprenez %s !", move.name); dupdate(); wait_for_input(KEY_SHIFT); player->moves[index] = copy_move(move); } else { - format_text(50, DHEIGHT-47, C_BLACK, "Vous pouvez apprendre %s !", move.name); + draw_text(50, DHEIGHT-47, C_BLACK, "Vous pouvez apprendre %s !", move.name); dupdate(); wait_for_input(KEY_SHIFT); replace_capacities(player, move); @@ -194,7 +197,7 @@ void reset_pp(struct Player *player) { for(int i = 0; i < index; i++) { player->moves[i]->pp = player->moves[i]->init_pp; } - format_text(50, DHEIGHT-47, C_BLACK, "Vous regagnez les PPs de l'ensemble de vos capacités"); + draw_text(50, DHEIGHT-47, C_BLACK, "Vous regagnez les PPs de l'ensemble de vos capacités"); dupdate(); wait_for_input(KEY_SHIFT); } @@ -205,7 +208,7 @@ void add_xp(struct Player *player, int xp) { //niveau suivant une progession N³ int calc_level = (int)pow(player->stats.xp, 0.33); for(int i = player->stats.level; i < calc_level; i++) { - format_text(50, DHEIGHT-47, C_BLACK, "Vous passez au niveau %d !", i+1); + draw_text(50, DHEIGHT-47, C_BLACK, "Vous passez au niveau %d !", i+1); dupdate(); wait_for_input(KEY_SHIFT); } @@ -218,7 +221,56 @@ void add_pp(struct Player *player, int amount) { int selection = select_capacity(player, "Choisir une capacité", false); player->moves[selection]->pp += amount; if(player->moves[selection]->pp > player->moves[selection]->init_pp) player->moves[selection]->pp = player->moves[selection]->init_pp; - format_text(50, DHEIGHT-47, C_BLACK, "Vous regagnez %d PPs sur %s", amount, player->moves[selection]->name); + draw_text(50, DHEIGHT-47, C_BLACK, "Vous regagnez %d PPs sur %s", amount, player->moves[selection]->name); dupdate(); wait_for_input(KEY_SHIFT); +} + +int yes_no_question(char const *format, ...) { + char text_arg[512]; + va_list args; + va_start(args, format); + vsnprintf(text_arg, 512, format, args); + va_end(args); + + int selection = 0; + int buffer = keydown(KEY_SHIFT); + while(1) { + clearevents(); + dclear(C_WHITE); + + selection += keydown(KEY_RIGHT) - keydown(KEY_LEFT); + if(selection > 1) selection = 1; + if(selection < 0) selection = 0; + + format_text_opt(95,10, 200, 13, C_BLACK, text_arg); + + dtext(95,150,C_BLACK, "NON"); + dtext(285,150,C_BLACK, "OUI"); + + dtext(95 + (selection * 190), DHEIGHT-47, C_RED, "[X]"); + dupdate(); + + if(keydown(KEY_SHIFT)) { + if(buffer) buffer = 0; + else break; + } + if(keydown(KEY_EXIT)) { + selection = 0; + break; + } + while(keydown_any(KEY_LEFT,KEY_RIGHT, KEY_SHIFT,0)) clearevents(); + } + return selection; +} + +void change_type(struct Player *player, struct Type type) { + if(strcmp(player->stats.type, type.name) != 0) { + int selection = yes_no_question("Voulez vous changer votre type %s en %s ?", player->stats.type, type.name); + if(selection) player->stats.type = type.name; + } else { + draw_text(50, DHEIGHT-47, C_BLACK, "Vous êtes déjà du type %s !", type.name); + dupdate(); + wait_for_input(KEY_SHIFT); + } } \ No newline at end of file diff --git a/src/talkable.c b/src/talkable.c index b979284..74d1167 100644 --- a/src/talkable.c +++ b/src/talkable.c @@ -11,6 +11,7 @@ #include "util.h" #include "event.h" #include "player.h" +#include "draw_util.h" struct Talkable default_value = { .x = 0, @@ -19,26 +20,6 @@ struct Talkable default_value = { .text = "default dialog" }; -/* Find the last word boundary between [str] and [limit]. If there is no word - boundary (ie. [limit] is in the first word of [str]), returns [limit]. - This function always return a position *after* [str] so that we always make - progress and don't loop. */ -char *word_boundary_before(char *str, char *limit) -{ - char *s = limit; - while(s > str) { - if(isspace(*s) || !*s) return s; - s--; - } - return limit; -} - -/* Skip spaces at the start of [str] */ -char *skip_spaces(char *str) -{ - return str + strspn(str, " \t\n"); -} - /*draw the dialog of a specified talkable tile*/ void draw_dialog(struct Game *game) { const char *delim = ";"; @@ -55,7 +36,7 @@ void draw_dialog(struct Game *game) { char *event = strchr(curr_line, '~'); if(event) handle_event(game, curr_line+1); else { - format_text(50, 58, C_BLACK, curr_line); + draw_text(50, 58, C_BLACK, curr_line); dprint(50,40, C_BLACK, "%s", talk->name); dupdate(); @@ -73,40 +54,4 @@ struct Talkable* get_dialog_xy(struct Map *map, int x, int y) { i++; } return &default_value; -} - -void format_text(int x, int y, const int color, char const *format, ...) { - int const DIALOG_WIDTH = 295, LINE_HEIGHT = 13; - extern bopti_image_t img_dialogue; - dimage(x-7,y-26,&img_dialogue); - - char text_arg[512]; - va_list args; - va_start(args, format); - vsnprintf(text_arg, 512, format, args); - va_end(args); - - format_text_opt(x, y, DIALOG_WIDTH, LINE_HEIGHT, color, text_arg); -} - -void format_text_opt(int x, int y, int width, int height, const int color, char const *format, ...) { - int const DIALOG_WIDTH = width, LINE_HEIGHT = height; - - char text_arg[512]; - va_list args; - va_start(args, format); - vsnprintf(text_arg, 512, format, args); - va_end(args); - - char *text = (char *)malloc(strlen(text_arg)+1); - strcpy(text, text_arg); - - while(*text) { - char *end = (char *)drsize(text, NULL, DIALOG_WIDTH, NULL); - char *last_word = word_boundary_before(text, end); - dtext_opt(x, y, color, C_NONE, DTEXT_LEFT, DTEXT_TOP, - text, last_word - text); - text = skip_spaces(last_word); - y += LINE_HEIGHT; - } } \ No newline at end of file diff --git a/src/type.c b/src/type.c index a45ed9b..73b4364 100644 --- a/src/type.c +++ b/src/type.c @@ -11,6 +11,7 @@ extern struct Types table_type; struct Type default_type = { .name = "-", .id = 0, + .color = 0xE6D6, .buff = {}, .less = {}, .null = {} @@ -47,23 +48,19 @@ float getTypeEffect(struct Type atk, struct Type def) { } void drawTypeEffects(struct Type type) { - while(1) { - dclear(C_WHITE); - dprint(120,10,C_RED, "Table de %s", type.name); - dtext(55,40,C_BLUE, "Super efficace"); - dtext(160,40,C_BLUE, "Peu efficace"); - dtext(260,40,C_BLUE, "Non efficace"); + dclear(C_WHITE); + dprint(120,10,C_RED, "Table de %s", type.name); + dtext(55,40,C_BLUE, "Super efficace"); + dtext(160,40,C_BLUE, "Peu efficace"); + dtext(260,40,C_BLUE, "Non efficace"); - for(int i = 0; i <= 3; i++) { - for(int j = 0; j <= NB_TYPES; j++) { - if(i==0) dprint(70+100*i, 60+20*j, C_BLACK, "%s", getTypeFromId(type.buff[j]).name); - if(i==1) dprint(70+100*i, 60+20*j, C_BLACK, "%s", getTypeFromId(type.less[j]).name); - if(i==2) dprint(70+100*i, 60+20*j, C_BLACK, "%s", getTypeFromId(type.null[j]).name); - } + for(int i = 0; i <= 3; i++) { + for(int j = 0; j <= NB_TYPES; j++) { + if(i==0) dprint(70+100*i, 60+20*j, C_BLACK, "%s", getTypeFromId(type.buff[j]).name); + if(i==1) dprint(70+100*i, 60+20*j, C_BLACK, "%s", getTypeFromId(type.less[j]).name); + if(i==2) dprint(70+100*i, 60+20*j, C_BLACK, "%s", getTypeFromId(type.null[j]).name); } - dupdate(); - pollevent(); - if(keydown(KEY_OPTN)) break; } + dupdate(); wait_for_input(KEY_SHIFT); } \ No newline at end of file diff --git a/src/util.c b/src/util.c index 6c19010..cf659f3 100644 --- a/src/util.c +++ b/src/util.c @@ -1,5 +1,10 @@ #include -#include +#include +#include +#include +#include +#include +#include #include "util.h" @@ -19,4 +24,46 @@ void wait_for_input(int input) { /** * Random [low;high[ */ -int rand_range(int low, int high) { return (rand() % (high - low)) + low; } \ No newline at end of file +int rand_range(int low, int high) { return (rand() % (high - low)) + low; } + +/* Find the last word boundary between [str] and [limit]. If there is no word + boundary (ie. [limit] is in the first word of [str]), returns [limit]. + This function always return a position *after* [str] so that we always make + progress and don't loop. */ +char *word_boundary_before(char *str, char *limit) +{ + char *s = limit; + while(s > str) { + if(isspace(*s) || !*s) return s; + s--; + } + return limit; +} + +/* Skip spaces at the start of [str] */ +char *skip_spaces(char *str) +{ + return str + strspn(str, " \t\n"); +} + +void format_text_opt(int x, int y, int width, int height, const int color, char const *format, ...) { + int const DIALOG_WIDTH = width, LINE_HEIGHT = height; + + char text_arg[512]; + va_list args; + va_start(args, format); + vsnprintf(text_arg, 512, format, args); + va_end(args); + + char *text = (char *)malloc(strlen(text_arg)+1); + strcpy(text, text_arg); + + while(*text) { + char *end = (char *)drsize(text, NULL, DIALOG_WIDTH, NULL); + char *last_word = word_boundary_before(text, end); + dtext_opt(x, y, color, C_NONE, DTEXT_LEFT, DTEXT_TOP, + text, last_word - text); + text = skip_spaces(last_word); + y += LINE_HEIGHT; + } +} \ No newline at end of file