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

CGHeroInstance* can be serialized over network even when hero has been defeated. Strongly typed hero type ID introduced.

Should fix #1260.
This commit is contained in:
Michał W. Urbańczyk 2013-05-18 22:30:48 +00:00
parent f95e6c233b
commit be7c2bd07f
19 changed files with 113 additions and 75 deletions

View File

@ -573,7 +573,7 @@ void processCommand(const std::string &message)
if(what == "hs") if(what == "hs")
{ {
BOOST_FOREACH(const CGHeroInstance *h, LOCPLINT->cb->getHeroesInfo()) BOOST_FOREACH(const CGHeroInstance *h, LOCPLINT->cb->getHeroesInfo())
if(h->type->ID == id1) if(h->type->ID.getNum() == id1)
if(const CArtifactInstance *a = h->getArt(ArtifactPosition(id2))) if(const CArtifactInstance *a = h->getArt(ArtifactPosition(id2)))
std::cout << a->nodeName(); std::cout << a->nodeName();
} }

View File

@ -239,6 +239,7 @@ void DisassembledArtifact::applyCl( CClient *cl )
void HeroVisit::applyCl( CClient *cl ) void HeroVisit::applyCl( CClient *cl )
{ {
assert(hero);
INTERFACE_CALL_IF_PRESENT(hero->tempOwner, heroVisit, hero, obj, starting); INTERFACE_CALL_IF_PRESENT(hero->tempOwner, heroVisit, hero, obj, starting);
} }
@ -487,7 +488,7 @@ void SetHeroesInTown::applyCl( CClient *cl )
void HeroRecruited::applyCl( CClient *cl ) void HeroRecruited::applyCl( CClient *cl )
{ {
CGHeroInstance *h = GS(cl)->map->heroes.back(); CGHeroInstance *h = GS(cl)->map->heroesOnMap.back();
if(h->subID != hid) if(h->subID != hid)
{ {
logNetwork->errorStream() << "Something wrong with hero recruited!"; logNetwork->errorStream() << "Something wrong with hero recruited!";

View File

@ -371,11 +371,11 @@ void CMapHandler::init()
offsetX = (mapW - (2*frameW+1)*32)/2; offsetX = (mapW - (2*frameW+1)*32)/2;
offsetY = (mapH - (2*frameH+1)*32)/2; offsetY = (mapH - (2*frameH+1)*32)/2;
for(int i=0;i<map->heroes.size();i++) for(int i=0;i<map->heroesOnMap.size();i++)
{ {
if( !graphics->getDef(map->heroes[i]) ) if( !graphics->getDef(map->heroesOnMap[i]) )
{ {
initHeroDef(map->heroes[i]); initHeroDef(map->heroesOnMap[i]);
} }
} }

View File

@ -678,7 +678,7 @@ void CGameState::randomizeObject(CGObjectInstance *cur)
h->type = VLC->heroh->heroes[ran.second]; h->type = VLC->heroh->heroes[ran.second];
h->portrait = h->type->imageIndex; h->portrait = h->type->imageIndex;
h->randomizeArmy(h->type->heroClass->faction); h->randomizeArmy(h->type->heroClass->faction);
map->heroes.push_back(h); map->heroesOnMap.push_back(h);
return; //TODO: maybe we should do something with definfo? return; //TODO: maybe we should do something with definfo?
} }
else if(ran.first==Obj::TOWN)//special code for town else if(ran.first==Obj::TOWN)//special code for town
@ -1071,7 +1071,7 @@ void CGameState::init(StartInfo * si)
CGHeroInstance * nnn = static_cast<CGHeroInstance*>(createObject(Obj::HERO,h,hpos,it->first)); CGHeroInstance * nnn = static_cast<CGHeroInstance*>(createObject(Obj::HERO,h,hpos,it->first));
nnn->id = ObjectInstanceID(map->objects.size()); nnn->id = ObjectInstanceID(map->objects.size());
nnn->initHero(); nnn->initHero();
map->heroes.push_back(nnn); map->heroesOnMap.push_back(nnn);
map->objects.push_back(nnn); map->objects.push_back(nnn);
map->addBlockVisTiles(nnn); map->addBlockVisTiles(nnn);
} }
@ -1130,7 +1130,7 @@ void CGameState::init(StartInfo * si)
if (!found) if (!found)
{ {
CGHeroInstance * nh = new CGHeroInstance(); CGHeroInstance * nh = new CGHeroInstance();
nh->initHero(hp->subID); nh->initHero(HeroTypeID(hp->subID));
replaceHero(gid, nh); replaceHero(gid, nh);
} }
} }
@ -1236,7 +1236,7 @@ void CGameState::init(StartInfo * si)
heroToPlace->id = obj.second; heroToPlace->id = obj.second;
heroToPlace->tempOwner = placeholder->tempOwner; heroToPlace->tempOwner = placeholder->tempOwner;
heroToPlace->pos = placeholder->pos; heroToPlace->pos = placeholder->pos;
heroToPlace->type = VLC->heroh->heroes[heroToPlace->type->ID]; heroToPlace->type = VLC->heroh->heroes[heroToPlace->type->ID.getNum()]; //TODO is this reasonable? either old type can be still used or it can be deleted?
BOOST_FOREACH(auto &&i, heroToPlace->stacks) BOOST_FOREACH(auto &&i, heroToPlace->stacks)
i.second->type = VLC->creh->creatures[i.second->getCreatureID()]; i.second->type = VLC->creh->creatures[i.second->getCreatureID()];
@ -1253,7 +1253,7 @@ void CGameState::init(StartInfo * si)
BOOST_FOREACH(auto &&i, heroToPlace->artifactsInBackpack) BOOST_FOREACH(auto &&i, heroToPlace->artifactsInBackpack)
fixArtifact(i.artifact); fixArtifact(i.artifact);
map->heroes.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);
@ -1261,49 +1261,57 @@ void CGameState::init(StartInfo * si)
} }
std::set<int> hids; //hero ids to create pool std::set<HeroTypeID> heroesToCreate; //ids of heroes to be created and put into the pool
for(ui32 i=0; i<map->allowedHeroes.size(); i++) //add to hids all allowed heroes for(ui32 i=0; i<map->allowedHeroes.size(); i++) //add to hids all allowed heroes
if(map->allowedHeroes[i]) if(map->allowedHeroes[i])
hids.insert(i); heroesToCreate.insert(HeroTypeID(i));
for (ui32 i=0; i<map->heroes.size();i++) //heroes instances initialization BOOST_FOREACH(auto hero, map->heroesOnMap) //heroes instances initialization
{ {
if (map->heroes[i]->getOwner() == PlayerColor::UNFLAGGABLE) if (hero->getOwner() == PlayerColor::UNFLAGGABLE)
{ {
logGlobal->warnStream() << "Warning - hero with uninitialized owner!"; logGlobal->warnStream() << "Warning - hero with uninitialized owner!";
continue; continue;
} }
CGHeroInstance * vhi = map->heroes[i];
vhi->initHero(); hero->initHero();
players.find(vhi->getOwner())->second.heroes.push_back(vhi); getPlayer(hero->getOwner())->heroes.push_back(hero);
hids.erase(vhi->subID); heroesToCreate.erase(hero->type->ID);
map->allHeroes[hero->type->ID.getNum()] = hero;
} }
BOOST_FOREACH(auto obj, map->objects) //prisons BOOST_FOREACH(auto obj, map->objects) //prisons
{ {
if(obj && obj->ID == Obj::PRISON) if(obj && obj->ID == Obj::PRISON)
hids.erase(obj->subID); {
heroesToCreate.erase(HeroTypeID(obj->subID));
map->allHeroes[obj->subID] = dynamic_cast<CGHeroInstance*>(obj.get());
}
} }
BOOST_FOREACH(auto ph, map->predefinedHeroes) BOOST_FOREACH(auto ph, map->predefinedHeroes)
{ {
if(!vstd::contains(hids, ph->subID)) if(!vstd::contains(heroesToCreate, HeroTypeID(ph->subID)))
continue; continue;
ph->initHero(); ph->initHero();
hpool.heroesPool[ph->subID] = ph; hpool.heroesPool[ph->subID] = ph;
hpool.pavailable[ph->subID] = 0xff; hpool.pavailable[ph->subID] = 0xff;
hids.erase(ph->subID); heroesToCreate.erase(ph->type->ID);
map->allHeroes[ph->subID] = ph;
} }
BOOST_FOREACH(int hid, hids) //all not used allowed heroes go with default state into the pool BOOST_FOREACH(HeroTypeID htype, heroesToCreate) //all not used allowed heroes go with default state into the pool
{ {
CGHeroInstance * vhi = new CGHeroInstance(); CGHeroInstance * vhi = new CGHeroInstance();
vhi->initHero(hid); vhi->initHero(htype);
hpool.heroesPool[hid] = vhi;
hpool.pavailable[hid] = 0xff; int typeID = htype.getNum();
map->allHeroes[typeID] = vhi;
hpool.heroesPool[typeID] = vhi;
hpool.pavailable[typeID] = 0xff;
} }
for(ui32 i=0; i<map->disposedHeroes.size(); i++) for(ui32 i=0; i<map->disposedHeroes.size(); i++)
@ -1684,7 +1692,7 @@ void CGameState::initDuel()
BOOST_FOREACH(TSecSKill secSkill, ss.heroSecSkills) BOOST_FOREACH(TSecSKill secSkill, ss.heroSecSkills)
h->setSecSkillLevel(SecondarySkill(secSkill.first), secSkill.second, 1); h->setSecSkillLevel(SecondarySkill(secSkill.first), secSkill.second, 1);
h->initHero(h->subID); h->initHero(HeroTypeID(h->subID));
obj->initObj(); obj->initObj();
} }
else else

