Пример #1
0
void C4MenuItem::DoTextProgress(int32_t &riByVal)
{
	// any progress to be done?
	if (TextDisplayProgress<0) return;
	// if this is an option or empty text, show it immediately
	if (IsSelectable || !*Caption) { TextDisplayProgress=-1; return; }
	// normal text: move forward in unbroken message, ignoring markup
	StdStrBuf sText(Caption);
	C4Markup MarkupChecker(false);
	const char *szPos = sText.getPtr(std::min<int>(TextDisplayProgress, sText.getLength()));
	while (riByVal && *szPos)
	{
		MarkupChecker.SkipTags(&szPos);
		if (!*szPos) break;
		--riByVal;

		// Advance one UTF-8 character
		uint32_t c = GetNextCharacter(&szPos);
		// Treat embedded images {{XXX}} as one entity
		if(c == '{' && *szPos == '{')
		{
			int32_t end = SCharPos('}', szPos);
			if(end > 0 && szPos[end+1] == '}')
				szPos += end + 2;
		}
	}
	if (!*szPos)
		TextDisplayProgress=-1;
	else
		TextDisplayProgress = szPos - Caption;
}
Пример #2
0
bool C4GameSave::SaveScenarioSections()
{
	// any scenario sections?
	if (!Game.pScenarioSections) return true;
	// prepare section filename
	int iWildcardPos = SCharPos('*', C4CFN_ScenarioSections);
	char fn[_MAX_FNAME+1];
	// save all modified sections
	for (C4ScenarioSection *pSect = Game.pScenarioSections; pSect; pSect = pSect->pNext)
	{
		// compose section filename
		SCopy(C4CFN_ScenarioSections, fn);
		SDelete(fn, 1, iWildcardPos); SInsert(fn, pSect->name.getData(), iWildcardPos);
		// do not save self, because that is implied in CurrentScenarioSection and the main landscape/object data
		if (pSect == Game.pCurrentScenarioSection)
			pSaveGroup->DeleteEntry(fn);
		else if (pSect->fModified)
		{
			// modified section: delete current
			pSaveGroup->DeleteEntry(fn);
			// replace by new
			pSaveGroup->Add(pSect->temp_filename.getData(), fn);
		}
	}
	// done, success
	return true;
}
Пример #3
0
void C4GraphicsOverlay::Read(const char **ppInput)
{
	// deprecated
	assert(false && "C4GraphicsOverlay::Read: deprecated");
#if 0
	const char *szReadFrom = *ppInput;
	// defaults
	eMode = MODE_None; pSourceGfx = NULL; *Action=0; dwBlitMode = 0; iPhase = 0; iID=0;
	// read ID
	SCopyUntil(szReadFrom, OSTR, ',', C4MaxName);
	szReadFrom += strlen(OSTR); if (*szReadFrom) ++szReadFrom;
	sscanf(OSTR, "%i", &iID);
	// read C4ID::Gfxname
	int32_t iLineLength = SLen(szReadFrom);
	// not C4ID::Name?
	if (iLineLength < 6 || szReadFrom[4]!=':' || szReadFrom[5]!=':')
	{
		DebugLog("C4Compiler error: Malformed graphics overlay definition!");
		return;
	}
	// get ID
	char id[5]; SCopy(szReadFrom, id, 4); szReadFrom += 6;
	C4Def *pSrcDef = ::Definitions.ID2Def(C4Id(id)); // defaults to NULL for unloaded def
	if (pSrcDef)
	{
		char GfxName[C4MaxName+1];
		SCopyUntil(szReadFrom, GfxName, ',', C4MaxName);
		szReadFrom += strlen(GfxName); if (*szReadFrom) ++szReadFrom;
		// get graphics - "C4ID::" leads to *szLine == NULL, and thus the default graphic of pSrcDef!
		pSourceGfx = pSrcDef->Graphics.Get(GfxName);
	}
	// read mode
	DWORD dwRead;
	SCopyUntil(szReadFrom, OSTR, ',', C4MaxName);
	szReadFrom += strlen(OSTR); if (*szReadFrom) ++szReadFrom;
	sscanf(OSTR, "%i", &dwRead); eMode = (Mode) dwRead;
	// read action
	SCopyUntil(szReadFrom, Action, ',', C4MaxName);
	szReadFrom += strlen(Action); if (*szReadFrom) ++szReadFrom;
	// read blit mode
	SCopyUntil(szReadFrom, OSTR, ',', C4MaxName);
	szReadFrom += strlen(OSTR); if (*szReadFrom) ++szReadFrom;
	sscanf(OSTR, "%i", &dwBlitMode);
	// read phase
	SCopyUntil(szReadFrom, OSTR, ',', C4MaxName);
	szReadFrom += strlen(OSTR); if (*szReadFrom) ++szReadFrom;
	sscanf(OSTR, "%i", &iPhase);
	// read transform
	if (*szReadFrom) ++szReadFrom; // '('
	int32_t iScanCnt = sscanf(szReadFrom, "%f,%f,%f,%f,%f,%f,%d",
	                          &Transform.mat[0], &Transform.mat[1], &Transform.mat[2],
	                          &Transform.mat[3], &Transform.mat[4], &Transform.mat[5], &Transform.FlipDir);
	if (iScanCnt != 7) { DebugLog("C4Compiler: malformed C4CV_Transform"); }
	iScanCnt = SCharPos(')', szReadFrom); if (iScanCnt>=0) szReadFrom += iScanCnt+1;
	// assign ptr immediately after read overlay
	*ppInput = szReadFrom;
	// update used facet according to read data
	UpdateFacet();
#endif
}
Пример #4
0
int32_t C4TextureMap::LoadMap(C4Group &hGroup, const char *szEntryName, BOOL *pOverloadMaterials, BOOL *pOverloadTextures)
  {
  char *bpMap;
  char szLine[100+1];
  int32_t cnt, iIndex, iTextures = 0;
  // Load text file into memory
  if (!hGroup.LoadEntry(szEntryName,&bpMap,NULL,1)) return 0;
  // Scan text buffer lines       
  for (cnt=0; SCopySegment(bpMap,cnt,szLine,0x0A,100); cnt++)
    if ( (szLine[0]!='#') && (SCharCount('=',szLine)==1) )
      {
      SReplaceChar(szLine,0x0D,0x00);
			if (Inside<int32_t>( iIndex = strtol(szLine,NULL,10), 0, C4M_MaxTexIndex-1 ))
				{
				const char *szMapping = szLine+SCharPos('=',szLine)+1;
				StdStrBuf Material, Texture;
				Material.CopyUntil(szMapping, '-'); Texture.Copy(SSearch(szMapping, "-"));
				if (AddEntry(iIndex, Material.getData(), Texture.getData()))
					iTextures++;
				}
      }
		else
			{
			if (SEqual2(szLine, "OverloadMaterials")) { fOverloadMaterials = TRUE; if(pOverloadMaterials) *pOverloadMaterials = TRUE; }
			if (SEqual2(szLine, "OverloadTextures")) { fOverloadTextures = TRUE;  if(pOverloadTextures) *pOverloadTextures = TRUE; }
			}
  // Delete buffer, return entry count
  delete [] bpMap;
	fEntriesAdded=false;
  return iTextures;
  }
