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