View File

@ -367,7 +367,6 @@ public:
bmap<PlayerColor, PlayerState> players; bmap<PlayerColor, PlayerState> players;
bmap<TeamID, TeamState> teams; bmap<TeamID, TeamState> teams;
CBonusSystemNode globalEffects; CBonusSystemNode globalEffects;
bmap<const CGHeroInstance*, const CGObjectInstance*> ongoingVisits;
struct DLL_LINKAGE HeroesPool struct DLL_LINKAGE HeroesPool
{ {

View File

@ -469,24 +469,24 @@ std::vector<JsonNode> CHeroHandler::loadLegacyData(size_t dataSize)
void CHeroHandler::loadObject(std::string scope, std::string name, const JsonNode & data) void CHeroHandler::loadObject(std::string scope, std::string name, const JsonNode & data)
{ {
auto object = loadFromJson(data); auto object = loadFromJson(data);
object->ID = heroes.size(); object->ID = HeroTypeID(heroes.size());
object->imageIndex = heroes.size() + 8; // 2 special frames + some extra portraits object->imageIndex = heroes.size() + 8; // 2 special frames + some extra portraits
heroes.push_back(object); heroes.push_back(object);
VLC->modh->identifiers.registerObject(scope, "hero", name, object->ID); VLC->modh->identifiers.registerObject(scope, "hero", name, object->ID.getNum());
} }
void CHeroHandler::loadObject(std::string scope, std::string name, const JsonNode & data, size_t index) void CHeroHandler::loadObject(std::string scope, std::string name, const JsonNode & data, size_t index)
{ {
auto object = loadFromJson(data); auto object = loadFromJson(data);
object->ID = index; object->ID = HeroTypeID(index);
object->imageIndex = index; object->imageIndex = index;
assert(heroes[index] == nullptr); // ensure that this id was not loaded before assert(heroes[index] == nullptr); // ensure that this id was not loaded before
heroes[index] = object; heroes[index] = object;
VLC->modh->identifiers.registerObject(scope, "hero", name, object->ID); VLC->modh->identifiers.registerObject(scope, "hero", name, object->ID.getNum());
} }
ui32 CHeroHandler::level (ui64 experience) const ui32 CHeroHandler::level (ui64 experience) const

View File

@ -59,7 +59,7 @@ public:
} }
}; };
si32 ID; HeroTypeID ID;
si32 imageIndex; si32 imageIndex;
std::vector<InitialArmyStack> initialArmy; std::vector<InitialArmyStack> initialArmy;

