| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347 | 
							- /*
 
-  * RmgObject.cpp, part of VCMI engine
 
-  *
 
-  * Authors: listed in file AUTHORS in main folder
 
-  *
 
-  * License: GNU General Public License v2.0 or later
 
-  * Full text of license available in license.txt file, in main folder
 
-  *
 
-  */
 
- #include "StdInc.h"
 
- #include "RmgObject.h"
 
- #include "RmgMap.h"
 
- #include "../mapObjects/CObjectHandler.h"
 
- #include "../mapping/CMapEditManager.h"
 
- #include "../mapping/CMap.h"
 
- #include "../VCMI_Lib.h"
 
- #include "../mapObjects/CommonConstructors.h"
 
- #include "../mapObjects/MapObjects.h" //needed to resolve templates for CommonConstructors.h
 
- #include "Functions.h"
 
- #include "../TerrainHandler.h"
 
- VCMI_LIB_NAMESPACE_BEGIN
 
- using namespace rmg;
 
- Object::Instance::Instance(const Object& parent, CGObjectInstance & object): dParent(parent), dObject(object)
 
- {
 
- 	setPosition(dPosition);
 
- }
 
- Object::Instance::Instance(const Object& parent, CGObjectInstance & object, const int3 & position): Instance(parent, object)
 
- {
 
- 	setPosition(position);
 
- }
 
- const Area & Object::Instance::getBlockedArea() const
 
- {
 
- 	if(dBlockedAreaCache.empty())
 
- 	{
 
- 		dBlockedAreaCache.assign(dObject.getBlockedPos());
 
- 		if(dObject.isVisitable() || dBlockedAreaCache.empty())
 
- 			dBlockedAreaCache.add(dObject.visitablePos());
 
- 	}
 
- 	return dBlockedAreaCache;
 
- }
 
- int3 Object::Instance::getPosition(bool isAbsolute) const
 
- {
 
- 	if(isAbsolute)
 
- 		return dPosition + dParent.getPosition();
 
- 	else
 
- 		return dPosition;
 
- }
 
- int3 Object::Instance::getVisitablePosition() const
 
- {
 
- 	return dObject.visitablePos();
 
- }
 
- const rmg::Area & Object::Instance::getAccessibleArea() const
 
- {
 
- 	if(dAccessibleAreaCache.empty())
 
- 	{
 
- 		auto neighbours = rmg::Area({getVisitablePosition()}).getBorderOutside();
 
- 		rmg::Area visitable = rmg::Area(neighbours) - getBlockedArea();
 
- 		for(auto & from : visitable.getTiles())
 
- 		{
 
- 			if(isVisitableFrom(from))
 
- 				dAccessibleAreaCache.add(from);
 
- 		}
 
- 	}
 
- 	return dAccessibleAreaCache;
 
- }
 
- void Object::Instance::setPosition(const int3 & position)
 
- {
 
- 	dPosition = position;
 
- 	dObject.pos = dPosition + dParent.getPosition();
 
- 	
 
- 	dBlockedAreaCache.clear();
 
- 	dAccessibleAreaCache.clear();
 
- 	dParent.dAccessibleAreaCache.clear();
 
- 	dParent.dAccessibleAreaFullCache.clear();
 
- 	dParent.dFullAreaCache.clear();
 
- }
 
- void Object::Instance::setPositionRaw(const int3 & position)
 
- {
 
- 	if(!dObject.pos.valid())
 
- 	{
 
- 		dObject.pos = dPosition + dParent.getPosition();
 
- 		dBlockedAreaCache.clear();
 
- 		dAccessibleAreaCache.clear();
 
- 		dParent.dAccessibleAreaCache.clear();
 
- 		dParent.dAccessibleAreaFullCache.clear();
 
- 		dParent.dFullAreaCache.clear();
 
- 	}
 
- 		
 
- 	auto shift = position + dParent.getPosition() - dObject.pos;
 
- 	
 
- 	dAccessibleAreaCache.translate(shift);
 
- 	dBlockedAreaCache.translate(shift);
 
- 	
 
- 	dPosition = position;
 
- 	dObject.pos = dPosition + dParent.getPosition();
 
- }
 
- void Object::Instance::setAnyTemplate()
 
- {
 
- 	auto templates = VLC->objtypeh->getHandlerFor(dObject.ID, dObject.subID)->getTemplates();
 
- 	if(templates.empty())
 
- 		throw rmgException(boost::to_string(boost::format("Did not find any graphics for object (%d,%d)") % dObject.ID % dObject.subID));
 
- 	dObject.appearance = templates.front();
 
- 	dAccessibleAreaCache.clear();
 
- 	setPosition(getPosition(false));
 
- }
 
