static void GUI_Purchase_ShowInvoice(void) { Widget *w = g_widgetInvoiceTail; Screen oldScreenID; uint16 y = 48; uint16 total = 0; uint16 x; char textBuffer[12]; oldScreenID = GFX_Screen_SetActive(SCREEN_1); GUI_DrawFilledRectangle(128, 48, 311, 159, 20); GUI_DrawText_Wrapper(String_Get_ByIndex(STR_ITEM_NAME_QTY_TOTAL), 128, y, 12, 0, 0x11); y += 7; GUI_DrawLine(129, y, 310, y, 12); y += 2; if (g_factoryWindowOrdered != 0) { uint16 i; for (i = 0; i < g_factoryWindowTotal; i++) { ObjectInfo *oi; uint16 amount; if (g_factoryWindowItems[i].amount == 0) continue; amount = g_factoryWindowItems[i].amount * g_factoryWindowItems[i].credits; total += amount; snprintf(textBuffer, sizeof(textBuffer), "%02d %5d", g_factoryWindowItems[i].amount, amount); oi = g_factoryWindowItems[i].objectInfo; GUI_DrawText_Wrapper(String_Get_ByIndex(oi->stringID_full), 128, y, 8, 0, 0x11); GUI_DrawText_Monospace(textBuffer, 311 - strlen(textBuffer) * 6, y, 15, 0, 6); y += 8; } } else { GUI_DrawText_Wrapper(String_Get_ByIndex(STR_NO_UNITS_ON_ORDER), 220, 99, 6, 0, 0x112); } GUI_DrawLine(129, 148, 310, 148, 12); GUI_DrawLine(129, 150, 310, 150, 12); snprintf(textBuffer, sizeof(textBuffer), "%d", total); x = 311 - strlen(textBuffer) * 6; /* "Total Cost :" */ GUI_DrawText_Wrapper(GUI_String_Get_ByIndex(STR_TOTAL_COST_), x - 3, 152, 11, 0, 0x211); GUI_DrawText_Monospace(textBuffer, x, 152, 11, 0, 6); GUI_Mouse_Hide_Safe(); GUI_Screen_Copy(16, 48, 16, 48, 23, 112, SCREEN_1, SCREEN_0); GUI_Mouse_Show_Safe(); GFX_Screen_SetActive(SCREEN_0); GUI_FactoryWindow_DrawCaption(String_Get_ByIndex(STR_INVOICE_OF_UNITS_ON_ORDER)); Input_History_Clear(); for (; GUI_Widget_HandleEvents(w) == 0; sleepIdle()) { GUI_DrawCredits(g_playerHouseID, 0); GUI_FactoryWindow_UpdateSelection(false); GUI_PaletteAnimate(); } GFX_Screen_SetActive(oldScreenID); w = GUI_Widget_Get_ByIndex(w, 10); if (w != NULL && Mouse_InsideRegion(w->offsetX, w->offsetY, w->offsetX + w->width, w->offsetY + w->height) != 0) { while (Input_Test(0x41) != 0 || Input_Test(0x42) != 0) sleepIdle(); Input_History_Clear(); } if (g_factoryWindowResult == FACTORY_CONTINUE) GUI_FactoryWindow_DrawDetails(); }
/** * Draw sprites and handle mouse in a mentat screen. * @param speakingMode If \c 1, the mentat is speaking. */ void GUI_Mentat_Animation(uint16 speakingMode) { static uint32 movingEyesTimer = 0; /* Timer when to change the eyes sprite. */ static uint16 movingEyesSprite = 0; /* Index in _mentatSprites of the displayed moving eyes. */ static uint16 movingEyesNextSprite = 0; /* If not 0, it decides the movingEyesNextSprite */ static uint32 movingMouthTimer = 0; static uint16 movingMouthSprite = 0; static uint32 movingOtherTimer = 0; static int16 otherSprite = 0; bool partNeedsRedraw; uint16 i; if (movingOtherTimer < g_timerGUI && !g_disableOtherMovement) { if (movingOtherTimer != 0) { uint8 *sprite; if (s_mentatSprites[2][1 + abs(otherSprite)] == NULL) { otherSprite = 1 - otherSprite; } else { otherSprite++; } sprite = s_mentatSprites[2][abs(otherSprite)]; GUI_Mouse_Hide_InRegion(s_otherLeft, s_otherTop, s_otherLeft + Sprite_GetWidth(sprite), s_otherTop + Sprite_GetHeight(sprite)); GUI_DrawSprite(SCREEN_0, sprite, s_otherLeft, s_otherTop, 0, 0); GUI_Mouse_Show_InRegion(); } switch (g_playerHouseID) { case HOUSE_HARKONNEN: movingOtherTimer = g_timerGUI + 300 * 60; break; case HOUSE_ATREIDES: movingOtherTimer = g_timerGUI + 60 * Tools_RandomLCG_Range(1,3); break; case HOUSE_ORDOS: if (otherSprite != 0) { movingOtherTimer = g_timerGUI + 6; } else { movingOtherTimer = g_timerGUI + 60 * Tools_RandomLCG_Range(10, 19); } break; default: break; } } if (speakingMode == 1) { if (movingMouthTimer < g_timerGUI) { uint8 *sprite; movingMouthSprite = Tools_RandomLCG_Range(0, 4); sprite = s_mentatSprites[1][movingMouthSprite]; GUI_Mouse_Hide_InRegion(s_mouthLeft, s_mouthTop, s_mouthLeft + Sprite_GetWidth(sprite), s_mouthTop + Sprite_GetHeight(sprite)); GUI_DrawSprite(SCREEN_0, sprite, s_mouthLeft, s_mouthTop, 0, 0); GUI_Mouse_Show_InRegion(); switch (movingMouthSprite) { case 0: movingMouthTimer = g_timerGUI + Tools_RandomLCG_Range(7, 30); break; case 1: case 2: case 3: movingMouthTimer = g_timerGUI + Tools_RandomLCG_Range(6, 10); break; case 4: movingMouthTimer = g_timerGUI + Tools_RandomLCG_Range(5, 6); break; default: break; } } } else { partNeedsRedraw = false; if (Input_Test(0x41) == 0 && Input_Test(0x42) == 0) { if (movingMouthSprite != 0) { movingMouthSprite = 0; movingMouthTimer = 0; partNeedsRedraw = true; } } else if (Mouse_InsideRegion(s_mouthLeft, s_mouthTop, s_mouthRight, s_mouthBottom) != 0) { if (movingMouthTimer != 0xFFFFFFFF) { movingMouthTimer = 0xFFFFFFFF; movingMouthSprite = Tools_RandomLCG_Range(1, 4); partNeedsRedraw = true; } } else { if (movingMouthSprite != 0) { movingMouthSprite = 0; movingMouthTimer = 0; partNeedsRedraw = true; } } if (partNeedsRedraw) { uint8 *sprite; sprite = s_mentatSprites[1][movingMouthSprite]; GUI_Mouse_Hide_InRegion(s_mouthLeft, s_mouthTop, s_mouthLeft + Sprite_GetWidth(sprite), s_mouthTop + Sprite_GetHeight(sprite)); GUI_DrawSprite(SCREEN_0, sprite, s_mouthLeft, s_mouthTop, 0, 0); GUI_Mouse_Show_InRegion(); } } partNeedsRedraw = false; if (Input_Test(0x41) != 0 || Input_Test(0x42) != 0) { if (Mouse_InsideRegion(s_eyesLeft, s_eyesTop, s_eyesRight, s_eyesBottom) != 0) { if (movingEyesSprite != 0x4) { partNeedsRedraw = true; movingEyesSprite = (movingEyesSprite == 3) ? 4 : 3; movingEyesNextSprite = 0; movingEyesTimer = 0; } if (partNeedsRedraw) { uint8 *sprite; sprite = s_mentatSprites[0][movingEyesSprite]; GUI_Mouse_Hide_InRegion(s_eyesLeft, s_eyesTop, s_eyesLeft + Sprite_GetWidth(sprite), s_eyesTop + Sprite_GetHeight(sprite)); GUI_DrawSprite(SCREEN_0, sprite, s_eyesLeft, s_eyesTop, 0, 0); GUI_Mouse_Show_InRegion(); } return; } } if (Mouse_InsideRegion((int16)s_eyesLeft - 16, (int16)s_eyesTop - 8, s_eyesRight + 16, s_eyesBottom + 24) != 0) { if (Mouse_InsideRegion((int16)s_eyesLeft - 8, s_eyesBottom, s_eyesRight + 8, SCREEN_HEIGHT - 1) != 0) { i = 3; } else { if (Mouse_InsideRegion(s_eyesRight, (int16)s_eyesTop - 8, s_eyesRight + 16, s_eyesBottom + 8) != 0) { i = 2; } else { i = (Mouse_InsideRegion((int16)s_eyesLeft - 16, (int16)s_eyesTop - 8, s_eyesLeft, s_eyesBottom + 8) == 0) ? 0 : 1; } } if (i != movingEyesSprite) { partNeedsRedraw = true; movingEyesSprite = i; movingEyesNextSprite = 0; movingEyesTimer = g_timerGUI; } } else { if (movingEyesTimer >= g_timerGUI) return; partNeedsRedraw = true; if (movingEyesNextSprite != 0) { movingEyesSprite = movingEyesNextSprite; movingEyesNextSprite = 0; if (movingEyesSprite != 4) { movingEyesTimer = g_timerGUI + Tools_RandomLCG_Range(20, 180); } else { movingEyesTimer = g_timerGUI + Tools_RandomLCG_Range(12, 30); } } else { i = 0; switch (speakingMode) { case 0: i = Tools_RandomLCG_Range(0, 7); if (i > 5) { i = 1; } else { if (i == 5) { i = 4; } } break; case 1: if (movingEyesSprite != ((!g_interrogation) ? 0 : 3)) { i = 0; } else { i = Tools_RandomLCG_Range(0, 17); if (i > 9) { i = 0; } else { if (i >= 5) { i = 4; } } } break; default: i = Tools_RandomLCG_Range(0, 15); if (i > 10) { i = 2; } else { if (i >= 5) { i = 4; } } break; } if ((i == 2 && movingEyesSprite == 1) || (i == 1 && movingEyesSprite == 2)) { movingEyesNextSprite = i; movingEyesSprite = 0; movingEyesTimer = g_timerGUI + Tools_RandomLCG_Range(1, 5); } else { if (i != movingEyesSprite && (i == 4 || movingEyesSprite == 4)) { movingEyesNextSprite = i; movingEyesSprite = 3; movingEyesTimer = g_timerGUI; } else { movingEyesSprite = i; if (i != 4) { movingEyesTimer = g_timerGUI + Tools_RandomLCG_Range(15, 180); } else { movingEyesTimer = g_timerGUI + Tools_RandomLCG_Range(6, 60); } } } if (g_interrogation && movingEyesSprite == 0) movingEyesSprite = 3; } } if (partNeedsRedraw) { uint8 *sprite; sprite = s_mentatSprites[0][movingEyesSprite]; GUI_Mouse_Hide_InRegion(s_eyesLeft, s_eyesTop, s_eyesLeft + Sprite_GetWidth(sprite), s_eyesTop + Sprite_GetHeight(sprite)); GUI_DrawSprite(SCREEN_0, sprite, s_eyesLeft, s_eyesTop, 0, 0); GUI_Mouse_Show_InRegion(); } }
/* Process input not caught by widgets, including keypad scrolling, * squad selection, and changing zoom levels. Also handles screen * shake logic. */ static void GameLoop_ProcessUnhandledInput(uint16 key) { const struct { Scancode code; int dx, dy; } keypad[8] = { {SCANCODE_KEYPAD_1, -1, 1}, {SCANCODE_KEYPAD_2, 0, 1}, {SCANCODE_KEYPAD_3, 1, 1}, {SCANCODE_KEYPAD_4, -1, 0}, {SCANCODE_KEYPAD_6, 1, 0}, {SCANCODE_KEYPAD_7, -1, -1}, {SCANCODE_KEYPAD_8, 0, -1}, {SCANCODE_KEYPAD_9, 1, -1} }; int dx = 0, dy = 0; for (unsigned int i = 0; i < lengthof(keypad); i++) { if ((key == keypad[i].code) || (key == 0 && Input_Test(keypad[i].code))) { dx += keypad[i].dx; dy += keypad[i].dy; } } if (dx != 0 || dy != 0) { dx = g_gameConfig.scrollSpeed * clamp(-1, dx, 1); dy = g_gameConfig.scrollSpeed * clamp(-1, dy, 1); } if ((fabsf(g_viewport_desiredDX) >= 4.0f) || (fabsf(g_viewport_desiredDY) >= 4.0f)) { dx += 0.25 * g_viewport_desiredDX; dy += 0.25 * g_viewport_desiredDY; if (fabsf(g_viewport_desiredDX) >= 4.0f) g_viewport_desiredDX *= 0.75; if (fabsf(g_viewport_desiredDY) >= 4.0f) g_viewport_desiredDY *= 0.75; } if (dx != 0 || dy != 0) { Map_MoveDirection(dx, dy); } switch (key) { case SCANCODE_1: case SCANCODE_2: case SCANCODE_3: case SCANCODE_4: case SCANCODE_5: case SCANCODE_6: case SCANCODE_7: case SCANCODE_8: case SCANCODE_9: case SCANCODE_0: Viewport_Hotkey((SquadID)(key - SCANCODE_1 + SQUADID_1)); break; case SCANCODE_H: Viewport_Homekey(); break; case SCANCODE_F5: Audio_DisplayMusicName(); break; case SCANCODE_F6: case SCANCODE_F7: { const bool increase = (key == SCANCODE_F7); const bool adjust_current_track_only = Input_Test(SCANCODE_LSHIFT); Audio_AdjustMusicVolume(increase ? 0.05f : -0.05f, adjust_current_track_only); Audio_DisplayMusicName(); } break; case SCANCODE_OPENBRACE: case SCANCODE_CLOSEBRACE: { ScreenDivID divID = (key == SCANCODE_OPENBRACE) ? SCREENDIV_MENUBAR : SCREENDIV_SIDEBAR; ScreenDiv* viewport = &g_screenDiv[SCREENDIV_VIEWPORT]; ScreenDiv* div = &g_screenDiv[divID]; const int oldh = viewport->height; div->scalex = (div->scalex >= 1.5f) ? 1.0f : 2.0f; div->scaley = div->scalex; A5_InitTransform(false); GameLoop_TweakWidgetDimensions(); g_factoryWindowTotal = -1; Map_MoveDirection(0, oldh - viewport->height); } return; case 0x80 | MOUSE_ZAXIS: if (g_mouseDZ == 0) break; if (g_gameConfig.holdControlToZoom) { if (!Input_Test(SCANCODE_LCTRL)) { Widget* w = GUI_Widget_Get_ByIndex(g_widgetLinkedListHead, 5); if ((w != NULL) && !w->flags.invisible) GUI_Widget_SpriteTextButton_Click(w); break; } } else { const WidgetProperties* w = &g_widgetProperties[WINDOWID_ACTIONPANEL_FRAME]; if (Mouse_InRegion_Div(SCREENDIV_SIDEBAR, w->xBase, w->yBase, w->xBase + w->width - 1, w->yBase + w->height - 1)) break; } /* Fall though. */ case SCANCODE_MINUS: case SCANCODE_EQUALS: case SCANCODE_KEYPAD_MINUS: case SCANCODE_KEYPAD_PLUS: { const float scaling_factor[] = {1.0f, 1.5f, 2.0f, 3.0f}; ScreenDiv* viewport = &g_screenDiv[SCREENDIV_VIEWPORT]; int curr; for (curr = 0; curr < (int)lengthof(scaling_factor); curr++) { if (viewport->scalex <= scaling_factor[curr]) break; } const int tilex = Tile_GetPackedX(g_viewportPosition); const int tiley = Tile_GetPackedY(g_viewportPosition); int viewport_cx = g_viewport_scrollOffsetX + viewport->width / 2; int viewport_cy = g_viewport_scrollOffsetY + viewport->height / 2; int new_scale; /* For mouse wheel zooming in, zoom towards the cursor. */ if ((key == (0x80 | MOUSE_ZAXIS)) && (g_mouseDZ > 0)) { const ScreenDiv* div = &g_screenDiv[SCREENDIV_VIEWPORT]; if (Mouse_InRegion_Div(SCREENDIV_VIEWPORT, 0, 0, div->width, div->height)) { int mousex, mousey; new_scale = curr + 1; Mouse_TransformToDiv(SCREENDIV_VIEWPORT, &mousex, &mousey); viewport_cx = (0.50 * viewport_cx) + (0.50 * mousex); viewport_cy = (0.50 * viewport_cy) + (0.50 * mousey); } else { new_scale = curr + 1; } } else { if (key == SCANCODE_EQUALS || key == SCANCODE_KEYPAD_PLUS) { new_scale = curr + 1; } else { new_scale = curr - 1; } } new_scale = clamp(0, new_scale, (int)lengthof(scaling_factor) - 1); viewport_cx += TILE_SIZE * tilex; viewport_cy += TILE_SIZE * tiley; if (new_scale != curr) { viewport->scalex = scaling_factor[new_scale]; viewport->scaley = scaling_factor[new_scale]; A5_InitTransform(false); GameLoop_TweakWidgetDimensions(); Map_CentreViewport(viewport_cx, viewport_cy); return; } } break; default: break; } /* If we did not init the transform, we may still need to do some * translation transforms for screen shakes. */ if (GFX_ScreenShake_Tick()) A5_InitTransform(false); }