static UIObject *CreateAddKeyObjs(Vec2i pos, EditorBrush *brush)
{
	UIObject *o2;
	UIObject *c = UIObjectCreate(UITYPE_CONTEXT_MENU, 0, pos, Vec2iZero());

	UIObject *o = UIObjectCreate(
		UITYPE_CUSTOM, 0,
		Vec2iZero(), Vec2iNew(TILE_WIDTH + 4, TILE_HEIGHT + 4));
	o->ChangeFunc = BrushSetBrushTypeAddKey;
	o->u.CustomDrawFunc = DrawKey;
	o->OnFocusFunc = ActivateIndexedEditorBrush;
	o->OnUnfocusFunc = DeactivateIndexedEditorBrush;
	pos = Vec2iZero();
	int width = 4;
	for (int i = 0; i < KEY_COUNT; i++)
	{
		o2 = UIObjectCopy(o);
		o2->IsDynamicData = 1;
		CMALLOC(o2->Data, sizeof(IndexedEditorBrush));
		((IndexedEditorBrush *)o2->Data)->Brush = brush;
		((IndexedEditorBrush *)o2->Data)->u.ItemIndex = i;
		o2->Pos = pos;
		UIObjectAddChild(c, o2);
		pos.x += o->Size.x;
		if (((i + 1) % width) == 0)
		{
			pos.x = 0;
			pos.y += o->Size.y;
		}
	}

	UIObjectDestroy(o);
	return c;
}
Example #2
0
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 UIObject *CreateSetKeyObjs(Vec2i pos, EditorBrush *brush)
{
	UIObject *o2;
	UIObject *c = UIObjectCreate(UITYPE_CONTEXT_MENU, 0, pos, Vec2iZero());

	UIObject *o = UIObjectCreate(
		UITYPE_CUSTOM, 0,
		Vec2iZero(), Vec2iNew(TILE_WIDTH + 4, TILE_HEIGHT + 4));
	o->ChangeFunc = BrushSetBrushTypeSetKey;
	o->u.CustomDrawFunc = DrawKey;
	o->OnFocusFunc = ActivateIndexedEditorBrush;
	o->OnUnfocusFunc = DeactivateIndexedEditorBrush;
	pos = Vec2iZero();
	for (int i = -1; i < KEY_COUNT; i++)
	{
		o2 = UIObjectCopy(o);
		o2->IsDynamicData = 1;
		CMALLOC(o2->Data, sizeof(IndexedEditorBrush));
		((IndexedEditorBrush *)o2->Data)->Brush = brush;
		((IndexedEditorBrush *)o2->Data)->ItemIndex = i;
		o2->Pos = pos;
		if (i == -1)
		{
			// -1 means no key
			CSTRDUP(o2->Tooltip, "no key");
		}
		UIObjectAddChild(c, o2);
		pos.x += o->Size.x;
	}

	UIObjectDestroy(o);
	return c;
}
Example #4
0
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));
	}
}
UIObject *CreateAddItemObjs(
	Vec2i pos, EditorBrush *brush, CampaignOptions *co)
{
	const int th = FontH();
	UIObject *o2;
	UIObject *c = UIObjectCreate(UITYPE_CONTEXT_MENU, 0, pos, Vec2iZero());

	UIObject *o = UIObjectCreate(
		UITYPE_LABEL, 0, Vec2iZero(), Vec2iNew(65, th));
	o->Data = brush;

	pos = Vec2iZero();
	o2 = UIObjectCopy(o);
	o2->Label = "Player start";
	o2->ChangeFunc = BrushSetBrushTypeSetPlayerStart;
	o2->Pos = pos;
	CSTRDUP(o2->Tooltip, "Location where players start");
	o2->OnFocusFunc = ActivateBrush;
	o2->OnUnfocusFunc = DeactivateBrush;
	o2->Data = brush;
	UIObjectAddChild(c, o2);
	pos.y += th;
	o2 = UIObjectCopy(o);
	o2->Label = "Map item >";
	o2->Pos = pos;
	UIObjectAddChild(o2, CreateAddMapItemObjs(
		o2->Size, AddMapItemBrushObjFunc, brush, sizeof(IndexedEditorBrush),
		true));
	UIObjectAddChild(c, o2);
	pos.y += th;
	o2 = UIObjectCopy(o);
	o2->Label = "Pickup spawner >";
	o2->Pos = pos;
	UIObjectAddChild(o2, CreateAddPickupSpawnerObjs(
		o2->Size, AddPickupSpawnerBrushObjFunc, brush,
		sizeof(IndexedEditorBrush)));
	UIObjectAddChild(c, o2);
	pos.y += th;
	o2 = UIObjectCopy(o);
	o2->Label = "Character >";
	o2->Pos = pos;
	UIObjectAddChild(o2, CreateAddCharacterObjs(o2->Size, brush, co));
	UIObjectAddChild(c, o2);
	pos.y += th;
	o2 = UIObjectCopy(o);
	o2->Label = "Objective >";
	o2->Pos = pos;
	UIObjectAddChild(o2, CreateAddObjectiveObjs(o2->Size, brush, co));
	UIObjectAddChild(c, o2);
	pos.y += th;
	o2 = UIObjectCopy(o);
	o2->Label = "Key >";
	o2->Pos = pos;
	UIObjectAddChild(o2, CreateAddKeyObjs(o2->Size, brush));
	UIObjectAddChild(c, o2);

	UIObjectDestroy(o);
	return c;
}
Example #6
0
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();
		}
	}
