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; }
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(); }
bool Combat::getMinMaxValues(Creature* creature, Creature* target, int32_t& min, int32_t& max) const { if(!creature) return false; if(creature->getCombatValues(min, max)) return true; else if(Player* player = creature->getPlayer()) { if(params.valueCallback) { params.valueCallback->getMinMaxValues(player, min, max, params.useCharges); return true; } else { switch(formulaType) { case FORMULA_LEVELMAGIC: { max = (int32_t)((player->getLevel() * 2 + player->getMagicLevel() * 3) * 1. * mina + minb); min = (int32_t)((player->getLevel() * 2 + player->getMagicLevel() * 3) * 1. * maxa + maxb); return true; } case FORMULA_SKILL: { Item* tool = player->getWeapon(); const Weapon* weapon = g_weapons->getWeapon(tool); min = (int32_t)minb; if(weapon) { max = (int32_t)(weapon->getWeaponDamage(player, target, tool, true) * maxa + maxb); if(params.useCharges && tool->hasCharges()) { int32_t newCharge = std::max((int32_t)0, ((int32_t)tool->getCharges()) - 1); g_game.transformItem(tool, tool->getID(), newCharge); } } else max = (int32_t)maxb; return true; } case FORMULA_VALUE: { min = (int32_t)mina; max = (int32_t)maxa; return true; } default: { min = 0; max = 0; return false; } } } } else if(formulaType == FORMULA_VALUE) { min = (int32_t)mina; max = (int32_t)maxa; return true; } return false; }
void ValueCallback::getMinMaxValues(Player* player, int32_t& min, int32_t& max, bool useCharges) const { //"onGetPlayerMinMaxValues"(...) if(m_scriptInterface->reserveScriptEnv()) { ScriptEnviroment* env = m_scriptInterface->getScriptEnv(); lua_State* L = m_scriptInterface->getLuaState(); if(!env->setCallbackId(m_scriptId, m_scriptInterface)) return; uint32_t cid = env->addThing(player); m_scriptInterface->pushFunction(m_scriptId); lua_pushnumber(L, cid); int32_t parameters = 1; switch(type) { case FORMULA_LEVELMAGIC: { //"onGetPlayerMinMaxValues"(cid, level, maglevel) lua_pushnumber(L, player->getLevel()); lua_pushnumber(L, player->getMagicLevel()); parameters += 2; break; } case FORMULA_SKILL: { //"onGetPlayerMinMaxValues"(cid, attackSkill, attackValue, attackFactor) Item* tool = player->getWeapon(); int32_t attackSkill = player->getWeaponSkill(tool); int32_t attackValue = 7; if(tool) { attackValue = tool->getAttack(); if(useCharges && tool->hasCharges()) { int32_t newCharge = std::max(0, tool->getCharges() - 1); g_game.transformItem(tool, tool->getID(), newCharge); } } float attackFactor = player->getAttackFactor(); lua_pushnumber(L, attackSkill); lua_pushnumber(L, attackValue); lua_pushnumber(L, attackFactor); parameters += 3; break; } default: { std::cout << "ValueCallback::getMinMaxValues - unknown callback type" << std::endl; return; break; } } int32_t size0 = lua_gettop(L); if(lua_pcall(L, parameters, 2 /*nReturnValues*/, 0) != 0) LuaScriptInterface::reportError(NULL, LuaScriptInterface::popString(L)); else { max = LuaScriptInterface::popNumber(L); min = LuaScriptInterface::popNumber(L); } if((lua_gettop(L) + parameters /*nParams*/ + 1) != size0) LuaScriptInterface::reportError(NULL, "Stack size changed!"); env->resetCallback(); m_scriptInterface->releaseScriptEnv(); } else { std::cout << "[Error] Call stack overflow. ValueCallback::getMinMaxValues" << std::endl; return; } }
bool Combat::getMinMaxValues(Creature* creature, Creature* target, int32_t& min, int32_t& max) const { if(creature){ if(creature->getCombatValues(min, max)){ return true; } else if(Player* player = creature->getPlayer()){ if(params.valueCallback){ params.valueCallback->getMinMaxValues(player, min, max, params.useCharges); return true; } else{ switch(formulaType){ case FORMULA_LEVELMAGIC: { max = (int32_t)((player->getLevel() + player->getMagicLevel() * 4) * 1. * mina + minb); min = (int32_t)((player->getLevel() + player->getMagicLevel() * 4) * 1. * maxa + maxb); Vocation* vocation = player->getVocation(); if(vocation){ if(max > 0 && min > 0 && vocation->getHealingBaseDamage() != 1.0){ min = int32_t(min * vocation->getHealingBaseDamage()); max = int32_t(max * vocation->getHealingBaseDamage()); } else if(max < 0 && min < 0 && vocation->getMagicBaseDamage() != 1.0){ min = int32_t(min * vocation->getMagicBaseDamage()); max = int32_t(max * vocation->getMagicBaseDamage()); } } return true; break; } case FORMULA_SKILL: { Item* tool = player->getWeapon(); const Weapon* weapon = g_weapons->getWeapon(tool); min = (int32_t)minb; if(weapon){ max = (int32_t)(weapon->getWeaponDamage(player, target, tool, true) * maxa + maxb); if(params.useCharges && tool->hasCharges() && g_config.getNumber(ConfigManager::REMOVE_WEAPON_CHARGES)){ int32_t newCharge = std::max((int32_t)0, ((int32_t)tool->getCharges()) - 1); g_game.transformItem(tool, tool->getID(), newCharge); } } else{ max = (int32_t)maxb; } return true; break; } case FORMULA_VALUE: { min = (int32_t)mina; max = (int32_t)maxa; return true; break; } default: min = 0; max = 0; return false; break; } //std::cout << "No callback set for combat" << std::endl; } } } if(formulaType == FORMULA_VALUE){ min = (int32_t)mina; max = (int32_t)maxa; return true; } return false; }
void ValueCallback::getMinMaxValues(Player* player, int32_t& min, int32_t& max, bool useCharges) const { //"onGetPlayerMinMaxValues"(...) if(m_scriptInterface->reserveScriptEnv()){ ScriptEnviroment* env = m_scriptInterface->getScriptEnv(); lua_State* L = m_scriptInterface->getLuaState(); if(!env->setCallbackId(m_scriptId, m_scriptInterface)) return; uint32_t cid = env->addThing(player); m_scriptInterface->pushFunction(m_scriptId); lua_pushnumber(L, cid); int32_t parameters = 1; bool isMagicFormula = false; switch(type){ case FORMULA_LEVELMAGIC: { //"onGetPlayerMinMaxValues"(cid, level, maglevel) lua_pushnumber(L, player->getLevel()); lua_pushnumber(L, player->getMagicLevel()); parameters += 2; isMagicFormula = true; break; } case FORMULA_SKILL: { //"onGetPlayerMinMaxValues"(cid, attackSkill, attackValue, attackFactor) Item* tool = player->getWeapon(); int32_t attackSkill = player->getWeaponSkill(tool); int32_t attackValue = g_config.getNumber(ConfigManager::FIST_STRENGTH); if(tool){ attackValue = tool->getAttack(); if(useCharges && tool->hasCharges() && g_config.getNumber(ConfigManager::REMOVE_WEAPON_CHARGES)){ int32_t newCharge = std::max(0, tool->getCharges() - 1); g_game.transformItem(tool, tool->getID(), newCharge); } } float attackFactor = player->getAttackFactor(); lua_pushnumber(L, attackSkill); lua_pushnumber(L, attackValue); lua_pushnumber(L, attackFactor); parameters += 3; break; } default: std::cout << "ValueCallback::getMinMaxValues - unknown callback type" << std::endl; return; break; } int size0 = lua_gettop(L); if(lua_pcall(L, parameters, 2 /*nReturnValues*/, 0) != 0){ LuaScriptInterface::reportError(NULL, LuaScriptInterface::popString(L)); } else{ max = LuaScriptInterface::popNumber(L); min = LuaScriptInterface::popNumber(L); Vocation* vocation = player->getVocation(); if(isMagicFormula && vocation){ if(max > 0 && min > 0 && vocation->getHealingBaseDamage() != 1.0){ min = int32_t(min * vocation->getHealingBaseDamage()); max = int32_t(max * vocation->getHealingBaseDamage()); } else if(max < 0 && min < 0 && vocation->getMagicBaseDamage() != 1.0){ min = int32_t(min * vocation->getMagicBaseDamage()); max = int32_t(max * vocation->getMagicBaseDamage()); } } } if((lua_gettop(L) + parameters /*nParams*/ + 1) != size0){ LuaScriptInterface::reportError(NULL, "Stack size changed!"); } env->resetCallback(); m_scriptInterface->releaseScriptEnv(); } else{ std::cout << "[Error] Call stack overflow. ValueCallback::getMinMaxValues" << std::endl; return; } }
void ValueCallback::getMinMaxValues(Player* player, int32_t& min, int32_t& max, bool useCharges) const { //"onGetPlayerMinMaxValues"(cid, ...) if(!m_interface->reserveEnv()) { LOGe("[ValueCallback::getMinMaxValues] Callstack overflow."); return; } ScriptEnviroment* env = m_interface->getEnv(); if(!env->setCallbackId(m_scriptId, m_interface)) return; m_interface->pushFunction(m_scriptId); lua_State* L = m_interface->getState(); lua_pushnumber(L, env->addThing(player)); int32_t parameters = 1; switch(type) { case FORMULA_LEVELMAGIC: { //"onGetPlayerMinMaxValues"(cid, level, magLevel) lua_pushnumber(L, player->getLevel()); lua_pushnumber(L, player->getMagicLevel()); parameters += 2; break; } case FORMULA_SKILL: { //"onGetPlayerMinMaxValues"(cid, level, skill, attack, factor) Item* tool = player->getWeapon(); lua_pushnumber(L, player->getLevel()); lua_pushnumber(L, player->getWeaponSkill(tool)); int32_t attack = 7; if(tool) { attack = tool->getAttack(); if(useCharges && tool->hasCharges() && server.configManager().getBool(ConfigManager::REMOVE_WEAPON_CHARGES)) server.game().transformItem(tool, tool->getId(), std::max(0, tool->getCharges() - 1)); } lua_pushnumber(L, attack); lua_pushnumber(L, player->getAttackFactor()); parameters += 4; break; } default: { LOGe("[ValueCallback::getMinMaxValues] Unknown callback type"); return; } } int32_t params = lua_gettop(L); if(!lua_pcall(L, parameters, 2, 0)) { min = LuaScriptInterface::popNumber(L); max = LuaScriptInterface::popNumber(L); player->increaseCombatValues(min, max, useCharges, type != FORMULA_SKILL); } else LuaScriptInterface::error(nullptr, std::string(LuaScriptInterface::popString(L))); if((lua_gettop(L) + parameters + 1) != params) LuaScriptInterface::error(__FUNCTION__, "Stack size changed!"); env->resetCallback(); m_interface->releaseEnv(); }
bool Combat::getMinMaxValues(const CreatureP& creature, const CreatureP& target, int32_t& min, int32_t& max) const { if(creature) { if(creature->getCombatValues(min, max)) return true; if(Player* player = creature->getPlayer()) { if(params.valueCallback) { params.valueCallback->getMinMaxValues(player, min, max, params.useCharges); return true; } min = max = 0; switch(formulaType) { case FORMULA_LEVELMAGIC: { min = (int32_t)((player->getLevel() / minl + player->getMagicLevel() * minm) * 1. * mina + minb); max = (int32_t)((player->getLevel() / maxl + player->getMagicLevel() * maxm) * 1. * maxa + maxb); if(minc && std::abs(min) < std::abs(minc)) min = minc; if(maxc && std::abs(max) < std::abs(maxc)) max = maxc; player->increaseCombatValues(min, max, params.useCharges, true); return true; } case FORMULA_SKILL: { Item* tool = player->getWeapon(); if(WeaponPC weapon = server.weapons().getWeapon(tool)) { max = (int32_t)(weapon->getWeaponDamage(*player, target.get(), tool, true) * maxa + maxb); if(params.useCharges && tool->hasCharges() && server.configManager().getBool(ConfigManager::REMOVE_WEAPON_CHARGES)) server.game().transformItem(tool, tool->getId(), std::max((int32_t)0, ((int32_t)tool->getCharges()) - 1)); } else max = (int32_t)maxb; min = (int32_t)minb; if(maxc && std::abs(max) < std::abs(maxc)) max = maxc; return true; } case FORMULA_VALUE: { min = (int32_t)minb; max = (int32_t)maxb; return true; } default: break; } return false; } } if(formulaType != FORMULA_VALUE) return false; min = (int32_t)mina; max = (int32_t)maxa; return true; }
bool Combat::getMinMaxValues(Creature* creature, Creature* target, CombatParams& _params, int32_t& min, int32_t& max) const { if(creature) { if(creature->getCombatValues(min, max)) return true; if(Player* player = creature->getPlayer()) { if(params.valueCallback) { params.valueCallback->getMinMaxValues(player, _params, min, max); return true; } min = max = 0; switch(formulaType) { case FORMULA_LEVELMAGIC: { max = (int32_t)((player->getLevel() * 2 + player->getMagicLevel() * 3) * 1. * mina + minb); min = (int32_t)((player->getLevel() * 2 + player->getMagicLevel() * 3) * 1. * maxa + maxb); player->increaseCombatValues(min, max, params.useCharges, true); return true; } case FORMULA_SKILL: { Item* item = player->getWeapon(false); if(const Weapon* weapon = g_weapons->getWeapon(item)) { _params.element.type = item->getElementType(); if(_params.element.type != COMBAT_NONE) { _params.element.damage = weapon->getWeaponElementDamage(player, item, true); _params.element.damage = random_range((int32_t)0, (int32_t)(_params.element.damage * maxa + maxb), DISTRO_NORMAL); } max = (int32_t)(weapon->getWeaponDamage(player, target, item, true) * maxa + maxb); if(params.useCharges && item->hasCharges() && g_config.getBool(ConfigManager::REMOVE_WEAPON_CHARGES)) g_game.transformItem(item, item->getID(), std::max((int32_t)0, ((int32_t)item->getCharges()) - 1)); } else max = (int32_t)maxb; return true; } case FORMULA_VALUE: { min = (int32_t)mina; max = (int32_t)maxa; return true; } default: min = max = 0; break; } return false; } } if(formulaType != FORMULA_VALUE) return false; min = (int32_t)mina; max = (int32_t)maxa; return true; }