|
@@ -346,8 +346,8 @@ void CGameHandler::giveExperience(const CGHeroInstance * hero, TExpType amountTo
|
|
TExpType maxExp = LIBRARY->heroh->reqExp(LIBRARY->heroh->maxSupportedLevel());
|
|
TExpType maxExp = LIBRARY->heroh->reqExp(LIBRARY->heroh->maxSupportedLevel());
|
|
TExpType currExp = hero->exp;
|
|
TExpType currExp = hero->exp;
|
|
|
|
|
|
- if (gs->map->levelLimit != 0)
|
|
|
|
- maxExp = LIBRARY->heroh->reqExp(gs->map->levelLimit);
|
|
|
|
|
|
+ if (gs->getMap().levelLimit != 0)
|
|
|
|
+ maxExp = LIBRARY->heroh->reqExp(gs->getMap().levelLimit);
|
|
|
|
|
|
TExpType canGainExp = 0;
|
|
TExpType canGainExp = 0;
|
|
if (maxExp > currExp)
|
|
if (maxExp > currExp)
|
|
@@ -421,7 +421,7 @@ void CGameHandler::changeSecSkill(const CGHeroInstance * hero, SecondarySkill wh
|
|
|
|
|
|
void CGameHandler::handleClientDisconnection(std::shared_ptr<CConnection> c)
|
|
void CGameHandler::handleClientDisconnection(std::shared_ptr<CConnection> c)
|
|
{
|
|
{
|
|
- if(gameLobby().getState() == EServerState::SHUTDOWN || !gs || !gs->scenarioOps)
|
|
|
|
|
|
+ if(gameLobby().getState() == EServerState::SHUTDOWN || !gs || !gs->getStartInfo())
|
|
{
|
|
{
|
|
assert(0); // game should have shut down before reaching this point!
|
|
assert(0); // game should have shut down before reaching this point!
|
|
return;
|
|
return;
|
|
@@ -430,7 +430,7 @@ void CGameHandler::handleClientDisconnection(std::shared_ptr<CConnection> c)
|
|
for(auto & playerConnections : connections)
|
|
for(auto & playerConnections : connections)
|
|
{
|
|
{
|
|
PlayerColor playerId = playerConnections.first;
|
|
PlayerColor playerId = playerConnections.first;
|
|
- auto * playerSettings = gs->scenarioOps->getPlayersSettings(playerId.getNum());
|
|
|
|
|
|
+ auto * playerSettings = gs->getStartInfo()->getPlayersSettings(playerId.getNum());
|
|
if(!playerSettings)
|
|
if(!playerSettings)
|
|
continue;
|
|
continue;
|
|
|
|
|
|
@@ -553,7 +553,7 @@ void CGameHandler::init(StartInfo *si, Load::ProgressAccumulator & progressTrack
|
|
for (auto & elem : gs->players)
|
|
for (auto & elem : gs->players)
|
|
turnOrder->addPlayer(elem.first);
|
|
turnOrder->addPlayer(elem.first);
|
|
|
|
|
|
- for (auto & elem : gs->map->allHeroes)
|
|
|
|
|
|
+ for (auto & elem : gs->getMap().allHeroes)
|
|
{
|
|
{
|
|
if(elem)
|
|
if(elem)
|
|
heroPool->getHeroSkillsRandomGenerator(elem->getHeroTypeID()); // init RMG seed
|
|
heroPool->getHeroSkillsRandomGenerator(elem->getHeroTypeID()); // init RMG seed
|
|
@@ -638,7 +638,7 @@ void CGameHandler::onNewTurn()
|
|
|
|
|
|
if (firstTurn)
|
|
if (firstTurn)
|
|
{
|
|
{
|
|
- for (auto obj : gs->map->objects)
|
|
|
|
|
|
+ for (auto obj : gs->getMap().objects)
|
|
{
|
|
{
|
|
if (obj && obj->ID == Obj::PRISON) //give imprisoned hero 0 exp to level him up. easiest to do at this point
|
|
if (obj && obj->ID == Obj::PRISON) //give imprisoned hero 0 exp to level him up. easiest to do at this point
|
|
{
|
|
{
|
|
@@ -655,7 +655,7 @@ void CGameHandler::onNewTurn()
|
|
addStatistics(gameState()->statistic); // write at end of turn
|
|
addStatistics(gameState()->statistic); // write at end of turn
|
|
}
|
|
}
|
|
|
|
|
|
- for (CGTownInstance *t : gs->map->towns)
|
|
|
|
|
|
+ for (CGTownInstance *t : gs->getMap().towns)
|
|
{
|
|
{
|
|
PlayerColor player = t->tempOwner;
|
|
PlayerColor player = t->tempOwner;
|
|
|
|
|
|
@@ -669,7 +669,7 @@ void CGameHandler::onNewTurn()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- for (CGTownInstance *t : gs->map->towns)
|
|
|
|
|
|
+ for (CGTownInstance *t : gs->getMap().towns)
|
|
{
|
|
{
|
|
if (t->hasBonusOfType (BonusType::DARKNESS))
|
|
if (t->hasBonusOfType (BonusType::DARKNESS))
|
|
{
|
|
{
|
|
@@ -696,7 +696,7 @@ void CGameHandler::onNewTurn()
|
|
checkVictoryLossConditionsForAll(); // check for map turn limit
|
|
checkVictoryLossConditionsForAll(); // check for map turn limit
|
|
|
|
|
|
//call objects
|
|
//call objects
|
|
- for (auto & elem : gs->map->objects)
|
|
|
|
|
|
+ for (auto & elem : gs->getMap().objects)
|
|
{
|
|
{
|
|
if (elem)
|
|
if (elem)
|
|
elem->newTurn(getRandomGenerator());
|
|
elem->newTurn(getRandomGenerator());
|
|
@@ -810,7 +810,7 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, EMovementMode moveme
|
|
logGlobal->trace("Player %d (%s) wants to move hero %d from %s to %s", asker, asker.toString(), hid.getNum(), h->anchorPos().toString(), dst.toString());
|
|
logGlobal->trace("Player %d (%s) wants to move hero %d from %s to %s", asker, asker.toString(), hid.getNum(), h->anchorPos().toString(), dst.toString());
|
|
const int3 hmpos = h->convertToVisitablePos(dst);
|
|
const int3 hmpos = h->convertToVisitablePos(dst);
|
|
|
|
|
|
- if (!gs->map->isInTheMap(hmpos))
|
|
|
|
|
|
+ if (!gs->getMap().isInTheMap(hmpos))
|
|
{
|
|
{
|
|
logGlobal->error("Destination tile is outside the map!");
|
|
logGlobal->error("Destination tile is outside the map!");
|
|
return false;
|
|
return false;
|
|
@@ -905,7 +905,7 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, EMovementMode moveme
|
|
// should be called if hero changes tile but before applying TryMoveHero package
|
|
// should be called if hero changes tile but before applying TryMoveHero package
|
|
auto leaveTile = [&]()
|
|
auto leaveTile = [&]()
|
|
{
|
|
{
|
|
- for (CGObjectInstance *obj : gs->map->getTile(h->visitablePos()).visitableObjects)
|
|
|
|
|
|
+ for (CGObjectInstance *obj : gs->getMap().getTile(h->visitablePos()).visitableObjects)
|
|
{
|
|
{
|
|
obj->onHeroLeave(h);
|
|
obj->onHeroLeave(h);
|
|
}
|
|
}
|
|
@@ -1142,7 +1142,7 @@ void CGameHandler::giveCreatures(const CArmedInstance *obj, const CGHeroInstance
|
|
//first we move creatures to give to make them army of object-source
|
|
//first we move creatures to give to make them army of object-source
|
|
for (auto & elem : creatures.Slots())
|
|
for (auto & elem : creatures.Slots())
|
|
{
|
|
{
|
|
- addToSlot(StackLocation(obj, obj->getSlotFor(elem.second->getCreature())), elem.second->getCreature(), elem.second->count);
|
|
|
|
|
|
+ addToSlot(StackLocation(obj->id, obj->getSlotFor(elem.second->getCreature())), elem.second->getCreature(), elem.second->count);
|
|
}
|
|
}
|
|
|
|
|
|
tryJoiningArmy(obj, h, remove, true);
|
|
tryJoiningArmy(obj, h, remove, true);
|
|
@@ -1166,7 +1166,7 @@ void CGameHandler::takeCreatures(ObjectInstanceID objid, const std::vector<CStac
|
|
if (i->second->getType() == sbd.getType())
|
|
if (i->second->getType() == sbd.getType())
|
|
{
|
|
{
|
|
TQuantity take = std::min(sbd.count - collected, i->second->count); //collect as much cres as we can
|
|
TQuantity take = std::min(sbd.count - collected, i->second->count); //collect as much cres as we can
|
|
- changeStackCount(StackLocation(obj, i->first), -take, false);
|
|
|
|
|
|
+ changeStackCount(StackLocation(obj->id, i->first), -take, false);
|
|
collected += take;
|
|
collected += take;
|
|
foundSth = true;
|
|
foundSth = true;
|
|
break;
|
|
break;
|
|
@@ -1879,8 +1879,8 @@ bool CGameHandler::arrangeStacks(ObjectInstanceID id1, ObjectInstanceID id2, ui8
|
|
|
|
|
|
const CCreatureSet & S1 = *s1;
|
|
const CCreatureSet & S1 = *s1;
|
|
const CCreatureSet & S2 = *s2;
|
|
const CCreatureSet & S2 = *s2;
|
|
- StackLocation sl1(s1, p1);
|
|
|
|
- StackLocation sl2(s2, p2);
|
|
|
|
|
|
+ StackLocation sl1(s1->id, p1);
|
|
|
|
+ StackLocation sl2(s2->id, p2);
|
|
|
|
|
|
if (!sl1.slot.validSlot() || !sl2.slot.validSlot())
|
|
if (!sl1.slot.validSlot() || !sl2.slot.validSlot())
|
|
{
|
|
{
|
|
@@ -1926,12 +1926,12 @@ bool CGameHandler::arrangeStacks(ObjectInstanceID id1, ObjectInstanceID id2, ui8
|
|
|
|
|
|
if (!s1->slotEmpty(p1) && !s2->slotEmpty(p2))
|
|
if (!s1->slotEmpty(p1) && !s2->slotEmpty(p2))
|
|
{
|
|
{
|
|
- if (notRemovable(sl1.army) || notRemovable(sl2.army))
|
|
|
|
|
|
+ if (notRemovable(s1) || notRemovable(s2))
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
- if (s1->slotEmpty(p1) && notRemovable(sl2.army))
|
|
|
|
|
|
+ if (s1->slotEmpty(p1) && notRemovable(s2))
|
|
return false;
|
|
return false;
|
|
- else if (s2->slotEmpty(p2) && notRemovable(sl1.army))
|
|
|
|
|
|
+ else if (s2->slotEmpty(p2) && notRemovable(s1))
|
|
return false;
|
|
return false;
|
|
|
|
|
|
swapStacks(sl1, sl2);
|
|
swapStacks(sl1, sl2);
|
|
@@ -1947,7 +1947,7 @@ bool CGameHandler::arrangeStacks(ObjectInstanceID id1, ObjectInstanceID id2, ui8
|
|
complain("Cannot merge empty stack!");
|
|
complain("Cannot merge empty stack!");
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
- else if (notRemovable(sl1.army))
|
|
|
|
|
|
+ else if (notRemovable(s1))
|
|
return false;
|
|
return false;
|
|
|
|
|
|
moveStack(sl1, sl2);
|
|
moveStack(sl1, sl2);
|
|
@@ -1982,12 +1982,12 @@ bool CGameHandler::arrangeStacks(ObjectInstanceID id1, ObjectInstanceID id2, ui8
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
- if (notRemovable(sl1.army))
|
|
|
|
|
|
+ if (notRemovable(s1))
|
|
{
|
|
{
|
|
if (s1->getStackCount(p1) > countLeftOnSrc)
|
|
if (s1->getStackCount(p1) > countLeftOnSrc)
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
- else if (notRemovable(sl2.army))
|
|
|
|
|
|
+ else if (notRemovable(s2))
|
|
{
|
|
{
|
|
if (s2->getStackCount(p1) < countLeftOnSrc)
|
|
if (s2->getStackCount(p1) < countLeftOnSrc)
|
|
return false;
|
|
return false;
|
|
@@ -2005,7 +2005,7 @@ bool CGameHandler::arrangeStacks(ObjectInstanceID id1, ObjectInstanceID id2, ui8
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
- if (notRemovable(sl1.army))
|
|
|
|
|
|
+ if (notRemovable(s1))
|
|
return false;
|
|
return false;
|
|
|
|
|
|
moveStack(sl1, sl2, val);
|
|
moveStack(sl1, sl2, val);
|
|
@@ -2034,7 +2034,7 @@ bool CGameHandler::disbandCreature(ObjectInstanceID id, SlotID pos)
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
- eraseStack(StackLocation(s1, pos));
|
|
|
|
|
|
+ eraseStack(StackLocation(s1->id, pos));
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2048,7 +2048,7 @@ bool CGameHandler::buildStructure(ObjectInstanceID tid, BuildingID requestedID,
|
|
if(t->hasBuilt(requestedID))
|
|
if(t->hasBuilt(requestedID))
|
|
COMPLAIN_RETF("Building %s is already built in %s", t->getTown()->buildings.at(requestedID)->getNameTranslated() % t->getNameTranslated());
|
|
COMPLAIN_RETF("Building %s is already built in %s", t->getTown()->buildings.at(requestedID)->getNameTranslated() % t->getNameTranslated());
|
|
|
|
|
|
- const CBuilding * requestedBuilding = t->getTown()->buildings.at(requestedID);
|
|
|
|
|
|
+ const auto & requestedBuilding = t->getTown()->buildings.at(requestedID);
|
|
|
|
|
|
//Vector with future list of built building and buildings in auto-mode that are not yet built.
|
|
//Vector with future list of built building and buildings in auto-mode that are not yet built.
|
|
std::vector<const CBuilding*> remainingAutoBuildings;
|
|
std::vector<const CBuilding*> remainingAutoBuildings;
|
|
@@ -2144,7 +2144,7 @@ bool CGameHandler::buildStructure(ObjectInstanceID tid, BuildingID requestedID,
|
|
else
|
|
else
|
|
{
|
|
{
|
|
if(build.second->mode == CBuilding::BUILD_AUTO) //not built auto building
|
|
if(build.second->mode == CBuilding::BUILD_AUTO) //not built auto building
|
|
- remainingAutoBuildings.push_back(build.second);
|
|
|
|
|
|
+ remainingAutoBuildings.push_back(build.second.get());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2154,7 +2154,7 @@ bool CGameHandler::buildStructure(ObjectInstanceID tid, BuildingID requestedID,
|
|
ns.built = force ? t->built : (t->built+1);
|
|
ns.built = force ? t->built : (t->built+1);
|
|
|
|
|
|
std::queue<const CBuilding*> buildingsToAdd;
|
|
std::queue<const CBuilding*> buildingsToAdd;
|
|
- buildingsToAdd.push(requestedBuilding);
|
|
|
|
|
|
+ buildingsToAdd.push(requestedBuilding.get());
|
|
|
|
|
|
while(!buildingsToAdd.empty())
|
|
while(!buildingsToAdd.empty())
|
|
{
|
|
{
|
|
@@ -2403,7 +2403,7 @@ bool CGameHandler::recruitCreatures(ObjectInstanceID objid, ObjectInstanceID dst
|
|
}
|
|
}
|
|
else
|
|
else
|
|
{
|
|
{
|
|
- addToSlot(StackLocation(army, slot), c, cram);
|
|
|
|
|
|
+ addToSlot(StackLocation(army->id, slot), c, cram);
|
|
}
|
|
}
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
@@ -2437,17 +2437,19 @@ bool CGameHandler::upgradeCreature(ObjectInstanceID objid, SlotID pos, CreatureI
|
|
gs->statistic.accumulatedValues[player].spentResourcesForArmy += totalCost;
|
|
gs->statistic.accumulatedValues[player].spentResourcesForArmy += totalCost;
|
|
|
|
|
|
//upgrade creature
|
|
//upgrade creature
|
|
- changeStackType(StackLocation(obj, pos), upgID.toCreature());
|
|
|
|
|
|
+ changeStackType(StackLocation(obj->id, pos), upgID.toCreature());
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
bool CGameHandler::changeStackType(const StackLocation &sl, const CCreature *c)
|
|
bool CGameHandler::changeStackType(const StackLocation &sl, const CCreature *c)
|
|
{
|
|
{
|
|
- if (!sl.army->hasStackAtSlot(sl.slot))
|
|
|
|
|
|
+ const CArmedInstance * obj = static_cast<const CArmedInstance *>(getObjInstance(sl.army));
|
|
|
|
+
|
|
|
|
+ if (!obj->hasStackAtSlot(sl.slot))
|
|
COMPLAIN_RET("Cannot find a stack to change type");
|
|
COMPLAIN_RET("Cannot find a stack to change type");
|
|
|
|
|
|
SetStackType sst;
|
|
SetStackType sst;
|
|
- sst.army = sl.army->id;
|
|
|
|
|
|
+ sst.army = obj->id;
|
|
sst.slot = sl.slot;
|
|
sst.slot = sl.slot;
|
|
sst.type = c->getId();
|
|
sst.type = c->getId();
|
|
sendAndApply(sst);
|
|
sendAndApply(sst);
|
|
@@ -2460,7 +2462,7 @@ void CGameHandler::moveArmy(const CArmedInstance *src, const CArmedInstance *dst
|
|
while(src->stacksCount())//while there are unmoved creatures
|
|
while(src->stacksCount())//while there are unmoved creatures
|
|
{
|
|
{
|
|
auto i = src->Slots().begin(); //iterator to stack to move
|
|
auto i = src->Slots().begin(); //iterator to stack to move
|
|
- StackLocation sl(src, i->first); //location of stack to move
|
|
|
|
|
|
+ StackLocation sl(src->id, i->first); //location of stack to move
|
|
|
|
|
|
SlotID pos = dst->getSlotFor(i->second->getCreature());
|
|
SlotID pos = dst->getSlotFor(i->second->getCreature());
|
|
if (!pos.validSlot())
|
|
if (!pos.validSlot())
|
|
@@ -2469,9 +2471,9 @@ void CGameHandler::moveArmy(const CArmedInstance *src, const CArmedInstance *dst
|
|
std::pair<SlotID, SlotID> toMerge;
|
|
std::pair<SlotID, SlotID> toMerge;
|
|
if (dst->mergeableStacks(toMerge, i->first) && allowMerging)
|
|
if (dst->mergeableStacks(toMerge, i->first) && allowMerging)
|
|
{
|
|
{
|
|
- moveStack(StackLocation(dst, toMerge.first), StackLocation(dst, toMerge.second)); //merge toMerge.first into toMerge.second
|
|
|
|
|
|
+ moveStack(StackLocation(dst->id, toMerge.first), StackLocation(dst->id, toMerge.second)); //merge toMerge.first into toMerge.second
|
|
assert(!dst->hasStackAtSlot(toMerge.first)); //we have now a new free slot
|
|
assert(!dst->hasStackAtSlot(toMerge.first)); //we have now a new free slot
|
|
- moveStack(sl, StackLocation(dst, toMerge.first)); //move stack to freed slot
|
|
|
|
|
|
+ moveStack(sl, StackLocation(dst->id, toMerge.first)); //move stack to freed slot
|
|
}
|
|
}
|
|
else
|
|
else
|
|
{
|
|
{
|
|
@@ -2481,7 +2483,7 @@ void CGameHandler::moveArmy(const CArmedInstance *src, const CArmedInstance *dst
|
|
}
|
|
}
|
|
else
|
|
else
|
|
{
|
|
{
|
|
- moveStack(sl, StackLocation(dst, pos));
|
|
|
|
|
|
+ moveStack(sl, StackLocation(dst->id, pos));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -3048,7 +3050,7 @@ bool CGameHandler::buyArtifact(const IMarket *m, const CGHeroInstance *h, GameRe
|
|
if(dynamic_cast<const CGTownInstance *>(m))
|
|
if(dynamic_cast<const CGTownInstance *>(m))
|
|
{
|
|
{
|
|
saa.id = ObjectInstanceID::NONE;
|
|
saa.id = ObjectInstanceID::NONE;
|
|
- saa.arts = gs->map->townMerchantArtifacts;
|
|
|
|
|
|
+ saa.arts = gs->getMap().townMerchantArtifacts;
|
|
}
|
|
}
|
|
else if(const CGBlackMarket *bm = dynamic_cast<const CGBlackMarket *>(m)) //black market
|
|
else if(const CGBlackMarket *bm = dynamic_cast<const CGBlackMarket *>(m)) //black market
|
|
{
|
|
{
|
|
@@ -3170,7 +3172,7 @@ bool CGameHandler::sellCreatures(ui32 count, const IMarket *market, const CGHero
|
|
assert(0);
|
|
assert(0);
|
|
}
|
|
}
|
|
|
|
|
|
- changeStackCount(StackLocation(hero, slot), -(TQuantity)count);
|
|
|
|
|
|
+ changeStackCount(StackLocation(hero->id, slot), -(TQuantity)count);
|
|
|
|
|
|
giveResource(hero->tempOwner, resourceID, b2 * units);
|
|
giveResource(hero->tempOwner, resourceID, b2 * units);
|
|
|
|
|
|
@@ -3201,7 +3203,7 @@ bool CGameHandler::transformInUndead(const IMarket *market, const CGHeroInstance
|
|
|| (s.getCreatureID() == CreatureID::HYDRA)
|
|
|| (s.getCreatureID() == CreatureID::HYDRA)
|
|
|| (s.getCreatureID() == CreatureID::CHAOS_HYDRA))
|
|
|| (s.getCreatureID() == CreatureID::CHAOS_HYDRA))
|
|
resCreature = CreatureID::BONE_DRAGON;
|
|
resCreature = CreatureID::BONE_DRAGON;
|
|
- changeStackType(StackLocation(army, slot), resCreature.toCreature());
|
|
|
|
|
|
+ changeStackType(StackLocation(army->id, slot), resCreature.toCreature());
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -3467,7 +3469,7 @@ bool CGameHandler::buildBoat(ObjectInstanceID objid, PlayerColor playerID)
|
|
}
|
|
}
|
|
|
|
|
|
int3 tile = obj->bestLocation();
|
|
int3 tile = obj->bestLocation();
|
|
- if (!gs->map->isInTheMap(tile))
|
|
|
|
|
|
+ if (!gs->getMap().isInTheMap(tile))
|
|
{
|
|
{
|
|
complain("Cannot find appropriate tile for a boat!");
|
|
complain("Cannot find appropriate tile for a boat!");
|
|
return false;
|
|
return false;
|
|
@@ -3557,7 +3559,7 @@ void CGameHandler::checkVictoryLossConditionsForPlayer(PlayerColor player)
|
|
}
|
|
}
|
|
|
|
|
|
//player lost -> all his objects become unflagged (neutral)
|
|
//player lost -> all his objects become unflagged (neutral)
|
|
- for (auto obj : gs->map->objects) //unflag objs
|
|
|
|
|
|
+ for (auto obj : gs->getMap().objects) //unflag objs
|
|
{
|
|
{
|
|
if (obj.get() && obj->tempOwner == player)
|
|
if (obj.get() && obj->tempOwner == player)
|
|
setOwner(obj, PlayerColor::NEUTRAL);
|
|
setOwner(obj, PlayerColor::NEUTRAL);
|
|
@@ -3613,7 +3615,7 @@ bool CGameHandler::dig(const CGHeroInstance *h)
|
|
InfoWindow iw;
|
|
InfoWindow iw;
|
|
iw.type = EInfoWindowMode::AUTO;
|
|
iw.type = EInfoWindowMode::AUTO;
|
|
iw.player = h->tempOwner;
|
|
iw.player = h->tempOwner;
|
|
- if (gs->map->grailPos == h->visitablePos())
|
|
|
|
|
|
+ if (gs->getMap().grailPos == h->visitablePos())
|
|
{
|
|
{
|
|
ArtifactID grail = ArtifactID::GRAIL;
|
|
ArtifactID grail = ArtifactID::GRAIL;
|
|
|
|
|
|
@@ -3679,7 +3681,7 @@ bool CGameHandler::sacrificeCreatures(const IMarket * market, const CGHeroInstan
|
|
|
|
|
|
int crid = hero->getStack(slot[i]).getId();
|
|
int crid = hero->getStack(slot[i]).getId();
|
|
|
|
|
|
- changeStackCount(StackLocation(hero, slot[i]), -(TQuantity)count[i]);
|
|
|
|
|
|
+ changeStackCount(StackLocation(hero->id, slot[i]), -(TQuantity)count[i]);
|
|
|
|
|
|
int dump;
|
|
int dump;
|
|
int exp;
|
|
int exp;
|
|
@@ -3742,14 +3744,16 @@ bool CGameHandler::sacrificeArtifact(const IMarket * market, const CGHeroInstanc
|
|
|
|
|
|
bool CGameHandler::insertNewStack(const StackLocation &sl, const CCreature *c, TQuantity count)
|
|
bool CGameHandler::insertNewStack(const StackLocation &sl, const CCreature *c, TQuantity count)
|
|
{
|
|
{
|
|
- if (sl.army->hasStackAtSlot(sl.slot))
|
|
|
|
|
|
+ auto army = dynamic_cast<const CArmedInstance*>(getObj(sl.army));
|
|
|
|
+
|
|
|
|
+ if (army->hasStackAtSlot(sl.slot))
|
|
COMPLAIN_RET("Slot is already taken!");
|
|
COMPLAIN_RET("Slot is already taken!");
|
|
|
|
|
|
if (!sl.slot.validSlot())
|
|
if (!sl.slot.validSlot())
|
|
COMPLAIN_RET("Cannot insert stack to that slot!");
|
|
COMPLAIN_RET("Cannot insert stack to that slot!");
|
|
|
|
|
|
InsertNewStack ins;
|
|
InsertNewStack ins;
|
|
- ins.army = sl.army->id;
|
|
|
|
|
|
+ ins.army = army->id;
|
|
ins.slot = sl.slot;
|
|
ins.slot = sl.slot;
|
|
ins.type = c->getId();
|
|
ins.type = c->getId();
|
|
ins.count = count;
|
|
ins.count = count;
|
|
@@ -3759,18 +3763,20 @@ bool CGameHandler::insertNewStack(const StackLocation &sl, const CCreature *c, T
|
|
|
|
|
|
bool CGameHandler::eraseStack(const StackLocation &sl, bool forceRemoval)
|
|
bool CGameHandler::eraseStack(const StackLocation &sl, bool forceRemoval)
|
|
{
|
|
{
|
|
- if (!sl.army->hasStackAtSlot(sl.slot))
|
|
|
|
|
|
+ auto army = dynamic_cast<const CArmedInstance*>(getObj(sl.army));
|
|
|
|
+
|
|
|
|
+ if (!army->hasStackAtSlot(sl.slot))
|
|
COMPLAIN_RET("Cannot find a stack to erase");
|
|
COMPLAIN_RET("Cannot find a stack to erase");
|
|
|
|
|
|
- if (sl.army->stacksCount() == 1 //from the last stack
|
|
|
|
- && sl.army->needsLastStack() //that must be left
|
|
|
|
|
|
+ if (army->stacksCount() == 1 //from the last stack
|
|
|
|
+ && army->needsLastStack() //that must be left
|
|
&& !forceRemoval) //ignore above conditions if we are forcing removal
|
|
&& !forceRemoval) //ignore above conditions if we are forcing removal
|
|
{
|
|
{
|
|
COMPLAIN_RET("Cannot erase the last stack!");
|
|
COMPLAIN_RET("Cannot erase the last stack!");
|
|
}
|
|
}
|
|
|
|
|
|
EraseStack es;
|
|
EraseStack es;
|
|
- es.army = sl.army->id;
|
|
|
|
|
|
+ es.army = army->id;
|
|
es.slot = sl.slot;
|
|
es.slot = sl.slot;
|
|
sendAndApply(es);
|
|
sendAndApply(es);
|
|
return true;
|
|
return true;
|
|
@@ -3778,7 +3784,9 @@ bool CGameHandler::eraseStack(const StackLocation &sl, bool forceRemoval)
|
|
|
|
|
|
bool CGameHandler::changeStackCount(const StackLocation &sl, TQuantity count, bool absoluteValue)
|
|
bool CGameHandler::changeStackCount(const StackLocation &sl, TQuantity count, bool absoluteValue)
|
|
{
|
|
{
|
|
- TQuantity currentCount = sl.army->getStackCount(sl.slot);
|
|
|
|
|
|
+ auto army = dynamic_cast<const CArmedInstance*>(getObj(sl.army));
|
|
|
|
+
|
|
|
|
+ TQuantity currentCount = army->getStackCount(sl.slot);
|
|
if ((absoluteValue && count < 0)
|
|
if ((absoluteValue && count < 0)
|
|
|| (!absoluteValue && -count > currentCount))
|
|
|| (!absoluteValue && -count > currentCount))
|
|
{
|
|
{
|
|
@@ -3793,7 +3801,7 @@ bool CGameHandler::changeStackCount(const StackLocation &sl, TQuantity count, bo
|
|
else
|
|
else
|
|
{
|
|
{
|
|
ChangeStackCount csc;
|
|
ChangeStackCount csc;
|
|
- csc.army = sl.army->id;
|
|
|
|
|
|
+ csc.army = army->id;
|
|
csc.slot = sl.slot;
|
|
csc.slot = sl.slot;
|
|
csc.count = count;
|
|
csc.count = count;
|
|
csc.absoluteValue = absoluteValue;
|
|
csc.absoluteValue = absoluteValue;
|
|
@@ -3804,7 +3812,9 @@ bool CGameHandler::changeStackCount(const StackLocation &sl, TQuantity count, bo
|
|
|
|
|
|
bool CGameHandler::addToSlot(const StackLocation &sl, const CCreature *c, TQuantity count)
|
|
bool CGameHandler::addToSlot(const StackLocation &sl, const CCreature *c, TQuantity count)
|
|
{
|
|
{
|
|
- const CCreature *slotC = sl.army->getCreature(sl.slot);
|
|
|
|
|
|
+ auto army = dynamic_cast<const CArmedInstance*>(getObj(sl.army));
|
|
|
|
+
|
|
|
|
+ const CCreature *slotC = army->getCreature(sl.slot);
|
|
if (!slotC) //slot is empty
|
|
if (!slotC) //slot is empty
|
|
insertNewStack(sl, c, count);
|
|
insertNewStack(sl, c, count);
|
|
else if (c == slotC)
|
|
else if (c == slotC)
|
|
@@ -3833,7 +3843,7 @@ void CGameHandler::tryJoiningArmy(const CArmedInstance *src, const CArmedInstanc
|
|
SlotID pos = dst->getSlotFor(i->second->getCreature());
|
|
SlotID pos = dst->getSlotFor(i->second->getCreature());
|
|
if (pos.validSlot())
|
|
if (pos.validSlot())
|
|
{
|
|
{
|
|
- moveStack(StackLocation(src, i->first), StackLocation(dst, pos));
|
|
|
|
|
|
+ moveStack(StackLocation(src->id, i->first), StackLocation(dst->id, pos));
|
|
cont = true;
|
|
cont = true;
|
|
break; //or iterator crashes
|
|
break; //or iterator crashes
|
|
}
|
|
}
|
|
@@ -3851,10 +3861,13 @@ void CGameHandler::tryJoiningArmy(const CArmedInstance *src, const CArmedInstanc
|
|
|
|
|
|
bool CGameHandler::moveStack(const StackLocation &src, const StackLocation &dst, TQuantity count)
|
|
bool CGameHandler::moveStack(const StackLocation &src, const StackLocation &dst, TQuantity count)
|
|
{
|
|
{
|
|
- if (!src.army->hasStackAtSlot(src.slot))
|
|
|
|
|
|
+ auto srcArmy = dynamic_cast<const CArmedInstance*>(getObj(src.army));
|
|
|
|
+ auto dstArmy = dynamic_cast<const CArmedInstance*>(getObj(dst.army));
|
|
|
|
+
|
|
|
|
+ if (!srcArmy->hasStackAtSlot(src.slot))
|
|
COMPLAIN_RET("No stack to move!");
|
|
COMPLAIN_RET("No stack to move!");
|
|
|
|
|
|
- if (dst.army->hasStackAtSlot(dst.slot) && dst.army->getCreature(dst.slot) != src.army->getCreature(src.slot))
|
|
|
|
|
|
+ if (dstArmy->hasStackAtSlot(dst.slot) && dstArmy->getCreature(dst.slot) != srcArmy->getCreature(src.slot))
|
|
COMPLAIN_RET("Cannot move: stack of different type at destination pos!");
|
|
COMPLAIN_RET("Cannot move: stack of different type at destination pos!");
|
|
|
|
|
|
if (!dst.slot.validSlot())
|
|
if (!dst.slot.validSlot())
|
|
@@ -3862,20 +3875,20 @@ bool CGameHandler::moveStack(const StackLocation &src, const StackLocation &dst,
|
|
|
|
|
|
if (count == -1)
|
|
if (count == -1)
|
|
{
|
|
{
|
|
- count = src.army->getStackCount(src.slot);
|
|
|
|
|
|
+ count = srcArmy->getStackCount(src.slot);
|
|
}
|
|
}
|
|
|
|
|
|
- if (src.army != dst.army //moving away
|
|
|
|
- && count == src.army->getStackCount(src.slot) //all creatures
|
|
|
|
- && src.army->stacksCount() == 1 //from the last stack
|
|
|
|
- && src.army->needsLastStack()) //that must be left
|
|
|
|
|
|
+ if (srcArmy != dstArmy //moving away
|
|
|
|
+ && count == srcArmy->getStackCount(src.slot) //all creatures
|
|
|
|
+ && srcArmy->stacksCount() == 1 //from the last stack
|
|
|
|
+ && srcArmy->needsLastStack()) //that must be left
|
|
{
|
|
{
|
|
COMPLAIN_RET("Cannot move away the last creature!");
|
|
COMPLAIN_RET("Cannot move away the last creature!");
|
|
}
|
|
}
|
|
|
|
|
|
RebalanceStacks rs;
|
|
RebalanceStacks rs;
|
|
- rs.srcArmy = src.army->id;
|
|
|
|
- rs.dstArmy = dst.army->id;
|
|
|
|
|
|
+ rs.srcArmy = srcArmy->id;
|
|
|
|
+ rs.dstArmy = dstArmy->id;
|
|
rs.srcSlot = src.slot;
|
|
rs.srcSlot = src.slot;
|
|
rs.dstSlot = dst.slot;
|
|
rs.dstSlot = dst.slot;
|
|
rs.count = count;
|
|
rs.count = count;
|
|
@@ -3898,19 +3911,22 @@ void CGameHandler::castSpell(const spells::Caster * caster, SpellID spellID, con
|
|
|
|
|
|
bool CGameHandler::swapStacks(const StackLocation & sl1, const StackLocation & sl2)
|
|
bool CGameHandler::swapStacks(const StackLocation & sl1, const StackLocation & sl2)
|
|
{
|
|
{
|
|
- if(!sl1.army->hasStackAtSlot(sl1.slot))
|
|
|
|
|
|
+ auto army1 = dynamic_cast<const CArmedInstance*>(getObj(sl1.army));
|
|
|
|
+ auto army2 = dynamic_cast<const CArmedInstance*>(getObj(sl2.army));
|
|
|
|
+
|
|
|
|
+ if(!army1->hasStackAtSlot(sl1.slot))
|
|
{
|
|
{
|
|
return moveStack(sl2, sl1);
|
|
return moveStack(sl2, sl1);
|
|
}
|
|
}
|
|
- else if(!sl2.army->hasStackAtSlot(sl2.slot))
|
|
|
|
|
|
+ else if(!army2->hasStackAtSlot(sl2.slot))
|
|
{
|
|
{
|
|
return moveStack(sl1, sl2);
|
|
return moveStack(sl1, sl2);
|
|
}
|
|
}
|
|
else
|
|
else
|
|
{
|
|
{
|
|
SwapStacks ss;
|
|
SwapStacks ss;
|
|
- ss.srcArmy = sl1.army->id;
|
|
|
|
- ss.dstArmy = sl2.army->id;
|
|
|
|
|
|
+ ss.srcArmy = army1->id;
|
|
|
|
+ ss.dstArmy = army2->id;
|
|
ss.srcSlot = sl1.slot;
|
|
ss.srcSlot = sl1.slot;
|
|
ss.dstSlot = sl2.slot;
|
|
ss.dstSlot = sl2.slot;
|
|
sendAndApply(ss);
|
|
sendAndApply(ss);
|
|
@@ -4036,7 +4052,7 @@ void CGameHandler::synchronizeArtifactHandlerLists()
|
|
|
|
|
|
bool CGameHandler::isValidObject(const CGObjectInstance *obj) const
|
|
bool CGameHandler::isValidObject(const CGObjectInstance *obj) const
|
|
{
|
|
{
|
|
- return vstd::contains(gs->map->objects, obj);
|
|
|
|
|
|
+ return vstd::contains(gs->getMap().objects, obj);
|
|
}
|
|
}
|
|
|
|
|
|
bool CGameHandler::isBlockedByQueries(const CPackForServer *pack, PlayerColor player)
|
|
bool CGameHandler::isBlockedByQueries(const CPackForServer *pack, PlayerColor player)
|
|
@@ -4237,7 +4253,7 @@ CGObjectInstance * CGameHandler::createNewObject(const int3 & visitablePosition,
|
|
if (!gs->isInTheMap(visitablePosition))
|
|
if (!gs->isInTheMap(visitablePosition))
|
|
throw std::runtime_error("Attempt to create object outside map at " + visitablePosition.toString());
|
|
throw std::runtime_error("Attempt to create object outside map at " + visitablePosition.toString());
|
|
|
|
|
|
- const TerrainTile & t = gs->map->getTile(visitablePosition);
|
|
|
|
|
|
+ const TerrainTile & t = gs->getMap().getTile(visitablePosition);
|
|
terrainType = t.getTerrainID();
|
|
terrainType = t.getTerrainID();
|
|
|
|
|
|
auto handler = LIBRARY->objtypeh->getHandlerFor(objectID, subID);
|
|
auto handler = LIBRARY->objtypeh->getHandlerFor(objectID, subID);
|