3 * Iter Vehemens ad Necem (IVAN)
4 * Copyright (C) Timo Kiviluoto
5 * Released under the GNU General
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
;
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()) {
50 if (!allowed
) continue;
53 if (lvl
&& lvl
->GetLevelScript() && lvl
->GetLevelScript()->GetTag() && !lvl
->GetLevelScript()->GetTag()->IsEmpty()) {
54 const fearray
<festring
> &tlist
= DataBase
->LevelTags
;
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;
68 const fearray
<festring
> &tlist
= DataBase
->LevelTags
;
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
);
81 Possible
.push_back(ConfigID
);
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;
95 fprintf(stderr
, "WARNING: WTF?! (protosystem::BalancedCreateMonster)\n");
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
);
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
));
121 /* This line is never reached, but it prevents warnings given by some (stupid) compilers. */
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;
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
);
163 if (RequiredCategory
== ANY_CATEGORY
) {
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];
177 sLong B
= PossibleCategorySize
[Category
] - 1;
179 sLong C
= (A
+ B
) >> 1;
181 if(ChosenCategory
[C
]->*PartialPossibilitySumPtr
> Rand
) B
= C
; else A
= C
;
183 ChosenDataBase
= ChosenCategory
[B
];
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()) {
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;
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
;
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);
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
));
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();
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
;
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
) {
333 } else if (Correct
.first
> Best
.first
|| (Correct
.first
== Best
.first
&& Correct
.second
< Best
.second
)) {
334 if (ConfigData
[c
]->CanBeWished
|| game::WizardModeIsActive()) {
336 ID
.second
= ConfigData
[c
]->Config
;
350 ADD_MESSAGE("You hear a booming voice: \"No, mortal! This will not be done!\"");
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);
364 character
* protosystem::CreateMonster (cfestring
&What
, int SpecialFlags
, truth Output
) {
365 std::pair
<const character::prototype
*, int> ID
= SearchForProto
<character
>(What
, Output
);
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.");
372 Char
->SendToHell(); // equipment
381 item
* protosystem::CreateItem (cfestring
&What
, truth Output
) {
382 std::pair
<const item::prototype
*, int> ID
= SearchForProto
<item
>(What
, Output
);
384 item
* Item
= ID
.first
->Spawn(ID
.second
);
385 festring Q
= "Do you want to wish for ";
386 Item
->AddName(Q
, INDEFINITE
|STRIPPED
);
388 if (!game::TruthQuestion(Q
)) { delete Item
; 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
);
407 ADD_MESSAGE("You hear a booming voice: \"No, mortal! This will not be done!\"");
414 if (Output
) ADD_MESSAGE("There is no such material.");
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
));
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
;
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
];
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;
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
));