Merge pull request #2387 from cppcooper/units-checking

Extends Units module
develop
Myk 2022-11-14 16:55:42 -08:00 committed by GitHub
commit 966623a919
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 1041 additions and 776 deletions

@ -1188,6 +1188,187 @@ Job module
Units module
------------
* ``dfhack.units.isUnitInBox(unit,x1,y1,z1,x2,y2,z2)``
The unit is within the specified coordinates.
* ``dfhack.units.isActive(unit)``
The unit is active (alive and on the map).
* ``dfhack.units.isVisible(unit)``
The unit is visible on the map.
* ``dfhack.units.isCitizen(unit[,ignore_sanity])``
The unit is an alive sane citizen of the fortress; wraps the
same checks the game uses to decide game-over by extinction,
with an additional sanity check. You can identify citizens,
regardless of their sanity, by passing ``true`` as the optional
second parameter.
* ``dfhack.units.isFortControlled(unit)``
Similar to ``dfhack.units.isCitizen(unit)``, but is based on checks
for units hidden in ambush, and includes tame animals. Returns *false*
if not in fort mode.
* ``dfhack.units.isOwnCiv(unit)``
The unit belongs to the player's civilization.
* ``dfhack.units.isOwnGroup(unit)``
The unit belongs to the player's group.
* ``dfhack.units.isOwnRace(unit)``
The unit belongs to the player's race.
* ``dfhack.units.isAlive(unit)``
The unit isn't dead or undead.
* ``dfhack.units.isDead(unit)``
The unit is completely dead and passive, or a ghost. Equivalent to
``dfhack.units.isKilled(unit) or dfhack.units.isGhost(unit)``.
* ``dfhack.units.isKilled(unit)``
The unit has been killed.
* ``dfhack.units.isSane(unit)``
The unit is capable of rational action, i.e. not dead, insane, zombie, or active werewolf.
* ``dfhack.units.isCrazed``
The unit is berserk and will attack all other creatures except members of its own species
that are also crazed. (can be modified by curses)
* ``dfhack.units.isGhost(unit)``
The unit is a ghost.
* ``dfhack.units.isHidden(unit)``
The unit is hidden to the player, accounting for sneaking. Works for any game mode.
* ``dfhack.units.isHidingCurse(unit)``
The unit is hiding a curse.
* ``dfhack.units.isMale(unit)``
* ``dfhack.units.isFemale(unit)``
* ``dfhack.units.isBaby(unit)``
* ``dfhack.units.isChild(unit)``
* ``dfhack.units.isAdult(unit)``
* ``dfhack.units.isGay(unit)``
* ``dfhack.units.isNaked(unit)``
Simple unit property checks
* ``dfhack.units.isVisiting(unit)``
The unit is visiting. eg. Merchants, Diplomatics, travelers.
* ``dfhack.units.isTrainableHunting(unit)``
The unit is trainable for hunting.
* ``dfhack.units.isTrainableWar(unit)``
The unit is trainable for war.
* ``dfhack.units.isTrained(unit)``
The unit is trained.
* ``dfhack.units.isHunter(unit)``
The unit is a trained hunter.
* ``dfhack.units.isWar(unit)``
The unit is trained for war.
* ``dfhack.units.isTame(unit)``
* ``dfhack.units.isTamable(unit)``
* ``dfhack.units.isDomesticated(unit)``
* ``dfhack.units.isMarkedForSlaughter(unit)``
* ``dfhack.units.isGelded(unit)``
* ``dfhack.units.isEggLayer(unit)``
* ``dfhack.units.isGrazer(unit)``
* ``dfhack.units.isMilkable(unit)``
Simple unit property checks.
* ``dfhack.units.isForest(unit)``
The unit is of the forest.
* ``dfhack.units.isMischievous(unit)``
The unit is mischievous.
* ``dfhack.units.isAvailableForAdoption(unit)``
The unit is available for adoption.
* ``dfhack.units.isOpposedToLife(unit)``
* ``dfhack.units.hasExtravision(unit)``
* ``dfhack.units.isBloodsucker(unit)``
Simple checks of caste attributes that can be modified by curses.
* ``dfhack.units.isDwarf(unit)``
The unit is of the correct race for the fortress.
* ``dfhack.units.isAnimal(unit)``
* ``dfhack.units.isMerchant(unit)``
* ``dfhack.units.isDiplomat(unit)``
Simple unit type checks.
* ``dfhack.units.isVisitor(unit)``
The unit is a regular visitor with no special purpose (eg. merchant).
* ``dfhack.units.isInvader(unit)``
The unit is an active invader or marauder.
* ``dfhack.units.isUndead(unit[,include_vamps])``
The unit is undead. Pass ``true`` as the optional second parameter to
count vampires as undead.
* ``dfhack.units.isNightCreature(unit)``
* ``dfhack.units.isSemiMegabeast(unit)``
* ``dfhack.units.isMegabeast(unit)``
* ``dfhack.units.isTitan(unit)``
* ``dfhack.units.isDemon(unit)``
Simple enemy type checks.
* ``dfhack.units.isDanger(unit)``
The unit is dangerous, and probably hostile. This includes
Great Dangers (see below), semi-megabeasts, night creatures,
undead, invaders, and crazed units.
* ``dfhack.units.isGreatDanger(unit)``
The unit is of Great Danger. This include demons, titans, and megabeasts.
* ``dfhack.units.getPosition(unit)``
Returns true *x,y,z* of the unit, or *nil* if invalid; may be not equal to unit.pos if caged.
@ -1238,72 +1419,15 @@ Units module
Returns the nemesis record of the unit if it has one, or *nil*.
* ``dfhack.units.isHidingCurse(unit)``
Checks if the unit hides improved attributes from its curse.
* ``dfhack.units.getPhysicalAttrValue(unit, attr_type)``
* ``dfhack.units.getMentalAttrValue(unit, attr_type)``
Computes the effective attribute value, including curse effect.
* ``dfhack.units.isCrazed(unit)``
* ``dfhack.units.isOpposedToLife(unit)``
* ``dfhack.units.hasExtravision(unit)``
* ``dfhack.units.isBloodsucker(unit)``
Simple checks of caste attributes that can be modified by curses.
* ``dfhack.units.getMiscTrait(unit, type[, create])``
Finds (or creates if requested) a misc trait object with the given id.
* ``dfhack.units.isActive(unit)``
The unit is active (alive and on the map).
* ``dfhack.units.isAlive(unit)``
The unit isn't dead or undead.
* ``dfhack.units.isDead(unit)``
The unit is completely dead and passive, or a ghost. Equivalent to
``dfhack.units.isKilled(unit) or dfhack.units.isGhost(unit)``.
* ``dfhack.units.isKilled(unit)``
The unit has been killed.
* ``dfhack.units.isGhost(unit)``
The unit is a ghost.
* ``dfhack.units.isSane(unit)``
The unit is capable of rational action, i.e. not dead, insane, zombie, or active werewolf.
* ``dfhack.units.isDwarf(unit)``
The unit is of the correct race of the fortress.
* ``dfhack.units.isCitizen(unit)``
The unit is an alive sane citizen of the fortress; wraps the
same checks the game uses to decide game-over by extinction.
* ``dfhack.units.isFortControlled(unit)``
Similar to ``dfhack.units.isCitizen(unit)``, but is based on checks for units hidden in ambush, and includes tame animals. Returns *false* if not in fort mode.
* ``dfhack.units.isVisible(unit)``
The unit is visible on the map.
* ``dfhack.units.isHidden(unit)``
The unit is hidden to the player, accounting for sneaking. Works for any game mode.
* ``dfhack.units.getAge(unit[,true_age])``
Returns the age of the unit in years as a floating-point value.