- void Object::Instance::setTemplate(TerrainId terrain)
 
- {
 
- 	auto templates = VLC->objtypeh->getHandlerFor(dObject.ID, dObject.subID)->getTemplates(terrain);
 
- 	if (templates.empty())
 
- 	{
 
- 		auto terrainName = VLC->terrainTypeHandler->getById(terrain)->getNameTranslated();
 
- 		throw rmgException(boost::to_string(boost::format("Did not find graphics for object (%d,%d) at %s") % dObject.ID % dObject.subID % terrainName));
 
- 	}
 
- 	dObject.appearance = templates.front();
 
- 	dAccessibleAreaCache.clear();
 
- 	setPosition(getPosition(false));
 
- }
 
- void Object::Instance::clear()
 
- {
 
- 	delete &dObject;
 
- 	dBlockedAreaCache.clear();
 
- 	dAccessibleAreaCache.clear();
 
- 	dParent.dAccessibleAreaCache.clear();
 
- 	dParent.dAccessibleAreaFullCache.clear();
 
- 	dParent.dFullAreaCache.clear();
 
- }
 
- bool Object::Instance::isVisitableFrom(const int3 & position) const
 
- {
 
- 	auto relPosition = position - getPosition(true);
 
- 	return dObject.appearance->isVisitableFrom(relPosition.x, relPosition.y);
 
- }
 
- CGObjectInstance & Object::Instance::object()
 
- {
 
- 	return dObject;
 
- }
 
- const CGObjectInstance & Object::Instance::object() const
 
- {
 
- 	return dObject;
 
- }
 
- Object::Object(CGObjectInstance & object, const int3 & position)
 
- {
 
- 	addInstance(object, position);
 
- }
 
- Object::Object(CGObjectInstance & object)
 
- {
 
- 	addInstance(object);
 
- }
 
- Object::Object(const Object & object)
 
- {
 
- 	dStrenght = object.dStrenght;
 
- 	for(auto & i : object.dInstances)
 
- 		addInstance(const_cast<CGObjectInstance &>(i.object()), i.getPosition());
 
- 	setPosition(object.getPosition());
 
- }
 
- std::list<Object::Instance*> Object::instances()
 
- {
 
- 	std::list<Object::Instance*> result;
 
- 	for(auto & i : dInstances)
 
- 		result.push_back(&i);
 
- 	return result;
 
- }
 
- std::list<const Object::Instance*> Object::instances() const
 
- {
 
- 	std::list<const Object::Instance*> result;
 
- 	for(const auto & i : dInstances)
 
- 		result.push_back(&i);
 
- 	return result;
 
- }
 
- void Object::addInstance(Instance & object)
 
- {
 
- 	//assert(object.dParent == *this);
 
- 	dInstances.push_back(object);
 
- 	dFullAreaCache.clear();
 
- 	dAccessibleAreaCache.clear();
 
- 	dAccessibleAreaFullCache.clear();
 
- }
 
- Object::Instance & Object::addInstance(CGObjectInstance & object)
 
- {
 
- 	dInstances.emplace_back(*this, object);
 
- 	dFullAreaCache.clear();
 
- 	dAccessibleAreaCache.clear();
 
- 	dAccessibleAreaFullCache.clear();
 
- 	return dInstances.back();
 
- }
 
- Object::Instance & Object::addInstance(CGObjectInstance & object, const int3 & position)
 
- {
 
- 	dInstances.emplace_back(*this, object, position);
 
- 	dFullAreaCache.clear();
 
- 	dAccessibleAreaCache.clear();
 
- 	dAccessibleAreaFullCache.clear();
 
- 	return dInstances.back();
 
- }
 
- const int3 & Object::getPosition() const
 
- {
 
- 	return dPosition;
 
- }
 
- int3 Object::getVisitablePosition() const
 
- {
 
- 	assert(!dInstances.empty());
 
- 	for(auto & instance : dInstances)
 
- 		if(!getArea().contains(instance.getVisitablePosition()))
 
- 			return instance.getVisitablePosition();
 
- 	
 
- 	return dInstances.back().getVisitablePosition(); //fallback - return position of last object
 
- }
 
- const rmg::Area & Object::getAccessibleArea(bool exceptLast) const
 
