summaryrefslogtreecommitdiff
path: root/vampirism.patch
diff options
context:
space:
mode:
Diffstat (limited to 'vampirism.patch')
-rw-r--r--vampirism.patch730
1 files changed, 405 insertions, 325 deletions
diff --git a/vampirism.patch b/vampirism.patch
index 319e1fd..4e1ce30 100644
--- a/vampirism.patch
+++ b/vampirism.patch
@@ -1,47 +1,54 @@
--- a/src/activity_handlers.cpp
+++ b/src/activity_handlers.cpp
-@@ -231,6 +231,7 @@
- static const species_id species_HUMAN( "HUMAN" );
- static const species_id species_ZOMBIE( "ZOMBIE" );
+@@ -190,6 +190,7 @@
+ static const itype_id itype_burnt_out_bionic( "burnt_out_bionic" );
+ static const itype_id itype_muscle( "muscle" );
+static const json_character_flag json_flag_VAMPIRE( "VAMPIRE" );
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" );
-@@ -616,7 +619,8 @@
+@@ -506,7 +507,8 @@
!corpse.in_species( species_ZOMBIE ) );
- if( is_human && !( u.has_trait_flag( json_flag_CANNIBAL ) ||
- u.has_trait_flag( json_flag_PSYCHOPATH ) ||
-- u.has_trait_flag( json_flag_SAPIOVORE ) ) ) {
-+ u.has_trait_flag( json_flag_SAPIOVORE ) ||
-+ u.has_trait_flag( json_flag_VAMPIRE ) ) ) {
+ if( is_human && !( you.has_flag( json_flag_CANNIBAL ) ||
+ you.has_flag( json_flag_PSYCHOPATH ) ||
+- you.has_flag( json_flag_SAPIOVORE ) ) ) {
++ you.has_flag( json_flag_SAPIOVORE ) ||
++ you.has_flag( json_flag_VAMPIRE ) ) ) {
- if( u.is_player() ) {
+ if( you.is_avatar() ) {
if( query_yn( _( "Would you dare desecrate the mortal remains of a fellow human being?" ) ) ) {
--- a/src/character.cpp
+++ b/src/character.cpp
-@@ -343,6 +343,9 @@
+@@ -441,6 +441,9 @@
static const trait_id trait_NOMAD2( "NOMAD2" );
static const trait_id trait_NOMAD3( "NOMAD3" );
static const trait_id trait_NOPAIN( "NOPAIN" );
+static const trait_id trait_PAINREC1( "PAINREC1" );
+static const trait_id trait_PAINREC2( "PAINREC2" );
+static const trait_id trait_PAINREC3( "PAINREC3" );
+ static const trait_id trait_PACIFIST( "PACIFIST" );
static const trait_id trait_PADDED_FEET( "PADDED_FEET" );
- static const trait_id trait_PAWS( "PAWS" );
- static const trait_id trait_PAWS_LARGE( "PAWS_LARGE" );
-@@ -370,6 +373,9 @@
+ static const trait_id trait_PAINRESIST( "PAINRESIST" );
+@@ -477,6 +480,8 @@
static const trait_id trait_TOUGH_FEET( "TOUGH_FEET" );
static const trait_id trait_TRANSPIRATION( "TRANSPIRATION" );
static const trait_id trait_URSINE_EYE( "URSINE_EYE" );
-+static const trait_id trait_VAMP_HUNGER( "VAMP_HUNGER" );
+static const trait_id trait_VAMP_SKIN( "VAMP_SKIN" );
+static const trait_id trait_VAMP_VISION( "VAMP_VISION" );
static const trait_id trait_VISCOUS( "VISCOUS" );
static const trait_id trait_WATERSLEEP( "WATERSLEEP" );
- static const trait_id trait_WEBBED( "WEBBED" );
-@@ -2095,6 +2096,9 @@
+ static const trait_id trait_WEB_SPINNER( "WEB_SPINNER" );
+@@ -500,6 +505,7 @@
+ case blood_type::blood_A: return "A";
+ case blood_type::blood_B: return "B";
+ case blood_type::blood_AB: return "AB";
++ case blood_type::blood_V: return "V";
+ // *INDENT-ON*
+ case blood_type::num_bt:
+ break;
+@@ -2270,6 +2276,9 @@
if( has_trait( trait_DEBUG_NIGHTVISION ) ) {
vision_mode_cache.set( DEBUG_NIGHTVISION );
}
@@ -51,10 +58,10 @@
if( has_nv() ) {
vision_mode_cache.set( NV_GOGGLES );
}
-@@ -2168,8 +2172,10 @@
- }
+@@ -2337,8 +2346,10 @@
+ ( LIGHT_AMBIENT_LIT - LIGHT_AMBIENT_MINIMAL ) );
- float range = get_per() / 3.0f - eyes_encumb / 10.0f;
+ float range = get_per() / 3.0f;
- if( vision_mode_cache[NV_GOGGLES] || vision_mode_cache[NIGHTVISION_3] ||
- vision_mode_cache[FULL_ELFA_VISION] || vision_mode_cache[CEPH_VISION] ) {
+ if( vision_mode_cache[VAMP_VISION] ) {
@@ -64,7 +71,7 @@
range += 10;
} else if( vision_mode_cache[NIGHTVISION_2] || vision_mode_cache[FELINE_VISION] ||
vision_mode_cache[URSINE_VISION] || vision_mode_cache[ELFA_VISION] ) {
-@@ -5442,7 +5447,15 @@
+@@ -4274,7 +4285,15 @@
{
int pain_ticks = rate_multiplier;
while( get_pain() > 0 && pain_ticks-- > 0 ) {
@@ -81,29 +88,12 @@
}
float rest = rest_quality();
-@@ -5745,6 +5758,7 @@
- const bool npc_no_food = is_npc() && get_option<bool>( "NO_NPC_FOOD" );
- const bool foodless = debug_ls || npc_no_food;
- const bool no_thirst = has_flag( json_flag_NO_THIRST );
-+ const bool vamp = has_trait( trait_VAMP_HUNGER );
- const bool mycus = has_trait( trait_M_DEPENDENT );
- const float kcal_per_time = get_bmr() / ( 12.0f * 24.0f );
- const int five_mins = ticks_between( from, to, 5_minutes );
-@@ -5821,7 +5835,7 @@
- }
- // Mycus and Metabolic Rehydration makes thirst unnecessary
- // since water is not limited by intake but by absorption, we can just set thirst to zero
-- if( mycus || no_thirst ) {
-+ if( mycus || vamp || no_thirst ) {
- set_thirst( 0 );
- }
-
-@@ -6153,19 +6167,21 @@
+@@ -4732,19 +4751,21 @@
void Character::check_needs_extremes()
{
// Check if we've overdosed... in any deadly way.
- if( get_stim() > 250 ) {
-+ if( ( get_stim() > 250 ) && !( has_trait( trait_VAMP_SKIN ) ) ) {
++ if( ( get_stim() > 250 ) && !( has_trait( trait_VAMP_SKIN ) ) ) {
add_msg_player_or_npc( m_bad,
_( "You have a sudden heart attack!" ),
_( "<npcname> has a sudden heart attack!" ) );
@@ -120,10 +110,10 @@
+ } else if( ( has_effect( effect_jetinjector ) &&
+ get_effect_dur( effect_jetinjector ) > 40_minutes ) &&
+ !( has_trait( trait_VAMP_SKIN ) ) ) {
- if( !( has_trait( trait_NOPAIN ) ) ) {
+ if( !has_trait( trait_NOPAIN ) ) {
add_msg_player_or_npc( m_bad,
_( "Your heart spasms painfully and stops." ),
-@@ -6176,13 +6192,14 @@
+@@ -4755,13 +4776,14 @@
}
get_event_bus().send<event_type::dies_from_drug_overdose>( getID(), effect_jetinjector );
set_part_hp_cur( body_part_torso, 0 );
@@ -140,7 +130,27 @@
add_msg_player_or_npc( m_bad,
_( "Your breathing slows down to a stop." ),
_( "<npcname>'s breathing slows down to a stop." ) );
-@@ -6447,7 +6464,7 @@
+@@ -8844,7 +8866,7 @@
+ int Character::heartrate_bpm() const
+ {
+ //Dead have no heartbeat usually and no heartbeat in omnicell
+- if( is_dead_state() || has_trait( trait_SLIMESPAWNER ) ) {
++ if( is_dead_state() || has_trait( trait_SLIMESPAWNER ) || has_trait( trait_VAMP_SKIN ) ) {
+ return 0;
+ }
+
+
+--- a/src/character_body.cpp
++++ b/src/character_body.cpp
+@@ -76,6 +76,7 @@
+ static const trait_id trait_PYROMANIA( "PYROMANIA" );
+ static const trait_id trait_SLIMY( "SLIMY" );
+ static const trait_id trait_URSINE_FUR( "URSINE_FUR" );
++static const trait_id trait_VAMP_SKIN( "VAMP_SKIN" );
+
+ static const vitamin_id vitamin_blood( "blood" );
+
+@@ -402,7 +403,7 @@
void Character::update_bodytemp()
{
@@ -149,19 +159,10 @@
set_all_parts_temp_conv( BODYTEMP_NORM );
set_all_parts_temp_cur( BODYTEMP_NORM );
return;
-@@ -11496,7 +11513,7 @@
- int Character::heartrate_bpm() const
- {
- //Dead have no heartbeat usually and no heartbeat in omnicell
-- if( is_dead_state() || has_trait( trait_SLIMESPAWNER ) ) {
-+ if( is_dead_state() || has_trait( trait_SLIMESPAWNER ) || has_trait( trait_VAMP_SKIN ) ) {
- return 0;
- }
- //This function returns heartrate in BPM basing of health, physical state, tiredness,
--- a/src/character.h
+++ b/src/character.h
-@@ -111,6 +111,7 @@
+@@ -120,6 +120,7 @@
/// @note vision modes do not necessarily match json ids or flags
enum vision_modes {
DEBUG_NIGHTVISION,
@@ -169,11 +170,19 @@
NV_GOGGLES,
NIGHTVISION_1,
NIGHTVISION_2,
-@@ -256,6 +256,8 @@
+@@ -241,6 +242,7 @@
+ blood_A,
+ blood_B,
+ blood_AB,
++ blood_V,
+ num_bt
+ };
+
+@@ -265,6 +267,8 @@
ALLERGY_WEAK,
/// Penalty for eating human flesh (unless psycho/cannibal)
CANNIBALISM,
-+ // Vampirism (unless psycho/cannibal)
++ /// Penalty for drinking human blood (unless vampire)
+ VAMPIRISM,
/// Comestible has parasites
PARASITES,
@@ -181,7 +190,25 @@
--- a/src/consumption.cpp
+++ b/src/consumption.cpp
-@@ -132,6 +132,7 @@
+@@ -77,11 +77,17 @@
+ static const efftype_id effect_took_thorazine( "took_thorazine" );
+ static const efftype_id effect_visuals( "visuals" );
+
++static const flag_id json_flag_ALLERGEN_ALCOHOL( "ALLERGEN_ALCOHOL" );
+ static const flag_id json_flag_ALLERGEN_EGG( "ALLERGEN_EGG" );
++static const flag_id json_flag_ALLERGEN_FOODSTUFF( "ALLERGEN_FOODSTUFF" );
+ static const flag_id json_flag_ALLERGEN_FRUIT( "ALLERGEN_FRUIT" );
++static const flag_id json_flag_ALLERGEN_HONEY( "ALLERGEN_HONEY" );
++static const flag_id json_flag_ALLERGEN_JUNK( "ALLERGEN_JUNK" );
+ static const flag_id json_flag_ALLERGEN_MEAT( "ALLERGEN_MEAT" );
++static const flag_id json_flag_ALLERGEN_MILK( "ALLERGEN_MILK" );
+ static const flag_id json_flag_ALLERGEN_NUT( "ALLERGEN_NUT" );
+ static const flag_id json_flag_ALLERGEN_VEGGY( "ALLERGEN_VEGGY" );
++static const flag_id json_flag_ALLERGEN_WATER( "ALLERGEN_WATER" );
+ static const flag_id json_flag_ALLERGEN_WHEAT( "ALLERGEN_WHEAT" );
+
+ static const item_category_id item_category_chems( "chems" );
+@@ -144,6 +150,7 @@
static const trait_id trait_THRESH_LUPINE( "THRESH_LUPINE" );
static const trait_id trait_THRESH_PLANT( "THRESH_PLANT" );
static const trait_id trait_THRESH_URSINE( "THRESH_URSINE" );
@@ -189,57 +216,53 @@
static const trait_id trait_VEGETARIAN( "VEGETARIAN" );
static const trait_id trait_WATERSLEEP( "WATERSLEEP" );
-@@ -146,6 +147,15 @@
- flag_id( "ALLERGEN_MEAT" ), flag_id( "ALLERGEN_EGG" )
+@@ -154,6 +161,15 @@
+ json_flag_ALLERGEN_WHEAT, json_flag_ALLERGEN_NUT
}};
-+static const std::array<flag_id, 11> vamp_blacklist {{
-+ flag_id( "ALLERGEN_VEGGY" ), flag_id( "ALLERGEN_FRUIT" ),
-+ flag_id( "ALLERGEN_WHEAT" ), flag_id( "ALLERGEN_NUT" ),
-+ flag_id( "ALLERGEN_MEAT" ), flag_id( "ALLERGEN_EGG" ),
-+ flag_id( "ALLERGEN_JUNK" ), flag_id( "ALLERGEN_MILK" ),
-+ flag_id( "ALLERGEN_HONEY" ), flag_id( "ALLERGEN_FOODSTUFF" ),
-+ flag_id( "ALLERGEN_ALCOHOL" )
++static const std::array<flag_id, 12> vamp_blacklist {{
++ json_flag_ALLERGEN_VEGGY, json_flag_ALLERGEN_FRUIT,
++ json_flag_ALLERGEN_WHEAT, json_flag_ALLERGEN_NUT,
++ json_flag_ALLERGEN_MEAT, json_flag_ALLERGEN_EGG,
++ json_flag_ALLERGEN_JUNK, json_flag_ALLERGEN_MILK,
++ json_flag_ALLERGEN_HONEY, json_flag_ALLERGEN_FOODSTUFF,
++ json_flag_ALLERGEN_ALCOHOL, json_flag_ALLERGEN_WATER
+ }};
+
- // TODO: Move pizza scraping here.
- static int compute_default_effective_kcal( const item &comest, const Character &you,
- const cata::flat_set<flag_id> &extra_flags = {} )
-@@ -711,6 +721,13 @@
- return ret_val<edible_rating>::make_failure( INEDIBLE_MUTATION, _( "Ugh, you can't drink that!" ) );
+ static const std::array<flag_id, 2> herbivore_blacklist {{
+ json_flag_ALLERGEN_MEAT, json_flag_ALLERGEN_EGG
+ }};
+@@ -805,6 +821,12 @@
+ _( "Eww. Inedible plant stuff!" ) );
}
-+ if( has_trait_flag( STATIC( json_character_flag( "VAMPIRE" ) ) ) &&
-+ food.has_any_flag( vamp_blacklist ) &&
++ if( has_trait( trait_VAMP_HUNGER ) && food.has_any_flag( vamp_blacklist ) &&
+ !food.has_flag( flag_VAMPIRISM_OK ) ) {
+ return ret_val<edible_rating>::make_failure( INEDIBLE_MUTATION,
+ _( "Bleh. This isn't blood!" ) );
+ }
+
- if( has_trait( trait_CARNIVORE ) && nutrition_for( food ) > 0 &&
- food.has_any_flag( carnivore_blacklist ) && !food.has_flag( flag_CARNIVORE_OK ) ) {
- return ret_val<edible_rating>::make_failure( INEDIBLE_MUTATION,
-@@ -763,11 +780,18 @@
+ if( ( has_trait( trait_HERBIVORE ) || has_trait( trait_RUMINANT ) ) &&
+ food.has_any_flag( herbivore_blacklist ) ) {
+ // Like non-cannibal, but more strict!
+@@ -851,8 +873,15 @@
}
}
+ const bool food_is_human_blood = food.has_flag( flag_VAMPIRISM );
-+ if( food_is_human_blood && !has_trait_flag( STATIC( json_character_flag( "VAMPIRE" ) ) ) &&
-+ !has_trait_flag( STATIC( json_character_flag( "CANNIBAL" ) ) ) ) {
++ if( food_is_human_blood && !has_flag( STATIC( json_character_flag( "VAMPIRE" ) ) ) &&
++ !has_flag( STATIC( json_character_flag( "CANNIBAL" ) ) ) ) {
+ add_consequence( _( "The thought of drinking human blood makes you feel sick." ), VAMPIRISM );
+ }
+
const bool carnivore = has_trait( trait_CARNIVORE );
- const bool food_is_human_flesh = food.has_flag( flag_CANNIBALISM ) ||
+- const bool food_is_human_flesh = food.has_flag( flag_CANNIBALISM ) ||
++ const bool food_is_human_flesh = ( food.has_flag( flag_CANNIBALISM ) &&
++ !food.has_flag( flag_VAMPIRISM ) ) ||
( food.has_flag( flag_STRICT_HUMANITARIANISM ) &&
- !has_trait_flag( json_flag_STRICT_HUMANITARIAN ) );
-- if( food_is_human_flesh && !has_trait_flag( STATIC( json_character_flag( "CANNIBAL" ) ) ) ) {
-+ if( food_is_human_flesh && !has_trait_flag( STATIC( json_character_flag( "CANNIBAL" ) ) ) &&
-+ !food.has_flag( flag_VAMPIRISM ) ) {
- add_consequence( _( "The thought of eating human flesh makes you feel sick." ), CANNIBALISM );
- }
-
-@@ -1136,10 +1160,54 @@
+ !has_flag( json_flag_STRICT_HUMANITARIAN ) );
+ if( food_is_human_flesh && !has_flag( STATIC( json_character_flag( "CANNIBAL" ) ) ) ) {
+@@ -1216,10 +1245,58 @@
}
}
@@ -253,6 +276,7 @@
+ const bool psycho = has_trait( trait_PSYCHOPATH );
+ const bool sapiovore = has_trait( trait_SAPIOVORE );
+ const bool spiritual = has_trait( trait_SPIRITUAL );
++ const bool numb = has_trait( trait_NUMB );
+ if( vamp ) {
+ add_msg_if_player( m_good, _( "You relish drinking the human blood." ) );
+ add_morale( MORALE_CANNIBAL, 30, 200 );
@@ -276,30 +300,33 @@
+ // Small bonus for violating a taboo.
+ add_morale( MORALE_CANNIBAL, 5, 50 );
+ } else if( psycho || sapiovore ) {
-+ add_msg_if_player( _( "Meh. You've eaten worse." ) );
++ add_msg_if_player( _( "Meh. You've drank worse." ) );
+ } else if( spiritual ) {
+ add_msg_if_player( m_bad,
+ _( "This is probably going to count against you if there's still an afterlife." ) );
+ add_morale( MORALE_CANNIBAL, -60, -400, 60_minutes, 30_minutes );
++ } else if( numb ) {
++ add_msg_if_player( m_bad, _( "You find this drink distasteful, but necessary." ) );
++ add_morale( MORALE_CANNIBAL, -60, -400, 60_minutes, 30_minutes );
+ } else {
-+ add_msg_if_player( m_bad, _( "You feel horrible for eating a person." ) );
++ add_msg_if_player( m_bad, _( "You feel horrible for drinking of a person." ) );
+ add_morale( MORALE_CANNIBAL, -60, -400, 60_minutes, 30_minutes );
+ }
+ }
+
const bool food_is_human_flesh = food.has_flag( flag_CANNIBALISM ) ||
( food.has_flag( flag_STRICT_HUMANITARIANISM ) &&
- !has_trait_flag( json_flag_STRICT_HUMANITARIAN ) );
+ !has_flag( json_flag_STRICT_HUMANITARIAN ) );
- if( food_is_human_flesh ) {
+ if( food_is_human_flesh && !food_is_human_blood ) {
// Sapiovores don't recognize humans as the same species.
// But let them possibly feel cool about eating sapient stuff - treat like psycho
// However, spiritual sapiovores should still recognize humans as having a soul or special for religious reasons
-@@ -1214,6 +1282,11 @@
- add_msg_if_player( m_bad, _( "Yuck! How can anybody eat this stuff?" ) );
+@@ -1303,6 +1380,11 @@
+ add_msg_if_player( m_bad, _( "Your stomach begins gurgling and you feel bloated and ill." ) );
add_morale( allergy, -75, -400, 30_minutes, 24_minutes );
}
-+ if( allergy != MORALE_NULL && has_trait_flag( STATIC( json_character_flag( "VAMPIRE" ) ) ) ) {
++ if( allergy != MORALE_NULL && has_flag( STATIC( json_character_flag( "VAMPIRE" ) ) ) ) {
+ add_msg_if_player( m_bad, _( "I can't stomach anything but blood!" ) );
+ add_morale( allergy, -75, -400, 30_minutes, 24_minutes );
+ vomit();
@@ -308,9 +335,35 @@
if( has_trait( trait_PROJUNK ) ) {
add_msg_if_player( m_good, _( "Mmm, junk food." ) );
+--- a/src/debug_menu.cpp
++++ b/src/debug_menu.cpp
+@@ -1728,6 +1728,7 @@
+ btype.addentry( static_cast<int>( blood_type::blood_A ), true, '2', "A" );
+ btype.addentry( static_cast<int>( blood_type::blood_B ), true, '3', "B" );
+ btype.addentry( static_cast<int>( blood_type::blood_AB ), true, '4', "AB" );
++ btype.addentry( static_cast<int>( blood_type::blood_AB ), true, '4', "V" );
+ btype.query();
+ if( btype.ret < 0 ) {
+ break;
+
+--- a/src/do_turn.cpp
++++ b/src/do_turn.cpp
+@@ -95,8 +95,9 @@
+ int iInfoLine = 0;
+
+ if( u.has_amount( itype_holybook_bible1, 1 ) || u.has_amount( itype_holybook_bible2, 1 ) ||
+- u.has_amount( itype_holybook_bible3, 1 ) ) {
+- if( !( u.has_trait( trait_CANNIBAL ) || u.has_trait( trait_PSYCHOPATH ) ) ) {
++ u.has_amount( itype_holybook_bible3, 1 ) || u.has_trait( trait_id( "THRESH_REAL_VAMP" ) ) ) {
++ if( !( u.has_trait( trait_id( "CANNIBAL" ) ) || u.has_trait( trait_id( "PSYCHOPATH" ) ) ||
++ u.has_trait( trait_id( "THRESH_REAL_VAMP" ) ) ) ) {
+ vRip.emplace_back( " _______ ___" );
+ vRip.emplace_back( " < `/ |" );
+ vRip.emplace_back( " > _ _ (" );
+
--- a/src/flag.cpp
+++ b/src/flag.cpp
-@@ -13,8 +13,11 @@
+@@ -15,13 +15,17 @@
const flag_id flag_ACT_IN_FIRE( "ACT_IN_FIRE" );
const flag_id flag_ACT_ON_RANGED_HIT( "ACT_ON_RANGED_HIT" );
const flag_id flag_ALARMCLOCK( "ALARMCLOCK" );
@@ -322,10 +375,17 @@
const flag_id flag_ALLERGEN_JUNK( "ALLERGEN_JUNK" );
const flag_id flag_ALLERGEN_MEAT( "ALLERGEN_MEAT" );
const flag_id flag_ALLERGEN_MILK( "ALLERGEN_MILK" );
-@@ -303,6 +306,8 @@
+ const flag_id flag_ALLERGEN_NUT( "ALLERGEN_NUT" );
+ const flag_id flag_ALLERGEN_VEGGY( "ALLERGEN_VEGGY" );
++const flag_id flag_ALLERGEN_WATER( "ALLERGEN_WATER" );
+ const flag_id flag_ALLERGEN_WHEAT( "ALLERGEN_WHEAT" );
+ const flag_id flag_ALLERGEN_WOOL( "ALLERGEN_WOOL" );
+ const flag_id flag_ALLOWS_NATURAL_ATTACKS( "ALLOWS_NATURAL_ATTACKS" );
+@@ -337,6 +341,9 @@
const flag_id flag_USE_EAT_VERB( "USE_EAT_VERB" );
const flag_id flag_USE_PLAYER_ENERGY( "USE_PLAYER_ENERGY" );
const flag_id flag_USE_UPS( "USE_UPS" );
++const flag_id flag_VAMPIRE( "VAMPIRE" );
+const flag_id flag_VAMPIRISM( "VAMPIRISM" );
+const flag_id flag_VAMPIRISM_OK( "VAMPIRISM_OK" );
const flag_id flag_VARSIZE( "VARSIZE" );
@@ -334,84 +394,71 @@
--- a/src/flag.h
+++ b/src/flag.h
-@@ -20,8 +20,11 @@
+@@ -24,13 +24,17 @@
extern const flag_id flag_ACT_IN_FIRE;
extern const flag_id flag_ACT_ON_RANGED_HIT;
extern const flag_id flag_ALARMCLOCK;
+extern const flag_id flag_ALLERGEN_ALCOHOL;
extern const flag_id flag_ALLERGEN_EGG;
-+extern const flag_id flag_ALLERGEN_FOODSTUFF;
extern const flag_id flag_ALLERGEN_FRUIT;
++extern const flag_id flag_ALLERGEN_FOODSTUFF;
+extern const flag_id flag_ALLERGEN_HONEY;
extern const flag_id flag_ALLERGEN_JUNK;
extern const flag_id flag_ALLERGEN_MEAT;
extern const flag_id flag_ALLERGEN_MILK;
-@@ -310,6 +313,8 @@
+ extern const flag_id flag_ALLERGEN_NUT;
+ extern const flag_id flag_ALLERGEN_VEGGY;
++extern const flag_id flag_ALLERGEN_WATER;
+ extern const flag_id flag_ALLERGEN_WHEAT;
+ extern const flag_id flag_ALLERGEN_WOOL;
+ extern const flag_id flag_ALLOWS_NATURAL_ATTACKS;
+@@ -342,6 +346,9 @@
extern const flag_id flag_USE_EAT_VERB;
extern const flag_id flag_USE_PLAYER_ENERGY;
extern const flag_id flag_USE_UPS;
++extern const flag_id flag_VAMPIRE;
+extern const flag_id flag_VAMPIRISM;
+extern const flag_id flag_VAMPIRISM_OK;
extern const flag_id flag_VARSIZE;
extern const flag_id flag_VEHICLE;
extern const flag_id flag_WAIST;
-
---- a/src/game.cpp
-+++ b/src/game.cpp
-@@ -1039,8 +1039,9 @@
- int iInfoLine = 0;
- if( u.has_amount( itype_holybook_bible1, 1 ) || u.has_amount( itype_holybook_bible2, 1 ) ||
-- u.has_amount( itype_holybook_bible3, 1 ) ) {
-- if( !( u.has_trait( trait_id( "CANNIBAL" ) ) || u.has_trait( trait_id( "PSYCHOPATH" ) ) ) ) {
-+ u.has_amount( itype_holybook_bible3, 1 ) || u.has_trait( trait_id( "THRESH_VAMP" ) ) ) {
-+ if( !( u.has_trait( trait_id( "CANNIBAL" ) ) || u.has_trait( trait_id( "PSYCHOPATH" ) ) ||
-+ u.has_trait( trait_id( "THRESH_VAMP" ) ) ) ) {
- vRip.emplace_back( " _______ ___" );
- vRip.emplace_back( " < `/ |" );
- vRip.emplace_back( " > _ _ (" );
-
--- a/src/item.cpp
+++ b/src/item.cpp
-@@ -155,6 +155,7 @@
+@@ -170,6 +170,7 @@
+ static const itype_id itype_waterproof_gunmod( "waterproof_gunmod" );
static const json_character_flag json_flag_CANNIBAL( "CANNIBAL" );
- static const json_character_flag json_flag_IMMUNE_SPOIL( "IMMUNE_SPOIL" );
+static const json_character_flag json_flag_VAMPIRE( "VAMPIRE" );
+ static const json_character_flag json_flag_IMMUNE_SPOIL( "IMMUNE_SPOIL" );
- static const bionic_id bio_digestion( "bio_digestion" );
-
-@@ -1967,19 +1967,35 @@
- info.emplace_back( "DESCRIPTION",
+ static const matec_id RAPID( "RAPID" );
+@@ -2477,7 +2480,24 @@
_( "* This food will cause an <bad>allergic reaction</bad>." ) );
}
+
+ if( food_item->has_flag( flag_VAMPIRISM ) &&
+ parts->test( iteminfo_parts::FOOD_VAMPIRISM ) ) {
-+ if( player_character.has_trait_flag( json_flag_VAMPIRE ) ) {
++ if( !player_character.has_flag( json_flag_CANNIBAL ) &&
++ !player_character.has_flag( json_flag_VAMPIRE ) ) {
+ info.emplace_back( "DESCRIPTION",
-+ _( "* This food contains <good>human blood</good>." ) );
-+ } else if( player_character.has_trait_flag( json_flag_CANNIBAL ) ) {
++ _( "* This food contains <bad>human flesh</bad>." ) );
++ } else if( player_character.has_flag( json_flag_CANNIBAL ) &&
++ !player_character.has_flag( json_flag_VAMPIRE ) ) {
+ info.emplace_back( "DESCRIPTION",
+ _( "* This food contains <good>human flesh</good>." ) );
+ } else {
+ info.emplace_back( "DESCRIPTION",
-+ _( "* This food contains <bad>human flesh</bad>." ) );
++ _( "* This food contains <good>human blood</good>." ) );
+ }
+ }
-
++
if( food_item->has_flag( flag_CANNIBALISM ) &&
+ !food_item->has_flag( flag_VAMPIRISM ) &&
parts->test( iteminfo_parts::FOOD_CANNIBALISM ) ) {
-- if( !player_character.has_trait_flag( json_flag_CANNIBAL ) ) {
-+ if( player_character.has_trait_flag( json_flag_CANNIBAL ) &&
-+ !player_character.has_trait_flag( json_flag_VAMPIRE ) ) {
- info.emplace_back( "DESCRIPTION",
-- _( "* This food contains <bad>human flesh</bad>." ) );
-+ _( "* This food contains <good>human flesh</good>." ) );
- } else {
+ if( !player_character.has_flag( json_flag_CANNIBAL ) ) {
info.emplace_back( "DESCRIPTION",
-- _( "* This food contains <good>human flesh</good>." ) );
-+ _( "* This food contains <bad>human flesh</bad>." ) );
+@@ -2488,7 +2508,8 @@
}
}
@@ -421,7 +468,7 @@
info.emplace_back( "DESCRIPTION",
_( "* This food is <bad>tainted</bad> and will poison you." ) );
}
-@@ -4374,6 +4390,7 @@
+@@ -5959,6 +5980,7 @@
case ALLERGY:
case ALLERGY_WEAK:
case CANNIBALISM:
@@ -432,34 +479,62 @@
--- a/src/item_factory.cpp
+++ b/src/item_factory.cpp
-@@ -2505,6 +2505,7 @@
- // First allergens:
- // An item is an allergen even if it has trace amounts of allergenic material
- { material_id( "hflesh" ), flag_CANNIBALISM },
-+ { material_id( "blood" ), flag_VAMPIRISM },
-
- { material_id( "hflesh" ), flag_ALLERGEN_MEAT },
- { material_id( "iflesh" ), flag_ALLERGEN_MEAT },
-@@ -2519,10 +2520,15 @@
- { material_id( "mushroom" ), flag_ALLERGEN_VEGGY },
- { material_id( "milk" ), flag_ALLERGEN_MILK },
- { material_id( "egg" ), flag_ALLERGEN_EGG },
-+ { material_id( "alcohol" ), flag_ALLERGEN_ALCOHOL },
-+ { material_id( "foodstuff" ), flag_ALLERGEN_FOODSTUFF },
-+ { material_id( "honey" ), flag_ALLERGEN_HONEY },
- { material_id( "junk" ), flag_ALLERGEN_JUNK },
- // Not food, but we can keep it here
- { material_id( "wool" ), flag_ALLERGEN_WOOL },
- // Now "made of". Those flags should not be passed
-+ { material_id( "blood" ), flag_VAMPIRISM_OK },
-+ { material_id( "blood" ), flag_CARNIVORE_OK },
- { material_id( "flesh" ), flag_CARNIVORE_OK },
- { material_id( "hflesh" ), flag_CARNIVORE_OK },
- { material_id( "iflesh" ), flag_CARNIVORE_OK },
+@@ -85,10 +85,13 @@
+
+ static const item_group_id Item_spawn_data_EMPTY_GROUP( "EMPTY_GROUP" );
+
++static const material_id material_alcohol( "alcohol" );
+ static const material_id material_bean( "bean" );
++static const material_id material_blood( "blood" );
+ static const material_id material_egg( "egg" );
+ static const material_id material_flesh( "flesh" );
+ static const material_id material_fruit( "fruit" );
++static const material_id material_foodplace_foodstuff( "foodplace_foodstuff" );
+ static const material_id material_garlic( "garlic" );
+ static const material_id material_hflesh( "hflesh" );
+ static const material_id material_honey( "honey" );
+@@ -101,6 +104,7 @@
+ static const material_id material_oil( "oil" );
+ static const material_id material_tomato( "tomato" );
+ static const material_id material_veggy( "veggy" );
++static const material_id material_water( "water" );
+ static const material_id material_wheat( "wheat" );
+ static const material_id material_wool( "wool" );
+
+@@ -3356,10 +3360,11 @@
+ // Set for all items (not just food and clothing) to avoid edge cases
+ void Item_factory::set_allergy_flags( itype &item_template )
+ {
+- static const std::array<std::pair<material_id, flag_id>, 22> all_pairs = { {
++ static const std::array<std::pair<material_id, flag_id>, 29> all_pairs = { {
+ // First allergens:
+ // An item is an allergen even if it has trace amounts of allergenic material
+ { material_hflesh, flag_CANNIBALISM },
++ { material_hflesh, flag_VAMPIRISM },
+
+ { material_hflesh, flag_ALLERGEN_MEAT },
+ { material_iflesh, flag_ALLERGEN_MEAT },
+@@ -3374,10 +3379,16 @@
+ { material_mushroom, flag_ALLERGEN_VEGGY },
+ { material_milk, flag_ALLERGEN_MILK },
+ { material_egg, flag_ALLERGEN_EGG },
++ { material_alcohol, flag_ALLERGEN_ALCOHOL },
++ { material_foodplace_foodstuff, flag_ALLERGEN_FOODSTUFF },
++ { material_water, flag_ALLERGEN_WATER },
++ { material_honey, flag_ALLERGEN_HONEY },
+ { material_junk, flag_ALLERGEN_JUNK },
+ // Not food, but we can keep it here
+ { material_wool, flag_ALLERGEN_WOOL },
+ // Now "made of". Those flags should not be passed
++ { material_blood, flag_VAMPIRISM_OK },
++ { material_blood, flag_CARNIVORE_OK },
+ { material_flesh, flag_CARNIVORE_OK },
+ { material_hflesh, flag_CARNIVORE_OK },
+ { material_iflesh, flag_CARNIVORE_OK },
--- a/src/iteminfo_query.h
+++ b/src/iteminfo_query.h
-@@ -41,6 +41,7 @@
+@@ -44,6 +44,7 @@
FOOD_VITAMINS,
FOOD_VIT_EFFECTS,
FOOD_CANNIBALISM,
@@ -471,74 +546,74 @@
--- a/src/iuse.cpp
+++ b/src/iuse.cpp
@@ -342,6 +342,7 @@
+ static const trait_id trait_THRESH_MYCUS( "THRESH_MYCUS" );
static const trait_id trait_THRESH_PLANT( "THRESH_PLANT" );
static const trait_id trait_TOLERANCE( "TOLERANCE" );
- static const trait_id trait_URSINE_EYE( "URSINE_EYE" );
+static const trait_id trait_VAMP_SKIN( "VAMP_SKIN" );
static const trait_id trait_WAYFARER( "WAYFARER" );
- static const quality_id qual_AXE( "AXE" );
+ static const vitamin_id vitamin_blood( "blood" );
@@ -4547,6 +4549,9 @@
if( p->has_trait( trait_ILLITERATE ) ) {
p->add_msg_if_player( m_info, _( "You don't know what you're looking at." ) );
return cata::nullopt;
+ } else if( p->has_trait( trait_VAMP_SKIN ) ) {
-+ p->add_msg_if_player( _( "Your %s shows warning: 'No heartbeat detected. "
++ p->add_msg_if_player( _( "Your %s shows a warning: 'No heartbeat detected. "
+ "This device must be worn to provide fitness feedback.'" ), it->tname() );
} else {
//What else should block using f-band?
- const int bpm = p->heartrate_bpm();
+ std::string msg;
--- a/src/map_field.cpp
+++ b/src/map_field.cpp
-@@ -92,6 +92,7 @@
- static const trait_id trait_M_SKIN3( "M_SKIN3" );
+@@ -94,6 +94,7 @@
+ static const trait_id trait_THRESH_INSECT( "THRESH_INSECT" );
static const trait_id trait_THRESH_MARLOSS( "THRESH_MARLOSS" );
static const trait_id trait_THRESH_MYCUS( "THRESH_MYCUS" );
+static const trait_id trait_VAMP_SKIN( "VAMP_SKIN" );
+ static const trait_id trait_THRESH_SPIDER( "THRESH_SPIDER" );
using namespace map_field_processing;
-
-@@ -1558,7 +1559,8 @@
+@@ -1623,7 +1624,8 @@
if( ( cur.get_field_intensity() > 1 || !one_in( 3 ) ) && ( !inside || one_in( 3 ) ) ) {
- u.add_env_effect( effect_teargas, bodypart_id( "mouth" ), 5, 20_seconds );
+ you.add_env_effect( effect_teargas, bodypart_id( "mouth" ), 5, 20_seconds );
}
- if( cur.get_field_intensity() > 1 && ( !inside || one_in( 3 ) ) ) {
-+ if( !( u.has_trait( trait_VAMP_SKIN ) ) && cur.get_field_intensity() > 1 && ( !inside ||
++ if( !( you.has_trait( trait_VAMP_SKIN ) ) && cur.get_field_intensity() > 1 && ( !inside ||
+ one_in( 3 ) ) ) {
- u.add_env_effect( effect_blind, bodypart_id( "eyes" ), cur.get_field_intensity() * 2, 10_seconds );
+ you.add_env_effect( effect_blind, bodypart_id( "eyes" ), cur.get_field_intensity() * 2,
+ 10_seconds );
}
- }
-@@ -1685,7 +1687,8 @@
+@@ -1748,7 +1750,8 @@
// The gas won't harm you inside a vehicle.
if( !inside ) {
// Full body suits protect you from the effects of the gas.
-- if( !( u.worn_with_flag( STATIC( flag_id( "GAS_PROOF" ) ) ) &&
-+ if( !( u.has_trait( trait_VAMP_SKIN ) ) &&
-+ !( u.worn_with_flag( STATIC( flag_id( "GAS_PROOF" ) ) ) &&
- u.get_env_resist( bodypart_id( "mouth" ) ) >= 15 &&
- u.get_env_resist( bodypart_id( "eyes" ) ) >= 15 ) ) {
+- if( !( you.worn_with_flag( STATIC( flag_id( "GAS_PROOF" ) ) ) &&
++ if( !( you.has_trait( trait_VAMP_SKIN ) ) &&
++ !( you.worn_with_flag( STATIC( flag_id( "GAS_PROOF" ) ) ) &&
+ you.get_env_resist( bodypart_id( "mouth" ) ) >= 15 &&
+ you.get_env_resist( bodypart_id( "eyes" ) ) >= 15 ) ) {
const int intensity = cur.get_field_intensity();
--- a/src/memorial_logger.cpp
+++ b/src/memorial_logger.cpp
-@@ -90,6 +90,7 @@
+@@ -60,6 +60,7 @@
+
static const trait_id trait_CANNIBAL( "CANNIBAL" );
static const trait_id trait_PSYCHOPATH( "PSYCHOPATH" );
++static const trait_id trait_THRESH_REAL_VAMP( "THRESH_REAL_VAMP" );
static const trait_id trait_SAPIOVORE( "SAPIOVORE" );
-+static const trait_id trait_THRESH_VAMP( "THRESH_VAMP" );
memorial_log_entry::memorial_log_entry( const std::string &preformatted_msg ) :
- preformatted_( preformatted_msg )
-@@ -590,6 +591,7 @@
+@@ -560,6 +561,7 @@
character_id ch = e.get<character_id>( "killer" );
if( ch == avatar_id ) {
std::string name = e.get<cata_variant_type::string>( "victim_name" );
-+ bool vampire = player_character.has_trait( trait_THRESH_VAMP );
++ bool vampire = player_character.has_trait( trait_THRESH_REAL_VAMP );
bool cannibal = player_character.has_trait( trait_CANNIBAL );
bool psycho = player_character.has_trait( trait_PSYCHOPATH );
if( player_character.has_trait( trait_SAPIOVORE ) ) {
-@@ -613,6 +615,10 @@
+@@ -583,6 +585,10 @@
add( pgettext( "memorial_male", "Killed an innocent, %s." ),
pgettext( "memorial_female", "Killed an innocent, %s." ),
name );
@@ -552,71 +627,72 @@
--- a/src/morale_types.cpp
+++ b/src/morale_types.cpp
-@@ -40,6 +40,7 @@
-
- morale_type( "morale_food_bad" ),
- morale_type( "morale_cannibal" ),
-+ morale_type( "morale_vampire" ),
- morale_type( "morale_vegetarian" ),
- morale_type( "morale_meatarian" ),
- morale_type( "morale_antifruit" ),
-@@ -138,6 +139,7 @@
- const morale_type MORALE_CRAVING_MARLOSS( "morale_craving_marloss" );
- const morale_type MORALE_FOOD_BAD( "morale_food_bad" );
+@@ -101,6 +101,7 @@
+ const morale_type MORALE_BOOK( "morale_book" );
+ const morale_type MORALE_BUTCHER( "morale_butcher" );
const morale_type MORALE_CANNIBAL( "morale_cannibal" );
+const morale_type MORALE_VAMPIRE( "morale_vampire" );
- const morale_type MORALE_VEGETARIAN( "morale_vegetarian" );
- const morale_type MORALE_MEATARIAN( "morale_meatarian" );
- const morale_type MORALE_ANTIFRUIT( "morale_antifruit" );
+ const morale_type MORALE_CHAT( "morale_chat" );
+ const morale_type MORALE_COLD( "morale_cold" );
+ const morale_type MORALE_COMFY( "morale_comfy" );
+@@ -138,6 +139,7 @@
+ static const morale_type morale_book( "morale_book" );
+ static const morale_type morale_butcher( "morale_butcher" );
+ static const morale_type morale_cannibal( "morale_cannibal" );
++static const morale_type morale_vampire( "morale_vampire" );
+ static const morale_type morale_chat( "morale_chat" );
+ static const morale_type morale_cold( "morale_cold" );
+ static const morale_type morale_comfy( "morale_comfy" );
--- a/src/morale_types.h
+++ b/src/morale_types.h
-@@ -62,6 +62,7 @@
+@@ -64,6 +64,7 @@
extern const morale_type MORALE_CRAVING_MARLOSS;
extern const morale_type MORALE_FOOD_BAD;
extern const morale_type MORALE_CANNIBAL;
+extern const morale_type MORALE_VAMPIRE;
extern const morale_type MORALE_VEGETARIAN;
+ extern const morale_type MORALE_ANTIVEGGY;
extern const morale_type MORALE_MEATARIAN;
- extern const morale_type MORALE_ANTIFRUIT;
--- a/src/mutation.cpp
+++ b/src/mutation.cpp
-@@ -67,6 +67,7 @@
+@@ -82,6 +82,7 @@
+ static const trait_id trait_SNAIL_TRAIL( "SNAIL_TRAIL" );
static const trait_id trait_STR_ALPHA( "STR_ALPHA" );
- static const trait_id trait_THRESH_MARLOSS( "THRESH_MARLOSS" );
- static const trait_id trait_THRESH_MYCUS( "THRESH_MYCUS" );
-+static const trait_id trait_VAMP_SKIN( "VAMP_SKIN" );
static const trait_id trait_TREE_COMMUNION( "TREE_COMMUNION" );
++static const trait_id trait_VAMP_SKIN( "VAMP_SKIN" );
static const trait_id trait_VOMITOUS( "VOMITOUS" );
static const trait_id trait_WEB_WEAVER( "WEB_WEAVER" );
-@@ -877,6 +878,10 @@
- {
- bool force_bad = one_in( 3 );
- bool force_good = false;
+
+@@ -1032,6 +1033,11 @@
+ bool allow_bad = picked_bad;
+ bool allow_neutral = true;
+
+ if( has_trait( trait_VAMP_SKIN ) ) {
+ add_msg_if_player( m_good, _( "Your Vampire blood quickly destroys the mutagenic contagion." ) );
+ return;
+ }
- if( has_trait( trait_ROBUST ) && force_bad ) {
- // Robust Genetics gives you a 33% chance for a good mutation,
- // instead of the 33% chance of a bad one.
++
+ if( true_random_chance > 0 && one_in( true_random_chance ) ) {
+ cat = mutation_category_ANY;
+ allow_good = true; // because i'm WILD YEAH
--- a/src/npc.cpp
+++ b/src/npc.cpp
-@@ -124,6 +124,7 @@
+@@ -156,6 +156,7 @@
static const trait_id trait_SAPIOVORE( "SAPIOVORE" );
- static const trait_id trait_SCHIZOPHRENIC( "SCHIZOPHRENIC" );
+ static const trait_id trait_SQUEAMISH( "SQUEAMISH" );
static const trait_id trait_TERRIFYING( "TERRIFYING" );
-+static const trait_id trait_THRESH_VAMP( "THRESH_VAMP" );
++static const trait_id trait_THRESH_REAL_VAMP( "THRESH_REAL_VAMP" );
class monfaction;
-@@ -2600,12 +2601,15 @@
+@@ -3012,12 +3013,15 @@
Character &player_character = get_player_character();
if( killer == &player_character && ( !guaranteed_hostile() || hit_by_player ) ) {
-+ bool vampire = player_character.has_trait( trait_THRESH_VAMP );
++ bool vampire = player_character.has_trait( trait_THRESH_REAL_VAMP );
bool cannibal = player_character.has_trait( trait_CANNIBAL );
bool psycho = player_character.has_trait( trait_PSYCHOPATH );
if( player_character.has_trait( trait_SAPIOVORE ) || psycho ) {
@@ -631,40 +707,30 @@
--- a/src/player_hardcoded_effects.cpp
+++ b/src/player_hardcoded_effects.cpp
-@@ -115,6 +115,8 @@
- static const trait_id trait_SEESLEEP( "SEESLEEP" );
+@@ -126,6 +126,8 @@
+ static const trait_id trait_NOPAIN( "NOPAIN" );
static const trait_id trait_SCHIZOPHRENIC( "SCHIZOPHRENIC" );
static const trait_id trait_THRESH_MYCUS( "THRESH_MYCUS" );
-+static const trait_id trait_THRESH_VAMP( "THRESH_VAMP" );
++static const trait_id trait_THRESH_REAL_VAMP( "THRESH_REAL_VAMP" );
+static const trait_id trait_VAMP_SKIN( "VAMP_SKIN" );
static const trait_id trait_WATERSLEEP( "WATERSLEEP" );
- static const json_character_flag json_flag_ALARMCLOCK( "ALARMCLOCK" );
-@@ -882,7 +884,9 @@
- }
+ static const vitamin_id vitamin_blood( "blood" );
+@@ -721,7 +723,9 @@
+ }
- if( dur > 1800_minutes && one_in( 300 * 512 ) ) {
-- if( !has_trait( trait_NOPAIN ) ) {
-+ if( has_trait( trait_VAMP_SKIN ) ) {
-+ return;
-+ } else if( !has_trait( trait_NOPAIN ) ) {
- add_msg_if_player( m_bad,
- _( "Your heart spasms painfully and stops, dragging you back to reality as you die." ) );
- } else {
-@@ -1337,6 +1341,9 @@
- // Determine the strength of effects or dreams based upon category strength
- int strength = 0; // Category too weak for any effect or dream
- if( crossed_threshold() ) {
-+ if( has_trait( trait_THRESH_VAMP ) ) {
-+ highcat = mutation_category_id( "VAMP" );
-+ }
- strength = 4; // Post-human.
- } else if( highest >= 20 && highest < 35 ) {
- strength = 1; // Low strength
+ if( dur > 1800_minutes && one_in( 300 * 512 ) ) {
+- if( !u.has_trait( trait_NOPAIN ) ) {
++ if( u.has_trait( trait_VAMP_SKIN ) ) {
++ return;
++ } else if( !u.has_trait( trait_NOPAIN ) ) {
+ u.add_msg_if_player( m_bad,
+ _( "Your heart spasms painfully and stops, dragging you back to reality as you die." ) );
+ } else {
--- a/src/suffer.cpp
+++ b/src/suffer.cpp
-@@ -151,6 +151,8 @@
+@@ -176,6 +176,8 @@
static const trait_id trait_TROGLO2( "TROGLO2" );
static const trait_id trait_TROGLO3( "TROGLO3" );
static const trait_id trait_UNSTABLE( "UNSTABLE" );
@@ -673,76 +739,69 @@
static const trait_id trait_VOMITOUS( "VOMITOUS" );
static const trait_id trait_WEB_SPINNER( "WEB_SPINNER" );
static const trait_id trait_WEB_WEAVER( "WEB_WEAVER" );
-@@ -243,7 +245,8 @@
+@@ -286,7 +288,7 @@
- void Character::suffer_while_underwater()
+ void suffer::while_underwater( Character &you )
{
-- if( !has_trait( trait_GILLS ) && !has_trait( trait_GILLS_CEPH ) ) {
-+ if( !has_trait( trait_GILLS ) && !has_trait( trait_GILLS_CEPH ) &&
-+ !has_trait( trait_VAMP_SKIN ) ) {
- oxygen--;
+- if( !you.has_flag( json_flag_GILLS ) ) {
++ if( !you.has_flag( json_flag_GILLS ) && !you.has_trait( trait_VAMP_SKIN ) ) {
+ you.oxygen--;
}
- if( oxygen < 12 && worn_with_flag( flag_REBREATHER ) ) {
-@@ -746,7 +749,8 @@
- return;
+ if( you.oxygen < 12 && you.worn_with_flag( flag_REBREATHER ) ) {
+@@ -862,12 +864,12 @@
+ you.vitamin_mod( vitamin_vitC, 1 );
}
-- if( has_trait( trait_ALBINO ) || has_effect( effect_datura ) || has_trait( trait_SUNBURN ) ) {
-+ if( has_trait( trait_ALBINO ) || has_effect( effect_datura ) || has_trait( trait_SUNBURN ) ||
-+ has_trait( trait_VAMP_CURSE ) ) {
- suffer_from_sunburn();
+- if( you.has_trait( trait_SUNBURN ) ) {
++ if( you.has_trait( trait_SUNBURN ) || you.has_trait( trait_VAMP_CURSE ) ) {
+ suffer::from_sunburn( you, true );
}
-@@ -772,6 +776,13 @@
- mod_int_bonus( -4 );
- mod_per_bonus( -4 );
+ // Albinism and datura have the same effects and do not stack with each other or sunburn.
+- if( !you.has_trait( trait_SUNBURN ) &&
++ if( ( !you.has_trait( trait_SUNBURN ) && !you.has_trait( trait_VAMP_CURSE ) ) &&
+ ( you.has_trait( trait_ALBINO ) || you.has_effect( effect_datura ) ) ) {
+ suffer::from_sunburn( you, false );
}
-+ if( has_trait( trait_VAMP_CURSE ) ) {
-+ mod_str_bonus( -4 );
-+ mod_dex_bonus( -4 );
-+ add_miss_reason( _( "You can't tolerate the sunlight!" ), 4 );
-+ mod_int_bonus( -4 );
-+ mod_per_bonus( -4 );
+@@ -895,6 +897,13 @@
+ you.mod_int_bonus( -4 );
+ you.mod_per_bonus( -4 );
+ }
++ if( you.has_trait( trait_VAMP_CURSE ) ) {
++ you.mod_str_bonus( -4 );
++ you.mod_dex_bonus( -4 );
++ you.add_miss_reason( _( "You can't tolerate the sunlight!" ), 4 );
++ you.mod_int_bonus( -4 );
++ you.mod_per_bonus( -4 );
+ }
}
std::map<bodypart_id, float> Character::bodypart_exposure()
-@@ -803,7 +814,8 @@
-
- void Character::suffer_from_sunburn()
+@@ -948,7 +957,10 @@
+ void suffer::from_sunburn( Character &you, bool severe )
{
-- if( !has_trait( trait_ALBINO ) && !has_effect( effect_datura ) && !has_trait( trait_SUNBURN ) ) {
-+ if( !has_trait( trait_ALBINO ) && !has_effect( effect_datura ) && !has_trait( trait_SUNBURN ) &&
-+ !has_trait( trait_VAMP_CURSE ) ) {
+ // Sunburn effects and albinism/datura occur about once per minute
+- if( !one_turn_in( 1_minutes ) ) {
++ // Vampirism is ten times per minute
++ if( !one_turn_in( 1_minutes ) && !you.has_trait( trait_VAMP_CURSE ) ) {
++ return;
++ } else if( !one_turn_in( 6_seconds ) && you.has_trait( trait_VAMP_CURSE ) ) {
return;
}
-@@ -820,6 +832,12 @@
- return;
- }
- sunlight_effect = _( "The sunlight burns!" );
-+ } else if( has_trait( trait_VAMP_CURSE ) ) {
-+ // Sunburn effects occur about 10 times per minute
-+ if( !one_turn_in( 6_seconds ) ) {
-+ return;
-+ }
-+ sunlight_effect = _( "The sunlight sears" );
- }
+@@ -2034,7 +2046,7 @@
+
+ healing_factor *= mutation_value( "mending_modifier" );
- // Sunglasses can keep the sun off the eyes.
-@@ -897,7 +915,7 @@
+- if( has_flag( json_flag_MEND_ALL ) ) {
++ if( has_flag( json_flag_MEND_ALL ) || has_trait( trait_VAMP_SKIN ) ) {
+ needs_splint = false;
}
- // Solar Sensitivity (SUNBURN) trait causes injury to exposed parts
-- if( has_trait( trait_SUNBURN ) ) {
-+ if( has_trait( trait_SUNBURN ) || has_trait( trait_VAMP_CURSE ) ) {
- mod_pain( 1 );
- // Check exposure of all body parts
- for( const std::pair<const bodypart_id, float> &bp_exp : bp_exposure ) {
--- a/data/json/field_type.json
+++ b/data/json/field_type.json
-@@ -354,7 +354,7 @@
+@@ -376,7 +376,7 @@
"has_fume": true,
"percent_spread": 90,
"dirty_transparency_cache": true,
@@ -751,7 +810,7 @@
},
{
"id": "fd_rubble",
-@@ -429,7 +429,7 @@
+@@ -467,7 +467,7 @@
"dirty_transparency_cache": true,
"percent_spread": 10,
"outdoor_age_speedup": "0 turns",
@@ -760,7 +819,7 @@
"priority": 8,
"half_life": "2 minutes",
"phase": "gas",
-@@ -515,7 +515,7 @@
+@@ -553,7 +553,7 @@
"outdoor_age_speedup": "3 minutes",
"dirty_transparency_cache": true,
"has_fume": true,
@@ -769,16 +828,25 @@
"priority": 8,
"half_life": "10 minutes",
"phase": "gas",
-@@ -544,7 +544,7 @@
- "outdoor_age_speedup": "0 turns",
+@@ -609,7 +609,7 @@
+ "outdoor_age_speedup": "3 minutes",
"dirty_transparency_cache": true,
"has_fume": true,
- "immunity_data": { "body_part_env_resistance": [ [ "mouth", 15 ] ] },
+ "immunity_data": { "body_part_env_resistance": [ [ "mouth", 15 ] ], "traits": [ "VAMP_SKIN" ] },
"priority": 8,
+ "half_life": "10 minutes",
+ "phase": "gas",
+@@ -638,7 +638,7 @@
+ "outdoor_age_speedup": "0 turns",
+ "dirty_transparency_cache": true,
+ "has_fume": true,
+- "immunity_data": { "body_part_env_resistance": [ [ "mouth", 15 ] ] },
++ "immunity_data": { "body_part_env_resistance": [ [ "mouth", 15 ], [ "eyes", 15 ] ], "traits": [ "VAMP_SKIN" ] },
+ "priority": 8,
"half_life": "5 minutes",
"phase": "gas",
-@@ -590,7 +590,7 @@
+@@ -684,7 +684,7 @@
"wandering_field": "fd_toxic_gas",
"gas_absorption_factor": 15,
"dirty_transparency_cache": true,
@@ -787,7 +855,7 @@
"phase": "gas",
"display_items": false,
"display_field": true,
-@@ -1138,7 +1138,7 @@
+@@ -1240,7 +1240,7 @@
"outdoor_age_speedup": "5 minutes",
"dirty_transparency_cache": true,
"has_fume": true,
@@ -796,7 +864,7 @@
"priority": 8,
"half_life": "50 minutes",
"phase": "gas",
-@@ -1160,7 +1160,7 @@
+@@ -1262,7 +1262,7 @@
"outdoor_age_speedup": "1 minutes",
"dirty_transparency_cache": true,
"has_fume": true,
@@ -805,7 +873,20 @@
"priority": 8,
"half_life": "15 minutes",
"phase": "gas",
-@@ -1407,7 +1407,7 @@
+@@ -1306,7 +1306,11 @@
+ "outdoor_age_speedup": "5 turns",
+ "dirty_transparency_cache": true,
+ "has_fume": true,
+- "immunity_data": { "flags": [ "MYCUS_IMMUNE" ], "body_part_env_resistance": [ [ "mouth", 15 ], [ "sensor", 15 ] ] },
++ "immunity_data": {
++ "flags": [ "MYCUS_IMMUNE" ],
++ "body_part_env_resistance": [ [ "mouth", 15 ], [ "sensor", 15 ] ],
++ "traits": [ "VAMP_SKIN" ]
++ },
+ "priority": 8,
+ "half_life": "4 minutes",
+ "phase": "gas",
+@@ -1509,7 +1509,7 @@
"outdoor_age_speedup": "3 minutes",
"dirty_transparency_cache": true,
"has_fume": true,
@@ -814,7 +895,7 @@
"priority": 8,
"half_life": "10 minutes",
"phase": "gas"
-@@ -1427,7 +1427,7 @@
+@@ -1529,7 +1529,7 @@
"outdoor_age_speedup": "1 minutes",
"dirty_transparency_cache": true,
"has_fume": true,
@@ -823,7 +904,7 @@
"priority": 8,
"half_life": "30 minutes",
"phase": "gas",
-@@ -1449,7 +1449,7 @@
+@@ -1551,7 +1551,7 @@
"outdoor_age_speedup": "1 minutes",
"dirty_transparency_cache": true,
"has_fume": true,
@@ -835,50 +916,49 @@
--- a/data/json/flags.json
+++ b/data/json/flags.json
-@@ -1120,6 +1120,21 @@
- "context": [ "COMESTIBLE" ]
+@@ -1120,6 +1120,22 @@
+ "type": "json_flag"
},
{
+ "id": "ALLERGEN_HONEY",
-+ "type": "json_flag",
-+ "context": [ "COMESTIBLE" ]
++ "type": "json_flag"
+ },
+ {
+ "id": "ALLERGEN_ALCOHOL",
-+ "type": "json_flag",
-+ "context": [ "COMESTIBLE" ]
++ "type": "json_flag"
+ },
+ {
+ "id": "ALLERGEN_FOODSTUFF",
-+ "type": "json_flag",
-+ "context": [ "COMESTIBLE" ]
++ "type": "json_flag"
++ },
++ {
++ "id": "ALLERGEN_WATER",
++ "type": "json_flag"
+ },
+ {
"id": "ALLERGEN_JUNK",
- "type": "json_flag",
- "context": [ "COMESTIBLE" ]
-@@ -1199,6 +1214,16 @@
- "type": "json_flag",
- "context": [ ]
+ "type": "json_flag"
},
-+ {
+@@ -1189,6 +1205,14 @@
+ "type": "json_flag"
+ },
+ {
+ "id": "VAMPIRISM",
-+ "type": "json_flag",
-+ "context": [ ]
++ "type": "json_flag"
+ },
+ {
+ "id": "VAMPIRISM_OK",
-+ "type": "json_flag",
-+ "context": [ ]
++ "type": "json_flag"
+ },
- {
++ {
"id": "CASING",
- "type": "json_flag",
+ "type": "json_flag"
+ },
--- a/data/json/morale_types.json
+++ b/data/json/morale_types.json
@@ -130,6 +130,11 @@
- "text": "Ate Demihuman Flesh"
+ "text": "Ate demihuman flesh"
},
{
+ "id": "morale_vampire",
@@ -888,11 +968,11 @@
+ {
"id": "morale_vegetarian",
"type": "morale_type",
- "text": "Ate Vegetables"
+ "text": "Ate vegetables"
--- a/data/json/mutations/mutation_ordering.json
+++ b/data/json/mutations/mutation_ordering.json
-@@ -75,6 +75,7 @@
+@@ -80,6 +80,7 @@
"TROGLO2",
"TROGLO3",
"URSINE_FUR",
@@ -900,12 +980,12 @@
"VISCOUS"
],
"order": 1500
-@@ -182,7 +183,7 @@
+@@ -189,7 +190,7 @@
{ "id": [ "FLOWERS" ], "order": 5000 },
- { "id": [ "ELFA_EARS", "FELINE_EARS", "LUPINE_EARS", "URSINE_EARS" ], "order": 5500 },
- { "id": [ "ANTENNAE", "ANTLERS", "CURVED_HORNS", "HORNS", "POINTED_HORNS" ], "order": 6000 },
+ { "id": [ "ELFA_EARS", "FELINE_EARS", "LUPINE_EARS", "RABBIT_EARS", "URSINE_EARS" ], "order": 5500 },
+ { "id": [ "ANTENNAE", "ANTLERS", "HORNS_CURLED", "HORNS", "HORNS_POINTED" ], "order": 6000 },
- { "id": [ "COMPOUND_EYES", "ELFAEYES", "FEL_EYE", "LIZ_EYE" ], "order": 6500 },
-+ { "id": [ "COMPOUND_EYES", "ELFAEYES", "FEL_EYE", "LIZ_EYE", "VAMP_EYES" ], "order": 6500 },
++ { "id": [ "COMPOUND_EYES", "ELFAEYES", "FEL_EYE", "LIZ_EYE", "REAL_VAMP_EYES" ], "order": 6500 },
{
"id": [
"BEAK",