Extends Units module

develop
Josh Cooper 2022-11-09 14:41:45 -08:00
parent c0ffcc2f79
commit 80824f5b75
3 changed files with 68 additions and 10 deletions

@ -72,7 +72,21 @@ changelog.txt uses a syntax similar to RST, with a few special sequences:
## API
- ``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 ``isAnimal()``, ``isDemon()``, ``isTitan()``, ``isMegabeast()``, ``isSemiMegabeast()``, and ``isNightCreature()``
- Units module: added new checks
- ``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``

@ -115,7 +115,7 @@ DFHACK_EXPORT df::unit_misc_trait *getMiscTrait(df::unit *unit, df::misc_trait_t
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 isCitizen(df::unit *unit, bool ignore_sanity = false);
DFHACK_EXPORT bool isFortControlled(df::unit *unit);
DFHACK_EXPORT bool isDwarf(df::unit *unit);
DFHACK_EXPORT bool isWar(df::unit* unit);
@ -138,6 +138,7 @@ 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 isInvader(df::unit* unit);
DFHACK_EXPORT bool isBaby(df::unit* unit);
DFHACK_EXPORT bool isChild(df::unit* unit);
DFHACK_EXPORT bool isAdult(df::unit* unit);
@ -150,15 +151,17 @@ 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 isVisiting(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 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 isUndead(df::unit* unit, bool ignore_vamps = true);
DFHACK_EXPORT bool isGhost(df::unit *unit);
DFHACK_EXPORT bool isActive(df::unit *unit);
DFHACK_EXPORT bool isKilled(df::unit *unit);
@ -167,8 +170,11 @@ DFHACK_EXPORT bool isDomesticated(df::unit* unit);
DFHACK_EXPORT bool isDemon(df::unit* unit);
DFHACK_EXPORT bool isTitan(df::unit* unit);
DFHACK_EXPORT bool isMegabeast(df::unit* unit);
DFHACK_EXPORT bool isGreatDanger(df::unit* unit);
DFHACK_EXPORT bool isSemiMegabeast(df::unit* unit);
DFHACK_EXPORT bool isNightCreature(df::unit* unit);
DFHACK_EXPORT bool isDanger(df::unit* unit);
DFHACK_EXPORT double getAge(df::unit *unit, bool true_age = false);
DFHACK_EXPORT int getKillCount(df::unit *unit);

@ -499,7 +499,7 @@ bool Units::isSane(df::unit *unit)
return true;
}
bool Units::isCitizen(df::unit *unit)
bool Units::isCitizen(df::unit *unit, bool ignore_sanity)
{
CHECK_NULL_POINTER(unit);
@ -519,7 +519,7 @@ bool Units::isCitizen(df::unit *unit)
unit->flags2.bits.resident)
return false;
if (!isSane(unit))
if (!ignore_sanity && !isSane(unit))
return false;
return isOwnGroup(unit);
@ -752,6 +752,15 @@ string Units::getRaceChildName(df::unit* unit)
return getRaceChildNameById(unit->race);
}
bool Units::isInvader(df::unit* unit) {
CHECK_NULL_POINTER(unit);
return !isOwnGroup(unit) &&
(unit->flags1.bits.marauder ||
unit->flags1.bits.invader_origin ||
unit->flags1.bits.active_invader);
}
bool Units::isBaby(df::unit* unit)
{
CHECK_NULL_POINTER(unit);
@ -1666,6 +1675,15 @@ df::activity_event *Units::getMainSocialEvent(df::unit *unit)
return entry->events[entry->events.size() - 1];
}
bool Units::isVisiting(df::unit* unit) {
CHECK_NULL_POINTER(unit);
return unit->flags1.bits.merchant ||
unit->flags1.bits.diplomat ||
unit->flags2.bits.visitor ||
unit->flags2.bits.visitor_uninvited;
}
bool Units::isMerchant(df::unit* unit)
{
CHECK_NULL_POINTER(unit);
@ -1680,6 +1698,12 @@ bool Units::isDiplomat(df::unit* unit)
return unit->flags1.bits.diplomat == 1;
}
bool Units::isVisitor(df::unit* unit)
{
CHECK_NULL_POINTER(unit);
return unit->flags2.bits.visitor || unit->flags2.bits.visitor_uninvited;
}
bool Units::isForest(df::unit* unit)
{
CHECK_NULL_POINTER(unit);
@ -1763,13 +1787,13 @@ bool Units::isNaked(df::unit* unit)
return (unit->inventory.empty());
}
bool Units::isUndead(df::unit* unit)
bool Units::isUndead(df::unit* unit, bool ignore_vamps)
{
CHECK_NULL_POINTER(unit);
// ignore vampires, they should be treated like normal dwarves
return (unit->flags3.bits.ghostly ||
( (unit->curse.add_tags1.bits.OPPOSED_TO_LIFE || unit->curse.add_tags1.bits.NOT_LIVING)
&& !unit->curse.add_tags1.bits.BLOODSUCKER ));
const auto &cb = unit->curse.add_tags1.bits;
return unit->flags3.bits.ghostly ||
((cb.OPPOSED_TO_LIFE || cb.NOT_LIVING) && (!ignore_vamps || !cb.BLOODSUCKER));
}
bool Units::isGhost(df::unit *unit)
@ -1850,6 +1874,12 @@ bool Units::isMegabeast(df::unit* unit)
return unit->enemy.caste_flags.is_set(df::enums::caste_raw_flags::MEGABEAST);
}
bool Units::isGreatDanger(df::unit* unit)
{
CHECK_NULL_POINTER(unit);
return isDemon(unit) || isTitan(unit) || isMegabeast(unit);
}
bool Units::isSemiMegabeast(df::unit* unit)
{
CHECK_NULL_POINTER(unit);
@ -1862,6 +1892,14 @@ bool Units::isNightCreature(df::unit* unit)
return unit->enemy.caste_flags.is_set(df::enums::caste_raw_flags::NIGHT_CREATURE);
}
bool Units::isDanger(df::unit* unit) {
CHECK_NULL_POINTER(unit);
return isInvader(unit) ||
isUndead(unit, false) ||
isSemiMegabeast(unit) ||
isNightCreature(unit) ||
isGreatDanger(unit);
}
// 50000 and up is level 0, 25000 and up is level 1, etc.
const vector<int32_t> Units::stress_cutoffs {50000, 25000, 10000, -10000, -25000, -50000, -100000};