diff options
-rw-r--r-- | ChangeLog | 19 | ||||
-rw-r--r-- | src/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/game.cpp | 3 | ||||
-rw-r--r-- | src/game.h | 1 | ||||
-rw-r--r-- | src/gui/skill.cpp | 125 | ||||
-rw-r--r-- | src/gui/skill.h | 21 | ||||
-rw-r--r-- | src/gui/status.cpp | 139 | ||||
-rw-r--r-- | src/gui/status.h | 7 | ||||
-rw-r--r-- | src/localplayer.cpp | 66 | ||||
-rw-r--r-- | src/localplayer.h | 88 | ||||
-rw-r--r-- | src/net/charserverhandler.cpp | 4 | ||||
-rw-r--r-- | src/net/gameserver/player.cpp | 14 | ||||
-rw-r--r-- | src/net/gameserver/player.h | 2 | ||||
-rw-r--r-- | src/net/playerhandler.cpp | 128 | ||||
-rw-r--r-- | src/net/protocol.h | 16 | ||||
-rw-r--r-- | src/net/skillhandler.cpp | 93 | ||||
-rw-r--r-- | src/net/skillhandler.h | 37 | ||||
-rw-r--r-- | src/particle.cpp | 6 | ||||
-rw-r--r-- | src/particle.h | 4 | ||||
-rw-r--r-- | src/resources/itemdb.cpp | 6 | ||||
-rw-r--r-- | src/resources/iteminfo.cpp | 2 | ||||
-rw-r--r-- | src/resources/iteminfo.h | 23 |
23 files changed, 448 insertions, 360 deletions
@@ -1,3 +1,22 @@ +2007-01-28 Philipp Sehmisch <tmw@crushnet.org> + + * src/game.cpp, src/game.h, src/net/skillhandler.cpp, + src/net/skillhandler.h, src/Makefile.am, src/CMakeLists.txt: + Removed skill handler (relict from eAthena) + * src/gui/skill.cpp, src/gui/skill.h: Implemented provisorical + dialog for viewing skill experience and skill levels. + * src/gui/status.cpp, src/gui/status.h: Implemented raising and + correcting of attributes in the character status GUI. + * src/localplayer.cpp, src/localplayer.h, + src/net/charserverhandler.cpp, src/net/gameserver/player.cpp, + src/net/gameserver/player.h, src/net/playerhandler.cpp, + src/net/protocol.h: Implemented netcode for skill system and + attribute increase system. + * src/resources/itemdp.cpp, src/resources/iteminfo.cpp, + src/resources/iteminfo.h: Updated skill palette to the latest + design decisions. + * data/items.xml: Fixed a few messed up slot numbers. + 2008-01-26 Bjørn Lindeijer <bjorn@lindeijer.nl> * src/gui/truetypefont.cpp: Image alpha should also be set to 1, in diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a6606c33..4d774f1b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -226,8 +226,6 @@ SET(SRCS net/playerhandler.cpp net/playerhandler.h net/protocol.h - net/skillhandler.cpp - net/skillhandler.h net/tradehandler.cpp net/tradehandler.h net/accountserver/account.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 31c17edb..a3a7bc1b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -178,8 +178,6 @@ tmw_SOURCES = gui/widgets/dropdown.cpp \ net/playerhandler.cpp \ net/playerhandler.h \ net/protocol.h \ - net/skillhandler.cpp \ - net/skillhandler.h \ net/tradehandler.cpp \ net/tradehandler.h \ net/accountserver/account.cpp \ diff --git a/src/game.cpp b/src/game.cpp index 4bf42a2d..1ad99268 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -77,7 +77,6 @@ #include "net/network.h" #include "net/npchandler.h" #include "net/playerhandler.h" -#include "net/skillhandler.h" #include "net/tradehandler.h" #include "resources/imagewriter.h" @@ -236,7 +235,6 @@ Game::Game(): mItemHandler(new ItemHandler()), mNpcHandler(new NPCHandler()), mPlayerHandler(new PlayerHandler()), - mSkillHandler(new SkillHandler()), mTradeHandler(new TradeHandler()), mLogicCounterId(0), mSecondsCounterId(0) { @@ -279,7 +277,6 @@ Game::Game(): Net::registerHandler(mItemHandler.get()); Net::registerHandler(mNpcHandler.get()); Net::registerHandler(mPlayerHandler.get()); - Net::registerHandler(mSkillHandler.get()); Net::registerHandler(mTradeHandler.get()); } @@ -67,7 +67,6 @@ class Game : public ConfigListener MessageHandlerPtr mItemHandler; MessageHandlerPtr mNpcHandler; MessageHandlerPtr mPlayerHandler; - MessageHandlerPtr mSkillHandler; MessageHandlerPtr mTradeHandler; SDL_TimerID mLogicCounterId; diff --git a/src/gui/skill.cpp b/src/gui/skill.cpp index c553863f..8c47c4ad 100644 --- a/src/gui/skill.cpp +++ b/src/gui/skill.cpp @@ -24,6 +24,7 @@ #include <algorithm> #include <guichan/widgets/label.hpp> +#include <guichan/widgets/container.hpp> #include "skill.h" @@ -35,32 +36,8 @@ #include "../localplayer.h" #include "../utils/dtor.h" - -const char *skill_db[] = { - // 0-99 - "", "Basic", "Sword", "Two hand", "HP regeneration", "Bash", "Provoke", "Magnum", "Endure", "MP regeneration", - "", "", "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "MAX weight", "Discount", "Overcharge", "", - "Identify", "", "", "", "", "", "", "", "Double", "Miss", - "", "", "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", "", "", - // 100-199 - "", "", "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", "", "", - "", "", "First aid", "Play as dead", "Moving recovery", "Fatal blow", "Auto berserk", "", "", "", - "", "", "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", "", "", -}; - +#include "../utils/toString.h" +#include "../utils/gettext.h" SkillDialog::SkillDialog(): Window("Skills") @@ -68,25 +45,32 @@ SkillDialog::SkillDialog(): setCloseButton(true); setDefaultSize(windowContainer->getWidth() - 255, 25, 240, 240); - mSkillListBox = new ListBox(this); - ScrollArea *skillScrollArea = new ScrollArea(mSkillListBox); - - mSkillListBox->setActionEventId("skill"); - - skillScrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER); - skillScrollArea->setDimension(gcn::Rectangle(5, 5, 230, 180)); + mSkillNameLabels.resize(CHAR_SKILL_NB); + mSkillLevelLabels.resize(CHAR_SKILL_NB); + mSkillExpLabels.resize(CHAR_SKILL_NB); - add(skillScrollArea); + for (int a=0; a < CHAR_SKILL_NB; a++) + { + mSkillNameLabels.at(a) = new gcn::Label(""); + mSkillNameLabels.at(a)->setPosition(1, a*10); + add(mSkillNameLabels.at(a)); + mSkillLevelLabels.at(a) = new gcn::Label(""); + mSkillLevelLabels.at(a)->setPosition(75, a*10); + add(mSkillLevelLabels.at(a)); + mSkillExpLabels.at(a) = new gcn::Label(""); + mSkillExpLabels.at(a)->setPosition(150, a*10); + add(mSkillExpLabels.at(a)); + } - mSkillListBox->addActionListener(this); + update(); setLocationRelativeTo(getParent()); - loadWindowState("Skills"); + loadWindowState(_("Skills")); } SkillDialog::~SkillDialog() { - cleanList(); + } void SkillDialog::action(const gcn::ActionEvent &event) @@ -100,60 +84,29 @@ void SkillDialog::action(const gcn::ActionEvent &event) } } -void SkillDialog::update() +void SkillDialog::draw(gcn::Graphics *g) { -} + update(); -int SkillDialog::getNumberOfElements() -{ - return mSkillList.size(); + Window::draw(g); } -std::string SkillDialog::getElementAt(int i) +void SkillDialog::update() { - if (i >= 0 && i < (int)mSkillList.size()) + for (int a = 0; a < CHAR_SKILL_NB; a++) { - char tmp[128]; - sprintf(tmp, "%s Lv: %i Sp: %i", - skill_db[mSkillList[i]->id], - mSkillList[i]->lv, - mSkillList[i]->sp); - return tmp; + int baseLevel = player_node->getAttributeBase(a + CHAR_SKILL_BEGIN); + int effLevel = player_node->getAttributeEffective(a + CHAR_SKILL_BEGIN); + std::string skillLevel("Lvl:" + toString(effLevel) + " / " + toString(baseLevel)); + + std::pair<int, int> exp = player_node->getExperience(a); + std::string sExp (toString(exp.first) + " / " + toString(exp.second)); + + mSkillNameLabels.at(a)->setCaption("Skill" + toString(a)); + mSkillNameLabels.at(a)->adjustSize(); + mSkillLevelLabels.at(a)->setCaption(skillLevel); + mSkillLevelLabels.at(a)->adjustSize(); + mSkillExpLabels.at(a)->setCaption(sExp); + mSkillExpLabels.at(a)->adjustSize(); } - return ""; -} - -bool SkillDialog::hasSkill(int id) -{ - for (unsigned int i = 0; i < mSkillList.size(); i++) { - if (mSkillList[i]->id == id) { - return true; - } - } - return false; -} - -void SkillDialog::addSkill(int id, int lvl, int mp) -{ - SKILL *tmp = new SKILL(); - tmp->id = id; - tmp->lv = lvl; - tmp->sp = mp; - mSkillList.push_back(tmp); -} - -void SkillDialog::setSkill(int id, int lvl, int mp) -{ - for (unsigned int i = 0; i < mSkillList.size(); i++) { - if (mSkillList[i]->id == id) { - mSkillList[i]->lv = lvl; - mSkillList[i]->sp = mp; - } - } -} - -void SkillDialog::cleanList() -{ - for_each(mSkillList.begin(), mSkillList.end(), make_dtor(mSkillList)); - mSkillList.clear(); } diff --git a/src/gui/skill.h b/src/gui/skill.h index f1a14d50..55d94d82 100644 --- a/src/gui/skill.h +++ b/src/gui/skill.h @@ -33,18 +33,13 @@ #include "../guichanfwd.h" -struct SKILL { - short id; /**< Index into "skill_db" array */ - short lv, sp; -}; /** * The skill dialog. * * \ingroup Interface */ -class SkillDialog : public Window, public gcn::ActionListener, - public gcn::ListModel +class SkillDialog : public Window, public gcn::ActionListener { public: /** @@ -61,18 +56,14 @@ class SkillDialog : public Window, public gcn::ActionListener, void update(); - int getNumberOfElements(); - std::string getElementAt(int); + void setExp(int id, int exp); - bool hasSkill(int id); - void addSkill(int id, int lv, int sp); - void setSkill(int id, int lv, int sp); - void cleanList(); + void draw(gcn::Graphics *g); private: - gcn::ListBox *mSkillListBox; - - std::vector<SKILL*> mSkillList; + std::vector<gcn::Label *> mSkillNameLabels; + std::vector<gcn::Label *> mSkillLevelLabels; + std::vector<gcn::Label *> mSkillExpLabels; }; extern SkillDialog *skillDialog; diff --git a/src/gui/status.cpp b/src/gui/status.cpp index b0a92665..b9ebfecf 100644 --- a/src/gui/status.cpp +++ b/src/gui/status.cpp @@ -87,7 +87,6 @@ StatusWindow::StatusWindow(LocalPlayer *player): // Static Labels gcn::Label *mStatsTitleLabel = new gcn::Label("Stats"); gcn::Label *mStatsTotalLabel = new gcn::Label("Total"); - gcn::Label *mStatsCostLabel = new gcn::Label("Cost"); // Derived Stats /* @@ -111,37 +110,44 @@ StatusWindow::StatusWindow(LocalPlayer *player): for (int i = 0; i < 6; i++) { mStatsLabel[i] = new gcn::Label(); mStatsDisplayLabel[i] = new gcn::Label(); - mPointsLabel[i] = new gcn::Label("0"); } - mRemainingStatsPointsLabel = new gcn::Label(); + mCharacterPointsLabel = new gcn::Label(); + mCorrectionPointsLabel = new gcn::Label(); // Set button events Id - mStatsButton[0] = new Button("+", "STR", this); - mStatsButton[1] = new Button("+", "AGI", this); - mStatsButton[2] = new Button("+", "DEX", this); - mStatsButton[3] = new Button("+", "VIT", this); - mStatsButton[4] = new Button("+", "INT", this); - mStatsButton[5] = new Button("+", "WIL", this); - mStatsButton[6] = new Button("+", "CHR", this); + mStatsPlus[0] = new Button("+", "STR+", this); + mStatsPlus[1] = new Button("+", "AGI+", this); + mStatsPlus[2] = new Button("+", "DEX+", this); + mStatsPlus[3] = new Button("+", "VIT+", this); + mStatsPlus[4] = new Button("+", "INT+", this); + mStatsPlus[5] = new Button("+", "WIL+", this); + + mStatsMinus[0] = new Button("-", "STR-", this); + mStatsMinus[1] = new Button("-", "AGI-", this); + mStatsMinus[2] = new Button("-", "DEX-", this); + mStatsMinus[3] = new Button("-", "VIT-", this); + mStatsMinus[4] = new Button("-", "INT-", this); + mStatsMinus[5] = new Button("-", "WIL-", this); + // Set position mStatsTitleLabel->setPosition(mHpLabel->getX(), mHpLabel->getY() + 23 ); mStatsTotalLabel->setPosition(110, mStatsTitleLabel->getY() + 15); int totalLabelY = mStatsTotalLabel->getY(); - mStatsCostLabel->setPosition(170, totalLabelY); for (int i = 0; i < 6; i++) { mStatsLabel[i]->setPosition(5, mStatsTotalLabel->getY() + (i * 23) + 15); - mStatsDisplayLabel[i]->setPosition(85, + mStatsMinus[i]->setPosition(85, totalLabelY + (i * 23) + 15); + mStatsDisplayLabel[i]->setPosition(125, totalLabelY + (i * 23) + 15); - mStatsButton[i]->setPosition(145, totalLabelY + (i * 23) + 10); - mPointsLabel[i]->setPosition(165, totalLabelY + (i * 23) + 15); + mStatsPlus[i]->setPosition(185, totalLabelY + (i * 23) + 15); } - mRemainingStatsPointsLabel->setPosition(5, mPointsLabel[6]->getY() + 25); + mCharacterPointsLabel->setPosition(5, mStatsDisplayLabel[5]->getY() + 25); + mCorrectionPointsLabel->setPosition(5, mStatsDisplayLabel[5]->getY() + 35); /* mStatsAttackLabel->setPosition(220, mStatsLabel[0]->getY()); mStatsDefenseLabel->setPosition(220, mStatsLabel[1]->getY()); @@ -162,13 +168,12 @@ StatusWindow::StatusWindow(LocalPlayer *player): // Assemble add(mStatsTitleLabel); add(mStatsTotalLabel); - add(mStatsCostLabel); for(int i = 0; i < 6; i++) { add(mStatsLabel[i]); add(mStatsDisplayLabel[i]); - add(mStatsButton[i]); - add(mPointsLabel[i]); + add(mStatsPlus[i]); + add(mStatsMinus[i]); }/* add(mStatsAttackLabel); add(mStatsDefenseLabel); @@ -186,14 +191,19 @@ StatusWindow::StatusWindow(LocalPlayer *player): add(mStatsEvadePoints); add(mStatsReflexPoints);*/ - add(mRemainingStatsPointsLabel); + add(mCharacterPointsLabel); + add(mCorrectionPointsLabel); } void StatusWindow::update() { // Status Part // ----------- - mLvlLabel->setCaption("Level: " + toString(mPlayer->getLevel())); + mLvlLabel->setCaption( "Level: " + + toString(mPlayer->getLevel()) + + " (" + + toString(mPlayer->getLevelProgress()) + + "%)"); mLvlLabel->adjustSize(); mMoneyLabel->setCaption("Money: " + toString(mPlayer->getMoney()) + " GP"); @@ -232,8 +242,8 @@ void StatusWindow::update() "Intelligence", "Willpower" }; - int statusPoints = mPlayer->getAttributeIncreasePoints(); - + int characterPoints = mPlayer->getCharacterPoints(); + int correctionPoints = mPlayer->getCorrectionPoints(); // Update labels for (int i = 0; i < 6; i++) { @@ -246,11 +256,16 @@ void StatusWindow::update() mStatsLabel[i]->adjustSize(); mStatsDisplayLabel[i]->adjustSize(); - mStatsButton[i]->setEnabled(statusPoints); + mStatsPlus[i]->setEnabled(characterPoints); + mStatsMinus[i]->setEnabled(correctionPoints); } - mRemainingStatsPointsLabel->setCaption("Remaining Status Points: " + - toString(statusPoints)); - mRemainingStatsPointsLabel->adjustSize(); + mCharacterPointsLabel->setCaption("Character Points: " + + toString(characterPoints)); + mCharacterPointsLabel->adjustSize(); + + mCorrectionPointsLabel->setCaption("Correction Points: " + + toString(correctionPoints)); + mCorrectionPointsLabel->adjustSize(); /* // Derived Stats Points @@ -304,31 +319,53 @@ void StatusWindow::action(const gcn::ActionEvent &event) const std::string &eventId = event.getId(); // Stats Part - if (eventId.length() == 3) + if (eventId == "STR+") + { + mPlayer->raiseAttribute(LocalPlayer::STR); + } + else if (eventId == "AGI+") + { + mPlayer->raiseAttribute(LocalPlayer::AGI); + } + else if (eventId == "DEX+") + { + mPlayer->raiseAttribute(LocalPlayer::DEX); + } + else if (eventId == "VIT+") + { + mPlayer->raiseAttribute(LocalPlayer::VIT); + } + else if (eventId == "INT+") + { + mPlayer->raiseAttribute(LocalPlayer::INT); + } + else if (eventId == "WIL+") + { + mPlayer->raiseAttribute(LocalPlayer::WIL); + } + + else if (eventId == "STR-") + { + mPlayer->lowerAttribute(LocalPlayer::STR); + } + else if (eventId == "AGI-") + { + mPlayer->lowerAttribute(LocalPlayer::AGI); + } + else if (eventId == "DEX-") + { + mPlayer->lowerAttribute(LocalPlayer::DEX); + } + else if (eventId == "VIT-") + { + mPlayer->lowerAttribute(LocalPlayer::VIT); + } + else if (eventId == "INT-") + { + mPlayer->lowerAttribute(LocalPlayer::INT); + } + else if (eventId == "WIL-") { - if (eventId == "STR") - { - mPlayer->raiseAttribute(LocalPlayer::STR); - } - else if (eventId == "AGI") - { - mPlayer->raiseAttribute(LocalPlayer::AGI); - } - else if (eventId == "DEX") - { - mPlayer->raiseAttribute(LocalPlayer::DEX); - } - else if (eventId == "VIT") - { - mPlayer->raiseAttribute(LocalPlayer::VIT); - } - else if (eventId == "INT") - { - mPlayer->raiseAttribute(LocalPlayer::INT); - } - else if (eventId == "WIL") - { - mPlayer->raiseAttribute(LocalPlayer::WIL); - } + mPlayer->lowerAttribute(LocalPlayer::WIL); } } diff --git a/src/gui/status.h b/src/gui/status.h index f3475263..6e613495 100644 --- a/src/gui/status.h +++ b/src/gui/status.h @@ -91,14 +91,15 @@ class StatusWindow : public Window, public gcn::ActionListener * Stats captions. */ gcn::Label *mStatsLabel[6]; - gcn::Label *mPointsLabel[6]; gcn::Label *mStatsDisplayLabel[6]; - gcn::Label *mRemainingStatsPointsLabel; + gcn::Label *mCharacterPointsLabel; + gcn::Label *mCorrectionPointsLabel; /** * Stats buttons. */ - gcn::Button *mStatsButton[6]; + gcn::Button *mStatsPlus[6]; + gcn::Button *mStatsMinus[6]; }; extern StatusWindow *statusWindow; diff --git a/src/localplayer.cpp b/src/localplayer.cpp index d01b613e..12de3de4 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -49,17 +49,21 @@ LocalPlayer::LocalPlayer(): mAttackRange(0), mInventory(new Inventory), mEquipment(new Equipment), - mAttributeBase(NB_CHARACTER_ATTRIBUTES, 0), - mAttributeEffective(NB_CHARACTER_ATTRIBUTES, 0), - mAttributeIncreasePoints(0), - mLevel(1), mMoney(0), + mAttributeBase(NB_CHARACTER_ATTRIBUTES, -1), + mAttributeEffective(NB_CHARACTER_ATTRIBUTES, -1), + mExpCurrent(CHAR_SKILL_NB, -1), + mExpNext(CHAR_SKILL_NB, -1), + mCharacterPoints(-1), + mCorrectionPoints(-1), + mLevel(1), mLevelProgress(0), + mMoney(0), mTotalWeight(1), mMaxWeight(1), mHP(1), mMaxHP(1), - mXp(0), mTarget(NULL), mPickUpTarget(NULL), mTrading(false), mLastAction(-1), mWalkingDir(0), - mDestX(0), mDestY(0) + mDestX(0), mDestY(0), + mExpMessageTime(0) { } @@ -74,6 +78,21 @@ void LocalPlayer::logic() mLastAction = -1; } + // Show XP messages + if(!mExpMessages.empty()) + { + if (mExpMessageTime == 0) + { + particleEngine->addTextRiseFadeOutEffect(mExpMessages.front(), + 0, 128, 255, + speechFont, + mPx + 16, mPy - 16); + mExpMessages.pop_front(); + mExpMessageTime = 30; + } + mExpMessageTime--; + } + Being::logic(); } @@ -326,7 +345,6 @@ void LocalPlayer::attack() else { sound.playSfx("sfx/fist-swish.ogg"); } - Net::GameServer::Player::attack(getSpriteDirection()); } @@ -346,19 +364,35 @@ void LocalPlayer::revive() void LocalPlayer::raiseAttribute(size_t attr) { + // we assume that the server allows the change. When not we will undo it later. + mCharacterPoints--; mAttributeBase.at(attr)++; - // TODO: Inform the server about our desire to raise the attribute + Net::GameServer::Player::raiseAttribute(attr + CHAR_ATTR_BEGIN); } -void LocalPlayer::setXp(int xp) +void LocalPlayer::lowerAttribute(size_t attr) { - if (mMap && xp > mXp) - { - const std::string text = toString(xp - mXp) + " xp"; + // we assume that the server allows the change. When not we will undo it later. + mCorrectionPoints--; + mCharacterPoints++; + mAttributeBase.at(attr)--; + Net::GameServer::Player::lowerAttribute(attr + CHAR_ATTR_BEGIN); +} - // Show XP number - particleEngine->addTextRiseFadeOutEffect(text, hitYellowFont, - mPx + 16, mPy - 16); +void LocalPlayer::setExperience(int skill, int current, int next) +{ + int diff = current - mExpCurrent.at(skill); + if (mMap && mExpCurrent.at(skill) != -1 && diff > 0) + { + const std::string text = toString(diff) + " xp skill" + toString(skill); + mExpMessages.push_back(text); } - mXp = xp; + + mExpCurrent.at(skill) = current; + mExpNext.at(skill) = next; +} + +std::pair<int, int> LocalPlayer::getExperience(int skill) +{ + return std::pair<int, int> (mExpCurrent.at(skill), mExpNext.at(skill)); } diff --git a/src/localplayer.h b/src/localplayer.h index 9deb2475..fca6f993 100644 --- a/src/localplayer.h +++ b/src/localplayer.h @@ -82,30 +82,39 @@ enum CHAR_ATTR_END, CHAR_ATTR_NB = CHAR_ATTR_END - CHAR_ATTR_BEGIN, - CHAR_SKILL_WEAPON_BEGIN = CHAR_ATTR_END, + CHAR_SKILL_BEGIN = CHAR_ATTR_END, + + CHAR_SKILL_WEAPON_BEGIN = CHAR_SKILL_BEGIN, CHAR_SKILL_WEAPON_NONE = CHAR_SKILL_WEAPON_BEGIN, CHAR_SKILL_WEAPON_KNIFE, CHAR_SKILL_WEAPON_SWORD, - CHAR_SKILL_WEAPON_SPEAR, - CHAR_SKILL_WEAPON_JAVELIN, - CHAR_SKILL_WEAPON_ROD, + CHAR_SKILL_WEAPON_POLEARM, CHAR_SKILL_WEAPON_STAFF, CHAR_SKILL_WEAPON_WHIP, - CHAR_SKILL_WEAPON_PROJECTILE, - CHAR_SKILL_WEAPON_BOOMERANG, CHAR_SKILL_WEAPON_BOW, - CHAR_SKILL_WEAPON_SICKLE, - CHAR_SKILL_WEAPON_CROSSBOW, - CHAR_SKILL_WEAPON_STICK, - CHAR_SKILL_WEAPON_HAMMER, + CHAR_SKILL_WEAPON_SHOOTING, + CHAR_SKILL_WEAPON_MACE, CHAR_SKILL_WEAPON_AXE, - CHAR_SKILL_WEAPON_HAND_PROJECTILE, + CHAR_SKILL_WEAPON_THROWN, CHAR_SKILL_WEAPON_END, CHAR_SKILL_WEAPON_NB = CHAR_SKILL_WEAPON_END - CHAR_SKILL_WEAPON_BEGIN, - // Magic skills should follow. + CHAR_SKILL_MAGIC_BEGIN = CHAR_SKILL_WEAPON_END, + CHAR_SKILL_MAGIC_IAMJUSTAPLACEHOLDER = CHAR_SKILL_MAGIC_BEGIN, + // add magic skills here + CHAR_SKILL_MAGIC_END, + CHAR_SKILL_MAGIC_NB = CHAR_SKILL_MAGIC_END - CHAR_SKILL_MAGIC_BEGIN, + + CHAR_SKILL_CRAFT_BEGIN = CHAR_SKILL_MAGIC_END, + CHAR_SKILL_CRAFT_IAMJUSTAPLACEHOLDER = CHAR_SKILL_CRAFT_BEGIN, + // add crafting skills here + CHAR_SKILL_CRAFT_END, + CHAR_SKILL_CRAFT_NB = CHAR_SKILL_CRAFT_END - CHAR_SKILL_CRAFT_BEGIN, + + CHAR_SKILL_END = CHAR_SKILL_CRAFT_END, + CHAR_SKILL_NB = CHAR_SKILL_END - CHAR_SKILL_BEGIN, - NB_CHARACTER_ATTRIBUTES = CHAR_SKILL_WEAPON_END + NB_CHARACTER_ATTRIBUTES = CHAR_SKILL_END }; @@ -235,8 +244,16 @@ class LocalPlayer : public Player */ void setWalkingDir(int dir); + /** + * Uses a character point to raise an attribute + */ void raiseAttribute(size_t attr); + /** + * Uses a correction point to lower an attribute + */ + void lowerAttribute(size_t attr); + void toggleSit(); void emote(Uint8 emotion); @@ -245,17 +262,6 @@ class LocalPlayer : public Player int getHP() const { return mHP; } - /** - * Sets the amount of XP. Shows XP gaining effect if the player is on - * a map. - */ - void setXp(int xp); - - /** - * Returns the amount of experience points. - */ - int getXp() const { return mXp; } - Uint32 mCharId; int getMaxHP() const @@ -275,6 +281,12 @@ class LocalPlayer : public Player void setLevel(int value) { mLevel = value; } + void setLevelProgress(int percent) + { mLevelProgress = percent; } + + int getLevelProgress() const + { return mLevelProgress; } + int getMoney() const { return mMoney; } @@ -299,8 +311,21 @@ class LocalPlayer : public Player void setAttributeEffective(int num, int value) { mAttributeEffective[num] = value; } - int getAttributeIncreasePoints() const - { return mAttributeIncreasePoints; } + int getCharacterPoints() const + { return mCharacterPoints; } + + void setCharacterPoints(int n) + { mCharacterPoints = n; } + + int getCorrectionPoints() const + { return mCorrectionPoints; } + + void setCorrectionPoints(int n) + { mCorrectionPoints = n; } + + void setExperience(int skill, int current, int next); + + std::pair<int, int> getExperience(int skill); float mLastAttackTime; /**< Used to synchronize the charge dialog */ @@ -313,14 +338,17 @@ class LocalPlayer : public Player // Character status: std::vector<int> mAttributeBase; std::vector<int> mAttributeEffective; - int mAttributeIncreasePoints; + std::vector<int> mExpCurrent; + std::vector<int> mExpNext; + int mCharacterPoints; + int mCorrectionPoints; int mLevel; + int mLevelProgress; int mMoney; int mTotalWeight; int mMaxWeight; int mHP; int mMaxHP; - int mXp; /**< Experience points. */ Being *mTarget; FloorItem *mPickUpTarget; @@ -330,6 +358,10 @@ class LocalPlayer : public Player int mWalkingDir; /**< The direction the player is walking in. */ int mDestX; /**< X coordinate of destination. */ int mDestY; /**< Y coordinate of destination. */ + + std::list<std::string> mExpMessages; /**< Queued exp messages*/ + int mExpMessageTime; + }; extern LocalPlayer *player_node; diff --git a/src/net/charserverhandler.cpp b/src/net/charserverhandler.cpp index bbfa82a4..c83b68f1 100644 --- a/src/net/charserverhandler.cpp +++ b/src/net/charserverhandler.cpp @@ -215,7 +215,9 @@ LocalPlayer* CharServerHandler::readPlayerData(MessageIn &msg, int &slot) tempPlayer->setGender(msg.readInt8()); int hs = msg.readInt8(), hc = msg.readInt8(); tempPlayer->setHairStyle(hs, hc); - tempPlayer->setLevel(msg.readInt8()); + tempPlayer->setLevel(msg.readInt16()); + tempPlayer->setCharacterPoints(msg.readInt16()); + tempPlayer->setCorrectionPoints(msg.readInt16()); tempPlayer->setMoney(msg.readInt32()); for (int i = 0; i < 7; i++) diff --git a/src/net/gameserver/player.cpp b/src/net/gameserver/player.cpp index bb3567d3..67edc7ad 100644 --- a/src/net/gameserver/player.cpp +++ b/src/net/gameserver/player.cpp @@ -154,3 +154,17 @@ void Net::GameServer::Player::tradeWithNPC(int item, int amount) msg.writeInt16(amount); Net::GameServer::connection->send(msg); } + +void Net::GameServer::Player::raiseAttribute(int attribute) +{ + MessageOut msg(PGMSG_RAISE_ATTRIBUTE); + msg.writeInt8(attribute); + Net::GameServer::connection->send(msg); +} + +void Net::GameServer::Player::lowerAttribute(int attribute) +{ + MessageOut msg(PGMSG_LOWER_ATTRIBUTE); + msg.writeInt8(attribute); + Net::GameServer::connection->send(msg); +} diff --git a/src/net/gameserver/player.h b/src/net/gameserver/player.h index b5f3e6d7..7ebb2830 100644 --- a/src/net/gameserver/player.h +++ b/src/net/gameserver/player.h @@ -51,6 +51,8 @@ namespace Net void tradeItem(int slot, int amount); void tradeMoney(int amount); void tradeWithNPC(int item, int amount); + void raiseAttribute(int attribute); + void lowerAttribute(int attribute); } } } diff --git a/src/net/playerhandler.cpp b/src/net/playerhandler.cpp index f6f7a8fa..951d6d4e 100644 --- a/src/net/playerhandler.cpp +++ b/src/net/playerhandler.cpp @@ -29,6 +29,7 @@ #include "../engine.h" #include "../localplayer.h" #include "../log.h" +#include "../particle.h" #include "../npc.h" #include "../gui/buy.h" @@ -90,6 +91,11 @@ PlayerHandler::PlayerHandler() GPMSG_PLAYER_MAP_CHANGE, GPMSG_PLAYER_SERVER_CHANGE, GPMSG_PLAYER_ATTRIBUTE_CHANGE, + GPMSG_PLAYER_EXP_CHANGE, + GPMSG_LEVELUP, + GPMSG_LEVEL_PROGRESS, + GPMSG_RAISE_ATTRIBUTE_RESPONSE, + GPMSG_LOWER_ATTRIBUTE_RESPONSE, 0 }; handledMessages = _messages; @@ -128,6 +134,14 @@ void PlayerHandler::handleMessage(MessageIn &msg) } else if (stat < NB_CHARACTER_ATTRIBUTES) { + if (stat >= CHAR_SKILL_BEGIN && stat < CHAR_SKILL_END + && player_node->getAttributeBase(stat) < base + && player_node->getAttributeBase(stat) > -1) + { + Particle* effect = particleEngine->addEffect("graphics/particles/skillup.particle.xml", 0, 0); + player_node->controlParticle(effect); + } + player_node->setAttributeBase(stat, base); player_node->setAttributeEffective(stat, value); } @@ -138,6 +152,120 @@ void PlayerHandler::handleMessage(MessageIn &msg) } } } break; + + case GPMSG_PLAYER_EXP_CHANGE: + { + logger->log("EXP Update"); + while (msg.getUnreadLength()) + { + int skill = msg.readInt8(); + int current = msg.readInt32(); + int next = msg.readInt32(); + + if (skill < CHAR_SKILL_NB) + { + player_node->setExperience(skill, current, next); + } + else + { + logger->log("Warning: server wants to update experience of unknown " + "skill %d to %d / %d", skill, current, next); + } + } + } break; + + case GPMSG_LEVELUP: + { + player_node->setLevel(msg.readInt16()); + player_node->setCharacterPoints(msg.readInt16()); + player_node->setCorrectionPoints(msg.readInt16()); + Particle* effect = particleEngine->addEffect("graphics/particles/levelup.particle.xml", 0, 0); + player_node->controlParticle(effect); + } break; + + + case GPMSG_LEVEL_PROGRESS: + { + logger->log("Level Progress Update"); + player_node->setLevelProgress(msg.readInt8()); + } break; + + + case GPMSG_RAISE_ATTRIBUTE_RESPONSE: + { + int errCode = msg.readInt8(); + int attrNum = msg.readInt8() - CHAR_ATTR_BEGIN; + switch (errCode) + { + case ATTRIBMOD_OK: + { + // feel(acknowledgment); + } break; + case ATTRIBMOD_INVALID_ATTRIBUTE: + { + logger->log("Warning: Server denied increase of attribute %d (unknown attribute) ", attrNum); + } break; + case ATTRIBMOD_NO_POINTS_LEFT: + { + // when the server says "you got no points" it + // has to be correct. The server is always right! + // undo attribute change and set points to 0 + logger->log("Warning: Server denied increase of attribute %d (no points left) ", attrNum); + int attrValue = player_node->getAttributeBase(attrNum) - 1; + player_node->setCharacterPoints(0); + player_node->setAttributeBase(attrNum, attrValue); + } break; + case ATTRIBMOD_DENIED: + { + // undo attribute change + logger->log("Warning: Server denied increase of attribute %d (reason unknown) ", attrNum); + int points = player_node->getCharacterPoints() - 1; + player_node->setCharacterPoints(points); + int attrValue = player_node->getAttributeBase(attrNum) - 1; + player_node->setAttributeBase(attrNum, attrValue); + } break; + } + } break; + + case GPMSG_LOWER_ATTRIBUTE_RESPONSE: + { + int errCode = msg.readInt8(); + int attrNum = msg.readInt8() - CHAR_ATTR_BEGIN; + switch (errCode) + { + case ATTRIBMOD_OK: + { + // feel(acknowledgment); + } break; + case ATTRIBMOD_INVALID_ATTRIBUTE: + { + logger->log("Warning: Server denied reduction of attribute %d (unknown attribute) ", attrNum); + } break; + case ATTRIBMOD_NO_POINTS_LEFT: + { + // when the server says "you got no points" it + // has to be correct. The server is always right! + // undo attribute change and set points to 0 + logger->log("Warning: Server denied reduction of attribute %d (no points left) ", attrNum); + int attrValue = player_node->getAttributeBase(attrNum) + 1; + player_node->setCorrectionPoints(0); + player_node->setAttributeBase(attrNum, attrValue); + break; + } break; + case ATTRIBMOD_DENIED: + { + // undo attribute change + logger->log("Warning: Server denied reduction of attribute %d (reason unknown) ", attrNum); + int charaPoints = player_node->getCharacterPoints() - 1; + player_node->setCharacterPoints(charaPoints); + int correctPoints = player_node->getCharacterPoints() + 1; + player_node->setCorrectionPoints(correctPoints); + int attrValue = player_node->getAttributeBase(attrNum) + 1; + player_node->setAttributeBase(attrNum, attrValue); + } break; + } + + } break; /* case SMSG_PLAYER_ARROW_MESSAGE: { diff --git a/src/net/protocol.h b/src/net/protocol.h index d8b9fcb2..e6f5869b 100644 --- a/src/net/protocol.h +++ b/src/net/protocol.h @@ -49,7 +49,7 @@ enum { APMSG_CHAR_CREATE_RESPONSE = 0x0021, // B error PAMSG_CHAR_DELETE = 0x0022, // B index APMSG_CHAR_DELETE_RESPONSE = 0x0023, // B error - APMSG_CHAR_INFO = 0x0024, // B index, S name, B gender, B hair style, B hair color, B level, W money, W*6 stats + APMSG_CHAR_INFO = 0x0024, // B index, S name, B gender, B hair style, B hair color, W level, W character points, W correction points, D money, W*6 stats PAMSG_CHAR_SELECT = 0x0026, // B index APMSG_CHAR_SELECT_RESPONSE = 0x0027, // B error, B*32 token, S game address, W game port, S chat address, W chat port PAMSG_EMAIL_CHANGE = 0x0030, // S email @@ -83,6 +83,13 @@ enum { GPMSG_INVENTORY = 0x0120, // { B slot, W item id [, B amount] }* GPMSG_INVENTORY_FULL = 0x0121, // { B slot, W item id [, B amount] }* GPMSG_PLAYER_ATTRIBUTE_CHANGE = 0x0130, // { B attribute, W base value, W modified value }* + GPMSG_PLAYER_EXP_CHANGE = 0x0140, // { B skill, D exp got, D exp needed }* + GPMSG_LEVELUP = 0x0150, // W new level + GPMSG_LEVEL_PROGRESS = 0x0151, // B percent completed to next levelup + PGMSG_RAISE_ATTRIBUTE = 0x0160, // B attribute + GPMSG_RAISE_ATTRIBUTE_RESPONSE = 0x0161, // B error, B attribute + PGMSG_LOWER_ATTRIBUTE = 0x0170, // B attribute + GPMSG_LOWER_ATTRIBUTE_RESPONSE = 0x0171, // B error, B attribute GPMSG_BEING_ENTER = 0x0200, // B type, W being id, B action, W*2 position // player: S name, B hair style, B hair color, B gender, B item bitmask, { W item id }* // monster: W type id @@ -183,6 +190,13 @@ enum { CREATE_TOO_MUCH_CHARACTERS }; +// Character attribute modification specific return value +enum AttribmodResponseCode { + ATTRIBMOD_OK = ERRMSG_OK, + ATTRIBMOD_INVALID_ATTRIBUTE = 0x40, + ATTRIBMOD_NO_POINTS_LEFT, + ATTRIBMOD_DENIED +}; // Object type enumeration enum { // A simple item diff --git a/src/net/skillhandler.cpp b/src/net/skillhandler.cpp deleted file mode 100644 index 8a19fe45..00000000 --- a/src/net/skillhandler.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* - * The Mana World - * Copyright 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 - * 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, - * 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 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id$ - */ - -#include "skillhandler.h" - -#include "messagein.h" -#include "protocol.h" - -#include "../log.h" - -#include "../gui/chat.h" -#include "../gui/skill.h" - -SkillHandler::SkillHandler() -{ - static const Uint16 _messages[] = { - 0 - }; - handledMessages = _messages; -} - -void SkillHandler::handleMessage(MessageIn &msg) -{ - switch (msg.getId()) - { -#if 0 - case SMSG_PLAYER_SKILLS: - msg.readInt16(); // length - skillCount = (msg.getLength() - 4) / 37; - skillDialog->cleanList(); - - for (int k = 0; k < skillCount; k++) - { - Sint16 skillId = msg.readInt16(); - msg.readInt16(); // target type - msg.readInt16(); // unknown - Sint16 level = msg.readInt16(); - Sint16 sp = msg.readInt16(); - msg.readInt16(); // range - std::string skillName = msg.readString(24); - Sint8 up = msg.readInt8(); - - if (level != 0 || up != 0) - { - if (skillDialog->hasSkill(skillId)) { - skillDialog->setSkill(skillId, level, sp); - } - else { - skillDialog->addSkill(skillId, level, sp); - } - } - } - break; - - case SMSG_SKILL_FAILED: - // Action failed (ex. sit because you have not reached the - // right level) - CHATSKILL action; - action.skill = msg.readInt16(); - action.bskill = msg.readInt16(); - action.unused = msg.readInt16(); // unknown - action.success = msg.readInt8(); - action.reason = msg.readInt8(); - if (action.success != SKILL_FAILED && - action.bskill == BSKILL_EMOTE) - { - logger->log("Action: %d/%d", action.bskill, action.success); - } - chatWindow->chatLog(action); - break; -#endif - } -} diff --git a/src/net/skillhandler.h b/src/net/skillhandler.h deleted file mode 100644 index 8c0653d4..00000000 --- a/src/net/skillhandler.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * The Mana World - * Copyright 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 - * 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, - * 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 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id$ - */ - -#ifndef _TMW_NET_SKILLHANDLER_H -#define _TMW_NET_SKILLHANDLER_H - -#include "messagehandler.h" - -class SkillHandler : public MessageHandler -{ - public: - SkillHandler(); - - void handleMessage(MessageIn &msg); -}; - -#endif diff --git a/src/particle.cpp b/src/particle.cpp index 93fc7893..dac8c62e 100644 --- a/src/particle.cpp +++ b/src/particle.cpp @@ -329,10 +329,12 @@ Particle::addTextSplashEffect(const std::string &text, } Particle* -Particle::addTextRiseFadeOutEffect(const std::string &text, gcn::Font *font, +Particle::addTextRiseFadeOutEffect(const std::string &text, + int colorR, int colorG, int colorB, + gcn::Font *font, int x, int y) { - Particle *newParticle = new TextParticle(mMap, text, 255, 255, 255, font); + Particle *newParticle = new TextParticle(mMap, text, colorR, colorG, colorB, font); newParticle->setPosition(x, y, 0); newParticle->setVelocity(0.0f, 0.0f, 0.5f); newParticle->setGravity(0.0015f); diff --git a/src/particle.h b/src/particle.h index 045ab9b9..0dd34065 100644 --- a/src/particle.h +++ b/src/particle.h @@ -123,7 +123,9 @@ class Particle : public Sprite * Creates a standalone text particle. */ Particle* - addTextRiseFadeOutEffect(const std::string &text, gcn::Font *font, + addTextRiseFadeOutEffect(const std::string &text, + int colorR, int colorG, int colorB, + gcn::Font *font, int x, int y); /** diff --git a/src/resources/itemdb.cpp b/src/resources/itemdb.cpp index c03e42a2..5f6846ba 100644 --- a/src/resources/itemdb.cpp +++ b/src/resources/itemdb.cpp @@ -79,16 +79,14 @@ WeaponType weaponTypeFromString (std::string name, int id = 0) if (name=="knife") return WPNTYPE_KNIFE; else if (name=="sword") return WPNTYPE_SWORD; else if (name=="polearm") return WPNTYPE_POLEARM; - else if (name=="javelin") return WPNTYPE_JAVELIN; else if (name=="staff") return WPNTYPE_STAFF; else if (name=="whip") return WPNTYPE_WHIP; - else if (name=="boomerang") return WPNTYPE_BOOMERANG; else if (name=="bow") return WPNTYPE_BOW; - else if (name=="sickle") return WPNTYPE_SICKLE; - else if (name=="crossbow") return WPNTYPE_CROSSBOW; + else if (name=="shooting") return WPNTYPE_SHOOTING; else if (name=="mace") return WPNTYPE_MACE; else if (name=="axe") return WPNTYPE_AXE; else if (name=="thrown") return WPNTYPE_THROWN; + else return WPNTYPE_NONE; } diff --git a/src/resources/iteminfo.cpp b/src/resources/iteminfo.cpp index ade7f685..ad4c9797 100644 --- a/src/resources/iteminfo.cpp +++ b/src/resources/iteminfo.cpp @@ -60,7 +60,7 @@ void ItemInfo::setWeaponType(int type) case WPNTYPE_BOW: mAttackType = ACTION_ATTACK_BOW; break; - case WPNTYPE_SICKLE: + case WPNTYPE_POLEARM: mAttackType = ACTION_ATTACK_SWING; break; default: diff --git a/src/resources/iteminfo.h b/src/resources/iteminfo.h index c637b010..90675a17 100644 --- a/src/resources/iteminfo.h +++ b/src/resources/iteminfo.h @@ -62,19 +62,16 @@ enum ItemType enum WeaponType { WPNTYPE_NONE = 0, - WPNTYPE_KNIFE,// 1 - WPNTYPE_SWORD,// 2 - WPNTYPE_POLEARM,// 3 - WPNTYPE_JAVELIN,// 4 - WPNTYPE_STAFF,// 5 - WPNTYPE_WHIP,// 6 - WPNTYPE_BOOMERANG,// 7 - WPNTYPE_BOW,// 8 - WPNTYPE_SICKLE,// 9 - WPNTYPE_CROSSBOW,// 10 - WPNTYPE_MACE,// 11 - WPNTYPE_AXE,// 12 - WPNTYPE_THROWN// 13 + WPNTYPE_KNIFE, + WPNTYPE_SWORD, + WPNTYPE_POLEARM, + WPNTYPE_STAFF, + WPNTYPE_WHIP, + WPNTYPE_BOW, + WPNTYPE_SHOOTING, + WPNTYPE_MACE, + WPNTYPE_AXE, + WPNTYPE_THROWN }; /** |