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