OpenClonk
C4RankSystem.cpp
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 1998-2000, Matthes Bender
5  * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
6  * Copyright (c) 2009-2016, The OpenClonk Team and contributors
7  *
8  * Distributed under the terms of the ISC license; see accompanying file
9  * "COPYING" for details.
10  *
11  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
12  * See accompanying file "TRADEMARK" for details.
13  *
14  * To redistribute this file separately, substitute the full license texts
15  * for the above references.
16  */
17 
18 /* Rank list for players or crew members */
19 
20 #include "C4Include.h"
21 #include "player/C4RankSystem.h"
22 
24 #include "c4group/C4Group.h"
25 #include "graphics/C4FacetEx.h"
27 
28 #include "platform/StdRegistry.h"
29 
31 {
32  Default();
33 }
34 
35 int C4RankSystem::Init(const char *szRegister,
36  const char *szDefRanks,
37  int iRankBase)
38 {
39 
40  // Init
41  SCopy(szRegister,Register,256);
42  RankBase=iRankBase;
43 
44  // Check registry for present rank names and set defaults
45 #ifdef _WIN32
46  int crank=0;
47  char keyname[30];
48  StdCopyStrBuf rankname;
49  bool Checking=true;
50  while (Checking)
51  {
52  sprintf(keyname,"Rank%03d",crank+1);
53  rankname = GetRegistryString(Register,keyname);
54  if (!rankname.isNull())
55  {
56  // Rank present
57  crank++;
58  }
59  else
60  {
61  // Rank not defined, check for default
62  rankname.AppendChars('\0', C4MaxName);
63  if (SCopySegment(szDefRanks,crank,rankname.getMData(),'|',C4MaxName)
64  && SetRegistryString(Register,keyname,rankname.getData()))
65  crank++;
66  else
67  Checking=false;
68  }
69  }
70  return crank;
71 #else
72  // clear any loaded rank names
73  Clear();
74  if (!szDefRanks) return 0;
75  // make a copy
76  szRankNames = new char[strlen(szDefRanks) + 1];
77  strcpy (szRankNames, szDefRanks);
78  // split into substrings by replacing the | with zeros
79  for (char * p = szRankNames; *p; ++p) if (*p == '|')
80  {
81  *p = 0;
82  ++iRankNum;
83  }
84  ++ iRankNum; // The last rank is already terminated by zero
85  // build a list of substrings
86  pszRankNames = new char *[iRankNum];
87  char * p = szRankNames;
88  for (int i = 0; i < iRankNum; ++i)
89  {
90  pszRankNames[i] = p;
91  p += strlen(p) + 1;
92  }
93  return iRankNum;
94 #endif
95 }
96 
97 bool C4RankSystem::Load(C4Group &hGroup, const char *szFilenames, int DefRankBase, const char *szLanguage)
98 {
99  // clear any loaded rank names
100  Clear();
101  assert(szFilenames); assert(szLanguage);
102  // load new
103  C4ComponentHost Ranks;
104  if (!C4Language::LoadComponentHost(&Ranks, hGroup, szFilenames, szLanguage)) return false;
105  size_t iSize = Ranks.GetDataSize();
106  if (!iSize) return false;
107  szRankNames=new char[iSize+1];
108  memcpy(szRankNames, Ranks.GetData(), iSize * sizeof(char));
109  szRankNames[iSize]=0;
110  // replace line breaks by zero-chars
111  unsigned int i=0;
112  for (; i<iSize; ++i)
113  if (szRankNames[i] == 0x0A || szRankNames[i] == 0x0D) szRankNames[i]=0;
114  // count names
115  char *pRank0=szRankNames, *pPos=szRankNames;
116  for (i=0; i<iSize; ++i,++pPos)
117  if (!*pPos)
118  {
119  // zero-character found: content?
120  if (pPos-pRank0>0)
121  {
122  // rank extension?
123  if (*pRank0 == '*')
124  ++iRankExtNum;
125  // no comment?
126  else if (*pRank0 != '#')
127  // no setting?
128  if (SCharPos('=', pRank0) < 0)
129  // count as name!
130  ++iRankNum;
131  }
132  // advance pos
133  pRank0=pPos+1;
134  }
135  // safety
136  if (!iRankNum) { Clear(); return false; }
137  // set default rank base
138  RankBase=DefRankBase;
139  // alloc lists
140  pszRankNames = new char *[iRankNum];
141  if (iRankExtNum) pszRankExtensions = new char *[iRankExtNum];
142  // fill list with names
143  // count names
144  pRank0=szRankNames; pPos=szRankNames;
145  char **pszCurrRank=pszRankNames;
146  char **pszCurrRankExt=pszRankExtensions;
147  for (i=0; i<iSize; ++i,++pPos)
148  if (!*pPos)
149  {
150  // zero-character found: content?
151  if (pPos-pRank0>0)
152  {
153  // extension?
154  if (*pRank0 == '*')
155  {
156  *pszCurrRankExt++ = pRank0+1;
157  }
158  // no comment?
159  else if (*pRank0 != '#')
160  {
161  // check if it's a setting
162  int iEqPos=SCharPos('=', pRank0);
163  if (iEqPos >= 0)
164  {
165  // get name and value of setting
166  pRank0[iEqPos]=0; char *szValue=pRank0+iEqPos+1;
167  if (SEqual(pRank0, "Base"))
168  // get rankbase
169  // note that invalid numbers may cause desyncs here...not very likely though :)
170  sscanf(szValue, "%d", &RankBase);
171  }
172  else
173  // yeeehaa! it's a name! store it, store it!
174  *pszCurrRank++=pRank0;
175  }
176  }
177  // advance pos
178  pRank0=pPos+1;
179  }
180  // check rankbase
181  if (!RankBase) RankBase=1000;
182  // ranks read, success
183  return true;
184 }
185 
186 StdStrBuf C4RankSystem::GetRankName(int iRank, bool fReturnLastIfOver)
187 {
188  if (iRank<0) return StdStrBuf();
189  // if a new-style ranklist is loaded, seek there
190  if (pszRankNames)
191  {
192  if (iRankNum<=0) return StdStrBuf();
193  // overflow check
194  if (iRank>=iRankNum*(iRankExtNum+1))
195  {
196  // rank undefined: Fallback to last rank
197  if (!fReturnLastIfOver) return StdStrBuf();
198  iRank = iRankNum*(iRankExtNum+1)-1;
199  }
200  StdStrBuf sResult;
201  if (iRank >= iRankNum)
202  {
203  // extended rank composed of two parts
204  int iExtension = iRank / iRankNum - 1;
205  iRank = iRank % iRankNum;
206  sResult.Format(pszRankExtensions[iExtension], pszRankNames[iRank]);
207  }
208  else
209  {
210  // simple rank
211  sResult.Ref(pszRankNames[iRank]);
212  }
213  return sResult;
214  }
215 #ifdef _WIN32
216  // old-style registry fallback
217  while (iRank>=0)
218  {
219  char keyname[30];
220  StdCopyStrBuf rankname;
221  sprintf(keyname,"Rank%03d",iRank+1);
222  rankname = GetRegistryString(Register,keyname);
223  if (!rankname.isNull())
224  return rankname;
225  if (!fReturnLastIfOver) return StdStrBuf();
226  --iRank;
227  }
228 #endif
229  return StdStrBuf();
230 }
231 
233 {
234  if (iRank<0) return 0;
235  return (int) ( pow (double(iRank), 1.5) * RankBase );
236 }
237 
239 {
240  int iRank=0;
241  while (Experience(iRank+1)<=iExp) ++iRank;
242  return iRank;
243 }
244 
245 bool C4RankSystem::Check(int iRank, const char *szDefRankName)
246 {
247 #ifdef _WIN32
248  char keyname[30];
249  sprintf(keyname,"Rank%03d",iRank);
250  if (!GetRegistryString(Register,keyname).isNull())
251  return false;
252  if (!szDefRankName || (SLen(szDefRankName)>C4MaxName))
253  return false;
254  return SetRegistryString(Register,keyname,szDefRankName);
255 #else
256  return true;
257 #endif
258 }
259 
261 {
262  // clear any loaded rank names
263  if (pszRankNames) { delete [] pszRankNames; pszRankNames=nullptr; }
264  if (pszRankExtensions) { delete [] pszRankExtensions; pszRankExtensions = nullptr; }
265  if (szRankNames) { delete [] szRankNames; szRankNames=nullptr; }
266  // reset number of ranks
267  iRankNum=0;
268  iRankExtNum=0;
269 }
270 
272 {
273  Clear();
274  Register[0]=0;
275  RankName[0]=0;
276  RankBase=1000;
277  iRankExtNum=0;
278 }
279 
280 bool C4RankSystem::DrawRankSymbol(C4FacetSurface *fctSymbol, int32_t iRank, C4Facet *pfctRankSymbols, int32_t iRankSymbolCount, bool fOwnSurface, int32_t iXOff, C4Facet *cgoDrawDirect)
281 {
282  // safety
283  if (iRank<0) iRank = 0;
284  // symbol by rank
285  int32_t iMaxRankSym,Q;
286  if (pfctRankSymbols->GetPhaseNum(iMaxRankSym, Q))
287  {
288  if (!iMaxRankSym) iMaxRankSym=1;
289  int32_t iBaseRank=iRank%iRankSymbolCount;
290  if (iRank/iRankSymbolCount)
291  {
292  // extended rank: draw
293  // extension star defaults to captain star; but use extended symbols if they are in the gfx
294  C4Facet fctExtended = ::GraphicsResource.fctCaptain;
295  if (iMaxRankSym > iRankSymbolCount)
296  {
297  int32_t iExtended = iRank / iRankSymbolCount - 1 + iRankSymbolCount;
298  if (iExtended >= iMaxRankSym)
299  {
300  // max rank exceeded
301  iExtended = iMaxRankSym - 1;
302  iBaseRank = iRankSymbolCount - 1;
303  }
304  fctExtended = pfctRankSymbols->GetPhase(iExtended);
305  }
306  int32_t iSize = pfctRankSymbols->Wdt;
307  if (!cgoDrawDirect)
308  {
309  fctSymbol->Create(iSize,iSize);
310  pfctRankSymbols->DrawX(fctSymbol->Surface, 0,0,iSize,iSize,iBaseRank);
311  fctExtended.DrawX(fctSymbol->Surface, 0,0,iSize*2/3,iSize*2/3);
312  }
313  else
314  {
315  pfctRankSymbols->Draw(cgoDrawDirect->Surface,cgoDrawDirect->X+iXOff,cgoDrawDirect->Y,iBaseRank);
316  fctExtended.Draw(cgoDrawDirect->Surface, cgoDrawDirect->X+iXOff-4,cgoDrawDirect->Y-3);
317  }
318  }
319  else
320  {
321  // regular rank: copy facet
322  if (cgoDrawDirect)
323  {
324  pfctRankSymbols->Draw(cgoDrawDirect->Surface, cgoDrawDirect->X+iXOff,cgoDrawDirect->Y,iBaseRank);
325  }
326  else if (fOwnSurface)
327  {
328  int32_t iSize = pfctRankSymbols->Wdt;
329  fctSymbol->Create(iSize,iSize);
330  pfctRankSymbols->DrawX(fctSymbol->Surface, 0,0,iSize,iSize,iBaseRank);
331  }
332  else
333  {
334  fctSymbol->Set(pfctRankSymbols->GetPhase(iBaseRank));
335  }
336  }
337  return true;
338  }
339  return false;
340 }
341 
C4GraphicsResource GraphicsResource
const unsigned int C4MaxName
C4RankSystem DefaultRanks
int SCharPos(char cTarget, const char *szInStr, int iIndex)
Definition: Standard.cpp:239
bool SCopySegment(const char *szString, int iSegment, char *sTarget, char cSeparator, int iMaxL, bool fSkipWhitespace)
Definition: Standard.cpp:279
void SCopy(const char *szSource, char *sTarget, size_t iMaxL)
Definition: Standard.cpp:152
#define sprintf
Definition: Standard.h:162
bool SEqual(const char *szStr1, const char *szStr2)
Definition: Standard.h:93
size_t SLen(const char *sptr)
Definition: Standard.h:74
int iSize
Definition: TstC4NetIO.cpp:32
const char * GetData() const
size_t GetDataSize() const
C4Surface * Surface
Definition: C4Facet.h:117
C4Facet GetPhase(int iPhaseX=0, int iPhaseY=0)
Definition: C4Facet.cpp:59
float Wdt
Definition: C4Facet.h:118
void Draw(C4Facet &cgo, bool fAspect=true, int32_t iPhaseX=0, int32_t iPhaseY=0, bool fTransparent=true)
Definition: C4Facet.cpp:154
bool GetPhaseNum(int32_t &rX, int32_t &rY)
Definition: C4Facet.cpp:472
void DrawX(C4Surface *sfcTarget, float iX, float iY, float iWdt, float iHgt, int32_t iPhaseX=0, int32_t iPhaseY=0) const
Definition: C4Facet.cpp:358
float Y
Definition: C4Facet.h:118
float X
Definition: C4Facet.h:118
bool Create(int iWdt, int iHgt, int iWdt2=C4FCT_Full, int iHgt2=C4FCT_Full)
Definition: C4FacetEx.cpp:54
void Set(const C4Facet &cpy)
Definition: C4FacetEx.h:46
static bool LoadComponentHost(C4ComponentHost *host, C4Group &hGroup, const char *szFilename, const char *szLanguage)
Definition: C4Language.cpp:232
static bool DrawRankSymbol(C4FacetSurface *fctSymbol, int32_t iRank, C4Facet *pfctRankSymbols, int32_t iRankSymbolCount, bool fOwnSurface, int32_t iXOff=0, C4Facet *cgoDrawDirect=nullptr)
char * szRankNames
Definition: C4RankSystem.h:38
int Init(const char *szRegister, const char *szDefRanks, int iRankBase)
StdStrBuf GetRankName(int iRank, bool fReturnLastIfOver)
char ** pszRankNames
Definition: C4RankSystem.h:37
int RankByExperience(int iExp)
char RankName[C4MaxName+1]
Definition: C4RankSystem.h:35
int Experience(int iRank)
char Register[256+1]
Definition: C4RankSystem.h:34
char ** pszRankExtensions
Definition: C4RankSystem.h:40
bool Check(int iRank, const char *szDefRankName)
bool Load(C4Group &hGroup, const char *szFilenames, int DefRankBase, const char *szLanguage)
void AppendChars(char cChar, size_t iCnt)
Definition: StdBuf.h:582
void Ref(const char *pnData)
Definition: StdBuf.h:455
const char * getData() const
Definition: StdBuf.h:442
char * getMData()
Definition: StdBuf.h:443
bool isNull() const
Definition: StdBuf.h:441
void Format(const char *szFmt,...) GNUC_FORMAT_ATTRIBUTE_O
Definition: StdBuf.cpp:174