1 /////////////////////////////////////////
2 //
3 // OpenLieroX
4 //
5 // code under LGPL, based on JasonBs work,
6 // enhanced by Dark Charlie and Albert Zeyer
7 //
8 //
9 /////////////////////////////////////////
10
11
12 // Weapon Restrictions class
13 // Created 30/3/03
14 // Jason Boettcher
15
16
17 #include <assert.h>
18
19 #include "LieroX.h"
20 #include "CGameScript.h"
21 #include "FindFile.h"
22 #include "StringUtils.h"
23 #include "CWpnRest.h"
24 #include "CBytestream.h"
25 #include "MathLib.h"
26 #include "WeaponDesc.h"
27
28
29 ///////////////////
30 // WpnRest Constructor
CWpnRest()31 CWpnRest::CWpnRest()
32 {
33 m_psWeaponList = NULL;
34 m_psSortedList = NULL;
35 m_nCount = 0;
36 iCycleState = wpr_banned;
37 }
38
39
40 ///////////////////
41 // Update the weapons list from a gamescript file
updateList(CGameScript * pcGameS)42 void CWpnRest::updateList(CGameScript *pcGameS)
43 {
44 assert( pcGameS );
45
46 // Go through the weapons in the gamescript
47 // If any weapon is not in our list, add it to the list
48 const weapon_t *psWpn = pcGameS->GetWeapons();
49 int count = pcGameS->GetNumWeapons();
50 int i;
51
52
53 for(i=0; i<count; i++, psWpn++) {
54
55 wpnrest_t *w = findWeapon( psWpn->Name );
56 if( !w ) {
57 // No match, add it to the list
58 addWeapon( psWpn->Name, wpr_enabled );
59 }
60 }
61
62 // Sort the list
63 sortList();
64 }
65
66
67 ///////////////////
68 // Reset all the weapons to default (enabled)
reset()69 void CWpnRest::reset()
70 {
71 wpnrest_t *psWpn = m_psWeaponList;
72 for(; psWpn; psWpn=psWpn->psNext) {
73 psWpn->nState = wpr_enabled;
74 }
75 }
76
77
78 ///////////////////
79 // Reset all the weapons in the current game script to default (enabled)
resetVisible(CGameScript * pcGameS)80 void CWpnRest::resetVisible(CGameScript *pcGameS)
81 {
82 assert(pcGameS);
83
84 wpnrest_t *psWpn = m_psWeaponList;
85 for(; psWpn; psWpn=psWpn->psNext) {
86 if(pcGameS->weaponExists(psWpn->szName))
87 psWpn->nState = wpr_enabled;
88 }
89 }
90
91
92 ///////////////////
93 // Randomize all the weapons in the current game script
randomizeVisible(CGameScript * pcGameS)94 void CWpnRest::randomizeVisible(CGameScript *pcGameS)
95 {
96 assert(pcGameS);
97
98 wpnrest_t *psWpn = m_psWeaponList;
99 for(; psWpn; psWpn=psWpn->psNext) {
100 if(pcGameS->weaponExists(psWpn->szName))
101 psWpn->nState = GetRandomInt(2);
102 }
103 }
104
105 ///////////////////
106 // Cycles the weapon states (enabled -> bonus -> disabled)
cycleVisible(CGameScript * pcGameS)107 void CWpnRest::cycleVisible(CGameScript *pcGameS)
108 {
109 assert(pcGameS);
110
111 if (iCycleState == 3) iCycleState = 0;
112 wpnrest_t *psWpn = m_psWeaponList;
113 for(; psWpn; psWpn=psWpn->psNext) {
114 if(pcGameS->weaponExists(psWpn->szName)) {
115 psWpn->nState = iCycleState;
116 }
117 }
118 iCycleState++;
119 }
120
121
122 ///////////////////
123 // Find a weapon in the list
findWeapon(const std::string & szName)124 wpnrest_t *CWpnRest::findWeapon(const std::string& szName)
125 {
126 if(szName == "")
127 return NULL;
128
129 std::string tmp = szName;
130 TrimSpaces(tmp);
131
132 wpnrest_t *psWpn = m_psWeaponList;
133
134 for(; psWpn; psWpn=psWpn->psNext) {
135
136 // We need to be a bit lenient here in case some simple mistakes in different game scripts occur
137 // Like case & leading/trailing spaces
138 if( stringcasecmp(psWpn->szName, tmp) == 0 )
139 return psWpn;
140 }
141
142 // No match
143 return NULL;
144 }
145
146
147 ///////////////////
148 // Add a weapon to the list
addWeapon(const std::string & szName,int nState)149 void CWpnRest::addWeapon(const std::string& szName, int nState)
150 {
151 if(szName == "") return;
152
153 wpnrest_t *psWpn = new wpnrest_t;
154
155 if( !psWpn )
156 return;
157
158 psWpn->szName = szName;
159 psWpn->nState = nState;
160
161 // Link it in
162 psWpn->psNext = m_psWeaponList;
163 m_psWeaponList = psWpn;
164
165 // Sort the list
166 sortList();
167 }
168
169
170 ///////////////////
171 // Save the weapons restrictions list
saveList(const std::string & szFilename)172 void CWpnRest::saveList(const std::string& szFilename)
173 {
174 // Save it as plain text
175 FILE *fp = OpenGameFile(szFilename, "wt");
176 if( !fp )
177 return;
178
179 wpnrest_t *psWpn = m_psWeaponList;
180 for(; psWpn; psWpn=psWpn->psNext) {
181 fprintf(fp, "%s,%d\n", psWpn->szName.c_str(), psWpn->nState);
182 }
183
184 fclose(fp);
185 }
186
187
188 ///////////////////
189 // Load the weapons restrictions list
loadList(const std::string & szFilename)190 void CWpnRest::loadList(const std::string& szFilename)
191 {
192 // Shutdown the list first
193 Shutdown();
194
195 FILE *fp = OpenGameFile(szFilename, "rt");
196 if( !fp )
197 return;
198
199 std::string line;
200
201 while( !feof(fp) && !ferror(fp) ) {
202 line = ReadUntil(fp, '\n');
203 std::vector<std::string> exploded = explode(line,",");
204 if (exploded.size() >= 2)
205 addWeapon(exploded[0],from_string<int>(exploded[1]));
206 }
207
208 fclose(fp);
209
210 // Sort the list
211 sortList();
212 }
213
214
215 ///////////////////
216 // Checks if the weapon is enabled or not
isEnabled(const std::string & szName)217 bool CWpnRest::isEnabled(const std::string& szName)
218 {
219 wpnrest_t *psWpn = findWeapon(szName);
220
221 // If we can't find the weapon, then assume it is banned
222 if( !psWpn )
223 return false;
224
225 return (psWpn->nState == wpr_enabled);
226 }
227
228 ///////////////////
229 // Checks if the weapon is bonus or not
isBonus(const std::string & szName)230 bool CWpnRest::isBonus(const std::string& szName)
231 {
232 wpnrest_t *psWpn = findWeapon(szName);
233
234 // If we can't find the weapon, then assume it is banned
235 if( !psWpn )
236 return false;
237
238 return (psWpn->nState == wpr_bonus);
239 }
240
241
242 ///////////////////
243 // Finds a weapon that is enabled and returns the name
findEnabledWeapon(CGameScript * pcGameS)244 std::string CWpnRest::findEnabledWeapon(CGameScript *pcGameS) {
245 assert(pcGameS);
246
247 // Go from the start of the list looking for an enabled weapon
248 // The weapon must also be in the gamescript
249 wpnrest_t *psWpn = m_psWeaponList;
250 for(; psWpn; psWpn=psWpn->psNext) {
251
252 if( psWpn->nState != wpr_enabled )
253 continue;
254
255 // Is the weapon in the gamescript?
256 if( !pcGameS->weaponExists(psWpn->szName) )
257 continue;
258
259 // Must be good
260 return psWpn->szName;
261 }
262
263 // No enabled weapons found
264 return "";
265 }
266
267
268 ///////////////////
269 // Get the state of a weapon
getWeaponState(const std::string & szName)270 int CWpnRest::getWeaponState(const std::string& szName)
271 {
272 wpnrest_t *psWpn = findWeapon(szName);
273
274 // Default to disabled if we can't find the weapon
275 if( !psWpn )
276 return wpr_banned;
277
278 return psWpn->nState;
279 }
280
281
282 ///////////////////
283 // Return the sorted weapon list
getList()284 wpnrest_t *CWpnRest::getList()
285 {
286 return m_psSortedList;
287 }
288
289
290 ///////////////////
291 // Return the number of weapons
getNumWeapons()292 int CWpnRest::getNumWeapons()
293 {
294 return m_nCount;
295 }
296
297
298 ///////////////////
299 // Create a sorted list
sortList()300 void CWpnRest::sortList()
301 {
302 int i, j;
303
304 // Free any previous list
305 if( m_psSortedList )
306 delete[] m_psSortedList;
307
308 // Count the number of weapons
309 m_nCount = 0;
310 wpnrest_t *psWpn = m_psWeaponList;
311 for(; psWpn; psWpn=psWpn->psNext)
312 m_nCount++;
313
314 // Allocate the sorted list
315 // TODO: is the following comment still valid?
316 // TODO: valgrid says, this got lost
317 m_psSortedList = new wpnrest_t[m_nCount];
318 if( !m_psSortedList )
319 return;
320
321 // Fill in the links
322 psWpn = m_psWeaponList;
323 for( i=0; i<m_nCount; i++, psWpn=psWpn->psNext)
324 m_psSortedList[i].psLink = psWpn;
325
326 if( m_nCount < 2 )
327 return;
328
329 // Sort the list using a simple bubble sort
330 wpnrest_t temp;
331 for(i=0; i<m_nCount; i++) {
332 for(j=0; j<m_nCount-1-i; j++) {
333
334 if( m_psSortedList[j].psLink->szName.compare( m_psSortedList[j+1].psLink->szName) > 0 ) {
335
336 // Swap the 2 items
337 temp = m_psSortedList[j];
338 m_psSortedList[j] = m_psSortedList[j+1];
339 m_psSortedList[j+1] = temp;
340 }
341 }
342 }
343 }
344
345
346 ///////////////////
347 // Send the list
sendList(CBytestream * psByteS,CGameScript * pcGameS)348 void CWpnRest::sendList(CBytestream *psByteS, CGameScript *pcGameS)
349 {
350 wpnrest_t *psWpn = NULL;
351
352 std::list<wpnrest_t *> rest_to_send;
353
354 // Add only weapons that are _not_ enabled
355 psWpn = m_psWeaponList;
356 for(; psWpn; psWpn = psWpn->psNext ) {
357 if(psWpn->nState != wpr_enabled && pcGameS->FindWeapon(psWpn->szName))
358 rest_to_send.push_back(psWpn);
359 }
360
361
362 // Write the header
363 psByteS->writeInt((int)rest_to_send.size(), 2);
364
365 // Write the restrictions
366 for (std::list<wpnrest_t *>::iterator it = rest_to_send.begin();
367 it != rest_to_send.end(); it++) {
368 psByteS->writeString((*it)->szName);
369 psByteS->writeByte((*it)->nState);
370 }
371 }
372
373
374 ///////////////////
375 // Receive the list
readList(CBytestream * psByteS)376 void CWpnRest::readList(CBytestream *psByteS)
377 {
378 std::string szName;
379 int nState;
380 wpnrest_t *psWpn = NULL;
381
382 // Initialize all the weapons to a default of 'enabled'
383 psWpn = m_psWeaponList;
384 for(; psWpn; psWpn = psWpn->psNext ) {
385 psWpn->nState = wpr_enabled;
386 }
387
388
389 int nCount = psByteS->readInt(2);
390
391 // Go through the list reading weapons
392 for( int i=0; i<nCount; i++ ) {
393 szName = psByteS->readString();
394 nState = psByteS->readByte();
395
396 // Try and find the weapon
397 psWpn = findWeapon(szName);
398 if( psWpn )
399 psWpn->nState = nState;
400 else {
401 // If the weapon doesn't exist, thats ok
402 // just add it to the list
403 addWeapon(szName,nState);
404 }
405 }
406 }
407
408
409 ///////////////////
410 // Shutdown the weapons restrictions list
Shutdown()411 void CWpnRest::Shutdown()
412 {
413 wpnrest_t *psWpn = m_psWeaponList;
414 wpnrest_t *psNext = NULL;
415
416 for(; psWpn; psWpn=psNext) {
417 psNext = psWpn->psNext;
418
419 delete psWpn;
420 }
421
422 m_psWeaponList = NULL;
423
424 // Free any sorted list
425 if( m_psSortedList )
426 delete[] m_psSortedList;
427 m_psSortedList = NULL;
428 }
429