void move_object(int objj,int tox,int toy,int spee,int ignwal) { if (!is_valid_object(objj)) quit("!MoveObject: invalid object number"); debug_script_log("Object %d start move to %d,%d", objj, tox, toy); int objX = objs[objj].x; int objY = objs[objj].y; set_route_move_speed(spee, spee); set_color_depth(8); int mslot=find_route(objX, objY, tox, toy, prepare_walkable_areas(-1), objj+1, 1, ignwal); set_color_depth(game.GetColorDepth()); if (mslot>0) { objs[objj].moving = mslot; mls[mslot].direct = ignwal; } }
void draw_text_window_and_bar(Bitmap **text_window_ds, bool should_free_ds, int*xins,int*yins,int*xx,int*yy,int*wii,color_t *set_text_color,int ovrheight, int ifnum) { draw_text_window(text_window_ds, should_free_ds, xins, yins, xx, yy, wii, set_text_color, ovrheight, ifnum); if ((topBar.wantIt) && (text_window_ds && *text_window_ds)) { // top bar on the dialog window with character's name // create an enlarged window, then free the old one Bitmap *ds = *text_window_ds; Bitmap *newScreenop = BitmapHelper::CreateBitmap(ds->GetWidth(), ds->GetHeight() + topBar.height, game.GetColorDepth()); newScreenop->Blit(ds, 0, 0, 0, topBar.height, ds->GetWidth(), ds->GetHeight()); delete *text_window_ds; *text_window_ds = newScreenop; ds = *text_window_ds; // draw the top bar color_t draw_color = ds->GetCompatibleColor(play.top_bar_backcolor); ds->FillRect(Rect(0, 0, ds->GetWidth() - 1, topBar.height - 1), draw_color); if (play.top_bar_backcolor != play.top_bar_bordercolor) { // draw the border draw_color = ds->GetCompatibleColor(play.top_bar_bordercolor); for (int j = 0; j < play.top_bar_borderwidth; j++) ds->DrawRect(Rect(j, j, ds->GetWidth() - (j + 1), topBar.height - (j + 1)), draw_color); } // draw the text int textx = (ds->GetWidth() / 2) - wgettextwidth_compensate(topBar.text, topBar.font) / 2; color_t text_color = ds->GetCompatibleColor(play.top_bar_textcolor); wouttext_outline(ds, textx, play.top_bar_borderwidth + 1, topBar.font, text_color, topBar.text); // don't draw it next time topBar.wantIt = 0; // adjust the text Y position yins[0] += topBar.height; } else if (topBar.wantIt) topBar.wantIt = 0; }
// Pass yy = -1 to find Y co-ord automatically // allowShrink = 0 for none, 1 for leftwards, 2 for rightwards // pass blocking=2 to create permanent overlay int _display_main(int xx,int yy,int wii,const char*text,int blocking,int usingfont,int asspch, int isThought, int allowShrink, bool overlayPositionFixed) { const bool use_speech_textwindow = (asspch < 0) && (game.options[OPT_SPEECHTYPE] >= 2); const bool use_thought_gui = (isThought) && (game.options[OPT_THOUGHTGUI] > 0); bool alphaChannel = false; char todis[STD_BUFFER_SIZE]; snprintf(todis, STD_BUFFER_SIZE - 1, "%s", text); int usingGui = -1; if (use_speech_textwindow) usingGui = play.speech_textwindow_gui; else if (use_thought_gui) usingGui = game.options[OPT_THOUGHTGUI]; int padding = get_textwindow_padding(usingGui); int paddingScaled = padding; int paddingDoubledScaled = padding * 2; // Just in case screen size does is not neatly divisible by 320x200 ensure_text_valid_for_font(todis, usingfont); break_up_text_into_lines(wii-2*padding,usingfont,todis); disp.lineheight = getfontheight_outlined(usingfont); disp.linespacing= getfontspacing_outlined(usingfont); disp.fulltxtheight = getheightoflines(usingfont, numlines); // if it's a normal message box and the game was being skipped, // ensure that the screen is up to date before the message box // is drawn on top of it if ((play.skip_until_char_stops >= 0) && (blocking == 1)) render_graphics(); EndSkippingUntilCharStops(); if (topBar.wantIt) { // ensure that the window is wide enough to display // any top bar text int topBarWid = wgettextwidth_compensate(topBar.text, topBar.font); topBarWid += (play.top_bar_borderwidth + 2) * 2; if (longestline < topBarWid) longestline = topBarWid; // the top bar should behave like DisplaySpeech wrt blocking blocking = 0; } if (asspch > 0) { // update the all_buttons_disabled variable in advance // of the adjust_x/y_for_guis calls play.disabled_user_interface++; update_gui_disabled_status(); play.disabled_user_interface--; } const Rect &ui_view = play.GetUIViewport(); if (xx == OVR_AUTOPLACE) ; // centre text in middle of screen else if (yy<0) yy= ui_view.GetHeight()/2-disp.fulltxtheight/2-padding; // speech, so it wants to be above the character's head else if (asspch > 0) { yy-=disp.fulltxtheight; if (yy < 5) yy=5; yy = adjust_y_for_guis (yy); } if (longestline < wii - paddingDoubledScaled) { // shrink the width of the dialog box to fit the text int oldWid = wii; //if ((asspch >= 0) || (allowShrink > 0)) // If it's not speech, or a shrink is allowed, then shrink it if ((asspch == 0) || (allowShrink > 0)) wii = longestline + paddingDoubledScaled; // shift the dialog box right to align it, if necessary if ((allowShrink == 2) && (xx >= 0)) xx += (oldWid - wii); } if (xx<-1) { xx=(-xx)-wii/2; if (xx < 0) xx = 0; xx = adjust_x_for_guis (xx, yy); if (xx + wii >= ui_view.GetWidth()) xx = (ui_view.GetWidth() - wii) - 5; } else if (xx<0) xx= ui_view.GetWidth()/2-wii/2; int ee, extraHeight = paddingDoubledScaled; color_t text_color = MakeColor(15); if (blocking < 2) remove_screen_overlay(OVER_TEXTMSG); Bitmap *text_window_ds = BitmapHelper::CreateTransparentBitmap((wii > 0) ? wii : 2, disp.fulltxtheight + extraHeight, game.GetColorDepth()); // inform draw_text_window to free the old bitmap const bool wantFreeScreenop = true; if ((strlen (todis) < 1) || (strcmp (todis, " ") == 0) || (wii == 0)) ; // if it's an empty speech line, don't draw anything else if (asspch) { //text_color = ds->GetCompatibleColor(12); int ttxleft = 0, ttxtop = paddingScaled, oriwid = wii - padding * 2; int drawBackground = 0; if (use_speech_textwindow) { drawBackground = 1; } else if (use_thought_gui) { // make it treat it as drawing inside a window now if (asspch > 0) asspch = -asspch; drawBackground = 1; } if (drawBackground) { draw_text_window_and_bar(&text_window_ds, wantFreeScreenop, &ttxleft, &ttxtop, &xx, &yy, &wii, &text_color, 0, usingGui); if (usingGui > 0) { alphaChannel = guis[usingGui].HasAlphaChannel(); } } else if ((ShouldAntiAliasText()) && (game.GetColorDepth() >= 24)) alphaChannel = true; for (ee=0;ee<numlines;ee++) { //int ttxp=wii/2 - wgettextwidth_compensate(lines[ee], usingfont)/2; int ttyp=ttxtop+ee*disp.linespacing; // asspch < 0 means that it's inside a text box so don't // centre the text if (asspch < 0) { if ((usingGui >= 0) && ((game.options[OPT_SPEECHTYPE] >= 2) || (isThought))) text_color = text_window_ds->GetCompatibleColor(guis[usingGui].FgColor); else text_color = text_window_ds->GetCompatibleColor(-asspch); wouttext_aligned(text_window_ds, ttxleft, ttyp, oriwid, usingfont, text_color, lines[ee], play.text_align); } else { text_color = text_window_ds->GetCompatibleColor(asspch); //wouttext_outline(ttxp,ttyp,usingfont,lines[ee]); wouttext_aligned(text_window_ds, ttxleft, ttyp, wii, usingfont, text_color, lines[ee], play.speech_text_align); } } } else { int xoffs,yoffs, oriwid = wii - padding * 2; draw_text_window_and_bar(&text_window_ds, wantFreeScreenop, &xoffs,&yoffs,&xx,&yy,&wii,&text_color); if (game.options[OPT_TWCUSTOM] > 0) { alphaChannel = guis[game.options[OPT_TWCUSTOM]].HasAlphaChannel(); } adjust_y_coordinate_for_text(&yoffs, usingfont); for (ee=0;ee<numlines;ee++) wouttext_aligned (text_window_ds, xoffs, yoffs + ee * disp.linespacing, oriwid, usingfont, text_color, lines[ee], play.text_align); } int ovrtype = OVER_TEXTMSG; if (blocking == 2) ovrtype=OVER_CUSTOM; else if (blocking >= OVER_CUSTOM) ovrtype=blocking; int nse = add_screen_overlay(xx, yy, ovrtype, text_window_ds, alphaChannel); // we should not delete text_window_ds here, because it is now owned by Overlay if (blocking>=2) { return screenover[nse].type; } if (blocking) { if (play.fast_forward) { remove_screen_overlay(OVER_TEXTMSG); play.messagetime=-1; return 0; } /* wputblock(xx,yy,screenop,1); remove_screen_overlay(OVER_TEXTMSG);*/ if (!play.mouse_cursor_hidden) ags_domouse(DOMOUSE_ENABLE); // play.skip_display has same values as SetSkipSpeech: // 0 = click mouse or key to skip // 1 = key only // 2 = can't skip at all // 3 = only on keypress, no auto timer // 4 = mouse only int countdown = GetTextDisplayTime (todis); int skip_setting = user_to_internal_skip_speech((SkipSpeechStyle)play.skip_display); while (1) { /* if (!play.mouse_cursor_hidden) ags_domouse(DOMOUSE_UPDATE); write_screen();*/ update_audio_system_on_game_loop(); render_graphics(); if (ags_mgetbutton()>NONE) { // If we're allowed, skip with mouse if (skip_setting & SKIP_MOUSECLICK) break; } int kp; if (run_service_key_controls(kp)) { // let them press ESC to skip the cutscene check_skip_cutscene_keypress (kp); if (play.fast_forward) break; if (skip_setting & SKIP_KEYPRESS) break; } PollUntilNextFrame(); countdown--; if (play.speech_has_voice) { // extend life of text if the voice hasn't finished yet if (channel_is_playing(SCHAN_SPEECH) && (play.fast_forward == 0)) { if (countdown <= 1) countdown = 1; } else // if the voice has finished, remove the speech countdown = 0; } if ((countdown < 1) && (skip_setting & SKIP_AUTOTIMER)) { play.ignore_user_input_until_time = AGS_Clock::now() + std::chrono::milliseconds(play.ignore_user_input_after_text_timeout_ms); break; } // if skipping cutscene, don't get stuck on No Auto Remove // text boxes if ((countdown < 1) && (play.fast_forward)) break; } if (!play.mouse_cursor_hidden) ags_domouse(DOMOUSE_DISABLE); remove_screen_overlay(OVER_TEXTMSG); construct_virtual_screen(true); } else { // if the speech does not time out, but we are skipping a cutscene, // allow it to time out if ((play.messagetime < 0) && (play.fast_forward)) play.messagetime = 2; if (!overlayPositionFixed) { screenover[nse].positionRelativeToScreen = false; VpPoint vpt = play.ScreenToRoom(screenover[nse].x, screenover[nse].y, false); screenover[nse].x = vpt.first.X; screenover[nse].y = vpt.first.Y; } GameLoopUntilEvent(UNTIL_NOOVERLAY,0); } play.messagetime=-1; return 0; }
void draw_text_window(Bitmap **text_window_ds, bool should_free_ds, int*xins,int*yins,int*xx,int*yy,int*wii, color_t *set_text_color, int ovrheight, int ifnum) { Bitmap *ds = *text_window_ds; if (ifnum < 0) ifnum = game.options[OPT_TWCUSTOM]; if (ifnum <= 0) { if (ovrheight) quit("!Cannot use QFG4 style options without custom text window"); draw_button_background(ds, 0,0,ds->GetWidth() - 1,ds->GetHeight() - 1,nullptr); if (set_text_color) *set_text_color = ds->GetCompatibleColor(16); xins[0]=3; yins[0]=3; } else { if (ifnum >= game.numgui) quitprintf("!Invalid GUI %d specified as text window (total GUIs: %d)", ifnum, game.numgui); if (!guis[ifnum].IsTextWindow()) quit("!GUI set as text window but is not actually a text window GUI"); int tbnum = get_but_pic(&guis[ifnum], 0); wii[0] += get_textwindow_border_width (ifnum); xx[0]-=game.SpriteInfos[tbnum].Width; yy[0]-=game.SpriteInfos[tbnum].Height; if (ovrheight == 0) ovrheight = disp.fulltxtheight; if (should_free_ds) delete *text_window_ds; int padding = get_textwindow_padding(ifnum); *text_window_ds = BitmapHelper::CreateTransparentBitmap(wii[0],ovrheight+(padding*2)+ game.SpriteInfos[tbnum].Height*2,game.GetColorDepth()); ds = *text_window_ds; int xoffs=game.SpriteInfos[tbnum].Width,yoffs= game.SpriteInfos[tbnum].Height; draw_button_background(ds, xoffs,yoffs,(ds->GetWidth() - xoffs) - 1,(ds->GetHeight() - yoffs) - 1,&guis[ifnum]); if (set_text_color) *set_text_color = ds->GetCompatibleColor(guis[ifnum].FgColor); xins[0]=xoffs+padding; yins[0]=yoffs+padding; } }