mirror of
https://github.com/OTCv8/otclientv8.git
synced 2025-10-20 06:33:26 +02:00
Open sourced 90% of files
This commit is contained in:
537
src/client/mapview.cpp
Normal file
537
src/client/mapview.cpp
Normal file
@@ -0,0 +1,537 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "mapview.h"
|
||||
|
||||
#include "creature.h"
|
||||
#include "map.h"
|
||||
#include "tile.h"
|
||||
#include "statictext.h"
|
||||
#include "animatedtext.h"
|
||||
#include "missile.h"
|
||||
#include "shadermanager.h"
|
||||
#include "lightview.h"
|
||||
#include "localplayer.h"
|
||||
#include "game.h"
|
||||
#include "spritemanager.h"
|
||||
|
||||
#include <framework/graphics/graphics.h>
|
||||
#include <framework/graphics/image.h>
|
||||
#include <framework/graphics/framebuffermanager.h>
|
||||
#include <framework/core/eventdispatcher.h>
|
||||
#include <framework/core/application.h>
|
||||
#include <framework/core/resourcemanager.h>
|
||||
#include <framework/graphics/texturemanager.h>
|
||||
#include <framework/graphics/atlas.h>
|
||||
|
||||
#include <framework/util/extras.h>
|
||||
#include <framework/core/adaptiverenderer.h>
|
||||
|
||||
MapView::MapView()
|
||||
{
|
||||
m_lockedFirstVisibleFloor = -1;
|
||||
m_cachedFirstVisibleFloor = 7;
|
||||
m_cachedLastVisibleFloor = 7;
|
||||
m_fadeOutTime = 0;
|
||||
m_fadeInTime = 0;
|
||||
m_minimumAmbientLight = 0;
|
||||
m_optimizedSize = Size(g_map.getAwareRange().horizontal(), g_map.getAwareRange().vertical()) * g_sprites.spriteSize();
|
||||
|
||||
setVisibleDimension(Size(15, 11));
|
||||
}
|
||||
|
||||
MapView::~MapView()
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
VALIDATE(!g_app.isTerminated());
|
||||
#endif
|
||||
}
|
||||
|
||||
void MapView::drawTileTexts(const Rect& rect, const Rect& srcRect)
|
||||
{
|
||||
Position cameraPosition = getCameraPosition();
|
||||
Point drawOffset = srcRect.topLeft();
|
||||
float horizontalStretchFactor = rect.width() / (float)srcRect.width();
|
||||
float verticalStretchFactor = rect.height() / (float)srcRect.height();
|
||||
|
||||
auto player = g_game.getLocalPlayer();
|
||||
for (auto& tile : m_cachedVisibleTiles) {
|
||||
Position tilePos = tile.first->getPosition();
|
||||
if (tilePos.z != player->getPosition().z) continue;
|
||||
|
||||
Point p = transformPositionTo2D(tilePos, cameraPosition) - drawOffset;
|
||||
p.x *= horizontalStretchFactor;
|
||||
p.y *= verticalStretchFactor;
|
||||
p += rect.topLeft();
|
||||
p.y += 5;
|
||||
|
||||
tile.first->drawTexts(p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MapView::drawBackground(const Rect& rect, const TilePtr& crosshairTile) {
|
||||
Position cameraPosition = getCameraPosition();
|
||||
if (m_mustUpdateVisibleTilesCache) {
|
||||
updateVisibleTilesCache();
|
||||
}
|
||||
|
||||
if (g_game.getFeature(Otc::GameForceLight)) {
|
||||
m_drawLight = true;
|
||||
m_minimumAmbientLight = 0.05f;
|
||||
}
|
||||
|
||||
Rect srcRect = calcFramebufferSource(rect.size());
|
||||
g_drawQueue->setFrameBuffer(rect, m_optimizedSize, srcRect);
|
||||
|
||||
if (m_drawLight) {
|
||||
Light ambientLight;
|
||||
if (cameraPosition.z <= Otc::SEA_FLOOR)
|
||||
ambientLight = g_map.getLight();
|
||||
if (!m_lightTexture || m_lightTexture->getSize() != m_drawDimension)
|
||||
m_lightTexture = TexturePtr(new Texture(m_drawDimension, false, true));
|
||||
m_lightView = std::make_unique<LightView>(m_lightTexture, m_drawDimension, rect, srcRect, ambientLight.color,
|
||||
std::max<int>(m_minimumAmbientLight * 255, ambientLight.intensity));
|
||||
}
|
||||
|
||||
auto itm = m_cachedVisibleTiles.begin();
|
||||
auto end = m_cachedVisibleTiles.end();
|
||||
for (int z = m_cachedLastVisibleFloor; z >= m_cachedFirstFadingFloor; --z) {
|
||||
float fading = 1.0;
|
||||
if (m_floorFading > 0) {
|
||||
fading = 0.;
|
||||
if (m_floorFading > 0) {
|
||||
fading = stdext::clamp<float>((float)m_fadingFloorTimers[z].elapsed_millis() / (float)m_floorFading, 0.f, 1.f);
|
||||
if (z < m_cachedFirstVisibleFloor)
|
||||
fading = 1.0 - fading;
|
||||
}
|
||||
if (fading == 0) break;
|
||||
}
|
||||
|
||||
size_t floorStart = g_drawQueue->size();
|
||||
size_t lightFloorStart = m_lightView ? m_lightView->size() : 0;
|
||||
for (; itm != end; ++itm) {
|
||||
Position tilePos = itm->first->getPosition();
|
||||
if (tilePos.z != z)
|
||||
break;
|
||||
|
||||
|
||||
Point tileDrawPos = transformPositionTo2D(tilePos, cameraPosition);
|
||||
|
||||
if (m_lightView) {
|
||||
ItemPtr ground = itm->first->getGround();
|
||||
if (ground && ground->isGround() && !ground->isTranslucent()) {
|
||||
m_lightView->setFieldBrightness(tileDrawPos, lightFloorStart, 0);
|
||||
}
|
||||
}
|
||||
|
||||
itm->first->drawBottom(tileDrawPos, m_lightView.get());
|
||||
if (m_crosshair && itm->first == crosshairTile)
|
||||
{
|
||||
g_drawQueue->addTexturedRect(Rect(tileDrawPos, tileDrawPos + Otc::TILE_PIXELS - 1),
|
||||
m_crosshair, Rect(0, 0, m_crosshair->getSize()));
|
||||
}
|
||||
itm->first->drawTop(tileDrawPos, m_lightView.get());
|
||||
}
|
||||
for (const MissilePtr& missile : g_map.getFloorMissiles(z)) {
|
||||
missile->draw(transformPositionTo2D(missile->getPosition(), cameraPosition), true, m_lightView.get());
|
||||
}
|
||||
if (fading < 0.99)
|
||||
g_drawQueue->setOpacity(floorStart, fading);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MapView::drawForeground(const Rect& rect)
|
||||
{
|
||||
// this could happen if the player position is not known yet
|
||||
Position cameraPosition = getCameraPosition();
|
||||
if (!cameraPosition.isValid())
|
||||
return;
|
||||
|
||||
Rect srcRect = calcFramebufferSource(rect.size());
|
||||
Point drawOffset = srcRect.topLeft();
|
||||
float horizontalStretchFactor = rect.width() / (float)srcRect.width();
|
||||
float verticalStretchFactor = rect.height() / (float)srcRect.height();
|
||||
|
||||
// creatures
|
||||
std::vector<std::pair<CreaturePtr, Point>> creatures;
|
||||
for (const CreaturePtr& creature : g_map.getSpectatorsInRangeEx(cameraPosition, false, m_visibleDimension.width() / 2, m_visibleDimension.width() / 2 + 1, m_visibleDimension.height() / 2, m_visibleDimension.height() / 2 + 1)) {
|
||||
if (!creature->canBeSeen())
|
||||
continue;
|
||||
|
||||
PointF jumpOffset = creature->getJumpOffset();
|
||||
Point creatureOffset = Point(16 - creature->getDisplacementX(), -creature->getDisplacementY() - 2);
|
||||
Position pos = creature->getPrewalkingPosition();
|
||||
Point p = transformPositionTo2D(pos, cameraPosition) - drawOffset;
|
||||
p += (creature->getDrawOffset() + creatureOffset) - Point(stdext::round(jumpOffset.x), stdext::round(jumpOffset.y));
|
||||
p.x = p.x * horizontalStretchFactor;
|
||||
p.y = p.y * verticalStretchFactor;
|
||||
p += rect.topLeft();
|
||||
creatures.push_back(std::make_pair(creature, p));
|
||||
}
|
||||
|
||||
for (auto& c : creatures) {
|
||||
int flags = Otc::DrawIcons;
|
||||
if (m_drawNames) { flags |= Otc::DrawNames; }
|
||||
if ((!c.first->isLocalPlayer() || m_drawPlayerBars) && !m_drawHealthBarsOnTop) {
|
||||
if (m_drawHealthBars) { flags |= Otc::DrawBars; }
|
||||
if (m_drawManaBar) { flags |= Otc::DrawManaBar; }
|
||||
}
|
||||
c.first->drawInformation(c.second, g_map.isCovered(c.first->getPrewalkingPosition(), m_cachedFirstVisibleFloor), rect, flags);
|
||||
}
|
||||
|
||||
if (m_lightView) {
|
||||
g_drawQueue->add(m_lightView.release());
|
||||
}
|
||||
|
||||
// texts
|
||||
int limit = g_adaptiveRenderer.textsLimit();
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
for (const StaticTextPtr& staticText : g_map.getStaticTexts()) {
|
||||
Position pos = staticText->getPosition();
|
||||
|
||||
if (pos.z != cameraPosition.z && staticText->getMessageMode() == Otc::MessageNone)
|
||||
continue;
|
||||
if ((staticText->getMessageMode() != Otc::MessageSay && staticText->getMessageMode() != Otc::MessageYell)) {
|
||||
if (i == 0)
|
||||
continue;
|
||||
} else if (i == 1)
|
||||
continue;
|
||||
|
||||
Point p = transformPositionTo2D(pos, cameraPosition) - drawOffset + Point(8, 0);
|
||||
p.x *= horizontalStretchFactor;
|
||||
p.y *= verticalStretchFactor;
|
||||
p += rect.topLeft();
|
||||
staticText->drawText(p, rect);
|
||||
if (--limit == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
limit = g_adaptiveRenderer.textsLimit();
|
||||
for (const AnimatedTextPtr& animatedText : g_map.getAnimatedTexts()) {
|
||||
Position pos = animatedText->getPosition();
|
||||
|
||||
if (pos.z != cameraPosition.z)
|
||||
continue;
|
||||
|
||||
Point p = transformPositionTo2D(pos, cameraPosition) - drawOffset + Point(16, 8);
|
||||
p.x *= horizontalStretchFactor;
|
||||
p.y *= verticalStretchFactor;
|
||||
p += rect.topLeft();
|
||||
animatedText->drawText(p, rect);
|
||||
if (--limit == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
// tile texts
|
||||
drawTileTexts(rect, srcRect);
|
||||
|
||||
// bars on top
|
||||
if (m_drawHealthBarsOnTop) {
|
||||
for (auto& c : creatures) {
|
||||
int flags = 0;
|
||||
if ((!c.first->isLocalPlayer() || m_drawPlayerBars)) {
|
||||
if (m_drawHealthBars) { flags |= Otc::DrawBars; }
|
||||
if (m_drawManaBar) { flags |= Otc::DrawManaBar; }
|
||||
}
|
||||
c.first->drawInformation(c.second, g_map.isCovered(c.first->getPrewalkingPosition(), m_cachedFirstVisibleFloor), rect, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MapView::updateVisibleTilesCache()
|
||||
{
|
||||
// hidden
|
||||
}
|
||||
|
||||
void MapView::updateGeometry(const Size& visibleDimension, const Size& optimizedSize)
|
||||
{
|
||||
m_multifloor = true;
|
||||
m_visibleDimension = visibleDimension;
|
||||
m_drawDimension = visibleDimension + Size(3, 3);
|
||||
m_virtualCenterOffset = (m_drawDimension / 2 - Size(1, 1)).toPoint();
|
||||
m_visibleCenterOffset = m_virtualCenterOffset;
|
||||
m_optimizedSize = m_drawDimension * g_sprites.spriteSize();
|
||||
requestVisibleTilesCacheUpdate();
|
||||
}
|
||||
|
||||
void MapView::onTileUpdate(const Position& pos)
|
||||
{
|
||||
requestVisibleTilesCacheUpdate();
|
||||
}
|
||||
|
||||
void MapView::onMapCenterChange(const Position& pos)
|
||||
{
|
||||
requestVisibleTilesCacheUpdate();
|
||||
}
|
||||
|
||||
void MapView::lockFirstVisibleFloor(int firstVisibleFloor)
|
||||
{
|
||||
m_lockedFirstVisibleFloor = firstVisibleFloor;
|
||||
requestVisibleTilesCacheUpdate();
|
||||
}
|
||||
|
||||
void MapView::unlockFirstVisibleFloor()
|
||||
{
|
||||
m_lockedFirstVisibleFloor = -1;
|
||||
requestVisibleTilesCacheUpdate();
|
||||
}
|
||||
|
||||
void MapView::setVisibleDimension(const Size& visibleDimension)
|
||||
{
|
||||
//if(visibleDimension == m_visibleDimension)
|
||||
// return;
|
||||
|
||||
if(visibleDimension.width() % 2 != 1 || visibleDimension.height() % 2 != 1) {
|
||||
g_logger.traceError("visible dimension must be odd");
|
||||
return;
|
||||
}
|
||||
|
||||
if(visibleDimension < Size(3,3)) {
|
||||
g_logger.traceError("reach max zoom in");
|
||||
return;
|
||||
}
|
||||
|
||||
updateGeometry(visibleDimension, m_optimizedSize);
|
||||
}
|
||||
|
||||
void MapView::optimizeForSize(const Size& visibleSize)
|
||||
{
|
||||
updateGeometry(m_visibleDimension, visibleSize);
|
||||
}
|
||||
|
||||
void MapView::followCreature(const CreaturePtr& creature)
|
||||
{
|
||||
m_follow = true;
|
||||
m_followingCreature = creature;
|
||||
requestVisibleTilesCacheUpdate();
|
||||
}
|
||||
|
||||
void MapView::setCameraPosition(const Position& pos)
|
||||
{
|
||||
m_follow = false;
|
||||
m_customCameraPosition = pos;
|
||||
requestVisibleTilesCacheUpdate();
|
||||
}
|
||||
|
||||
Position MapView::getPosition(const Point& point, const Size& mapSize)
|
||||
{
|
||||
Position cameraPosition = getCameraPosition();
|
||||
|
||||
// if we have no camera, its impossible to get the tile
|
||||
if(!cameraPosition.isValid())
|
||||
return Position();
|
||||
|
||||
Rect srcRect = calcFramebufferSource(mapSize);
|
||||
float sh = srcRect.width() / (float)mapSize.width();
|
||||
float sv = srcRect.height() / (float)mapSize.height();
|
||||
|
||||
Point framebufferPos = Point(point.x * sh, point.y * sv);
|
||||
Point realPos = (framebufferPos + srcRect.topLeft());
|
||||
Point centerOffset = realPos / Otc::TILE_PIXELS;
|
||||
|
||||
Point tilePos2D = getVisibleCenterOffset() - m_drawDimension.toPoint() + centerOffset + Point(2,2);
|
||||
if(tilePos2D.x + cameraPosition.x < 0 && tilePos2D.y + cameraPosition.y < 0)
|
||||
return Position();
|
||||
|
||||
Position position = Position(tilePos2D.x, tilePos2D.y, 0) + cameraPosition;
|
||||
|
||||
if(!position.isValid())
|
||||
return Position();
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
Point MapView::getPositionOffset(const Point& point, const Size& mapSize)
|
||||
{
|
||||
Position cameraPosition = getCameraPosition();
|
||||
|
||||
// if we have no camera, its impossible to get the tile
|
||||
if (!cameraPosition.isValid())
|
||||
return Point(0, 0);
|
||||
|
||||
Rect srcRect = calcFramebufferSource(mapSize);
|
||||
float sh = srcRect.width() / (float)mapSize.width();
|
||||
float sv = srcRect.height() / (float)mapSize.height();
|
||||
|
||||
Point framebufferPos = Point(point.x * sh, point.y * sv);
|
||||
Point realPos = (framebufferPos + srcRect.topLeft());
|
||||
return Point(realPos.x % Otc::TILE_PIXELS, realPos.y % Otc::TILE_PIXELS);
|
||||
}
|
||||
|
||||
void MapView::move(int x, int y)
|
||||
{
|
||||
m_moveOffset.x += x;
|
||||
m_moveOffset.y += y;
|
||||
|
||||
int32_t tmp = m_moveOffset.x / g_sprites.spriteSize();
|
||||
bool requestTilesUpdate = false;
|
||||
if(tmp != 0) {
|
||||
m_customCameraPosition.x += tmp;
|
||||
m_moveOffset.x %= g_sprites.spriteSize();
|
||||
requestTilesUpdate = true;
|
||||
}
|
||||
|
||||
tmp = m_moveOffset.y / g_sprites.spriteSize();
|
||||
if(tmp != 0) {
|
||||
m_customCameraPosition.y += tmp;
|
||||
m_moveOffset.y %= g_sprites.spriteSize();
|
||||
requestTilesUpdate = true;
|
||||
}
|
||||
|
||||
if(requestTilesUpdate)
|
||||
requestVisibleTilesCacheUpdate();
|
||||
}
|
||||
|
||||
Rect MapView::calcFramebufferSource(const Size& destSize, bool inNextFrame)
|
||||
{
|
||||
float scaleFactor = g_sprites.spriteSize()/(float)Otc::TILE_PIXELS;
|
||||
Point drawOffset = ((m_drawDimension - m_visibleDimension - Size(1,1)).toPoint()/2) * g_sprites.spriteSize();
|
||||
if(isFollowingCreature())
|
||||
drawOffset += m_followingCreature->getWalkOffset(inNextFrame) * scaleFactor;
|
||||
|
||||
Size srcSize = destSize;
|
||||
Size srcVisible = m_visibleDimension * g_sprites.spriteSize();
|
||||
srcSize.scale(srcVisible, Fw::KeepAspectRatio);
|
||||
drawOffset.x += (srcVisible.width() - srcSize.width()) / 2;
|
||||
drawOffset.y += (srcVisible.height() - srcSize.height()) / 2;
|
||||
|
||||
return Rect(drawOffset, srcSize);
|
||||
}
|
||||
|
||||
int MapView::calcFirstVisibleFloor(bool forFading)
|
||||
{
|
||||
int z = 7;
|
||||
// return forced first visible floor
|
||||
if(m_lockedFirstVisibleFloor != -1) {
|
||||
z = m_lockedFirstVisibleFloor;
|
||||
} else {
|
||||
Position cameraPosition = getCameraPosition();
|
||||
|
||||
// this could happens if the player is not known yet
|
||||
if(cameraPosition.isValid()) {
|
||||
// avoid rendering multifloors in far views
|
||||
if(!m_multifloor) {
|
||||
z = cameraPosition.z;
|
||||
} else {
|
||||
// if nothing is limiting the view, the first visible floor is 0
|
||||
int firstFloor = 0;
|
||||
|
||||
// limits to underground floors while under sea level
|
||||
if(cameraPosition.z > Otc::SEA_FLOOR)
|
||||
firstFloor = std::max<int>(cameraPosition.z - Otc::AWARE_UNDEGROUND_FLOOR_RANGE, (int)Otc::UNDERGROUND_FLOOR);
|
||||
|
||||
// loop in 3x3 tiles around the camera
|
||||
for(int ix = -1; ix <= 1 && firstFloor < cameraPosition.z && !forFading; ++ix) {
|
||||
for(int iy = -1; iy <= 1 && firstFloor < cameraPosition.z; ++iy) {
|
||||
Position pos = cameraPosition.translated(ix, iy);
|
||||
|
||||
// process tiles that we can look through, e.g. windows, doors
|
||||
if((ix == 0 && iy == 0) || ((std::abs(ix) != std::abs(iy)) && g_map.isLookPossible(pos))) {
|
||||
Position upperPos = pos;
|
||||
Position coveredPos = pos;
|
||||
|
||||
while(coveredPos.coveredUp() && upperPos.up() && upperPos.z >= firstFloor) {
|
||||
// check tiles physically above
|
||||
TilePtr tile = g_map.getTile(upperPos);
|
||||
if(tile && tile->limitsFloorsView(!g_map.isLookPossible(pos))) {
|
||||
firstFloor = upperPos.z + 1;
|
||||
break;
|
||||
}
|
||||
|
||||
// check tiles geometrically above
|
||||
tile = g_map.getTile(coveredPos);
|
||||
if(tile && tile->limitsFloorsView(g_map.isLookPossible(pos))) {
|
||||
firstFloor = coveredPos.z + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
z = firstFloor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// just ensure the that the floor is in the valid range
|
||||
z = stdext::clamp<int>(z, 0, (int)Otc::MAX_Z);
|
||||
return z;
|
||||
}
|
||||
|
||||
int MapView::calcLastVisibleFloor()
|
||||
{
|
||||
if(!m_multifloor)
|
||||
return calcFirstVisibleFloor();
|
||||
|
||||
int z = 7;
|
||||
|
||||
Position cameraPosition = getCameraPosition();
|
||||
// this could happens if the player is not known yet
|
||||
if(cameraPosition.isValid()) {
|
||||
// view only underground floors when below sea level
|
||||
if(cameraPosition.z > Otc::SEA_FLOOR)
|
||||
z = cameraPosition.z + Otc::AWARE_UNDEGROUND_FLOOR_RANGE;
|
||||
else
|
||||
z = Otc::SEA_FLOOR;
|
||||
}
|
||||
|
||||
if(m_lockedFirstVisibleFloor != -1)
|
||||
z = std::max<int>(m_lockedFirstVisibleFloor, z);
|
||||
|
||||
// just ensure the that the floor is in the valid range
|
||||
z = stdext::clamp<int>(z, 0, (int)Otc::MAX_Z);
|
||||
return z;
|
||||
}
|
||||
|
||||
Point MapView::transformPositionTo2D(const Position& position, const Position& relativePosition) {
|
||||
return Point((m_virtualCenterOffset.x + (position.x - relativePosition.x) - (relativePosition.z - position.z)) * g_sprites.spriteSize(),
|
||||
(m_virtualCenterOffset.y + (position.y - relativePosition.y) - (relativePosition.z - position.z)) * g_sprites.spriteSize());
|
||||
}
|
||||
|
||||
|
||||
Position MapView::getCameraPosition()
|
||||
{
|
||||
if (isFollowingCreature()) {
|
||||
return m_followingCreature->getPrewalkingPosition();
|
||||
}
|
||||
|
||||
return m_customCameraPosition;
|
||||
}
|
||||
|
||||
void MapView::setDrawLights(bool enable)
|
||||
{
|
||||
m_drawLight = enable;
|
||||
}
|
||||
|
||||
void MapView::setCrosshair(const std::string& file)
|
||||
{
|
||||
if (file == "")
|
||||
m_crosshair = nullptr;
|
||||
else
|
||||
m_crosshair = g_textures.getTexture(file);
|
||||
}
|
||||
|
||||
/* vim: set ts=4 sw=4 et: */
|
Reference in New Issue
Block a user