Skip to content

Commit

Permalink
Change milking to an activity, restore udders on load catchup (#37523)
Browse files Browse the repository at this point in the history
  • Loading branch information
davidpwbrown authored Feb 4, 2020
1 parent a3e0d4e commit 84c1209
Show file tree
Hide file tree
Showing 11 changed files with 102 additions and 32 deletions.
10 changes: 5 additions & 5 deletions data/json/effects.json
Original file line number Diff line number Diff line change
Expand Up @@ -1680,11 +1680,11 @@
"rating": "bad"
},
{
"type": "effect_type",
"id": "milked",
"name": [ "Milked" ],
"desc": [ "The creature has been partially or fully milked." ],
"max_duration": "1 d"
"type": "effect_type",
"id": "milked",
"name": [ "Milked" ],
"desc": [ "The creature has been partially or fully milked." ],
"max_duration": "1 d"
},
{
"type": "effect_type",
Expand Down
4 changes: 2 additions & 2 deletions data/json/monsters/mammal.json
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@
"melee_cut": 6,
"dodge": 2,
"armor_bash": 2,
"starting_ammo": { "milk_raw": 10 },
"starting_ammo": { "milk_raw": 40 },
"path_settings": { "max_dist": 10 },
"anger_triggers": [ "HURT" ],
"fear_triggers": [ "PLAYER_CLOSE" ],
Expand Down Expand Up @@ -1876,7 +1876,7 @@
"melee_dice_sides": 6,
"melee_cut": 2,
"dodge": 2,
"starting_ammo": { "milk_raw": 2 },
"starting_ammo": { "milk_raw": 5 },
"anger_triggers": [ ],
"harvest": "mammal_large_wool",
"reproduction": { "baby_monster": "mon_sheep_lamb", "baby_count": 1, "baby_timer": 275 },
Expand Down
10 changes: 10 additions & 0 deletions data/json/player_activities.json
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,16 @@
"based_on": "neither",
"no_resume": true
},
{
"id": "ACT_MILK",
"type": "activity_type",
"activity_level": "LIGHT_EXERCISE",
"verb": "milking an animal",
"suspendable": false,
"rooted": true,
"based_on": "time",
"no_resume": true
},
{
"id": "ACT_HOTWIRE_CAR",
"type": "activity_type",
Expand Down
40 changes: 40 additions & 0 deletions src/activity_handlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ activity_handlers::finish_functions = {
{ ACT_WASH, washing_finish },
{ ACT_HACKSAW, hacksaw_finish },
{ ACT_CHOP_TREE, chop_tree_finish },
{ ACT_MILK, milk_finish },
{ ACT_CHOP_LOGS, chop_logs_finish },
{ ACT_CHOP_PLANKS, chop_planks_finish },
{ ACT_JACKHAMMER, jackhammer_finish },
Expand Down Expand Up @@ -1274,6 +1275,45 @@ void activity_handlers::butcher_finish( player_activity *act, player *p )
resume_for_multi_activities( *p );
}

void activity_handlers::milk_finish( player_activity *act, player *p )
{
if( act->coords.empty() ) {
debugmsg( "milking activity with no position of monster stored" );
return;
}
const tripoint source_pos = g->m.getlocal( act->coords.at( 0 ) );
monster *source_mon = g->critter_at<monster>( source_pos );
if( source_mon == nullptr ) {
debugmsg( "could not find source creature for liquid transfer" );
return;
}
auto milked_item = source_mon->ammo.find( "milk_raw" );
if( milked_item == source_mon->ammo.end() ) {
debugmsg( "animal has no milk ammo type" );
return;
}
if( milked_item->second <= 0 ) {
debugmsg( "started milking but udders are now empty before milking finishes" );
return;
}
item milk( milked_item->first, calendar::turn, milked_item->second );
milk.set_item_temperature( 311.75 );
if( liquid_handler::handle_liquid( milk, nullptr, 1, nullptr, nullptr, -1, source_mon ) ) {
milked_item->second = 0;
if( milk.charges > 0 ) {
milked_item->second = milk.charges;
} else {
p->add_msg_if_player( _( "The %s's udders run dry." ), source_mon->get_name() );
}
}
// if the monster was not manually tied up, but needed to be fixed in place temporarily then
// remove that now.
if( !act->str_values.empty() && act->str_values[0] == "temp_tie" ) {
source_mon->remove_effect( effect_tied );
}
act->set_to_null();
}

void activity_handlers::fill_liquid_do_turn( player_activity *act, player *p )
{
player_activity &act_ref = *act;
Expand Down
1 change: 1 addition & 0 deletions src/activity_handlers.h
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ void pickaxe_finish( player_activity *act, player *p );
void reload_finish( player_activity *act, player *p );
void start_fire_finish( player_activity *act, player *p );
void train_finish( player_activity *act, player *p );
void milk_finish( player_activity *act, player *p );
void vehicle_finish( player_activity *act, player *p );
void start_engines_finish( player_activity *act, player *p );
void churn_finish( player_activity *act, player *p );
Expand Down
1 change: 1 addition & 0 deletions src/cata_string_consts.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ static const activity_id ACT_FERTILIZE_PLOT( "ACT_FERTILIZE_PLOT" );
static const activity_id ACT_FETCH_REQUIRED( "ACT_FETCH_REQUIRED" );
static const activity_id ACT_FIELD_DRESS( "ACT_FIELD_DRESS" );
static const activity_id ACT_FILL_LIQUID( "ACT_FILL_LIQUID" );
static const activity_id ACT_MILK( "ACT_MILK" );
static const activity_id ACT_FILL_PIT( "ACT_FILL_PIT" );
static const activity_id ACT_FIND_MOUNT( "ACT_FIND_MOUNT" );
static const activity_id ACT_FIRSTAID( "ACT_FIRSTAID" );
Expand Down
6 changes: 5 additions & 1 deletion src/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4111,7 +4111,11 @@ void game::monmove()
}

m.creature_in_field( critter );

if( calendar::once_every( 1_days ) ) {
critter.refill_udders();
critter.try_biosignature();
critter.try_reproduce();
}
while( critter.moves > 0 && !critter.is_dead() && !critter.has_effect( effect_ridden ) ) {
critter.made_footstep = false;
// Controlled critters don't make their own plans
Expand Down
33 changes: 9 additions & 24 deletions src/monexamine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -668,39 +668,24 @@ void monexamine::tie_or_untie( monster &z )

void monexamine::milk_source( monster &source_mon )
{
const auto milked_item = source_mon.type->starting_ammo.find( "milk_raw" );
if( milked_item == source_mon.type->starting_ammo.end() ) {
const auto milked_item = source_mon.ammo.find( "milk_raw" );
if( milked_item == source_mon.ammo.end() ) {
debugmsg( "%s is milkable but has no milk in its starting ammo!",
source_mon.get_name() );
return;
}
const int milk_per_day = milked_item->second;
const time_duration milking_freq = 1_days / milk_per_day;

int remaining_milk = milk_per_day;
if( source_mon.has_effect( effect_milked ) ) {
remaining_milk -= source_mon.get_effect_dur( effect_milked ) / milking_freq;
}

if( remaining_milk > 0 ) {
if( milked_item->second > 0 ) {
const int moves = to_moves<int>( time_duration::from_minutes( milked_item->second / 2 ) );
g->u.assign_activity( ACT_MILK, moves, -1 );
g->u.activity.coords.push_back( g->m.getabs( source_mon.pos() ) );
// pin the cow in place if it isn't already
bool temp_tie = !source_mon.has_effect( effect_tied );
if( temp_tie ) {
source_mon.add_effect( effect_tied, 1_turns, num_bp, true );
g->u.activity.str_values.push_back( "temp_tie" );
}

item milk( milked_item->first, calendar::turn, remaining_milk );
milk.set_item_temperature( 311.75 );
if( liquid_handler::handle_liquid( milk, nullptr, 1, nullptr, nullptr, -1, &source_mon ) ) {
add_msg( _( "You milk the %s." ), source_mon.get_name() );
int transferred_milk = remaining_milk - milk.charges;
source_mon.add_effect( effect_milked, milking_freq * transferred_milk );
g->u.mod_moves( -to_moves<int>( transferred_milk * 1_minutes / 5 ) );
}
if( temp_tie ) {
source_mon.remove_effect( effect_tied );
}
add_msg( _( "You milk the %s." ), source_mon.get_name() );
} else {
add_msg( _( "The %s's udders run dry." ), source_mon.get_name() );
add_msg( _( "The %s has no more milk." ), source_mon.get_name() );
}
}
24 changes: 24 additions & 0 deletions src/monster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ monster::monster()
upgrade_time = -1;
last_updated = 0;
biosig_timer = -1;
udder_timer = calendar::turn;
horde_attraction = MHA_NULL;
}

Expand Down Expand Up @@ -359,6 +360,28 @@ void monster::try_reproduce()
}
}

void monster::refill_udders()
{
if( !has_flag( MF_MILKABLE ) ) {
return;
}
const auto milked_item = type->starting_ammo.find( "milk_raw" );
auto current_milk = ammo.find( "milk_raw" );
if( milked_item == type->starting_ammo.end() || current_milk == ammo.end() ) {
debugmsg( "%s is milkable but has no milk in its starting ammo!", get_name() );
return;
}
if( current_milk->second == milked_item->second ) {
// already full up
return;
}
if( calendar::turn - udder_timer > 1_days ) {
// no point granularizing this really, you milk once a day.
current_milk->second = milked_item->second;
udder_timer = calendar::turn;
}
}

void monster::try_biosignature()
{
if( !biosignatures ) {
Expand Down Expand Up @@ -2793,6 +2816,7 @@ void monster::on_load()
try_upgrade( false );
try_reproduce();
try_biosignature();
refill_udders();

const time_duration dt = calendar::turn - last_updated;
last_updated = calendar::turn;
Expand Down
2 changes: 2 additions & 0 deletions src/monster.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ class monster : public Creature
void try_upgrade( bool pin_time );
void try_reproduce();
void try_biosignature();
void refill_udders();
void spawn( const tripoint &p );
m_size get_size() const override;
units::mass get_weight() const override;
Expand Down Expand Up @@ -548,6 +549,7 @@ class monster : public Creature
cata::optional<time_point> baby_timer;
bool biosignatures;
cata::optional<time_point> biosig_timer;
time_point udder_timer;
monster_horde_attraction horde_attraction;
/** Found path. Note: Not used by monsters that don't pathfind! **/
std::vector<tripoint> path;
Expand Down
3 changes: 3 additions & 0 deletions src/savegame_json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1926,6 +1926,8 @@ void monster::load( const JsonObject &data )
biosignatures = data.get_bool( "biosignatures", type->biosignatures );
biosig_timer = data.get_int( "biosig_timer", -1 );

data.read( "udder_timer", udder_timer );

horde_attraction = static_cast<monster_horde_attraction>( data.get_int( "horde_attraction", 0 ) );

data.read( "inv", inv );
Expand Down Expand Up @@ -2008,6 +2010,7 @@ void monster::store( JsonOut &json ) const
json.member( "baby_timer", baby_timer );
json.member( "biosignatures", biosignatures );
json.member( "biosig_timer", biosig_timer );
json.member( "udder_timer", udder_timer );

json.member( "summon_time_limit", summon_time_limit );

Expand Down

0 comments on commit 84c1209

Please sign in to comment.