Exemplo n.º 1
0
static void pie_Draw3DButton(iIMDShape *shape)
{
	const PIELIGHT colour = WZCOL_WHITE;
	const PIELIGHT teamcolour = pal_GetTeamColour(NetPlay.players[selectedPlayer].colour);
	pie_SetFogStatus(false);
	pie_SetDepthBufferStatus(DEPTH_CMP_LEQ_WRT_ON);
	pie_ActivateShader(SHADER_BUTTON, shape, teamcolour, colour);
	pie_SetRendMode(REND_OPAQUE);
	glColor4ubv(colour.vector);     // Only need to set once for entire model
	pie_SetTexturePage(shape->texpage);
	glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_NORMAL_ARRAY);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	glBindBuffer(GL_ARRAY_BUFFER, shape->buffers[VBO_VERTEX]); glVertexPointer(3, GL_FLOAT, 0, NULL);
	glBindBuffer(GL_ARRAY_BUFFER, shape->buffers[VBO_NORMAL]); glNormalPointer(GL_FLOAT, 0, NULL);
	glBindBuffer(GL_ARRAY_BUFFER, shape->buffers[VBO_TEXCOORD]); glTexCoordPointer(2, GL_FLOAT, 0, NULL);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, shape->buffers[VBO_INDEX]);
	glDrawElements(GL_TRIANGLES, shape->npolys * 3, GL_UNSIGNED_SHORT, NULL);
	glDisableClientState(GL_VERTEX_ARRAY);
	glDisableClientState(GL_NORMAL_ARRAY);
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	polyCount += shape->npolys;
	pie_DeactivateShader();
	pie_SetDepthBufferStatus(DEPTH_CMP_ALWAYS_WRT_ON);
}
Exemplo n.º 2
0
void pie_Draw3DShape(iIMDShape *shape, int frame, int team, PIELIGHT colour, int pieFlag, int pieFlagData)
{
	pieCount++;

	ASSERT(frame >= 0, "Negative frame %d", frame);
	ASSERT(team >= 0, "Negative team %d", team);

	const PIELIGHT teamcolour = pal_GetTeamColour(team);
	if (pieFlag & pie_BUTTON)
	{
		pie_Draw3DButton(shape, teamcolour);
	}
	else
	{
		SHAPE tshape;
		tshape.shape = shape;
		tshape.frame = frame;
		tshape.colour = colour;
		tshape.teamcolour = teamcolour;
		tshape.flag = pieFlag;
		tshape.flag_data = pieFlagData;
		pie_GetMatrix(&tshape.matrix[0][0]);

		if (pieFlag & pie_HEIGHT_SCALED)	// construct
		{
			tshape.matrix = glm::scale(tshape.matrix, glm::vec3(1.0f, (float)pieFlagData / (float)pie_RAISE_SCALE, 1.0f));
		}
		if (pieFlag & pie_RAISE)		// collapse
		{
			tshape.matrix = glm::translate(tshape.matrix, glm::vec3(1.0f, (-shape->max.y * (pie_RAISE_SCALE - pieFlagData)) * (1.0f / pie_RAISE_SCALE), 1.0f));
		}

		if (pieFlag & (pie_ADDITIVE | pie_TRANSLUCENT | pie_PREMULTIPLIED))
		{
			tshapes.push_back(tshape);
		}
		else
		{
			if (shadows && (pieFlag & pie_SHADOW || pieFlag & pie_STATIC_SHADOW))
			{
				float distance;

				// draw a shadow
				ShadowcastingShape scshape;
				pie_GetMatrix(&scshape.matrix[0][0]);
				distance = scshape.matrix[3][0] * scshape.matrix[3][0];
				distance += scshape.matrix[3][1] * scshape.matrix[3][1];
				distance += scshape.matrix[3][2] * scshape.matrix[3][2];

				// if object is too far in the fog don't generate a shadow.
				if (distance < SHADOW_END_DISTANCE)
				{
					glm::vec4 pos_light0;
					glm::mat4 invmat = glm::inverse(scshape.matrix);

					// Calculate the light position relative to the object
					glGetLightfv(GL_LIGHT0, GL_POSITION, &pos_light0[0]);
					scshape.light = invmat * pos_light0;
					scshape.shape = shape;
					scshape.flag = pieFlag;
					scshape.flag_data = pieFlagData;

					scshapes.push_back(scshape);
				}
			}
			shapes.push_back(tshape);
		}
	}
}
Exemplo n.º 3
0
void pie_Draw3DShape(iIMDShape *shape, int frame, int team, PIELIGHT colour, int pieFlag, int pieFlagData)
{
	PIELIGHT teamcolour;

	ASSERT_OR_RETURN(, shape, "Attempting to draw null sprite");

	teamcolour = pal_GetTeamColour(team);

	pieCount++;

	ASSERT(frame >= 0, "Negative frame %d", frame);
	ASSERT(team >= 0, "Negative team %d", team);

	if (drawing_interface || !shadows)
	{
		pie_Draw3DShape2(shape, frame, colour, teamcolour, pieFlag, pieFlagData);
	}
	else
	{
		if (pieFlag & (pie_ADDITIVE | pie_TRANSLUCENT | pie_PREMULTIPLIED) && !(pieFlag & pie_FORCE_IMMEDIATE))
		{
			TranslucentShape tshape;
			glGetFloatv(GL_MODELVIEW_MATRIX, tshape.matrix);
			tshape.shape = shape;
			tshape.frame = frame;
			tshape.colour = colour;
			tshape.flag = pieFlag;
			tshape.flag_data = pieFlagData;
			tshapes.push_back(tshape);
		}
		else
		{
			if(pieFlag & pie_SHADOW || pieFlag & pie_STATIC_SHADOW)
			{
				float distance;

				// draw a shadow
				ShadowcastingShape scshape;
				glGetFloatv(GL_MODELVIEW_MATRIX, scshape.matrix);
				distance = scshape.matrix[12] * scshape.matrix[12];
				distance += scshape.matrix[13] * scshape.matrix[13];
				distance += scshape.matrix[14] * scshape.matrix[14];

				// if object is too far in the fog don't generate a shadow.
				if (distance < SHADOW_END_DISTANCE)
				{
					float invmat[9], pos_light0[4];

					inverse_matrix( scshape.matrix, invmat );

					// Calculate the light position relative to the object
					glGetLightfv(GL_LIGHT0, GL_POSITION, pos_light0);
					scshape.light.x = invmat[0] * pos_light0[0] + invmat[3] * pos_light0[1] + invmat[6] * pos_light0[2];
					scshape.light.y = invmat[1] * pos_light0[0] + invmat[4] * pos_light0[1] + invmat[7] * pos_light0[2];
					scshape.light.z = invmat[2] * pos_light0[0] + invmat[5] * pos_light0[1] + invmat[8] * pos_light0[2];

					scshape.shape = shape;
					scshape.flag = pieFlag;
					scshape.flag_data = pieFlagData;

					scshapes.push_back(scshape);
				}
			}

			pie_Draw3DShape2(shape, frame, colour, teamcolour, pieFlag, pieFlagData);
		}
	}
}
Exemplo n.º 4
0
void pie_Draw3DShape(iIMDShape *shape, int frame, int team, PIELIGHT colour, PIELIGHT specular, int pieFlag, int pieFlagData)
{
	PIELIGHT teamcolour;

	ASSERT_OR_RETURN(, shape, "Attempting to draw null sprite");

	teamcolour = pal_GetTeamColour(team);

	pieCount++;

	if (frame == 0)
	{
		frame = team;
	}

	if (drawing_interface || !shadows)
	{
		pie_Draw3DShape2(shape, frame, colour, teamcolour, specular, pieFlag, pieFlagData);
	}
	else
	{
		if (pieFlag & (pie_ADDITIVE | pie_TRANSLUCENT))
		{
			if (tshapes_size <= nb_tshapes)
			{
				if (tshapes_size == 0)
				{
					tshapes_size = 64;
					tshapes = (transluscent_shape_t*)malloc(tshapes_size*sizeof(transluscent_shape_t));
					memset( tshapes, 0, tshapes_size*sizeof(transluscent_shape_t) );
				}
				else
				{
					const unsigned int old_size = tshapes_size;
					tshapes_size <<= 1;
					tshapes = (transluscent_shape_t*)realloc(tshapes, tshapes_size*sizeof(transluscent_shape_t));
					memset( &tshapes[old_size], 0, (tshapes_size-old_size)*sizeof(transluscent_shape_t) );
				}
			}
			glGetFloatv(GL_MODELVIEW_MATRIX, tshapes[nb_tshapes].matrix);
			tshapes[nb_tshapes].shape = shape;
			tshapes[nb_tshapes].frame = frame;
			tshapes[nb_tshapes].colour = colour;
			tshapes[nb_tshapes].specular = specular;
			tshapes[nb_tshapes].flag = pieFlag;
			tshapes[nb_tshapes].flag_data = pieFlagData;
			nb_tshapes++;
		}
		else
		{
			if(pieFlag & pie_SHADOW || pieFlag & pie_STATIC_SHADOW)
			{
				float distance;

				// draw a shadow
				if (scshapes_size <= nb_scshapes)
				{
					if (scshapes_size == 0)
					{
						scshapes_size = 64;
						scshapes = (shadowcasting_shape_t*)malloc(scshapes_size*sizeof(shadowcasting_shape_t));
						memset( scshapes, 0, scshapes_size*sizeof(shadowcasting_shape_t) );
					}
					else
					{
						const unsigned int old_size = scshapes_size;
						scshapes_size <<= 1;
						scshapes = (shadowcasting_shape_t*)realloc(scshapes, scshapes_size*sizeof(shadowcasting_shape_t));
						memset( &scshapes[old_size], 0, (scshapes_size-old_size)*sizeof(shadowcasting_shape_t) );
					}
				}

				glGetFloatv(GL_MODELVIEW_MATRIX, scshapes[nb_scshapes].matrix);
				distance = scshapes[nb_scshapes].matrix[12] * scshapes[nb_scshapes].matrix[12];
				distance += scshapes[nb_scshapes].matrix[13] * scshapes[nb_scshapes].matrix[13];
				distance += scshapes[nb_scshapes].matrix[14] * scshapes[nb_scshapes].matrix[14];

				// if object is too far in the fog don't generate a shadow.
				if (distance < SHADOW_END_DISTANCE)
				{
					float invmat[9], pos_light0[4];

					inverse_matrix( scshapes[nb_scshapes].matrix, invmat );

					// Calculate the light position relative to the object
					glGetLightfv(GL_LIGHT0, GL_POSITION, pos_light0);
					scshapes[nb_scshapes].light.x = invmat[0] * pos_light0[0] + invmat[3] * pos_light0[1] + invmat[6] * pos_light0[2];
					scshapes[nb_scshapes].light.y = invmat[1] * pos_light0[0] + invmat[4] * pos_light0[1] + invmat[7] * pos_light0[2];
					scshapes[nb_scshapes].light.z = invmat[2] * pos_light0[0] + invmat[5] * pos_light0[1] + invmat[8] * pos_light0[2];

					scshapes[nb_scshapes].shape = shape;
					scshapes[nb_scshapes].flag = pieFlag;
					scshapes[nb_scshapes].flag_data = pieFlagData;

					nb_scshapes++;
				}
			}

			pie_Draw3DShape2(shape, frame, colour, teamcolour, specular, pieFlag, pieFlagData);
		}
	}
}
Exemplo n.º 5
0
static void displayMultiPlayer(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset, PIELIGHT *pColours)
{
	char			str[128];
	UDWORD			x					= xOffset+psWidget->x;
	UDWORD			y					= yOffset+psWidget->y;
	UDWORD			player = psWidget->UserData; //get the in game player number.
	Position		position;
	Vector3i 		rotation;

	if( responsibleFor(player,0) )
	{
		displayExtraGubbins(widgGetFromID(psWScreen,MULTIMENU_FORM)->height);
	}

	iV_SetFont(font_regular);											// font
	iV_SetTextColour(WZCOL_TEXT_BRIGHT);

	if(isHumanPlayer(player) || (game.type == SKIRMISH && player<game.maxPlayers) )
	{
		ssprintf(str, "%d: %s", NetPlay.players[player].position, getPlayerName(player));
		if (isHumanPlayer(player))
		{
			SetPlayerTextColor(alliances[selectedPlayer][player], player);
		}
		else
		{
			SetPlayerTextColor(alliances[selectedPlayer][player], player);
		}

		while(iV_GetTextWidth(str) >= (MULTIMENU_C0-MULTIMENU_C2-10) )
		{
			str[strlen(str)-1]='\0';
		}
		iV_DrawText(str, x+MULTIMENU_C2, y+MULTIMENU_FONT_OSET);

		//c3-7 alliance
		//manage buttons by showing or hiding them. gifts only in campaign,
		{
			if(game.alliance != NO_ALLIANCES)
			{
				if(alliances[selectedPlayer][player] == ALLIANCE_FORMED)
				{
					if(player != selectedPlayer &&  !giftsUp[player] )
					{
						if (game.alliance != ALLIANCES_TEAMS)
						{
							widgReveal(psWScreen,MULTIMENU_GIFT_RAD+ player);
							widgReveal(psWScreen,MULTIMENU_GIFT_RES+ player);
						}
						widgReveal(psWScreen,MULTIMENU_GIFT_DRO+ player);
						widgReveal(psWScreen,MULTIMENU_GIFT_POW+ player);
						giftsUp[player] = true;
					}
				}
				else
				{
					if(player != selectedPlayer && giftsUp[player])
					{
						if (game.alliance != ALLIANCES_TEAMS)
						{
							widgHide(psWScreen,MULTIMENU_GIFT_RAD+ player);
							widgHide(psWScreen,MULTIMENU_GIFT_RES+ player);
						}
						widgHide(psWScreen,MULTIMENU_GIFT_DRO+ player);
						widgHide(psWScreen,MULTIMENU_GIFT_POW+ player);
						giftsUp[player] = false;
					}
				}
			}
		}
	}
	if(isHumanPlayer(player))
	{
		SetPlayerTextColor(alliances[selectedPlayer][player], player);

		// Let's use the real score for MP games
		if (NetPlay.bComms)
		{
			//c8:score,
			if (Cheated)
			{
				sprintf(str,"(cheated)");
			}
			else
			{
				sprintf(str,"%d",getMultiStats(player).recentScore);
			}
			iV_DrawText(str, x+MULTIMENU_C8, y+MULTIMENU_FONT_OSET);

			//c9:kills,
			sprintf(str,"%d",getMultiStats(player).recentKills);
			iV_DrawText(str, x+MULTIMENU_C9, y+MULTIMENU_FONT_OSET);
		}
		else
		{
			// estimate of score for skirmish games
			sprintf(str,"%d",ingame.skScores[player][0]);
			iV_DrawText(str, x+MULTIMENU_C8, y+MULTIMENU_FONT_OSET);
			// estimated kills
			sprintf(str,"%d",ingame.skScores[player][1]);
			iV_DrawText(str, x+MULTIMENU_C9, y+MULTIMENU_FONT_OSET);
		}

		if(!getDebugMappingStatus())
		{
			//only show player's units, and nobody elses.
			//c10:units
			if (myResponsibility(player))
			{
				SetPlayerTextColor(alliances[selectedPlayer][player], player);
				sprintf(str, "%d", getNumDroids(player) + getNumTransporterDroids(player));
				iV_DrawText(str, x+MULTIMENU_C10, y+MULTIMENU_FONT_OSET);
			}

			if (runningMultiplayer())
			{
				//c11:ping
				if (player != selectedPlayer)
				{
					if (ingame.PingTimes[player] >= 2000)
					{
						sprintf(str,"???");
					}
					else
					{
						sprintf(str, "%d", ingame.PingTimes[player]);
					}
					iV_DrawText(str, x+MULTIMENU_C11, y+MULTIMENU_FONT_OSET);
				}
			}
			else
			{
				int num;
				STRUCTURE *temp;
				// NOTE, This tallys up *all* the structures you have. Test out via 'start with no base'.
				for (num = 0, temp = apsStructLists[player]; temp != NULL;num++,temp = temp->psNext) {}
				//c11: Structures
				sprintf(str, "%d", num);
				iV_DrawText(str, x+MULTIMENU_C11, y+MULTIMENU_FONT_OSET);
			}
		}
	}
	else
	{
		SetPlayerTextColor(alliances[selectedPlayer][player], player);

		// Let's use the real score for MP games
		if (NetPlay.bComms)
		{
			//c8:score,
			if (Cheated)
			{
				sprintf(str,"(cheated)");
			}
			else
			{
				sprintf(str,"%d",getMultiStats(player).recentScore);
			}
			iV_DrawText(str, x+MULTIMENU_C8, y+MULTIMENU_FONT_OSET);

			//c9:kills,
			sprintf(str,"%d",getMultiStats(player).recentKills);
			iV_DrawText(str, x+MULTIMENU_C9, y+MULTIMENU_FONT_OSET);
		}
		else
		{
			// estimate of score for skirmish games
			sprintf(str,"%d",ingame.skScores[player][0]);
			iV_DrawText(str, x+MULTIMENU_C8, y+MULTIMENU_FONT_OSET);
			// estimated kills
			sprintf(str,"%d",ingame.skScores[player][1]);
			iV_DrawText(str, x+MULTIMENU_C9, y+MULTIMENU_FONT_OSET);
		}
	}

	/* Display player power instead of number of played games
	  * and number of units instead of ping when in debug mode
	  */
	if(getDebugMappingStatus())			//Won't pass this when in both release and multiplayer modes
	{
		//c10: Total number of player units in possession
		sprintf(str,"%d",getNumDroids(player) + getNumTransporterDroids(player));
		iV_DrawText(str, x+MULTIMENU_C10, y+MULTIMENU_FONT_OSET);

		//c11: Player power
		sprintf(str, "%u", (int)getPower(player));
		iV_DrawText(str, MULTIMENU_FORM_X+MULTIMENU_C11, y+MULTIMENU_FONT_OSET);
	}

	// a droid of theirs.
	DROID *displayDroid = apsDroidLists[player];
	while (displayDroid != NULL && !displayDroid->visible[selectedPlayer])
	{
		displayDroid = displayDroid->psNext;
	}
	if (displayDroid)
	{
		pie_SetGeometricOffset( MULTIMENU_FORM_X+MULTIMENU_C1 ,y+MULTIMENU_PLAYER_H);
		rotation.x = -15;
		rotation.y = 45;
		rotation.z = 0;
		position.x = 0;
		position.y = 0;
		position.z = 2000;		//scale them!

		displayComponentButtonObject(displayDroid, &rotation, &position, false, 100);
	}
	else if(apsDroidLists[player])
	{
		// Show that they have droids, but not which droids, since we can't see them.
		iV_DrawImageTc(IntImages, IMAGE_GENERIC_TANK, IMAGE_GENERIC_TANK_TC, MULTIMENU_FORM_X + MULTIMENU_C1 - iV_GetImageWidth(IntImages, IMAGE_GENERIC_TANK)/2, y + MULTIMENU_PLAYER_H - iV_GetImageHeight(IntImages, IMAGE_GENERIC_TANK), pal_GetTeamColour(getPlayerColour(player)));
	}

	// clean up widgets if player leaves while menu is up.
	if(!isHumanPlayer(player) && !(game.type == SKIRMISH && player<game.maxPlayers))
	{
		if(widgGetFromID(psWScreen,MULTIMENU_CHANNEL+player))
		{
			widgDelete(psWScreen,MULTIMENU_CHANNEL+ player);
		}

		if(widgGetFromID(psWScreen,MULTIMENU_ALLIANCE_BASE+player) )
		{
			widgDelete(psWScreen,MULTIMENU_ALLIANCE_BASE+ player);
			widgDelete(psWScreen,MULTIMENU_GIFT_RAD+ player);
			widgDelete(psWScreen,MULTIMENU_GIFT_RES+ player);
			widgDelete(psWScreen,MULTIMENU_GIFT_DRO+ player);
			widgDelete(psWScreen,MULTIMENU_GIFT_POW+ player);
			giftsUp[player] = false;
		}
	}
}
Exemplo n.º 6
0
static void displayMultiPlayer(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset)
{
	char str[128];
	int x = xOffset + psWidget->x();
	int y = yOffset + psWidget->y();
	unsigned player = psWidget->UserData;  // Get the in game player number.

	if (responsibleFor(player, 0))
	{
		displayExtraGubbins(widgGetFromID(psWScreen,MULTIMENU_FORM)->height());
	}

	iV_SetFont(font_regular);  // font
	iV_SetTextColour(WZCOL_TEXT_BRIGHT);

	const bool isHuman = isHumanPlayer(player);
	const bool isAlly = aiCheckAlliances(selectedPlayer, player);
	const bool isSelectedPlayer = player == selectedPlayer;

	SetPlayerTextColor(alliances[selectedPlayer][player], player);

	if (isHuman || (game.type == SKIRMISH && player<game.maxPlayers) )
	{
		ssprintf(str, "%d: %s", NetPlay.players[player].position, getPlayerName(player));

		while (iV_GetTextWidth(str) >= MULTIMENU_C0 - MULTIMENU_C2 - 10)
		{
			str[strlen(str) - 1] = '\0';
		}
		iV_DrawText(str, x + MULTIMENU_C2, y + MULTIMENU_FONT_OSET);

		//c3-7 alliance
		//manage buttons by showing or hiding them. gifts only in campaign,
		if (alliancesCanGiveAnything(game.alliance))
		{
			if (isAlly && !isSelectedPlayer && !giftsUp[player] )
			{
				if (alliancesCanGiveResearchAndRadar(game.alliance))
				{
					widgReveal(psWScreen, MULTIMENU_GIFT_RAD + player);
					widgReveal(psWScreen, MULTIMENU_GIFT_RES + player);
				}
				widgReveal(psWScreen, MULTIMENU_GIFT_DRO + player);
				widgReveal(psWScreen, MULTIMENU_GIFT_POW + player);
				giftsUp[player] = true;
			}
			else if (!isAlly && !isSelectedPlayer && giftsUp[player])
			{
				if (alliancesCanGiveResearchAndRadar(game.alliance))
				{
					widgHide(psWScreen, MULTIMENU_GIFT_RAD + player);
					widgHide(psWScreen, MULTIMENU_GIFT_RES + player);
				}
				widgHide(psWScreen, MULTIMENU_GIFT_DRO + player);
				widgHide(psWScreen, MULTIMENU_GIFT_POW + player);
				giftsUp[player] = false;
			}
		}
	}

	// Let's use the real score for MP games
	if (NetPlay.bComms)
	{
		//c8:score,
		if (Cheated)
		{
			sprintf(str, "(cheated)");
		}
		else
		{
			sprintf(str, "%d", getMultiStats(player).recentScore);
		}
		iV_DrawText(str, x + MULTIMENU_C8, y + MULTIMENU_FONT_OSET);

		//c9:kills,
		sprintf(str, "%d", getMultiStats(player).recentKills);
		iV_DrawText(str, x + MULTIMENU_C9, y + MULTIMENU_FONT_OSET);
	}
	else
	{
		// estimate of score for skirmish games
		sprintf(str, "%d", ingame.skScores[player][0]);
		iV_DrawText(str, x + MULTIMENU_C8, y + MULTIMENU_FONT_OSET);
		// estimated kills
		sprintf(str, "%d", ingame.skScores[player][1]);
		iV_DrawText(str, x + MULTIMENU_C9, y + MULTIMENU_FONT_OSET);
	}

	//only show player's and allies' unit counts, and nobody elses.
	//c10:units
	if (isAlly || getDebugMappingStatus())
	{
		sprintf(str, "%d", getNumDroids(player) + getNumTransporterDroids(player));
		iV_DrawText(str, x + MULTIMENU_C10, y + MULTIMENU_FONT_OSET);
	}

	/* Display player power instead of number of played games
	  * and number of units instead of ping when in debug mode
	  */
	if (getDebugMappingStatus())  //Won't pass this when in both release and multiplayer modes
	{
		//c11: Player power
		sprintf(str, "%u", (int)getPower(player));
		iV_DrawText(str, MULTIMENU_FORM_X + MULTIMENU_C11, y + MULTIMENU_FONT_OSET);
	}
	else if (runningMultiplayer())
	{
		//c11:ping
		if (!isSelectedPlayer && isHuman)
		{
			if (ingame.PingTimes[player] < PING_LIMIT)
			{
				sprintf(str, "%03d", ingame.PingTimes[player]);
			}
			else
			{
				sprintf(str, "∞");
			}
			iV_DrawText(str, x + MULTIMENU_C11, y + MULTIMENU_FONT_OSET);
		}
	}
	else
	{
		//c11: Structures
		if (isAlly || getDebugMappingStatus())
		{
			// NOTE, This tallys up *all* the structures you have. Test out via 'start with no base'.
			int num = 0;
			for (STRUCTURE *temp = apsStructLists[player]; temp != NULL; temp = temp->psNext)
			{
				++num;
			}
			sprintf(str, "%d", num);
			iV_DrawText(str, x + MULTIMENU_C11, y + MULTIMENU_FONT_OSET);
		}
	}

	// a droid of theirs.
	DROID *displayDroid = apsDroidLists[player];
	while (displayDroid != NULL && !displayDroid->visible[selectedPlayer])
	{
		displayDroid = displayDroid->psNext;
	}
	if (displayDroid)
	{
		pie_SetGeometricOffset( MULTIMENU_FORM_X+MULTIMENU_C1 ,y+MULTIMENU_PLAYER_H);
		Vector3i rotation(-15, 45, 0);
		Position position(0, 0, BUTTON_DEPTH);  // Scale them.
		if (displayDroid->droidType == DROID_SUPERTRANSPORTER)
		{
			position.z = 7850;
		}
		else if (displayDroid->droidType == DROID_TRANSPORTER)
		{
			position.z = 4100;
		}

		displayComponentButtonObject(displayDroid, &rotation, &position, false, 100);
	}
	else if (apsDroidLists[player])
	{
		// Show that they have droids, but not which droids, since we can't see them.
		iV_DrawImageTc(IntImages, IMAGE_GENERIC_TANK, IMAGE_GENERIC_TANK_TC, MULTIMENU_FORM_X + MULTIMENU_C1 - iV_GetImageWidth(IntImages, IMAGE_GENERIC_TANK)/2, y + MULTIMENU_PLAYER_H - iV_GetImageHeight(IntImages, IMAGE_GENERIC_TANK), pal_GetTeamColour(getPlayerColour(player)));
	}

	// clean up widgets if player leaves while menu is up.
	if (!isHuman && !(game.type == SKIRMISH && player < game.maxPlayers))
	{
		if (widgGetFromID(psWScreen, MULTIMENU_CHANNEL + player) != NULL)
		{
			widgDelete(psWScreen, MULTIMENU_CHANNEL + player);
		}

		if (widgGetFromID(psWScreen, MULTIMENU_ALLIANCE_BASE + player) != NULL)
		{
			widgDelete(psWScreen, MULTIMENU_ALLIANCE_BASE + player);
			widgDelete(psWScreen, MULTIMENU_GIFT_RAD + player);
			widgDelete(psWScreen, MULTIMENU_GIFT_RES + player);
			widgDelete(psWScreen, MULTIMENU_GIFT_DRO + player);
			widgDelete(psWScreen, MULTIMENU_GIFT_POW + player);
			giftsUp[player] = false;
		}
	}
}