OpenClonk
C4ObjectInfoList.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 /* Dynamic list for crew member info */
19 
20 #include "C4Include.h"
22 
23 #include "c4group/C4Components.h"
24 #include "object/C4Def.h"
25 #include "object/C4DefList.h"
26 #include "object/C4GameObjects.h"
27 #include "object/C4ObjectInfo.h"
28 #include "player/C4RankSystem.h"
29 
31 {
32  Default();
33 }
34 
36 {
37  Clear();
38 }
39 
41 {
42  First = nullptr;
43  iNumCreated = 0;
44 }
45 
47 {
48  C4ObjectInfo *next;
49  while (First)
50  {
51  next = First->Next;
52  delete First;
53  First = next;
54  }
55 }
56 
58 {
59  C4ObjectInfo *ninf;
60  int32_t infn = 0;
61  char entryname[256 + 1];
62 
63  // Search all oci files
64  hGroup.ResetSearch();
65  while (hGroup.FindNextEntry(C4CFN_ObjectInfoFiles, entryname))
66  {
67  if ((ninf = new C4ObjectInfo))
68  {
69  if (ninf->Load(hGroup,entryname))
70  {
71  Add(ninf);
72  infn++;
73  }
74  else
75  {
76  delete ninf;
77  }
78  }
79  }
80 
81  // Search subfolders
82  hGroup.ResetSearch();
83  while (hGroup.FindNextEntry("*", entryname))
84  {
85  C4Group ItemGroup;
86  if (ItemGroup.OpenAsChild(&hGroup, entryname))
87  {
88  Load(ItemGroup);
89  }
90  }
91 
92  return infn;
93 }
94 
96 {
97  if (!pInfo)
98  {
99  return false;
100  }
101  pInfo->Next = First;
102  First = pInfo;
103  return true;
104 }
105 
107 {
108  // Append a number to the name if it already exists, starting at 2
109 
110  // 1 space, up to 10 characters for integer max size,
111  // 1 terminating zero, 1 extra space for overflow (negative value) = 13 characters
112  char number_suffix[13];
113  size_t namelen = SLen(sName);
114  for (int32_t identifier = 2; NameExists(sName); identifier++)
115  {
116  sprintf(number_suffix, " %d", identifier);
117  SCopy(number_suffix, sName + std::min(namelen, C4MaxName - SLen(number_suffix)));
118  }
119 }
120 
121 bool C4ObjectInfoList::NameExists(const char *szName)
122 {
123  C4ObjectInfo *cinf;
124  for (cinf = First; cinf; cinf = cinf->Next)
125  {
126  if (SEqualNoCase(szName, cinf->Name))
127  {
128  return true;
129  }
130  }
131  return false;
132 }
133 
135 {
136  C4Def *pDef;
137  C4ObjectInfo *pInfo;
138  C4ObjectInfo *pHiExp = nullptr;
139 
140  // Search list
141  for (pInfo = First; pInfo; pInfo = pInfo->Next)
142  {
143  // Valid only
144  if ((pDef = rDefs.ID2Def(pInfo->id)))
145  {
146  // Use standard crew or matching id
147  if ( (!c_id && !pDef->NativeCrew) || (pInfo->id == c_id) )
148  {
149  // Participating and not in action
150  if (pInfo->Participation && !pInfo->InAction && !pInfo->HasDied)
151  {
152  // Highest experience
153  if (!pHiExp || (pInfo->Experience > pHiExp->Experience))
154  {
155  // Set this
156  pHiExp = pInfo;
157  }
158  }
159  }
160  }
161  }
162 
163  // Found
164  if (pHiExp)
165  {
166  pHiExp->Recruit();
167  return pHiExp;
168  }
169 
170  return nullptr;
171 }
172 
174 {
175  C4ObjectInfo *pInfo;
176  // Create new info object
177  if (!(pInfo = new C4ObjectInfo))
178  {
179  return nullptr;
180  }
181  // Default type clonk if none specified
182  if (n_id == C4ID::None)
183  {
184  n_id = C4ID::Clonk;
185  }
186  // Check type valid and def available
187  C4Def *pDef = nullptr;
188  if (pDefs && !(pDef = pDefs->ID2Def(n_id)))
189  {
190  delete pInfo;
191  return nullptr;
192  }
193  // Set name source
194  const char *cpNames = Game.Names.GetData();
195  if (pDef->pClonkNames)
196  {
197  cpNames = pDef->pClonkNames->GetData();
198  }
199  // Default by type
200  ((C4ObjectInfoCore*) pInfo)->Default(n_id, pDefs, cpNames);
201  // Set birthday
202  pInfo->Birthday = time(nullptr); // TODO: Use the function from C4ObjectInfo here, instead of assigning it manually
203  // Make valid names
204  MakeValidName(pInfo->Name);
205  // Add
206  Add(pInfo);
207  ++iNumCreated;
208  return pInfo;
209 }
210 
212 {
213  C4ObjectInfo *cinf;
214  for (cinf = First; cinf; cinf = cinf->Next)
215  {
216  cinf->Evaluate();
217  }
218 }
219 
220 bool C4ObjectInfoList::Save(C4Group &hGroup, bool fSavegame, bool fStoreTiny, C4DefList *pDefs)
221 {
222  // Save in opposite order (for identical crew order on load)
223  C4ObjectInfo *pInfo;
224  for (pInfo = GetLast(); pInfo; pInfo = GetPrevious(pInfo))
225  {
226  // Don't save TemporaryCrew in regular player files
227  if (!fSavegame)
228  {
229  C4Def *pDef = C4Id2Def(pInfo->id);
230  if (pDef && pDef->TemporaryCrew)
231  {
232  continue;
233  }
234  }
235  // save
236  if (!pInfo->Save(hGroup, fStoreTiny, pDefs))
237  {
238  return false;
239  }
240  }
241  return true;
242 }
243 
245 {
246  C4ObjectInfo *pInfo;
247  // Find matching name, participating, alive and not in action
248  for (pInfo = First; pInfo; pInfo = pInfo->Next)
249  {
250  if (SEqualNoCase(pInfo->Name, szByName)
251  && pInfo->Participation
252  && !pInfo->InAction
253  && !pInfo->HasDied)
254  {
255  pInfo->Recruit();
256  return pInfo;
257  }
258  }
259  return nullptr;
260 }
261 
263 {
264  C4ObjectInfo *cinf;
265  for (cinf = First; cinf; cinf = cinf->Next)
266  {
267  ::Objects.ClearInfo(cinf);
268  }
269 }
270 
272 {
273  C4ObjectInfo *cInfo = First;
274  while (cInfo && cInfo->Next)
275  {
276  cInfo = cInfo->Next;
277  }
278  return cInfo;
279 }
280 
282 {
283  for (C4ObjectInfo *cInfo = First; cInfo; cInfo=cInfo->Next)
284  {
285  if (cInfo->Next == pInfo)
286  {
287  return cInfo;
288  }
289  }
290  return nullptr;
291 }
292 
294 {
295  for (C4ObjectInfo *cInfo = First; cInfo; cInfo = cInfo->Next)
296  {
297  if (cInfo == pInfo)
298  {
299  return true;
300  }
301  }
302  return false;
303 }
304 
306 {
307  C4ObjectInfo *pInfo;
308  C4ObjectInfo *pPrev;
309  // Search list
310  for (pInfo = First, pPrev = nullptr; pInfo; )
311  {
312  // Invalid?
313  if (!rDefs.ID2Def(pInfo->id))
314  {
315  C4ObjectInfo *pDelete = pInfo;
316  if (pPrev)
317  {
318  pPrev->Next = pInfo->Next;
319  }
320  else
321  {
322  First = pInfo->Next;
323  }
324  pInfo = pInfo->Next;
325  delete pDelete;
326  }
327  else
328  {
329  pPrev = pInfo;
330  pInfo = pInfo->Next;
331  }
332  }
333 }
#define C4CFN_ObjectInfoFiles
Definition: C4Components.h:170
C4Def * C4Id2Def(C4ID id)
Definition: C4DefList.h:84
C4Game Game
Definition: C4Globals.cpp:52
C4GameObjects Objects
Definition: C4Globals.cpp:48
const unsigned int C4MaxName
void SCopy(const char *szSource, char *sTarget, size_t iMaxL)
Definition: Standard.cpp:152
bool SEqualNoCase(const char *szStr1, const char *szStr2, int iLen)
Definition: Standard.cpp:213
#define sprintf
Definition: Standard.h:162
size_t SLen(const char *sptr)
Definition: Standard.h:74
const char * GetData() const
Definition: C4Def.h:99
int32_t TemporaryCrew
Definition: C4Def.h:140
C4ComponentHost * pClonkNames
Definition: C4Def.h:185
int32_t NativeCrew
Definition: C4Def.h:113
C4Def * ID2Def(C4ID id)
C4ComponentHost Names
Definition: C4Game.h:78
bool FindNextEntry(const char *wildcard, StdStrBuf *filename=nullptr, size_t *size=nullptr, bool start_at_filename=false)
Definition: C4Group.cpp:2217
bool OpenAsChild(C4Group *mother, const char *entry_name, bool is_exclusive=false, bool do_create=false)
Definition: C4Group.cpp:1952
void ResetSearch(bool reload_contents=false)
Definition: C4Group.cpp:1316
Definition: C4Id.h:26
static const C4ID Clonk
Definition: C4Id.h:40
static const C4ID None
Definition: C4Id.h:39
char Name[C4MaxName+1]
Definition: C4InfoCore.h:37
int32_t Birthday
Definition: C4InfoCore.h:46
int32_t Participation
Definition: C4InfoCore.h:38
int32_t Experience
Definition: C4InfoCore.h:43
C4ObjectInfo * Next
Definition: C4ObjectInfo.h:41
bool Load(C4Group &hGroup)
bool Save(C4Group &hGroup, bool fStoreTiny, C4DefList *pDefs)
C4ObjectInfo * First
void MakeValidName(char *sName)
bool Add(C4ObjectInfo *pInfo)
bool Save(C4Group &hGroup, bool fSavegame, bool fStoreTiny, C4DefList *pDefs)
bool IsElement(C4ObjectInfo *pInfo)
C4ObjectInfo * GetLast()
C4ObjectInfo * New(C4ID n_id, C4DefList *pDefs)
C4ObjectInfo * GetPrevious(C4ObjectInfo *pInfo)
bool NameExists(const char *szName)
void Strip(C4DefList &rDefs)
C4ObjectInfo * GetIdle(C4ID c_id, C4DefList &rDefs)
int32_t Load(C4Group &hGroup)
void ClearInfo(C4ObjectInfo *info)