replaced old numbered script file system with new "modules" system; "Include" is...
[k8-i-v-a-n.git] / src / game / database.cpp
bloba02c64e50c574f1c3befe79ed824089898477f05
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"
15 #include "wterra.h"
18 int CreateConfigTable (databasebase ***ConfigTable, databasebase ***TempTable,
19 databasebase **ConfigArray, sLong *TempTableInfo, int Type, int Configs, int TempTables)
21 memset(ConfigTable, 0, CONFIG_TABLE_SIZE*sizeof(databasebase **));
22 for (int c = 0; c < Configs; ++c) {
23 int Config = ConfigArray[c]->Config;
24 int Hash = (Config >> 8) ^ (Config & 0xFF);
25 if ((TempTableInfo[Hash] & 0xFFFF) != Type) {
26 TempTable[0][Hash] = ConfigArray[c];
27 TempTableInfo[Hash] = Type | 0x10000;
28 } else {
29 int Conflicts = (TempTableInfo[Hash] & 0xFFFF0000) >> 16;
30 if (Conflicts == TempTables) TempTable[TempTables++] = new databasebase *[CONFIG_TABLE_SIZE];
31 TempTable[Conflicts][Hash] = ConfigArray[c];
32 TempTableInfo[Hash] += 0x10000;
35 for (int c1 = 0; c1 < CONFIG_TABLE_SIZE; ++c1) {
36 if ((TempTableInfo[c1] & 0xFFFF) == Type) {
37 int Entries = (TempTableInfo[c1] & 0xFFFF0000) >> 16;
38 ConfigTable[c1] = new databasebase*[Entries + 1];
39 for (int c2 = 0; c2 < Entries; ++c2) ConfigTable[c1][c2] = TempTable[c2][c1];
40 ConfigTable[c1][Entries] = 0;
43 return TempTables;
47 static void collectHandler (festring &dest, std::stack<TextInput *> &infStack, TextInput **iff) {
48 TextInput *inFile = *iff;
49 festring Word = inFile->ReadWord(true);
50 dest << "on " << Word << "\n{\n";
51 if (inFile->ReadWord() != "{") ABORT("'{' missing in datafile %s line %d!", inFile->GetFileName().CStr(), inFile->TokenLine());
52 int cnt = 1;
53 truth inStr = false;
54 for (;;) {
55 int ch = inFile->GetChar();
56 if (ch == EOF) {
57 if (infStack.empty()) ABORT("'}' missing in datafile %s line %d!", inFile->GetFileName().CStr(), inFile->TokenLine());
58 delete inFile;
59 *iff = inFile = infStack.top();
60 infStack.pop();
61 continue;
63 dest << (char)ch;
64 if (inStr) {
65 if (ch == '"') inStr = false;
66 else if (ch == '\\') {
67 ch = inFile->GetChar();
68 if (ch == EOF) ABORT("Unexpected end of file %s!", inFile->GetFileName().CStr());
69 dest << (char)ch;
71 continue;
73 if (ch == '}') {
74 if (--cnt < 1) break;
75 } else if (ch == '{') {
76 cnt++;
77 } else if (ch == '"') {
78 inStr = true;
81 dest << "\n";
85 template <class type> void databasecreator<type>::ReadFrom (const festring &baseFileName) {
86 std::stack<TextInput *> infStack;
88 // add module files
89 auto modlist = game::GetModuleList();
90 for (unsigned idx = modlist.size(); idx > 0; --idx) {
91 festring infname = game::GetGameDir()+"script/"+modlist[idx-1]+"/"+baseFileName+".dat";
92 if (inputfile::fileExists(infname)) {
93 TextInput *ifl = new TextInputFile(infname, &game::GetGlobalValueMap());
94 ifl->setGetVarCB(game::ldrGetVar);
95 infStack.push(ifl);
99 // add main file
101 festring infname = game::GetGameDir()+"script/"+baseFileName+".dat";
102 TextInput *ifl = new TextInputFile(infname, &game::GetGlobalValueMap());
103 ifl->setGetVarCB(game::ldrGetVar);
104 infStack.push(ifl);
107 if (infStack.size() == 0) ABORT("Cannot find '%s' scripts!", baseFileName.CStr());
109 // load files
110 typedef typename type::prototype prototype;
111 festring Word, defName;
112 database *TempConfig[1024];
113 databasebase **TempTable[1024];
114 sLong TempTableInfo[CONFIG_TABLE_SIZE];
115 int TempTables = 1;
116 databasebase *FirstTempTable[CONFIG_TABLE_SIZE];
117 TempTable[0] = FirstTempTable;
118 memset(TempTableInfo, 0, sizeof(TempTableInfo));
119 CreateDataBaseMemberMap();
120 while (!infStack.empty()) {
121 TextInput *inFile = infStack.top();
122 infStack.pop();
123 inFile->setGetVarCB(game::ldrGetVar);
124 //fprintf(stderr, "MAIN: %s\n", inFile->GetFileName().CStr());
125 for (inFile->ReadWord(Word, false); !inFile->Eof(); inFile->ReadWord(Word, false)) {
126 if (Word == "Include") {
127 Word = inFile->ReadWord();
128 if (inFile->ReadWord() != ";") ABORT("Invalid terminator in file %s at line %d!", inFile->GetFileName().CStr(), inFile->TokenLine());
129 //fprintf(stderr, "loading: %s\n", Word.CStr());
130 TextInput *incf = new TextInputFile(inputfile::buildIncludeName(inFile->GetFileName(), Word), &game::GetGlobalValueMap());
131 infStack.push(inFile);
132 inFile = incf;
133 inFile->setGetVarCB(game::ldrGetVar);
134 continue;
136 if (Word == "Message") {
137 Word = inFile->ReadWord();
138 if (inFile->ReadWord() != ";") ABORT("Invalid terminator in file %s at line %d!", inFile->GetFileName().CStr(), inFile->TokenLine());
139 fprintf(stderr, "MESSAGE: %s\n", Word.CStr());
140 continue;
142 ////////
143 truth doExtend = false, doOverride = false;
144 if (Word == "Extend") {
145 Word = inFile->ReadWord();
146 doExtend = true;
147 } else if (Word == "Override" || Word == "Redefine") {
148 Word = inFile->ReadWord();
149 doOverride = true;
151 ////////
152 defName = Word;
153 int Type = protocontainer<type>::SearchCodeName(Word);
154 if (!Type) ABORT("Odd term <%s> encountered in %s datafile %s line %d!", Word.CStr(), protocontainer<type>::GetMainClassID(), inFile->GetFileName().CStr(), inFile->TokenLine());
155 //fprintf(stderr, "class <%s>\n", Word.CStr());
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(inputfile::buildIncludeName(inFile->GetFileName(), 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());
221 TextInput *incf = new TextInputFile(game::GetGameDir()+"script/"+fname, &game::GetGlobalValueMap());
222 infStack.push(inFile);
223 inFile = incf;
225 ABORT("Config includes aren't supported yet!");
226 } else {
227 //fprintf(stderr, "new config %d (%s) for %s\n", ConfigNumber, inFile->numStr().CStr(), defName.CStr());
228 database *ConfigDataBase = new database(*Proto->ChooseBaseForConfig(TempConfig, Configs, ConfigNumber));
229 festring cfgname = inFile->numStr();
230 festring infname = inFile->GetFileName();
231 ConfigDataBase->InitDefaults(Proto, ConfigNumber, cfgname);
232 TempConfig[Configs++] = ConfigDataBase;
233 if (inFile->ReadWord() != "{") ABORT("'{' missing in %s datafile %s line %d!", protocontainer<type>::GetMainClassID(), inFile->GetFileName().CStr(), inFile->TokenLine());
234 for (inFile->ReadWord(Word); Word != "}"; inFile->ReadWord(Word)) {
235 if (Word == "on") {
236 collectHandler(Proto->mOnEvents, infStack, &inFile);
237 continue;
239 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());
241 ConfigDataBase->PostProcess();
243 continue;
245 if (Word == "on") {
246 collectHandler(Proto->mOnEvents, infStack, &inFile);
247 continue;
249 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());
251 DataBase->PostProcess();
252 //Configs = Proto->CreateSpecialConfigurations(TempConfig, Configs);
253 Proto->ConfigData = new database *[Configs];
254 Proto->ConfigSize = Configs;
255 memmove(Proto->ConfigData, TempConfig, Configs*sizeof(database *));
257 delete inFile;
260 int c1;
261 for (c1 = 0; c1 < SPECIAL_CONFIGURATION_GENERATION_LEVELS; ++c1) {
262 for (int c2 = 1; c2 < protocontainer<type>::GetSize(); ++c2) {
263 prototype *Proto = protocontainer<type>::GetProtoData()[c2];
264 int Configs = Proto->ConfigSize;
265 memmove(TempConfig, Proto->ConfigData, Configs*sizeof(database *));
266 Configs = Proto->CreateSpecialConfigurations(TempConfig, Configs, c1);
267 if (Proto->ConfigSize != Configs) {
268 delete [] Proto->ConfigData;
269 Proto->ConfigData = new database *[Configs];
270 Proto->ConfigSize = Configs;
271 memmove(Proto->ConfigData, TempConfig, Configs*sizeof(database *));
275 for (c1 = 1; c1 < protocontainer<type>::GetSize(); ++c1) {
276 prototype *Proto = protocontainer<type>::GetProtoData()[c1];
277 TempTables =
278 CreateConfigTable(reinterpret_cast<databasebase ***>(Proto->ConfigTable),
279 TempTable,
280 reinterpret_cast<databasebase **>(Proto->ConfigData),
281 TempTableInfo, c1, Proto->ConfigSize, TempTables);
283 for (c1 = 1; c1 < TempTables; ++c1) delete [] TempTable[c1];
284 GetDataBaseMemberMap().clear();
288 template <class type> int databasecreator<type>::CreateDivineConfigurations (const prototype *Proto, database **TempConfig, int Configs) {
289 int OldConfigs = Configs;
290 for (int c1 = 1; c1 < protocontainer<god>::GetSize(); ++c1) {
291 database *ConfigDataBase = 0;
292 int c2;
293 festring dcfgname = "divine";
294 for (c2 = 1; c2 < OldConfigs; ++c2) {
295 ConfigDataBase = TempConfig[c2];
296 if (ConfigDataBase->Config == c1) {
297 dcfgname << " ";
298 dcfgname << ConfigDataBase->CfgStrName;
299 break;
302 truth Created = false;
303 if (c2 == OldConfigs) {
304 ConfigDataBase = new database(**TempConfig);
305 ConfigDataBase->InitDefaults(Proto, c1, dcfgname);
306 Created = true;
308 ConfigDataBase->AttachedGod = c1;
309 ConfigDataBase->PostFix << "of " << festring(protocontainer<god>::GetProto(c1)->GetClassID()).CapitalizeCopy();
310 if (Created) TempConfig[Configs++] = ConfigDataBase;
312 return Configs;
316 template int databasecreator<character>::CreateDivineConfigurations (const prototype *, database **, int);
317 template int databasecreator<item>::CreateDivineConfigurations (const prototype *, database **, int);
318 template int databasecreator<olterrain>::CreateDivineConfigurations (const prototype *, database **, int);
321 template <class database, class member> struct databasemember : public databasememberbase<database> {
322 databasemember (member Member) : Member(Member) {}
323 virtual void ReadData (database &DataBase, TextInput &SaveFile) { ::ReadData(DataBase.*Member, SaveFile); }
324 member Member;
328 template <class database, class member> void AddMember(std::map<festring, databasememberbase<database>*>& Map, cchar* Str, member Member)
330 Map.insert(std::pair<festring, databasememberbase<database>*>(Str, new databasemember<database, member>(Member)));
334 /* Explicit instantiations seem to increase compile speed greatly here... */
336 #define INST_ADD_MEMBER(type, member) \
337 template void AddMember<type##database, member type##database::*>(std::map<festring, databasememberbase<type##database>*>&, cchar*, member type##database::*)
339 INST_ADD_MEMBER(character, int);
340 //INST_ADD_MEMBER(character, sLong); //k8:64
341 INST_ADD_MEMBER(character, packcol16);
342 INST_ADD_MEMBER(character, col24);
343 INST_ADD_MEMBER(character, packv2);
344 INST_ADD_MEMBER(character, festring);
345 INST_ADD_MEMBER(character, fearray<sLong>);
346 INST_ADD_MEMBER(character, fearray<festring>);
347 INST_ADD_MEMBER(character, contentscript<item>);
349 INST_ADD_MEMBER(item, int);
350 //INST_ADD_MEMBER(item, sLong); //k8:64
351 INST_ADD_MEMBER(item, col24);
352 INST_ADD_MEMBER(item, v2);
353 INST_ADD_MEMBER(item, festring);
354 INST_ADD_MEMBER(item, fearray<sLong>);
355 INST_ADD_MEMBER(item, fearray<festring>);
357 INST_ADD_MEMBER(glterrain, int);
358 //INST_ADD_MEMBER(glterrain, sLong); //k8:64
359 INST_ADD_MEMBER(glterrain, v2);
360 INST_ADD_MEMBER(glterrain, festring);
361 INST_ADD_MEMBER(glterrain, fearray<sLong>);
363 INST_ADD_MEMBER(olterrain, int);
364 //INST_ADD_MEMBER(olterrain, sLong); //k8:64
365 INST_ADD_MEMBER(olterrain, v2);
366 INST_ADD_MEMBER(olterrain, festring);
367 INST_ADD_MEMBER(olterrain, fearray<sLong>);
368 INST_ADD_MEMBER(olterrain, fearray<contentscript<item> >);
370 INST_ADD_MEMBER(owterrain, int);
371 //INST_ADD_MEMBER(owterrain, sLong); //k8:64
372 INST_ADD_MEMBER(owterrain, v2);
373 INST_ADD_MEMBER(owterrain, festring);
375 INST_ADD_MEMBER(material, int);
376 //INST_ADD_MEMBER(material, sLong); //k8:64
377 INST_ADD_MEMBER(material, col24);
378 INST_ADD_MEMBER(material, festring);
379 INST_ADD_MEMBER(material, contentscript<item>);
381 #define ADD_MEMBER(data) AddMember(Map, #data, &database::data);
383 template<> void databasecreator<character>::CreateDataBaseMemberMap () {
384 databasemembermap &Map = GetDataBaseMemberMap();
385 ADD_MEMBER(DefaultArmStrength);
386 ADD_MEMBER(DefaultLegStrength);
387 ADD_MEMBER(DefaultDexterity);
388 ADD_MEMBER(DefaultAgility);
389 ADD_MEMBER(DefaultEndurance);
390 ADD_MEMBER(DefaultPerception);
391 ADD_MEMBER(DefaultIntelligence);
392 ADD_MEMBER(DefaultWisdom);
393 ADD_MEMBER(DefaultWillPower);
394 ADD_MEMBER(DefaultCharisma);
395 ADD_MEMBER(DefaultMana);
396 ADD_MEMBER(DefaultMoney);
397 ADD_MEMBER(TotalSize);
398 ADD_MEMBER(CanRead);
399 ADD_MEMBER(Sex);
400 ADD_MEMBER(CanBeGenerated);
401 ADD_MEMBER(CriticalModifier);
402 ADD_MEMBER(StandVerb);
403 ADD_MEMBER(CanOpen);
404 ADD_MEMBER(Frequency);
405 ADD_MEMBER(EnergyResistance);
406 ADD_MEMBER(FireResistance);
407 ADD_MEMBER(PoisonResistance);
408 ADD_MEMBER(ElectricityResistance);
409 ADD_MEMBER(AcidResistance);
410 ADD_MEMBER(SoundResistance);
411 ADD_MEMBER(IsUnique);
412 ADD_MEMBER(ConsumeFlags);
413 ADD_MEMBER(TotalVolume);
414 ADD_MEMBER(HeadBitmapPos);
415 ADD_MEMBER(TorsoBitmapPos);
416 ADD_MEMBER(ArmBitmapPos);
417 ADD_MEMBER(LegBitmapPos);
418 ADD_MEMBER(RightArmBitmapPos);
419 ADD_MEMBER(LeftArmBitmapPos);
420 ADD_MEMBER(RightLegBitmapPos);
421 ADD_MEMBER(LeftLegBitmapPos);
422 ADD_MEMBER(GroinBitmapPos);
423 ADD_MEMBER(ClothColor);
424 ADD_MEMBER(SkinColor);
425 ADD_MEMBER(CapColor);
426 ADD_MEMBER(HairColor);
427 ADD_MEMBER(EyeColor);
428 ADD_MEMBER(TorsoMainColor);
429 ADD_MEMBER(BeltColor);
430 ADD_MEMBER(BootColor);
431 ADD_MEMBER(TorsoSpecialColor);
432 ADD_MEMBER(ArmMainColor);
433 ADD_MEMBER(GauntletColor);
434 ADD_MEMBER(ArmSpecialColor);
435 ADD_MEMBER(LegMainColor);
436 ADD_MEMBER(LegSpecialColor);
437 ADD_MEMBER(IsNameable);
438 ADD_MEMBER(BaseEmitation);
439 ADD_MEMBER(UsesLongArticle);
440 ADD_MEMBER(Adjective);
441 ADD_MEMBER(UsesLongAdjectiveArticle);
442 ADD_MEMBER(NameSingular);
443 ADD_MEMBER(NamePlural);
444 ADD_MEMBER(PostFix);
445 ADD_MEMBER(ArticleMode);
446 ADD_MEMBER(IsAbstract);
447 ADD_MEMBER(IsPolymorphable);
448 ADD_MEMBER(BaseUnarmedStrength);
449 ADD_MEMBER(BaseBiteStrength);
450 ADD_MEMBER(BaseKickStrength);
451 ADD_MEMBER(AttackStyle);
452 ADD_MEMBER(CanUseEquipment);
453 ADD_MEMBER(CanKick);
454 ADD_MEMBER(CanTalk);
455 ADD_MEMBER(ClassStates);
456 ADD_MEMBER(CanBeWished);
457 ADD_MEMBER(Alias);
458 ADD_MEMBER(CreateDivineConfigurations);
459 ADD_MEMBER(CreateGolemMaterialConfigurations);
460 ADD_MEMBER(Helmet);
461 ADD_MEMBER(Amulet);
462 ADD_MEMBER(Cloak);
463 ADD_MEMBER(BodyArmor);
464 ADD_MEMBER(Belt);
465 ADD_MEMBER(RightWielded);
466 ADD_MEMBER(LeftWielded);
467 ADD_MEMBER(RightRing);
468 ADD_MEMBER(LeftRing);
469 ADD_MEMBER(RightGauntlet);
470 ADD_MEMBER(LeftGauntlet);
471 ADD_MEMBER(RightBoot);
472 ADD_MEMBER(LeftBoot);
473 ADD_MEMBER(AttributeBonus);
474 ADD_MEMBER(KnownCWeaponSkills);
475 ADD_MEMBER(CWeaponSkillHits);
476 ADD_MEMBER(RightSWeaponSkillHits);
477 ADD_MEMBER(LeftSWeaponSkillHits);
478 ADD_MEMBER(PanicLevel);
479 ADD_MEMBER(CanBeCloned);
480 ADD_MEMBER(Inventory);
481 ADD_MEMBER(DangerModifier);
482 ADD_MEMBER(DefaultName);
483 ADD_MEMBER(FriendlyReplies);
484 ADD_MEMBER(HostileReplies);
485 ADD_MEMBER(CanZap);
486 ADD_MEMBER(FleshMaterial);
487 ADD_MEMBER(HasALeg);
488 ADD_MEMBER(DeathMessage);
489 ADD_MEMBER(IgnoreDanger);
490 ADD_MEMBER(HPRequirementForGeneration);
491 ADD_MEMBER(DayRequirementForGeneration);
492 ADD_MEMBER(IsExtraCoward);
493 ADD_MEMBER(SpillsBlood);
494 ADD_MEMBER(HasEyes);
495 ADD_MEMBER(HasHead);
496 ADD_MEMBER(CanThrow);
497 ADD_MEMBER(UsesNutrition);
498 ADD_MEMBER(AttackWisdomLimit);
499 ADD_MEMBER(AttachedGod);
500 ADD_MEMBER(BodyPartsDisappearWhenSevered);
501 ADD_MEMBER(CanBeConfused);
502 ADD_MEMBER(CanApply);
503 ADD_MEMBER(WieldedPosition);
504 ADD_MEMBER(NaturalSparkleFlags);
505 ADD_MEMBER(BiteCapturesBodyPart);
506 ADD_MEMBER(IsPlant);
507 ADD_MEMBER(MoveType);
508 ADD_MEMBER(DestroysWalls);
509 ADD_MEMBER(IsRooted);
510 ADD_MEMBER(BloodMaterial);
511 ADD_MEMBER(VomitMaterial);
512 ADD_MEMBER(HasSecondaryMaterial);
513 ADD_MEMBER(IsImmuneToLeprosy);
514 ADD_MEMBER(PolymorphIntelligenceRequirement);
515 ADD_MEMBER(AutomaticallySeen);
516 ADD_MEMBER(CanHear);
517 ADD_MEMBER(DefaultCommandFlags);
518 ADD_MEMBER(ConstantCommandFlags);
519 ADD_MEMBER(WillCarryItems);
520 ADD_MEMBER(ForceVomitMessage);
521 ADD_MEMBER(SweatMaterial);
522 ADD_MEMBER(Sweats);
523 ADD_MEMBER(IsImmuneToItemTeleport);
524 ADD_MEMBER(AlwaysUseMaterialAttributes);
525 ADD_MEMBER(IsEnormous);
526 ADD_MEMBER(ScienceTalkAdjectiveAttribute);
527 ADD_MEMBER(ScienceTalkSubstantiveAttribute);
528 ADD_MEMBER(ScienceTalkPrefix);
529 ADD_MEMBER(ScienceTalkName);
530 ADD_MEMBER(ScienceTalkPossibility);
531 ADD_MEMBER(ScienceTalkIntelligenceModifier);
532 ADD_MEMBER(ScienceTalkWisdomModifier);
533 ADD_MEMBER(ScienceTalkCharismaModifier);
534 ADD_MEMBER(ScienceTalkIntelligenceRequirement);
535 ADD_MEMBER(ScienceTalkWisdomRequirement);
536 ADD_MEMBER(ScienceTalkCharismaRequirement);
537 ADD_MEMBER(IsExtraFragile);
538 ADD_MEMBER(AllowUnconsciousness);
539 ADD_MEMBER(CanChoke);
540 ADD_MEMBER(IsImmuneToStickiness);
541 ADD_MEMBER(DisplacePriority);
542 ADD_MEMBER(RunDescriptionLineOne);
543 ADD_MEMBER(RunDescriptionLineTwo);
544 ADD_MEMBER(ForceCustomStandVerb);
545 ADD_MEMBER(VomittingIsUnhealthy);
546 ADD_MEMBER(AllowPlayerToChangeEquipment);
547 ADD_MEMBER(TamingDifficulty);
548 ADD_MEMBER(IsMasochist);
549 ADD_MEMBER(IsSadist);
550 ADD_MEMBER(IsCatacombCreature);
551 ADD_MEMBER(CreateUndeadConfigurations);
552 ADD_MEMBER(UndeadVersions);
553 ADD_MEMBER(UndeadAttributeModifier);
554 ADD_MEMBER(UndeadVolumeModifier);
555 ADD_MEMBER(UndeadCopyMaterials);
556 ADD_MEMBER(CanBeGeneratedOnlyInTheCatacombs);
557 ADD_MEMBER(IsAlcoholic);
558 ADD_MEMBER(IsImmuneToWhipOfThievery);
559 ADD_MEMBER(IsRangedAttacker);
560 ADD_MEMBER(WhatCategoryToThrow);
561 ADD_MEMBER(WhatWeaponConfigToThrow);
562 ADD_MEMBER(WhatThrowItemTypesToThrow);
563 ADD_MEMBER(AllowedDungeons);
564 ADD_MEMBER(LevelTags);
565 ADD_MEMBER(HomeLevel);
566 ADD_MEMBER(NaturalTeam);
570 template<> void databasecreator<item>::CreateDataBaseMemberMap () {
571 databasemembermap &Map = GetDataBaseMemberMap();
572 ADD_MEMBER(Possibility);
573 ADD_MEMBER(IsDestroyable);
574 ADD_MEMBER(CanBeWished);
575 ADD_MEMBER(IsMaterialChangeable);
576 ADD_MEMBER(WeaponCategory);
577 ADD_MEMBER(IsPolymorphSpawnable);
578 ADD_MEMBER(IsAutoInitializable);
579 ADD_MEMBER(Category);
580 ADD_MEMBER(EnergyResistance);
581 ADD_MEMBER(FireResistance);
582 ADD_MEMBER(PoisonResistance);
583 ADD_MEMBER(ElectricityResistance);
584 ADD_MEMBER(AcidResistance);
585 ADD_MEMBER(SoundResistance);
586 ADD_MEMBER(StrengthModifier);
587 ADD_MEMBER(FormModifier);
588 ADD_MEMBER(DefaultSize);
589 ADD_MEMBER(DefaultMainVolume);
590 ADD_MEMBER(DefaultSecondaryVolume);
591 ADD_MEMBER(BitmapPos);
592 ADD_MEMBER(Price);
593 ADD_MEMBER(BaseEmitation);
594 ADD_MEMBER(UsesLongArticle);
595 ADD_MEMBER(Adjective);
596 ADD_MEMBER(UsesLongAdjectiveArticle);
597 ADD_MEMBER(NameSingular);
598 ADD_MEMBER(NamePlural);
599 ADD_MEMBER(PostFix);
600 ADD_MEMBER(ArticleMode);
601 ADD_MEMBER(MainMaterialConfig);
602 ADD_MEMBER(SecondaryMaterialConfig);
603 ADD_MEMBER(MaterialConfigChances);
604 ADD_MEMBER(IsAbstract);
605 ADD_MEMBER(IsPolymorphable);
606 ADD_MEMBER(Alias);
607 ADD_MEMBER(OKVisualEffects);
608 ADD_MEMBER(CanBeGeneratedInContainer);
609 ADD_MEMBER(ForcedVisualEffects);
610 ADD_MEMBER(Roundness);
611 ADD_MEMBER(GearStates);
612 ADD_MEMBER(IsTwoHanded);
613 ADD_MEMBER(CreateDivineConfigurations);
614 ADD_MEMBER(CanBeCloned);
615 ADD_MEMBER(CanBeMirrored);
616 ADD_MEMBER(BeamRange);
617 ADD_MEMBER(CanBeBroken);
618 ADD_MEMBER(WallBitmapPos);
619 ADD_MEMBER(FlexibleNameSingular);
620 ADD_MEMBER(MaxCharges);
621 ADD_MEMBER(MinCharges);
622 ADD_MEMBER(CanBePiled);
623 ADD_MEMBER(StorageVolume);
624 ADD_MEMBER(MaxGeneratedContainedItems);
625 ADD_MEMBER(AffectsArmStrength);
626 ADD_MEMBER(AffectsLegStrength);
627 ADD_MEMBER(AffectsDexterity);
628 ADD_MEMBER(AffectsAgility);
629 ADD_MEMBER(AffectsEndurance);
630 ADD_MEMBER(AffectsPerception);
631 ADD_MEMBER(AffectsIntelligence);
632 ADD_MEMBER(AffectsWisdom);
633 ADD_MEMBER(AffectsWillPower);
634 ADD_MEMBER(AffectsCharisma);
635 ADD_MEMBER(AffectsMana);
636 ADD_MEMBER(BaseEnchantment);
637 ADD_MEMBER(PriceIsProportionalToEnchantment);
638 ADD_MEMBER(InElasticityPenaltyModifier);
639 ADD_MEMBER(CanBeUsedBySmith);
640 ADD_MEMBER(AffectsCarryingCapacity);
641 ADD_MEMBER(DamageDivider);
642 ADD_MEMBER(HandleInPairs);
643 ADD_MEMBER(CanBeEnchanted);
644 ADD_MEMBER(BeamColor);
645 ADD_MEMBER(BeamEffect);
646 ADD_MEMBER(BeamStyle);
647 ADD_MEMBER(WearWisdomLimit);
648 ADD_MEMBER(AttachedGod);
649 ADD_MEMBER(BreakEffectRangeSquare);
650 ADD_MEMBER(WieldedBitmapPos);
651 ADD_MEMBER(IsQuestItem);
652 ADD_MEMBER(IsGoodWithPlants);
653 ADD_MEMBER(CreateLockConfigurations);
654 ADD_MEMBER(CanBePickedUp);
655 ADD_MEMBER(CoverPercentile);
656 ADD_MEMBER(TorsoArmorBitmapPos);
657 ADD_MEMBER(ArmArmorBitmapPos);
658 ADD_MEMBER(AthleteArmArmorBitmapPos);
659 ADD_MEMBER(LegArmorBitmapPos);
660 ADD_MEMBER(HelmetBitmapPos);
661 ADD_MEMBER(CloakBitmapPos);
662 ADD_MEMBER(BeltBitmapPos);
663 ADD_MEMBER(GauntletBitmapPos);
664 ADD_MEMBER(BootBitmapPos);
665 ADD_MEMBER(HasSecondaryMaterial);
666 ADD_MEMBER(AllowEquip);
667 ADD_MEMBER(ReadDifficulty);
668 ADD_MEMBER(IsValuable);
669 ADD_MEMBER(EnchantmentMinusChance);
670 ADD_MEMBER(EnchantmentPlusChance);
671 ADD_MEMBER(TeleportPriority);
672 ADD_MEMBER(HasNormalPictureDirection);
673 ADD_MEMBER(DamageFlags);
674 ADD_MEMBER(IsKamikazeWeapon);
675 ADD_MEMBER(FlexibilityIsEssential);
676 ADD_MEMBER(BreakMsg);
677 ADD_MEMBER(IsSadistWeapon);
678 ADD_MEMBER(IsThrowingWeapon);
679 ADD_MEMBER(ThrowItemTypes);
680 ADD_MEMBER(CanFlame);
681 ADD_MEMBER(AllowedDungeons);
682 ADD_MEMBER(LevelTags);
686 template <class type> void databasecreator<type>::CreateLTerrainDataBaseMemberMap () {
687 databasemembermap &Map = GetDataBaseMemberMap();
688 ADD_MEMBER(BitmapPos);
689 ADD_MEMBER(UsesLongArticle);
690 ADD_MEMBER(Adjective);
691 ADD_MEMBER(UsesLongAdjectiveArticle);
692 ADD_MEMBER(NameSingular);
693 ADD_MEMBER(NamePlural);
694 ADD_MEMBER(PostFix);
695 ADD_MEMBER(ArticleMode);
696 ADD_MEMBER(MainMaterialConfig);
697 ADD_MEMBER(SecondaryMaterialConfig);
698 ADD_MEMBER(MaterialConfigChances);
699 ADD_MEMBER(IsAbstract);
700 ADD_MEMBER(OKVisualEffects);
701 ADD_MEMBER(MaterialColorB);
702 ADD_MEMBER(MaterialColorC);
703 ADD_MEMBER(MaterialColorD);
704 ADD_MEMBER(SitMessage);
705 ADD_MEMBER(ShowMaterial);
706 ADD_MEMBER(AttachedGod);
707 ADD_MEMBER(Walkability);
708 ADD_MEMBER(HasSecondaryMaterial);
709 ADD_MEMBER(UseBorderTiles);
710 ADD_MEMBER(BorderTilePriority);
714 template<> void databasecreator<glterrain>::CreateDataBaseMemberMap () {
715 CreateLTerrainDataBaseMemberMap();
719 template<> void databasecreator<olterrain>::CreateDataBaseMemberMap () {
720 CreateLTerrainDataBaseMemberMap();
721 databasemembermap &Map = GetDataBaseMemberMap();
722 ADD_MEMBER(CreateDivineConfigurations);
723 ADD_MEMBER(DigMessage);
724 ADD_MEMBER(CanBeDestroyed);
725 ADD_MEMBER(RestModifier);
726 ADD_MEMBER(RestMessage);
727 ADD_MEMBER(IsUpLink);
728 ADD_MEMBER(StorageVolume);
729 ADD_MEMBER(HPModifier);
730 ADD_MEMBER(IsSafeToCreateDoor);
731 ADD_MEMBER(OpenBitmapPos);
732 ADD_MEMBER(CreateLockConfigurations);
733 ADD_MEMBER(IsAlwaysTransparent);
734 ADD_MEMBER(CreateWindowConfigurations);
735 ADD_MEMBER(WindowBitmapPos);
736 ADD_MEMBER(ShowThingsUnder);
737 ADD_MEMBER(LeftOverItems);
738 ADD_MEMBER(IsWall);
742 template<> void databasecreator<owterrain>::CreateDataBaseMemberMap () {
743 //CreateWTerrainDataBaseMemberMap();
744 databasemembermap &Map = GetDataBaseMemberMap();
745 ADD_MEMBER(BitmapPos);
746 ADD_MEMBER(IsAbstract);
747 ADD_MEMBER(NameSingular);
748 ADD_MEMBER(NameStem);
749 ADD_MEMBER(UsesLongArticle);
750 ADD_MEMBER(AttachedDungeon);
751 ADD_MEMBER(AttachedArea);
752 ADD_MEMBER(CanBeGenerated);
753 ADD_MEMBER(NativeGTerrainType);
754 ADD_MEMBER(RevealEnvironmentInitially);
755 ADD_MEMBER(CanBeOnAnyTerrain);
756 ADD_MEMBER(WantContinentWith);
757 ADD_MEMBER(Probability);
758 ADD_MEMBER(CanBeSkipped);
759 ADD_MEMBER(PlaceInitially);
763 template<> void databasecreator<material>::CreateDataBaseMemberMap () {
764 databasemembermap &Map = GetDataBaseMemberMap();
765 ADD_MEMBER(CommonFlags);
766 ADD_MEMBER(NameFlags);
767 ADD_MEMBER(CategoryFlags);
768 ADD_MEMBER(BodyFlags);
769 ADD_MEMBER(InteractionFlags);
770 ADD_MEMBER(StrengthValue);
771 ADD_MEMBER(ConsumeType);
772 ADD_MEMBER(Density);
773 ADD_MEMBER(Color);
774 ADD_MEMBER(RainColor);
775 ADD_MEMBER(PriceModifier);
776 ADD_MEMBER(Emitation);
777 ADD_MEMBER(NutritionValue);
778 ADD_MEMBER(NameStem);
779 ADD_MEMBER(AdjectiveStem);
780 ADD_MEMBER(Effect);
781 ADD_MEMBER(ConsumeEndMessage);
782 ADD_MEMBER(HitMessage);
783 ADD_MEMBER(ExplosivePower);
784 ADD_MEMBER(Alpha);
785 ADD_MEMBER(Flexibility);
786 ADD_MEMBER(SpoilModifier);
787 ADD_MEMBER(EffectStrength);
788 ADD_MEMBER(DigProductMaterial);
789 ADD_MEMBER(ConsumeWisdomLimit);
790 ADD_MEMBER(AttachedGod);
791 ADD_MEMBER(BreatheMessage);
792 ADD_MEMBER(StepInWisdomLimit);
793 ADD_MEMBER(RustModifier);
794 ADD_MEMBER(Acidicity);
795 ADD_MEMBER(NaturalForm);
796 ADD_MEMBER(HardenedMaterial);
797 ADD_MEMBER(SoftenedMaterial);
798 ADD_MEMBER(IntelligenceRequirement);
799 ADD_MEMBER(Stickiness);
800 ADD_MEMBER(DisablesPanicWhenConsumed);
801 ADD_MEMBER(BlockESP);
805 #define ADD_BASE_VALUE(name)\
806 if (Word == #name) game::GetGlobalValueMap()[CONST_S("Base")] = DataBase.*static_cast<databasemember<database, feuLong database::*>*>(Data)->Member;
809 template <class type> void databasecreator<type>::SetBaseValue(cfestring &, databasememberbase<database> *, database &) {}
811 template<> void databasecreator<material>::SetBaseValue(cfestring &Word, databasememberbase<materialdatabase> *Data,
812 materialdatabase &DataBase)
814 ADD_BASE_VALUE(CommonFlags);
815 ADD_BASE_VALUE(NameFlags);
816 ADD_BASE_VALUE(CategoryFlags);
817 ADD_BASE_VALUE(BodyFlags);
818 ADD_BASE_VALUE(InteractionFlags);
822 template <class type> truth databasecreator<type>::AnalyzeData (TextInput &SaveFile, cfestring &Word, database &DataBase) {
823 typename databasemembermap::iterator i = GetDataBaseMemberMap().find(Word);
824 if (i != GetDataBaseMemberMap().end()) {
825 SetBaseValue(Word, i->second, DataBase);
826 i->second->ReadData(DataBase, SaveFile);
827 CheckDefaults(Word, DataBase);
828 return true;
830 return false;
834 template <> void databasecreator<character>::CheckDefaults (cfestring &Word, character::database &DataBase) {
835 if (Word == "ArmBitmapPos") { DataBase.RightArmBitmapPos = DataBase.LeftArmBitmapPos = DataBase.ArmBitmapPos; return; }
836 if (Word == "LegBitmapPos") { DataBase.GroinBitmapPos = DataBase.RightLegBitmapPos = DataBase.LeftLegBitmapPos = DataBase.LegBitmapPos; return; }
837 if (Word == "ClothColor") { DataBase.CapColor = DataBase.TorsoMainColor = DataBase.ArmMainColor = DataBase.GauntletColor = DataBase.LegMainColor = DataBase.ClothColor; return; }
838 if (Word == "NameSingular") { DataBase.NamePlural = DataBase.NameSingular+'s'; return; }
839 if (Word == "BaseUnarmedStrength") { DataBase.BaseBiteStrength = DataBase.BaseUnarmedStrength>>1; DataBase.BaseKickStrength = DataBase.BaseUnarmedStrength<<1; return; }
840 if (Word == "RightGauntlet") { DataBase.LeftGauntlet = DataBase.RightGauntlet; return; }
841 if (Word == "RightBoot") { DataBase.LeftBoot = DataBase.RightBoot; return; }
842 if (Word == "IsUnique") { DataBase.CanBeWished = !DataBase.IsUnique; return; }
843 if (Word == "DefaultName") {
844 // k8: don't add duplicate alias
845 for (uInt c = 0; c < DataBase.Alias.Size; ++c) {
846 if (DataBase.Alias[c] == DataBase.DefaultName) return;
848 DataBase.Alias.Add(DataBase.DefaultName);
850 if (DataBase.Alias.Size != 1) {
851 printf("=== %s ===\n", DataBase.NameSingular.CStr());
852 for (uInt c = 0; c < DataBase.Alias.Size; ++c) {
853 printf(" %u: %s\n", c, DataBase.Alias[c].CStr());
857 return;
862 template <> void databasecreator<item>::CheckDefaults (cfestring &Word, item::database &DataBase) {
863 if (Word == "NameSingular") { DataBase.NamePlural = DataBase.NameSingular+'s'; DataBase.FlexibleNameSingular = DataBase.NameSingular; return; }
864 if (Word == "BitmapPos") { DataBase.WallBitmapPos = DataBase.BitmapPos; return; }
865 if (Word == "MaterialConfigChances") { DataBase.MaterialConfigChanceSum = femath::SumArray(DataBase.MaterialConfigChances); return; }
866 if (Word == "CanBeCloned") { DataBase.CanBeMirrored = DataBase.CanBeCloned; return; }
870 template <> void databasecreator<glterrain>::CheckDefaults (cfestring &Word, glterrain::database &DataBase) {
871 if (Word == "NameSingular") { DataBase.NamePlural = DataBase.NameSingular+'s'; return; }
872 if (Word == "MaterialConfigChances") { DataBase.MaterialConfigChanceSum = femath::SumArray(DataBase.MaterialConfigChances); return; }
876 template <> void databasecreator<olterrain>::CheckDefaults (cfestring &Word, olterrain::database &DataBase) {
877 if (Word == "NameSingular") { DataBase.NamePlural = DataBase.NameSingular+'s'; return; }
878 if (Word == "MaterialConfigChances") { DataBase.MaterialConfigChanceSum = femath::SumArray(DataBase.MaterialConfigChances); return; }
882 template <> void databasecreator<material>::CheckDefaults (cfestring &Word, material::database &DataBase) {
883 if (Word == "NameStem") { DataBase.AdjectiveStem = DataBase.NameStem; return; }
884 if (Word == "Color") { DataBase.RainColor = DataBase.Color; return; }
888 template<> void databasecreator<owterrain>::CheckDefaults (cfestring& Word, owterrain::database& DataBase) {
893 void databasesystem::Initialize () {
894 /* Must be before character */
895 databasecreator<material>::ReadFrom("material");
896 databasecreator<character>::ReadFrom("char");
897 /* Must be before olterrain */
898 databasecreator<item>::ReadFrom("item");
899 databasecreator<glterrain>::ReadFrom("glterra");
900 databasecreator<olterrain>::ReadFrom("olterra");
901 /* Must be last */
902 databasecreator<owterrain>::ReadFrom("owterra");
906 template <class type> inline void databasecreator<type>::FindDataBase (const database *&DataBase, const prototype *Proto, int Config) {
907 database **Table = Proto->ConfigTable[(Config >> 8) ^ (Config & 0xFF)];
908 if (Table) {
909 if ((*Table)->Config == Config) {
910 DataBase = *Table;
911 return;
913 for (++Table; *Table; ++Table) {
914 if ((*Table)->Config == Config) {
915 DataBase = *Table;
916 return;
920 DataBase = 0;
924 template void databasecreator<character>::FindDataBase (const database *&, const prototype *, int);
925 template void databasecreator<material>::FindDataBase (const database *&, const prototype *, int);
927 template <class type> void databasecreator<type>::InstallDataBase (type *Instance, int Config) {
928 const prototype *Proto = Instance->FindProtoType();
929 FindDataBase(Instance->DataBase, Proto, Config);
930 if (!Instance->DataBase) {
931 //*((int *)0) = 0;
932 ABORT("Undefined %s configuration #%08x sought!", Proto->GetClassID(), (unsigned int)Config);
936 #define INST_INSTALL_DATABASE(type) template void databasecreator<type>::InstallDataBase(type *, int)
938 INST_INSTALL_DATABASE(material);
939 INST_INSTALL_DATABASE(character);
940 INST_INSTALL_DATABASE(item);
941 INST_INSTALL_DATABASE(glterrain);
942 INST_INSTALL_DATABASE(olterrain);
943 INST_INSTALL_DATABASE(owterrain);