@ -77,6 +77,22 @@ changelog.txt uses a syntax similar to RST, with a few special sequences:
- ``Gui::anywhere_hotkey``: for plugin commands bound to keybindings that can be invoked on any screen
- ``Lua::PushInterfaceKeys()``: transforms viewscreen ``feed()`` keys into something that can be interpreted by lua-based widgets
- ``Lua::Push()``: now handles maps with otherwise supported keys and values
- Units module: added new checks
- ``isUnitInBox()``
- ``isAnimal()``
- ``isVisiting()`` any visiting unit (diplomat, merchant, visitor)
- ``isVisitor()`` ie. not merchants or diplomats
- ``isInvader()``
- ``isDemon()`` returns true for unique/regular demons
- ``isTitan()``
- ``isMegabeast()``
- ``isGreatDanger()`` returns true if unit is a demon, titan, or megabeast
- ``isSemiMegabeast()``
- ``isNightCreature()``
- ``isDanger()`` returns true if is a 'GreatDanger', semi-megabeast, night creature, undead, or invader
- Units module: modifies existing checks
- ``isUndead(df::unit* unit)`` => ``isUndead(df::unit* unit, bool ignore_vamps = true)`` isUndead used to always ignore vamps, now it does it by default and includes them when false is passed
- ``isCitizen(df::unit* unit)`` => ``isCitizen(df::unit* unit, bool ignore_sanity = false)`` isCitizen used to always check sanity, now it does it by default and ignores sanity when true is passed
- Constructions module: added ``insert()`` to insert constructions into the game's sorted list.
- MiscUtils: moved the following string transformation functions from ``uicommon.h``: ``int_to_string``, ``ltrim``, ``rtrim``, and ``trim``; added ``string_to_int``

