CombatDamage Combat::getCombatDamage(Creature* creature, Creature* target) const { CombatDamage damage; damage.origin = params.origin; damage.primary.type = params.combatType; if (formulaType == COMBAT_FORMULA_DAMAGE) { damage.primary.value = normal_random( static_cast<int32_t>(mina), static_cast<int32_t>(maxa) ); } else if (creature) { int32_t min, max; if (creature->getCombatValues(min, max)) { damage.primary.value = normal_random(min, max); } else if (Player* player = creature->getPlayer()) { if (params.valueCallback) { params.valueCallback->getMinMaxValues(player, damage, params.useCharges); } else if (formulaType == COMBAT_FORMULA_LEVELMAGIC) { int32_t levelFormula = player->getLevel() * 2 + player->getMagicLevel() * 3; damage.primary.value = normal_random( static_cast<int32_t>(levelFormula * mina + minb), static_cast<int32_t>(levelFormula * maxa + maxb) ); } else if (formulaType == COMBAT_FORMULA_SKILL) { Item* tool = player->getWeapon(); const Weapon* weapon = g_weapons->getWeapon(tool); if (weapon) { damage.primary.value = normal_random( static_cast<int32_t>(minb), static_cast<int32_t>(weapon->getWeaponDamage(player, target, tool, true) * maxa + maxb) ); damage.secondary.type = weapon->getElementType(); damage.secondary.value = weapon->getElementDamage(player, target, tool); if (params.useCharges) { uint16_t charges = tool->getCharges(); if (charges != 0) { g_game.transformItem(tool, tool->getID(), charges - 1); } } } else { damage.primary.value = normal_random( static_cast<int32_t>(minb), static_cast<int32_t>(maxb) ); } } } } return damage; }
int32_t WeaponWand::getWeaponDamage(const Player*, const Creature*, const Item*, bool maxDamage /*= false*/) const { if (maxDamage) { return -maxChange; } return -normal_random(minChange, maxChange); }
int32_t WeaponDistance::getWeaponDamage(const Player* player, const Creature* target, const Item* item, bool maxDamage /*= false*/) const { int32_t attackValue = ammuAttackValue; if (item->getWeaponType() == WEAPON_AMMO) { Item* bow = const_cast<Player*>(player)->getWeapon(true); if (bow) { attackValue += bow->getAttack(); } } int32_t attackSkill = player->getSkillLevel(SKILL_DISTANCE); float attackFactor = player->getAttackFactor(); int32_t maxValue = static_cast<int32_t>(Weapons::getMaxWeaponDamage(player->getLevel(), attackSkill, attackValue, attackFactor) * player->getVocation()->distDamageMultiplier); if (maxDamage) { return -maxValue; } int32_t minValue; if (target) { if (target->getPlayer()) { minValue = static_cast<int32_t>(std::ceil(player->getLevel() * 0.1)); } else { minValue = static_cast<int32_t>(std::ceil(player->getLevel() * 0.2)); } } else { minValue = 0; } return -normal_random(minValue, maxValue); }
bool Weapon::useFist(Player* player, Creature* target) { if (!Position::areInRange<1, 1>(player->getPosition(), target->getPosition())) { return false; } float attackFactor = player->getAttackFactor(); int32_t attackSkill = player->getSkillLevel(SKILL_FIST); int32_t attackValue = 7; int32_t maxDamage = Weapons::getMaxWeaponDamage(player->getLevel(), attackSkill, attackValue, attackFactor); CombatParams params; params.combatType = COMBAT_PHYSICALDAMAGE; params.blockedByArmor = true; params.blockedByShield = true; CombatDamage damage; damage.origin = ORIGIN_MELEE; damage.primary.type = params.combatType; damage.primary.value = -normal_random(0, maxDamage); Combat::doCombatHealth(player, target, damage, params); if (!player->hasFlag(PlayerFlag_NotGainSkill) && player->getAddAttackSkill()) { player->addSkillAdvance(SKILL_FIST, 1); } return true; }
int32_t WeaponDistance::getElementDamage(const Player* player, const Creature* target, const Item* item) const { if (elementType == COMBAT_NONE) { return 0; } int32_t attackValue = elementDamage; if (item->getWeaponType() == WEAPON_AMMO) { Item* weapon = player->getWeapon(true); if (weapon) { attackValue += weapon->getAttack(); } } int32_t attackSkill = player->getSkillLevel(SKILL_DISTANCE); float attackFactor = player->getAttackFactor(); int32_t minValue = 0; int32_t maxValue = Weapons::getMaxWeaponDamage(player->getLevel(), attackSkill, attackValue, attackFactor); if (target) { if (target->getPlayer()) { minValue = static_cast<int32_t>(std::ceil(player->getLevel() * 0.1)); } else { minValue = static_cast<int32_t>(std::ceil(player->getLevel() * 0.2)); } } return -normal_random(minValue, static_cast<int32_t>(maxValue * player->getVocation()->distDamageMultiplier)); }
int32_t WeaponDistance::getElementDamage(const Player* player, const Creature* target, const Item* item) const { if (elementType == COMBAT_NONE) { return 0; } int32_t attackValue = elementDamage; if (item->getWeaponType() == WEAPON_AMMO) { Item* bow = const_cast<Player*>(player)->getWeapon(true); if (bow) { attackValue += bow->getAttack(); } } int32_t attackSkill = player->getSkill(SKILL_DIST, SKILL_LEVEL); float attackFactor = player->getAttackFactor(); int32_t maxValue = Weapons::getMaxWeaponDamage(player->getLevel(), attackSkill, attackValue, attackFactor); if (uniform_random(1, 100) <= g_config.getNumber(ConfigManager::CRITICAL_HIT_CHANCE)) { maxValue *= 2; } int32_t minValue = 0; if (target) { if (target->getPlayer()) { minValue = static_cast<int32_t>(std::ceil(player->getLevel() * 0.1)); } else { minValue = static_cast<int32_t>(std::ceil(player->getLevel() * 0.2)); } } return -normal_random(minValue, static_cast<int32_t>(maxValue * player->getVocation()->distDamageMultiplier)); }
bool Weapon::useFist(Player* player, Creature* target) { const Position& playerPos = player->getPosition(); const Position& targetPos = target->getPosition(); if (Position::areInRange<1, 1>(playerPos, targetPos)) { float attackFactor = player->getAttackFactor(); int32_t attackSkill = player->getSkill(SKILL_FIST, SKILL_LEVEL); int32_t attackValue = 7; int32_t maxDamage = Weapons::getMaxWeaponDamage(player->getLevel(), attackSkill, attackValue, attackFactor); if (uniform_random(1, 100) <= g_config.getNumber(ConfigManager::CRITICAL_HIT_CHANCE)) { maxDamage *= 2; } CombatParams params; params.combatType = COMBAT_PHYSICALDAMAGE; params.blockedByArmor = true; params.blockedByShield = true; CombatDamage damage; damage.primary.type = params.combatType; damage.primary.value = -normal_random(0, maxDamage); Combat::doCombatHealth(player, target, damage, params); if (!player->hasFlag(PlayerFlag_NotGainSkill) && player->getAddAttackSkill()) { player->addSkillAdvance(SKILL_FIST, 1); } return true; } return false; }
int32_t WeaponMelee::getWeaponDamage(const Player* player, const Creature*, const Item* item, bool maxDamage /*= false*/) const { int32_t attackSkill = player->getWeaponSkill(item); int32_t attackValue = std::max<int32_t>(0, item->getAttack()); float attackFactor = player->getAttackFactor(); int32_t maxValue = static_cast<int32_t>(Weapons::getMaxWeaponDamage(player->getLevel(), attackSkill, attackValue, attackFactor) * player->getVocation()->meleeDamageMultiplier); if (maxDamage) { return -maxValue; } return -normal_random(0, maxValue); }
int32_t WeaponMelee::getElementDamage(const Player* player, const Creature*, const Item* item) const { if (elementType == COMBAT_NONE) { return 0; } int32_t attackSkill = player->getWeaponSkill(item); int32_t attackValue = std::max<int32_t>(0, elementDamage); float attackFactor = player->getAttackFactor(); int32_t maxValue = Weapons::getMaxWeaponDamage(player->getLevel(), attackSkill, attackValue, attackFactor); return -normal_random(0, static_cast<int32_t>(maxValue * player->getVocation()->meleeDamageMultiplier)); }
int32_t WeaponMelee::getElementDamage(const Player* player, const Item* item) const { int32_t attackSkill = player->getWeaponSkill(item); int32_t attackValue = std::max<int32_t>(0, elementDamage); float attackFactor = player->getAttackFactor(); int32_t maxValue = Weapons::getMaxWeaponDamage(player->getLevel(), attackSkill, attackValue, attackFactor); if (uniform_random(1, 100) <= g_config.getNumber(ConfigManager::CRITICAL_HIT_CHANCE)) { maxValue *= 2; } maxValue = int32_t(maxValue * player->getVocation()->meleeDamageMultiplier); return -normal_random(0, maxValue); }
void ValueCallback::getMinMaxValues(Player* player, CombatDamage& damage, bool useCharges) const { //"onGetPlayerMinMaxValues"(...) if (!m_scriptInterface->reserveScriptEnv()) { std::cout << "[Error - ValueCallback::getMinMaxValues] Call stack overflow" << std::endl; return; } ScriptEnvironment* env = m_scriptInterface->getScriptEnv(); if (!env->setCallbackId(m_scriptId, m_scriptInterface)) { m_scriptInterface->resetScriptEnv(); return; } lua_State* L = m_scriptInterface->getLuaState(); m_scriptInterface->pushFunction(m_scriptId); lua_pushnumber(L, player->getID()); int32_t parameters = 1; switch (type) { case COMBAT_FORMULA_LEVELMAGIC: { //"onGetPlayerMinMaxValues"(cid, level, maglevel) lua_pushnumber(L, player->getLevel()); lua_pushnumber(L, player->getMagicLevel()); parameters += 2; break; } case COMBAT_FORMULA_SKILL: { //"onGetPlayerMinMaxValues"(cid, attackSkill, attackValue, attackFactor) Item* tool = player->getWeapon(); const Weapon* weapon = g_weapons->getWeapon(tool); int32_t attackValue = 7; if (weapon) { attackValue = tool->getAttack(); damage.secondary.type = weapon->getElementType(); damage.secondary.value = weapon->getElementDamage(player, nullptr, tool); if (useCharges) { uint16_t charges = tool->getCharges(); if (charges != 0) { g_game.transformItem(tool, tool->getID(), charges - 1); } } } lua_pushnumber(L, player->getWeaponSkill(tool)); lua_pushnumber(L, attackValue); lua_pushnumber(L, player->getAttackFactor()); parameters += 3; break; } default: { std::cout << "ValueCallback::getMinMaxValues - unknown callback type" << std::endl; m_scriptInterface->resetScriptEnv(); return; } } int32_t size0 = lua_gettop(L); if (lua_pcall(L, parameters, 2, 0) != 0) { LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L)); } else { damage.primary.value = normal_random( LuaScriptInterface::getNumber<int32_t>(L, -2), LuaScriptInterface::getNumber<int32_t>(L, -1) ); lua_pop(L, 2); } if ((lua_gettop(L) + parameters + 1) != size0) { LuaScriptInterface::reportError(nullptr, "Stack size changed!"); } m_scriptInterface->resetScriptEnv(); }