Пример #5
0
bool C4ComponentHost::GetLanguageString(const char *szLanguage,
                                        StdStrBuf &rTarget) {
  const char *cptr;
  // No good parameters
  if (!szLanguage || !Data) return false;
  // Search for two-letter language identifier in text body, i.e. "DE:"
  char langindex[4] = "";
  for (int clseg = 0;
       SCopySegment(szLanguage ? szLanguage : "", clseg, langindex, ',', 2);
       clseg++) {
    SAppend(":", langindex);
    if (cptr = SSearch(Data.getData(), langindex)) {
      // Return the according string
      int iEndPos = SCharPos('\r', cptr);
      if (iEndPos < 0) iEndPos = SCharPos('\n', cptr);
      if (iEndPos < 0) iEndPos = strlen(cptr);
      rTarget.Copy(cptr, iEndPos);
      return true;
    }
  }
  // Language string not found
  return false;
}
Пример #6
0
bool FnParTexCol(C4String *mattex, uint8_t& fg, uint8_t& bg)
{
	// Return index of material-texture definition for a single color
	// Defaults to underground (tunnel background) color. Prefix material with ^ to get overground (sky background) color,
	// or specify as mattex1:mattex2 for foreground-background pair.
	if (!mattex || !mattex->GetCStr()) return false;

	int sep_pos = SCharPos(':', mattex->GetCStr());
	if (sep_pos == -1)
	{
		const char *cmattex = mattex->GetCStr();
		bool ift = true;
		if (*cmattex == '^') { ift=false; ++cmattex; }
		
		uint8_t col;
		if (!TexColSingle(cmattex, col)) return false;

		fg = col;
		if (ift)
			bg = ::MapScript.pTexMap->DefaultBkgMatTex(fg);
		else
			bg = C4M_MaxTexIndex; // sky

		return true;
	}
	else
	{
		const char *cmattex = mattex->GetCStr();
		std::string fg_mattex(cmattex, cmattex + sep_pos);
		std::string bg_mattex(cmattex + sep_pos + 1);

		uint8_t fg_col, bg_col;
		if (!TexColSingle(fg_mattex.c_str(), fg_col)) return false;
		if (!TexColSingle(bg_mattex.c_str(), bg_col)) return false;

		fg = fg_col; bg = bg_col;
		return true;
	}
}
bool C4DefGraphics::Load(C4Group &hGroup, StdMeshSkeletonLoader &loader, bool fColorByOwner)
{
	char Filename[_MAX_PATH+1]; *Filename=0;

	// load skeletons
	hGroup.ResetSearch();
	while (hGroup.FindNextEntry("*", Filename, NULL, !!*Filename))
	{
		if (!WildcardMatch(C4CFN_DefSkeleton, Filename) && !WildcardMatch(C4CFN_DefSkeletonXml, Filename)) continue;
		LoadSkeleton(hGroup, Filename, loader);
	}

	// Try from Mesh first
	if (!LoadMesh(hGroup, C4CFN_DefMesh, loader))
		if(!LoadMesh(hGroup, C4CFN_DefMeshXml, loader))
			LoadBitmap(hGroup, C4CFN_DefGraphics, C4CFN_ClrByOwner, C4CFN_NormalMap, fColorByOwner);

	// load additional graphics
	C4DefGraphics *pLastGraphics = this;
	const int32_t iOverlayWildcardPos = SCharPos('*', C4CFN_ClrByOwnerEx);
	hGroup.ResetSearch(); *Filename=0;
	const char* const AdditionalGraphics[] = { C4CFN_DefGraphicsEx, C4CFN_DefGraphicsExMesh, C4CFN_DefGraphicsExMeshXml, NULL };
	while (hGroup.FindNextEntry("*", Filename, NULL, !!*Filename))
	{
		for(const char* const* szWildcard = AdditionalGraphics; *szWildcard != NULL; ++szWildcard)
		{
			if(!WildcardMatch(*szWildcard, Filename)) continue;
			// skip def graphics
			if (SEqualNoCase(Filename, C4CFN_DefGraphics) || SEqualNoCase(Filename, C4CFN_DefMesh) || SEqualNoCase(Filename, C4CFN_DefMeshXml)) continue;
			// skip scaled def graphics
			if (WildcardMatch(C4CFN_DefGraphicsScaled, Filename)) continue;
			// get name
			char GrpName[_MAX_PATH+1];
			const int32_t iWildcardPos = SCharPos('*', *szWildcard);
			SCopy(Filename + iWildcardPos, GrpName, _MAX_PATH);
			RemoveExtension(GrpName);
			// remove trailing number for scaled graphics
			int32_t extpos; int scale;
			if ((extpos = SCharLastPos('.', GrpName)) > -1)
				if (sscanf(GrpName+extpos+1, "%d", &scale) == 1)
					GrpName[extpos] = '\0';
			// clip to max length
			GrpName[C4MaxName]=0;
			// create new graphics
			pLastGraphics->pNext = new C4AdditionalDefGraphics(pDef, GrpName);
			pLastGraphics = pLastGraphics->pNext;
			if(*szWildcard == AdditionalGraphics[0])
			{
				// create overlay-filename
				char OverlayFn[_MAX_PATH+1];
				if(fColorByOwner)
				{
					// GraphicsX.png -> OverlayX.png
					SCopy(C4CFN_ClrByOwnerEx, OverlayFn, _MAX_PATH);
					OverlayFn[iOverlayWildcardPos]=0;
					SAppend(Filename + iWildcardPos, OverlayFn);
					EnforceExtension(OverlayFn, GetExtension(C4CFN_ClrByOwnerEx));
				}

				// create normal filename
				char NormalFn[_MAX_PATH+1];
				SCopy(C4CFN_NormalMapEx, NormalFn, _MAX_PATH);
				NormalFn[iOverlayWildcardPos]=0;
				SAppend(Filename + iWildcardPos, NormalFn);
				EnforceExtension(NormalFn, GetExtension(C4CFN_NormalMapEx));

				// load them
				if (!pLastGraphics->LoadBitmap(hGroup, Filename, fColorByOwner ? OverlayFn : NULL, NormalFn, fColorByOwner))
					return false;
			}
			else
			{
				if (!pLastGraphics->LoadMesh(hGroup, Filename, loader))
					return false;
			}
		}
	}
	// done, success
	return true;
}
Пример #8
0
bool C4RankSystem::Load(C4Group &hGroup, const char *szFilenames, int DefRankBase, const char *szLanguage)
	{
	// clear any loaded rank names
	Clear();
	assert(szFilenames); assert(szLanguage);
	// load new
	C4ComponentHost Ranks;
	if (!Ranks.LoadEx("Ranks", hGroup, szFilenames, szLanguage)) return false;
	size_t iSize = Ranks.GetDataSize();
	if (!iSize) return false;
	szRankNames=new char[iSize+1];
	memcpy(szRankNames, Ranks.GetData(), iSize * sizeof(char));
	szRankNames[iSize]=0;
	Ranks.Close();
	// replace line breaks by zero-chars
	unsigned int i=0;
	for (; i<iSize; ++i)
		if (szRankNames[i] == 0x0A || szRankNames[i] == 0x0D) szRankNames[i]=0;
	// count names
	char *pRank0=szRankNames, *pPos=szRankNames;
	for (i=0; i<iSize; ++i,++pPos)
		if (!*pPos)
			{
			// zero-character found: content?
			if (pPos-pRank0>0)
				{
				// rank extension?
				if (*pRank0 == '*')
					++iRankExtNum;
				// no comment?
				else if (*pRank0 != '#')
					// no setting?
					if (SCharPos('=', pRank0) < 0)
						// count as name!
						++iRankNum;
				}
			// advance pos
			pRank0=pPos+1;
			}
	// safety
	if (!iRankNum) { Clear(); return false; }
	// set default rank base
	RankBase=DefRankBase;
	// alloc lists
	pszRankNames = new char *[iRankNum];
	if (iRankExtNum) pszRankExtensions = new char *[iRankExtNum];
	// fill list with names
	// count names
	pRank0=szRankNames; pPos=szRankNames;
	char **pszCurrRank=pszRankNames;
	char **pszCurrRankExt=pszRankExtensions;
	for (i=0; i<iSize; ++i,++pPos)
		if (!*pPos)
			{
			// zero-character found: content?
			if (pPos-pRank0>0)
				// extension?
				if (*pRank0 == '*')
					{
					*pszCurrRankExt++ = pRank0+1;
					}
				// no comment?
				else if (*pRank0 != '#')
					{
					// check if it's a setting
					int iEqPos=SCharPos('=', pRank0);
					if (iEqPos >= 0)
						{
						// get name and value of setting
						pRank0[iEqPos]=0; char *szValue=pRank0+iEqPos+1;
						if (SEqual(pRank0, "Base"))
							// get rankbase
							// note that invalid numbers may cause desyncs here...not very likely though :)
							sscanf(szValue, "%d", &RankBase);
						}
					else
						// yeeehaa! it's a name! store it, store it!
						*pszCurrRank++=pRank0;
					}
			// advance pos
			pRank0=pPos+1;
			}
	// check rankbase
	if (!RankBase) RankBase=1000;
	// ranks read, success
	return true;
	}