View File

@ -757,9 +757,9 @@ CGHeroInstance::CGHeroInstance()
secSkills.push_back(std::make_pair(SecondarySkill::DEFAULT, -1)); secSkills.push_back(std::make_pair(SecondarySkill::DEFAULT, -1));
} }
void CGHeroInstance::initHero(int SUBID) void CGHeroInstance::initHero(HeroTypeID SUBID)
{ {
subID = SUBID; subID = SUBID.getNum();
initHero(); initHero();
} }
@ -4355,7 +4355,7 @@ bool CQuest::checkQuest (const CGHeroInstance * h) const
} }
return true; return true;
case MISSION_HERO: case MISSION_HERO:
if (m13489val == h->type->ID) if (m13489val == h->type->ID.getNum())
return true; return true;
return false; return false;
case MISSION_PLAYER: case MISSION_PLAYER:

View File

@ -405,7 +405,7 @@ public:
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
void initHero(); void initHero();
void initHero(int SUBID); void initHero(HeroTypeID SUBID);
void putArtifact(ArtifactPosition pos, CArtifactInstance *art); void putArtifact(ArtifactPosition pos, CArtifactInstance *art);
void putInBackpack(CArtifactInstance *art); void putInBackpack(CArtifactInstance *art);

View File

@ -468,12 +468,21 @@ CSerializer::CSerializer()
void CSerializer::addStdVecItems(CGameState *gs, LibClasses *lib) void CSerializer::addStdVecItems(CGameState *gs, LibClasses *lib)
{ {
registerVectoredType(&gs->map->objects, &CGObjectInstance::id); registerVectoredType<CGObjectInstance, ObjectInstanceID>(&gs->map->objects,
registerVectoredType(&lib->heroh->heroes, &CHero::ID); [](const CGObjectInstance &obj){ return obj.id; });
registerVectoredType(&lib->creh->creatures, &CCreature::idNumber); registerVectoredType<CHero, HeroTypeID>(&lib->heroh->heroes,
registerVectoredType(&lib->arth->artifacts, &CArtifact::id); [](const CHero &h){ return h.ID; });
registerVectoredType(&gs->map->artInstances, &CArtifactInstance::id); registerVectoredType<CGHeroInstance, HeroTypeID>(&gs->map->allHeroes,
registerVectoredType(&gs->map->quests, &CQuest::qid); [](const CGHeroInstance &h){ return h.type->ID; });
registerVectoredType<CCreature, CreatureID>(&lib->creh->creatures,
[](const CCreature &cre){ return cre.idNumber; });
registerVectoredType<CArtifact, ArtifactID>(&lib->arth->artifacts,
[](const CArtifact &art){ return art.id; });
registerVectoredType<CArtifactInstance, ArtifactInstanceID>(&gs->map->artInstances,
[](const CArtifactInstance &artInst){ return artInst.id; });
registerVectoredType<CQuest, si32>(&gs->map->quests,
[](const CQuest &q){ return q.qid; });
smartVectorMembersSerialization = true; smartVectorMembersSerialization = true;
} }

