From 8546361abaa6123acd9dc1429575d1fd1cf6a4ec Mon Sep 17 00:00:00 2001 From: Thorbjørn Lindeijer Date: Sat, 2 Mar 2024 16:01:51 +0100 Subject: Added support for customizing NPC and Monster hover cursor To match support for this in M+, since TMW uses this functionality on two of its NPCs. --- src/being.cpp | 23 +++++++++--------- src/being.h | 3 +++ src/gui/viewport.cpp | 9 ++----- src/log.cpp | 16 +++--------- src/log.h | 2 +- src/resources/beinginfo.cpp | 59 ++++++++++++++++++++++++++++++++++----------- src/resources/beinginfo.h | 10 ++++++++ src/resources/monsterdb.cpp | 4 ++- src/resources/npcdb.cpp | 4 ++- 9 files changed, 82 insertions(+), 48 deletions(-) diff --git a/src/being.cpp b/src/being.cpp index 6b21198a..98ba78e1 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -49,7 +49,6 @@ #include "net/npchandler.h" #include "resources/beinginfo.h" -#include "resources/image.h" #include "resources/itemdb.h" #include "resources/iteminfo.h" #include "resources/monsterdb.h" @@ -129,6 +128,11 @@ ActorSprite::TargetCursorSize Being::getTargetCursorSize() const return mInfo->getTargetCursorSize(); } +Cursor Being::getHoverCursor() const +{ + return mInfo->getHoverCursor(); +} + unsigned char Being::getWalkMask() const { return mInfo->getWalkMask(); @@ -345,17 +349,14 @@ void Being::takeDamage(Being *attacker, int amount, if (amount > 0) { - if (mInfo) + if (attacker) { - if (attacker) - { - sound.playSfx(mInfo->getSound(SOUND_EVENT_HURT), - attacker->getPixelX(), attacker->getPixelY()); - } - else - { - sound.playSfx(mInfo->getSound(SOUND_EVENT_HURT)); - } + sound.playSfx(mInfo->getSound(SOUND_EVENT_HURT), + attacker->getPixelX(), attacker->getPixelY()); + } + else + { + sound.playSfx(mInfo->getSound(SOUND_EVENT_HURT)); } if (getType() == MONSTER) diff --git a/src/being.h b/src/being.h index 4fdef2c5..411db3b7 100644 --- a/src/being.h +++ b/src/being.h @@ -24,6 +24,7 @@ #include "actorsprite.h" #include "eventlistener.h" +#include "gui/gui.h" #include "map.h" #include "position.h" #include "vector.h" @@ -297,6 +298,8 @@ class Being : public ActorSprite, public EventListener TargetCursorSize getTargetCursorSize() const override; + Cursor getHoverCursor() const; + /** * Gets the way the object is blocked by other objects. */ diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp index 9db1707c..8c174c8d 100644 --- a/src/gui/viewport.cpp +++ b/src/gui/viewport.cpp @@ -587,17 +587,12 @@ void Viewport::updateCursorType() { switch (mHoverBeing->getType()) { - // NPCs case ActorSprite::NPC: - gui->setCursorType(Cursor::TALK); - break; - - // Monsters case ActorSprite::MONSTER: - gui->setCursorType(Cursor::FIGHT); + gui->setCursorType(mHoverBeing->getHoverCursor()); break; default: - gui->setCursorType(Cursor::POINTER); + gui->setCursorType(Cursor::POINTER); break; } // Item mouseover diff --git a/src/log.cpp b/src/log.cpp index 47fe5e0f..6921750e 100644 --- a/src/log.cpp +++ b/src/log.cpp @@ -29,18 +29,8 @@ #include #include -Logger::Logger(): - mLogToStandardOut(true) -{ -} - -Logger::~Logger() -{ - if (mLogFile.is_open()) - { - mLogFile.close(); - } -} +Logger::Logger() = default; +Logger::~Logger() = default; void Logger::setLogFile(const std::string &logFilename) { @@ -102,6 +92,6 @@ void Logger::error(const std::string &error_text) { log("Error: %s", error_text.c_str()); std::cerr << "Error: " << error_text << std::endl; - SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error", error_text.c_str(), NULL); + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error", error_text.c_str(), nullptr); exit(1); } diff --git a/src/log.h b/src/log.h index 14a80b58..14e0a560 100644 --- a/src/log.h +++ b/src/log.h @@ -65,7 +65,7 @@ class Logger private: std::ofstream mLogFile; - bool mLogToStandardOut; + bool mLogToStandardOut = true; }; extern Logger *logger; diff --git a/src/resources/beinginfo.cpp b/src/resources/beinginfo.cpp index da65355a..e76cb8e3 100644 --- a/src/resources/beinginfo.cpp +++ b/src/resources/beinginfo.cpp @@ -26,42 +26,73 @@ #include "utils/gettext.h" +#include + BeingInfo *BeingInfo::Unknown = new BeingInfo; +static std::optional targetCursorSizeFromString(const std::string &cursor) +{ + if (cursor == "small") return ActorSprite::TC_SMALL; + if (cursor == "medium") return ActorSprite::TC_MEDIUM; + if (cursor == "large") return ActorSprite::TC_LARGE; + + return {}; +} + +static std::optional cursorFromString(const std::string &cursor) +{ + if (cursor == "pointer") return Cursor::POINTER; + if (cursor == "attack") return Cursor::FIGHT; + if (cursor == "pickup") return Cursor::PICKUP; + if (cursor == "talk") return Cursor::TALK; + if (cursor == "action") return Cursor::ACTION; + if (cursor == "left") return Cursor::LEFT; + if (cursor == "up") return Cursor::UP; + if (cursor == "right") return Cursor::RIGHT; + if (cursor == "down") return Cursor::DOWN; + + return {}; +} + BeingInfo::BeingInfo(): mName(_("unnamed")), - mWalkMask(Map::BLOCKMASK_WALL | Map::BLOCKMASK_CHARACTER - | Map::BLOCKMASK_MONSTER) + mWalkMask(Map::BLOCKMASK_WALL | Map::BLOCKMASK_CHARACTER | Map::BLOCKMASK_MONSTER) { SpriteDisplay display; SpriteReference errorSprite(paths.getStringValue("spriteErrorFile"), 0); display.sprites.push_back(errorSprite); - setDisplay(display); + setDisplay(std::move(display)); } BeingInfo::~BeingInfo() = default; void BeingInfo::setDisplay(SpriteDisplay display) { - mDisplay = display; + mDisplay = std::move(display); } void BeingInfo::setTargetCursorSize(const std::string &size) { - if (size == "small") - setTargetCursorSize(ActorSprite::TC_SMALL); - else if (size == "medium") - setTargetCursorSize(ActorSprite::TC_MEDIUM); - else if (size == "large") - setTargetCursorSize(ActorSprite::TC_LARGE); - else + const auto targetCursorSize = targetCursorSizeFromString(size); + if (!targetCursorSize) + { + logger->log("Unknown targetCursor value \"%s\" for %s", + size.c_str(), getName().c_str()); + } + setTargetCursorSize(targetCursorSize.value_or(ActorSprite::TC_MEDIUM)); +} + +void BeingInfo::setHoverCursor(const std::string &cursorName) +{ + const auto cursor = cursorFromString(cursorName); + if (!cursor) { - logger->log("Unknown target cursor type \"%s\" for %s - using medium " - "sized one", size.c_str(), getName().c_str()); - setTargetCursorSize(ActorSprite::TC_MEDIUM); + logger->log("Unknown hoverCursor value \"%s\" for %s", + cursorName.c_str(), getName().c_str()); } + setHoverCursor(cursor.value_or(Cursor::POINTER)); } void BeingInfo::addSound(SoundEvent event, const std::string &filename) diff --git a/src/resources/beinginfo.h b/src/resources/beinginfo.h index e2d11c93..a4736439 100644 --- a/src/resources/beinginfo.h +++ b/src/resources/beinginfo.h @@ -24,6 +24,7 @@ #include "actorsprite.h" +#include "gui/gui.h" #include "resources/spritedef.h" #include @@ -81,6 +82,14 @@ class BeingInfo ActorSprite::TargetCursorSize getTargetCursorSize() const { return mTargetCursorSize; } + void setHoverCursor(const std::string &cursorName); + + void setHoverCursor(Cursor cursor) + { mHoverCursor = cursor; } + + Cursor getHoverCursor() const + { return mHoverCursor; } + void addSound(SoundEvent event, const std::string &filename); const std::string &getSound(SoundEvent event) const; @@ -108,6 +117,7 @@ class BeingInfo SpriteDisplay mDisplay; std::string mName; ActorSprite::TargetCursorSize mTargetCursorSize = ActorSprite::TC_MEDIUM; + Cursor mHoverCursor = Cursor::POINTER; std::map> mSounds; std::map mAttacks; unsigned char mWalkMask; diff --git a/src/resources/monsterdb.cpp b/src/resources/monsterdb.cpp index fa1ac5af..fc860958 100644 --- a/src/resources/monsterdb.cpp +++ b/src/resources/monsterdb.cpp @@ -79,6 +79,8 @@ void MonsterDB::readMonsterNode(xmlNodePtr node, const std::string &filename) currentInfo->setTargetCursorSize(XML::getProperty(node, "targetCursor", "medium")); + currentInfo->setHoverCursor(XML::getProperty(node, "hoverCursor", "attack")); + SpriteDisplay display; //iterate s and s @@ -147,7 +149,7 @@ void MonsterDB::readMonsterNode(xmlNodePtr node, const std::string &filename) (const char*) spriteNode->xmlChildrenNode->content); } } - currentInfo->setDisplay(display); + currentInfo->setDisplay(std::move(display)); mMonsterInfos[XML::getProperty(node, "id", 0) + mMonsterIdOffset] = currentInfo; } diff --git a/src/resources/npcdb.cpp b/src/resources/npcdb.cpp index 6a0685d2..83d91b20 100644 --- a/src/resources/npcdb.cpp +++ b/src/resources/npcdb.cpp @@ -55,6 +55,8 @@ void NPCDB::readNPCNode(xmlNodePtr node, const std::string &filename) currentInfo->setTargetCursorSize(XML::getProperty(node, "targetCursor", "medium")); + currentInfo->setHoverCursor(XML::getProperty(node, "hoverCursor", "talk")); + SpriteDisplay display; for_each_xml_child_node(spriteNode, node) { @@ -72,7 +74,7 @@ void NPCDB::readNPCNode(xmlNodePtr node, const std::string &filename) } } - currentInfo->setDisplay(display); + currentInfo->setDisplay(std::move(display)); mNPCInfos[id] = currentInfo; } -- cgit v1.2.3-70-g09d2