mirror of
https://github.com/vcmi/vcmi.git
synced 2025-07-07 00:58:39 +02:00
NewObject pack now receives visitable position instead of h3m position
This commit is contained in:
@ -961,7 +961,7 @@ void ApplyClientNetPackVisitor::visitNewObject(NewObject & pack)
|
|||||||
{
|
{
|
||||||
cl.invalidatePaths();
|
cl.invalidatePaths();
|
||||||
|
|
||||||
const CGObjectInstance *obj = cl.getObj(pack.id);
|
const CGObjectInstance *obj = cl.getObj(pack.createdObjectID);
|
||||||
if(CGI->mh)
|
if(CGI->mh)
|
||||||
CGI->mh->onObjectFadeIn(obj);
|
CGI->mh->onObjectFadeIn(obj);
|
||||||
|
|
||||||
|
@ -745,11 +745,14 @@ struct DLL_LINKAGE NewObject : public CPackForClient
|
|||||||
{
|
{
|
||||||
void applyGs(CGameState * gs);
|
void applyGs(CGameState * gs);
|
||||||
|
|
||||||
|
/// Object ID to create
|
||||||
Obj ID;
|
Obj ID;
|
||||||
|
/// Object secondary ID to create
|
||||||
ui32 subID = 0;
|
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;
|
virtual void visitTyped(ICPackVisitor & visitor) override;
|
||||||
|
|
||||||
@ -757,7 +760,7 @@ struct DLL_LINKAGE NewObject : public CPackForClient
|
|||||||
{
|
{
|
||||||
h & ID;
|
h & ID;
|
||||||
h & subID;
|
h & subID;
|
||||||
h & pos;
|
h & targetPos;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1492,32 +1492,20 @@ void NewObject::applyGs(CGameState *gs)
|
|||||||
{
|
{
|
||||||
TerrainId terrainType = ETerrainId::NONE;
|
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();
|
logGlobal->error("Attempt to create object outside map at %s!", targetPos.toString());
|
||||||
testObject.pos = pos;
|
return;
|
||||||
testObject.appearance = VLC->objtypeh->getHandlerFor(ID, subID)->getTemplates(ETerrainId::WATER).front();
|
}
|
||||||
|
|
||||||
[[maybe_unused]] const int3 previousXAxisTile = CGBoat::translatePos(pos, true);
|
const TerrainTile & t = gs->map->getTile(targetPos);
|
||||||
assert(gs->isInTheMap(previousXAxisTile) && (testObject.visitablePos() == previousXAxisTile));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const TerrainTile & t = gs->map->getTile(pos);
|
|
||||||
terrainType = t.terType->getId();
|
terrainType = t.terType->getId();
|
||||||
}
|
|
||||||
|
|
||||||
auto handler = VLC->objtypeh->getHandlerFor(ID, subID);
|
auto handler = VLC->objtypeh->getHandlerFor(ID, subID);
|
||||||
CGObjectInstance * o = handler->create();
|
CGObjectInstance * o = handler->create();
|
||||||
handler->configureObject(o, gs->getRandomGenerator());
|
handler->configureObject(o, gs->getRandomGenerator());
|
||||||
|
|
||||||
switch(ID)
|
if (ID == Obj::MONSTER) //probably more options will be needed
|
||||||
{
|
|
||||||
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
|
|
||||||
{
|
{
|
||||||
//CStackInstance hlp;
|
//CStackInstance hlp;
|
||||||
auto * cre = dynamic_cast<CGCreature *>(o);
|
auto * cre = dynamic_cast<CGCreature *>(o);
|
||||||
@ -1529,20 +1517,27 @@ void NewObject::applyGs(CGameState *gs)
|
|||||||
cre->identifier = -1;
|
cre->identifier = -1;
|
||||||
cre->addToSlot(SlotID(0), new CStackInstance(CreatureID(subID), -1)); //add placeholder stack
|
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->ID = ID;
|
||||||
o->subID = subID;
|
o->subID = subID;
|
||||||
o->pos = pos;
|
o->pos = targetPos - o->getVisitableOffset();
|
||||||
o->appearance = handler->getTemplates(terrainType).front();
|
|
||||||
id = o->id = ObjectInstanceID(static_cast<si32>(gs->map->objects.size()));
|
|
||||||
|
|
||||||
gs->map->objects.emplace_back(o);
|
gs->map->objects.emplace_back(o);
|
||||||
gs->map->addBlockVisTiles(o);
|
gs->map->addBlockVisTiles(o);
|
||||||
o->initObj(gs->getRandomGenerator());
|
o->initObj(gs->getRandomGenerator());
|
||||||
gs->map->calculateGuardingGreaturePositions();
|
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)
|
void NewArtifact::applyGs(CGameState *gs)
|
||||||
|
@ -454,6 +454,7 @@ void CGHeroInstance::onHeroVisit(const CGHeroInstance * h) const
|
|||||||
NewObject no;
|
NewObject no;
|
||||||
no.ID = Obj::BOAT;
|
no.ID = Obj::BOAT;
|
||||||
no.subID = getBoatType().getNum();
|
no.subID = getBoatType().getNum();
|
||||||
|
no.targetPos = boatPos;
|
||||||
|
|
||||||
cb->sendAndApply(&no);
|
cb->sendAndApply(&no);
|
||||||
|
|
||||||
|
@ -1294,22 +1294,6 @@ CGBoat::CGBoat()
|
|||||||
layer = EPathfindingLayer::EEPathfindingLayer::SAIL;
|
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)
|
void CGSirens::initObj(CRandomGenerator & rand)
|
||||||
{
|
{
|
||||||
blockVisit = true;
|
blockVisit = true;
|
||||||
@ -1409,8 +1393,7 @@ void CGShipyard::serializeJsonOptions(JsonSerializeFormat& handler)
|
|||||||
|
|
||||||
BoatId CGShipyard::getBoatType() const
|
BoatId CGShipyard::getBoatType() const
|
||||||
{
|
{
|
||||||
// In H3, external shipyard will always create same boat as castle
|
return createdBoat;
|
||||||
return EBoatId::CASTLE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCartographer::onHeroVisit( const CGHeroInstance * h ) const
|
void CCartographer::onHeroVisit( const CGHeroInstance * h ) const
|
||||||
|
@ -359,7 +359,6 @@ public:
|
|||||||
std::array<std::string, PlayerColor::PLAYER_LIMIT_I> flagAnimations;
|
std::array<std::string, PlayerColor::PLAYER_LIMIT_I> flagAnimations;
|
||||||
|
|
||||||
CGBoat();
|
CGBoat();
|
||||||
static int3 translatePos(const int3 &pos, bool reverse = false);
|
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
|
@ -201,7 +201,7 @@ ESpellCastResult SummonBoatMechanics::applyAdventureEffects(SpellCastEnvironment
|
|||||||
{
|
{
|
||||||
ChangeObjPos cop;
|
ChangeObjPos cop;
|
||||||
cop.objid = nearest->id;
|
cop.objid = nearest->id;
|
||||||
cop.nPos = CGBoat::translatePos(summonPos);
|
cop.nPos = summonPos;
|
||||||
env->apply(&cop);
|
env->apply(&cop);
|
||||||
}
|
}
|
||||||
else if(schoolLevel < 2) //none or basic level -> cannot create boat :(
|
else if(schoolLevel < 2) //none or basic level -> cannot create boat :(
|
||||||
@ -216,7 +216,7 @@ ESpellCastResult SummonBoatMechanics::applyAdventureEffects(SpellCastEnvironment
|
|||||||
NewObject no;
|
NewObject no;
|
||||||
no.ID = Obj::BOAT;
|
no.ID = Obj::BOAT;
|
||||||
no.subID = BoatId(EBoatId::NECROPOLIS);
|
no.subID = BoatId(EBoatId::NECROPOLIS);
|
||||||
no.pos = CGBoat::translatePos(summonPos);
|
no.targetPos = summonPos;
|
||||||
env->apply(&no);
|
env->apply(&no);
|
||||||
}
|
}
|
||||||
return ESpellCastResult::OK;
|
return ESpellCastResult::OK;
|
||||||
|
@ -4432,7 +4432,7 @@ bool CGameHandler::hireHero(const CGObjectInstance *obj, ui8 hid, PlayerColor pl
|
|||||||
NewObject no;
|
NewObject no;
|
||||||
no.ID = Obj::BOAT;
|
no.ID = Obj::BOAT;
|
||||||
no.subID = nh->getBoatType().getNum();
|
no.subID = nh->getBoatType().getNum();
|
||||||
no.pos = hr.tile + int3(1,0,0);
|
no.targetPos = obj->visitablePos();
|
||||||
sendAndApply(&no);
|
sendAndApply(&no);
|
||||||
|
|
||||||
hr.boatId = getTopObj(hr.tile)->id;
|
hr.boatId = getTopObj(hr.tile)->id;
|
||||||
@ -5660,7 +5660,7 @@ bool CGameHandler::buildBoat(ObjectInstanceID objid, PlayerColor playerID)
|
|||||||
NewObject no;
|
NewObject no;
|
||||||
no.ID = Obj::BOAT;
|
no.ID = Obj::BOAT;
|
||||||
no.subID = obj->getBoatType().getNum();
|
no.subID = obj->getBoatType().getNum();
|
||||||
no.pos = tile + int3(1,0,0);
|
no.targetPos = tile;
|
||||||
sendAndApply(&no);
|
sendAndApply(&no);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -5806,7 +5806,7 @@ bool CGameHandler::dig(const CGHeroInstance *h)
|
|||||||
//create a hole
|
//create a hole
|
||||||
NewObject no;
|
NewObject no;
|
||||||
no.ID = Obj::HOLE;
|
no.ID = Obj::HOLE;
|
||||||
no.pos = h->visitablePos();
|
no.targetPos = h->visitablePos();
|
||||||
no.subID = 0;
|
no.subID = 0;
|
||||||
sendAndApply(&no);
|
sendAndApply(&no);
|
||||||
|
|
||||||
@ -7409,7 +7409,7 @@ const ObjectInstanceID CGameHandler::putNewObject(Obj ID, int subID, int3 pos)
|
|||||||
NewObject no;
|
NewObject no;
|
||||||
no.ID = ID; //creature
|
no.ID = ID; //creature
|
||||||
no.subID= subID;
|
no.subID= subID;
|
||||||
no.pos = pos;
|
no.targetPos = pos;
|
||||||
sendAndApply(&no);
|
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
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user