Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tweaking skill rust to fix learning overall #50176

Merged
merged 45 commits into from
Aug 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
c772e83
better learning!
I-am-Erk Jul 23, 2021
b3517df
Update skill.cpp
I-am-Erk Jul 23, 2021
d79816a
Update skill.cpp
I-am-Erk Jul 23, 2021
669db59
fix current_level_exp calc
I-am-Erk Jul 23, 2021
a40e558
fix overthink error
I-am-Erk Jul 23, 2021
fc4bb7a
fix a bit of logic error
I-am-Erk Jul 23, 2021
3ef25e9
books only train theory
I-am-Erk Jul 24, 2021
9a8df5b
Update skill.cpp
I-am-Erk Jul 24, 2021
2fd5472
rename "highest" to "theory"
I-am-Erk Jul 24, 2021
aee94bc
theory level meets requirements
I-am-Erk Jul 24, 2021
9cc8306
recipe requirements can be theory based
I-am-Erk Jul 24, 2021
a620a91
Books increase theory
I-am-Erk Jul 24, 2021
cf08ac2
rust rate drops as you accumulate rust
I-am-Erk Jul 25, 2021
8bc65d0
messy player display
I-am-Erk Jul 25, 2021
dd94f2e
fix some bugs, slow rust rate
I-am-Erk Jul 26, 2021
7609cc8
Update character.cpp
I-am-Erk Jul 26, 2021
b845cd8
Update src/character.cpp
I-am-Erk Jul 27, 2021
cb19e4d
make book larnin' show theory experience
I-am-Erk Jul 27, 2021
af1debc
fix up rust rate calculations
I-am-Erk Jul 27, 2021
3820c9e
attribute effects
I-am-Erk Jul 28, 2021
6991942
attribute effects
I-am-Erk Jul 28, 2021
dc966ed
cleanup compile errors
I-am-Erk Jul 28, 2021
0e68235
strength rust calculations
I-am-Erk Jul 28, 2021
07a011b
audit references to practical/theoretical
I-am-Erk Jul 28, 2021
6c4c3d6
fix a few math errors I thought of last night
I-am-Erk Jul 28, 2021
bf59bb8
fix compiler errors
I-am-Erk Jul 28, 2021
809f48b
book theory gain falls off as level gap increases
I-am-Erk Jul 28, 2021
54a3a88
npc book read is theory
I-am-Erk Jul 28, 2021
095f9c3
Update npc.cpp
I-am-Erk Jul 28, 2021
8c54586
Update character.cpp
I-am-Erk Jul 28, 2021
cb1d0bb
Update npc.cpp
I-am-Erk Jul 28, 2021
d412972
NPC skill affects their teaching
I-am-Erk Jul 28, 2021
bd33105
Update skill.cpp
I-am-Erk Jul 28, 2021
854135a
astyle
I-am-Erk Jul 28, 2021
1d320d7
audit more practical/knowledge spots
I-am-Erk Jul 29, 2021
fec1635
finally fix book learning
I-am-Erk Jul 29, 2021
dde8c2f
astyle
I-am-Erk Jul 29, 2021
21f443b
some tests
I-am-Erk Jul 29, 2021
0a9bd20
change theory to knowledge
I-am-Erk Jul 29, 2021
81fd173
Update skill.h
I-am-Erk Jul 29, 2021
eceedb4
Build fix
kevingranade Aug 9, 2021
2765e8b
Fix knowledge and skill sync logic
kevingranade Aug 9, 2021
b40016c
Remove inconsistency from test
kevingranade Aug 9, 2021
b7e5665
Correct xp to next level calculation
kevingranade Aug 10, 2021
b754ee0
Make mingw less angry.
kevingranade Aug 10, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 21 additions & 18 deletions src/activity_actor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1161,7 +1161,7 @@ void read_activity_actor::read_book( Character &learner,
const cata::value_ptr<islot_book> &islotbook,
SkillLevel &skill_level, double penalty )
{
const int originalSkillLevel = skill_level.level();
const int originalSkillLevel = skill_level.knowledgeLevel();

// Calculate experience gained
/** @EFFECT_INT increases reading comprehension */
Expand Down Expand Up @@ -1263,25 +1263,27 @@ bool read_activity_actor::player_read( avatar &you )
}

