コード例 #1
0
ファイル: campaigns.c プロジェクト: NSYXin/cdogs-sdl
static void CampaignListTerminate(campaign_list_t *list)
{
	CFREE(list->Name);
	CA_FOREACH(campaign_list_t, sublist, list->subFolders)
		CampaignListTerminate(sublist);
	CA_FOREACH_END()
	CArrayTerminate(&list->subFolders);
	CA_FOREACH(CampaignEntry, e, list->list)
		CampaignEntryTerminate(e);
	CA_FOREACH_END()
	CArrayTerminate(&list->list);
}
コード例 #2
0
ファイル: map_object.c プロジェクト: carstene1ns/cdogs-sdl
void MapObjectsTerminate(MapObjects *classes)
{
	MapObjectsClear(&classes->Classes);
	CArrayTerminate(&classes->Classes);
	MapObjectsClear(&classes->CustomClasses);
	CArrayTerminate(&classes->CustomClasses);
	CA_FOREACH(char *, s, classes->Destructibles)
		CFREE(*s);
	CA_FOREACH_END()
	CArrayTerminate(&classes->Destructibles);
	CA_FOREACH(char *, s, classes->Bloods)
		CFREE(*s);
	CA_FOREACH_END()
	CArrayTerminate(&classes->Bloods);
}
コード例 #3
0
ファイル: joystick.c プロジェクト: ChunHungLiu/cdogs-sdl
void JoyTerminate(CArray *joys)
{
	CA_FOREACH(Joystick, j, *joys)
		JoyTerminateOne(j);
	CA_FOREACH_END()
	CArrayTerminate(joys);
}
コード例 #4
0
ファイル: ui_object.c プロジェクト: FlyingTarrasque/cdogs-sdl
void UIObjectDestroy(UIObject *o)
{
	CFREE(o->Tooltip);
	CA_FOREACH(UIObject *, obj, o->Children)
		UIObjectDestroy(*obj);
	CA_FOREACH_END()
	CArrayTerminate(&o->Children);
	if (o->IsDynamicData)
	{
		CFREE(o->Data);
	}
	switch (o->Type)
	{
	case UITYPE_TEXTBOX:
		CFREE(o->u.Textbox.Hint);
		break;
	case UITYPE_TAB:
		CArrayTerminate(&o->u.Tab.Labels);
		break;
	default:
		// do nothing
		break;
	}
	CFREE(o);
}
コード例 #5
0
ファイル: draw.c プロジェクト: cxong/cdogs-sdl
static void DrawDebris(DrawBuffer *b, struct vec2i offset)
{
	Tile *tile = &b->tiles[0][0];
	for (int y = 0; y < Y_TILES; y++)
	{
		CArrayClear(&b->displaylist);
		for (int x = 0; x < b->Size.x; x++, tile++)
		{
			if (tile->outOfSight)
			{
				continue;
			}
			CA_FOREACH(ThingId, tid, tile->things)
				const Thing *ti = ThingIdGetThing(tid);
				if (ThingDrawLast(ti))
				{
					CArrayPushBack(&b->displaylist, &ti);
				}
			CA_FOREACH_END()
		}
		DrawBufferSortDisplayList(b);
		CA_FOREACH(const Thing *, tp, b->displaylist)
			DrawThing(b, *tp, offset);
		CA_FOREACH_END()
		tile += X_TILES - b->Size.x;
	}
}
コード例 #6
0
ファイル: screens_end.c プロジェクト: cxong/cdogs-sdl
static GameLoopResult DogfightScoresUpdate(GameLoopData *data, LoopRunner *l)
{
	PlayerList *pl = data->Data;

	const GameLoopResult result = MenuUpdate(&pl->ms);
	if (result == UPDATE_RESULT_OK)
	{
		// Calculate PVP rounds won
		int maxScore = 0;
		CA_FOREACH(PlayerData, p, gPlayerDatas)
			if (IsPlayerAlive(p))
			{
				p->Totals.Score++;
				maxScore = MAX(maxScore, p->Totals.Score);
			}
		CA_FOREACH_END()
		gCampaign.IsComplete =
			maxScore == ModeMaxRoundsWon(gCampaign.Entry.Mode);
		CASSERT(maxScore <= ModeMaxRoundsWon(gCampaign.Entry.Mode),
			"score exceeds max rounds won");
		if (gCampaign.IsComplete)
		{
			LoopRunnerChange(l, ScreenDogfightFinalScores());
		}
		else
		{
			LoopRunnerChange(
				l, HighScoresScreen(&gCampaign, &gGraphicsDevice));
		}
	}
コード例 #7
0
ファイル: autosave.c プロジェクト: NSYXin/cdogs-sdl
void AutosaveTerminate(Autosave *autosave)
{
	CA_FOREACH(MissionSave, m, autosave->Missions)
		CampaignEntryTerminate(&m->Campaign);
	CA_FOREACH_END()
	CArrayTerminate(&autosave->Missions);
}
コード例 #8
0
ファイル: screens_end.c プロジェクト: cxong/cdogs-sdl
static PlayerList *PlayerListNew(
	GameLoopResult (*updateFunc)(GameLoopData *, LoopRunner *),
	void (*drawFunc)(void *), void *data,
	const bool hasMenu, const bool showWinners)
{
	PlayerList *pl;
	CMALLOC(pl, sizeof *pl);
	pl->pos = svec2i_zero();
	pl->size = gGraphicsDevice.cachedConfig.Res;
	pl->scroll = 0;
	pl->updateFunc = updateFunc;
	pl->drawFunc = drawFunc;
	pl->data = data;
	pl->hasMenu = hasMenu;
	pl->showWinners = showWinners;
	CArrayInit(&pl->playerUIDs, sizeof(int));
	// Collect all players, then order by score descending
	int playersAlive = 0;
	CA_FOREACH(const PlayerData, p, gPlayerDatas)
		CArrayPushBack(&pl->playerUIDs, &p->UID);
		if (p->Lives > 0)
		{
			playersAlive++;
		}
	CA_FOREACH_END()
	qsort(
		pl->playerUIDs.data,
		pl->playerUIDs.size,
		pl->playerUIDs.elemSize,
		ComparePlayerScores);
	pl->showLastMan = playersAlive == 1;
	return pl;
}
コード例 #9
0
ファイル: draw.c プロジェクト: NSYXin/cdogs-sdl
static void DrawWallsAndThings(DrawBuffer *b, Vec2i offset)
{
    Vec2i pos;
    Tile *tile = &b->tiles[0][0];
    pos.y = b->dy + cWallOffset.dy + offset.y;
    for (int y = 0; y < Y_TILES; y++, pos.y += TILE_HEIGHT)
    {
        CArrayClear(&b->displaylist);
        pos.x = b->dx + cWallOffset.dx + offset.x;
        for (int x = 0; x < b->Size.x; x++, tile++, pos.x += TILE_WIDTH)
        {
            if (tile->flags & MAPTILE_IS_WALL)
            {
                if (!(tile->flags & MAPTILE_DELAY_DRAW))
                {
                    DrawWallColumn(y, pos, tile);
                }
            }
            else if (tile->flags & MAPTILE_OFFSET_PIC)
            {
                // Drawing doors
                // Doors may be offset; vertical doors are drawn centered
                // horizontal doors are bottom aligned
                Vec2i doorPos = pos;
                doorPos.x += (TILE_WIDTH - tile->picAlt->pic.size.x) / 2;
                if (tile->picAlt->pic.size.y > 16)
                {
                    doorPos.y +=
                        TILE_HEIGHT - (tile->picAlt->pic.size.y % TILE_HEIGHT);
                }
                BlitMasked(
                    &gGraphicsDevice,
                    &tile->picAlt->pic,
                    doorPos,
                    GetTileLOSMask(tile),
                    0);
            }

            // Draw the items that are in LOS
            if (tile->flags & MAPTILE_OUT_OF_SIGHT)
            {
                continue;
            }
            CA_FOREACH(ThingId, tid, tile->things)
            const TTileItem *ti = ThingIdGetTileItem(tid);
            // Don't draw debris, they are drawn later
            if (TileItemIsDebris(ti))
            {
                continue;
            }
            CArrayPushBack(&b->displaylist, &ti);
            CA_FOREACH_END()
        }
        DrawBufferSortDisplayList(b);
        CA_FOREACH(const TTileItem *, tp, b->displaylist)
        DrawThing(b, *tp, offset);
        CA_FOREACH_END()
        tile += X_TILES - b->Size.x;
    }
}
コード例 #10
0
ファイル: draw.c プロジェクト: NSYXin/cdogs-sdl
static void DrawDebris(DrawBuffer *b, Vec2i offset)
{
    Tile *tile = &b->tiles[0][0];
    for (int y = 0; y < Y_TILES; y++)
    {
        CArrayClear(&b->displaylist);
        for (int x = 0; x < b->Size.x; x++, tile++)
        {
            if (tile->flags & MAPTILE_OUT_OF_SIGHT)
            {
                continue;
            }
            CA_FOREACH(ThingId, tid, tile->things)
            const TTileItem *ti = ThingIdGetTileItem(tid);
            if (TileItemIsDebris(ti))
            {
                CArrayPushBack(&b->displaylist, &ti);
            }
            CA_FOREACH_END()
        }
        DrawBufferSortDisplayList(b);
        CA_FOREACH(const TTileItem *, tp, b->displaylist)
        DrawThing(b, *tp, offset);
        CA_FOREACH_END()
        tile += X_TILES - b->Size.x;
    }
}
コード例 #11
0
ファイル: autosave.c プロジェクト: NSYXin/cdogs-sdl
static void AddMissionNodes(Autosave *a, json_t *root, const char *nodeName)
{
	json_t *missions = json_new_array();
	CA_FOREACH(MissionSave, m, a->Missions)
		json_insert_child(missions, CreateMissionNode(m));
	CA_FOREACH_END()
	json_insert_pair_into_object(root, nodeName, missions);
}
コード例 #12
0
ファイル: map_object.c プロジェクト: carstene1ns/cdogs-sdl
static void ReloadDestructibles(MapObjects *mo)
{
	CA_FOREACH(char *, s, mo->Destructibles)
		CFREE(*s);
	CA_FOREACH_END()
	CArrayClear(&mo->Destructibles);
	AddDestructibles(mo, &mo->Classes);
	AddDestructibles(mo, &mo->CustomClasses);
}
コード例 #13
0
ファイル: ammo.c プロジェクト: cxong/cdogs-sdl
void AmmoClassesClear(CArray *ammo)
{
	CA_FOREACH(Ammo, a, *ammo)
		CFREE(a->Name);
		CFREE(a->Sound);
		CFREE(a->DefaultGun);
	CA_FOREACH_END()
	CArrayClear(ammo);
}
コード例 #14
0
ファイル: config.c プロジェクト: CliffsDover/cdogs-sdl
void ConfigDestroy(Config *c)
{
	CFREE(c->Name);
	if (c->Type == CONFIG_TYPE_GROUP)
	{
		CA_FOREACH(Config, child, c->u.Group)
			ConfigDestroy(child);
		CA_FOREACH_END()
		CArrayTerminate(&c->u.Group);
	}
}
コード例 #15
0
ファイル: draw.c プロジェクト: cxong/cdogs-sdl
static void DrawWallsAndThings(DrawBuffer *b, struct vec2i offset)
{
	struct vec2i pos;
	Tile *tile = &b->tiles[0][0];
	pos.y = b->dy + WALL_OFFSET_Y + offset.y;
	const bool useFog = ConfigGetBool(&gConfig, "Game.Fog");
	for (int y = 0; y < Y_TILES; y++, pos.y += TILE_HEIGHT)
	{
		CArrayClear(&b->displaylist);
		pos.x = b->dx + offset.x;
		for (int x = 0; x < b->Size.x; x++, tile++, pos.x += TILE_WIDTH)
		{
			if (tile->Class->Type == TILE_CLASS_WALL)
			{
				DrawLOSPic(tile, tile->Class->Pic, pos, useFog);
			}
			else if (tile->Class->Type == TILE_CLASS_DOOR &&
				tile->ClassAlt && tile->ClassAlt->Pic)
			{
				// Drawing doors
				// Doors may be offset; vertical doors are drawn centered
				// horizontal doors are bottom aligned
				struct vec2i doorPos = pos;
				const Pic *pic = tile->ClassAlt->Pic;
				doorPos.x += (TILE_WIDTH - pic->size.x) / 2;
				if (pic->size.y > 16)
				{
					doorPos.y += TILE_HEIGHT - (pic->size.y % TILE_HEIGHT);
				}
				DrawLOSPic(tile, pic, doorPos, useFog);
			}

			// Draw the items that are in LOS
			if (tile->outOfSight)
			{
				continue;
			}
			CA_FOREACH(ThingId, tid, tile->things)
				const Thing *ti = ThingIdGetThing(tid);
				// Drawn later
				if (ThingDrawLast(ti))
				{
					continue;
				}
				CArrayPushBack(&b->displaylist, &ti);
			CA_FOREACH_END()
		}
		DrawBufferSortDisplayList(b);
		CA_FOREACH(const Thing *, tp, b->displaylist)
			DrawThing(b, *tp, offset);
		CA_FOREACH_END()
		tile += X_TILES - b->Size.x;
	}
}
コード例 #16
0
ファイル: game.c プロジェクト: ChunHungLiu/cdogs-sdl
bool RunGame(const CampaignOptions *co, struct MissionOptions *m, Map *map)
{
	// Clear the background
	DrawRectangle(
		&gGraphicsDevice, Vec2iZero(), gGraphicsDevice.cachedConfig.Res,
		colorBlack, 0);
	SDL_UpdateTexture(
		gGraphicsDevice.bkg, NULL, gGraphicsDevice.buf,
		gGraphicsDevice.cachedConfig.Res.x * sizeof(Uint32));

	MapLoad(map, m, co);

	// Seed random if PVP mode (otherwise players will always spawn in same
	// position)
	if (IsPVP(co->Entry.Mode))
	{
		srand((unsigned int)time(NULL));
	}

	if (!co->IsClient)
	{
		MapLoadDynamic(map, m, &co->Setting.characters);

		// For PVP modes, mark all map as explored
		if (IsPVP(co->Entry.Mode))
		{
			MapMarkAllAsVisited(map);
		}

		// Reset players for the mission
		CA_FOREACH(const PlayerData, p, gPlayerDatas)
			// Only reset for local players; for remote ones wait for the
			// client ready message
			if (!p->IsLocal) continue;
			GameEvent e = GameEventNew(GAME_EVENT_PLAYER_DATA);
			e.u.PlayerData = PlayerDataMissionReset(p);
			GameEventsEnqueue(&gGameEvents, e);
		CA_FOREACH_END()
		// Process the events to force add the players
		HandleGameEvents(&gGameEvents, NULL, NULL, NULL);

		// Note: place players first,
		// as bad guys are placed away from players
		Vec2i firstPos = Vec2iZero();
		CA_FOREACH(const PlayerData, p, gPlayerDatas)
			if (!p->Ready) continue;
			firstPos = PlacePlayer(&gMap, p, firstPos, true);
		CA_FOREACH_END()
		if (!IsPVP(co->Entry.Mode))
		{
			InitializeBadGuys();
			CreateEnemies();
		}
	}
コード例 #17
0
ファイル: bullet_class.c プロジェクト: NSYXin/cdogs-sdl
// TODO: use map structure?
BulletClass *StrBulletClass(const char *s)
{
	if (s == NULL || strlen(s) == 0)
	{
		return NULL;
	}
	CA_FOREACH(BulletClass, b, gBulletClasses.CustomClasses)
		if (strcmp(s, b->Name) == 0)
		{
			return b;
		}
	CA_FOREACH_END()
	CA_FOREACH(BulletClass, b, gBulletClasses.Classes)
		if (strcmp(s, b->Name) == 0)
		{
			return b;
		}
	CA_FOREACH_END()
	CASSERT(false, "cannot parse bullet name");
	return NULL;
}
コード例 #18
0
ファイル: campaigns.c プロジェクト: NSYXin/cdogs-sdl
void CampaignSettingTerminate(CampaignSetting *setting)
{
	CFREE(setting->Title);
	CFREE(setting->Author);
	CFREE(setting->Description);
	CA_FOREACH(Mission, m, setting->Missions)
		MissionTerminate(m);
	CA_FOREACH_END()
	CArrayTerminate(&setting->Missions);
	CharacterStoreTerminate(&setting->characters);
	memset(setting, 0, sizeof *setting);
}
コード例 #19
0
ファイル: ammo.c プロジェクト: cxong/cdogs-sdl
int StrAmmoId(const char *s)
{
	if (s == NULL || strlen(s) == 0)
	{
		return 0;
	}
	CA_FOREACH(Ammo, a, gAmmo.CustomAmmo)
		if (strcmp(s, a->Name) == 0)
		{
			return _ca_index + (int)gAmmo.Ammo.size;
		}
	CA_FOREACH_END()
	CA_FOREACH(Ammo, a, gAmmo.Ammo)
		if (strcmp(s, a->Name) == 0)
		{
			return _ca_index;
		}
	CA_FOREACH_END()
	CASSERT(false, "cannot parse ammo name");
	return 0;
}
コード例 #20
0
ファイル: map_object.c プロジェクト: carstene1ns/cdogs-sdl
int DestructibleMapObjectIndex(const MapObject *mo)
{
	if (mo == NULL)
	{
		return 0;
	}
	CA_FOREACH(const char *, name, gMapObjects.Destructibles)
		const MapObject *d = StrMapObject(*name);
		if (d == mo)
		{
			return _ca_index;
		}
	CA_FOREACH_END()
	CASSERT(false, "cannot find destructible map object");
	return -1;
}
コード例 #21
0
ファイル: gamedata.c プロジェクト: ChunHungLiu/cdogs-sdl
void MissionOptionsTerminate(struct MissionOptions *mo)
{
	ActorsTerminate();
	ObjsTerminate();
	MobObjsTerminate();
	PickupsTerminate();
	ParticlesTerminate(&gParticles);
	WatchesTerminate();
	CA_FOREACH(PlayerData, p, gPlayerDatas)
		p->ActorUID = -1;
	CA_FOREACH_END()
	gMission.HasStarted = false;
	gMission.HasBegun = false;
	CArrayTerminate(&mo->Weapons);

	memset(mo, 0, sizeof *mo);
}
コード例 #22
0
ファイル: sounds.c プロジェクト: NSYXin/cdogs-sdl
Mix_Chunk *StrSound(const char *s)
{
	if (s == NULL || strlen(s) == 0)
	{
		return NULL;
	}
	CA_FOREACH(SoundData, sound, gSoundDevice.customSounds)
		if (strcmp(sound->Name, s) == 0)
		{
			return sound->data;
		}
	CA_FOREACH_END()
	CA_FOREACH(SoundData, sound, gSoundDevice.sounds)
		if (strcmp(sound->Name, s) == 0)
		{
			return sound->data;
		}
	CA_FOREACH_END()
	return NULL;
}
コード例 #23
0
ファイル: map_object.c プロジェクト: carstene1ns/cdogs-sdl
MapObject *StrMapObject(const char *s)
{
	if (s == NULL || strlen(s) == 0)
	{
		return NULL;
	}
	CA_FOREACH(MapObject, c, gMapObjects.CustomClasses)
		if (strcmp(s, c->Name) == 0)
		{
			return c;
		}
	CA_FOREACH_END()
	CA_FOREACH(MapObject, c, gMapObjects.Classes)
		if (strcmp(s, c->Name) == 0)
		{
			return c;
		}
	CA_FOREACH_END()
	return NULL;
}
コード例 #24
0
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;
	}
}
コード例 #25
0
bool ScreenMissionSummary(
	CampaignOptions *c, struct MissionOptions *m, const bool completed)
{
	if (completed)
	{
		// 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);
		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
		CA_FOREACH(const Objective, o, m->missionData->Objectives)
			if (ObjectiveIsPerfect(o))
			{
				bonus += PERFECT_BONUS;
			}
		CA_FOREACH_END()
		bonus += GetAccessBonus(m);
		bonus += GetTimeBonus(m, NULL);

		CA_FOREACH(PlayerData, p, gPlayerDatas)
			ApplyBonuses(p, bonus);
		CA_FOREACH_END()
	}
	MenuSystem ms;
	const int h = FontH() * 10;
	MenuSystemInit(
		&ms, &gEventHandlers, &gGraphicsDevice,
		Vec2iNew(0, gGraphicsDevice.cachedConfig.Res.y - h),
		Vec2iNew(gGraphicsDevice.cachedConfig.Res.x, h));
	ms.current = ms.root = MenuCreateNormal("", "", MENU_TYPE_NORMAL, 0);
	// Use return code 0 for whether to continue the game
	if (completed)
	{
		MenuAddSubmenu(ms.root, MenuCreateReturn("Continue", 0));
	}
	else
	{
		MenuAddSubmenu(ms.root, MenuCreateReturn("Replay mission", 0));
		MenuAddSubmenu(ms.root, MenuCreateReturn("Back to menu", 1));
	}
	ms.allowAborts = true;
	MenuAddExitType(&ms, MENU_TYPE_RETURN);
	MenuSystemAddCustomDisplay(&ms, MissionSummaryDraw, m);
	MenuLoop(&ms);
	return ms.current->u.returnCode == 0;
}
コード例 #26
0
ファイル: draw.c プロジェクト: CliffsDover/cdogs-sdl
static void DrawWallsAndThings(DrawBuffer *b, Vec2i offset)
{
	Vec2i pos;
	Tile *tile = &b->tiles[0][0];
	pos.y = b->dy + WALL_OFFSET_Y + offset.y;
	const bool useFog = ConfigGetBool(&gConfig, "Game.Fog");
	for (int y = 0; y < Y_TILES; y++, pos.y += TILE_HEIGHT)
	{
		CArrayClear(&b->displaylist);
		pos.x = b->dx + offset.x;
		for (int x = 0; x < b->Size.x; x++, tile++, pos.x += TILE_WIDTH)
		{
			if (tile->flags & MAPTILE_IS_WALL)
			{
				if (!(tile->flags & MAPTILE_DELAY_DRAW))
				{
					DrawWallColumn(y, pos, tile);
				}
			}
			else if (tile->flags & MAPTILE_OFFSET_PIC)
			{
				// Drawing doors
				// Doors may be offset; vertical doors are drawn centered
				// horizontal doors are bottom aligned
				Vec2i doorPos = pos;
				doorPos.x += (TILE_WIDTH - tile->picAlt->pic.size.x) / 2;
				if (tile->picAlt->pic.size.y > 16)
				{
					doorPos.y +=
						TILE_HEIGHT - (tile->picAlt->pic.size.y % TILE_HEIGHT);
				}
				switch (GetTileLOS(tile, useFog))
				{
				case TILE_LOS_NORMAL:
					Blit(&gGraphicsDevice, &tile->picAlt->pic, doorPos);
					break;
				case TILE_LOS_FOG:
					BlitMasked(
						&gGraphicsDevice,
						&tile->picAlt->pic,
						doorPos,
						colorFog,
						false);
					break;
				case TILE_LOS_NONE:
				default:
					// don't draw anything
					break;
				}
			}

			// Draw the items that are in LOS
			if (tile->flags & MAPTILE_OUT_OF_SIGHT)
			{
				continue;
			}
			CA_FOREACH(ThingId, tid, tile->things)
				const TTileItem *ti = ThingIdGetTileItem(tid);
				// Drawn later
				if (TileItemDrawLast(ti))
				{
					continue;
				}
				CArrayPushBack(&b->displaylist, &ti);
			CA_FOREACH_END()
		}
		DrawBufferSortDisplayList(b);
		CA_FOREACH(const TTileItem *, tp, b->displaylist)
			DrawThing(b, *tp, offset);
		CA_FOREACH_END()
		tile += X_TILES - b->Size.x;
	}
}
コード例 #27
0
void SetupQuickPlayCampaign(CampaignSetting *setting)
{
	Mission *m;
	CMALLOC(m, sizeof *m);
	MissionInit(m);
	m->WallStyle = rand() % WALL_STYLE_COUNT;
	m->FloorStyle = rand() % FLOOR_STYLE_COUNT;
	m->RoomStyle = rand() % FLOOR_STYLE_COUNT;
	m->ExitStyle = rand() % GetExitCount();
	m->KeyStyle = rand() % KEYSTYLE_COUNT;
	strcpy(
		m->DoorStyle, DoorStyleStr(rand() % gPicManager.doorStyleNames.size));
	m->Size = GenerateQuickPlayMapSize(
		ConfigGetEnum(&gConfig, "QuickPlay.MapSize"));
	m->Type = MAPTYPE_CLASSIC;	// TODO: generate different map types
	switch (m->Type)
	{
	case MAPTYPE_CLASSIC:
		m->u.Classic.Walls = GenerateQuickPlayParam(
			ConfigGetEnum(&gConfig, "QuickPlay.WallCount"), 0, 5, 15, 30);
		m->u.Classic.WallLength = GenerateQuickPlayParam(
			ConfigGetEnum(&gConfig, "QuickPlay.WallLength"), 1, 3, 6, 12);
		m->u.Classic.CorridorWidth = rand() % 3 + 1;
		m->u.Classic.Rooms.Count = GenerateQuickPlayParam(
			ConfigGetEnum(&gConfig, "QuickPlay.RoomCount"), 0, 2, 5, 12);
		m->u.Classic.Rooms.Min = rand() % 10 + 5;
		m->u.Classic.Rooms.Max = rand() % 10 + m->u.Classic.Rooms.Min;
		m->u.Classic.Rooms.Edge = 1;
		m->u.Classic.Rooms.Overlap = 1;
		m->u.Classic.Rooms.Walls = rand() % 5;
		m->u.Classic.Rooms.WallLength = rand() % 6 + 1;
		m->u.Classic.Rooms.WallPad = rand() % 4 + 1;
		m->u.Classic.Squares = GenerateQuickPlayParam(
			ConfigGetEnum(&gConfig, "QuickPlay.SquareCount"), 0, 1, 3, 6);
		m->u.Classic.Doors.Enabled = rand() % 2;
		m->u.Classic.Doors.Min = 1;
		m->u.Classic.Doors.Max = 6;
		m->u.Classic.Pillars.Count = rand() % 5;
		m->u.Classic.Pillars.Min = rand() % 3 + 1;
		m->u.Classic.Pillars.Max = rand() % 3 + m->u.Classic.Pillars.Min;
		break;
	default:
		assert(0 && "unknown map type");
		break;
	}
	CharacterStoreTerminate(&setting->characters);
	CharacterStoreInit(&setting->characters);
	int c = GenerateQuickPlayParam(
		ConfigGetEnum(&gConfig, "QuickPlay.EnemyCount"), 3, 5, 8, 12);
	SetupQuickPlayEnemies(m, c, &setting->characters);

	c = GenerateQuickPlayParam(
		ConfigGetEnum(&gConfig, "QuickPlay.ItemCount"), 0, 2, 5, 10);
	for (int i = 0; i < c; i++)
	{
		MapObjectDensity mop;
		mop.M = IndexMapObject(rand() % MapObjectsCount(&gMapObjects));
		mop.Density = GenerateQuickPlayParam(
			ConfigGetEnum(&gConfig, "QuickPlay.ItemCount"), 0, 5, 10, 20);
		CArrayPushBack(&m->MapObjectDensities, &mop);
	}
	m->EnemyDensity = (40 + (rand() % 20)) / m->Enemies.size;
	CA_FOREACH(const GunDescription, g, gGunDescriptions.Guns)
		if (g->IsRealGun)
		{
			CArrayPushBack(&m->Weapons, &g);
		}
	CA_FOREACH_END()
	m->WallMask = RandomBGColor();
	m->FloorMask = RandomBGColor();
	m->RoomMask = RandomBGColor();
	m->AltMask = RandomBGColor();

	CFREE(setting->Title);
	CSTRDUP(setting->Title, "Quick play");
	CFREE(setting->Author);
	CSTRDUP(setting->Author, "");
	CFREE(setting->Description);
	CSTRDUP(setting->Description, "");
	CArrayPushBack(&setting->Missions, m);
	CFREE(m);
}
コード例 #28
0
static void CreateAddObjectiveSubObjs(UIObject *c, void *vData)
{
	EditorBrushAndCampaign *data = vData;
	Mission *m = CampaignGetCurrentMission(data->Campaign);
	// Check if the data is still the same; if so don't recreate the
	// child UI objects
	// This is because during the course of UI operations, this element
	// could be highlighted again; if we recreate then we invalidate
	// UI pointers.
	bool needToRecreate = false;
	int childIndex = 0;
	CA_FOREACH(const Objective, obj, m->Objectives)
		int secondaryCount = 1;
		const CharacterStore *store = &data->Campaign->Setting.characters;
		switch (obj->Type)
		{
		case OBJECTIVE_KILL:
			secondaryCount = (int)store->specialIds.size;
			break;
		case OBJECTIVE_COLLECT:
			break;
		case OBJECTIVE_DESTROY:
			break;
		case OBJECTIVE_RESCUE:
			secondaryCount = (int)store->prisonerIds.size;
			break;
		default:
			continue;
		}
		for (int j = 0; j < (int)secondaryCount; j++)
		{
			if ((int)c->Children.size <= childIndex)
			{
				needToRecreate = true;
				break;
			}
			UIObject *o2 = *(UIObject **)CArrayGet(&c->Children, childIndex);
			if (((EditorBrushAndCampaign *)o2->Data)->Brush.u.ItemIndex != _ca_index ||
				((EditorBrushAndCampaign *)o2->Data)->Brush.Index2 != j)
			{
				needToRecreate = true;
				break;
			}
			childIndex++;
		}
		if (needToRecreate)
		{
			break;
		}
	CA_FOREACH_END()
	if (!needToRecreate)
	{
		return;
	}

	// Recreate the child UI objects
	c->Highlighted = NULL;
	CA_FOREACH(UIObject *, obj, c->Children)
		UIObjectDestroy(*obj);
	CA_FOREACH_END()
	CArrayTerminate(&c->Children);
	CArrayInit(&c->Children, sizeof c);

	UIObject *o = UIObjectCreate(
		UITYPE_CUSTOM, 0,
		Vec2iZero(), Vec2iNew(TILE_WIDTH + 4, TILE_HEIGHT * 2 + 4));
	o->ChangeFunc = BrushSetBrushTypeAddObjective;
	o->u.CustomDrawFunc = DrawObjective;
	o->OnFocusFunc = ActivateEditorBrushAndCampaignBrush;
	o->OnUnfocusFunc = DeactivateEditorBrushAndCampaignBrush;
	Vec2i pos = Vec2iZero();
	CA_FOREACH(const Objective, obj, m->Objectives)
		int secondaryCount = 1;
		const CharacterStore *store = &data->Campaign->Setting.characters;
		switch (obj->Type)
		{
		case OBJECTIVE_KILL:
			secondaryCount = (int)store->specialIds.size;
			o->Size.y = TILE_HEIGHT * 2 + 4;
			break;
		case OBJECTIVE_COLLECT:
			o->Size.y = TILE_HEIGHT + 4;
			break;
		case OBJECTIVE_DESTROY:
			o->Size.y = TILE_HEIGHT * 2 + 4;
			break;
		case OBJECTIVE_RESCUE:
			secondaryCount = (int)store->prisonerIds.size;
			o->Size.y = TILE_HEIGHT * 2 + 4;
			break;
		default:
			continue;
		}
		for (int j = 0; j < (int)secondaryCount; j++)
		{
			UIObject *o2 = UIObjectCopy(o);
			CSTRDUP(o2->Tooltip, ObjectiveTypeStr(obj->Type));
			o2->IsDynamicData = true;
			CMALLOC(o2->Data, sizeof(EditorBrushAndCampaign));
			((EditorBrushAndCampaign *)o2->Data)->Brush.Brush =
				data->Brush.Brush;
			((EditorBrushAndCampaign *)o2->Data)->Campaign = data->Campaign;
			((EditorBrushAndCampaign *)o2->Data)->Brush.u.ItemIndex = _ca_index;
			((EditorBrushAndCampaign *)o2->Data)->Brush.Index2 = j;
			o2->Pos = pos;
			UIObjectAddChild(c, o2);
			pos.x += o->Size.x;
		}
		pos.x = 0;
		pos.y += o->Size.y;
	CA_FOREACH_END()
	UIObjectDestroy(o);
}