From ca345593178d1db0542751d0651e44e8ac2438bc Mon Sep 17 00:00:00 2001 From: dpwb Date: Wed, 12 Feb 2020 14:21:11 +0000 Subject: [PATCH 01/10] fix old milk --- src/activity_handlers.cpp | 7 +++++-- src/monexamine.cpp | 12 ++++++++---- src/monster.cpp | 17 +++++++++++++---- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/activity_handlers.cpp b/src/activity_handlers.cpp index 506bc1952fdaf..e572e4a3ace9e 100644 --- a/src/activity_handlers.cpp +++ b/src/activity_handlers.cpp @@ -1281,8 +1281,11 @@ void activity_handlers::milk_finish( player_activity *act, player *p ) } auto milked_item = source_mon->ammo.find( "milk_raw" ); if( milked_item == source_mon->ammo.end() ) { - debugmsg( "animal has no milk ammo type" ); - return; + milked_item = source_mon->ammo.find( "milk" ); + 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" ); diff --git a/src/monexamine.cpp b/src/monexamine.cpp index 9b358da1ddb7b..fb698990f458d 100644 --- a/src/monexamine.cpp +++ b/src/monexamine.cpp @@ -668,11 +668,15 @@ void monexamine::tie_or_untie( monster &z ) void monexamine::milk_source( monster &source_mon ) { - const auto milked_item = source_mon.ammo.find( "milk_raw" ); + 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; + // old save cow + milked_item = source_mon.ammo.find( "milk" ); + if( milked_item == source_mon.ammo.end() ) { + debugmsg( "%s is milkable but has no milk in its starting ammo!", + source_mon.get_name() ); + return; + } } if( milked_item->second > 0 ) { const int moves = to_moves( time_duration::from_minutes( milked_item->second / 2 ) ); diff --git a/src/monster.cpp b/src/monster.cpp index 1a1594433b278..143bb8567be59 100644 --- a/src/monster.cpp +++ b/src/monster.cpp @@ -365,12 +365,21 @@ 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() ); + auto milked_item = type->starting_ammo.find( "milk_raw" ); + if( milked_item == type->starting_ammo.end() ) { + // old save cows. + milked_item = type->starting_ammo.find( "milk" ); + if( milked_item == type->starting_ammo.end() ) { + debugmsg( "%s is milkable but has no milk in its starting ammo!", get_name() ); + return; + } + } + auto current_milk = ammo.find( milked_item->first ); + if( current_milk == ammo.end() ) { + // how? return; } + // if we got here, we got milk. if( current_milk->second == milked_item->second ) { // already full up return; From 61f4ee82d828ecb4ef2c0edc6c57972adc21eb6c Mon Sep 17 00:00:00 2001 From: dpwb Date: Thu, 13 Feb 2020 12:27:13 +0000 Subject: [PATCH 02/10] change milk to milk_raw on load where applicable --- src/activity_handlers.cpp | 7 ++----- src/monexamine.cpp | 9 ++------- src/monster.cpp | 35 +++++++++++++++++++++++++---------- 3 files changed, 29 insertions(+), 22 deletions(-) diff --git a/src/activity_handlers.cpp b/src/activity_handlers.cpp index e572e4a3ace9e..506bc1952fdaf 100644 --- a/src/activity_handlers.cpp +++ b/src/activity_handlers.cpp @@ -1281,11 +1281,8 @@ void activity_handlers::milk_finish( player_activity *act, player *p ) } auto milked_item = source_mon->ammo.find( "milk_raw" ); if( milked_item == source_mon->ammo.end() ) { - milked_item = source_mon->ammo.find( "milk" ); - if( milked_item == source_mon->ammo.end() ) { - debugmsg( "animal has no milk ammo type" ); - return; - } + debugmsg( "animal has no milk ammo type" ); + return; } if( milked_item->second <= 0 ) { debugmsg( "started milking but udders are now empty before milking finishes" ); diff --git a/src/monexamine.cpp b/src/monexamine.cpp index fb698990f458d..7b25ad770e482 100644 --- a/src/monexamine.cpp +++ b/src/monexamine.cpp @@ -670,13 +670,8 @@ void monexamine::milk_source( monster &source_mon ) { auto milked_item = source_mon.ammo.find( "milk_raw" ); if( milked_item == source_mon.ammo.end() ) { - // old save cow - milked_item = source_mon.ammo.find( "milk" ); - if( milked_item == source_mon.ammo.end() ) { - debugmsg( "%s is milkable but has no milk in its starting ammo!", - source_mon.get_name() ); - return; - } + add_msg( m_info, _( "The %s has no milk." ), source_mon.get_name() ); + return; } if( milked_item->second > 0 ) { const int moves = to_moves( time_duration::from_minutes( milked_item->second / 2 ) ); diff --git a/src/monster.cpp b/src/monster.cpp index 143bb8567be59..fbaef54174573 100644 --- a/src/monster.cpp +++ b/src/monster.cpp @@ -362,22 +362,35 @@ void monster::try_reproduce() void monster::refill_udders() { - if( !has_flag( MF_MILKABLE ) ) { - return; - } - auto milked_item = type->starting_ammo.find( "milk_raw" ); + auto milked_item = type->starting_ammo.find( "milk_raw " ); if( milked_item == type->starting_ammo.end() ) { - // old save cows. milked_item = type->starting_ammo.find( "milk" ); if( milked_item == type->starting_ammo.end() ) { - debugmsg( "%s is milkable but has no milk in its starting ammo!", get_name() ); + // this may be a sheep from a very old save. + // sheep didnt use to be milkable, but now they have that flag, + // but the old save would keep their old blank starting ammo. + // cant modify the type, and cant get what their starting ammo should be. + // so just let the sheep remain milkless return; } } - auto current_milk = ammo.find( milked_item->first ); + auto current_milk = ammo.find( "milk_raw" ); if( current_milk == ammo.end() ) { - // how? - return; + current_milk = ammo.find( "milk" ); + if( current_milk == ammo.end() ) { + debugmsg( "%s has neither milk nor raw milk in its udders", get_name() ); + return; + } else { + // take this opportunity to update udders to raw_milk + std::swap( ammo["milk_raw"], current_milk->second ); + // Erase old key-value from map + ammo.erase( current_milk ); + current_milk = ammo.find( "milk_raw" ); + if( current_milk == ammo.end() ) { + //how? + return; + } + } } // if we got here, we got milk. if( current_milk->second == milked_item->second ) { @@ -2825,7 +2838,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; From 67b15306b385fed0bb622969c680f3948e937621 Mon Sep 17 00:00:00 2001 From: dpwb Date: Thu, 13 Feb 2020 21:36:59 +0000 Subject: [PATCH 03/10] remove unreachable section --- src/monster.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/monster.cpp b/src/monster.cpp index fbaef54174573..5ba5ee2c16e2e 100644 --- a/src/monster.cpp +++ b/src/monster.cpp @@ -386,10 +386,6 @@ void monster::refill_udders() // Erase old key-value from map ammo.erase( current_milk ); current_milk = ammo.find( "milk_raw" ); - if( current_milk == ammo.end() ) { - //how? - return; - } } } // if we got here, we got milk. From 589631facfd2f0d1b92be5350b5f1a0e0f972245 Mon Sep 17 00:00:00 2001 From: dpwb Date: Tue, 25 Feb 2020 00:25:38 +0000 Subject: [PATCH 04/10] fix milk checking - stop restricting to milk type except when its the case of upgrading milk to raw_milk --- data/json/monsters/mammal.json | 4 ++-- src/activity_handlers.cpp | 4 ++-- src/game.cpp | 4 +++- src/monexamine.cpp | 11 ++++++----- src/monmove.cpp | 4 ---- src/monster.cpp | 34 ++++++++++++++-------------------- src/monstergenerator.cpp | 11 +++++++++++ src/savegame_json.cpp | 10 +++++++++- 8 files changed, 47 insertions(+), 35 deletions(-) diff --git a/data/json/monsters/mammal.json b/data/json/monsters/mammal.json index ac9b287c3a2ae..2987cafcaccc4 100644 --- a/data/json/monsters/mammal.json +++ b/data/json/monsters/mammal.json @@ -344,7 +344,7 @@ "melee_cut": 6, "dodge": 2, "armor_bash": 2, - "starting_ammo": { "milk_raw": 40 }, + "starting_ammo": { "water": 40 }, "path_settings": { "max_dist": 10 }, "anger_triggers": [ "HURT" ], "fear_triggers": [ "PLAYER_CLOSE" ], @@ -1876,7 +1876,7 @@ "melee_dice_sides": 6, "melee_cut": 2, "dodge": 2, - "starting_ammo": { "milk_raw": 5 }, + "starting_ammo": { "water": 5 }, "anger_triggers": [ ], "harvest": "mammal_large_wool", "reproduction": { "baby_monster": "mon_sheep_lamb", "baby_count": 1, "baby_timer": 275 }, 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 7b25ad770e482..3bc628a2f3695 100644 --- a/src/monexamine.cpp +++ b/src/monexamine.cpp @@ -668,13 +668,14 @@ void monexamine::tie_or_untie( monster &z ) void monexamine::milk_source( monster &source_mon ) { - auto milked_item = source_mon.ammo.find( "milk_raw" ); - if( milked_item == source_mon.ammo.end() ) { - add_msg( m_info, _( "The %s has no milk." ), 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/monmove.cpp b/src/monmove.cpp index a91efe9bdebe5..50724571a6acf 100644 --- a/src/monmove.cpp +++ b/src/monmove.cpp @@ -576,7 +576,6 @@ void monster::move() if( wandf > 0 ) { wandf--; } - //Hallucinations have a chance of disappearing each turn if( is_hallucination() && one_in( 25 ) ) { die( nullptr ); @@ -631,9 +630,7 @@ void monster::move() if( !local_attack_data.enabled ) { continue; } - // Cooldowns are decremented in monster::process_turn - if( local_attack_data.cooldown == 0 && !pacified && !is_hallucination() ) { if( !sp_type.second->call( *this ) ) { continue; @@ -647,7 +644,6 @@ void monster::move() reset_special( special_name ); } } - // Check if they're dragging a foe and find their hapless victim player *dragged_foe = find_dragged_foe(); diff --git a/src/monster.cpp b/src/monster.cpp index 5ba5ee2c16e2e..8511543d84b6f 100644 --- a/src/monster.cpp +++ b/src/monster.cpp @@ -362,40 +362,34 @@ void monster::try_reproduce() void monster::refill_udders() { - auto milked_item = type->starting_ammo.find( "milk_raw " ); - if( milked_item == type->starting_ammo.end() ) { - milked_item = type->starting_ammo.find( "milk" ); - if( milked_item == type->starting_ammo.end() ) { - // this may be a sheep from a very old save. - // sheep didnt use to be milkable, but now they have that flag, - // but the old save would keep their old blank starting ammo. - // cant modify the type, and cant get what their starting ammo should be. - // so just let the sheep remain milkless - return; - } + if( type->starting_ammo.empty() ) { + std::cout << "starting ammo empty" << std::endl; + debugmsg( "monster %s has no starting ammo to refill udders", get_name() ); + return; + } + std::cout << "refill udders started for " << get_name() << std::endl; + 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( current_milk == ammo.end() ) { current_milk = ammo.find( "milk" ); - if( current_milk == ammo.end() ) { - debugmsg( "%s has neither milk nor raw milk in its udders", get_name() ); - return; - } else { - // take this opportunity to update udders to raw_milk - std::swap( ammo["milk_raw"], current_milk->second ); + 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 ); - current_milk = ammo.find( "milk_raw" ); } } // if we got here, we got milk. - if( current_milk->second == milked_item->second ) { + 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; } } 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..8338c0ff69b4f 100644 --- a/src/savegame_json.cpp +++ b/src/savegame_json.cpp @@ -1931,10 +1931,18 @@ void monster::load( const JsonObject &data ) data.read( "dragged_foe_id", dragged_foe_id ); if( data.has_int( "ammo" ) && !type->starting_ammo.empty() ) { - // Legacy loading for ammo. + // Legacy loading for ammo.z 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", "" ) ); From fd7f2bb53169a5fa606cd6abe9592d9d157735d5 Mon Sep 17 00:00:00 2001 From: dpwb Date: Tue, 25 Feb 2020 00:30:29 +0000 Subject: [PATCH 05/10] remove debug code --- src/monster.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/monster.cpp b/src/monster.cpp index 8511543d84b6f..e810c9c043f3a 100644 --- a/src/monster.cpp +++ b/src/monster.cpp @@ -363,11 +363,9 @@ void monster::try_reproduce() void monster::refill_udders() { if( type->starting_ammo.empty() ) { - std::cout << "starting ammo empty" << std::endl; debugmsg( "monster %s has no starting ammo to refill udders", get_name() ); return; } - std::cout << "refill udders started for " << get_name() << std::endl; 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; From 1b69d51ef23a521f5a0856a2a74f2b2777671a21 Mon Sep 17 00:00:00 2001 From: dpwb Date: Tue, 25 Feb 2020 00:34:45 +0000 Subject: [PATCH 06/10] remove test code that turned milk to water --- data/json/monsters/mammal.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/json/monsters/mammal.json b/data/json/monsters/mammal.json index 2987cafcaccc4..ac9b287c3a2ae 100644 --- a/data/json/monsters/mammal.json +++ b/data/json/monsters/mammal.json @@ -344,7 +344,7 @@ "melee_cut": 6, "dodge": 2, "armor_bash": 2, - "starting_ammo": { "water": 40 }, + "starting_ammo": { "milk_raw": 40 }, "path_settings": { "max_dist": 10 }, "anger_triggers": [ "HURT" ], "fear_triggers": [ "PLAYER_CLOSE" ], @@ -1876,7 +1876,7 @@ "melee_dice_sides": 6, "melee_cut": 2, "dodge": 2, - "starting_ammo": { "water": 5 }, + "starting_ammo": { "milk_raw": 5 }, "anger_triggers": [ ], "harvest": "mammal_large_wool", "reproduction": { "baby_monster": "mon_sheep_lamb", "baby_count": 1, "baby_timer": 275 }, From 57533688d27afe3a45aba0e33205e14b0bfac65d Mon Sep 17 00:00:00 2001 From: dpwb Date: Tue, 25 Feb 2020 00:35:34 +0000 Subject: [PATCH 07/10] remove erroneous edits to monmove.cpp --- src/monmove.cpp | 97 ++++++++++++++++++++++++++----------------------- 1 file changed, 52 insertions(+), 45 deletions(-) diff --git a/src/monmove.cpp b/src/monmove.cpp index 50724571a6acf..a11fece252eaf 100644 --- a/src/monmove.cpp +++ b/src/monmove.cpp @@ -52,13 +52,13 @@ bool monster::wander() bool monster::is_immune_field( const field_type_id &fid ) const { if( fid == fd_fungal_haze ) { - return has_flag( MF_NO_BREATHE ) || type->in_species( FUNGUS ); + return has_flag( MF_NO_BREATHE ) || type->in_species( species_FUNGUS ); } if( fid == fd_fungicidal_gas ) { - return !type->in_species( FUNGUS ); + return !type->in_species( species_FUNGUS ); } if( fid == fd_insecticidal_gas ) { - return !type->in_species( INSECT ) && !type->in_species( SPIDER ); + return !type->in_species( species_INSECT ) && !type->in_species( species_SPIDER ); } const field_type &ft = fid.obj(); if( ft.has_fume ) { @@ -89,10 +89,10 @@ bool monster::will_move_to( const tripoint &p ) const { if( g->m.impassable( p ) ) { if( digging() ) { - if( !g->m.has_flag( "BURROWABLE", p ) ) { + if( !g->m.has_flag( flag_BURROWABLE, p ) ) { return false; } - } else if( !( can_climb() && g->m.has_flag( "CLIMBABLE", p ) ) ) { + } else if( !( can_climb() && g->m.has_flag( flag_CLIMBABLE, p ) ) ) { return false; } } @@ -101,11 +101,11 @@ bool monster::will_move_to( const tripoint &p ) const return false; } - if( digs() && !g->m.has_flag( "DIGGABLE", p ) && !g->m.has_flag( "BURROWABLE", p ) ) { + if( digs() && !g->m.has_flag( flag_DIGGABLE, p ) && !g->m.has_flag( flag_BURROWABLE, p ) ) { return false; } - if( has_flag( MF_AQUATIC ) && !g->m.has_flag( "SWIMMABLE", p ) ) { + if( has_flag( MF_AQUATIC ) && !g->m.has_flag( flag_SWIMMABLE, p ) ) { return false; } @@ -163,7 +163,7 @@ bool monster::will_move_to( const tripoint &p ) const // Some things are only avoided if we're not attacking if( attitude( &g->u ) != MATT_ATTACK ) { // Sharp terrain is ignored while attacking - if( avoid_simple && g->m.has_flag( "SHARP", p ) && + if( avoid_simple && g->m.has_flag( flag_SHARP, p ) && !( type->size == MS_TINY || flies() ) ) { return false; } @@ -462,7 +462,7 @@ void monster::plan() friendly = 100; for( auto critter : g->m.get_creatures_in_radius( pos(), 6 ) ) { monster *mon = dynamic_cast( critter ); - if( mon != nullptr && mon->type->in_species( ZOMBIE ) ) { + if( mon != nullptr && mon->type->in_species( species_ZOMBIE ) ) { anger = 100; } else { anger = 0; @@ -546,14 +546,19 @@ static float get_stagger_adjust( const tripoint &source, const tripoint &destina return std::max( 0.01f, initial_dist - new_dist ); } +/** + * Returns true if the given square presents a possibility of drowning for the monster: it's deep water, it's liquid, + * the monster can drown, and there is no boardable vehicle part present. + */ +bool monster::is_aquatic_danger( const tripoint &at_pos ) +{ + return g->m.has_flag_ter( TFLAG_DEEP_WATER, at_pos ) && g->m.has_flag( flag_LIQUID, at_pos ) && + can_drown() && !g->m.veh_at( at_pos ).part_with_feature( flag_BOARDABLE, false ); +} + bool monster::die_if_drowning( const tripoint &at_pos, const int chance ) { - if( g->m.has_flag( "LIQUID", at_pos ) && can_drown() && one_in( chance ) ) { - // if there's a vehicle here with a boardable part, the monster is on it - // and not drowning - if( g->m.veh_at( at_pos ).part_with_feature( "BOARDABLE", false ) ) { - return false; - } + if( is_aquatic_danger( at_pos ) && one_in( chance ) ) { die( nullptr ); if( g->u.sees( at_pos ) ) { add_msg( _( "The %s drowns!" ), name() ); @@ -576,6 +581,7 @@ void monster::move() if( wandf > 0 ) { wandf--; } + //Hallucinations have a chance of disappearing each turn if( is_hallucination() && one_in( 25 ) ) { die( nullptr ); @@ -630,7 +636,9 @@ void monster::move() if( !local_attack_data.enabled ) { continue; } + // Cooldowns are decremented in monster::process_turn + if( local_attack_data.cooldown == 0 && !pacified && !is_hallucination() ) { if( !sp_type.second->call( *this ) ) { continue; @@ -644,6 +652,7 @@ void monster::move() reset_special( special_name ); } } + // Check if they're dragging a foe and find their hapless victim player *dragged_foe = find_dragged_foe(); @@ -658,11 +667,9 @@ void monster::move() } } - // The monster is in a deep water tile and has a chance to drown - if( g->m.has_flag_ter( TFLAG_DEEP_WATER, pos() ) ) { - if( die_if_drowning( pos(), 10 ) ) { - return; - } + // if the monster is in a deep water tile, it has a chance to drown + if( die_if_drowning( pos(), 10 ) ) { + return; } if( moves < 0 ) { @@ -690,7 +697,7 @@ void monster::move() // don't move if a passenger in a moving vehicle auto vp = g->m.veh_at( pos() ); - bool harness_part = static_cast( g->m.veh_at( pos() ).part_with_feature( "ANIMAL_CTRL", + bool harness_part = static_cast( g->m.veh_at( pos() ).part_with_feature( flag_ANIMAL_CTRL, true ) ); if( vp && vp->vehicle().is_moving() && vp->vehicle().get_pet( vp->part_index() ) ) { moves = 0; @@ -1128,40 +1135,40 @@ int monster::calc_movecost( const tripoint &f, const tripoint &t ) const const int source_cost = g->m.move_cost( f ); const int dest_cost = g->m.move_cost( t ); // Digging and flying monsters ignore terrain cost - if( flies() || ( digging() && g->m.has_flag( "DIGGABLE", t ) ) ) { + if( flies() || ( digging() && g->m.has_flag( flag_DIGGABLE, t ) ) ) { movecost = 100; // Swimming monsters move super fast in water } else if( swims() ) { - if( g->m.has_flag( "SWIMMABLE", f ) ) { + if( g->m.has_flag( flag_SWIMMABLE, f ) ) { movecost += 25; } else { movecost += 50 * g->m.move_cost( f ); } - if( g->m.has_flag( "SWIMMABLE", t ) ) { + if( g->m.has_flag( flag_SWIMMABLE, t ) ) { movecost += 25; } else { movecost += 50 * g->m.move_cost( t ); } } else if( can_submerge() ) { // No-breathe monsters have to walk underwater slowly - if( g->m.has_flag( "SWIMMABLE", f ) ) { + if( g->m.has_flag( flag_SWIMMABLE, f ) ) { movecost += 250; } else { movecost += 50 * g->m.move_cost( f ); } - if( g->m.has_flag( "SWIMMABLE", t ) ) { + if( g->m.has_flag( flag_SWIMMABLE, t ) ) { movecost += 250; } else { movecost += 50 * g->m.move_cost( t ); } movecost /= 2; } else if( climbs() ) { - if( g->m.has_flag( "CLIMBABLE", f ) ) { + if( g->m.has_flag( flag_CLIMBABLE, f ) ) { movecost += 150; } else { movecost += 50 * g->m.move_cost( f ); } - if( g->m.has_flag( "CLIMBABLE", t ) ) { + if( g->m.has_flag( flag_CLIMBABLE, t ) ) { movecost += 150; } else { movecost += 50 * g->m.move_cost( t ); @@ -1248,7 +1255,7 @@ bool monster::bash_at( const tripoint &p ) return false; } - bool flat_ground = g->m.has_flag( "ROAD", p ) || g->m.has_flag( "FLAT", p ); + bool flat_ground = g->m.has_flag( flag_ROAD, p ) || g->m.has_flag( flag_FLAT, p ); if( flat_ground ) { bool can_bash_ter = g->m.is_bashable_ter( p ); bool try_bash_ter = one_in( 50 ); @@ -1408,14 +1415,14 @@ bool monster::move_to( const tripoint &p, bool force, const float stagger_adjust // Allows climbing monsters to move on terrain with movecost <= 0 Creature *critter = g->critter_at( destination, is_hallucination() ); - if( g->m.has_flag( "CLIMBABLE", destination ) ) { + if( g->m.has_flag( flag_CLIMBABLE, destination ) ) { if( g->m.impassable( destination ) && critter == nullptr ) { if( flies() ) { moves -= 100; force = true; if( g->u.sees( *this ) ) { add_msg( _( "The %1$s flies over the %2$s." ), name(), - g->m.has_flag_furn( "CLIMBABLE", p ) ? g->m.furnname( p ) : + g->m.has_flag_furn( flag_CLIMBABLE, p ) ? g->m.furnname( p ) : g->m.tername( p ) ); } } else if( climbs() ) { @@ -1423,7 +1430,7 @@ bool monster::move_to( const tripoint &p, bool force, const float stagger_adjust force = true; if( g->u.sees( *this ) ) { add_msg( _( "The %1$s climbs over the %2$s." ), name(), - g->m.has_flag_furn( "CLIMBABLE", p ) ? g->m.furnname( p ) : + g->m.has_flag_furn( flag_CLIMBABLE, p ) ? g->m.furnname( p ) : g->m.tername( p ) ); } } @@ -1491,15 +1498,17 @@ bool monster::move_to( const tripoint &p, bool force, const float stagger_adjust if( type->size != MS_TINY && on_ground ) { const int sharp_damage = rng( 1, 10 ); const int rough_damage = rng( 1, 2 ); - if( g->m.has_flag( "SHARP", pos() ) && !one_in( 4 ) && get_armor_cut( bp_torso ) < sharp_damage ) { + if( g->m.has_flag( flag_SHARP, pos() ) && !one_in( 4 ) && + get_armor_cut( bp_torso ) < sharp_damage ) { apply_damage( nullptr, bp_torso, sharp_damage ); } - if( g->m.has_flag( "ROUGH", pos() ) && one_in( 6 ) && get_armor_cut( bp_torso ) < rough_damage ) { + if( g->m.has_flag( flag_ROUGH, pos() ) && one_in( 6 ) && + get_armor_cut( bp_torso ) < rough_damage ) { apply_damage( nullptr, bp_torso, rough_damage ); } } - if( g->m.has_flag( "UNSTABLE", destination ) && on_ground ) { + if( g->m.has_flag( flag_UNSTABLE, destination ) && on_ground ) { add_effect( effect_bouldering, 1_turns, num_bp, true ); } else if( has_effect( effect_bouldering ) ) { remove_effect( effect_bouldering ); @@ -1516,10 +1525,10 @@ bool monster::move_to( const tripoint &p, bool force, const float stagger_adjust return true; } if( !will_be_water && ( digs() || can_dig() ) ) { - underwater = g->m.has_flag( "DIGGABLE", pos() ); + underwater = g->m.has_flag( flag_DIGGABLE, pos() ); } // Diggers turn the dirt into dirtmound - if( digging() && g->m.has_flag( "DIGGABLE", pos() ) ) { + if( digging() && g->m.has_flag( flag_DIGGABLE, pos() ) ) { int factor = 0; switch( type->size ) { case MS_TINY: @@ -1812,14 +1821,12 @@ void monster::knock_back_to( const tripoint &to ) } // If we're still in the function at this point, we're actually moving a tile! - if( g->m.has_flag_ter( TFLAG_DEEP_WATER, to ) ) { - // die_if_drowning will kill the monster if necessary, but if the deep water - // tile is on a vehicle, we should check for swimmers out of water - if( !die_if_drowning( to ) && has_flag( MF_AQUATIC ) ) { - die( nullptr ); - if( u_see ) { - add_msg( _( "The %s flops around and dies!" ), name() ); - } + // die_if_drowning will kill the monster if necessary, but if the deep water + // tile is on a vehicle, we should check for swimmers out of water + if( !die_if_drowning( to ) && has_flag( MF_AQUATIC ) ) { + die( nullptr ); + if( u_see ) { + add_msg( _( "The %s flops around and dies!" ), name() ); } } From fee7f6ca53d29262c62b34c17bab57d4b9b6a822 Mon Sep 17 00:00:00 2001 From: dpwb Date: Tue, 25 Feb 2020 00:37:36 +0000 Subject: [PATCH 08/10] Revert "remove erroneous edits to monmove.cpp" This reverts commit 57533688d27afe3a45aba0e33205e14b0bfac65d. --- src/monmove.cpp | 97 +++++++++++++++++++++++-------------------------- 1 file changed, 45 insertions(+), 52 deletions(-) diff --git a/src/monmove.cpp b/src/monmove.cpp index a11fece252eaf..50724571a6acf 100644 --- a/src/monmove.cpp +++ b/src/monmove.cpp @@ -52,13 +52,13 @@ bool monster::wander() bool monster::is_immune_field( const field_type_id &fid ) const { if( fid == fd_fungal_haze ) { - return has_flag( MF_NO_BREATHE ) || type->in_species( species_FUNGUS ); + return has_flag( MF_NO_BREATHE ) || type->in_species( FUNGUS ); } if( fid == fd_fungicidal_gas ) { - return !type->in_species( species_FUNGUS ); + return !type->in_species( FUNGUS ); } if( fid == fd_insecticidal_gas ) { - return !type->in_species( species_INSECT ) && !type->in_species( species_SPIDER ); + return !type->in_species( INSECT ) && !type->in_species( SPIDER ); } const field_type &ft = fid.obj(); if( ft.has_fume ) { @@ -89,10 +89,10 @@ bool monster::will_move_to( const tripoint &p ) const { if( g->m.impassable( p ) ) { if( digging() ) { - if( !g->m.has_flag( flag_BURROWABLE, p ) ) { + if( !g->m.has_flag( "BURROWABLE", p ) ) { return false; } - } else if( !( can_climb() && g->m.has_flag( flag_CLIMBABLE, p ) ) ) { + } else if( !( can_climb() && g->m.has_flag( "CLIMBABLE", p ) ) ) { return false; } } @@ -101,11 +101,11 @@ bool monster::will_move_to( const tripoint &p ) const return false; } - if( digs() && !g->m.has_flag( flag_DIGGABLE, p ) && !g->m.has_flag( flag_BURROWABLE, p ) ) { + if( digs() && !g->m.has_flag( "DIGGABLE", p ) && !g->m.has_flag( "BURROWABLE", p ) ) { return false; } - if( has_flag( MF_AQUATIC ) && !g->m.has_flag( flag_SWIMMABLE, p ) ) { + if( has_flag( MF_AQUATIC ) && !g->m.has_flag( "SWIMMABLE", p ) ) { return false; } @@ -163,7 +163,7 @@ bool monster::will_move_to( const tripoint &p ) const // Some things are only avoided if we're not attacking if( attitude( &g->u ) != MATT_ATTACK ) { // Sharp terrain is ignored while attacking - if( avoid_simple && g->m.has_flag( flag_SHARP, p ) && + if( avoid_simple && g->m.has_flag( "SHARP", p ) && !( type->size == MS_TINY || flies() ) ) { return false; } @@ -462,7 +462,7 @@ void monster::plan() friendly = 100; for( auto critter : g->m.get_creatures_in_radius( pos(), 6 ) ) { monster *mon = dynamic_cast( critter ); - if( mon != nullptr && mon->type->in_species( species_ZOMBIE ) ) { + if( mon != nullptr && mon->type->in_species( ZOMBIE ) ) { anger = 100; } else { anger = 0; @@ -546,19 +546,14 @@ static float get_stagger_adjust( const tripoint &source, const tripoint &destina return std::max( 0.01f, initial_dist - new_dist ); } -/** - * Returns true if the given square presents a possibility of drowning for the monster: it's deep water, it's liquid, - * the monster can drown, and there is no boardable vehicle part present. - */ -bool monster::is_aquatic_danger( const tripoint &at_pos ) -{ - return g->m.has_flag_ter( TFLAG_DEEP_WATER, at_pos ) && g->m.has_flag( flag_LIQUID, at_pos ) && - can_drown() && !g->m.veh_at( at_pos ).part_with_feature( flag_BOARDABLE, false ); -} - bool monster::die_if_drowning( const tripoint &at_pos, const int chance ) { - if( is_aquatic_danger( at_pos ) && one_in( chance ) ) { + if( g->m.has_flag( "LIQUID", at_pos ) && can_drown() && one_in( chance ) ) { + // if there's a vehicle here with a boardable part, the monster is on it + // and not drowning + if( g->m.veh_at( at_pos ).part_with_feature( "BOARDABLE", false ) ) { + return false; + } die( nullptr ); if( g->u.sees( at_pos ) ) { add_msg( _( "The %s drowns!" ), name() ); @@ -581,7 +576,6 @@ void monster::move() if( wandf > 0 ) { wandf--; } - //Hallucinations have a chance of disappearing each turn if( is_hallucination() && one_in( 25 ) ) { die( nullptr ); @@ -636,9 +630,7 @@ void monster::move() if( !local_attack_data.enabled ) { continue; } - // Cooldowns are decremented in monster::process_turn - if( local_attack_data.cooldown == 0 && !pacified && !is_hallucination() ) { if( !sp_type.second->call( *this ) ) { continue; @@ -652,7 +644,6 @@ void monster::move() reset_special( special_name ); } } - // Check if they're dragging a foe and find their hapless victim player *dragged_foe = find_dragged_foe(); @@ -667,9 +658,11 @@ void monster::move() } } - // if the monster is in a deep water tile, it has a chance to drown - if( die_if_drowning( pos(), 10 ) ) { - return; + // The monster is in a deep water tile and has a chance to drown + if( g->m.has_flag_ter( TFLAG_DEEP_WATER, pos() ) ) { + if( die_if_drowning( pos(), 10 ) ) { + return; + } } if( moves < 0 ) { @@ -697,7 +690,7 @@ void monster::move() // don't move if a passenger in a moving vehicle auto vp = g->m.veh_at( pos() ); - bool harness_part = static_cast( g->m.veh_at( pos() ).part_with_feature( flag_ANIMAL_CTRL, + bool harness_part = static_cast( g->m.veh_at( pos() ).part_with_feature( "ANIMAL_CTRL", true ) ); if( vp && vp->vehicle().is_moving() && vp->vehicle().get_pet( vp->part_index() ) ) { moves = 0; @@ -1135,40 +1128,40 @@ int monster::calc_movecost( const tripoint &f, const tripoint &t ) const const int source_cost = g->m.move_cost( f ); const int dest_cost = g->m.move_cost( t ); // Digging and flying monsters ignore terrain cost - if( flies() || ( digging() && g->m.has_flag( flag_DIGGABLE, t ) ) ) { + if( flies() || ( digging() && g->m.has_flag( "DIGGABLE", t ) ) ) { movecost = 100; // Swimming monsters move super fast in water } else if( swims() ) { - if( g->m.has_flag( flag_SWIMMABLE, f ) ) { + if( g->m.has_flag( "SWIMMABLE", f ) ) { movecost += 25; } else { movecost += 50 * g->m.move_cost( f ); } - if( g->m.has_flag( flag_SWIMMABLE, t ) ) { + if( g->m.has_flag( "SWIMMABLE", t ) ) { movecost += 25; } else { movecost += 50 * g->m.move_cost( t ); } } else if( can_submerge() ) { // No-breathe monsters have to walk underwater slowly - if( g->m.has_flag( flag_SWIMMABLE, f ) ) { + if( g->m.has_flag( "SWIMMABLE", f ) ) { movecost += 250; } else { movecost += 50 * g->m.move_cost( f ); } - if( g->m.has_flag( flag_SWIMMABLE, t ) ) { + if( g->m.has_flag( "SWIMMABLE", t ) ) { movecost += 250; } else { movecost += 50 * g->m.move_cost( t ); } movecost /= 2; } else if( climbs() ) { - if( g->m.has_flag( flag_CLIMBABLE, f ) ) { + if( g->m.has_flag( "CLIMBABLE", f ) ) { movecost += 150; } else { movecost += 50 * g->m.move_cost( f ); } - if( g->m.has_flag( flag_CLIMBABLE, t ) ) { + if( g->m.has_flag( "CLIMBABLE", t ) ) { movecost += 150; } else { movecost += 50 * g->m.move_cost( t ); @@ -1255,7 +1248,7 @@ bool monster::bash_at( const tripoint &p ) return false; } - bool flat_ground = g->m.has_flag( flag_ROAD, p ) || g->m.has_flag( flag_FLAT, p ); + bool flat_ground = g->m.has_flag( "ROAD", p ) || g->m.has_flag( "FLAT", p ); if( flat_ground ) { bool can_bash_ter = g->m.is_bashable_ter( p ); bool try_bash_ter = one_in( 50 ); @@ -1415,14 +1408,14 @@ bool monster::move_to( const tripoint &p, bool force, const float stagger_adjust // Allows climbing monsters to move on terrain with movecost <= 0 Creature *critter = g->critter_at( destination, is_hallucination() ); - if( g->m.has_flag( flag_CLIMBABLE, destination ) ) { + if( g->m.has_flag( "CLIMBABLE", destination ) ) { if( g->m.impassable( destination ) && critter == nullptr ) { if( flies() ) { moves -= 100; force = true; if( g->u.sees( *this ) ) { add_msg( _( "The %1$s flies over the %2$s." ), name(), - g->m.has_flag_furn( flag_CLIMBABLE, p ) ? g->m.furnname( p ) : + g->m.has_flag_furn( "CLIMBABLE", p ) ? g->m.furnname( p ) : g->m.tername( p ) ); } } else if( climbs() ) { @@ -1430,7 +1423,7 @@ bool monster::move_to( const tripoint &p, bool force, const float stagger_adjust force = true; if( g->u.sees( *this ) ) { add_msg( _( "The %1$s climbs over the %2$s." ), name(), - g->m.has_flag_furn( flag_CLIMBABLE, p ) ? g->m.furnname( p ) : + g->m.has_flag_furn( "CLIMBABLE", p ) ? g->m.furnname( p ) : g->m.tername( p ) ); } } @@ -1498,17 +1491,15 @@ bool monster::move_to( const tripoint &p, bool force, const float stagger_adjust if( type->size != MS_TINY && on_ground ) { const int sharp_damage = rng( 1, 10 ); const int rough_damage = rng( 1, 2 ); - if( g->m.has_flag( flag_SHARP, pos() ) && !one_in( 4 ) && - get_armor_cut( bp_torso ) < sharp_damage ) { + if( g->m.has_flag( "SHARP", pos() ) && !one_in( 4 ) && get_armor_cut( bp_torso ) < sharp_damage ) { apply_damage( nullptr, bp_torso, sharp_damage ); } - if( g->m.has_flag( flag_ROUGH, pos() ) && one_in( 6 ) && - get_armor_cut( bp_torso ) < rough_damage ) { + if( g->m.has_flag( "ROUGH", pos() ) && one_in( 6 ) && get_armor_cut( bp_torso ) < rough_damage ) { apply_damage( nullptr, bp_torso, rough_damage ); } } - if( g->m.has_flag( flag_UNSTABLE, destination ) && on_ground ) { + if( g->m.has_flag( "UNSTABLE", destination ) && on_ground ) { add_effect( effect_bouldering, 1_turns, num_bp, true ); } else if( has_effect( effect_bouldering ) ) { remove_effect( effect_bouldering ); @@ -1525,10 +1516,10 @@ bool monster::move_to( const tripoint &p, bool force, const float stagger_adjust return true; } if( !will_be_water && ( digs() || can_dig() ) ) { - underwater = g->m.has_flag( flag_DIGGABLE, pos() ); + underwater = g->m.has_flag( "DIGGABLE", pos() ); } // Diggers turn the dirt into dirtmound - if( digging() && g->m.has_flag( flag_DIGGABLE, pos() ) ) { + if( digging() && g->m.has_flag( "DIGGABLE", pos() ) ) { int factor = 0; switch( type->size ) { case MS_TINY: @@ -1821,12 +1812,14 @@ void monster::knock_back_to( const tripoint &to ) } // If we're still in the function at this point, we're actually moving a tile! - // die_if_drowning will kill the monster if necessary, but if the deep water - // tile is on a vehicle, we should check for swimmers out of water - if( !die_if_drowning( to ) && has_flag( MF_AQUATIC ) ) { - die( nullptr ); - if( u_see ) { - add_msg( _( "The %s flops around and dies!" ), name() ); + if( g->m.has_flag_ter( TFLAG_DEEP_WATER, to ) ) { + // die_if_drowning will kill the monster if necessary, but if the deep water + // tile is on a vehicle, we should check for swimmers out of water + if( !die_if_drowning( to ) && has_flag( MF_AQUATIC ) ) { + die( nullptr ); + if( u_see ) { + add_msg( _( "The %s flops around and dies!" ), name() ); + } } } From 43e57729c395b27dca5fd3c9291af4f9958a03e3 Mon Sep 17 00:00:00 2001 From: dpwb Date: Tue, 25 Feb 2020 00:39:03 +0000 Subject: [PATCH 09/10] remove erroneous edits --- src/monmove.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/monmove.cpp b/src/monmove.cpp index 50724571a6acf..a91efe9bdebe5 100644 --- a/src/monmove.cpp +++ b/src/monmove.cpp @@ -576,6 +576,7 @@ void monster::move() if( wandf > 0 ) { wandf--; } + //Hallucinations have a chance of disappearing each turn if( is_hallucination() && one_in( 25 ) ) { die( nullptr ); @@ -630,7 +631,9 @@ void monster::move() if( !local_attack_data.enabled ) { continue; } + // Cooldowns are decremented in monster::process_turn + if( local_attack_data.cooldown == 0 && !pacified && !is_hallucination() ) { if( !sp_type.second->call( *this ) ) { continue; @@ -644,6 +647,7 @@ void monster::move() reset_special( special_name ); } } + // Check if they're dragging a foe and find their hapless victim player *dragged_foe = find_dragged_foe(); From c26d600f52b94d3a2959750748658d41076ef681 Mon Sep 17 00:00:00 2001 From: davidpwbrown <39344466+davidpwbrown@users.noreply.github.com> Date: Tue, 25 Feb 2020 00:40:09 +0000 Subject: [PATCH 10/10] Update src/savegame_json.cpp --- src/savegame_json.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/savegame_json.cpp b/src/savegame_json.cpp index 8338c0ff69b4f..738710b01d857 100644 --- a/src/savegame_json.cpp +++ b/src/savegame_json.cpp @@ -1931,7 +1931,7 @@ void monster::load( const JsonObject &data ) data.read( "dragged_foe_id", dragged_foe_id ); if( data.has_int( "ammo" ) && !type->starting_ammo.empty() ) { - // Legacy loading for ammo.z + // Legacy loading for ammo. normalize_ammo( data.get_int( "ammo" ) ); } else { data.read( "ammo", ammo );