`NaturalTeam` for characters
[k8-i-v-a-n.git] / src / game / database.cpp
blob92d5bc9ef73d4a8e773e682c854cf3c6b3a5aa8d
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 */
13 #include <stack>
14 #include "feparse.h"
17 int CreateConfigTable (databasebase ***ConfigTable, databasebase ***TempTable,
18 databasebase **ConfigArray, sLong *TempTableInfo, int Type, int Configs, int TempTables)
20 memset(ConfigTable, 0, CONFIG_TABLE_SIZE*sizeof(databasebase **));
21 for (int c = 0; c < Configs; ++c) {
22 int Config = ConfigArray[c]->Config;
23 int Hash = (Config >> 8) ^ (Config & 0xFF);
24 if ((TempTableInfo[Hash] & 0xFFFF) != Type) {
25 TempTable[0][Hash] = ConfigArray[c];
26 TempTableInfo[Hash] = Type | 0x10000;
27 } else {
28 int Conflicts = (TempTableInfo[Hash] & 0xFFFF0000) >> 16;
29 if (Conflicts == TempTables) TempTable[TempTables++] = new databasebase *[CONFIG_TABLE_SIZE];
30 TempTable[Conflicts][Hash] = ConfigArray[c];
31 TempTableInfo[Hash] += 0x10000;
34 for (int c1 = 0; c1 < CONFIG_TABLE_SIZE; ++c1) {
35 if ((TempTableInfo[c1] & 0xFFFF) == Type) {
36 int Entries = (TempTableInfo[c1] & 0xFFFF0000) >> 16;
37 ConfigTable[c1] = new databasebase*[Entries + 1];
38 for (int c2 = 0; c2 < Entries; ++c2) ConfigTable[c1][c2] = TempTable[c2][c1];
39 ConfigTable[c1][Entries] = 0;
42 return TempTables;
46 static void collectHandler (festring &dest, std::stack<TextInput *> &infStack, TextInput **iff) {
47 TextInput *inFile = *iff;
48 festring Word = inFile->ReadWord(true);
49 dest << "on " << Word << "\n{\n";
50 if (inFile->ReadWord() != "{") ABORT("'{' missing in datafile %s line %d!", inFile->GetFileName().CStr(), inFile->TokenLine());
51 int cnt = 1;
52 truth inStr = false;
53 for (;;) {
54 int ch = inFile->GetChar();
55 if (ch == EOF) {
56 if (infStack.empty()) ABORT("'}' missing in datafile %s line %d!", inFile->GetFileName().CStr(), inFile->TokenLine());
57 delete inFile;
58 *iff = inFile = infStack.top();
59 infStack.pop();
60 continue;
62 dest << (char)ch;
63 if (inStr) {
64 if (ch == '"') inStr = false;
65 else if (ch == '\\') {
66 ch = inFile->GetChar();
67 if (ch == EOF) ABORT("Unexpected end of file %s!", inFile->GetFileName().CStr());
68 dest << (char)ch;
70 continue;
72 if (ch == '}') {
73 if (--cnt < 1) break;
74 } else if (ch == '{') {
75 cnt++;
76 } else if (ch == '"') {
77 inStr = true;
80 dest << "\n";
84 template <class type> void databasecreator<type>::ReadFrom (const festring &baseFileName) {
85 std::stack<TextInput *> infStack;
86 for (int fno = 99; fno >= -1; fno--) {
87 festring cfname;
88 cfname << game::GetGameDir() << "script/" << baseFileName;
89 if (fno >= 0) {
90 char bnum[8];
91 sprintf(bnum, "_%02d", fno);
92 cfname << bnum;
94 cfname << ".dat";
95 if (!inputfile::fileExists(cfname)) continue;
96 TextInput *ifl = new TextInputFile(cfname, &game::GetGlobalValueMap(), false);
97 if (!ifl->IsOpen()) {
98 delete ifl;
99 continue;
101 infStack.push(ifl);
105 for (size_t f = 0; f < infStack.size(); f++) {
106 inputfile *inFile = infStack.at(f);
107 fprintf(stderr, "found: %s\n", inFile->GetFileName().CStr());
111 typedef typename type::prototype prototype;
112 festring Word, defName;
113 database *TempConfig[1024];
114 databasebase **TempTable[1024];
115 sLong TempTableInfo[CONFIG_TABLE_SIZE];
116 int TempTables = 1;
117 databasebase *FirstTempTable[CONFIG_TABLE_SIZE];
118 TempTable[0] = FirstTempTable;
119 memset(TempTableInfo, 0, CONFIG_TABLE_SIZE*sizeof(sLong));
120 CreateDataBaseMemberMap();
121 while (!infStack.empty()) {
122 TextInput *inFile = infStack.top();
123 infStack.pop();
124 inFile->setGetVarCB(game::ldrGetVar);
125 //fprintf(stderr, "MAIN: %s\n", inFile->GetFileName().CStr());
126 for (inFile->ReadWord(Word, false); !inFile->Eof(); inFile->ReadWord(Word, false)) {
127 if (Word == "Include") {
128 Word = inFile->ReadWord();
129 if (inFile->ReadWord() != ";") ABORT("Invalid terminator in file %s at line %d!", inFile->GetFileName().CStr(), inFile->TokenLine());
130 //fprintf(stderr, "loading: %s\n", Word.CStr());
131 TextInput *incf = new TextInputFile(game::GetGameDir()+"script/"+Word, &game::GetGlobalValueMap());
132 infStack.push(inFile);
133 inFile = incf;
134 inFile->setGetVarCB(game::ldrGetVar);
135 continue;
137 if (Word == "Message") {
138 Word = inFile->ReadWord();
139 if (inFile->ReadWord() != ";") ABORT("Invalid terminator in file %s at line %d!", inFile->GetFileName().CStr(), inFile->TokenLine());
140 fprintf(stderr, "MESSAGE: %s\n", Word.CStr());
141 continue;
143 ////////
144 truth doExtend = false, doOverride = false;
145 if (Word == "Extend") {
146 Word = inFile->ReadWord();
147 doExtend = true;
148 } else if (Word == "Override" || Word == "Redefine") {
149 Word = inFile->ReadWord();
150 doOverride = true;
152 ////////
153 defName = Word;
154 int Type = protocontainer<type>::SearchCodeName(Word);
155 if (!Type) ABORT("Odd term <%s> encountered in %s datafile %s line %d!", Word.CStr(), protocontainer<type>::GetMainClassID(), inFile->GetFileName().CStr(), inFile->TokenLine());
156 prototype *Proto = protocontainer<type>::GetProtoData()[Type];
157 if (!Proto) ABORT("Something weird with <%s> in file %s at line %d!", defName.CStr(), inFile->GetFileName().CStr(), inFile->TokenLine());
158 database *DataBase;
159 int Configs;
160 if (doOverride) {
161 if (!Proto->ConfigData) ABORT("Can't override undefined <%s> in file %s at line %d!", defName.CStr(), inFile->GetFileName().CStr(), inFile->TokenLine());
162 delete [] Proto->ConfigData;
163 Proto->ConfigData = NULL;
164 Proto->ConfigSize = 0;
166 if (doExtend) {
167 if (!Proto->ConfigData) ABORT("Can't extend undefined <%s> in file %s at line %d!", defName.CStr(), inFile->GetFileName().CStr(), inFile->TokenLine());
168 DataBase = Proto->ConfigData[0];
169 Configs = Proto->ConfigSize;
170 for (int f = 0; f < Configs; f++) TempConfig[f] = Proto->ConfigData[f];
171 delete [] Proto->ConfigData;
172 Proto->ConfigData = NULL;
173 Proto->ConfigSize = 0;
174 } else {
175 if (Proto->ConfigData) ABORT("Can't redefine <%s> in file %s at line %d!", defName.CStr(), inFile->GetFileName().CStr(), inFile->TokenLine());
176 if (Proto->Base && !Proto->Base->ConfigData) ABORT("Database has no description of base prototype <%s> in file %s at line %d!", Proto->Base->GetClassID(), inFile->GetFileName().CStr(), inFile->TokenLine());
177 DataBase = Proto->Base ? new database(**Proto->Base->ConfigData) : new database;
178 DataBase->InitDefaults(Proto, 0, "default");
179 TempConfig[0] = DataBase;
180 Configs = 1;
182 if (inFile->ReadWord() != "{") ABORT("'{' missing in %s datafile %s line %d!", protocontainer<type>::GetMainClassID(), inFile->GetFileName().CStr(), inFile->TokenLine());
183 //for (inFile->ReadWord(Word); Word != "}"; inFile->ReadWord(Word))
184 for (;;) {
185 inFile->ReadWord(Word, false);
186 if (Word == "" && inFile->Eof()) {
187 if (infStack.empty()) ABORT("'}' missing in %s datafile %s line %d!", protocontainer<type>::GetMainClassID(), inFile->GetFileName().CStr(), inFile->TokenLine());
188 delete inFile;
189 inFile = infStack.top();
190 infStack.pop();
191 continue;
193 //fprintf(stderr, "D: %d; <%s>\n", (int)infStack.size(), Word.CStr());
194 if (Word == "}") break;
196 if (Word == "Include") {
197 Word = inFile->ReadWord();
198 if (inFile->ReadWord() != ";") ABORT("Invalid terminator in file %s at line %d!", inFile->GetFileName().CStr(), inFile->TokenLine());
199 //fprintf(stderr, "loading: %s\n", Word.CStr());
200 TextInput *incf = new TextInputFile(game::GetGameDir()+"script/"+Word, &game::GetGlobalValueMap());
201 infStack.push(inFile);
202 inFile = incf;
203 inFile->setGetVarCB(game::ldrGetVar);
204 continue;
206 if (Word == "Message") {
207 Word = inFile->ReadWord();
208 if (inFile->ReadWord() != ";") ABORT("Invalid terminator in file %s at line %d!", inFile->GetFileName().CStr(), inFile->TokenLine());
209 fprintf(stderr, "MESSAGE: %s\n", Word.CStr());
210 continue;
212 if (Word == "Config") {
213 sLong ConfigNumber = -1;
214 truth isString = false;
215 festring fname;
216 fname = inFile->ReadStringOrNumberKeepStr(&ConfigNumber, &isString);
217 if (isString) {
218 // include file
219 //fprintf(stderr, "loading: %s\n", fname.CStr());
220 TextInput *incf = new TextInputFile(game::GetGameDir()+"script/"+fname, &game::GetGlobalValueMap());
221 infStack.push(inFile);
222 inFile = incf;
223 } else {
224 //fprintf(stderr, "new config %d (%s) for %s\n", ConfigNumber, inFile->numStr().CStr(), defName.CStr());
225 database *ConfigDataBase = new database(*Proto->ChooseBaseForConfig(TempConfig, Configs, ConfigNumber));
226 ConfigDataBase->InitDefaults(Proto, ConfigNumber, inFile->numStr());
227 TempConfig[Configs++] = ConfigDataBase;
228 if (inFile->ReadWord() != "{") ABORT("'{' missing in %s datafile %s line %d!", protocontainer<type>::GetMainClassID(), inFile->GetFileName().CStr(), inFile->TokenLine());
229 for (inFile->ReadWord(Word); Word != "}"; inFile->ReadWord(Word)) {
230 if (Word == "on") {
231 collectHandler(Proto->mOnEvents, infStack, &inFile);
232 continue;
234 if (!AnalyzeData(*inFile, Word, *ConfigDataBase)) ABORT("Illegal datavalue %s found while building up %s config #%d, file %s, line %d!", Word.CStr(), Proto->GetClassID(), ConfigNumber, inFile->GetFileName().CStr(), inFile->TokenLine());
236 ConfigDataBase->PostProcess();
238 continue;
240 if (Word == "on") {
241 collectHandler(Proto->mOnEvents, infStack, &inFile);
242 continue;
244 if (!AnalyzeData(*inFile, Word, *DataBase)) ABORT("Illegal datavalue %s found while building up %s, file %s, line %d!", Word.CStr(), Proto->GetClassID(), inFile->GetFileName().CStr(), inFile->TokenLine());
246 DataBase->PostProcess();
247 //Configs = Proto->CreateSpecialConfigurations(TempConfig, Configs);
248 Proto->ConfigData = new database *[Configs];
249 Proto->ConfigSize = Configs;
250 memmove(Proto->ConfigData, TempConfig, Configs*sizeof(database *));
252 delete inFile;
255 int c1;
256 for (c1 = 0; c1 < SPECIAL_CONFIGURATION_GENERATION_LEVELS; ++c1) {
257 for (int c2 = 1; c2 < protocontainer<type>::GetSize(); ++c2) {
258 prototype *Proto = protocontainer<type>::GetProtoData()[c2];
259 int Configs = Proto->ConfigSize;
260 memmove(TempConfig, Proto->ConfigData, Configs*sizeof(database *));
261 Configs = Proto->CreateSpecialConfigurations(TempConfig, Configs, c1);
262 if (Proto->ConfigSize != Configs) {
263 delete [] Proto->ConfigData;
264 Proto->ConfigData = new database *[Configs];
265 Proto->ConfigSize = Configs;
266 memmove(Proto->ConfigData, TempConfig, Configs*sizeof(database *));
270 for (c1 = 1; c1 < protocontainer<type>::GetSize(); ++c1) {
271 prototype *Proto = protocontainer<type>::GetProtoData()[c1];
272 TempTables =
273 CreateConfigTable(reinterpret_cast<databasebase ***>(Proto->ConfigTable),
274 TempTable,
275 reinterpret_cast<databasebase **>(Proto->ConfigData),
276 TempTableInfo, c1, Proto->ConfigSize, TempTables);
278 for (c1 = 1; c1 < TempTables; ++c1) delete [] TempTable[c1];
279 GetDataBaseMemberMap().clear();
283 template <class type> int databasecreator<type>::CreateDivineConfigurations (const prototype *Proto, database **TempConfig, int Configs) {
284 int OldConfigs = Configs;
285 for (int c1 = 1; c1 < protocontainer<god>::GetSize(); ++c1) {
286 database *ConfigDataBase = 0;
287 int c2;
288 festring dcfgname = "divine";
289 for (c2 = 1; c2 < OldConfigs; ++c2) {
290 ConfigDataBase = TempConfig[c2];
291 if (ConfigDataBase->Config == c1) {
292 dcfgname << " ";
293 dcfgname << ConfigDataBase->CfgStrName;
294 break;
297 truth Created = false;
298 if (c2 == OldConfigs) {
299 ConfigDataBase = new database(**TempConfig);
300 ConfigDataBase->InitDefaults(Proto, c1, dcfgname);
301 Created = true;
303 ConfigDataBase->AttachedGod = c1;
304 ConfigDataBase->PostFix << "of " << festring(protocontainer<god>::GetProto(c1)->GetClassID()).CapitalizeCopy();
305 if (Created) TempConfig[Configs++] = ConfigDataBase;
307 return Configs;
311 template int databasecreator<character>::CreateDivineConfigurations (const prototype *, database **, int);
312 template int databasecreator<item>::CreateDivineConfigurations (const prototype *, database **, int);
313 template int databasecreator<olterrain>::CreateDivineConfigurations (const prototype *, database **, int);
316 template <class database, class member> struct databasemember : public databasememberbase<database> {
317 databasemember (member Member) : Member(Member) {}
318 virtual void ReadData (database &DataBase, TextInput &SaveFile) { ::ReadData(DataBase.*Member, SaveFile); }
319 member Member;
323 template <class database, class member> void AddMember(std::map<festring, databasememberbase<database>*>& Map, cchar* Str, member Member)
325 Map.insert(std::pair<festring, databasememberbase<database>*>(Str, new databasemember<database, member>(Member)));
329 /* Explicit instantiations seem to increase compile speed greatly here... */
331 #define INST_ADD_MEMBER(type, member) \
332 template void AddMember<type##database, member type##database::*>(std::map<festring, databasememberbase<type##database>*>&, cchar*, member type##database::*)
334 INST_ADD_MEMBER(character, int);
335 //INST_ADD_MEMBER(character, sLong); //k8:64
336 INST_ADD_MEMBER(character, packcol16);
337 INST_ADD_MEMBER(character, col24);
338 INST_ADD_MEMBER(character, packv2);
339 INST_ADD_MEMBER(character, festring);
340 INST_ADD_MEMBER(character, fearray<sLong>);
341 INST_ADD_MEMBER(character, fearray<festring>);
342 INST_ADD_MEMBER(character, contentscript<item>);
344 INST_ADD_MEMBER(item, int);
345 //INST_ADD_MEMBER(item, sLong); //k8:64
346 INST_ADD_MEMBER(item, col24);
347 INST_ADD_MEMBER(item, v2);
348 INST_ADD_MEMBER(item, festring);
349 INST_ADD_MEMBER(item, fearray<sLong>);
350 INST_ADD_MEMBER(item, fearray<festring>);
352 INST_ADD_MEMBER(glterrain, int);
353 //INST_ADD_MEMBER(glterrain, sLong); //k8:64
354 INST_ADD_MEMBER(glterrain, v2);
355 INST_ADD_MEMBER(glterrain, festring);
356 INST_ADD_MEMBER(glterrain, fearray<sLong>);
358 INST_ADD_MEMBER(olterrain, int);
359 //INST_ADD_MEMBER(olterrain, sLong); //k8:64
360 INST_ADD_MEMBER(olterrain, v2);
361 INST_ADD_MEMBER(olterrain, festring);
362 INST_ADD_MEMBER(olterrain, fearray<sLong>);
363 INST_ADD_MEMBER(olterrain, fearray<contentscript<item> >);
365 INST_ADD_MEMBER(material, int);
366 //INST_ADD_MEMBER(material, sLong); //k8:64
367 INST_ADD_MEMBER(material, col24);
368 INST_ADD_MEMBER(material, festring);
369 INST_ADD_MEMBER(material, contentscript<item>);
371 #define ADD_MEMBER(data) AddMember(Map, #data, &database::data);
373 template<> void databasecreator<character>::CreateDataBaseMemberMap () {
374 databasemembermap &Map = GetDataBaseMemberMap();
375 ADD_MEMBER(DefaultArmStrength);
376 ADD_MEMBER(DefaultLegStrength);
377 ADD_MEMBER(DefaultDexterity);
378 ADD_MEMBER(DefaultAgility);
379 ADD_MEMBER(DefaultEndurance);
380 ADD_MEMBER(DefaultPerception);
381 ADD_MEMBER(DefaultIntelligence);
382 ADD_MEMBER(DefaultWisdom);
383 ADD_MEMBER(DefaultWillPower);
384 ADD_MEMBER(DefaultCharisma);
385 ADD_MEMBER(DefaultMana);
386 ADD_MEMBER(DefaultMoney);
387 ADD_MEMBER(TotalSize);
388 ADD_MEMBER(CanRead);
389 ADD_MEMBER(Sex);
390 ADD_MEMBER(CanBeGenerated);
391 ADD_MEMBER(CriticalModifier);
392 ADD_MEMBER(StandVerb);
393 ADD_MEMBER(CanOpen);
394 ADD_MEMBER(Frequency);
395 ADD_MEMBER(EnergyResistance);
396 ADD_MEMBER(FireResistance);
397 ADD_MEMBER(PoisonResistance);
398 ADD_MEMBER(ElectricityResistance);
399 ADD_MEMBER(AcidResistance);
400 ADD_MEMBER(SoundResistance);
401 ADD_MEMBER(IsUnique);
402 ADD_MEMBER(ConsumeFlags);
403 ADD_MEMBER(TotalVolume);
404 ADD_MEMBER(HeadBitmapPos);
405 ADD_MEMBER(TorsoBitmapPos);
406 ADD_MEMBER(ArmBitmapPos);
407 ADD_MEMBER(LegBitmapPos);
408 ADD_MEMBER(RightArmBitmapPos);
409 ADD_MEMBER(LeftArmBitmapPos);
410 ADD_MEMBER(RightLegBitmapPos);
411 ADD_MEMBER(LeftLegBitmapPos);
412 ADD_MEMBER(GroinBitmapPos);
413 ADD_MEMBER(ClothColor);
414 ADD_MEMBER(SkinColor);
415 ADD_MEMBER(CapColor);
416 ADD_MEMBER(HairColor);
417 ADD_MEMBER(EyeColor);
418 ADD_MEMBER(TorsoMainColor);
419 ADD_MEMBER(BeltColor);
420 ADD_MEMBER(BootColor);
421 ADD_MEMBER(TorsoSpecialColor);
422 ADD_MEMBER(ArmMainColor);
423 ADD_MEMBER(GauntletColor);
424 ADD_MEMBER(ArmSpecialColor);
425 ADD_MEMBER(LegMainColor);
426 ADD_MEMBER(LegSpecialColor);
427 ADD_MEMBER(IsNameable);
428 ADD_MEMBER(BaseEmitation);
429 ADD_MEMBER(UsesLongArticle);
430 ADD_MEMBER(Adjective);
431 ADD_MEMBER(UsesLongAdjectiveArticle);
432 ADD_MEMBER(NameSingular);
433 ADD_MEMBER(NamePlural);
434 ADD_MEMBER(PostFix);
435 ADD_MEMBER(ArticleMode);
436 ADD_MEMBER(IsAbstract);
437 ADD_MEMBER(IsPolymorphable);
438 ADD_MEMBER(BaseUnarmedStrength);
439 ADD_MEMBER(BaseBiteStrength);
440 ADD_MEMBER(BaseKickStrength);
441 ADD_MEMBER(AttackStyle);
442 ADD_MEMBER(CanUseEquipment);
443 ADD_MEMBER(CanKick);
444 ADD_MEMBER(CanTalk);
445 ADD_MEMBER(ClassStates);
446 ADD_MEMBER(CanBeWished);
447 ADD_MEMBER(Alias);
448 ADD_MEMBER(CreateDivineConfigurations);
449 ADD_MEMBER(CreateGolemMaterialConfigurations);
450 ADD_MEMBER(Helmet);
451 ADD_MEMBER(Amulet);
452 ADD_MEMBER(Cloak);
453 ADD_MEMBER(BodyArmor);
454 ADD_MEMBER(Belt);
455 ADD_MEMBER(RightWielded);
456 ADD_MEMBER(LeftWielded);
457 ADD_MEMBER(RightRing);
458 ADD_MEMBER(LeftRing);
459 ADD_MEMBER(RightGauntlet);
460 ADD_MEMBER(LeftGauntlet);
461 ADD_MEMBER(RightBoot);
462 ADD_MEMBER(LeftBoot);
463 ADD_MEMBER(AttributeBonus);
464 ADD_MEMBER(KnownCWeaponSkills);
465 ADD_MEMBER(CWeaponSkillHits);
466 ADD_MEMBER(RightSWeaponSkillHits);
467 ADD_MEMBER(LeftSWeaponSkillHits);
468 ADD_MEMBER(PanicLevel);
469 ADD_MEMBER(CanBeCloned);
470 ADD_MEMBER(Inventory);
471 ADD_MEMBER(DangerModifier);
472 ADD_MEMBER(DefaultName);
473 ADD_MEMBER(FriendlyReplies);
474 ADD_MEMBER(HostileReplies);
475 ADD_MEMBER(CanZap);
476 ADD_MEMBER(FleshMaterial);
477 ADD_MEMBER(HasALeg);
478 ADD_MEMBER(DeathMessage);
479 ADD_MEMBER(IgnoreDanger);
480 ADD_MEMBER(HPRequirementForGeneration);
481 ADD_MEMBER(DayRequirementForGeneration);
482 ADD_MEMBER(IsExtraCoward);
483 ADD_MEMBER(SpillsBlood);
484 ADD_MEMBER(HasEyes);
485 ADD_MEMBER(HasHead);
486 ADD_MEMBER(CanThrow);
487 ADD_MEMBER(UsesNutrition);
488 ADD_MEMBER(AttackWisdomLimit);
489 ADD_MEMBER(AttachedGod);
490 ADD_MEMBER(BodyPartsDisappearWhenSevered);
491 ADD_MEMBER(CanBeConfused);
492 ADD_MEMBER(CanApply);
493 ADD_MEMBER(WieldedPosition);
494 ADD_MEMBER(NaturalSparkleFlags);
495 ADD_MEMBER(BiteCapturesBodyPart);
496 ADD_MEMBER(IsPlant);
497 ADD_MEMBER(MoveType);
498 ADD_MEMBER(DestroysWalls);
499 ADD_MEMBER(IsRooted);
500 ADD_MEMBER(BloodMaterial);
501 ADD_MEMBER(VomitMaterial);
502 ADD_MEMBER(HasSecondaryMaterial);
503 ADD_MEMBER(IsImmuneToLeprosy);
504 ADD_MEMBER(PolymorphIntelligenceRequirement);
505 ADD_MEMBER(AutomaticallySeen);
506 ADD_MEMBER(CanHear);
507 ADD_MEMBER(DefaultCommandFlags);
508 ADD_MEMBER(ConstantCommandFlags);
509 ADD_MEMBER(WillCarryItems);
510 ADD_MEMBER(ForceVomitMessage);
511 ADD_MEMBER(SweatMaterial);
512 ADD_MEMBER(Sweats);
513 ADD_MEMBER(IsImmuneToItemTeleport);
514 ADD_MEMBER(AlwaysUseMaterialAttributes);
515 ADD_MEMBER(IsEnormous);
516 ADD_MEMBER(ScienceTalkAdjectiveAttribute);
517 ADD_MEMBER(ScienceTalkSubstantiveAttribute);
518 ADD_MEMBER(ScienceTalkPrefix);
519 ADD_MEMBER(ScienceTalkName);
520 ADD_MEMBER(ScienceTalkPossibility);
521 ADD_MEMBER(ScienceTalkIntelligenceModifier);
522 ADD_MEMBER(ScienceTalkWisdomModifier);
523 ADD_MEMBER(ScienceTalkCharismaModifier);
524 ADD_MEMBER(ScienceTalkIntelligenceRequirement);
525 ADD_MEMBER(ScienceTalkWisdomRequirement);
526 ADD_MEMBER(ScienceTalkCharismaRequirement);
527 ADD_MEMBER(IsExtraFragile);
528 ADD_MEMBER(AllowUnconsciousness);
529 ADD_MEMBER(CanChoke);
530 ADD_MEMBER(IsImmuneToStickiness);
531 ADD_MEMBER(DisplacePriority);
532 ADD_MEMBER(RunDescriptionLineOne);
533 ADD_MEMBER(RunDescriptionLineTwo);
534 ADD_MEMBER(ForceCustomStandVerb);
535 ADD_MEMBER(VomittingIsUnhealthy);
536 ADD_MEMBER(AllowPlayerToChangeEquipment);
537 ADD_MEMBER(TamingDifficulty);
538 ADD_MEMBER(IsMasochist);
539 ADD_MEMBER(IsSadist);
540 ADD_MEMBER(IsCatacombCreature);
541 ADD_MEMBER(CreateUndeadConfigurations);
542 ADD_MEMBER(UndeadVersions);
543 ADD_MEMBER(UndeadAttributeModifier);
544 ADD_MEMBER(UndeadVolumeModifier);
545 ADD_MEMBER(UndeadCopyMaterials);
546 ADD_MEMBER(CanBeGeneratedOnlyInTheCatacombs);
547 ADD_MEMBER(IsAlcoholic);
548 ADD_MEMBER(IsImmuneToWhipOfThievery);
549 ADD_MEMBER(IsRangedAttacker);
550 ADD_MEMBER(WhatCategoryToThrow);
551 ADD_MEMBER(WhatWeaponConfigToThrow);
552 ADD_MEMBER(WhatThrowItemTypesToThrow);
553 ADD_MEMBER(AllowedDungeons);
554 ADD_MEMBER(LevelTags);
555 ADD_MEMBER(HomeLevel);
556 ADD_MEMBER(NaturalTeam);
560 template<> void databasecreator<item>::CreateDataBaseMemberMap () {
561 databasemembermap &Map = GetDataBaseMemberMap();
562 ADD_MEMBER(Possibility);
563 ADD_MEMBER(IsDestroyable);
564 ADD_MEMBER(CanBeWished);
565 ADD_MEMBER(IsMaterialChangeable);
566 ADD_MEMBER(WeaponCategory);
567 ADD_MEMBER(IsPolymorphSpawnable);
568 ADD_MEMBER(IsAutoInitializable);
569 ADD_MEMBER(Category);
570 ADD_MEMBER(FireResistance);
571 ADD_MEMBER(PoisonResistance);
572 ADD_MEMBER(ElectricityResistance);
573 ADD_MEMBER(AcidResistance);
574 ADD_MEMBER(SoundResistance);
575 ADD_MEMBER(StrengthModifier);
576 ADD_MEMBER(FormModifier);
577 ADD_MEMBER(DefaultSize);
578 ADD_MEMBER(DefaultMainVolume);
579 ADD_MEMBER(DefaultSecondaryVolume);
580 ADD_MEMBER(BitmapPos);
581 ADD_MEMBER(Price);
582 ADD_MEMBER(BaseEmitation);
583 ADD_MEMBER(UsesLongArticle);
584 ADD_MEMBER(Adjective);
585 ADD_MEMBER(UsesLongAdjectiveArticle);
586 ADD_MEMBER(NameSingular);
587 ADD_MEMBER(NamePlural);
588 ADD_MEMBER(PostFix);
589 ADD_MEMBER(ArticleMode);
590 ADD_MEMBER(MainMaterialConfig);
591 ADD_MEMBER(SecondaryMaterialConfig);
592 ADD_MEMBER(MaterialConfigChances);
593 ADD_MEMBER(IsAbstract);
594 ADD_MEMBER(IsPolymorphable);
595 ADD_MEMBER(Alias);
596 ADD_MEMBER(OKVisualEffects);
597 ADD_MEMBER(CanBeGeneratedInContainer);
598 ADD_MEMBER(ForcedVisualEffects);
599 ADD_MEMBER(Roundness);
600 ADD_MEMBER(GearStates);
601 ADD_MEMBER(IsTwoHanded);
602 ADD_MEMBER(CreateDivineConfigurations);
603 ADD_MEMBER(CanBeCloned);
604 ADD_MEMBER(CanBeMirrored);
605 ADD_MEMBER(BeamRange);
606 ADD_MEMBER(CanBeBroken);
607 ADD_MEMBER(WallBitmapPos);
608 ADD_MEMBER(FlexibleNameSingular);
609 ADD_MEMBER(MaxCharges);
610 ADD_MEMBER(MinCharges);
611 ADD_MEMBER(CanBePiled);
612 ADD_MEMBER(StorageVolume);
613 ADD_MEMBER(MaxGeneratedContainedItems);
614 ADD_MEMBER(AffectsArmStrength);
615 ADD_MEMBER(AffectsLegStrength);
616 ADD_MEMBER(AffectsDexterity);
617 ADD_MEMBER(AffectsAgility);
618 ADD_MEMBER(AffectsEndurance);
619 ADD_MEMBER(AffectsPerception);
620 ADD_MEMBER(AffectsIntelligence);
621 ADD_MEMBER(AffectsWisdom);
622 ADD_MEMBER(AffectsWillPower);
623 ADD_MEMBER(AffectsCharisma);
624 ADD_MEMBER(AffectsMana);
625 ADD_MEMBER(BaseEnchantment);
626 ADD_MEMBER(PriceIsProportionalToEnchantment);
627 ADD_MEMBER(InElasticityPenaltyModifier);
628 ADD_MEMBER(CanBeUsedBySmith);
629 ADD_MEMBER(AffectsCarryingCapacity);
630 ADD_MEMBER(DamageDivider);
631 ADD_MEMBER(HandleInPairs);
632 ADD_MEMBER(CanBeEnchanted);
633 ADD_MEMBER(BeamColor);
634 ADD_MEMBER(BeamEffect);
635 ADD_MEMBER(BeamStyle);
636 ADD_MEMBER(WearWisdomLimit);
637 ADD_MEMBER(AttachedGod);
638 ADD_MEMBER(BreakEffectRangeSquare);
639 ADD_MEMBER(WieldedBitmapPos);
640 ADD_MEMBER(IsQuestItem);
641 ADD_MEMBER(IsGoodWithPlants);
642 ADD_MEMBER(CreateLockConfigurations);
643 ADD_MEMBER(CanBePickedUp);
644 ADD_MEMBER(CoverPercentile);
645 ADD_MEMBER(TorsoArmorBitmapPos);
646 ADD_MEMBER(ArmArmorBitmapPos);
647 ADD_MEMBER(AthleteArmArmorBitmapPos);
648 ADD_MEMBER(LegArmorBitmapPos);
649 ADD_MEMBER(HelmetBitmapPos);
650 ADD_MEMBER(CloakBitmapPos);
651 ADD_MEMBER(BeltBitmapPos);
652 ADD_MEMBER(GauntletBitmapPos);
653 ADD_MEMBER(BootBitmapPos);
654 ADD_MEMBER(HasSecondaryMaterial);
655 ADD_MEMBER(AllowEquip);
656 ADD_MEMBER(ReadDifficulty);
657 ADD_MEMBER(IsValuable);
658 ADD_MEMBER(EnchantmentMinusChance);
659 ADD_MEMBER(EnchantmentPlusChance);
660 ADD_MEMBER(TeleportPriority);
661 ADD_MEMBER(HasNormalPictureDirection);
662 ADD_MEMBER(DamageFlags);
663 ADD_MEMBER(IsKamikazeWeapon);
664 ADD_MEMBER(FlexibilityIsEssential);
665 ADD_MEMBER(BreakMsg);
666 ADD_MEMBER(IsSadistWeapon);
667 ADD_MEMBER(IsThrowingWeapon);
668 ADD_MEMBER(ThrowItemTypes);
669 ADD_MEMBER(CanFlame);
670 ADD_MEMBER(AllowedDungeons);
671 ADD_MEMBER(LevelTags);
675 template <class type> void databasecreator<type>::CreateLTerrainDataBaseMemberMap () {
676 databasemembermap &Map = GetDataBaseMemberMap();
677 ADD_MEMBER(BitmapPos);
678 ADD_MEMBER(UsesLongArticle);
679 ADD_MEMBER(Adjective);
680 ADD_MEMBER(UsesLongAdjectiveArticle);
681 ADD_MEMBER(NameSingular);
682 ADD_MEMBER(NamePlural);
683 ADD_MEMBER(PostFix);
684 ADD_MEMBER(ArticleMode);
685 ADD_MEMBER(MainMaterialConfig);
686 ADD_MEMBER(SecondaryMaterialConfig);
687 ADD_MEMBER(MaterialConfigChances);
688 ADD_MEMBER(IsAbstract);
689 ADD_MEMBER(OKVisualEffects);
690 ADD_MEMBER(MaterialColorB);
691 ADD_MEMBER(MaterialColorC);
692 ADD_MEMBER(MaterialColorD);
693 ADD_MEMBER(SitMessage);
694 ADD_MEMBER(ShowMaterial);
695 ADD_MEMBER(AttachedGod);
696 ADD_MEMBER(Walkability);
697 ADD_MEMBER(HasSecondaryMaterial);
698 ADD_MEMBER(UseBorderTiles);
699 ADD_MEMBER(BorderTilePriority);
703 template<> void databasecreator<glterrain>::CreateDataBaseMemberMap () {
704 CreateLTerrainDataBaseMemberMap();
708 template<> void databasecreator<olterrain>::CreateDataBaseMemberMap () {
709 CreateLTerrainDataBaseMemberMap();
710 databasemembermap &Map = GetDataBaseMemberMap();
711 ADD_MEMBER(CreateDivineConfigurations);
712 ADD_MEMBER(DigMessage);
713 ADD_MEMBER(CanBeDestroyed);
714 ADD_MEMBER(RestModifier);
715 ADD_MEMBER(RestMessage);
716 ADD_MEMBER(IsUpLink);
717 ADD_MEMBER(StorageVolume);
718 ADD_MEMBER(HPModifier);
719 ADD_MEMBER(IsSafeToCreateDoor);
720 ADD_MEMBER(OpenBitmapPos);
721 ADD_MEMBER(CreateLockConfigurations);
722 ADD_MEMBER(IsAlwaysTransparent);
723 ADD_MEMBER(CreateWindowConfigurations);
724 ADD_MEMBER(WindowBitmapPos);
725 ADD_MEMBER(ShowThingsUnder);
726 ADD_MEMBER(LeftOverItems);
727 ADD_MEMBER(IsWall);
731 template<> void databasecreator<material>::CreateDataBaseMemberMap () {
732 databasemembermap &Map = GetDataBaseMemberMap();
733 ADD_MEMBER(CommonFlags);
734 ADD_MEMBER(NameFlags);
735 ADD_MEMBER(CategoryFlags);
736 ADD_MEMBER(BodyFlags);
737 ADD_MEMBER(InteractionFlags);
738 ADD_MEMBER(StrengthValue);
739 ADD_MEMBER(ConsumeType);
740 ADD_MEMBER(Density);
741 ADD_MEMBER(Color);
742 ADD_MEMBER(RainColor);
743 ADD_MEMBER(PriceModifier);
744 ADD_MEMBER(Emitation);
745 ADD_MEMBER(NutritionValue);
746 ADD_MEMBER(NameStem);
747 ADD_MEMBER(AdjectiveStem);
748 ADD_MEMBER(Effect);
749 ADD_MEMBER(ConsumeEndMessage);
750 ADD_MEMBER(HitMessage);
751 ADD_MEMBER(ExplosivePower);
752 ADD_MEMBER(Alpha);
753 ADD_MEMBER(Flexibility);
754 ADD_MEMBER(SpoilModifier);
755 ADD_MEMBER(EffectStrength);
756 ADD_MEMBER(DigProductMaterial);
757 ADD_MEMBER(ConsumeWisdomLimit);
758 ADD_MEMBER(AttachedGod);
759 ADD_MEMBER(BreatheMessage);
760 ADD_MEMBER(StepInWisdomLimit);
761 ADD_MEMBER(RustModifier);
762 ADD_MEMBER(Acidicity);
763 ADD_MEMBER(NaturalForm);
764 ADD_MEMBER(HardenedMaterial);
765 ADD_MEMBER(SoftenedMaterial);
766 ADD_MEMBER(IntelligenceRequirement);
767 ADD_MEMBER(Stickiness);
768 ADD_MEMBER(DisablesPanicWhenConsumed);
769 ADD_MEMBER(BlockESP);
773 #define ADD_BASE_VALUE(name)\
774 if (Word == #name) game::GetGlobalValueMap()[CONST_S("Base")] = DataBase.*static_cast<databasemember<database, feuLong database::*>*>(Data)->Member;
777 template <class type> void databasecreator<type>::SetBaseValue(cfestring &, databasememberbase<database> *, database &) {}
779 template<> void databasecreator<material>::SetBaseValue(cfestring &Word, databasememberbase<materialdatabase> *Data,
780 materialdatabase &DataBase)
782 ADD_BASE_VALUE(CommonFlags);
783 ADD_BASE_VALUE(NameFlags);
784 ADD_BASE_VALUE(CategoryFlags);
785 ADD_BASE_VALUE(BodyFlags);
786 ADD_BASE_VALUE(InteractionFlags);
790 template <class type> truth databasecreator<type>::AnalyzeData (TextInput &SaveFile, cfestring &Word, database &DataBase) {
791 typename databasemembermap::iterator i = GetDataBaseMemberMap().find(Word);
792 if (i != GetDataBaseMemberMap().end()) {
793 SetBaseValue(Word, i->second, DataBase);
794 i->second->ReadData(DataBase, SaveFile);
795 CheckDefaults(Word, DataBase);
796 return true;
798 return false;
802 template <> void databasecreator<character>::CheckDefaults (cfestring &Word, character::database &DataBase) {
803 if (Word == "ArmBitmapPos") { DataBase.RightArmBitmapPos = DataBase.LeftArmBitmapPos = DataBase.ArmBitmapPos; return; }
804 if (Word == "LegBitmapPos") { DataBase.GroinBitmapPos = DataBase.RightLegBitmapPos = DataBase.LeftLegBitmapPos = DataBase.LegBitmapPos; return; }
805 if (Word == "ClothColor") { DataBase.CapColor = DataBase.TorsoMainColor = DataBase.ArmMainColor = DataBase.GauntletColor = DataBase.LegMainColor = DataBase.ClothColor; return; }
806 if (Word == "NameSingular") { DataBase.NamePlural = DataBase.NameSingular+'s'; return; }
807 if (Word == "BaseUnarmedStrength") { DataBase.BaseBiteStrength = DataBase.BaseUnarmedStrength>>1; DataBase.BaseKickStrength = DataBase.BaseUnarmedStrength<<1; return; }
808 if (Word == "RightGauntlet") { DataBase.LeftGauntlet = DataBase.RightGauntlet; return; }
809 if (Word == "RightBoot") { DataBase.LeftBoot = DataBase.RightBoot; return; }
810 if (Word == "IsUnique") { DataBase.CanBeWished = !DataBase.IsUnique; return; }
811 if (Word == "DefaultName") {
812 // k8: don't add duplicate alias
813 for (uInt c = 0; c < DataBase.Alias.Size; ++c) {
814 if (DataBase.Alias[c] == DataBase.DefaultName) return;
816 DataBase.Alias.Add(DataBase.DefaultName);
818 if (DataBase.Alias.Size != 1) {
819 printf("=== %s ===\n", DataBase.NameSingular.CStr());
820 for (uInt c = 0; c < DataBase.Alias.Size; ++c) {
821 printf(" %u: %s\n", c, DataBase.Alias[c].CStr());
825 return;
830 template <> void databasecreator<item>::CheckDefaults (cfestring &Word, item::database &DataBase) {
831 if (Word == "NameSingular") { DataBase.NamePlural = DataBase.NameSingular+'s'; DataBase.FlexibleNameSingular = DataBase.NameSingular; return; }
832 if (Word == "BitmapPos") { DataBase.WallBitmapPos = DataBase.BitmapPos; return; }
833 if (Word == "MaterialConfigChances") { DataBase.MaterialConfigChanceSum = femath::SumArray(DataBase.MaterialConfigChances); return; }
834 if (Word == "CanBeCloned") { DataBase.CanBeMirrored = DataBase.CanBeCloned; return; }
838 template <> void databasecreator<glterrain>::CheckDefaults (cfestring &Word, glterrain::database &DataBase) {
839 if (Word == "NameSingular") { DataBase.NamePlural = DataBase.NameSingular+'s'; return; }
840 if (Word == "MaterialConfigChances") { DataBase.MaterialConfigChanceSum = femath::SumArray(DataBase.MaterialConfigChances); return; }
844 template <> void databasecreator<olterrain>::CheckDefaults (cfestring &Word, olterrain::database &DataBase) {
845 if (Word == "NameSingular") { DataBase.NamePlural = DataBase.NameSingular+'s'; return; }
846 if (Word == "MaterialConfigChances") { DataBase.MaterialConfigChanceSum = femath::SumArray(DataBase.MaterialConfigChances); return; }
850 template <> void databasecreator<material>::CheckDefaults (cfestring &Word, material::database &DataBase) {
851 if (Word == "NameStem") { DataBase.AdjectiveStem = DataBase.NameStem; return; }
852 if (Word == "Color") { DataBase.RainColor = DataBase.Color; return; }
856 void databasesystem::Initialize () {
857 /* Must be before character */
858 databasecreator<material>::ReadFrom("material");
859 databasecreator<character>::ReadFrom("char");
860 /* Must be before olterrain */
861 databasecreator<item>::ReadFrom("item");
862 databasecreator<glterrain>::ReadFrom("glterra");
863 databasecreator<olterrain>::ReadFrom("olterra");
867 template <class type> inline void databasecreator<type>::FindDataBase (const database *&DataBase, const prototype *Proto, int Config) {
868 database **Table = Proto->ConfigTable[(Config >> 8) ^ (Config & 0xFF)];
869 if (Table) {
870 if ((*Table)->Config == Config) {
871 DataBase = *Table;
872 return;
874 for (++Table; *Table; ++Table) {
875 if ((*Table)->Config == Config) {
876 DataBase = *Table;
877 return;
881 DataBase = 0;
885 template void databasecreator<character>::FindDataBase (const database *&, const prototype *, int);
886 template void databasecreator<material>::FindDataBase (const database *&, const prototype *, int);
888 template <class type> void databasecreator<type>::InstallDataBase (type *Instance, int Config) {
889 const prototype *Proto = Instance->FindProtoType();
890 FindDataBase(Instance->DataBase, Proto, Config);
891 if (!Instance->DataBase) {
892 //*((int *)0) = 0;
893 ABORT("Undefined %s configuration #%08x sought!", Proto->GetClassID(), (unsigned int)Config);
897 #define INST_INSTALL_DATABASE(type) template void databasecreator<type>::InstallDataBase(type *, int)
899 INST_INSTALL_DATABASE(material);
900 INST_INSTALL_DATABASE(character);
901 INST_INSTALL_DATABASE(item);
902 INST_INSTALL_DATABASE(glterrain);
903 INST_INSTALL_DATABASE(olterrain);