Example #7
0
void PicTrim(Pic *pic, const bool xTrim, const bool yTrim)
{
	// Scan all pixels looking for the min/max of x and y
	Vec2i min = pic->size;
	Vec2i max = Vec2iZero();
	for (Vec2i pos = Vec2iZero(); pos.y < pic->size.y; pos.y++)
	{
		for (pos.x = 0; pos.x < pic->size.x; pos.x++)
		{
			const Uint32 pixel = *(pic->Data + pos.x + pos.y * pic->size.x);
			if (PixelToColor(&gGraphicsDevice, pixel).a > 0)
			{
				min.x = MIN(min.x, pos.x);
				min.y = MIN(min.y, pos.y);
				max.x = MAX(max.x, pos.x);
				max.y = MAX(max.y, pos.y);
			}
		}
	}
	// If no opaque pixels found, don't trim
	Vec2i newSize = pic->size;
	Vec2i offset = Vec2iZero();
	if (min.x < max.x && min.y < max.y)
	{
		if (xTrim)
		{
			newSize.x = max.x - min.x + 1;
			offset.x = min.x;
		}
		if (yTrim)
		{
			newSize.y = max.y - min.y + 1;
			offset.y = min.y;
		}
	}
	// Trim by copying pixels
	Uint32 *newData;
	CMALLOC(newData, newSize.x * newSize.y * sizeof *newData);
	for (Vec2i pos = Vec2iZero(); pos.y < newSize.y; pos.y++)
	{
		for (pos.x = 0; pos.x < newSize.x; pos.x++)
		{
			Uint32 *target = newData + pos.x + pos.y * newSize.x;
			const int srcIdx =
				pos.x + offset.x + (pos.y + offset.y) * pic->size.x;
			*target = *(pic->Data + srcIdx);
		}
	}
	// Replace the old data
	CFREE(pic->Data);
	pic->Data = newData;
	pic->size = newSize;
	pic->offset = Vec2iZero();
}
Example #8
0
void ShowControls(void)
{
	FontOpts opts = FontOptsNew();
	opts.HAlign = ALIGN_CENTER;
	opts.VAlign = ALIGN_END;
	opts.Area = gGraphicsDevice.cachedConfig.Res;
	opts.Pad.y = 10;
#ifdef __GCWZERO__
	FontStrOpt(
		"(use joystick or D pad + START + SELECT)", Vec2iZero(), opts);
#else
	FontStrOpt(
		"(use joystick 1 or arrow keys + Enter/Backspace)", Vec2iZero(), opts);
#endif
}
static void CreateAddCharacterSubObjs(UIObject *c, void *vData)
{
	EditorBrushAndCampaign *data = vData;
	CharacterStore *store = &data->Campaign->Setting.characters;
	if (c->Children.size == store->OtherChars.size)
	{
		return;
	}
	// Recreate the child UI objects
	c->Highlighted = NULL;
	UIObject **objs = c->Children.data;
	for (int i = 0; i < (int)c->Children.size; i++, objs++)
	{
		UIObjectDestroy(*objs);
	}
	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 = BrushSetBrushTypeAddCharacter;
	o->u.CustomDrawFunc = DrawCharacter;
	o->OnFocusFunc = ActivateEditorBrushAndCampaignBrush;
	o->OnUnfocusFunc = DeactivateEditorBrushAndCampaignBrush;
	Vec2i pos = Vec2iZero();
	int width = 8;
	for (int i = 0; i < (int)store->OtherChars.size; i++)
	{
		UIObject *o2 = UIObjectCopy(o);
		Character *ch = CArrayGet(&store->OtherChars, i);
		CSTRDUP(o2->Tooltip, ch->Gun->name);
		o2->IsDynamicData = 1;
		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 = i;
		o2->Pos = pos;
		UIObjectAddChild(c, o2);
		pos.x += o->Size.x;
		if (((i + 1) % width) == 0)
		{
			pos.x = 0;
			pos.y += o->Size.y;
		}
	}
	UIObjectDestroy(o);
}
Example #10
0
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);
	}
}
Example #11
0
static void DrawEditorTiles(DrawBuffer *b, Vec2i offset)
{
	Vec2i pos;
	Tile *tile = &b->tiles[0][0];
	pos.y = b->dy + offset.y;
	for (int y = 0; y < Y_TILES; y++, pos.y += TILE_HEIGHT)
	{
		pos.x = b->dx + offset.x;
		for (int x = 0; x < b->Size.x; x++, tile++, pos.x += TILE_WIDTH)
		{
			if (gMission.missionData->Type == MAPTYPE_STATIC)
			{
				Vec2i start = gMission.missionData->u.Static.Start;
				if (!Vec2iEqual(start, Vec2iZero()) &&
					Vec2iEqual(start, Vec2iNew(x + b->xStart, y + b->yStart)))
				{
					// mission start
					BlitMasked(
						&gGraphicsDevice,
						PicManagerGetPic(&gPicManager, "editor/start"),
						pos, colorWhite, 1);
				}
			}
		}
		tile += X_TILES - b->Size.x;
	}
}
Example #12
0
static void MakeBackground(GraphicsDevice *g, int buildTables)
{
	if (buildTables)
	{
		// Automatically pan camera to middle of screen
		Mission *m = gMission.missionData;
		Vec2i focusTile = Vec2iScaleDiv(m->Size, 2);
		// Better yet, if the map has a known start position, focus on that
		if (m->Type == MAPTYPE_STATIC &&
			!Vec2iEqual(m->u.Static.Start, Vec2iZero()))
		{
			focusTile = m->u.Static.Start;
		}
		camera = Vec2iCenterOfTile(focusTile);
	}

	// Clear background first
	for (int i = 0; i < GraphicsGetScreenSize(&g->cachedConfig); i++)
	{
		g->buf[i] = PixelFromColor(g, colorBlack);
	}
	GrafxDrawExtra extra;
	extra.guideImage = brush.GuideImageSurface;
	extra.guideImageAlpha = brush.GuideImageAlpha;

	DrawBufferTerminate(&sDrawBuffer);
	DrawBufferInit(&sDrawBuffer, Vec2iNew(X_TILES, Y_TILES), &gGraphicsDevice);
	GrafxMakeBackground(
		g, &sDrawBuffer, &gCampaign, &gMission, &gMap,
		tintNone, 1, buildTables, camera, &extra);
}
Example #13
0
static Vec2i GenerateQuickPlayMapSize(QuickPlayQuantity size)
{
	const int minMapDim = 16;
	const int maxMapDim = 64;
	// Map sizes based on total dimensions (width + height)
	// Small: 32 - 64
	// Medium: 64 - 96
	// Large: 96 - 128
	// Restrictions: at least 16, at most 64 per side
	switch (size)
	{
	case QUICKPLAY_QUANTITY_ANY:
		return GenerateRandomPairPartitionWithRestrictions(
			32 + (rand() % (128 - 32 + 1)),
			minMapDim, maxMapDim);
	case QUICKPLAY_QUANTITY_SMALL:
		return GenerateRandomPairPartitionWithRestrictions(
			32 + (rand() % (64 - 32 + 1)),
			minMapDim, maxMapDim);
	case QUICKPLAY_QUANTITY_MEDIUM:
		return GenerateRandomPairPartitionWithRestrictions(
			64 + (rand() % (96 - 64 + 1)),
			minMapDim, maxMapDim);
	case QUICKPLAY_QUANTITY_LARGE:
		return GenerateRandomPairPartitionWithRestrictions(
			96 + (rand() % (128 - 96 + 1)),
			minMapDim, maxMapDim);
	default:
		assert(0 && "invalid quick play map size config");
		return Vec2iZero();
	}
}
Example #14
0
void PicLoad(
	Pic *p, const Vec2i size, const Vec2i offset,
	const SDL_Surface *image, const SDL_Surface *s)
{
	p->size = size;
	p->offset = Vec2iZero();
	CMALLOC(p->Data, size.x * size.y * sizeof *((Pic *)0)->Data);
	// Manually copy the pixels and replace the alpha component,
	// since our gfx device format has no alpha
	int srcI = offset.y*image->w + offset.x;
	for (int i = 0; i < size.x * size.y; i++, srcI++)
	{
		const Uint32 alpha =
			((Uint32 *)image->pixels)[srcI] >> image->format->Ashift;
		// If completely transparent, replace rgb with black (0) too
		// This is because transparency blitting checks entire pixel
		if (alpha == 0)
		{
			p->Data[i] = 0;
		}
		else
		{
			const Uint32 pixel = ((Uint32 *)s->pixels)[srcI];
			const Uint32 rgbMask =
				s->format->Rmask | s->format->Gmask | s->format->Bmask;
			p->Data[i] =
				(pixel & rgbMask) | (alpha << gGraphicsDevice.Ashift);
		}
		if ((i + 1) % size.x == 0)
		{
			srcI += image->w - size.x;
		}
	}
}
Example #15
0
void PicLoad(
	Pic *p, const Vec2i size, const Vec2i offset, const SDL_Surface *image)
{
	p->size = size;
	p->offset = Vec2iZero();
	p->Data = malloc(size.x * size.y * sizeof *((Pic *)0)->Data);
	// Manually copy the pixels and replace the alpha component,
	// since our gfx device format has no alpha
	int srcI = offset.y*image->w + offset.x;
	for (int i = 0; i < size.x * size.y; i++, srcI++)
	{
		const Uint32 pixel = ((Uint32 *)image->pixels)[srcI];
		SDL_Color c;
		SDL_GetRGBA(pixel, image->format, &c.r, &c.g, &c.b, &c.a);
		// If completely transparent, replace rgb with black (0) too
		// This is because transparency blitting checks entire pixel
		if (c.a == 0)
		{
			p->Data[i] = 0;
		}
		else
		{
			p->Data[i] = WHITE;
		}
		if ((i + 1) % size.x == 0)
		{
			srcI += image->w - size.x;
		}
	}
}
Example #16
0
bool NumPlayersSelection(
	GameMode mode, GraphicsDevice *graphics, EventHandlers *handlers)
{
	MenuSystem ms;
	MenuSystemInit(
		&ms, handlers, graphics,
		Vec2iZero(),
		graphics->cachedConfig.Res);
	ms.allowAborts = true;
	ms.root = ms.current = MenuCreateNormal(
		"",
		"Select number of players",
		MENU_TYPE_NORMAL,
		0);
	for (int i = 0; i < MAX_LOCAL_PLAYERS; i++)
	{
		char buf[2];
		if (IsMultiplayer(mode) && i == 0)
		{
			// At least two players for dogfights
			continue;
		}
		sprintf(buf, "%d", i + 1);
		MenuAddSubmenu(ms.current, MenuCreateReturn(buf, i + 1));
	}
	MenuAddExitType(&ms, MENU_TYPE_RETURN);

	MenuLoop(&ms);
	const bool ok = !ms.hasAbort;
	if (ok)
	{
		const int numPlayers = ms.current->u.returnCode;
		for (int i = 0; i < (int)gPlayerDatas.size; i++)
		{
			const PlayerData *p = CArrayGet(&gPlayerDatas, i);
			CASSERT(!p->IsLocal, "unexpected local player");
		}
		if (NetClientIsConnected(&gNetClient))
		{
			// Tell the server that we want to add new players
			NetMsgNewPlayers np;
			np.ClientId = gNetClient.ClientId;
			np.NumPlayers = numPlayers;
			NetClientSendMsg(&gNetClient, MSG_NEW_PLAYERS, &np);
		}
		else
		{
			// We are the server, just add the players
			for (int i = 0; i < numPlayers; i++)
			{
				PlayerData *p = PlayerDataAdd(&gPlayerDatas);
				PlayerDataSetLocalDefaults(p, i);
				p->inputDevice = INPUT_DEVICE_UNSET;
			}
		}
	}
	MenuSystemTerminate(&ms);
	return ok;
}
Example #17
0
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;
}
Example #18
0
void UIButtonSetPic(UIObject *o, Pic *pic)
{
	assert(o->Type == UITYPE_BUTTON && "invalid UI type");
	o->u.Button.Pic = pic;
	if (Vec2iEqual(o->Size, Vec2iZero()))
	{
		o->Size = o->u.Button.Pic->size;
	}
}
Example #19
0
void CameraInit(Camera *camera)
{
	memset(camera, 0, sizeof *camera);
	DrawBufferInit(
		&camera->Buffer, Vec2iNew(X_TILES, Y_TILES), &gGraphicsDevice);
	camera->lastPosition = Vec2iZero();
	HUDInit(&camera->HUD, &gGraphicsDevice, &gMission);
	camera->shake = ScreenShakeZero();
}
Example #20
0
// TODO: reimplement in camera
Vec2i GetPlayerCenter(
	GraphicsDevice *device, const Camera *camera,
	const PlayerData *pData, const int playerIdx)
{
	if (pData->ActorUID < 0)
	{
		// Player is dead
		return Vec2iZero();
	}
	Vec2i center = Vec2iZero();
	int w = device->cachedConfig.Res.x;
	int h = device->cachedConfig.Res.y;

	if (GetNumPlayers(PLAYER_ALIVE_OR_DYING, true, true) == 1 ||
		GetNumPlayers(PLAYER_ALIVE_OR_DYING, false , true) == 1 ||
		CameraIsSingleScreen())
	{
		const Vec2i pCenter = camera->lastPosition;
		const Vec2i screenCenter =
			Vec2iNew(w / 2, device->cachedConfig.Res.y / 2);
		const TActor *actor = ActorGetByUID(pData->ActorUID);
		const Vec2i p = Vec2iNew(actor->tileItem.x, actor->tileItem.y);
		center = Vec2iAdd(Vec2iMinus(p, pCenter), screenCenter);
	}
	else
	{
		const int numLocalPlayers = GetNumPlayers(PLAYER_ANY, false, true);
		if (numLocalPlayers == 2)
		{
			center.x = playerIdx == 0 ? w / 4 : w * 3 / 4;
			center.y = h / 2;
		}
		else if (numLocalPlayers >= 3 && numLocalPlayers <= 4)
		{
			center.x = (playerIdx & 1) ? w * 3 / 4 : w / 4;
			center.y = (playerIdx >= 2) ? h * 3 / 4 : h / 4;
		}
		else
		{
			CASSERT(false, "invalid number of players");
		}
	}
	return center;
}
Example #21
0
static void DrawWeaponStatus(
	HUD *hud, const TActor *actor, Vec2i pos,
	const FontAlign hAlign, const FontAlign vAlign)
{
	const Weapon *weapon = ActorGetGun(actor);

	// Draw gun icon, and allocate padding to draw the gun icon
	const GunDescription *g = ActorGetGun(actor)->Gun;
	const Vec2i iconPos = Vec2iAligned(
		Vec2iNew(pos.x - 2, pos.y - 2),
		g->Icon->size, hAlign, vAlign, gGraphicsDevice.cachedConfig.Res);
	Blit(&gGraphicsDevice, g->Icon, iconPos);

	// don't draw gauge if not reloading
	if (weapon->lock > 0)
	{
		const Vec2i gaugePos = Vec2iAdd(pos, Vec2iNew(-1 + GUN_ICON_PAD, -1));
		const Vec2i size = Vec2iNew(GAUGE_WIDTH - GUN_ICON_PAD, FontH() + 2);
		const color_t barColor = { 0, 0, 255, 255 };
		const int maxLock = weapon->Gun->Lock;
		int innerWidth;
		color_t backColor = { 128, 128, 128, 255 };
		if (maxLock == 0)
		{
			innerWidth = 0;
		}
		else
		{
			innerWidth = MAX(1, size.x * (maxLock - weapon->lock) / maxLock);
		}
		DrawGauge(
			hud->device, gaugePos, size, innerWidth, barColor, backColor,
			hAlign, vAlign);
	}
	FontOpts opts = FontOptsNew();
	opts.HAlign = hAlign;
	opts.VAlign = vAlign;
	opts.Area = gGraphicsDevice.cachedConfig.Res;
	opts.Pad = Vec2iNew(pos.x + GUN_ICON_PAD, pos.y);
	char buf[128];
	if (ConfigGetBool(&gConfig, "Game.Ammo") && weapon->Gun->AmmoId >= 0)
	{
		// Include ammo counter
		sprintf(buf, "%s %d/%d",
			weapon->Gun->name,
			ActorGunGetAmmo(actor, weapon),
			AmmoGetById(&gAmmo, weapon->Gun->AmmoId)->Max);
	}
	else
	{
		strcpy(buf, weapon->Gun->name);
	}
	FontStrOpt(buf, Vec2iZero(), opts);
}
Example #22
0
void WallClockDraw(WallClock *wc)
{
	char s[50];
	sprintf(s, "%02d:%02d", wc->hours, wc->minutes);

	FontOpts opts = FontOptsNew();
	opts.VAlign = ALIGN_END;
	opts.Area = gGraphicsDevice.cachedConfig.Res;
	opts.Pad = Vec2iNew(10, 5 + FontH());
	FontStrOpt(s, Vec2iZero(), opts);
}
Example #23
0
Vec2i GetWallBounceFullPos(
	const Vec2i startFull, const Vec2i newFull, Vec2i *velFull)
{
	CASSERT(velFull != NULL, "need velocity for wall bouncing");
	Vec2i newReal = Vec2iFull2Real(newFull);
	if (!ShootWall(newReal.x, newReal.y))
	{
		return newFull;
	}
	Vec2i startRealPos = Vec2iFull2Real(startFull);
	Vec2i bounceFull = startFull;
	if (!ShootWall(startRealPos.x, newReal.y))
	{
		bounceFull.y = newFull.y;
		velFull->x *= -1;
	}
	else if (!ShootWall(newReal.x, startRealPos.y))
	{
		bounceFull.x = newFull.x;
		velFull->y *= -1;
	}
	else
	{
		*velFull = Vec2iScale(*velFull, -1);
		// Keep bouncing back if it's inside a wall
		// However, do not bounce more than half a tile's size
		if (!Vec2iIsZero(*velFull))
		{
			Vec2i bounceReal = newReal;
			const int maxBounces = MAX(
				velFull->x / 256 / TILE_WIDTH,
				velFull->y / 256 / TILE_HEIGHT);
			for (int i = 0;
				i < maxBounces &&
				MapIsRealPosIn(&gMap, bounceReal) &&
				ShootWall(bounceReal.x, bounceReal.y);
				i++)
			{
				bounceFull = Vec2iAdd(bounceFull, *velFull);
				bounceReal = Vec2iFull2Real(bounceFull);
			}
			// If still colliding wall or outside map,
			// can't recover from this point; zero velocity and return
			if (!MapIsRealPosIn(&gMap, bounceReal) ||
				ShootWall(bounceReal.x, bounceReal.y))
			{
				*velFull = Vec2iZero();
				return startFull;
			}
		}
	}
	return bounceFull;
}
Example #24
0
void FPSCounterDraw(FPSCounter *counter)
{
	char s[50];
	counter->framesDrawn++;
	sprintf(s, "FPS: %d", counter->fps);

	FontOpts opts = FontOptsNew();
	opts.HAlign = ALIGN_END;
	opts.VAlign = ALIGN_END;
	opts.Area = gGraphicsDevice.cachedConfig.Res;
	opts.Pad = Vec2iNew(10, 5 + FontH());
	FontStrOpt(s, Vec2iZero(), opts);
}
static UIObject *CreateAddCharacterObjs(
	Vec2i pos, EditorBrush *brush, CampaignOptions *co)
{
	UIObject *c = UIObjectCreate(UITYPE_CONTEXT_MENU, 0, pos, Vec2iZero());
	// Need to update UI objects dynamically as new characters can be
	// added and removed
	c->OnFocusFunc = CreateAddCharacterSubObjs;
	c->IsDynamicData = 1;
	CMALLOC(c->Data, sizeof(EditorBrushAndCampaign));
	((EditorBrushAndCampaign *)c->Data)->Brush.Brush = brush;
	((EditorBrushAndCampaign *)c->Data)->Campaign = co;

	return c;
}
Example #26
0
static void AddAndPlacePlayers(void)
{
	Vec2i firstPos = Vec2iZero();
	for (int i = 0; i < (int)gPlayerDatas.size; i++)
	{
		const PlayerData *p = CArrayGet(&gPlayerDatas, i);
		if (!p->IsUsed)
		{
			continue;
		}

		firstPos = PlacePlayer(&gMap, p, firstPos, true);
	}
}
static UIObject *CreateAddWreckObjs(Vec2i pos, EditorBrush *brush)
{
	UIObject *o2;
	UIObject *c = UIObjectCreate(UITYPE_CONTEXT_MENU, 0, pos, Vec2iZero());

	UIObject *o = UIObjectCreate(
		UITYPE_CUSTOM, 0,
		Vec2iZero(), Vec2iNew(TILE_WIDTH + 4, TILE_HEIGHT + 4));
	o->ChangeFunc = BrushSetBrushTypeAddWreck;
	o->u.CustomDrawFunc = DrawWreck;
	o->OnFocusFunc = ActivateIndexedEditorBrush;
	o->OnUnfocusFunc = DeactivateIndexedEditorBrush;
	pos = Vec2iZero();
	const int width = 8;
	for (int i = 0; i < (int)gMapObjects.Destructibles.size; i++)
	{
		o2 = UIObjectCopy(o);
		o2->IsDynamicData = 1;
		CMALLOC(o2->Data, sizeof(IndexedEditorBrush));
		((IndexedEditorBrush *)o2->Data)->Brush = brush;
		((IndexedEditorBrush *)o2->Data)->u.ItemIndex = i;
		o2->Pos = pos;
		UIObjectAddChild(c, o2);
		pos.x += o->Size.x;
		if (((i + 1) % width) == 0)
		{
			pos.x = 0;
			pos.y += o->Size.y;
		}
		const char **name = CArrayGet(&gMapObjects.Destructibles, i);
		const MapObject *mo = StrMapObject(*name);
		CSTRDUP(o2->Tooltip, mo->Name);
	}

	UIObjectDestroy(o);
	return c;
}
Example #28
0
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));
		}
	}
}
Example #29
0
void MissionStaticLayout(Mission *m, Vec2i oldSize)
{
	assert(m->Type == MAPTYPE_STATIC && "invalid map type");
	// re-layout the static map after a resize
	// The mission contains the new size; the old dimensions are oldSize
	// Simply try to "paint" the old tiles to the new mission
	Vec2i v;
	CArray oldTiles;
	CArrayInit(&oldTiles, m->u.Static.Tiles.elemSize);
	CArrayCopy(&oldTiles, &m->u.Static.Tiles);

	// Clear the tiles first
	CArrayTerminate(&m->u.Static.Tiles);
	CArrayInit(&m->u.Static.Tiles, oldTiles.elemSize);
	for (v.y = 0; v.y < m->Size.y; v.y++)
	{
		for (v.x = 0; v.x < m->Size.x; v.x++)
		{
			unsigned short tile = MAP_FLOOR;
			CArrayPushBack(&m->u.Static.Tiles, &tile);
		}
	}

	// Paint the old tiles back
	for (v.y = 0; v.y < m->Size.y; v.y++)
	{
		for (v.x = 0; v.x < m->Size.x; v.x++)
		{
			if (v.x >= oldSize.x || v.y >= oldSize.y)
			{
				MissionTrySetTile(m, v, MAP_NOTHING);
			}
			else
			{
				int idx = v.y * oldSize.x + v.x;
				unsigned short *tile = CArrayGet(&oldTiles, idx);
				MissionTrySetTile(m, v, *tile);
			}
		}
	}

	CArrayTerminate(&oldTiles);

	if (m->u.Static.Start.x >= m->Size.x || m->u.Static.Start.y >= m->Size.y)
	{
		m->u.Static.Start = Vec2iZero();
	}
}
Example #30
0
void PicFromPicPaletted(GraphicsDevice *g, Pic *pic, PicPaletted *picP)
{
	pic->size = Vec2iNew(picP->w, picP->h);
	pic->offset = Vec2iZero();
	CMALLOC(pic->Data, pic->size.x * pic->size.y * sizeof *pic->Data);
	for (int i = 0; i < pic->size.x * pic->size.y; i++)
	{
		unsigned char palette = *(picP->data + i);
		pic->Data[i] = PixelFromColor(g, PaletteToColor(palette));
		// Special case: if the palette colour is 0, it's transparent
		if (palette == 0)
		{
			pic->Data[i] = 0;
		}
	}
}