- {
 
- 	if(dInstances.empty())
 
- 		return dAccessibleAreaFullCache;
 
- 	if(exceptLast && !dAccessibleAreaCache.empty())
 
- 		return dAccessibleAreaCache;
 
- 	if(!exceptLast && !dAccessibleAreaFullCache.empty())
 
- 		return dAccessibleAreaFullCache;
 
- 	
 
- 	for(auto i = dInstances.begin(); i != std::prev(dInstances.end()); ++i)
 
- 		dAccessibleAreaCache.unite(i->getAccessibleArea());
 
- 	
 
- 	dAccessibleAreaFullCache = dAccessibleAreaCache;
 
- 	dAccessibleAreaFullCache.unite(dInstances.back().getAccessibleArea());
 
- 	dAccessibleAreaCache.subtract(getArea());
 
- 	dAccessibleAreaFullCache.subtract(getArea());
 
- 	
 
- 	if(exceptLast)
 
- 		return dAccessibleAreaCache;
 
- 	else
 
- 		return dAccessibleAreaFullCache;
 
- }
 
- void Object::setPosition(const int3 & position)
 
- {
 
- 	dAccessibleAreaCache.translate(position - dPosition);
 
- 	dAccessibleAreaFullCache.translate(position - dPosition);
 
- 	dFullAreaCache.translate(position - dPosition);
 
- 	
 
- 	dPosition = position;
 
- 	for(auto& i : dInstances)
 
- 		i.setPositionRaw(i.getPosition());
 
- }
 
- void Object::setTemplate(const TerrainId & terrain)
 
- {
 
- 	for(auto& i : dInstances)
 
- 		i.setTemplate(terrain);
 
- }
 
- const Area & Object::getArea() const
 
- {
 
- 	if(!dFullAreaCache.empty() || dInstances.empty())
 
- 		return dFullAreaCache;
 
- 	
 
- 	for(const auto & instance : dInstances)
 
- 	{
 
- 		dFullAreaCache.unite(instance.getBlockedArea());
 
- 	}
 
- 	
 
- 	return dFullAreaCache;
 
- }
 
- void Object::Instance::finalize(RmgMap & map)
 
- {
 
- 	if(!map.isOnMap(getPosition(true)))
 
- 		throw rmgException(boost::to_string(boost::format("Position of object %d at %s is outside the map") % dObject.id % getPosition(true).toString()));
 
- 	
 
- 	//If no specific template was defined for this object, select any matching
 
- 	if (!dObject.appearance)
 
- 	{
 
- 		auto terrainType = map.map().getTile(getPosition(true)).terType;
 
- 		auto templates = VLC->objtypeh->getHandlerFor(dObject.ID, dObject.subID)->getTemplates(terrainType->getId());
 
- 		if (templates.empty())
 
- 		{
 
- 			throw rmgException(boost::to_string(boost::format("Did not find graphics for object (%d,%d) at %s (terrain %d)") % dObject.ID % dObject.subID % getPosition(true).toString() % terrainType));
 
- 		}
 
- 		else
 
- 		{
 
- 			setTemplate(terrainType->getId());
 
- 		}
 
- 	}
 
- 	if (dObject.isVisitable() && !map.isOnMap(dObject.visitablePos()))
 
- 		throw rmgException(boost::to_string(boost::format("Visitable tile %s of object %d at %s is outside the map") % dObject.visitablePos().toString() % dObject.id % dObject.pos.toString()));
 
- 	
 
- 	for (auto & tile : dObject.getBlockedPos())
 
- 	{
 
- 		if(!map.isOnMap(tile))
 
- 			throw rmgException(boost::to_string(boost::format("Tile %s of object %d at %s is outside the map") % tile.toString() % dObject.id % dObject.pos.toString()));
 
- 	}
 
- 	
 
- 	for(auto & tile : getBlockedArea().getTilesVector())
 
- 	{
 
- 		map.setOccupied(tile, ETileType::ETileType::USED);
 
- 	}
 
- 	
 
- 	map.getEditManager()->insertObject(&dObject);
 
- }
 
- void Object::finalize(RmgMap & map)
 
- {
 
- 	if(dInstances.empty())
 
- 		throw rmgException("Cannot finalize object without instances");
 
- 	
 
- 	for(auto iter = dInstances.begin(); iter != dInstances.end(); ++iter)
 
- 	{
 
- 		iter->finalize(map);
 
- 	}
 
- }
 
- void Object::clear()
 
- {
 
- 	for(auto & instance : dInstances)
 
- 		instance.clear();
 
- 	dInstances.clear();
 
- 	dFullAreaCache.clear();
 
- 	dAccessibleAreaCache.clear();
 
- 	dAccessibleAreaFullCache.clear();
 
- }
 
-  
 
- VCMI_LIB_NAMESPACE_END
 
 
  |