diff options
Diffstat (limited to 'src')
91 files changed, 938 insertions, 1023 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5a4b38fc..c8752fbc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,6 +1,7 @@ FIND_PACKAGE(LibXml2 REQUIRED) FIND_PACKAGE(PhysFS REQUIRED) FIND_PACKAGE(ZLIB REQUIRED) +FIND_PACKAGE(SigC++ REQUIRED) IF (CMAKE_COMPILER_IS_GNUCXX) # Help getting compilation warnings @@ -36,7 +37,7 @@ IF (MINGW) "<CMAKE_RC_COMPILER> <FLAGS> <DEFINES> -O coff -o <OBJECT> <SOURCE>") ENDIF() -SET(FLAGS "-DPACKAGE_VERSION=\\\"${VERSION}\\\"") +SET(FLAGS "${FLAGS} -DPACKAGE_VERSION=\\\"${VERSION}\\\"") SET(FLAGS "${FLAGS} -DPKG_DATADIR=\\\"${PKG_DATADIR}/\\\"") SET(FLAGS "${FLAGS} -DLOCALEDIR=\\\"${LOCALEDIR}/\\\"") @@ -93,6 +94,8 @@ INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR} ${PHYSFS_INCLUDE_DIR} ${LIBXML2_INCLUDE_DIR} + ${SIGC++_INCLUDE_DIR} + ${SIGC++Config_INCLUDE_DIR} ) # Fix some stuff that gets not hidden by mainline modules @@ -212,9 +215,10 @@ SET(SRCS_MANASERVGAME game-server/commandhandler.h game-server/effect.h game-server/effect.cpp + game-server/emotemanager.h + game-server/emotemanager.cpp game-server/entity.h game-server/entity.cpp - game-server/eventlistener.h game-server/gamehandler.h game-server/gamehandler.cpp game-server/inventory.h @@ -315,6 +319,7 @@ FOREACH(program ${PROGRAMS}) ${PHYSFS_LIBRARY} ${LIBXML2_LIBRARIES} ${ZLIB_LIBRARIES} + ${SIGC++_LIBRARIES} ${OPTIONAL_LIBRARIES} ${EXTRA_LIBRARIES}) INSTALL(TARGETS ${program} RUNTIME DESTINATION ${PKG_BINDIR}) diff --git a/src/account-server/account.cpp b/src/account-server/account.cpp index 0878c760..ed7c5df4 100644 --- a/src/account-server/account.cpp +++ b/src/account-server/account.cpp @@ -43,13 +43,13 @@ void Account::setCharacters(const Characters &characters) void Account::addCharacter(Character *character) { - unsigned int slot = (unsigned int) character->getCharacterSlot(); + unsigned slot = (unsigned) character->getCharacterSlot(); assert(isSlotEmpty(slot)); mCharacters[slot] = character; } -void Account::delCharacter(unsigned int slot) +void Account::delCharacter(unsigned slot) { for (Characters::iterator iter = mCharacters.begin(), iter_end = mCharacters.end(); iter != iter_end; ++iter) diff --git a/src/account-server/account.h b/src/account-server/account.h index 98794fbf..46693e80 100644 --- a/src/account-server/account.h +++ b/src/account-server/account.h @@ -158,7 +158,7 @@ class Account * * @param slot slot index of the character. */ - void delCharacter(unsigned int slot); + void delCharacter(unsigned slot); /** * Get all the characters. diff --git a/src/account-server/accounthandler.cpp b/src/account-server/accounthandler.cpp index a7b43e2a..a65d8240 100644 --- a/src/account-server/accounthandler.cpp +++ b/src/account-server/accounthandler.cpp @@ -739,7 +739,7 @@ void AccountHandler::handleCharacterCreateMessage(AccountClient &client, // than <account_maxCharacters> characters. Characters &chars = acc->getCharacters(); if (slot < 1 || slot > mMaxCharacters - || !acc->isSlotEmpty((unsigned int) slot)) + || !acc->isSlotEmpty((unsigned) slot)) { reply.writeInt8(CREATE_INVALID_SLOT); client.send(reply); @@ -757,13 +757,13 @@ void AccountHandler::handleCharacterCreateMessage(AccountClient &client, // Customization of character's attributes... std::vector<int> attributes = std::vector<int>(mModifiableAttributes.size(), 0); - for (unsigned int i = 0; i < mModifiableAttributes.size(); ++i) + for (unsigned i = 0; i < mModifiableAttributes.size(); ++i) attributes[i] = 5; Character *newCharacter = new Character(name); // Set the initial attributes provided by the client - for (unsigned int i = 0; i < mModifiableAttributes.size(); ++i) + for (unsigned i = 0; i < mModifiableAttributes.size(); ++i) { newCharacter->mAttributes.insert( std::make_pair(mModifiableAttributes.at(i), attributes[i])); diff --git a/src/account-server/character.h b/src/account-server/character.h index 5e6bd3b3..0b697392 100644 --- a/src/account-server/character.h +++ b/src/account-server/character.h @@ -55,22 +55,22 @@ struct SpecialValue : currentMana(0) {} - SpecialValue(unsigned int currentMana) + SpecialValue(unsigned currentMana) : currentMana(currentMana) {} - unsigned int currentMana; + unsigned currentMana; }; /** * Stores attributes by their id. */ -typedef std::map<unsigned int, AttributeValue> AttributeMap; +typedef std::map<unsigned, AttributeValue> AttributeMap; /** * Stores specials by their id. */ -typedef std::map<unsigned int, SpecialValue> SpecialMap; +typedef std::map<unsigned, SpecialValue> SpecialMap; class Character { @@ -87,10 +87,10 @@ class Character /** * Gets the slot of the character. */ - unsigned int getCharacterSlot() const + unsigned getCharacterSlot() const { return mCharacterSlot; } - void setCharacterSlot(unsigned int slot) + void setCharacterSlot(unsigned slot) { mCharacterSlot = slot; } /** Gets the account the character belongs to. */ @@ -148,10 +148,10 @@ class Character void setLevel(int level) { mLevel = level; } /** Sets the value of a base attribute of the character. */ - void setAttribute(unsigned int id, double value) + void setAttribute(unsigned id, double value) { mAttributes[id].base = value; } - void setModAttribute(unsigned int id, double value) + void setModAttribute(unsigned id, double value) { mAttributes[id].modified = value; } int getSkillSize() const @@ -277,7 +277,7 @@ class Character Possessions mPossessions; //!< All the possesions of the character. std::string mName; //!< Name of the character. int mDatabaseID; //!< Character database ID. - unsigned int mCharacterSlot; //!< Character slot. + unsigned mCharacterSlot; //!< Character slot. int mAccountID; //!< Account ID of the owner. Account *mAccount; //!< Account owning the character. Point mPos; //!< Position the being is at. @@ -307,6 +307,6 @@ class Character /** * Type definition for a list of Characters. */ -typedef std::map<unsigned int, Character* > Characters; +typedef std::map<unsigned, Character* > Characters; #endif diff --git a/src/account-server/main-account.cpp b/src/account-server/main-account.cpp index ab4df75e..db69fe69 100644 --- a/src/account-server/main-account.cpp +++ b/src/account-server/main-account.cpp @@ -23,6 +23,10 @@ #include "../config.h" #endif +#ifdef __MINGW32__ +#include "common/winver.h" +#endif + #include "account-server/accounthandler.h" #include "account-server/serverhandler.h" #include "account-server/storage.h" diff --git a/src/account-server/serverhandler.cpp b/src/account-server/serverhandler.cpp index c938324f..04fd1e23 100644 --- a/src/account-server/serverhandler.cpp +++ b/src/account-server/serverhandler.cpp @@ -57,7 +57,7 @@ typedef std::map<unsigned short, MapStatistics> ServerStatistics; */ struct GameServer: NetComputer { - GameServer(ENetPeer *peer): NetComputer(peer), port(0) {} + GameServer(ENetPeer *peer): NetComputer(peer), server(0), port(0) {} std::string address; NetComputer *server; @@ -185,7 +185,7 @@ void ServerHandler::processMessage(NetComputer *comp, MessageIn &msg) const std::string password = msg.readString(); // checks the version of the remote item database with our local copy - unsigned int dbversion = msg.readInt32(); + unsigned dbversion = msg.readInt32(); LOG_INFO("Game server uses itemsdatabase with version " << dbversion); LOG_DEBUG("AGMSG_REGISTER_RESPONSE"); @@ -487,7 +487,7 @@ void ServerHandler::processMessage(NetComputer *comp, MessageIn &msg) // send the post if valid if (post) { - for (unsigned int i = 0; i < post->getNumberOfLetters(); ++i) + for (unsigned i = 0; i < post->getNumberOfLetters(); ++i) { // get each letter, send the sender's name, // the contents and any attachments @@ -495,7 +495,7 @@ void ServerHandler::processMessage(NetComputer *comp, MessageIn &msg) result.writeString(letter->getSender()->getName()); result.writeString(letter->getContents()); std::vector<InventoryItem> items = letter->getAttachments(); - for (unsigned int j = 0; j < items.size(); ++j) + for (unsigned j = 0; j < items.size(); ++j) { result.writeInt16(items[j].itemId); result.writeInt16(items[j].amount); @@ -546,7 +546,7 @@ void ServerHandler::processMessage(NetComputer *comp, MessageIn &msg) LOG_DEBUG("Creating letter"); Letter *letter = new Letter(0, sender, receiver); letter->addText(contents); - for (unsigned int i = 0; i < items.size(); ++i) + for (unsigned i = 0; i < items.size(); ++i) { InventoryItem item; item.itemId = items[i].first; @@ -708,7 +708,7 @@ void GameServerHandler::syncDatabase(MessageIn &msg) int charId = msg.readInt32(); bool online = (msg.readInt8() == 1); storage->setOnlineStatus(charId, online); - } + } break; } } diff --git a/src/account-server/storage.cpp b/src/account-server/storage.cpp index 9426c885..067967e1 100644 --- a/src/account-server/storage.cpp +++ b/src/account-server/storage.cpp @@ -174,8 +174,6 @@ Account *Storage::getAccountBySQL() if (accountInfo.isEmpty()) return 0; - // Specialize the string_to functor to convert - // a string to an unsigned int. string_to< unsigned > toUint; unsigned id = toUint(accountInfo(0, 0)); @@ -265,8 +263,6 @@ void Storage::fixCharactersSlot(int accountId) if (charInfo.isEmpty()) return; - // Specialize the string_to functor to convert - // a string to an unsigned int. string_to< unsigned > toUint; std::map<unsigned, unsigned> slotsToUpdate; @@ -347,8 +343,6 @@ Character *Storage::getCharacterBySQL(Account *owner) { Character *character = 0; - // Specialize the string_to functor to convert - // a string to an unsigned int. string_to< unsigned > toUint; string_to< int > toInt; @@ -361,8 +355,6 @@ Character *Storage::getCharacterBySQL(Account *owner) if (charInfo.isEmpty()) return 0; - // Specialize the string_to functor to convert - // a string to an unsigned short. string_to< unsigned short > toUshort; string_to< double > toDouble; @@ -417,10 +409,10 @@ Character *Storage::getCharacterBySQL(Account *owner) const dal::RecordSet &attrInfo = mDb->execSql(s.str()); if (!attrInfo.isEmpty()) { - const unsigned int nRows = attrInfo.rows(); - for (unsigned int row = 0; row < nRows; ++row) + const unsigned nRows = attrInfo.rows(); + for (unsigned row = 0; row < nRows; ++row) { - unsigned int id = toUint(attrInfo(row, 0)); + unsigned id = toUint(attrInfo(row, 0)); character->setAttribute(id, toDouble(attrInfo(row, 1))); character->setModAttribute(id, toDouble(attrInfo(row, 2))); } @@ -437,10 +429,10 @@ Character *Storage::getCharacterBySQL(Account *owner) const dal::RecordSet &skillInfo = mDb->execSql(s.str()); if (!skillInfo.isEmpty()) { - const unsigned int nRows = skillInfo.rows(); - for (unsigned int row = 0; row < nRows; ++row) + const unsigned nRows = skillInfo.rows(); + for (unsigned row = 0; row < nRows; ++row) { - unsigned int id = toUint(skillInfo(row, 0)); + unsigned id = toUint(skillInfo(row, 0)); character->setExperience(id, toInt(skillInfo(row, 1))); } } @@ -455,8 +447,8 @@ Character *Storage::getCharacterBySQL(Account *owner) const dal::RecordSet &statusInfo = mDb->execSql(s.str()); if (!statusInfo.isEmpty()) { - const unsigned int nRows = statusInfo.rows(); - for (unsigned int row = 0; row < nRows; row++) + const unsigned nRows = statusInfo.rows(); + for (unsigned row = 0; row < nRows; row++) { character->applyStatusEffect( toUint(statusInfo(row, 0)), // Status Id @@ -472,8 +464,8 @@ Character *Storage::getCharacterBySQL(Account *owner) const dal::RecordSet &killsInfo = mDb->execSql(s.str()); if (!killsInfo.isEmpty()) { - const unsigned int nRows = killsInfo.rows(); - for (unsigned int row = 0; row < nRows; row++) + const unsigned nRows = killsInfo.rows(); + for (unsigned row = 0; row < nRows; row++) { character->setKillCount( toUint(killsInfo(row, 0)), // MonsterID @@ -490,8 +482,8 @@ Character *Storage::getCharacterBySQL(Account *owner) const dal::RecordSet &specialsInfo = mDb->execSql(s.str()); if (!specialsInfo.isEmpty()) { - const unsigned int nRows = specialsInfo.rows(); - for (unsigned int row = 0; row < nRows; row++) + const unsigned nRows = specialsInfo.rows(); + for (unsigned row = 0; row < nRows; row++) { character->giveSpecial(toUint(specialsInfo(row, 0)), toUint(specialsInfo(row, 1))); @@ -523,7 +515,7 @@ Character *Storage::getCharacterBySQL(Account *owner) { equipItem.itemId = toUint(equipInfo(k, 1)); equipItem.itemInstance = toUint(equipInfo(k, 2)); - equipData.insert(std::pair<unsigned int, EquipmentItem>( + equipData.insert(std::pair<unsigned, EquipmentItem>( toUint(equipInfo(k, 0)), equipItem)); } @@ -591,7 +583,7 @@ Character *Storage::getCharacter(const std::string &name) return 0; } -unsigned int Storage::getCharacterId(const std::string &name) +unsigned Storage::getCharacterId(const std::string &name) { std::ostringstream sql; sql << "SELECT id FROM " << CHARACTERS_TBL_NAME << " WHERE name = ?"; @@ -629,7 +621,7 @@ bool Storage::doesUserNameExist(const std::string &name) const dal::RecordSet &accountInfo = mDb->processSql(); std::istringstream ssStream(accountInfo(0, 0)); - unsigned int iReturn = 1; + unsigned iReturn = 1; ssStream >> iReturn; return iReturn != 0; } @@ -662,7 +654,7 @@ bool Storage::doesEmailAddressExist(const std::string &email) const dal::RecordSet &accountInfo = mDb->processSql(); std::istringstream ssStream(accountInfo(0, 0)); - unsigned int iReturn = 1; + unsigned iReturn = 1; ssStream >> iReturn; return iReturn != 0; } @@ -884,8 +876,8 @@ bool Storage::updateCharacter(Character *character) { sql.str(""); unsigned short slot = j->first; - unsigned int itemId = j->second.itemId; - unsigned int amount = j->second.amount; + unsigned itemId = j->second.itemId; + unsigned amount = j->second.amount; assert(itemId); sql << base << slot << ", " << itemId << ", " << amount << ");"; mDb->execSql(sql.str()); @@ -935,14 +927,6 @@ bool Storage::updateCharacter(Character *character) return true; } -void Storage::flushSkill(const Character *character, int skillId) -{ - // Note: Deprecated, use DALStorage::updateExperience instead!!! - // TODO: Remove calls of flushSkill for updateExperience instead. - updateExperience(character->getDatabaseID(), skillId, - character->getExperience(skillId)); -} - void Storage::addAccount(Account *account) { assert(account->getCharacters().size() == 0); @@ -1084,8 +1068,6 @@ void Storage::flush(Account *account) // or updated in database. // Now, let's remove those who are no more in memory from database. - // Specialize the string_to functor to convert - // a string to an unsigned int. string_to<unsigned short> toUint; std::ostringstream sqlSelectNameIdCharactersTable; @@ -1099,7 +1081,7 @@ void Storage::flush(Account *account) // We compare chars from memory and those existing in db, // and delete those not in mem but existing in db. bool charFound; - for (unsigned int i = 0; i < charInMemInfo.rows(); ++i) // In database + for (unsigned i = 0; i < charInMemInfo.rows(); ++i) // In database { charFound = false; for (Characters::const_iterator it = characters.begin(), @@ -1118,7 +1100,7 @@ void Storage::flush(Account *account) // We store the id of the char to delete, // because as deleted, the RecordSet is also emptied, // and that creates an error. - unsigned int charId = toUint(charInMemInfo(i, 1)); + unsigned charId = toUint(charInMemInfo(i, 1)); delCharacter(charId); } } @@ -1235,7 +1217,7 @@ void Storage::updateExperience(int charId, int skillId, int skillValue) } } -void Storage::updateAttribute(int charId, unsigned int attrId, +void Storage::updateAttribute(int charId, unsigned attrId, double base, double mod) { try @@ -1349,7 +1331,7 @@ void Storage::addGuild(Guild *guild) mDb->bindValue(1, guild->getName()); const dal::RecordSet& guildInfo = mDb->processSql(); - string_to<unsigned int> toUint; + string_to<unsigned> toUint; unsigned id = toUint(guildInfo(0, 0)); guild->setId(id); } @@ -1531,7 +1513,7 @@ std::map<int, Guild*> Storage::getGuildList() return guilds; // Loop through every row in the table and assign it to a guild - for (unsigned int i = 0; i < guildInfo.rows(); ++i) + for (unsigned i = 0; i < guildInfo.rows(); ++i) { Guild* guild = new Guild(guildInfo(i,1)); guild->setId(toShort(guildInfo(i,0))); @@ -1550,7 +1532,7 @@ std::map<int, Guild*> Storage::getGuildList() const dal::RecordSet& memberInfo = mDb->execSql(memberSql.str()); std::list<std::pair<int, int> > members; - for (unsigned int j = 0; j < memberInfo.rows(); ++j) + for (unsigned j = 0; j < memberInfo.rows(); ++j) { members.push_back(std::pair<int, int>(toUint(memberInfo(j, 0)), toUint(memberInfo(j, 1)))); @@ -1677,7 +1659,7 @@ std::map<std::string, std::string> Storage::getAllWorldStateVars(int mapId) mDb->bindValue(1, mapId); const dal::RecordSet &results = mDb->processSql(); - for (unsigned int i = 0; i < results.rows(); ++i) + for (unsigned i = 0; i < results.rows(); ++i) { variables[results(i, 0)] = results(i, 1); } @@ -1998,8 +1980,6 @@ Post *Storage::getStoredPost(int playerId) { Post *p = new Post(); - // Specialize the string_to functor to convert - // a string to an unsigned int. string_to< unsigned > toUint; try @@ -2016,7 +1996,7 @@ Post *Storage::getStoredPost(int playerId) return p; } - for (unsigned int i = 0; i < post.rows(); i++ ) + for (unsigned i = 0; i < post.rows(); i++ ) { // Load sender and receiver Character *sender = getCharacter(toUint(post(i, 1)), 0); @@ -2248,10 +2228,10 @@ void Storage::addTransaction(const Transaction &trans) } } -std::vector<Transaction> Storage::getTransactions(unsigned int num) +std::vector<Transaction> Storage::getTransactions(unsigned num) { std::vector<Transaction> transactions; - string_to<unsigned int> toUint; + string_to<unsigned> toUint; try { @@ -2283,7 +2263,7 @@ std::vector<Transaction> Storage::getTransactions(unsigned int num) std::vector<Transaction> Storage::getTransactions(time_t date) { std::vector<Transaction> transactions; - string_to<unsigned int> toUint; + string_to<unsigned> toUint; try { @@ -2292,7 +2272,7 @@ std::vector<Transaction> Storage::getTransactions(time_t date) << date; const dal::RecordSet &rec = mDb->execSql(sql.str()); - for (unsigned int i = 0; i < rec.rows(); ++i) + for (unsigned i = 0; i < rec.rows(); ++i) { Transaction trans; trans.mCharacterId = toUint(rec(i, 1)); diff --git a/src/account-server/storage.h b/src/account-server/storage.h index b71be22f..06645c69 100644 --- a/src/account-server/storage.h +++ b/src/account-server/storage.h @@ -101,7 +101,7 @@ class Storage * * @return the id of the character */ - unsigned int getCharacterId(const std::string &name); + unsigned getCharacterId(const std::string &name); /** * Add an account to the database. @@ -152,7 +152,7 @@ class Storage * @param base The base value of the attribute for this character * @param mod The cached modified value for this character. */ - void updateAttribute(int charId, unsigned int attrId, + void updateAttribute(int charId, unsigned attrId, double base, double mod); /** @@ -241,17 +241,6 @@ class Storage bool updateCharacter(Character *ptr); /** - * Save changes of a skill to the database permanently. - * - * @param character Character thats skill has changed. - * @param skill_id Identifier of the changed skill. - * - * @exception dbl::DbSqlQueryExecFailure. - * @deprecated Use DALStorage::updateExperience instead!!! - */ - void flushSkill(const Character *character, int skillId); - - /** * Add a new guild. * * @param guild The guild to add in database. @@ -427,7 +416,7 @@ class Storage * * @return the database version number. */ - unsigned int getItemDatabaseVersion() const + unsigned getItemDatabaseVersion() const { return mItemDbVersion; } /** @@ -450,7 +439,7 @@ class Storage * * @return a vector of transactions. */ - std::vector<Transaction> getTransactions(unsigned int num); + std::vector<Transaction> getTransactions(unsigned num); /** * Retrieve all transactions since the given \a date. @@ -508,7 +497,7 @@ class Storage void syncDatabase(); dal::DataProvider *mDb; /**< the data provider */ - unsigned int mItemDbVersion; /**< Version of the item database. */ + unsigned mItemDbVersion; /**< Version of the item database. */ }; extern Storage *storage; diff --git a/src/chat-server/chatclient.h b/src/chat-server/chatclient.h index a0812a30..7e8c4e2e 100644 --- a/src/chat-server/chatclient.h +++ b/src/chat-server/chatclient.h @@ -46,7 +46,7 @@ class ChatClient : public NetComputer } std::string characterName; - unsigned int characterId; + unsigned characterId; std::vector<ChatChannel *> channels; std::vector<Guild *> guilds; Party *party; diff --git a/src/chat-server/chathandler.h b/src/chat-server/chathandler.h index 06d72513..1a96cfbc 100644 --- a/src/chat-server/chathandler.h +++ b/src/chat-server/chathandler.h @@ -214,7 +214,7 @@ class ChatHandler : public ConnectionHandler * Finds out the name of a character by its id. Either searches it * in the list of online characters or otherwise gets it from the db. */ - unsigned int getIdOfChar(const std::string &name); + unsigned getIdOfChar(const std::string &name); /** * Sends a message to every client in a registered channel. diff --git a/src/chat-server/guildhandler.cpp b/src/chat-server/guildhandler.cpp index 949728c2..1bbe3671 100644 --- a/src/chat-server/guildhandler.cpp +++ b/src/chat-server/guildhandler.cpp @@ -350,7 +350,7 @@ void ChatHandler::handleGuildKickMember(ChatClient &client, MessageIn &msg) return; } ChatClient *otherClient = getClient(otherCharName); - unsigned int otherCharId; + unsigned otherCharId; if (otherClient) otherCharId = otherClient->characterId; else diff --git a/src/chat-server/party.h b/src/chat-server/party.h index da8755b3..18bec58d 100644 --- a/src/chat-server/party.h +++ b/src/chat-server/party.h @@ -48,19 +48,19 @@ public: /** * Return number of users in party */ - unsigned int userCount() const { return mUsers.size(); } + unsigned userCount() const { return mUsers.size(); } /** * Return the party id */ - unsigned int getId() const { return mId; } + unsigned getId() const { return mId; } const PartyUsers &getUsers() const { return mUsers; } private: PartyUsers mUsers; - unsigned int mId; + unsigned mId; }; #endif diff --git a/src/chat-server/post.cpp b/src/chat-server/post.cpp index eff5ddb3..dc1e0d1e 100644 --- a/src/chat-server/post.cpp +++ b/src/chat-server/post.cpp @@ -23,7 +23,7 @@ #include "../account-server/character.h" #include "../common/configuration.h" -Letter::Letter(unsigned int type, Character *sender, Character *receiver) +Letter::Letter(unsigned type, Character *sender, Character *receiver) : mId(0), mType(type), mSender(sender), mReceiver(receiver) { } @@ -59,7 +59,7 @@ std::string Letter::getContents() const bool Letter::addAttachment(InventoryItem item) { - unsigned int max = Configuration::getValue("mail_maxAttachments", 3); + unsigned max = Configuration::getValue("mail_maxAttachments", 3); if (mAttachments.size() > max) { return false; @@ -100,7 +100,7 @@ Post::~Post() bool Post::addLetter(Letter *letter) { - unsigned int max = Configuration::getValue("mail_maxLetters", 10); + unsigned max = Configuration::getValue("mail_maxLetters", 10); if (mLetters.size() > max) { return false; @@ -120,7 +120,7 @@ Letter* Post::getLetter(int letter) const return mLetters[letter]; } -unsigned int Post::getNumberOfLetters() const +unsigned Post::getNumberOfLetters() const { return mLetters.size(); } diff --git a/src/chat-server/post.h b/src/chat-server/post.h index c8006faa..2d0b2ae0 100644 --- a/src/chat-server/post.h +++ b/src/chat-server/post.h @@ -42,7 +42,7 @@ public: * @param sender Pointer to character that sent the letter * @param receiver Pointer to character that will receive the letter */ - Letter(unsigned int type, Character *sender, Character *receiver); + Letter(unsigned type, Character *sender, Character *receiver); ~Letter(); @@ -62,7 +62,7 @@ public: /** * Gets the type of the letter. (unused) */ - unsigned int getType() const + unsigned getType() const { return mType; } /** @@ -113,8 +113,8 @@ public: std::vector<InventoryItem> getAttachments() const; private: - unsigned int mId; - unsigned int mType; + unsigned mId; + unsigned mType; unsigned long mExpiry; std::string mContents; std::vector<InventoryItem> mAttachments; @@ -143,7 +143,7 @@ public: * Return number of letters in post * @return Returns the size of mLetters */ - unsigned int getNumberOfLetters() const; + unsigned getNumberOfLetters() const; private: std::vector<Letter*> mLetters; diff --git a/src/common/inventorydata.h b/src/common/inventorydata.h index 490abff2..b410b3fb 100644 --- a/src/common/inventorydata.h +++ b/src/common/inventorydata.h @@ -39,8 +39,8 @@ struct InventoryItem itemId(0), amount(0) {} - unsigned int itemId; - unsigned int amount; + unsigned itemId; + unsigned amount; }; struct EquipmentItem @@ -49,25 +49,25 @@ struct EquipmentItem itemId(0), itemInstance(0) {} - EquipmentItem(unsigned int itemId, unsigned int itemInstance) + EquipmentItem(unsigned itemId, unsigned itemInstance) { this->itemId = itemId; this->itemInstance = itemInstance; } // The item id taken from the item db. - unsigned int itemId; + unsigned itemId; // A unique instance number used to separate items when equipping the same // item id multiple times on possible multiple slots. - unsigned int itemInstance; + unsigned itemInstance; }; // inventory slot id -> { item } -typedef std::map< unsigned int, InventoryItem > InventoryData; +typedef std::map< unsigned, InventoryItem > InventoryData; // equip slot id -> { item id, item instance } // Equipment taking up multiple equip slot ids will be referenced multiple times -typedef std::multimap< unsigned int, EquipmentItem > EquipData; +typedef std::multimap< unsigned, EquipmentItem > EquipData; /** * Structure storing the equipment and inventory of a Player. diff --git a/src/common/manaserv_protocol.h b/src/common/manaserv_protocol.h index 4bac0837..6a1e31d6 100644 --- a/src/common/manaserv_protocol.h +++ b/src/common/manaserv_protocol.h @@ -133,6 +133,8 @@ enum { GPMSG_BEING_LEAVE = 0x0201, // W being id GPMSG_ITEM_APPEAR = 0x0202, // W item id, W*2 position GPMSG_BEING_LOOKS_CHANGE = 0x0210, // B sprite layers changed, { B slot type, W item id }* + GPMSG_BEING_EMOTE = 0x0211, // W being id, W emote id + PGMSG_BEING_EMOTE = 0x0212, // W emoticon id PGMSG_WALK = 0x0260, // W*2 destination PGMSG_ACTION_CHANGE = 0x0270, // B Action GPMSG_BEING_ACTION_CHANGE = 0x0271, // W being id, B action diff --git a/src/common/transaction.h b/src/common/transaction.h index fdd0b8f7..51c373eb 100644 --- a/src/common/transaction.h +++ b/src/common/transaction.h @@ -23,8 +23,8 @@ struct Transaction { - unsigned int mAction; - unsigned int mCharacterId; + unsigned mAction; + unsigned mCharacterId; std::string mMessage; }; diff --git a/src/common/winver.h b/src/common/winver.h new file mode 100644 index 00000000..03a0c215 --- /dev/null +++ b/src/common/winver.h @@ -0,0 +1,6 @@ +/* VERSION DEFINITIONS */ +#define VER_MAJOR 0 +#define VER_MINOR 1 +#define VER_RELEASE 0 +#define VER_BUILD 0 +#define PACKAGE_VERSION "0.1.0.0" diff --git a/src/common/winver.h.in b/src/common/winver.h.in new file mode 100644 index 00000000..fb0aac2c --- /dev/null +++ b/src/common/winver.h.in @@ -0,0 +1,6 @@ +/* VERSION DEFINITIONS */ +#define VER_MAJOR ${VER_MAJOR} +#define VER_MINOR ${VER_MINOR} +#define VER_RELEASE ${VER_RELEASE} +#define VER_BUILD ${VER_BUILD} +#define PACKAGE_VERSION "${VERSION}" diff --git a/src/dal/mysqldataprovider.cpp b/src/dal/mysqldataprovider.cpp index 13036461..9f9c4a93 100644 --- a/src/dal/mysqldataprovider.cpp +++ b/src/dal/mysqldataprovider.cpp @@ -32,7 +32,7 @@ const std::string MySqlDataProvider::CFGPARAM_MYSQL_USER ="mysql_username"; const std::string MySqlDataProvider::CFGPARAM_MYSQL_PWD ="mysql_password"; const std::string MySqlDataProvider::CFGPARAM_MYSQL_HOST_DEF = "localhost"; -const unsigned int MySqlDataProvider::CFGPARAM_MYSQL_PORT_DEF = 3306; +const unsigned MySqlDataProvider::CFGPARAM_MYSQL_PORT_DEF = 3306; const std::string MySqlDataProvider::CFGPARAM_MYSQL_DB_DEF = "mana"; const std::string MySqlDataProvider::CFGPARAM_MYSQL_USER_DEF = "mana"; const std::string MySqlDataProvider::CFGPARAM_MYSQL_PWD_DEF = "mana"; @@ -84,7 +84,7 @@ void MySqlDataProvider::connect() = Configuration::getValue(CFGPARAM_MYSQL_USER, CFGPARAM_MYSQL_USER_DEF); const std::string password = Configuration::getValue(CFGPARAM_MYSQL_PWD, CFGPARAM_MYSQL_PWD_DEF); - const unsigned int tcpPort + const unsigned tcpPort = Configuration::getValue(CFGPARAM_MYSQL_PORT, CFGPARAM_MYSQL_PORT_DEF); // allocate and initialize a new MySQL object suitable @@ -158,10 +158,10 @@ const RecordSet &MySqlDataProvider::execSql(const std::string& sql, throw DbSqlQueryExecFailure(mysql_error(mDb)); // set the field names. - unsigned int nFields = mysql_num_fields(res); + unsigned nFields = mysql_num_fields(res); MYSQL_FIELD* fields = mysql_fetch_fields(res); Row fieldNames; - for (unsigned int i = 0; i < nFields; ++i) + for (unsigned i = 0; i < nFields; ++i) fieldNames.push_back(fields[i].name); mRecordSet.setColumnHeaders(fieldNames); @@ -172,7 +172,7 @@ const RecordSet &MySqlDataProvider::execSql(const std::string& sql, { Row r; - for (unsigned int i = 0; i < nFields; ++i) + for (unsigned i = 0; i < nFields; ++i) r.push_back(static_cast<char *>(row[i])); mRecordSet.add(r); @@ -411,13 +411,13 @@ const RecordSet &MySqlDataProvider::processSql() res = mysql_stmt_result_metadata(mStmt); // set the field names. - unsigned int nFields = mysql_num_fields(res); + unsigned nFields = mysql_num_fields(res); MYSQL_FIELD* fields = mysql_fetch_fields(res); Row fieldNames; resultBind = new MYSQL_BIND[mysql_num_fields(res)]; - unsigned int i = 0; + unsigned i = 0; for (i = 0; i < mysql_num_fields(res); ++i) { resultBind[i].buffer_type = MYSQL_TYPE_STRING; diff --git a/src/dal/mysqldataprovider.h b/src/dal/mysqldataprovider.h index 945b284f..6f8de3a8 100644 --- a/src/dal/mysqldataprovider.h +++ b/src/dal/mysqldataprovider.h @@ -192,7 +192,7 @@ class MySqlDataProvider: public DataProvider /** defines the default value of the CFGPARAM_MYSQL_HOST parameter */ static const std::string CFGPARAM_MYSQL_HOST_DEF; /** defines the default value of the CFGPARAM_MYSQL_PORT parameter */ - static const unsigned int CFGPARAM_MYSQL_PORT_DEF; + static const unsigned CFGPARAM_MYSQL_PORT_DEF; /** defines the default value of the CFGPARAM_MYSQL_DB parameter */ static const std::string CFGPARAM_MYSQL_DB_DEF; /** defines the default value of the CFGPARAM_MYSQL_USER parameter */ diff --git a/src/dal/pqdataprovider.cpp b/src/dal/pqdataprovider.cpp index 58959129..34dd5486 100644 --- a/src/dal/pqdataprovider.cpp +++ b/src/dal/pqdataprovider.cpp @@ -100,22 +100,22 @@ const RecordSet &PqDataProvider::execSql(const std::string& sql, } // get field count - unsigned int nFields = PQnfields(res); + unsigned nFields = PQnfields(res); // fill column names Row fieldNames; - for (unsigned int i = 0; i < nFields; i++) + for (unsigned i = 0; i < nFields; i++) { fieldNames.push_back(PQfname(res, i)); } mRecordSet.setColumnHeaders(fieldNames); // fill rows - for (unsigned int r = 0; r < PQntuples(res); r++) + for (unsigned r = 0; r < PQntuples(res); r++) { Row row; - for (unsigned int i = 0; i < nFields; i++) + for (unsigned i = 0; i < nFields; i++) row.push_back(PQgetvalue(res, r, i)); mRecordSet.add(row); diff --git a/src/dal/recordset.cpp b/src/dal/recordset.cpp index 065bbd77..0529325f 100644 --- a/src/dal/recordset.cpp +++ b/src/dal/recordset.cpp @@ -61,7 +61,7 @@ bool RecordSet::isEmpty() const * * @return the number of rows. */ -unsigned int RecordSet::rows() const +unsigned RecordSet::rows() const { return mRows.size(); } @@ -71,7 +71,7 @@ unsigned int RecordSet::rows() const * * @return the number of columns. */ -unsigned int RecordSet::cols() const +unsigned RecordSet::cols() const { return mHeaders.size(); } @@ -93,7 +93,7 @@ void RecordSet::setColumnHeaders(const Row &headers) */ void RecordSet::add(const Row &row) { - const unsigned int nCols = mHeaders.size(); + const unsigned nCols = mHeaders.size(); if (nCols == 0) { throw RsColumnHeadersNotSet(); @@ -110,8 +110,8 @@ void RecordSet::add(const Row &row) mRows.push_back(row); } -const std::string &RecordSet::operator()(const unsigned int row, - const unsigned int col) const +const std::string &RecordSet::operator()(const unsigned row, + const unsigned col) const { if ((row >= mRows.size()) || (col >= mHeaders.size())) { std::ostringstream os; @@ -125,7 +125,7 @@ const std::string &RecordSet::operator()(const unsigned int row, return mRows[row][col]; } -const std::string &RecordSet::operator()(const unsigned int row, +const std::string &RecordSet::operator()(const unsigned row, const std::string& name) const { if (row >= mRows.size()) { @@ -147,8 +147,8 @@ const std::string &RecordSet::operator()(const unsigned int row, } // find the field index. - const unsigned int nCols = mHeaders.size(); - unsigned int i; + const unsigned nCols = mHeaders.size(); + unsigned i; for (i = 0; i < nCols; ++i) { if (mHeaders[i] == name) { break; diff --git a/src/dal/recordset.h b/src/dal/recordset.h index 80c2e68f..91b434de 100644 --- a/src/dal/recordset.h +++ b/src/dal/recordset.h @@ -67,14 +67,14 @@ class RecordSet * * @return the number of rows. */ - unsigned int rows() const; + unsigned rows() const; /** * Get the number of columns. * * @return the number of columns. */ - unsigned int cols() const; + unsigned cols() const; /** * Set the column headers. @@ -115,8 +115,8 @@ class RecordSet * @exception std::invalid_argument if the recordset is empty. */ const std::string& - operator()(const unsigned int row, - const unsigned int col) const; + operator()(const unsigned row, + const unsigned col) const; /** @@ -134,7 +134,7 @@ class RecordSet * the recordset is empty. */ const std::string& - operator()(const unsigned int row, + operator()(const unsigned row, const std::string &name) const; diff --git a/src/game-server/actor.h b/src/game-server/actor.h index 324393df..13d4af55 100644 --- a/src/game-server/actor.h +++ b/src/game-server/actor.h @@ -37,7 +37,8 @@ enum UPDATEFLAG_ACTIONCHANGE = 8, UPDATEFLAG_LOOKSCHANGE = 16, UPDATEFLAG_DIRCHANGE = 32, - UPDATEFLAG_HEALTHCHANGE = 64 + UPDATEFLAG_HEALTHCHANGE = 64, + UPDATEFLAG_EMOTE = 128 }; /** diff --git a/src/game-server/attack.cpp b/src/game-server/attack.cpp index 7f539f1a..1825b86a 100644 --- a/src/game-server/attack.cpp +++ b/src/game-server/attack.cpp @@ -20,6 +20,8 @@ #include "attack.h" +#include <cassert> + #include "common/defines.h" #include "game-server/character.h" @@ -28,21 +30,20 @@ AttackInfo *AttackInfo::readAttackNode(xmlNodePtr node) { std::string skill = XML::getProperty(node, "skill", std::string()); + unsigned skillId; if (utils::isNumeric(skill)) - { skillId = utils::stringToInt(skill); - } else - { skillId = skillManager->getId(skill); - if (skillId == 0) - { - LOG_WARN("Error parsing Attack node: Invalid skill " << skill - << " taking default skill"); - skillId = skillManager->getDefaultSkillId(); - } + + if (!skill.empty() && !skillManager->exists(skillId)) + { + LOG_WARN("Error parsing Attack node: Invalid skill " << skill + << " taking default skill"); + skillId = skillManager->getDefaultSkillId(); } + unsigned id = XML::getProperty(node, "id", 0); unsigned priority = XML::getProperty(node, "priority", 0); unsigned warmupTime = XML::getProperty(node, "warmuptime", 0); @@ -118,17 +119,19 @@ void Attacks::startAttack(Attack *attack) attack->getAttackInfo()->getCooldownTime()); } -void Attacks::tick(std::vector<Attack *> *ret) +void Attacks::getUsuableAttacks(std::vector<Attack *> *ret) { + assert(ret != 0); + // we have a current Attack - if (!mAttackTimer.expired() && mCurrentAttack) + if ((!mAttackTimer.expired() && mCurrentAttack)) return; for (std::vector<Attack>::iterator it = mAttacks.begin(); it != mAttacks.end(); ++it) { Attack &attack = *it; - if (ret && attack.isUsuable()) + if (attack.isUsuable()) { ret->push_back(&attack); } diff --git a/src/game-server/attack.h b/src/game-server/attack.h index 7270a007..0bcc361c 100644 --- a/src/game-server/attack.h +++ b/src/game-server/attack.h @@ -175,15 +175,12 @@ class Attacks mCurrentAttack(0) {} - /** - * Whether the being has at least one auto attack that is ready. - */ void add(AttackInfo *); void remove(AttackInfo *); void markAttackAsTriggered(); Attack *getTriggerableAttack(); void startAttack(Attack *attack); - void tick(std::vector<Attack *> *ret); + void getUsuableAttacks(std::vector<Attack *> *ret); /** * Tells the number of attacks available diff --git a/src/game-server/attribute.cpp b/src/game-server/attribute.cpp index 31d743f4..71e5d944 100644 --- a/src/game-server/attribute.cpp +++ b/src/game-server/attribute.cpp @@ -133,7 +133,7 @@ bool durationCompare(const AttributeModifierState *lhs, return lhs->mDuration < rhs->mDuration; } -bool AttributeModifiersEffect::remove(double value, unsigned int id, +bool AttributeModifiersEffect::remove(double value, unsigned id, bool fullCheck) { /* We need to find and check this entry exists, and erase the entry @@ -249,16 +249,17 @@ bool AttributeModifiersEffect::recalculateModifiedValue(double newPrevLayerValue bool Attribute::add(unsigned short duration, double value, - unsigned int layer, int level) + unsigned layer, int id) { assert(mMods.size() > layer); - LOG_DEBUG("Adding modifier to attribute with duration " << duration << - ", value " << value << ", at layer " << layer << " with id " - << level); + LOG_DEBUG("Adding modifier to attribute with duration " << duration + << ", value " << value + << ", at layer " << layer + << " with id " << id); if (mMods.at(layer)->add(duration, value, (layer ? mMods.at(layer - 1)->getCachedModifiedValue() : mBase) - , level)) + , id)) { while (++layer < mMods.size()) { @@ -277,7 +278,7 @@ bool Attribute::add(unsigned short duration, double value, return false; } -bool Attribute::remove(double value, unsigned int layer, +bool Attribute::remove(double value, unsigned layer, int lvl, bool fullcheck) { assert(mMods.size() > layer); @@ -321,7 +322,7 @@ Attribute::Attribute(const AttributeManager::AttributeInfo &info): const std::vector<AttributeModifier> &modifiers = info.modifiers; LOG_DEBUG("Construction of new attribute with '" << modifiers.size() << "' layers."); - for (unsigned int i = 0; i < modifiers.size(); ++i) + for (unsigned i = 0; i < modifiers.size(); ++i) { LOG_DEBUG("Adding layer with stackable type " << modifiers[i].stackableType diff --git a/src/game-server/attribute.h b/src/game-server/attribute.h index 046c8f63..736e54a6 100644 --- a/src/game-server/attribute.h +++ b/src/game-server/attribute.h @@ -31,7 +31,7 @@ class AttributeModifierState public: AttributeModifierState(unsigned short duration, double value, - unsigned int id) + unsigned id) : mDuration(duration) , mValue(value) , mId(id) @@ -48,7 +48,7 @@ class AttributeModifierState * dispells or similar. Exact usage depends on the effect, * origin, etc. */ - const unsigned int mId; + const unsigned mId; friend bool durationCompare(const AttributeModifierState*, const AttributeModifierState*); friend class AttributeModifiersEffect; @@ -75,7 +75,7 @@ class AttributeModifiersEffect /** * remove() - as with Attribute::remove(). */ - bool remove(double value, unsigned int id, bool fullCheck); + bool remove(double value, unsigned id, bool fullCheck); /** * Performs the necessary modifications to mMod when the states change. @@ -132,7 +132,11 @@ class AttributeModifiersEffect class Attribute { public: - Attribute() {throw;} // DEBUG; Find improper constructions + Attribute() + : mBase(0) + , mMinValue(0) + , mMaxValue(0) + {throw;} // DEBUG; Find improper constructions Attribute(const AttributeManager::AttributeInfo &info); @@ -160,7 +164,7 @@ class Attribute * @param id Used to identify this effect. * @return Whether the modified attribute value was changed. */ - bool add(unsigned short duration, double value, unsigned int layer, int id = 0); + bool add(unsigned short duration, double value, unsigned layer, int id = 0); /** * @param value The value of the modifier to be removed. @@ -174,7 +178,7 @@ class Attribute * or only those that are otherwise permanent (ie. duration of 0) * @returns Whether the modified attribute value was changed. */ - bool remove(double value, unsigned int layer, int id, bool fullcheck); + bool remove(double value, unsigned layer, int id, bool fullcheck); /** * clearMods() removes *all* modifications present in this Attribute (!) diff --git a/src/game-server/attributemanager.cpp b/src/game-server/attributemanager.cpp index 3a70fd9a..42c2624d 100644 --- a/src/game-server/attributemanager.cpp +++ b/src/game-server/attributemanager.cpp @@ -33,7 +33,7 @@ void AttributeManager::reload() { mTagMap.clear(); mAttributeMap.clear(); - for (unsigned int i = 0; i < MaxScope; ++i) + for (unsigned i = 0; i < MaxScope; ++i) mAttributeScopes[i].clear(); readAttributesFile(); @@ -43,11 +43,11 @@ void AttributeManager::reload() << ", NonStackableBonus is " << NonStackableBonus << "."); LOG_DEBUG("Additive is " << Additive << ", Multiplicative is " << Multiplicative << "."); const std::string *tag; - unsigned int count = 0; + unsigned count = 0; for (AttributeMap::const_iterator i = mAttributeMap.begin(); i != mAttributeMap.end(); ++i) { - unsigned int lCount = 0; + unsigned lCount = 0; LOG_DEBUG(" "<<i->first<<" : "); for (std::vector<AttributeModifier>::const_iterator j = i->second.modifiers.begin(); @@ -144,13 +144,15 @@ void AttributeManager::readAttributeNode(xmlNodePtr attributeNode) return; } - mAttributeMap[id].modifiers = std::vector<AttributeModifier>(); - mAttributeMap[id].minimum = XML::getFloatProperty(attributeNode, "minimum", - std::numeric_limits<double>::min()); - mAttributeMap[id].maximum = XML::getFloatProperty(attributeNode, "maximum", - std::numeric_limits<double>::max()); - mAttributeMap[id].modifiable = XML::getBoolProperty(attributeNode, "modifiable", - false); + AttributeInfo &attribute = mAttributeMap[id]; + + attribute.modifiers = std::vector<AttributeModifier>(); + attribute.minimum = XML::getFloatProperty(attributeNode, "minimum", + std::numeric_limits<double>::min()); + attribute.maximum = XML::getFloatProperty(attributeNode, "maximum", + std::numeric_limits<double>::max()); + attribute.modifiable = XML::getBoolProperty(attributeNode, "modifiable", + false); for_each_xml_child_node(subNode, attributeNode) { @@ -171,22 +173,19 @@ void AttributeManager::readAttributeNode(xmlNodePtr attributeNode) } else if (scope == "CHARACTER") { - mAttributeScopes[CharacterScope][id] = - &mAttributeMap.at(id); + mAttributeScopes[CharacterScope][id] = &attribute; LOG_DEBUG("Attribute manager: attribute '" << id << "' added to default character scope."); } else if (scope == "MONSTER") { - mAttributeScopes[MonsterScope][id] = - &mAttributeMap.at(id); + mAttributeScopes[MonsterScope][id] = &attribute; LOG_DEBUG("Attribute manager: attribute '" << id << "' added to default monster scope."); } else if (scope == "BEING") { - mAttributeScopes[BeingScope][id] = - &mAttributeMap.at(id); + mAttributeScopes[BeingScope][id] = &attribute; LOG_DEBUG("Attribute manager: attribute '" << id << "' added to default being scope."); } @@ -250,6 +249,15 @@ void AttributeManager::readModifierNode(xmlNodePtr modifierNode, return; } + if (stackableType == NonStackable && effectType == Multiplicative) + { + LOG_WARN("Attribute manager: attribute '" << attributeId + << "' has a non sense modifier. " + << "Having NonStackable and Multiplicative makes no sense! " + << "Skipping modifier!"); + return; + } + mAttributeMap[attributeId].modifiers.push_back( AttributeModifier(stackableType, effectType)); diff --git a/src/game-server/attributemanager.h b/src/game-server/attributemanager.h index 63ebf643..1a55006c 100644 --- a/src/game-server/attributemanager.h +++ b/src/game-server/attributemanager.h @@ -94,7 +94,7 @@ class AttributeManager minimum(std::numeric_limits<double>::min()), maximum(std::numeric_limits<double>::max()), modifiable(false) - {} + {} /** The minimum and maximum permitted attribute values. */ double minimum; diff --git a/src/game-server/being.cpp b/src/game-server/being.cpp index ba45c0fd..2c334b37 100644 --- a/src/game-server/being.cpp +++ b/src/game-server/being.cpp @@ -27,7 +27,6 @@ #include "game-server/attributemanager.h" #include "game-server/character.h" #include "game-server/collisiondetection.h" -#include "game-server/eventlistener.h" #include "game-server/mapcomposite.h" #include "game-server/effect.h" #include "game-server/skillmanager.h" @@ -35,6 +34,11 @@ #include "game-server/statusmanager.h" #include "utils/logger.h" #include "utils/speedconv.h" +#include "scripting/scriptmanager.h" + + +Script::Ref Being::mRecalculateDerivedAttributesCallback; +Script::Ref Being::mRecalculateBaseAttributeCallback; Being::Being(EntityType type): Actor(type), @@ -42,7 +46,8 @@ Being::Being(EntityType type): mTarget(NULL), mGender(GENDER_UNSPECIFIED), mCurrentAttack(0), - mDirection(DOWN) + mDirection(DOWN), + mEmoteId(0) { const AttributeManager::AttributeScope &attr = attributeManager->getAttributeScope(BeingScope); LOG_DEBUG("Being creation: initialisation of " << attr.size() << " attributes."); @@ -58,6 +63,9 @@ Being::Being(EntityType type): Attribute(*it1->second))); } + + signal_inserted.connect(sigc::mem_fun(this, &Being::inserted)); + // TODO: Way to define default base values? // Should this be handled by the virtual modifiedAttribute? // URGENT either way @@ -71,6 +79,14 @@ Being::Being(EntityType type): #endif } +void Being::triggerEmote(int id) +{ + mEmoteId = id; + + if (id > -1) + raiseUpdateFlags(UPDATEFLAG_EMOTE); +} + int Being::damage(Actor * /* source */, const Damage &damage) { if (mAction == DEAD) @@ -111,6 +127,7 @@ int Being::damage(Actor * /* source */, const Damage &damage) "implemented yet and should not be used!"); HPloss = 0; #endif + break; case DAMAGE_DIRECT: break; default: @@ -177,14 +194,7 @@ void Being::died() // reset target mTarget = NULL; - for (Listeners::iterator i = mListeners.begin(), - i_end = mListeners.end(); i != i_end;) - { - const EventListener &l = **i; - ++i; // In case the listener removes itself from the list on the fly. - if (l.dispatch->died) - l.dispatch->died(&l, this); - } + signal_died.emit(this); } void Being::processAttacks() @@ -194,7 +204,7 @@ void Being::processAttacks() // Ticks attacks even when not attacking to permit cooldowns and warmups. std::vector<Attack *> attacksReady; - mAttacks.tick(&attacksReady); + mAttacks.getUsuableAttacks(&attacksReady); if (Attack *triggerableAttack = mAttacks.getTriggerableAttack()) { @@ -203,37 +213,37 @@ void Being::processAttacks() } // Deal with the ATTACK action. - if (!attacksReady.empty()) - { - Attack *highestPriorityAttack = 0; - // Performs all ready attacks. - for (std::vector<Attack *>::iterator it = attacksReady.begin(), - it_end = attacksReady.end(); it != it_end; ++it) - { - // check if target is in range using the pythagorean theorem - int distx = this->getPosition().x - mTarget->getPosition().x; - int disty = this->getPosition().y - mTarget->getPosition().y; - int distSquare = (distx * distx + disty * disty); - AttackInfo *info = (*it)->getAttackInfo(); - int maxDist = info->getDamage().range + getSize(); - - if (distSquare <= maxDist * maxDist && - (!highestPriorityAttack || - info->getPriority() - < info->getPriority())) - { - highestPriorityAttack = *it; - } - } - if (highestPriorityAttack) + if (attacksReady.empty()) + return; + + Attack *highestPriorityAttack = 0; + // Performs all ready attacks. + for (std::vector<Attack *>::const_iterator it = attacksReady.begin(), + it_end = attacksReady.end(); it != it_end; ++it) + { + // check if target is in range using the pythagorean theorem + int distx = this->getPosition().x - mTarget->getPosition().x; + int disty = this->getPosition().y - mTarget->getPosition().y; + int distSquare = (distx * distx + disty * disty); + AttackInfo *info = (*it)->getAttackInfo(); + int maxDist = info->getDamage().range + getSize(); + + if (distSquare <= maxDist * maxDist && + (!highestPriorityAttack || + highestPriorityAttack->getAttackInfo()->getPriority() + < info->getPriority())) { - mAttacks.startAttack(highestPriorityAttack); - mCurrentAttack = highestPriorityAttack; - setDestination(getPosition()); - // TODO: Turn into direction of enemy - raiseUpdateFlags(UPDATEFLAG_ATTACK); + highestPriorityAttack = *it; } } + if (highestPriorityAttack) + { + mAttacks.startAttack(highestPriorityAttack); + mCurrentAttack = highestPriorityAttack; + setDestination(getPosition()); + // TODO: Turn into direction of enemy + raiseUpdateFlags(UPDATEFLAG_ATTACK); + } } void Being::addAttack(AttackInfo *attackInfo) @@ -497,22 +507,27 @@ void Being::setAction(BeingAction action) } } -void Being::applyModifier(unsigned int attr, double value, unsigned int layer, - unsigned int duration, unsigned int id) +void Being::applyModifier(unsigned attr, double value, unsigned layer, + unsigned duration, unsigned id) { mAttributes.at(attr).add(duration, value, layer, id); updateDerivedAttributes(attr); } -bool Being::removeModifier(unsigned int attr, double value, unsigned int layer, - unsigned int id, bool fullcheck) +bool Being::removeModifier(unsigned attr, double value, unsigned layer, + unsigned id, bool fullcheck) { bool ret = mAttributes.at(attr).remove(value, layer, id, fullcheck); updateDerivedAttributes(attr); return ret; } -void Being::setAttribute(unsigned int id, double value) +void Being::setGender(BeingGender gender) +{ + mGender = gender; +} + +void Being::setAttribute(unsigned id, double value) { AttributeMap::iterator ret = mAttributes.find(id); if (ret == mAttributes.end()) @@ -532,7 +547,7 @@ void Being::setAttribute(unsigned int id, double value) } } -double Being::getAttribute(unsigned int id) const +double Being::getAttribute(unsigned id) const { AttributeMap::const_iterator ret = mAttributes.find(id); if (ret == mAttributes.end()) @@ -545,7 +560,7 @@ double Being::getAttribute(unsigned int id) const } -double Being::getModifiedAttribute(unsigned int id) const +double Being::getModifiedAttribute(unsigned id) const { AttributeMap::const_iterator ret = mAttributes.find(id); if (ret == mAttributes.end()) @@ -557,82 +572,71 @@ double Being::getModifiedAttribute(unsigned int id) const return ret->second.getModifiedAttribute(); } -void Being::setModAttribute(unsigned int, double) +void Being::setModAttribute(unsigned, double) { // No-op to satisfy shared structure. // The game-server calculates this manually. return; } -bool Being::recalculateBaseAttribute(unsigned int attr) +void Being::recalculateBaseAttribute(unsigned attr) { LOG_DEBUG("Being: Received update attribute recalculation request for " << attr << "."); if (!mAttributes.count(attr)) { LOG_DEBUG("Being::recalculateBaseAttribute: " << attr << " not found!"); - return false; + return; } - double newBase = getAttribute(attr); - switch (attr) - { - case ATTR_HP_REGEN: - { - double hpPerSec = getModifiedAttribute(ATTR_VIT) * 0.05; - newBase = (hpPerSec * TICKS_PER_HP_REGENERATION / 10); - } - break; - case ATTR_HP: - double diff; - if ((diff = getModifiedAttribute(ATTR_HP) - - getModifiedAttribute(ATTR_MAX_HP)) > 0) - newBase -= diff; - break; - case ATTR_MAX_HP: - newBase = ((getModifiedAttribute(ATTR_VIT) + 3) - * (getModifiedAttribute(ATTR_VIT) + 20)) * 0.125; - break; - case ATTR_MOVE_SPEED_TPS: - newBase = 3.0 + getModifiedAttribute(ATTR_AGI) * 0.08; // Provisional. - break; - case ATTR_MOVE_SPEED_RAW: - newBase = utils::tpsToRawSpeed( - getModifiedAttribute(ATTR_MOVE_SPEED_TPS)); - break; - case ATTR_INV_CAPACITY: - // Provisional - newBase = 2000.0 + getModifiedAttribute(ATTR_STR) * 180.0; - break; - } - if (newBase != getAttribute(attr)) + // Handle speed conversion inside the engine + if (attr == ATTR_MOVE_SPEED_RAW) { - setAttribute(attr, newBase); - return true; + double newBase = utils::tpsToRawSpeed( + getModifiedAttribute(ATTR_MOVE_SPEED_TPS)); + if (newBase != getAttribute(attr)) + setAttribute(attr, newBase); + return; } - LOG_DEBUG("Being: No changes to sync for attribute '" << attr << "'."); - return false; + + if (!mRecalculateBaseAttributeCallback.isValid()) + return; + + Script *script = ScriptManager::currentState(); + script->setMap(getMap()); + script->prepare(mRecalculateBaseAttributeCallback); + script->push(this); + script->push(attr); + script->execute(); } -void Being::updateDerivedAttributes(unsigned int attr) +void Being::updateDerivedAttributes(unsigned attr) { LOG_DEBUG("Being: Updating derived attribute(s) of: " << attr); + + // Handle default actions before handing over to the script engine switch (attr) { case ATTR_MAX_HP: - updateDerivedAttributes(ATTR_HP); case ATTR_HP: raiseUpdateFlags(UPDATEFLAG_HEALTHCHANGE); break; case ATTR_MOVE_SPEED_TPS: - if (getAttribute(attr) > 0.0f) - setAttribute(ATTR_MOVE_SPEED_RAW, utils::tpsToRawSpeed( - getModifiedAttribute(ATTR_MOVE_SPEED_TPS))); - break; - default: - // Do nothing + // Does not make a lot of sense to have in the scripts. + // So handle it here: + recalculateBaseAttribute(ATTR_MOVE_SPEED_RAW); break; } + + if (!mRecalculateDerivedAttributesCallback.isValid()) + return; + + Script *script = ScriptManager::currentState(); + script->setMap(getMap()); + script->prepare(mRecalculateDerivedAttributesCallback); + script->push(this); + script->push(attr); + script->execute(); } void Being::applyStatusEffect(int id, int timer) @@ -743,20 +747,13 @@ void Being::update() processAttacks(); } -void Being::inserted() +void Being::inserted(Entity *) { - Actor::inserted(); - // Reset the old position, since after insertion it is important that it is // in sync with the zone that we're currently present in. mOld = getPosition(); } -void Being::setGender(BeingGender gender) -{ - mGender = gender; -} - void Being::processAttack(Attack &attack) { performAttack(mTarget, attack.getAttackInfo()->getDamage()); diff --git a/src/game-server/being.h b/src/game-server/being.h index eee81470..1d1f4204 100644 --- a/src/game-server/being.h +++ b/src/game-server/being.h @@ -36,7 +36,7 @@ class Being; class MapComposite; class StatusEffect; -typedef std::map< unsigned int, Attribute > AttributeMap; +typedef std::map< unsigned, Attribute > AttributeMap; struct Status { @@ -49,7 +49,7 @@ typedef std::map< int, Status > StatusEffects; /** * Type definition for a list of hits */ -typedef std::vector<unsigned int> Hits; +typedef std::vector<unsigned> Hits; /** * Generic being (living actor). Keeps direction, destination and a few other @@ -192,31 +192,31 @@ class Being : public Actor /** * Sets an attribute. */ - void setAttribute(unsigned int id, double value); + void setAttribute(unsigned id, double value); /** * Gets an attribute. */ - double getAttribute(unsigned int id) const; + double getAttribute(unsigned id) const; /** * Gets an attribute after applying modifiers. */ - double getModifiedAttribute(unsigned int id) const; + double getModifiedAttribute(unsigned id) const; /** * No-op to satisfy shared structure. * @note The game server calculates this manually, so nothing happens * here. */ - void setModAttribute(unsigned int, double); + void setModAttribute(unsigned, double); /** * Checks whether or not an attribute exists in this being. * @returns True if the attribute is present in the being, false otherwise. */ - bool checkAttributeExists(unsigned int id) const + bool checkAttributeExists(unsigned id) const { return mAttributes.count(id); } /** @@ -226,11 +226,11 @@ class Being : public Actor * @param lvl If non-zero, indicates that a temporary modifier can be * dispelled prematuraly by a spell of given level. */ - void applyModifier(unsigned int attr, double value, unsigned int layer, - unsigned int duration = 0, unsigned int id = 0); + void applyModifier(unsigned attr, double value, unsigned layer, + unsigned duration = 0, unsigned id = 0); - bool removeModifier(unsigned int attr, double value, unsigned int layer, - unsigned int id = 0, bool fullcheck = false); + bool removeModifier(unsigned attr, double value, unsigned layer, + unsigned id = 0, bool fullcheck = false); /** * Called when an attribute modifier is changed. @@ -238,14 +238,14 @@ class Being : public Actor * attributes if it has changed. * @returns Whether it was changed. */ - virtual bool recalculateBaseAttribute(unsigned int); + virtual void recalculateBaseAttribute(unsigned); /** * Attribute has changed, recalculate base value of dependant * attributes (and handle other actions for the modified * attribute) */ - virtual void updateDerivedAttributes(unsigned int); + virtual void updateDerivedAttributes(unsigned); /** * Sets a statuseffect on this being @@ -297,10 +297,24 @@ class Being : public Actor void setTarget(Being *target) { mTarget = target; } + static void setUpdateDerivedAttributesCallback(Script *script) + { script->assignCallback(mRecalculateDerivedAttributesCallback); } + + static void setRecalculateBaseAttributeCallback(Script *script) + { script->assignCallback(mRecalculateBaseAttributeCallback); } + + sigc::signal<void, Being *> signal_died; + + /** + * Activate an emote flag on the being. + */ + void triggerEmote(int id); + /** - * Overridden in order to reset the old position upon insertion. + * Tells the last emote used. */ - virtual void inserted(); + int getLastEmote() const + { return mEmoteId; } protected: /** @@ -332,6 +346,11 @@ class Being : public Actor Being(const Being &rhs); Being &operator=(const Being &rhs); + /** + * Connected to signal_inserted to reset the old position. + */ + void inserted(Entity *); + Path mPath; BeingDirection mDirection; /**< Facing direction. */ @@ -340,6 +359,15 @@ class Being : public Actor /** Time until hp is regenerated again */ Timeout mHealthRegenerationTimeout; + + /** The last being emote Id. Used when triggering a being emoticon. */ + int mEmoteId; + + /** Called when derived attributes need to get calculated */ + static Script::Ref mRecalculateDerivedAttributesCallback; + + /** Called when a base attribute needs to get calculated */ + static Script::Ref mRecalculateBaseAttributeCallback; }; #endif // BEING_H diff --git a/src/game-server/buysell.cpp b/src/game-server/buysell.cpp index 78c2bfe0..1a0d8d91 100644 --- a/src/game-server/buysell.cpp +++ b/src/game-server/buysell.cpp @@ -76,7 +76,7 @@ int BuySell::registerPlayerItems() for (InventoryData::const_iterator it = inventoryData.begin(), it_end = inventoryData.end(); it != it_end; ++it) { - unsigned int nb = it->second.amount; + unsigned nb = it->second.amount; if (!nb) continue; diff --git a/src/game-server/buysell.h b/src/game-server/buysell.h index 506dc8ad..38566005 100644 --- a/src/game-server/buysell.h +++ b/src/game-server/buysell.h @@ -76,7 +76,7 @@ class BuySell typedef std::vector< TradedItem > TradedItems; /** The attribute ID of the currency to use. Hardcoded for now (FIXME) */ - unsigned int mCurrencyId; + unsigned mCurrencyId; Character *mChar; /**< Character involved. */ TradedItems mItems; /**< Traded items. */ diff --git a/src/game-server/character.cpp b/src/game-server/character.cpp index 90a261fc..61fb35d1 100644 --- a/src/game-server/character.cpp +++ b/src/game-server/character.cpp @@ -24,7 +24,6 @@ #include "game-server/accountconnection.h" #include "game-server/attributemanager.h" #include "game-server/buysell.h" -#include "game-server/eventlistener.h" #include "game-server/inventory.h" #include "game-server/item.h" #include "game-server/itemmanager.h" @@ -465,98 +464,35 @@ void Character::modifiedAllAttribute() } } -bool Character::recalculateBaseAttribute(unsigned int attr) +void Character::recalculateBaseAttribute(unsigned attr) { - /* - * `attr' may or may not have changed. Recalculate the base value. - */ + // `attr' may or may not have changed. Recalculate the base value. LOG_DEBUG("Received update attribute recalculation request at Character " "for " << attr << "."); if (!mAttributes.count(attr)) - return false; - double newBase = getAttribute(attr); - - /* - * Calculate new base. - */ - switch (attr) - { - case ATTR_ACCURACY: - newBase = getModifiedAttribute(ATTR_DEX); // Provisional - break; - case ATTR_DEFENSE: - newBase = 0.3 * getModifiedAttribute(ATTR_VIT); - break; - case ATTR_DODGE: - newBase = getModifiedAttribute(ATTR_AGI); // Provisional - break; - case ATTR_MAGIC_DODGE: - newBase = 1.0; - // TODO - break; - case ATTR_MAGIC_DEFENSE: - newBase = 0.0; - // TODO - break; - case ATTR_BONUS_ASPD: - newBase = 0.0; - // TODO - break; - case ATTR_STR: - if (mKnuckleAttackInfo) - { - Damage &knuckleDamage = mKnuckleAttackInfo->getDamage(); - knuckleDamage.base = getModifiedAttribute(ATTR_STR); - knuckleDamage.delta = knuckleDamage.base / 2; - } - break; - default: - return Being::recalculateBaseAttribute(attr); - } + return; - if (newBase != getAttribute(attr)) + if (attr == ATTR_STR && mKnuckleAttackInfo) { - setAttribute(attr, newBase); - updateDerivedAttributes(attr); - return true; + // TODO: dehardcode this + Damage &knuckleDamage = mKnuckleAttackInfo->getDamage(); + knuckleDamage.base = getModifiedAttribute(ATTR_STR); + knuckleDamage.delta = knuckleDamage.base / 2; } - LOG_DEBUG("No changes to sync for attribute '" << attr << "'."); - return false; + Being::recalculateBaseAttribute(attr); + } -void Character::updateDerivedAttributes(unsigned int attr) + +void Character::updateDerivedAttributes(unsigned attr) { /* * `attr' has changed, perform updates accordingly. */ flagAttribute(attr); - switch(attr) - { - case ATTR_STR: - recalculateBaseAttribute(ATTR_INV_CAPACITY); - break; - case ATTR_AGI: - recalculateBaseAttribute(ATTR_DODGE); - recalculateBaseAttribute(ATTR_MOVE_SPEED_TPS); - break; - case ATTR_VIT: - recalculateBaseAttribute(ATTR_MAX_HP); - recalculateBaseAttribute(ATTR_HP_REGEN); - recalculateBaseAttribute(ATTR_DEFENSE); - break; - case ATTR_INT: - // TODO - break; - case ATTR_DEX: - recalculateBaseAttribute(ATTR_ACCURACY); - break; - case ATTR_WIL: - // TODO - break; - default: - Being::updateDerivedAttributes(attr); - } + + Being::updateDerivedAttributes(attr); } void Character::flagAttribute(int attr) @@ -776,15 +712,12 @@ void Character::addAttack(AttackInfo *attackInfo) void Character::removeAttack(AttackInfo *attackInfo) { + Being::removeAttack(attackInfo); // Add knuckle attack - if (mAttacks.getNumber() == 1) - { + if (mAttacks.getNumber() == 0) Being::addAttack(mKnuckleAttackInfo); - } - Being::removeAttack(attackInfo); } - void Character::disconnected() { mConnected = false; @@ -795,14 +728,7 @@ void Character::disconnected() else GameState::remove(this); - for (Listeners::iterator i = mListeners.begin(), - i_end = mListeners.end(); i != i_end;) - { - const EventListener &l = **i; - ++i; // In case the listener removes itself from the list on the fly. - if (l.dispatch->disconnected) - l.dispatch->disconnected(&l, this); - } + signal_disconnected.emit(this); } bool Character::takeSpecial(int id) diff --git a/src/game-server/character.h b/src/game-server/character.h index 4dc077e8..830504c7 100644 --- a/src/game-server/character.h +++ b/src/game-server/character.h @@ -45,22 +45,22 @@ class Trade; struct SpecialValue { - SpecialValue(unsigned int currentMana, + SpecialValue(unsigned currentMana, const SpecialManager::SpecialInfo *specialInfo) : currentMana(currentMana) , rechargeSpeed(specialInfo->defaultRechargeSpeed) , specialInfo(specialInfo) {} - unsigned int currentMana; - unsigned int rechargeSpeed; + unsigned currentMana; + unsigned rechargeSpeed; const SpecialManager::SpecialInfo *specialInfo; }; /** * Stores specials by their id. */ -typedef std::map<unsigned int, SpecialValue> SpecialMap; +typedef std::map<unsigned, SpecialValue> SpecialMap; /** * The representation of a player's character in the game world. @@ -251,18 +251,18 @@ class Character : public Being void modifiedAllAttribute(); /** - * Recalculate the base value of an attribute and update derived - * attributes if it has changed. - * @returns Whether it was changed. - */ - bool recalculateBaseAttribute(unsigned int); + * Recalculate the base value of an attribute and update derived + * attributes if it has changed. + */ + void recalculateBaseAttribute(unsigned); + /** * Attribute has changed, recalculate base value of dependant * attributes (and handle other actions for the modified * attribute) */ - void updateDerivedAttributes(unsigned int); + void updateDerivedAttributes(unsigned); /** * Calls all the "disconnected" listener. @@ -428,6 +428,8 @@ class Character : public Being virtual void removeAttack(AttackInfo *attackInfo); + sigc::signal<void, Character *> signal_disconnected; + protected: /** * Gets the way the actor blocks pathfinding for other objects diff --git a/src/game-server/command.cpp b/src/game-server/command.cpp index 5e87f9f6..e80b9f98 100644 --- a/src/game-server/command.cpp +++ b/src/game-server/command.cpp @@ -256,7 +256,7 @@ static void ban(Character *from, Character *ch, const std::string &duration) switch (duration[duration.length() - 1]) { case 'd': d = d * 24; // nobreak - case 'h': d = d * 60; + case 'h': d = d * 60; break; } accountHandler->banCharacter(ch, d); } diff --git a/src/game-server/commandhandler.cpp b/src/game-server/commandhandler.cpp index b48f1188..6de22242 100644 --- a/src/game-server/commandhandler.cpp +++ b/src/game-server/commandhandler.cpp @@ -177,7 +177,7 @@ static void say(const std::string message, Character *player) } /* -static bool checkPermission(Character *player, unsigned int permissions) +static bool checkPermission(Character *player, unsigned permissions) { if (player->getAccountLevel() & permissions) { @@ -196,7 +196,7 @@ static bool checkPermission(Character *player, unsigned int permissions) static std::string playerRights(Character *ch) { std::stringstream str; - str << (unsigned int)ch->getAccountLevel(); + str << (unsigned)ch->getAccountLevel(); str << " ( "; std::list<std::string> classes = PermissionManager::getClassList(ch); diff --git a/src/game-server/emotemanager.cpp b/src/game-server/emotemanager.cpp new file mode 100644 index 00000000..35f0aa47 --- /dev/null +++ b/src/game-server/emotemanager.cpp @@ -0,0 +1,70 @@ +/* + * The Mana Server + * Copyright (C) 2012 The Mana Developers + * + * This file is part of The Mana Server. + * + * The Mana Server 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 Server 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 Server. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "emotemanager.h" + +#include "utils/xml.h" +#include "utils/logger.h" + +void EmoteManager::initialize() +{ + clear(); + + XML::Document doc(mEmoteFile); + xmlNodePtr rootNode = doc.rootNode(); + + if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "emotes")) + { + LOG_ERROR("Emote Manager: " << mEmoteFile + << " is not a valid emote file!"); + return; + } + + LOG_INFO("Loading emote reference: " << mEmoteFile); + + for_each_xml_child_node(emoteNode, rootNode) + { + if (!xmlStrEqual(emoteNode->name, BAD_CAST "emote")) + continue; + + int id = XML::getProperty(emoteNode, "id", -1); + if (id < 0) + { + LOG_WARN("The " << mEmoteFile << " file is containing an invalid id" + "(" << id << ") and will be ignored."); + continue; + } + + mEmoteIds.push_back(id); + } + LOG_INFO(mEmoteIds.size() << " emotes available."); +} + +bool EmoteManager::isIdAvailable(int id) const +{ + std::vector<int>::const_iterator it = mEmoteIds.begin(); + std::vector<int>::const_iterator it_end = mEmoteIds.end(); + for (; it != it_end; ++it) + { + if ((*it) == id) + return true; + } + return false; +} diff --git a/src/game-server/emotemanager.h b/src/game-server/emotemanager.h new file mode 100644 index 00000000..42c71680 --- /dev/null +++ b/src/game-server/emotemanager.h @@ -0,0 +1,64 @@ +/* + * The Mana Server + * Copyright (C) 2011-2012 The Mana Developers + * + * This file is part of The Mana Server. + * + * The Mana Server 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 Server 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 Server. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef EMOTEMANAGER_H +#define EMOTEMANAGER_H + +#include "utils/string.h" +#include "utils/xml.h" + +#include <vector> + +class EmoteManager +{ +public: + + EmoteManager(const std::string &emoteFile): + mEmoteFile(emoteFile) + { } + + ~EmoteManager() + { clear(); } + + /** + * Loads emote reference file. + */ + void initialize(); + + /** + * Tells whether the given id is a valid emote one. + */ + bool isIdAvailable(int id) const; + +private: + /** + * Clears up the emote list. + */ + void clear() + { mEmoteIds.clear(); } + + std::string mEmoteFile; + std::vector<int> mEmoteIds; +}; + +extern EmoteManager *emoteManager; + +#endif // EMOTEMANAGER_H diff --git a/src/game-server/entity.cpp b/src/game-server/entity.cpp index 671ef5e6..6cb61e58 100644 --- a/src/game-server/entity.cpp +++ b/src/game-server/entity.cpp @@ -18,51 +18,4 @@ * along with The Mana Server. If not, see <http://www.gnu.org/licenses/>. */ -#include <cassert> - #include "game-server/entity.h" - -#include "game-server/eventlistener.h" - -Entity::~Entity() -{ - /* As another object will stop listening and call removeListener when it is - deleted, the following assertion ensures that all the calls to - removeListener have been performed will this object was still alive. It - is not strictly necessary, as there are cases where no removal is - performed (e.g. ~SpawnArea). But this is rather exceptional, so keep the - assertion to catch all the other forgotten calls to removeListener. */ - assert(mListeners.empty()); -} - -void Entity::addListener(const EventListener *l) -{ - mListeners.insert(l); -} - -void Entity::removeListener(const EventListener *l) -{ - mListeners.erase(l); -} - -void Entity::inserted() -{ - for (Listeners::iterator i = mListeners.begin(), - i_end = mListeners.end(); i != i_end;) - { - const EventListener &l = **i; - ++i; // In case the listener removes itself from the list on the fly. - if (l.dispatch->inserted) l.dispatch->inserted(&l, this); - } -} - -void Entity::removed() -{ - for (Listeners::iterator i = mListeners.begin(), - i_end = mListeners.end(); i != i_end;) - { - const EventListener &l = **i; - ++i; // In case the listener removes itself from the list on the fly. - if (l.dispatch->removed) l.dispatch->removed(&l, this); - } -} diff --git a/src/game-server/entity.h b/src/game-server/entity.h index 652db7c7..91f13699 100644 --- a/src/game-server/entity.h +++ b/src/game-server/entity.h @@ -23,18 +23,20 @@ #include "common/manaserv_protocol.h" -using namespace ManaServ; - #include <set> -class EventListener; +#include <sigc++/signal.h> +#include <sigc++/trackable.h> + +using namespace ManaServ; + class MapComposite; /** * Base class for in-game objects. Knows only its type and the map it resides * on. Provides listeners. */ -class Entity +class Entity : public sigc::trackable { public: Entity(EntityType type, MapComposite *map = 0) @@ -42,7 +44,7 @@ class Entity mType(type) {} - virtual ~Entity(); + virtual ~Entity() {} /** * Gets type of this entity. @@ -88,29 +90,8 @@ class Entity virtual void setMap(MapComposite *map) { mMap = map; } - /** - * Adds a new listener. - */ - void addListener(const EventListener *); - - /** - * Removes an existing listener. - */ - void removeListener(const EventListener *); - - /** - * Calls all the "inserted" listeners. - */ - virtual void inserted(); - - /** - * Calls all the "removed" listeners. - */ - virtual void removed(); - - protected: - typedef std::set< const EventListener * > Listeners; - Listeners mListeners; /**< List of event listeners. */ + sigc::signal<void, Entity *> signal_inserted; + sigc::signal<void, Entity *> signal_removed; private: MapComposite *mMap; /**< Map the entity is on */ diff --git a/src/game-server/eventlistener.h b/src/game-server/eventlistener.h deleted file mode 100644 index 53d92077..00000000 --- a/src/game-server/eventlistener.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * The Mana Server - * Copyright (C) 2007-2010 The Mana World Development Team - * - * This file is part of The Mana Server. - * - * The Mana Server 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 Server 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 Server. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef GAMESERVER_EVENTLISTENER_H -#define GAMESERVER_EVENTLISTENER_H - -class Entity; -class Being; -class Character; - -struct EventDispatch; - -/** - * Pointer to a dispatch table. - */ -struct EventListener -{ - const EventDispatch *dispatch; - EventListener(const EventDispatch *d): dispatch(d) {} -}; - -/** - * Dispatch table for event notification. - */ -struct EventDispatch -{ - /** - * Called just after something is inserted in a map. - */ - void (*inserted)(const EventListener *, Entity *); - - /** - * Called just before something is removed from a map. - */ - void (*removed)(const EventListener *, Entity *); - - /** - * Called just after a being has died. - */ - void (*died)(const EventListener *, Being *); - - /** - * Called just before a character is deleted. - */ - void (*disconnected)(const EventListener *, Character *); - - /** - * Initializes dispatch methods as missing. - */ - EventDispatch(): - inserted(0), removed(0), died(0), disconnected(0) - {} -}; - -/** - * Helper for using member functions as dispatch methods. The 3-level structure - * is due to default template parameter not being allowed on functions yet. - * Conceptually, this helper takes two parameters: the name of the member - * variable pointing to the dispatch table and the name of the member function - * to call on dispatch. With these two parameters, it creates a dispatch - * method. When called, this free function forwards the call to the member - * function. - * Pseudo-syntax for getting a dispatch method: - * <code>&EventListenerFactory< _, DispatchPointerName >::create< _, MemberFunctionName >::function</code> - * See the start of the spawnarea.cpp file for a complete example. - */ -template< class T, EventListener T::*D > -struct EventListenerFactory -{ - template< class U, void (T::*F)(U *), class V = U > - struct create - { - static void function(const EventListener *d, V *u) - { - /* Get the address of the T object by substracting the offset of D - from the pointer d. */ - T *t = (T *)((char *)d - - ((char *)&(((T *)42)->*D) - (char *)&(*(T *)42))); - // Then call the method F of this T object. - (t->*F)(u); - } - }; -}; - -#endif diff --git a/src/game-server/gamehandler.cpp b/src/game-server/gamehandler.cpp index 8dde8d9a..3b356a5c 100644 --- a/src/game-server/gamehandler.cpp +++ b/src/game-server/gamehandler.cpp @@ -28,6 +28,7 @@ #include "game-server/accountconnection.h" #include "game-server/buysell.h" #include "game-server/commandhandler.h" +#include "game-server/emotemanager.h" #include "game-server/inventory.h" #include "game-server/item.h" #include "game-server/itemmanager.h" @@ -43,7 +44,7 @@ #include "utils/logger.h" #include "utils/tokendispenser.h" -const unsigned int TILES_TO_BE_NEAR = 7; +const unsigned TILES_TO_BE_NEAR = 7; GameHandler::GameHandler(): mTokenCollector(this) @@ -302,6 +303,10 @@ void GameHandler::processMessage(NetComputer *computer, MessageIn &message) handlePartyInvite(client, message); break; + case PGMSG_BEING_EMOTE: + handleTriggerEmoticon(client, message); + break; + default: LOG_WARN("Invalid message type"); client.send(MessageOut(XXMSG_INVALID)); @@ -464,6 +469,7 @@ void GameHandler::handleNpc(GameClient &client, MessageIn &message) case PGMSG_NPC_TALK_NEXT: default: npc->prompt(client.character, message.getId() == PGMSG_NPC_TALK); + break; } } @@ -918,6 +924,13 @@ void GameHandler::handlePartyInvite(GameClient &client, MessageIn &message) client.send(out); } +void GameHandler::handleTriggerEmoticon(GameClient &client, MessageIn &message) +{ + const int id = message.readInt16(); + if (emoteManager->isIdAvailable(id)) + client.character->triggerEmote(id); +} + void GameHandler::sendNpcError(GameClient &client, int id, const std::string &errorMsg) { diff --git a/src/game-server/gamehandler.h b/src/game-server/gamehandler.h index c0d843e9..c05e0087 100644 --- a/src/game-server/gamehandler.h +++ b/src/game-server/gamehandler.h @@ -152,6 +152,8 @@ class GameHandler: public ConnectionHandler void handlePartyInvite(GameClient &client, MessageIn &message); + void handleTriggerEmoticon(GameClient &client, MessageIn &message); + void sendNpcError(GameClient &client, int id, const std::string &errorMsg); diff --git a/src/game-server/inventory.cpp b/src/game-server/inventory.cpp index 4f5e1811..d523c7b8 100644 --- a/src/game-server/inventory.cpp +++ b/src/game-server/inventory.cpp @@ -68,7 +68,7 @@ void Inventory::initialize() /* * Construct a set of item Ids to keep track of duplicate item Ids. */ - std::set<unsigned int> itemIds; + std::set<unsigned> itemIds; /* * Construct a set of itemIds to keep track of duplicate itemIds. @@ -136,19 +136,25 @@ void Inventory::initialize() } } -unsigned int Inventory::getItem(unsigned int slot) const +unsigned Inventory::getItem(unsigned slot) const { InventoryData::iterator item = mPoss->inventory.find(slot); return item != mPoss->inventory.end() ? item->second.itemId : 0; } -unsigned int Inventory::insert(unsigned int itemId, unsigned int amount) +unsigned Inventory::insert(unsigned itemId, unsigned amount) { if (!itemId || !amount) return 0; MessageOut invMsg(GPMSG_INVENTORY); - unsigned int maxPerSlot = itemManager->getItem(itemId)->getMaxPerSlot(); + ItemClass *item = itemManager->getItem(itemId); + if (!item) { + LOG_ERROR("Inventory: Trying to insert invalid item id " << itemId + << " (amount: " << amount << ")"); + return amount; + } + unsigned maxPerSlot = item->getMaxPerSlot(); LOG_DEBUG("Inventory: Inserting " << amount << " item(s) Id: " << itemId << " for character '" << mCharacter->getName() << "'."); @@ -210,7 +216,6 @@ unsigned int Inventory::insert(unsigned int itemId, unsigned int amount) break; } - ItemClass *item = itemManager->getItem(itemId); if (item) { // EVIL HACK!! This allows to prevent sending the item to client. @@ -227,10 +232,10 @@ unsigned int Inventory::insert(unsigned int itemId, unsigned int amount) return amount; } -unsigned int Inventory::count(unsigned int itemId, +unsigned Inventory::count(unsigned itemId, bool inInventory, bool inEquipment) const { - unsigned int nb = 0; + unsigned nb = 0; if (inInventory) { for (InventoryData::iterator it = mPoss->inventory.begin(), @@ -258,7 +263,7 @@ unsigned int Inventory::count(unsigned int itemId, return nb; } -int Inventory::getFirstSlot(unsigned int itemId) +int Inventory::getFirstSlot(unsigned itemId) { for (InventoryData::iterator it = mPoss->inventory.begin(), it_end = mPoss->inventory.end(); it != it_end; ++it) @@ -267,7 +272,7 @@ int Inventory::getFirstSlot(unsigned int itemId) return -1; } -unsigned int Inventory::remove(unsigned int itemId, unsigned int amount) +unsigned Inventory::remove(unsigned itemId, unsigned amount) { if (!itemId || !amount) return amount; @@ -286,7 +291,7 @@ unsigned int Inventory::remove(unsigned int itemId, unsigned int amount) { if (amount) { - unsigned int sub = std::min(amount, it->second.amount); + unsigned sub = std::min(amount, it->second.amount); amount -= sub; it->second.amount -= sub; invMsg.writeInt16(it->first); @@ -329,8 +334,8 @@ unsigned int Inventory::remove(unsigned int itemId, unsigned int amount) return amount; } -unsigned int Inventory::move(unsigned int slot1, unsigned int slot2, - unsigned int amount) +unsigned Inventory::move(unsigned slot1, unsigned slot2, + unsigned amount) { LOG_DEBUG(amount << " item(s) requested to move from: " << slot1 << " to " << slot2 << " for character: '" << mCharacter->getName() << "'."); @@ -347,7 +352,7 @@ unsigned int Inventory::move(unsigned int slot1, unsigned int slot2, MessageOut invMsg(GPMSG_INVENTORY); - unsigned int nb = std::min(amount, it1->second.amount); + unsigned nb = std::min(amount, it1->second.amount); if (it2 == inv_end) { // Slot2 does not yet exist. @@ -360,7 +365,7 @@ unsigned int Inventory::move(unsigned int slot1, unsigned int slot2, amount -= nb; //Save the itemId in case of deletion of the iterator - unsigned int itemId = it1->second.itemId; + unsigned itemId = it1->second.itemId; invMsg.writeInt16(slot1); // Slot if (it1->second.amount) { @@ -390,8 +395,8 @@ unsigned int Inventory::move(unsigned int slot1, unsigned int slot2, // and when all the amount of slot 1 is moving onto slot 2. if (amount >= it1->second.amount) { - unsigned int itemId = it1->second.itemId; - unsigned int amount = it1->second.amount; + unsigned itemId = it1->second.itemId; + unsigned amount = it1->second.amount; it1->second.itemId = it2->second.itemId; it1->second.amount = it2->second.amount; it2->second.itemId = itemId; @@ -453,7 +458,7 @@ unsigned int Inventory::move(unsigned int slot1, unsigned int slot2, return amount; } -unsigned int Inventory::removeFromSlot(unsigned int slot, unsigned int amount) +unsigned Inventory::removeFromSlot(unsigned slot, unsigned amount) { InventoryData::iterator it = mPoss->inventory.find(slot); @@ -484,7 +489,7 @@ unsigned int Inventory::removeFromSlot(unsigned int slot, unsigned int amount) if (!exists && it->second.itemId) lastSlotOfItemRemaining = true; - unsigned int sub = std::min(amount, it->second.amount); + unsigned sub = std::min(amount, it->second.amount); amount -= sub; it->second.amount -= sub; invMsg.writeInt16(it->first); @@ -513,7 +518,7 @@ unsigned int Inventory::removeFromSlot(unsigned int slot, unsigned int amount) } -void Inventory::updateEquipmentTrigger(unsigned int oldId, unsigned int newId) +void Inventory::updateEquipmentTrigger(unsigned oldId, unsigned newId) { if (!oldId && !newId) return; @@ -535,7 +540,7 @@ void Inventory::updateEquipmentTrigger(ItemClass *oldI, ItemClass *newI) newI->useTrigger(mCharacter, ITT_EQUIP); } -unsigned int Inventory::getNewEquipItemInstance() +unsigned Inventory::getNewEquipItemInstance() { std::set<int> alreadyUsed; for (EquipData::const_iterator it = mPoss->equipSlots.begin(); @@ -544,15 +549,15 @@ unsigned int Inventory::getNewEquipItemInstance() alreadyUsed.insert(it->second.itemInstance); } - unsigned int itemInstance = 1; + unsigned itemInstance = 1; while (alreadyUsed.count(itemInstance)) itemInstance++; return itemInstance; } -bool Inventory::checkEquipmentCapacity(unsigned int equipmentSlot, - unsigned int capacityRequested) +bool Inventory::checkEquipmentCapacity(unsigned equipmentSlot, + unsigned capacityRequested) { int capacity = itemManager->getEquipSlotCapacity(equipmentSlot); @@ -606,7 +611,7 @@ bool Inventory::equip(int inventorySlot) } // List of potential unique itemInstances to unequip first. - std::set<unsigned int> equipInstancesToUnequipFirst; + std::set<unsigned> equipInstancesToUnequipFirst; // We first check the equipment slots for: // - 1. whether enough total equip slot space is available. @@ -653,7 +658,7 @@ bool Inventory::equip(int inventorySlot) } // Potential Pre-unequipment process - for (std::set<unsigned int>::const_iterator it3 = + for (std::set<unsigned>::const_iterator it3 = equipInstancesToUnequipFirst.begin(); it3 != equipInstancesToUnequipFirst.end(); ++it3) { @@ -676,8 +681,8 @@ bool Inventory::equip(int inventorySlot) // Compute an unique equip item Instance id (unicity is per character only.) int itemInstance = getNewEquipItemInstance(); - unsigned int capacityLeft = equipReq.capacityRequired; - unsigned int capacityUsed = 0; + unsigned capacityLeft = equipReq.capacityRequired; + unsigned capacityUsed = 0; // Apply equipment changes for (EquipData::iterator it4 = mPoss->equipSlots.begin(), it4_end = mPoss->equipSlots.end(); it4 != it4_end; ++it4) @@ -707,7 +712,7 @@ bool Inventory::equip(int inventorySlot) // Hence, we add them back if(capacityLeft) { - unsigned int maxCapacity = + unsigned maxCapacity = itemManager->getEquipSlotCapacity(equipReq.equipSlotId); // A should never happen case @@ -717,7 +722,7 @@ bool Inventory::equip(int inventorySlot) { EquipmentItem equipItem(it->second.itemId, itemInstance); mPoss->equipSlots.insert( - std::make_pair<unsigned int, EquipmentItem> + std::make_pair<unsigned, EquipmentItem> (equipReq.equipSlotId, equipItem)); --capacityLeft; } @@ -744,7 +749,7 @@ bool Inventory::equip(int inventorySlot) return true; } -unsigned int Inventory::getSlotItemInstance(unsigned int slot) +unsigned Inventory::getSlotItemInstance(unsigned slot) { EquipData::iterator it = mPoss->equipSlots.find(slot); if (it != mPoss->equipSlots.end()) @@ -752,7 +757,7 @@ unsigned int Inventory::getSlotItemInstance(unsigned int slot) return 0; } -bool Inventory::unequipItem(unsigned int itemId) +bool Inventory::unequipItem(unsigned itemId) { std::set<unsigned> itemInstances; for (EquipData::iterator it = mPoss->equipSlots.begin(), @@ -775,14 +780,14 @@ bool Inventory::unequipItem(unsigned int itemId) return true; } -bool Inventory::unequip(unsigned int itemInstance) +bool Inventory::unequip(unsigned itemInstance) { if (!itemInstance) return false; // The itemId to unequip - unsigned int itemId = 0; - unsigned int slotTypeId = 0; + unsigned itemId = 0; + unsigned slotTypeId = 0; bool addedToInventory = false; @@ -831,7 +836,7 @@ bool Inventory::unequip(unsigned int itemInstance) return true; } -void Inventory::checkLookchanges(unsigned int slotTypeId) +void Inventory::checkLookchanges(unsigned slotTypeId) { if (itemManager->isEquipSlotVisible(slotTypeId)) mCharacter->raiseUpdateFlags(UPDATEFLAG_LOOKSCHANGE); diff --git a/src/game-server/inventory.h b/src/game-server/inventory.h index 3dacb919..42856bff 100644 --- a/src/game-server/inventory.h +++ b/src/game-server/inventory.h @@ -70,64 +70,64 @@ class Inventory * @returns whether all item id could be unequipped. * @note returns true when no item with given ids were equipped. */ - bool unequipItem(unsigned int itemId); + bool unequipItem(unsigned itemId); /** * Unequips item from given equipment slot. * @param itemInstance The item instance id used to know what to unequip * @returns Whether it was unequipped. */ - bool unequip(unsigned int itemInstance); + bool unequip(unsigned itemInstance); /** * Gets the item instance from the given equipment slot. * Return 0 if none. */ - unsigned int getSlotItemInstance(unsigned int slot); + unsigned getSlotItemInstance(unsigned slot); /** * Inserts some items into the inventory. * @return number of items not inserted (to be dropped on floor?). */ - unsigned int insert(unsigned int itemId, unsigned int amount); + unsigned insert(unsigned itemId, unsigned amount); /** * Removes some items from inventory. * @return number of items not removed. */ - unsigned int remove(unsigned int itemId, unsigned int amount); + unsigned remove(unsigned itemId, unsigned amount); /** * Moves some items from the first slot to the second one. * @returns number of items not moved. */ - unsigned int move(unsigned int slot1, unsigned int slot2, - unsigned int amount); + unsigned move(unsigned slot1, unsigned slot2, + unsigned amount); /** * Removes some items from inventory. * @return number of items not removed. */ - unsigned int removeFromSlot(unsigned int slot, unsigned int amount); + unsigned removeFromSlot(unsigned slot, unsigned amount); /** * Counts number of items with given Id. * @param inInventory Search in player's inventory. * @param inEquipment Search in player's equipment. */ - unsigned int count(unsigned int itemId, bool inInventory = true, + unsigned count(unsigned itemId, bool inInventory = true, bool inEquipment = true) const; /** * Gets the ID of the items in a given slot. */ - unsigned int getItem(unsigned int slot) const; + unsigned getItem(unsigned slot) const; /** * Returns the first inventory slot with the given item Id. * Returns -1 otherwise. */ - int getFirstSlot(unsigned int itemId); + int getFirstSlot(unsigned itemId); private: /** @@ -135,15 +135,15 @@ class Inventory * @param equipmentSlot the slot in equipement to check. * @param capacityRequested the capacity needed. */ - bool checkEquipmentCapacity(unsigned int equipmentSlot, - unsigned int capacityRequested); + bool checkEquipmentCapacity(unsigned equipmentSlot, + unsigned capacityRequested); /** * Test whether the inventory has enough space to welcome * the willing-to-be equipment slot. * @todo */ - bool hasInventoryEnoughSpace(unsigned int /* equipmentSlot */) + bool hasInventoryEnoughSpace(unsigned /* equipmentSlot */) { return true; } /** @@ -151,14 +151,14 @@ class Inventory * This is especially useful for scripted equipment. * @todo */ - bool testUnequipScriptRequirements(unsigned int /* equipementSlot */) + bool testUnequipScriptRequirements(unsigned /* equipementSlot */) { return true; } /** * Test the items equipment for scripted requirements. * @todo */ - bool testEquipScriptRequirements(unsigned int /* itemId */) + bool testEquipScriptRequirements(unsigned /* itemId */) { return true; } /** @@ -167,7 +167,7 @@ class Inventory * This is used to differenciate some items that can be equipped * multiple times, like one-handed weapons for instance. */ - unsigned int getNewEquipItemInstance(); + unsigned getNewEquipItemInstance(); /** * Check the inventory is within the slot limit and capacity. @@ -179,12 +179,12 @@ class Inventory /** * Check potential visible character sprite changes. */ - void checkLookchanges(unsigned int slotTypeId); + void checkLookchanges(unsigned slotTypeId); /** * Apply equipment triggers. */ - void updateEquipmentTrigger(unsigned int oldId, unsigned int itemId); + void updateEquipmentTrigger(unsigned oldId, unsigned itemId); void updateEquipmentTrigger(ItemClass *oldI, ItemClass *newI); Possessions *mPoss; /**< Pointer to the modified possessions. */ diff --git a/src/game-server/item.h b/src/game-server/item.h index 7004a2d8..54112c4a 100644 --- a/src/game-server/item.h +++ b/src/game-server/item.h @@ -37,7 +37,7 @@ struct ItemEquipRequirement { capacityRequired(0) {} - unsigned int equipSlotId, capacityRequired; + unsigned equipSlotId, capacityRequired; }; /** @@ -73,7 +73,7 @@ enum ItemTriggerType ITT_NULL = 0, ITT_IN_INVY, // Associated effects apply when the item is in the inventory ITT_ACTIVATE, // Associated effects apply when the item is activated - ITT_EQUIP, // Assosciated effects apply when the item is equipped + ITT_EQUIP, // Associated effects apply when the item is equipped ITT_LEAVE_INVY, // Associated effects apply when the item leaves the inventory ITT_UNEQUIP, // Associated effects apply when the item is unequipped ITT_EQUIPCHG // When the item is still equipped, but in a different way @@ -110,8 +110,8 @@ class ItemEffectInfo class ItemEffectAttrMod : public ItemEffectInfo { public: - ItemEffectAttrMod(unsigned int attrId, unsigned int layer, double value, - unsigned int id, unsigned int duration = 0) : + ItemEffectAttrMod(unsigned attrId, unsigned layer, double value, + unsigned id, unsigned duration = 0) : mAttributeId(attrId), mAttributeLayer(layer), mMod(value), mDuration(duration), mId(id) {} @@ -120,11 +120,11 @@ class ItemEffectAttrMod : public ItemEffectInfo void dispell(Being *itemUser); private: - unsigned int mAttributeId; - unsigned int mAttributeLayer; + unsigned mAttributeId; + unsigned mAttributeLayer; double mMod; - unsigned int mDuration; - unsigned int mId; + unsigned mDuration; + unsigned mId; }; class ItemEffectAttack : public ItemEffectInfo @@ -178,7 +178,7 @@ class ItemEffectScript : public ItemEffectInfo class ItemClass { public: - ItemClass(int id, unsigned int maxperslot): + ItemClass(int id, unsigned maxperslot): mDatabaseID(id), mName("unnamed"), mSpriteID(0), @@ -215,7 +215,7 @@ class ItemClass /** * Gets max item per slot. */ - unsigned int getMaxPerSlot() const + unsigned getMaxPerSlot() const { return mMaxPerSlot; } bool hasTrigger(ItemTriggerType id) @@ -273,7 +273,7 @@ class ItemClass unsigned short mSpriteID; unsigned short mCost; /**< Unit cost the item. */ /** Max item amount per slot in inventory. */ - unsigned int mMaxPerSlot; + unsigned mMaxPerSlot; std::multimap< ItemTriggerType, ItemEffectInfo * > mEffects; std::multimap< ItemTriggerType, ItemEffectInfo * > mDispells; diff --git a/src/game-server/itemmanager.cpp b/src/game-server/itemmanager.cpp index 946815ad..4837ce98 100644 --- a/src/game-server/itemmanager.cpp +++ b/src/game-server/itemmanager.cpp @@ -54,7 +54,7 @@ void ItemManager::deinitialize() delete i->second; } - for (std::map< unsigned int, EquipSlotInfo* >::iterator it = + for (std::map< unsigned, EquipSlotInfo* >::iterator it = mEquipSlotsInfo.begin(), it_end = mEquipSlotsInfo.end(); it != it_end; ++it) { @@ -76,24 +76,24 @@ ItemClass *ItemManager::getItemByName(const std::string &name) const return mItemClassesByName.value(name); } -unsigned int ItemManager::getDatabaseVersion() const +unsigned ItemManager::getDatabaseVersion() const { return mItemDatabaseVersion; } -unsigned int ItemManager::getEquipSlotIdFromName(const std::string &name) const +unsigned ItemManager::getEquipSlotIdFromName(const std::string &name) const { EquipSlotInfo *slotInfo = mNamedEquipSlotsInfo.value(name); return slotInfo ? slotInfo->slotId : 0; } -unsigned int ItemManager::getEquipSlotCapacity(unsigned int id) const +unsigned ItemManager::getEquipSlotCapacity(unsigned id) const { EquipSlotsInfo::const_iterator i = mEquipSlotsInfo.find(id); return i != mEquipSlotsInfo.end() ? i->second->slotCapacity : 0; } -bool ItemManager::isEquipSlotVisible(unsigned int id) const +bool ItemManager::isEquipSlotVisible(unsigned id) const { EquipSlotsInfo::const_iterator i = mEquipSlotsInfo.find(id); return i != mEquipSlotsInfo.end() ? i->second->visibleSlot : false; @@ -160,7 +160,7 @@ void ItemManager::readEquipSlotsFile() EquipSlotInfo *equipSlotInfo = new EquipSlotInfo(slotId, name, capacity, visible); mEquipSlotsInfo.insert( - std::make_pair<unsigned int, EquipSlotInfo*>(slotId, equipSlotInfo)); + std::make_pair<unsigned, EquipSlotInfo*>(slotId, equipSlotInfo)); mNamedEquipSlotsInfo.insert(name, equipSlotInfo); totalCapacity += capacity; @@ -222,7 +222,7 @@ void ItemManager::readItemNode(xmlNodePtr itemNode) return; } - unsigned int maxPerSlot = XML::getProperty(itemNode, "max-per-slot", 0); + unsigned maxPerSlot = XML::getProperty(itemNode, "max-per-slot", 0); if (!maxPerSlot) { LOG_WARN("Item Manager: Missing max-per-slot property for " @@ -373,7 +373,7 @@ void ItemManager::readEffectNode(xmlNodePtr effectNode, ItemClass *item) "but no attribute specified!"); continue; } - unsigned int duration = XML::getProperty(subNode, + unsigned duration = XML::getProperty(subNode, "duration", 0); ModifierLocation location = attributeManager->getLocation(tag); diff --git a/src/game-server/itemmanager.h b/src/game-server/itemmanager.h index cc4fb0ae..6a1f459b 100644 --- a/src/game-server/itemmanager.h +++ b/src/game-server/itemmanager.h @@ -36,14 +36,14 @@ struct EquipSlotInfo slotId(0), slotCapacity(0), visibleSlot(false) {} - EquipSlotInfo(unsigned int id, const std::string &name, - unsigned int capacity, bool visible): + EquipSlotInfo(unsigned id, const std::string &name, + unsigned capacity, bool visible): slotId(id), slotName(name), slotCapacity(capacity), visibleSlot(visible) {} - unsigned int slotId; + unsigned slotId; std::string slotName; - unsigned int slotCapacity; + unsigned slotCapacity; bool visibleSlot; }; @@ -92,16 +92,16 @@ class ItemManager /** * Gets the version of the loaded item database. */ - unsigned int getDatabaseVersion() const; + unsigned getDatabaseVersion() const; - unsigned int getEquipSlotIdFromName(const std::string &name) const; + unsigned getEquipSlotIdFromName(const std::string &name) const; - unsigned int getEquipSlotCapacity(unsigned int id) const; + unsigned getEquipSlotCapacity(unsigned id) const; - unsigned int getVisibleEquipSlotCount() const + unsigned getVisibleEquipSlotCount() const { return mVisibleEquipSlotCount; } - bool isEquipSlotVisible(unsigned int id) const; + bool isEquipSlotVisible(unsigned id) const; private: /** Loads the equip slots that a character has available to them. */ @@ -118,9 +118,9 @@ class ItemManager utils::NameMap<ItemClass*> mItemClassesByName; // Map an equip slot id with the equip slot info. - typedef std::map< unsigned int, EquipSlotInfo* > EquipSlotsInfo; + typedef std::map< unsigned, EquipSlotInfo* > EquipSlotsInfo; // Reference to the vector position of equipSlots - typedef std::vector< unsigned int > VisibleEquipSlots; + typedef std::vector< unsigned > VisibleEquipSlots; EquipSlotsInfo mEquipSlotsInfo; // Map a string (name of slot) with (str-id, max-per-equip-slot) @@ -129,10 +129,10 @@ class ItemManager std::string mItemsFile; std::string mEquipSlotsFile; - unsigned int mVisibleEquipSlotCount; // Cache + unsigned mVisibleEquipSlotCount; // Cache /** Version of the loaded items database file.*/ - unsigned int mItemDatabaseVersion; + unsigned mItemDatabaseVersion; }; extern ItemManager *itemManager; diff --git a/src/game-server/main-game.cpp b/src/game-server/main-game.cpp index 406e7c5b..f76189f9 100644 --- a/src/game-server/main-game.cpp +++ b/src/game-server/main-game.cpp @@ -25,6 +25,7 @@ #include "game-server/accountconnection.h" #include "game-server/attributemanager.h" #include "game-server/gamehandler.h" +#include "game-server/emotemanager.h" #include "game-server/itemmanager.h" #include "game-server/mapmanager.h" #include "game-server/monstermanager.h" @@ -53,6 +54,7 @@ #ifdef __MINGW32__ #include <windows.h> +#include "common/winver.h" #define usleep(usec) (Sleep ((usec) / 1000), 0) #endif @@ -74,6 +76,7 @@ using utils::Logger; #define DEFAULT_PERMISSION_FILE "permissions.xml" #define DEFAULT_MAIN_SCRIPT_FILE "scripts/main.lua" #define DEFAULT_SPECIALSDB_FILE "specials.xml" +#define DEFAULT_EMOTESDB_FILE "emotes.xml" static int const WORLD_TICK_SKIP = 2; /** tolerance for lagging behind in world calculation) **/ @@ -89,6 +92,7 @@ ItemManager *itemManager = new ItemManager(DEFAULT_ITEMSDB_FILE, DEFAULT_EQUIPDB MonsterManager *monsterManager = new MonsterManager(DEFAULT_MONSTERSDB_FILE); SkillManager *skillManager = new SkillManager(DEFAULT_SKILLSDB_FILE); SpecialManager *specialManager = new SpecialManager(DEFAULT_SPECIALSDB_FILE); +EmoteManager *emoteManager = new EmoteManager(DEFAULT_EMOTESDB_FILE); /** Core game message handler */ GameHandler *gameHandler; @@ -141,6 +145,7 @@ static void initializeServer() specialManager->initialize(); itemManager->initialize(); monsterManager->initialize(); + emoteManager->initialize(); StatusManager::initialize(DEFAULT_STATUSDB_FILE); PermissionManager::initialize(DEFAULT_PERMISSION_FILE); @@ -196,6 +201,7 @@ static void deinitializeServer() delete monsterManager; monsterManager = 0; delete skillManager; skillManager = 0; delete itemManager; itemManager = 0; + delete emoteManager; emoteManager = 0; MapManager::deinitialize(); StatusManager::deinitialize(); ScriptManager::deinitialize(); diff --git a/src/game-server/map.cpp b/src/game-server/map.cpp index e372f03d..b4e66e02 100644 --- a/src/game-server/map.cpp +++ b/src/game-server/map.cpp @@ -35,7 +35,11 @@ class PathInfo { public: PathInfo() - : whichList(0) + : Gcost(0) + , Hcost(0) + , whichList(0) + , parentX(0) + , parentY(0) {} int Gcost; /**< Cost from start to this location */ diff --git a/src/game-server/mapcomposite.cpp b/src/game-server/mapcomposite.cpp index cdea12a8..4c7dc66a 100644 --- a/src/game-server/mapcomposite.cpp +++ b/src/game-server/mapcomposite.cpp @@ -92,6 +92,7 @@ void MapZone::insert(Actor *obj) default: { objects.push_back(obj); + break; } } } @@ -117,6 +118,7 @@ void MapZone::remove(Actor *obj) { i = objects.begin() + nbMovingObjects; i_end = objects.end(); + break; } } i = std::find(i, i_end, obj); @@ -464,7 +466,8 @@ MapComposite::MapComposite(int id, const std::string &name): mMap(0), mContent(0), mName(name), - mID(id) + mID(id), + mPvPRules(PVP_NONE) { } diff --git a/src/game-server/monster.cpp b/src/game-server/monster.cpp index 2bc542cd..47246005 100644 --- a/src/game-server/monster.cpp +++ b/src/game-server/monster.cpp @@ -35,18 +35,6 @@ #include <cmath> -struct MonsterTargetEventDispatch: EventDispatch -{ - MonsterTargetEventDispatch() - { - typedef EventListenerFactory<Monster, &Monster::mTargetListener> Factory; - removed = &Factory::create< Entity, &Monster::forgetTarget >::function; - died = &Factory::create<Entity, &Monster::forgetTarget, Being>::function; - } -}; - -static MonsterTargetEventDispatch monsterTargetEventDispatch; - MonsterClass::~MonsterClass() { for (std::vector<AttackInfo *>::iterator it = mAttacks.begin(), @@ -56,7 +44,7 @@ MonsterClass::~MonsterClass() } } -float MonsterClass::getVulnerability(Element element) const +double MonsterClass::getVulnerability(Element element) const { Vulnerabilities::const_iterator it = mVulnerabilities.find(element); if (it == mVulnerabilities.end()) @@ -67,7 +55,6 @@ float MonsterClass::getVulnerability(Element element) const Monster::Monster(MonsterClass *specy): Being(OBJECT_MONSTER), mSpecy(specy), - mTargetListener(&monsterTargetEventDispatch), mOwner(NULL) { LOG_DEBUG("Monster spawned! (id: " << mSpecy->getId() << ")."); @@ -83,7 +70,7 @@ Monster::Monster(MonsterClass *specy): for (AttributeManager::AttributeScope::const_iterator it = mobAttr.begin(), it_end = mobAttr.end(); it != it_end; ++it) { - mAttributes.insert(std::pair< unsigned int, Attribute > + mAttributes.insert(std::pair< unsigned, Attribute > (it->first, Attribute(*it->second))); } @@ -105,13 +92,13 @@ Monster::Monster(MonsterClass *specy): setAttribute(it2->first, mutation ? - attr * (100 + (rand()%(mutation << 1)) - mutation) / 100.0 : + attr * (100 + (rand() % (mutation * 2)) - mutation) / 100.0 : attr); } } mDamageMutation = mutation ? - (100 + (rand()%(mutation << 1)) - mutation) / 100.0 : 1; + (100 + (rand() % (mutation * 2)) - mutation) / 100.0 : 1; setSize(specy->getSize()); setGender(specy->getGender()); @@ -130,19 +117,10 @@ Monster::Monster(MonsterClass *specy): { addAttack(*it); } - - // Load default script - loadScript(specy->getScript()); } Monster::~Monster() { - // Remove death listeners. - for (std::map<Being *, int>::iterator i = mAnger.begin(), - i_end = mAnger.end(); i != i_end; ++i) - { - i->first->removeListener(&mTargetListener); - } } void Monster::update() @@ -229,11 +207,11 @@ void Monster::refreshTarget() // Determine how much we hate the target int targetPriority = 0; - std::map<Being *, int, std::greater<Being *> >::iterator angerIterator; - angerIterator = mAnger.find(target); + std::map<Being *, AggressionInfo>::iterator angerIterator = mAnger.find(target); if (angerIterator != mAnger.end()) { - targetPriority = angerIterator->second; + const AggressionInfo &aggressionInfo = angerIterator->second; + targetPriority = aggressionInfo.anger; } else if (mSpecy->isAggressive()) { @@ -307,25 +285,6 @@ void Monster::processAttack(Attack &attack) } } -void Monster::loadScript(const std::string &scriptName) -{ - if (scriptName.length() == 0) - return; - - std::stringstream filename; - filename << "scripts/monster/" << scriptName; - if (ResourceManager::exists(filename.str())) - { - LOG_INFO("Loading monster script: " << filename.str()); - ScriptManager::currentState()->loadFile(filename.str()); - } - else - { - LOG_WARN("Could not find script file \"" - << filename.str() << "\" for monster"); - } -} - int Monster::calculatePositionPriority(Point position, int targetPriority) { Point thisPos = getPosition(); @@ -359,11 +318,15 @@ int Monster::calculatePositionPriority(Point position, int targetPriority) } } -void Monster::forgetTarget(Entity *t) +void Monster::forgetTarget(Entity *entity) { - Being *b = static_cast< Being * >(t); + Being *b = static_cast< Being * >(entity); + { + AggressionInfo &aggressionInfo = mAnger[b]; + aggressionInfo.removedConnection.disconnect(); + aggressionInfo.diedConnection.disconnect(); + } mAnger.erase(b); - b->removeListener(&mTargetListener); if (b->getType() == OBJECT_CHARACTER) { @@ -375,20 +338,42 @@ void Monster::forgetTarget(Entity *t) void Monster::changeAnger(Actor *target, int amount) { - if (target && (target->getType() == OBJECT_MONSTER - || target->getType() == OBJECT_CHARACTER)) + const EntityType type = target->getType(); + if (type != OBJECT_MONSTER && type != OBJECT_CHARACTER) + return; + + Being *being = static_cast< Being * >(target); + + if (mAnger.find(being) != mAnger.end()) { - Being *t = static_cast< Being * >(target); - if (mAnger.find(t) != mAnger.end()) - { - mAnger[t] += amount; - } - else - { - mAnger[t] = amount; - t->addListener(&mTargetListener); - } + mAnger[being].anger += amount; } + else + { + AggressionInfo &aggressionInfo = mAnger[being]; + aggressionInfo.anger = amount; + + // Forget target either when it's removed or died, whichever + // happens first. + aggressionInfo.removedConnection = + being->signal_removed.connect(sigc::mem_fun(this, &Monster::forgetTarget)); + aggressionInfo.diedConnection = + being->signal_died.connect(sigc::mem_fun(this, &Monster::forgetTarget)); + } +} + +std::map<Being *, int> Monster::getAngerList() const +{ + std::map<Being *, int> result; + std::map<Being *, AggressionInfo>::const_iterator i, i_end; + + for (i = mAnger.begin(), i_end = mAnger.end(); i != i_end; ++i) + { + const AggressionInfo &aggressionInfo = i->second; + result.insert(std::make_pair(i->first, aggressionInfo.anger)); + } + + return result; } int Monster::damage(Actor *source, const Damage &damage) @@ -399,9 +384,7 @@ int Monster::damage(Actor *source, const Damage &damage) newDamage.delta = newDamage.delta * factor; int HPLoss = Being::damage(source, newDamage); if (source) - { changeAnger(source, HPLoss); - } if (HPLoss && source && source->getType() == OBJECT_CHARACTER) { @@ -466,14 +449,14 @@ void Monster::died() iChar++) { Character *character = (*iChar).first; - std::set<size_t> *skillSet = &(*iChar).second; + const std::set<size_t> &skillSet = (*iChar).second; if (mLegalExpReceivers.find(character) == mLegalExpReceivers.end() - || skillSet->size() < 1) + || skillSet.empty()) continue; - int expPerSkill = int(expPerChar / skillSet->size()); - for (iSkill = skillSet->begin(); iSkill != skillSet->end(); + int expPerSkill = int(expPerChar / skillSet.size()); + for (iSkill = skillSet.begin(); iSkill != skillSet.end(); iSkill++) { character->receiveExperience(*iSkill, expPerSkill, @@ -483,44 +466,3 @@ void Monster::died() } } } - -bool Monster::recalculateBaseAttribute(unsigned int attr) -{ - LOG_DEBUG("Monster: Received update attribute recalculation request for " - << attr << "."); - if (!mAttributes.count(attr)) - { - LOG_DEBUG("Monster::recalculateBaseAttribute: " - << attr << " not found!"); - return false; - } - double newBase = getAttribute(attr); - - switch (attr) - { - // Those a set only at load time. - case ATTR_MAX_HP: - case ATTR_DODGE: - case ATTR_MAGIC_DODGE: - case ATTR_ACCURACY: - case ATTR_DEFENSE: - case ATTR_MAGIC_DEFENSE: - case ATTR_HP_REGEN: - case ATTR_MOVE_SPEED_TPS: - case ATTR_INV_CAPACITY: - // nothing to do. - break; - - // Only HP and Speed Raw updated for monsters - default: - Being::recalculateBaseAttribute(attr); - break; - } - if (newBase != getAttribute(attr)) - { - setAttribute(attr, newBase); - return true; - } - LOG_DEBUG("Monster: No changes to sync for attribute '" << attr << "'."); - return false; -} diff --git a/src/game-server/monster.h b/src/game-server/monster.h index a1a82eb5..b924b371 100644 --- a/src/game-server/monster.h +++ b/src/game-server/monster.h @@ -22,7 +22,6 @@ #define MONSTER_H #include "game-server/being.h" -#include "game-server/eventlistener.h" #include "common/defines.h" #include "scripting/script.h" #include "utils/string.h" @@ -31,6 +30,9 @@ #include <vector> #include <string> +#include <sigc++/connection.h> + +class Character; class ItemClass; class Script; @@ -62,7 +64,7 @@ struct MonsterAttack std::string scriptEvent; }; -typedef std::map<Element, float> Vulnerabilities; +typedef std::map<Element, double> Vulnerabilities; /** * Class describing the characteristics of a generic monster. @@ -195,16 +197,10 @@ class MonsterClass /** Returns all attacks of the monster. */ std::vector<AttackInfo *> &getAttackInfos() { return mAttacks; } - void setVulnerability(Element element, float factor) + void setVulnerability(Element element, double factor) { mVulnerabilities[element] = factor; } - float getVulnerability(Element element) const; - - /** sets the script file for the monster */ - void setScript(const std::string &filename) { mScript = filename; } - - /** Returns script filename */ - const std::string &getScript() const { return mScript; } + double getVulnerability(Element element) const; void setUpdateCallback(Script *script) { script->assignCallback(mUpdateCallback); } @@ -237,7 +233,6 @@ class MonsterClass int mOptimalLevel; std::vector<AttackInfo *> mAttacks; Vulnerabilities mVulnerabilities; - std::string mScript; /** * A reference to the script function that is called each update. @@ -301,11 +296,6 @@ class Monster : public Being virtual void processAttack(Attack &attack); /** - * Loads a script file for this monster - */ - void loadScript(const std::string &scriptName); - - /** * Kills the being. */ void died(); @@ -315,8 +305,7 @@ class Monster : public Being */ void changeAnger(Actor *target, int amount); - const std::map<Being *, int> &getAngerList() const - { return mAnger; } + std::map<Being *, int> getAngerList() const; /** * Calls the damage function in Being and updates the aggro list @@ -326,15 +315,7 @@ class Monster : public Being /** * Removes a being from the anger list. */ - void forgetTarget(Entity *being); - - /** - * Called when an attribute modifier is changed. - * Recalculate the base value of an attribute and update derived - * attributes if it has changed. - * @returns Whether it was changed. - */ - virtual bool recalculateBaseAttribute(unsigned int); + void forgetTarget(Entity *entity); protected: /** @@ -351,10 +332,16 @@ class Monster : public Being MonsterClass *mSpecy; /** Aggression towards other beings. */ - std::map<Being *, int> mAnger; - - /** Listener for updating the anger list. */ - EventListener mTargetListener; + struct AggressionInfo { + AggressionInfo() + : anger(0) + {} + + int anger; + sigc::connection removedConnection; + sigc::connection diedConnection; + }; + std::map<Being *, AggressionInfo> mAnger; /** * Character who currently owns this monster (killsteal protection). diff --git a/src/game-server/monstermanager.cpp b/src/game-server/monstermanager.cpp index cfe540d8..0fb62da0 100644 --- a/src/game-server/monstermanager.cpp +++ b/src/game-server/monstermanager.cpp @@ -258,11 +258,12 @@ void MonsterManager::initialize() } } - else if (xmlStrEqual(subnode->name, BAD_CAST "script")) + else if (xmlStrEqual(subnode->name, BAD_CAST "vulnerability")) { - xmlChar *filename = subnode->xmlChildrenNode->content; - std::string val = (char *)filename; - monster->setScript(val); + Element element = elementFromString( + XML::getProperty(subnode, "element", std::string())); + double factor = XML::getFloatProperty(subnode, "factor", 1.0); + monster->setVulnerability(element, factor); } else if (xmlStrEqual(subnode->name, BAD_CAST "vulnerability")) { diff --git a/src/game-server/npc.cpp b/src/game-server/npc.cpp index 82cd6a51..ce6ac32e 100644 --- a/src/game-server/npc.cpp +++ b/src/game-server/npc.cpp @@ -54,6 +54,8 @@ void NPC::update() return; Script *script = ScriptManager::currentState(); + script->setMap(getMap()); + script->prepare(mUpdateCallback); script->push(this); script->execute(); diff --git a/src/game-server/quest.cpp b/src/game-server/quest.cpp index 4d659227..c28a4213 100644 --- a/src/game-server/quest.cpp +++ b/src/game-server/quest.cpp @@ -18,24 +18,27 @@ * along with The Mana Server. If not, see <http://www.gnu.org/licenses/>. */ -#include <cassert> -#include <list> -#include <map> -#include <string> - #include "game-server/quest.h" #include "game-server/accountconnection.h" #include "game-server/character.h" -#include "game-server/eventlistener.h" #include "utils/logger.h" +#include <cassert> +#include <list> +#include <map> +#include <string> + +#include <sigc++/connection.h> + typedef std::list< QuestCallback * > QuestCallbacks; typedef std::map< std::string, QuestCallbacks > PendingVariables; struct PendingQuest { Character *character; + sigc::connection removedConnection; + sigc::connection disconnectedConnection; PendingVariables variables; }; @@ -72,22 +75,6 @@ void setQuestVar(Character *ch, const std::string &name, accountHandler->updateCharacterVar(ch, name, value); } -/** - * Listener for deleting related quests when a character disappears. - */ -struct QuestDeathListener: EventDispatch -{ - static void partialRemove(const EventListener *, Entity *); - - static void fullRemove(const EventListener *, Character *); - - QuestDeathListener() - { - removed = &partialRemove; - disconnected = &fullRemove; - } -}; - void QuestRefCallback::triggerCallback(Character *ch, const std::string &value) const { @@ -103,10 +90,7 @@ void QuestRefCallback::triggerCallback(Character *ch, s->execute(); } -static QuestDeathListener questDeathDummy; -static EventListener questDeathListener(&questDeathDummy); - -void QuestDeathListener::partialRemove(const EventListener *, Entity *t) +static void partialRemove(Entity *t) { int id = static_cast< Character * >(t)->getDatabaseID(); PendingVariables &variables = pendingQuests[id].variables; @@ -119,11 +103,18 @@ void QuestDeathListener::partialRemove(const EventListener *, Entity *t) // The listener is kept in case a fullRemove is needed later. } -void QuestDeathListener::fullRemove(const EventListener *, Character *ch) +static void fullRemove(Character *ch) { - ch->removeListener(&questDeathListener); + int id = ch->getDatabaseID(); + + { + PendingQuest &pendingQuest = pendingQuests[id]; + pendingQuest.removedConnection.disconnect(); + pendingQuest.disconnectedConnection.disconnect(); + } + // Remove anything related to this character. - pendingQuests.erase(ch->getDatabaseID()); + pendingQuests.erase(id); } void recoverQuestVar(Character *ch, const std::string &name, @@ -134,11 +125,19 @@ void recoverQuestVar(Character *ch, const std::string &name, PendingQuests::iterator i = pendingQuests.lower_bound(id); if (i == pendingQuests.end() || i->first != id) { - i = pendingQuests.insert(i, std::make_pair(id, PendingQuest())); - i->second.character = ch; - /* Register a listener, because we cannot afford to get invalid - pointers, when we finally recover the variable. */ - ch->addListener(&questDeathListener); + PendingQuest pendingQuest; + pendingQuest.character = ch; + + /* Connect to removed and disconnected signals, because we cannot + * afford to get invalid pointers, when we finally recover the + * variable. + */ + pendingQuest.removedConnection = + ch->signal_removed.connect(sigc::ptr_fun(partialRemove)); + pendingQuest.disconnectedConnection = + ch->signal_disconnected.connect(sigc::ptr_fun(fullRemove)); + + i = pendingQuests.insert(i, std::make_pair(id, pendingQuest)); } i->second.variables[name].push_back(f); accountHandler->requestCharacterVar(ch, name); @@ -149,12 +148,14 @@ void recoveredQuestVar(int id, const std::string &value) { PendingQuests::iterator i = pendingQuests.find(id); - if (i == pendingQuests.end()) return; + if (i == pendingQuests.end()) + return; - Character *ch = i->second.character; - ch->removeListener(&questDeathListener); + PendingQuest &pendingQuest = i->second; + pendingQuest.removedConnection.disconnect(); + pendingQuest.disconnectedConnection.disconnect(); - PendingVariables &variables = i->second.variables; + PendingVariables &variables = pendingQuest.variables; PendingVariables::iterator j = variables.find(name); if (j == variables.end()) { @@ -162,6 +163,7 @@ void recoveredQuestVar(int id, return; } + Character *ch = pendingQuest.character; ch->questCache[name] = value; // Call the registered callbacks. diff --git a/src/game-server/quest.h b/src/game-server/quest.h index 05caa6ab..0d130789 100644 --- a/src/game-server/quest.h +++ b/src/game-server/quest.h @@ -42,23 +42,21 @@ class QuestCallback class QuestThreadCallback : public QuestCallback { public: - QuestThreadCallback(void (*handler)(Character *, - const std::string &value, - Script *mScript), + typedef void (*Handler)(Character *, + const std::string &value, + Script *mScript); + + QuestThreadCallback(Handler handler, Script *script) : mHandler(handler), mScript(script) { } - virtual void triggerCallback(Character *ch, - const std::string &value) const + void triggerCallback(Character *ch, const std::string &value) const { mHandler(ch, value, mScript); } private: - void (*mHandler)(Character *, - const std::string &value, - Script *mScript); - + Handler mHandler; Script *mScript; }; @@ -69,8 +67,7 @@ class QuestRefCallback : public QuestCallback mQuestName(questName) { script->assignCallback(mRef); } - virtual void triggerCallback(Character *ch, - const std::string &value) const; + void triggerCallback(Character *ch, const std::string &value) const; private: Script::Ref mRef; diff --git a/src/game-server/skillmanager.cpp b/src/game-server/skillmanager.cpp index b5a94cbe..2e78194c 100644 --- a/src/game-server/skillmanager.cpp +++ b/src/game-server/skillmanager.cpp @@ -131,7 +131,7 @@ void SkillManager::readSkillNode(xmlNodePtr skillNode, } mSkillsInfo.insert( - std::make_pair<unsigned int, SkillInfo*>(skillInfo->id, skillInfo)); + std::make_pair<unsigned, SkillInfo*>(skillInfo->id, skillInfo)); std::string keyName = setName + "_" + skillInfo->skillName; mNamedSkillsInfo.insert(keyName, skillInfo); @@ -167,27 +167,33 @@ void SkillManager::printDebugSkillTable() } } -unsigned int SkillManager::getId(const std::string &set, - const std::string &name) const +unsigned SkillManager::getId(const std::string &set, + const std::string &name) const { std::string key = utils::toLower(set) + "_" + utils::toLower(name); return getId(key); } -unsigned int SkillManager::getId(const std::string &skillName) const +unsigned SkillManager::getId(const std::string &skillName) const { SkillInfo *skillInfo = mNamedSkillsInfo.value(skillName); return skillInfo ? skillInfo->id : 0; } -const std::string SkillManager::getSkillName(unsigned int id) const +const std::string SkillManager::getSkillName(unsigned id) const { SkillsInfo::const_iterator it = mSkillsInfo.find(id); return it != mSkillsInfo.end() ? it->second->skillName : ""; } -const std::string SkillManager::getSetName(unsigned int id) const +const std::string SkillManager::getSetName(unsigned id) const { SkillsInfo::const_iterator it = mSkillsInfo.find(id); return it != mSkillsInfo.end() ? it->second->setName : ""; } + +bool SkillManager::exists(unsigned id) const +{ + SkillsInfo::const_iterator it = mSkillsInfo.find(id); + return it != mSkillsInfo.end(); +} diff --git a/src/game-server/skillmanager.h b/src/game-server/skillmanager.h index 36e2485e..85f7f42e 100644 --- a/src/game-server/skillmanager.h +++ b/src/game-server/skillmanager.h @@ -49,18 +49,20 @@ class SkillManager /** * Gets the skill Id from a set and a skill string. */ - unsigned int getId(const std::string &set, const std::string &name) const; + unsigned getId(const std::string &set, const std::string &name) const; /** * Gets the skill Id from a string formatted in this way: * "setname_skillname" */ - unsigned int getId(const std::string &skillName) const; + unsigned getId(const std::string &skillName) const; - const std::string getSkillName(unsigned int id) const; - const std::string getSetName(unsigned int id) const; + const std::string getSkillName(unsigned id) const; + const std::string getSetName(unsigned id) const; - unsigned int getDefaultSkillId() const + bool exists(unsigned id) const; + + unsigned getDefaultSkillId() const { return mDefaultSkillId; } private: struct SkillInfo { @@ -68,7 +70,7 @@ class SkillManager id(0) {} - unsigned int id; + unsigned id; std::string setName; std::string skillName; }; @@ -86,13 +88,13 @@ class SkillManager std::string mSkillFile; // The skill map - typedef std::map<unsigned int, SkillInfo*> SkillsInfo; + typedef std::map<unsigned, SkillInfo*> SkillsInfo; SkillsInfo mSkillsInfo; // A map used to get skills per name. utils::NameMap<SkillInfo*> mNamedSkillsInfo; // The default skill id - unsigned int mDefaultSkillId; + unsigned mDefaultSkillId; }; extern SkillManager *skillManager; diff --git a/src/game-server/spawnarea.cpp b/src/game-server/spawnarea.cpp index 155d4c0d..73dca6b2 100644 --- a/src/game-server/spawnarea.cpp +++ b/src/game-server/spawnarea.cpp @@ -25,18 +25,6 @@ #include "game-server/state.h" #include "utils/logger.h" -struct SpawnAreaEventDispatch : EventDispatch -{ - SpawnAreaEventDispatch() - { - typedef EventListenerFactory< SpawnArea, &SpawnArea::mSpawnedListener > - Factory; - removed = &Factory::create< Entity, &SpawnArea::decrease >::function; - } -}; - -static SpawnAreaEventDispatch spawnAreaEventDispatch; - SpawnArea::SpawnArea(MapComposite *map, MonsterClass *specy, const Rectangle &zone, @@ -44,7 +32,6 @@ SpawnArea::SpawnArea(MapComposite *map, int spawnRate): Entity(OBJECT_OTHER, map), mSpecy(specy), - mSpawnedListener(&spawnAreaEventDispatch), mZone(zone), mMaxBeings(maxBeings), mSpawnRate(spawnRate), @@ -102,7 +89,9 @@ void SpawnArea::update() if (c) { - being->addListener(&mSpawnedListener); + being->signal_removed.connect( + sigc::mem_fun(this, &SpawnArea::decrease)); + being->setMap(map); being->setPosition(position); being->clearDestination(); @@ -125,8 +114,7 @@ void SpawnArea::update() } } -void SpawnArea::decrease(Entity *t) +void SpawnArea::decrease(Entity *) { --mNumBeings; - t->removeListener(&mSpawnedListener); } diff --git a/src/game-server/spawnarea.h b/src/game-server/spawnarea.h index cc0642f1..628c072e 100644 --- a/src/game-server/spawnarea.h +++ b/src/game-server/spawnarea.h @@ -21,7 +21,6 @@ #ifndef SPAWNAREA_H #define SPAWNAREA_H -#include "game-server/eventlistener.h" #include "game-server/entity.h" #include "utils/point.h" @@ -47,7 +46,6 @@ class SpawnArea : public Entity private: MonsterClass *mSpecy; /**< Specy of monster that spawns in this area. */ - EventListener mSpawnedListener; /**< Tracking of spawned monsters. */ Rectangle mZone; int mMaxBeings; /**< Maximum population of this area. */ int mSpawnRate; /**< Number of beings spawning per minute. */ diff --git a/src/game-server/specialmanager.cpp b/src/game-server/specialmanager.cpp index 32669bca..39616faa 100644 --- a/src/game-server/specialmanager.cpp +++ b/src/game-server/specialmanager.cpp @@ -143,14 +143,14 @@ void SpecialManager::clear() mNamedSpecialsInfo.clear(); } -unsigned int SpecialManager::getId(const std::string &set, - const std::string &name) const +unsigned SpecialManager::getId(const std::string &set, + const std::string &name) const { std::string key = utils::toLower(set) + "_" + utils::toLower(name); return getId(key); } -unsigned int SpecialManager::getId(const std::string &specialName) const +unsigned SpecialManager::getId(const std::string &specialName) const { if (mNamedSpecialsInfo.contains(specialName)) return mNamedSpecialsInfo.value(specialName)->id; diff --git a/src/game-server/specialmanager.h b/src/game-server/specialmanager.h index b7a4f54b..e9203a34 100644 --- a/src/game-server/specialmanager.h +++ b/src/game-server/specialmanager.h @@ -48,12 +48,12 @@ public: target(TARGET_BEING) {} - unsigned int id; + unsigned id; std::string name; std::string setName; bool rechargeable; int defaultRechargeSpeed; - unsigned int neededMana; + unsigned neededMana; TargetMode target; Script::Ref rechargedCallback; Script::Ref useCallback; @@ -79,13 +79,13 @@ public: /** * Gets the specials Id from a set and a special string. */ - unsigned int getId(const std::string &set, const std::string &name) const; + unsigned getId(const std::string &set, const std::string &name) const; /** * Gets the specials Id from a string formatted in this way: * "setname_skillname" */ - unsigned int getId(const std::string &specialName) const; + unsigned getId(const std::string &specialName) const; const std::string getSpecialName(int id) const; const std::string getSetName(int id) const; @@ -102,7 +102,7 @@ private: const std::string &setName); std::string mSpecialFile; - typedef std::map<unsigned int, SpecialInfo*> SpecialsInfo; + typedef std::map<unsigned, SpecialInfo*> SpecialsInfo; SpecialsInfo mSpecialsInfo; typedef utils::NameMap<SpecialInfo*> NamedSpecialsInfo; NamedSpecialsInfo mNamedSpecialsInfo; diff --git a/src/game-server/state.cpp b/src/game-server/state.cpp index 249040a8..5353a236 100644 --- a/src/game-server/state.cpp +++ b/src/game-server/state.cpp @@ -84,11 +84,11 @@ static void serializeLooks(Character *ch, MessageOut &msg) // We'll use a set to check whether we already sent the update for the given // item instance. - std::set<unsigned int> itemInstances; + std::set<unsigned> itemInstances; // The map storing the info about the look changes to send //{ slot type id, item id } - std::map <unsigned int, unsigned int> lookChanges; + std::map <unsigned, unsigned> lookChanges; // Note that we can send several updates on the same slot type as different // items may have been equipped. @@ -105,8 +105,8 @@ static void serializeLooks(Character *ch, MessageOut &msg) // we encounter the item, so we can send the look change. // We also send empty slots for unequipment handling. lookChanges.insert( - std::make_pair<unsigned int, unsigned int>(it->first, - it->second.itemId)); + std::make_pair<unsigned, unsigned>(it->first, + it->second.itemId)); } } @@ -115,7 +115,7 @@ static void serializeLooks(Character *ch, MessageOut &msg) // Number of look changes to send msg.writeInt8(lookChanges.size()); - for (std::map<unsigned int, unsigned int>::const_iterator it2 = + for (std::map<unsigned, unsigned>::const_iterator it2 = lookChanges.begin(), it2_end = lookChanges.end(); it2 != it2_end; ++it2) { @@ -193,6 +193,19 @@ static void informPlayer(MapComposite *map, Character *p) gameHandler->sendTo(p, LooksMsg); } + // Send emote messages. + if (oflags & UPDATEFLAG_EMOTE) + { + int emoteId = o->getLastEmote(); + if (emoteId > -1) + { + MessageOut EmoteMsg(GPMSG_BEING_EMOTE); + EmoteMsg.writeInt16(oid); + EmoteMsg.writeInt16(emoteId); + gameHandler->sendTo(p, EmoteMsg); + } + } + // Send direction change messages. if (oflags & UPDATEFLAG_DIRCHANGE) { @@ -271,6 +284,7 @@ static void informPlayer(MapComposite *map, Character *p) default: assert(false); // TODO + break; } gameHandler->sendTo(p, enterMsg); } @@ -500,7 +514,7 @@ bool GameState::insert(Entity *ptr) if (!ptr->isVisible()) { map->insert(ptr); - ptr->inserted(); + ptr->signal_inserted.emit(ptr); return true; } @@ -525,7 +539,7 @@ bool GameState::insert(Entity *ptr) return false; } - obj->inserted(); + obj->signal_inserted.emit(obj); // DEBUG INFO switch (obj->getType()) @@ -558,6 +572,7 @@ bool GameState::insert(Entity *ptr) case OBJECT_OTHER: default: LOG_DEBUG("Entity inserted: " << obj->getType()); + break; } obj->raiseUpdateFlags(UPDATEFLAG_NEW_ON_MAP); @@ -598,7 +613,7 @@ void GameState::remove(Entity *ptr) MapComposite *map = ptr->getMap(); int visualRange = Configuration::getValue("game_visualRange", 448); - ptr->removed(); + ptr->signal_removed.emit(ptr); // DEBUG INFO switch (ptr->getType()) @@ -631,6 +646,7 @@ void GameState::remove(Entity *ptr) case OBJECT_OTHER: default: LOG_DEBUG("Entity removed: " << ptr->getType()); + break; } if (ptr->canMove()) diff --git a/src/game-server/trade.h b/src/game-server/trade.h index d425767a..43b674fb 100644 --- a/src/game-server/trade.h +++ b/src/game-server/trade.h @@ -101,7 +101,7 @@ class Trade TradedItems mItems1, mItems2; /**< Traded items. */ int mMoney1, mMoney2; /**< Traded money. */ TradeState mState; /**< State of transaction. */ - unsigned int mCurrencyId; /**< The attribute to use as currency. */ + unsigned mCurrencyId; /**< The attribute to use as currency. */ }; #endif diff --git a/src/net/connectionhandler.cpp b/src/net/connectionhandler.cpp index 5aaf90e0..d116aa93 100644 --- a/src/net/connectionhandler.cpp +++ b/src/net/connectionhandler.cpp @@ -162,7 +162,7 @@ void ConnectionHandler::sendToEveryone(const MessageOut &msg) } } -unsigned int ConnectionHandler::getClientCount() const +unsigned ConnectionHandler::getClientCount() const { return clients.size(); } diff --git a/src/net/connectionhandler.h b/src/net/connectionhandler.h index 96fc90cd..7dde004f 100644 --- a/src/net/connectionhandler.h +++ b/src/net/connectionhandler.h @@ -79,7 +79,7 @@ class ConnectionHandler /** * Return the number of connected clients. */ - unsigned int getClientCount() const; + unsigned getClientCount() const; private: ENetAddress address; /**< Includes the port to listen to. */ diff --git a/src/net/messagein.cpp b/src/net/messagein.cpp index b797f0a0..ce1be488 100644 --- a/src/net/messagein.cpp +++ b/src/net/messagein.cpp @@ -27,6 +27,7 @@ #ifndef USE_NATIVE_DOUBLE #include <sstream> #endif +#include <stdint.h> #include "net/messagein.h" #include "utils/logger.h" diff --git a/src/net/messageout.cpp b/src/net/messageout.cpp index d39fd23e..af305a6e 100644 --- a/src/net/messageout.cpp +++ b/src/net/messageout.cpp @@ -28,14 +28,15 @@ #include <limits> #include <sstream> #endif +#include <stdint.h> #include <string> #include <enet/enet.h> /** Initial amount of bytes allocated for the messageout data buffer. */ -const unsigned int INITIAL_DATA_CAPACITY = 16; +const unsigned INITIAL_DATA_CAPACITY = 16; /** Factor by which the messageout data buffer is increased when too small. */ -const unsigned int CAPACITY_GROW_FACTOR = 2; +const unsigned CAPACITY_GROW_FACTOR = 2; static bool debugModeEnabled = false; diff --git a/src/net/messageout.h b/src/net/messageout.h index a39e306b..af5980f4 100644 --- a/src/net/messageout.h +++ b/src/net/messageout.h @@ -75,7 +75,7 @@ class MessageOut /** * Returns the length of the data. */ - unsigned int getLength() const { return mPos; } + unsigned getLength() const { return mPos; } /** * Sets whether the debug mode is enabled. In debug mode, the internal @@ -96,8 +96,8 @@ class MessageOut void writeValueType(ManaServ::ValueType type); char *mData; /**< Data building up. */ - unsigned int mPos; /**< Position in the data. */ - unsigned int mDataSize; /**< Allocated datasize. */ + unsigned mPos; /**< Position in the data. */ + unsigned mDataSize; /**< Allocated datasize. */ bool mDebugMode; /**< Include debugging information. */ /** diff --git a/src/net/netcomputer.cpp b/src/net/netcomputer.cpp index c4af3420..8834f4a6 100644 --- a/src/net/netcomputer.cpp +++ b/src/net/netcomputer.cpp @@ -57,7 +57,7 @@ void NetComputer::disconnect(const MessageOut &msg) } void NetComputer::send(const MessageOut &msg, bool reliable, - unsigned int channel) + unsigned channel) { LOG_DEBUG("Sending message " << msg << " to " << *this); diff --git a/src/net/netcomputer.h b/src/net/netcomputer.h index ee5d2cdc..09840348 100644 --- a/src/net/netcomputer.h +++ b/src/net/netcomputer.h @@ -68,7 +68,7 @@ class NetComputer * be sent. */ void send(const MessageOut &msg, bool reliable = true, - unsigned int channel = 0); + unsigned channel = 0); /** * Returns IP address of computer in 32bit int form diff --git a/src/scripting/lua.cpp b/src/scripting/lua.cpp index 6285f382..4e2cd283 100644 --- a/src/scripting/lua.cpp +++ b/src/scripting/lua.cpp @@ -69,6 +69,30 @@ extern "C" { /** + * on_update_derived_attribute( function(Being*) ): void + * Sets a listener function to handle + * recalculation of derived attributes event. + */ +static int on_update_derived_attribute(lua_State *s) +{ + luaL_checktype(s, 1, LUA_TFUNCTION); + Being::setUpdateDerivedAttributesCallback(getScript(s)); + return 0; +} + + +/** + * on_recalculateBaseAttributeCallback( function(Being*) ): void + * Sets a listener function to the attribute recalculation event. + */ +static int on_recalculate_base_attribute(lua_State *s) +{ + luaL_checktype(s, 1, LUA_TFUNCTION); + Being::setRecalculateBaseAttributeCallback(getScript(s)); + return 0; +} + +/** * on_character_death( function(Character*) ): void * Sets a listener function to the character death event. */ @@ -458,8 +482,6 @@ static int chr_get_inventory(lua_State *s) int firstTableStackPosition = lua_gettop(s); int tableIndex = 1; - std::string itemName = ""; - for (InventoryData::const_iterator it = invData.begin(), it_end = invData.end(); it != it_end; ++it) { @@ -470,20 +492,19 @@ static int chr_get_inventory(lua_State *s) lua_createtable(s, 0, 4); int subTableStackPosition = lua_gettop(s); // Stores the item info in it. - lua_pushstring(s, "slot"); + lua_pushliteral(s, "slot"); lua_pushinteger(s, it->first); // The slot id lua_settable(s, subTableStackPosition); - lua_pushstring(s, "id"); + lua_pushliteral(s, "id"); lua_pushinteger(s, it->second.itemId); lua_settable(s, subTableStackPosition); - lua_pushstring(s, "name"); - itemName = itemManager->getItem(it->second.itemId)->getName(); - lua_pushstring(s, itemName.c_str()); + lua_pushliteral(s, "name"); + push(s, itemManager->getItem(it->second.itemId)->getName()); lua_settable(s, subTableStackPosition); - lua_pushstring(s, "amount"); + lua_pushliteral(s, "amount"); lua_pushinteger(s, it->second.amount); lua_settable(s, subTableStackPosition); @@ -517,7 +538,6 @@ static int chr_get_equipment(lua_State *s) int firstTableStackPosition = lua_gettop(s); int tableIndex = 1; - std::string itemName; std::set<unsigned> itemInstances; for (EquipData::const_iterator it = equipData.begin(), @@ -534,17 +554,16 @@ static int chr_get_equipment(lua_State *s) lua_createtable(s, 0, 3); int subTableStackPosition = lua_gettop(s); // Stores the item info in it. - lua_pushstring(s, "slot"); + lua_pushliteral(s, "slot"); lua_pushinteger(s, it->first); // The slot id lua_settable(s, subTableStackPosition); - lua_pushstring(s, "id"); + lua_pushliteral(s, "id"); lua_pushinteger(s, it->second.itemId); lua_settable(s, subTableStackPosition); - lua_pushstring(s, "name"); - itemName = itemManager->getItem(it->second.itemId)->getName(); - lua_pushstring(s, itemName.c_str()); + lua_pushliteral(s, "name"); + push(s, itemManager->getItem(it->second.itemId)->getName()); lua_settable(s, subTableStackPosition); // Add the sub-table as value of the main one. @@ -1127,7 +1146,7 @@ static int being_remove_attribute_modifier(lua_State *s) static int being_get_name(lua_State *s) { Being *being = checkBeing(s, 1); - lua_pushstring(s, being->getName().c_str()); + push(s, being->getName()); return 1; } @@ -1309,7 +1328,7 @@ static int monster_get_name(lua_State *s) luaL_error(s, "monster_get_name called with unknown monster id."); return 0; } - lua_pushstring(s, spec->getName().c_str()); + push(s, spec->getName()); return 1; } @@ -1386,7 +1405,7 @@ static int chr_get_quest(lua_State *s) bool res = getQuestVar(q, name, value); if (res) { - lua_pushstring(s, value.c_str()); + push(s, value); return 1; } QuestCallback *f = new QuestThreadCallback(&LuaScript::getQuestCallback, @@ -1453,7 +1472,7 @@ static int chr_try_get_quest(lua_State *s) std::string value; bool res = getQuestVar(q, name, value); if (res) - lua_pushstring(s, value.c_str()); + push(s, value); else lua_pushnil(s); return 1; @@ -1469,9 +1488,8 @@ static int getvar_map(lua_State *s) luaL_argcheck(s, name[0] != 0, 1, "empty variable name"); MapComposite *map = checkCurrentMap(s); - std::string value = map->getVariable(name); - lua_pushstring(s, value.c_str()); + push(s, map->getVariable(name)); return 1; } @@ -1500,8 +1518,7 @@ static int getvar_world(lua_State *s) const char *name = luaL_checkstring(s, 1); luaL_argcheck(s, name[0] != 0, 1, "empty variable name"); - std::string value = GameState::getVariable(name); - lua_pushstring(s, value.c_str()); + push(s, GameState::getVariable(name)); return 1; } @@ -1716,7 +1733,11 @@ static int chr_get_post(lua_State *s) static int being_register(lua_State *s) { Being *being = checkBeing(s, 1); - being->addListener(getScript(s)->getScriptListener()); + Script *script = getScript(s); + + being->signal_died.connect(sigc::mem_fun(script, &Script::processDeathEvent)); + being->signal_removed.connect(sigc::mem_fun(script, &Script::processRemoveEvent)); + return 0; } @@ -2128,8 +2149,7 @@ static int get_map_property(lua_State *s) const char *property = luaL_checkstring(s, 1); Map *map = checkCurrentMap(s)->getMap(); - std::string value = map->getProperty(property); - lua_pushstring(s, value.c_str()); + push(s, map->getProperty(property)); return 1; } @@ -2210,7 +2230,7 @@ static int item_get_name(lua_State *s) luaL_error(s, "item_get_name called with unknown item id."); return 0; } - lua_pushstring(s, it->getName().c_str()); + push(s, it->getName()); return 1; } @@ -2314,7 +2334,7 @@ static int map_object_get_property(lua_State *s) std::string property = obj->getProperty(key); if (!property.empty()) { - lua_pushstring(s, property.c_str()); + push(s, property); return 1; } else @@ -2346,7 +2366,7 @@ static int map_object_get_bounds(lua_State *s) static int map_object_get_name(lua_State *s) { MapObject *obj = LuaMapObject::check(s, 1); - lua_pushstring(s, obj->getName().c_str()); + push(s, obj->getName()); return 1; } @@ -2357,7 +2377,7 @@ static int map_object_get_name(lua_State *s) static int map_object_get_type(lua_State *s) { MapObject *obj = LuaMapObject::check(s, 1); - lua_pushstring(s, obj->getType().c_str()); + push(s, obj->getType()); return 1; } @@ -2398,7 +2418,7 @@ static int get_special_info(lua_State *s) static int specialinfo_get_name(lua_State *s) { SpecialManager::SpecialInfo *info = LuaSpecialInfo::check(s, 1); - lua_pushstring(s, info->name.c_str()); + push(s, info->name); return 1; } @@ -2419,7 +2439,7 @@ static int specialinfo_is_rechargeable(lua_State *s) static int specialinfo_get_category(lua_State *s) { SpecialManager::SpecialInfo *info = LuaSpecialInfo::check(s, 1); - lua_pushstring(s, info->setName.c_str()); + push(s, info->setName); return 1; } @@ -2559,7 +2579,7 @@ static int require_loader(lua_State *s) if (!path.empty()) luaL_loadfile(s, path.c_str()); else - lua_pushstring(s, "File not found"); + lua_pushliteral(s, "File not found"); return 1; } @@ -2573,15 +2593,21 @@ LuaScript::LuaScript(): luaL_openlibs(mRootState); // Register package loader that goes through the resource manager - // table.insert(package.loaders, 2, require_loader) + // package.loaders[2] = require_loader lua_getglobal(mRootState, "package"); +#if LUA_VERSION_NUM < 502 lua_getfield(mRootState, -1, "loaders"); +#else + lua_getfield(mRootState, -1, "searchers"); +#endif lua_pushcfunction(mRootState, require_loader); lua_rawseti(mRootState, -2, 2); lua_pop(mRootState, 2); // Put the callback functions in the scripting environment. static luaL_Reg const callbacks[] = { + { "on_update_derived_attribute", &on_update_derived_attribute }, + { "on_recalculate_base_attribute", &on_recalculate_base_attribute }, { "on_character_death", &on_character_death }, { "on_character_death_accept", &on_character_death_accept }, { "on_character_login", &on_character_login }, @@ -2699,8 +2725,13 @@ LuaScript::LuaScript(): { "get_special_info", &get_special_info }, { NULL, NULL } }; +#if LUA_VERSION_NUM < 502 lua_pushvalue(mRootState, LUA_GLOBALSINDEX); luaL_register(mRootState, NULL, callbacks); +#else + lua_pushglobaltable(mRootState); + luaL_setfuncs(mRootState, callbacks, 0); +#endif lua_pop(mRootState, 1); // pop the globals table static luaL_Reg const members_AttackInfo[] = { diff --git a/src/scripting/luascript.cpp b/src/scripting/luascript.cpp index e2b127f7..f4ea39ac 100644 --- a/src/scripting/luascript.cpp +++ b/src/scripting/luascript.cpp @@ -82,7 +82,7 @@ void LuaScript::push(int v) void LuaScript::push(const std::string &v) { assert(nbArgs >= 0); - lua_pushstring(mCurrentState, v.c_str()); + lua_pushlstring(mCurrentState, v.c_str(), v.length()); ++nbArgs; } @@ -151,7 +151,11 @@ bool LuaScript::resume() setMap(mCurrentThread->mMap); const int tmpNbArgs = nbArgs; nbArgs = -1; +#if LUA_VERSION_NUM < 502 int result = lua_resume(mCurrentState, tmpNbArgs); +#else + int result = lua_resume(mCurrentState, NULL, tmpNbArgs); +#endif setMap(0); if (result == 0) // Thread is done @@ -241,6 +245,7 @@ void LuaScript::processDeathEvent(Being *entity) { if (mDeathNotificationCallback.isValid()) { + setMap(entity->getMap()); prepare(mDeathNotificationCallback); push(entity); //TODO: get and push a list of creatures who contributed to killing the @@ -253,14 +258,13 @@ void LuaScript::processRemoveEvent(Entity *entity) { if (mRemoveNotificationCallback.isValid()) { + setMap(entity->getMap()); prepare(mRemoveNotificationCallback); push(entity); //TODO: get and push a list of creatures who contributed to killing the // being. This might be very interesting for scripting quests. execute(); } - - entity->removeListener(getScriptListener()); } /** diff --git a/src/scripting/luascript.h b/src/scripting/luascript.h index 7631d982..9515bf0e 100644 --- a/src/scripting/luascript.h +++ b/src/scripting/luascript.h @@ -28,6 +28,8 @@ extern "C" { #include "scripting/script.h" +class Character; + /** * Implementation of the Script class for Lua. */ diff --git a/src/scripting/luautil.cpp b/src/scripting/luautil.cpp index 3de23c77..f7b39e29 100644 --- a/src/scripting/luautil.cpp +++ b/src/scripting/luautil.cpp @@ -86,8 +86,8 @@ void UserDataCache::insert(lua_State *s, void *object) // The metatable that makes the values in the table above weak lua_newtable(s); // UD, Cache, {} - lua_pushstring(s, "__mode"); - lua_pushstring(s, "v"); + lua_pushliteral(s, "__mode"); + lua_pushliteral(s, "v"); lua_rawset(s, -3); // UD, Cache, { __mode = "v" } lua_setmetatable(s, -2); // UD, Cache diff --git a/src/scripting/luautil.h b/src/scripting/luautil.h index 1ff2ab8d..8e380d4e 100644 --- a/src/scripting/luautil.h +++ b/src/scripting/luautil.h @@ -102,8 +102,13 @@ public: mTypeName = typeName; luaL_newmetatable(s, mTypeName); // metatable - lua_pushstring(s, "__index"); // metatable, "__index" - luaL_register(s, typeName, members); // metatable, "__index", {} + lua_pushliteral(s, "__index"); // metatable, "__index" + lua_createtable(s, 0, 0); // metatable, "__index", {} +#if LUA_VERSION_NUM < 502 + luaL_register(s, NULL, members); +#else + luaL_setfuncs(s, members, 0); +#endif lua_rawset(s, -3); // metatable lua_pop(s, 1); // -empty- } @@ -125,8 +130,12 @@ public: void *userData = lua_newuserdata(s, sizeof(T*)); * static_cast<T**>(userData) = object; +#if LUA_VERSION_NUM < 502 luaL_newmetatable(s, mTypeName); lua_setmetatable(s, -2); +#else + luaL_setmetatable(s, mTypeName); +#endif UserDataCache::insert(s, object); } @@ -188,7 +197,7 @@ inline void push(lua_State *s, int val) inline void push(lua_State *s, const std::string &val) { - lua_pushstring(s, val.c_str()); + lua_pushlstring(s, val.c_str(), val.length()); } inline void push(lua_State *s, Entity *val) diff --git a/src/scripting/script.cpp b/src/scripting/script.cpp index 3e299461..63ab7ff4 100644 --- a/src/scripting/script.cpp +++ b/src/scripting/script.cpp @@ -40,8 +40,7 @@ Script::Ref Script::mUpdateCallback; Script::Script(): mCurrentThread(0), - mMap(0), - mEventListener(&scriptEventDispatch) + mMap(0) {} Script::~Script() diff --git a/src/scripting/script.h b/src/scripting/script.h index 238bc34c..8dee23a9 100644 --- a/src/scripting/script.h +++ b/src/scripting/script.h @@ -23,19 +23,21 @@ #include "common/inventorydata.h" #include "common/manaserv_protocol.h" -#include "game-server/eventlistener.h" #include <list> #include <string> #include <vector> +#include <sigc++/trackable.h> + +class Being; class MapComposite; class Entity; /** * Abstract interface for calling functions written in an external language. */ -class Script +class Script : public sigc::trackable { public: /** @@ -216,9 +218,6 @@ class Script MapComposite *getMap() const { return mMap; } - EventListener *getScriptListener() - { return &mEventListener; } - virtual void processDeathEvent(Being *entity) = 0; virtual void processRemoveEvent(Entity *entity) = 0; @@ -235,7 +234,6 @@ class Script private: MapComposite *mMap; - EventListener mEventListener; /**< Tracking of being deaths. */ std::vector<Thread*> mThreads; static Ref mCreateNpcDelayedCallback; @@ -245,16 +243,4 @@ class Script friend class Thread; }; -struct ScriptEventDispatch: EventDispatch -{ - ScriptEventDispatch() - { - typedef EventListenerFactory< Script, &Script::mEventListener > Factory; - died = &Factory::create< Being, &Script::processDeathEvent >::function; - removed = &Factory::create< Entity, &Script::processRemoveEvent >::function; - } -}; - -static ScriptEventDispatch scriptEventDispatch; - #endif // SCRIPTING_SCRIPT_H diff --git a/src/serialize/characterdata.h b/src/serialize/characterdata.h index cab51197..abcc6114 100644 --- a/src/serialize/characterdata.h +++ b/src/serialize/characterdata.h @@ -132,10 +132,10 @@ void deserializeCharacterData(T &data, MessageIn &msg) data.setCorrectionPoints(msg.readInt16()); // character attributes - unsigned int attrSize = msg.readInt16(); - for (unsigned int i = 0; i < attrSize; ++i) + unsigned attrSize = msg.readInt16(); + for (unsigned i = 0; i < attrSize; ++i) { - unsigned int id = msg.readInt16(); + unsigned id = msg.readInt16(); double base = msg.readDouble(), mod = msg.readDouble(); data.setAttribute(id, base); @@ -193,7 +193,7 @@ void deserializeCharacterData(T &data, MessageIn &msg) Possessions &poss = data.getPossessions(); EquipData equipData; int equipSlotsSize = msg.readInt16(); - unsigned int eqSlot; + unsigned eqSlot; EquipmentItem equipItem; for (int j = 0; j < equipSlotsSize; ++j) { diff --git a/src/sql/sqlite/createTables.sql b/src/sql/sqlite/createTables.sql index 06dbd195..d845e842 100644 --- a/src/sql/sqlite/createTables.sql +++ b/src/sql/sqlite/createTables.sql @@ -18,6 +18,8 @@ -- along with The Mana Server. If not, see <http://www.gnu.org/licenses/>. -- +BEGIN; + ----------------------------------------------------------------------------- -- Tables ----------------------------------------------------------------------------- @@ -480,3 +482,5 @@ INSERT INTO mana_transaction_codes VALUES ( 51, 'Command RESTART_THIS', 'Com INSERT INTO mana_transaction_codes VALUES ( 52, 'Command RESTART_ALL', 'Commands' ); INSERT INTO mana_transaction_codes VALUES ( 53, 'Command ATTRIBUTE', 'Commands' ); INSERT INTO mana_transaction_codes VALUES ( 54, 'Command KICK', 'Commands' ); + +END; diff --git a/src/utils/functors.h b/src/utils/functors.h index ef1aa046..fce3bec5 100644 --- a/src/utils/functors.h +++ b/src/utils/functors.h @@ -29,26 +29,6 @@ namespace { /** - * Functor used for the search of an object by name in a list. - * - * Note: - * - this functor assumes that the object defines as public the following - * method: std::string getName() const. - * - this functor assumes that the list is a list of pointers. - */ -template <typename T> -struct obj_name_is - : public std::binary_function<T, std::string, bool> -{ - bool - operator()(const T& obj, - const std::string& name) const - { - return (obj->getName() == name); - } -}; - -/** * Functor to convert a string into another type using * std::istringstream.operator>>(). */ diff --git a/src/utils/point.h b/src/utils/point.h index 988b6c5a..b077286d 100644 --- a/src/utils/point.h +++ b/src/utils/point.h @@ -25,7 +25,7 @@ #include <ostream> /** - * A point in positive space. Usually represents pixel coordinates on a map. + * A point. Usually represents pixel coordinates on a map. */ class Point { @@ -62,8 +62,7 @@ class Point }; /** - * A rectangle in positive space. Usually represents a pixel-based zone on a - * map. + * A rectangle. Usually represents a pixel-based zone on a map. */ class Rectangle { diff --git a/src/utils/string.cpp b/src/utils/string.cpp index b74b91ee..fdc5eb59 100644 --- a/src/utils/string.cpp +++ b/src/utils/string.cpp @@ -40,7 +40,7 @@ std::string toLower(std::string s) bool isNumeric(const std::string &s) { - for (unsigned int i = 0; i < s.size(); ++i) + for (unsigned i = 0; i < s.size(); ++i) { if (!isdigit(s[i])) { diff --git a/src/utils/stringfilter.cpp b/src/utils/stringfilter.cpp index b48d267f..e3696097 100644 --- a/src/utils/stringfilter.cpp +++ b/src/utils/stringfilter.cpp @@ -100,8 +100,8 @@ bool StringFilter::filterContent(const std::string &text) const bool StringFilter::isEmailValid(const std::string &email) const { - unsigned int min = Configuration::getValue("account_minEmailLength", 7); - unsigned int max = Configuration::getValue("account_maxEmailLength", 128); + unsigned min = Configuration::getValue("account_minEmailLength", 7); + unsigned max = Configuration::getValue("account_maxEmailLength", 128); // Testing email validity if (email.length() < min || email.length() > max) diff --git a/src/utils/timer.cpp b/src/utils/timer.cpp index aea10add..c01a4134 100644 --- a/src/utils/timer.cpp +++ b/src/utils/timer.cpp @@ -43,7 +43,7 @@ static uint64_t getTimeInMillisec() namespace utils { -Timer::Timer(unsigned int ms) +Timer::Timer(unsigned ms) { active = false; interval = ms; @@ -97,7 +97,7 @@ void Timer::stop() active = false; } -void Timer::changeInterval(unsigned int newinterval) +void Timer::changeInterval(unsigned newinterval) { interval = newinterval; } diff --git a/src/utils/timer.h b/src/utils/timer.h index 2c6ca891..2fb9e7b1 100644 --- a/src/utils/timer.h +++ b/src/utils/timer.h @@ -42,7 +42,7 @@ class Timer * * @param ms the interval in milliseconds */ - Timer(unsigned int ms); + Timer(unsigned ms); /** * Returns the number of elapsed ticks since last call. @@ -67,13 +67,13 @@ class Timer /** * Changes the interval between two pulses. */ - void changeInterval(unsigned int newinterval); + void changeInterval(unsigned newinterval); private: /** * Interval between two pulses. */ - unsigned int interval; + unsigned interval; /** * The time the last pulse occured. |