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
20 script::datamap
posscript::DataMap
;
21 script::datamap
materialscript::DataMap
;
22 script::datamap
basecontentscript::DataMap
;
23 script::datamap contentscript
<character
>::DataMap
;
24 script::datamap contentscript
<item
>::DataMap
;
25 script::datamap contentscript
<glterrain
>::DataMap
;
26 script::datamap contentscript
<olterrain
>::DataMap
;
27 script::datamap
squarescript::DataMap
;
28 script::datamap
roomscript::DataMap
;
29 script::datamap
levelscript::DataMap
;
30 script::datamap
dungeonscript::DataMap
;
31 script::datamap
teamscript::DataMap
;
32 script::datamap
gamescript::DataMap
;
34 template <class type
, class contenttype
> script::datamap contentmap
<type
, contenttype
>::DataMap
;
37 template <class type
> void scriptmember
<type
>::ReadFrom (inputfile
&SaveFile
) {
38 SrcFile
= SaveFile
.GetFileName();
39 SrcLine
= SaveFile
.CurrentLine();
40 if (!Member
) Member
= new type
;
41 ReadData(*Member
, SaveFile
);
45 template <class type
> void scriptmember
<type
>::Replace (scriptmemberbase
&Base
) {
46 scriptmember
<type
> &Data
= static_cast<scriptmember
<type
> &>(Base
);
53 SrcFile
= Base
.SrcFile
;
54 SrcLine
= Base
.SrcLine
;
58 template <class type
> void scriptmember
<type
>::Save (outputfile
&SaveFile
) const {
61 SaveFile
<< SrcFile
<< SrcLine
;
68 template <class type
> void scriptmember
<type
>::Load (inputfile
&SaveFile
) {
71 SaveFile
>> SrcFile
>> SrcLine
;
77 #define INST_SCRIPT_MEMBER(type)\
78 template void scriptmember< type >::ReadFrom(inputfile &);\
79 template void scriptmember< type >::Replace(scriptmemberbase &);\
80 template void scriptmember< type >::Save(outputfile &) const;\
81 template void scriptmember< type >::Load(inputfile &)
83 INST_SCRIPT_MEMBER(uChar
);
84 INST_SCRIPT_MEMBER(short);
85 INST_SCRIPT_MEMBER(int);
86 //INST_SCRIPT_MEMBER(sLong); //k8:64
87 INST_SCRIPT_MEMBER(v2
);
88 INST_SCRIPT_MEMBER(festring
);
89 INST_SCRIPT_MEMBER(fearray
<v2
>);
90 INST_SCRIPT_MEMBER(rect
);
91 INST_SCRIPT_MEMBER(interval
);
92 INST_SCRIPT_MEMBER(region
);
93 INST_SCRIPT_MEMBER(posscript
);
94 INST_SCRIPT_MEMBER(materialscript
);
95 INST_SCRIPT_MEMBER(squarescript
);
96 INST_SCRIPT_MEMBER(roomscript
);
97 INST_SCRIPT_MEMBER(levelscript
);
98 INST_SCRIPT_MEMBER(contentscript
<character
>);
99 INST_SCRIPT_MEMBER(fearray
<contentscript
<item
> >);
100 INST_SCRIPT_MEMBER(contentscript
<glterrain
>);
101 INST_SCRIPT_MEMBER(contentscript
<olterrain
>);
102 INST_SCRIPT_MEMBER(charactercontentmap
);
103 INST_SCRIPT_MEMBER(itemcontentmap
);
104 INST_SCRIPT_MEMBER(glterraincontentmap
);
105 INST_SCRIPT_MEMBER(olterraincontentmap
);
106 INST_SCRIPT_MEMBER(fearray
<packv2
>);
109 template <class type
> void fastscriptmember
<type
>::ReadFrom (inputfile
&SaveFile
) {
110 SrcFile
= SaveFile
.GetFileName();
111 SrcLine
= SaveFile
.CurrentLine();
112 ReadData(*&Member
, SaveFile
); // gcc 3.4.1 sucks
116 template <class type
> void fastscriptmember
<type
>::Replace (scriptmemberbase
&Base
) {
117 fastscriptmember
<type
> &Data
= static_cast<fastscriptmember
<type
> &>(Base
);
119 Member
= Data
.Member
;
120 SrcFile
= Base
.SrcFile
;
121 SrcLine
= Base
.SrcLine
;
125 template <class type
> void fastscriptmember
<type
>::Save(outputfile
&SaveFile
) const {
126 SaveFile
<< SrcFile
<< SrcLine
;
131 template <class type
> void fastscriptmember
<type
>::Load (inputfile
&SaveFile
) {
132 SaveFile
>> SrcFile
>> SrcLine
;
133 SaveFile
>> *&Member
; // gcc 3.4.1 sucks
137 #define INST_FAST_SCRIPT_MEMBER(type)\
138 template void fastscriptmember< type >::ReadFrom(inputfile&);\
139 template void fastscriptmember< type >::Replace(scriptmemberbase&);\
140 template void fastscriptmember< type >::Save(outputfile&) const;\
141 template void fastscriptmember< type >::Load(inputfile&)
143 INST_FAST_SCRIPT_MEMBER(char);
144 INST_FAST_SCRIPT_MEMBER(uChar
);
145 INST_FAST_SCRIPT_MEMBER(int);
146 //INST_FAST_SCRIPT_MEMBER(sLong); //k8:64
147 INST_FAST_SCRIPT_MEMBER(feuLong
);
148 INST_FAST_SCRIPT_MEMBER(packv2
);
151 void script::Save (outputfile
&SaveFile
) const {
152 SaveFile
<< SrcFile
<< SrcLine
;
153 SaveDataMap(GetDataMap(), SaveFile
);
157 void script::Load (inputfile
&SaveFile
) {
158 SaveFile
>> SrcFile
>> SrcLine
;
159 LoadDataMap(GetDataMap(), SaveFile
);
163 truth
script::ReadMember (inputfile
&SaveFile
, cfestring
&Word
) {
164 scriptmemberbase
*Data
= GetData(Word
.CStr());
167 Data
->ReadFrom(SaveFile
);
174 scriptmemberbase
*script::GetDataFromMap (const datamap
&DataMap
, cchar
*Identifier
) {
175 datamap::const_iterator i
= DataMap
.find(Identifier
);
177 return i
!= DataMap
.end() ? &(this->*i
->second
) : 0;
181 void script::SaveDataMap (const datamap
&DataMap
, outputfile
&SaveFile
) const {
182 for (datamap::const_iterator i
= DataMap
.begin(); i
!= DataMap
.end(); ++i
) (this->*i
->second
).Save(SaveFile
);
186 void script::LoadDataMap (const datamap
&DataMap
, inputfile
&SaveFile
) {
187 for (datamap::const_iterator i
= DataMap
.begin(); i
!= DataMap
.end(); ++i
) (this->*i
->second
).Load(SaveFile
);
191 template <class scriptmemberptr
> void InitMember (script::datamap
&DataMap
, cchar
*Identifier
, scriptmemberptr DataMember
) {
192 DataMap
[Identifier
] = reinterpret_cast<scriptmemberbase
script::*>(DataMember
);
196 #define INIT_ENTRY(name) InitMember(DataMap, #name, &scripttype::name##Holder)
197 #define INIT(name, value) name##Holder(value)
200 void posscript::InitDataMap () {
207 void posscript::ReadFrom (inputfile
&SaveFile
) {
208 static festring Word
;
210 SrcFile
= SaveFile
.GetFileName();
211 SrcLine
= SaveFile
.CurrentLine();
212 SaveFile
.ReadWord(Word
);
215 VectorHolder
.ReadFrom(SaveFile
);
216 } else if (Word
== "Random") {
218 FlagsHolder
.ReadFrom(SaveFile
);
219 } else if (Word
== "BoundedRandom") {
221 BordersHolder
.ReadFrom(SaveFile
);
222 FlagsHolder
.ReadFrom(SaveFile
);
227 void posscript::Save (outputfile
&SaveFile
) const {
228 script::Save(SaveFile
);
233 void posscript::Load (inputfile
&SaveFile
) {
234 script::Load(SaveFile
);
239 void materialscript::InitDataMap () {
244 void materialscript::ReadFrom (inputfile
&SaveFile
) {
245 static festring Word
;
247 SrcFile
= SaveFile
.GetFileName();
248 SrcLine
= SaveFile
.CurrentLine();
249 SaveFile
.ReadWord(Word
);
250 if (Word
== "=") SaveFile
.ReadWord(Word
);
254 valuemap::const_iterator i
= game::GetGlobalValueMap().find(Word
);
256 if (i
!= game::GetGlobalValueMap().end()) Config
= i
->second
;
257 else ABORT("Unconfigured material script detected at line %d!", SaveFile
.TokenLine());
259 if (SaveFile
.ReadWord() != "{") return;
260 for (SaveFile
.ReadWord(Word
); Word
!= "}"; SaveFile
.ReadWord(Word
)) {
261 if (!ReadMember(SaveFile
, Word
)) {
262 ABORT("Odd script term %s encountered in material script line %d!", Word
.CStr(), SaveFile
.TokenLine());
268 material
*materialscript::Instantiate () const {
269 return MAKE_MATERIAL(Config
, GetVolume() ? GetVolume()->Randomize() : 0);
273 void materialscript::Save (outputfile
&SaveFile
) const {
274 script::Save(SaveFile
);
275 SaveFile
<< (uShort
)Config
;
279 void materialscript::Load (inputfile
&SaveFile
) {
280 script::Load(SaveFile
);
288 void basecontentscript::InitDataMap () {
289 INIT_ENTRY(MainMaterial
);
290 INIT_ENTRY(SecondaryMaterial
);
291 INIT_ENTRY(Parameters
);
295 basecontentscript::basecontentscript () : script(), ContentType(0), Random(false), Config(0), INIT(Parameters
, NO_PARAMETERS
) {
299 void basecontentscript::ReadFrom (inputfile
&SaveFile
) {
300 static festring Word
;
302 SrcFile
= SaveFile
.GetFileName();
303 SrcLine
= SaveFile
.CurrentLine();
304 SaveFile
.ReadWord(Word
);
306 mCode
= SaveFile
.ReadCode();
307 SaveFile
.ReadWord(Word
);
309 if (Word
== "=" || Word
== ",") SaveFile
.ReadWord(Word
);
310 valuemap::const_iterator i
= game::GetGlobalValueMap().find(Word
);
311 if (i
!= game::GetGlobalValueMap().end()) {
312 if (!GetMainMaterial()) MainMaterialHolder
.Member
= new materialscript
;
313 MainMaterialHolder
.Member
->SetConfig(i
->second
);
314 SaveFile
.ReadWord(Word
);
315 i
= game::GetGlobalValueMap().find(Word
);
316 if (i
!= game::GetGlobalValueMap().end()) {
317 if (!GetSecondaryMaterial()) SecondaryMaterialHolder
.Member
= new materialscript
;
318 SecondaryMaterialHolder
.Member
->SetConfig(i
->second
);
319 SaveFile
.ReadWord(Word
);
322 if (Word
== "NaturalMaterialForm") {
324 ContentType
= NATURAL_MATERIAL_FORM
;
325 SaveFile
.ReadWord(Word
);
326 } else if (Word
== "Random") {
328 SaveFile
.ReadWord(Word
);
331 ContentType
= SearchCodeName(Word
);
332 if (ContentType
|| Word
== "0") SaveFile
.ReadWord(Word
);
333 else ABORT("Odd script term %s encountered in %s content script, file %s line %d!", Word
.CStr(), GetClassID(), SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
336 Config
= SaveFile
.ReadNumber();
337 SaveFile
.ReadWord(Word
);
342 for (SaveFile
.ReadWord(Word
); Word
!= "}"; SaveFile
.ReadWord(Word
)) {
343 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());
347 mCode
= SaveFile
.ReadCode();
348 SaveFile
.ReadWord(Word
);
350 if (Word
!= ";" && Word
!= ",") ABORT("Odd terminator %s encountered in %s content script, file %s line %d!", Word
.CStr(), GetClassID(), SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
355 scriptmemberbase
*basecontentscript::GetData (cchar
*String
) {
356 scriptmemberbase
*Return
= GetDataFromMap(GetDataMap(), String
);
357 return Return
? Return
: GetDataFromMap(DataMap
, String
);
361 void basecontentscript::Save (outputfile
&SaveFile
) const {
362 SaveFile
<< SrcFile
<< SrcLine
;
363 SaveDataMap(GetDataMap(), SaveFile
);
364 SaveDataMap(DataMap
, SaveFile
);
365 SaveFile
<< ContentType
;
366 SaveFile
.Put(!!Random
);
371 void basecontentscript::Load (inputfile
&SaveFile
) {
372 SaveFile
>> SrcFile
>> SrcLine
;
373 LoadDataMap(GetDataMap(), SaveFile
);
374 LoadDataMap(DataMap
, SaveFile
);
375 ContentType
= ReadType(uShort
, SaveFile
);
376 Random
= SaveFile
.Get();
381 template <class type
> type
*contentscripttemplate
<type
>::BasicInstantiate (int SpecialFlags
) const {
383 const typename
type::prototype
*Proto
= protocontainer
<type
>::GetProto(ContentType
);
384 const typename
type::database
*const *ConfigData
= Proto
->GetConfigData();
385 const materialscript
*MainMaterial
= GetMainMaterial();
386 const materialscript
*SecondaryMaterial
= GetSecondaryMaterial();
387 const typename
type::database
*DataBase
= *ConfigData
;
388 truth UseOverriddenMaterials
= false;
390 if (!Config
&& DataBase
->IsAbstract
) {
392 DataBase
= ConfigData
[1+RAND()%(Proto
->GetConfigSize()-1)];
393 if (DataBase
->AllowRandomInstantiation()) {
394 if (!(SpecialFlags
& NO_MATERIALS
) && MainMaterial
&& (!DataBase
->HasSecondaryMaterial
|| SecondaryMaterial
)) {
395 SpecialFlags
|= NO_MATERIALS
;
396 UseOverriddenMaterials
= true;
398 Instance
= Proto
->Spawn(DataBase
->Config
, SpecialFlags
|NO_PIC_UPDATE
);
402 if (!(SpecialFlags
& NO_MATERIALS
) && MainMaterial
&& (!DataBase
->HasSecondaryMaterial
|| SecondaryMaterial
)) {
403 SpecialFlags
|= NO_MATERIALS
;
404 UseOverriddenMaterials
= true;
406 Instance
= Proto
->Spawn(Config
, SpecialFlags
|NO_PIC_UPDATE
);
408 if (GetParameters() != NO_PARAMETERS
) Instance
->SetParameters(GetParameters());
409 if (UseOverriddenMaterials
) {
410 Instance
->InitMaterials(MainMaterial
, SecondaryMaterial
, false);
412 if (MainMaterial
) Instance
->ChangeMainMaterial(MainMaterial
->Instantiate(), SpecialFlags
|NO_PIC_UPDATE
);
413 if (SecondaryMaterial
) Instance
->ChangeSecondaryMaterial(SecondaryMaterial
->Instantiate(), SpecialFlags
|NO_PIC_UPDATE
);
415 if (!(SpecialFlags
& NO_PIC_UPDATE
)) Instance
->UpdatePictures();
420 /* Called by an inline function in script.h... */
422 template glterrain
*contentscripttemplate
<glterrain
>::BasicInstantiate (int) const;
424 template <class type
> int contentscripttemplate
<type
>::SearchCodeName (cfestring
&String
) const {
425 return protocontainer
<type
>::SearchCodeName(String
);
428 /* GCC 2.952 SUCKS!!! IT MUST BURN!!! */
430 template int contentscripttemplate
<character
>::SearchCodeName(cfestring
&) const;
431 template int contentscripttemplate
<item
>::SearchCodeName(cfestring
&) const;
432 template int contentscripttemplate
<glterrain
>::SearchCodeName(cfestring
&) const;
433 template int contentscripttemplate
<olterrain
>::SearchCodeName(cfestring
&) const;
435 cchar
*contentscript
<character
>::GetClassID () const { return "character"; }
436 cchar
*contentscript
<item
>::GetClassID () const { return "item"; }
437 cchar
*contentscript
<glterrain
>::GetClassID () const { return "glterrain"; }
438 cchar
*contentscript
<olterrain
>::GetClassID () const { return "olterrain"; }
441 void contentscript
<character
>::InitDataMap () {
442 INIT_ENTRY(Inventory
);
443 INIT_ENTRY(WayPoint
);
449 contentscript
<character
>::contentscript () : INIT(Team
, DEFAULT_TEAM
), INIT(Flags
, 0) {
453 character
*contentscript
<character
>::Instantiate (int SpecialFlags
) const {
454 character
*Instance
= contentscripttemplate
<character
>::BasicInstantiate(SpecialFlags
);
456 //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());
467 if (GetTeam() != DEFAULT_TEAM
) Instance
->SetTeam(game::GetTeam(GetTeam()));
468 const fearray
<contentscript
<item
> > *Inventory
= GetInventory();
469 if (Inventory
) Instance
->AddToInventory(*Inventory
, SpecialFlags
);
470 const fearray
<packv2
> *WayPoint
= GetWayPoint();
471 if (WayPoint
) Instance
->SetWayPoints(*WayPoint
);
472 Instance
->RestoreHP();
473 Instance
->RestoreStamina();
478 contentscript
<item
>::contentscript () :
479 INIT(Category
, ANY_CATEGORY
),
481 INIT(MaxPrice
, MAX_PRICE
),
482 INIT(Team
, DEFAULT_TEAM
),
483 INIT(SquarePosition
, CENTER
),
485 INIT(ConfigFlags
, 0),
486 INIT(SpoilPercentage
, 0),
487 INIT(Enchantment
, 0),
488 INIT(IsActive
, false)
493 void contentscript
<item
>::InitDataMap () {
494 INIT_ENTRY(ItemsInside
);
496 INIT_ENTRY(MinPrice
);
497 INIT_ENTRY(MaxPrice
);
498 INIT_ENTRY(LifeExpectancy
);
500 INIT_ENTRY(Category
);
501 INIT_ENTRY(SquarePosition
);
503 INIT_ENTRY(ConfigFlags
);
504 INIT_ENTRY(SpoilPercentage
);
505 INIT_ENTRY(Enchantment
);
506 INIT_ENTRY(IsActive
);
510 item
*contentscript
<item
>::InstantiateBasedOnMaterial (int MaterialConfig
, int SpecialFlags
) const {
511 if (ContentType
== NATURAL_MATERIAL_FORM
) {
512 const materialscript
*MainMaterial
= GetMainMaterial();
513 sLong Volume
= MainMaterial
&& MainMaterial
->GetVolume() ? MainMaterial
->GetVolume()->Randomize() : 0;
514 return material::CreateNaturalForm(MaterialConfig
, Volume
);
516 return Instantiate(SpecialFlags
);
520 item
*contentscript
<item
>::Instantiate (int SpecialFlags
) const {
521 int Chance
= GetChance();
524 if (!mCode
.IsEmpty()) {
525 game::ClearEventData();
526 if (!game::RunAllowScriptStr(mCode
)) return 0;
529 if (Chance
!= 100 && Chance
<= RAND_N(100)) return 0;
531 Instance
= protosystem::BalancedCreateItem(0, GetMinPrice(), GetMaxPrice(), GetCategory(), SpecialFlags
, GetConfigFlags());
533 Instance
= contentscripttemplate
<item
>::BasicInstantiate(SpecialFlags
);
535 if (GetLifeExpectancy()) Instance
->SetLifeExpectancy(GetLifeExpectancy()->Min
, (GetLifeExpectancy()->Max
- GetLifeExpectancy()->Min
) + 1);
536 if (GetTeam() != DEFAULT_TEAM
) Instance
->SetTeam(GetTeam());
537 if (IsActive()) Instance
->SetIsActive(true);
538 if (GetEnchantment() != 0) Instance
->SetEnchantment(GetEnchantment());
539 const fearray
<contentscript
<item
> > *ItemsInside
= GetItemsInside();
540 if (ItemsInside
) Instance
->SetItemsInside(*ItemsInside
, SpecialFlags
);
541 if (GetSpoilPercentage() != 0) Instance
->SetSpoilPercentage(GetSpoilPercentage());
546 truth
IsValidScript (const fearray
<contentscript
<item
> > *Array
) {
547 for (uInt c
= 0; c
< Array
->Size
; ++c
) if (IsValidScript(&Array
->Data
[c
])) return true;
552 void contentscript
<glterrain
>::InitDataMap () {
553 INIT_ENTRY(IsInside
);
557 contentscript
<olterrain
>::contentscript () :
558 INIT(VisualEffects
, 0),
559 INIT(AttachedArea
, DEFAULT_ATTACHED_AREA
),
560 INIT(AttachedEntry
, DEFAULT_ATTACHED_ENTRY
)
565 void contentscript
<olterrain
>::InitDataMap () {
566 INIT_ENTRY(ItemsInside
);
568 INIT_ENTRY(VisualEffects
);
569 INIT_ENTRY(AttachedArea
);
570 INIT_ENTRY(AttachedEntry
);
574 olterrain
*contentscript
<olterrain
>::Instantiate (int SpecialFlags
) const {
575 if (!ContentType
) return 0;
576 olterrain
*Instance
= contentscripttemplate
<olterrain
>::BasicInstantiate(SpecialFlags
);
577 if (GetVisualEffects()) {
578 Instance
->SetVisualEffects(GetVisualEffects());
579 Instance
->UpdatePictures();
581 if (GetAttachedArea() != DEFAULT_ATTACHED_AREA
) Instance
->SetAttachedArea(GetAttachedArea());
582 if (GetAttachedEntry() != DEFAULT_ATTACHED_ENTRY
) Instance
->SetAttachedEntry(GetAttachedEntry());
583 cfestring
*Text
= GetText();
584 if (Text
) Instance
->SetText(*Text
);
585 const fearray
<contentscript
<item
> > *ItemsInside
= GetItemsInside();
586 if (ItemsInside
) Instance
->SetItemsInside(*ItemsInside
, SpecialFlags
);
591 squarescript::squarescript () : INIT(EntryIndex
, NO_ENTRY
), INIT(AttachRequired
, false) {
595 void squarescript::InitDataMap () {
596 INIT_ENTRY(Position
);
597 INIT_ENTRY(Character
);
599 INIT_ENTRY(GTerrain
);
600 INIT_ENTRY(OTerrain
);
602 INIT_ENTRY(EntryIndex
);
603 INIT_ENTRY(AttachRequired
);
607 void squarescript::ReadFrom (inputfile
&SaveFile
) {
608 static festring Word
;
610 SrcFile
= SaveFile
.GetFileName();
611 SrcLine
= SaveFile
.CurrentLine();
612 SaveFile
.ReadWord(Word
);
614 PositionHolder
.ReadFrom(SaveFile
);
615 if (SaveFile
.ReadWord() != "{") ABORT("Bracket missing in square script line %d!", SaveFile
.TokenLine());
616 for (SaveFile
.ReadWord(Word
); Word
!= "}"; SaveFile
.ReadWord(Word
)) {
617 if (!ReadMember(SaveFile
, Word
)) ABORT("Odd script term %s encountered in square script line %d!", Word
.CStr(), SaveFile
.TokenLine());
620 GTerrainHolder
.ReadFrom(SaveFile
);
621 OTerrainHolder
.ReadFrom(SaveFile
);
626 template <class type
, class contenttype
> contentmap
<type
, contenttype
>::contentmap() : ContentMap(0) {
630 template <class type
, class contenttype
> contentmap
<type
, contenttype
>::~contentmap
<type
, contenttype
> () {
631 delete [] ContentMap
;
635 template <class type
, class contenttype
> void contentmap
<type
, contenttype
>::InitDataMap () {
641 template <class type
, class contenttype
> void contentmap
<type
, contenttype
>::ReadFrom (inputfile
&SaveFile
) {
642 typedef std::map
<int, contenttype
> maptype
;
643 typedef typename
maptype::iterator mapiterator
;
644 festring Word1
, Word2
;
646 SrcFile
= SaveFile
.GetFileName();
647 SrcLine
= SaveFile
.CurrentLine();
648 if (ContentMap
) ABORT("Illegal %s content map redefinition on line %d!", protocontainer
<type
>::GetMainClassID(), SaveFile
.TokenLine());
649 if (SaveFile
.ReadWord() != "{") ABORT("Bracket missing in %s content map script line %d!", protocontainer
<type
>::GetMainClassID(), SaveFile
.TokenLine());
650 SymbolMap
.insert(std::pair
<int, contenttype
>('.', contenttype()));
651 for (SaveFile
.ReadWord(Word1
); Word1
!= "}"; Word1
= SaveFile
.ReadWord()) {
652 if (Word1
== "Types") {
653 if (SaveFile
.ReadWord() != "{") ABORT("Missing bracket in %s content map script line %d!", protocontainer
<type
>::GetMainClassID(), SaveFile
.TokenLine());
654 for (SaveFile
.ReadWord(Word2
); Word2
!= "}"; Word2
= SaveFile
.ReadWord()) {
655 std::pair
<mapiterator
, bool> Return
= SymbolMap
.insert(std::pair
<int, contenttype
>(Word2
[0], contenttype()));
658 ReadData(Return
.first
->second
, SaveFile
);
660 ABORT("Symbol %c defined again in %s content map script line %d!", Word2
[0], protocontainer
<type
>::GetMainClassID(), SaveFile
.TokenLine());
665 if (!ReadMember(SaveFile
, Word1
)) ABORT("Odd script term %s encountered in %s content script line %d!", Word1
.CStr(), protocontainer
<type
>::GetMainClassID(), SaveFile
.TokenLine());
668 v2 Size
= *GetSize();
670 Alloc2D(ContentMap
, Size
.X
, Size
.Y
);
671 if (SaveFile
.ReadWord() != "{") ABORT("Missing bracket in %s content map script line %d!", protocontainer
<type
>::GetMainClassID(), SaveFile
.TokenLine());
672 for (int y
= 0; y
< Size
.Y
; ++y
) {
673 for (int x
= 0; x
< Size
.X
; ++x
) {
674 int Char
= SaveFile
.ReadLetter();
675 typename
std::map
<int, contenttype
>::iterator i
= SymbolMap
.find(Char
);
677 if (i
!= SymbolMap
.end()) {
678 ContentMap
[x
][y
] = std::make_pair(Char
, &i
->second
);
680 ABORT("Illegal content %c in %s content map line %d!", Char
, protocontainer
<type
>::GetMainClassID(), SaveFile
.TokenLine());
684 if (SaveFile
.ReadWord() != "}") ABORT("Missing bracket in %s content map script line %d!", protocontainer
<type
>::GetMainClassID(), SaveFile
.TokenLine());
688 template <class type
, class contenttype
> void contentmap
<type
, contenttype
>::Save (outputfile
&SaveFile
) const {
689 script::Save(SaveFile
);
690 SaveFile
<< SymbolMap
;
692 v2 Size
= *GetSize();
693 for (int y
= 0; y
< Size
.Y
; ++y
)
694 for (int x
= 0; x
< Size
.X
; ++x
)
695 SaveFile
<< char(ContentMap
[x
][y
].first
);
699 template <class type
, class contenttype
> void contentmap
<type
, contenttype
>::Load (inputfile
&SaveFile
) {
700 script::Load(SaveFile
);
701 SaveFile
>> SymbolMap
;
703 v2 Size
= *GetSize();
705 Alloc2D(ContentMap
, Size
.X
, Size
.Y
);
706 for (int y
= 0; y
< Size
.Y
; ++y
) {
707 for (int x
= 0; x
< Size
.X
; ++x
) {
708 int Char
= ReadType(char, SaveFile
);
710 ContentMap
[x
][y
] = std::make_pair(Char
, &SymbolMap
.find(Char
)->second
);
716 const std::list
<squarescript
> &roomscript::GetSquare () const { return Square
; }
719 void roomscript::InitDataMap () {
720 INIT_ENTRY(CharacterMap
);
722 INIT_ENTRY(GTerrainMap
);
723 INIT_ENTRY(OTerrainMap
);
724 INIT_ENTRY(WallSquare
);
725 INIT_ENTRY(FloorSquare
);
726 INIT_ENTRY(DoorSquare
);
729 INIT_ENTRY(AltarPossible
);
730 INIT_ENTRY(GenerateDoor
);
731 INIT_ENTRY(GenerateTunnel
);
732 INIT_ENTRY(DivineMaster
);
733 INIT_ENTRY(GenerateLanterns
);
735 INIT_ENTRY(GenerateFountains
);
736 INIT_ENTRY(AllowLockedDoors
);
737 INIT_ENTRY(AllowBoobyTrappedDoors
);
739 INIT_ENTRY(IsInside
);
740 INIT_ENTRY(GenerateWindows
);
741 INIT_ENTRY(UseFillSquareWalls
);
743 INIT_ENTRY(GenerateWards
);
744 INIT_ENTRY(AllowedDivineMasters
);
748 void roomscript::ReadFrom (inputfile
&SaveFile
) {
751 SrcFile
= SaveFile
.GetFileName();
752 SrcLine
= SaveFile
.CurrentLine();
753 if (SaveFile
.ReadWord() != "{") ABORT("Bracket missing in room script line %d!", SaveFile
.TokenLine());
754 for (SaveFile
.ReadWord(Word
); Word
!= "}"; SaveFile
.ReadWord(Word
)) {
755 if (Word
== "Square") {
756 Square
.push_back(squarescript());
757 Square
.back().ReadFrom(SaveFile
);
760 if (!ReadMember(SaveFile
, Word
)) ABORT("Odd script term %s encountered in room script line %d!", Word
.CStr(), SaveFile
.TokenLine());
765 void roomscript::Save (outputfile
&SaveFile
) const {
766 script::Save(SaveFile
);
771 void roomscript::Load (inputfile
&SaveFile
) {
772 script::Load(SaveFile
);
777 const std::list
<squarescript
> &levelscript::GetSquare () const { return Square
; }
778 const std::list
<roomscript
> &levelscript::GetRoom () const { return Room
; }
781 void levelscript::InitDataMap () {
782 INIT_ENTRY(RoomDefault
);
783 INIT_ENTRY(FillSquare
);
784 INIT_ENTRY(TunnelSquare
);
785 INIT_ENTRY(LevelMessage
);
789 INIT_ENTRY(GenerateMonsters
);
790 INIT_ENTRY(IsOnGround
);
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 (inputfile
&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 (inputfile
&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 (inputfile
&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 (inputfile
&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 inputfile
incf(game::GetGameDir()+"script/"+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();