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

Implement RUMMAGE_POCKET activity #52975

Closed
wants to merge 11 commits into from
8 changes: 8 additions & 0 deletions data/json/player_activities.json
Original file line number Diff line number Diff line change
Expand Up @@ -1077,5 +1077,13 @@
"interruptable": false,
"suspendable": false,
"interruptable_with_kb": false
},
{
"id": "ACT_RUMMAGE_POCKET",
"type": "activity_type",
"activity_level": "NO_EXERCISE",
"verb": "rummaging pocket",
"based_on": "speed",
"no_resume": true
}
]
137 changes: 137 additions & 0 deletions src/activity_actor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "creature_tracker.h"
#include "debug.h"
#include "enums.h"
#include "enum_conversions.h"
#include "event.h"
#include "event_bus.h"
#include "field_type.h"
Expand Down Expand Up @@ -116,6 +117,7 @@ static const activity_id ACT_PLAY_WITH_PET( "ACT_PLAY_WITH_PET" );
static const activity_id ACT_PRYING( "ACT_PRYING" );
static const activity_id ACT_READ( "ACT_READ" );
static const activity_id ACT_RELOAD( "ACT_RELOAD" );
static const activity_id ACT_RUMMAGE_POCKET( "ACT_RUMMAGE_POCKET" );
static const activity_id ACT_SHAVE( "ACT_SHAVE" );
static const activity_id ACT_SHEARING( "ACT_SHEARING" );
static const activity_id ACT_STASH( "ACT_STASH" );
Expand Down Expand Up @@ -5194,6 +5196,140 @@ std::unique_ptr<activity_actor> haircut_activity_actor::deserialize( JsonValue &
return haircut_activity_actor().clone();
}

void rummage_activity_actor::start( player_activity &act, Character &who )
{
int moves = 0;
if( kind == action::drop ) {
for( const drop_location &i_loc : item_loc ) {
//Only add the move cost for items inside a container
if( i_loc.first.where() == item_location::type::container ) {
moves += i_loc.first.obtain_cost( who );
}
}
} else {
moves += item_loc.front().first.obtain_cost( who );
}
act.moves_total = moves;
act.moves_left = moves;
}

void rummage_activity_actor::do_turn( player_activity &/*act*/, Character & /*who*/ )
{
}

void rummage_activity_actor::finish( player_activity &act, Character &who )
{
who.add_msg_if_player( m_good, _( "You rummaged your pockets to find the item" ) );
// some function calls in the switch block spawn activities e.g.
// avatar::read spawns an ACT_READ activity, so we need to set
// this one to null before calling them
act.set_to_null();

switch( kind ) {
case action::activate: {
avatar &player_character = get_avatar();
avatar_action::use_item( player_character, item_loc.front().first );
return;
}
case action::drop: {
who.drop( item_loc, m_pnt );
return;
}
case action::eat: {
avatar &player_character = get_avatar();
avatar_action::eat( player_character, item_loc.front().first );
return;
}
case action::read: {
avatar &player_character = get_avatar();
item_location i_loc = item_loc.front().first;

if( i_loc->type->can_use( "learn_spell" ) ) {
item spell_book = *i_loc.get_item();
spell_book.get_use( "learn_spell" )->call(
player_character, spell_book, spell_book.active, player_character.pos() );
} else {
player_character.read( i_loc );
}
return;
}
case action::wear: {
avatar &player_character = get_avatar();
player_character.wear( item_loc.front().first );
return;
}
case action::wield: {
avatar &player_character = get_avatar();
player_character.wield( item_loc.front().first );
return;
}
default:
debugmsg( "Unexpected action kind in rummage_pocket_activity_actor::finish" );
return;
}
}

void rummage_activity_actor::serialize( JsonOut &jsout ) const
{
jsout.start_object();

jsout.member( "item_loc", item_loc );
jsout.member_as_string( "action", kind );
jsout.member( "m_pnt", m_pnt );

jsout.end_object();
}

std::unique_ptr<activity_actor> rummage_activity_actor::deserialize( JsonValue &jsin )
{
rummage_activity_actor actor( drop_locations{}, action::none, tripoint_zero );

JsonObject data = jsin.get_object();

data.read( "item_loc", actor.item_loc );
const action k = data.get_enum_value<action>( "action" );
actor.kind = k;
data.read( "m_pnt", actor.m_pnt );

return actor.clone();
}

