bool ScreenMissionBriefing(const struct MissionOptions *m) { const int w = gGraphicsDevice.cachedConfig.Res.x; const int h = gGraphicsDevice.cachedConfig.Res.y; const int y = h / 4; MissionBriefingData mData; memset(&mData, 0, sizeof mData); mData.IsOK = true; // Title CMALLOC(mData.Title, strlen(m->missionData->Title) + 32); sprintf(mData.Title, "Mission %d: %s", m->index + 1, m->missionData->Title); mData.TitleOpts = FontOptsNew(); mData.TitleOpts.HAlign = ALIGN_CENTER; mData.TitleOpts.Area = gGraphicsDevice.cachedConfig.Res; mData.TitleOpts.Pad.y = y - 25; // Password if (m->index > 0) { sprintf( mData.Password, "Password: %s", gAutosave.LastMission.Password); mData.PasswordOpts = FontOptsNew(); mData.PasswordOpts.HAlign = ALIGN_CENTER; mData.PasswordOpts.Area = gGraphicsDevice.cachedConfig.Res; mData.PasswordOpts.Pad.y = y - 15; } // Split the description, and prepare it for typewriter effect mData.TypewriterCount = 0; // allow some slack for newlines CMALLOC(mData.Description, strlen(m->missionData->Description) * 2 + 1); CCALLOC(mData.TypewriterBuf, strlen(m->missionData->Description) * 2 + 1); // Pad about 1/6th of the screen width total (1/12th left and right) FontSplitLines(m->missionData->Description, mData.Description, w * 5 / 6); mData.DescriptionPos = Vec2iNew(w / 12, y); // Objectives mData.ObjectiveDescPos = Vec2iNew(w / 6, y + FontStrH(mData.Description) + h / 10); mData.ObjectiveInfoPos = Vec2iNew(w - (w / 6), mData.ObjectiveDescPos.y + FontH()); mData.ObjectiveHeight = h / 12; mData.MissionOptions = m; GameLoopData gData = GameLoopDataNew( &mData, MissionBriefingUpdate, &mData, MissionBriefingDraw); GameLoop(&gData); if (mData.IsOK) { SoundPlay(&gSoundDevice, StrSound("mg")); } CFREE(mData.Title); CFREE(mData.Description); CFREE(mData.TypewriterBuf); return mData.IsOK; }
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); } }
void WeaponMenuCreate( WeaponMenu *menu, int numPlayers, int player, const int playerUID, EventHandlers *handlers, GraphicsDevice *graphics) { MenuSystem *ms = &menu->ms; WeaponMenuData *data = &menu->data; Vec2i pos, size; int w = graphics->cachedConfig.Res.x; int h = graphics->cachedConfig.Res.y; data->display.PlayerUID = playerUID; data->display.currentMenu = &ms->current; data->display.Dir = DIRECTION_DOWN; data->PlayerUID = playerUID; switch (numPlayers) { case 1: // Single menu, entire screen pos = Vec2iNew(w / 2, 0); size = Vec2iNew(w / 2, h); break; case 2: // Two menus, side by side pos = Vec2iNew(player * w / 2 + w / 4, 0); size = Vec2iNew(w / 4, h); break; case 3: case 4: // Four corners pos = Vec2iNew((player & 1) * w / 2 + w / 4, (player / 2) * h / 2); size = Vec2iNew(w / 4, h / 2); break; default: CASSERT(false, "not implemented"); pos = Vec2iNew(w / 2, 0); size = Vec2iNew(w / 2, h); break; } MenuSystemInit(ms, handlers, graphics, pos, size); ms->align = MENU_ALIGN_LEFT; ms->root = ms->current = MenuCreateNormal( "", "", MENU_TYPE_NORMAL, 0); ms->root->u.normal.maxItems = 11; const CArray *weapons = &gMission.Weapons; for (int i = 0; i < (int)weapons->size; i++) { const GunDescription **g = CArrayGet(weapons, i); menu_t *gunMenu; if ((*g)->Description != NULL) { // Gun description menu gunMenu = MenuCreateNormal((*g)->name, "", MENU_TYPE_NORMAL, 0); char *buf; CMALLOC(buf, strlen((*g)->Description) * 2); FontSplitLines((*g)->Description, buf, size.x * 5 / 6); MenuAddSubmenu(gunMenu, MenuCreateBack(buf)); CFREE(buf); gunMenu->u.normal.isSubmenusAlt = true; MenuSetCustomDisplay(gunMenu, DisplayDescriptionGunIcon, *g); } else { gunMenu = MenuCreate((*g)->name, MENU_TYPE_BASIC); } MenuAddSubmenu(ms->root, gunMenu); } MenuSetPostInputFunc(ms->root, WeaponSelect, &data->display); // Disable menu items where the player already has the weapon PlayerData *pData = PlayerDataGetByUID(playerUID); for (int i = 0; i < pData->weaponCount; i++) { for (int j = 0; j < (int)weapons->size; j++) { const GunDescription **g = CArrayGet(weapons, j); if (pData->weapons[i] == *g) { MenuDisableSubmenu(ms->root, j); } } } MenuAddSubmenu(ms->root, MenuCreateSeparator("")); MenuAddSubmenu( ms->root, MenuCreateNormal("(End)", "", MENU_TYPE_NORMAL, 0)); // Select "(End)" ms->root->u.normal.index = (int)ms->root->u.normal.subMenus.size - 1; // Disable "Done" if no weapons selected if (pData->weaponCount == 0) { MenuDisableSubmenu(ms->root, (int)ms->root->u.normal.subMenus.size - 1); } MenuSetCustomDisplay(ms->root, DisplayGunIcon, NULL); MenuSystemAddCustomDisplay(ms, MenuDisplayPlayer, &data->display); MenuSystemAddCustomDisplay(ms, DisplayEquippedWeapons, data); MenuSystemAddCustomDisplay( ms, MenuDisplayPlayerControls, &data->PlayerUID); }