diff options
author | Andrei Karas <akaras@inbox.ru> | 2011-04-21 05:25:01 +0300 |
---|---|---|
committer | Andrei Karas <akaras@inbox.ru> | 2011-04-21 05:25:01 +0300 |
commit | 8037d33c9f429d4c0322da383cdda46776c3c14e (patch) | |
tree | 7460a6dd0c774817ff1dd92aa190776ae1684ed9 | |
parent | d7eae524bf7e88ebb5a324431b74a77ce1e7fded (diff) | |
download | manaplus-8037d33c9f429d4c0322da383cdda46776c3c14e.tar.gz manaplus-8037d33c9f429d4c0322da383cdda46776c3c14e.tar.bz2 manaplus-8037d33c9f429d4c0322da383cdda46776c3c14e.tar.xz manaplus-8037d33c9f429d4c0322da383cdda46776c3c14e.zip |
Impliment attack filter.
Add tab in social tab.
-rw-r--r-- | src/actorspritemanager.cpp | 112 | ||||
-rw-r--r-- | src/defaults.cpp | 1 | ||||
-rw-r--r-- | src/game.cpp | 1 | ||||
-rw-r--r-- | src/gui/popupmenu.cpp | 182 | ||||
-rw-r--r-- | src/gui/popupmenu.h | 3 | ||||
-rw-r--r-- | src/gui/setup_other.cpp | 14 | ||||
-rw-r--r-- | src/gui/setup_other.h | 3 | ||||
-rw-r--r-- | src/gui/socialwindow.cpp | 160 | ||||
-rw-r--r-- | src/gui/socialwindow.h | 4 | ||||
-rw-r--r-- | src/gui/viewport.cpp | 6 | ||||
-rw-r--r-- | src/gui/viewport.h | 2 | ||||
-rw-r--r-- | src/gui/widgets/avatarlistbox.cpp | 25 | ||||
-rw-r--r-- | src/localplayer.cpp | 75 | ||||
-rw-r--r-- | src/localplayer.h | 47 | ||||
-rw-r--r-- | src/map.h | 4 |
15 files changed, 621 insertions, 18 deletions
diff --git a/src/actorspritemanager.cpp b/src/actorspritemanager.cpp index 44dc30892..bbcf29090 100644 --- a/src/actorspritemanager.cpp +++ b/src/actorspritemanager.cpp @@ -25,6 +25,7 @@ #include "configuration.h" #include "localplayer.h" #include "log.h" +#include "main.h" #include "playerinfo.h" #include "playerrelations.h" @@ -99,6 +100,7 @@ class SortBeingFunctor return being1->getDistance() < being2->getDistance(); int d1, d2; +#ifdef MANASERV_SUPPORT if (Net::getNetworkType() == ServerInfo::MANASERV) { const Vector &pos1 = being1->getPosition(); @@ -109,6 +111,7 @@ class SortBeingFunctor + abs((static_cast<int>(pos2.y)) - y); } else +#endif { d1 = abs(being1->getTileX() - x) + abs(being1->getTileY() - y); d2 = abs(being2->getTileX() - x) + abs(being2->getTileY() - y); @@ -116,9 +119,28 @@ class SortBeingFunctor if (d1 != d2) return d1 < d2; + if (beings) + { + int w1 = defaultIndex; + int w2 = defaultIndex; + std::map<std::string, int>::iterator it1 + = beings->find(being1->getName()); + std::map<std::string, int>::iterator it2 + = beings->find(being2->getName()); + if (it1 != beings->end()) + w1 = (*it1).second; + if (it2 != beings->end()) + w2 = (*it2).second; + + if (w1 != w2) + return w1 < w2; + } + return (being1->getName() < being2->getName()); } int x, y; + std::map<std::string, int> *beings; + int defaultIndex; } beingSorter; @@ -654,12 +676,31 @@ Being *ActorSpriteManager::findNearestLivingBeing(Being *aroundBeing, return 0; Being *closestBeing = 0; + std::set<std::string> attackMobs; + std::set<std::string> ignoreAttackMobs; + std::map<std::string, int> mobsMap; + int defaultIndex = 10000; maxDist = maxDist * maxDist; bool cycleSelect = (mCyclePlayers && type == Being::PLAYER) || (mCycleMonsters && type == Being::MONSTER); + bool filtered = config.getBoolValue("enableAttackFilter"); + bool ignoreDefault = false; + if (filtered) + { + attackMobs = player_node->getAttackMobsSet(); + ignoreAttackMobs = player_node->getIgnoreAttackMobsSet(); + mobsMap = player_node->getAttackMobsMap(); + beingSorter.beings = &mobsMap; + if (ignoreAttackMobs.find("") != ignoreAttackMobs.end()) + ignoreDefault = true; + std::map<std::string, int>::iterator itr = mobsMap.find(""); + if (itr != mobsMap.end()) + defaultIndex = (*itr).second; + } + if (cycleSelect) { std::vector<Being*> sortedBeings; @@ -676,6 +717,19 @@ Being *ActorSpriteManager::findNearestLivingBeing(Being *aroundBeing, Being *being = static_cast<Being*>(*i); + if (filtered) + { + if (ignoreAttackMobs.find(being->getName()) + != ignoreAttackMobs.end()) + { + continue; + } + if (ignoreDefault && attackMobs.find(being->getName()) + == attackMobs.end()) + { + continue; + } + } if (validateBeing(aroundBeing, being, type, 0, maxDist)) { if (being != excluded) @@ -689,7 +743,18 @@ Being *ActorSpriteManager::findNearestLivingBeing(Being *aroundBeing, beingSorter.x = x; beingSorter.y = y; + if (filtered) + { + beingSorter.beings = &mobsMap; + beingSorter.defaultIndex = defaultIndex; + } + else + { + beingSorter.beings = 0; + } sort(sortedBeings.begin(), sortedBeings.end(), beingSorter); + if (filtered) + beingSorter.beings = 0; if (player_node->getTarget() == NULL) { @@ -725,10 +790,26 @@ Being *ActorSpriteManager::findNearestLivingBeing(Being *aroundBeing, } Being *being = static_cast<Being*>(*i); + if (filtered) + { + if (ignoreAttackMobs.find(being->getName()) + != ignoreAttackMobs.end()) + { + continue; + } + if (ignoreDefault && attackMobs.find(being->getName()) + == attackMobs.end()) + { + continue; + } + } + // Being *being = (*i); bool valid = validateBeing(aroundBeing, being, type, excluded, 50); int d = being->getDistance(); +// logger->log("dist: %d", dist); +// logger->log("name: %s, %d, %d", being->getName().c_str(), (int)valid, d); if (being->getType() != Being::MONSTER || !mTargetOnlyReachable) { // if distance not calculated, use old distance @@ -738,16 +819,31 @@ Being *ActorSpriteManager::findNearestLivingBeing(Being *aroundBeing, // logger->log("being name:" + being->getName()); // logger->log("d:" + toString(d)); -// logger->log("valid:" + toString(valid)); +// logger->log("valid:" + toString(valid)) - if (valid && (d < dist || closestBeing == 0)) + if (valid && (d <= dist || closestBeing == 0)) { -// if ((being->getType() == type || type == Being::UNKNOWN) -// && (d < dist || closestBeing == NULL) // it is closer -// && (being->mAction != Being::DEAD // no dead beings -// || (config.getValue("targetDeadPlayers", false) && type == Being::PLAYER)) -// && being != aroundBeing) -// { + if (closestBeing && filtered && d == dist) + { + int w1 = defaultIndex; + int w2 = defaultIndex; + std::map<std::string, int>::iterator it1 + = mobsMap.find(closestBeing->getName()); + std::map<std::string, int>::iterator it2 + = mobsMap.find(being->getName()); + if (it1 != mobsMap.end()) + w1 = (*it1).second; + if (it2 != mobsMap.end()) + w2 = (*it2).second; + + if (w2 < w1) + { + dist = d; + closestBeing = being; + } + continue; + } + dist = d; closestBeing = being; } diff --git a/src/defaults.cpp b/src/defaults.cpp index 7f9c31204..1446be4ec 100644 --- a/src/defaults.cpp +++ b/src/defaults.cpp @@ -196,6 +196,7 @@ DefaultsData* getConfigDefaults() AddDEF(configData, "showBeingPopup", true); AddDEF(configData, "showExtMinimaps", false); AddDEF(configData, "hideChatInput", true); + AddDEF(configData, "enableAttackFilter", true); return configData; } diff --git a/src/game.cpp b/src/game.cpp index 9c1e4ca0d..d5ac15ef3 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -224,6 +224,7 @@ static void createGuiWindows() whoIsOnline = new WhoIsOnline(); killStats = new KillStats; socialWindow = new SocialWindow(); + socialWindow->updateAttackFilter(); localChatTab = new ChatTab(_("General")); localChatTab->setAllowHighlight(false); diff --git a/src/gui/popupmenu.cpp b/src/gui/popupmenu.cpp index 6c43fdfa1..06ee9a9b8 100644 --- a/src/gui/popupmenu.cpp +++ b/src/gui/popupmenu.cpp @@ -246,7 +246,32 @@ void PopupMenu::showPopup(int x, int y, Being *being) mBrowserBox->addRow(_("@@attack|Attack@@")); if (player_node->isGM()) + { + mBrowserBox->addRow("##3---"); mBrowserBox->addRow(_("@@admin-kick|Kick@@")); + } + + if (config.getBoolValue("enableAttackFilter")) + { + mBrowserBox->addRow("##3---"); + if (player_node->isInAttackList(name)) + { + mBrowserBox->addRow( + _("@@remove attack|Remove from attack list@@")); + } + else if (player_node->isInIgnoreAttackList(name)) + { + mBrowserBox->addRow( + _("@@remove attack|Remove from ignore list@@")); + } + else + { + mBrowserBox->addRow( + _("@@add attack|Add to attack list@@")); + mBrowserBox->addRow( + _("@@add attack ignore|Add to ignore list@@")); + } + } } break; @@ -1122,6 +1147,120 @@ void PopupMenu::handleLink(const std::string &link, { mTab->setNoAway(false); } + else if (link == "remove attack" && being) + { + if (player_node && being->getType() == Being::MONSTER) + { + player_node->removeAttackMob(being->getName()); + if (socialWindow) + socialWindow->updateAttackFilter(); + } + } + else if (link == "add attack" && being) + { + if (player_node && being->getType() == Being::MONSTER) + { + player_node->addAttackMob(being->getName()); + if (socialWindow) + socialWindow->updateAttackFilter(); + } + } + else if (link == "add attack ignore" && being) + { + if (player_node && being->getType() == Being::MONSTER) + { + player_node->addIgnoreAttackMob(being->getName()); + if (socialWindow) + socialWindow->updateAttackFilter(); + } + } + else if (link == "attack moveup") + { + if (player_node) + { + int idx = player_node->getAttackMobIndex(mNick); + if (idx > 0) + { + std::list<std::string> mobs = player_node->getAttackMobs(); + std::list<std::string>::iterator it = mobs.begin(); + std::list<std::string>::iterator it2 = mobs.begin(); + while (it != mobs.end()) + { + if (*it == mNick) + { + -- it2; + mobs.splice(it2, mobs, it); + player_node->setAttackMobs(mobs); + player_node->rebuildAttackMobs(); + break; + } + ++ it; + ++ it2; + } + + if (socialWindow) + socialWindow->updateAttackFilter(); + } + } + } + else if (link == "attack movedown") + { + if (player_node) + { + int idx = player_node->getAttackMobIndex(mNick); + int size = player_node->getAttackMobsSize(); + if (idx + 1 < size) + { + std::list<std::string> mobs = player_node->getAttackMobs(); + std::list<std::string>::iterator it = mobs.begin(); + std::list<std::string>::iterator it2 = mobs.begin(); + while (it != mobs.end()) + { + if (*it == mNick) + { + ++ it2; + if (it2 == mobs.end()) + break; + + mobs.splice(it, mobs, it2); + player_node->setAttackMobs(mobs); + player_node->rebuildAttackMobs(); + break; + } + ++ it; + ++ it2; + } + + if (socialWindow) + socialWindow->updateAttackFilter(); + } + } + } + else if (link == "attack remove") + { + if (player_node) + { + if (mNick.empty()) + { + if (player_node->isInAttackList(mNick)) + { + player_node->removeAttackMob(mNick); + player_node->addIgnoreAttackMob(mNick); + } + else + { + player_node->removeAttackMob(mNick); + player_node->addAttackMob(mNick); + } + } + else + { + player_node->removeAttackMob(mNick); + } + if (socialWindow) + socialWindow->updateAttackFilter(); + } + } else if (link == "guild-pos" && !mNick.empty()) { showChangePos(getX(), getY()); @@ -1459,6 +1598,49 @@ void PopupMenu::showPopup(int x, int y, ProgressBar *b) showPopup(x, y); } +void PopupMenu::showAttackMonsterPopup(int x, int y, std::string name, + bool isAttack) +{ + if (!player_node) + return; + + mNick = name; + + mBrowserBox->clearRows(); + + if (name.empty()) + mBrowserBox->addRow(_("(default)")); + else + mBrowserBox->addRow(name); + if (isAttack) + { + int idx = player_node->getAttackMobIndex(name); + int size = player_node->getAttackMobsSize(); + if (idx > 0) + { + mBrowserBox->addRow(strprintf( + "@@attack moveup|%s@@", _("Move up"))); + } + if (idx + 1 < size) + { + mBrowserBox->addRow(strprintf( + "@@attack movedown|%s@@", _("Move down"))); + } + mBrowserBox->addRow(strprintf( + "@@attack remove|%s@@", _("Remove"))); + } + else + { + mBrowserBox->addRow(strprintf( + "@@attack remove|%s@@", _("Remove"))); + } + + mBrowserBox->addRow("##3---"); + mBrowserBox->addRow(strprintf("@@cancel|%s@@", _("Cancel"))); + + showPopup(x, y); +} + void PopupMenu::showPopup(int x, int y) { setContentSize(mBrowserBox->getWidth() + 8, mBrowserBox->getHeight() + 8); diff --git a/src/gui/popupmenu.h b/src/gui/popupmenu.h index 6dca1ff64..61720d417 100644 --- a/src/gui/popupmenu.h +++ b/src/gui/popupmenu.h @@ -117,6 +117,9 @@ class PopupMenu : public Popup, public LinkHandler void showSpellPopup(int x, int y, TextCommand *cmd); + void showAttackMonsterPopup(int x, int y, std::string name, + bool isAttack); + /** * Shows the related popup menu when right click on the chat * at the specified mouse coordinates. diff --git a/src/gui/setup_other.cpp b/src/gui/setup_other.cpp index 7a43b5480..bc1a07ed3 100644 --- a/src/gui/setup_other.cpp +++ b/src/gui/setup_other.cpp @@ -66,6 +66,7 @@ #define ACTION_SHOW_JOB_EXP "show job exp" #define ACTION_SHOW_BEING_POPUP "show being popup" #define ACTION_SHOW_EXTENDED_MINIMAPS "show extended minimaps" +#define ACTION_ENABLE_ATTACK_FILTER "attack filter" Setup_Other::Setup_Other(): mShowMonstersTakedDamage(config.getBoolValue("showMonstersTakedDamage")), @@ -94,6 +95,7 @@ Setup_Other::Setup_Other(): mShowJobExp(config.getBoolValue("showJobExp")), mShowBeingPopup(config.getBoolValue("showBeingPopup")), mShowExtMinimaps(config.getBoolValue("showExtMinimaps")), + mEnableAttackFilter(config.getBoolValue("enableAttackFilter")), mEditDialog(0) { setName(_("Misc")); @@ -187,6 +189,9 @@ Setup_Other::Setup_Other(): mShowExtMinimapsCheckBox = new CheckBox(_("Show extended minimaps"), mShowExtMinimaps, this, ACTION_SHOW_EXTENDED_MINIMAPS); + mEnableAttackFilterCheckBox = new CheckBox(_("Enable attack filter"), + mEnableAttackFilter, this, ACTION_ENABLE_ATTACK_FILTER); + // Do the layout LayoutHelper h(this); ContainerPlacer place = h.getPlacer(0, 0); @@ -205,6 +210,7 @@ Setup_Other::Setup_Other(): place(12, 8, mShowJobExpCheckBox, 10); place(12, 9, mShowBeingPopupCheckBox, 10); place(12, 10, mShowExtMinimapsCheckBox, 10); + place(12, 11, mEnableAttackFilterCheckBox, 10); place(0, 3, mFloorItemsHighlightCheckBox, 12); place(0, 4, mHighlightAttackRangeCheckBox, 12); place(0, 5, mHighlightMonsterAttackRangeCheckBox, 12); @@ -349,6 +355,10 @@ void Setup_Other::action(const gcn::ActionEvent &event) { mShowExtMinimaps = mShowExtMinimapsCheckBox->isSelected(); } + else if (event.getId() == ACTION_ENABLE_ATTACK_FILTER) + { + mEnableAttackFilter = mEnableAttackFilterCheckBox->isSelected(); + } } void Setup_Other::cancel() @@ -430,6 +440,9 @@ void Setup_Other::cancel() mShowExtMinimaps = config.getBoolValue("showExtMinimaps"); mShowExtMinimapsCheckBox->setSelected(mShowExtMinimaps); + + mEnableAttackFilter = config.getBoolValue("enableAttackFilter"); + mEnableAttackFilterCheckBox->setSelected(mEnableAttackFilter); } void Setup_Other::apply() @@ -460,6 +473,7 @@ void Setup_Other::apply() config.setValue("showJobExp", mShowJobExp); config.setValue("showBeingPopup", mShowBeingPopup); config.setValue("showExtMinimaps", mShowExtMinimaps); + config.setValue("enableAttackFilter", mEnableAttackFilter); logger->setDebugLog(mDebugLog); } diff --git a/src/gui/setup_other.h b/src/gui/setup_other.h index 44daa1237..8bf4fe659 100644 --- a/src/gui/setup_other.h +++ b/src/gui/setup_other.h @@ -122,6 +122,9 @@ class Setup_Other : public SetupTab, public gcn::ActionListener gcn::CheckBox *mShowExtMinimapsCheckBox; bool mShowExtMinimaps; + gcn::CheckBox *mEnableAttackFilterCheckBox; + bool mEnableAttackFilter; + EditDialog *mEditDialog; }; diff --git a/src/gui/socialwindow.cpp b/src/gui/socialwindow.cpp index 8a134b5c3..c6ec12cd8 100644 --- a/src/gui/socialwindow.cpp +++ b/src/gui/socialwindow.cpp @@ -500,7 +500,6 @@ private: class NavigationTab : public SocialTab { - public: NavigationTab() { @@ -768,6 +767,141 @@ protected: }; +class AttackTab : public SocialTab +{ +public: + AttackTab() + { + mBeings = new BeingsListModal(); + + mList = new AvatarListBox(mBeings); + mScroll = new ScrollArea(mList); + + mScroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_AUTO); + mScroll->setVerticalScrollPolicy(gcn::ScrollArea::SHOW_ALWAYS); + + setCaption(_("Atk")); + } + + ~AttackTab() + { + delete mList; + mList = 0; + delete mScroll; + mScroll = 0; + delete mBeings; + mBeings = 0; + } + + void invite() + { + } + + void leave() + { + } + + void updateList() + { + if (!socialWindow || !player_node) + return; + + std::vector<Avatar*> *avatars = mBeings->getMembers(); + + std::list<std::string> mobs = player_node->getAttackMobs(); + std::list<std::string>::iterator i = mobs.begin(); + + std::vector<Avatar*>::iterator ia = avatars->begin(); + + while (ia != avatars->end()) + { + delete *ia; + ++ ia; + } + + avatars->clear(); + Avatar *ava = new Avatar(_("Selected mobs")); + ava->setOnline(false); + ava->setLevel(-1); + ava->setType(MapItem::SEPARATOR); + ava->setX(0); + ava->setY(0); + avatars->push_back(ava); + + while (i != mobs.end()) + { + std::string name; + int level = -1; + if (*i == "") + { + name = _("(default)"); + level = 0; + } + else + { + name = *i; + } + Avatar *ava = new Avatar(name); + ava->setOnline(true); + ava->setLevel(level); + ava->setType(MapItem::MONSTER); + ava->setX(0); + ava->setY(0); + avatars->push_back(ava); + + ++ i; + } + + ava = new Avatar(_("Ignore mobs")); + ava->setOnline(false); + ava->setLevel(-1); + ava->setType(MapItem::SEPARATOR); + ava->setX(0); + ava->setY(0); + avatars->push_back(ava); + + mobs = player_node->getIgnoreAttackMobs(); + i = mobs.begin(); + + while (i != mobs.end()) + { + std::string name; + int level = -1; + if (*i == "") + { + name = _("(default)"); + level = 0; + } + else + { + name = *i; + } + Avatar *ava = new Avatar(name); + ava->setOnline(false); + ava->setLevel(level); + ava->setType(MapItem::MONSTER); + ava->setX(0); + ava->setY(0); + avatars->push_back(ava); + + ++ i; + } + + } + + void updateAvatar(std::string name _UNUSED_) + { + } + + void resetDamage(std::string name _UNUSED_) + { + } + +private: + BeingsListModal *mBeings; + +}; + class CreatePopup : public Popup, public LinkHandler { public: @@ -866,6 +1000,16 @@ SocialWindow::SocialWindow() : mNavigation = new NavigationTab(); mTabs->addTab(mNavigation, mNavigation->mScroll); + if (config.getBoolValue("enableAttackFilter")) + { + mAttackFilter = new AttackTab(); + mTabs->addTab(mAttackFilter, mAttackFilter->mScroll); + } + else + { + mAttackFilter = 0; + } + if (player_node && player_node->getParty()) addTab(player_node->getParty()); @@ -899,6 +1043,10 @@ SocialWindow::~SocialWindow() mCreatePopup = 0; delete mPlayers; mPlayers = 0; + delete mNavigation; + mNavigation = 0; + delete mAttackFilter; + mAttackFilter = 0; } bool SocialWindow::addTab(Guild *guild) @@ -1204,7 +1352,7 @@ void SocialWindow::updateActiveList() void SocialWindow::logic() { unsigned int nowTime = cur_time; - if (nowTime - mLastUpdateTime > 1 && mNeedUpdate) + if (mNeedUpdate && nowTime - mLastUpdateTime > 1) { mPlayers->updateList(); mNeedUpdate = false; @@ -1304,4 +1452,10 @@ void SocialWindow::prevTab() tab--; mTabs->setSelectedTab(tab); -}
\ No newline at end of file +} + +void SocialWindow::updateAttackFilter() +{ + if (mAttackFilter) + mAttackFilter->updateList(); +} diff --git a/src/gui/socialwindow.h b/src/gui/socialwindow.h index 8d4e904f0..c9cd296dc 100644 --- a/src/gui/socialwindow.h +++ b/src/gui/socialwindow.h @@ -36,6 +36,7 @@ #define _UNUSED_ #endif +class AttackTab; class Button; class ConfirmDialog; class CreatePopup; @@ -120,6 +121,8 @@ public: void selectPortal(unsigned num); + void updateAttackFilter(); + protected: friend class SocialTab; @@ -139,6 +142,7 @@ protected: typedef std::map<Party*, SocialTab*> PartyMap; PartyMap mParties; + SocialTab *mAttackFilter; SocialTab *mPlayers; SocialTab *mNavigation; diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp index ef33aa75b..e34dd658a 100644 --- a/src/gui/viewport.cpp +++ b/src/gui/viewport.cpp @@ -620,6 +620,12 @@ void Viewport::showPopup(int x, int y, ProgressBar *bar) mPopupMenu->showPopup(x, y, bar); } +void Viewport::showAttackMonsterPopup(std::string name, bool isAttack) +{ + mPopupMenu->showAttackMonsterPopup(getMouseX(), getMouseY(), + name, isAttack); +} + void Viewport::closePopupMenu() { if (mPopupMenu) diff --git a/src/gui/viewport.h b/src/gui/viewport.h index 1daa871d1..d6e0fc3dc 100644 --- a/src/gui/viewport.h +++ b/src/gui/viewport.h @@ -160,6 +160,8 @@ class Viewport : public WindowContainer, public gcn::MouseListener, void showSpellPopup(TextCommand *cmd); + void showAttackMonsterPopup(std::string name, bool isAttack); + /** * Shows the related popup menu when right click on the chat * at the specified mouse coordinates. diff --git a/src/gui/widgets/avatarlistbox.cpp b/src/gui/widgets/avatarlistbox.cpp index c1458d3fd..8309ad156 100644 --- a/src/gui/widgets/avatarlistbox.cpp +++ b/src/gui/widgets/avatarlistbox.cpp @@ -114,10 +114,13 @@ void AvatarListBox::draw(gcn::Graphics *gcnGraphics) if (!a) continue; - // Draw online status - Image *icon = a->getOnline() ? onlineIcon : offlineIcon; - if (icon) - graphics->drawImage(icon, 2, y + 1); + if (a->getType() != MapItem::SEPARATOR) + { + // Draw online status + Image *icon = a->getOnline() ? onlineIcon : offlineIcon; + if (icon) + graphics->drawImage(icon, 2, y + 1); + } if (a->getDisplayBold()) graphics->setFont(boldFont); @@ -316,6 +319,20 @@ void AvatarListBox::mousePressed(gcn::MouseEvent &event) model->getAvatarAt(selected)->getName()); } } + else if (ava->getType() == MapItem::MONSTER) + { + if (model->getAvatarAt(selected)->getLevel() == 0) + { + viewport->showAttackMonsterPopup("", + model->getAvatarAt(selected)->getOnline()); + } + else + { + viewport->showAttackMonsterPopup( + model->getAvatarAt(selected)->getName(), + model->getAvatarAt(selected)->getOnline()); + } + } else { Map *map = viewport->getMap(); diff --git a/src/localplayer.cpp b/src/localplayer.cpp index ac113a54a..a4289b22b 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -179,6 +179,7 @@ LocalPlayer::LocalPlayer(int id, int subtype): config.addListener("showJobExp", this); setShowName(config.getBoolValue("showownname")); beingInfoCache.clear(); + addAttackMob(""); } LocalPlayer::~LocalPlayer() @@ -2568,12 +2569,19 @@ bool LocalPlayer::isReachable(Being *being, int maxCost) if (being->isReachable() == Being::REACH_NO) return false; - if (being->getTileX() - 1 <= getTileX() + if (being->getTileX() == getTileX() + && being->getTileY() == getTileY()) + { + being->setDistance(0); + being->setIsReachable(Being::REACH_YES); + return true; + } + else if (being->getTileX() - 1 <= getTileX() && being->getTileX() + 1 >= getTileX() && being->getTileY() - 1 <= getTileY() && being->getTileY() + 1 >= getTileY()) { - being->setDistance(0); + being->setDistance(1); being->setIsReachable(Being::REACH_YES); return true; } @@ -3774,6 +3782,69 @@ void LocalPlayer::checkNewName(Being *being) } } +void LocalPlayer::removeAttackMob(const std::string &name) +{ + mAttackMobs.remove(name); + mIgnoreAttackMobs.remove(name); + mAttackMobsSet.erase(name); + mIgnoreAttackMobsSet.erase(name); + rebuildAttackMobs(); +} + +void LocalPlayer::addAttackMob(std::string name) +{ + int size = getAttackMobsSize(); + if (size > 0) + { + int idx = getAttackMobIndex(""); + if (idx + 1 == size) + { + std::list<std::string>::iterator itr = mAttackMobs.end(); + -- itr; + mAttackMobs.insert(itr, name); + } + else + { + mAttackMobs.push_back(name); + } + } + else + { + mAttackMobs.push_back(name); + } + mAttackMobsSet.insert(name); + rebuildAttackMobs(); +} + +void LocalPlayer::addIgnoreAttackMob(std::string name) +{ + mIgnoreAttackMobs.push_back(name); + mIgnoreAttackMobsSet.insert(name); + rebuildAttackMobs(); +} + +void LocalPlayer::rebuildAttackMobs() +{ + mAttackMobsMap.clear(); + std::list<std::string>::iterator i = mAttackMobs.begin(); + int cnt = 0; + while (i != mAttackMobs.end()) + { + mAttackMobsMap[*i] = cnt; + ++ i; + ++ cnt; + } +} + +int LocalPlayer::getAttackMobIndex(std::string name) +{ + std::map<std::string, int>::iterator i = mAttackMobsMap.find(name); + if (i == mAttackMobsMap.end()) + return -1; + + return (*i).second; +} + void AwayListener::action(const gcn::ActionEvent &event) { if (event.getId() == "ok" && player_node && player_node->getAwayMode()) diff --git a/src/localplayer.h b/src/localplayer.h index f5e15e5f6..904ce74db 100644 --- a/src/localplayer.h +++ b/src/localplayer.h @@ -450,6 +450,48 @@ class LocalPlayer : public Being, public ActorSpriteListener, void checkNewName(Being *being); + bool isInAttackList(const std::string &name) + { return mAttackMobsSet.find(name) != mAttackMobsSet.end(); } + + bool isInIgnoreAttackList(const std::string &name) + { return mIgnoreAttackMobsSet.find(name) + != mIgnoreAttackMobsSet.end(); } + + bool isInAttackOrIgnoreList(const std::string &name) + { return mAttackMobsSet.find(name) != mAttackMobsSet.end() || + mIgnoreAttackMobsSet.find(name) != mIgnoreAttackMobsSet.end(); } + + void removeAttackMob(const std::string &name); + + void addAttackMob(std::string name); + + void addIgnoreAttackMob(std::string name); + + std::list<std::string> getAttackMobs() + { return mAttackMobs; } + + void setAttackMobs(std::list<std::string> mobs) + { mAttackMobs = mobs; } + + int getAttackMobsSize() + { return mAttackMobs.size(); } + + std::list<std::string> getIgnoreAttackMobs() + { return mIgnoreAttackMobs; } + + std::set<std::string> getAttackMobsSet() + { return mAttackMobsSet; } + + std::set<std::string> getIgnoreAttackMobsSet() + { return mIgnoreAttackMobsSet; } + + void rebuildAttackMobs(); + + std::map<std::string, int> getAttackMobsMap() + { return mAttackMobsMap; } + + int getAttackMobIndex(std::string name); + protected: /** Whether or not the name settings have changed */ bool mUpdateName; @@ -576,6 +618,11 @@ class LocalPlayer : public Being, public ActorSpriteListener, bool mServerAttack; std::string mLastHitFrom; std::string mWaitFor; + std::list<std::string> mAttackMobs; + std::list<std::string> mIgnoreAttackMobs; + std::set<std::string> mAttackMobsSet; + std::set<std::string> mIgnoreAttackMobsSet; + std::map<std::string, int> mAttackMobsMap; }; extern LocalPlayer *player_node; @@ -579,7 +579,9 @@ class MapItem ARROW_LEFT = 6, ARROW_RIGHT = 7, PORTAL = 8, - MUSIC = 9 + MUSIC = 9, + MONSTER = 10, + SEPARATOR = 11 }; MapItem(); |