Пример #9
0
bool C4MusicFileOgg::Init(const char *strFile)
{
	// Clear previous
	Clear();
	// Base init file
	if (!C4MusicFile::Init(strFile)) return false;
	// Initial file loading
	// Currently, the whole compressed file is kept in memory because reading/seeking inside C4Group is problematic. Uncompress while playing.
	// This uses about 50MB of RAM (for ala's music pack) and increases startup time a bit.
	// Later, this could be replaced with proper random access in c4group. Either replacing the file format or e.g. storing the current zlib state here
	//  and then updating callbacks.read/seek/close/tell_func to read data from the group directly as needed
	char *file_contents;
	size_t file_size;
	if (!C4Group_ReadFile(FileName, &file_contents, &file_size))
		return false;
	data.SetOwnedData((BYTE *)file_contents, file_size);

	// Prepare ogg reader
	vorbis_info* info;
	memset(&ogg_file, 0, sizeof(ogg_file));
	ov_callbacks callbacks;
	callbacks.read_func = &::C4SoundLoaders::VorbisLoader::read_func;
	callbacks.seek_func = &::C4SoundLoaders::VorbisLoader::seek_func;
	callbacks.close_func = &::C4SoundLoaders::VorbisLoader::close_func;
	callbacks.tell_func = &::C4SoundLoaders::VorbisLoader::tell_func;

	// open using callbacks
	if (ov_open_callbacks(&data, &ogg_file, NULL, 0, callbacks) != 0)
	{
		ov_clear(&ogg_file);
		return false;
	}

	// get information about music
	info = ov_info(&ogg_file, -1);
	if (info->channels == 1)
		ogg_info.format = AL_FORMAT_MONO16;
	else
		ogg_info.format = AL_FORMAT_STEREO16;
	ogg_info.sample_rate = info->rate;
	ogg_info.sample_length = ov_time_total(&ogg_file, -1) / 1000.0;
	
	// Get categories from ogg comment header
	vorbis_comment *comment = ov_comment(&ogg_file, -1);
	const char *comment_id = "COMMENT=";
	int comment_id_len = strlen(comment_id);
	for (int i = 0; i < comment->comments; ++i)
	{
		if (comment->comment_lengths[i] > comment_id_len)
		{
			if (SEqual2NoCase(comment->user_comments[i], comment_id, comment_id_len))
			{
				// Add all categories delimeted by ';'
				const char *categories_string = comment->user_comments[i] + comment_id_len;
				for (;;)
				{
					int delimeter = SCharPos(';', categories_string);
					StdCopyStrBuf category;
					category.Copy(categories_string, delimeter >= 0 ? delimeter : SLen(categories_string));
					categories.push_back(category);
					if (delimeter < 0) break;
					categories_string += delimeter+1;
				}
			}
		}
	}

	// mark successfully loaded
	return loaded = true;
}
Пример #10
0
bool C4MainMenu::MenuCommand(const char *szCommand, bool fIsCloseCommand)
{
	// Determine player
	C4Player *pPlr = ::Players.Get(Player);
	// Activate
	if (SEqual2(szCommand,"ActivateMenu:"))
	{
		if (C4GameOverDlg::IsShown()) return false; // no new menus during game over dlg
		if (SEqual(szCommand+13,"Main")) return ActivateMain(Player);
		if (SEqual(szCommand+13,"Hostility")) return ActivateHostility(Player);
		if (SEqual(szCommand+13,"NewPlayer")) return ActivateNewPlayer(Player);
		if (SEqual(szCommand+13,"Goals"))
		{
			::Control.DoInput(CID_PlrAction, C4ControlPlayerAction::ActivateGoalMenu(::Players.Get(Player)), CDT_Queue);
			return true;
		}
		if (SEqual(szCommand+13,"Rules")) return ActivateRules(Player);
		if (SEqual(szCommand+13,"Host")) return ActivateHost(Player);
		if (SEqual(szCommand+13,"Client")) return ActivateClient(Player);
		if (SEqual(szCommand+13,"Options")) return ActivateOptions(Player);
		if (SEqual(szCommand+13,"Display")) return ActivateDisplay(Player);
		if (SEqual(szCommand+13,"Save:Game")) return ActivateSavegame(Player);
		if (SEqual(szCommand+13,"TeamSel")) return pPlr ? pPlr->ActivateMenuTeamSelection(true) : false;
		if (SEqual(szCommand+13,"Surrender")) return ActivateSurrender(Player);
		if (SEqual(szCommand+13,"Observer")) return ActivateObserver();
	}
	// JoinPlayer
	if (SEqual2(szCommand,"JoinPlayer:"))
	{
		// not in league or replay mode
		if (Game.Parameters.isLeague() || Game.C4S.Head.Replay) return false;
		// join player
		// 2do: not for observers and such?
		Players.JoinNew(szCommand+11);
		return true;
	}
	// SetHostility
	if (SEqual2(szCommand,"SetHostility:"))
	{
		// only if allowed
		if (!Game.Teams.IsHostilityChangeAllowed()) return false;
		int32_t iOpponent; sscanf(szCommand+13,"%i",&iOpponent);
		C4Player *pOpponent = ::Players.Get(iOpponent);
		if (!pOpponent || pOpponent->GetType() != C4PT_User) return false;
		::Control.DoInput(CID_PlrAction, C4ControlPlayerAction::SetHostility(::Players.Get(Player), pOpponent, !::Players.HostilityDeclared(Player, pOpponent->Number)), CDT_Queue);
		return true;
	}
	// Abort
	if (SEqual2(szCommand,"Abort"))
	{
		FullScreen.ShowAbortDlg();
		return true;
	}
	// Surrender
	if (SEqual2(szCommand,"Surrender"))
	{
		::Control.DoInput(CID_PlrAction, C4ControlPlayerAction::Surrender(::Players.Get(Player)), CDT_Queue);
		return true;
	}
	// Save game
	if (SEqual2(szCommand, "Save:Game:"))
	{
		char strFilename[_MAX_PATH + 1]; SCopySegment(szCommand, 2, strFilename, ':', _MAX_PATH);
		char strTitle[_MAX_PATH + 1]; SCopy(szCommand + SCharPos(':', szCommand, 2) + 1, strTitle, _MAX_PATH);
		Game.QuickSave(strFilename, strTitle);
		ActivateSavegame(Player);
		return true;
	}
	// Kick
	if (SEqual2(szCommand,"Host:Kick:"))
	{
		int iClientID = atoi(szCommand+10);
		if (iClientID && ::Network.isEnabled())
		{
			if (Game.Parameters.isLeague() && ::Players.GetAtClient(iClientID))
				::Network.Vote(VT_Kick, true, iClientID);
			else
			{
				C4Client *pClient = Game.Clients.getClientByID(iClientID);
				if (pClient) Game.Clients.CtrlRemove(pClient, LoadResStr("IDS_MSG_KICKBYMENU"));
				Close(true);
			}
		}
		return true;
	}
	// Part
	if (SEqual2(szCommand,"Part"))
	{
		if (::Network.isEnabled())
		{
			if (Game.Parameters.isLeague() && ::Players.GetLocalByIndex(0))
				::Network.Vote(VT_Kick, true, ::Control.ClientID());
			else
			{
				Game.RoundResults.EvaluateNetwork(C4RoundResults::NR_NetError, LoadResStr("IDS_ERR_GAMELEFTVIAPLAYERMENU"));
				::Network.Clear();
			}
		}
		return true;
	}
	// Options
	if (SEqual2(szCommand,"Options:"))
	{
		// Music
		if (SEqual(szCommand + 8, "Music"))
		{
			Application.MusicSystem.ToggleOnOff();
		}
		// Sound
		if (SEqual(szCommand + 8, "Sound"))
		{
			if (Config.Sound.RXSound)
			{
				Application.SoundSystem.Clear();
				Config.Sound.RXSound = false;
			}
			else
			{
				Config.Sound.RXSound = true;
				if (!Application.SoundSystem.Init())
					{ Log(LoadResStr("IDS_PRC_NOSND")); }
			}
		}
		// Reopen with updated options
		ActivateOptions(Player, GetSelection());
		return true;
	}
	// Display
	if (SEqual2(szCommand,"Display:"))
	{
		// Upper board
		if (SEqual(szCommand + 8, "UpperBoard"))
		{
			Config.Graphics.UpperBoard = !Config.Graphics.UpperBoard;
			::Viewports.RecalculateViewports();
		}
		// FPS
		if (SEqual(szCommand + 8, "FPS")) Config.General.FPS = !Config.General.FPS;
		// Player names
		if (SEqual(szCommand + 8, "PlayerNames")) Config.Graphics.ShowCrewNames = !Config.Graphics.ShowCrewNames;
		// Clonk names
		if (SEqual(szCommand + 8, "ClonkNames")) Config.Graphics.ShowCrewCNames = !Config.Graphics.ShowCrewCNames;
		// Clock
		if (SEqual(szCommand + 8, "Clock")) Config.Graphics.ShowClock = !Config.Graphics.ShowClock;
		// Reopen with updated options
		ActivateDisplay(Player, GetSelection());
		return true;
	}
	// Goal info
	if (SEqual2(szCommand,"Player:Goal:") || SEqual2(szCommand,"Player:Rule:"))
	{
		if (!ValidPlr(Player)) return false; // observers may not look at goal/rule info, because it requires queue activation
		Close(true);
		C4Object *pObj; C4ID idItem(szCommand+12); C4Def * pDef = C4Id2Def(idItem);
		if (pDef && (pObj = ::Objects.Find(pDef)))
			::Control.DoInput(CID_PlrAction, C4ControlPlayerAction::ActivateGoal(::Players.Get(Player), pObj), CDT_Queue);
		else
			return false;
		return true;
	}
	// Team selection
	if (SEqual2(szCommand, "TeamSel:"))
	{
		Close(true);
		int32_t idTeam = atoi(szCommand+8);

		// OK, join this team
		if (pPlr) pPlr->DoTeamSelection(idTeam);
		return true;
	}
	// Team switch
	if (SEqual2(szCommand, "TeamSwitch:"))
	{
		Close(true);
		int32_t idTeam = atoi(szCommand+11);

		// check if it's still allowed
		if (!Game.Teams.IsTeamSwitchAllowed()) return false;
		// OK, join this team
		::Control.DoInput(CID_PlrAction, C4ControlPlayerAction::SetTeam(::Players.Get(Player), idTeam), CDT_Queue);
		return true;
	}
	// Observe
	if (SEqual2(szCommand, "Observe:"))
	{
		const char *szObserverTarget = szCommand+8;
		C4Viewport *pVP = ::Viewports.GetViewport(NO_OWNER);
		if (pVP) // viewport may have closed meanwhile
		{
			if (SEqual(szObserverTarget, "Free"))
			{
				// free view
				pVP->Init(NO_OWNER, true);
				return true;
			}
			else
			{
				// view following player
				int32_t iPlr = atoi(szObserverTarget);
				if (ValidPlr(iPlr))
				{
					pVP->Init(iPlr, true);
					return true;
				}
			}
		}
		return false;
	}
	// No valid command
	return false;
}
Пример #11
0
bool C4Markup::Read(const char **ppText, bool fSkip)
{
	char Tag[50]; C4MarkupTag *pNewTag=nullptr; int iTagLen,iParLen;
	// get tag
	if (!SCopyEnclosed(*ppText, '<', '>', Tag, 49)) return false;
	iTagLen=SLen(Tag);
	// split tag to name and pars
	char *szPars=nullptr; int iSPos;
	if ((iSPos=SCharPos(' ', Tag))>-1)
	{
		Tag[iSPos]=0;
		szPars=Tag+iSPos+1;
	}
	// closing tag?
	if (Tag[0]=='/')
	{
		// no parameters
		if (szPars) return false;
		if (!fSkip)
		{
			// is this the tag to be closed?
			if (!pLast) return false;
			if (!SEqual(pLast->TagName(), Tag+1)) return false;
			// close it
			delete Pop();
		}
	}
	// italic
	else if (SEqual(Tag, "i"))
	{
		// no parameters
		if (szPars) return false;
		// create italic tag
		if (!fSkip) pNewTag=new C4MarkupTagItalic();
	}
	// colored
	else if (SEqual(Tag, "c"))
	{
		// no parameters?
		if (!szPars) return false;
		if ((iParLen=SLen(szPars))>8) return false;
		if (!fSkip)
		{
			// get color value by parameter
			DWORD dwClr=0;
			for (int i=0; i<iParLen; ++i)
			{
				BYTE b;
				if (szPars[i]>='0' && szPars[i]<='9') b=szPars[i]-'0';
				else if (szPars[i]>='a' && szPars[i]<='f') b=szPars[i]-'a'+10;
				else return false;
				dwClr|=(b<<((iParLen-i-1)*4));
			}
			// adjust alpha if not given
			if (iParLen<=6) dwClr|=0xff000000;
			// create color tag
			pNewTag=new C4MarkupTagColor(dwClr);
		}
	}
	// unknown tag
	else return false;
	// add created tag
	if (pNewTag) Push(pNewTag);
	// advance past tag
	*ppText+=iTagLen+2;
	// success
	return true;
}