1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

- fixed #1643 -> hero placeholder handling

- fixed bug when loading victory/loss conditions of the 3rd scenario in the first ROE campaign
- fixed bug when loading artifacts to hero of the 3rd scenario in the first ROE campaign (due to corrupt H3M map)
- implemented function object to quickly find a object by it's sub ID in a list
- added netbackbase.h to header list in CMake
- removed false message which said that the server loaded the map successfully
This commit is contained in:
beegee1 2014-01-30 18:56:31 +00:00
parent 27be6a8f13
commit d4fd361d4b
9 changed files with 177 additions and 72 deletions

View File

@ -326,10 +326,7 @@ void CClient::newGame( CConnection *con, StartInfo *si )
c << ui8(2) << ui8(1); //new game; one client c << ui8(2) << ui8(1); //new game; one client
c << *si; c << *si;
c >> pom8; c >> pom8;
if(pom8) if(pom8) throw std::runtime_error("Server cannot open the map!");
throw std::runtime_error("Server cannot open the map!");
else
logNetwork->infoStream() << "Server opened map properly.";
} }
c >> si; c >> si;

View File

@ -432,6 +432,23 @@ CGHeroInstance * CGameState::HeroesPool::pickHeroFor(bool native, PlayerColor pl
return ret; return ret;
} }
void CGameState::CrossoverHeroesList::addHeroToBothLists(CGHeroInstance * hero)
{
heroesFromPreviousScenario.push_back(hero);
heroesFromAnyPreviousScenarios.push_back(hero);
}
void CGameState::CrossoverHeroesList::removeHeroFromBothLists(CGHeroInstance * hero)
{
heroesFromPreviousScenario -= hero;
heroesFromAnyPreviousScenarios -= hero;
}
CGameState::CampaignHeroReplacement::CampaignHeroReplacement(CGHeroInstance * hero, ObjectInstanceID heroPlaceholderId) : hero(hero), heroPlaceholderId(heroPlaceholderId)
{
}
int CGameState::pickNextHeroType(PlayerColor owner) const int CGameState::pickNextHeroType(PlayerColor owner) const
{ {
const PlayerSettings &ps = scenarioOps->getIthPlayersSettings(owner); const PlayerSettings &ps = scenarioOps->getIthPlayersSettings(owner);
@ -1104,15 +1121,15 @@ void CGameState::placeCampaignHeroes()
} }
// replace heroes placeholders // replace heroes placeholders
auto sourceCrossoverHeroes = getCrossoverHeroesFromPreviousScenario(); auto crossoverHeroes = getCrossoverHeroesFromPreviousScenarios();
if(!sourceCrossoverHeroes.empty()) if(!crossoverHeroes.heroesFromAnyPreviousScenarios.empty())
{ {
logGlobal->debugStream() << "\tPrepare crossover heroes";
auto crossoverHeroes = prepareCrossoverHeroes(sourceCrossoverHeroes, scenarioOps->campState->getCurrentScenario().travelOptions);
logGlobal->debugStream() << "\tGenerate list of hero placeholders"; logGlobal->debugStream() << "\tGenerate list of hero placeholders";
const auto campaignHeroReplacements = generateCampaignHeroesToReplace(crossoverHeroes); auto campaignHeroReplacements = generateCampaignHeroesToReplace(crossoverHeroes);
logGlobal->debugStream() << "\tPrepare crossover heroes";
prepareCrossoverHeroes(campaignHeroReplacements, scenarioOps->campState->getCurrentScenario().travelOptions);
// remove same heroes on the map which will be added through crossover heroes // remove same heroes on the map which will be added through crossover heroes
// INFO: we will remove heroes because later it may be possible that the API doesn't allow having heroes // INFO: we will remove heroes because later it may be possible that the API doesn't allow having heroes
@ -1121,7 +1138,7 @@ void CGameState::placeCampaignHeroes()
for(auto & campaignHeroReplacement : campaignHeroReplacements) for(auto & campaignHeroReplacement : campaignHeroReplacements)
{ {
auto hero = getUsedHero(HeroTypeID(campaignHeroReplacement.first->subID)); auto hero = getUsedHero(HeroTypeID(campaignHeroReplacement.hero->subID));
if(hero) if(hero)
{ {
removedHeroes.push_back(hero); removedHeroes.push_back(hero);
@ -1176,30 +1193,58 @@ void CGameState::placeStartingHero(PlayerColor playerColor, HeroTypeID heroTypeI
map->getEditManager()->insertObject(hero, townPos); map->getEditManager()->insertObject(hero, townPos);
} }
std::vector<CGHeroInstance *> CGameState::getCrossoverHeroesFromPreviousScenario() const CGameState::CrossoverHeroesList CGameState::getCrossoverHeroesFromPreviousScenarios() const
{ {
std::vector<CGHeroInstance *> crossoverHeroes; CrossoverHeroesList crossoverHeroes;
auto campaignState = scenarioOps->campState; auto campaignState = scenarioOps->campState;
auto bonus = campaignState->getBonusForCurrentMap(); auto bonus = campaignState->getBonusForCurrentMap();
if (bonus->type == CScenarioTravel::STravelBonus::HEROES_FROM_PREVIOUS_SCENARIO) if (bonus->type == CScenarioTravel::STravelBonus::HEROES_FROM_PREVIOUS_SCENARIO)
{ {
crossoverHeroes = campaignState->camp->scenarios[bonus->info2].crossoverHeroes; crossoverHeroes.heroesFromAnyPreviousScenarios = crossoverHeroes.heroesFromPreviousScenario = campaignState->camp->scenarios[bonus->info2].crossoverHeroes;
} }
else else
{ {
if(!campaignState->mapsConquered.empty()) if(!campaignState->mapsConquered.empty())
{ {
crossoverHeroes = campaignState->camp->scenarios[campaignState->mapsConquered.back()].crossoverHeroes; crossoverHeroes.heroesFromPreviousScenario = campaignState->camp->scenarios[campaignState->mapsConquered.back()].crossoverHeroes;
for(auto mapNr : campaignState->mapsConquered)
{
// create a list of deleted heroes
auto & scenario = campaignState->camp->scenarios[mapNr];
auto lostCrossoverHeroes = scenario.getLostCrossoverHeroes();
// remove heroes which didn't reached the end of the scenario, but were available at the start
for(auto hero : lostCrossoverHeroes)
{
range::remove_if(crossoverHeroes.heroesFromAnyPreviousScenarios, CGObjectInstanceBySubIdFinder(hero));
}
// now add heroes which completed the scenario
for(auto hero : scenario.crossoverHeroes)
{
// add new heroes and replace old heroes with newer ones
range::remove_if(crossoverHeroes.heroesFromAnyPreviousScenarios, CGObjectInstanceBySubIdFinder(hero));
crossoverHeroes.heroesFromAnyPreviousScenarios.push_back(hero);
}
}
} }
} }
return std::move(crossoverHeroes); return std::move(crossoverHeroes);
} }
std::vector<CGHeroInstance *> CGameState::prepareCrossoverHeroes(const std::vector<CGHeroInstance *> & sourceCrossoverHeroes, const CScenarioTravel & travelOptions) void CGameState::prepareCrossoverHeroes(std::vector<CGameState::CampaignHeroReplacement> & campaignHeroReplacements, const CScenarioTravel & travelOptions) const
{ {
auto crossoverHeroes = sourceCrossoverHeroes; //TODO deep copy hero instances //TODO deep copy hero instances
// create heroes list for convenience iterating
std::vector<CGHeroInstance *> crossoverHeroes;
for(auto & campaignHeroReplacement : campaignHeroReplacements)
{
crossoverHeroes.push_back(campaignHeroReplacement.hero);
}
if(!(travelOptions.whatHeroKeeps & 1)) if(!(travelOptions.whatHeroKeeps & 1))
{ {
@ -1280,8 +1325,6 @@ std::vector<CGHeroInstance *> CGameState::prepareCrossoverHeroes(const std::vect
return !(travelOptions.monstersKeptByHero[crid / 8] & (1 << (crid % 8)) ); return !(travelOptions.monstersKeptByHero[crid / 8] & (1 << (crid % 8)) );
}); });
} }
return std::move(crossoverHeroes);
} }
void CGameState::placeStartingHeroes() void CGameState::placeStartingHeroes()
@ -2696,9 +2739,9 @@ std::set<HeroTypeID> CGameState::getUnusedAllowedHeroes(bool alsoIncludeNotAllow
return ret; return ret;
} }
std::vector<std::pair<CGHeroInstance*, ObjectInstanceID> > CGameState::generateCampaignHeroesToReplace(std::vector<CGHeroInstance *> & crossoverHeroes) std::vector<CGameState::CampaignHeroReplacement> CGameState::generateCampaignHeroesToReplace(CrossoverHeroesList & crossoverHeroes)
{ {
std::vector<std::pair<CGHeroInstance*, ObjectInstanceID> > campaignHeroReplacements; std::vector<CampaignHeroReplacement> campaignHeroReplacements;
auto removeHeroPlaceholder = [this](CGHeroPlaceholder * heroPlaceholder) auto removeHeroPlaceholder = [this](CGHeroPlaceholder * heroPlaceholder)
{ {
@ -2708,56 +2751,50 @@ std::vector<std::pair<CGHeroInstance*, ObjectInstanceID> > CGameState::generateC
}; };
//selecting heroes by type //selecting heroes by type
for(int g = 0; g < map->objects.size(); ++g) for(auto obj : map->objects)
{ {
CGObjectInstance * obj = map->objects[g]; if(obj && obj->ID == Obj::HERO_PLACEHOLDER)
if (obj && obj->ID == Obj::HERO_PLACEHOLDER)
{ {
CGHeroPlaceholder * hp = static_cast<CGHeroPlaceholder*>(obj); auto heroPlaceholder = dynamic_cast<CGHeroPlaceholder *>(obj.get());
if(heroPlaceholder->subID != 0xFF) //select by type
const ObjectInstanceID gid = ObjectInstanceID(g);
if(hp->subID != 0xFF) //select by type
{ {
bool found = false; auto it = range::find_if(crossoverHeroes.heroesFromAnyPreviousScenarios, [heroPlaceholder](CGHeroInstance * hero)
for(auto ghi : crossoverHeroes)
{ {
if (ghi->subID == hp->subID) return hero->subID == heroPlaceholder->subID;
{ });
found = true; if(it == crossoverHeroes.heroesFromAnyPreviousScenarios.end())
campaignHeroReplacements.push_back(std::make_pair(ghi, gid)); {
crossoverHeroes -= ghi; removeHeroPlaceholder(heroPlaceholder);
break;
}
} }
if(!found) else
{ {
removeHeroPlaceholder(hp); campaignHeroReplacements.push_back(CampaignHeroReplacement(*it, obj->id));
crossoverHeroes.removeHeroFromBothLists(*it);
} }
} }
} }
} }
//selecting heroes by power //selecting heroes by power
std::sort(crossoverHeroes.begin(), crossoverHeroes.end(), [](const CGHeroInstance * a, const CGHeroInstance * b) range::sort(crossoverHeroes.heroesFromPreviousScenario, [](const CGHeroInstance * a, const CGHeroInstance * b)
{ {
return a->getHeroStrength() > b->getHeroStrength(); return a->getHeroStrength() > b->getHeroStrength();
}); //sort, descending strength }); //sort, descending strength
// sort hero placeholders descending power // sort hero placeholders descending power
std::vector<CGHeroPlaceholder *> heroPlaceholders; std::vector<CGHeroPlaceholder *> heroPlaceholders;
for(int g = 0; g < map->objects.size(); ++g) for(auto obj : map->objects)
{ {
CGObjectInstance * obj = map->objects[g];
if(obj && obj->ID == Obj::HERO_PLACEHOLDER) if(obj && obj->ID == Obj::HERO_PLACEHOLDER)
{ {
CGHeroPlaceholder * hp = dynamic_cast<CGHeroPlaceholder*>(obj); auto heroPlaceholder = dynamic_cast<CGHeroPlaceholder *>(obj.get());
if(hp->subID == 0xFF) //select by power if(heroPlaceholder->subID == 0xFF) //select by power
{ {
heroPlaceholders.push_back(hp); heroPlaceholders.push_back(heroPlaceholder);
} }
} }
} }
std::sort(heroPlaceholders.begin(), heroPlaceholders.end(), [](const CGHeroPlaceholder * a, const CGHeroPlaceholder * b) range::sort(heroPlaceholders, [](const CGHeroPlaceholder * a, const CGHeroPlaceholder * b)
{ {
return a->power > b->power; return a->power > b->power;
}); });
@ -2765,9 +2802,9 @@ std::vector<std::pair<CGHeroInstance*, ObjectInstanceID> > CGameState::generateC
for(int i = 0; i < heroPlaceholders.size(); ++i) for(int i = 0; i < heroPlaceholders.size(); ++i)
{ {
auto heroPlaceholder = heroPlaceholders[i]; auto heroPlaceholder = heroPlaceholders[i];
if(crossoverHeroes.size() > i) if(crossoverHeroes.heroesFromPreviousScenario.size() > i)
{ {
campaignHeroReplacements.push_back(std::make_pair(crossoverHeroes[i], heroPlaceholder->id)); campaignHeroReplacements.push_back(CampaignHeroReplacement(crossoverHeroes.heroesFromPreviousScenario[i], heroPlaceholder->id));
} }
else else
{ {
@ -2778,16 +2815,16 @@ std::vector<std::pair<CGHeroInstance*, ObjectInstanceID> > CGameState::generateC
return campaignHeroReplacements; return campaignHeroReplacements;
} }
void CGameState::replaceHeroesPlaceholders(const std::vector<std::pair<CGHeroInstance*, ObjectInstanceID> > &campHeroReplacements) void CGameState::replaceHeroesPlaceholders(const std::vector<CGameState::CampaignHeroReplacement> & campaignHeroReplacements)
{ {
for(auto obj : campHeroReplacements) for(auto campaignHeroReplacement : campaignHeroReplacements)
{ {
CGHeroPlaceholder *placeholder = dynamic_cast<CGHeroPlaceholder*>(getObjInstance(obj.second)); auto heroPlaceholder = dynamic_cast<CGHeroPlaceholder*>(getObjInstance(campaignHeroReplacement.heroPlaceholderId));
CGHeroInstance *heroToPlace = obj.first; CGHeroInstance *heroToPlace = campaignHeroReplacement.hero;
heroToPlace->id = obj.second; heroToPlace->id = campaignHeroReplacement.heroPlaceholderId;
heroToPlace->tempOwner = placeholder->tempOwner; heroToPlace->tempOwner = heroPlaceholder->tempOwner;
heroToPlace->pos = placeholder->pos; heroToPlace->pos = heroPlaceholder->pos;
heroToPlace->type = VLC->heroh->heroes[heroToPlace->subID]; heroToPlace->type = VLC->heroh->heroes[heroToPlace->subID];
for(auto &&i : heroToPlace->stacks) for(auto &&i : heroToPlace->stacks)
@ -2808,6 +2845,8 @@ void CGameState::replaceHeroesPlaceholders(const std::vector<std::pair<CGHeroIns
map->heroesOnMap.push_back(heroToPlace); map->heroesOnMap.push_back(heroToPlace);
map->objects[heroToPlace->id.getNum()] = heroToPlace; map->objects[heroToPlace->id.getNum()] = heroToPlace;
map->addBlockVisTiles(heroToPlace); map->addBlockVisTiles(heroToPlace);
scenarioOps->campState->getCurrentScenario().placedCrossoverHeroes.push_back(heroToPlace);
} }
} }

View File

@ -460,6 +460,20 @@ public:
} }
private: private:
struct CrossoverHeroesList
{
std::vector<CGHeroInstance *> heroesFromPreviousScenario, heroesFromAnyPreviousScenarios;
void addHeroToBothLists(CGHeroInstance * hero);
void removeHeroFromBothLists(CGHeroInstance * hero);
};
struct CampaignHeroReplacement
{
CampaignHeroReplacement(CGHeroInstance * hero, ObjectInstanceID heroPlaceholderId);
CGHeroInstance * hero;
ObjectInstanceID heroPlaceholderId;
};
// ----- initialization ----- // ----- initialization -----
void initNewGame(); void initNewGame();
@ -472,15 +486,15 @@ private:
void randomizeObject(CGObjectInstance *cur); void randomizeObject(CGObjectInstance *cur);
void initPlayerStates(); void initPlayerStates();
void placeCampaignHeroes(); void placeCampaignHeroes();
std::vector<CGHeroInstance *> getCrossoverHeroesFromPreviousScenario() const; CrossoverHeroesList getCrossoverHeroesFromPreviousScenarios() const;
/// gets prepared and copied hero instances with crossover heroes from prev. scenario and travel options from current scenario
std::vector<CGHeroInstance *> prepareCrossoverHeroes(const std::vector<CGHeroInstance *> & sourceCrossoverHeroes, const CScenarioTravel & travelOptions);
/// returns heroes and placeholders in where heroes will be put /// returns heroes and placeholders in where heroes will be put
std::vector<std::pair<CGHeroInstance*, ObjectInstanceID> > generateCampaignHeroesToReplace(std::vector<CGHeroInstance *> & crossoverHeroes); std::vector<CampaignHeroReplacement> generateCampaignHeroesToReplace(CrossoverHeroesList & crossoverHeroes);
void replaceHeroesPlaceholders(const std::vector<std::pair<CGHeroInstance*, ObjectInstanceID> > &campHeroReplacements); /// gets prepared and copied hero instances with crossover heroes from prev. scenario and travel options from current scenario
void prepareCrossoverHeroes(std::vector<CampaignHeroReplacement> & campaignHeroReplacements, const CScenarioTravel & travelOptions) const;
void replaceHeroesPlaceholders(const std::vector<CampaignHeroReplacement> & campaignHeroReplacements);
void placeStartingHeroes(); void placeStartingHeroes();
void placeStartingHero(PlayerColor playerColor, HeroTypeID heroTypeId, int3 townPos); void placeStartingHero(PlayerColor playerColor, HeroTypeID heroTypeId, int3 townPos);
void initStartingResources(); void initStartingResources();

View File

@ -94,6 +94,7 @@ set(lib_HEADERS
int3.h int3.h
Interprocess.h Interprocess.h
NetPacks.h NetPacks.h
NetPacksBase.h
RegisterTypes.h RegisterTypes.h
StartInfo.h StartInfo.h
UnlockGuard.h UnlockGuard.h

View File

@ -519,6 +519,16 @@ bool CGObjectInstance::passableFor(PlayerColor color) const
return getPassableness() & 1<<color.getNum(); return getPassableness() & 1<<color.getNum();
} }
CGObjectInstanceBySubIdFinder::CGObjectInstanceBySubIdFinder(CGObjectInstance * obj) : obj(obj)
{
}
bool CGObjectInstanceBySubIdFinder::operator()(CGObjectInstance * obj) const
{
return this->obj->subID == obj->subID;
}
static int lowestSpeed(const CGHeroInstance * chi) static int lowestSpeed(const CGHeroInstance * chi)
{ {
if(!chi->Slots().size()) if(!chi->Slots().size())

View File

@ -228,6 +228,18 @@ protected:
void getNameVis(std::string &hname) const; void getNameVis(std::string &hname) const;
void giveDummyBonus(ObjectInstanceID heroID, ui8 duration = Bonus::ONE_DAY) const; void giveDummyBonus(ObjectInstanceID heroID, ui8 duration = Bonus::ONE_DAY) const;
}; };
/// function object which can be used to find an object with an specific sub ID
class CGObjectInstanceBySubIdFinder
{
public:
CGObjectInstanceBySubIdFinder(CGObjectInstance * obj);
bool operator()(CGObjectInstance * obj) const;
private:
CGObjectInstance * obj;
};
class CGHeroPlaceholder : public CGObjectInstance class CGHeroPlaceholder : public CGObjectInstance
{ {
public: public:

View File

@ -337,6 +337,23 @@ const CGHeroInstance * CCampaignScenario::strongestHero( PlayerColor owner ) con
return i == ownedHeroes.end() ? nullptr : *i; return i == ownedHeroes.end() ? nullptr : *i;
} }
std::vector<CGHeroInstance *> CCampaignScenario::getLostCrossoverHeroes() const
{
std::vector<CGHeroInstance *> lostCrossoverHeroes;
if(conquered)
{
for(auto hero : placedCrossoverHeroes)
{
auto it = range::find_if(crossoverHeroes, CGObjectInstanceBySubIdFinder(hero));
if(it == crossoverHeroes.end())
{
lostCrossoverHeroes.push_back(hero);
}
}
}
return std::move(lostCrossoverHeroes);
}
bool CScenarioTravel::STravelBonus::isBonusForHero() const bool CScenarioTravel::STravelBonus::isBonusForHero() const
{ {
return type == SPELL || type == MONSTER || type == ARTIFACT || type == SPELL_SCROLL || type == PRIMARY_SKILL return type == SPELL || type == MONSTER || type == ARTIFACT || type == SPELL_SCROLL || type == PRIMARY_SKILL
@ -376,6 +393,11 @@ const CCampaignScenario & CCampaignState::getCurrentScenario() const
return camp->scenarios[*currentMap]; return camp->scenarios[*currentMap];
} }
CCampaignScenario & CCampaignState::getCurrentScenario()
{
return camp->scenarios[*currentMap];
}
ui8 CCampaignState::currentBonusID() const ui8 CCampaignState::currentBonusID() const
{ {
return chosenCampaignBonuses.at(*currentMap); return chosenCampaignBonuses.at(*currentMap);

View File

@ -109,15 +109,17 @@ public:
CScenarioTravel travelOptions; CScenarioTravel travelOptions;
std::vector<CGHeroInstance *> crossoverHeroes; // contains all heroes with the same state when the campaign scenario was finished std::vector<CGHeroInstance *> crossoverHeroes; // contains all heroes with the same state when the campaign scenario was finished
std::vector<CGHeroInstance *> placedCrossoverHeroes; // contains all placed crossover heroes defined by hero placeholders when the scenario was started
const CGHeroInstance * strongestHero(PlayerColor owner) const; const CGHeroInstance * strongestHero(PlayerColor owner) const;
void loadPreconditionRegions(ui32 regions); void loadPreconditionRegions(ui32 regions);
bool isNotVoid() const; bool isNotVoid() const;
std::vector<CGHeroInstance *> getLostCrossoverHeroes() const; /// returns a list of crossover heroes which started the scenario, but didn't complete it
template <typename Handler> void serialize(Handler &h, const int formatVersion) template <typename Handler> void serialize(Handler &h, const int formatVersion)
{ {
h & mapName & scenarioName & packedMapSize & preconditionRegions & regionColor & difficulty & conquered & regionText & h & mapName & scenarioName & packedMapSize & preconditionRegions & regionColor & difficulty & conquered & regionText &
prolog & epilog & travelOptions & crossoverHeroes; prolog & epilog & travelOptions & crossoverHeroes & placedCrossoverHeroes;
} }
}; };
@ -151,7 +153,8 @@ public:
//void initNewCampaign(const StartInfo &si); //void initNewCampaign(const StartInfo &si);
void setCurrentMapAsConquered(const std::vector<CGHeroInstance*> & heroes); void setCurrentMapAsConquered(const std::vector<CGHeroInstance*> & heroes);
boost::optional<CScenarioTravel::STravelBonus> getBonusForCurrentMap() const; boost::optional<CScenarioTravel::STravelBonus> getBonusForCurrentMap() const;
const CCampaignScenario &getCurrentScenario() const; const CCampaignScenario & getCurrentScenario() const;
CCampaignScenario & getCurrentScenario();
ui8 currentBonusID() const; ui8 currentBonusID() const;
CCampaignState(); CCampaignState();

View File

@ -9,23 +9,21 @@
*/ */
#include "StdInc.h" #include "StdInc.h"
#include "MapFormatH3M.h"
#include <boost/crc.hpp> #include <boost/crc.hpp>
#include "../CStopWatch.h" #include "MapFormatH3M.h"
#include "../filesystem/Filesystem.h"
#include "CMap.h" #include "CMap.h"
#include "../CStopWatch.h"
#include "../filesystem/Filesystem.h"
#include "../CSpellHandler.h" #include "../CSpellHandler.h"
#include "../CCreatureHandler.h" #include "../CCreatureHandler.h"
#include "../CGeneralTextHandler.h" #include "../CGeneralTextHandler.h"
#include "../CHeroHandler.h" #include "../CHeroHandler.h"
#include "../CObjectHandler.h" #include "../CObjectHandler.h"
#include "../CDefObjInfoHandler.h" #include "../CDefObjInfoHandler.h"
#include "../VCMI_Lib.h" #include "../VCMI_Lib.h"
#include "../NetPacksBase.h"
const bool CMapLoaderH3M::IS_PROFILING_ENABLED = false; const bool CMapLoaderH3M::IS_PROFILING_ENABLED = false;
@ -442,7 +440,6 @@ void CMapLoaderH3M::readVictoryLossConditions()
{ {
EventCondition cond(EventCondition::CONTROL); EventCondition cond(EventCondition::CONTROL);
cond.objectType = Obj::CREATURE_GENERATOR1; // FIXME: generators 2-4? cond.objectType = Obj::CREATURE_GENERATOR1; // FIXME: generators 2-4?
cond.position = readInt3();
specialVictory.effect.toOtherMessage = VLC->generaltexth->allTexts[289]; specialVictory.effect.toOtherMessage = VLC->generaltexth->allTexts[289];
specialVictory.onFulfill = VLC->generaltexth->allTexts[288]; specialVictory.onFulfill = VLC->generaltexth->allTexts[288];
@ -473,7 +470,7 @@ void CMapLoaderH3M::readVictoryLossConditions()
default: default:
assert(0); assert(0);
} }
//bool allowNormalVictory = reader.readBool();
// if condition is human-only turn it into following construction: AllOf(human, condition) // if condition is human-only turn it into following construction: AllOf(human, condition)
if (!appliesToAI) if (!appliesToAI)
{ {
@ -869,7 +866,17 @@ bool CMapLoaderH3M::loadArtifactToSlot(CGHeroInstance * hero, int slot)
slot = ArtifactPosition::SPELLBOOK; slot = ArtifactPosition::SPELLBOOK;
} }
hero->putArtifact(ArtifactPosition(slot), createArtifact(aid)); // this is needed, because some H3M maps (last scenario of ROE map) contain invalid data like misplaced artifacts
auto artifact = createArtifact(aid);
auto artifactPos = ArtifactPosition(slot);
if (artifact->canBePutAt(ArtifactLocation(hero, artifactPos)))
{
hero->putArtifact(artifactPos, artifact);
}
else
{
logGlobal->debugStream() << "Artifact can't be put at the specified location."; //TODO add more debugging information
}
} }
return isArt; return isArt;