mirror of
https://github.com/vcmi/vcmi.git
synced 2025-03-23 21:29:13 +02:00
Merge pull request #1196 from IvanSavenko/hero_positioning_fix
Fixes incorrect positioning of heroes on spawn/release from prison
This commit is contained in:
commit
40e55e2788
@ -1873,17 +1873,27 @@ void CGameState::initVisitingAndGarrisonedHeroes()
|
|||||||
{
|
{
|
||||||
for(CGTownInstance *t : k->second.towns)
|
for(CGTownInstance *t : k->second.towns)
|
||||||
{
|
{
|
||||||
int3 vistile = t->visitablePos(); vistile.x++; //tile next to the entrance
|
bool heroOnTownBlockableTile = t->blockingAt(h->visitablePos().x, h->visitablePos().y);
|
||||||
if(vistile == h->pos || h->pos==t->visitablePos())
|
bool heroOnTownVisitableTile = t->visitableAt(h->visitablePos().x, h->visitablePos().y);
|
||||||
{
|
|
||||||
t->setVisitingHero(h);
|
// current hero position is at one of blocking tiles of current town
|
||||||
if(h->pos == t->pos) //visiting hero placed in the editor has same pos as the town - we need to correct it
|
// assume that this hero should be visiting the town (H3M format quirk) and move hero to correct position
|
||||||
|
if (heroOnTownBlockableTile)
|
||||||
{
|
{
|
||||||
|
int3 townVisitablePos = t->visitablePos();
|
||||||
|
int3 correctedPos = townVisitablePos + h->getVisitableOffset();
|
||||||
|
|
||||||
map->removeBlockVisTiles(h);
|
map->removeBlockVisTiles(h);
|
||||||
h->pos.x -= 1;
|
h->pos = correctedPos;
|
||||||
map->addBlockVisTiles(h);
|
map->addBlockVisTiles(h);
|
||||||
|
|
||||||
|
assert(t->visitableAt(h->visitablePos().x, h->visitablePos().y));
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
if (heroOnTownBlockableTile || heroOnTownVisitableTile)
|
||||||
|
{
|
||||||
|
assert(t->visitingHero == nullptr);
|
||||||
|
t->setVisitingHero(h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -703,13 +703,18 @@ DLL_LINKAGE void GiveHero::applyGs(CGameState *gs)
|
|||||||
//bonus system
|
//bonus system
|
||||||
h->detachFrom(gs->globalEffects);
|
h->detachFrom(gs->globalEffects);
|
||||||
h->attachTo(*gs->getPlayerState(player));
|
h->attachTo(*gs->getPlayerState(player));
|
||||||
h->appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, h->type->heroClass->getIndex())->getTemplates().front();
|
|
||||||
|
|
||||||
|
auto oldOffset = h->getVisitableOffset();
|
||||||
gs->map->removeBlockVisTiles(h,true);
|
gs->map->removeBlockVisTiles(h,true);
|
||||||
|
h->appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, h->type->heroClass->getIndex())->getTemplates().front();
|
||||||
|
auto newOffset = h->getVisitableOffset();
|
||||||
|
|
||||||
h->setOwner(player);
|
h->setOwner(player);
|
||||||
h->movement = h->maxMovePoints(true);
|
h->movement = h->maxMovePoints(true);
|
||||||
|
h->pos = h->pos - oldOffset + newOffset;
|
||||||
gs->map->heroesOnMap.push_back(h);
|
gs->map->heroesOnMap.push_back(h);
|
||||||
gs->getPlayerState(h->getOwner())->heroes.push_back(h);
|
gs->getPlayerState(h->getOwner())->heroes.push_back(h);
|
||||||
|
|
||||||
gs->map->addBlockVisTiles(h);
|
gs->map->addBlockVisTiles(h);
|
||||||
h->inTownGarrison = false;
|
h->inTownGarrison = false;
|
||||||
}
|
}
|
||||||
|
@ -195,7 +195,9 @@ std::set<int3> CGObjectInstance::getBlockedOffsets() const
|
|||||||
|
|
||||||
void CGObjectInstance::setType(si32 ID, si32 subID)
|
void CGObjectInstance::setType(si32 ID, si32 subID)
|
||||||
{
|
{
|
||||||
const TerrainTile &tile = cb->gameState()->map->getTile(visitablePos());
|
auto position = visitablePos();
|
||||||
|
auto oldOffset = getVisitableOffset();
|
||||||
|
auto &tile = cb->gameState()->map->getTile(position);
|
||||||
|
|
||||||
//recalculate blockvis tiles - new appearance might have different blockmap than before
|
//recalculate blockvis tiles - new appearance might have different blockmap than before
|
||||||
cb->gameState()->map->removeBlockVisTiles(this, true);
|
cb->gameState()->map->removeBlockVisTiles(this, true);
|
||||||
@ -206,14 +208,23 @@ void CGObjectInstance::setType(si32 ID, si32 subID)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(!handler->getTemplates(tile.terType->id).empty())
|
if(!handler->getTemplates(tile.terType->id).empty())
|
||||||
|
{
|
||||||
appearance = handler->getTemplates(tile.terType->id)[0];
|
appearance = handler->getTemplates(tile.terType->id)[0];
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
logGlobal->warn("Object %d:%d at %s has no templates suitable for terrain %s", ID, subID, visitablePos().toString(), tile.terType->name);
|
||||||
appearance = handler->getTemplates()[0]; // get at least some appearance since alternative is crash
|
appearance = handler->getTemplates()[0]; // get at least some appearance since alternative is crash
|
||||||
|
}
|
||||||
|
|
||||||
if(this->ID == Obj::PRISON && ID == Obj::HERO)
|
if(this->ID == Obj::PRISON && ID == Obj::HERO)
|
||||||
{
|
{
|
||||||
//adjust for the prison offset
|
auto newOffset = getVisitableOffset();
|
||||||
pos = visitablePos();
|
// FIXME: potentially unused code - setType is NOT called when releasing hero from prison
|
||||||
|
// instead, appearance update & pos adjustment occurs in GiveHero::applyGs
|
||||||
|
|
||||||
|
// adjust position since hero and prison may have different visitable offset
|
||||||
|
pos = pos - oldOffset + newOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->ID = Obj(ID);
|
this->ID = Obj(ID);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user