namespace io
{
template<>
std::string enum_to_string<rummage_activity_actor::action>(
const rummage_activity_actor::action kind )
{
switch( kind ) {
case rummage_activity_actor::action::activate:
return "activate";
case rummage_activity_actor::action::drop:
return "drop";
case rummage_activity_actor::action::eat:
return "eat";
case rummage_activity_actor::action::none:
return "none";
case rummage_activity_actor::action::read:
return "read";
case rummage_activity_actor::action::wear:
return "wear";
case rummage_activity_actor::action::wield:
return "wield";
case rummage_activity_actor::action::last:
break;
}
debugmsg( "Invalid rummage_activity_actor::action" );
cata_fatal( "Invalid rummage_activity_actor::action" );
}
} //namespace io

template<>
struct enum_traits<rummage_activity_actor::action> {
static constexpr rummage_activity_actor::action last =
rummage_activity_actor::action::last;
};


namespace activity_actors
{

Expand Down Expand Up @@ -5234,6 +5370,7 @@ deserialize_functions = {
{ ACT_PLAY_WITH_PET, &play_with_pet_activity_actor::deserialize },
{ ACT_READ, &read_activity_actor::deserialize },
{ ACT_RELOAD, &reload_activity_actor::deserialize },
{ ACT_RUMMAGE_POCKET, &rummage_activity_actor::deserialize },
{ ACT_SHAVE, &shave_activity_actor::deserialize },
{ ACT_SHEARING, &shearing_activity_actor::deserialize },
{ ACT_STASH, &stash_activity_actor::deserialize },
Expand Down
44 changes: 44 additions & 0 deletions src/activity_actor_definitions.h
Original file line number Diff line number Diff line change
Expand Up @@ -1571,4 +1571,48 @@ class haircut_activity_actor : public activity_actor
static std::unique_ptr<activity_actor> deserialize( JsonValue & );
};

class rummage_activity_actor : public activity_actor
{

public:
enum class action : int {
activate,
drop,
eat,
none,
read,
wear,
wield,
last
};
using item_locations = drop_locations;

private:
item_locations item_loc;
action kind;
tripoint m_pnt;

public:
rummage_activity_actor() = default;
rummage_activity_actor( const item_location &i_loc, action act_kind,
const tripoint &pnt = tripoint_zero )
: item_loc( { std::make_pair( i_loc, i_loc->count() ) } ), kind( act_kind ), m_pnt( pnt ) {}
rummage_activity_actor( const drop_locations &drop_loc, action act_kind,
const tripoint &pnt = tripoint_zero )
: item_loc( drop_loc ), kind( act_kind ), m_pnt( pnt ) {}
activity_id get_type() const override {
return activity_id( "ACT_RUMMAGE_POCKET" );
}

void start( player_activity &act, Character & ) override;
void do_turn( player_activity &, Character & ) override;
void finish( player_activity &act, Character &who ) override;

std::unique_ptr<activity_actor> clone() const override {
return std::make_unique<rummage_activity_actor>( *this );
}
void serialize( JsonOut & ) const override;
static std::unique_ptr<activity_actor> deserialize( JsonValue & );
};

#endif // CATA_SRC_ACTIVITY_ACTOR_DEFINITIONS_H
9 changes: 7 additions & 2 deletions src/avatar_action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1080,8 +1080,13 @@ static void update_lum( item_location loc, bool add )

void avatar_action::use_item( avatar &you )
{
item_location loc;
avatar_action::use_item( you, loc );
item_location loc = game_menus::inv::use( you );
if( loc.where() == item_location::type::container ) {
you.assign_activity( player_activity( rummage_activity_actor( loc,
rummage_activity_actor::action::activate ) ) );
} else {
avatar_action::use_item( you, loc );
}
}

void avatar_action::use_item( avatar &you, item_location &loc )
Expand Down
67 changes: 57 additions & 10 deletions src/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1886,7 +1886,13 @@ int game::inventory_item_menu( item_location locThisItem,
if( locThisItem.get_item()->type->has_use() &&
!locThisItem.get_item()->item_has_uses_recursive( true ) ) {
// Item has uses and none of its contents (if any) has uses.
avatar_action::use_item( u, locThisItem );

if( locThisItem.where() == item_location::type::container ) {
u.assign_activity( player_activity( rummage_activity_actor( locThisItem,
rummage_activity_actor::action::activate ) ) );
} else {
avatar_action::use_item( u, locThisItem );
}
} else if( locThisItem.get_item()->item_has_uses_recursive() ) {
game::item_action_menu( locThisItem );
} else {
Expand All @@ -1898,23 +1904,39 @@ int game::inventory_item_menu( item_location locThisItem,
}
case 'E':
if( !locThisItem.get_item()->is_container() ) {
avatar_action::eat( u, locThisItem );
if( locThisItem.where() == item_location::type::container ) {
u.assign_activity( player_activity( rummage_activity_actor( locThisItem,
rummage_activity_actor::action::eat ) ) )
;
} else {
avatar_action::eat( u, locThisItem );
}
} else {
avatar_action::eat( u, game_menus::inv::consume( u, locThisItem ) );
}
break;
case 'W': {
contents_change_handler handler;
handler.unseal_pocket_containing( locThisItem );
u.wear( locThisItem );
if( locThisItem.where() == item_location::type::container ) {
u.assign_activity( player_activity( rummage_activity_actor( locThisItem,
rummage_activity_actor::action::wear ) ) );
} else {
u.wear( locThisItem );
}
handler.handle_by( u );
break;
}
case 'w':
if( u.can_wield( *locThisItem ).success() ) {
contents_change_handler handler;
handler.unseal_pocket_containing( locThisItem );
wield( locThisItem );
if( locThisItem.where() == item_location::type::container ) {
u.assign_activity( player_activity( rummage_activity_actor( locThisItem,
rummage_activity_actor::action::wield ) ) );
} else {
wield( locThisItem );
}
handler.handle_by( u );
} else {
add_msg( m_info, "%s", u.can_wield( *locThisItem ).c_str() );
Expand All @@ -1933,9 +1955,15 @@ int game::inventory_item_menu( item_location locThisItem,
case 'T':
u.takeoff( locThisItem );
break;
case 'd':
u.drop( locThisItem, u.pos() );
case 'd': {
if( locThisItem.where() == item_location::type::container ) {
u.assign_activity( player_activity( rummage_activity_actor( locThisItem,
rummage_activity_actor::action::drop, u.pos() ) ) );
} else {
u.drop( locThisItem, u.pos() );
}
break;
}
case 'U':
u.unload( locThisItem );
break;
Expand All @@ -1948,9 +1976,15 @@ int game::inventory_item_menu( item_location locThisItem,
case 'm':
avatar_action::mend( u, locThisItem );
break;
case 'R':
u.read( locThisItem );
case 'R': {
if( locThisItem.where() == item_location::type::container ) {
u.assign_activity( player_activity( rummage_activity_actor( locThisItem,
rummage_activity_actor::action::read ) ) );
} else {
u.read( locThisItem );
}
break;
}
case 'D':
u.disassemble( locThisItem, false );
break;
Expand Down Expand Up @@ -7892,7 +7926,15 @@ void game::unload_container()

void game::drop_in_direction( const tripoint &pnt )
{
u.drop( game_menus::inv::multidrop( u ), pnt );
drop_locations drop_loc = game_menus::inv::multidrop( u );
for( const drop_location &d_loc : drop_loc ) {
if( d_loc.first.where() == item_location::type::container ) {
u.assign_activity( player_activity( rummage_activity_actor( drop_loc,
rummage_activity_actor::action::drop, pnt ) ) );
return;
}
}
u.drop( drop_loc, pnt );
}

// Used to set up the first Hotkey in the display set
Expand Down Expand Up @@ -8738,7 +8780,12 @@ void game::wield()
item_location loc = game_menus::inv::wield( u );

if( loc ) {
wield( loc );
if( loc.where() == item_location::type::container ) {
u.assign_activity( player_activity( rummage_activity_actor( loc,
rummage_activity_actor::action::wield ) ) );
} else {
wield( loc );
}
} else {
add_msg( _( "Never mind." ) );
}
Expand Down
Loading