1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-26 03:52:01 +02:00

NewObject pack now receives visitable position instead of h3m position

This commit is contained in:
Ivan Savenko 2023-06-20 22:06:45 +03:00
parent 56680e102d
commit d8879f1e53
8 changed files with 45 additions and 64 deletions

View File

@ -961,7 +961,7 @@ void ApplyClientNetPackVisitor::visitNewObject(NewObject & pack)
{
cl.invalidatePaths();
const CGObjectInstance *obj = cl.getObj(pack.id);
const CGObjectInstance *obj = cl.getObj(pack.createdObjectID);
if(CGI->mh)
CGI->mh->onObjectFadeIn(obj);

View File

@ -745,11 +745,14 @@ struct DLL_LINKAGE NewObject : public CPackForClient
{
void applyGs(CGameState * gs);
/// Object ID to create
Obj ID;
/// Object secondary ID to create
ui32 subID = 0;
int3 pos;
/// Position of visitable tile of created object
int3 targetPos;
ObjectInstanceID id; //used locally, filled during applyGs
ObjectInstanceID createdObjectID; //used locally, filled during applyGs
virtual void visitTyped(ICPackVisitor & visitor) override;
@ -757,7 +760,7 @@ struct DLL_LINKAGE NewObject : public CPackForClient
{
h & ID;
h & subID;
h & pos;
h & targetPos;
}
};

View File

@ -1492,32 +1492,20 @@ void NewObject::applyGs(CGameState *gs)
{
TerrainId terrainType = ETerrainId::NONE;
if(ID == Obj::BOAT && !gs->isInTheMap(pos)) //special handling for bug #3060 - pos outside map but visitablePos is not
if (!gs->isInTheMap(targetPos))
{
CGObjectInstance testObject = CGObjectInstance();
testObject.pos = pos;
testObject.appearance = VLC->objtypeh->getHandlerFor(ID, subID)->getTemplates(ETerrainId::WATER).front();
logGlobal->error("Attempt to create object outside map at %s!", targetPos.toString());
return;
}
[[maybe_unused]] const int3 previousXAxisTile = CGBoat::translatePos(pos, true);
assert(gs->isInTheMap(previousXAxisTile) && (testObject.visitablePos() == previousXAxisTile));
}
else
{
const TerrainTile & t = gs->map->getTile(pos);
const TerrainTile & t = gs->map->getTile(targetPos);
terrainType = t.terType->getId();
}
auto handler = VLC->objtypeh->getHandlerFor(ID, subID);
CGObjectInstance * o = handler->create();
handler->configureObject(o, gs->getRandomGenerator());
switch(ID)
{
case Obj::BOAT:
terrainType = ETerrainId::WATER; //TODO: either boat should only spawn on water, or all water objects should be handled this way
break;
case Obj::MONSTER: //probably more options will be needed
if (ID == Obj::MONSTER) //probably more options will be needed
{
//CStackInstance hlp;
auto * cre = dynamic_cast<CGCreature *>(o);
@ -1529,20 +1517,27 @@ void NewObject::applyGs(CGameState *gs)
cre->identifier = -1;
cre->addToSlot(SlotID(0), new CStackInstance(CreatureID(subID), -1)); //add placeholder stack
}
break;
}
assert(!handler->getTemplates(terrainType).empty());
if (!handler->getTemplates(terrainType).empty())
o->appearance = handler->getTemplates(terrainType).front();
else
o->appearance = handler->getTemplates().front();
o->id = ObjectInstanceID(static_cast<si32>(gs->map->objects.size()));
o->ID = ID;
o->subID = subID;
o->pos = pos;
o->appearance = handler->getTemplates(terrainType).front();
id = o->id = ObjectInstanceID(static_cast<si32>(gs->map->objects.size()));
o->pos = targetPos - o->getVisitableOffset();
gs->map->objects.emplace_back(o);
gs->map->addBlockVisTiles(o);
o->initObj(gs->getRandomGenerator());
gs->map->calculateGuardingGreaturePositions();
logGlobal->debug("Added object id=%d; address=%x; name=%s", id, (intptr_t)o, o->getObjectName());
createdObjectID = o->id;
logGlobal->debug("Added object id=%d; address=%x; name=%s", o->id, (intptr_t)o, o->getObjectName());
}
void NewArtifact::applyGs(CGameState *gs)

