moved almost all hardcoded constants to "define.dat"
[k8-i-v-a-n.git] / src / game / database.cpp
blobfaa2bbcd8f039b806b8efbb440cbe317902f51ff
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 festring cfgname = inFile->numStr();
227 festring infname = inFile->GetFileName();
228 ConfigDataBase->InitDefaults(Proto, ConfigNumber, cfgname);
229 TempConfig[Configs++] = ConfigDataBase;
230 if (inFile->ReadWord() != "{") ABORT("'{' missing in %s datafile %s line %d!", protocontainer<type>::GetMainClassID(), inFile->GetFileName().CStr(), inFile->TokenLine());
231 for (inFile->ReadWord(Word); Word != "}"; inFile->ReadWord(Word)) {
232 if (Word == "on") {
233 collectHandler(Proto->mOnEvents, infStack, &inFile);
234 continue;
236 if (!AnalyzeData(*inFile, Word, *ConfigDataBase)) ABORT("Illegal datavalue %s found while building up %s config #%d (%s), file %s, line %d!", Word.CStr(), Proto->GetClassID(), ConfigNumber, cfgname.CStr(), infname.CStr(), inFile->TokenLine());
238 ConfigDataBase->PostProcess();
240 continue;
242 if (Word == "on") {
243 collectHandler(Proto->mOnEvents, infStack, &inFile);
244 continue;
246 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());
248 DataBase->PostProcess();
249 //Configs = Proto->CreateSpecialConfigurations(TempConfig, Configs);
250 Proto->ConfigData = new database *[Configs];
251 Proto->ConfigSize = Configs;
252 memmove(Proto->ConfigData, TempConfig, Configs*sizeof(database *));
254 delete inFile;
257 int c1;
258 for (c1 = 0; c1 < SPECIAL_CONFIGURATION_GENERATION_LEVELS; ++c1) {
259 for (int c2 = 1; c2 < protocontainer<type>::GetSize(); ++c2) {
260 prototype *Proto = protocontainer<type>::GetProtoData()[c2];
261 int Configs = Proto->ConfigSize;
262 memmove(TempConfig, Proto->ConfigData, Configs*sizeof(database *));
263 Configs = Proto->CreateSpecialConfigurations(TempConfig, Configs, c1);
264 if (Proto->ConfigSize != Configs) {
265 delete [] Proto->ConfigData;
266 Proto->ConfigData = new database *[Configs];
267 Proto->ConfigSize = Configs;
268 memmove(Proto->ConfigData, TempConfig, Configs*sizeof(database *));
272 for (c1 = 1; c1 < protocontainer<type>::GetSize(); ++c1) {
273 prototype *Proto = protocontainer<type>::GetProtoData()[c1];
274 TempTables =
275 CreateConfigTable(reinterpret_cast<databasebase ***>(Proto->ConfigTable),
276 TempTable,
277 reinterpret_cast<databasebase **>(Proto->ConfigData),
278 TempTableInfo, c1, Proto->ConfigSize, TempTables);
280 for (c1 = 1; c1 < TempTables; ++c1) delete [] TempTable[c1];
281 GetDataBaseMemberMap().clear();
285 template <class type> int databasecreator<type>::CreateDivineConfigurations (const prototype *Proto, database **TempConfig, int Configs) {
286 int OldConfigs = Configs;
287 for (int c1 = 1; c1 < protocontainer<god>::GetSize(); ++c1) {
288 database *ConfigDataBase = 0;
289 int c2;
290 festring dcfgname = "divine";
291 for (c2 = 1; c2 < OldConfigs; ++c2) {
292 ConfigDataBase = TempConfig[c2];
293 if (ConfigDataBase->Config == c1) {
294 dcfgname << " ";
295 dcfgname << ConfigDataBase->CfgStrName;
296 break;
299 truth Created = false;
300 if (c2 == OldConfigs) {
301 ConfigDataBase = new database(**TempConfig);
302 ConfigDataBase->InitDefaults(Proto, c1, dcfgname);
303 Created = true;
305 ConfigDataBase->AttachedGod = c1;
306 ConfigDataBase->PostFix << "of " << festring(protocontainer<god>::GetProto(c1)->GetClassID()).CapitalizeCopy();
307 if (Created) TempConfig[Configs++] = ConfigDataBase;
309 return Configs;
313 template int databasecreator<character>::CreateDivineConfigurations (const prototype *, database **, int);
314 template int databasecreator<item>::CreateDivineConfigurations (const prototype *, database **, int);
315 template int databasecreator<olterrain>::CreateDivineConfigurations (const prototype *, database **, int);
318 template <class database, class member> struct databasemember : public databasememberbase<database> {
319 databasemember (member Member) : Member(Member) {}
320 virtual void ReadData (database &DataBase, TextInput &SaveFile) { ::ReadData(DataBase.*Member, SaveFile); }
321 member Member;
325 template <class database, class member> void AddMember(std::map<festring, databasememberbase<database>*>& Map, cchar* Str, member Member)
327 Map.insert(std::pair<festring, databasememberbase<database>*>(Str, new databasemember<database, member>(Member)));
331 /* Explicit instantiations seem to increase compile speed greatly here... */
333 #define INST_ADD_MEMBER(type, member) \
334 template void AddMember<type##database, member type##database::*>(std::map<festring, databasememberbase<type##database>*>&, cchar*, member type##database::*)
336 INST_ADD_MEMBER(character, int);
337 //INST_ADD_MEMBER(character, sLong); //k8:64
338 INST_ADD_MEMBER(character, packcol16);
339 INST_ADD_MEMBER(character, col24);
340 INST_ADD_MEMBER(character, packv2);
341 INST_ADD_MEMBER(character, festring);
342 INST_ADD_MEMBER(character, fearray<sLong>);
343 INST_ADD_MEMBER(character, fearray<festring>);
344 INST_ADD_MEMBER(character, contentscript<item>);
346 INST_ADD_MEMBER(item, int);
347 //INST_ADD_MEMBER(item, sLong); //k8:64
348 INST_ADD_MEMBER(item, col24);
349 INST_ADD_MEMBER(item, v2);
350 INST_ADD_MEMBER(item, festring);
351 INST_ADD_MEMBER(item, fearray<sLong>);
352 INST_ADD_MEMBER(item, fearray<festring>);
354 INST_ADD_MEMBER(glterrain, int);
355 //INST_ADD_MEMBER(glterrain, sLong); //k8:64
356 INST_ADD_MEMBER(glterrain, v2);
357 INST_ADD_MEMBER(glterrain, festring);
358 INST_ADD_MEMBER(glterrain, fearray<sLong>);
360 INST_ADD_MEMBER(olterrain, int);
361 //INST_ADD_MEMBER(olterrain, sLong); //k8:64
362 INST_ADD_MEMBER(olterrain, v2);
363 INST_ADD_MEMBER(olterrain, festring);
364 INST_ADD_MEMBER(olterrain, fearray<sLong>);
365 INST_ADD_MEMBER(olterrain, fearray<contentscript<item> >);
367 INST_ADD_MEMBER(material, int);
368 //INST_ADD_MEMBER(material, sLong); //k8:64
369 INST_ADD_MEMBER(material, col24);
370 INST_ADD_MEMBER(material, festring);
371 INST_ADD_MEMBER(material, contentscript<item>);
373 #define ADD_MEMBER(data) AddMember(Map, #data, &database::data);
375 template<> void databasecreator<character>::CreateDataBaseMemberMap () {
376 databasemembermap &Map = GetDataBaseMemberMap();
377 ADD_MEMBER(DefaultArmStrength);
378 ADD_MEMBER(DefaultLegStrength);
379 ADD_MEMBER(DefaultDexterity);
380 ADD_MEMBER(DefaultAgility);
381 ADD_MEMBER(DefaultEndurance);
382 ADD_MEMBER(DefaultPerception);
383 ADD_MEMBER(DefaultIntelligence);
384 ADD_MEMBER(DefaultWisdom);
385 ADD_MEMBER(DefaultWillPower);
386 ADD_MEMBER(DefaultCharisma);
387 ADD_MEMBER(DefaultMana);
388 ADD_MEMBER(DefaultMoney);
389 ADD_MEMBER(TotalSize);
390 ADD_MEMBER(CanRead);
391 ADD_MEMBER(Sex);
392 ADD_MEMBER(CanBeGenerated);
393 ADD_MEMBER(CriticalModifier);
394 ADD_MEMBER(StandVerb);
395 ADD_MEMBER(CanOpen);
396 ADD_MEMBER(Frequency);
397 ADD_MEMBER(EnergyResistance);
398 ADD_MEMBER(FireResistance);
399 ADD_MEMBER(PoisonResistance);
400 ADD_MEMBER(ElectricityResistance);
401 ADD_MEMBER(AcidResistance);
402 ADD_MEMBER(SoundResistance);
403 ADD_MEMBER(IsUnique);
404 ADD_MEMBER(ConsumeFlags);
405 ADD_MEMBER(TotalVolume);
406 ADD_MEMBER(HeadBitmapPos);
407 ADD_MEMBER(TorsoBitmapPos);
408 ADD_MEMBER(ArmBitmapPos);
409 ADD_MEMBER(LegBitmapPos);
410 ADD_MEMBER(RightArmBitmapPos);
411 ADD_MEMBER(LeftArmBitmapPos);
412 ADD_MEMBER(RightLegBitmapPos);
413 ADD_MEMBER(LeftLegBitmapPos);
414 ADD_MEMBER(GroinBitmapPos);
415 ADD_MEMBER(ClothColor);
416 ADD_MEMBER(SkinColor);
417 ADD_MEMBER(CapColor);
418 ADD_MEMBER(HairColor);
419 ADD_MEMBER(EyeColor);
420 ADD_MEMBER(TorsoMainColor);
421 ADD_MEMBER(BeltColor);
422 ADD_MEMBER(BootColor);
423 ADD_MEMBER(TorsoSpecialColor);
424 ADD_MEMBER(ArmMainColor);
425 ADD_MEMBER(GauntletColor);
426 ADD_MEMBER(ArmSpecialColor);
427 ADD_MEMBER(LegMainColor);
428 ADD_MEMBER(LegSpecialColor);
429 ADD_MEMBER(IsNameable);
430 ADD_MEMBER(BaseEmitation);
431 ADD_MEMBER(UsesLongArticle);
432 ADD_MEMBER(Adjective);
433 ADD_MEMBER(UsesLongAdjectiveArticle);
434 ADD_MEMBER(NameSingular);
435 ADD_MEMBER(NamePlural);
436 ADD_MEMBER(PostFix);
437 ADD_MEMBER(ArticleMode);
438 ADD_MEMBER(IsAbstract);
439 ADD_MEMBER(IsPolymorphable);
440 ADD_MEMBER(BaseUnarmedStrength);
441 ADD_MEMBER(BaseBiteStrength);
442 ADD_MEMBER(BaseKickStrength);
443 ADD_MEMBER(AttackStyle);
444 ADD_MEMBER(CanUseEquipment);
445 ADD_MEMBER(CanKick);
446 ADD_MEMBER(CanTalk);
447 ADD_MEMBER(ClassStates);
448 ADD_MEMBER(CanBeWished);
449 ADD_MEMBER(Alias);
450 ADD_MEMBER(CreateDivineConfigurations);
451 ADD_MEMBER(CreateGolemMaterialConfigurations);
452 ADD_MEMBER(Helmet);
453 ADD_MEMBER(Amulet);
454 ADD_MEMBER(Cloak);
455 ADD_MEMBER(BodyArmor);
456 ADD_MEMBER(Belt);
457 ADD_MEMBER(RightWielded);
458 ADD_MEMBER(LeftWielded);
459 ADD_MEMBER(RightRing);
460 ADD_MEMBER(LeftRing);
461 ADD_MEMBER(RightGauntlet);
462 ADD_MEMBER(LeftGauntlet);
463 ADD_MEMBER(RightBoot);
464 ADD_MEMBER(LeftBoot);
465 ADD_MEMBER(AttributeBonus);
466 ADD_MEMBER(KnownCWeaponSkills);
467 ADD_MEMBER(CWeaponSkillHits);
468 ADD_MEMBER(RightSWeaponSkillHits);
469 ADD_MEMBER(LeftSWeaponSkillHits);
470 ADD_MEMBER(PanicLevel);
471 ADD_MEMBER(CanBeCloned);
472 ADD_MEMBER(Inventory);
473 ADD_MEMBER(DangerModifier);
474 ADD_MEMBER(DefaultName);
475 ADD_MEMBER(FriendlyReplies);
476 ADD_MEMBER(HostileReplies);
477 ADD_MEMBER(CanZap);
478 ADD_MEMBER(FleshMaterial);
479 ADD_MEMBER(HasALeg);
480 ADD_MEMBER(DeathMessage);
481 ADD_MEMBER(IgnoreDanger);
482 ADD_MEMBER(HPRequirementForGeneration);
483 ADD_MEMBER(DayRequirementForGeneration);
484 ADD_MEMBER(IsExtraCoward);
485 ADD_MEMBER(SpillsBlood);
486 ADD_MEMBER(HasEyes);
487 ADD_MEMBER(HasHead);
488 ADD_MEMBER(CanThrow);
489 ADD_MEMBER(UsesNutrition);
490 ADD_MEMBER(AttackWisdomLimit);
491 ADD_MEMBER(AttachedGod);
492 ADD_MEMBER(BodyPartsDisappearWhenSevered);
493 ADD_MEMBER(CanBeConfused);
494 ADD_MEMBER(CanApply);
495 ADD_MEMBER(WieldedPosition);
496 ADD_MEMBER(NaturalSparkleFlags);
497 ADD_MEMBER(BiteCapturesBodyPart);
498 ADD_MEMBER(IsPlant);
499 ADD_MEMBER(MoveType);
500 ADD_MEMBER(DestroysWalls);
501 ADD_MEMBER(IsRooted);
502 ADD_MEMBER(BloodMaterial);
503 ADD_MEMBER(VomitMaterial);
504 ADD_MEMBER(HasSecondaryMaterial);
505 ADD_MEMBER(IsImmuneToLeprosy);
506 ADD_MEMBER(PolymorphIntelligenceRequirement);
507 ADD_MEMBER(AutomaticallySeen);
508 ADD_MEMBER(CanHear);
509 ADD_MEMBER(DefaultCommandFlags);
510 ADD_MEMBER(ConstantCommandFlags);
511 ADD_MEMBER(WillCarryItems);
512 ADD_MEMBER(ForceVomitMessage);
513 ADD_MEMBER(SweatMaterial);
514 ADD_MEMBER(Sweats);
515 ADD_MEMBER(IsImmuneToItemTeleport);
516 ADD_MEMBER(AlwaysUseMaterialAttributes);
517 ADD_MEMBER(IsEnormous);
518 ADD_MEMBER(ScienceTalkAdjectiveAttribute);
519 ADD_MEMBER(ScienceTalkSubstantiveAttribute);
520 ADD_MEMBER(ScienceTalkPrefix);
521 ADD_MEMBER(ScienceTalkName);
522 ADD_MEMBER(ScienceTalkPossibility);
523 ADD_MEMBER(ScienceTalkIntelligenceModifier);
524 ADD_MEMBER(ScienceTalkWisdomModifier);
525 ADD_MEMBER(ScienceTalkCharismaModifier);
526 ADD_MEMBER(ScienceTalkIntelligenceRequirement);
527 ADD_MEMBER(ScienceTalkWisdomRequirement);
528 ADD_MEMBER(ScienceTalkCharismaRequirement);
529 ADD_MEMBER(IsExtraFragile);
530 ADD_MEMBER(AllowUnconsciousness);
531 ADD_MEMBER(CanChoke);
532 ADD_MEMBER(IsImmuneToStickiness);
533 ADD_MEMBER(DisplacePriority);
534 ADD_MEMBER(RunDescriptionLineOne);
535 ADD_MEMBER(RunDescriptionLineTwo);
536 ADD_MEMBER(ForceCustomStandVerb);
537 ADD_MEMBER(VomittingIsUnhealthy);
538 ADD_MEMBER(AllowPlayerToChangeEquipment);
539 ADD_MEMBER(TamingDifficulty);
540 ADD_MEMBER(IsMasochist);
541 ADD_MEMBER(IsSadist);
542 ADD_MEMBER(IsCatacombCreature);
543 ADD_MEMBER(CreateUndeadConfigurations);
544 ADD_MEMBER(UndeadVersions);
545 ADD_MEMBER(UndeadAttributeModifier);
546 ADD_MEMBER(UndeadVolumeModifier);
547 ADD_MEMBER(UndeadCopyMaterials);
548 ADD_MEMBER(CanBeGeneratedOnlyInTheCatacombs);
549 ADD_MEMBER(IsAlcoholic);
550 ADD_MEMBER(IsImmuneToWhipOfThievery);
551 ADD_MEMBER(IsRangedAttacker);
552 ADD_MEMBER(WhatCategoryToThrow);
553 ADD_MEMBER(WhatWeaponConfigToThrow);
554 ADD_MEMBER(WhatThrowItemTypesToThrow);
555 ADD_MEMBER(AllowedDungeons);
556 ADD_MEMBER(LevelTags);
557 ADD_MEMBER(HomeLevel);
558 ADD_MEMBER(NaturalTeam);
562 template<> void databasecreator<item>::CreateDataBaseMemberMap () {
563 databasemembermap &Map = GetDataBaseMemberMap();
564 ADD_MEMBER(Possibility);
565 ADD_MEMBER(IsDestroyable);
566 ADD_MEMBER(CanBeWished);
567 ADD_MEMBER(IsMaterialChangeable);
568 ADD_MEMBER(WeaponCategory);
569 ADD_MEMBER(IsPolymorphSpawnable);
570 ADD_MEMBER(IsAutoInitializable);
571 ADD_MEMBER(Category);
572 ADD_MEMBER(EnergyResistance);
573 ADD_MEMBER(FireResistance);
574 ADD_MEMBER(PoisonResistance);
575 ADD_MEMBER(ElectricityResistance);
576 ADD_MEMBER(AcidResistance);
577 ADD_MEMBER(SoundResistance);
578 ADD_MEMBER(StrengthModifier);
579 ADD_MEMBER(FormModifier);
580 ADD_MEMBER(DefaultSize);
581 ADD_MEMBER(DefaultMainVolume);
582 ADD_MEMBER(DefaultSecondaryVolume);
583 ADD_MEMBER(BitmapPos);
584 ADD_MEMBER(Price);
585 ADD_MEMBER(BaseEmitation);
586 ADD_MEMBER(UsesLongArticle);
587 ADD_MEMBER(Adjective);
588 ADD_MEMBER(UsesLongAdjectiveArticle);
589 ADD_MEMBER(NameSingular);
590 ADD_MEMBER(NamePlural);
591 ADD_MEMBER(PostFix);
592 ADD_MEMBER(ArticleMode);
593 ADD_MEMBER(MainMaterialConfig);
594 ADD_MEMBER(SecondaryMaterialConfig);
595 ADD_MEMBER(MaterialConfigChances);
596 ADD_MEMBER(IsAbstract);
597 ADD_MEMBER(IsPolymorphable);
598 ADD_MEMBER(Alias);
599 ADD_MEMBER(OKVisualEffects);
600 ADD_MEMBER(CanBeGeneratedInContainer);
601 ADD_MEMBER(ForcedVisualEffects);
602 ADD_MEMBER(Roundness);
603 ADD_MEMBER(GearStates);
604 ADD_MEMBER(IsTwoHanded);
605 ADD_MEMBER(CreateDivineConfigurations);
606 ADD_MEMBER(CanBeCloned);
607 ADD_MEMBER(CanBeMirrored);
608 ADD_MEMBER(BeamRange);
609 ADD_MEMBER(CanBeBroken);
610 ADD_MEMBER(WallBitmapPos);
611 ADD_MEMBER(FlexibleNameSingular);
612 ADD_MEMBER(MaxCharges);
613 ADD_MEMBER(MinCharges);
614 ADD_MEMBER(CanBePiled);
615 ADD_MEMBER(StorageVolume);
616 ADD_MEMBER(MaxGeneratedContainedItems);
617 ADD_MEMBER(AffectsArmStrength);
618 ADD_MEMBER(AffectsLegStrength);
619 ADD_MEMBER(AffectsDexterity);
620 ADD_MEMBER(AffectsAgility);
621 ADD_MEMBER(AffectsEndurance);
622 ADD_MEMBER(AffectsPerception);
623 ADD_MEMBER(AffectsIntelligence);
624 ADD_MEMBER(AffectsWisdom);
625 ADD_MEMBER(AffectsWillPower);
626 ADD_MEMBER(AffectsCharisma);
627 ADD_MEMBER(AffectsMana);
628 ADD_MEMBER(BaseEnchantment);
629 ADD_MEMBER(PriceIsProportionalToEnchantment);
630 ADD_MEMBER(InElasticityPenaltyModifier);
631 ADD_MEMBER(CanBeUsedBySmith);
632 ADD_MEMBER(AffectsCarryingCapacity);
633 ADD_MEMBER(DamageDivider);
634 ADD_MEMBER(HandleInPairs);
635 ADD_MEMBER(CanBeEnchanted);
636 ADD_MEMBER(BeamColor);
637 ADD_MEMBER(BeamEffect);
638 ADD_MEMBER(BeamStyle);
639 ADD_MEMBER(WearWisdomLimit);
640 ADD_MEMBER(AttachedGod);
641 ADD_MEMBER(BreakEffectRangeSquare);
642 ADD_MEMBER(WieldedBitmapPos);
643 ADD_MEMBER(IsQuestItem);
644 ADD_MEMBER(IsGoodWithPlants);
645 ADD_MEMBER(CreateLockConfigurations);
646 ADD_MEMBER(CanBePickedUp);
647 ADD_MEMBER(CoverPercentile);
648 ADD_MEMBER(TorsoArmorBitmapPos);
649 ADD_MEMBER(ArmArmorBitmapPos);
650 ADD_MEMBER(AthleteArmArmorBitmapPos);
651 ADD_MEMBER(LegArmorBitmapPos);
652 ADD_MEMBER(HelmetBitmapPos);
653 ADD_MEMBER(CloakBitmapPos);
654 ADD_MEMBER(BeltBitmapPos);
655 ADD_MEMBER(GauntletBitmapPos);
656 ADD_MEMBER(BootBitmapPos);
657 ADD_MEMBER(HasSecondaryMaterial);
658 ADD_MEMBER(AllowEquip);
659 ADD_MEMBER(ReadDifficulty);
660 ADD_MEMBER(IsValuable);
661 ADD_MEMBER(EnchantmentMinusChance);
662 ADD_MEMBER(EnchantmentPlusChance);
663 ADD_MEMBER(TeleportPriority);
664 ADD_MEMBER(HasNormalPictureDirection);
665 ADD_MEMBER(DamageFlags);
666 ADD_MEMBER(IsKamikazeWeapon);
667 ADD_MEMBER(FlexibilityIsEssential);
668 ADD_MEMBER(BreakMsg);
669 ADD_MEMBER(IsSadistWeapon);
670 ADD_MEMBER(IsThrowingWeapon);
671 ADD_MEMBER(ThrowItemTypes);
672 ADD_MEMBER(CanFlame);
673 ADD_MEMBER(AllowedDungeons);
674 ADD_MEMBER(LevelTags);
678 template <class type> void databasecreator<type>::CreateLTerrainDataBaseMemberMap () {
679 databasemembermap &Map = GetDataBaseMemberMap();
680 ADD_MEMBER(BitmapPos);
681 ADD_MEMBER(UsesLongArticle);
682 ADD_MEMBER(Adjective);
683 ADD_MEMBER(UsesLongAdjectiveArticle);
684 ADD_MEMBER(NameSingular);
685 ADD_MEMBER(NamePlural);
686 ADD_MEMBER(PostFix);
687 ADD_MEMBER(ArticleMode);
688 ADD_MEMBER(MainMaterialConfig);
689 ADD_MEMBER(SecondaryMaterialConfig);
690 ADD_MEMBER(MaterialConfigChances);
691 ADD_MEMBER(IsAbstract);
692 ADD_MEMBER(OKVisualEffects);
693 ADD_MEMBER(MaterialColorB);
694 ADD_MEMBER(MaterialColorC);
695 ADD_MEMBER(MaterialColorD);
696 ADD_MEMBER(SitMessage);
697 ADD_MEMBER(ShowMaterial);
698 ADD_MEMBER(AttachedGod);
699 ADD_MEMBER(Walkability);
700 ADD_MEMBER(HasSecondaryMaterial);
701 ADD_MEMBER(UseBorderTiles);
702 ADD_MEMBER(BorderTilePriority);
706 template<> void databasecreator<glterrain>::CreateDataBaseMemberMap () {
707 CreateLTerrainDataBaseMemberMap();
711 template<> void databasecreator<olterrain>::CreateDataBaseMemberMap () {
712 CreateLTerrainDataBaseMemberMap();
713 databasemembermap &Map = GetDataBaseMemberMap();
714 ADD_MEMBER(CreateDivineConfigurations);
715 ADD_MEMBER(DigMessage);
716 ADD_MEMBER(CanBeDestroyed);
717 ADD_MEMBER(RestModifier);
718 ADD_MEMBER(RestMessage);
719 ADD_MEMBER(IsUpLink);
720 ADD_MEMBER(StorageVolume);
721 ADD_MEMBER(HPModifier);
722 ADD_MEMBER(IsSafeToCreateDoor);
723 ADD_MEMBER(OpenBitmapPos);
724 ADD_MEMBER(CreateLockConfigurations);
725 ADD_MEMBER(IsAlwaysTransparent);
726 ADD_MEMBER(CreateWindowConfigurations);
727 ADD_MEMBER(WindowBitmapPos);
728 ADD_MEMBER(ShowThingsUnder);
729 ADD_MEMBER(LeftOverItems);
730 ADD_MEMBER(IsWall);
734 template<> void databasecreator<material>::CreateDataBaseMemberMap () {
735 databasemembermap &Map = GetDataBaseMemberMap();
736 ADD_MEMBER(CommonFlags);
737 ADD_MEMBER(NameFlags);
738 ADD_MEMBER(CategoryFlags);
739 ADD_MEMBER(BodyFlags);
740 ADD_MEMBER(InteractionFlags);
741 ADD_MEMBER(StrengthValue);
742 ADD_MEMBER(ConsumeType);
743 ADD_MEMBER(Density);
744 ADD_MEMBER(Color);
745 ADD_MEMBER(RainColor);
746 ADD_MEMBER(PriceModifier);
747 ADD_MEMBER(Emitation);
748 ADD_MEMBER(NutritionValue);
749 ADD_MEMBER(NameStem);
750 ADD_MEMBER(AdjectiveStem);
751 ADD_MEMBER(Effect);
752 ADD_MEMBER(ConsumeEndMessage);
753 ADD_MEMBER(HitMessage);
754 ADD_MEMBER(ExplosivePower);
755 ADD_MEMBER(Alpha);
756 ADD_MEMBER(Flexibility);
757 ADD_MEMBER(SpoilModifier);
758 ADD_MEMBER(EffectStrength);
759 ADD_MEMBER(DigProductMaterial);
760 ADD_MEMBER(ConsumeWisdomLimit);
761 ADD_MEMBER(AttachedGod);
762 ADD_MEMBER(BreatheMessage);
763 ADD_MEMBER(StepInWisdomLimit);
764 ADD_MEMBER(RustModifier);
765 ADD_MEMBER(Acidicity);
766 ADD_MEMBER(NaturalForm);
767 ADD_MEMBER(HardenedMaterial);
768 ADD_MEMBER(SoftenedMaterial);
769 ADD_MEMBER(IntelligenceRequirement);
770 ADD_MEMBER(Stickiness);
771 ADD_MEMBER(DisablesPanicWhenConsumed);
772 ADD_MEMBER(BlockESP);
776 #define ADD_BASE_VALUE(name)\
777 if (Word == #name) game::GetGlobalValueMap()[CONST_S("Base")] = DataBase.*static_cast<databasemember<database, feuLong database::*>*>(Data)->Member;
780 template <class type> void databasecreator<type>::SetBaseValue(cfestring &, databasememberbase<database> *, database &) {}
782 template<> void databasecreator<material>::SetBaseValue(cfestring &Word, databasememberbase<materialdatabase> *Data,
783 materialdatabase &DataBase)
785 ADD_BASE_VALUE(CommonFlags);
786 ADD_BASE_VALUE(NameFlags);
787 ADD_BASE_VALUE(CategoryFlags);
788 ADD_BASE_VALUE(BodyFlags);
789 ADD_BASE_VALUE(InteractionFlags);
793 template <class type> truth databasecreator<type>::AnalyzeData (TextInput &SaveFile, cfestring &Word, database &DataBase) {
794 typename databasemembermap::iterator i = GetDataBaseMemberMap().find(Word);
795 if (i != GetDataBaseMemberMap().end()) {
796 SetBaseValue(Word, i->second, DataBase);
797 i->second->ReadData(DataBase, SaveFile);
798 CheckDefaults(Word, DataBase);
799 return true;
801 return false;
805 template <> void databasecreator<character>::CheckDefaults (cfestring &Word, character::database &DataBase) {
806 if (Word == "ArmBitmapPos") { DataBase.RightArmBitmapPos = DataBase.LeftArmBitmapPos = DataBase.ArmBitmapPos; return; }
807 if (Word == "LegBitmapPos") { DataBase.GroinBitmapPos = DataBase.RightLegBitmapPos = DataBase.LeftLegBitmapPos = DataBase.LegBitmapPos; return; }
808 if (Word == "ClothColor") { DataBase.CapColor = DataBase.TorsoMainColor = DataBase.ArmMainColor = DataBase.GauntletColor = DataBase.LegMainColor = DataBase.ClothColor; return; }
809 if (Word == "NameSingular") { DataBase.NamePlural = DataBase.NameSingular+'s'; return; }
810 if (Word == "BaseUnarmedStrength") { DataBase.BaseBiteStrength = DataBase.BaseUnarmedStrength>>1; DataBase.BaseKickStrength = DataBase.BaseUnarmedStrength<<1; return; }
811 if (Word == "RightGauntlet") { DataBase.LeftGauntlet = DataBase.RightGauntlet; return; }
812 if (Word == "RightBoot") { DataBase.LeftBoot = DataBase.RightBoot; return; }
813 if (Word == "IsUnique") { DataBase.CanBeWished = !DataBase.IsUnique; return; }
814 if (Word == "DefaultName") {
815 // k8: don't add duplicate alias
816 for (uInt c = 0; c < DataBase.Alias.Size; ++c) {
817 if (DataBase.Alias[c] == DataBase.DefaultName) return;
819 DataBase.Alias.Add(DataBase.DefaultName);
821 if (DataBase.Alias.Size != 1) {
822 printf("=== %s ===\n", DataBase.NameSingular.CStr());
823 for (uInt c = 0; c < DataBase.Alias.Size; ++c) {
824 printf(" %u: %s\n", c, DataBase.Alias[c].CStr());
828 return;
833 template <> void databasecreator<item>::CheckDefaults (cfestring &Word, item::database &DataBase) {
834 if (Word == "NameSingular") { DataBase.NamePlural = DataBase.NameSingular+'s'; DataBase.FlexibleNameSingular = DataBase.NameSingular; return; }
835 if (Word == "BitmapPos") { DataBase.WallBitmapPos = DataBase.BitmapPos; return; }
836 if (Word == "MaterialConfigChances") { DataBase.MaterialConfigChanceSum = femath::SumArray(DataBase.MaterialConfigChances); return; }
837 if (Word == "CanBeCloned") { DataBase.CanBeMirrored = DataBase.CanBeCloned; return; }
841 template <> void databasecreator<glterrain>::CheckDefaults (cfestring &Word, glterrain::database &DataBase) {
842 if (Word == "NameSingular") { DataBase.NamePlural = DataBase.NameSingular+'s'; return; }
843 if (Word == "MaterialConfigChances") { DataBase.MaterialConfigChanceSum = femath::SumArray(DataBase.MaterialConfigChances); return; }
847 template <> void databasecreator<olterrain>::CheckDefaults (cfestring &Word, olterrain::database &DataBase) {
848 if (Word == "NameSingular") { DataBase.NamePlural = DataBase.NameSingular+'s'; return; }
849 if (Word == "MaterialConfigChances") { DataBase.MaterialConfigChanceSum = femath::SumArray(DataBase.MaterialConfigChances); return; }
853 template <> void databasecreator<material>::CheckDefaults (cfestring &Word, material::database &DataBase) {
854 if (Word == "NameStem") { DataBase.AdjectiveStem = DataBase.NameStem; return; }
855 if (Word == "Color") { DataBase.RainColor = DataBase.Color; return; }
859 void databasesystem::Initialize () {
860 /* Must be before character */
861 databasecreator<material>::ReadFrom("material");
862 databasecreator<character>::ReadFrom("char");
863 /* Must be before olterrain */
864 databasecreator<item>::ReadFrom("item");
865 databasecreator<glterrain>::ReadFrom("glterra");
866 databasecreator<olterrain>::ReadFrom("olterra");
870 template <class type> inline void databasecreator<type>::FindDataBase (const database *&DataBase, const prototype *Proto, int Config) {
871 database **Table = Proto->ConfigTable[(Config >> 8) ^ (Config & 0xFF)];
872 if (Table) {
873 if ((*Table)->Config == Config) {
874 DataBase = *Table;
875 return;
877 for (++Table; *Table; ++Table) {
878 if ((*Table)->Config == Config) {
879 DataBase = *Table;
880 return;
884 DataBase = 0;
888 template void databasecreator<character>::FindDataBase (const database *&, const prototype *, int);
889 template void databasecreator<material>::FindDataBase (const database *&, const prototype *, int);
891 template <class type> void databasecreator<type>::InstallDataBase (type *Instance, int Config) {
892 const prototype *Proto = Instance->FindProtoType();
893 FindDataBase(Instance->DataBase, Proto, Config);
894 if (!Instance->DataBase) {
895 //*((int *)0) = 0;
896 ABORT("Undefined %s configuration #%08x sought!", Proto->GetClassID(), (unsigned int)Config);
900 #define INST_INSTALL_DATABASE(type) template void databasecreator<type>::InstallDataBase(type *, int)
902 INST_INSTALL_DATABASE(material);
903 INST_INSTALL_DATABASE(character);
904 INST_INSTALL_DATABASE(item);
905 INST_INSTALL_DATABASE(glterrain);
906 INST_INSTALL_DATABASE(olterrain);