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

Auto eat and drink from auto-zones during long activities/waiting #36543

Merged
merged 11 commits into from Apr 4, 2020
Merged
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
47 changes: 32 additions & 15 deletions data/json/player_activities.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
"verb": "reading",
"rooted": true,
"based_on": "speed",
"refuel_fires": true
"refuel_fires": true,
"auto_needs": true
},
{
"id": "ACT_MULTIPLE_CONSTRUCTION",
Expand All @@ -33,7 +34,8 @@
"based_on": "neither",
"suspendable": false,
"no_resume": true,
"multi_activity": true
"multi_activity": true,
"auto_needs": true
},
{
"id": "ACT_MULTIPLE_MINE",
Expand Down Expand Up @@ -80,7 +82,8 @@
"based_on": "neither",
"suspendable": false,
"no_resume": true,
"multi_activity": true
"multi_activity": true,
"auto_needs": true
},
{
"id": "ACT_MULTIPLE_BUTCHER",
Expand All @@ -90,7 +93,8 @@
"based_on": "neither",
"suspendable": false,
"no_resume": true,
"multi_activity": true
"multi_activity": true,
"auto_needs": true
},
{
"id": "ACT_MULTIPLE_CHOP_TREES",
Expand All @@ -100,14 +104,16 @@
"based_on": "neither",
"suspendable": false,
"no_resume": true,
"multi_activity": true
"multi_activity": true,
"auto_needs": true
},
{
"id": "ACT_MULTIPLE_FISH",
"type": "activity_type",
"activity_level": "LIGHT_EXERCISE",
"verb": "fishing",
"based_on": "neither"
"based_on": "neither",
"auto_needs": true
},
{
"id": "ACT_GENERIC_GAME",
Expand All @@ -133,15 +139,17 @@
"rooted": true,
"based_on": "time",
"no_resume": true,
"refuel_fires": true
"refuel_fires": true,
"auto_needs": true
},
{
"id": "ACT_CRAFT",
"type": "activity_type",
"activity_level": "MODERATE_EXERCISE",
"verb": "crafting",
"based_on": "neither",
"refuel_fires": true
"refuel_fires": true,
"auto_needs": true
},
{
"id": "ACT_DISASSEMBLE",
Expand All @@ -151,7 +159,8 @@
"suspendable": false,
"rooted": true,
"based_on": "speed",
"refuel_fires": true
"refuel_fires": true,
"auto_needs": true
},
{
"id": "ACT_BUTCHER",
Expand Down Expand Up @@ -209,7 +218,8 @@
"verb": "salvaging",
"based_on": "speed",
"no_resume": true,
"refuel_fires": true
"refuel_fires": true,
"auto_needs": true
},
{
"id": "ACT_FORAGE",
Expand All @@ -224,6 +234,7 @@
"activity_level": "ACTIVE_EXERCISE",
"based_on": "neither",
"refuel_fires": true,
"auto_needs": true,
"verb": "constructing"
},
{
Expand Down Expand Up @@ -255,7 +266,8 @@
"verb": "waiting",
"rooted": true,
"based_on": "time",
"no_resume": true
"no_resume": true,
"auto_needs": true
},
{
"id": "ACT_FIRSTAID",
Expand Down Expand Up @@ -403,7 +415,8 @@
"suspendable": false,
"based_on": "neither",
"no_resume": true,
"multi_activity": true
"multi_activity": true,
"auto_needs": true
},
{
"id": "ACT_FERTILIZE_PLOT",
Expand All @@ -412,7 +425,8 @@
"verb": "fertilizing plots",
"suspendable": false,
"based_on": "neither",
"no_resume": true
"no_resume": true,
"auto_needs": true
},
{
"id": "ACT_ADV_INVENTORY",
Expand Down Expand Up @@ -533,7 +547,8 @@
"verb": "repairing",
"rooted": true,
"based_on": "neither",
"refuel_fires": true
"refuel_fires": true,
"auto_needs": true
},
{
"id": "ACT_MEND_ITEM",
Expand All @@ -542,7 +557,8 @@
"verb": "mending",
"rooted": true,
"based_on": "speed",
"refuel_fires": true
"refuel_fires": true,
"auto_needs": true
},
{
"id": "ACT_GUNMOD_ADD",
Expand Down Expand Up @@ -791,6 +807,7 @@
"verb": "studying",
"suspendable": false,
"refuel_fires": true,
"auto_needs": true,
"rooted": true,
"based_on": "time",
"no_resume": true
Expand Down
4 changes: 3 additions & 1 deletion doc/PLAYER_ACTIVITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ Activities are long term actions, that can be interrupted and (optionally) conti
* speed: `player_activity::moves_left` may be decremented faster or slower, depending on the character's speed.
* neither: `moves_left` will not be decremented. Thus you must define a do_turn function; otherwise the activity will never end!
* no_resume (false): Rather than resuming, you must always restart the activity from scratch.
* multi_activity(false): This activity will repeat until it cannot do any more work, used for NPC and player zone activities.
* multi_activity(false): This activity will repeat until it cannot do any more work, used for NPC and player zone activities.
* refuel_fires( false ): If true, the player will automatically refuel fires during the long activity.
* auto_needs( false ) : If true, the player will automatically eat and drink from specific auto_consume zones during long activities.

## Termination

Expand Down
3 changes: 2 additions & 1 deletion src/activity_handlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4875,7 +4875,8 @@ void activity_handlers::spellcasting_finish( player_activity *act, player *p )
spell_being_cast.xp() );
}
if( spell_being_cast.get_level() != old_level ) {
g->events().send<event_type::player_levels_spell>( spell_being_cast.id(), spell_being_cast.get_level() );
g->events().send<event_type::player_levels_spell>( spell_being_cast.id(),
spell_being_cast.get_level() );
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/activity_handlers.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ bool generic_multi_activity_handler( player_activity &act, player &p, bool check
void activity_on_turn_fetch( player_activity &, player *p );
void activity_on_turn_pickup();
void activity_on_turn_wear( player_activity &act, player &p );
bool find_auto_consume( player &p, bool food );
void try_fuel_fire( player_activity &act, player &p, bool starting_fire = false );

enum class item_drop_reason {
Expand Down
75 changes: 75 additions & 0 deletions src/activity_item_handling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <utility>

#include "avatar.h"
#include "avatar_action.h"
#include "construction.h"
#include "clzones.h"
#include "debug.h"
Expand Down Expand Up @@ -73,6 +74,7 @@ static const activity_id ACT_VEHICLE( "ACT_VEHICLE" );
static const activity_id ACT_VEHICLE_DECONSTRUCTION( "ACT_VEHICLE_DECONSTRUCTION" );
static const activity_id ACT_VEHICLE_REPAIR( "ACT_VEHICLE_REPAIR" );
static const efftype_id effect_pet( "pet" );
static const efftype_id effect_nausea( "nausea" );

static const trap_str_id tr_firewood_source( "tr_firewood_source" );
static const trap_str_id tr_unfinished_construction( "tr_unfinished_construction" );
Expand Down Expand Up @@ -3118,6 +3120,79 @@ static cata::optional<tripoint> find_refuel_spot_trap( const std::vector<tripoin
return {};
}

bool find_auto_consume( player &p, const bool food )
{
// return false if there is no point searching again while the activity is still happening.
if( p.is_npc() ) {
return false;
}
if( p.has_effect( effect_nausea ) ) {
return true;
}
static const std::string flag_MELTS( "MELTS" );
static const std::string flag_EDIBLE_FROZEN( "EDIBLE_FROZEN" );
const tripoint pos = p.pos();
zone_manager &mgr = zone_manager::get_manager();
zone_type_id consume_type_zone( "" );
if( food ) {
consume_type_zone = zone_type_id( "AUTO_EAT" );
} else {
consume_type_zone = zone_type_id( "AUTO_DRINK" );
}
const std::unordered_set<tripoint> &dest_set = mgr.get_near( consume_type_zone, g->m.getabs( pos ),
ACTIVITY_SEARCH_DISTANCE );
if( dest_set.empty() ) {
return false;
}
for( const tripoint loc : dest_set ) {
if( loc.z != p.pos().z ) {
continue;
}
map_stack food_there = g->m.i_at( g->m.getlocal( loc ) );
for( item &it : food_there ) {
item &comest = p.get_consumable_from( it );
if( comest.is_null() || comest.is_craft() || !comest.is_food() ||
p.fun_for( comest ).first < -5 ) {
// not good eatings.
continue;
}
if( !p.can_consume( it ) ) {
continue;
}
if( food && p.compute_effective_nutrients( comest ).kcal < 50 ) {
// not filling enough
continue;
}
if( !p.will_eat( comest, false ).success() ) {
// wont like it, cannibal meat etc
continue;
}
if( !it.is_owned_by( p, true ) ) {
// it aint ours.
continue;
}
if( !food && comest.get_comestible()->quench < 15 ) {
// not quenching enough
continue;
}
if( !food && it.is_watertight_container() && it.contents_made_of( SOLID ) ) {
This conversation was marked as resolved.
Show resolved Hide resolved
// its frozen
continue;
}
p.mod_moves( -Pickup::cost_to_move_item( p, it ) * std::max( rl_dist( p.pos(),
This conversation was marked as resolved.
Show resolved Hide resolved
g->m.getlocal( loc ) ), 1 ) );
item_location item_loc( map_cursor( g->m.getlocal( loc ) ), &it );
avatar_action::eat( g->u, item_loc );
// eat() may have removed the item, so check its still there.
if( item_loc.get_item() && item_loc->is_container() ) {
item_loc->on_contents_changed();
}
return true;
}
}
return false;
}

void try_fuel_fire( player_activity &act, player &p, const bool starting_fire )
{
const tripoint pos = p.pos();
Expand Down
1 change: 1 addition & 0 deletions src/activity_type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ void activity_type::load( const JsonObject &jo )
assign( jo, "no_resume", result.no_resume_, true );
assign( jo, "multi_activity", result.multi_activity_, false );
assign( jo, "refuel_fires", result.refuel_fires, false );
assign( jo, "auto_needs", result.auto_needs, false );

std::string activity_level = jo.get_string( "activity_level", "" );
if( activity_level.empty() ) {
Expand Down
8 changes: 7 additions & 1 deletion src/activity_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class activity_type
bool no_resume_ = false;
bool multi_activity_ = false;
bool refuel_fires = false;
bool auto_needs = false;
float activity_level = NO_EXERCISE;

public:
Expand Down Expand Up @@ -68,7 +69,12 @@ class activity_type
bool will_refuel_fires() const {
return refuel_fires;
}

/**
* If true, player will automatically consume from relevant auto-eat/drink zones during activity
*/
bool valid_auto_needs() const {
return auto_needs;
}
void call_do_turn( player_activity *, player * ) const;
/** Returns whether it had a finish function or not */
bool call_finish( player_activity *, player * ) const;
Expand Down
6 changes: 6 additions & 0 deletions src/clzones.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,12 @@ zone_manager::zone_manager()
types.emplace( zone_type_id( "CAMP_FOOD" ),
zone_type( translate_marker( "Basecamp: Food" ),
translate_marker( "Items in this zone will be added to a basecamp's food supply in the Distribute Food mission." ) ) );
types.emplace( zone_type_id( "AUTO_EAT" ),
zone_type( translate_marker( "Auto Eat" ),
translate_marker( "Items in this zone will be automatically eaten during a long activity if you get hungry." ) ) );
types.emplace( zone_type_id( "AUTO_DRINK" ),
zone_type( translate_marker( "Auto Drink" ),
translate_marker( "Items in this zone will be automatically consumed during a long activity if you get thirsty." ) ) );

}

Expand Down
3 changes: 2 additions & 1 deletion src/iuse_actor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1968,7 +1968,8 @@ int enzlave_actor::use( player &p, item &it, bool t, const tripoint & ) const

for( item &corpse_candidate : items ) {
const mtype *mt = corpse_candidate.get_mtype();
if( corpse_candidate.is_corpse() && mt->in_species( ZOMBIE ) && mt->made_of( material_id( "flesh" ) ) &&
if( corpse_candidate.is_corpse() && mt->in_species( ZOMBIE ) &&
mt->made_of( material_id( "flesh" ) ) &&
mt->in_species( HUMAN ) && corpse_candidate.active && !corpse_candidate.has_var( "zlave" ) ) {
corpses.push_back( &corpse_candidate );
}
Expand Down
16 changes: 16 additions & 0 deletions src/player_activity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,22 @@ void player_activity::do_turn( player &p )
if( *this && type->will_refuel_fires() ) {
try_fuel_fire( *this, p );
}
if( calendar::once_every( 30_minutes ) ) {
no_food_nearby_for_auto_consume = false;
no_drink_nearby_for_auto_consume = false;
}
if( *this && !p.is_npc() && type->valid_auto_needs() && !no_food_nearby_for_auto_consume ) {
if( p.stomach.contains() <= p.stomach.capacity( p ) / 4 && p.get_kcal_percent() < 0.95f ) {
if( !find_auto_consume( p, true ) ) {
no_food_nearby_for_auto_consume = true;
}
}
if( p.get_thirst() > 130 && !no_drink_nearby_for_auto_consume ) {
if( !find_auto_consume( p, false ) ) {
no_drink_nearby_for_auto_consume = true;
}
}
}
if( type->based_on() == based_on_type::TIME ) {
if( moves_left >= 100 ) {
moves_left -= 100;
Expand Down
2 changes: 2 additions & 0 deletions src/player_activity.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ class player_activity
std::unordered_set<tripoint> coord_set;
std::vector<weak_ptr_fast<monster>> monsters;
tripoint placement;
bool no_drink_nearby_for_auto_consume = false;
bool no_food_nearby_for_auto_consume = false;
/** If true, the activity will be auto-resumed next time the player attempts
* an identical activity. This value is set dynamically.
*/
Expand Down