From bbe0eb5e96bdfd0d85e1bf0c835ba819b1d7ef81 Mon Sep 17 00:00:00 2001 From: Ketmar Dark Date: Sun, 29 Oct 2017 12:47:51 +0200 Subject: [PATCH] entities without definitions in script will be removed from game; it is now possible to turn off modules with new entities (i hope) --- src/felib/felibdef.h | 17 ++++++++++++++++ src/game/char.cpp | 4 +++- src/game/database.cpp | 17 +++++++++++----- src/game/game.cpp | 24 ++++++++++++++++++---- src/game/level.cpp | 6 ++++-- src/game/proto.cpp | 41 +++++++++++++++++++++++++------------ src/game/proto.h | 56 ++++++++++++++++++++++++++++++++++++++------------- src/game/script.cpp | 1 + src/game/worldmap.cpp | 4 +++- 9 files changed, 130 insertions(+), 40 deletions(-) diff --git a/src/felib/felibdef.h b/src/felib/felibdef.h index 663037e..1bcbd6a 100644 --- a/src/felib/felibdef.h +++ b/src/felib/felibdef.h @@ -184,4 +184,21 @@ using rcint = int; #define SPARKLING_D 8 +// ////////////////////////////////////////////////////////////////////////// // +#include +#include +#include + +template std::string getTypeName () { + int status; + std::string name = typeid(T).name(); + char *demangled = abi::__cxa_demangle(name.c_str(), 0/*NULL*/, 0/*NULL*/, &status); + if (status == 0) { + name = demangled; + std::free(demangled); + } + return name; +} + + #endif diff --git a/src/game/char.cpp b/src/game/char.cpp index a275e8b..946ee00 100644 --- a/src/game/char.cpp +++ b/src/game/char.cpp @@ -5068,9 +5068,10 @@ int characterprototype::CreateSpecialConfigurations (characterdatabase **TempCon if (Level == 1 && TempConfig[0]->CreateUndeadConfigurations) { for (int c = 1; c < protocontainer::GetSize(); ++c) { const character::prototype *Proto = protocontainer::GetProto(c); + if (!Proto) continue; // missing character const character::database *const *CharacterConfigData = Proto->GetConfigData(); if (!CharacterConfigData) ABORT("No database entry for character <%s>!", Proto->GetClassID()); - const character::database*const* End = CharacterConfigData + Proto->GetConfigSize(); + const character::database*const* End = CharacterConfigData+Proto->GetConfigSize(); for (++CharacterConfigData; CharacterConfigData != End; ++CharacterConfigData) { const character::database *CharacterDataBase = *CharacterConfigData; if (CharacterDataBase->UndeadVersions) { @@ -5122,6 +5123,7 @@ int characterprototype::CreateSpecialConfigurations (characterdatabase **TempCon if (Level == 0 && TempConfig[0]->CreateGolemMaterialConfigurations) { for (int c = 1; c < protocontainer::GetSize(); ++c) { const material::prototype* Proto = protocontainer::GetProto(c); + if (!Proto) continue; // missing matherial const material::database*const* MaterialConfigData = Proto->GetConfigData(); const material::database*const* End = MaterialConfigData + Proto->GetConfigSize(); for (++MaterialConfigData; MaterialConfigData != End; ++MaterialConfigData) { diff --git a/src/game/database.cpp b/src/game/database.cpp index a02c64e..5972348 100644 --- a/src/game/database.cpp +++ b/src/game/database.cpp @@ -256,11 +256,14 @@ template void databasecreator::ReadFrom (const festring &base } delete inFile; } - // - int c1; - for (c1 = 0; c1 < SPECIAL_CONFIGURATION_GENERATION_LEVELS; ++c1) { + + // remove undefined items + protocontainer::Cleanup(); + + for (int c1 = 0; c1 < SPECIAL_CONFIGURATION_GENERATION_LEVELS; ++c1) { for (int c2 = 1; c2 < protocontainer::GetSize(); ++c2) { prototype *Proto = protocontainer::GetProtoData()[c2]; + if (!Proto) continue; // missing something int Configs = Proto->ConfigSize; memmove(TempConfig, Proto->ConfigData, Configs*sizeof(database *)); Configs = Proto->CreateSpecialConfigurations(TempConfig, Configs, c1); @@ -272,15 +275,19 @@ template void databasecreator::ReadFrom (const festring &base } } } - for (c1 = 1; c1 < protocontainer::GetSize(); ++c1) { + + for (int c1 = 1; c1 < protocontainer::GetSize(); ++c1) { prototype *Proto = protocontainer::GetProtoData()[c1]; + if (!Proto) continue; // missing something TempTables = CreateConfigTable(reinterpret_cast(Proto->ConfigTable), TempTable, reinterpret_cast(Proto->ConfigData), TempTableInfo, c1, Proto->ConfigSize, TempTables); } - for (c1 = 1; c1 < TempTables; ++c1) delete [] TempTable[c1]; + + for (int c1 = 1; c1 < TempTables; ++c1) delete [] TempTable[c1]; + GetDataBaseMemberMap().clear(); } diff --git a/src/game/game.cpp b/src/game/game.cpp index 6aeb7df..1ddd436 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -1293,7 +1293,11 @@ cchar *game::GetVerbalPlayerAlignment () { void game::CreateGods () { God = new god*[GODS+1]; God[0] = 0; - for (int c = 1; c < protocontainer::GetSize(); ++c) God[c] = protocontainer::GetProto(c)->Spawn(); + for (int c = 1; c < protocontainer::GetSize(); ++c) { + auto proto = protocontainer::GetProto(c); + if (!proto) ABORT("God #%d is not defined!", c); + God[c] = proto->Spawn(); + } } @@ -1855,6 +1859,7 @@ void game::InitDangerMap () { for (int c1 = 1; c1 < protocontainer::GetSize(); ++c1) { BusyAnimation(); const character::prototype *Proto = protocontainer::GetProto(c1); + if (!Proto) continue; // missing character const character::database *const *ConfigData = Proto->GetConfigData(); int ConfigSize = Proto->GetConfigSize(); for (int c2 = 0; c2 < ConfigSize; ++c2) { @@ -1887,6 +1892,7 @@ void game::InitDangerMap () { void game::CalculateNextDanger () { if (IsInWilderness() || !*CurrentLevel->GetLevelScript()->GenerateMonsters()) return; const character::prototype *Proto = protocontainer::GetProto(NextDangerIDType); + if (!Proto) ABORT("Oops! game::CalculateNextDanger() failed!"); // missing character const character::database *const *ConfigData = Proto->GetConfigData(); const character::database *DataBase = ConfigData[NextDangerIDConfigIndex]; dangermap::iterator DangerIterator = DangerMap.find(configid(NextDangerIDType, DataBase->Config)); @@ -1922,9 +1928,14 @@ void game::CalculateNextDanger () { //fprintf(stderr, "game::CalculateNextDanger(): EXIT0\n"); return; } + int loopCount = 0; for (;;) { - if (++NextDangerIDType >= protocontainer::GetSize()) NextDangerIDType = 1; + if (++NextDangerIDType >= protocontainer::GetSize()) { + NextDangerIDType = 1; + if (++loopCount > 2) ABORT("Oops! Cannot calculate next danger!"); + } Proto = protocontainer::GetProto(NextDangerIDType); + if (!Proto) continue; // missing character ConfigData = Proto->GetConfigData(); int ConfigSize = Proto->GetConfigSize(); for (int c = 0; c < ConfigSize; ++c) { @@ -2386,7 +2397,9 @@ void game::DisplayMassacreList (const massacremap &MassacreMap, cchar *Reason, s charactervector GraveYard; // for (massacremap::const_iterator i1 = MassacreMap.begin(); i1 != MassacreMap.end(); ++i1) { - character *Victim = protocontainer::GetProto(i1->first.Type)->Spawn(i1->first.Config); + auto monsProto = protocontainer::GetProto(i1->first.Type); + if (!monsProto) continue; // missing character + character *Victim = monsProto->Spawn(i1->first.Config); Victim->SetAssignedName(i1->first.Name); massacresetentry Entry; GraveYard.push_back(Victim); @@ -2553,6 +2566,7 @@ double game::CalculateAverageDangerOfAllNormalEnemies () { int Enemies = 0; for (int c1 = 1; c1 < protocontainer::GetSize(); ++c1) { const character::prototype *Proto = protocontainer::GetProto(c1); + if (!Proto) continue; // missing character const character::database*const *ConfigData = Proto->GetConfigData(); int ConfigSize = Proto->GetConfigSize(); for (int c2 = 0; c2 < ConfigSize; ++c2) { @@ -2599,7 +2613,9 @@ sLong game::GetScore () { KillData.DangerSum += i->second.DangerSum; } for (i = SumMap.begin(); i != SumMap.end(); ++i) { - character *Char = protocontainer::GetProto(i->first.Type)->Spawn(i->first.Config); + auto monsProto = protocontainer::GetProto(i->first.Type); + if (!monsProto) continue; // missing character + character *Char = monsProto->Spawn(i->first.Config); int SumOfAttributes = Char->GetSumOfAttributes(); Counter += sqrt(i->second.DangerSum / DEFAULT_GENERATION_DANGER) * SumOfAttributes * SumOfAttributes; delete Char; diff --git a/src/game/level.cpp b/src/game/level.cpp index 0761b5f..06ad3df 100644 --- a/src/game/level.cpp +++ b/src/game/level.cpp @@ -307,8 +307,10 @@ truth level::MakeRoom (const roomscript *RoomScript) { } } - room *RoomClass = protocontainer::GetProto(*RoomScript->GetType())->Spawn(); - // + auto roomProto = protocontainer::GetProto(*RoomScript->GetType()); + if (!roomProto) ABORT("No prototype #%d for room!", *RoomScript->GetType()); + room *RoomClass = roomProto->Spawn(); + RoomClass->SetScript(RoomScript); RoomClass->SetPos(Pos); RoomClass->SetSize(Size); diff --git a/src/game/proto.cpp b/src/game/proto.cpp index f33d3a8..a4eacde 100644 --- a/src/game/proto.cpp +++ b/src/game/proto.cpp @@ -23,6 +23,7 @@ sLong protosystem::TotalItemPossibility; #include "level.h" +// ////////////////////////////////////////////////////////////////////////// // character *protosystem::BalancedCreateMonster (level *lvl) { if (!lvl) lvl = game::GetCurrentLevel(); for (int c = 0; ; ++c) { @@ -30,6 +31,7 @@ character *protosystem::BalancedCreateMonster (level *lvl) { std::vector Possible; for (int Type = 1; Type < protocontainer::GetSize(); ++Type) { const character::prototype *Proto = protocontainer::GetProto(Type); + if (!Proto) continue; // missing character const character::database *const *ConfigData = Proto->GetConfigData(); int ConfigSize = Proto->GetConfigSize(); for (int c = 0; c < ConfigSize; ++c) { @@ -106,6 +108,7 @@ character *protosystem::BalancedCreateMonster (level *lvl) { for (int i = 0; i < 25; ++i) { configid Chosen = Possible[RAND_GOOD(Possible.size())]; const character::prototype *Proto = protocontainer::GetProto(Chosen.Type); + if (!Proto) continue; // missing character character *Monster = Proto->Spawn(Chosen.Config); if (c >= 100 || ((Monster->GetFrequency() == 10000 || Monster->GetFrequency() > RAND_GOOD(10000)) && @@ -250,7 +253,8 @@ character *protosystem::CreateMonster (int MinDanger, int MaxDanger, int Special for (int c = 0; !Monster; ++c) { for (int Type = 1; Type < protocontainer::GetSize(); ++Type) { - const character::prototype* Proto = protocontainer::GetProto(Type); + const character::prototype *Proto = protocontainer::GetProto(Type); + if (!Proto) continue; // missing character const character::database*const* ConfigData = Proto->GetConfigData(); int ConfigSize = Proto->GetConfigSize(); @@ -281,7 +285,9 @@ character *protosystem::CreateMonster (int MinDanger, int MaxDanger, int Special } configid Chosen = Possible[RAND_GOOD(Possible.size())]; - Monster = protocontainer::GetProto(Chosen.Type)->Spawn(Chosen.Config, SpecialFlags); + auto monsProto = protocontainer::GetProto(Chosen.Type); + if (!monsProto) ABORT("Cannot create monster of type %d without prototype!", Chosen.Type); + Monster = monsProto->Spawn(Chosen.Config, SpecialFlags); Monster->SignalGeneration(); Monster->SetTeam(game::GetTeam(MONSTER_TEAM)); } @@ -321,6 +327,7 @@ template std::pair SearchFor // for (int c = 1; c < protocontainer::GetSize(); ++c) { const prototype *Proto = protocontainer::GetProto(c); + if (!Proto) continue; // missing something const database *const *ConfigData = Proto->GetConfigData(); int ConfigSize = Proto->GetConfigSize(); // @@ -398,9 +405,9 @@ item* protosystem::CreateItem (cfestring &What, truth Output) { material* protosystem::CreateMaterial (cfestring& What, sLong Volume, truth Output) { for (int c1 = 1; c1 < protocontainer::GetSize(); ++c1) { const material::prototype* Proto = protocontainer::GetProto(c1); + if (!Proto) continue; // missing material const material::database*const* ConfigData = Proto->GetConfigData(); int ConfigSize = Proto->GetConfigSize(); - for (int c2 = 1; c2 < ConfigSize; ++c2) { if (ConfigData[c2]->NameStem == What) { if (ConfigData[c2]->CommonFlags & CAN_BE_WISHED || game::WizardModeIsActive()) { @@ -413,9 +420,7 @@ material* protosystem::CreateMaterial (cfestring& What, sLong Volume, truth Outp } } } - if (Output) ADD_MESSAGE("There is no such material."); - return 0; } @@ -425,6 +430,7 @@ material* protosystem::CreateMaterial (cfestring& What, sLong Volume, truth Outp void protosystem::CreateEveryCharacter (charactervector &Character) { for (int c1 = 1; c1 < protocontainer::GetSize(); ++c1) { const character::prototype* Proto = protocontainer::GetProto(c1); + if (!Proto) continue; // missing character const character::database*const* ConfigData = Proto->GetConfigData(); int ConfigSize = Proto->GetConfigSize(); for (int c2 = 0; c2 < ConfigSize; ++c2) { @@ -437,6 +443,7 @@ void protosystem::CreateEveryCharacter (charactervector &Character) { void protosystem::CreateEveryItem (itemvectorvector &Item) { for (int c = 1; c < protocontainer::GetSize(); ++c) { const item::prototype* Proto = protocontainer::GetProto(c); + if (!Proto) continue; // missing item const item::database*const* ConfigData = Proto->GetConfigData(); int ConfigSize = Proto->GetConfigSize(); for (int c2 = 0; c2 < ConfigSize; ++c2) { @@ -451,6 +458,7 @@ void protosystem::CreateEveryItem (itemvectorvector &Item) { void protosystem::CreateEveryMaterial (std::vector &Material) { for (int c1 = 1; c1 < protocontainer::GetSize(); ++c1) { const material::prototype* Proto = protocontainer::GetProto(c1); + if (!Proto) continue; // missing material const material::database*const* ConfigData = Proto->GetConfigData(); int ConfigSize = Proto->GetConfigSize(); for (int c2 = 1; c2 < ConfigSize; ++c2) { @@ -465,6 +473,7 @@ void protosystem::CreateEveryMaterial (std::vector &Material) { void protosystem::CreateEveryNormalEnemy (charactervector& EnemyVector) { for (int c = 1; c < protocontainer::GetSize(); ++c) { const character::prototype* Proto = protocontainer::GetProto(c); + if (!Proto) continue; // missing character const character::database*const* ConfigData = Proto->GetConfigData(); int ConfigSize = Proto->GetConfigSize(); for (int c2 = 0; c2 < ConfigSize; ++c2) { @@ -479,13 +488,13 @@ void protosystem::CreateEveryNormalEnemy (charactervector& EnemyVector) { void protosystem::Initialize () { typedef item::prototype prototype; typedef item::database database; - int c; - for (c = 1; c < protocontainer::GetSize(); ++c) { + protocontainer::Cleanup(); + + for (int c = 1; c < protocontainer::GetSize(); ++c) { const prototype *Proto = protocontainer::GetProtoData()[c]; - if (!Proto->GetConfigData()) { - ABORT("Seems that database is missing <%s>!", Proto->GetClassID()); - } + if (!Proto) continue; // missing something + if (!Proto->GetConfigData()) ABORT("Seems that database is missing <%s>!", Proto->GetClassID()); ItemConfigDataSize += Proto->GetConfigSize(); if (Proto->GetConfigData()[0]->IsAbstract) --ItemConfigDataSize; } @@ -493,8 +502,9 @@ void protosystem::Initialize () { ItemConfigData = new database*[ItemConfigDataSize]; int Index = 0; - for (c = 1; c < protocontainer::GetSize(); ++c) { + for (int c = 1; c < protocontainer::GetSize(); ++c) { const prototype* Proto = protocontainer::GetProtoData()[c]; + if (!Proto) continue; // missing something const database*const* ProtoConfigData = Proto->GetConfigData(); const database* MainDataBase = *ProtoConfigData; @@ -529,8 +539,8 @@ void protosystem::Initialize () { delete [] DataBaseBuffer; - for (c = 0; c < ItemConfigDataSize; ++c) { - database* DataBase = ItemConfigData[c]; + for (int c = 0; c < ItemConfigDataSize; ++c) { + database *DataBase = ItemConfigData[c]; TotalItemPossibility += DataBase->Possibility; DataBase->PartialPossibilitySum = TotalItemPossibility; } @@ -540,6 +550,7 @@ void protosystem::Initialize () { void protosystem::InitCharacterDataBaseFlags () { for (int c1 = 1; c1 < protocontainer::GetSize(); ++c1) { const character::prototype* Proto = protocontainer::GetProto(c1); + if (!Proto) continue; // missing character character::database** ConfigData = Proto->ConfigData; int ConfigSize = Proto->GetConfigSize(); for (int c2 = 0; c2 < ConfigSize; ++c2) { @@ -552,6 +563,7 @@ void protosystem::InitCharacterDataBaseFlags () { void protosystem::SaveCharacterDataBaseFlags (outputfile &SaveFile) { for (int c1 = 1; c1 < protocontainer::GetSize(); ++c1) { const character::prototype* Proto = protocontainer::GetProto(c1); + if (!Proto) continue; // missing character const character::database*const* ConfigData = Proto->ConfigData; int ConfigSize = Proto->GetConfigSize(); for (int c2 = 0; c2 < ConfigSize; ++c2) SaveFile << ConfigData[c2]->Flags; @@ -562,6 +574,7 @@ void protosystem::SaveCharacterDataBaseFlags (outputfile &SaveFile) { void protosystem::LoadCharacterDataBaseFlags (inputfile &SaveFile) { for (int c1 = 1; c1 < protocontainer::GetSize(); ++c1) { const character::prototype* Proto = protocontainer::GetProto(c1); + if (!Proto) continue; // missing character character::database** ConfigData = Proto->ConfigData; int ConfigSize = Proto->GetConfigSize(); for (int c2 = 0; c2 < ConfigSize; ++c2) SaveFile >> ConfigData[c2]->Flags; @@ -572,6 +585,7 @@ void protosystem::LoadCharacterDataBaseFlags (inputfile &SaveFile) { void protosystem::CreateEverySeenCharacter (charactervector &Character) { for (int c1 = 1; c1 < protocontainer::GetSize(); ++c1) { const character::prototype* Proto = protocontainer::GetProto(c1); + if (!Proto) continue; // missing character const character::database*const* ConfigData = Proto->GetConfigData(); int ConfigSize = Proto->GetConfigSize(); for (int c2 = 0; c2 < ConfigSize; ++c2) { @@ -588,6 +602,7 @@ void protosystem::CreateEverySeenCharacter (charactervector &Character) { void protosystem::CreateEveryMaterial (std::vector &Material, const god *God, ccharacter *Char) { for (int c1 = 1; c1 < protocontainer::GetSize(); ++c1) { const material::prototype* Proto = protocontainer::GetProto(c1); + if (!Proto) continue; // missing material const material::database*const* ConfigData = Proto->GetConfigData(); int ConfigSize = Proto->GetConfigSize(); for (int c2 = 1; c2 < ConfigSize; ++c2) { diff --git a/src/game/proto.h b/src/game/proto.h index b7a0fc7..c357edf 100644 --- a/src/game/proto.h +++ b/src/game/proto.h @@ -24,6 +24,7 @@ #include "game.h" +// ////////////////////////////////////////////////////////////////////////// // class character; class item; class material; @@ -34,6 +35,7 @@ template class databasecreator; struct itemdatabase; +// ////////////////////////////////////////////////////////////////////////// // typedef std::map valuemap; typedef std::vector itemvector; typedef std::vector itemvectorvector; @@ -41,28 +43,53 @@ typedef std::vector charactervector; typedef std::vector materialvector; +// ////////////////////////////////////////////////////////////////////////// // template class protocontainer { - public: +public: friend class protosystem; friend class databasecreator; + +public: typedef typename type::prototype prototype; - static int Add(prototype*); - static const prototype* GetProto(int I) { return GetProtoData()[I]; } - static int SearchCodeName(cfestring&); - static cchar* GetMainClassID() { return GetProtoData()[1]->GetClassID(); } - static int GetSize() { return GetSizeRef(); } - private: - static prototype**& GetProtoData(); - static valuemap& GetCodeNameMap(); - static int& GetSizeRef(); + +public: + static int Add (prototype *); + static const prototype *GetProto (int I) { return GetProtoData()[I]; } + static int SearchCodeName (cfestring &); + static cchar *GetMainClassID () { return GetProtoData()[1]->GetClassID(); } + static int GetSize () { return GetSizeRef(); } + + static void Cleanup (); + +private: + static int &GetSizeRef (); + static prototype**& GetProtoData (); + static valuemap& GetCodeNameMap (); }; -template inline int protocontainer::Add (prototype *Proto) { +template inline void protocontainer::Cleanup () { + // nullify undefined prototypes + for (int idx = 1; idx < GetSize(); ++idx) { + auto proto = GetProtoData()[idx]; + if (!proto) continue; + if (!proto->GetConfigData()) { + // this entity has no script prototype... + //ABORT("Seems that database is missing <%s>!", proto->GetClassID()); + fprintf(stderr, "Removing undefined entity <%s>..\n", proto->GetClassID()); + GetProtoData()[idx] = nullptr; + auto it = GetCodeNameMap().find(proto->GetClassID()); + if (it != GetCodeNameMap().end()) GetCodeNameMap().erase(it); + } + } +} + + +template int protocontainer::Add (prototype *proto) { if (!GetSize()) (GetProtoData() = new prototype*[1024])[GetSizeRef()++] = 0; int Index = GetSizeRef()++; - GetProtoData()[Index] = Proto; - std::pair Pair(Proto->GetClassID(), Index); + GetProtoData()[Index] = proto; + std::pair Pair(proto->GetClassID(), Index); GetCodeNameMap().insert(Pair); return Index; } @@ -74,6 +101,7 @@ template inline int protocontainer::SearchCodeName (cfestring } +// ////////////////////////////////////////////////////////////////////////// // class protosystem { public: static character* BalancedCreateMonster(level * = 0); @@ -113,7 +141,7 @@ template inline outputfile &operator << (outputfile &SaveFile, cons template inline inputfile &operator >> (inputfile &SaveFile, type *&Class) { uShort Type = 0; SaveFile >> Type; - Class = Type ? protocontainer::GetProto(Type)->SpawnAndLoad(SaveFile) : 0; + Class = (Type ? protocontainer::GetProto(Type)->SpawnAndLoad(SaveFile) : 0); return SaveFile; } diff --git a/src/game/script.cpp b/src/game/script.cpp index f1e8242..e9e590b 100644 --- a/src/game/script.cpp +++ b/src/game/script.cpp @@ -382,6 +382,7 @@ void basecontentscript::Load (inputfile &SaveFile) { template type *contentscripttemplate::BasicInstantiate (int SpecialFlags) const { type *Instance = 0; const typename type::prototype *Proto = protocontainer::GetProto(ContentType); + if (!Proto) ABORT("BasicInstantiate error for type '%s'!", getTypeName().c_str()); const typename type::database *const *ConfigData = Proto->GetConfigData(); const materialscript *MainMaterial = GetMainMaterial(); const materialscript *SecondaryMaterial = GetSecondaryMaterial(); diff --git a/src/game/worldmap.cpp b/src/game/worldmap.cpp index 000fe70..ca233d0 100644 --- a/src/game/worldmap.cpp +++ b/src/game/worldmap.cpp @@ -641,7 +641,9 @@ void worldmap::SmoothClimate () { game::BusyAnimation(); for (int x = 0; x < XSize; ++x) { for (int y = 0; y < YSize; ++y) { - Map[x][y]->ChangeGWTerrain(protocontainer::GetProto(TypeBuffer[x][y])->Spawn()); + auto terraProto = protocontainer::GetProto(TypeBuffer[x][y]); + if (!terraProto) ABORT("Oops! No gwterrain prototype for type #%d!\n", TypeBuffer[x][y]); + Map[x][y]->ChangeGWTerrain(terraProto->Spawn()); } } } -- 2.11.4.GIT