diff --git a/src/activity_handlers.cpp b/src/activity_handlers.cpp index 506bc1952fdaf..f3c65637c4d2b 100644 --- a/src/activity_handlers.cpp +++ b/src/activity_handlers.cpp @@ -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 ) { diff --git a/src/game.cpp b/src/game.cpp index 6572fa29b119d..d0c240450a725 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -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(); } diff --git a/src/monexamine.cpp b/src/monexamine.cpp index 9b358da1ddb7b..3bc628a2f3695 100644 --- a/src/monexamine.cpp +++ b/src/monexamine.cpp @@ -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( time_duration::from_minutes( milked_item->second / 2 ) ); + if( milkable_ammo->second > 0 ) { + const int moves = to_moves( 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 diff --git a/src/monster.cpp b/src/monster.cpp index 1a1594433b278..e810c9c043f3a 100644 --- a/src/monster.cpp +++ b/src/monster.cpp @@ -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; } } @@ -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; diff --git a/src/monstergenerator.cpp b/src/monstergenerator.cpp index 7fc39dfbb71ab..8d1f7bb66bc72 100644 --- a/src/monstergenerator.cpp +++ b/src/monstergenerator.cpp @@ -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() ); diff --git a/src/savegame_json.cpp b/src/savegame_json.cpp index 7f1f039f315d1..738710b01d857 100644 --- a/src/savegame_json.cpp +++ b/src/savegame_json.cpp @@ -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", "" ) );