diff --git a/src/activity_handlers.cpp b/src/activity_handlers.cpp index e8a8ace636003..c700e3aae06e7 100644 --- a/src/activity_handlers.cpp +++ b/src/activity_handlers.cpp @@ -218,6 +218,7 @@ static const skill_id skill_computer( "computer" ); static const skill_id skill_firstaid( "firstaid" ); static const skill_id skill_survival( "survival" ); +static const species_id species_FERAL( "FERAL" ); static const species_id species_HUMAN( "HUMAN" ); static const species_id species_ZOMBIE( "ZOMBIE" ); @@ -532,7 +533,8 @@ static void set_up_butchery( player_activity &act, Character &you, butcher_type } } - const bool is_human = corpse.id == mtype_id::NULL_ID() || ( corpse.in_species( species_HUMAN ) && + const bool is_human = corpse.id == mtype_id::NULL_ID() || ( ( corpse.in_species( species_HUMAN ) || + corpse.in_species( species_FERAL ) ) && !corpse.in_species( species_ZOMBIE ) ); // applies to all butchery actions except for dissections diff --git a/src/npc.cpp b/src/npc.cpp index 213c6f0c19dc0..a96c992aa6955 100644 --- a/src/npc.cpp +++ b/src/npc.cpp @@ -115,6 +115,11 @@ static const item_group_id Item_spawn_data_survivor_bashing( "survivor_bashing" static const item_group_id Item_spawn_data_survivor_cutting( "survivor_cutting" ); static const item_group_id Item_spawn_data_survivor_stabbing( "survivor_stabbing" ); +static const json_character_flag json_flag_CANNIBAL( "CANNIBAL" ); +static const json_character_flag json_flag_PSYCHOPATH( "PSYCHOPATH" ); +static const json_character_flag json_flag_SAPIOVORE( "SAPIOVORE" ); +static const json_character_flag json_flag_SPIRITUAL( "SPIRITUAL" ); + static const mfaction_str_id monfaction_bee( "bee" ); static const mfaction_str_id monfaction_human( "human" ); static const mfaction_str_id monfaction_player( "player" ); @@ -144,14 +149,13 @@ static const skill_id skill_throw( "throw" ); static const skill_id skill_unarmed( "unarmed" ); static const trait_id trait_BEE( "BEE" ); -static const trait_id trait_CANNIBAL( "CANNIBAL" ); static const trait_id trait_DEBUG_MIND_CONTROL( "DEBUG_MIND_CONTROL" ); static const trait_id trait_HALLUCINATION( "HALLUCINATION" ); +static const trait_id trait_KILLER( "KILLER" ); static const trait_id trait_MUTE( "MUTE" ); static const trait_id trait_NO_BASH( "NO_BASH" ); +static const trait_id trait_PACIFIST( "PACIFIST" ); static const trait_id trait_PROF_DICEMASTER( "PROF_DICEMASTER" ); -static const trait_id trait_PSYCHOPATH( "PSYCHOPATH" ); -static const trait_id trait_SAPIOVORE( "SAPIOVORE" ); static const trait_id trait_SQUEAMISH( "SQUEAMISH" ); static const trait_id trait_TERRIFYING( "TERRIFYING" ); @@ -1668,7 +1672,7 @@ npc_opinion npc::get_opinion_values( const Character &you ) const } } - if( you.has_trait( trait_SAPIOVORE ) ) { + if( you.has_flag( json_flag_SAPIOVORE ) ) { npc_values.fear += 10; // Sapiovores = Scary } if( you.has_trait( trait_TERRIFYING ) ) { @@ -1855,7 +1859,7 @@ void npc::on_attacked( const Creature &attacker ) if( is_hallucination() ) { die( nullptr ); } - if( attacker.is_avatar() && !is_enemy() && !is_dead() ) { + if( attacker.is_avatar() && !is_enemy() && !is_dead() && !guaranteed_hostile() ) { make_angry(); hit_by_player = true; } @@ -2955,7 +2959,6 @@ void npc::die( Creature *nkiller ) // *only* set to true in this function! return; } - prevent_death_reminder = false; dialogue d( get_talker_for( this ), nkiller == nullptr ? nullptr : get_talker_for( nkiller ) ); for( effect_on_condition_id &eoc : death_eocs ) { @@ -3018,17 +3021,51 @@ void npc::die( Creature *nkiller ) if( Character *ch = dynamic_cast( killer ) ) { get_event_bus().send( ch->getID(), getID(), get_name() ); } - Character &player_character = get_player_character(); - if( killer == &player_character && ( !guaranteed_hostile() || hit_by_player ) ) { - bool cannibal = player_character.has_trait( trait_CANNIBAL ); - bool psycho = player_character.has_trait( trait_PSYCHOPATH ); - if( player_character.has_trait( trait_SAPIOVORE ) || psycho ) { - // No morale effect - } else if( cannibal ) { - player_character.add_morale( MORALE_KILLED_INNOCENT, -5, 0, 2_days, 3_hours ); - } else { - player_character.add_morale( MORALE_KILLED_INNOCENT, -100, 0, 2_days, 3_hours ); + if( killer == &player_character ) { + if( player_character.has_trait( trait_PACIFIST ) ) { + add_msg( _( "A cold shock of guilt washes over you." ) ); + player_character.add_morale( MORALE_KILLER_HAS_KILLED, -15, 0, 1_days, 1_hours ); + } + if( hit_by_player ) { + int morale_effect = -90; + // Just because you like eating people doesn't mean you love killing innocents + if( player_character.has_flag( json_flag_CANNIBAL ) && morale_effect < 0 ) { + morale_effect = std::min( 0, morale_effect + 50 ); + } // Pacifists double dip on penalties if they kill an innocent + if( player_character.has_trait( trait_PACIFIST ) ) { + morale_effect -= 15; + } + if( player_character.has_flag( json_flag_PSYCHOPATH ) || + player_character.has_flag( json_flag_SAPIOVORE ) ) { + morale_effect = 0; + } // Killer has the psychopath flag, so we're at +5 total. Whee! + if( player_character.has_trait( trait_KILLER ) ) { + morale_effect += 5; + } // only god can juge me + if( player_character.has_flag( json_flag_SPIRITUAL ) && + ( !player_character.has_flag( json_flag_PSYCHOPATH ) || + ( player_character.has_flag( json_flag_PSYCHOPATH ) && + player_character.has_trait( trait_KILLER ) ) ) && + !player_character.has_flag( json_flag_SAPIOVORE ) ) { + if( morale_effect < 0 ) { + add_msg( _( "You feel ashamed of your actions." ) ); + morale_effect -= 10; + } // skulls for the skull throne + if( morale_effect > 0 ) { + add_msg( _( "You feel a sense of righteous purpose." ) ); + morale_effect += 5; + } + } + if( morale_effect == 0 ) { + // No morale effect + } else if( morale_effect <= -50 ) { + player_character.add_morale( MORALE_KILLED_INNOCENT, morale_effect, 0, 2_days, 3_hours ); + } else if( morale_effect > -50 && morale_effect < 0 ) { + player_character.add_morale( MORALE_KILLED_INNOCENT, morale_effect, 0, 1_days, 1_hours ); + } else { + player_character.add_morale( MORALE_KILLED_INNOCENT, morale_effect, 0, 3_hours, 7_minutes ); + } } }