View File

@ -297,14 +297,15 @@ struct SerializationLevel
static const int value = SerializationLevel::type::value; static const int value = SerializationLevel::type::value;
}; };
template <typename T, typename U> template <typename ObjType, typename IdType>
struct VectorisedObjectInfo struct VectorisedObjectInfo
{ {
const std::vector<ConstTransitivePtr<T> > *vector; //pointer to the appropriate vector const std::vector<ConstTransitivePtr<ObjType> > *vector; //pointer to the appropriate vector
const U T::*idPtr; //pointer to the field representing the position in the vector std::function<IdType(const ObjType &)> idRetriever;
//const IdType ObjType::*idPtr; //pointer to the field representing the position in the vector
VectorisedObjectInfo(const std::vector< ConstTransitivePtr<T> > *Vector, const U T::*IdPtr) VectorisedObjectInfo(const std::vector< ConstTransitivePtr<ObjType> > *Vector, std::function<IdType(const ObjType &)> IdGetter)
:vector(Vector), idPtr(IdPtr) :vector(Vector), idRetriever(IdGetter)
{ {
} }
}; };
@ -337,14 +338,14 @@ public:
virtual void reportState(CLogger * out){}; virtual void reportState(CLogger * out){};
template <typename T, typename U> template <typename T, typename U>
void registerVectoredType(const std::vector<T*> *Vector, const U T::*IdPtr) void registerVectoredType(const std::vector<T*> *Vector, const std::function<U(const T&)> &idRetriever)
{ {
vectors[&typeid(T)] = VectorisedObjectInfo<T, U>(Vector, IdPtr); vectors[&typeid(T)] = VectorisedObjectInfo<T, U>(Vector, idRetriever);
} }
template <typename T, typename U> template <typename T, typename U>
void registerVectoredType(const std::vector<ConstTransitivePtr<T> > *Vector, const U T::*IdPtr) void registerVectoredType(const std::vector<ConstTransitivePtr<T> > *Vector, const std::function<U(const T&)> &idRetriever)
{ {
vectors[&typeid(T)] = VectorisedObjectInfo<T, U>(Vector, IdPtr); vectors[&typeid(T)] = VectorisedObjectInfo<T, U>(Vector, idRetriever);
} }
template <typename T, typename U> template <typename T, typename U>
@ -387,7 +388,7 @@ public:
if(!obj) if(!obj)
return U(-1); return U(-1);
return obj->*oInfo.idPtr; return oInfo.idRetriever(*obj);
} }
void addStdVecItems(CGameState *gs, LibClasses *lib = VLC); void addStdVecItems(CGameState *gs, LibClasses *lib = VLC);
@ -422,11 +423,14 @@ struct VectorisedTypeFor
{ {
typedef typename typedef typename
//if //if
mpl::eval_if<boost::is_same<CGHeroInstance,T>,
mpl::identity<CGHeroInstance>,
//else if
mpl::eval_if<boost::is_base_of<CGObjectInstance,T>, mpl::eval_if<boost::is_base_of<CGObjectInstance,T>,
mpl::identity<CGObjectInstance>, mpl::identity<CGObjectInstance>,
//else //else
mpl::identity<T> mpl::identity<T>
>::type type; > >::type type;
}; };
template <typename U> template <typename U>
struct VectorizedIDType struct VectorizedIDType
@ -439,14 +443,20 @@ struct VectorizedIDType
mpl::eval_if<boost::is_same<CCreature,U>, mpl::eval_if<boost::is_same<CCreature,U>,
mpl::identity<CreatureID>, mpl::identity<CreatureID>,
//else if //else if
mpl::eval_if<boost::is_same<CHero,U>,
mpl::identity<HeroTypeID>,
//else if
mpl::eval_if<boost::is_same<CArtifactInstance,U>, mpl::eval_if<boost::is_same<CArtifactInstance,U>,
mpl::identity<ArtifactInstanceID>, mpl::identity<ArtifactInstanceID>,
//else if //else if
mpl::eval_if<boost::is_same<CGHeroInstance,U>,
mpl::identity<HeroTypeID>,
//else if
mpl::eval_if<boost::is_base_of<CGObjectInstance,U>, mpl::eval_if<boost::is_base_of<CGObjectInstance,U>,
mpl::identity<ObjectInstanceID>, mpl::identity<ObjectInstanceID>,
//else //else
mpl::identity<si32> mpl::identity<si32>
> > > >::type type; > > > > > >::type type;
}; };
template <typename Handler> template <typename Handler>