@ -1559,6 +1559,63 @@ static const luaL_Reg dfhack_job_funcs[] = {
/***** Units module *****/
static const LuaWrapper::FunctionReg dfhack_units_module[] = {
WRAPM(Units, isUnitInBox),
WRAPM(Units, isActive),
WRAPM(Units, isVisible),
WRAPM(Units, isCitizen),
WRAPM(Units, isFortControlled),
WRAPM(Units, isOwnCiv),
WRAPM(Units, isOwnGroup),
WRAPM(Units, isOwnRace),
WRAPM(Units, isAlive),
WRAPM(Units, isDead),
WRAPM(Units, isKilled),
WRAPM(Units, isSane),
WRAPM(Units, isCrazed),
WRAPM(Units, isGhost),
WRAPM(Units, isHidden),
WRAPM(Units, isHidingCurse),
WRAPM(Units, isMale),
WRAPM(Units, isFemale),
WRAPM(Units, isBaby),
WRAPM(Units, isChild),
WRAPM(Units, isAdult),
WRAPM(Units, isGay),
WRAPM(Units, isNaked),
WRAPM(Units, isVisiting),
WRAPM(Units, isTrainableHunting),
WRAPM(Units, isTrainableWar),
WRAPM(Units, isTrained),
WRAPM(Units, isHunter),
WRAPM(Units, isWar),
WRAPM(Units, isTame),
WRAPM(Units, isTamable),
WRAPM(Units, isDomesticated),
WRAPM(Units, isMarkedForSlaughter),
WRAPM(Units, isGelded),
WRAPM(Units, isEggLayer),
WRAPM(Units, isGrazer),
WRAPM(Units, isMilkable),
WRAPM(Units, isForest),
WRAPM(Units, isMischievous),
WRAPM(Units, isAvailableForAdoption),
WRAPM(Units, hasExtravision),
WRAPM(Units, isOpposedToLife),
WRAPM(Units, isBloodsucker),
WRAPM(Units, isDwarf),
WRAPM(Units, isAnimal),
WRAPM(Units, isMerchant),
WRAPM(Units, isDiplomat),
WRAPM(Units, isVisitor),
WRAPM(Units, isInvader),
WRAPM(Units, isUndead),
WRAPM(Units, isNightCreature),
WRAPM(Units, isSemiMegabeast),
WRAPM(Units, isMegabeast),
WRAPM(Units, isTitan),
WRAPM(Units, isDemon),
WRAPM(Units, isDanger),
WRAPM(Units, isGreatDanger),
WRAPM(Units, teleport),
WRAPM(Units, getGeneralRef),
WRAPM(Units, getSpecificRef),
@ -1567,23 +1624,9 @@ static const LuaWrapper::FunctionReg dfhack_units_module[] = {
WRAPM(Units, getVisibleName),
WRAPM(Units, getIdentity),
WRAPM(Units, getNemesis),
WRAPM(Units, isHidingCurse),
WRAPM(Units, getPhysicalAttrValue),
WRAPM(Units, getMentalAttrValue),
WRAPM(Units, isCrazed),
WRAPM(Units, isOpposedToLife),
WRAPM(Units, hasExtravision),
WRAPM(Units, isBloodsucker),
WRAPM(Units, isMischievous),
WRAPM(Units, getMiscTrait),
WRAPM(Units, isDead),
WRAPM(Units, isAlive),
WRAPM(Units, isSane),
WRAPM(Units, isDwarf),
WRAPM(Units, isCitizen),
WRAPM(Units, isFortControlled),
WRAPM(Units, isVisible),
WRAPM(Units, isHidden),
WRAPM(Units, getAge),
WRAPM(Units, getKillCount),
WRAPM(Units, getNominalSkill),
@ -1601,12 +1644,6 @@ static const LuaWrapper::FunctionReg dfhack_units_module[] = {
WRAPM(Units, getGoalName),
WRAPM(Units, isGoalAchieved),
WRAPM(Units, getSquadName),
WRAPM(Units, isWar),
WRAPM(Units, isHunter),
WRAPM(Units, isAvailableForAdoption),
WRAPM(Units, isOwnCiv),
WRAPM(Units, isOwnGroup),
WRAPM(Units, isOwnRace),
WRAPM(Units, getPhysicalDescription),
WRAPM(Units, getRaceName),
WRAPM(Units, getRaceNamePlural),
@ -1615,31 +1652,6 @@ static const LuaWrapper::FunctionReg dfhack_units_module[] = {
WRAPM(Units, getRaceBabyNameById),
WRAPM(Units, getRaceChildName),
WRAPM(Units, getRaceChildNameById),
WRAPM(Units, isBaby),
WRAPM(Units, isChild),
WRAPM(Units, isAdult),
WRAPM(Units, isEggLayer),
WRAPM(Units, isGrazer),
WRAPM(Units, isMilkable),
WRAPM(Units, isTrainableWar),
WRAPM(Units, isTrainableHunting),
WRAPM(Units, isTamable),
WRAPM(Units, isMale),
WRAPM(Units, isFemale),
WRAPM(Units, isMerchant),
WRAPM(Units, isDiplomat),
WRAPM(Units, isForest),
WRAPM(Units, isMarkedForSlaughter),
WRAPM(Units, isTame),
WRAPM(Units, isTrained),
WRAPM(Units, isGay),
WRAPM(Units, isNaked),
WRAPM(Units, isUndead),
WRAPM(Units, isGhost),
WRAPM(Units, isActive),
WRAPM(Units, isKilled),
WRAPM(Units, isGelded),
WRAPM(Units, isDomesticated),
WRAPM(Units, getMainSocialActivity),
WRAPM(Units, getMainSocialEvent),
WRAPM(Units, getStressCategory),
@ -1705,6 +1717,8 @@ static int units_getUnitsInBox(lua_State *state)
{
luaL_checktype(state, 7, LUA_TFUNCTION);
units.erase(std::remove_if(units.begin(), units.end(), [&state](df::unit *unit) -> bool {
// todo: merging this filter into the base function would be welcomed by plugins
// (it would also be faster, and less obfuscated than this [ie. erase(remove_if)])
lua_dup(state); // copy function
Lua::PushDFObject(state, unit);
lua_call(state, 1, 1);

@ -68,6 +68,73 @@ static const int MAX_COLORS = 15;
* The Units module - allows reading all non-vermin units and their properties
*/
DFHACK_EXPORT bool isUnitInBox(df::unit* u,
int16_t x1, int16_t y1, int16_t z1,
int16_t x2, int16_t y2, int16_t z2);
DFHACK_EXPORT bool isActive(df::unit *unit);
DFHACK_EXPORT bool isVisible(df::unit* unit);
DFHACK_EXPORT bool isCitizen(df::unit *unit, bool ignore_sanity = false);
DFHACK_EXPORT bool isFortControlled(df::unit *unit);
DFHACK_EXPORT bool isOwnCiv(df::unit* unit);
DFHACK_EXPORT bool isOwnGroup(df::unit* unit);
DFHACK_EXPORT bool isOwnRace(df::unit* unit);
DFHACK_EXPORT bool isAlive(df::unit *unit);
DFHACK_EXPORT bool isDead(df::unit *unit);
DFHACK_EXPORT bool isKilled(df::unit *unit);
DFHACK_EXPORT bool isSane(df::unit *unit);
DFHACK_EXPORT bool isCrazed(df::unit *unit);
DFHACK_EXPORT bool isGhost(df::unit *unit);
/// is unit hidden to the player? accounts for ambushing
DFHACK_EXPORT bool isHidden(df::unit *unit);
DFHACK_EXPORT bool isHidingCurse(df::unit *unit);
DFHACK_EXPORT bool isMale(df::unit* unit);
DFHACK_EXPORT bool isFemale(df::unit* unit);
DFHACK_EXPORT bool isBaby(df::unit* unit);
DFHACK_EXPORT bool isChild(df::unit* unit);
DFHACK_EXPORT bool isAdult(df::unit* unit);
DFHACK_EXPORT bool isGay(df::unit* unit);
DFHACK_EXPORT bool isNaked(df::unit* unit);
DFHACK_EXPORT bool isVisiting(df::unit* unit);
DFHACK_EXPORT bool isTrainableHunting(df::unit* unit);
DFHACK_EXPORT bool isTrainableWar(df::unit* unit);
DFHACK_EXPORT bool isTrained(df::unit* unit);
DFHACK_EXPORT bool isHunter(df::unit* unit);
DFHACK_EXPORT bool isWar(df::unit* unit);
DFHACK_EXPORT bool isTame(df::unit* unit);
DFHACK_EXPORT bool isTamable(df::unit* unit);
DFHACK_EXPORT bool isDomesticated(df::unit* unit);
DFHACK_EXPORT bool isMarkedForSlaughter(df::unit* unit);
DFHACK_EXPORT bool isGelded(df::unit* unit);
DFHACK_EXPORT bool isEggLayer(df::unit* unit);
DFHACK_EXPORT bool isGrazer(df::unit* unit);
DFHACK_EXPORT bool isMilkable(df::unit* unit);
DFHACK_EXPORT bool isForest(df::unit* unit);
DFHACK_EXPORT bool isMischievous(df::unit *unit);
DFHACK_EXPORT bool isAvailableForAdoption(df::unit* unit);
DFHACK_EXPORT bool hasExtravision(df::unit *unit);
DFHACK_EXPORT bool isOpposedToLife(df::unit *unit);
DFHACK_EXPORT bool isBloodsucker(df::unit *unit);
DFHACK_EXPORT bool isDwarf(df::unit *unit);
DFHACK_EXPORT bool isAnimal(df::unit* unit);
DFHACK_EXPORT bool isMerchant(df::unit* unit);
DFHACK_EXPORT bool isDiplomat(df::unit* unit);
DFHACK_EXPORT bool isVisitor(df::unit* unit);
DFHACK_EXPORT bool isInvader(df::unit* unit);
DFHACK_EXPORT bool isUndead(df::unit* unit, bool include_vamps = false);
DFHACK_EXPORT bool isNightCreature(df::unit* unit);
DFHACK_EXPORT bool isSemiMegabeast(df::unit* unit);
DFHACK_EXPORT bool isMegabeast(df::unit* unit);
DFHACK_EXPORT bool isTitan(df::unit* unit);
DFHACK_EXPORT bool isDemon(df::unit* unit);
DFHACK_EXPORT bool isDanger(df::unit* unit);
DFHACK_EXPORT bool isGreatDanger(df::unit* unit);
/* Read Functions */
// Read units in a box, starting with index. Returns -1 if no more units
// found. Call repeatedly do get all units in a specified box (uses tile coords)
@ -99,35 +166,12 @@ DFHACK_EXPORT df::language_name *getVisibleName(df::unit *unit);
DFHACK_EXPORT df::identity *getIdentity(df::unit *unit);
DFHACK_EXPORT df::nemesis_record *getNemesis(df::unit *unit);
DFHACK_EXPORT bool isHidingCurse(df::unit *unit);
DFHACK_EXPORT int getPhysicalAttrValue(df::unit *unit, df::physical_attribute_type attr);
DFHACK_EXPORT int getMentalAttrValue(df::unit *unit, df::mental_attribute_type attr);
DFHACK_EXPORT bool casteFlagSet(int race, int caste, df::caste_raw_flags flag);
DFHACK_EXPORT bool isCrazed(df::unit *unit);
DFHACK_EXPORT bool isOpposedToLife(df::unit *unit);
DFHACK_EXPORT bool hasExtravision(df::unit *unit);
DFHACK_EXPORT bool isBloodsucker(df::unit *unit);
DFHACK_EXPORT bool isMischievous(df::unit *unit);
DFHACK_EXPORT df::unit_misc_trait *getMiscTrait(df::unit *unit, df::misc_trait_type type, bool create = false);
DFHACK_EXPORT bool isDead(df::unit *unit);
DFHACK_EXPORT bool isAlive(df::unit *unit);
DFHACK_EXPORT bool isSane(df::unit *unit);
DFHACK_EXPORT bool isCitizen(df::unit *unit);
DFHACK_EXPORT bool isFortControlled(df::unit *unit);
DFHACK_EXPORT bool isDwarf(df::unit *unit);
DFHACK_EXPORT bool isWar(df::unit* unit);
DFHACK_EXPORT bool isHunter(df::unit* unit);
DFHACK_EXPORT bool isAvailableForAdoption(df::unit* unit);
DFHACK_EXPORT bool isOwnCiv(df::unit* unit);
DFHACK_EXPORT bool isOwnGroup(df::unit* unit);
DFHACK_EXPORT bool isOwnRace(df::unit* unit);
DFHACK_EXPORT bool isVisible(df::unit* unit);
/// is unit hidden to the player? accounts for ambushing
DFHACK_EXPORT bool isHidden(df::unit *unit);
DFHACK_EXPORT std::string getRaceNameById(int32_t race_id);
DFHACK_EXPORT std::string getRaceName(df::unit* unit);
DFHACK_EXPORT std::string getPhysicalDescription(df::unit* unit);
@ -138,31 +182,6 @@ DFHACK_EXPORT std::string getRaceBabyName(df::unit* unit);
DFHACK_EXPORT std::string getRaceChildNameById(int32_t race_id);
DFHACK_EXPORT std::string getRaceChildName(df::unit* unit);
DFHACK_EXPORT bool isBaby(df::unit* unit);
DFHACK_EXPORT bool isChild(df::unit* unit);
DFHACK_EXPORT bool isAdult(df::unit* unit);
DFHACK_EXPORT bool isEggLayer(df::unit* unit);
DFHACK_EXPORT bool isGrazer(df::unit* unit);
DFHACK_EXPORT bool isMilkable(df::unit* unit);
DFHACK_EXPORT bool isTrainableWar(df::unit* unit);
DFHACK_EXPORT bool isTrainableHunting(df::unit* unit);
DFHACK_EXPORT bool isTamable(df::unit* unit);
DFHACK_EXPORT bool isMale(df::unit* unit);
DFHACK_EXPORT bool isFemale(df::unit* unit);
DFHACK_EXPORT bool isMerchant(df::unit* unit);
DFHACK_EXPORT bool isDiplomat(df::unit* unit);
DFHACK_EXPORT bool isForest(df::unit* unit);
DFHACK_EXPORT bool isMarkedForSlaughter(df::unit* unit);
DFHACK_EXPORT bool isTame(df::unit* unit);
DFHACK_EXPORT bool isTrained(df::unit* unit);
DFHACK_EXPORT bool isGay(df::unit* unit);
DFHACK_EXPORT bool isNaked(df::unit* unit);
DFHACK_EXPORT bool isUndead(df::unit* unit);
DFHACK_EXPORT bool isGhost(df::unit *unit);
DFHACK_EXPORT bool isActive(df::unit *unit);
DFHACK_EXPORT bool isKilled(df::unit *unit);
DFHACK_EXPORT bool isGelded(df::unit* unit);
DFHACK_EXPORT bool isDomesticated(df::unit* unit);
DFHACK_EXPORT double getAge(df::unit *unit, bool true_age = false);
DFHACK_EXPORT int getKillCount(df::unit *unit);

File diff suppressed because it is too large Load Diff