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)); } }
static void MissionBriefingDraw(void *data) { const MissionBriefingData *mData = data; GraphicsClear(&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 CA_FOREACH( const Objective, o, mData->MissionOptions->missionData->Objectives) // Do not brief optional objectives if (o->Required == 0) { continue; } Vec2i offset = Vec2iNew(0, _ca_index * mData->ObjectiveHeight); FontStr(o->Description, Vec2iAdd(mData->ObjectiveDescPos, offset)); // Draw the icons slightly offset so that tall icons don't overlap each // other offset.x = -16 * (_ca_index & 1); DrawObjectiveInfo(o, Vec2iAdd(mData->ObjectiveInfoPos, offset)); CA_FOREACH_END() }
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; } }
static void MissionSummaryDraw( const menu_t *menu, GraphicsDevice *g, const Vec2i p, const Vec2i size, const void *data) { UNUSED(menu); UNUSED(p); UNUSED(size); const struct MissionOptions *m = data; 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 = g->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; CA_FOREACH(const Objective, o, m->missionData->Objectives) // Do not mention optional objectives with none completed if (o->done == 0 && !ObjectiveIsRequired(o)) { continue; } // Objective icon DrawObjectiveInfo(o, Vec2iAdd(pos, Vec2iNew(-26, FontH()))); // Objective completion text char s[100]; sprintf(s, "Objective %d: %d of %d, %d required", idx, o->done, o->Count, o->Required); FontOpts opts = FontOptsNew(); opts.Area = gGraphicsDevice.cachedConfig.Res; opts.Pad = pos; if (!ObjectiveIsRequired(o)) { // 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 (!ObjectiveIsComplete(o)) { opts.Mask = colorRed; FontStrOpt("Failed", Vec2iZero(), opts); } else if (ObjectiveIsPerfect(o) && AreAnySurvived()) { opts.Mask = colorGreen; char buf[16]; sprintf(buf, "Perfect: %d", PERFECT_BONUS); FontStrOpt(buf, Vec2iZero(), opts); } else if (ObjectiveIsRequired(o)) { FontStrOpt("Done", Vec2iZero(), opts); } else { FontStrOpt("Bonus!", Vec2iZero(), opts); } pos.y += 15; idx++; CA_FOREACH_END() // 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 PlayerData *pds[MAX_LOCAL_PLAYERS]; idx = 0; CA_FOREACH(PlayerData, pd, gPlayerDatas) if (!pd->IsLocal) { continue; } pds[idx] = pd; idx++; CA_FOREACH_END() Vec2i playerSize; switch (idx) { case 1: playerSize = Vec2iNew(w, h / 2); DrawPlayerSummary(Vec2iZero(), playerSize, pds[0]); break; case 2: // side by side playerSize = Vec2iNew(w / 2, h / 2); DrawPlayerSummary(Vec2iZero(), playerSize, pds[0]); DrawPlayerSummary(Vec2iNew(w / 2, 0), playerSize, pds[1]); break; case 3: // fallthrough case 4: // 2x2 playerSize = Vec2iNew(w / 2, h / 4); DrawPlayerSummary(Vec2iZero(), playerSize, pds[0]); DrawPlayerSummary(Vec2iNew(w / 2, 0), playerSize, pds[1]); DrawPlayerSummary(Vec2iNew(0, h / 4), playerSize, pds[2]); if (idx == 4) { DrawPlayerSummary(Vec2iNew(w / 2, h / 4), playerSize, pds[3]); } break; default: CASSERT(false, "not implemented"); break; } }
void Display(int index, int xc, int yc, int key) { char s[128]; int y = 5; int i; SetSecondaryMouseRects(NULL); memset(GetDstScreen(), 58, 64000); sprintf(s, "Key: 0x%x", key); TextStringAt(270, 190, s); DisplayText(25, y, campaign.title, yc == YC_CAMPAIGNTITLE && xc == XC_CAMPAIGNTITLE, 1); if (fileChanged) DrawTPic(10, y, gPics[221], NULL); if (currentMission) { sprintf(s, "Mission %d/%d", index + 1, campaign.missionCount); DisplayText(270, y, s, yc == YC_MISSIONINDEX, 0); y += TextHeight() + 3; DisplayText(25, y, currentMission->title, yc == YC_MISSIONTITLE && xc == XC_MISSIONTITLE, 1); y += TextHeight() + 2; sprintf(s, "Width: %d", currentMission->mapWidth); DisplayText(20, y, s, yc == YC_MISSIONPROPS && xc == XC_WIDTH, 0); sprintf(s, "Height: %d", currentMission->mapHeight); DisplayText(60, y, s, yc == YC_MISSIONPROPS && xc == XC_HEIGHT, 0); sprintf(s, "Walls: %d", currentMission->wallCount); DisplayText(100, y, s, yc == YC_MISSIONPROPS && xc == XC_WALLCOUNT, 0); sprintf(s, "Len: %d", currentMission->wallLength); DisplayText(140, y, s, yc == YC_MISSIONPROPS && xc == XC_WALLLENGTH, 0); sprintf(s, "Rooms: %d", currentMission->roomCount); DisplayText(180, y, s, yc == YC_MISSIONPROPS && xc == XC_ROOMCOUNT, 0); sprintf(s, "Sqr: %d", currentMission->squareCount); DisplayText(220, y, s, yc == YC_MISSIONPROPS && xc == XC_SQRCOUNT, 0); sprintf(s, "Dens: %d", currentMission->baddieDensity); DisplayText(260, y, s, yc == YC_MISSIONPROPS && xc == XC_DENSITY, 0); y += TextHeight(); DisplayText(20, y, "Wall", yc == YC_MISSIONLOOKS && xc == XC_WALL, 0); DisplayText(50, y, "Floor", yc == YC_MISSIONLOOKS && xc == XC_FLOOR, 0); DisplayText(80, y, "Rooms", yc == YC_MISSIONLOOKS && xc == XC_ROOM, 0); DisplayText(110, y, "Doors", yc == YC_MISSIONLOOKS && xc == XC_DOORS, 0); DisplayText(140, y, "Keys", yc == YC_MISSIONLOOKS && xc == XC_KEYS, 0); DisplayText(170, y, "Exit", yc == YC_MISSIONLOOKS && xc == XC_EXIT, 0); sprintf(s, "Walls: %s", RangeName(currentMission->wallRange)); DisplayText(200, y, s, yc == YC_MISSIONLOOKS && xc == XC_COLOR1, 0); sprintf(s, "Floor: %s", RangeName(currentMission->floorRange)); DisplayText(200, y + TH, s, yc == YC_MISSIONLOOKS && xc == XC_COLOR2, 0); sprintf(s, "Rooms: %s", RangeName(currentMission->roomRange)); DisplayText(200, y + 2 * TH, s, yc == YC_MISSIONLOOKS && xc == XC_COLOR3, 0); sprintf(s, "Extra: %s", RangeName(currentMission->altRange)); DisplayText(200, y + 3 * TH, s, yc == YC_MISSIONLOOKS && xc == XC_COLOR4, 0); DrawPic(20, y + TH, gPics[cWallPics [currentMission->wallStyle % WALL_COUNT][WALL_SINGLE]], NULL); DrawPic(50, y + TH, gPics[cFloorPics [currentMission->floorStyle % FLOOR_COUNT][FLOOR_NORMAL]], NULL); DrawPic(80, y + TH, gPics[cRoomPics [currentMission->roomStyle % ROOMFLOOR_COUNT][ROOMFLOOR_NORMAL]], NULL); DrawPic(110, y + TH, gPics[cGeneralPics[gMission.doorPics[0].horzPic]. picIndex], NULL); DrawTPic(140, y + TH, gPics[cGeneralPics[gMission.keyPics[0]].picIndex], NULL); DrawPic(170, y + TH, gPics[gMission.exitPic], NULL); y += TH + 25; DisplayText(20, y, "Mission description", yc == YC_MISSIONDESC, 0); y += TextHeight(); sprintf(s, "Characters (%d/%d)", currentMission->baddieCount, BADDIE_MAX); DisplayText(20, y, s, yc == YC_CHARACTERS, 0); y += TextHeight(); sprintf(s, "Mission objective characters (%d/%d)", currentMission->specialCount, SPECIAL_MAX); DisplayText(20, y, s, yc == YC_SPECIALS, 0); y += TextHeight(); sprintf(s, "Available weapons (%d/%d)", gMission.weaponCount, WEAPON_MAX); DisplayText(20, y, s, yc == YC_WEAPONS, 0); y += TextHeight(); sprintf(s, "Map items (%d/%d)", gMission.objectCount, ITEMS_MAX); DisplayText(20, y, s, yc == YC_ITEMS, 0); y += TextHeight() + 2; if (currentMission->objectiveCount) { for (i = 0; i < currentMission->objectiveCount; i++) { DisplayText(20, y, currentMission->objectives[i]. description, yc - YC_OBJECTIVES == i, 1); y += TextHeight(); } } else DisplayText(20, y, "-- mission objectives --", yc == YC_OBJECTIVES, 0); } else if (campaign.missionCount) { sprintf(s, "End/%d", campaign.missionCount); DisplayText(270, y, s, yc == YC_MISSIONINDEX, 0); } y = 170; switch (yc) { case YC_CAMPAIGNTITLE: DisplayText(20, 150, campaign.author, yc == YC_CAMPAIGNTITLE && xc == XC_AUTHOR, 1); MissionDescription(150 + TH, campaign.description, yc == YC_CAMPAIGNTITLE && xc == XC_CAMPAIGNDESC); SetSecondaryMouseRects(localCampaignClicks); break; case YC_MISSIONTITLE: DisplayText(20, 150, currentMission->song, yc == YC_MISSIONTITLE && xc == XC_MUSICFILE, 1); SetSecondaryMouseRects(localMissionClicks); break; case YC_MISSIONDESC: MissionDescription(150, currentMission->description, yc == YC_MISSIONDESC); break; case YC_CHARACTERS: TextStringAt(5, 190, "Use Insert, Delete and PageUp/PageDown"); if (!currentMission) break; for (i = 0; i < currentMission->baddieCount; i++) DisplayCharacter(20 + 20 * i, y, CHARACTER_OTHERS + i, xc == i); SetSecondaryMouseRects(localCharacterClicks); break; case YC_SPECIALS: TextStringAt(5, 190, "Use Insert, Delete and PageUp/PageDown"); if (!currentMission) break; for (i = 0; i < currentMission->specialCount; i++) DisplayCharacter(20 + 20 * i, y, CHARACTER_OTHERS + currentMission->baddieCount + i, xc == i); SetSecondaryMouseRects(localCharacterClicks); break; case YC_ITEMS: TextStringAt(5, 190, "Use Insert, Delete and PageUp/PageDown"); if (!currentMission) break; for (i = 0; i < currentMission->itemCount; i++) DisplayMapItem(10 + 20 * i, y, gMission.mapObjects[i], currentMission->itemDensity[i], xc == i); break; case YC_WEAPONS: if (!currentMission) break; ListWeapons(150, xc); break; default: if (currentMission && yc >= YC_OBJECTIVES && yc - YC_OBJECTIVES < currentMission->objectiveCount) { TextStringAt(5, 190, "Use Insert, Delete and PageUp/PageDown"); DrawObjectiveInfo(yc - YC_OBJECTIVES, y, xc); } break; } vsync(); CopyToScreen(); }