summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErik Schilling <ablu.erikschilling@googlemail.com>2013-02-17 12:24:45 +0100
committerErik Schilling <ablu.erikschilling@googlemail.com>2013-08-26 22:56:47 +0200
commit44ee071d7ece5a2023f79307f36e8a244c9e7b3a (patch)
tree06b7fcea59bbbf1963b460ca9b678d0ea6fa90e4
parente3a1e9c89e102dbf961c624435c495c759776312 (diff)
downloadmanaserv-44ee071d7ece5a2023f79307f36e8a244c9e7b3a.tar.gz
manaserv-44ee071d7ece5a2023f79307f36e8a244c9e7b3a.tar.bz2
manaserv-44ee071d7ece5a2023f79307f36e8a244c9e7b3a.tar.xz
manaserv-44ee071d7ece5a2023f79307f36e8a244c9e7b3a.zip
Removed skills
This removes support for skills. The plan is to allow to implement the skills as they were implemented before via attributes. This adds a lot more flexibility to the server creators while also removing the confusion about skills and attributes. So this change does: - Remove the skillmanager with all its calls, the skill xml file, etc - Move exp giving to the script engine: --> Allows to implement the old behaviour (and more) in the scripts - Remove the exp tag from the monster definition: + Since the server itself does not require it anymore it feels wrong to require it for EVERY monster. TODO: Add a system to add properties to the monsters/items.xml which allow defining things like the exp and allows to read the value from the script engine. + Small drawback, but it should not be hard to implement this property system. - Drop the level networking and calculation. + level calculation will happen via the attribute system later but i would prefer to do this in a seperate patch since this patch already got longer than expected especially since this requires to make setting correction points and available status points scriptable. + The level would be simply set as a attribute, the int number of it will be the level, the remaining digits will be the % number till the next levelup. - NOT remove any existing skill tables in the database update scripts. + There is no way to move them into the attribute table in a unified way (there are too many different way they could have been used). So server admins have to care about moving theirs skills to attributes themselves. + Keeping the old tables does not hurt for existing databases. So removing does not give any advantage/is required anyway. The now obsolote info about the EXP transaction is not removed for updated databases either. (The update script basically only bumps the version number without doing anything else. - bump the network protocol version --> old clients won't be able to connect. - bump the database version --> serveradmins need to update their db.
-rw-r--r--example/monsters.xml5
-rw-r--r--example/permissions.xml1
-rw-r--r--example/settings.xml1
-rw-r--r--example/skills.xml22
-rw-r--r--gameserver.cbp2
-rw-r--r--scripts/lua/libmana-constants.lua13
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/account-server/accounthandler.cpp1
-rw-r--r--src/account-server/character.cpp1
-rw-r--r--src/account-server/character.h26
-rw-r--r--src/account-server/serverhandler.cpp16
-rw-r--r--src/account-server/storage.cpp130
-rw-r--r--src/account-server/storage.h19
-rw-r--r--src/common/manaserv_protocol.h11
-rw-r--r--src/common/transaction.h1
-rw-r--r--src/game-server/accountconnection.cpp11
-rw-r--r--src/game-server/accountconnection.h10
-rw-r--r--src/game-server/being.cpp1
-rw-r--r--src/game-server/character.cpp162
-rw-r--r--src/game-server/character.h115
-rw-r--r--src/game-server/commandhandler.cpp49
-rw-r--r--src/game-server/itemmanager.cpp1
-rw-r--r--src/game-server/main-game.cpp2
-rw-r--r--src/game-server/monster.h14
-rw-r--r--src/game-server/monstermanager.cpp13
-rw-r--r--src/game-server/settingsmanager.cpp9
-rw-r--r--src/game-server/skillmanager.cpp201
-rw-r--r--src/game-server/skillmanager.h103
-rw-r--r--src/scripting/lua.cpp93
-rw-r--r--src/scripting/luautil.cpp11
-rw-r--r--src/scripting/luautil.h1
-rw-r--r--src/serialize/characterdata.h22
-rw-r--r--src/sql/mysql/createTables.sql20
-rw-r--r--src/sql/mysql/updates/update_22_to_23.sql15
-rw-r--r--src/sql/sqlite/createTables.sql18
-rw-r--r--src/sql/sqlite/updates/update_22_to_23.sql58
36 files changed, 86 insertions, 1094 deletions
diff --git a/example/monsters.xml b/example/monsters.xml
index 890a3b2b..53fd3382 100644
--- a/example/monsters.xml
+++ b/example/monsters.xml
@@ -25,7 +25,6 @@ attributes <TAG>: Tells all the monsters attribute. These attribute, as for ite
For instance, with a mutation of 50, each attribute can be altered to become 100% to 149% of what they are.
element[string]: Tells to which element the weakness is. ('fire', 'earth', 'ice', 'metal' are some examples.)
factor[float]: Tells the defense against an element is reduced in percent. (A value of 0.7 indicates that the defense is lowered by 30%).
-exp<TAG>: Tells how much experience point a monster is giving upon victory.
-->
<monsters>
@@ -44,7 +43,6 @@ exp<TAG>: Tells how much experience point a monster is giving up
size="4"
mutation="50"
/>
- <exp>10</exp>
<attribute id="HP" value="200" />
<attribute id="Max HP" value="200" />
<attribute id="Movement speed" value="2" />
@@ -62,7 +60,6 @@ exp<TAG>: Tells how much experience point a monster is giving up
<drop item="2" percent="1"/>
<drop item="5" percent="0.5"/>
<drop item="9" percent="7"/>
- <exp>20</exp>
<attributes
size="8"
/>
@@ -91,7 +88,6 @@ exp<TAG>: Tells how much experience point a monster is giving up
<drop item="4" percent="5"/>
<drop item="6" percent="0.1"/>
<drop item="9" percent="5.4"/>
- <exp>50</exp>
<attributes
size="8"
gender="female"
@@ -113,7 +109,6 @@ exp<TAG>: Tells how much experience point a monster is giving up
<drop item="7" percent="1.9"/>
<drop item="8" percent="0.1"/>
<drop item="9" percent="7.5"/>
- <exp>60</exp>
<attributes
size="4"
/>
diff --git a/example/permissions.xml b/example/permissions.xml
index 6385d505..97ce8c6f 100644
--- a/example/permissions.xml
+++ b/example/permissions.xml
@@ -20,7 +20,6 @@
<allow>@money</allow>
<allow>@spawn</allow>
<allow>@attribute</allow>
- <allow>@skills</allow>
<allow>@charwarp</allow>
<allow>@killmonsters</allow>
<allow>@getpos</allow>
diff --git a/example/settings.xml b/example/settings.xml
index 6f2516d5..edb90406 100644
--- a/example/settings.xml
+++ b/example/settings.xml
@@ -3,7 +3,6 @@
<include file="attributes.xml" />
<include file="abilities.xml" />
<include file="maps.xml" />
- <include file="skills.xml" />
<include file="equip.xml" />
<include file="items.xml" />
<include file="monsters.xml" />
diff --git a/example/skills.xml b/example/skills.xml
deleted file mode 100644
index 7019759f..00000000
--- a/example/skills.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<skills>
- <skill-set name="Weapons">
- <skill id="100" name="Unarmed" icon="graphics/skills/unarmed.png" default="true" />
- <skill id="101" name="Knife" icon="graphics/skills/knife.png" />
- <skill id="102" name="Sword" icon="graphics/skills/sword.png" />
- <skill id="103" name="Polearm" icon="graphics/skills/polearm.png" />
- <skill id="104" name="Staff" icon="graphics/skills/staff.png" />
- <skill id="105" name="Whip" icon="graphics/skills/whip.png" />
- <skill id="106" name="Bow" icon="graphics/skills/bow.png" />
- <skill id="107" name="Shooting" icon="graphics/skills/shooting.png" />
- <skill id="108" name="Mace" icon="graphics/skills/mace.png" />
- <skill id="109" name="Axe" icon="graphics/skills/axe.png" />
- <skill id="110" name="Thrown" icon="graphics/skills/thrown.png" />
- </skill-set>
- <skill-set name="Magic">
- <skill id="200" name="Magic Example" />
- </skill-set>
- <skill-set name="Crafts">
- <skill id="300" name="Craft Example" />
- </skill-set>
-</skills>
diff --git a/gameserver.cbp b/gameserver.cbp
index 90bed40f..dcb6abba 100644
--- a/gameserver.cbp
+++ b/gameserver.cbp
@@ -170,8 +170,6 @@
<Unit filename="src/game-server/quest.h" />
<Unit filename="src/game-server/settingsmanager.cpp" />
<Unit filename="src/game-server/settingsmanager.h" />
- <Unit filename="src/game-server/skillmanager.cpp" />
- <Unit filename="src/game-server/skillmanager.h" />
<Unit filename="src/game-server/spawnareacomponent.cpp" />
<Unit filename="src/game-server/spawnareacomponent.h" />
<Unit filename="src/game-server/state.cpp" />
diff --git a/scripts/lua/libmana-constants.lua b/scripts/lua/libmana-constants.lua
index c187797c..426170e6 100644
--- a/scripts/lua/libmana-constants.lua
+++ b/scripts/lua/libmana-constants.lua
@@ -103,19 +103,6 @@ EMOTE_PERTURBED = 10011;
EMOTE_SPEECH = 10012;
EMOTE_BLAH = 10013;
--- Skills - TODO: should be obtainable in a smarter way
-SKILL_WEAPON_NONE = 100
-SKILL_WEAPON_KNIFE = 101
-SKILL_WEAPON_SWORD = 102
-SKILL_WEAPON_POLEARM = 103
-SKILL_WEAPON_STAFF = 104
-SKILL_WEAPON_WHIP = 105
-SKILL_WEAPON_BOW = 106
-SKILL_WEAPON_SHOOTING = 107
-SKILL_WEAPON_MACE = 108
-SKILL_WEAPON_AXE = 109
-SKILL_WEAPON_THROWN = 110
-
-- Loglevels
LOG_FATAL = 0
LOG_ERROR = 1
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 4eac8517..5cc8f1a8 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -259,8 +259,6 @@ SET(SRCS_MANASERVGAME
game-server/quest.cpp
game-server/settingsmanager.h
game-server/settingsmanager.cpp
- game-server/skillmanager.h
- game-server/skillmanager.cpp
game-server/spawnareacomponent.h
game-server/spawnareacomponent.cpp
game-server/state.h
diff --git a/src/account-server/accounthandler.cpp b/src/account-server/accounthandler.cpp
index 2656d210..87cb2b46 100644
--- a/src/account-server/accounthandler.cpp
+++ b/src/account-server/accounthandler.cpp
@@ -280,7 +280,6 @@ void AccountHandler::sendCharacterData(AccountClient &client,
charInfo.writeInt8(ch.getGender());
charInfo.writeInt8(ch.getHairStyle());
charInfo.writeInt8(ch.getHairColor());
- charInfo.writeInt16(ch.getLevel());
charInfo.writeInt16(ch.getCharacterPoints());
charInfo.writeInt16(ch.getCorrectionPoints());
diff --git a/src/account-server/character.cpp b/src/account-server/character.cpp
index 19d679df..3fc3ed19 100644
--- a/src/account-server/character.cpp
+++ b/src/account-server/character.cpp
@@ -32,7 +32,6 @@ CharacterData::CharacterData(const std::string &name, int id):
mGender(0),
mHairStyle(0),
mHairColor(0),
- mLevel(0),
mCharacterPoints(0),
mCorrectionPoints(0),
mAccountLevel(0)
diff --git a/src/account-server/character.h b/src/account-server/character.h
index 53443c4b..58e32dad 100644
--- a/src/account-server/character.h
+++ b/src/account-server/character.h
@@ -156,12 +156,6 @@ class CharacterData
void setAccountLevel(int l, bool force = false)
{ if (force) mAccountLevel = l; }
- /**
- * Gets the level of the character.
- */
- int getLevel() const { return mLevel; }
- void setLevel(int level) { mLevel = level; }
-
/** Sets the value of a base attribute of the character. */
void setAttribute(unsigned id, double value)
{ mAttributes[id].base = value; }
@@ -172,24 +166,6 @@ class CharacterData
const AttributeMap &getAttributes() const
{ return mAttributes; }
- int getSkillSize() const
- { return mExperience.size(); }
-
- const std::map<int, int>::const_iterator getSkillBegin() const
- { return mExperience.begin(); }
-
- const std::map<int, int>::const_iterator getSkillEnd() const
- { return mExperience.end(); }
-
- int getExperience(int skill) const
- { return mExperience.find(skill)->second; }
-
- void setExperience(int skill, int value)
- { mExperience[skill] = value; }
-
- void receiveExperience(int skill, int value)
- { mExperience[skill] += value; }
-
/**
* Get / Set a status effects
*/
@@ -300,7 +276,6 @@ class CharacterData
Account *mAccount; //!< Account owning the character.
Point mPos; //!< Position the being is at.
AttributeMap mAttributes; //!< Attributes.
- std::map<int, int> mExperience; //!< Skill Experience.
std::map<int, Status> mStatusEffects; //!< Status Effects
std::map<int, int> mKillCount; //!< Kill Count
AbilityMap mAbilities;
@@ -308,7 +283,6 @@ class CharacterData
unsigned char mGender; //!< Gender of the being.
unsigned char mHairStyle; //!< Hair style of the being.
unsigned char mHairColor; //!< Hair color of the being.
- short mLevel; //!< Level of the being.
short mCharacterPoints; //!< Unused character points.
short mCorrectionPoints; //!< Unused correction points.
unsigned char mAccountLevel; //!< Level of the associated account.
diff --git a/src/account-server/serverhandler.cpp b/src/account-server/serverhandler.cpp
index 1ba3c03d..19c32fda 100644
--- a/src/account-server/serverhandler.cpp
+++ b/src/account-server/serverhandler.cpp
@@ -414,13 +414,6 @@ void ServerHandler::processMessage(NetComputer *comp, MessageIn &msg)
storage->banCharacter(id, duration);
} break;
- case GAMSG_CHANGE_PLAYER_LEVEL:
- {
- int id = msg.readInt32();
- int level = msg.readInt16();
- storage->setPlayerLevel(id, level);
- } break;
-
case GAMSG_CHANGE_ACCOUNT_LEVEL:
{
int id = msg.readInt32();
@@ -693,15 +686,6 @@ void GameServerHandler::syncDatabase(MessageIn &msg)
storage->updateAttribute(charId, attrId, base, mod);
} break;
- case SYNC_CHARACTER_SKILL:
- {
- LOG_DEBUG("received SYNC_CHARACTER_SKILL");
- int charId = msg.readInt32();
- int skillId = msg.readInt8();
- int skillValue = msg.readInt32();
- storage->updateExperience(charId, skillId, skillValue);
- } break;
-
case SYNC_ONLINE_STATUS:
{
LOG_DEBUG("received SYNC_ONLINE_STATUS");
diff --git a/src/account-server/storage.cpp b/src/account-server/storage.cpp
index 965024a0..2ddb2e08 100644
--- a/src/account-server/storage.cpp
+++ b/src/account-server/storage.cpp
@@ -75,7 +75,6 @@ static const char *DB_VERSION_PARAMETER = "database_version";
static const char *ACCOUNTS_TBL_NAME = "mana_accounts";
static const char *CHARACTERS_TBL_NAME = "mana_characters";
static const char *CHAR_ATTR_TBL_NAME = "mana_char_attr";
-static const char *CHAR_SKILLS_TBL_NAME = "mana_char_skills";
static const char *CHAR_STATUS_EFFECTS_TBL_NAME = "mana_char_status_effects";
static const char *CHAR_KILL_COUNT_TBL_NAME = "mana_char_kill_stats";
static const char *CHAR_ABILITIES_TBL_NAME = "mana_char_abilities";
@@ -363,13 +362,12 @@ CharacterData *Storage::getCharacterBySQL(Account *owner)
character->setGender(toUshort(charInfo(0, 3)));
character->setHairStyle(toUshort(charInfo(0, 4)));
character->setHairColor(toUshort(charInfo(0, 5)));
- character->setLevel(toUshort(charInfo(0, 6)));
- character->setCharacterPoints(toUshort(charInfo(0, 7)));
- character->setCorrectionPoints(toUshort(charInfo(0, 8)));
- Point pos(toInt(charInfo(0, 9)), toInt(charInfo(0, 10)));
+ character->setCharacterPoints(toUshort(charInfo(0, 6)));
+ character->setCorrectionPoints(toUshort(charInfo(0, 7)));
+ Point pos(toInt(charInfo(0, 8)), toInt(charInfo(0, 9)));
character->setPosition(pos);
- int mapId = toUint(charInfo(0, 11));
+ int mapId = toUint(charInfo(0, 10));
if (mapId > 0)
{
character->setMapId(mapId);
@@ -381,7 +379,7 @@ CharacterData *Storage::getCharacterBySQL(Account *owner)
character->setMapId(Configuration::getValue("char_defaultMap", 1));
}
- character->setCharacterSlot(toUint(charInfo(0, 12)));
+ character->setCharacterSlot(toUint(charInfo(0, 11)));
// Fill the account-related fields. Last step, as it may require a new
// SQL query.
@@ -422,25 +420,6 @@ CharacterData *Storage::getCharacterBySQL(Account *owner)
s.clear();
s.str("");
- // Load skills.
- s << "SELECT skill_id, skill_exp "
- << "FROM " << CHAR_SKILLS_TBL_NAME
- << " WHERE char_id = " << character->getDatabaseID();
-
- const dal::RecordSet &skillInfo = mDb->execSql(s.str());
- if (!skillInfo.isEmpty())
- {
- const unsigned nRows = skillInfo.rows();
- for (unsigned row = 0; row < nRows; ++row)
- {
- unsigned id = toUint(skillInfo(row, 0));
- character->setExperience(id, toInt(skillInfo(row, 1)));
- }
- }
-
- s.clear();
- s.str("");
-
// Load the status effects
s << "select status_id, status_time FROM "
<< CHAR_STATUS_EFFECTS_TBL_NAME
@@ -723,7 +702,6 @@ bool Storage::updateCharacter(CharacterData *character)
<< "gender = '" << character->getGender() << "', "
<< "hair_style = '" << character->getHairStyle() << "', "
<< "hair_color = '" << character->getHairColor() << "', "
- << "level = '" << character->getLevel() << "', "
<< "char_pts = '" << character->getCharacterPoints() << "', "
<< "correct_pts = '"<< character->getCorrectionPoints() << "', "
<< "x = '" << character->getPosition().x << "', "
@@ -754,23 +732,6 @@ bool Storage::updateCharacter(CharacterData *character)
"SQL query failure: ", e);
}
- // Character's skills
- try
- {
- std::map<int, int>::const_iterator skill_it;
- for (skill_it = character->mExperience.begin();
- skill_it != character->mExperience.end(); skill_it++)
- {
- updateExperience(character->getDatabaseID(),
- skill_it->first, skill_it->second);
- }
- }
- catch (const dal::DbSqlQueryExecFailure& e)
- {
- utils::throwError("(DALStorage::updateCharacter #3) "
- "SQL query failure: ", e);
- }
-
// Character's kill count
try
{
@@ -1022,14 +983,13 @@ void Storage::flush(Account *account)
sqlInsertCharactersTable
<< "insert into " << CHARACTERS_TBL_NAME
<< " (user_id, name, gender, hair_style, hair_color,"
- << " level, char_pts, correct_pts,"
+ << " char_pts, correct_pts,"
<< " x, y, map_id, slot) values ("
<< account->getID() << ", \""
<< character->getName() << "\", "
<< character->getGender() << ", "
<< (int)character->getHairStyle() << ", "
<< (int)character->getHairColor() << ", "
- << (int)character->getLevel() << ", "
<< (int)character->getCharacterPoints() << ", "
<< (int)character->getCorrectionPoints() << ", "
<< character->getPosition().x << ", "
@@ -1053,15 +1013,6 @@ void Storage::flush(Account *account)
attr_it->second.base,
attr_it->second.modified);
}
-
- // Update the characters skill
- std::map<int, int>::const_iterator skill_it;
- for (skill_it = character->mExperience.begin();
- skill_it != character->mExperience.end(); skill_it++)
- {
- updateExperience(character->getDatabaseID(),
- skill_it->first, skill_it->second);
- }
}
}
@@ -1173,51 +1124,6 @@ void Storage::updateCharacterPoints(int charId,
}
}
-void Storage::updateExperience(int charId, int skillId, int skillValue)
-{
- try
- {
- std::ostringstream sql;
- // If experience has decreased to 0 we don't store it anymore,
- // since it's the default behaviour.
- if (skillValue == 0)
- {
- sql << "DELETE FROM " << CHAR_SKILLS_TBL_NAME
- << " WHERE char_id = " << charId
- << " AND skill_id = " << skillId;
- mDb->execSql(sql.str());
- return;
- }
-
- // Try to update the skill
- sql.clear();
- sql.str("");
- sql << "UPDATE " << CHAR_SKILLS_TBL_NAME
- << " SET skill_exp = " << skillValue
- << " WHERE char_id = " << charId
- << " AND skill_id = " << skillId;
- mDb->execSql(sql.str());
-
- // Check if the update has modified a row
- if (mDb->getModifiedRows() > 0)
- return;
-
- sql.clear();
- sql.str("");
- sql << "INSERT INTO " << CHAR_SKILLS_TBL_NAME << " "
- << "(char_id, skill_id, skill_exp) VALUES ( "
- << charId << ", "
- << skillId << ", "
- << skillValue << ")";
- mDb->execSql(sql.str());
- }
- catch (const dal::DbSqlQueryExecFailure &e)
- {
- utils::throwError("(DALStorage::updateExperience) SQL query failure: ",
- e);
- }
-}
-
void Storage::updateAttribute(int charId, unsigned attrId,
double base, double mod)
{
@@ -1795,13 +1701,6 @@ void Storage::delCharacter(int charId) const
<< " WHERE owner_id = '" << charId << "';";
mDb->execSql(sql.str());
- // Delete the skills of the character
- sql.clear();
- sql.str("");
- sql << "DELETE FROM " << CHAR_SKILLS_TBL_NAME
- << " WHERE char_id = '" << charId << "';";
- mDb->execSql(sql.str());
-
// Delete from the quests table
sql.clear();
sql.str("");
@@ -1886,23 +1785,6 @@ void Storage::setAccountLevel(int id, int level)
}
}
-void Storage::setPlayerLevel(int id, int level)
-{
- try
- {
- std::ostringstream sql;
- sql << "update " << CHARACTERS_TBL_NAME
- << " set level = " << level
- << " where id = " << id << ";";
- mDb->execSql(sql.str());
- }
- catch (const dal::DbSqlQueryExecFailure &e)
- {
- utils::throwError("(DALStorage::setPlayerLevel) SQL query failure: ",
- e);
- }
-}
-
void Storage::storeLetter(Letter *letter)
{
try
diff --git a/src/account-server/storage.h b/src/account-server/storage.h
index fbc4cd8c..7acc78e6 100644
--- a/src/account-server/storage.h
+++ b/src/account-server/storage.h
@@ -135,15 +135,6 @@ class Storage
int charPoints, int corrPoints);
/**
- * Write a modification message about character skills to the database.
- *
- * @param CharId ID of the character
- * @param SkillId ID of the skill
- * @param SkillValue new skill points
- */
- void updateExperience(int charId, int skillId, int skillValue);
-
- /**
* Write a modification message about character attributes
* to the database.
*
@@ -156,7 +147,7 @@ class Storage
double base, double mod);
/**
- * Write a modification message about character skills to the database.
+ * Write a modification message about kill counts to the database.
*
* @param CharId ID of the character
* @param monsterId ID of the monster type
@@ -384,14 +375,6 @@ class Storage
void setAccountLevel(int id, int level);
/**
- * Set the level on a character.
- *
- * @param id The id of the character
- * @param level The level to set for the character
- */
- void setPlayerLevel(int id, int level);
-
- /**
* Store letter.
*
* @param letter The letter to store
diff --git a/src/common/manaserv_protocol.h b/src/common/manaserv_protocol.h
index 4e584137..734ba1f2 100644
--- a/src/common/manaserv_protocol.h
+++ b/src/common/manaserv_protocol.h
@@ -29,8 +29,8 @@
namespace ManaServ {
enum {
- PROTOCOL_VERSION = 3,
- SUPPORTED_DB_VERSION = 22
+ PROTOCOL_VERSION = 4,
+ SUPPORTED_DB_VERSION = 23
};
/**
@@ -82,7 +82,7 @@ enum {
APMSG_CHAR_CREATE_RESPONSE = 0x0021, // B error
PAMSG_CHAR_DELETE = 0x0022, // B slot
APMSG_CHAR_DELETE_RESPONSE = 0x0023, // B error
- // B slot, S name, B gender, B hair style, B hair color, W level,
+ // B slot, S name, B gender, B hair style, B hair color,
// W character points, W correction points,
// {D attr id, D base value (in 1/256ths) D mod value (in 256ths) }*
APMSG_CHAR_INFO = 0x0024, // ^
@@ -118,9 +118,6 @@ enum {
GPMSG_INVENTORY_FULL = 0x0121, // W inventory slot count { W slot, W itemId, W amount }, { W equip slot, W item Id, W item Instance}*
GPMSG_EQUIP = 0x0122, // W item Id, W equip slot type count //{ W equip slot, W capacity used}*//<- When equipping, //{ W item instance, W 0}*//<- When unequipping
GPMSG_PLAYER_ATTRIBUTE_CHANGE = 0x0130, // { W attribute, D base value (in 1/256ths), D modified value (in 1/256ths)}*
- GPMSG_PLAYER_EXP_CHANGE = 0x0140, // { W skill, D exp got, D exp needed, W skill level }*
- GPMSG_LEVELUP = 0x0150, // W new level, W character points, W correction points
- GPMSG_LEVEL_PROGRESS = 0x0151, // B percent completed to next levelup
PGMSG_RAISE_ATTRIBUTE = 0x0160, // W attribute
GPMSG_RAISE_ATTRIBUTE_RESPONSE = 0x0161, // B error, W attribute
PGMSG_LOWER_ATTRIBUTE = 0x0170, // W attribute
@@ -271,7 +268,6 @@ enum {
GAMSG_SET_VAR_WORLD = 0x0547, // S name, S value
AGMSG_SET_VAR_WORLD = 0x0548, // S name, S value
GAMSG_BAN_PLAYER = 0x0550, // D id, W duration
- GAMSG_CHANGE_PLAYER_LEVEL = 0x0555, // D id, W level
GAMSG_CHANGE_ACCOUNT_LEVEL = 0x0556, // D id, W level
GAMSG_STATISTICS = 0x0560, // { W map id, W entity nb, W monster nb, W player nb, { D character id }* }*
CGMSG_CHANGED_PARTY = 0x0590, // D character id, D party id
@@ -322,7 +318,6 @@ enum {
enum {
SYNC_CHARACTER_POINTS = 0x01, // D charId, D charPoints, D corrPoints
SYNC_CHARACTER_ATTRIBUTE = 0x02, // D charId, D attrId, DF base, DF mod
- SYNC_CHARACTER_SKILL = 0x03, // D charId, B skillId, D skill value
SYNC_ONLINE_STATUS = 0x04 // D charId, B 0 = offline, 1 = online
};
diff --git a/src/common/transaction.h b/src/common/transaction.h
index 51c373eb..12a1d61a 100644
--- a/src/common/transaction.h
+++ b/src/common/transaction.h
@@ -63,7 +63,6 @@ enum
TRANS_ATTR_INCREASE,
TRANS_ATTR_DECREASE,
TRANS_CMD_MUTE,
- TRANS_CMD_EXP,
TRANS_CMD_INVISIBLE,
TRANS_CMD_COMBAT,
TRANS_CMD_ANNOUNCE,
diff --git a/src/game-server/accountconnection.cpp b/src/game-server/accountconnection.cpp
index e52393bd..06674780 100644
--- a/src/game-server/accountconnection.cpp
+++ b/src/game-server/accountconnection.cpp
@@ -476,17 +476,6 @@ void AccountConnection::updateAttributes(int charId, int attrId, double base,
syncChanges();
}
-void AccountConnection::updateExperience(int charId, int skillId,
- int skillValue)
-{
- ++mSyncMessages;
- mSyncBuffer->writeInt8(SYNC_CHARACTER_SKILL);
- mSyncBuffer->writeInt32(charId);
- mSyncBuffer->writeInt8(skillId);
- mSyncBuffer->writeInt32(skillValue);
- syncChanges();
-}
-
void AccountConnection::updateOnlineStatus(int charId, bool online)
{
++mSyncMessages;
diff --git a/src/game-server/accountconnection.h b/src/game-server/accountconnection.h
index 2ad79dd2..f6ef8678 100644
--- a/src/game-server/accountconnection.h
+++ b/src/game-server/accountconnection.h
@@ -141,16 +141,6 @@ class AccountConnection : public Connection
double mod);
/**
- * Write a modification message about character skills to the sync
- * buffer.
- *
- * @param charId ID of the character
- * @param skillId ID of the skill
- * @param skillValue new skill points
- */
- void updateExperience(int charId, int skillId, int skillValue);
-
- /**
* Update the status of a character to online (true) or offline
* (false).
*
diff --git a/src/game-server/being.cpp b/src/game-server/being.cpp
index b4feda9c..b49e3cba 100644
--- a/src/game-server/being.cpp
+++ b/src/game-server/being.cpp
@@ -29,7 +29,6 @@
#include "game-server/collisiondetection.h"
#include "game-server/mapcomposite.h"
#include "game-server/effect.h"
-#include "game-server/skillmanager.h"
#include "game-server/statuseffect.h"
#include "game-server/statusmanager.h"
#include "utils/logger.h"
diff --git a/src/game-server/character.cpp b/src/game-server/character.cpp
index a8d29625..e4a30a2f 100644
--- a/src/game-server/character.cpp
+++ b/src/game-server/character.cpp
@@ -31,7 +31,6 @@
#include "game-server/map.h"
#include "game-server/mapcomposite.h"
#include "game-server/mapmanager.h"
-#include "game-server/skillmanager.h"
#include "game-server/state.h"
#include "game-server/trade.h"
#include "scripting/scriptmanager.h"
@@ -46,12 +45,6 @@
#include <cmath>
#include <limits.h>
-// Experience curve related values
-const float CharacterComponent::EXPCURVE_EXPONENT = 3.0f;
-const float CharacterComponent::EXPCURVE_FACTOR = 10.0f;
-const float CharacterComponent::LEVEL_SKILL_PRECEDENCE_FACTOR = 0.75f;
-const float CharacterComponent::EXP_LEVEL_FLEXIBILITY = 1.0f;
-
Script::Ref CharacterComponent::mDeathCallback;
Script::Ref CharacterComponent::mDeathAcceptedCallback;
Script::Ref CharacterComponent::mLoginCallback;
@@ -76,10 +69,6 @@ CharacterComponent::CharacterComponent(Entity &entity, MessageIn &msg):
mDatabaseID(-1),
mHairStyle(0),
mHairColor(0),
- mLevel(1),
- mLevelProgress(0),
- mUpdateLevelProgress(false),
- mRecalculateLevel(true),
mSendAbilityCooldown(false),
mParty(0),
mTransaction(TRANS_NONE),
@@ -133,13 +122,6 @@ CharacterComponent::~CharacterComponent()
void CharacterComponent::update(Entity &entity)
{
- // Update character level if needed.
- if (mRecalculateLevel)
- {
- mRecalculateLevel = false;
- recalculateLevel(entity);
- }
-
// Dead character: don't regenerate anything else
if (entity.getComponent<BeingComponent>()->getAction() == DEAD)
return;
@@ -304,27 +286,6 @@ void CharacterComponent::sendStatus(Entity &entity)
}
if (attribMsg.getLength() > 2) gameHandler->sendTo(mClient, attribMsg);
mModifiedAttributes.clear();
-
- MessageOut expMsg(GPMSG_PLAYER_EXP_CHANGE);
- for (std::set<size_t>::const_iterator i = mModifiedExperience.begin(),
- i_end = mModifiedExperience.end(); i != i_end; ++i)
- {
- int skill = *i;
- expMsg.writeInt16(skill);
- expMsg.writeInt32(getExpGot(skill));
- expMsg.writeInt32(getExpNeeded(skill));
- expMsg.writeInt16(levelForExp(getExperience(skill)));
- }
- if (expMsg.getLength() > 2) gameHandler->sendTo(mClient, expMsg);
- mModifiedExperience.clear();
-
- if (mUpdateLevelProgress)
- {
- mUpdateLevelProgress = false;
- MessageOut progressMessage(GPMSG_LEVEL_PROGRESS);
- progressMessage.writeInt8(mLevelProgress);
- gameHandler->sendTo(mClient, progressMessage);
- }
}
void CharacterComponent::modifiedAllAttributes(Entity &entity)
@@ -350,55 +311,6 @@ void CharacterComponent::attributeChanged(Entity *entity, unsigned attr)
mModifiedAttributes.insert(attr);
}
-int CharacterComponent::expForLevel(int level)
-{
- return int(pow(level, EXPCURVE_EXPONENT) * EXPCURVE_FACTOR);
-}
-
-int CharacterComponent::levelForExp(int exp)
-{
- return int(pow(float(exp) / EXPCURVE_FACTOR, 1.0f / EXPCURVE_EXPONENT));
-}
-
-void CharacterComponent::receiveExperience(int skill, int experience, int optimalLevel)
-{
- // reduce experience when skill is over optimal level
- int levelOverOptimum = levelForExp(getExperience(skill)) - optimalLevel;
- if (optimalLevel && levelOverOptimum > 0)
- {
- experience *= EXP_LEVEL_FLEXIBILITY
- / (levelOverOptimum + EXP_LEVEL_FLEXIBILITY);
- }
-
- // Add exp
- int oldExp = mExperience[skill];
- long int newExp = mExperience[skill] + experience;
- if (newExp < 0)
- newExp = 0; // Avoid integer underflow/negative exp.
-
- // Check the skill cap
- long int maxSkillCap = Configuration::getValue("game_maxSkillCap", INT_MAX);
- assert(maxSkillCap <= INT_MAX); // Avoid integer overflow.
- if (newExp > maxSkillCap)
- {
- newExp = maxSkillCap;
- if (oldExp != maxSkillCap)
- {
- LOG_INFO("Player hit the skill cap");
- // TODO: Send a message to player letting them know they hit the cap
- // or not?
- }
- }
- mExperience[skill] = newExp;
- mModifiedExperience.insert(skill);
-
- // Inform account server
- if (newExp != oldExp)
- accountHandler->updateExperience(getDatabaseID(), skill, newExp);
-
- mRecalculateLevel = true;
-}
-
void CharacterComponent::incrementKillCount(int monsterType)
{
std::map<int, int>::iterator i = mKillCount.find(monsterType);
@@ -422,80 +334,6 @@ int CharacterComponent::getKillCount(int monsterType) const
return 0;
}
-
-void CharacterComponent::recalculateLevel(Entity &entity)
-{
- std::list<float> levels;
- std::map<int, int>::const_iterator a;
- for (a = getSkillBegin(); a != getSkillEnd(); a++)
- {
- // Only use the first 1000 skill levels in calculation
- if (a->first < 1000)
- {
- float expGot = getExpGot(a->first);
- float expNeed = getExpNeeded(a->first);
- levels.push_back(levelForExp(a->first) + expGot / expNeed);
- }
- }
- levels.sort();
-
- std::list<float>::iterator i = levels.end();
- float level = 0.0f;
- float factor = 1.0f;
- float factorSum = 0.0f;
- while (i != levels.begin())
- {
- i--;
- level += *i * factor;
- factorSum += factor;
- factor *= LEVEL_SKILL_PRECEDENCE_FACTOR;
- }
- level /= factorSum;
- level += 1.0f; // + 1.0f because the lowest level is 1 and not 0
-
- while (mLevel < level)
- {
- levelup(entity);
- }
-
- int levelProgress = int((level - floor(level)) * 100);
- if (levelProgress != mLevelProgress)
- {
- mLevelProgress = levelProgress;
- mUpdateLevelProgress = true;
- }
-}
-
-int CharacterComponent::getExpNeeded(size_t skill) const
-{
- int level = levelForExp(getExperience(skill));
- return CharacterComponent::expForLevel(level + 1) - expForLevel(level);
-}
-
-int CharacterComponent::getExpGot(size_t skill) const
-{
- int level = levelForExp(getExperience(skill));
- return mExperience.at(skill) - CharacterComponent::expForLevel(level);
-}
-
-void CharacterComponent::levelup(Entity &entity)
-{
- mLevel++;
-
- mCharacterPoints += CHARPOINTS_PER_LEVELUP;
- mCorrectionPoints += CORRECTIONPOINTS_PER_LEVELUP;
- if (mCorrectionPoints > CORRECTIONPOINTS_MAX)
- mCorrectionPoints = CORRECTIONPOINTS_MAX;
-
- MessageOut levelupMsg(GPMSG_LEVELUP);
- levelupMsg.writeInt16(mLevel);
- levelupMsg.writeInt16(mCharacterPoints);
- levelupMsg.writeInt16(mCorrectionPoints);
- gameHandler->sendTo(mClient, levelupMsg);
- LOG_INFO(entity.getComponent<BeingComponent>()->getName()
- << " reached level " << mLevel);
-}
-
AttribmodResponseCode CharacterComponent::useCharacterPoint(Entity &entity,
int attribute)
{
diff --git a/src/game-server/character.h b/src/game-server/character.h
index b5d923e6..162235ad 100644
--- a/src/game-server/character.h
+++ b/src/game-server/character.h
@@ -69,10 +69,6 @@ public:
void setCorrectionPoints(int correctionPoints);
int getCorrectionPoints() const;
- void setExperience(int skill, int level);
- void setLevel(int level) const;
- int getLevel() const;
-
int getAccountLevel() const;
void setHairStyle(int style);
@@ -82,10 +78,6 @@ public:
void setAccountLevel(int level);
- int getSkillSize() const;
- const std::map<int, int>::const_iterator getSkillBegin() const;
- const std::map<int, int>::const_iterator getSkillEnd() const;
-
void applyStatusEffect(int status, int time);
int getStatusEffectSize() const;
const std::map<int, Status>::const_iterator getStatusEffectBegin() const;
@@ -127,7 +119,7 @@ class CharacterComponent : public Component
~CharacterComponent();
/**
- * recalculates the level when necessary and calls Being::update
+ * calls Being::update and handles special recharges and status effects
*/
void update(Entity &entity);
@@ -213,9 +205,6 @@ class CharacterComponent : public Component
int getHairColor() const { return mHairColor; }
void setHairColor(int color) { mHairColor = color; }
- int getLevel() const { return mLevel; }
- void setLevel(int level) { mLevel = level; }
-
int getAccountLevel() const { return mAccountLevel; }
void setAccountLevel(int l) { mAccountLevel = l; }
@@ -258,21 +247,6 @@ class CharacterComponent : public Component
std::map< std::string, std::string > questCache;
/**
- * Gives a skill a specific amount of exp and checks if a levelup
- * occured.
- */
- void receiveExperience(int skill, int experience, int optimalLevel);
-
- int getSkillSize() const
- { return mExperience.size(); }
-
- const std::map<int, int>::const_iterator getSkillBegin() const
- { return mExperience.begin(); }
-
- const std::map<int, int>::const_iterator getSkillEnd() const
- { return mExperience.end(); }
-
- /**
* Used to serialize kill count.
*/
int getKillCountSize() const
@@ -288,18 +262,6 @@ class CharacterComponent : public Component
{ mKillCount[monsterId] = kills; }
/**
- * Gets total accumulated exp for skill.
- */
- int getExperience(int skill) const
- { return mExperience.find(skill)->second; }
-
- /**
- * Sets total accumulated exp for skill.
- */
- void setExperience(int skill, int value)
- { mExperience[skill] = 0; receiveExperience(skill, value, 0); }
-
- /**
* Adds one kill of the monster type to the characters kill count.
*/
void incrementKillCount(int monsterType);
@@ -310,16 +272,6 @@ class CharacterComponent : public Component
int getKillCount(int monsterType) const;
/**
- * Returns the exp needed to reach a specific skill level
- */
- static int expForLevel(int level);
-
- /**
- * Returns the level for a given exp
- */
- static int levelForExp(int exp);
-
- /**
* Tries to use a character point to increase a
* basic attribute
*/
@@ -395,34 +347,6 @@ class CharacterComponent : public Component
CharacterComponent(const CharacterComponent &);
CharacterComponent &operator=(const CharacterComponent &);
- static const float EXPCURVE_EXPONENT;
- static const float EXPCURVE_FACTOR;
- static const float LEVEL_SKILL_PRECEDENCE_FACTOR; // I am taking suggestions for a better name
- static const float EXP_LEVEL_FLEXIBILITY;
- static const int CHARPOINTS_PER_LEVELUP = 5;
- static const int CORRECTIONPOINTS_PER_LEVELUP = 2;
- static const int CORRECTIONPOINTS_MAX = 10;
-
- /**
- * Advances the character by one level;
- */
- void levelup(Entity &entity);
-
- /**
- * Returns the exp needed for next skill levelup
- */
- int getExpNeeded(size_t skill) const;
-
- /**
- * Returns the exp collected on this skill level
- */
- int getExpGot(size_t skill) const;
-
- /**
- * Recalculates the character level
- */
- void recalculateLevel(Entity &entity);
-
void abilityStatusChanged(int id);
void abilityCooldownActivated();
@@ -451,21 +375,14 @@ class CharacterComponent : public Component
/** Attributes modified since last update. */
std::set<size_t> mModifiedAttributes;
- std::set<size_t> mModifiedExperience;
-
- std::map<int, int> mExperience; /**< experience collected for each skill.*/
std::set<unsigned> mModifiedAbilities;
int mDatabaseID; /**< Character's database ID. */
unsigned char mHairStyle; /**< Hair Style of the character. */
unsigned char mHairColor; /**< Hair Color of the character. */
- int mLevel; /**< Level of the character. */
- int mLevelProgress; /**< progress to next level in percent */
int mCharacterPoints; /**< Unused attribute points that can be distributed */
int mCorrectionPoints; /**< Unused attribute correction points */
- bool mUpdateLevelProgress; /**< Flag raised when percent to next level changed */
- bool mRecalculateLevel; /**< Flag raised when the character level might have increased */
bool mSendAbilityCooldown;
unsigned char mAccountLevel; /**< Account level of the user. */
int mParty; /**< Party id of the character */
@@ -562,21 +479,6 @@ inline int CharacterData::getCorrectionPoints() const
return mCharacterComponent->getCorrectionPoints();
}
-inline void CharacterData::setExperience(int skill, int level)
-{
- mCharacterComponent->setExperience(skill, level);
-}
-
-inline void CharacterData::setLevel(int level) const
-{
- mCharacterComponent->setLevel(level);
-}
-
-inline int CharacterData::getLevel() const
-{
- return mCharacterComponent->getLevel();
-}
-
inline int CharacterData::getAccountLevel() const
{
return mCharacterComponent->getAccountLevel();
@@ -607,21 +509,6 @@ inline void CharacterData::setAccountLevel(int level)
mCharacterComponent->setAccountLevel(level);
}
-inline int CharacterData::getSkillSize() const
-{
- return mCharacterComponent->getSkillSize();
-}
-
-inline const std::map<int, int>::const_iterator CharacterData::getSkillBegin() const
-{
- return mCharacterComponent->getSkillBegin();
-}
-
-inline const std::map<int, int>::const_iterator CharacterData::getSkillEnd() const
-{
- return mCharacterComponent->getSkillEnd();
-}
-
inline void CharacterData::applyStatusEffect(int status, int time)
{
mEntity->getComponent<BeingComponent>()->applyStatusEffect(status, time);
diff --git a/src/game-server/commandhandler.cpp b/src/game-server/commandhandler.cpp
index e54b9eaf..3cdb2f43 100644
--- a/src/game-server/commandhandler.cpp
+++ b/src/game-server/commandhandler.cpp
@@ -80,7 +80,6 @@ static void handleLogsay(Entity*, std::string&);
static void handleKillMonsters(Entity*, std::string&);
static void handleCraft(Entity*, std::string&);
static void handleGetPos(Entity*, std::string&);
-static void handleSkills(Entity*, std::string&);
static void handleEffect(Entity*, std::string&);
static void handleGiveAbility(Entity*, std::string&);
static void handleTakeAbility(Entity*, std::string&);
@@ -147,8 +146,6 @@ static CmdRef const cmdRef[] =
"Crafts something.", &handleCraft},
{"getpos", "<character>",
"Gets the position of a character.", &handleGetPos},
- {"skills", "<character>",
- "Lists all skills and their values of a character", &handleSkills},
{"effect", "<effectid> <x> <y> / <effectid> <being> / <effectid>",
"Shows an effect at the given position or on the given being. "
"The player's character is targeted if neither of them is provided.",
@@ -1516,52 +1513,6 @@ static void handleGetPos(Entity *player, std::string &args)
say(str.str(), player);
}
-static void handleSkills(Entity *player, std::string &args)
-{
- std::string character = getArgument(args);
- if (character.empty())
- {
- say("Invalid amount of arguments given.", player);
- say("Usage: @skills <character>", player);
- return;
- }
- Entity *other;
- if (character == "#")
- other = player;
- else
- other = gameHandler->getCharacterByNameSlow(character);
- if (!other)
- {
- say("Invalid character, or player is offline.", player);
- return;
- }
-
-
- auto *characterComponent =
- player->getComponent<CharacterComponent>();
-
- say("List of skills of player '" +
- other->getComponent<BeingComponent>()->getName() + "':", player);
- std::map<int, int>::const_iterator it =
- characterComponent->getSkillBegin();
- std::map<int, int>::const_iterator it_end =
- characterComponent->getSkillEnd();
-
- if (it == it_end)
- {
- say("No skills available.", player);
- return;
- }
-
- while (it != it_end)
- {
- std::stringstream str;
- str << "Id: " << it->first << " value: " << it->second;
- say(str.str(), player);
- ++it;
- }
-}
-
static void handleEffect(Entity *player, std::string &args)
{
std::vector<std::string> arguments;
diff --git a/src/game-server/itemmanager.cpp b/src/game-server/itemmanager.cpp
index 0362c5d9..bcb64072 100644
--- a/src/game-server/itemmanager.cpp
+++ b/src/game-server/itemmanager.cpp
@@ -24,7 +24,6 @@
#include "common/resourcemanager.h"
#include "game-server/attributemanager.h"
#include "game-server/item.h"
-#include "game-server/skillmanager.h"
#include "scripting/script.h"
#include "scripting/scriptmanager.h"
#include "utils/logger.h"
diff --git a/src/game-server/main-game.cpp b/src/game-server/main-game.cpp
index 7d053bf9..7b78bc21 100644
--- a/src/game-server/main-game.cpp
+++ b/src/game-server/main-game.cpp
@@ -30,7 +30,6 @@
#include "game-server/itemmanager.h"
#include "game-server/mapmanager.h"
#include "game-server/monstermanager.h"
-#include "game-server/skillmanager.h"
#include "game-server/abilitymanager.h"
#include "game-server/statusmanager.h"
#include "game-server/postman.h"
@@ -82,7 +81,6 @@ AbilityManager *abilityManager = new AbilityManager();
AttributeManager *attributeManager = new AttributeManager();
ItemManager *itemManager = new ItemManager();
MonsterManager *monsterManager = new MonsterManager();
-SkillManager *skillManager = new SkillManager();
EmoteManager *emoteManager = new EmoteManager();
SettingsManager *settingsManager = new SettingsManager(DEFAULT_SETTINGS_FILE);
diff --git a/src/game-server/monster.h b/src/game-server/monster.h
index ae798efc..e50f7451 100644
--- a/src/game-server/monster.h
+++ b/src/game-server/monster.h
@@ -67,7 +67,6 @@ class MonsterClass
mGender(GENDER_UNSPECIFIED),
mSpeed(1),
mSize(16),
- mExp(-1),
mMutation(0),
mOptimalLevel(0)
{}
@@ -118,18 +117,6 @@ class MonsterClass
/** Returns collision circle radius. */
int getSize() const { return mSize; }
- /** Sets experience reward for killing the monster. */
- void setExp(int exp) { mExp = exp; }
-
- /** Returns experience reward for killing the monster. */
- int getExp() const { return mExp; }
-
- /** Gets maximum skill level after which exp reward is reduced */
- void setOptimalLevel(int level) { mOptimalLevel = level; }
-
- /** Sets maximum skill level after which exp reward is reduced. */
- int getOptimalLevel() const { return mOptimalLevel; }
-
/** Sets mutation factor in percent. */
void setMutation(unsigned factor) { mMutation = factor; }
@@ -155,7 +142,6 @@ class MonsterClass
std::set<AbilityManager::AbilityInfo *> mAbilities;
float mSpeed; /**< The monster class speed in tiles per second */
int mSize;
- int mExp;
int mMutation;
int mOptimalLevel;
diff --git a/src/game-server/monstermanager.cpp b/src/game-server/monstermanager.cpp
index 0043cdb4..327c5c10 100644
--- a/src/game-server/monstermanager.cpp
+++ b/src/game-server/monstermanager.cpp
@@ -216,22 +216,9 @@ void MonsterManager::readMonsterNode(xmlNodePtr node, const std::string &filenam
monster->addAbility(info);
}
- else if (xmlStrEqual(subnode->name, BAD_CAST "exp"))
- {
- xmlChar *exp = subnode->xmlChildrenNode->content;
- monster->setExp(atoi((const char*)exp));
- monster->setOptimalLevel(XML::getProperty(subnode, "level", 0));
- }
}
monster->setDrops(drops);
- if (monster->getExp() == -1)
- {
- LOG_WARN(filename
- << ": No experience defined for monster Id:" << monsterId
- << " (" << name << ")");
- monster->setExp(0);
- }
}
/**
diff --git a/src/game-server/settingsmanager.cpp b/src/game-server/settingsmanager.cpp
index 75aea3ce..29c4f214 100644
--- a/src/game-server/settingsmanager.cpp
+++ b/src/game-server/settingsmanager.cpp
@@ -27,7 +27,6 @@
#include "game-server/abilitymanager.h"
#include "game-server/attributemanager.h"
-#include "game-server/skillmanager.h"
#include "game-server/itemmanager.h"
#include "game-server/mapmanager.h"
#include "game-server/monstermanager.h"
@@ -44,7 +43,6 @@ void SettingsManager::initialize()
// initialize all managers in correct order
MapManager::initialize();
attributeManager->initialize();
- skillManager->initialize();
abilityManager->initialize();
itemManager->initialize();
monsterManager->initialize();
@@ -65,7 +63,6 @@ void SettingsManager::reload()
{
MapManager::reload();
attributeManager->reload();
- skillManager->reload();
abilityManager->reload();
itemManager->reload();
monsterManager->reload();
@@ -138,11 +135,6 @@ void SettingsManager::loadFile(const std::string &filename)
// attribute config
attributeManager->readAttributeNode(childNode);
}
- else if (xmlStrEqual(childNode->name, BAD_CAST "skill-set"))
- {
- // skills config
- skillManager->readSkillSetNode(childNode, filename);
- }
else if (xmlStrEqual(childNode->name, BAD_CAST "ability-category"))
{
// ability config
@@ -191,7 +183,6 @@ void SettingsManager::checkStatus()
{
MapManager::checkStatus();
attributeManager->checkStatus();
- skillManager->checkStatus();
abilityManager->checkStatus();
itemManager->checkStatus();
monsterManager->checkStatus();
diff --git a/src/game-server/skillmanager.cpp b/src/game-server/skillmanager.cpp
deleted file mode 100644
index 8ebe18f2..00000000
--- a/src/game-server/skillmanager.cpp
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * The Mana Server
- * Copyright (C) 2004-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/>.
- */
-
-#include "game-server/skillmanager.h"
-
-#include "utils/logger.h"
-
-#include <map>
-
-void SkillManager::clear()
-{
- for (SkillsInfo::iterator it = mSkillsInfo.begin(),
- it_end = mSkillsInfo.end(); it != it_end; ++it)
- {
- delete it->second;
- }
-
- mSkillsInfo.clear();
- mNamedSkillsInfo.clear();
- mDefaultSkillId = 0;
-}
-
-void SkillManager::initialize()
-{
- clear();
-}
-
-void SkillManager::reload()
-{
- initialize();
-}
-
-/**
- * Read a <skill-set> element from settings.
- * Used by SettingsManager.
- */
-void SkillManager::readSkillSetNode(xmlNodePtr node, const std::string& filename)
-{
- std::string setName = XML::getProperty(node, "name", std::string());
- if (setName.empty())
- {
- LOG_WARN("The " << filename << " file is containing unamed <skill-set> "
- "tags and will be ignored.");
- return;
- }
-
- setName = utils::toLower(setName);
-
- for_each_xml_child_node(skillNode, node)
- {
- if (xmlStrEqual(skillNode->name, BAD_CAST "skill")) {
- readSkillNode(skillNode, setName);
- }
- }
-}
-
-/**
- * Check the status of recently loaded configuration.
- */
-void SkillManager::checkStatus()
-{
- printDebugSkillTable();
-
- if (!mDefaultSkillId)
- LOG_WARN("SkillManager: No default weapon-type id was given during "
- "Skill map loading. "
- "Players won't be able to earn XP when unarmed.");
-
- LOG_INFO("Loaded " << mSkillsInfo.size() << " skills");
-}
-
-void SkillManager::readSkillNode(xmlNodePtr skillNode,
- const std::string& setName)
-{
- if (!xmlStrEqual(skillNode->name, BAD_CAST "skill"))
- return;
-
- SkillInfo *skillInfo = new SkillInfo;
- skillInfo->setName = setName;
- skillInfo->skillName = utils::toLower(
- XML::getProperty(skillNode, "name", std::string()));
- int id = XML::getProperty(skillNode, "id", 0);
-
- if (id <= 0 || skillInfo->skillName.empty())
- {
- LOG_WARN("Invalid skill (empty name or id <= 0) in set: " << setName);
- return;
- }
- skillInfo->id = (unsigned)id;
-
- SkillsInfo::iterator it = mSkillsInfo.find(skillInfo->id);
- if (it != mSkillsInfo.end())
- {
- LOG_WARN("SkillManager: The same id: " << skillInfo->id
- << " is given for skill names: " << it->first
- << " and " << skillInfo->skillName);
- LOG_WARN("The skill reference: " << skillInfo->id
- << ": '" << skillInfo->skillName << "' will be ignored.");
- return;
- }
-
- if (XML::getBoolProperty(skillNode, "default", false))
- {
- if (mDefaultSkillId)
- {
- LOG_WARN("SkillManager: "
- "Default Skill id already defined as "
- << mDefaultSkillId
- << ". Redefinit it as: " << skillInfo->id);
- }
- else
- {
- LOG_INFO("SkillManager: Defining skill id: " << skillInfo->id
- << " as default weapon-type id.");
- }
- mDefaultSkillId = skillInfo->id;
- }
-
- mSkillsInfo.insert(std::make_pair(skillInfo->id, skillInfo));
-
- std::string keyName = setName + "_" + skillInfo->skillName;
- mNamedSkillsInfo.insert(keyName, skillInfo);
-}
-
-void SkillManager::printDebugSkillTable()
-{
- if (::utils::Logger::mVerbosity >= ::utils::Logger::Debug)
- {
- std::string lastSet;
- LOG_DEBUG("Skill map:"
- << std::endl << "-----");
- for (SkillsInfo::iterator it = mSkillsInfo.begin();
- it != mSkillsInfo.end(); ++it)
- {
- if (!lastSet.compare(it->second->setName))
- {
- lastSet = it->second->setName;
- LOG_DEBUG("Skill set: " << lastSet);
- }
-
- if (it->first == mDefaultSkillId)
- {
- LOG_DEBUG("'" << it->first << "': " << it->second->skillName
- << " (Default)");
- }
- else
- {
- LOG_DEBUG("'" << it->first << "': " << it->second->skillName);
- }
- }
- LOG_DEBUG("-----");
- }
-}
-
-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 SkillManager::getId(const std::string &skillName) const
-{
- SkillInfo *skillInfo = mNamedSkillsInfo.value(skillName);
- return skillInfo ? skillInfo->id : 0;
-}
-
-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 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
deleted file mode 100644
index 12828fe4..00000000
--- a/src/game-server/skillmanager.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * The Mana Server
- * Copyright (C) 2004-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 SKILLMANAGER_H
-#define SKILLMANAGER_H
-
-#include "utils/string.h"
-#include "utils/xml.h"
-
-class SkillManager
-{
- public:
- SkillManager():
- mDefaultSkillId(0)
- {}
-
- ~SkillManager()
- { clear(); }
-
- /**
- * Loads skill reference file.
- */
- void initialize();
-
- /**
- * Reloads skill reference file.
- */
- void reload();
-
- /**
- * Gets the skill Id from a set and a skill string.
- */
- 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 getId(const std::string &skillName) const;
-
- const std::string getSkillName(unsigned id) const;
- const std::string getSetName(unsigned id) const;
-
- bool exists(unsigned id) const;
-
- unsigned getDefaultSkillId() const
- { return mDefaultSkillId; }
-
- void readSkillSetNode(xmlNodePtr node, const std::string &filename);
-
- void checkStatus();
-
- private:
- struct SkillInfo {
- SkillInfo():
- id(0)
- {}
-
- unsigned id;
- std::string setName;
- std::string skillName;
- };
-
- /*
- * Clears up the skill maps.
- */
- void clear();
-
- void printDebugSkillTable();
-
- void readSkillNode(xmlNodePtr skillNode, const std::string& setName);
-
- // The skill map
- 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 mDefaultSkillId;
-};
-
-extern SkillManager *skillManager;
-
-#endif // SKILLMANAGER_H
diff --git a/src/scripting/lua.cpp b/src/scripting/lua.cpp
index a76c9399..624fbda1 100644
--- a/src/scripting/lua.cpp
+++ b/src/scripting/lua.cpp
@@ -1878,95 +1878,6 @@ static int entity_set_gender(lua_State *s)
return 0;
}
-/** LUA entity:level (being)
- * entity:level()
- * entity:level(int skill_id)
- * entity:level(string skill_name)
- **
- * Valid only for character entities.
- *
- * **Return value:** Returns the level of the character. If a skill is passed
- * (either by name or id) the level of this skill is returned.
- *
- * **Note:** If the skill is provided as string (`skill_name`) you have to
- * use this format: &lt;setname&gt;_&lt;skillname&gt;. So for example: "Weapons_Unarmed".
- */
-static int entity_get_level(lua_State *s)
-{
- Entity *ch = checkCharacter(s, 1);
- auto *characterComponent = ch->getComponent<CharacterComponent>();
- if (lua_gettop(s) > 1)
- {
- int skillId = checkSkill(s, 2);
- lua_pushinteger(s, characterComponent->levelForExp(
- characterComponent->getExperience(skillId)));
- }
- else
- {
- lua_pushinteger(s, characterComponent->getLevel());
- }
- return 1;
-}
-
-/** LUA entity:xp (being)
- * entity:xp(int skill_id)
- * entity:xp(string skill_name)
- **
- * Valid only for character entities.
- *
- * **Return value:** The total experience collected by the character in
- * `skill`.
- *
- * If the skill is provided as string (`skillname`) you have to use this
- * format: &lt;setname&gt;_&lt;skillname&gt;. So for example: "Weapons_Unarmed".
- */
-static int entity_get_xp(lua_State *s)
-{
- Entity *c = checkCharacter(s, 1);
- int skill = checkSkill(s, 2);
- const int exp = c->getComponent<CharacterComponent>()->getExperience(skill);
-
- lua_pushinteger(s, exp);
- return 1;
-}
-
-/** LUA entity:give_xp (being)
- * entity:give_xp(int skill, int amount [, int optimalLevel])
- * entity:give_xp(string skillname, int amount [, int optimalLevel])
- **
- * Valid only for character entities.
- *
- * Gives the character `amount` experience in skill `skill`. When an
- * optimal level is set (over 0), the experience is reduced when the characters
- * skill level is beyond this. If the skill is provided as string
- * (`skillname`) you have to use this format: &lt;setname&gt;_&lt;skillname&gt;.
- * So for example: "Weapons_Unarmed".
- */
-static int entity_give_xp(lua_State *s)
-{
- Entity *c = checkCharacter(s, 1);
- int skill = checkSkill(s, 2);
- const int exp = luaL_checkint(s, 3);
- const int optimalLevel = luaL_optint(s, 4, 0);
-
- c->getComponent<CharacterComponent>()->receiveExperience(skill, exp,
- optimalLevel);
- return 0;
-}
-
-/** LUA xp_for_level (being)
- * xp_for_level(int level)
- **
- * **Return value:** Returns the total experience necessary (counted from
- * level 0) for reaching `level` in any skill.
- */
-static int xp_for_level(lua_State *s)
-{
- const int level = luaL_checkint(s, 1);
- lua_pushinteger(s, CharacterComponent::expForLevel(level));
- return 1;
-}
-
/** LUA entity:add_hit_taken (being)
* add_hit_taken(int damage)
**
@@ -3374,7 +3285,6 @@ LuaScript::LuaScript():
{ "getvar_world", getvar_world },
{ "setvar_world", setvar_world },
{ "chr_get_post", chr_get_post },
- { "xp_for_level", xp_for_level },
{ "monster_create", monster_create },
{ "trigger_create", trigger_create },
{ "get_beings_in_circle", get_beings_in_circle },
@@ -3442,9 +3352,6 @@ LuaScript::LuaScript():
{ "remove_attribute_modifier", entity_remove_attribute_modifier },
{ "gender", entity_get_gender },
{ "set_gender", entity_set_gender },
- { "level", entity_get_level },
- { "xp", entity_get_xp },
- { "give_xp", entity_give_xp },
{ "hair_color", entity_get_hair_color },
{ "set_hair_color", entity_set_hair_color },
{ "hair_style", entity_get_hair_style },
diff --git a/src/scripting/luautil.cpp b/src/scripting/luautil.cpp
index 8d166469..c9738694 100644
--- a/src/scripting/luautil.cpp
+++ b/src/scripting/luautil.cpp
@@ -28,7 +28,6 @@
#include "game-server/monster.h"
#include "game-server/monstermanager.h"
#include "game-server/npc.h"
-#include "game-server/skillmanager.h"
#include "utils/logger.h"
@@ -215,16 +214,6 @@ Entity *checkNpc(lua_State *s, int p)
return entity;
}
-int checkSkill(lua_State *s, int p)
-{
- if (lua_isnumber(s, p))
- return luaL_checkint(s, p);
-
- int id = skillManager->getId(luaL_checkstring(s, p));
- luaL_argcheck(s, id != 0, p, "invalid skill name");
- return id;
-}
-
AbilityManager::AbilityInfo *checkAbility(lua_State *s, int p)
{
AbilityManager::AbilityInfo *abilityInfo;
diff --git a/src/scripting/luautil.h b/src/scripting/luautil.h
index fc198310..220d4c2f 100644
--- a/src/scripting/luautil.h
+++ b/src/scripting/luautil.h
@@ -178,7 +178,6 @@ ItemClass * checkItemClass(lua_State *s, int p);
Entity * checkMonster(lua_State *s, int p);
MonsterClass * checkMonsterClass(lua_State *s, int p);
Entity * checkNpc(lua_State *s, int p);
-int checkSkill(lua_State *s, int p);
AbilityManager::AbilityInfo * checkAbility(lua_State *s, int p);
const AttributeManager::AttributeInfo *checkAttribute(lua_State *s, int p);
unsigned char checkWalkMask(lua_State *s, int p);
diff --git a/src/serialize/characterdata.h b/src/serialize/characterdata.h
index ada7e252..a8554684 100644
--- a/src/serialize/characterdata.h
+++ b/src/serialize/characterdata.h
@@ -38,7 +38,6 @@ void serializeCharacterData(const T &data, MessageOut &msg)
msg.writeInt8(data.getGender());
msg.writeInt8(data.getHairStyle());
msg.writeInt8(data.getHairColor());
- msg.writeInt16(data.getLevel());
msg.writeInt16(data.getCharacterPoints());
msg.writeInt16(data.getCorrectionPoints());
@@ -52,16 +51,6 @@ void serializeCharacterData(const T &data, MessageOut &msg)
msg.writeDouble(attributeIt.second.getModifiedAttribute());
}
- // character skills
- msg.writeInt16(data.getSkillSize());
-
- std::map<int, int>::const_iterator skill_it;
- for (skill_it = data.getSkillBegin(); skill_it != data.getSkillEnd() ; skill_it++)
- {
- msg.writeInt16(skill_it->first);
- msg.writeInt32(skill_it->second);
- }
-
// status effects currently affecting the character
msg.writeInt16(data.getStatusEffectSize());
std::map<int, Status>::const_iterator status_it;
@@ -126,7 +115,6 @@ void deserializeCharacterData(T &data, MessageIn &msg)
data.setGender(ManaServ::getGender(msg.readInt8()));
data.setHairStyle(msg.readInt8());
data.setHairColor(msg.readInt8());
- data.setLevel(msg.readInt16());
data.setCharacterPoints(msg.readInt16());
data.setCorrectionPoints(msg.readInt16());
@@ -141,16 +129,6 @@ void deserializeCharacterData(T &data, MessageIn &msg)
data.setModAttribute(id, mod);
}
- // character skills
- int skillSize = msg.readInt16();
-
- for (int i = 0; i < skillSize; ++i)
- {
- int skill = msg.readInt16();
- int level = msg.readInt32();
- data.setExperience(skill,level);
- }
-
// status effects currently affecting the character
int statusSize = msg.readInt16();
diff --git a/src/sql/mysql/createTables.sql b/src/sql/mysql/createTables.sql
index 212d4812..50fdae90 100644
--- a/src/sql/mysql/createTables.sql
+++ b/src/sql/mysql/createTables.sql
@@ -33,7 +33,6 @@ CREATE TABLE IF NOT EXISTS `mana_characters` (
`gender` tinyint(3) unsigned NOT NULL,
`hair_style` tinyint(3) unsigned NOT NULL,
`hair_color` tinyint(3) unsigned NOT NULL,
- `level` tinyint(3) unsigned NOT NULL,
`char_pts` smallint(5) unsigned NOT NULL,
`correct_pts` smallint(5) unsigned NOT NULL,
-- location on the map
@@ -70,21 +69,6 @@ CREATE TABLE IF NOT EXISTS `mana_char_attr` (
DEFAULT CHARSET=utf8;
--
--- table: `mana_char_skills`
---
-CREATE TABLE IF NOT EXISTS `mana_char_skills` (
- `char_id` int(10) unsigned NOT NULL,
- `skill_id` smallint(5) unsigned NOT NULL,
- `skill_exp` smallint(5) unsigned NOT NULL,
- --
- PRIMARY KEY (`char_id`, `skill_id`),
- FOREIGN KEY (`char_id`)
- REFERENCES `mana_characters` (`id`)
- ON DELETE CASCADE
-) ENGINE=InnoDB
-DEFAULT CHARSET=utf8;
-
---
-- table: `mana_char_status_effects`
--
CREATE TABLE IF NOT EXISTS `mana_char_status_effects` (
@@ -417,7 +401,6 @@ AS
c.user_id as user_id,
c.name as name,
c.gender as gender,
- c.level as level,
c.map_id as map_id
FROM mana_online_list l
JOIN mana_characters c
@@ -438,7 +421,7 @@ AUTO_INCREMENT=0 ;
INSERT INTO mana_world_states VALUES('accountserver_startup',-1,'0', NOW());
INSERT INTO mana_world_states VALUES('accountserver_version',-1,'0', NOW());
-INSERT INTO mana_world_states VALUES('database_version', -1,'22', NOW());
+INSERT INTO mana_world_states VALUES('database_version', -1,'23', NOW());
-- all known transaction codes
@@ -475,7 +458,6 @@ INSERT INTO mana_transaction_codes VALUES ( 30, 'Trade items', 'Act
INSERT INTO mana_transaction_codes VALUES ( 31, 'Attribute increased', 'Character' );
INSERT INTO mana_transaction_codes VALUES ( 32, 'Attribute decreased', 'Character' );
INSERT INTO mana_transaction_codes VALUES ( 33, 'Command MUTE', 'Commands' );
-INSERT INTO mana_transaction_codes VALUES ( 34, 'Command EXP', 'Commands' );
INSERT INTO mana_transaction_codes VALUES ( 35, 'Command INVISIBLE', 'Commands' );
INSERT INTO mana_transaction_codes VALUES ( 36, 'Command COMBAT', 'Commands' );
INSERT INTO mana_transaction_codes VALUES ( 37, 'Command ANNOUNCE', 'Commands' );
diff --git a/src/sql/mysql/updates/update_22_to_23.sql b/src/sql/mysql/updates/update_22_to_23.sql
new file mode 100644
index 00000000..c4affaed
--- /dev/null
+++ b/src/sql/mysql/updates/update_22_to_23.sql
@@ -0,0 +1,15 @@
+START TRANSACTION;
+
+-- There is no way to convert all your skills to attributes. You will have to
+-- do this manually.
+
+ALTER TABLE mana_characters DROP COLUMN level;
+
+-- Update database version.
+UPDATE mana_world_states
+ SET value = '23',
+ moddate = UNIX_TIMESTAMP()
+ WHERE state_name = 'database_version';
+
+COMMIT;
+
diff --git a/src/sql/sqlite/createTables.sql b/src/sql/sqlite/createTables.sql
index aaf18efc..72a70090 100644
--- a/src/sql/sqlite/createTables.sql
+++ b/src/sql/sqlite/createTables.sql
@@ -51,7 +51,6 @@ CREATE TABLE mana_characters
gender INTEGER NOT NULL,
hair_style INTEGER NOT NULL,
hair_color INTEGER NOT NULL,
- level INTEGER NOT NULL,
char_pts INTEGER NOT NULL,
correct_pts INTEGER NOT NULL,
x INTEGER NOT NULL,
@@ -81,19 +80,6 @@ CREATE INDEX mana_char_attr_char ON mana_char_attr ( char_id );
-----------------------------------------------------------------------------
-CREATE TABLE mana_char_skills
-(
- char_id INTEGER NOT NULL,
- skill_id INTEGER NOT NULL,
- skill_exp INTEGER NOT NULL,
- --
- FOREIGN KEY (char_id) REFERENCES mana_characters(id)
-);
-
-CREATE INDEX mana_char_skills_char ON mana_char_skills ( char_id );
-
------------------------------------------------------------------------------
-
CREATE TABLE mana_char_status_effects
(
char_id INTEGER NOT NULL,
@@ -387,7 +373,6 @@ AS
c.user_id as user_id,
c.name as name,
c.gender as gender,
- c.level as level,
c.map_id as map_id
FROM mana_online_list l
JOIN mana_characters c
@@ -424,7 +409,7 @@ AS
INSERT INTO mana_world_states VALUES('accountserver_startup',-1,'0', strftime('%s','now'));
INSERT INTO mana_world_states VALUES('accountserver_version',-1,'0', strftime('%s','now'));
-INSERT INTO mana_world_states VALUES('database_version', -1,'22', strftime('%s','now'));
+INSERT INTO mana_world_states VALUES('database_version', -1,'23', strftime('%s','now'));
-- all known transaction codes
@@ -461,7 +446,6 @@ INSERT INTO mana_transaction_codes VALUES ( 30, 'Trade items', 'Act
INSERT INTO mana_transaction_codes VALUES ( 31, 'Attribute increased', 'Character' );
INSERT INTO mana_transaction_codes VALUES ( 32, 'Attribute decreased', 'Character' );
INSERT INTO mana_transaction_codes VALUES ( 33, 'Command MUTE', 'Commands' );
-INSERT INTO mana_transaction_codes VALUES ( 34, 'Command EXP', 'Commands' );
INSERT INTO mana_transaction_codes VALUES ( 35, 'Command INVISIBLE', 'Commands' );
INSERT INTO mana_transaction_codes VALUES ( 36, 'Command COMBAT', 'Commands' );
INSERT INTO mana_transaction_codes VALUES ( 37, 'Command ANNOUNCE', 'Commands' );
diff --git a/src/sql/sqlite/updates/update_22_to_23.sql b/src/sql/sqlite/updates/update_22_to_23.sql
new file mode 100644
index 00000000..7172b56f
--- /dev/null
+++ b/src/sql/sqlite/updates/update_22_to_23.sql
@@ -0,0 +1,58 @@
+BEGIN;
+
+-- There is no way to convert all your skills to attributes. You will have to
+-- do this manually.
+
+CREATE TABLE mana_characters_backup
+(
+ id INTEGER PRIMARY KEY,
+ user_id INTEGER NOT NULL,
+ name TEXT NOT NULL UNIQUE,
+ gender INTEGER NOT NULL,
+ hair_style INTEGER NOT NULL,
+ hair_color INTEGER NOT NULL,
+ char_pts INTEGER NOT NULL,
+ correct_pts INTEGER NOT NULL,
+ x INTEGER NOT NULL,
+ y INTEGER NOT NULL,
+ map_id INTEGER NOT NULL,
+ slot INTEGER NOT NULL,
+ --
+ FOREIGN KEY (user_id) REFERENCES mana_accounts(id)
+);
+
+INSERT INTO mana_characters_backup SELECT
+ id, user_id, name, gender, hair_style, hair_color, char_pts, correct_pts,
+ x, y, map_id, slot FROM mana_characters;
+
+DROP TABLE mana_characters;
+
+CREATE TABLE mana_characters
+(
+ id INTEGER PRIMARY KEY,
+ user_id INTEGER NOT NULL,
+ name TEXT NOT NULL UNIQUE,
+ gender INTEGER NOT NULL,
+ hair_style INTEGER NOT NULL,
+ hair_color INTEGER NOT NULL,
+ char_pts INTEGER NOT NULL,
+ correct_pts INTEGER NOT NULL,
+ x INTEGER NOT NULL,
+ y INTEGER NOT NULL,
+ map_id INTEGER NOT NULL,
+ slot INTEGER NOT NULL,
+ --
+ FOREIGN KEY (user_id) REFERENCES mana_accounts(id)
+);
+
+INSERT INTO mana_characters SELECT * FROM mana_characters_backup;
+DROP TABLE mana_characters_backup;
+
+-- Update the database version, and set date of update
+UPDATE mana_world_states
+ SET value = '23',
+ moddate = strftime('%s','now')
+ WHERE state_name = 'database_version';
+
+END;
+