moved almost all hardcoded constants to "define.dat"
[k8-i-v-a-n.git] / src / game / proto.cpp
blob689b9b9fd499eae37505f3878ca578133e9a68cb
1 /*
3 * Iter Vehemens ad Necem (IVAN)
4 * Copyright (C) Timo Kiviluoto
5 * Released under the GNU General
6 * Public License
8 * See LICENSING which should be included
9 * along with this file for more details
12 /* Compiled through dataset.cpp */
14 itemdatabase **protosystem::ItemConfigData;
15 int protosystem::ItemConfigDataSize;
16 itemdatabase **protosystem::ItemCategoryData[ITEM_CATEGORIES];
17 int protosystem::ItemCategorySize[ITEM_CATEGORIES];
18 sLong protosystem::ItemCategoryPossibility[ITEM_CATEGORIES];
19 sLong protosystem::TotalItemPossibility;
22 #include "confdef.h"
23 #include "level.h"
26 character *protosystem::BalancedCreateMonster (level *lvl) {
27 if (!lvl) lvl = game::GetCurrentLevel();
28 for (int c = 0; ; ++c) {
29 double MinDifficulty = game::GetMinDifficulty(), MaxDifficulty = MinDifficulty*25;
30 std::vector<configid> Possible;
31 for (int Type = 1; Type < protocontainer<character>::GetSize(); ++Type) {
32 const character::prototype *Proto = protocontainer<character>::GetProto(Type);
33 const character::database *const *ConfigData = Proto->GetConfigData();
34 int ConfigSize = Proto->GetConfigSize();
35 for (int c = 0; c < ConfigSize; ++c) {
36 const character::database *DataBase = ConfigData[c];
37 if (!DataBase->IsAbstract && DataBase->CanBeGenerated) {
38 // check allowed dungeons
40 truth allowed = false;
41 const fearray<int> &dlist = DataBase->AllowedDungeons;
43 //if (dlist[0] != ALL_DUNGEONS) fprintf(stderr, "(%u) [%d] [%d]\n", dlist.Size, dlist[0], game::GetCurrentDungeonIndex());
44 for (uInt f = 0; f < dlist.Size; ++f) {
45 if (dlist[f] == ALL_DUNGEONS || dlist[f] == game::GetCurrentDungeonIndex()) {
46 allowed = true;
47 break;
50 if (!allowed) continue;
52 // check allowed tags
53 if (lvl && lvl->GetLevelScript() && lvl->GetLevelScript()->GetTag() && !lvl->GetLevelScript()->GetTag()->IsEmpty()) {
54 const fearray<festring> &tlist = DataBase->LevelTags;
55 if (tlist.Size > 0) {
56 truth allowed = false;
57 cfestring *tag = lvl->GetLevelScript()->GetTag();
58 //fprintf(stderr, "looking for level tag [%s]\n", tag->CStr());
59 for (uInt f = 0; f < tlist.Size; ++f) {
60 //fprintf(stderr, " tag #%u: [%s]\n", f, tlist[f].CStr());
61 //if (tlist[f] == *tag) fprintf(stderr, "TAG HIT: [%s]\n", tag->CStr());
62 if (tlist[f] == "*" || tlist[f] == *tag) { allowed = true; break; }
64 if (!allowed) continue;
66 } else {
67 // level have no tag
68 const fearray<festring> &tlist = DataBase->LevelTags;
69 if (tlist.Size > 0) {
70 truth allowed = false;
71 for (uInt f = 0; f < tlist.Size; ++f) if (tlist[f] == "*") { allowed = true; break; }
72 if (!allowed) continue;
76 if (DataBase->IsUnique && (DataBase->Flags&HAS_BEEN_GENERATED)) continue;
77 truth IsCatacomb = *game::GetCurrentLevel()->GetLevelScript()->IsCatacomb();
78 if ((IsCatacomb && !DataBase->IsCatacombCreature) || (!IsCatacomb && DataBase->CanBeGeneratedOnlyInTheCatacombs)) continue;
79 configid ConfigID(Type, ConfigData[c]->Config);
80 if (c >= 100) {
81 Possible.push_back(ConfigID);
82 continue;
84 const dangerid &DangerID = game::GetDangerMap().find(ConfigID)->second;
85 if (!DataBase->IgnoreDanger) {
86 double Danger = DangerID.EquippedDanger;
87 if (Danger > 99.0 || Danger < 0.0011 || (DataBase->IsUnique && Danger < 3.5)) continue;
88 double DangerModifier = DataBase->DangerModifier==100 ? Danger : Danger*100/DataBase->DangerModifier;
89 if (DangerModifier < MinDifficulty || DangerModifier > MaxDifficulty) continue;
91 ivantime Time;
92 game::GetTime(Time);
94 if (!PLAYER) {
95 fprintf(stderr, "WARNING: WTF?! (protosystem::BalancedCreateMonster)\n");
96 //continue;
98 if (PLAYER->GetMaxHP() < DataBase->HPRequirementForGeneration && Time.Day < DataBase->DayRequirementForGeneration) continue;
99 Possible.push_back(ConfigID);
104 if (Possible.empty()) continue;
106 for (int i = 0; i < 25; ++i) {
107 configid Chosen = Possible[RAND_GOOD(Possible.size())];
108 const character::prototype *Proto = protocontainer<character>::GetProto(Chosen.Type);
109 character *Monster = Proto->Spawn(Chosen.Config);
110 if (c >= 100 ||
111 ((Monster->GetFrequency() == 10000 || Monster->GetFrequency() > RAND_GOOD(10000)) &&
112 (Monster->IsUnique() ||
113 (Monster->GetTimeToKill(PLAYER, true) > 5000 && PLAYER->GetTimeToKill(Monster, true) < 200000)))) {
114 Monster->SetTeam(game::GetTeam(MONSTER_TEAM));
115 return Monster;
117 delete Monster;
121 /* This line is never reached, but it prevents warnings given by some (stupid) compilers. */
122 return 0;
126 item *protosystem::BalancedCreateItem (level *lvl, sLong MinPrice, sLong MaxPrice, sLong RequiredCategory, int SpecialFlags, int ConfigFlags, int RequiredGod, truth Polymorph) {
127 typedef item::database database;
128 database **PossibleCategory[ITEM_CATEGORIES];
129 int PossibleCategorySize[ITEM_CATEGORIES];
130 sLong PartialCategoryPossibilitySum[ITEM_CATEGORIES];
131 int PossibleCategories = 0;
132 sLong TotalPossibility = 0;
133 sLong database::*PartialPossibilitySumPtr;
135 if (!lvl) lvl = game::GetCurrentLevel();
137 if (RequiredCategory == ANY_CATEGORY) {
138 PartialPossibilitySumPtr = &database::PartialPossibilitySum;
139 PossibleCategory[0] = ItemConfigData;
140 PossibleCategorySize[0] = ItemConfigDataSize;
141 TotalPossibility = TotalItemPossibility;
142 PartialCategoryPossibilitySum[0] = TotalPossibility;
143 PossibleCategories = 1;
144 } else {
145 PartialPossibilitySumPtr = &database::PartialCategoryPossibilitySum;
147 for (sLong CategoryIndex = 0, Category = 1; CategoryIndex < ITEM_CATEGORIES; ++CategoryIndex, Category <<= 1) {
148 if (Category & RequiredCategory) {
149 PossibleCategory[PossibleCategories] = ItemCategoryData[CategoryIndex];
150 PossibleCategorySize[PossibleCategories] = ItemCategorySize[CategoryIndex];
151 TotalPossibility += ItemCategoryPossibility[CategoryIndex];
152 PartialCategoryPossibilitySum[PossibleCategories] = TotalPossibility;
153 ++PossibleCategories;
158 for (int c0 = 0;; ++c0) {
159 for (int c1 = 0; c1 < BALANCED_CREATE_ITEM_ITERATIONS; ++c1) {
160 sLong Rand = RAND_GOOD(TotalPossibility);
161 int Category;
163 if (RequiredCategory == ANY_CATEGORY) {
164 Category = 0;
165 } else {
166 for (int c2 = 0;; ++c2) if (PartialCategoryPossibilitySum[c2] > Rand) { Category = c2; break; }
167 if (Category) Rand -= PartialCategoryPossibilitySum[Category-1];
170 const database *const *ChosenCategory = PossibleCategory[Category];
171 const database *ChosenDataBase;
173 if (ChosenCategory[0]->PartialCategoryPossibilitySum > Rand) {
174 ChosenDataBase = ChosenCategory[0];
175 } else {
176 sLong A = 0;
177 sLong B = PossibleCategorySize[Category] - 1;
178 for (;;) {
179 sLong C = (A + B) >> 1;
180 if (A != C) {
181 if(ChosenCategory[C]->*PartialPossibilitySumPtr > Rand) B = C; else A = C;
182 } else {
183 ChosenDataBase = ChosenCategory[B];
184 break;
189 int Config = ChosenDataBase->Config;
191 if ((!(ConfigFlags & NO_BROKEN) || !(Config & BROKEN)) && (!Polymorph || ChosenDataBase->IsPolymorphSpawnable)) {
192 // check allowed dungeons
194 truth allowed = false;
195 const fearray<int> &dlist = ChosenDataBase->AllowedDungeons;
197 //if (dlist[0] != ALL_DUNGEONS) fprintf(stderr, "(%u) [%d] [%d]\n", dlist.Size, dlist[0], game::GetCurrentDungeonIndex());
198 for (uInt f = 0; f < dlist.Size; ++f) {
199 if (dlist[f] == ALL_DUNGEONS || dlist[f] == game::GetCurrentDungeonIndex()) {
200 allowed = true;
201 break;
204 if (!allowed) continue;
206 // check allowed tags
207 if (lvl && lvl->GetLevelScript() && lvl->GetLevelScript()->GetTag() && !lvl->GetLevelScript()->GetTag()->IsEmpty()) {
208 const fearray<festring> &tlist = ChosenDataBase->LevelTags;
209 if (tlist.Size > 0) {
210 truth allowed = false;
211 cfestring *tag = lvl->GetLevelScript()->GetTag();
212 //fprintf(stderr, "looking for level tag [%s]\n", tag->CStr());
213 for (uInt f = 0; f < tlist.Size; ++f) {
214 //fprintf(stderr, " tag #%u: [%s]\n", f, tlist[f].CStr());
215 //if (tlist[f] == *tag) fprintf(stderr, "TAG HIT: [%s]\n", tag->CStr());
216 if (tlist[f] == "*" || tlist[f] == *tag) { allowed = true; break; }
218 if (!allowed) continue;
220 } else {
221 // level have no tag
222 const fearray<festring> &tlist = ChosenDataBase->LevelTags;
223 if (tlist.Size > 0) {
224 truth allowed = false;
225 for (uInt f = 0; f < tlist.Size; ++f) if (tlist[f] == "*") { allowed = true; break; }
226 if (!allowed) continue;
230 item *Item = ChosenDataBase->ProtoType->Spawn(Config, SpecialFlags);
231 truth GodOK = !RequiredGod || Item->GetAttachedGod() == RequiredGod;
232 /* Optimization, GetTruePrice() may be rather slow */
233 if (((MinPrice == 0 && MaxPrice == MAX_PRICE) || (Config & BROKEN && ConfigFlags & IGNORE_BROKEN_PRICE)) && GodOK) return Item;
234 sLong Price = Item->GetTruePrice();
235 if (Item->HandleInPairs()) Price <<= 1;
236 if (Price >= MinPrice && Price <= MaxPrice && GodOK) return Item;
237 delete Item;
240 if (c0 == 25 && RequiredGod) return 0;
241 MinPrice = MinPrice * 7 >> 3;
242 MaxPrice = MaxPrice * 9 >> 3;
247 character *protosystem::CreateMonster (int MinDanger, int MaxDanger, int SpecialFlags) {
248 std::vector<configid> Possible;
249 character* Monster = 0;
251 for (int c = 0; !Monster; ++c) {
252 for (int Type = 1; Type < protocontainer<character>::GetSize(); ++Type) {
253 const character::prototype* Proto = protocontainer<character>::GetProto(Type);
254 const character::database*const* ConfigData = Proto->GetConfigData();
255 int ConfigSize = Proto->GetConfigSize();
257 for (int c = 0; c < ConfigSize; ++c) {
258 const character::database* DataBase = ConfigData[c];
260 if (!DataBase->IsAbstract && DataBase->CanBeGenerated && DataBase->CanBeWished && !DataBase->IsUnique &&
261 (DataBase->Frequency == 10000 || DataBase->Frequency > RAND_GOOD(10000)))
263 configid ConfigID(Type, DataBase->Config);
265 if ((MinDanger > 0 || MaxDanger < 1000000) && c < 25) {
266 const dangerid& DangerID = game::GetDangerMap().find(ConfigID)->second;
267 double RawDanger = SpecialFlags & NO_EQUIPMENT ? DangerID.NakedDanger : DangerID.EquippedDanger;
268 int Danger = int(DataBase->DangerModifier == 100 ? RawDanger * 1000 : RawDanger * 100000 / DataBase->DangerModifier);
269 if (Danger < MinDanger || Danger > MaxDanger) continue;
272 Possible.push_back(ConfigID);
277 if (Possible.empty()) {
278 MinDanger = (MinDanger > 0 ? Max(MinDanger * 3 >> 2, 1) : 0);
279 MaxDanger = (MaxDanger < 1000000 ? Min(MaxDanger * 5 >> 2, 999999) : 1000000);
280 continue;
283 configid Chosen = Possible[RAND_GOOD(Possible.size())];
284 Monster = protocontainer<character>::GetProto(Chosen.Type)->Spawn(Chosen.Config, SpecialFlags);
285 Monster->SignalGeneration();
286 Monster->SetTeam(game::GetTeam(MONSTER_TEAM));
289 return Monster;
293 template <class type> std::pair<int, int> CountCorrectNameLetters (const typename type::database *DataBase, cfestring &Identifier) {
294 std::pair<int, int> Result(0, 0);
296 if (!DataBase->NameSingular.IsEmpty()) ++Result.second;
297 if (festring::IgnoreCaseFind(Identifier, " " + DataBase->NameSingular + ' ') != festring::NPos) Result.first += DataBase->NameSingular.GetSize();
298 if (!DataBase->Adjective.IsEmpty()) ++Result.second;
299 if (DataBase->Adjective.GetSize() && festring::IgnoreCaseFind(Identifier, " " + DataBase->Adjective + ' ') != festring::NPos) Result.first += DataBase->Adjective.GetSize();
300 if (!DataBase->PostFix.IsEmpty()) ++Result.second;
301 if (DataBase->PostFix.GetSize() && festring::IgnoreCaseFind(Identifier, " " + DataBase->PostFix + ' ') != festring::NPos) Result.first += DataBase->PostFix.GetSize();
303 for (uInt c = 0; c < DataBase->Alias.Size; ++c) {
304 if (festring::IgnoreCaseFind(Identifier, " " + DataBase->Alias[c] + ' ') != festring::NPos) Result.first += DataBase->Alias[c].GetSize();
307 return Result;
311 template <class type> std::pair<const typename type::prototype *, int> SearchForProto (cfestring &What, truth Output) {
312 typedef typename type::prototype prototype;
313 typedef typename type::database database;
315 festring Identifier;
316 Identifier << ' ' << What << ' ';
317 truth Illegal = false, Conflict = false;
318 truth BrokenRequested = (festring::IgnoreCaseFind(Identifier, " broken ") != festring::NPos);
319 std::pair<const prototype *, int> ID(0, 0);
320 std::pair<int, int> Best(0, 0);
322 for (int c = 1; c < protocontainer<type>::GetSize(); ++c) {
323 const prototype *Proto = protocontainer<type>::GetProto(c);
324 const database *const *ConfigData = Proto->GetConfigData();
325 int ConfigSize = Proto->GetConfigSize();
327 for (int c = 0; c < ConfigSize; ++c) {
328 if (!ConfigData[c]->IsAbstract) {
329 if (BrokenRequested == !(ConfigData[c]->Config & BROKEN)) continue;
330 std::pair<int, int> Correct = CountCorrectNameLetters<type>(ConfigData[c], Identifier);
331 if (Correct == Best) {
332 Conflict = true;
333 } else if (Correct.first > Best.first || (Correct.first == Best.first && Correct.second < Best.second)) {
334 if (ConfigData[c]->CanBeWished || game::WizardModeIsActive()) {
335 ID.first = Proto;
336 ID.second = ConfigData[c]->Config;
337 Best = Correct;
338 Conflict = false;
339 } else {
340 Illegal = true;
347 if (Output) {
348 if (!Best.first) {
349 if (Illegal) {
350 ADD_MESSAGE("You hear a booming voice: \"No, mortal! This will not be done!\"");
351 } else {
352 ADD_MESSAGE("What a strange wish!");
354 } else if (Conflict) {
355 ADD_MESSAGE("Be more precise!");
356 return std::pair<const prototype*, int>(0, 0);
360 return ID;
364 character* protosystem::CreateMonster (cfestring &What, int SpecialFlags, truth Output) {
365 std::pair<const character::prototype*, int> ID = SearchForProto<character>(What, Output);
366 if (ID.first) {
367 character *Char = ID.first->Spawn(ID.second, SpecialFlags);
368 if (!Char->HasBeenSeen() && !game::WizardModeIsActive()) {
369 ADD_MESSAGE("You have no idea what this creature is like.");
370 //delete Char;
371 //k8:delete Char;
372 Char->SendToHell(); // equipment
373 return 0;
375 return Char;
377 return 0;
381 item* protosystem::CreateItem (cfestring &What, truth Output) {
382 std::pair<const item::prototype*, int> ID = SearchForProto<item>(What, Output);
383 if (ID.first) {
384 item* Item = ID.first->Spawn(ID.second);
385 festring Q = "Do you want to wish for ";
386 Item->AddName(Q, INDEFINITE|STRIPPED);
387 Q << "?";
388 if (!game::TruthQuestion(Q)) { delete Item; return 0; }
389 return Item;
391 return 0;
395 material* protosystem::CreateMaterial (cfestring& What, sLong Volume, truth Output) {
396 for (int c1 = 1; c1 < protocontainer<material>::GetSize(); ++c1) {
397 const material::prototype* Proto = protocontainer<material>::GetProto(c1);
398 const material::database*const* ConfigData = Proto->GetConfigData();
399 int ConfigSize = Proto->GetConfigSize();
401 for (int c2 = 1; c2 < ConfigSize; ++c2) {
402 if (ConfigData[c2]->NameStem == What) {
403 if (ConfigData[c2]->CommonFlags & CAN_BE_WISHED || game::WizardModeIsActive()) {
404 return ConfigData[c2]->ProtoType->Spawn(ConfigData[c2]->Config, Volume);
406 if (Output) {
407 ADD_MESSAGE("You hear a booming voice: \"No, mortal! This will not be done!\"");
408 return 0;
414 if (Output) ADD_MESSAGE("There is no such material.");
416 return 0;
420 //#ifdef WIZARD
422 void protosystem::CreateEveryCharacter (charactervector &Character) {
423 for (int c1 = 1; c1 < protocontainer<character>::GetSize(); ++c1) {
424 const character::prototype* Proto = protocontainer<character>::GetProto(c1);
425 const character::database*const* ConfigData = Proto->GetConfigData();
426 int ConfigSize = Proto->GetConfigSize();
427 for (int c2 = 0; c2 < ConfigSize; ++c2) {
428 if (!ConfigData[c2]->IsAbstract) Character.push_back(Proto->Spawn(ConfigData[c2]->Config));
434 void protosystem::CreateEveryItem (itemvectorvector &Item) {
435 for (int c = 1; c < protocontainer<item>::GetSize(); ++c) {
436 const item::prototype* Proto = protocontainer<item>::GetProto(c);
437 const item::database*const* ConfigData = Proto->GetConfigData();
438 int ConfigSize = Proto->GetConfigSize();
439 for (int c2 = 0; c2 < ConfigSize; ++c2) {
440 if (!ConfigData[c2]->IsAbstract && ConfigData[c2]->IsAutoInitializable) {
441 Item.push_back(itemvector(1, Proto->Spawn(ConfigData[c2]->Config)));
448 void protosystem::CreateEveryMaterial (std::vector<material*> &Material) {
449 for (int c1 = 1; c1 < protocontainer<material>::GetSize(); ++c1) {
450 const material::prototype* Proto = protocontainer<material>::GetProto(c1);
451 const material::database*const* ConfigData = Proto->GetConfigData();
452 int ConfigSize = Proto->GetConfigSize();
453 for (int c2 = 1; c2 < ConfigSize; ++c2) {
454 Material.push_back(Proto->Spawn(ConfigData[c2]->Config));
459 //#endif
462 void protosystem::CreateEveryNormalEnemy (charactervector& EnemyVector) {
463 for (int c = 1; c < protocontainer<character>::GetSize(); ++c) {
464 const character::prototype* Proto = protocontainer<character>::GetProto(c);
465 const character::database*const* ConfigData = Proto->GetConfigData();
466 int ConfigSize = Proto->GetConfigSize();
467 for (int c2 = 0; c2 < ConfigSize; ++c2) {
468 if (!ConfigData[c2]->IsAbstract && !ConfigData[c2]->IsUnique && ConfigData[c2]->CanBeGenerated) {
469 EnemyVector.push_back(Proto->Spawn(ConfigData[c2]->Config, NO_PIC_UPDATE|NO_EQUIPMENT_PIC_UPDATE));
476 void protosystem::Initialize () {
477 typedef item::prototype prototype;
478 typedef item::database database;
479 int c;
481 for (c = 1; c < protocontainer<item>::GetSize(); ++c) {
482 const prototype *Proto = protocontainer<item>::GetProtoData()[c];
483 if (!Proto->GetConfigData()) {
484 ABORT("Seems that database is missing <%s>!", Proto->GetClassID());
486 ItemConfigDataSize += Proto->GetConfigSize();
487 if (Proto->GetConfigData()[0]->IsAbstract) --ItemConfigDataSize;
490 ItemConfigData = new database*[ItemConfigDataSize];
491 int Index = 0;
493 for (c = 1; c < protocontainer<item>::GetSize(); ++c) {
494 const prototype* Proto = protocontainer<item>::GetProtoData()[c];
495 const database*const* ProtoConfigData = Proto->GetConfigData();
496 const database* MainDataBase = *ProtoConfigData;
498 if (!MainDataBase->IsAbstract) ItemConfigData[Index++] = const_cast<database*>(MainDataBase);
500 int ConfigSize = Proto->GetConfigSize();
502 for (int c2 = 1; c2 < ConfigSize; ++c2) ItemConfigData[Index++] = const_cast<database*>(ProtoConfigData[c2]);
505 database **DataBaseBuffer = new database*[ItemConfigDataSize];
507 for (int CategoryIndex = 0, Category = 1; CategoryIndex < ITEM_CATEGORIES; ++CategoryIndex, Category <<= 1) {
508 sLong TotalPossibility = 0;
509 int CSize = 0;
511 for (int c = 0; c < ItemConfigDataSize; ++c) {
512 database* DataBase = ItemConfigData[c];
514 if (DataBase->Category == Category) {
515 DataBaseBuffer[CSize++] = DataBase;
516 TotalPossibility += DataBase->Possibility;
517 DataBase->PartialCategoryPossibilitySum = TotalPossibility;
521 ItemCategoryData[CategoryIndex] = new database*[CSize];
522 ItemCategorySize[CategoryIndex] = CSize;
523 ItemCategoryPossibility[CategoryIndex] = TotalPossibility;
524 memmove(ItemCategoryData[CategoryIndex], DataBaseBuffer, CSize*sizeof(database*));
527 delete [] DataBaseBuffer;
529 for (c = 0; c < ItemConfigDataSize; ++c) {
530 database* DataBase = ItemConfigData[c];
531 TotalItemPossibility += DataBase->Possibility;
532 DataBase->PartialPossibilitySum = TotalItemPossibility;
537 void protosystem::InitCharacterDataBaseFlags () {
538 for (int c1 = 1; c1 < protocontainer<character>::GetSize(); ++c1) {
539 const character::prototype* Proto = protocontainer<character>::GetProto(c1);
540 character::database** ConfigData = Proto->ConfigData;
541 int ConfigSize = Proto->GetConfigSize();
542 for (int c2 = 0; c2 < ConfigSize; ++c2) {
543 if (!ConfigData[c2]->AutomaticallySeen) ConfigData[c2]->Flags = 0; else ConfigData[c2]->Flags = HAS_BEEN_SEEN;
549 void protosystem::SaveCharacterDataBaseFlags (outputfile &SaveFile) {
550 for (int c1 = 1; c1 < protocontainer<character>::GetSize(); ++c1) {
551 const character::prototype* Proto = protocontainer<character>::GetProto(c1);
552 const character::database*const* ConfigData = Proto->ConfigData;
553 int ConfigSize = Proto->GetConfigSize();
554 for (int c2 = 0; c2 < ConfigSize; ++c2) SaveFile << ConfigData[c2]->Flags;
559 void protosystem::LoadCharacterDataBaseFlags (inputfile &SaveFile) {
560 for (int c1 = 1; c1 < protocontainer<character>::GetSize(); ++c1) {
561 const character::prototype* Proto = protocontainer<character>::GetProto(c1);
562 character::database** ConfigData = Proto->ConfigData;
563 int ConfigSize = Proto->GetConfigSize();
564 for (int c2 = 0; c2 < ConfigSize; ++c2) SaveFile >> ConfigData[c2]->Flags;
569 void protosystem::CreateEverySeenCharacter (charactervector &Character) {
570 for (int c1 = 1; c1 < protocontainer<character>::GetSize(); ++c1) {
571 const character::prototype* Proto = protocontainer<character>::GetProto(c1);
572 const character::database*const* ConfigData = Proto->GetConfigData();
573 int ConfigSize = Proto->GetConfigSize();
574 for (int c2 = 0; c2 < ConfigSize; ++c2) {
575 if (!ConfigData[c2]->IsAbstract && ConfigData[c2]->Flags & HAS_BEEN_SEEN) {
576 character* Char = Proto->Spawn(ConfigData[c2]->Config);
577 Char->SetAssignedName("");
578 Character.push_back(Char);
585 void protosystem::CreateEveryMaterial (std::vector<material*> &Material, const god *God, ccharacter *Char) {
586 for (int c1 = 1; c1 < protocontainer<material>::GetSize(); ++c1) {
587 const material::prototype* Proto = protocontainer<material>::GetProto(c1);
588 const material::database*const* ConfigData = Proto->GetConfigData();
589 int ConfigSize = Proto->GetConfigSize();
590 for (int c2 = 1; c2 < ConfigSize; ++c2) {
591 if (God->LikesMaterial(ConfigData[c2], Char)) Material.push_back(Proto->Spawn(ConfigData[c2]->Config));