@ -63,11 +63,15 @@ using namespace std;
# include "df/burrow.h"
# include "df/burrow.h"
# include "df/creature_raw.h"
# include "df/creature_raw.h"
# include "df/caste_raw.h"
# include "df/caste_raw.h"
# include "df/game_mode.h"
# include "df/unit_misc_trait.h"
# include "df/unit_skill.h"
using namespace DFHack ;
using namespace DFHack ;
using namespace df : : enums ;
using namespace df : : enums ;
using df : : global : : world ;
using df : : global : : world ;
using df : : global : : ui ;
using df : : global : : ui ;
using df : : global : : gamemode ;
bool Units : : isValid ( )
bool Units : : isValid ( )
{
{
@ -626,8 +630,9 @@ static bool casteFlagSet(int race, int caste, df::caste_raw_flags flag)
return craw - > flags . is_set ( flag ) ;
return craw - > flags . is_set ( flag ) ;
}
}
static bool isCrazed ( df : : unit * unit )
bool Units : : isCrazed ( df : : unit * unit )
{
{
CHECK_NULL_POINTER ( unit ) ;
if ( unit - > flags3 . bits . scuttle )
if ( unit - > flags3 . bits . scuttle )
return false ;
return false ;
if ( unit - > curse . rem_tags1 . bits . CRAZED )
if ( unit - > curse . rem_tags1 . bits . CRAZED )
@ -637,13 +642,54 @@ static bool isCrazed(df::unit *unit)
return casteFlagSet ( unit - > race , unit - > caste , caste_raw_flags : : CRAZED ) ;
return casteFlagSet ( unit - > race , unit - > caste , caste_raw_flags : : CRAZED ) ;
}
}
static bool isOpposedToLife ( df : : unit * unit )
bool Units : : isOpposedToLife ( df : : unit * unit )
{
{
CHECK_NULL_POINTER ( unit ) ;
if ( unit - > curse . rem_tags1 . bits . OPPOSED_TO_LIFE )
if ( unit - > curse . rem_tags1 . bits . OPPOSED_TO_LIFE )
return false ;
return false ;
if ( unit - > curse . add_tags1 . bits . OPPOSED_TO_LIFE )
if ( unit - > curse . add_tags1 . bits . OPPOSED_TO_LIFE )
return true ;
return true ;
return casteFlagSet ( unit - > race , unit - > caste , caste_raw_flags : : CANNOT_UNDEAD ) ;
return casteFlagSet ( unit - > race , unit - > caste , caste_raw_flags : : OPPOSED_TO_LIFE ) ;
}
bool Units : : hasExtravision ( df : : unit * unit )
{
CHECK_NULL_POINTER ( unit ) ;
if ( unit - > curse . rem_tags1 . bits . EXTRAVISION )
return false ;
if ( unit - > curse . add_tags1 . bits . EXTRAVISION )
return true ;
return casteFlagSet ( unit - > race , unit - > caste , caste_raw_flags : : EXTRAVISION ) ;
}
bool Units : : isBloodsucker ( df : : unit * unit )
{
CHECK_NULL_POINTER ( unit ) ;
if ( unit - > curse . rem_tags1 . bits . BLOODSUCKER )
return false ;
if ( unit - > curse . add_tags1 . bits . BLOODSUCKER )
return true ;
return casteFlagSet ( unit - > race , unit - > caste , caste_raw_flags : : BLOODSUCKER ) ;
}
df : : unit_misc_trait * Units : : getMiscTrait ( df : : unit * unit , df : : misc_trait_type type , bool create )
{
CHECK_NULL_POINTER ( unit ) ;
auto & vec = unit - > status . misc_traits ;
for ( size_t i = 0 ; i < vec . size ( ) ; i + + )
if ( vec [ i ] - > id = = type )
return vec [ i ] ;
if ( create )
{
auto obj = new df : : unit_misc_trait ( ) ;
obj - > id = type ;
vec . push_back ( obj ) ;
return obj ;
}
return NULL ;
}
}
bool DFHack : : Units : : isDead ( df : : unit * unit )
bool DFHack : : Units : : isDead ( df : : unit * unit )
@ -753,6 +799,113 @@ double DFHack::Units::getAge(df::unit *unit, bool true_age)
return cur_time - birth_time ;
return cur_time - birth_time ;
}
}
inline int adjust_skill_rating ( int & rating , bool is_adventure , int value , int dwarf3_4 , int dwarf1_2 , int adv9_10 , int adv3_4 , int adv1_2 )
{
if ( is_adventure )
{
if ( value > = adv1_2 ) rating > > = 1 ;
else if ( value > = adv3_4 ) rating = rating * 3 / 4 ;
else if ( value > = adv9_10 ) rating = rating * 9 / 10 ;
}
else
{
if ( value > = dwarf1_2 ) rating > > = 1 ;
else if ( value > = dwarf3_4 ) return rating * 3 / 4 ;
}
}
int Units : : getEffectiveSkill ( df : : unit * unit , df : : job_skill skill_id )
{
CHECK_NULL_POINTER ( unit ) ;
/*
* This is 100 % reverse - engineered from DF code .
*/
if ( ! unit - > status . current_soul )
return 0 ;
// Retrieve skill from unit soul:
df : : enum_field < df : : job_skill , int16_t > key ( skill_id ) ;
auto skill = binsearch_in_vector ( unit - > status . current_soul - > skills , & df : : unit_skill : : id , key ) ;
int rating = 0 ;
if ( skill )
rating = std : : max ( 0 , int ( skill - > rating ) - skill - > rusty ) ;
// Apply special states
if ( unit - > counters . soldier_mood = = df : : unit : : T_counters : : None )
{
if ( unit - > counters . nausea > 0 ) rating > > = 1 ;
if ( unit - > counters . winded > 0 ) rating > > = 1 ;
if ( unit - > counters . stunned > 0 ) rating > > = 1 ;
if ( unit - > counters . dizziness > 0 ) rating > > = 1 ;
if ( unit - > counters2 . fever > 0 ) rating > > = 1 ;
}
if ( unit - > counters . soldier_mood ! = df : : unit : : T_counters : : MartialTrance )
{
if ( ! unit - > flags3 . bits . ghostly & & ! unit - > flags3 . bits . scuttle & &
! unit - > flags2 . bits . vision_good & & ! unit - > flags2 . bits . vision_damaged & &
! hasExtravision ( unit ) )
{
rating > > = 2 ;
}
if ( unit - > counters . pain > = 100 & & unit - > mood = = - 1 )
{
rating > > = 1 ;
}
if ( unit - > counters2 . exhaustion > = 2000 )
{
rating = rating * 3 / 4 ;
if ( unit - > counters2 . exhaustion > = 4000 )
{
rating = rating * 3 / 4 ;
if ( unit - > counters2 . exhaustion > = 6000 )
rating = rating * 3 / 4 ;
}
}
}
// Hunger etc timers
bool is_adventure = ( gamemode & & * gamemode = = game_mode : : ADVENTURE ) ;
if ( ! unit - > flags3 . bits . scuttle & & isBloodsucker ( unit ) )
{
using namespace df : : enums : : misc_trait_type ;
if ( auto trait = getMiscTrait ( unit , TimeSinceSuckedBlood ) )
{
adjust_skill_rating (
rating , is_adventure , trait - > value ,
302400 , 403200 , // dwf 3/4; 1/2
1209600 , 1209600 , 2419200 // adv 9/10; 3/4; 1/2
) ;
}
}
adjust_skill_rating (
rating , is_adventure , unit - > counters2 . thirst_timer ,
50000 , 50000 , 115200 , 172800 , 345600
) ;
adjust_skill_rating (
rating , is_adventure , unit - > counters2 . hunger_timer ,
75000 , 75000 , 172800 , 1209600 , 2592000
) ;
if ( is_adventure & & unit - > counters2 . sleepiness_timer > = 846000 )
rating > > = 2 ;
else
adjust_skill_rating (
rating , is_adventure , unit - > counters2 . sleepiness_timer ,
150000 , 150000 , 172800 , 259200 , 345600
) ;
return rating ;
}
static bool noble_pos_compare ( const Units : : NoblePosition & a , const Units : : NoblePosition & b )
static bool noble_pos_compare ( const Units : : NoblePosition & a , const Units : : NoblePosition & b )
{
{
if ( a . position - > precedence < b . position - > precedence )
if ( a . position - > precedence < b . position - > precedence )