static void CampaignIntroDraw(void *data) { // This will only draw once const CampaignSetting *c = data; GraphicsBlitBkg(&gGraphicsDevice); const int w = gGraphicsDevice.cachedConfig.Res.x; const int h = gGraphicsDevice.cachedConfig.Res.y; const int y = h / 4; // Display title + author char *buf; CMALLOC(buf, strlen(c->Title) + strlen(c->Author) + 16); sprintf(buf, "%s by %s", c->Title, c->Author); FontOpts opts = FontOptsNew(); opts.HAlign = ALIGN_CENTER; opts.Area = gGraphicsDevice.cachedConfig.Res; opts.Pad.y = y - 25; FontStrOpt(buf, Vec2iZero(), opts); CFREE(buf); // Display campaign description // allow some slack for newlines if (strlen(c->Description) > 0) { CMALLOC(buf, strlen(c->Description) * 2); // Pad about 1/6th of the screen width total (1/12th left and right) FontSplitLines(c->Description, buf, w * 5 / 6); FontStr(buf, Vec2iNew(w / 12, y)); CFREE(buf); } }
static void MissionBriefingDraw(void *data) { const MissionBriefingData *mData = data; GraphicsBlitBkg(&gGraphicsDevice); // Mission title FontStrOpt(mData->Title, Vec2iZero(), mData->TitleOpts); // Display password FontStrOpt(mData->Password, Vec2iZero(), mData->PasswordOpts); // Display description with typewriter effect FontStr(mData->TypewriterBuf, mData->DescriptionPos); // Display objectives for (int i = 0; i < (int)mData->MissionOptions->missionData->Objectives.size; i++) { const MissionObjective *o = CArrayGet(&mData->MissionOptions->missionData->Objectives, i); // Do not brief optional objectives if (o->Required == 0) { continue; } const Vec2i yInc = Vec2iNew(0, i * mData->ObjectiveHeight); FontStr(o->Description, Vec2iAdd(mData->ObjectiveDescPos, yInc)); DrawObjectiveInfo( mData->MissionOptions, i, Vec2iAdd(mData->ObjectiveInfoPos, yInc)); } }
void MenuLoop(MenuSystem *menu) { assert(menu->numExitTypes > 0); for (;; SDL_Delay(10)) { // Input InputPoll(menu->joysticks, menu->keyboard); // Update if (menu->current->type == MENU_TYPE_KEYS && menu->current->u.normal.changeKeyMenu != NULL) { MenuProcessChangeKey(menu->current); } else { int cmd = GetMenuCmd(); menu->current = MenuProcessCmd(menu->current, cmd); } if (MenuHasExitType(menu, menu->current->type)) { break; } // Draw if (menu->graphics != NULL) { GraphicsBlitBkg(menu->graphics); } ShowControls(); MenuDisplay(menu); CopyToScreen(); } }
static void MenuDraw(void *data) { const MenuSystem *ms = data; GraphicsBlitBkg(ms->graphics); ShowControls(); MenuDisplay(ms); }
void MenuLoop(MenuSystem *menu) { assert(menu->numExitTypes > 0); for (;; SDL_Delay(10)) { MusicSetPlaying(&gSoundDevice, SDL_GetAppState() & SDL_APPINPUTFOCUS); // Input InputPoll(menu->inputDevices, SDL_GetTicks()); // Update if (menu->current->type == MENU_TYPE_KEYS && menu->current->u.normal.changeKeyMenu != NULL) { MenuProcessChangeKey(menu->current); } else { int cmd = GetMenuCmd(gPlayerDatas); MenuProcessCmd(menu, cmd); } if (MenuIsExit(menu)) { break; } // Draw GraphicsBlitBkg(menu->graphics); ShowControls(); MenuDisplay(menu); BlitFlip(menu->graphics, &gConfig.Graphics); } }
int NumPlayersSelection( int *numPlayers, campaign_mode_e mode, GraphicsDevice *graphics, InputDevices *input) { MenuSystem ms; int i; int res = 0; MenuSystemInit( &ms, input, graphics, Vec2iZero(), Vec2iNew( graphics->cachedConfig.ResolutionWidth, graphics->cachedConfig.ResolutionHeight)); ms.root = ms.current = MenuCreateNormal( "", "Select number of players", MENU_TYPE_NORMAL, 0); for (i = 0; i < MAX_PLAYERS; i++) { if (mode == CAMPAIGN_MODE_DOGFIGHT && i == 0) { // At least two players for dogfights continue; } char buf[2]; sprintf(buf, "%d", i + 1); MenuAddSubmenu(ms.current, MenuCreateReturn(buf, i + 1)); } MenuAddExitType(&ms, MENU_TYPE_RETURN); for (;;) { int cmd; InputPoll(&gInputDevices, SDL_GetTicks()); if (KeyIsPressed(&gInputDevices.keyboard, SDLK_ESCAPE)) { res = 0; break; // hack to allow exit } cmd = GetMenuCmd(gPlayerDatas); MenuProcessCmd(&ms, cmd); if (MenuIsExit(&ms)) { *numPlayers = ms.current->u.returnCode; res = 1; break; } GraphicsBlitBkg(graphics); MenuDisplay(&ms); BlitFlip(graphics, &gConfig.Graphics); SDL_Delay(10); } MenuSystemTerminate(&ms); return res; }
static void DogfightFinalScoresDraw(void *data) { UNUSED(data); // This will only draw once const int w = gGraphicsDevice.cachedConfig.Res.x; const int h = gGraphicsDevice.cachedConfig.Res.y; GraphicsBlitBkg(&gGraphicsDevice); // Work out who's the winner, or if it's a tie int maxScore = 0; int playersWithMaxScore = 0; for (int i = 0; i < (int)gPlayerDatas.size; i++) { const PlayerData *p = CArrayGet(&gPlayerDatas, i); if (p->RoundsWon > maxScore) { maxScore = p->RoundsWon; playersWithMaxScore = 1; } else if (p->RoundsWon == maxScore) { playersWithMaxScore++; } } const bool isTie = playersWithMaxScore == (int)gPlayerDatas.size; // Draw players and their names spread evenly around the screen. // If it's a tie, display the message in the centre, // otherwise display the winner just below the winning player #define DRAW_TEXT "It's a draw!" #define WINNER_TEXT "Winner!" CASSERT( gPlayerDatas.size >= 2 && gPlayerDatas.size <= 4, "Unimplemented number of players for dogfight"); for (int i = 0; i < (int)gPlayerDatas.size; i++) { const Vec2i pos = Vec2iNew( w / 4 + (i & 1) * w / 2, gPlayerDatas.size == 2 ? h / 2 : h / 4 + (i / 2) * h / 2); const PlayerData *p = CArrayGet(&gPlayerDatas, i); DisplayCharacterAndName(pos, &p->Char, p->name); ShowPlayerScore(pos, p->RoundsWon); if (!isTie && maxScore == p->RoundsWon) { FontStrMask( WINNER_TEXT, Vec2iNew(pos.x - FontStrW(WINNER_TEXT) / 2, pos.y + 30), colorGreen); } } if (isTie) { FontStrCenter(DRAW_TEXT); } }
static void PlayerEquipDraw(void *data) { const PlayerEquipData *pData = data; GraphicsBlitBkg(&gGraphicsDevice); for (int i = 0; i < GetNumPlayers(false, false, true); i++) { MenuDisplay(&pData->menus[i].ms); } }
static void DeathmatchFinalScoresDraw(void *data) { UNUSED(data); // This will only draw once const int w = gGraphicsDevice.cachedConfig.Res.x; const int h = gGraphicsDevice.cachedConfig.Res.y; GraphicsBlitBkg(&gGraphicsDevice); // Work out the highest kills int maxKills = 0; for (int i = 0; i < (int)gPlayerDatas.size; i++) { const PlayerData *p = CArrayGet(&gPlayerDatas, i); if (p->kills > maxKills) { maxKills = p->kills; } } // Draw players and their names spread evenly around the screen. CASSERT( gPlayerDatas.size >= 2 && gPlayerDatas.size <= 4, "Unimplemented number of players for deathmatch"); #define LAST_MAN_TEXT "Last man standing!" for (int i = 0; i < (int)gPlayerDatas.size; i++) { const Vec2i pos = Vec2iNew( w / 4 + (i & 1) * w / 2, gPlayerDatas.size == 2 ? h / 2 : h / 4 + (i / 2) * h / 2); const PlayerData *p = CArrayGet(&gPlayerDatas, i); DisplayCharacterAndName(pos, &p->Char, p->name); // Kills char s[16]; sprintf(s, "Kills: %d", p->kills); FontStrMask( s, Vec2iNew(pos.x - FontStrW(s) / 2, pos.y + 20), p->kills == maxKills ? colorGreen : colorWhite); // Last man standing? if (p->Lives > 0) { FontStrMask( LAST_MAN_TEXT, Vec2iNew(pos.x - FontStrW(LAST_MAN_TEXT) / 2, pos.y + 30), colorGreen); } } }
static void PlayerSelectionDraw(void *data) { const PlayerSelectionData *pData = data; GraphicsBlitBkg(&gGraphicsDevice); const int w = gGraphicsDevice.cachedConfig.Res.x; const int h = gGraphicsDevice.cachedConfig.Res.y; int idx = 0; for (int i = 0; i < (int)gPlayerDatas.size; i++, idx++) { const PlayerData *p = CArrayGet(&gPlayerDatas, i); if (!p->IsLocal) { idx--; continue; } if (p->inputDevice != INPUT_DEVICE_UNSET) { MenuDisplay(&pData->menus[idx].ms); } else { Vec2i center = Vec2iZero(); const char *prompt = "Press Fire to join..."; const Vec2i offset = Vec2iScaleDiv(FontStrSize(prompt), -2); switch (GetNumPlayers(false, false, true)) { case 1: // Center of screen center = Vec2iNew(w / 2, h / 2); break; case 2: // Side by side center = Vec2iNew(idx * w / 2 + w / 4, h / 2); break; case 3: case 4: // Four corners center = Vec2iNew( (idx & 1) * w / 2 + w / 4, (idx / 2) * h / 2 + h / 4); break; default: CASSERT(false, "not implemented"); break; } FontStr(prompt, Vec2iAdd(center, offset)); } } }
static void DogfightScoresDraw(void *data) { UNUSED(data); // This will only draw once const int w = gGraphicsDevice.cachedConfig.Res.x; const int h = gGraphicsDevice.cachedConfig.Res.y; GraphicsBlitBkg(&gGraphicsDevice); CASSERT( gPlayerDatas.size >= 2 && gPlayerDatas.size <= 4, "Unimplemented number of players for dogfight"); for (int i = 0; i < (int)gPlayerDatas.size; i++) { const Vec2i pos = Vec2iNew( w / 4 + (i & 1) * w / 2, gPlayerDatas.size == 2 ? h / 2 : h / 4 + (i / 2) * h / 2); const PlayerData *p = CArrayGet(&gPlayerDatas, i); DisplayCharacterAndName(pos, &p->Char, p->name); ShowPlayerScore(pos, p->RoundsWon); } }
static void VictoryDraw(void *data) { // This will only draw once const CampaignOptions *c = data; GraphicsBlitBkg(&gGraphicsDevice); const int w = gGraphicsDevice.cachedConfig.Res.x; const int h = gGraphicsDevice.cachedConfig.Res.y; FontOpts opts = FontOptsNew(); opts.HAlign = ALIGN_CENTER; opts.Area = gGraphicsDevice.cachedConfig.Res; int y = 100; // Congratulations text #define CONGRATULATIONS "Congratulations, you have completed " FontStrOpt(CONGRATULATIONS, Vec2iNew(0, y), opts); y += 15; opts.Mask = colorRed; FontStrOpt(c->Setting.Title, Vec2iNew(0, y), opts); // Display players switch (gPlayerDatas.size) { case 1: { const PlayerData *p = CArrayGet(&gPlayerDatas, 0); DisplayCharacterAndName(Vec2iNew(w / 4, h / 4), &p->Char, p->name); } break; case 2: { // side by side const PlayerData *p1 = CArrayGet(&gPlayerDatas, 0); DisplayCharacterAndName( Vec2iNew(w / 8, h / 4), &p1->Char, p1->name); const PlayerData *p2 = CArrayGet(&gPlayerDatas, 1); DisplayCharacterAndName( Vec2iNew(w / 8 + w / 2, h / 4), &p2->Char, p2->name); } break; case 3: // fallthrough case 4: { // 2x2 const PlayerData *p1 = CArrayGet(&gPlayerDatas, 0); DisplayCharacterAndName( Vec2iNew(w / 8, h / 8), &p1->Char, p1->name); const PlayerData *p2 = CArrayGet(&gPlayerDatas, 1); DisplayCharacterAndName( Vec2iNew(w / 8 + w / 2, h / 8), &p2->Char, p2->name); const PlayerData *p3 = CArrayGet(&gPlayerDatas, 2); DisplayCharacterAndName( Vec2iNew(w / 8, h / 8 + h / 4), &p3->Char, p3->name); if (gPlayerDatas.size == 4) { const PlayerData *p4 = CArrayGet(&gPlayerDatas, 3); DisplayCharacterAndName( Vec2iNew(w / 8 + w / 2, h / 8 + h / 4), &p4->Char, p4->name); } } break; default: CASSERT(false, "not implemented"); break; } // Final words const char *finalWordsSingle[] = { "Ha, next time I'll use my good hand", "Over already? I was just warming up...", "There's just no good opposition to be found these days!", "Well, maybe I'll just do my monthly reload then", "Woof woof", "I'll just bury the bones in the back yard, he-he", "I just wish they'd let me try bare-handed", "Rambo? Who's Rambo?", "<in Austrian accent:> I'll be back", "Gee, my trigger finger is sore", "I need more practice. I think I missed a few shots at times" }; const char *finalWordsMulti[] = { "United we stand, divided we conquer", "Nothing like good teamwork, is there?", "Which way is the camera?", "We eat bullets for breakfast and have grenades as dessert", "We're so cool we have to wear mittens", }; const char *finalWords; if (gPlayerDatas.size == 1) { const int numWords = sizeof finalWordsSingle / sizeof(char *); finalWords = finalWordsSingle[rand() % numWords]; } else { const int numWords = sizeof finalWordsMulti / sizeof(char *); finalWords = finalWordsMulti[rand() % numWords]; } Vec2i pos = Vec2iNew((w - FontStrW(finalWords)) / 2, h / 2 + 20); pos = FontChMask('"', pos, colorDarker); pos = FontStrMask(finalWords, pos, colorPurple); FontChMask('"', pos, colorDarker); }
static void MissionSummaryDraw(void *data) { // This will only draw once const struct MissionOptions *m = data; GraphicsBlitBkg(&gGraphicsDevice); const int w = gGraphicsDevice.cachedConfig.Res.x; const int h = gGraphicsDevice.cachedConfig.Res.y; // Display password if (strlen(gAutosave.LastMission.Password) > 0) { char s[64]; sprintf(s, "Last password: %s", gAutosave.LastMission.Password); FontOpts opts = FontOptsNew(); opts.HAlign = ALIGN_CENTER; opts.VAlign = ALIGN_END; opts.Area = gGraphicsDevice.cachedConfig.Res; opts.Pad.y = opts.Area.y / 12; FontStrOpt(s, Vec2iZero(), opts); } // Display objectives and bonuses Vec2i pos = Vec2iNew(w / 6, h / 2 + h / 10); int idx = 1; for (int i = 0; i < (int)m->missionData->Objectives.size; i++) { const struct Objective *o = CArrayGet(&m->Objectives, i); const MissionObjective *mo = CArrayGet(&m->missionData->Objectives, i); // Do not mention optional objectives with none completed if (o->done == 0 && mo->Required == 0) { continue; } // Objective icon DrawObjectiveInfo(m, i, Vec2iAdd(pos, Vec2iNew(-26, FontH()))); // Objective completion text char s[100]; sprintf(s, "Objective %d: %d of %d, %d required", idx, o->done, mo->Count, mo->Required); FontOpts opts = FontOptsNew(); opts.Area = gGraphicsDevice.cachedConfig.Res; opts.Pad = pos; if (mo->Required == 0) { // Show optional objectives in purple opts.Mask = colorPurple; } FontStrOpt(s, Vec2iZero(), opts); // Objective status text opts = FontOptsNew(); opts.HAlign = ALIGN_END; opts.Area = gGraphicsDevice.cachedConfig.Res; opts.Pad = pos; if (o->done < mo->Required) { opts.Mask = colorRed; FontStrOpt("Failed", Vec2iZero(), opts); } else if ( o->done == mo->Count && o->done > mo->Required && AreAnySurvived()) { opts.Mask = colorGreen; char buf[16]; sprintf(buf, "Perfect: %d", PERFECT_BONUS); FontStrOpt(buf, Vec2iZero(), opts); } else if (mo->Required > 0) { FontStrOpt("Done", Vec2iZero(), opts); } else { FontStrOpt("Bonus!", Vec2iZero(), opts); } pos.y += 15; idx++; } // Draw other bonuses if (AreAnySurvived()) { char s[64]; sprintf(s, "Access bonus: %d", GetAccessBonus(m)); FontStr(s, pos); pos.y += FontH() + 1; int seconds; const int timeBonus = GetTimeBonus(m, &seconds); sprintf(s, "Time bonus: %d secs x 25 = %d", seconds, timeBonus); FontStr(s, pos); } // Draw per-player summaries Vec2i size; switch (gPlayerDatas.size) { case 1: size = Vec2iNew(w, h / 2); DrawPlayerSummary(Vec2iZero(), size, CArrayGet(&gPlayerDatas, 0)); break; case 2: // side by side size = Vec2iNew(w / 2, h / 2); DrawPlayerSummary(Vec2iZero(), size, CArrayGet(&gPlayerDatas, 0)); DrawPlayerSummary( Vec2iNew(w / 2, 0), size, CArrayGet(&gPlayerDatas, 1)); break; case 3: // fallthrough case 4: // 2x2 size = Vec2iNew(w / 2, h / 4); DrawPlayerSummary(Vec2iZero(), size, CArrayGet(&gPlayerDatas, 0)); DrawPlayerSummary( Vec2iNew(w / 2, 0), size, CArrayGet(&gPlayerDatas, 1)); DrawPlayerSummary( Vec2iNew(0, h / 4), size, CArrayGet(&gPlayerDatas, 2)); if (gPlayerDatas.size == 4) { DrawPlayerSummary( Vec2iNew(w / 2, h / 4), size, CArrayGet(&gPlayerDatas, 3)); } break; default: CASSERT(false, "not implemented"); break; } }
int PlayerEquip(int numPlayers, GraphicsDevice *graphics) { int i; WeaponMenu menus[MAX_PLAYERS]; for (i = 0; i < numPlayers; i++) { WeaponMenuCreate( &menus[i], numPlayers, i, &gCampaign.Setting.characters.players[i], &gPlayerDatas[i], &gInputDevices, graphics, &gConfig.Input); } debug(D_NORMAL, "\n"); for (;;) { int cmds[MAX_PLAYERS]; int isDone = 1; InputPoll(&gInputDevices, SDL_GetTicks()); if (KeyIsPressed(&gInputDevices.keyboard, SDLK_ESCAPE)) { return 0; // hack to exit from menu } GetPlayerCmds(&cmds, gPlayerDatas); for (i = 0; i < numPlayers; i++) { if (!MenuIsExit(&menus[i].ms)) { MenuProcessCmd(&menus[i].ms, cmds[i]); } else if (gPlayerDatas[i].weaponCount == 0) { // Check exit condition; must have selected at least one weapon // Otherwise reset the current menu menus[i].ms.current = menus[i].ms.root; } } for (i = 0; i < numPlayers; i++) { if (!MenuIsExit(&menus[i].ms)) { isDone = 0; } } if (isDone) { break; } GraphicsBlitBkg(graphics); for (i = 0; i < numPlayers; i++) { MenuDisplay(&menus[i].ms); } BlitFlip(graphics, &gConfig.Graphics); SDL_Delay(10); } for (i = 0; i < numPlayers; i++) { MenuSystemTerminate(&menus[i].ms); } return 1; }
int PlayerSelection(int numPlayers, GraphicsDevice *graphics) { int i; int hasInputDevice[MAX_PLAYERS]; PlayerSelectMenu menus[MAX_PLAYERS]; for (i = 0; i < numPlayers; i++) { PlayerSelectMenusCreate( &menus[i], numPlayers, i, &gCampaign.Setting.characters.players[i], &gPlayerDatas[i], &gInputDevices, graphics, &gConfig.Input); hasInputDevice[i] = 0; } KeyInit(&gInputDevices.keyboard); for (;;) { int cmds[MAX_PLAYERS]; int isDone = 1; InputPoll(&gInputDevices, SDL_GetTicks()); if (KeyIsPressed(&gInputDevices.keyboard, SDLK_ESCAPE)) { // TODO: destroy menus return 0; // hack to allow exit } GetPlayerCmds(&cmds, gPlayerDatas); for (i = 0; i < numPlayers; i++) { if (hasInputDevice[i] && !MenuIsExit(&menus[i].ms)) { MenuProcessCmd(&menus[i].ms, cmds[i]); } } for (i = 0; i < numPlayers; i++) { if (!MenuIsExit(&menus[i].ms)) { isDone = 0; } } if (isDone) { break; } AssignPlayerInputDevices( hasInputDevice, numPlayers, gPlayerDatas, &gInputDevices, &gConfig.Input); GraphicsBlitBkg(graphics); for (i = 0; i < numPlayers; i++) { if (hasInputDevice[i]) { MenuDisplay(&menus[i].ms); } else { Vec2i center; const char *prompt = "Press Fire to join..."; Vec2i offset = Vec2iScaleDiv(TextGetSize(prompt), -2); int w = graphics->cachedConfig.ResolutionWidth; int h = graphics->cachedConfig.ResolutionHeight; switch (numPlayers) { case 1: // Center of screen center = Vec2iNew(w / 2, h / 2); break; case 2: // Side by side center = Vec2iNew(i * w / 2 + w / 4, h / 2); break; case 3: case 4: // Four corners center = Vec2iNew( (i & 1) * w / 2 + w / 4, (i / 2) * h / 2 + h / 4); break; default: assert(0 && "not implemented"); break; } DrawTextString(prompt, graphics, Vec2iAdd(center, offset)); } } BlitFlip(graphics, &gConfig.Graphics); SDL_Delay(10); } for (i = 0; i < numPlayers; i++) { MenuSystemTerminate(&menus[i].ms); } return 1; }
static void Display(GraphicsDevice *g, int yc, HandleInputResult result) { char s[128]; int y = 5; int i; int w = g->cachedConfig.Res.x; int h = g->cachedConfig.Res.y; Mission *mission = CampaignGetCurrentMission(&gCampaign); if (mission) { // Re-make the background if the resolution has changed if (gEventHandlers.HasResolutionChanged) { MakeBackground(g, 0); } if (result.RemakeBg || brush.IsGuideImageNew) { // Clear background first for (i = 0; i < GraphicsGetScreenSize(&g->cachedConfig); i++) { g->buf[i] = PixelFromColor(g, colorBlack); } brush.IsGuideImageNew = false; GrafxDrawExtra extra; extra.guideImage = brush.GuideImageSurface; extra.guideImageAlpha = brush.GuideImageAlpha; GrafxDrawBackground(g, &sDrawBuffer, tintNone, camera, &extra); } GraphicsBlitBkg(g); // Draw brush highlight tiles if (brush.IsActive && IsBrushPosValid(brush.Pos, mission)) { EditorBrushSetHighlightedTiles(&brush); } for (i = 0; i < (int)brush.HighlightedTiles.size; i++) { Vec2i *pos = CArrayGet(&brush.HighlightedTiles, i); Vec2i screenPos = GetScreenPos(*pos); if (screenPos.x >= 0 && screenPos.x < w && screenPos.y >= 0 && screenPos.y < h) { DrawRectangle( g, screenPos, Vec2iNew(TILE_WIDTH, TILE_HEIGHT), colorWhite, DRAW_FLAG_LINE); } } sprintf( s, "Mission %d/%d", gCampaign.MissionIndex + 1, (int)gCampaign.Setting.Missions.size); TextStringMasked(&gTextManager, s, g, Vec2iNew(270, y), yc == YC_MISSIONINDEX ? colorRed : colorWhite); if (brush.LastPos.x) { sprintf(s, "(%d, %d)", brush.Pos.x, brush.Pos.y); TextString(&gTextManager, s, g, Vec2iNew(w - 40, h - 16)); } } else { ClearScreen(g); if (gCampaign.Setting.Missions.size) { sprintf(s, "End/%d", (int)gCampaign.Setting.Missions.size); TextStringMasked(&gTextManager, s, g, Vec2iNew(270, y), yc == YC_MISSIONINDEX ? colorRed : colorWhite); } } if (fileChanged) { DrawTPic(10, y, PicManagerGetOldPic(&gPicManager, 221)); } TextString(&gTextManager, "Press F1 for help", g, Vec2iNew(20, h - 20 - CDogsTextHeight())); y = 150; UIObjectDraw( sObjs, g, Vec2iZero(), gEventHandlers.mouse.currentPos, &sDrawObjs); if (result.WillDisplayAutomap && mission) { AutomapDraw(AUTOMAP_FLAGS_SHOWALL, true); } else { if (sTooltipObj && sTooltipObj->Tooltip) { UITooltipDraw( g, gEventHandlers.mouse.currentPos, sTooltipObj->Tooltip); } MouseDraw(&gEventHandlers.mouse); } BlitFlip(g, &gConfig.Graphics); }