diff --git a/LUA_API.rst b/LUA_API.rst index dab299741..422ba6b49 100644 --- a/LUA_API.rst +++ b/LUA_API.rst @@ -503,6 +503,10 @@ C++ function wrappers Thin wrappers around C++ functions, similar to the ones for virtual methods. +* ``dfhack.TranslateName(name,in_english,only_last_name)`` + + Convert a language_name or only the last name part to string. + Gui module ---------- @@ -558,3 +562,22 @@ Job module * ``dfhack.job.is_item_equal(job_item1,job_item2)`` Compares important fields in the job item structures. + +Units module +------------ + +* ``dfhack.units.getVisibleName(unit)`` + + Returns the name visible in game, accounting for false identities. + +* ``dfhack.units.isDead(unit)`` + + The unit is completely dead and passive. + +* ``dfhack.units.isAlive(unit)`` + + The unit isn't dead or undead. + +* ``dfhack.units.isSane(unit)`` + + The unit is capable of rational action, i.e. not dead, insane or zombie. diff --git a/Lua API.html b/Lua API.html index 877bdbd88..ab64eea9a 100644 --- a/Lua API.html +++ b/Lua API.html @@ -338,6 +338,7 @@ ul.auto-toc {
  • C++ function wrappers
  • @@ -761,6 +762,11 @@ However, currently every entry has a 180+-byte dead-weight overhead.

    C++ function wrappers

    Thin wrappers around C++ functions, similar to the ones for virtual methods.

    +

    Gui module

    +
    +

    Units module

    + +
    diff --git a/library/LuaTools.cpp b/library/LuaTools.cpp index 5afd1156b..5a87c931d 100644 --- a/library/LuaTools.cpp +++ b/library/LuaTools.cpp @@ -40,6 +40,8 @@ distribution. #include "modules/World.h" #include "modules/Gui.h" #include "modules/Job.h" +#include "modules/Translation.h" +#include "modules/Units.h" #include "LuaWrapper.h" #include "LuaTools.h" @@ -641,9 +643,9 @@ static const luaL_Reg dfhack_funcs[] = { { NULL, NULL } }; -/* - * Per-world persistent configuration storage. - */ +/************************************************** + * Per-world persistent configuration storage API * + **************************************************/ static PersistentDataItem persistent_by_struct(lua_State *state, int idx) { @@ -783,6 +785,7 @@ static int dfhack_persistent_save(lua_State *state) lua_settop(state, 1); + // Retrieve existing or create a new entry PersistentDataItem ref; bool added = false; @@ -804,6 +807,7 @@ static int dfhack_persistent_save(lua_State *state) ref = Core::getInstance().getWorld()->GetPersistentData(str); } + // Auto-add if not found if (!ref.isValid()) { ref = Core::getInstance().getWorld()->AddPersistentData(str); @@ -812,6 +816,7 @@ static int dfhack_persistent_save(lua_State *state) added = true; } + // Copy data from lua to C++ memory lua_getfield(state, 1, "value"); if (const char *str = lua_tostring(state, -1)) ref.val() = str; @@ -830,6 +835,7 @@ static int dfhack_persistent_save(lua_State *state) } lua_pop(state, 1); + // Reinitialize lua from C++ and return read_persistent(state, ref, false); lua_pushboolean(state, added); return 2; @@ -856,6 +862,10 @@ static void OpenPersistent(lua_State *state) lua_pop(state, 1); } +/************************ + * Wrappers for C++ API * + ************************/ + static void OpenModule(lua_State *state, const char *mname, const LuaWrapper::FunctionReg *reg) { luaL_getsubtable(state, lua_gettop(state), mname); @@ -867,6 +877,11 @@ static void OpenModule(lua_State *state, const char *mname, const LuaWrapper::Fu #define WRAP(function) { #function, df::wrap_function(&function) } #define WRAPN(name, function) { #name, df::wrap_function(&function) } +static const LuaWrapper::FunctionReg dfhack_module[] = { + WRAPM(Translation, TranslateName), + { NULL, NULL } +}; + static const LuaWrapper::FunctionReg dfhack_gui_module[] = { WRAPM(Gui, getSelectedWorkshopJob), WRAPM(Gui, getSelectedJob), @@ -889,6 +904,18 @@ static const LuaWrapper::FunctionReg dfhack_job_module[] = { { NULL, NULL } }; +static const LuaWrapper::FunctionReg dfhack_units_module[] = { + WRAPM(Units, getVisibleName), + WRAPM(Units, isDead), + WRAPM(Units, isAlive), + WRAPM(Units, isSane), + { NULL, NULL } +}; + +/************************ + * Main Open function * + ************************/ + lua_State *DFHack::Lua::Open(color_ostream &out, lua_State *state) { if (!state) @@ -917,8 +944,10 @@ lua_State *DFHack::Lua::Open(color_ostream &out, lua_State *state) OpenPersistent(state); + LuaWrapper::SetFunctionWrappers(state, dfhack_module); OpenModule(state, "gui", dfhack_gui_module); OpenModule(state, "job", dfhack_job_module); + OpenModule(state, "units", dfhack_units_module); lua_setglobal(state, "dfhack"); diff --git a/library/RemoteTools.cpp b/library/RemoteTools.cpp index 01c110643..00344d6a2 100644 --- a/library/RemoteTools.cpp +++ b/library/RemoteTools.cpp @@ -256,7 +256,7 @@ void DFHack::describeUnit(BasicUnitInfo *info, df::unit *unit, info->set_pos_y(unit->pos.y); info->set_pos_z(unit->pos.z); - auto name = Units::GetVisibleName(unit); + auto name = Units::getVisibleName(unit); if (name->has_name) describeName(info->mutable_name(), name); diff --git a/library/include/modules/Units.h b/library/include/modules/Units.h index 0fd75bf1f..b966a39be 100644 --- a/library/include/modules/Units.h +++ b/library/include/modules/Units.h @@ -193,7 +193,7 @@ DFHACK_EXPORT void CopyNameTo(df::unit *creature, df::language_name * target); DFHACK_EXPORT bool RemoveOwnedItemByIdx(const uint32_t index, int32_t id); DFHACK_EXPORT bool RemoveOwnedItemByPtr(df::unit * unit, int32_t id); -DFHACK_EXPORT df::language_name *GetVisibleName(df::unit *unit); +DFHACK_EXPORT df::language_name *getVisibleName(df::unit *unit); DFHACK_EXPORT bool isDead(df::unit *unit); DFHACK_EXPORT bool isAlive(df::unit *unit); diff --git a/library/lua/dfhack.lua b/library/lua/dfhack.lua index 1101367fc..9e2cdf257 100644 --- a/library/lua/dfhack.lua +++ b/library/lua/dfhack.lua @@ -58,9 +58,10 @@ end -- Misc functions function printall(table) - if table == nil then return end - for k,v in pairs(table) do - print(k," = "..tostring(v)) + if type(table) == 'table' or df.isvalid(table) == 'ref' then + for k,v in pairs(table) do + print(string.format("%-23s\t = %s",tostring(k),tostring(v))) + end end end diff --git a/library/modules/Translation.cpp b/library/modules/Translation.cpp index 7b5fa654c..bc0724707 100644 --- a/library/modules/Translation.cpp +++ b/library/modules/Translation.cpp @@ -35,6 +35,7 @@ using namespace std; #include "Types.h" #include "ModuleFactory.h" #include "Core.h" +#include "Error.h" using namespace DFHack; using namespace df::enums; @@ -93,6 +94,8 @@ void addNameWord (string &out, const string &word) string Translation::TranslateName(const df::language_name * name, bool inEnglish, bool onlyLastPart) { + CHECK_NULL_POINTER(name); + string out; string word; diff --git a/library/modules/Units.cpp b/library/modules/Units.cpp index f6259bd3b..3dc5d1b04 100644 --- a/library/modules/Units.cpp +++ b/library/modules/Units.cpp @@ -527,8 +527,10 @@ void Units::CopyNameTo(df::unit * creature, df::language_name * target) Translation::copyName(&creature->name, target); } -df::language_name *Units::GetVisibleName(df::unit *unit) +df::language_name *Units::getVisibleName(df::unit *unit) { + CHECK_NULL_POINTER(unit); + df::historical_figure *figure = df::historical_figure::find(unit->hist_figure_id); if (figure) @@ -555,11 +557,15 @@ df::language_name *Units::GetVisibleName(df::unit *unit) bool DFHack::Units::isDead(df::unit *unit) { + CHECK_NULL_POINTER(unit); + return unit->flags1.bits.dead; } bool DFHack::Units::isAlive(df::unit *unit) { + CHECK_NULL_POINTER(unit); + return !unit->flags1.bits.dead && !unit->flags3.bits.ghostly && !unit->curse.add_tags1.bits.NOT_LIVING; @@ -567,23 +573,22 @@ bool DFHack::Units::isAlive(df::unit *unit) bool DFHack::Units::isSane(df::unit *unit) { + CHECK_NULL_POINTER(unit); + if (unit->flags1.bits.dead || unit->flags3.bits.ghostly || unit->curse.add_tags1.bits.OPPOSED_TO_LIFE || unit->curse.add_tags1.bits.CRAZED) return false; - if (unit->flags1.bits.has_mood) + switch (unit->mood) { - switch (unit->mood) - { - case mood_type::Melancholy: - case mood_type::Raving: - case mood_type::Berserk: - return false; - default: - break; - } + case mood_type::Melancholy: + case mood_type::Raving: + case mood_type::Berserk: + return false; + default: + break; } return true;