Beispiel #1
0
bool ScreenMissionSummary(CampaignOptions *c, struct MissionOptions *m)
{
	// Save password
	MissionSave ms;
	MissionSaveInit(&ms);
	ms.Campaign = c->Entry;
	// Don't make password for next level if there is none
	int passwordIndex = m->index + 1;
	if (passwordIndex == c->Entry.NumMissions)
	{
		passwordIndex--;
	}
	strcpy(ms.Password, MakePassword(passwordIndex, 0));
	ms.MissionsCompleted = m->index + 1;
	AutosaveAddMission(&gAutosave, &ms, ms.Campaign.BuiltinIndex);
	AutosaveSave(&gAutosave, GetConfigFilePath(AUTOSAVE_FILE));

	// Calculate bonus scores
	// Bonuses only apply if at least one player has lived
	if (AreAnySurvived())
	{
		int bonus = 0;
		// Objective bonuses
		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);
			if (o->done == mo->Count && o->done > mo->Required)
			{
				// Perfect
				bonus += PERFECT_BONUS;
			}
		}
		bonus += GetAccessBonus(m);
		bonus += GetTimeBonus(m, NULL);

		for (int i = 0; i < (int)gPlayerDatas.size; i++)
		{
			PlayerData *p = CArrayGet(&gPlayerDatas, i);
			ApplyBonuses(p, bonus);
		}
	}
	GameLoopWaitForAnyKeyOrButtonData wData;
	GameLoopData gData = GameLoopDataNew(
		&wData, GameLoopWaitForAnyKeyOrButtonFunc,
		m, MissionSummaryDraw);
	GameLoop(&gData);
	if (wData.IsOK)
	{
		SoundPlay(&gSoundDevice, StrSound("mg"));
	}
	return wData.IsOK;
}
Beispiel #2
0
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;
	}
}