View File

@ -190,6 +190,12 @@ class ObjectInstanceID : public BaseForID<ObjectInstanceID, si32>
friend class CNonConstInfoCallback; friend class CNonConstInfoCallback;
}; };
class HeroTypeID : public BaseForID<HeroTypeID, si32>
{
INSTID_LIKE_CLASS_COMMON(HeroTypeID, si32)
};
class SlotID : public BaseForID<SlotID, si32> class SlotID : public BaseForID<SlotID, si32>
{ {
INSTID_LIKE_CLASS_COMMON(SlotID, si32) INSTID_LIKE_CLASS_COMMON(SlotID, si32)

View File

@ -767,7 +767,7 @@ std::vector < const CGHeroInstance *> CPlayerSpecificInfoCallback::getHeroesInfo
{ {
//boost::shared_lock<boost::shared_mutex> lock(*gs->mx); //boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
std::vector < const CGHeroInstance *> ret; std::vector < const CGHeroInstance *> ret;
BOOST_FOREACH(auto hero, gs->map->heroes) BOOST_FOREACH(auto hero, gs->map->heroesOnMap)
{ {
if( !player || (hero->tempOwner == *player) || if( !player || (hero->tempOwner == *player) ||
(isVisible(hero->getPosition(false), player) && !onlyOur) ) (isVisible(hero->getPosition(false), player) && !onlyOur) )
@ -946,7 +946,7 @@ const TeamState * CGameInfoCallback::getPlayerTeam( PlayerColor color ) const
const CGHeroInstance* CGameInfoCallback::getHeroWithSubid( int subid ) const const CGHeroInstance* CGameInfoCallback::getHeroWithSubid( int subid ) const
{ {
BOOST_FOREACH(const CGHeroInstance *h, gs->map->heroes) BOOST_FOREACH(const CGHeroInstance *h, gs->map->heroesOnMap)
if(h->subID == subid) if(h->subID == subid)
return h; return h;

View File

@ -308,7 +308,7 @@ DLL_LINKAGE void RemoveObject::applyGs( CGameState *gs )
{ {
CGHeroInstance *h = static_cast<CGHeroInstance*>(obj); CGHeroInstance *h = static_cast<CGHeroInstance*>(obj);
PlayerState *p = gs->getPlayer(h->tempOwner); PlayerState *p = gs->getPlayer(h->tempOwner);
gs->map->heroes -= h; gs->map->heroesOnMap -= h;
p->heroes -= h; p->heroes -= h;
h->detachFrom(h->whereShouldBeAttached(gs)); h->detachFrom(h->whereShouldBeAttached(gs));
h->tempOwner = PlayerColor::NEUTRAL; //no one owns beaten hero h->tempOwner = PlayerColor::NEUTRAL; //no one owns beaten hero
@ -510,7 +510,7 @@ DLL_LINKAGE void HeroRecruited::applyGs( CGameState *gs )
gs->map->objects[h->id.getNum()] = h; gs->map->objects[h->id.getNum()] = h;
h->initHeroDefInfo(); h->initHeroDefInfo();
gs->map->heroes.push_back(h); gs->map->heroesOnMap.push_back(h);
p->heroes.push_back(h); p->heroes.push_back(h);
h->attachTo(p); h->attachTo(p);
h->initObj(); h->initObj();
@ -534,7 +534,7 @@ DLL_LINKAGE void GiveHero::applyGs( CGameState *gs )
h->setOwner(player); h->setOwner(player);
h->movement = h->maxMovePoints(true); h->movement = h->maxMovePoints(true);
h->initHeroDefInfo(); h->initHeroDefInfo();
gs->map->heroes.push_back(h); gs->map->heroesOnMap.push_back(h);
gs->getPlayer(h->getOwner())->heroes.push_back(h); gs->getPlayer(h->getOwner())->heroes.push_back(h);
gs->map->addBlockVisTiles(h); gs->map->addBlockVisTiles(h);
h->inTownGarrison = false; h->inTownGarrison = false;
@ -894,10 +894,6 @@ DLL_LINKAGE void DisassembledArtifact::applyGs( CGameState *gs )
DLL_LINKAGE void HeroVisit::applyGs( CGameState *gs ) DLL_LINKAGE void HeroVisit::applyGs( CGameState *gs )
{ {
if(starting)
gs->ongoingVisits[hero] = obj;
else
gs->ongoingVisits.erase(hero);
} }
DLL_LINKAGE void SetAvailableArtifacts::applyGs( CGameState *gs ) DLL_LINKAGE void SetAvailableArtifacts::applyGs( CGameState *gs )

View File

@ -230,9 +230,9 @@ void CMap::addBlockVisTiles(CGObjectInstance * obj)
CGHeroInstance * CMap::getHero(int heroID) CGHeroInstance * CMap::getHero(int heroID)
{ {
for(ui32 i=0; i<heroes.size();i++) for(ui32 i=0; i<heroesOnMap.size();i++)
if(heroes[i]->subID == heroID) if(heroesOnMap[i]->subID == heroID)
return heroes[i]; return heroesOnMap[i];
return nullptr; return nullptr;
} }

View File

@ -366,11 +366,17 @@ public:
int3 grailPos; int3 grailPos;
int grailRadious; int grailRadious;
//Central lists of items in game. Position of item in the vectors below is their (instance) id.
std::vector< ConstTransitivePtr<CGObjectInstance> > objects; std::vector< ConstTransitivePtr<CGObjectInstance> > objects;
std::vector< ConstTransitivePtr<CGHeroInstance> > heroes;
std::vector< ConstTransitivePtr<CGTownInstance> > towns; std::vector< ConstTransitivePtr<CGTownInstance> > towns;
std::vector< ConstTransitivePtr<CArtifactInstance> > artInstances; std::vector< ConstTransitivePtr<CArtifactInstance> > artInstances;
std::vector< ConstTransitivePtr<CQuest> > quests; std::vector< ConstTransitivePtr<CQuest> > quests;
std::vector< ConstTransitivePtr<CGHeroInstance> > allHeroes; //indexed by [hero_type_id]; on map, disposed, prisons, etc.
//Helper lists
std::vector< ConstTransitivePtr<CGHeroInstance> > heroesOnMap;
/// associative list to identify which hero/creature id belongs to which object id(index for objects) /// associative list to identify which hero/creature id belongs to which object id(index for objects)
bmap<si32, ObjectInstanceID> questIdentifierToId; bmap<si32, ObjectInstanceID> questIdentifierToId;
@ -428,7 +434,7 @@ public:
} }
h & customDefs & objects; h & customDefs & objects;
h & heroes & towns & artInstances; h & heroesOnMap & towns & artInstances;
// static members // static members
h & CGTeleport::objs; h & CGTeleport::objs;

View File

@ -924,7 +924,7 @@ void CInsertObjectOperation::execute()
} }
if(obj->ID == Obj::HERO) if(obj->ID == Obj::HERO)
{ {
map->heroes.push_back(static_cast<CGHeroInstance*>(obj)); map->heroesOnMap.push_back(static_cast<CGHeroInstance*>(obj));
} }
map->addBlockVisTiles(obj); map->addBlockVisTiles(obj);
} }

View File

@ -92,6 +92,8 @@ void CMapLoaderH3M::init()
readHeader(); readHeader();
times.push_back(MapLoadingTime("header", sw.getDiff())); times.push_back(MapLoadingTime("header", sw.getDiff()));
map->allHeroes.resize(map->allowedHeroes.size());
readDisposedHeroes(); readDisposedHeroes();
times.push_back(MapLoadingTime("disposed heroes", sw.getDiff())); times.push_back(MapLoadingTime("disposed heroes", sw.getDiff()));
@ -1469,11 +1471,11 @@ void CMapLoaderH3M::readObjects()
} }
if(nobj->ID == Obj::HERO) if(nobj->ID == Obj::HERO)
{ {
map->heroes.push_back(static_cast<CGHeroInstance*>(nobj)); map->heroesOnMap.push_back(static_cast<CGHeroInstance*>(nobj));
} }
} }
std::sort(map->heroes.begin(), map->heroes.end(), [](const ConstTransitivePtr<CGHeroInstance> & a, const ConstTransitivePtr<CGHeroInstance> & b) std::sort(map->heroesOnMap.begin(), map->heroesOnMap.end(), [](const ConstTransitivePtr<CGHeroInstance> & a, const ConstTransitivePtr<CGHeroInstance> & b)
{ {
return a->subID < b->subID; return a->subID < b->subID;
}); });

View File

@ -4840,6 +4840,7 @@ void CGameHandler::objectVisitEnded(const CObjectVisitQuery &query)
HeroVisit hv; HeroVisit hv;
hv.obj = nullptr; //not necessary, moreover may have been deleted in the meantime hv.obj = nullptr; //not necessary, moreover may have been deleted in the meantime
hv.hero = query.visitingHero; hv.hero = query.visitingHero;
assert(hv.hero);
hv.starting = false; hv.starting = false;
sendAndApply(&hv); sendAndApply(&hv);
} }
@ -4977,7 +4978,7 @@ void CGameHandler::checkLossVictory( PlayerColor player )
if(gs->scenarioOps->campState) if(gs->scenarioOps->campState)
{ {
std::vector<CGHeroInstance *> hes; std::vector<CGHeroInstance *> hes;
BOOST_FOREACH(CGHeroInstance * ghi, gs->map->heroes) BOOST_FOREACH(CGHeroInstance * ghi, gs->map->heroesOnMap)
{ {
if (ghi->tempOwner == player) if (ghi->tempOwner == player)
{ {