Beispiel #1
0
bool C4MainMenu::ActivateSurrender(int32_t iPlayer)
{
	C4FacetSurface fctSymbol;
	InitRefSym(C4GUI::Icon::GetIconFacet(C4GUI::Ico_Surrender), LoadResStr("IDS_MENU_SURRENDER"), iPlayer, C4MN_Extra_None, 0, 0, C4MN_Style_Context);
	SetAlignment(C4MN_Align_Left | C4MN_Align_Bottom);
	fctSymbol.Create(C4SymbolSize, C4SymbolSize); GfxR->fctOKCancel.Draw(fctSymbol,true,3,0);
	Add(LoadResStr("IDS_BTN_YES"), fctSymbol, "Surrender");
	fctSymbol.Create(C4SymbolSize, C4SymbolSize); GfxR->fctOKCancel.Draw(fctSymbol,true,1,0);
	Add(LoadResStr("IDS_BTN_NO"), fctSymbol, "");
	SetCloseCommand("ActivateMenu:Main");
	return true;
}
Beispiel #2
0
bool C4MainMenu::ActivateClient(int32_t iPlayer)
{
	// Menu symbol/init
	C4FacetSurface fctSymbol;
	InitRefSym(C4GUI::Icon::GetIconFacet(C4GUI::Ico_Disconnect), LoadResStr("IDS_MENU_DISCONNECTFROMSERVER"), iPlayer, C4MN_Extra_None, 0, 0, C4MN_Style_Context);
	SetAlignment(C4MN_Align_Left | C4MN_Align_Bottom);
	fctSymbol.Create(C4SymbolSize, C4SymbolSize); GfxR->fctOKCancel.Draw(fctSymbol,true,3,0);
	Add(LoadResStr("IDS_BTN_YES"), fctSymbol, "Part");
	fctSymbol.Create(C4SymbolSize, C4SymbolSize); GfxR->fctOKCancel.Draw(fctSymbol,true,1,0);
	Add(LoadResStr("IDS_BTN_NO"), fctSymbol, "");
	SetCloseCommand("ActivateMenu:Main");
	return true;
}
Beispiel #3
0
bool C4MainMenu::ActivateHostility(int32_t iPlayer)
{
	// Init menu
	C4FacetSurface fctSymbol;
	fctSymbol.Create(C4SymbolSize, C4SymbolSize);
	GfxR->fctMenu.GetPhase(7).Draw(fctSymbol);
	Init(fctSymbol, LoadResStr("IDS_MENU_CPATTACK"), iPlayer, C4MN_Extra_None, 0, C4MN_Hostility);
	SetAlignment(C4MN_Align_Left | C4MN_Align_Bottom);
	SetPermanent(true);
	Refill();
	// Go back to options menu on close
	SetCloseCommand("ActivateMenu:Main");
	return true;
}
Beispiel #4
0
bool C4MainMenu::ActivateGoals(int32_t iPlayer, bool fDoActivate)
{
	C4FacetSurface fctSymbol;
	C4Facet fctGF; // goal fulfilled facet

	if (fDoActivate)
	{
		// Menu symbol/init
		InitRefSym(GfxR->fctMenu.GetPhase(4),LoadResStr("IDS_MENU_CPGOALS"),iPlayer);
		SetAlignment(C4MN_Align_Left | C4MN_Align_Bottom);
		SetPermanent(false);
		fctGF.Set(NULL, C4SymbolSize-::GraphicsResource.fctCaptain.Wdt-2, 2, ::GraphicsResource.fctCaptain.Wdt, ::GraphicsResource.fctCaptain.Hgt);
	}
	// determine if the goals are fulfilled - do the calls even if the menu is not to be opened to ensure synchronization
	C4IDList GoalList, FulfilledGoalList;
	C4RoundResults::EvaluateGoals(GoalList, FulfilledGoalList, iPlayer);
	// Add Items
	if (fDoActivate)
	{
		int32_t iNumGoals = GoalList.GetNumberOfIDs(), cnt;
		C4ID idGoal; C4Def *pDef;
		for (int32_t i=0; i<iNumGoals; ++i)
			if ((idGoal = GoalList.GetID(i, &cnt)))
				if ((pDef = C4Id2Def(idGoal)))
				{
					fctSymbol.Create(C4SymbolSize,C4SymbolSize);
					// 2do: If an object instance is known, draw the object instead?
					// this would allow us to do dynamic pictures and overlays; e.g. draw the actual, required settlement score
					// for settlement score goals
					// Same for pDef->GetName(), pDef->GetDesc()
					pDef->Draw(fctSymbol);
					if (FulfilledGoalList.GetIDCount(idGoal))
					{
						fctGF.Surface=fctSymbol.Surface;
						::GraphicsResource.fctCaptain.Draw(fctGF);
					}
					StdStrBuf Command; Command.Format("Player:Goal:%s", idGoal.ToString());
					Add(pDef->GetName(),fctSymbol,Command.getData(),C4MN_Item_NoCount,NULL,"");
				}
		// Go back to options menu on close
		SetCloseCommand("ActivateMenu:Main");
	}
	// Done
	return true;
}
Beispiel #5
0
bool C4MainMenu::ActivateNewPlayer(int32_t iPlayer)
{
	// league or replay game
	if (Game.Parameters.isLeague() || Game.C4S.Head.Replay) return false;
	// Max player limit
	if (::Players.GetCount() >= Game.Parameters.MaxPlayers) return false;

	// Menu symbol/init
	if (GfxR->fctPlayerClr.Surface)
		GfxR->fctPlayerClr.Surface->SetClr(0xff);
	InitRefSym(GfxR->fctPlayerClr, LoadResStr("IDS_MENU_NOPLRFILES"), iPlayer);
	for (DirectoryIterator iter(Config.General.UserDataPath); *iter; ++iter)
		if (WildcardMatch("*.ocp", *iter))
		{
			char szFilename[_MAX_PATH+1], szCommand[_MAX_PATH+30+1];
			SCopy(*iter, szFilename, _MAX_PATH);
			if (DirectoryExists(szFilename)) continue;
			if (::Players.FileInUse(szFilename)) continue;
			// Open group
			C4Group hGroup;
			if (!hGroup.Open(szFilename)) continue;
			// Load player info
			C4PlayerInfoCore C4P;
			if (!C4P.Load(hGroup)) { hGroup.Close(); continue; }
			// Close group
			hGroup.Close();
			// Add player item
			sprintf(szCommand, "JoinPlayer:%s", szFilename);
			StdStrBuf sItemText;
			sItemText.Format(LoadResStr("IDS_MENU_NEWPLAYER"), C4P.PrefName);
			C4FacetSurface fctSymbol;
			// Add menu item
			Add(sItemText.getData(), fctSymbol, szCommand);
			// Reset symbol facet (menu holds on to the surface)
			fctSymbol.Default();
		}

	// Alignment
	SetAlignment(C4MN_Align_Left | C4MN_Align_Bottom);
	// Go back to options menu on close
	SetCloseCommand("ActivateMenu:Main");

	return true;
}
Beispiel #6
0
bool C4MainMenu::ActivateRules(int32_t iPlayer)
{
	// Menu symbol/init
	char Command[256];
	C4FacetSurface fctSymbol;
	InitRefSym(GfxR->fctMenu.GetPhase(5),LoadResStr("IDS_MENU_CPRULES"),iPlayer);
	SetAlignment(C4MN_Align_Left | C4MN_Align_Bottom);
	SetPermanent(false);
	// Items
	int32_t cnt; C4ID idGoal; C4Def *pDef;
	for (cnt=0; (idGoal=::Objects.GetListID(C4D_Rule,cnt)); cnt++)
		if ((pDef=C4Id2Def(idGoal)))
		{
			fctSymbol.Create(C4SymbolSize,C4SymbolSize); pDef->Draw(fctSymbol);
			sprintf(Command, "Player:Rule:%s", idGoal.ToString());
			Add(pDef->GetName(),fctSymbol,Command,C4MN_Item_NoCount,NULL,"");
		}
	// Go back to options menu on close
	SetCloseCommand("ActivateMenu:Main");
	// Done
	return true;
}
bool C4ObjectInfo::Save(C4Group &hGroup, bool fStoreTiny, C4DefList *pDefs)
{
	// Set group file name; rename if necessary
	char szTempGroup[_MAX_PATH+1];
	SCopy(Name, szTempGroup, _MAX_PATH);
	MakeFilenameFromTitle(szTempGroup);
	SAppend(".oci",szTempGroup, _MAX_PATH);
	if (!SEqualNoCase(Filename, szTempGroup))
	{
		if (!Filename[0])
		{
			// first time creation of file - make sure it's not a duplicate
			SCopy(szTempGroup, Filename, _MAX_PATH);
			while (hGroup.FindEntry(Filename))
			{
				// if a crew info of that name exists already, rename!
				RemoveExtension(Filename);
				int32_t iFinNum = GetTrailingNumber(Filename), iLen = SLen(Filename);
				while (iLen && Inside(Filename[iLen-1], '0', '9')) --iLen;
				if (iLen>_MAX_PATH-22) { LogF("Error generating unique filename for %s(%s): Path overflow", Name, hGroup.GetFullName().getData()); break; }
				snprintf(Filename+iLen, 22, "%d", iFinNum+1);
				EnforceExtension(Filename, "oci");
			}
		}
		else
		{
			// Crew was renamed; file rename necessary, if the name is not blocked by another crew info
			if (!hGroup.FindEntry(szTempGroup))
			{
				if (hGroup.Rename(Filename, szTempGroup))
					SCopy(szTempGroup, Filename, _MAX_PATH);
				else
				{
					// could not rename. Not fatal; just use old file
					LogF("Error adjusting crew info for %s into %s: Rename error from %s to %s!", Name, hGroup.GetFullName().getData(), Filename, szTempGroup);
				}
			}
		}
	}
	// Open group
	C4Group hTemp;
	if (!hTemp.OpenAsChild(&hGroup, Filename, false, true))
		return false;
	// custom rank image present?
	if (pDefs && !fStoreTiny)
	{
		C4Def *pDef = pDefs->ID2Def(id);
		if (pDef)
		{
			if (pDef->pRankSymbols)
			{
				C4FacetSurface fctRankSymbol;
				if (C4RankSystem::DrawRankSymbol(&fctRankSymbol, Rank, pDef->pRankSymbols, pDef->iNumRankSymbols, true))
				{
					fctRankSymbol.GetFace().SavePNG(hTemp, C4CFN_ClonkRank);
				}
			}
			else
			{
				// definition does not have custom rank symbols: Remove any rank image from Clonk
				hTemp.Delete(C4CFN_ClonkRank);
			}
		}
	}

	// Save info to temp group
	if (!C4ObjectInfoCore::Save(hTemp, pDefs))
		{ hTemp.Close(); return false; }
	// Close temp group
	hTemp.Close();
	// Success
	return true;
}
Beispiel #8
0
bool C4ObjectMenu::DoRefillInternal(bool &rfRefilled)
{
	// Variables
	C4FacetSurface fctSymbol;
	C4Object *pObj;
	char szCaption[256+1],szCommand[256+1],szCommand2[256+1];
	int32_t iCount;
	C4Def *pDef;
	C4IDList ListItems;
	C4Object *pTarget;
	C4Facet fctTarget;

	// Refill
	switch (Identification)
	{
		// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	case C4MN_Activate:
		// Clear items
		ClearItems();
		// Refill target
		if (!(pTarget=RefillObject)) return false;
		{
			// Add target contents items
			C4ObjectListIterator iter(pTarget->Contents);
			while ((pObj = iter.GetNext(&iCount)))
			{
				pDef = pObj->Def;
				if (pDef->NoGet) continue;
				// Prefer fully constructed objects
				if (~pObj->OCF & OCF_FullCon)
				{
					// easy way: only if first concat check matches
					// this doesn't catch all possibilities, but that will rarely matter
					C4Object *pObj2=pTarget->Contents.Find(pDef, ANY_OWNER, OCF_FullCon);
					if (pObj2) if (pObj2->CanConcatPictureWith(pObj)) pObj = pObj2;
				}
				// Caption
				sprintf(szCaption,LoadResStr("IDS_MENU_ACTIVATE"),(const char *) pObj->GetName());
				// Picture
				fctSymbol.Set(fctSymbol.Surface, 0,0,C4SymbolSize,C4SymbolSize);
				pObj->Picture2Facet(fctSymbol);
				// Commands
				sprintf(szCommand,"SetCommand(\"Activate\",Object(%d))&&ExecuteCommand()",pObj->Number);
				sprintf(szCommand2,"SetCommand(\"Activate\",nil,%d,0,Object(%d),%s)&&ExecuteCommand()",pTarget->Contents.ObjectCount(pDef->id),pTarget->Number,pDef->id.ToString());
				// Add menu item
				Add(szCaption,fctSymbol,szCommand,iCount,pObj,"",pDef->id,szCommand2,true,pObj->GetValue(pTarget, NO_OWNER));
				// facet taken over (arrg!)
				fctSymbol.Default();
			}
		}
		break;
		// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	case C4MN_Get:
	case C4MN_Contents:
		// Clear items
		ClearItems();
		// Refill target
		if (!(pTarget = RefillObject)) return false;
		{
			// Add target contents items
			C4ObjectListIterator iter(pTarget->Contents);
			while ((pObj = iter.GetNext(&iCount)))
			{
				pDef = pObj->Def;
				if (pDef->NoGet) continue;
				// Prefer fully constructed objects
				if (~pObj->OCF & OCF_FullCon)
				{
					// easy way: only if first concat check matches
					// this doesn't catch all possibilities, but that will rarely matter
					C4Object *pObj2 = pTarget->Contents.Find(pDef, ANY_OWNER, OCF_FullCon);
					if (pObj2) if (pObj2->CanConcatPictureWith(pObj)) pObj = pObj2;
				}
				// Determine whether to get or activate
				bool fGet = true;
				if (!(pObj->OCF & OCF_Carryable)) fGet = false; // not a carryable item
				if (Identification == C4MN_Contents)
				{
					if (Object && !!Object->Call(PSF_RejectCollection, &C4AulParSet(pObj->Def, pObj))) fGet = false; // collection rejected
				}
				if (!(pTarget->OCF & OCF_Entrance)) fGet = true; // target object has no entrance: cannot activate - force get
				// Caption
				sprintf(szCaption, LoadResStr(fGet ? "IDS_MENU_GET" : "IDS_MENU_ACTIVATE"), (const char *)pObj->GetName());
				// Picture
				fctSymbol.Set(fctSymbol.Surface, 0, 0, C4SymbolSize, C4SymbolSize);
				pObj->Picture2Facet(fctSymbol);
				// Primary command: get/activate single object
				sprintf(szCommand, "SetCommand(\"%s\", Object(%d)) && ExecuteCommand()", fGet ? "Get" : "Activate", pObj->Number);
				// Secondary command: get/activate all objects of the chosen type
				szCommand2[0] = 0; int32_t iAllCount;
				if ((iAllCount = pTarget->Contents.ObjectCount(pDef->id)) > 1)
					sprintf(szCommand2, "SetCommand(\"%s\", nil, %d,0, Object(%d), %s) && ExecuteCommand()", fGet ? "Get" : "Activate", iAllCount, pTarget->Number, pDef->id.ToString());
				// Add menu item (with object)
				Add(szCaption, fctSymbol, szCommand, iCount, pObj, "", pDef->id, szCommand2);
				fctSymbol.Default();
			}
		}
		break;
		// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	default:
		// Not an internal menu
		return true;
		// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	}

	// Successfull internal refill
	rfRefilled = true;
	return true;
}
Beispiel #9
0
bool C4MainMenu::ActivateMain(int32_t iPlayer)
{
	// Determine player
	C4Player *pPlr = ::Players.Get(iPlayer);
	// Menu symbol/init
	C4FacetSurface fctSymbol;
	fctSymbol.Create(C4SymbolSize, C4SymbolSize);
	GfxR->fctOKCancel.Draw(fctSymbol, true, 1, 1);
	Init(fctSymbol, LoadResStr(pPlr ? "IDS_MENU_CPMAIN" : "IDS_MENU_OBSERVER"), iPlayer, C4MN_Extra_None, 0, 0, C4MN_Style_Context);
	SetAlignment(C4MN_Align_Left | C4MN_Align_Bottom);
	// Goals+Rules (player menu only)
	// Goal menu can't be shown because of script callbacks
	// Rule menu could be shown, but rule activation would issue script callbacks and trigger client activation
	// Showing rules but not showing goals would be strange anyway
	if (pPlr)
	{
		// Goals
		AddRefSym(LoadResStr("IDS_MENU_CPGOALS"),GfxR->fctMenu.GetPhase(4),"ActivateMenu:Goals",C4MN_Item_NoCount,NULL,LoadResStr("IDS_MENU_CPGOALSINFO"));
		// Rules
		AddRefSym(LoadResStr("IDS_MENU_CPRULES"),GfxR->fctMenu.GetPhase(5),"ActivateMenu:Rules",C4MN_Item_NoCount,NULL,LoadResStr("IDS_MENU_CPRULESINFO"));
	}
	// Observer menu in free viewport
	if (!pPlr)
	{
		AddRefSym(LoadResStr("IDS_TEXT_VIEW"),C4GUI::Icon::GetIconFacet(C4GUI::Ico_View),"ActivateMenu:Observer",C4MN_Item_NoCount,NULL,LoadResStr("IDS_TEXT_DETERMINEPLAYERVIEWTOFOLL"));
	}
	// Hostility (player menu only)
	if (pPlr && (::Players.GetCount() > 1))
	{
		GfxR->fctFlagClr.Surface->SetClr(0xff0000);
		AddRefSym(LoadResStr("IDS_MENU_CPATTACK"),GfxR->fctMenu.GetPhase(7),"ActivateMenu:Hostility",C4MN_Item_NoCount,NULL,LoadResStr("IDS_MENU_CPATTACKINFO"));
	}
	// Team change
	if (pPlr && Game.Teams.IsTeamSwitchAllowed())
	{
		C4Facet fctTeams; fctTeams = C4GUI::Icon::GetIconFacet(C4GUI::Ico_Team);
		AddRefSym(LoadResStr("IDS_MSG_SELTEAM"),fctTeams,"ActivateMenu:TeamSel",C4MN_Item_NoCount,NULL,LoadResStr("IDS_MSG_ALLOWSYOUTOJOINADIFFERENT"));
	}
	// Player join
	if ((::Players.GetCount() < Game.Parameters.MaxPlayers) && !Game.Parameters.isLeague())
	{
		AddRefSym(LoadResStr("IDS_MENU_CPNEWPLAYER"),GfxR->fctPlayerClr.GetPhase(),"ActivateMenu:NewPlayer",C4MN_Item_NoCount,NULL,LoadResStr("IDS_MENU_CPNEWPLAYERINFO"));
	}
	// Save game (player menu only - should we allow saving games with no players in it?)
	/*
	if (pPlr && (!::Network.isEnabled() || ::Network.isHost()))
	{
		AddRefSym(LoadResStr("IDS_MENU_CPSAVEGAME"),GfxR->fctMenu.GetPhase(0),"ActivateMenu:Save:Game",C4MN_Item_NoCount,NULL,LoadResStr("IDS_MENU_CPSAVEGAMEINFO"));
	}*/
	// Options
	AddRefSym(LoadResStr("IDS_MNU_OPTIONS"), GfxR->fctOptions.GetPhase(0), "ActivateMenu:Options",C4MN_Item_NoCount, NULL, LoadResStr("IDS_MNU_OPTIONSINFO"));
	// Disconnect
	if (::Network.isEnabled())
	{
		// Host
		if (::Network.isHost() && Game.Clients.getClient(NULL))
			AddRefSym(LoadResStr("IDS_MENU_DISCONNECT"), C4GUI::Icon::GetIconFacet(C4GUI::Ico_Disconnect), "ActivateMenu:Host", C4MN_Item_NoCount, NULL, LoadResStr("IDS_TEXT_KICKCERTAINCLIENTSFROMTHE"));
		// Client
		if (!::Network.isHost())
			AddRefSym(LoadResStr("IDS_MENU_DISCONNECT"), C4GUI::Icon::GetIconFacet(C4GUI::Ico_Disconnect), "ActivateMenu:Client", C4MN_Item_NoCount, NULL, LoadResStr("IDS_TEXT_DISCONNECTTHEGAMEFROMTHES"));
	}
	// Surrender (player menu only)
	if (pPlr)
		AddRefSym(LoadResStr("IDS_MENU_CPSURRENDER"), C4GUI::Icon::GetIconFacet(C4GUI::Ico_Surrender), "ActivateMenu:Surrender", C4MN_Item_NoCount, NULL, LoadResStr("IDS_MENU_CPSURRENDERINFO"));
	// Abort
	if (!Application.isEditor)
		AddRefSym(LoadResStr("IDS_MENU_ABORT"), C4GUI::Icon::GetIconFacet(C4GUI::Ico_Exit), "Abort", C4MN_Item_NoCount, NULL, LoadResStr("IDS_MENU_ABORT_DESC"));
	// No empty menus
	if (GetItemCount()==0) Close(false);
	// Done
	return true;
}
Beispiel #10
0
bool C4MainMenu::DoRefillInternal(bool &rfRefilled)
{
	// Variables
	C4FacetSurface fctSymbol;
	C4Player *pPlayer;
	C4IDList ListItems;
	C4Facet fctTarget;
	bool fWasEmpty = !GetItemCount();

	// Refill
	switch (Identification)
	{
		// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	case C4MN_Hostility:
	{
		// Clear items
		ClearItems();
		// Refill player
		if (!(pPlayer = ::Players.Get(Player))) return false;
		// Refill items
		C4Player *pPlr; int32_t iIndex;
		for (iIndex=0; (pPlr = ::Players.GetByIndex(iIndex)); iIndex++)
			// Ignore player self and invisible
			if (pPlr != pPlayer) if (!pPlr->IsInvisible())
				{
					// Symbol
					fctSymbol.Create(C4SymbolSize,C4SymbolSize);
					pPlayer->DrawHostility(fctSymbol,iIndex);
					// Message
					StdStrBuf sMsg;
					bool isFriendly = pPlayer->Hostility.find(pPlr) == pPlayer->Hostility.end();
					if (isFriendly)
						sMsg.Format(LoadResStr("IDS_MENU_ATTACK"),pPlr->GetName());
					else
						sMsg.Format(LoadResStr("IDS_MENU_NOATTACK"),pPlr->GetName());
					// Command
					char szCommand[1000];
					sprintf(szCommand,"SetHostility:%i",pPlr->Number);
					// Info caption
					char szInfoCaption[C4MaxTitle+1],szFriendly[50],szNot[30]="";
					SCopy(LoadResStr(isFriendly ? "IDS_MENU_ATTACKHOSTILE" : "IDS_MENU_ATTACKFRIENDLY"),szFriendly);
					if (!isFriendly) SCopy(LoadResStr("IDS_MENU_ATTACKNOT"),szNot);
					sprintf(szInfoCaption,LoadResStr("IDS_MENU_ATTACKINFO"),pPlr->GetName(),szFriendly,szNot);
					if (iIndex==pPlayer->Number) SCopy(LoadResStr("IDS_MENU_ATTACKSELF"),szInfoCaption);
					// Add item
					Add(sMsg.getData(),fctSymbol,szCommand,C4MN_Item_NoCount,NULL,szInfoCaption);
					fctSymbol.Default();
				}
		break;
	}
	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	case C4MN_TeamSelection:
	case C4MN_TeamSwitch:
	{
		// Clear items
		ClearItems();
		// add all teams as menu items
		// 2do: Icon
		C4Team *pTeam; int32_t i=0; bool fAddNewTeam=Game.Teams.IsAutoGenerateTeams();
		for (;;)
		{
			pTeam = Game.Teams.GetTeamByIndex(i);
			if (pTeam)
			{
				// next regular team
				++i;
				// do not add a new team if an empty team exists
				if (!pTeam->GetPlayerCount()) fAddNewTeam = false;
			}
			else if (fAddNewTeam)
			{
				// join new team
				fAddNewTeam = false;
			}
			else
			{
				// all teams done
				break;
			}
			// create team symbol: Icon spec if specified; otherwise flag for empty and crew for nonempty team
			fctSymbol.Create(C4SymbolSize,C4SymbolSize);
			const char *szIconSpec = pTeam ? pTeam->GetIconSpec() : NULL;
			bool fHasIcon = false;
			if (szIconSpec && *szIconSpec)
			{
				fHasIcon = Game.DrawTextSpecImage(fctSymbol, szIconSpec, NULL, pTeam->GetColor());
			}
			if (!fHasIcon)
			{
				if (pTeam && pTeam->GetPlayerCount())
					::GraphicsResource.fctCrewClr.DrawClr(fctSymbol, true, pTeam->GetColor());
				else
					C4GUI::Icon::GetIconFacet(C4GUI::Ico_Team).Draw(fctSymbol, true);
			}
			StdStrBuf sTeamName;
			if (pTeam)
			{
				sTeamName.Take(pTeam->GetNameWithParticipants());
			}
			else
				sTeamName.Ref(LoadResStr("IDS_PRC_NEWTEAM"));
			const char *szOperation = (Identification == C4MN_TeamSwitch) ? "TeamSwitch" : "TeamSel";
			Add(sTeamName.getData(), fctSymbol,FormatString("%s:%d", szOperation, pTeam ? pTeam->GetID() : TEAMID_New).getData(),
			    C4MN_Item_NoCount,NULL,FormatString(LoadResStr("IDS_MSG_JOINTEAM"), sTeamName.getData()).getData(), C4ID(pTeam ? pTeam->GetID() : 0));
			fctSymbol.Default();
		}
		break;
	}
	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	case C4MN_Observer: // observer menu
	{
		// Clear items
		ClearItems();
		// Check validity
		C4Viewport *pVP = ::Viewports.GetViewport(NO_OWNER);
		if (!pVP) return false;
		int32_t iInitialSelection = 0;
		// Add free view
		AddRefSym(LoadResStr("IDS_MSG_FREEVIEW"), C4GUI::Icon::GetIconFacet(C4GUI::Ico_Star), "Observe:Free", C4MN_Item_NoCount, NULL, LoadResStr("IDS_MSG_FREELYSCROLLAROUNDTHEMAP"));
		// Add players
		C4Player *pPlr; int32_t iIndex;
		for (iIndex=0; (pPlr = ::Players.GetByIndex(iIndex)); iIndex++)
		{
			// Ignore invisible
			if (!pPlr->IsInvisible())
			{
				// Symbol
				fctSymbol.Create(C4SymbolSize,C4SymbolSize);
				::GraphicsResource.fctPlayerClr.DrawClr(fctSymbol, true, pPlr->ColorDw);
				// Message
				StdStrBuf sMsg;
				DWORD dwClr = pPlr->ColorDw;
				sMsg.Format("<c %x>%s</c>", (unsigned int)C4GUI::MakeColorReadableOnBlack(dwClr), pPlr->GetName());
				// Command
				StdStrBuf sCommand;
				sCommand.Format("Observe:%d", (int)pPlr->Number);
				// Info caption
				StdStrBuf sInfo;
				sInfo.Format(LoadResStr("IDS_TEXT_FOLLOWVIEWOFPLAYER"), pPlr->GetName());
				// Add item
				Add(sMsg.getData(),fctSymbol,sCommand.getData(),C4MN_Item_NoCount,NULL,sInfo.getData());
				fctSymbol.Default();
				// check if this is the currently selected player
				if (pVP->GetPlayer() == pPlr->Number) iInitialSelection = GetItemCount()-1;
			}
			// Initial selection on followed player
			if (fWasEmpty) SetSelection(iInitialSelection, false, true);
		}
	}
	break;
	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	default:
		// No internal refill needed
		return true;
		// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	}

	// Successfull internal refill
	rfRefilled = true;
	return true;
}