3 * Iter Vehemens ad Necem (IVAN)
4 * Copyright (C) Timo Kiviluoto
5 * Released under the GNU General
8 * See LICENSING which should be included
9 * along with this file for more details
21 script::datamap
posscript::DataMap
;
22 script::datamap
materialscript::DataMap
;
23 script::datamap
basecontentscript::DataMap
;
24 script::datamap contentscript
<character
>::DataMap
;
25 script::datamap contentscript
<item
>::DataMap
;
26 script::datamap contentscript
<glterrain
>::DataMap
;
27 script::datamap contentscript
<olterrain
>::DataMap
;
28 script::datamap
squarescript::DataMap
;
29 script::datamap
roomscript::DataMap
;
30 script::datamap
levelscript::DataMap
;
31 script::datamap
dungeonscript::DataMap
;
32 script::datamap
teamscript::DataMap
;
33 script::datamap
gamescript::DataMap
;
35 template <class type
, class contenttype
> script::datamap contentmap
<type
, contenttype
>::DataMap
;
38 template <class type
> void scriptmember
<type
>::ReadFrom (TextInput
&SaveFile
) {
39 SrcFile
= SaveFile
.GetFileName();
40 SrcLine
= SaveFile
.CurrentLine();
41 if (!Member
) Member
= new type
;
42 ReadData(*Member
, SaveFile
);
46 template <class type
> void scriptmember
<type
>::Replace (scriptmemberbase
&Base
) {
47 scriptmember
<type
> &Data
= static_cast<scriptmember
<type
> &>(Base
);
54 SrcFile
= Base
.SrcFile
;
55 SrcLine
= Base
.SrcLine
;
59 template <class type
> void scriptmember
<type
>::Save (outputfile
&SaveFile
) const {
62 SaveFile
<< SrcFile
<< SrcLine
;
69 template <class type
> void scriptmember
<type
>::Load (inputfile
&SaveFile
) {
72 SaveFile
>> SrcFile
>> SrcLine
;
78 #define INST_SCRIPT_MEMBER(type)\
79 template void scriptmember< type >::ReadFrom(TextInput &);\
80 template void scriptmember< type >::Replace(scriptmemberbase &);\
81 template void scriptmember< type >::Save(outputfile &) const;\
82 template void scriptmember< type >::Load(inputfile &)
84 INST_SCRIPT_MEMBER(uChar
);
85 INST_SCRIPT_MEMBER(short);
86 INST_SCRIPT_MEMBER(int);
87 //INST_SCRIPT_MEMBER(sLong); //k8:64
88 INST_SCRIPT_MEMBER(v2
);
89 INST_SCRIPT_MEMBER(festring
);
90 INST_SCRIPT_MEMBER(fearray
<v2
>);
91 INST_SCRIPT_MEMBER(rect
);
92 INST_SCRIPT_MEMBER(interval
);
93 INST_SCRIPT_MEMBER(region
);
94 INST_SCRIPT_MEMBER(posscript
);
95 INST_SCRIPT_MEMBER(materialscript
);
96 INST_SCRIPT_MEMBER(squarescript
);
97 INST_SCRIPT_MEMBER(roomscript
);
98 INST_SCRIPT_MEMBER(levelscript
);
99 INST_SCRIPT_MEMBER(contentscript
<character
>);
100 INST_SCRIPT_MEMBER(fearray
<contentscript
<item
> >);
101 INST_SCRIPT_MEMBER(contentscript
<glterrain
>);
102 INST_SCRIPT_MEMBER(contentscript
<olterrain
>);
103 INST_SCRIPT_MEMBER(charactercontentmap
);
104 INST_SCRIPT_MEMBER(itemcontentmap
);
105 INST_SCRIPT_MEMBER(glterraincontentmap
);
106 INST_SCRIPT_MEMBER(olterraincontentmap
);
107 INST_SCRIPT_MEMBER(fearray
<packv2
>);
110 template <class type
> void fastscriptmember
<type
>::ReadFrom (TextInput
&SaveFile
) {
111 SrcFile
= SaveFile
.GetFileName();
112 SrcLine
= SaveFile
.CurrentLine();
113 ReadData(*&Member
, SaveFile
); // gcc 3.4.1 sucks
117 template <class type
> void fastscriptmember
<type
>::Replace (scriptmemberbase
&Base
) {
118 fastscriptmember
<type
> &Data
= static_cast<fastscriptmember
<type
> &>(Base
);
120 Member
= Data
.Member
;
121 SrcFile
= Base
.SrcFile
;
122 SrcLine
= Base
.SrcLine
;
126 template <class type
> void fastscriptmember
<type
>::Save(outputfile
&SaveFile
) const {
127 SaveFile
<< SrcFile
<< SrcLine
;
132 template <class type
> void fastscriptmember
<type
>::Load (inputfile
&SaveFile
) {
133 SaveFile
>> SrcFile
>> SrcLine
;
134 SaveFile
>> *&Member
; // gcc 3.4.1 sucks
138 #define INST_FAST_SCRIPT_MEMBER(type)\
139 template void fastscriptmember< type >::ReadFrom(TextInput&);\
140 template void fastscriptmember< type >::Replace(scriptmemberbase&);\
141 template void fastscriptmember< type >::Save(outputfile&) const;\
142 template void fastscriptmember< type >::Load(inputfile&)
144 INST_FAST_SCRIPT_MEMBER(char);
145 INST_FAST_SCRIPT_MEMBER(uChar
);
146 INST_FAST_SCRIPT_MEMBER(int);
147 //INST_FAST_SCRIPT_MEMBER(sLong); //k8:64
148 INST_FAST_SCRIPT_MEMBER(feuLong
);
149 INST_FAST_SCRIPT_MEMBER(packv2
);
152 void script::Save (outputfile
&SaveFile
) const {
153 SaveFile
<< SrcFile
<< SrcLine
;
154 SaveDataMap(GetDataMap(), SaveFile
);
158 void script::Load (inputfile
&SaveFile
) {
159 SaveFile
>> SrcFile
>> SrcLine
;
160 LoadDataMap(GetDataMap(), SaveFile
);
164 truth
script::ReadMember (TextInput
&SaveFile
, cfestring
&Word
) {
165 scriptmemberbase
*Data
= GetData(Word
.CStr());
168 Data
->ReadFrom(SaveFile
);
175 scriptmemberbase
*script::GetDataFromMap (const datamap
&DataMap
, cchar
*Identifier
) {
176 datamap::const_iterator i
= DataMap
.find(Identifier
);
178 return i
!= DataMap
.end() ? &(this->*i
->second
) : 0;
182 void script::SaveDataMap (const datamap
&DataMap
, outputfile
&SaveFile
) const {
183 for (datamap::const_iterator i
= DataMap
.begin(); i
!= DataMap
.end(); ++i
) (this->*i
->second
).Save(SaveFile
);
187 void script::LoadDataMap (const datamap
&DataMap
, inputfile
&SaveFile
) {
188 for (datamap::const_iterator i
= DataMap
.begin(); i
!= DataMap
.end(); ++i
) (this->*i
->second
).Load(SaveFile
);
192 template <class scriptmemberptr
> void InitMember (script::datamap
&DataMap
, cchar
*Identifier
, scriptmemberptr DataMember
) {
193 DataMap
[Identifier
] = reinterpret_cast<scriptmemberbase
script::*>(DataMember
);
197 #define INIT_ENTRY(name) InitMember(DataMap, #name, &scripttype::name##Holder)
198 #define INIT(name, value) name##Holder(value)
201 void posscript::InitDataMap () {
208 void posscript::ReadFrom (TextInput
&SaveFile
) {
209 static festring Word
;
211 SrcFile
= SaveFile
.GetFileName();
212 SrcLine
= SaveFile
.CurrentLine();
213 SaveFile
.ReadWord(Word
);
216 VectorHolder
.ReadFrom(SaveFile
);
217 } else if (Word
== "Random") {
219 FlagsHolder
.ReadFrom(SaveFile
);
220 } else if (Word
== "BoundedRandom") {
222 BordersHolder
.ReadFrom(SaveFile
);
223 FlagsHolder
.ReadFrom(SaveFile
);
228 void posscript::Save (outputfile
&SaveFile
) const {
229 script::Save(SaveFile
);
234 void posscript::Load (inputfile
&SaveFile
) {
235 script::Load(SaveFile
);
240 void materialscript::InitDataMap () {
245 void materialscript::ReadFrom (TextInput
&SaveFile
) {
246 static festring Word
;
248 SrcFile
= SaveFile
.GetFileName();
249 SrcLine
= SaveFile
.CurrentLine();
250 SaveFile
.ReadWord(Word
);
251 if (Word
== "=") SaveFile
.ReadWord(Word
);
255 valuemap::const_iterator i
= game::GetGlobalValueMap().find(Word
);
257 if (i
!= game::GetGlobalValueMap().end()) Config
= i
->second
;
258 else ABORT("Unconfigured material script detected at line %d!", SaveFile
.TokenLine());
260 if (SaveFile
.ReadWord() != "{") return;
261 for (SaveFile
.ReadWord(Word
); Word
!= "}"; SaveFile
.ReadWord(Word
)) {
262 if (!ReadMember(SaveFile
, Word
)) {
263 ABORT("Odd script term %s encountered in material script line %d!", Word
.CStr(), SaveFile
.TokenLine());
269 material
*materialscript::Instantiate () const {
270 return MAKE_MATERIAL(Config
, GetVolume() ? GetVolume()->Randomize() : 0);
274 void materialscript::Save (outputfile
&SaveFile
) const {
275 script::Save(SaveFile
);
276 SaveFile
<< (uShort
)Config
;
280 void materialscript::Load (inputfile
&SaveFile
) {
281 script::Load(SaveFile
);
289 void basecontentscript::InitDataMap () {
290 INIT_ENTRY(MainMaterial
);
291 INIT_ENTRY(SecondaryMaterial
);
292 INIT_ENTRY(Parameters
);
296 basecontentscript::basecontentscript () : script(), ContentType(0), Random(false), Config(0), INIT(Parameters
, NO_PARAMETERS
) {
300 void basecontentscript::ReadFrom (TextInput
&SaveFile
) {
301 static festring Word
;
303 SrcFile
= SaveFile
.GetFileName();
304 SrcLine
= SaveFile
.CurrentLine();
305 SaveFile
.ReadWord(Word
);
307 mCode
= SaveFile
.ReadCode();
308 SaveFile
.ReadWord(Word
);
310 if (Word
== "=" || Word
== ",") SaveFile
.ReadWord(Word
);
311 valuemap::const_iterator i
= game::GetGlobalValueMap().find(Word
);
312 if (i
!= game::GetGlobalValueMap().end()) {
313 if (!GetMainMaterial()) MainMaterialHolder
.Member
= new materialscript
;
314 MainMaterialHolder
.Member
->SetConfig(i
->second
);
315 SaveFile
.ReadWord(Word
);
316 i
= game::GetGlobalValueMap().find(Word
);
317 if (i
!= game::GetGlobalValueMap().end()) {
318 if (!GetSecondaryMaterial()) SecondaryMaterialHolder
.Member
= new materialscript
;
319 SecondaryMaterialHolder
.Member
->SetConfig(i
->second
);
320 SaveFile
.ReadWord(Word
);
323 if (Word
== "NaturalMaterialForm") {
325 ContentType
= NATURAL_MATERIAL_FORM
;
326 SaveFile
.ReadWord(Word
);
327 } else if (Word
== "Random") {
329 SaveFile
.ReadWord(Word
);
332 ContentType
= SearchCodeName(Word
);
333 if (ContentType
|| Word
== "0") SaveFile
.ReadWord(Word
);
334 else ABORT("Odd script term %s encountered in %s content script, file %s line %d!", Word
.CStr(), GetClassID(), SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
337 Config
= SaveFile
.ReadNumber();
338 SaveFile
.ReadWord(Word
);
343 for (SaveFile
.ReadWord(Word
); Word
!= "}"; SaveFile
.ReadWord(Word
)) {
344 if (!ReadMember(SaveFile
, Word
)) ABORT("Odd script term %s encountered in %s content script, file %s line %d!", Word
.CStr(), GetClassID(), SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
348 mCode
= SaveFile
.ReadCode();
349 SaveFile
.ReadWord(Word
);
351 if (Word
!= ";" && Word
!= ",") ABORT("Odd terminator %s encountered in %s content script, file %s line %d!", Word
.CStr(), GetClassID(), SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
356 scriptmemberbase
*basecontentscript::GetData (cchar
*String
) {
357 scriptmemberbase
*Return
= GetDataFromMap(GetDataMap(), String
);
358 return Return
? Return
: GetDataFromMap(DataMap
, String
);
362 void basecontentscript::Save (outputfile
&SaveFile
) const {
363 SaveFile
<< SrcFile
<< SrcLine
;
364 SaveDataMap(GetDataMap(), SaveFile
);
365 SaveDataMap(DataMap
, SaveFile
);
366 SaveFile
<< ContentType
;
367 SaveFile
.Put(!!Random
);
372 void basecontentscript::Load (inputfile
&SaveFile
) {
373 SaveFile
>> SrcFile
>> SrcLine
;
374 LoadDataMap(GetDataMap(), SaveFile
);
375 LoadDataMap(DataMap
, SaveFile
);
376 ContentType
= ReadType(uShort
, SaveFile
);
377 Random
= SaveFile
.Get();
382 template <class type
> type
*contentscripttemplate
<type
>::BasicInstantiate (int SpecialFlags
) const {
384 const typename
type::prototype
*Proto
= protocontainer
<type
>::GetProto(ContentType
);
385 if (!Proto
) ABORT("BasicInstantiate error for type '%s'!", getTypeName
<type
>().c_str());
386 const typename
type::database
*const *ConfigData
= Proto
->GetConfigData();
387 const materialscript
*MainMaterial
= GetMainMaterial();
388 const materialscript
*SecondaryMaterial
= GetSecondaryMaterial();
389 const typename
type::database
*DataBase
= *ConfigData
;
390 truth UseOverriddenMaterials
= false;
392 if (!Config
&& DataBase
->IsAbstract
) {
394 DataBase
= ConfigData
[1+RAND()%(Proto
->GetConfigSize()-1)];
395 if (DataBase
->AllowRandomInstantiation()) {
396 if (!(SpecialFlags
& NO_MATERIALS
) && MainMaterial
&& (!DataBase
->HasSecondaryMaterial
|| SecondaryMaterial
)) {
397 SpecialFlags
|= NO_MATERIALS
;
398 UseOverriddenMaterials
= true;
400 Instance
= Proto
->Spawn(DataBase
->Config
, SpecialFlags
|NO_PIC_UPDATE
);
404 if (!(SpecialFlags
& NO_MATERIALS
) && MainMaterial
&& (!DataBase
->HasSecondaryMaterial
|| SecondaryMaterial
)) {
405 SpecialFlags
|= NO_MATERIALS
;
406 UseOverriddenMaterials
= true;
408 Instance
= Proto
->Spawn(Config
, SpecialFlags
|NO_PIC_UPDATE
);
410 if (GetParameters() != NO_PARAMETERS
) Instance
->SetParameters(GetParameters());
411 if (UseOverriddenMaterials
) {
412 Instance
->InitMaterials(MainMaterial
, SecondaryMaterial
, false);
414 if (MainMaterial
) Instance
->ChangeMainMaterial(MainMaterial
->Instantiate(), SpecialFlags
|NO_PIC_UPDATE
);
415 if (SecondaryMaterial
) Instance
->ChangeSecondaryMaterial(SecondaryMaterial
->Instantiate(), SpecialFlags
|NO_PIC_UPDATE
);
417 if (!(SpecialFlags
& NO_PIC_UPDATE
)) Instance
->UpdatePictures();
422 /* Called by an inline function in script.h... */
424 template glterrain
*contentscripttemplate
<glterrain
>::BasicInstantiate (int) const;
426 template <class type
> int contentscripttemplate
<type
>::SearchCodeName (cfestring
&String
) const {
427 return protocontainer
<type
>::SearchCodeName(String
);
430 /* GCC 2.952 SUCKS!!! IT MUST BURN!!! */
432 template int contentscripttemplate
<character
>::SearchCodeName(cfestring
&) const;
433 template int contentscripttemplate
<item
>::SearchCodeName(cfestring
&) const;
434 template int contentscripttemplate
<glterrain
>::SearchCodeName(cfestring
&) const;
435 template int contentscripttemplate
<olterrain
>::SearchCodeName(cfestring
&) const;
437 cchar
*contentscript
<character
>::GetClassID () const { return "character"; }
438 cchar
*contentscript
<item
>::GetClassID () const { return "item"; }
439 cchar
*contentscript
<glterrain
>::GetClassID () const { return "glterrain"; }
440 cchar
*contentscript
<olterrain
>::GetClassID () const { return "olterrain"; }
443 void contentscript
<character
>::InitDataMap () {
444 INIT_ENTRY(Inventory
);
445 INIT_ENTRY(WayPoint
);
451 contentscript
<character
>::contentscript () : INIT(Team
, DEFAULT_TEAM
), INIT(Flags
, 0) {
455 character
*contentscript
<character
>::Instantiate (int SpecialFlags
) const {
456 character
*Instance
= contentscripttemplate
<character
>::BasicInstantiate(SpecialFlags
);
457 //fprintf(stderr, "instantiating character '%s'\n", Instance->GetNameSingular().CStr());
458 if (!mCode
.IsEmpty()) {
459 game::ClearEventData();
460 if (!game::RunAllowScriptStr(mCode
)) {
461 //fprintf(stderr, "dropping character '%s'\n", Instance->GetNameSingular().CStr());
466 if (GetTeam() != DEFAULT_TEAM
) Instance
->SetTeam(game::GetTeam(GetTeam()));
467 const fearray
<contentscript
<item
> > *Inventory
= GetInventory();
468 if (Inventory
) Instance
->AddToInventory(*Inventory
, SpecialFlags
);
469 const fearray
<packv2
> *WayPoint
= GetWayPoint();
470 if (WayPoint
) Instance
->SetWayPoints(*WayPoint
);
471 Instance
->RestoreHP();
472 Instance
->RestoreStamina();
477 contentscript
<item
>::contentscript () :
478 INIT(Category
, ANY_CATEGORY
),
480 INIT(MaxPrice
, MAX_PRICE
),
481 INIT(Team
, DEFAULT_TEAM
),
482 INIT(SquarePosition
, CENTER
),
484 INIT(ConfigFlags
, 0),
485 INIT(SpoilPercentage
, 0),
486 INIT(Enchantment
, 0),
487 INIT(IsActive
, false)
492 void contentscript
<item
>::InitDataMap () {
493 INIT_ENTRY(ItemsInside
);
495 INIT_ENTRY(MinPrice
);
496 INIT_ENTRY(MaxPrice
);
497 INIT_ENTRY(LifeExpectancy
);
499 INIT_ENTRY(Category
);
500 INIT_ENTRY(SquarePosition
);
502 INIT_ENTRY(ConfigFlags
);
503 INIT_ENTRY(SpoilPercentage
);
504 INIT_ENTRY(Enchantment
);
505 INIT_ENTRY(IsActive
);
509 item
*contentscript
<item
>::InstantiateBasedOnMaterial (int MaterialConfig
, int SpecialFlags
) const {
510 if (ContentType
== NATURAL_MATERIAL_FORM
) {
511 const materialscript
*MainMaterial
= GetMainMaterial();
512 sLong Volume
= MainMaterial
&& MainMaterial
->GetVolume() ? MainMaterial
->GetVolume()->Randomize() : 0;
513 return material::CreateNaturalForm(MaterialConfig
, Volume
);
515 return Instantiate(SpecialFlags
);
519 item
*contentscript
<item
>::Instantiate (int SpecialFlags
) const {
520 int Chance
= GetChance();
523 if (!mCode
.IsEmpty()) {
524 game::ClearEventData();
525 if (!game::RunAllowScriptStr(mCode
)) return 0;
528 if (Chance
!= 100 && Chance
<= RAND_N(100)) return 0;
530 Instance
= protosystem::BalancedCreateItem(0, GetMinPrice(), GetMaxPrice(), GetCategory(), SpecialFlags
, GetConfigFlags());
532 Instance
= contentscripttemplate
<item
>::BasicInstantiate(SpecialFlags
);
534 if (GetLifeExpectancy()) Instance
->SetLifeExpectancy(GetLifeExpectancy()->Min
, (GetLifeExpectancy()->Max
- GetLifeExpectancy()->Min
) + 1);
535 if (GetTeam() != DEFAULT_TEAM
) Instance
->SetTeam(GetTeam());
536 if (IsActive()) Instance
->SetIsActive(true);
537 if (GetEnchantment() != 0) Instance
->SetEnchantment(GetEnchantment());
538 const fearray
<contentscript
<item
> > *ItemsInside
= GetItemsInside();
539 if (ItemsInside
) Instance
->SetItemsInside(*ItemsInside
, SpecialFlags
);
540 if (GetSpoilPercentage() != 0) Instance
->SetSpoilPercentage(GetSpoilPercentage());
545 truth
IsValidScript (const fearray
<contentscript
<item
> > *Array
) {
546 for (uInt c
= 0; c
< Array
->Size
; ++c
) if (IsValidScript(&Array
->Data
[c
])) return true;
551 void contentscript
<glterrain
>::InitDataMap () {
552 INIT_ENTRY(IsInside
);
556 contentscript
<olterrain
>::contentscript () :
557 INIT(VisualEffects
, 0),
558 INIT(AttachedArea
, DEFAULT_ATTACHED_AREA
),
559 INIT(AttachedEntry
, DEFAULT_ATTACHED_ENTRY
)
564 void contentscript
<olterrain
>::InitDataMap () {
565 INIT_ENTRY(ItemsInside
);
567 INIT_ENTRY(VisualEffects
);
568 INIT_ENTRY(AttachedArea
);
569 INIT_ENTRY(AttachedEntry
);
573 olterrain
*contentscript
<olterrain
>::Instantiate (int SpecialFlags
) const {
574 if (!ContentType
) return 0;
575 olterrain
*Instance
= contentscripttemplate
<olterrain
>::BasicInstantiate(SpecialFlags
);
576 if (GetVisualEffects()) {
577 Instance
->SetVisualEffects(GetVisualEffects());
578 Instance
->UpdatePictures();
580 if (GetAttachedArea() != DEFAULT_ATTACHED_AREA
) Instance
->SetAttachedArea(GetAttachedArea());
581 if (GetAttachedEntry() != DEFAULT_ATTACHED_ENTRY
) Instance
->SetAttachedEntry(GetAttachedEntry());
582 cfestring
*Text
= GetText();
583 if (Text
) Instance
->SetText(*Text
);
584 const fearray
<contentscript
<item
> > *ItemsInside
= GetItemsInside();
585 if (ItemsInside
) Instance
->SetItemsInside(*ItemsInside
, SpecialFlags
);
590 squarescript::squarescript () : INIT(EntryIndex
, NO_ENTRY
), INIT(AttachRequired
, false) {
594 void squarescript::InitDataMap () {
595 INIT_ENTRY(Position
);
596 INIT_ENTRY(Character
);
598 INIT_ENTRY(GTerrain
);
599 INIT_ENTRY(OTerrain
);
601 INIT_ENTRY(EntryIndex
);
602 INIT_ENTRY(AttachRequired
);
606 void squarescript::ReadFrom (TextInput
&SaveFile
) {
607 static festring Word
;
609 SrcFile
= SaveFile
.GetFileName();
610 SrcLine
= SaveFile
.CurrentLine();
611 SaveFile
.ReadWord(Word
);
613 PositionHolder
.ReadFrom(SaveFile
);
614 if (SaveFile
.ReadWord() != "{") ABORT("Bracket missing in square script line %d!", SaveFile
.TokenLine());
615 for (SaveFile
.ReadWord(Word
); Word
!= "}"; SaveFile
.ReadWord(Word
)) {
616 if (!ReadMember(SaveFile
, Word
)) ABORT("Odd script term %s encountered in square script line %d!", Word
.CStr(), SaveFile
.TokenLine());
619 GTerrainHolder
.ReadFrom(SaveFile
);
620 OTerrainHolder
.ReadFrom(SaveFile
);
625 template <class type
, class contenttype
> contentmap
<type
, contenttype
>::contentmap() : ContentMap(0) {
629 template <class type
, class contenttype
> contentmap
<type
, contenttype
>::~contentmap
<type
, contenttype
> () {
630 delete [] ContentMap
;
634 template <class type
, class contenttype
> void contentmap
<type
, contenttype
>::InitDataMap () {
640 template <class type
, class contenttype
> void contentmap
<type
, contenttype
>::ReadFrom (TextInput
&SaveFile
) {
641 typedef std::map
<int, contenttype
> maptype
;
642 typedef typename
maptype::iterator mapiterator
;
643 festring Word1
, Word2
;
645 SrcFile
= SaveFile
.GetFileName();
646 SrcLine
= SaveFile
.CurrentLine();
647 if (ContentMap
) ABORT("Illegal %s content map redefinition on line %d!", protocontainer
<type
>::GetMainClassID(), SaveFile
.TokenLine());
648 if (SaveFile
.ReadWord() != "{") ABORT("Bracket missing in %s content map script line %d!", protocontainer
<type
>::GetMainClassID(), SaveFile
.TokenLine());
649 SymbolMap
.insert(std::pair
<int, contenttype
>('.', contenttype()));
650 for (SaveFile
.ReadWord(Word1
); Word1
!= "}"; Word1
= SaveFile
.ReadWord()) {
651 if (Word1
== "Types") {
652 if (SaveFile
.ReadWord() != "{") ABORT("Missing bracket in %s content map script line %d!", protocontainer
<type
>::GetMainClassID(), SaveFile
.TokenLine());
653 for (SaveFile
.ReadWord(Word2
); Word2
!= "}"; Word2
= SaveFile
.ReadWord()) {
654 std::pair
<mapiterator
, bool> Return
= SymbolMap
.insert(std::pair
<int, contenttype
>(Word2
[0], contenttype()));
657 ReadData(Return
.first
->second
, SaveFile
);
659 ABORT("Symbol %c defined again in %s content map script line %d!", Word2
[0], protocontainer
<type
>::GetMainClassID(), SaveFile
.TokenLine());
664 if (!ReadMember(SaveFile
, Word1
)) ABORT("Odd script term %s encountered in %s content script line %d!", Word1
.CStr(), protocontainer
<type
>::GetMainClassID(), SaveFile
.TokenLine());
667 v2 Size
= *GetSize();
669 Alloc2D(ContentMap
, Size
.X
, Size
.Y
);
670 if (SaveFile
.ReadWord() != "{") ABORT("Missing bracket in %s content map script line %d!", protocontainer
<type
>::GetMainClassID(), SaveFile
.TokenLine());
671 for (int y
= 0; y
< Size
.Y
; ++y
) {
672 for (int x
= 0; x
< Size
.X
; ++x
) {
673 int Char
= SaveFile
.ReadLetter();
674 typename
std::map
<int, contenttype
>::iterator i
= SymbolMap
.find(Char
);
676 if (i
!= SymbolMap
.end()) {
677 ContentMap
[x
][y
] = std::make_pair(Char
, &i
->second
);
679 ABORT("Illegal content %c in %s content map line %d!", Char
, protocontainer
<type
>::GetMainClassID(), SaveFile
.TokenLine());
683 if (SaveFile
.ReadWord() != "}") ABORT("Missing bracket in %s content map script line %d!", protocontainer
<type
>::GetMainClassID(), SaveFile
.TokenLine());
687 template <class type
, class contenttype
> void contentmap
<type
, contenttype
>::Save (outputfile
&SaveFile
) const {
688 script::Save(SaveFile
);
689 SaveFile
<< SymbolMap
;
691 v2 Size
= *GetSize();
692 for (int y
= 0; y
< Size
.Y
; ++y
)
693 for (int x
= 0; x
< Size
.X
; ++x
)
694 SaveFile
<< char(ContentMap
[x
][y
].first
);
698 template <class type
, class contenttype
> void contentmap
<type
, contenttype
>::Load (inputfile
&SaveFile
) {
699 script::Load(SaveFile
);
700 SaveFile
>> SymbolMap
;
702 v2 Size
= *GetSize();
704 Alloc2D(ContentMap
, Size
.X
, Size
.Y
);
705 for (int y
= 0; y
< Size
.Y
; ++y
) {
706 for (int x
= 0; x
< Size
.X
; ++x
) {
707 int Char
= ReadType(char, SaveFile
);
709 ContentMap
[x
][y
] = std::make_pair(Char
, &SymbolMap
.find(Char
)->second
);
715 const std::list
<squarescript
> &roomscript::GetSquare () const { return Square
; }
718 void roomscript::InitDataMap () {
719 INIT_ENTRY(CharacterMap
);
721 INIT_ENTRY(GTerrainMap
);
722 INIT_ENTRY(OTerrainMap
);
723 INIT_ENTRY(WallSquare
);
724 INIT_ENTRY(FloorSquare
);
725 INIT_ENTRY(DoorSquare
);
728 INIT_ENTRY(AltarPossible
);
729 INIT_ENTRY(GenerateDoor
);
730 INIT_ENTRY(GenerateTunnel
);
731 INIT_ENTRY(DivineMaster
);
732 INIT_ENTRY(GenerateLanterns
);
734 INIT_ENTRY(GenerateFountains
);
735 INIT_ENTRY(AllowLockedDoors
);
736 INIT_ENTRY(AllowBoobyTrappedDoors
);
738 INIT_ENTRY(IsInside
);
739 INIT_ENTRY(GenerateWindows
);
740 INIT_ENTRY(UseFillSquareWalls
);
742 INIT_ENTRY(GenerateWards
);
743 INIT_ENTRY(AllowedDivineMasters
);
747 void roomscript::ReadFrom (TextInput
&SaveFile
) {
750 SrcFile
= SaveFile
.GetFileName();
751 SrcLine
= SaveFile
.CurrentLine();
752 if (SaveFile
.ReadWord() != "{") ABORT("Bracket missing in room script line %d!", SaveFile
.TokenLine());
753 for (SaveFile
.ReadWord(Word
); Word
!= "}"; SaveFile
.ReadWord(Word
)) {
754 if (Word
== "Square") {
755 Square
.push_back(squarescript());
756 Square
.back().ReadFrom(SaveFile
);
759 if (!ReadMember(SaveFile
, Word
)) ABORT("Odd script term %s encountered in room script line %d!", Word
.CStr(), SaveFile
.TokenLine());
764 void roomscript::Save (outputfile
&SaveFile
) const {
765 script::Save(SaveFile
);
770 void roomscript::Load (inputfile
&SaveFile
) {
771 script::Load(SaveFile
);
776 const std::list
<squarescript
> &levelscript::GetSquare () const { return Square
; }
777 const std::list
<roomscript
> &levelscript::GetRoom () const { return Room
; }
780 void levelscript::InitDataMap () {
781 INIT_ENTRY(RoomDefault
);
782 INIT_ENTRY(FillSquare
);
783 INIT_ENTRY(TunnelSquare
);
784 INIT_ENTRY(LevelMessage
);
788 INIT_ENTRY(GenerateMonsters
);
789 INIT_ENTRY(IsOnGround
);
790 INIT_ENTRY(EarthquakesAffectTunnels
);
791 INIT_ENTRY(TeamDefault
);
792 INIT_ENTRY(Description
);
793 INIT_ENTRY(LOSModifier
);
794 INIT_ENTRY(IgnoreDefaultSpecialSquares
);
795 INIT_ENTRY(DifficultyBase
);
796 INIT_ENTRY(DifficultyDelta
);
797 INIT_ENTRY(MonsterAmountBase
);
798 INIT_ENTRY(MonsterAmountDelta
);
799 INIT_ENTRY(MonsterGenerationIntervalBase
);
800 INIT_ENTRY(MonsterGenerationIntervalDelta
);
801 INIT_ENTRY(AutoReveal
);
802 INIT_ENTRY(ShortDescription
);
803 INIT_ENTRY(CanGenerateBone
);
804 INIT_ENTRY(ItemMinPriceBase
);
805 INIT_ENTRY(ItemMinPriceDelta
);
807 INIT_ENTRY(EnchantmentMinusChanceBase
);
808 INIT_ENTRY(EnchantmentMinusChanceDelta
);
809 INIT_ENTRY(EnchantmentPlusChanceBase
);
810 INIT_ENTRY(EnchantmentPlusChanceDelta
);
811 INIT_ENTRY(BackGroundType
);
812 INIT_ENTRY(IsCatacomb
);
813 INIT_ENTRY(EnterImage
);
814 INIT_ENTRY(EnterTextDisplacement
);
819 void levelscript::ReadFrom (TextInput
&SaveFile
) {
822 SrcFile
= SaveFile
.GetFileName();
823 SrcLine
= SaveFile
.CurrentLine();
824 if (SaveFile
.ReadWord() != "{") ABORT("Bracket missing in level script line %d!", SaveFile
.TokenLine());
826 cv2
*Size
= static_cast<const levelscript
*>(Base
)->GetSize();
829 game::GetGlobalValueMap()["XSize"] = Size
->X
;
830 game::GetGlobalValueMap()["YSize"] = Size
->Y
;
833 for (SaveFile
.ReadWord(Word
); Word
!= "}"; SaveFile
.ReadWord(Word
)) {
834 if (Word
== "Square") {
835 Square
.push_back(squarescript());
836 Square
.back().ReadFrom(SaveFile
);
839 if (Word
== "Room") {
840 Room
.push_back(roomscript());
841 const roomscript
*RoomDefault
= GetRoomDefault();
842 if (RoomDefault
) Room
.back().SetBase(RoomDefault
);
843 Room
.back().ReadFrom(SaveFile
);
846 if (!ReadMember(SaveFile
, Word
)) ABORT("Odd script term %s encountered in level script line %d!", Word
.CStr(), SaveFile
.TokenLine());
847 if (Word
== "Size") {
848 game::GetGlobalValueMap()["XSize"] = GetSize()->X
;
849 game::GetGlobalValueMap()["YSize"] = GetSize()->Y
;
853 const levelscript
*LevelBase
= static_cast<const levelscript
*>(Base
);
855 if (LevelBase
&& RoomDefaultHolder
.Member
) RoomDefaultHolder
.Member
->SetBase(LevelBase
->RoomDefaultHolder
.Member
);
856 valuemap::iterator i
= game::GetGlobalValueMap().find("XSize");
857 if (i
!= game::GetGlobalValueMap().end()) game::GetGlobalValueMap().erase(i
);
858 i
= game::GetGlobalValueMap().find("YSize");
859 if (i
!= game::GetGlobalValueMap().end()) game::GetGlobalValueMap().erase(i
);
863 void levelscript::Combine (levelscript
&Script
) {
864 if (!Base
) Base
= Script
.Base
;
865 Square
.splice(Square
.end(), Script
.Square
);
866 Room
.splice(Room
.end(), Script
.Room
);
867 for (std::list
<roomscript
>::iterator i1
= Room
.begin(); i1
!= Room
.end(); ++i1
) i1
->SetBase(GetRoomDefault());
868 for (datamap::const_iterator i2
= DataMap
.begin(); i2
!= DataMap
.end(); ++i2
) (this->*i2
->second
).Replace(Script
.*i2
->second
);
872 void levelscript::SetBase (const scriptwithbase
*What
) {
873 const levelscript
*LevelBase
= static_cast<const levelscript
*>(Base
= What
);
874 roomscript
*BaseRoomDefault
= LevelBase
->RoomDefaultHolder
.Member
;
876 if (BaseRoomDefault
) {
877 roomscript
*ThisRoomDefault
= RoomDefaultHolder
.Member
;
878 if (!ThisRoomDefault
) {
879 for (std::list
<roomscript
>::iterator i
= Room
.begin(); i
!= Room
.end(); ++i
) i
->SetBase(BaseRoomDefault
);
881 ThisRoomDefault
->SetBase(BaseRoomDefault
);
887 void levelscript::Save (outputfile
&SaveFile
) const {
888 script::Save(SaveFile
);
889 //if (Tag) SaveFile << Tag; else SaveFile << "";
890 SaveFile
<< Square
<< Room
;
894 void levelscript::Load (inputfile
&SaveFile
) {
895 script::Load(SaveFile
);
896 SaveFile
>> Square
>> Room
;
898 const roomscript
*RoomDefault
= GetRoomDefault();
899 if (RoomDefault
) for (std::list
<roomscript
>::iterator i
= Room
.begin(); i
!= Room
.end(); ++i
) i
->SetBase(RoomDefault
);
903 dungeonscript::dungeonscript () {
907 dungeonscript::~dungeonscript () {
911 const std::map
<int, levelscript
> &dungeonscript::GetLevel () const { return Level
; }
914 void dungeonscript::InitDataMap () {
915 INIT_ENTRY(LevelDefault
);
917 INIT_ENTRY(Description
);
918 INIT_ENTRY(ShortDescription
);
922 void dungeonscript::ReadFrom (TextInput
&SaveFile
) {
925 SrcFile
= SaveFile
.GetFileName();
926 SrcLine
= SaveFile
.CurrentLine();
927 if (SaveFile
.ReadWord() != "{") ABORT("Bracket missing in dungeon script line %d!", SaveFile
.TokenLine());
928 for (SaveFile
.ReadWord(Word
); Word
!= "}"; SaveFile
.ReadWord(Word
)) {
929 if (Word
== "Level") {
930 int Index
= SaveFile
.ReadNumber();
931 std::pair
<std::map
<int, levelscript
>::iterator
, bool> Return
= Level
.insert(std::make_pair(Index
, levelscript()));
934 levelscript
&LS
= Return
.first
->second
;
935 const levelscript
*LevelDefault
= GetLevelDefault();
937 if (LevelDefault
) LS
.SetBase(LevelDefault
);
938 LS
.ReadFrom(SaveFile
);
940 ABORT("Level #%d defined again in dungeon script line %d!", Index
, SaveFile
.TokenLine());
944 if (Word
== "RandomLevel") {
946 ReadData(Interval
, SaveFile
);
947 RandomLevel
.push_back(std::make_pair(Interval
, levelscript()));
948 const levelscript
*LevelDefault
= GetLevelDefault();
950 if (LevelDefault
) RandomLevel
.back().second
.SetBase(LevelDefault
);
951 RandomLevel
.back().second
.ReadFrom(SaveFile
);
954 if (!ReadMember(SaveFile
, Word
)) ABORT("Odd script term %s encountered in dungeon script line %d!", Word
.CStr(), SaveFile
.TokenLine());
959 void dungeonscript::RandomizeLevels () {
960 for (std::list
<std::pair
<interval
, levelscript
> >::iterator i
= RandomLevel
.begin(); i
!= RandomLevel
.end(); ++i
) {
961 int Index
= i
->first
.Randomize();
962 Level
[Index
].Combine(i
->second
);
968 void dungeonscript::Save (outputfile
&SaveFile
) const {
969 script::Save(SaveFile
);
970 SaveFile
<< Level
<< RandomLevel
;
974 void dungeonscript::Load (inputfile
&SaveFile
) {
975 script::Load(SaveFile
);
976 SaveFile
>> Level
>> RandomLevel
;
977 const levelscript
*LevelDefault
= GetLevelDefault();
979 for (std::map
<int, levelscript
>::iterator i1
= Level
.begin(); i1
!= Level
.end(); ++i1
) i1
->second
.SetBase(LevelDefault
);
980 for (std::list
<std::pair
<interval
, levelscript
> >::iterator i2
= RandomLevel
.begin(); i2
!= RandomLevel
.end(); ++i2
) i2
->second
.SetBase(LevelDefault
);
985 const std::vector
<std::pair
<int, int> > &teamscript::GetRelation () const { return Relation
; }
988 void teamscript::InitDataMap () {
989 INIT_ENTRY(KillEvilness
);
994 void teamscript::ReadFrom (TextInput
&SaveFile
) {
997 SrcFile
= SaveFile
.GetFileName();
998 SrcLine
= SaveFile
.CurrentLine();
999 if (SaveFile
.ReadWord() != "{") ABORT("Bracket missing in team script line %d!", SaveFile
.TokenLine());
1000 for (SaveFile
.ReadWord(Word
); Word
!= "}"; SaveFile
.ReadWord(Word
)) {
1001 if (Word
== "Relation") {
1002 std::pair
<int, int> Rel
;
1004 Rel
.first
= SaveFile
.ReadNumber();
1005 Rel
.second
= SaveFile
.ReadNumber();
1006 Relation
.push_back(Rel
);
1009 if (!ReadMember(SaveFile
, Word
)) ABORT("Odd script term %s encountered in team script line %d!", Word
.CStr(), SaveFile
.TokenLine());
1014 void teamscript::Save (outputfile
&SaveFile
) const {
1015 script::Save(SaveFile
);
1016 SaveFile
<< Relation
;
1020 void teamscript::Load (inputfile
&SaveFile
) {
1021 script::Load(SaveFile
);
1022 SaveFile
>> Relation
;
1026 const std::list
<std::pair
<int, teamscript
> > &gamescript::GetTeam () const { return Team
; }
1027 const std::map
<int, dungeonscript
> &gamescript::GetDungeon () const { return Dungeon
; }
1030 void gamescript::InitDataMap () {
1031 //INIT_ENTRY(Dungeons);
1032 //INIT_ENTRY(Teams);
1036 void gamescript::ReadFrom (TextInput
&SaveFile
) {
1039 SrcFile
= SaveFile
.GetFileName();
1040 SrcLine
= SaveFile
.CurrentLine();
1041 SaveFile
.setGetVarCB(game::ldrGetVar
);
1042 for (SaveFile
.ReadWord(Word
, false); !SaveFile
.Eof(); SaveFile
.ReadWord(Word
, false)) {
1043 if (Word
== "Dungeon") {
1044 int Index
= SaveFile
.ReadNumber();
1046 if (Index
< 0 || Index
> 16383) ABORT("Invalid dungeon number (%d) in game script file %s line %d!", Index
, SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
1047 if (mDungeons
< Index
) mDungeons
= Index
;
1048 //fprintf(stderr, "dungeon: %d; mDungeons: %d\n", Index, mDungeons);
1049 std::pair
<dungeonlist::iterator
, bool> Return
= Dungeon
.insert(std::make_pair(Index
, dungeonscript()));
1051 if (Return
.second
) Return
.first
->second
.ReadFrom(SaveFile
);
1052 else ABORT("Dungeon #%d defined again in game script file %s line %d!", Index
, SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
1055 if (Word
== "Team") {
1056 int Index
= SaveFile
.ReadNumber();
1058 if (Index
< 0 || Index
> 16383) ABORT("Invalid team number (%d) in game script file %s line %d!", Index
, SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
1059 for (teamlist::const_iterator it
= Team
.begin(); it
!= Team
.end(); ++it
) {
1060 if (it
->first
== Index
) ABORT("Team #%d redefinition in file %s at line %d!", Index
, SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
1062 if (mTeams
< Index
+1) mTeams
= Index
+1;
1065 fprintf(stderr, "new team #%d\n", Index);
1066 fprintf(stderr, "defined teams:\n");
1067 for (teamlist::const_iterator it = Team.begin(); it != Team.end(); ++it) fprintf(stderr, " %d\n", it->first);
1071 Team
.push_back(teamlistitem(Index
, teamscript()));
1072 Team
.back().second
.ReadFrom(SaveFile
);
1075 if (Word
== "Include") {
1076 Word
= SaveFile
.ReadWord();
1077 if (SaveFile
.ReadWord() != ";") ABORT("Invalid terminator in file %s at line %d!", SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
1078 //fprintf(stderr, "loading: %s\n", Word.CStr());
1079 TextInputFile
incf(inputfile::buildIncludeName(SaveFile
.GetFileName(), Word
), &game::GetGlobalValueMap());
1083 if (Word
== "Message") {
1084 Word
= SaveFile
.ReadWord();
1085 if (SaveFile
.ReadWord() != ";") ABORT("Invalid terminator in file %s at line %d!", SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
1086 fprintf(stderr
, "MESSAGE: %s\n", Word
.CStr());
1089 if (!ReadMember(SaveFile
, Word
)) ABORT("Odd script term %s encountered in game script file %s line %d!", Word
.CStr(), SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
1094 void gamescript::RandomizeLevels () {
1095 for (std::map
<int, dungeonscript
>::iterator i
= Dungeon
.begin(); i
!= Dungeon
.end(); ++i
) i
->second
.RandomizeLevels();
1099 void gamescript::Save (outputfile
&SaveFile
) const {
1100 script::Save(SaveFile
);
1101 SaveFile
<< Team
<< Dungeon
;
1105 void gamescript::Load (inputfile
&SaveFile
) {
1106 script::Load(SaveFile
);
1107 SaveFile
>> Team
>> Dungeon
;
1111 outputfile
&operator << (outputfile
&SaveFile
, const gamescript
*Script
) {
1112 Script
->Save(SaveFile
);
1117 inputfile
&operator >> (inputfile
&SaveFile
, gamescript
*&Script
) {
1118 Script
= new gamescript
;
1119 Script
->Load(SaveFile
);
1124 void scriptsystem::Initialize () {
1125 posscript::InitDataMap();
1126 materialscript::InitDataMap();
1127 basecontentscript::InitDataMap();
1128 contentscript
<character
>::InitDataMap();
1129 contentscript
<item
>::InitDataMap();
1130 contentscript
<glterrain
>::InitDataMap();
1131 contentscript
<olterrain
>::InitDataMap();
1132 squarescript::InitDataMap();
1133 itemcontentmap::InitDataMap();
1134 charactercontentmap::InitDataMap();
1135 glterraincontentmap::InitDataMap();
1136 olterraincontentmap::InitDataMap();
1137 roomscript::InitDataMap();
1138 levelscript::InitDataMap();
1139 dungeonscript::InitDataMap();
1140 teamscript::InitDataMap();
1141 gamescript::InitDataMap();