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

feat(port): attunements infrastructure #3135

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -206,3 +206,4 @@ Xcode/
/tests/pch/tests-pch.hpp.pch
/tests/catch/catch.hpp.gch
/tests/catch/catch.hpp.pch
cbn_notes.txt
95 changes: 95 additions & 0 deletions src/iexamine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,101 @@ void iexamine::gaspump( player &p, const tripoint &examp )
add_msg( m_info, _( "Out of order." ) );
}

static bool has_attunement_spell_prereqs( Character &you, const trait_id &attunement )
{
// for each prereq we need to check that the player has 2 level 15 spells
for( const trait_id &prereq : attunement->prereqs ) {
int spells_known = 0;
for( const spell &sp : you.spells_known_of_class( prereq ) ) {
if( sp.get_level() >= 15 ) {
spells_known++;
}
}
if( spells_known < 2 ) {
return false;
}
}
return true;
}

void iexamine::attunement_altar( Character &you, const tripoint & )
{
std::set<trait_id> attunements;
for( const mutation_branch &mut : mutation_branch::get_all() ) {
if( mut.flags.count( json_flag_ATTUNEMENT ) ) {
attunements.emplace( mut.id );
}
}
// remove the attunements the player does not have prereqs for
for( auto iter = attunements.begin(); iter != attunements.end(); ) {
bool has_prereq = true;
// the normal usage of prereqs only needs one, but attunements put all their prereqs into the same array
// each prereqs is required for it as well
for( const trait_id &prereq : ( *iter )->prereqs ) {
if( !you.has_trait( prereq ) ) {
has_prereq = false;
break;
}
}
if( has_prereq ) {
++iter;
} else {
iter = attunements.erase( iter );
}
}
if( attunements.empty() ) {
// the player doesn't have at least two base classes
you.add_msg_if_player( _( "This altar gives you the creeps." ) );
return;
}
// remove the attunements the player has conflicts for
for( auto iter = attunements.begin(); iter != attunements.end(); ) {
if( !you.has_opposite_trait( *iter ) && you.mutation_ok( *iter, true, true, true ) ) {
++iter;
} else {
iter = attunements.erase( iter );
}
}
if( attunements.empty() ) {
you.add_msg_if_player( _( "You've attained what you can for now." ) );
return;
}
for( auto iter = attunements.begin(); iter != attunements.end(); ) {
if( has_attunement_spell_prereqs( you, *iter ) ) {
++iter;
} else {
iter = attunements.erase( iter );
}
}
if( attunements.empty() ) {
you.add_msg_if_player( _( "You feel that the altar does not deem you worthy, yet." ) );
return;
}
uilist attunement_list;
attunement_list.title = _( "Pick an Attunement to show the world your Worth." );
for( const trait_id &attunement : attunements ) {
// There's no way for you to have this mutation, so a variant is pointless
attunement_list.addentry( attunement->name() );
}
attunement_list.query();
if( attunement_list.ret == UILIST_CANCEL ) {
you.add_msg_if_player( _( "Maybe later." ) );
return;
}
auto attunement_iter = attunements.begin();
std::advance( attunement_iter, attunement_list.ret );
const trait_id &attunement = *attunement_iter;
// There's no way for you to have this mutation, so a variant is pointless
if( query_yn( string_format( _( "Are you sure you want to pick %s? This selection is permanent." ),
attunement->name() ) ) ) {
you.toggle_trait( attunement );
// There's no way for you to have this mutation, so a variant is pointless
you.add_msg_if_player( m_info, attunement->desc() );
} else {
you.add_msg_if_player( _( "Maybe later." ) );
}
}

void iexamine::translocator( player &, const tripoint &examp )
{
// TODO: fix point types
Expand Down
2 changes: 2 additions & 0 deletions src/iexamine.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ void sign( player &p, const tripoint &examp );
void pay_gas( player &p, const tripoint &examp );
void ledge( player &p, const tripoint &examp );
void autodoc( player &p, const tripoint &examp );
bool has_attunement_spell_prereqs( Character &you, const trait_id &attunement );
void attunement_altar( Character &you, const tripoint &examp );
void translocator( player &p, const tripoint &examp );
void on_smoke_out( const tripoint &examp,
const time_point &start_time ); //activates end of smoking effects
Expand Down
4 changes: 3 additions & 1 deletion src/mutation_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -620,7 +620,9 @@ void mutation_branch::check_consistency()

nc_color mutation_branch::get_display_color() const
{
if( threshold || profession ) {
if( flags.count( STATIC( json_character_flag( "ATTUNEMENT" ) ) ) ) {
return c_green;
} else if( threshold || profession ) {
return c_white;
} else if( debug ) {
return c_light_cyan;
Expand Down