bool Character::recalculateBaseAttribute(unsigned int attr) { /* * `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; default: return Being::recalculateBaseAttribute(attr); } if (newBase != getAttribute(attr)) { setAttribute(attr, newBase); updateDerivedAttributes(attr); return true; } LOG_DEBUG("No changes to sync for attribute '" << attr << "'."); return false; }
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); } }
bool Attribute::add(unsigned short duration, double value, unsigned layer, int id) { assert(mMods.size() > layer); 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) , id)) { while (++layer < mMods.size()) { if (!mMods.at(layer)->recalculateModifiedValue( mMods.at(layer - 1)->getCachedModifiedValue())) { LOG_DEBUG("Modifier added, but modified value not changed."); return false; } } LOG_DEBUG("Modifier added. Base value: " << mBase << ", new modified " "value: " << getModifiedAttribute() << "."); return true; } LOG_DEBUG("Failed to add modifier!"); return false; }
void Character::flagAttribute(int attr) { // Inform the client of this attribute modification. accountHandler->updateAttributes(getDatabaseID(), attr, getAttribute(attr), getModifiedAttribute(attr)); mModifiedAttributes.insert(attr); }
void Monster::processAttack() { if (!mTarget) { setAction(STAND); return; } if (!mCurrentAttack) return; mAttackTimeout.set(mCurrentAttack->aftDelay + mCurrentAttack->preDelay); float damageFactor = mCurrentAttack->damageFactor; Damage dmg; dmg.skill = 0; dmg.base = getModifiedAttribute(MOB_ATTR_PHY_ATK_MIN) * damageFactor; dmg.delta = getModifiedAttribute(MOB_ATTR_PHY_ATK_DELTA) * damageFactor; dmg.cth = getModifiedAttribute(ATTR_ACCURACY); dmg.element = mCurrentAttack->element; dmg.range = mCurrentAttack->range; int hit = performAttack(mTarget, dmg); if (!mCurrentAttack->scriptEvent.empty() && hit > -1) { Script::Ref function = mSpecy->getEventCallback(mCurrentAttack->scriptEvent); if (function.isValid()) { Script *script = ScriptManager::currentState(); script->setMap(getMap()); script->prepare(function); script->push(this); script->push(mTarget); script->push(hit); script->execute(); } } }
void Character::processAttacks() { // Ticks attacks even when not attacking to permit cooldowns and warmups. std::list<AutoAttack> attacksReady; mAutoAttacks.tick(&attacksReady); if (mAction != ATTACK || !mTarget) { mAutoAttacks.stop(); return; } // Deal with the ATTACK action. // Install default bare knuckle attack if no attacks were added from config. // TODO: Get this from configuration. if (!mAutoAttacks.getAutoAttacksNumber()) { int damageBase = getModifiedAttribute(ATTR_STR); int damageDelta = damageBase / 2; Damage knuckleDamage; knuckleDamage.skill = skillManager->getDefaultSkillId(); knuckleDamage.base = damageBase; knuckleDamage.delta = damageDelta; knuckleDamage.cth = 2; knuckleDamage.element = ELEMENT_NEUTRAL; knuckleDamage.type = DAMAGE_PHYSICAL; knuckleDamage.range = (getSize() < DEFAULT_TILE_LENGTH) ? DEFAULT_TILE_LENGTH : getSize(); AutoAttack knuckleAttack(knuckleDamage, 7, 3); mAutoAttacks.add(knuckleAttack); } if (attacksReady.empty()) { if (!mAutoAttacks.areActive()) mAutoAttacks.start(); } else { // Performs all ready attacks. for (std::list<AutoAttack>::iterator it = attacksReady.begin(); it != attacksReady.end(); ++it) { performAttack(mTarget, it->getDamage()); } } }
void Character::recalculateBaseAttribute(unsigned attr) { // `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; if (attr == ATTR_STR && mKnuckleAttackInfo) { // TODO: dehardcode this Damage &knuckleDamage = mKnuckleAttackInfo->getDamage(); knuckleDamage.base = getModifiedAttribute(ATTR_STR); knuckleDamage.delta = knuckleDamage.base / 2; } Being::recalculateBaseAttribute(attr); }
uint16_t Player::getModifiedMinDamage() const { uint16_t inventoryMinDamage = getModifiedAttribute( inventory, this, 0, &getItemMinDamageHelper, &getSpellMinDamageHelper, NON_NULLABLE_ATTRIBUTE_MIN ); return inventoryMinDamage; }
uint16_t Player::getModifiedSpellEffectElementModifierPoints( ElementType::ElementType elementType ) const { return getModifiedAttribute( elementType, inventory, this, getSpellEffectElementModifierPoints( elementType ) + getSpellEffectAllModifierPoints(), &getItemSpellEffectElementModifierPointsHelper, &getSpellSpellEffectElementModifierPointsHelper, NULLABLE_ATTRIBUTE_MIN ) + StatsSystem::getStatsSystem()->calculateSpellEffectElementModifierPoints( elementType, this ); }
uint16_t Player::getModifiedSpellCriticalModifierPoints() const { return getModifiedAttribute( inventory, this, getSpellCriticalModifierPoints(), &getItemSpellCriticalModifierPointsHelper, &getSpellSpellCriticalModifierPointsHelper, NULLABLE_ATTRIBUTE_MIN ) + StatsSystem::getStatsSystem()->calculateSpellCriticalModifierPoints( this ); }
uint16_t Player::getModifiedFatigueRegen() const { return getModifiedAttribute( inventory, this, getFatigueRegen(), &getItemFatigueRegenHelper, &getSpellFatigueRegenHelper, NULLABLE_ATTRIBUTE_MIN ); }
uint16_t Player::getModifiedArmor() const { return getModifiedAttribute( inventory, this, getArmor(), &getItemArmorHelper, &getSpellArmorHelper, NULLABLE_ATTRIBUTE_MIN ) + StatsSystem::getStatsSystem()->calculateDamageReductionPoints( this ); }
uint16_t Player::getModifiedMaxDamage() const { uint16_t inventoryMaxDamage = getModifiedAttribute( inventory, this, 0, &getItemMaxDamageHelper, &getSpellMaxDamageHelper, getModifiedMinDamage() ); return inventoryMaxDamage; }
uint16_t Player::getModifiedMaxMana() const { return getModifiedAttribute( inventory, this, getMaxMana(), &getItemManaHelper, &getSpellManaHelper, NULLABLE_ATTRIBUTE_MIN ); }
uint16_t Player::getModifiedMaxHealth() const { return getModifiedAttribute( inventory, this, getMaxHealth(), &getItemHealthHelper, &getSpellHealthHelper, NON_NULLABLE_ATTRIBUTE_MIN ); }
uint16_t Player::getModifiedWisdom() const { return getModifiedAttribute( inventory, this, getWisdom(), &getItemWisdomHelper, &getSpellWisdomHelper, NON_NULLABLE_ATTRIBUTE_MIN ); }
uint16_t Player::getModifiedIntellect() const { return getModifiedAttribute( inventory, this, getIntellect(), &getItemIntellectHelper, &getSpellIntellectHelper, NON_NULLABLE_ATTRIBUTE_MIN ); }
uint16_t Player::getModifiedVitality() const { return getModifiedAttribute( inventory, this, getVitality(), &getItemVitalityHelper, &getSpellVitalityHelper, NON_NULLABLE_ATTRIBUTE_MIN ); }