if( skill &&
learner->get_skill_level( skill ) < islotbook->level &&
learner->get_knowledge_level( skill ) < islotbook->level &&
learner->get_skill_level_object( skill ).can_train() ) {

SkillLevel &skill_level = learner->get_skill_level_object( skill );
std::string skill_name = skill.obj().name();
const int originalSkillLevel = skill_level.level();
const int originalSkillLevel = skill_level.knowledgeLevel();

read_book( *learner, islotbook, skill_level, penalty );
const int newSkillLevel = skill_level.knowledgeLevel();


// levels up the skill
if( skill_level != originalSkillLevel ) {
if( newSkillLevel != originalSkillLevel ) {
get_event_bus().send<event_type::gains_skill_level>(
learner->getID(), skill, skill_level.level() );
learner->getID(), skill, skill_level.knowledgeLevel() );

if( learner->is_avatar() ) {
add_msg( m_good, _( "You increase %s to level %d." ), skill.obj().name(),
add_msg( m_good, _( "You theoretical knowledge of %s increases to level %d." ), skill.obj().name(),
originalSkillLevel + 1 );
} else {
add_msg( m_good, _( "%s increases their %s level." ), learner->disp_name(),
add_msg( m_good, _( "%s increases their %s knowledge." ), learner->disp_name(),
skill.obj().name() );
}

Expand All @@ -1292,7 +1294,7 @@ bool read_activity_actor::player_read( avatar &you )
} else {
if( learner->is_avatar() ) {
add_msg( m_info, _( "You learn a little about %s! (%d%%)" ), skill_name,
skill_level.exercise() );
skill_level.knowledgeExperience() );
} else {
little_learned.push_back( learner->disp_name() );
}
Expand Down Expand Up @@ -1355,7 +1357,7 @@ bool read_activity_actor::player_readma( avatar &you )
skill_id skill_used = style_to_learn->primary_skill;

int difficulty = std::max( 1, style_to_learn->learn_difficulty );
difficulty = std::max( 1, 20 + difficulty * 2 - you.get_skill_level( skill_used ) * 2 );
difficulty = std::max( 1, 20 + difficulty * 2 - you.get_knowledge_level( skill_used ) * 2 );
add_msg_debug( debugmode::DF_ACT_READ, "Chance to learn one in: %d", difficulty );

if( one_in( difficulty ) ) {
Expand Down Expand Up @@ -1409,18 +1411,19 @@ bool read_activity_actor::npc_read( npc &learner )
book->mark_chapter_as_read( learner );

if( skill &&
learner.get_skill_level( skill ) < islotbook->level &&
learner.get_knowledge_level( skill ) < islotbook->level &&
learner.get_skill_level_object( skill ).can_train() ) {

SkillLevel &skill_level = learner.get_skill_level_object( skill );
std::string skill_name = skill.obj().name();
const int originalSkillLevel = skill_level.level();
const int originalSkillLevel = skill_level.knowledgeLevel();

read_book( learner, islotbook, skill_level, 1.0 );

if( skill_level != originalSkillLevel ) {
const int newSkillLevel = skill_level.knowledgeLevel();
if( newSkillLevel != originalSkillLevel ) {
get_event_bus().send<event_type::gains_skill_level>(
learner.getID(), skill, skill_level.level() );
learner.getID(), skill, skill_level.knowledgeLevel() );

if( display_messages ) {
add_msg( m_good, _( "%s increases their %s level." ), learner.disp_name(),
Expand Down Expand Up @@ -1544,16 +1547,16 @@ std::string read_activity_actor::get_progress_message( const player_activity & )
const skill_id &skill = islotbook->skill;

if( skill &&
you.get_skill_level( skill ) < islotbook->level &&
you.get_knowledge_level( skill ) < islotbook->level &&
you.get_skill_level_object( skill ).can_train() &&
you.has_identified( book->typeId() ) ) {
const SkillLevel &skill_level = you.get_skill_level_object( skill );
//~ skill_name current_skill_level -> next_skill_level (% to next level)
return string_format( pgettext( "reading progress", "%1$s %2$d -> %3$d (%4$d%%)" ),
skill.obj().name(),
skill_level.level(),
skill_level.level() + 1,
skill_level.exercise() );
skill_level.knowledgeLevel(),
skill_level.knowledgeLevel() + 1,
skill_level.knowledgeExperience() );
}

return std::string();
Expand Down Expand Up @@ -3484,7 +3487,7 @@ void disable_activity_actor::finish( player_activity &act, Character &/*who*/ )

bool disable_activity_actor::can_disable_or_reprogram( const monster &monster )
{
if( get_avatar().get_skill_level( skill_electronics ) + get_avatar().get_skill_level(
if( get_avatar().get_knowledge_level( skill_electronics ) + get_avatar().get_knowledge_level(
skill_mechanics ) <= 0 ) {
return false;
}
Expand Down
4 changes: 2 additions & 2 deletions src/activity_handlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2000,9 +2000,9 @@ void activity_handlers::train_finish( player_activity *act, player *p )
if( sk.is_valid() ) {
const Skill &skill = sk.obj();
std::string skill_name = skill.name();
int old_skill_level = p->get_skill_level( sk );
int old_skill_level = p->get_knowledge_level( sk );
p->practice( sk, 100, old_skill_level + 2 );
int new_skill_level = p->get_skill_level( sk );
int new_skill_level = p->get_knowledge_level( sk );
if( old_skill_level != new_skill_level ) {
add_msg( m_good, _( "You finish training %s to level %d." ),
skill_name, new_skill_level );
Expand Down
8 changes: 4 additions & 4 deletions src/avatar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ bool avatar::read( item_location &book, item_location ereader )

auto get_text =
[&]( const std::map<npc *, std::string> &m, const std::pair<npc *, std::string> &elem ) {
const int lvl = elem.first->get_skill_level( skill );
const int lvl = elem.first->get_knowledge_level( skill );
const std::string lvl_text = skill ? string_format( _( " | current level: %d" ), lvl ) : "";
const std::string name_text = elem.first->disp_name() + elem.second;
return string_format( "%s%s", left_justify( name_text, max_length( m ) ), lvl_text );
Expand All @@ -407,7 +407,7 @@ bool avatar::read( item_location &book, item_location ereader )

menu.addentry( 0, true, '0', _( "Read once" ) );

const int lvl = get_skill_level( skill );
const int lvl = get_knowledge_level( skill );
menu.addentry( 2 + getID().get_value(), lvl < type->level, '1',
string_format( _( "Read until you gain a level | current level: %d" ), lvl ) );

Expand Down Expand Up @@ -611,10 +611,10 @@ void avatar::identify( const item &item )

add_msg( _( "You skim %s to find out what's in it." ), book.type_name() );
if( skill && get_skill_level_object( skill ).can_train() ) {
add_msg( m_info, _( "Can bring your %s skill to %d." ),
add_msg( m_info, _( "Can bring your %s knowledge to %d." ),
skill.obj().name(), reading->level );
if( reading->req != 0 ) {
add_msg( m_info, _( "Requires %s level %d to understand." ),
add_msg( m_info, _( "Requires %s knoweldge level %d to understand." ),
skill.obj().name(), reading->req );
}
}
Expand Down
86 changes: 59 additions & 27 deletions src/character.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2409,6 +2409,13 @@ void Character::practice( const skill_id &id, int amount, int cap, bool suppress
return;
}

// Your ability to "catch up" skill experience to knowledge is mostly a function of intelligence,
// but perception also plays a role, representing both memory/attentiveness and catching on to how
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would perception really be involved here? Wouldn't something like natural physical prowess (dexterity = muscle memory?) tie to more physical/reflex based skills? Intelligence to skills requiring more complex understanding of concepts and ideas? I'm a bit unclear as to how perception factors in here... attentiveness is more of a factor of focus and mental fortitude (intelligence?) isn't it?

Now if we were talking about learning something through observation of someone demonstrating something to you, then both perception (ability to notice fine details) and intelligence (ability to understand those details) would make sense.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Focus, yes. Attentiveness? Plenty of people are intelligent but have problems paying attention - ADHD/ADD. Differentiating between skills in how they're affected by this split is planned.

// the two apply to each other.
float catchup_modifier = 1.0f + ( 2.0f * get_int() + get_per() ) / 24.0f; // 2 for an average person
float knowledge_modifier = 1.0f + get_int() /
40.0f; // 1.2 for an average person, always a bit higher than base amount

const auto highest_skill = [&]() {
std::pair<skill_id, int> result( skill_id::NULL_ID(), -1 );
for( const auto &pair : *_skills ) {
Expand All @@ -2426,25 +2433,21 @@ void Character::practice( const skill_id &id, int amount, int cap, bool suppress
amount = adjust_for_focus( amount );

if( has_trait( trait_PACIFIST ) && skill.is_combat_skill() ) {
if( !one_in( 3 ) ) {
amount = 0;
}
amount /= 3.0f;
}
if( has_trait_flag( json_flag_PRED2 ) && skill.is_combat_skill() ) {
if( one_in( 3 ) ) {
amount *= 2;
}
catchup_modifier *= 2.0f;
}
if( has_trait_flag( json_flag_PRED3 ) && skill.is_combat_skill() ) {
amount *= 2;
catchup_modifier *= 2.0f;
}

if( has_trait_flag( json_flag_PRED4 ) && skill.is_combat_skill() ) {
amount *= 3;
catchup_modifier *= 3.0f;
}

if( isSavant && id != savantSkill ) {
amount /= 2;
amount *= 0.5f;
}

if( amount > 0 && get_skill_level( id ) > cap ) { //blunt grinding cap implementation for crafting
Expand All @@ -2454,17 +2457,24 @@ void Character::practice( const skill_id &id, int amount, int cap, bool suppress
}
}
if( amount > 0 && level.isTraining() ) {
int oldLevel = get_skill_level( id );
get_skill_level_object( id ).train( amount );
int newLevel = get_skill_level( id );
int old_practical_level = get_skill_level( id );
int old_theoretical_level = get_knowledge_level( id );
get_skill_level_object( id ).train( amount, catchup_modifier, knowledge_modifier );
int new_practical_level = get_skill_level( id );
int new_theoretical_level = get_knowledge_level( id );
std::string skill_name = skill.name();
if( newLevel > oldLevel ) {
get_event_bus().send<event_type::gains_skill_level>( getID(), id, newLevel );
if( new_practical_level > old_practical_level ) {
get_event_bus().send<event_type::gains_skill_level>( getID(), id, new_practical_level );
}
if( is_avatar() && newLevel > oldLevel ) {
add_msg( m_good, _( "Your skill in %s has increased to %d!" ), skill_name, newLevel );
if( is_avatar() && new_practical_level > old_practical_level ) {
add_msg( m_good, _( "Your practical skill in %s has increased to %d!" ), skill_name,
new_practical_level );
}
if( is_avatar() && newLevel > cap ) {
if( is_avatar() && new_theoretical_level > old_theoretical_level ) {
add_msg( m_good, _( "Your theoretical understanding of %s has increased to %d!" ), skill_name,
new_theoretical_level );
}
if( is_avatar() && new_practical_level > cap ) {
//inform player immediately that the current recipe can't be used to train further
add_msg( m_info, _( "You feel that %s tasks of this level are becoming trivial." ),
skill_name );
Expand Down Expand Up @@ -4240,6 +4250,15 @@ int Character::get_skill_level( const skill_id &ident, const item &context ) con
return _skills->get_skill_level( ident, context );
}

int Character::get_knowledge_level( const skill_id &ident ) const
{
return _skills->get_knowledge_level( ident );
}

int Character::get_knowledge_level( const skill_id &ident, const item &context ) const
{
return _skills->get_knowledge_level( ident, context );
}
void Character::set_skill_level( const skill_id &ident, const int level )
{
get_skill_level_object( ident ).level( level );
Expand All @@ -4249,6 +4268,16 @@ void Character::mod_skill_level( const skill_id &ident, const int delta )
{
_skills->mod_skill_level( ident, delta );
}
void Character::set_knowledge_level( const skill_id &ident, const int level )
{
get_skill_level_object( ident ).knowledgeLevel( level );
}

void Character::mod_knowledge_level( const skill_id &ident, const int delta )
{
_skills->mod_skill_level( ident, delta );
}


std::string Character::enumerate_unmet_requirements( const item &it, const item &context ) const
{
Expand Down Expand Up @@ -4326,7 +4355,7 @@ bool Character::meets_skill_requirements( const construction &con ) const
{
return std::all_of( con.required_skills.begin(), con.required_skills.end(),
[&]( const std::pair<skill_id, int> &pr ) {
return get_skill_level( pr.first ) >= pr.second;
return get_knowledge_level( pr.first ) >= pr.second;
} );
}

Expand Down Expand Up @@ -4408,7 +4437,6 @@ void Character::apply_skill_boost()

void Character::do_skill_rust()
{
const int rust_rate_tmp = rust_rate();
for( std::pair<const skill_id, SkillLevel> &pair : *_skills ) {
const Skill &aSkill = *pair.first;
SkillLevel &skill_level_obj = pair.second;
Expand Down Expand Up @@ -4436,14 +4464,16 @@ void Character::do_skill_rust()

const int rust_resist = enchantment_cache->modify_value( enchant_vals::mod::READING_EXP, 0 );
const int oldSkillLevel = skill_level_obj.level();
if( skill_level_obj.rust( rust_resist, rust_rate_tmp ) ) {
if( skill_level_obj.rust( rust_resist ) ) {
add_msg_if_player( m_warning,
_( "Your knowledge of %s begins to fade, but your memory banks retain it!" ), aSkill.name() );
mod_power_level( -bio_memory->power_trigger );
}
const int newSkill = skill_level_obj.level();
if( newSkill < oldSkillLevel ) {
add_msg_if_player( m_bad, _( "Your skill in %s has reduced to %d!" ), aSkill.name(), newSkill );
add_msg_if_player( m_bad,
_( "Your practical skill in %s may need some refreshing. It has dropped to %d." ), aSkill.name(),
newSkill );
}
}
}
Expand Down Expand Up @@ -5770,7 +5800,9 @@ void Character::update_body( const time_point &from, const time_point &to )
as_avatar()->advance_daily_calories();
}

do_skill_rust();
if( calendar::once_every( 24_hours ) ) {
do_skill_rust();
}
}

item *Character::best_quality_item( const quality_id &qual )
Expand Down Expand Up @@ -13352,7 +13384,7 @@ book_mastery Character::get_book_mastery( const item &book ) const
return book_mastery::MASTERED;
}

const int skill_level = get_skill_level( skill );
const int skill_level = get_knowledge_level( skill );
const int skill_requirement = type->req;
const int max_skill_learnable = type->level;

Expand Down Expand Up @@ -13566,9 +13598,9 @@ const Character *Character::get_book_reader( const item &book,
}
if( get_book_mastery( book ) == book_mastery::CANT_UNDERSTAND ) {
reasons.push_back( is_avatar() ? string_format( _( "%s %d needed to understand. You have %d" ),
book_skill->name(), book_skill_requirement, get_skill_level( book_skill ) ) :
book_skill->name(), book_skill_requirement, get_knowledge_level( book_skill ) ) :
string_format( _( "%s %d needed to understand. %s has %d" ), book_skill->name(),
book_skill_requirement, disp_name(), get_skill_level( book_skill ) ) );
book_skill_requirement, disp_name(), get_knowledge_level( book_skill ) ) );
return nullptr;
}

Expand Down Expand Up @@ -13613,7 +13645,7 @@ const Character *Character::get_book_reader( const item &book,
} else if( elem->get_book_mastery( book ) == book_mastery::CANT_UNDERSTAND ) {
reasons.push_back( string_format( _( "%s %d needed to understand. %s has %d" ),
book_skill->name(), book_skill_requirement, elem->disp_name(),
elem->get_skill_level( book_skill ) ) );
elem->get_knowledge_level( book_skill ) ) );
} else if( elem->has_trait( trait_HYPEROPIC ) &&
!elem->worn_with_flag( STATIC( flag_id( "FIX_FARSIGHT" ) ) ) &&
!elem->has_effect( effect_contacts ) ) {
Expand Down Expand Up @@ -13652,7 +13684,7 @@ int Character::time_to_read( const item &book, const Character &reader,
// The reader's reading speed has an effect only if they're trying to understand the book as they read it
// Reading speed is assumed to be how well you learn from books (as opposed to hands-on experience)
const bool try_understand = reader.fun_to_read( book ) ||
reader.get_skill_level( skill ) < type->level;
reader.get_knowledge_level( skill ) < type->level;
int reading_speed = try_understand ? std::max( reader.read_speed(), read_speed() ) : read_speed();
if( learner ) {
reading_speed = std::max( reading_speed, learner->read_speed() );
Expand Down
4 changes: 4 additions & 0 deletions src/character.h
Original file line number Diff line number Diff line change
Expand Up @@ -1825,13 +1825,17 @@ class Character : public Creature, public visitable
// --------------- Skill Stuff ---------------
int get_skill_level( const skill_id &ident ) const;
int get_skill_level( const skill_id &ident, const item &context ) const;
int get_knowledge_level( const skill_id &ident ) const;
int get_knowledge_level( const skill_id &ident, const item &context ) const;

const SkillLevelMap &get_all_skills() const;
SkillLevel &get_skill_level_object( const skill_id &ident );
const SkillLevel &get_skill_level_object( const skill_id &ident ) const;

void set_skill_level( const skill_id &ident, int level );
void mod_skill_level( const skill_id &ident, int delta );
void set_knowledge_level( const skill_id &ident, int level );
void mod_knowledge_level( const skill_id &ident, int delta );
/** Checks whether the character's skills meet the required */
bool meets_skill_requirements( const std::map<skill_id, int> &req,
const item &context = item() ) const;
Expand Down
4 changes: 2 additions & 2 deletions src/character_crafting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ recipe_subset Character::get_available_recipes( const inventory &crafting_inv,
res.include( get_recipes_from_books( *np->inv ) );
// Being told what to do
res.include_if( np->get_learned_recipes(), [ this ]( const recipe & r ) {
return get_skill_level( r.skill_used ) >= static_cast<int>( r.difficulty *
return get_knowledge_level( r.skill_used ) >= static_cast<int>( r.difficulty *
0.8f ); // Skilled enough to understand
} );
}
Expand All @@ -153,7 +153,7 @@ std::set<itype_id> Character::get_books_for_recipe( const inventory &crafting_in
const recipe *r ) const
{
std::set<itype_id> book_ids;
const int skill_level = get_skill_level( r->skill_used );
const int skill_level = get_knowledge_level( r->skill_used );
for( const auto &book_lvl : r->booksets ) {
itype_id book_id = book_lvl.first;
int required_skill_level = book_lvl.second.skill_req;
Expand Down
Loading