From 6ab270d129e098f0200824a798ad2117a6ec33c8 Mon Sep 17 00:00:00 2001
From: Alexander Gavrilov
Date: Thu, 26 Apr 2012 12:03:56 +0400
Subject: [PATCH] Retrieve unit noble position info, and use it in
getProfessionName.
---
LUA_API.rst | 10 +++-
Lua API.html | 9 +++-
library/LuaApi.cpp | 31 +++++++++++++
library/include/modules/Units.h | 13 +++++-
library/modules/Units.cpp | 82 +++++++++++++++++++++++++++++++--
plugins/lua/sort/units.lua | 9 ++++
6 files changed, 145 insertions(+), 9 deletions(-)
diff --git a/LUA_API.rst b/LUA_API.rst
index 32716fbf8..acbba3272 100644
--- a/LUA_API.rst
+++ b/LUA_API.rst
@@ -728,9 +728,15 @@ Units module
Returns the age of the unit in years as a floating-point value.
If ``true_age`` is true, ignores false identities.
-* ``dfhack.units.getProfessionName(unit[,plural])``
+* ``dfhack.units.getNoblePositions(unit)``
- Retrieves the profession name using custom profession or raws.
+ Returns a list of tables describing noble position assignments, or *nil*.
+ Every table has fields ``entity``, ``assignment`` and ``position``.
+
+* ``dfhack.units.getProfessionName(unit[,ignore_noble,plural])``
+
+ Retrieves the profession name using custom profession, noble assignments
+ or raws. The ``ignore_noble`` boolean disables the use of noble positions.
* ``dfhack.units.getCasteProfessionName(race,caste,prof_id[,plural])``
diff --git a/Lua API.html b/Lua API.html
index 916c6eef8..def3790c9 100644
--- a/Lua API.html
+++ b/Lua API.html
@@ -959,8 +959,13 @@ a lua list containing them.
Returns the age of the unit in years as a floating-point value.
If true_age is true, ignores false identities.
-dfhack.units.getProfessionName(unit[,plural])
-Retrieves the profession name using custom profession or raws.
+dfhack.units.getNoblePositions(unit)
+Returns a list of tables describing noble position assignments, or nil.
+Every table has fields entity, assignment and position.
+
+dfhack.units.getProfessionName(unit[,ignore_noble,plural])
+Retrieves the profession name using custom profession, noble assignments
+or raws. The ignore_noble boolean disables the use of noble positions.
dfhack.units.getCasteProfessionName(race,caste,prof_id[,plural])
Retrieves the profession name for the given race/caste using raws.
diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp
index 71df50e22..8c56379a7 100644
--- a/library/LuaApi.cpp
+++ b/library/LuaApi.cpp
@@ -61,6 +61,10 @@ distribution.
#include "df/assumed_identity.h"
#include "df/nemesis_record.h"
#include "df/historical_figure.h"
+#include "df/historical_entity.h"
+#include "df/entity_position.h"
+#include "df/entity_position_assignment.h"
+#include "df/histfig_entity_link_positionst.h"
#include "df/plant_raw.h"
#include "df/creature_raw.h"
#include "df/inorganic_raw.h"
@@ -628,8 +632,35 @@ static int units_getPosition(lua_State *state)
return Lua::PushPosXYZ(state, Units::getPosition(Lua::CheckDFObject(state,1)));
}
+static int units_getNoblePositions(lua_State *state)
+{
+ std::vector np;
+
+ if (Units::getNoblePositions(&np, Lua::CheckDFObject(state,1)))
+ {
+ lua_createtable(state, np.size(), 0);
+
+ for (size_t i = 0; i < np.size(); i++)
+ {
+ lua_createtable(state, 0, 3);
+ Lua::PushDFObject(state, np[i].entity);
+ lua_setfield(state, -2, "entity");
+ Lua::PushDFObject(state, np[i].assignment);
+ lua_setfield(state, -2, "assignment");
+ Lua::PushDFObject(state, np[i].position);
+ lua_setfield(state, -2, "position");
+ lua_rawseti(state, -2, i+1);
+ }
+ }
+ else
+ lua_pushnil(state);
+
+ return 1;
+}
+
static const luaL_Reg dfhack_units_funcs[] = {
{ "getPosition", units_getPosition },
+ { "getNoblePositions", units_getNoblePositions },
{ NULL, NULL }
};
diff --git a/library/include/modules/Units.h b/library/include/modules/Units.h
index 8e4fe2ade..e1f8baa12 100644
--- a/library/include/modules/Units.h
+++ b/library/include/modules/Units.h
@@ -38,6 +38,9 @@ namespace df
struct nemesis_record;
struct burrow;
struct assumed_identity;
+ struct historical_entity;
+ struct entity_position_assignment;
+ struct entity_position;
}
/**
@@ -218,7 +221,15 @@ DFHACK_EXPORT void setInBurrow(df::unit *unit, df::burrow *burrow, bool enable);
DFHACK_EXPORT double getAge(df::unit *unit, bool true_age = false);
-DFHACK_EXPORT std::string getProfessionName(df::unit *unit, bool plural = false);
+struct NoblePosition {
+ df::historical_entity *entity;
+ df::entity_position_assignment *assignment;
+ df::entity_position *position;
+};
+
+DFHACK_EXPORT bool getNoblePositions(std::vector *pvec, df::unit *unit);
+
+DFHACK_EXPORT std::string getProfessionName(df::unit *unit, bool ignore_noble = false, bool plural = false);
DFHACK_EXPORT std::string getCasteProfessionName(int race, int caste, df::profession pid, bool plural = false);
}
}
diff --git a/library/modules/Units.cpp b/library/modules/Units.cpp
index a691dc5d9..4ea225ade 100644
--- a/library/modules/Units.cpp
+++ b/library/modules/Units.cpp
@@ -55,6 +55,9 @@ using namespace std;
#include "df/historical_entity.h"
#include "df/historical_figure.h"
#include "df/historical_figure_info.h"
+#include "df/entity_position.h"
+#include "df/entity_position_assignment.h"
+#include "df/histfig_entity_link_positionst.h"
#include "df/assumed_identity.h"
#include "df/burrow.h"
#include "df/creature_raw.h"
@@ -762,14 +765,85 @@ double DFHack::Units::getAge(df::unit *unit, bool true_age)
return cur_time - birth_time;
}
-std::string DFHack::Units::getProfessionName(df::unit *unit, bool plural)
+static bool noble_pos_compare(const Units::NoblePosition &a, const Units::NoblePosition &b)
+{
+ if (a.position->precedence < b.position->precedence)
+ return true;
+ if (a.position->precedence > b.position->precedence)
+ return false;
+ return a.position->id < b.position->id;
+}
+
+bool DFHack::Units::getNoblePositions(std::vector *pvec, df::unit *unit)
+{
+ CHECK_NULL_POINTER(unit);
+
+ pvec->clear();
+
+ auto histfig = df::historical_figure::find(unit->hist_figure_id);
+ if (!histfig)
+ return false;
+
+ for (size_t i = 0; i < histfig->entity_links.size(); i++)
+ {
+ auto link = histfig->entity_links[i];
+ auto epos = strict_virtual_cast(link);
+ if (!epos)
+ continue;
+
+ NoblePosition pos;
+
+ pos.entity = df::historical_entity::find(epos->entity_id);
+ if (!pos.entity)
+ continue;
+
+ pos.assignment = binsearch_in_vector(pos.entity->positions.assignments, epos->assignment_id);
+ if (!pos.assignment)
+ continue;
+
+ pos.position = binsearch_in_vector(pos.entity->positions.own, pos.assignment->position_id);
+ if (!pos.position)
+ continue;
+
+ pvec->push_back(pos);
+ }
+
+ if (pvec->empty())
+ return false;
+
+ std::sort(pvec->begin(), pvec->end(), noble_pos_compare);
+ return true;
+}
+
+std::string DFHack::Units::getProfessionName(df::unit *unit, bool ignore_noble, bool plural)
{
std::string prof = unit->custom_profession;
+ if (!prof.empty())
+ return prof;
- if (prof.empty())
- prof = getCasteProfessionName(unit->race, unit->caste, unit->profession, plural);
+ std::vector np;
+
+ if (!ignore_noble && getNoblePositions(&np, unit))
+ {
+ switch (unit->sex)
+ {
+ case 0:
+ prof = np[0].position->name_female[plural ? 1 : 0];
+ break;
+ case 1:
+ prof = np[0].position->name_male[plural ? 1 : 0];
+ break;
+ default:
+ break;
+ }
+
+ if (prof.empty())
+ prof = np[0].position->name[plural ? 1 : 0];
+ if (!prof.empty())
+ return prof;
+ }
- return prof;
+ return getCasteProfessionName(unit->race, unit->caste, unit->profession, plural);
}
std::string DFHack::Units::getCasteProfessionName(int race, int casteid, df::profession pid, bool plural)
diff --git a/plugins/lua/sort/units.lua b/plugins/lua/sort/units.lua
index 7a332d094..35795502d 100644
--- a/plugins/lua/sort/units.lua
+++ b/plugins/lua/sort/units.lua
@@ -52,6 +52,15 @@ local function findRaceCaste(unit)
return rraw, safe_index(rraw, 'caste', unit.caste)
end
+orders.noble = {
+ key = function(unit)
+ local info = dfhack.units.getNoblePositions(unit)
+ if info then
+ return info[1].position.precedence
+ end
+ end
+}
+
orders.profession = {
key = function(unit)
local cp = dfhack.units.getProfessionName(unit)