diff options
Diffstat (limited to 'src/gui/viewport.cpp')
-rw-r--r-- | src/gui/viewport.cpp | 345 |
1 files changed, 162 insertions, 183 deletions
diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp index a746fb03..cbd1f3f7 100644 --- a/src/gui/viewport.cpp +++ b/src/gui/viewport.cpp @@ -1,62 +1,61 @@ /* * The Mana World - * Copyright 2004 The Mana World Development Team + * Copyright (C) 2004 The Mana World Development Team * * This file is part of The Mana World. * - * The Mana World is free software; you can redistribute it and/or modify + * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * any later version. * - * The Mana World is distributed in the hope that it will be useful, + * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with The Mana World; if not, write to the Free Software + * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "viewport.h" - -#include <guichan/sdl/sdlinput.hpp> - -#include "gui.h" +#include "ministatus.h" #include "popupmenu.h" +#include "viewport.h" -#include "../simpleanimation.h" #include "../beingmanager.h" #include "../configuration.h" #include "../flooritemmanager.h" +#include "../game.h" #include "../graphics.h" +#include "../keyboardconfig.h" #include "../localplayer.h" #include "../map.h" #include "../monster.h" #include "../npc.h" +#include "../textmanager.h" -#include "../resources/animation.h" #include "../resources/monsterinfo.h" #include "../resources/resourcemanager.h" -#include "../resources/image.h" -#include "../resources/imageset.h" - -#include "../utils/tostring.h" -#include <cassert> +#include "../utils/stringutils.h" extern volatile int tick_time; -extern int get_elapsed_time(int start_time); Viewport::Viewport(): mMap(0), - mViewX(0.0f), - mViewY(0.0f), + mPixelViewX(0.0f), + mPixelViewY(0.0f), + mTileViewX(0), + mTileViewY(0), mShowDebugPath(false), mVisibleNames(false), mPlayerFollowMouse(false), +#ifdef TMWSERV_SUPPORT mLocalWalkTime(-1) +#else + mWalkTime(0) +#endif { setOpaque(false); addMouseListener(this); @@ -71,52 +70,7 @@ Viewport::Viewport(): config.addListener("ScrollRadius", this); config.addListener("visiblenames", this); - mPopupMenu = new PopupMenu(); - - // Load target cursors - loadTargetCursor("graphics/gui/target-cursor-blue-s.png", 44, 35, - false, Being::TC_SMALL); - loadTargetCursor("graphics/gui/target-cursor-red-s.png", 44, 35, - true, Being::TC_SMALL); - loadTargetCursor("graphics/gui/target-cursor-blue-m.png", 62, 44, - false, Being::TC_MEDIUM); - loadTargetCursor("graphics/gui/target-cursor-red-m.png", 62, 44, - true, Being::TC_MEDIUM); - loadTargetCursor("graphics/gui/target-cursor-blue-l.png", 82, 60, - false, Being::TC_LARGE); - loadTargetCursor("graphics/gui/target-cursor-red-l.png", 82, 60, - true, Being::TC_LARGE); -} - -void Viewport::loadTargetCursor(const std::string &filename, - int width, int height, - bool outRange, Being::TargetCursorSize size) -{ - assert(size >= Being::TC_SMALL); - assert(size < Being::NUM_TC); - - ImageSet* currentImageSet; - SimpleAnimation* currentCursor; - - ResourceManager *resman = ResourceManager::getInstance(); - - currentImageSet = resman->getImageSet(filename, width, height); - Animation *anim = new Animation(); - for (unsigned int i = 0; i < currentImageSet->size(); ++i) - { - anim->addFrame(currentImageSet->get(i), 75, 0, 0); - } - currentCursor = new SimpleAnimation(anim); - - if (outRange) - { - mOutRangeImages[size] = currentImageSet; - mTargetCursorOutRange[size] = currentCursor; - } - else { - mInRangeImages[size] = currentImageSet; - mTargetCursorInRange[size] = currentCursor; - } + mPopupMenu = new PopupMenu; } Viewport::~Viewport() @@ -124,14 +78,6 @@ Viewport::~Viewport() delete mPopupMenu; config.removeListener("visiblenames", this); - - for (int i = Being::TC_SMALL; i < Being::NUM_TC; i++) - { - delete mTargetCursorInRange[i]; - delete mTargetCursorOutRange[i]; - mInRangeImages[i]->decRef(); - mOutRangeImages[i]->decRef(); - } } void Viewport::setMap(Map *map) @@ -139,6 +85,8 @@ void Viewport::setMap(Map *map) mMap = map; } +extern MiniStatusWindow *miniStatusWindow; + void Viewport::draw(gcn::Graphics *gcnGraphics) { static int lastTick = tick_time; @@ -148,6 +96,10 @@ void Viewport::draw(gcn::Graphics *gcnGraphics) Graphics *graphics = static_cast<Graphics*>(gcnGraphics); + // Ensure the client doesn't freak out if a feature localplayer uses + // is dependent on a map. + player_node->mMapInitialized = true; + // Avoid freaking out when tick_time overflows if (tick_time < lastTick) { @@ -155,12 +107,22 @@ void Viewport::draw(gcn::Graphics *gcnGraphics) } // Calculate viewpoint +#ifdef TMWSERV_SUPPORT int midTileX = (graphics->getWidth() + mScrollCenterOffsetX) / 2; int midTileY = (graphics->getHeight() + mScrollCenterOffsetX) / 2; const Vector &playerPos = player_node->getPosition(); const int player_x = (int) playerPos.x - midTileX; const int player_y = (int) playerPos.y - midTileY; +#else + int midTileX = (graphics->getWidth() + mScrollCenterOffsetX) / 32 / 2; + int midTileY = (graphics->getHeight() + mScrollCenterOffsetY) / 32 / 2; + + int player_x = (player_node->mX - midTileX) * 32 + + player_node->getXOffset(); + int player_y = (player_node->mY - midTileY) * 32 + + player_node->getYOffset(); +#endif if (mScrollLaziness < 1) mScrollLaziness = 1; // Avoids division by zero @@ -168,34 +130,34 @@ void Viewport::draw(gcn::Graphics *gcnGraphics) // Apply lazy scrolling while (lastTick < tick_time) { - if (player_x > mViewX + mScrollRadius) + if (player_x > mPixelViewX + mScrollRadius) { - mViewX += (player_x - mViewX - mScrollRadius) / mScrollLaziness; + mPixelViewX += (player_x - mPixelViewX - mScrollRadius) / mScrollLaziness; } - if (player_x < mViewX - mScrollRadius) + if (player_x < mPixelViewX - mScrollRadius) { - mViewX += (player_x - mViewX + mScrollRadius) / mScrollLaziness; + mPixelViewX += (player_x - mPixelViewX + mScrollRadius) / mScrollLaziness; } - if (player_y > mViewY + mScrollRadius) + if (player_y > mPixelViewY + mScrollRadius) { - mViewY += (player_y - mViewY - mScrollRadius) / mScrollLaziness; + mPixelViewY += (player_y - mPixelViewY - mScrollRadius) / mScrollLaziness; } - if (player_y < mViewY - mScrollRadius) + if (player_y < mPixelViewY - mScrollRadius) { - mViewY += (player_y - mViewY + mScrollRadius) / mScrollLaziness; + mPixelViewY += (player_y - mPixelViewY + mScrollRadius) / mScrollLaziness; } lastTick++; } // Auto center when player is off screen - if ( player_x - mViewX > graphics->getWidth() / 2 - || mViewX - player_x > graphics->getWidth() / 2 - || mViewY - player_y > graphics->getHeight() / 2 - || player_y - mViewY > graphics->getHeight() / 2 + if ( player_x - mPixelViewX > graphics->getWidth() / 2 + || mPixelViewX - player_x > graphics->getWidth() / 2 + || mPixelViewY - player_y > graphics->getHeight() / 2 + || player_y - mPixelViewY > graphics->getHeight() / 2 ) { - mViewX = player_x; - mViewY = player_y; + mPixelViewX = player_x; + mPixelViewY = player_y; }; // Don't move camera so that the end of the map is on screen @@ -205,49 +167,62 @@ void Viewport::draw(gcn::Graphics *gcnGraphics) mMap->getHeight() * mMap->getTileHeight() - graphics->getHeight(); if (mMap) { - if (mViewX < 0) { - mViewX = 0; + if (mPixelViewX < 0) { + mPixelViewX = 0; } - if (mViewY < 0) { - mViewY = 0; + if (mPixelViewY < 0) { + mPixelViewY = 0; } - if (mViewX > viewXmax) { - mViewX = viewXmax; + if (mPixelViewX > viewXmax) { + mPixelViewX = viewXmax; } - if (mViewY > viewYmax) { - mViewY = viewYmax; + if (mPixelViewY > viewYmax) { + mPixelViewY = viewYmax; } } + mTileViewX = (int) (mPixelViewX + 16) / 32; + mTileViewY = (int) (mPixelViewY + 16) / 32; + // Draw tiles and sprites if (mMap) { - mMap->draw(graphics, (int) mViewX, (int) mViewY); - drawTargetCursor(graphics); // TODO: Draw the cursor with the sprite - drawTargetName(graphics); + mMap->draw(graphics, (int) mPixelViewX, (int) mPixelViewY); + if (mShowDebugPath) { - mMap->drawCollision(graphics, (int) mViewX, (int) mViewY); + mMap->drawCollision(graphics, + (int) mPixelViewX, + (int) mPixelViewY); #if 0 drawDebugPath(graphics); #endif } } + if (player_node->mUpdateName) + { + player_node->mUpdateName = false; + player_node->setName(player_node->getName()); + } + + + // Draw text + if (textManager) + { + textManager->draw(graphics, (int) mPixelViewX, (int) mPixelViewY); + } + // Draw player names, speech, and emotion sprite as needed Beings &beings = beingManager->getAll(); for (BeingIterator i = beings.begin(); i != beings.end(); i++) { - (*i)->drawSpeech(graphics, -(int) mViewX, -(int) mViewY); - if (mVisibleNames) - (*i)->drawName(graphics, -(int) mViewX, -(int) mViewY); - else if ((*i) == mSelectedBeing) - (*i)->drawName(graphics, -(int) mViewX, -(int) mViewY); - (*i)->drawEmotion(graphics, -(int) mViewX, -(int) mViewY); - - if (mShowDebugPath && !(*i)->getPath().empty()) - drawPath(graphics, (*i)->getPath()); + (*i)->drawSpeech(-(int) mPixelViewX, -(int) mPixelViewY); + (*i)->drawEmotion(graphics, -(int) mPixelViewX, -(int) mPixelViewY); } + if (miniStatusWindow) + miniStatusWindow->drawIcons(graphics); + // Draw contained widgets WindowContainer::draw(gcnGraphics); } @@ -263,67 +238,19 @@ void Viewport::logic() Uint8 button = SDL_GetMouseState(&mouseX, &mouseY); if (mPlayerFollowMouse && button & SDL_BUTTON(1) && +#ifdef TMWSERV_SUPPORT get_elapsed_time(mLocalWalkTime) >= walkingMouseDelay) { mLocalWalkTime = tick_time; - player_node->setDestination(mouseX + (int) mViewX, - mouseY + (int) mViewY); - } - - for (int i = Being::TC_SMALL; i < Being::NUM_TC; i++) + player_node->setDestination(mouseX + (int) mPixelViewX, + mouseY + (int) mPixelViewY); +#else + mWalkTime != player_node->mWalkTime) { - mTargetCursorInRange[i]->update(10); - mTargetCursorOutRange[i]->update(10); - } -} - -void Viewport::drawTargetCursor(Graphics *graphics) -{ - // Draw target marker if needed - Being *target = player_node->getTarget(); - if (target) - { - // Calculate target circle position - - // Find whether target is in range - const Vector &dist = - target->getPosition() - player_node->getPosition(); - const int rangeX = abs((int) dist.x); - const int rangeY = abs((int) dist.y); - const int attackRange = player_node->getAttackRange(); - - // Get the correct target cursors graphic - Being::TargetCursorSize cursorSize = target->getTargetCursorSize(); - Image* targetCursor; - if (rangeX > attackRange || rangeY > attackRange) - targetCursor = mTargetCursorOutRange[cursorSize]->getCurrentImage(); - else - targetCursor = mTargetCursorInRange[cursorSize]->getCurrentImage(); - - // Draw the target cursor at the correct position - int posX = target->getPixelX() - - targetCursor->getWidth() / 2 - (int) mViewX; - int posY = target->getPixelY() - 16 - - targetCursor->getHeight() / 2 - (int) mViewY; - - graphics->drawImage(targetCursor, posX, posY); - } -} - -void Viewport::drawTargetName(Graphics *graphics) -{ - // Draw target marker if needed - Being *target = player_node->getTarget(); - if (target && target->getType() == Being::MONSTER) - { - graphics->setFont(speechFont); - graphics->setColor(gcn::Color(255, 32, 32)); - - const MonsterInfo &mi = static_cast<Monster*>(target)->getInfo(); - int posX = target->getPixelX() - (int) mViewX; - int posY = target->getPixelY() + 16 - target->getHeight() - (int) mViewY; - - graphics->drawText(mi.getName(), posX, posY, gcn::Graphics::CENTER); + player_node->setDestination(mouseX / 32 + mTileViewX, + mouseY / 32 + mTileViewY); + mWalkTime = player_node->mWalkTime; +#endif } } @@ -333,8 +260,8 @@ void Viewport::drawDebugPath(Graphics *graphics) int mouseX, mouseY; SDL_GetMouseState(&mouseX, &mouseY); - const int mouseTileX = (mouseX + (int) mViewX) / 32; - const int mouseTileY = (mouseY + (int) mViewY) / 32; + const int mouseTileX = (mouseX + (int) mPixelViewX) / 32; + const int mouseTileY = (mouseY + (int) mPixelViewY) / 32; const Vector &playerPos = player_node->getPosition(); Path debugPath = mMap->findPath( @@ -350,8 +277,8 @@ void Viewport::drawPath(Graphics *graphics, const Path &path) graphics->setColor(gcn::Color(255, 0, 0)); for (Path::const_iterator i = path.begin(); i != path.end(); ++i) { - int squareX = i->x * 32 - (int) mViewX + 12; - int squareY = i->y * 32 - (int) mViewY + 12; + int squareX = i->x * 32 - (int) mPixelViewX + 12; + int squareY = i->y * 32 - (int) mPixelViewY + 12; graphics->fillRectangle(gcn::Rectangle(squareX, squareY, 8, 8)); graphics->drawText( @@ -366,10 +293,14 @@ void Viewport::mousePressed(gcn::MouseEvent &event) if (!mMap || !player_node || player_node->mAction == Being::DEAD) return; + // Check if we are busy + if (current_npc) + return; + mPlayerFollowMouse = false; - const int pixelx = event.getX() + (int) mViewX; - const int pixely = event.getY() + (int) mViewY; + const int pixelx = event.getX() + (int) mPixelViewX; + const int pixely = event.getY() + (int) mPixelViewY; const int tilex = pixelx / mMap->getTileWidth(); const int tiley = pixely / mMap->getTileHeight(); @@ -380,12 +311,13 @@ void Viewport::mousePressed(gcn::MouseEvent &event) FloorItem *floorItem; if ((being = beingManager->findBeingByPixel(pixelx, pixely)) && - being != player_node) + being != player_node) { - mPopupMenu->showPopup(event.getX(), event.getY(), being); - return; + mPopupMenu->showPopup(event.getX(), event.getY(), being); + return; } - else if((floorItem = floorItemManager->findByCoordinates(tilex, tiley))) + else if ((floorItem = floorItemManager->findByCoordinates(tilex, + tiley))) { mPopupMenu->showPopup(event.getX(), event.getY(), floorItem); return; @@ -403,24 +335,63 @@ void Viewport::mousePressed(gcn::MouseEvent &event) if (event.getButton() == gcn::MouseEvent::LEFT) { FloorItem *item; +#ifdef EATHENA_SUPPORT + Being *being; + // Interact with some being +// if ((being = beingManager->findBeing(tilex, tiley))) + if ((being = beingManager->findBeingByPixel(pixelx, pixely))) + { + switch (being->getType()) + { + case Being::NPC: + dynamic_cast<NPC*>(being)->talk(); + break; + + case Being::MONSTER: + case Being::PLAYER: + if (being->mAction == Being::DEAD) + break; + + if (player_node->withinAttackRange(being) || keyboard.isKeyActive(keyboard.KEY_ATTACK)) + { + player_node->setGotoTarget(being); + player_node->attack(being, !keyboard.isKeyActive(keyboard.KEY_TARGET)); + } + else + { + player_node->setDestination(tilex, tiley); + } + break; + + default: + break; + } + } // Pick up some item + else +#endif if ((item = floorItemManager->findByCoordinates(tilex, tiley))) { - player_node->pickUp(item); + player_node->pickUp(item); } // Just walk around else { +#ifdef TMWSERV_SUPPORT // FIXME: REALLY UGLY! Uint8 *keys = SDL_GetKeyState(NULL); if (!(keys[SDLK_LSHIFT] || keys[SDLK_RSHIFT]) && get_elapsed_time(mLocalWalkTime) >= walkingMouseDelay) { mLocalWalkTime = tick_time; - player_node->setDestination(event.getX() + (int) mViewX, - event.getY() + (int) mViewY); + player_node->setDestination(event.getX() + (int) mPixelViewX, + event.getY() + (int) mPixelViewY); } +#else + player_node->stopAttack(); + player_node->setDestination(tilex, tiley); +#endif mPlayerFollowMouse = true; } } @@ -443,13 +414,22 @@ void Viewport::mouseDragged(gcn::MouseEvent &event) if (!mMap || !player_node) return; +#ifdef TMWSERV_SUPPORT if (mPlayerFollowMouse && get_elapsed_time(mLocalWalkTime) >= walkingMouseDelay) { mLocalWalkTime = tick_time; - player_node->setDestination(event.getX() + (int) mViewX, - event.getY() + (int) mViewY); + player_node->setDestination(event.getX() + (int) mPixelViewX, + event.getY() + (int) mPixelViewY); } +#else + if (mPlayerFollowMouse && mWalkTime == player_node->mWalkTime) + { + int destX = event.getX() / 32 + mTileViewX; + int destY = event.getY() / 32 + mTileViewY; + player_node->setDestination(destX, destY); + } +#endif } void Viewport::mouseReleased(gcn::MouseEvent &event) @@ -478,9 +458,8 @@ void Viewport::mouseMoved(gcn::MouseEvent &event) if (!mMap || !player_node) return; - const int tilex = (event.getX() + (int) mViewX) / 32; - const int tiley = (event.getY() + (int) mViewY) / 32; + const int tilex = (event.getX() + (int) mPixelViewX) / 32; + const int tiley = (event.getY() + (int) mPixelViewY) / 32; mSelectedBeing = beingManager->findBeing(tilex, tiley); } - |