1 ////////////////////////////////////////////////////////////////////////////////
2 // Scorched3D (c) 2000-2009
4 // This file is part of Scorched3D.
6 // Scorched3D is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
11 // Scorched3D is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with Scorched3D; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 ////////////////////////////////////////////////////////////////////////////////
21 #include <XML/XMLFile.h>
22 #include <common/Defines.h>
23 #include <common/Logger.h>
24 #include <weapons/AccessoryStore.h>
25 #include <weapons/Weapon.h>
26 #include <lang/LangResource.h>
30 AccessoryStore::AccessoryStore() : muzzleFlash_(0)
35 AccessoryStore::~AccessoryStore()
40 bool AccessoryStore::parseFile(
41 ScorchedContext
&context
, ProgressCounter
*counter
)
43 if (counter
) counter
->setNewOp(LANG_RESOURCE("LOADING_WEAPONS", "Loading Weapons"));
45 std::string fileName
= S3D::getDataFile("data/accessories.xml");
49 if (!file
.readFile(fileName
.c_str()))
51 S3D::dialogMessage("AccessoryStore", S3D::formatStringBuffer(
52 "Failed to parse \"%s\"\n%s",
54 file
.getParserError()));
59 if (!file
.getRootNode())
61 S3D::dialogMessage("AccessoryStore", S3D::formatStringBuffer(
62 "Failed to find accessory file \"%s\"",
67 // Itterate all of the accessories in the file
68 int noChildren
= file
.getRootNode()->getChildren().size();
70 XMLNode
*currentNode
= 0;
71 while (file
.getRootNode()->getNamedChild("accessory", currentNode
, false))
73 if (counter
) counter
->setNewPercentage(
74 float(++childCount
) / float(noChildren
) * 100.0f
);
76 // Parse the accessory
77 AccessoryCreateContext
createContext(context
);
78 Accessory
*accessory
= new Accessory();
79 if (!accessory
->parseXML(createContext
, currentNode
))
81 return currentNode
->returnError(
82 S3D::formatStringBuffer("Failed to create accessory \"%s\"",
83 accessory
->getName()));
87 if (findByPrimaryAccessoryName(accessory
->getName()))
89 return currentNode
->returnError(
90 S3D::formatStringBuffer("Accessory \"%s\" already exists",
91 accessory
->getName()));
95 tabGroups_
.insert(accessory
->getTabGroupName());
96 accessories_
.push_back(accessory
);
98 // Add weapons to death animations, weighted by arms level
99 if (accessory
->getAction()->getType() == AccessoryPart::AccessoryWeapon
)
101 Weapon
*weapon
= (Weapon
*) accessory
->getAction();
102 if (0 == strcmp(accessory
->getName(), "WeaponMuzzle"))
104 muzzleFlash_
= weapon
;
106 else if (0 == strcmp(accessory
->getName(), "WeaponDeathAnimation"))
108 deathAnimation_
= weapon
;
112 // Add to the map so references can find it
113 parsingNodes_
[accessory
->getName()] = currentNode
;
118 return file
.getRootNode()->returnError(
119 "Failed to find WeaponMuzzle weapon used for muzzle flash.");
121 if (!deathAnimation_
)
123 return file
.getRootNode()->returnError(
124 "Failed to find WeaponDeathAnimation weapon used for tank explosions.");
127 // Clear mapping as it now contains invalid pointers
128 parsingNodes_
.clear();
129 return file
.getRootNode()->failChildren();
132 AccessoryPart
*AccessoryStore::createAccessoryPart(
133 AccessoryCreateContext
&context
,
134 Accessory
*parent
, XMLNode
*currentNode
)
136 XMLNode
*typeNode
= 0;
137 if (!currentNode
->getNamedParameter("type", typeNode
)) return false;
139 AccessoryPart
*accessoryPart
=
140 AccessoryMetaRegistration::getNewAccessory(typeNode
->getContent(), this);
143 S3D::dialogMessage("AccessoryStore", S3D::formatStringBuffer(
144 "Failed to find accessory part type \"%s\"",
145 typeNode
->getContent()));
148 // Set the parent accessory
149 accessoryPart
->setParent(parent
);
151 // Tell this accessory instance to initialize its settings from
152 // the current accessory xml definition node
153 if (!accessoryPart
->parseXML(context
, currentNode
)) return 0;
155 // There should not be any children left
156 // Any that are, are children that have not been
157 // handled by the parse routine
158 if (!currentNode
->failChildren()) return 0;
159 DIALOG_ASSERT(accessoryPart
->getParent());
162 accessoryParts_
.push_back(accessoryPart
);
163 return accessoryPart
;
166 void AccessoryStore::sortList(std::list
<Accessory
*> &accList
, int sortKey
)
170 std::vector
<Accessory
*> accVector
;
171 std::list
<Accessory
*>::iterator itor
;
172 for (itor
= accList
.begin();
173 itor
!= accList
.end();
176 accVector
.push_back(*itor
);
179 // Crudely sort by name or price
180 // stl sort method list is broken in visual c 6
186 for (int i
=0; i
<int(accVector
.size())-1; i
++)
190 // When sorting by price, use accessory name as a
191 // secondary sort key.
193 if ((sortKey
== SortName
) ||
194 (sortKey
== SortPrice
&& accVector
[i
]->getPrice() == accVector
[i
+ 1]->getPrice()))
196 swap
= strcmp(accVector
[i
]->getName(), accVector
[i
+ 1]->getName()) < 0;
198 else if (sortKey
== SortPrice
)
200 swap
= accVector
[i
]->getPrice() < accVector
[i
+ 1]->getPrice();
205 Accessory
*tmp
= accVector
[i
];
206 accVector
[i
] = accVector
[i
+1];
207 accVector
[i
+1] = tmp
;
215 for (int i
=0; i
<int(accVector
.size()); i
++)
217 accList
.push_front(accVector
[i
]);
222 std::set
<Accessory
*> accessorySet
;
223 std::list
<Accessory
*>::iterator setItor
;
224 for (setItor
= accList
.begin();
225 setItor
!= accList
.end();
228 Accessory
*accessory
= *setItor
;
229 accessorySet
.insert(accessory
);
233 std::list
<Accessory
*>::iterator itor
;
234 for (itor
= accessories_
.begin();
235 itor
!= accessories_
.end();
238 Accessory
*accessory
= *itor
;
239 if (accessorySet
.find(accessory
) != accessorySet
.end())
241 accList
.push_back(accessory
);
247 std::list
<Accessory
*> AccessoryStore::getAllAccessoriesByTabGroup(
248 const char *tabgroup
, int sortKey
)
250 std::list
<Accessory
*> result
;
251 std::list
<Accessory
*>::iterator itor
;
252 for (itor
= accessories_
.begin();
253 itor
!= accessories_
.end();
256 Accessory
*accessory
= (*itor
);
257 if (0 == strcmp(tabgroup
, accessory
->getTabGroupName()))
259 result
.push_back(*itor
);
263 if (sortKey
) sortList(result
, sortKey
);
267 std::list
<Accessory
*> AccessoryStore::getAllAccessories(int sortKey
)
269 std::list
<Accessory
*> result
;
270 std::list
<Accessory
*>::iterator itor
;
271 for (itor
= accessories_
.begin();
272 itor
!= accessories_
.end();
275 result
.push_back(*itor
);
278 if (sortKey
) sortList(result
, sortKey
);
282 Weapon
*AccessoryStore::getMuzzelFlash()
287 Weapon
*AccessoryStore::getDeathAnimation()
289 return deathAnimation_
;
292 Accessory
*AccessoryStore::findByPrimaryAccessoryName(const char *name
)
294 std::list
<Accessory
*>::iterator itor
;
295 for (itor
= accessories_
.begin();
296 itor
!= accessories_
.end();
299 Accessory
*accessory
= (*itor
);
300 if (strcmp(accessory
->getName(), name
) == 0)
308 Accessory
*AccessoryStore::findByAccessoryId(unsigned int id
)
310 std::list
<Accessory
*>::iterator itor
;
311 for (itor
= accessories_
.begin();
312 itor
!= accessories_
.end();
315 Accessory
*accessory
= (*itor
);
316 if (accessory
->getAccessoryId() == id
)
324 AccessoryPart
*AccessoryStore::findAccessoryPartByAccessoryId(unsigned int id
, const char *type
)
326 std::list
<AccessoryPart
*>::iterator itor
;
327 for (itor
= accessoryParts_
.begin();
328 itor
!= accessoryParts_
.end();
331 AccessoryPart
*accessoryPart
= (*itor
);
332 if (accessoryPart
->getParent()->getAccessoryId() == id
&&
333 0 == strcmp(accessoryPart
->getAccessoryTypeName(), type
))
335 return accessoryPart
;
341 AccessoryPart
*AccessoryStore::findByAccessoryPartId(unsigned int id
)
343 std::list
<AccessoryPart
*>::iterator itor
;
344 for (itor
= accessoryParts_
.begin();
345 itor
!= accessoryParts_
.end();
348 AccessoryPart
*accessoryPart
= (*itor
);
349 if (accessoryPart
->getAccessoryPartId() == id
)
351 return accessoryPart
;
357 void AccessoryStore::clearAccessories()
359 AccessoryPart::resetAccessoryPartIds();
360 Accessory::resetAccessoryIds();
363 while (!accessories_
.empty())
365 Accessory
*accessory
= accessories_
.front();
366 accessories_
.pop_front();
369 while (!accessoryParts_
.empty())
371 AccessoryPart
*accessoryPart
= accessoryParts_
.front();
372 accessoryParts_
.pop_front();
373 delete accessoryPart
;
377 bool AccessoryStore::writeWeapon(NetBuffer
&buffer
, Weapon
*weapon
)
379 return writeAccessoryPart(buffer
, weapon
);
382 Weapon
*AccessoryStore::readWeapon(NetBufferReader
&reader
)
384 AccessoryPart
*accessoryPart
= readAccessoryPart(reader
);
386 accessoryPart
->getType() == AccessoryPart::AccessoryWeapon
)
388 return ((Weapon
*) accessoryPart
);
393 bool AccessoryStore::writeAccessoryPart(NetBuffer
&buffer
, AccessoryPart
*part
)
395 if (part
) buffer
.addToBuffer(part
->getAccessoryPartId());
396 else buffer
.addToBuffer((unsigned int) 0);
400 AccessoryPart
*AccessoryStore::readAccessoryPart(NetBufferReader
&reader
)
403 if (!reader
.getFromBuffer(partId
)) return 0;
404 AccessoryPart
*accessoryPart
= findByAccessoryPartId(partId
);
406 accessoryPart
->getAccessoryPartId() == partId
)
408 return accessoryPart
;
413 bool AccessoryStore::writeEconomyToBuffer(NetBuffer
&buffer
)
415 std::list
<Accessory
*> accessories
= getAllAccessories();
416 buffer
.addToBuffer((int) accessories
.size());
418 std::list
<Accessory
*>::iterator itor
;
419 for (itor
= accessories
.begin();
420 itor
!= accessories
.end();
423 Accessory
*accessory
= (*itor
);
424 buffer
.addToBuffer(accessory
->getAccessoryId());
425 buffer
.addToBuffer(accessory
->getPrice());
426 buffer
.addToBuffer(accessory
->getSellPrice());
431 bool AccessoryStore::readEconomyFromBuffer(NetBufferReader
&reader
)
433 int noAccessories
= 0;
434 if (!reader
.getFromBuffer(noAccessories
)) return false;
435 for (int a
=0; a
<noAccessories
; a
++)
437 unsigned int accessoryId
= 0;
438 int price
= 0, sellPrice
= 0;
439 if (!reader
.getFromBuffer(accessoryId
)) return false;
440 if (!reader
.getFromBuffer(price
)) return false;
441 if (!reader
.getFromBuffer(sellPrice
)) return false;
443 Accessory
*accessory
= findByAccessoryId(accessoryId
);
444 if (!accessory
) return false;
445 accessory
->setPrice(price
);
446 accessory
->setSellPrice(sellPrice
);