mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Use lua for damage calculation formula evaluation
This commit is contained in:
parent
543ce94132
commit
fdfb7fca12
@ -518,21 +518,19 @@ if(NOT ENABLE_MINIMAL_LIB)
|
||||
find_package(TBB REQUIRED)
|
||||
endif()
|
||||
|
||||
if(ENABLE_LUA)
|
||||
find_package(luajit)
|
||||
find_package(luajit)
|
||||
|
||||
if(TARGET luajit::luajit)
|
||||
message(STATUS "Using LuaJIT provided by system")
|
||||
else()
|
||||
message(STATUS "Cannot find LuaJIT! Fallback to using usual Lua.")
|
||||
find_package(Lua REQUIRED)
|
||||
if(Lua_FOUND)
|
||||
add_library(luajit::luajit UNKNOWN IMPORTED)
|
||||
set_target_properties(luajit::luajit PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${LUA_INCLUDE_DIR}")
|
||||
set_target_properties(luajit::luajit PROPERTIES
|
||||
IMPORTED_LOCATION "${LUA_LIBRARIES}")
|
||||
endif()
|
||||
if(TARGET luajit::luajit)
|
||||
message(STATUS "Using LuaJIT provided by system")
|
||||
else()
|
||||
message(STATUS "Cannot find LuaJIT! Fallback to using usual Lua.")
|
||||
find_package(Lua REQUIRED)
|
||||
if(Lua_FOUND)
|
||||
add_library(luajit::luajit UNKNOWN IMPORTED)
|
||||
set_target_properties(luajit::luajit PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${LUA_INCLUDE_DIR}")
|
||||
set_target_properties(luajit::luajit PROPERTIES
|
||||
IMPORTED_LOCATION "${LUA_LIBRARIES}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
@ -751,7 +751,7 @@ endif()
|
||||
|
||||
set_target_properties(vcmi PROPERTIES COMPILE_DEFINITIONS "VCMI_DLL=1")
|
||||
target_link_libraries(vcmi PUBLIC
|
||||
minizip::minizip ZLIB::ZLIB TBB::tbb
|
||||
minizip::minizip ZLIB::ZLIB TBB::tbb luajit::luajit
|
||||
${SYSTEM_LIBS} Boost::boost Boost::thread Boost::filesystem Boost::program_options Boost::locale Boost::date_time
|
||||
)
|
||||
|
||||
|
@ -20,6 +20,110 @@
|
||||
#include "../IGameSettings.h"
|
||||
#include "../VCMI_Lib.h"
|
||||
|
||||
#include <lua.hpp>
|
||||
|
||||
class LuaExpressionEvaluator : boost::noncopyable
|
||||
{
|
||||
lua_State * luaState = nullptr;
|
||||
const std::string expression;
|
||||
int compiledReference = -1;
|
||||
|
||||
void compile();
|
||||
void registerLibrary();
|
||||
public:
|
||||
LuaExpressionEvaluator(const std::string & expression);
|
||||
~LuaExpressionEvaluator();
|
||||
|
||||
void setVariable(const std::string & name, double value);
|
||||
double evaluate();
|
||||
};
|
||||
|
||||
void LuaExpressionEvaluator::registerLibrary()
|
||||
{
|
||||
const auto & luaMax = [](lua_State * state)
|
||||
{
|
||||
lua_Number a = luaL_checknumber(state, 1);
|
||||
lua_Number b = luaL_checknumber(state, 2);
|
||||
lua_pushnumber(state, std::max(a,b));
|
||||
return 1;
|
||||
};
|
||||
|
||||
const auto & luaMin = [](lua_State * state)
|
||||
{
|
||||
lua_Number a = luaL_checknumber(state, 1);
|
||||
lua_Number b = luaL_checknumber(state, 2);
|
||||
lua_pushnumber(state, std::min(a,b));
|
||||
return 1;
|
||||
};
|
||||
|
||||
const auto & luaClamp = [](lua_State * state)
|
||||
{
|
||||
lua_Number a = luaL_checknumber(state, 1);
|
||||
lua_Number b = luaL_checknumber(state, 2);
|
||||
lua_Number c = luaL_checknumber(state, 3);
|
||||
lua_pushnumber(state, std::clamp(a,b,c));
|
||||
return 1;
|
||||
};
|
||||
|
||||
const luaL_Reg registry[] = {
|
||||
{ "max", luaMax },
|
||||
{ "min", luaMin },
|
||||
{ "clamp", luaClamp },
|
||||
{ nullptr, nullptr }
|
||||
};
|
||||
|
||||
lua_pushvalue(luaState, LUA_GLOBALSINDEX);
|
||||
luaL_setfuncs(luaState,registry,0);
|
||||
}
|
||||
|
||||
LuaExpressionEvaluator::LuaExpressionEvaluator(const std::string & expression)
|
||||
: expression(expression)
|
||||
{
|
||||
luaState = luaL_newstate();
|
||||
registerLibrary();
|
||||
compile();
|
||||
}
|
||||
|
||||
LuaExpressionEvaluator::~LuaExpressionEvaluator()
|
||||
{
|
||||
lua_close(luaState);
|
||||
}
|
||||
|
||||
void LuaExpressionEvaluator::setVariable(const std::string & name, double value)
|
||||
{
|
||||
lua_pushnumber(luaState, value);
|
||||
lua_setglobal(luaState, name.c_str());
|
||||
}
|
||||
|
||||
void LuaExpressionEvaluator::compile()
|
||||
{
|
||||
int result = luaL_loadstring(luaState, expression.c_str());
|
||||
|
||||
if (result)
|
||||
{
|
||||
logGlobal->error("Lua compilation failure: %s", lua_tostring(luaState,-1));
|
||||
lua_pop(luaState,1);
|
||||
}
|
||||
|
||||
assert(result == LUA_OK);
|
||||
compiledReference = luaL_ref(luaState, LUA_REGISTRYINDEX);
|
||||
}
|
||||
|
||||
double LuaExpressionEvaluator::evaluate()
|
||||
{
|
||||
lua_rawgeti(luaState, LUA_REGISTRYINDEX, compiledReference);
|
||||
int errorCode = lua_pcall(luaState,0,1,0);
|
||||
if (errorCode)
|
||||
{
|
||||
logGlobal->error("Lua evaluation failure: %s", lua_tostring(luaState,-1));
|
||||
lua_pop(luaState,1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
double result = lua_tonumber(luaState,-1);
|
||||
lua_pop(luaState,1);
|
||||
return result;
|
||||
}
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
@ -208,18 +312,12 @@ int DamageCalculator::getTargetDefenseIgnored() const
|
||||
|
||||
double DamageCalculator::getAttackSkillFactor() const
|
||||
{
|
||||
int attackAdvantage = getActorAttackEffective() - getTargetDefenseEffective();
|
||||
static LuaExpressionEvaluator evaluator("return clamp((attack - defense) * 0.05, 0, 4)");
|
||||
|
||||
if(attackAdvantage > 0)
|
||||
{
|
||||
// FIXME: use cb to acquire these settings
|
||||
const double attackMultiplier = VLC->engineSettings()->getDouble(EGameSettings::COMBAT_ATTACK_POINT_DAMAGE_FACTOR);
|
||||
const double attackMultiplierCap = VLC->engineSettings()->getDouble(EGameSettings::COMBAT_ATTACK_POINT_DAMAGE_FACTOR_CAP);
|
||||
const double attackFactor = std::min(attackMultiplier * attackAdvantage, attackMultiplierCap);
|
||||
|
||||
return attackFactor;
|
||||
}
|
||||
return 0.f;
|
||||
evaluator.setVariable("defense", getTargetDefenseEffective());
|
||||
evaluator.setVariable("attack", getActorAttackEffective());
|
||||
double result = evaluator.evaluate();
|
||||
return result;
|
||||
}
|
||||
|
||||
double DamageCalculator::getAttackBlessFactor() const
|
||||
@ -308,19 +406,12 @@ double DamageCalculator::getAttackRevengeFactor() const
|
||||
|
||||
double DamageCalculator::getDefenseSkillFactor() const
|
||||
{
|
||||
int defenseAdvantage = getTargetDefenseEffective() - getActorAttackEffective();
|
||||
static LuaExpressionEvaluator evaluator("return clamp((defense - attack) * 0.025, 0, 0.7)");
|
||||
|
||||
//bonus from attack/defense skills
|
||||
if(defenseAdvantage > 0) //decreasing dmg
|
||||
{
|
||||
// FIXME: use cb to acquire these settings
|
||||
const double defenseMultiplier = VLC->engineSettings()->getDouble(EGameSettings::COMBAT_DEFENSE_POINT_DAMAGE_FACTOR);
|
||||
const double defenseMultiplierCap = VLC->engineSettings()->getDouble(EGameSettings::COMBAT_DEFENSE_POINT_DAMAGE_FACTOR_CAP);
|
||||
|
||||
const double dec = std::min(defenseMultiplier * defenseAdvantage, defenseMultiplierCap);
|
||||
return dec;
|
||||
}
|
||||
return 0.0;
|
||||
evaluator.setVariable("defense", getTargetDefenseEffective());
|
||||
evaluator.setVariable("attack", getActorAttackEffective());
|
||||
double result = evaluator.evaluate();
|
||||
return result;
|
||||
}
|
||||
|
||||
double DamageCalculator::getDefenseArmorerFactor() const
|
||||
|
Loading…
Reference in New Issue
Block a user