52 m_mapViews.push_back(mapView);
57 auto it = std::find(m_mapViews.begin(), m_mapViews.end(), mapView);
58 if(it != m_mapViews.end())
68 mapView->onTileUpdate(pos);
77 m_tileBlocks[i].clear();
84 m_tilesRect =
Rect(65534, 65534, 0, 0);
89 for(
const auto& pair : m_knownCreatures) {
93 m_knownCreatures.clear();
96 m_floorMissiles[i].clear();
103 m_animatedTexts.clear();
104 m_staticTexts.clear();
112 if(thing->isItem() || thing->isCreature() || thing->isEffect()) {
117 if(thing->isMissile()) {
118 m_floorMissiles[pos.
z].push_back(thing->static_self_cast<
Missile>());
119 }
else if(thing->isAnimatedText()) {
124 for(
auto other : m_animatedTexts) {
125 if(other->getPosition() == pos) {
126 prevAnimatedText = other;
127 if(other->merge(animatedText)) {
134 if(prevAnimatedText) {
135 Point offset = prevAnimatedText->getOffset();
136 float t = prevAnimatedText->getTimer().ticksElapsed();
139 offset +=
Point(0, y);
141 offset.
y = std::min<int>(offset.
y, 12);
142 animatedText->setOffset(offset);
144 m_animatedTexts.push_back(animatedText);
146 }
else if(thing->isStaticText()) {
149 for(
auto other : m_staticTexts) {
151 if(other->getPosition() == pos && other->addMessage(staticText->getName(), staticText->getMessageMode(), staticText->getFirstMessage())) {
158 m_staticTexts.push_back(staticText);
163 thing->setPosition(pos);
173 return tile->getThing(stackPos);
183 if(thing->isMissile()) {
185 int z = missile->getPosition().z;
186 auto it = std::find(m_floorMissiles[
z].begin(), m_floorMissiles[
z].end(), missile);
187 if(it != m_floorMissiles[
z].end()) {
188 m_floorMissiles[
z].erase(it);
191 }
else if(thing->isAnimatedText()) {
193 auto it = std::find(m_animatedTexts.begin(), m_animatedTexts.end(), animatedText);
194 if(it != m_animatedTexts.end()) {
195 m_animatedTexts.erase(it);
198 }
else if(thing->isStaticText()) {
200 auto it = std::find(m_staticTexts.begin(), m_staticTexts.end(), staticText);
201 if(it != m_staticTexts.end()) {
202 m_staticTexts.erase(it);
205 }
else if(
const TilePtr& tile = thing->getTile())
206 ret = tile->removeThing(thing);
225 thing->static_self_cast<
Item>()->setColor(color);
226 else if(thing->isCreature()) {
227 const TilePtr& tile = thing->getTile();
233 topThing->static_self_cast<
Item>()->setColor(color);
244 else if(thing->isCreature()) {
245 const TilePtr& tile = thing->getTile();
257 for(
auto staticText : m_staticTexts) {
259 if(staticText->getPosition() == pos)
269 if(pos.
x < m_tilesRect.
left())
271 if(pos.
y < m_tilesRect.
top())
273 if(pos.
x > m_tilesRect.
right())
275 if(pos.
y > m_tilesRect.
bottom())
277 TileBlock& block = m_tileBlocks[pos.
z][getBlockIndex(pos)];
281 template <
typename... Items>
287 auto vec = {items...};
298 if(pos.
x < m_tilesRect.
left())
300 if(pos.
y < m_tilesRect.
top())
302 if(pos.
x > m_tilesRect.
right())
304 if(pos.
y > m_tilesRect.
bottom())
306 TileBlock& block = m_tileBlocks[pos.
z][getBlockIndex(pos)];
314 auto it = m_tileBlocks[pos.
z].find(getBlockIndex(pos));
315 if(it != m_tileBlocks[pos.
z].end())
316 return it->second.get(pos);
329 for(
const auto& pair : m_tileBlocks[
z]) {
333 tiles.push_back(tile);
339 for(
const auto& pair : m_tileBlocks[floor]) {
343 tiles.push_back(tile);
354 auto it = m_tileBlocks[pos.
z].find(getBlockIndex(pos));
355 if(it != m_tileBlocks[pos.
z].end()) {
365 for(
auto itt = m_staticTexts.begin();itt != m_staticTexts.end();) {
367 if(staticText->getPosition() == pos && staticText->getMessageMode() ==
Otc::MessageNone)
368 itt = m_staticTexts.erase(itt);
377 m_zoneFlags |= (
uint32)zone;
379 m_zoneFlags &= ~(
uint32)zone;
386 else if(m_zoneFlags == 0)
392 if((m_zoneFlags & zone) == zone)
393 m_zoneColors[zone] = color;
398 auto it = m_zoneColors.find(flag);
399 if(it == m_zoneColors.end())
444 std::map<Position, ItemPtr> ret;
447 for(
const auto& pair : m_tileBlocks[
z]) {
450 if(
unlikely(!tile || tile->isEmpty()))
452 for(
const ItemPtr& item : tile->getItems()) {
453 if(item->getId() == clientId) {
454 ret.insert(std::make_pair(tile->getPosition(), item));
468 m_knownCreatures[creature->
getId()] = creature;
473 auto it = m_knownCreatures.find(
id);
474 if(it == m_knownCreatures.end())
484 auto it = m_knownCreatures.find(
id);
485 if(it != m_knownCreatures.end())
486 m_knownCreatures.erase(it);
489 void Map::removeUnawareThings()
492 for(
const auto& pair : m_knownCreatures) {
499 for(
auto it = m_staticTexts.begin(); it != m_staticTexts.end();) {
502 it = m_staticTexts.erase(it);
510 std::unordered_map<uint, TileBlock>& tileBlocks = m_tileBlocks[
z];
511 for(
auto it = tileBlocks.begin(); it != tileBlocks.end();) {
513 bool blockEmpty =
true;
518 const Position& pos = tile->getPosition();
526 it = tileBlocks.erase(it);
536 if(m_centralPosition == centralPosition)
539 m_centralPosition = centralPosition;
541 removeUnawareThings();
548 if(!localPlayer || localPlayer->
getPosition() == m_centralPosition)
551 if(tile && tile->hasThing(localPlayer))
557 if(!localPlayer->isRemoved())
558 localPlayer->onDisappear();
559 localPlayer->setPosition(pos);
560 localPlayer->onAppear();
561 g_logger.debug(
"forced player position update");
566 mapView->onMapCenterChange(centralPosition);
588 std::vector<CreaturePtr> creatures;
599 for(
int iz=-minZRange; iz<=maxZRange; ++iz) {
600 for(
int iy=-minYRange; iy<=maxYRange; ++iy) {
601 for(
int ix=-minXRange; ix<=maxXRange; ++ix) {
607 creatures.insert(creatures.end(), tileCreatures.rbegin(), tileCreatures.rend());
625 while(tilePos.
coveredUp() && tilePos.
z >= firstFloor) {
638 while(tilePos.
coveredUp() && tilePos.
z >= firstFloor) {
642 for(
int x=0;x<2 && !done;++x) {
643 for(
int y=0;y<2 && !done;++y) {
665 while(groundedPos.
z != m_centralPosition.
z) {
666 if(groundedPos.
z > m_centralPosition.
z) {
667 if(groundedPos.
x == 65535 || groundedPos.
y == 65535)
672 if(groundedPos.
x == 0 || groundedPos.
y == 0)
677 return m_centralPosition.
isInRange(groundedPos, m_awareRange.
left,
685 m_awareRange = range;
686 removeUnawareThings();
729 struct LessNode : std::binary_function<std::pair<Node*, float>, std::pair<Node*, float>, bool> {
730 bool operator()(std::pair<Node*, float> a, std::pair<Node*, float> b)
const {
731 return b.second < a.second;
736 std::vector<Otc::Direction>& dirs = std::get<0>(ret);
741 if(startPos == goalPos) {
746 if(startPos.
z != goalPos.
z) {
765 std::unordered_map<Position, Node*, PositionHasher> nodes;
766 std::priority_queue<std::pair<Node*, float>, std::vector<std::pair<Node*, float>>, LessNode> searchList;
768 Node *currentNode =
new Node(startPos);
769 currentNode->pos = startPos;
770 nodes[startPos] = currentNode;
771 Node *foundNode =
nullptr;
773 if((
int)nodes.size() > maxComplexity) {
779 if(currentNode->pos == goalPos && (!foundNode || currentNode->cost < foundNode->cost))
780 foundNode = currentNode;
783 if(foundNode && currentNode->totalCost >= foundNode->cost)
786 for(
int i=-1;i<=1;++i) {
787 for(
int j=-1;j<=1;++j) {
791 bool wasSeen =
false;
792 bool hasCreature =
false;
793 bool isNotWalkable =
true;
794 bool isNotPathable =
true;
797 Position neighborPos = currentNode->pos.translated(i, j);
801 hasCreature = tile->hasCreature();
803 isNotPathable = !tile->isPathable();
804 speed = tile->getGroundSpeed();
811 if(isNotWalkable || isNotPathable)
816 float walkFactor = 0;
817 if(neighborPos != goalPos) {
837 Otc::Direction walkDir = currentNode->pos.getDirectionFromPosition(neighborPos);
843 float cost = currentNode->cost + (speed * walkFactor) / 100.0f;
846 if(nodes.find(neighborPos) == nodes.end()) {
847 neighborNode =
new Node(neighborPos);
848 nodes[neighborPos] = neighborNode;
850 neighborNode = nodes[neighborPos];
851 if(neighborNode->cost <= cost)
855 neighborNode->prev = currentNode;
856 neighborNode->cost = cost;
857 neighborNode->totalCost = neighborNode->cost + neighborPos.
distance(goalPos);
858 neighborNode->dir = walkDir;
859 searchList.push(std::make_pair(neighborNode, neighborNode->totalCost));
863 if(!searchList.empty()) {
864 currentNode = searchList.top().first;
867 currentNode =
nullptr;
871 currentNode = foundNode;
873 dirs.push_back(currentNode->dir);
874 currentNode = currentNode->prev;
877 std::reverse(dirs.begin(), dirs.end());