long visitable<Character>::charges_of( const std::string &what, int limit ) const { auto self = static_cast<const Character *>( this ); auto p = dynamic_cast<const player *>( self ); if( what == "toolset") { if( p && p->has_active_bionic( "bio_tools" ) ) { return std::min( p->power_level, limit ); } else { return 0; } } if( what == "UPS" ) { long qty = 0; qty += charges_of( "UPS_off" ); qty += charges_of( "adv_UPS_off" ) / 0.6; if ( p && p->has_active_bionic( "bio_ups" ) ) { qty += p->power_level * 10; } return std::min( qty, long( limit ) ); } return charges_of_internal( *this, what, limit ); }
bool player::can_feed_battery_with( const item &it ) const { if( !it.is_ammo() || can_eat( it ).success() || !has_active_bionic( bio_batteries ) ) { return false; } return it.type->ammo->type.count( ammotype( "battery" ) ); }
bool player::can_feed_reactor_with( const item &it ) const { static const std::set<ammotype> acceptable = {{ ammotype( "reactor_slurry" ), ammotype( "plutonium" ) } }; if( !it.is_ammo() || can_eat( it ).success() ) { return false; } if( !has_active_bionic( bio_reactor ) && !has_active_bionic( bio_advreactor ) ) { return false; } return std::any_of( acceptable.begin(), acceptable.end(), [ &it ]( const ammotype & elem ) { return it.type->ammo->type.count( elem ); } ); }
bool player::can_arm_block() { martialart ma = martialarts[style_selected]; if (ma.arm_block < 0 || !(ma.arm_block_with_bio_armor_arms && has_bionic("bio_armor_arms"))) return false; int unarmed_skill = has_active_bionic("bio_cqb") ? 5 : (int)skillLevel("unarmed"); if (unarmed_skill < ma.arm_block && !(ma.arm_block_with_bio_armor_arms && has_bionic("bio_armor_arms"))) return false; if (hp_cur[hp_arm_l] > 0 || hp_cur[hp_arm_r] > 0) return true; else return false; }
bool Character::has_nv() { static bool nv = false; if( !nv_cached ) { nv_cached = true; nv = (worn_with_flag("GNV_EFFECT") || has_active_bionic("bio_night_vision")); } return nv; }
bool player::can_feed_furnace_with( const item &it ) const { if( !it.flammable() || it.has_flag( "RADIOACTIVE" ) || can_eat( it ).success() ) { return false; } if( !has_active_bionic( bio_furnace ) ) { return false; } return it.typeId() != "corpse"; // @todo Eliminate the hard-coded special case. }
bool player::can_arm_block() { martialart ma = martialarts[style_selected]; int unarmed_skill = has_active_bionic("bio_cqb") ? 5 : (int)skillLevel("unarmed"); // Success conditions. if (hp_cur[hp_arm_l] > 0 || hp_cur[hp_arm_r] > 0) { if( unarmed_skill >= ma.arm_block ) { return true; } else if( ma.arm_block_with_bio_armor_arms && has_bionic("bio_armor_arms") ) { return true; } } // if not above, can't block. return false; }
bool player::can_arm_block() const { const martialart &ma = style_selected.obj(); ///\EFFECT_UNARMED increases ability to perform arm block int unarmed_skill = has_active_bionic( bionic_id( "bio_cqb" ) ) ? 5 : (int)get_skill_level(skill_id("unarmed")); // Success conditions. if (hp_cur[hp_arm_l] > 0 || hp_cur[hp_arm_r] > 0) { if( unarmed_skill >= ma.arm_block ) { return true; } else if( ma.arm_block_with_bio_armor_arms && has_bionic( bionic_id( "bio_armor_arms" ) ) ) { return true; } } // if not above, can't block. return false; }
int visitable<Character>::amount_of( const std::string& what, bool pseudo, int limit ) const { auto self = static_cast<const Character *>( this ); if( what == "toolset" && pseudo && self->has_active_bionic( "bio_tools" ) ) { return 1; } if( what == "apparatus" && pseudo ) { int qty = 0; visit_items( [&qty, &limit] ( const item *e ) { qty += e->has_quality( "SMOKE_PIPE", 1 ); return qty < limit ? VisitResponse::SKIP : VisitResponse::ABORT; } ); return std::min( qty, limit ); } return amount_of_internal( *this, what, pseudo, limit ); }
void Character::reset_stats() { // Bionic buffs if (has_active_bionic("bio_hydraulics")) mod_str_bonus(20); if (has_bionic("bio_eye_enhancer")) mod_per_bonus(2); if (has_bionic("bio_str_enhancer")) mod_str_bonus(2); if (has_bionic("bio_int_enhancer")) mod_int_bonus(2); if (has_bionic("bio_dex_enhancer")) mod_dex_bonus(2); // Trait / mutation buffs if (has_trait("THICK_SCALES")) { mod_dex_bonus(-2); } if (has_trait("CHITIN2") || has_trait("CHITIN3") || has_trait("CHITIN_FUR3")) { mod_dex_bonus(-1); } if (has_trait("BIRD_EYE")) { mod_per_bonus(4); } if (has_trait("INSECT_ARMS")) { mod_dex_bonus(-2); } if (has_trait("WEBBED")) { mod_dex_bonus(-1); } if (has_trait("ARACHNID_ARMS")) { mod_dex_bonus(-4); } if (has_trait("ARM_TENTACLES") || has_trait("ARM_TENTACLES_4") || has_trait("ARM_TENTACLES_8")) { mod_dex_bonus(1); } // Dodge-related effects if (has_trait("TAIL_LONG")) { mod_dodge_bonus(2); } if (has_trait("TAIL_CATTLE")) { mod_dodge_bonus(1); } if (has_trait("TAIL_RAT")) { mod_dodge_bonus(2); } if (has_trait("TAIL_THICK") && !(has_active_mutation("TAIL_THICK")) ) { mod_dodge_bonus(1); } if (has_trait("TAIL_RAPTOR")) { mod_dodge_bonus(3); } if (has_trait("TAIL_FLUFFY")) { mod_dodge_bonus(4); } if (has_trait("WINGS_BAT")) { mod_dodge_bonus(-3); } if (has_trait("WINGS_BUTTERFLY")) { mod_dodge_bonus(-4); } ///\EFFECT_STR_MAX above 15 decreases Dodge bonus by 1 (NEGATIVE) if (str_max >= 16) {mod_dodge_bonus(-1);} // Penalty if we're huge ///\EFFECT_STR_MAX below 6 increases Dodge bonus by 1 else if (str_max <= 5) {mod_dodge_bonus(1);} // Bonus if we're small nv_cached = false; // Reset our stats to normal levels // Any persistent buffs/debuffs will take place in effects, // player::suffer(), etc. // repopulate the stat fields str_cur = str_max + get_str_bonus(); dex_cur = dex_max + get_dex_bonus(); per_cur = per_max + get_per_bonus(); int_cur = int_max + get_int_bonus(); // Floor for our stats. No stat changes should occur after this! if( dex_cur < 0 ) { dex_cur = 0; } if( str_cur < 0 ) { str_cur = 0; } if( per_cur < 0 ) { per_cur = 0; } if( int_cur < 0 ) { int_cur = 0; } // Does nothing! TODO: Remove Creature::reset_stats(); }
// This must be called when any of the following change: // - effects // - bionics // - traits // - underwater // - clothes // With the exception of clothes, all changes to these character attributes must // occur through a function in this class which calls this function. Clothes are // typically added/removed with wear() and takeoff(), but direct access to the // 'wears' vector is still allowed due to refactor exhaustion. void Character::recalc_sight_limits() { sight_max = 9999; vision_mode_cache.reset(); // Set sight_max. if (has_effect("blind") || worn_with_flag("BLIND") || has_active_bionic("bio_blindfold")) { sight_max = 0; } else if( has_effect("boomered") && (!(has_trait("PER_SLIME_OK"))) ) { sight_max = 1; vision_mode_cache.set( BOOMERED ); } else if (has_effect("in_pit") || (underwater && !has_bionic("bio_membrane") && !has_trait("MEMBRANE") && !worn_with_flag("SWIM_GOGGLES") && !has_trait("CEPH_EYES") && !has_trait("PER_SLIME_OK") ) ) { sight_max = 1; } else if (has_active_mutation("SHELL2")) { // You can kinda see out a bit. sight_max = 2; } else if ( (has_trait("MYOPIC") || has_trait("URSINE_EYE")) && !is_wearing("glasses_eye") && !is_wearing("glasses_monocle") && !is_wearing("glasses_bifocal") && !has_effect("contacts")) { sight_max = 4; } else if (has_trait("PER_SLIME")) { sight_max = 6; } else if( has_effect( "darkness" ) ) { vision_mode_cache.set( DARKNESS ); sight_max = 10; } // Debug-only NV, by vache's request if( has_trait("DEBUG_NIGHTVISION") ) { vision_mode_cache.set( DEBUG_NIGHTVISION ); } if( has_nv() ) { vision_mode_cache.set( NV_GOGGLES ); } if( has_active_mutation("NIGHTVISION3") || is_wearing("rm13_armor_on") ) { vision_mode_cache.set( NIGHTVISION_3 ); } if( has_active_mutation("ELFA_FNV") ) { vision_mode_cache.set( FULL_ELFA_VISION ); } if( has_active_mutation("CEPH_VISION") ) { vision_mode_cache.set( CEPH_VISION ); } if (has_active_mutation("ELFA_NV")) { vision_mode_cache.set( ELFA_VISION ); } if( has_active_mutation("NIGHTVISION2") ) { vision_mode_cache.set( NIGHTVISION_2 ); } if( has_active_mutation("FEL_NV") ) { vision_mode_cache.set( FELINE_VISION ); } if( has_active_mutation("URSINE_EYE") ) { vision_mode_cache.set( URSINE_VISION ); } if (has_active_mutation("NIGHTVISION")) { vision_mode_cache.set(NIGHTVISION_1); } if( has_trait("BIRD_EYE") ) { vision_mode_cache.set( BIRD_EYE); } }
void Character::reset_stats() { Creature::reset_stats(); // Bionic buffs if (has_active_bionic("bio_hydraulics")) mod_str_bonus(20); if (has_bionic("bio_eye_enhancer")) mod_per_bonus(2); if (has_bionic("bio_str_enhancer")) mod_str_bonus(2); if (has_bionic("bio_int_enhancer")) mod_int_bonus(2); if (has_bionic("bio_dex_enhancer")) mod_dex_bonus(2); // Trait / mutation buffs if (has_trait("THICK_SCALES")) { mod_dex_bonus(-2); } if (has_trait("CHITIN2") || has_trait("CHITIN3") || has_trait("CHITIN_FUR3")) { mod_dex_bonus(-1); } if (has_trait("BIRD_EYE")) { mod_per_bonus(4); } if (has_trait("INSECT_ARMS")) { mod_dex_bonus(-2); } if (has_trait("WEBBED")) { mod_dex_bonus(-1); } if (has_trait("ARACHNID_ARMS")) { mod_dex_bonus(-4); } if (has_trait("ARM_TENTACLES") || has_trait("ARM_TENTACLES_4") || has_trait("ARM_TENTACLES_8")) { mod_dex_bonus(1); } // Dodge-related effects if (has_trait("TAIL_LONG")) { mod_dodge_bonus(2); } if (has_trait("TAIL_CATTLE")) { mod_dodge_bonus(1); } if (has_trait("TAIL_RAT")) { mod_dodge_bonus(2); } if (has_trait("TAIL_THICK") && !(has_active_mutation("TAIL_THICK")) ) { mod_dodge_bonus(1); } if (has_trait("TAIL_RAPTOR")) { mod_dodge_bonus(3); } if (has_trait("TAIL_FLUFFY")) { mod_dodge_bonus(4); } if (has_trait("WINGS_BAT")) { mod_dodge_bonus(-3); } if (has_trait("WINGS_BUTTERFLY")) { mod_dodge_bonus(-4); } if (str_max >= 16) {mod_dodge_bonus(-1);} // Penalty if we're huge else if (str_max <= 5) {mod_dodge_bonus(1);} // Bonus if we're small nv_cached = false; }