Skip to content

Commit

Permalink
spell learning
Browse files Browse the repository at this point in the history
  • Loading branch information
KorGgenT committed May 11, 2019
1 parent c7afe8d commit 41582ae
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 2 deletions.
9 changes: 9 additions & 0 deletions data/json/player_activities.json
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,15 @@
"based_on": "neither",
"no_resume": true
},
{
"id": "ACT_STUDY_SPELL",
"type": "activity_type",
"stop_phrase": "Stop studying?",
"suspendable": false,
"rooted": true,
"based_on": "time",
"no_resume": true
},
{
"id": "ACT_CONSUME_DRINK_MENU",
"type": "activity_type",
Expand Down
47 changes: 45 additions & 2 deletions src/activity_handlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "iexamine.h"
#include "itype.h"
#include "iuse_actor.h"
#include "magic.h"
#include "map.h"
#include "map_iterator.h"
#include "mapdata.h"
Expand Down Expand Up @@ -143,7 +144,8 @@ activity_handlers::do_turn_functions = {
{ activity_id( "ACT_FERTILIZE_PLOT" ), fertilize_plot_do_turn },
{ activity_id( "ACT_TRY_SLEEP" ), try_sleep_do_turn },
{ activity_id( "ACT_ROBOT_CONTROL" ), robot_control_do_turn },
{ activity_id( "ACT_TREE_COMMUNION" ), tree_communion_do_turn }
{ activity_id( "ACT_TREE_COMMUNION" ), tree_communion_do_turn },
{ activity_id( "ACT_STUDY_SPELL" ), study_spell_do_turn}
};

const std::map< activity_id, std::function<void( player_activity *, player * )> >
Expand Down Expand Up @@ -204,7 +206,8 @@ activity_handlers::finish_functions = {
{ activity_id( "ACT_SHAVE" ), shaving_finish },
{ activity_id( "ACT_HAIRCUT" ), haircut_finish },
{ activity_id( "ACT_UNLOAD_MAG" ), unload_mag_finish },
{ activity_id( "ACT_ROBOT_CONTROL" ), robot_control_finish }
{ activity_id( "ACT_ROBOT_CONTROL" ), robot_control_finish },
{ activity_id( "ACT_STUDY_SPELL" ), study_spell_finish }
};

void messages_in_process( const player_activity &act, const player &p )
Expand Down Expand Up @@ -3537,3 +3540,43 @@ void activity_handlers::tree_communion_do_turn( player_activity *act, player *p
p->add_msg_if_player( m_info, _( "The trees have shown you what they will." ) );
act->set_to_null();
}

void activity_handlers::study_spell_do_turn( player_activity *act, player *p )
{
if( p->fine_detail_vision_mod() > 4 ) {
act->values[2] = -1;
act->moves_left = 0;
return;
}
if( act->get_str_value( 1 ) == "study" ) {
spell &studying = p->magic.get_spell( spell_id( act->name ) );
if( act->get_str_value( 0 ) == "gain_level" ) {
if( studying.get_level() < act->get_value( 1 ) ) {
act->moves_left = 1000000;
} else {
act->moves_left = 0;
}
}
const int xp = roll_remainder( studying.exp_modifier( *p ) );
act->values[0] += xp;
studying.gain_exp( xp );
}
act->moves_left -= 100;
}

void activity_handlers::study_spell_finish( player_activity *act, player *p )
{
act->set_to_null();

if( act->get_str_value( 1 ) == "study" ) {
p->add_msg_if_player( m_good, _( "You gained %i experience from your study session." ),
act->get_value( 0 ) );
p->practice( skill_id( "spellcraft" ), act->get_value( 0 ) / 5,
p->magic.get_spell( spell_id( act->name ) ).get_difficulty() );
} else if( act->get_str_value( 1 ) == "learn" && act->values[2] == 0 ) {
p->magic.learn_spell( act->name, *p );
}
if( act->values[2] == -1 ) {
p->add_msg_if_player( m_bad, _( "It's too dark to read." ) );
}
}
2 changes: 2 additions & 0 deletions src/activity_handlers.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ void harvest_plot_do_turn( player_activity *act, player *p );
void try_sleep_do_turn( player_activity *act, player *p );
void robot_control_do_turn( player_activity *act, player *p );
void tree_communion_do_turn( player_activity *act, player *p );
void study_spell_do_turn( player_activity *act, player *p );

// defined in activity_handlers.cpp
extern const std::map< activity_id, std::function<void( player_activity *, player * )> >
Expand Down Expand Up @@ -150,6 +151,7 @@ void shaving_finish( player_activity *act, player *p );
void haircut_finish( player_activity *act, player *p );
void unload_mag_finish( player_activity *act, player *p );
void robot_control_finish( player_activity *act, player *p );
void study_spell_finish( player_activity *act, player *p );

// defined in activity_handlers.cpp
extern const std::map< activity_id, std::function<void( player_activity *, player * )> >
Expand Down
103 changes: 103 additions & 0 deletions src/iuse_actor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "cata_utility.h"
#include "coordinate_conversions.h"
#include "crafting.h"
#include "creature.h"
#include "debug.h"
#include "vpart_position.h"
#include "effect.h"
Expand All @@ -33,6 +34,7 @@
#include "item.h"
#include "item_factory.h"
#include "itype.h"
#include "magic.h"
#include "map.h"
#include "map_iterator.h"
#include "map_selector.h"
Expand Down Expand Up @@ -2116,6 +2118,107 @@ ret_val<bool> musical_instrument_actor::can_use( const player &p, const item &,
return ret_val<bool>::make_success();
}

iuse_actor *learn_spell_actor::clone() const
{
return new learn_spell_actor( *this );
}

void learn_spell_actor::load( JsonObject &obj )
{
spells = obj.get_string_array( "spells" );
}

void learn_spell_actor::info( const item &, std::vector<iteminfo> &dump ) const
{
std::string message;
if( spells.size() == 1 ) {
message = _( "This can teach you a spell." );
} else {
message = _( "This can teach you a number of spells." );
}
dump.emplace_back( "DESCRIPTION", message );
dump.emplace_back( "DESCRIPTION", _( "Spells Contained:" ) );
for( const std::string sp : spells ) {
dump.emplace_back( "SPELL", spell_id( sp ).obj().name );
}
}

long learn_spell_actor::use( player &p, item &, bool, const tripoint & ) const
{
if( p.fine_detail_vision_mod() > 4 ) {
p.add_msg_if_player( _( "It's too dark to read." ) );
return 0;
}
std::vector<uilist_entry> uilist_initializer;
bool know_it_all = true;
for( const std::string sp_id_str : spells ) {
const spell_id sp_id( sp_id_str );
const std::string sp_nm = sp_id.obj().name;
uilist_entry entry( sp_nm );
if( p.magic.knows_spell( sp_id ) ) {
const spell sp = p.magic.get_spell( sp_id );
entry.ctxt = string_format( "Level %u", sp.get_level() );
if( sp.is_max_level() ) {
entry.ctxt += _( " (Max)" );
entry.enabled = false;
} else {
know_it_all = false;
}
} else {
if( p.magic.can_learn_spell( p, sp_id ) ) {
entry.ctxt = _( "Study to Learn" );
know_it_all = false;
} else {
entry.ctxt = _( "Can't learn!" );
entry.enabled = false;
}
}
uilist_initializer.emplace_back( entry );
}

if( know_it_all ) {
add_msg( m_info, _( "You already know everything this could teach you." ) );
return 0;
}

const int action = uilist( _( "Study a spell:" ), uilist_initializer );
if( action < 0 ) {
return 0;
}
const bool knows_spell = p.magic.knows_spell( spells[action] );
player_activity study_spell( activity_id( "ACT_STUDY_SPELL" ),
p.magic.time_to_learn_spell( p, spells[action] ) );
study_spell.str_values = {
"", // reserved for "until you gain a spell level" option [0]
"learn"
}; // [1]
study_spell.values = { 0, 0, 0 };
if( knows_spell ) {
study_spell.str_values[1] = "study";
const int study_time = uilist( _( "Spend how long studying?" ), {
{ 30000, true, -1, _( "30 minutes" ) },
{ 60000, true, -1, _( "1 hour" ) },
{ 120000, true, -1, _( "2 hours" ) },
{ 240000, true, -1, _( "4 hours" ) },
{ 480000, true, -1, _( "8 hours" ) },
{ 10100, true, -1, _( "Until you gain a spell level" ) }
} );
if( study_time <= 0 ) {
return 0;
}
study_spell.moves_total = study_time;
}
study_spell.moves_left = study_spell.moves_total;
if( study_spell.moves_total == 10100 ) {
study_spell.str_values[0] = "gain_level";
study_spell.values[0]; // reserved for xp
study_spell.values[1] = p.magic.get_spell( spell_id( spells[action] ) ).get_level() + 1;
}
study_spell.name = spells[action];
p.assign_activity( study_spell, false );
return 0;
}

iuse_actor *holster_actor::clone() const
{
return new holster_actor( *this );
Expand Down
18 changes: 18 additions & 0 deletions src/iuse_actor.h
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,24 @@ class musical_instrument_actor : public iuse_actor
iuse_actor *clone() const override;
};

/**
* Learn a spell
*/
class learn_spell_actor : public iuse_actor
{
public:
// list of spell ids that can be learned from this item
std::vector<std::string> spells;

learn_spell_actor( const std::string &type = "learn_spell" ) : iuse_actor( type ) {}

~learn_spell_actor() override = default;
void load( JsonObject &jo ) override;
long use( player &p, item &, bool, const tripoint & ) const override;
iuse_actor *clone() const override;
void info( const item &, std::vector<iteminfo> & ) const override;
};

/**
* Holster a weapon
*/
Expand Down

0 comments on commit 41582ae

Please sign in to comment.