View File

@ -454,6 +454,7 @@ void CGHeroInstance::onHeroVisit(const CGHeroInstance * h) const
NewObject no;
no.ID = Obj::BOAT;
no.subID = getBoatType().getNum();
no.targetPos = boatPos;
cb->sendAndApply(&no);

View File

@ -1294,22 +1294,6 @@ CGBoat::CGBoat()
layer = EPathfindingLayer::EEPathfindingLayer::SAIL;
}
int3 CGBoat::translatePos(const int3& pos, bool reverse /* = false */)
{
//pos - offset we want to place the boat at the map
//returned value - actual position as seen by game mechanics
//If reverse = true, then it's the opposite.
if (!reverse)
{
return pos + int3(1, 0, 0);
}
else
{
return pos - int3(1, 0, 0);
}
}
void CGSirens::initObj(CRandomGenerator & rand)
{
blockVisit = true;
@ -1409,8 +1393,7 @@ void CGShipyard::serializeJsonOptions(JsonSerializeFormat& handler)
BoatId CGShipyard::getBoatType() const
{
// In H3, external shipyard will always create same boat as castle
return EBoatId::CASTLE;
return createdBoat;
}
void CCartographer::onHeroVisit( const CGHeroInstance * h ) const

View File

@ -359,7 +359,6 @@ public:
std::array<std::string, PlayerColor::PLAYER_LIMIT_I> flagAnimations;
CGBoat();
static int3 translatePos(const int3 &pos, bool reverse = false);
template <typename Handler> void serialize(Handler &h, const int version)
{

View File

@ -201,7 +201,7 @@ ESpellCastResult SummonBoatMechanics::applyAdventureEffects(SpellCastEnvironment
{
ChangeObjPos cop;
cop.objid = nearest->id;
cop.nPos = CGBoat::translatePos(summonPos);
cop.nPos = summonPos;
env->apply(&cop);
}
else if(schoolLevel < 2) //none or basic level -> cannot create boat :(
@ -216,7 +216,7 @@ ESpellCastResult SummonBoatMechanics::applyAdventureEffects(SpellCastEnvironment
NewObject no;
no.ID = Obj::BOAT;
no.subID = BoatId(EBoatId::NECROPOLIS);
no.pos = CGBoat::translatePos(summonPos);
no.targetPos = summonPos;
env->apply(&no);
}
return ESpellCastResult::OK;

View File

@ -4432,7 +4432,7 @@ bool CGameHandler::hireHero(const CGObjectInstance *obj, ui8 hid, PlayerColor pl
NewObject no;
no.ID = Obj::BOAT;
no.subID = nh->getBoatType().getNum();
no.pos = hr.tile + int3(1,0,0);
no.targetPos = obj->visitablePos();
sendAndApply(&no);
hr.boatId = getTopObj(hr.tile)->id;
@ -5660,7 +5660,7 @@ bool CGameHandler::buildBoat(ObjectInstanceID objid, PlayerColor playerID)
NewObject no;
no.ID = Obj::BOAT;
no.subID = obj->getBoatType().getNum();
no.pos = tile + int3(1,0,0);
no.targetPos = tile;
sendAndApply(&no);
return true;
@ -5806,7 +5806,7 @@ bool CGameHandler::dig(const CGHeroInstance *h)
//create a hole
NewObject no;
no.ID = Obj::HOLE;
no.pos = h->visitablePos();
no.targetPos = h->visitablePos();
no.subID = 0;
sendAndApply(&no);
@ -7409,7 +7409,7 @@ const ObjectInstanceID CGameHandler::putNewObject(Obj ID, int subID, int3 pos)
NewObject no;
no.ID = ID; //creature
no.subID= subID;
no.pos = pos;
no.targetPos = pos;
sendAndApply(&no);
return no.id; //id field will be filled during applying on gs
return no.createdObjectID; //id field will be filled during applying on gs
}