void Character::sendStatus() { MessageOut attribMsg(GPMSG_PLAYER_ATTRIBUTE_CHANGE); for (std::set<size_t>::const_iterator i = mModifiedAttributes.begin(), i_end = mModifiedAttributes.end(); i != i_end; ++i) { int attr = *i; attribMsg.writeInt16(attr); attribMsg.writeInt32(getAttribute(attr) * 256); attribMsg.writeInt32(getModifiedAttribute(attr) * 256); } if (attribMsg.getLength() > 2) gameHandler->sendTo(this, 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(this, expMsg); mModifiedExperience.clear(); if (mUpdateLevelProgress) { mUpdateLevelProgress = false; MessageOut progressMessage(GPMSG_LEVEL_PROGRESS); progressMessage.writeInt8(mLevelProgress); gameHandler->sendTo(this, progressMessage); } }
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; } }
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; }
int CharacterComponent::getExpGot(size_t skill) const { int level = levelForExp(getExperience(skill)); return mExperience.at(skill) - CharacterComponent::expForLevel(level); }
int CharacterComponent::getExpNeeded(size_t skill) const { int level = levelForExp(getExperience(skill)); return CharacterComponent::expForLevel(level + 1) - expForLevel(level); }