2
* Copyright (C) 2002 by the Widelands Development Team
4
* This program is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU General Public License
6
* as published by the Free Software Foundation; either version 2
7
* of the License, or (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software
16
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
#include "editor_game_base.h"
23
#include "filesystem.h"
30
#include "warehouse.h"
31
#include "wexception.h"
39
Tribe_Descr::Tribe_Descr(const char* name)
41
snprintf(m_name, sizeof(m_name), "%s", name);
47
snprintf(directory, sizeof(directory), "tribes/%s", name);
49
m_default_encdata.clear();
50
parse_wares(directory);
51
parse_buildings(directory);
52
parse_workers(directory);
53
parse_bobs(directory);
54
parse_root_conf(directory);
56
catch(std::exception &e)
58
throw wexception("Error loading tribe %s: %s", name, e.what());
62
Tribe_Descr::~Tribe_Descr(void)
74
void Tribe_Descr::postload(Editor_Game_Base* g)
76
// TODO: move more loads to postload
81
Tribe_Descr::load_graphics
86
void Tribe_Descr::load_graphics()
90
for(i = 0; i < m_workers.get_nitems(); i++)
91
m_workers.get(i)->load_graphics();
93
for(i = 0; i < m_wares.get_nitems(); i++)
94
m_wares.get(i)->load_graphics();
96
for(i = 0; i < m_buildings.get_nitems(); i++)
97
m_buildings.get(i)->load_graphics();
102
// down here: private read functions for loading
107
Tribe_Descr::parse_root_conf
109
Read and process the main conf file
112
void Tribe_Descr::parse_root_conf(const char *directory)
116
snprintf(fname, sizeof(fname), "%s/conf", directory);
124
s = prof.get_safe_section("tribe");
126
s->get_string("author");
127
s->get_string("name"); // descriptive name
128
s->get_string("descr"); // long description
130
// Section [defaults]
131
s = prof.get_section("defaults");
134
m_default_encdata.parse(s);
136
// Section [frontier]
137
s = prof.get_section("frontier");
139
throw wexception("Missing section [frontier]");
141
m_anim_frontier = g_anim.get(directory, s, 0, &m_default_encdata);
144
s = prof.get_section("flag");
146
throw wexception("Missing section [flag]");
148
m_anim_flag = g_anim.get(directory, s, 0, &m_default_encdata);
151
s = prof.get_safe_section("startwares");
152
Section::Value* value;
154
while((value=s->get_next_val(0))) {
155
int idx = m_wares.get_index(value->get_name());
157
throw wexception("In section [startwares], ware %s is not know!", value->get_name());
159
std::string name=value->get_name();
160
m_startwares[name]=value->get_int();
164
s = prof.get_safe_section("startworkers");
165
while((value=s->get_next_val(0))) {
166
if(!strcmp(value->get_name(),"soldier")) continue; // Ignore soldiers here
167
int idx = m_workers.get_index(value->get_name());
169
throw wexception("In section [startworkers], worker %s is not know!", value->get_name());
171
std::string name=value->get_name();
172
m_startworkers[name]=value->get_int();
176
s = prof.get_safe_section("startsoldiers");
177
while((value=s->get_next_val(0))) {
178
// NOTE: no check here, since we do not know about max levels and so on
179
std::string soldier=value->get_name();
180
m_startsoldiers[soldier]=value->get_int();
183
catch(std::exception &e) {
184
throw wexception("%s: %s", fname, e.what());
191
Tribe_Descr::parse_buildings
193
Read all the building descriptions
196
void Tribe_Descr::parse_buildings(const char *rootdir)
201
snprintf(subdir, sizeof(subdir), "%s/buildings", rootdir);
203
g_fs->FindFiles(subdir, "*", &dirs);
205
for(filenameset_t::iterator it = dirs.begin(); it != dirs.end(); it++) {
206
Building_Descr *descr = 0;
209
descr = Building_Descr::create_from_dir(this, it->c_str(), &m_default_encdata);
210
} catch(std::exception &e) {
211
log("Building %s failed: %s (garbage directory?)\n", it->c_str(), e.what());
213
log("Building %s failed: unknown exception (garbage directory?)\n", it->c_str());
217
m_buildings.add(descr);
224
Tribe_Descr::parse_workers
226
Read all worker descriptions
229
void Tribe_Descr::parse_workers(const char *directory)
234
snprintf(subdir, sizeof(subdir), "%s/workers", directory);
236
g_fs->FindFiles(subdir, "*", &dirs);
238
for(filenameset_t::iterator it = dirs.begin(); it != dirs.end(); it++) {
239
Worker_Descr *descr = 0;
242
descr = Worker_Descr::create_from_dir(this, it->c_str(), &m_default_encdata);
243
} catch(std::exception &e) {
244
log("Worker %s failed: %s (garbage directory?)\n", it->c_str(), e.what());
246
log("Worker %s failed: unknown exception (garbage directory?)\n", it->c_str());
250
m_workers.add(descr);
256
Tribe_Descr::parse_wares
258
Parse the wares belonging to this tribe, adding it to the games warelist. This is delayed until the game starts,
259
and is called by the Game class
262
void Tribe_Descr::parse_wares(const char* directory)
264
Descr_Maintainer<Item_Ware_Descr>* wares=&m_wares;
268
snprintf(subdir, sizeof(subdir), "%s/wares", directory);
270
g_fs->FindFiles(subdir, "*", &dirs);
272
for(filenameset_t::iterator it = dirs.begin(); it != dirs.end(); it++) {
275
snprintf(fname, sizeof(fname), "%s/conf", it->c_str());
277
if (!g_fs->FileExists(fname))
281
const char *slash = strrchr(it->c_str(), '/');
282
const char *backslash = strrchr(it->c_str(), '\\');
284
if (backslash && (!slash || backslash > slash))
292
if (wares->get_index(name) >= 0)
293
log("Ware %s is already known in world init\n", it->c_str());
295
Item_Ware_Descr* descr = 0;
299
descr = Item_Ware_Descr::create_from_dir(name, it->c_str());
301
catch(std::exception& e)
303
cerr << it->c_str() << ": " << e.what() << " (garbage directory?)" << endl;
307
cerr << it->c_str() << ": Unknown exception" << endl;
316
* Parse the player bobs (animations, immovables, critters)
318
void Tribe_Descr::parse_bobs(const char* directory) {
322
snprintf(subdir, sizeof(subdir), "%s/bobs", directory);
324
g_fs->FindFiles(subdir, "*", &dirs);
326
for(filenameset_t::iterator it = dirs.begin(); it != dirs.end(); it++) {
329
snprintf(fname, sizeof(fname), "%s/conf", it->c_str());
331
if (!g_fs->FileExists(fname))
335
const char *slash = strrchr(it->c_str(), '/');
336
const char *backslash = strrchr(it->c_str(), '\\');
338
if (backslash && (!slash || backslash > slash))
348
Profile prof(fname, "global"); // section-less file
349
Section *s = prof.get_safe_section("global");
350
const char *type = s->get_safe_string("type");
352
if (!strcasecmp(type, "critter")) {
354
descr = Bob_Descr::create_from_dir(name, it->c_str(), &prof, this);
357
Immovable_Descr *descr = new Immovable_Descr(name, this);
358
descr->parse(it->c_str(), &prof);
359
m_immovables.add(descr);
361
} catch(std::exception &e) {
362
cerr << it->c_str() << ": " << e.what() << " (garbage directory?)" << endl;
364
cerr << it->c_str() << ": unknown exception (garbage directory?)" << endl;
371
void Tribe_Descr::load_warehouse_with_start_wares()
373
This loads a warehouse with the given start wares as defined in
377
void Tribe_Descr::load_warehouse_with_start_wares(Editor_Game_Base* egbase, Warehouse* wh) {
378
std::map<std::string, int>::iterator cur;
380
for(cur=m_startwares.begin(); cur!=m_startwares.end(); cur++) {
381
wh->insert_wares(get_safe_ware_index((*cur).first.c_str()), (*cur).second);
383
for(cur=m_startworkers.begin(); cur!=m_startworkers.end(); cur++) {
384
wh->insert_workers(get_safe_worker_index((*cur).first.c_str()), (*cur).second);
386
for(cur=m_startsoldiers.begin(); cur!=m_startsoldiers.end(); cur++) {
387
std::vector<std::string> list;
388
split_string(cur->first, &list, "/");
391
throw wexception("Error in tribe (%s), startsoldier %s is not valid!", get_name(), cur->first.c_str());
394
int hplvl=strtol(list[0].c_str(),&endp, 0);
396
throw wexception("Bad hp level '%s'", list[0].c_str());
397
int attacklvl=strtol(list[1].c_str(),&endp, 0);
399
throw wexception("Bad attack level '%s'", list[1].c_str());
400
int defenselvl=strtol(list[2].c_str(),&endp, 0);
402
throw wexception("Bad defense level '%s'", list[2].c_str());
403
int evadelvl=strtol(list[3].c_str(),&endp, 0);
405
throw wexception("Bad evade level '%s'", list[3].c_str());
408
for(i=0;i<cur->second; i++) {
409
if(egbase->is_game()) {
410
Game* game=static_cast<Game*>(egbase);
411
Soldier_Descr* soldierd=static_cast<Soldier_Descr*>(get_worker_descr(get_worker_index("soldier")));
412
Soldier* soldier=static_cast<Soldier*>(soldierd->create(game, wh->get_owner(), wh, wh->get_position()));
413
soldier->set_level(hplvl,attacklvl,defenselvl,evadelvl);
414
wh->incorporate_worker(game, soldier);
417
//TODO: What to do in editor
423
* does this tribe exist?
425
bool Tribe_Descr::exists_tribe(std::string name) {
427
buf="tribes/" + name + "/conf";;
430
return f.TryOpen(g_fs, buf.c_str());
434
* Returns all tribes that exists
436
void Tribe_Descr::get_all_tribes(std::vector<std::string>* retval) {
440
filenameset_t m_tribes;
441
g_fs->FindFiles("tribes", "*", &m_tribes);
442
for(filenameset_t::iterator pname = m_tribes.begin(); pname != m_tribes.end(); pname++) {
443
std::string tribe=*pname;
444
tribe.erase(0,7); // remove 'tribes/'
445
if(Tribe_Descr::exists_tribe(tribe.c_str()))
446
retval->push_back(tribe);
452
Resource_Descr::get_indicator
454
Find the best matching indicator for the given amount.
457
int Tribe_Descr::get_resource_indicator(Resource_Descr *res, uint amount)
459
if(!res || !amount) {
460
int idx=get_immovable_index("resi_none");
462
throw wexception("Tribe %s doesn't declare a resource indicator resi_none!\n", get_name());
469
int num_indicators=0;
471
sprintf(buffer, "resi_%s%i", res->get_name(), i);
472
if(get_immovable_index(buffer)==-1)
478
if(!num_indicators) {
479
// Upsy, no indicators for this resource
480
throw wexception("Tribe %s doesn't declar a resource indicator for resource %s!\n", get_name(), res->get_name());
483
uint bestmatch = (uint) (( static_cast<float>(amount)/res->get_max_amount() ) * num_indicators);
484
if(((int)amount)<res->get_max_amount())
485
bestmatch+=1; // Resi start with 1, not 0
487
sprintf(buffer, "resi_%s%i", res->get_name(), bestmatch);
489
// NoLog("Resource(%s): Indicator '%s' for amount = %u\n",
490
// res->get_name(), buffer, amount);
494
return get_immovable_index(buffer);
498
* Return the given ware or die trying
500
int Tribe_Descr::get_safe_ware_index(const char *name) {
501
int retval=get_ware_index(name);
504
throw wexception("Tribe_Descr::get_safe_ware_index: Unknown ware %s!", name);
509
* Return the given worker or die trying
511
int Tribe_Descr::get_safe_worker_index(const char *name) {
512
int retval=get_worker_index(name);
515
throw wexception("Tribe_Descr::get_safe_worker_index: Unknown worker %s!", name);
520
* Return the given building or die trying
522
int Tribe_Descr::get_safe_building_index(const char *name) {
523
int retval=get_building_index(name);
526
throw wexception("Tribe_Descr::get_safe_building_index: Unknown building %s!", name);