diff --git a/src/config.h b/src/config.h index 19aad6fc..9c21efb8 100644 --- a/src/config.h +++ b/src/config.h @@ -52,6 +52,7 @@ CONFIGDEF_KEYBINDING(KEY_NOBACKGROUND, "key_nobackground", SDL_SCANCODE_LALT) \ CONFIGDEF_KEYBINDING(KEY_POWERUP, "key_powerup", SDL_SCANCODE_2) \ CONFIGDEF_KEYBINDING(KEY_POWERDOWN, "key_powerdown", SDL_SCANCODE_1) \ + CONFIGDEF_KEYBINDING(KEY_FPSLIMIT_OFF, "key_fpslimit_off", SDL_SCANCODE_RSHIFT) \ #define GPKEYDEFS \ diff --git a/src/dialog.c b/src/dialog.c index 484d0167..6168efad 100644 --- a/src/dialog.c +++ b/src/dialog.c @@ -105,7 +105,8 @@ void draw_dialog(Dialog *dialog) { if(dialog->messages[dialog->pos].side == Right) glColor3f(0.6,0.6,1); - draw_text(AL_Center, VIEWPORT_W/2, VIEWPORT_H-110, dialog->messages[dialog->pos].msg, _fonts.standard); + + draw_text_auto_wrapped(AL_Center, VIEWPORT_W/2, VIEWPORT_H-110, dialog->messages[dialog->pos].msg, VIEWPORT_W * 0.85, _fonts.standard); if(dialog->messages[dialog->pos].side == Right) glColor3f(1,1,1); diff --git a/src/player.c b/src/player.c index fee014ad..03c43218 100644 --- a/src/player.c +++ b/src/player.c @@ -520,7 +520,7 @@ bool player_event(Player *plr, uint8_t type, uint16_t value) { break; case EV_RELEASE: - player_setinputflag(plr, value, false); + useful = player_setinputflag(plr, value, false); break; case EV_AXIS_LR: diff --git a/src/resource/font.c b/src/resource/font.c index 7c418d62..c6328e7f 100644 --- a/src/resource/font.c +++ b/src/resource/font.c @@ -213,6 +213,12 @@ void draw_text(Alignment align, float x, float y, const char *text, TTF_Font *fo free(buf); } +void draw_text_auto_wrapped(Alignment align, float x, float y, const char *text, int width, TTF_Font *font) { + char buf[strlen(text) * 2]; + wrap_text(buf, sizeof(buf), text, width, font); + draw_text(align, x, y, buf, font); +} + int stringwidth(char *s, TTF_Font *font) { int w; TTF_SizeUTF8(font, s, &w, NULL); @@ -248,3 +254,60 @@ void shorten_text_up_to_width(char *s, float width, TTF_Font *font) { } } } + +void wrap_text(char *buf, size_t bufsize, const char *src, int width, TTF_Font *font) { + assert(buf != NULL); + assert(src != NULL); + assert(font != NULL); + assert(bufsize > strlen(src) + 1); + assert(width > 0); + + char src_copy[strlen(src) + 1]; + char *sptr = src_copy; + char *next = NULL; + char *curline = buf; + + strcpy(src_copy, src); + *buf = 0; + + while(next = strtok_r(NULL, " \t\n", &sptr)) { + int curwidth; + + if(!*next) { + continue; + } + + if(*curline) { + curwidth = stringwidth(curline, font); + } else { + curwidth = 0; + } + + char tmpbuf[strlen(curline) + strlen(next) + 2]; + strcpy(tmpbuf, curline); + strcat(tmpbuf, " "); + strcat(tmpbuf, next); + + int totalwidth = stringwidth(tmpbuf, font); + + if(totalwidth > width) { + if(curwidth == 0) { + log_fatal( + "Single word '%s' won't fit on one line. " + "Word width: %i, max width: %i, source string: %s", + next, stringwidth(next, font), width, src + ); + } + + strlcat(buf, "\n", bufsize); + curline = strchr(curline, 0); + } else { + if(*curline) { + strlcat(buf, " ", bufsize); + } + + } + + strlcat(buf, next, bufsize); + } +} diff --git a/src/resource/font.h b/src/resource/font.h index 9e4aee62..c306d94f 100644 --- a/src/resource/font.h +++ b/src/resource/font.h @@ -40,12 +40,15 @@ SDL_Surface* fontrender_render(FontRenderer *f, const char *text, TTF_Font *font Texture *load_text(const char *text, TTF_Font *font); void draw_text(Alignment align, float x, float y, const char *text, TTF_Font *font); +void draw_text_auto_wrapped(Alignment align, float x, float y, const char *text, int width, TTF_Font *font); void draw_text_prerendered(Alignment align, float x, float y, SDL_Surface *surf); int stringwidth(char *s, TTF_Font *font); int stringheight(char *s, TTF_Font *font); int charwidth(char c, TTF_Font *font); + void shorten_text_up_to_width(char *s, float width, TTF_Font *font); +void wrap_text(char *buf, size_t bufsize, const char *src, int width, TTF_Font *font); void init_fonts(void); void uninit_fonts(void); diff --git a/src/stage.c b/src/stage.c index 5e6288dd..8c6d364e 100644 --- a/src/stage.c +++ b/src/stage.c @@ -280,10 +280,6 @@ bool stage_input_handler_gameplay(SDL_Event *event, void *arg) { switch(type) { case TE_GAME_KEY_DOWN: - if(code == KEY_NOBACKGROUND) { - break; - } - if(code == KEY_HAHAIWIN) { #ifdef DEBUG stage_finish(GAMEOVER_WIN); @@ -516,7 +512,11 @@ typedef struct StageFrameState { } StageFrameState; static bool stage_fpslimit_condition(void *arg) { +#ifdef DEBUG + return !gamekeypressed(KEY_FPSLIMIT_OFF) && (global.replaymode != REPLAY_PLAY || !gamekeypressed(KEY_SKIP)) && !global.frameskip; +#else return (global.replaymode != REPLAY_PLAY || !gamekeypressed(KEY_SKIP)) && !global.frameskip; +#endif } static bool stage_frame(void *arg) { diff --git a/src/stages/stage5_events.c b/src/stages/stage5_events.c index a6760561..8bdb7e5d 100644 --- a/src/stages/stage5_events.c +++ b/src/stages/stage5_events.c @@ -34,7 +34,8 @@ Dialog *stage5_boss_dialog(void) { dadd_msg(d,Right, "Weren’t those earlier bombs enough of\na deterrent? As this world is cutting\ninto the space of Heaven, only those\nauthorized are allowed to investigate."); dadd_msg(d,Right, "You’re not a Celestial or anyone else\nfrom Heaven. That means you cannot go\nfurther."); dadd_msg(d,Left, "C’mon, you’re good at readin’ the atmosphere,\nright? Then ya should know that I’m not gonna\nback down after comin’ this far."); - dadd_msg(d,Right, "I don’t have time to reason with you,\nunfortunately. When it comes to an average\nhuman sticking out arrogantly, there’s only one reasonable\ncourse of action for a bolt of lightning to take."); + dadd_msg(d,Right, "I don’t have time to reason with you,\nunfortunately."); + dadd_msg(d,Right, "When it comes to an average\nhuman sticking out arrogantly, there’s only one reasonable\ncourse of action for a bolt of lightning to take."); dadd_msg(d,Right, "Prepare to be struck down from\nHeaven’s door!"); } else if(pc->id == PLR_CHAR_YOUMU) { dadd_msg(d,Left, "You were quite difficult to pin down.\nDon’t worry; I’ll listen to whatever warning\nyou have before I continue forward."); diff --git a/src/stages/stage6_events.c b/src/stages/stage6_events.c index a24059f7..ec6b7ca1 100644 --- a/src/stages/stage6_events.c +++ b/src/stages/stage6_events.c @@ -33,7 +33,8 @@ Dialog *stage6_dialog(void) { dadd_msg(d,Right, "That is because you completely misunderstand.\nI am not a shikigami, and never was. My duty\nwas once to protect a powerful youkai, but when she\nleft for Gensokyo, I was left behind."); dadd_msg(d,Right, "Together with my friend, Kurumi, we left for the\nOutside World and were stranded there. But I gained an incredible\nnew power once I realized my true calling as a mathematical theorist."); dadd_msg(d,Left, "I don’t completely follow, but if you’re a youkai,\nI can’t see how you could be a scientist.\nIt goes against your nature."); - dadd_msg(d,Right, "An unenlightened fool such as yourself could never\ncomprehend my transcendence. I have become more than a simple youkai,\nfor I alone am now capable of discovering the secrets\nbehind the illusion of reality!"); + dadd_msg(d,Right, "An unenlightened fool such as yourself could never\ncomprehend my transcendence."); + dadd_msg(d,Right, "I have become more than a simple youkai,\nfor I alone am now capable of discovering the secrets\nbehind the illusion of reality!"); dadd_msg(d,Left, "Well, whatever you’re doing here is disintegrating\nthe barrier of common sense and madness keeping Gensokyo\nfrom collapsing into the Outside World."); dadd_msg(d,Left, "You’re also infringing on the Netherworld’s\nspace and my mistress is particularly upset\nabout that. That means I have to stop you, no matter what."); dadd_msg(d,Right, "Pitiful servant of the dead. You’ll never\nbe able to stop my life’s work from being fulfilled!\nI’ll simply unravel that nonsense behind your half-and-half\nexistence!"); @@ -47,9 +48,13 @@ static Dialog *stage6_interboss_dialog(void) { PlayerCharacter *pc = global.plr.mode->character; Dialog *d = create_dialog(pc->dialog_sprite_name, "dialog/elly"); - dadd_msg(d, Right, "You’ve gotten this far… I can’t believe it!\nBut that will not matter once I show you the\ntruth of this world, and every world. Space, time, dimensions…\nit all becomes clear when you understand\nThe Theory of Everything!\nPrepare to see the barrier destroyed!"); + dadd_msg(d, Right, "You’ve gotten this far… I can’t believe it!\nBut that will not matter once I show you the\ntruth of this world, and every world."); + dadd_msg(d, Right, "Space, time, dimensions…\nit all becomes clear when you understand\nThe Theory of Everything!"); + dadd_msg(d, Right, "Prepare to see the barrier destroyed!"); + return d; } + int stage6_hacker(Enemy *e, int t) { TIMER(&t); AT(EVENT_DEATH) { @@ -1555,6 +1560,12 @@ Boss* stage6_spawn_elly(complex pos) { return b; } +static void elly_insert_interboss_dialog(Boss *b, int t) { + if(t == 0) { + global.dialog = stage6_interboss_dialog(); + } +} + Boss* create_elly(void) { Boss *b = stage6_spawn_elly(-200.0*I); @@ -1571,6 +1582,7 @@ Boss* create_elly(void) { boss_add_attack_from_info(b, &stage6_spells.baryon.spacetime_curvature, false); boss_add_attack(b, AT_Normal, "Baryon", 40, 50000, elly_baryonattack2, NULL); boss_add_attack_from_info(b, &stage6_spells.baryon.higgs_boson_uncovered, false); + boss_add_attack(b, AT_Move, "", 0, 0, elly_insert_interboss_dialog, NULL); boss_add_attack(b, AT_Move, "Explode", 6, 10, elly_baryon_explode, NULL); boss_add_attack_from_info(b, &stage6_spells.extra.curvature_domination, false); boss_add_attack_from_info(b, &stage6_spells.final.theory_of_everything, false);