`RandomChance` type, and two new item fields: `MagicEffectChance`, `MagicEffectDuration`
[k8-i-v-a-n.git] / src / game / database.cpp
blob9be6faa459f0f8409beb1fb6f418b3f8f7071bd8
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 template <class type> void databasecreator<type>::ReadFrom (const festring &baseFileName) {
48 std::stack<TextInput *> infStack;
50 // add module files
51 auto modlist = game::GetModuleList();
52 for (unsigned idx = modlist.size(); idx > 0; --idx) {
53 festring infname = game::GetGameDir()+"script/"+modlist[idx-1]+"/"+baseFileName+".dat";
54 if (inputfile::fileExists(infname)) {
55 TextInput *ifl = new TextInputFile(infname, &game::GetGlobalValueMap());
56 ifl->setGetVarCB(game::ldrGetVar);
57 infStack.push(ifl);
61 // add main file
63 festring infname = game::GetGameDir()+"script/"+baseFileName+".dat";
64 TextInput *ifl = new TextInputFile(infname, &game::GetGlobalValueMap());
65 ifl->setGetVarCB(game::ldrGetVar);
66 infStack.push(ifl);
69 if (infStack.size() == 0) ABORT("Cannot find '%s' scripts!", baseFileName.CStr());
71 // load files
72 typedef typename type::prototype prototype;
73 festring Word, defName;
74 database *TempConfig[1024];
75 databasebase **TempTable[1024];
76 sLong TempTableInfo[CONFIG_TABLE_SIZE];
77 int TempTables = 1;
78 databasebase *FirstTempTable[CONFIG_TABLE_SIZE];
79 TempTable[0] = FirstTempTable;
80 memset(TempTableInfo, 0, sizeof(TempTableInfo));
81 CreateDataBaseMemberMap();
82 while (!infStack.empty()) {
83 TextInput *inFile = infStack.top();
84 infStack.pop();
85 inFile->setGetVarCB(game::ldrGetVar);
86 //fprintf(stderr, "MAIN: %s\n", inFile->GetFileName().CStr());
87 for (inFile->ReadWord(Word, false); !inFile->Eof(); inFile->ReadWord(Word, false)) {
88 if (Word == "Include") {
89 Word = inFile->ReadWord();
90 if (inFile->ReadWord() != ";") ABORT("Invalid terminator in file %s at line %d!", inFile->GetFileName().CStr(), inFile->TokenLine());
91 //fprintf(stderr, "loading: %s\n", Word.CStr());
92 TextInput *incf = new TextInputFile(inputfile::buildIncludeName(inFile->GetFileName(), Word), &game::GetGlobalValueMap());
93 infStack.push(inFile);
94 inFile = incf;
95 inFile->setGetVarCB(game::ldrGetVar);
96 continue;
98 if (Word == "Message") {
99 Word = inFile->ReadWord();
100 if (inFile->ReadWord() != ";") ABORT("Invalid terminator in file %s at line %d!", inFile->GetFileName().CStr(), inFile->TokenLine());
101 fprintf(stderr, "MESSAGE: %s\n", Word.CStr());
102 continue;
104 ////////
105 truth doExtend = false, doOverride = false;
106 if (Word == "Extend") {
107 Word = inFile->ReadWord();
108 doExtend = true;
109 } else if (Word == "Override" || Word == "Redefine") {
110 Word = inFile->ReadWord();
111 doOverride = true;
113 ////////
114 defName = Word;
115 int Type = protocontainer<type>::SearchCodeName(Word);
116 if (!Type) ABORT("Odd term <%s> encountered in %s datafile %s line %d!", Word.CStr(), protocontainer<type>::GetMainClassID(), inFile->GetFileName().CStr(), inFile->TokenLine());
117 //fprintf(stderr, "class <%s>\n", Word.CStr());
118 prototype *Proto = protocontainer<type>::GetProtoData()[Type];
119 if (!Proto) ABORT("Something weird with <%s> in file %s at line %d!", defName.CStr(), inFile->GetFileName().CStr(), inFile->TokenLine());
120 database *DataBase;
121 int Configs;
122 if (doOverride) {
123 if (!Proto->ConfigData) ABORT("Can't override undefined <%s> in file %s at line %d!", defName.CStr(), inFile->GetFileName().CStr(), inFile->TokenLine());
124 delete [] Proto->ConfigData;
125 Proto->ConfigData = NULL;
126 Proto->ConfigSize = 0;
128 if (doExtend) {
129 if (!Proto->ConfigData) ABORT("Can't extend undefined <%s> in file %s at line %d!", defName.CStr(), inFile->GetFileName().CStr(), inFile->TokenLine());
130 DataBase = Proto->ConfigData[0];
131 Configs = Proto->ConfigSize;
132 for (int f = 0; f < Configs; f++) TempConfig[f] = Proto->ConfigData[f];
133 delete [] Proto->ConfigData;
134 Proto->ConfigData = NULL;
135 Proto->ConfigSize = 0;
136 } else {
137 if (Proto->ConfigData) ABORT("Can't redefine <%s> in file %s at line %d!", defName.CStr(), inFile->GetFileName().CStr(), inFile->TokenLine());
138 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());
139 DataBase = Proto->Base ? new database(**Proto->Base->ConfigData) : new database;
140 DataBase->InitDefaults(Proto, 0, "default");
141 TempConfig[0] = DataBase;
142 Configs = 1;
144 if (inFile->ReadWord() != "{") ABORT("'{' missing in %s datafile %s line %d!", protocontainer<type>::GetMainClassID(), inFile->GetFileName().CStr(), inFile->TokenLine());
145 //for (inFile->ReadWord(Word); Word != "}"; inFile->ReadWord(Word))
146 for (;;) {
147 inFile->ReadWord(Word, false);
148 if (Word == "" && inFile->Eof()) {
149 if (infStack.empty()) ABORT("'}' missing in %s datafile %s line %d!", protocontainer<type>::GetMainClassID(), inFile->GetFileName().CStr(), inFile->TokenLine());
150 delete inFile;
151 inFile = infStack.top();
152 infStack.pop();
153 continue;
155 //fprintf(stderr, "D: %d; <%s>\n", (int)infStack.size(), Word.CStr());
156 if (Word == "}") break;
158 if (Word == "Include") {
159 Word = inFile->ReadWord();
160 if (inFile->ReadWord() != ";") ABORT("Invalid terminator in file %s at line %d!", inFile->GetFileName().CStr(), inFile->TokenLine());
161 //fprintf(stderr, "loading: %s\n", Word.CStr());
162 TextInput *incf = new TextInputFile(inputfile::buildIncludeName(inFile->GetFileName(), Word), &game::GetGlobalValueMap());
163 infStack.push(inFile);
164 inFile = incf;
165 inFile->setGetVarCB(game::ldrGetVar);
166 continue;
168 if (Word == "Message") {
169 Word = inFile->ReadWord();
170 if (inFile->ReadWord() != ";") ABORT("Invalid terminator in file %s at line %d!", inFile->GetFileName().CStr(), inFile->TokenLine());
171 fprintf(stderr, "MESSAGE: %s\n", Word.CStr());
172 continue;
174 if (Word == "Config") {
175 sLong ConfigNumber = -1;
176 truth isString = false;
177 festring fname;
178 fname = inFile->ReadStringOrNumberKeepStr(&ConfigNumber, &isString);
179 if (isString) {
180 // include file
181 //fprintf(stderr, "loading: %s\n", fname.CStr());
183 TextInput *incf = new TextInputFile(game::GetGameDir()+"script/"+fname, &game::GetGlobalValueMap());
184 infStack.push(inFile);
185 inFile = incf;
187 ABORT("Config includes aren't supported yet!");
188 } else {
189 //fprintf(stderr, "new config %d (%s) for %s\n", ConfigNumber, inFile->numStr().CStr(), defName.CStr());
190 database *ConfigDataBase = new database(*Proto->ChooseBaseForConfig(TempConfig, Configs, ConfigNumber));
191 festring cfgname = inFile->numStr();
192 festring infname = inFile->GetFileName();
193 ConfigDataBase->InitDefaults(Proto, ConfigNumber, cfgname);
194 TempConfig[Configs++] = ConfigDataBase;
195 if (inFile->ReadWord() != "{") ABORT("'{' missing in %s datafile %s line %d!", protocontainer<type>::GetMainClassID(), inFile->GetFileName().CStr(), inFile->TokenLine());
196 for (inFile->ReadWord(Word); Word != "}"; inFile->ReadWord(Word)) {
197 if (Word == "on") {
198 Proto->mOnEvents.collectSource(infStack, &inFile);
199 continue;
201 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());
203 ConfigDataBase->PostProcess();
205 continue;
207 if (Word == "on") {
208 Proto->mOnEvents.collectSource(infStack, &inFile);
209 continue;
211 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());
213 DataBase->PostProcess();
214 //Configs = Proto->CreateSpecialConfigurations(TempConfig, Configs);
215 Proto->ConfigData = new database *[Configs];
216 Proto->ConfigSize = Configs;
217 memmove(Proto->ConfigData, TempConfig, Configs*sizeof(database *));
219 delete inFile;
222 // remove undefined items
223 protocontainer<type>::Cleanup();
225 for (int c1 = 0; c1 < SPECIAL_CONFIGURATION_GENERATION_LEVELS; ++c1) {
226 for (int c2 = 1; c2 < protocontainer<type>::GetSize(); ++c2) {
227 prototype *Proto = protocontainer<type>::GetProtoData()[c2];
228 if (!Proto) continue; // missing something
229 int Configs = Proto->ConfigSize;
230 memmove(TempConfig, Proto->ConfigData, Configs*sizeof(database *));
231 Configs = Proto->CreateSpecialConfigurations(TempConfig, Configs, c1);
232 if (Proto->ConfigSize != Configs) {
233 delete [] Proto->ConfigData;
234 Proto->ConfigData = new database *[Configs];
235 Proto->ConfigSize = Configs;
236 memmove(Proto->ConfigData, TempConfig, Configs*sizeof(database *));
241 for (int c1 = 1; c1 < protocontainer<type>::GetSize(); ++c1) {
242 prototype *Proto = protocontainer<type>::GetProtoData()[c1];
243 if (!Proto) continue; // missing something
244 TempTables =
245 CreateConfigTable(reinterpret_cast<databasebase ***>(Proto->ConfigTable),
246 TempTable,
247 reinterpret_cast<databasebase **>(Proto->ConfigData),
248 TempTableInfo, c1, Proto->ConfigSize, TempTables);
251 for (int c1 = 1; c1 < TempTables; ++c1) delete [] TempTable[c1];
253 GetDataBaseMemberMap().clear();
257 template <class type> int databasecreator<type>::CreateDivineConfigurations (const prototype *Proto, database **TempConfig, int Configs) {
258 int OldConfigs = Configs;
259 for (int c1 = 1; c1 < protocontainer<god>::GetSize(); ++c1) {
260 database *ConfigDataBase = 0;
261 int c2;
262 festring dcfgname = "divine";
263 for (c2 = 1; c2 < OldConfigs; ++c2) {
264 ConfigDataBase = TempConfig[c2];
265 if (ConfigDataBase->Config == c1) {
266 dcfgname << " ";
267 dcfgname << ConfigDataBase->CfgStrName;
268 break;
271 truth Created = false;
272 if (c2 == OldConfigs) {
273 ConfigDataBase = new database(**TempConfig);
274 ConfigDataBase->InitDefaults(Proto, c1, dcfgname);
275 Created = true;
277 ConfigDataBase->AttachedGod = c1;
278 ConfigDataBase->PostFix << "of " << festring(protocontainer<god>::GetProto(c1)->GetClassID()).CapitalizeCopy();
279 if (Created) TempConfig[Configs++] = ConfigDataBase;
281 return Configs;
285 template int databasecreator<character>::CreateDivineConfigurations (const prototype *, database **, int);
286 template int databasecreator<item>::CreateDivineConfigurations (const prototype *, database **, int);
287 template int databasecreator<olterrain>::CreateDivineConfigurations (const prototype *, database **, int);
290 template <class database, class member> struct databasemember : public databasememberbase<database> {
291 databasemember (member Member) : Member(Member) {}
292 virtual void ReadData (database &DataBase, TextInput &SaveFile) { ::ReadData(DataBase.*Member, SaveFile); }
293 member Member;
297 template <class database, class member> void AddMember(std::map<festring, databasememberbase<database>*>& Map, cchar* Str, member Member)
299 Map.insert(std::pair<festring, databasememberbase<database>*>(Str, new databasemember<database, member>(Member)));
303 /* Explicit instantiations seem to increase compile speed greatly here... */
305 #define INST_ADD_MEMBER(type, member) \
306 template void AddMember<type##database, member type##database::*>(std::map<festring, databasememberbase<type##database>*>&, cchar*, member type##database::*)
308 INST_ADD_MEMBER(character, int);
309 //INST_ADD_MEMBER(character, sLong); //k8:64
310 INST_ADD_MEMBER(character, packcol16);
311 INST_ADD_MEMBER(character, col24);
312 INST_ADD_MEMBER(character, packv2);
313 INST_ADD_MEMBER(character, festring);
314 INST_ADD_MEMBER(character, fearray<sLong>);
315 INST_ADD_MEMBER(character, fearray<festring>);
316 INST_ADD_MEMBER(character, contentscript<item>);
318 INST_ADD_MEMBER(item, int);
319 //INST_ADD_MEMBER(item, sLong); //k8:64
320 INST_ADD_MEMBER(item, col24);
321 INST_ADD_MEMBER(item, v2);
322 INST_ADD_MEMBER(item, festring);
323 INST_ADD_MEMBER(item, fearray<sLong>);
324 INST_ADD_MEMBER(item, fearray<festring>);
325 INST_ADD_MEMBER(item, RandomChance);
327 INST_ADD_MEMBER(glterrain, int);
328 //INST_ADD_MEMBER(glterrain, sLong); //k8:64
329 INST_ADD_MEMBER(glterrain, v2);
330 INST_ADD_MEMBER(glterrain, festring);
331 INST_ADD_MEMBER(glterrain, fearray<sLong>);
333 INST_ADD_MEMBER(olterrain, int);
334 //INST_ADD_MEMBER(olterrain, sLong); //k8:64
335 INST_ADD_MEMBER(olterrain, v2);
336 INST_ADD_MEMBER(olterrain, festring);
337 INST_ADD_MEMBER(olterrain, fearray<sLong>);
338 INST_ADD_MEMBER(olterrain, fearray<contentscript<item> >);
340 INST_ADD_MEMBER(owterrain, int);
341 //INST_ADD_MEMBER(owterrain, sLong); //k8:64
342 INST_ADD_MEMBER(owterrain, v2);
343 INST_ADD_MEMBER(owterrain, festring);
345 INST_ADD_MEMBER(gwterrain, int);
346 //INST_ADD_MEMBER(gwterrain, sLong); //k8:64
347 INST_ADD_MEMBER(gwterrain, v2);
348 INST_ADD_MEMBER(gwterrain, festring);
349 INST_ADD_MEMBER(gwterrain, float);
351 INST_ADD_MEMBER(material, int);
352 //INST_ADD_MEMBER(material, sLong); //k8:64
353 INST_ADD_MEMBER(material, col24);
354 INST_ADD_MEMBER(material, festring);
355 INST_ADD_MEMBER(material, contentscript<item>);
357 #define ADD_MEMBER(data) AddMember(Map, #data, &database::data);
359 template<> void databasecreator<character>::CreateDataBaseMemberMap () {
360 databasemembermap &Map = GetDataBaseMemberMap();
361 ADD_MEMBER(DefaultArmStrength);
362 ADD_MEMBER(DefaultLegStrength);
363 ADD_MEMBER(DefaultDexterity);
364 ADD_MEMBER(DefaultAgility);
365 ADD_MEMBER(DefaultEndurance);
366 ADD_MEMBER(DefaultPerception);
367 ADD_MEMBER(DefaultIntelligence);
368 ADD_MEMBER(DefaultWisdom);
369 ADD_MEMBER(DefaultWillPower);
370 ADD_MEMBER(DefaultCharisma);
371 ADD_MEMBER(DefaultMana);
372 ADD_MEMBER(DefaultMoney);
373 ADD_MEMBER(TotalSize);
374 ADD_MEMBER(CanRead);
375 ADD_MEMBER(Sex);
376 ADD_MEMBER(CanBeGenerated);
377 ADD_MEMBER(CriticalModifier);
378 ADD_MEMBER(StandVerb);
379 ADD_MEMBER(CanOpen);
380 ADD_MEMBER(Frequency);
381 ADD_MEMBER(EnergyResistance);
382 ADD_MEMBER(FireResistance);
383 ADD_MEMBER(PoisonResistance);
384 ADD_MEMBER(ElectricityResistance);
385 ADD_MEMBER(AcidResistance);
386 ADD_MEMBER(SoundResistance);
387 ADD_MEMBER(IsUnique);
388 ADD_MEMBER(ConsumeFlags);
389 ADD_MEMBER(TotalVolume);
390 ADD_MEMBER(HeadBitmapPos);
391 ADD_MEMBER(TorsoBitmapPos);
392 ADD_MEMBER(ArmBitmapPos);
393 ADD_MEMBER(LegBitmapPos);
394 ADD_MEMBER(RightArmBitmapPos);
395 ADD_MEMBER(LeftArmBitmapPos);
396 ADD_MEMBER(RightLegBitmapPos);
397 ADD_MEMBER(LeftLegBitmapPos);
398 ADD_MEMBER(GroinBitmapPos);
399 ADD_MEMBER(ClothColor);
400 ADD_MEMBER(SkinColor);
401 ADD_MEMBER(CapColor);
402 ADD_MEMBER(HairColor);
403 ADD_MEMBER(EyeColor);
404 ADD_MEMBER(TorsoMainColor);
405 ADD_MEMBER(BeltColor);
406 ADD_MEMBER(BootColor);
407 ADD_MEMBER(TorsoSpecialColor);
408 ADD_MEMBER(ArmMainColor);
409 ADD_MEMBER(GauntletColor);
410 ADD_MEMBER(ArmSpecialColor);
411 ADD_MEMBER(LegMainColor);
412 ADD_MEMBER(LegSpecialColor);
413 ADD_MEMBER(IsNameable);
414 ADD_MEMBER(BaseEmitation);
415 ADD_MEMBER(UsesLongArticle);
416 ADD_MEMBER(Adjective);
417 ADD_MEMBER(UsesLongAdjectiveArticle);
418 ADD_MEMBER(NameSingular);
419 ADD_MEMBER(NamePlural);
420 ADD_MEMBER(PostFix);
421 ADD_MEMBER(ArticleMode);
422 ADD_MEMBER(IsAbstract);
423 ADD_MEMBER(IsPolymorphable);
424 ADD_MEMBER(BaseUnarmedStrength);
425 ADD_MEMBER(BaseBiteStrength);
426 ADD_MEMBER(BaseKickStrength);
427 ADD_MEMBER(AttackStyle);
428 ADD_MEMBER(CanUseEquipment);
429 ADD_MEMBER(CanKick);
430 ADD_MEMBER(CanTalk);
431 ADD_MEMBER(ClassStates);
432 ADD_MEMBER(CanBeWished);
433 ADD_MEMBER(Alias);
434 ADD_MEMBER(CreateDivineConfigurations);
435 ADD_MEMBER(CreateGolemMaterialConfigurations);
436 ADD_MEMBER(Helmet);
437 ADD_MEMBER(Amulet);
438 ADD_MEMBER(Cloak);
439 ADD_MEMBER(BodyArmor);
440 ADD_MEMBER(Belt);
441 ADD_MEMBER(RightWielded);
442 ADD_MEMBER(LeftWielded);
443 ADD_MEMBER(RightRing);
444 ADD_MEMBER(LeftRing);
445 ADD_MEMBER(RightGauntlet);
446 ADD_MEMBER(LeftGauntlet);
447 ADD_MEMBER(RightBoot);
448 ADD_MEMBER(LeftBoot);
449 ADD_MEMBER(AttributeBonus);
450 ADD_MEMBER(KnownCWeaponSkills);
451 ADD_MEMBER(CWeaponSkillHits);
452 ADD_MEMBER(RightSWeaponSkillHits);
453 ADD_MEMBER(LeftSWeaponSkillHits);
454 ADD_MEMBER(PanicLevel);
455 ADD_MEMBER(CanBeCloned);
456 ADD_MEMBER(Inventory);
457 ADD_MEMBER(DangerModifier);
458 ADD_MEMBER(DefaultName);
459 ADD_MEMBER(FriendlyReplies);
460 ADD_MEMBER(HostileReplies);
461 ADD_MEMBER(CanZap);
462 ADD_MEMBER(FleshMaterial);
463 ADD_MEMBER(HasALeg);
464 ADD_MEMBER(DeathMessage);
465 ADD_MEMBER(IgnoreDanger);
466 ADD_MEMBER(HPRequirementForGeneration);
467 ADD_MEMBER(DayRequirementForGeneration);
468 ADD_MEMBER(IsExtraCoward);
469 ADD_MEMBER(SpillsBlood);
470 ADD_MEMBER(HasEyes);
471 ADD_MEMBER(HasHead);
472 ADD_MEMBER(CanThrow);
473 ADD_MEMBER(UsesNutrition);
474 ADD_MEMBER(AttackWisdomLimit);
475 ADD_MEMBER(AttachedGod);
476 ADD_MEMBER(BodyPartsDisappearWhenSevered);
477 ADD_MEMBER(CanBeConfused);
478 ADD_MEMBER(CanApply);
479 ADD_MEMBER(WieldedPosition);
480 ADD_MEMBER(NaturalSparkleFlags);
481 ADD_MEMBER(BiteCapturesBodyPart);
482 ADD_MEMBER(IsPlant);
483 ADD_MEMBER(MoveType);
484 ADD_MEMBER(DestroysWalls);
485 ADD_MEMBER(IsRooted);
486 ADD_MEMBER(BloodMaterial);
487 ADD_MEMBER(VomitMaterial);
488 ADD_MEMBER(HasSecondaryMaterial);
489 ADD_MEMBER(IsImmuneToLeprosy);
490 ADD_MEMBER(PolymorphIntelligenceRequirement);
491 ADD_MEMBER(AutomaticallySeen);
492 ADD_MEMBER(CanHear);
493 ADD_MEMBER(DefaultCommandFlags);
494 ADD_MEMBER(ConstantCommandFlags);
495 ADD_MEMBER(WillCarryItems);
496 ADD_MEMBER(ForceVomitMessage);
497 ADD_MEMBER(SweatMaterial);
498 ADD_MEMBER(Sweats);
499 ADD_MEMBER(IsImmuneToItemTeleport);
500 ADD_MEMBER(AlwaysUseMaterialAttributes);
501 ADD_MEMBER(IsEnormous);
502 ADD_MEMBER(ScienceTalkAdjectiveAttribute);
503 ADD_MEMBER(ScienceTalkSubstantiveAttribute);
504 ADD_MEMBER(ScienceTalkPrefix);
505 ADD_MEMBER(ScienceTalkName);
506 ADD_MEMBER(ScienceTalkPossibility);
507 ADD_MEMBER(ScienceTalkIntelligenceModifier);
508 ADD_MEMBER(ScienceTalkWisdomModifier);
509 ADD_MEMBER(ScienceTalkCharismaModifier);
510 ADD_MEMBER(ScienceTalkIntelligenceRequirement);
511 ADD_MEMBER(ScienceTalkWisdomRequirement);
512 ADD_MEMBER(ScienceTalkCharismaRequirement);
513 ADD_MEMBER(IsExtraFragile);
514 ADD_MEMBER(AllowUnconsciousness);
515 ADD_MEMBER(CanChoke);
516 ADD_MEMBER(IsImmuneToStickiness);
517 ADD_MEMBER(DisplacePriority);
518 ADD_MEMBER(RunDescriptionLineOne);
519 ADD_MEMBER(RunDescriptionLineTwo);
520 ADD_MEMBER(ForceCustomStandVerb);
521 ADD_MEMBER(VomittingIsUnhealthy);
522 ADD_MEMBER(AllowPlayerToChangeEquipment);
523 ADD_MEMBER(TamingDifficulty);
524 ADD_MEMBER(IsMasochist);
525 ADD_MEMBER(IsSadist);
526 ADD_MEMBER(IsCatacombCreature);
527 ADD_MEMBER(CreateUndeadConfigurations);
528 ADD_MEMBER(UndeadVersions);
529 ADD_MEMBER(UndeadAttributeModifier);
530 ADD_MEMBER(UndeadVolumeModifier);
531 ADD_MEMBER(UndeadCopyMaterials);
532 ADD_MEMBER(CanBeGeneratedOnlyInTheCatacombs);
533 ADD_MEMBER(IsAlcoholic);
534 ADD_MEMBER(IsImmuneToWhipOfThievery);
535 ADD_MEMBER(IsRangedAttacker);
536 ADD_MEMBER(WhatCategoryToThrow);
537 ADD_MEMBER(WhatWeaponConfigToThrow);
538 ADD_MEMBER(WhatThrowItemTypesToThrow);
539 ADD_MEMBER(AllowedDungeons);
540 ADD_MEMBER(LevelTags);
541 ADD_MEMBER(HomeLevel);
542 ADD_MEMBER(NaturalTeam);
546 template<> void databasecreator<item>::CreateDataBaseMemberMap () {
547 databasemembermap &Map = GetDataBaseMemberMap();
548 ADD_MEMBER(Possibility);
549 ADD_MEMBER(IsDestroyable);
550 ADD_MEMBER(CanBeWished);
551 ADD_MEMBER(IsMaterialChangeable);
552 ADD_MEMBER(WeaponCategory);
553 ADD_MEMBER(IsPolymorphSpawnable);
554 ADD_MEMBER(IsAutoInitializable);
555 ADD_MEMBER(Category);
556 ADD_MEMBER(EnergyResistance);
557 ADD_MEMBER(FireResistance);
558 ADD_MEMBER(PoisonResistance);
559 ADD_MEMBER(ElectricityResistance);
560 ADD_MEMBER(AcidResistance);
561 ADD_MEMBER(SoundResistance);
562 ADD_MEMBER(StrengthModifier);
563 ADD_MEMBER(FormModifier);
564 ADD_MEMBER(DefaultSize);
565 ADD_MEMBER(DefaultMainVolume);
566 ADD_MEMBER(DefaultSecondaryVolume);
567 ADD_MEMBER(BitmapPos);
568 ADD_MEMBER(Price);
569 ADD_MEMBER(BaseEmitation);
570 ADD_MEMBER(UsesLongArticle);
571 ADD_MEMBER(Adjective);
572 ADD_MEMBER(UsesLongAdjectiveArticle);
573 ADD_MEMBER(NameSingular);
574 ADD_MEMBER(NamePlural);
575 ADD_MEMBER(PostFix);
576 ADD_MEMBER(ArticleMode);
577 ADD_MEMBER(MainMaterialConfig);
578 ADD_MEMBER(SecondaryMaterialConfig);
579 ADD_MEMBER(MaterialConfigChances);
580 ADD_MEMBER(IsAbstract);
581 ADD_MEMBER(IsPolymorphable);
582 ADD_MEMBER(Alias);
583 ADD_MEMBER(OKVisualEffects);
584 ADD_MEMBER(CanBeGeneratedInContainer);
585 ADD_MEMBER(ForcedVisualEffects);
586 ADD_MEMBER(Roundness);
587 ADD_MEMBER(GearStates);
588 ADD_MEMBER(IsTwoHanded);
589 ADD_MEMBER(CreateDivineConfigurations);
590 ADD_MEMBER(CanBeCloned);
591 ADD_MEMBER(CanBeMirrored);
592 ADD_MEMBER(BeamRange);
593 ADD_MEMBER(CanBeBroken);
594 ADD_MEMBER(WallBitmapPos);
595 ADD_MEMBER(FlexibleNameSingular);
596 ADD_MEMBER(MaxCharges);
597 ADD_MEMBER(MinCharges);
598 ADD_MEMBER(CanBePiled);
599 ADD_MEMBER(StorageVolume);
600 ADD_MEMBER(MaxGeneratedContainedItems);
601 ADD_MEMBER(AffectsArmStrength);
602 ADD_MEMBER(AffectsLegStrength);
603 ADD_MEMBER(AffectsDexterity);
604 ADD_MEMBER(AffectsAgility);
605 ADD_MEMBER(AffectsEndurance);
606 ADD_MEMBER(AffectsPerception);
607 ADD_MEMBER(AffectsIntelligence);
608 ADD_MEMBER(AffectsWisdom);
609 ADD_MEMBER(AffectsWillPower);
610 ADD_MEMBER(AffectsCharisma);
611 ADD_MEMBER(AffectsMana);
612 ADD_MEMBER(BaseEnchantment);
613 ADD_MEMBER(PriceIsProportionalToEnchantment);
614 ADD_MEMBER(InElasticityPenaltyModifier);
615 ADD_MEMBER(CanBeUsedBySmith);
616 ADD_MEMBER(AffectsCarryingCapacity);
617 ADD_MEMBER(DamageDivider);
618 ADD_MEMBER(HandleInPairs);
619 ADD_MEMBER(CanBeEnchanted);
620 ADD_MEMBER(BeamColor);
621 ADD_MEMBER(BeamEffect);
622 ADD_MEMBER(BeamStyle);
623 ADD_MEMBER(WearWisdomLimit);
624 ADD_MEMBER(AttachedGod);
625 ADD_MEMBER(BreakEffectRangeSquare);
626 ADD_MEMBER(WieldedBitmapPos);
627 ADD_MEMBER(IsQuestItem);
628 ADD_MEMBER(IsGoodWithPlants);
629 ADD_MEMBER(CreateLockConfigurations);
630 ADD_MEMBER(CanBePickedUp);
631 ADD_MEMBER(CoverPercentile);
632 ADD_MEMBER(TorsoArmorBitmapPos);
633 ADD_MEMBER(ArmArmorBitmapPos);
634 ADD_MEMBER(AthleteArmArmorBitmapPos);
635 ADD_MEMBER(LegArmorBitmapPos);
636 ADD_MEMBER(HelmetBitmapPos);
637 ADD_MEMBER(CloakBitmapPos);
638 ADD_MEMBER(BeltBitmapPos);
639 ADD_MEMBER(GauntletBitmapPos);
640 ADD_MEMBER(BootBitmapPos);
641 ADD_MEMBER(HasSecondaryMaterial);
642 ADD_MEMBER(AllowEquip);
643 ADD_MEMBER(ReadDifficulty);
644 ADD_MEMBER(IsValuable);
645 ADD_MEMBER(EnchantmentMinusChance);
646 ADD_MEMBER(EnchantmentPlusChance);
647 ADD_MEMBER(TeleportPriority);
648 ADD_MEMBER(HasNormalPictureDirection);
649 ADD_MEMBER(DamageFlags);
650 ADD_MEMBER(IsKamikazeWeapon);
651 ADD_MEMBER(FlexibilityIsEssential);
652 ADD_MEMBER(BreakMsg);
653 ADD_MEMBER(IsSadistWeapon);
654 ADD_MEMBER(IsThrowingWeapon);
655 ADD_MEMBER(ThrowItemTypes);
656 ADD_MEMBER(CanFlame);
657 ADD_MEMBER(MagicEffectDuration);
658 ADD_MEMBER(MagicEffectChance);
659 ADD_MEMBER(AllowedDungeons);
660 ADD_MEMBER(LevelTags);
664 template <class type> void databasecreator<type>::CreateLTerrainDataBaseMemberMap () {
665 databasemembermap &Map = GetDataBaseMemberMap();
666 ADD_MEMBER(BitmapPos);
667 ADD_MEMBER(UsesLongArticle);
668 ADD_MEMBER(Adjective);
669 ADD_MEMBER(UsesLongAdjectiveArticle);
670 ADD_MEMBER(NameSingular);
671 ADD_MEMBER(NamePlural);
672 ADD_MEMBER(PostFix);
673 ADD_MEMBER(ArticleMode);
674 ADD_MEMBER(MainMaterialConfig);
675 ADD_MEMBER(SecondaryMaterialConfig);
676 ADD_MEMBER(MaterialConfigChances);
677 ADD_MEMBER(IsAbstract);
678 ADD_MEMBER(OKVisualEffects);
679 ADD_MEMBER(MaterialColorB);
680 ADD_MEMBER(MaterialColorC);
681 ADD_MEMBER(MaterialColorD);
682 ADD_MEMBER(SitMessage);
683 ADD_MEMBER(ShowMaterial);
684 ADD_MEMBER(AttachedGod);
685 ADD_MEMBER(Walkability);
686 ADD_MEMBER(HasSecondaryMaterial);
687 ADD_MEMBER(UseBorderTiles);
688 ADD_MEMBER(BorderTilePriority);
692 template<> void databasecreator<glterrain>::CreateDataBaseMemberMap () {
693 CreateLTerrainDataBaseMemberMap();
697 template<> void databasecreator<olterrain>::CreateDataBaseMemberMap () {
698 CreateLTerrainDataBaseMemberMap();
699 databasemembermap &Map = GetDataBaseMemberMap();
700 ADD_MEMBER(CreateDivineConfigurations);
701 ADD_MEMBER(DigMessage);
702 ADD_MEMBER(CanBeDestroyed);
703 ADD_MEMBER(RestModifier);
704 ADD_MEMBER(RestMessage);
705 ADD_MEMBER(IsUpLink);
706 ADD_MEMBER(StorageVolume);
707 ADD_MEMBER(HPModifier);
708 ADD_MEMBER(IsSafeToCreateDoor);
709 ADD_MEMBER(OpenBitmapPos);
710 ADD_MEMBER(CreateLockConfigurations);
711 ADD_MEMBER(IsAlwaysTransparent);
712 ADD_MEMBER(CreateWindowConfigurations);
713 ADD_MEMBER(WindowBitmapPos);
714 ADD_MEMBER(ShowThingsUnder);
715 ADD_MEMBER(LeftOverItems);
716 ADD_MEMBER(IsWall);
720 template<> void databasecreator<gwterrain>::CreateDataBaseMemberMap () {
721 databasemembermap &Map = GetDataBaseMemberMap();
722 ADD_MEMBER(BitmapPos);
723 ADD_MEMBER(IsAbstract);
724 ADD_MEMBER(NameStem);
725 ADD_MEMBER(UsesLongArticle);
726 ADD_MEMBER(Priority);
727 ADD_MEMBER(AnimationFrames);
728 ADD_MEMBER(IsFatalToStay);
729 ADD_MEMBER(SurviveMessage);
730 ADD_MEMBER(MonsterSurviveMessage);
731 ADD_MEMBER(DeathMessage);
732 ADD_MEMBER(MonsterDeathVerb);
733 ADD_MEMBER(ScoreEntry);
734 ADD_MEMBER(Walkability);
735 //HACK: worldmap generation constants
736 ADD_MEMBER(MaxTemperature);
737 ADD_MEMBER(LatitudeEffect);
738 ADD_MEMBER(AltitudeEffect);
739 ADD_MEMBER(TemperatureCold);
740 ADD_MEMBER(TemperatureMedium);
741 ADD_MEMBER(TemperatureWarm);
742 ADD_MEMBER(TemperatureHot);
746 template<> void databasecreator<owterrain>::CreateDataBaseMemberMap () {
747 databasemembermap &Map = GetDataBaseMemberMap();
748 ADD_MEMBER(BitmapPos);
749 ADD_MEMBER(IsAbstract);
750 ADD_MEMBER(NameSingular);
751 ADD_MEMBER(NameStem);
752 ADD_MEMBER(UsesLongArticle);
753 ADD_MEMBER(AttachedDungeon);
754 ADD_MEMBER(AttachedArea);
755 ADD_MEMBER(CanBeGenerated);
756 ADD_MEMBER(NativeGTerrainType);
757 ADD_MEMBER(RevealEnvironmentInitially);
758 ADD_MEMBER(CanBeOnAnyTerrain);
759 ADD_MEMBER(WantContinentWith);
760 ADD_MEMBER(Probability);
761 ADD_MEMBER(CanBeSkipped);
762 ADD_MEMBER(PlaceInitially);
766 template<> void databasecreator<material>::CreateDataBaseMemberMap () {
767 databasemembermap &Map = GetDataBaseMemberMap();
768 ADD_MEMBER(CommonFlags);
769 ADD_MEMBER(NameFlags);
770 ADD_MEMBER(CategoryFlags);
771 ADD_MEMBER(BodyFlags);
772 ADD_MEMBER(InteractionFlags);
773 ADD_MEMBER(StrengthValue);
774 ADD_MEMBER(ConsumeType);
775 ADD_MEMBER(Density);
776 ADD_MEMBER(Color);
777 ADD_MEMBER(RainColor);
778 ADD_MEMBER(PriceModifier);
779 ADD_MEMBER(Emitation);
780 ADD_MEMBER(NutritionValue);
781 ADD_MEMBER(NameStem);
782 ADD_MEMBER(AdjectiveStem);
783 ADD_MEMBER(Effect);
784 ADD_MEMBER(ConsumeEndMessage);
785 ADD_MEMBER(HitMessage);
786 ADD_MEMBER(ExplosivePower);
787 ADD_MEMBER(Alpha);
788 ADD_MEMBER(Flexibility);
789 ADD_MEMBER(SpoilModifier);
790 ADD_MEMBER(EffectStrength);
791 ADD_MEMBER(DigProductMaterial);
792 ADD_MEMBER(ConsumeWisdomLimit);
793 ADD_MEMBER(AttachedGod);
794 ADD_MEMBER(BreatheMessage);
795 ADD_MEMBER(StepInWisdomLimit);
796 ADD_MEMBER(RustModifier);
797 ADD_MEMBER(Acidicity);
798 ADD_MEMBER(NaturalForm);
799 ADD_MEMBER(HardenedMaterial);
800 ADD_MEMBER(SoftenedMaterial);
801 ADD_MEMBER(IntelligenceRequirement);
802 ADD_MEMBER(Stickiness);
803 ADD_MEMBER(DisablesPanicWhenConsumed);
804 ADD_MEMBER(BlockESP);
808 #define ADD_BASE_VALUE(name)\
809 if (Word == #name) game::GetGlobalValueMap()[CONST_S("Base")] = DataBase.*static_cast<databasemember<database, feuLong database::*>*>(Data)->Member;
812 template <class type> void databasecreator<type>::SetBaseValue(cfestring &, databasememberbase<database> *, database &) {}
814 template<> void databasecreator<material>::SetBaseValue(cfestring &Word, databasememberbase<materialdatabase> *Data,
815 materialdatabase &DataBase)
817 ADD_BASE_VALUE(CommonFlags);
818 ADD_BASE_VALUE(NameFlags);
819 ADD_BASE_VALUE(CategoryFlags);
820 ADD_BASE_VALUE(BodyFlags);
821 ADD_BASE_VALUE(InteractionFlags);
825 template <class type> truth databasecreator<type>::AnalyzeData (TextInput &SaveFile, cfestring &Word, database &DataBase) {
826 typename databasemembermap::iterator i = GetDataBaseMemberMap().find(Word);
827 if (i != GetDataBaseMemberMap().end()) {
828 SetBaseValue(Word, i->second, DataBase);
829 i->second->ReadData(DataBase, SaveFile);
830 CheckDefaults(Word, DataBase);
831 return true;
833 return false;
837 template <> void databasecreator<character>::CheckDefaults (cfestring &Word, character::database &DataBase) {
838 if (Word == "ArmBitmapPos") { DataBase.RightArmBitmapPos = DataBase.LeftArmBitmapPos = DataBase.ArmBitmapPos; return; }
839 if (Word == "LegBitmapPos") { DataBase.GroinBitmapPos = DataBase.RightLegBitmapPos = DataBase.LeftLegBitmapPos = DataBase.LegBitmapPos; return; }
840 if (Word == "ClothColor") { DataBase.CapColor = DataBase.TorsoMainColor = DataBase.ArmMainColor = DataBase.GauntletColor = DataBase.LegMainColor = DataBase.ClothColor; return; }
841 if (Word == "NameSingular") { DataBase.NamePlural = DataBase.NameSingular+'s'; return; }
842 if (Word == "BaseUnarmedStrength") { DataBase.BaseBiteStrength = DataBase.BaseUnarmedStrength>>1; DataBase.BaseKickStrength = DataBase.BaseUnarmedStrength<<1; return; }
843 if (Word == "RightGauntlet") { DataBase.LeftGauntlet = DataBase.RightGauntlet; return; }
844 if (Word == "RightBoot") { DataBase.LeftBoot = DataBase.RightBoot; return; }
845 if (Word == "IsUnique") { DataBase.CanBeWished = !DataBase.IsUnique; return; }
846 if (Word == "DefaultName") {
847 // k8: don't add duplicate alias
848 for (uInt c = 0; c < DataBase.Alias.Size; ++c) {
849 if (DataBase.Alias[c] == DataBase.DefaultName) return;
851 DataBase.Alias.Add(DataBase.DefaultName);
853 if (DataBase.Alias.Size != 1) {
854 printf("=== %s ===\n", DataBase.NameSingular.CStr());
855 for (uInt c = 0; c < DataBase.Alias.Size; ++c) {
856 printf(" %u: %s\n", c, DataBase.Alias[c].CStr());
860 return;
865 template <> void databasecreator<item>::CheckDefaults (cfestring &Word, item::database &DataBase) {
866 if (Word == "NameSingular") { DataBase.NamePlural = DataBase.NameSingular+'s'; DataBase.FlexibleNameSingular = DataBase.NameSingular; return; }
867 if (Word == "BitmapPos") { DataBase.WallBitmapPos = DataBase.BitmapPos; return; }
868 if (Word == "MaterialConfigChances") { DataBase.MaterialConfigChanceSum = femath::SumArray(DataBase.MaterialConfigChances); return; }
869 if (Word == "CanBeCloned") { DataBase.CanBeMirrored = DataBase.CanBeCloned; return; }
873 template <> void databasecreator<glterrain>::CheckDefaults (cfestring &Word, glterrain::database &DataBase) {
874 if (Word == "NameSingular") { DataBase.NamePlural = DataBase.NameSingular+'s'; return; }
875 if (Word == "MaterialConfigChances") { DataBase.MaterialConfigChanceSum = femath::SumArray(DataBase.MaterialConfigChances); return; }
879 template <> void databasecreator<olterrain>::CheckDefaults (cfestring &Word, olterrain::database &DataBase) {
880 if (Word == "NameSingular") { DataBase.NamePlural = DataBase.NameSingular+'s'; return; }
881 if (Word == "MaterialConfigChances") { DataBase.MaterialConfigChanceSum = femath::SumArray(DataBase.MaterialConfigChances); return; }
885 template <> void databasecreator<material>::CheckDefaults (cfestring &Word, material::database &DataBase) {
886 if (Word == "NameStem") { DataBase.AdjectiveStem = DataBase.NameStem; return; }
887 if (Word == "Color") { DataBase.RainColor = DataBase.Color; return; }
891 template<> void databasecreator<owterrain>::CheckDefaults (cfestring& Word, owterrain::database& DataBase) {
895 template<> void databasecreator<gwterrain>::CheckDefaults (cfestring& Word, gwterrain::database& DataBase) {
900 void databasesystem::Initialize () {
901 /* Must be before character */
902 databasecreator<material>::ReadFrom("material");
903 databasecreator<character>::ReadFrom("char");
904 /* Must be before olterrain */
905 databasecreator<item>::ReadFrom("item");
906 databasecreator<glterrain>::ReadFrom("glterra");
907 databasecreator<olterrain>::ReadFrom("olterra");
908 databasecreator<gwterrain>::ReadFrom("gwterra");
909 /* Must be last */
910 databasecreator<owterrain>::ReadFrom("owterra");
914 template <class type> inline void databasecreator<type>::FindDataBase (const database *&DataBase, const prototype *Proto, int Config) {
915 database **Table = Proto->ConfigTable[(Config >> 8) ^ (Config & 0xFF)];
916 if (Table) {
917 if ((*Table)->Config == Config) {
918 DataBase = *Table;
919 return;
921 for (++Table; *Table; ++Table) {
922 if ((*Table)->Config == Config) {
923 DataBase = *Table;
924 return;
928 DataBase = 0;
932 template void databasecreator<character>::FindDataBase (const database *&, const prototype *, int);
933 template void databasecreator<material>::FindDataBase (const database *&, const prototype *, int);
935 template <class type> void databasecreator<type>::InstallDataBase (type *Instance, int Config) {
936 const prototype *Proto = Instance->FindProtoType();
937 FindDataBase(Instance->DataBase, Proto, Config);
938 if (!Instance->DataBase) {
939 //*((int *)0) = 0;
940 ABORT("Undefined %s configuration #%08x sought!", Proto->GetClassID(), (unsigned int)Config);
944 #define INST_INSTALL_DATABASE(type) template void databasecreator<type>::InstallDataBase(type *, int)
946 INST_INSTALL_DATABASE(material);
947 INST_INSTALL_DATABASE(character);
948 INST_INSTALL_DATABASE(item);
949 INST_INSTALL_DATABASE(glterrain);
950 INST_INSTALL_DATABASE(olterrain);
951 INST_INSTALL_DATABASE(gwterrain);
952 INST_INSTALL_DATABASE(owterrain);