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)
|
find_package(TBB REQUIRED)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(ENABLE_LUA)
|
find_package(luajit)
|
||||||
find_package(luajit)
|
|
||||||
|
|
||||||
if(TARGET luajit::luajit)
|
if(TARGET luajit::luajit)
|
||||||
message(STATUS "Using LuaJIT provided by system")
|
message(STATUS "Using LuaJIT provided by system")
|
||||||
else()
|
else()
|
||||||
message(STATUS "Cannot find LuaJIT! Fallback to using usual Lua.")
|
message(STATUS "Cannot find LuaJIT! Fallback to using usual Lua.")
|
||||||
find_package(Lua REQUIRED)
|
find_package(Lua REQUIRED)
|
||||||
if(Lua_FOUND)
|
if(Lua_FOUND)
|
||||||
add_library(luajit::luajit UNKNOWN IMPORTED)
|
add_library(luajit::luajit UNKNOWN IMPORTED)
|
||||||
set_target_properties(luajit::luajit PROPERTIES
|
set_target_properties(luajit::luajit PROPERTIES
|
||||||
INTERFACE_INCLUDE_DIRECTORIES "${LUA_INCLUDE_DIR}")
|
INTERFACE_INCLUDE_DIRECTORIES "${LUA_INCLUDE_DIR}")
|
||||||
set_target_properties(luajit::luajit PROPERTIES
|
set_target_properties(luajit::luajit PROPERTIES
|
||||||
IMPORTED_LOCATION "${LUA_LIBRARIES}")
|
IMPORTED_LOCATION "${LUA_LIBRARIES}")
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -751,7 +751,7 @@ endif()
|
|||||||
|
|
||||||
set_target_properties(vcmi PROPERTIES COMPILE_DEFINITIONS "VCMI_DLL=1")
|
set_target_properties(vcmi PROPERTIES COMPILE_DEFINITIONS "VCMI_DLL=1")
|
||||||
target_link_libraries(vcmi PUBLIC
|
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
|
${SYSTEM_LIBS} Boost::boost Boost::thread Boost::filesystem Boost::program_options Boost::locale Boost::date_time
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -20,6 +20,110 @@
|
|||||||
#include "../IGameSettings.h"
|
#include "../IGameSettings.h"
|
||||||
#include "../VCMI_Lib.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
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
@ -208,18 +312,12 @@ int DamageCalculator::getTargetDefenseIgnored() const
|
|||||||
|
|
||||||
double DamageCalculator::getAttackSkillFactor() const
|
double DamageCalculator::getAttackSkillFactor() const
|
||||||
{
|
{
|
||||||
int attackAdvantage = getActorAttackEffective() - getTargetDefenseEffective();
|
static LuaExpressionEvaluator evaluator("return clamp((attack - defense) * 0.05, 0, 4)");
|
||||||
|
|
||||||
if(attackAdvantage > 0)
|
evaluator.setVariable("defense", getTargetDefenseEffective());
|
||||||
{
|
evaluator.setVariable("attack", getActorAttackEffective());
|
||||||
// FIXME: use cb to acquire these settings
|
double result = evaluator.evaluate();
|
||||||
const double attackMultiplier = VLC->engineSettings()->getDouble(EGameSettings::COMBAT_ATTACK_POINT_DAMAGE_FACTOR);
|
return result;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double DamageCalculator::getAttackBlessFactor() const
|
double DamageCalculator::getAttackBlessFactor() const
|
||||||
@ -308,19 +406,12 @@ double DamageCalculator::getAttackRevengeFactor() const
|
|||||||
|
|
||||||
double DamageCalculator::getDefenseSkillFactor() 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
|
evaluator.setVariable("defense", getTargetDefenseEffective());
|
||||||
if(defenseAdvantage > 0) //decreasing dmg
|
evaluator.setVariable("attack", getActorAttackEffective());
|
||||||
{
|
double result = evaluator.evaluate();
|
||||||
// FIXME: use cb to acquire these settings
|
return result;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double DamageCalculator::getDefenseArmorerFactor() const
|
double DamageCalculator::getDefenseArmorerFactor() const
|
||||||
|
Loading…
Reference in New Issue
Block a user