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

Fix cow milking from cows from old saves with old milk not raw milk. #37965

Merged
merged 10 commits into from Mar 2, 2020
4 changes: 2 additions & 2 deletions src/activity_handlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1279,9 +1279,9 @@ void activity_handlers::milk_finish( player_activity *act, player *p )
debugmsg( "could not find source creature for liquid transfer" );
return;
}
auto milked_item = source_mon->ammo.find( "milk_raw" );
auto milked_item = source_mon->ammo.find( source_mon->type->starting_ammo.begin()->first );
if( milked_item == source_mon->ammo.end() ) {
debugmsg( "animal has no milk ammo type" );
debugmsg( "animal has no milkable ammo type" );
return;
}
if( milked_item->second <= 0 ) {
Expand Down
4 changes: 3 additions & 1 deletion src/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4109,7 +4109,9 @@ void game::monmove()

m.creature_in_field( critter );
if( calendar::once_every( 1_days ) ) {
critter.refill_udders();
if( critter.has_flag( MF_MILKABLE ) ) {
critter.refill_udders();
}
critter.try_biosignature();
critter.try_reproduce();
}
Expand Down
12 changes: 6 additions & 6 deletions src/monexamine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -668,14 +668,14 @@ void monexamine::tie_or_untie( monster &z )

void monexamine::milk_source( monster &source_mon )
{
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() );
std::string milked_item = source_mon.type->starting_ammo.begin()->first;
auto milkable_ammo = source_mon.ammo.find( milked_item );
if( milkable_ammo == source_mon.ammo.end() ) {
debugmsg( "The %s has no milkable %s.", source_mon.get_name(), milked_item );
return;
}
if( milked_item->second > 0 ) {
const int moves = to_moves<int>( time_duration::from_minutes( milked_item->second / 2 ) );
if( milkable_ammo->second > 0 ) {
const int moves = to_moves<int>( time_duration::from_minutes( milkable_ammo->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
Expand Down
28 changes: 20 additions & 8 deletions src/monster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -362,22 +362,32 @@ void monster::try_reproduce()

void monster::refill_udders()
{
if( !has_flag( MF_MILKABLE ) ) {
if( type->starting_ammo.empty() ) {
debugmsg( "monster %s has no starting ammo to refill udders", get_name() );
return;
}
const auto milked_item = type->starting_ammo.find( "milk_raw" );
if( ammo.empty() ) {
// legacy animals got empty ammo map, fill them up now if needed.
ammo[type->starting_ammo.begin()->first] = type->starting_ammo.begin()->second;
}
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 == ammo.end() ) {
current_milk = ammo.find( "milk" );
if( current_milk != ammo.end() ) {
// take this opportunity to update milk udders to raw_milk
ammo["milk_raw"] = current_milk->second;
// Erase old key-value from map
ammo.erase( current_milk );
}
}
if( current_milk->second == milked_item->second ) {
// if we got here, we got milk.
if( current_milk->second == type->starting_ammo.begin()->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;
ammo.begin()->second = type->starting_ammo.begin()->second;
udder_timer = calendar::turn;
}
}
Expand Down Expand Up @@ -2816,7 +2826,9 @@ void monster::on_load()
try_upgrade( false );
try_reproduce();
try_biosignature();
refill_udders();
if( has_flag( MF_MILKABLE ) ) {
refill_udders();
}

const time_duration dt = calendar::turn - last_updated;
last_updated = calendar::turn;
Expand Down
11 changes: 11 additions & 0 deletions src/monstergenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1102,6 +1102,17 @@ void MonsterGenerator::check_monster_definitions() const
if( mon.harvest == "null" && !mon.has_flag( MF_ELECTRONIC ) && mon.id != mtype_id( "mon_null" ) ) {
debugmsg( "monster %s has no harvest entry", mon.id.c_str(), mon.harvest.c_str() );
}
if( mon.has_flag( MF_MILKABLE ) && mon.starting_ammo.empty() ) {
debugmsg( "monster %s is flagged milkable, but has no starting ammo", mon.id.c_str() );
}
if( mon.has_flag( MF_MILKABLE ) && !mon.starting_ammo.empty() &&
!item( itype_id( mon.starting_ammo.begin()->first ) ).made_of( LIQUID ) ) {
debugmsg( "monster % is flagged milkable, but starting ammo %s is not a liquid type",
mon.id.c_str(), mon.starting_ammo.begin()->first );
}
if( mon.has_flag( MF_MILKABLE ) && mon.starting_ammo.size() > 1 ) {
debugmsg( "monster % is flagged milkable, but has multiple starting_ammo defined", mon.id.c_str() );
}
for( auto &spec : mon.species ) {
if( !spec.is_valid() ) {
debugmsg( "monster %s has invalid species %s", mon.id.c_str(), spec.c_str() );
Expand Down
8 changes: 8 additions & 0 deletions src/savegame_json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1935,6 +1935,14 @@ void monster::load( const JsonObject &data )
normalize_ammo( data.get_int( "ammo" ) );
} else {
data.read( "ammo", ammo );
// legacy loading for milkable creatures, fix mismatch.
if( has_flag( MF_MILKABLE ) && !type->starting_ammo.empty() && !ammo.empty() &&
type->starting_ammo.begin()->first != ammo.begin()->first ) {
const std::string old_type = ammo.begin()->first;
const int old_value = ammo.begin()->second;
ammo[type->starting_ammo.begin()->first] = old_value;
ammo.erase( old_type );
}
}

faction = mfaction_str_id( data.get_string( "faction", "" ) );
Expand Down