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; } }