From b9ea5088bd0fce00591cbebf2bba75245f3ea981 Mon Sep 17 00:00:00 2001 From: ShnitzelX2 <65314588+ShnitzelX2@users.noreply.github.com> Date: Mon, 7 Oct 2024 00:12:02 -0400 Subject: [PATCH 1/5] move avatar::randomize and related methods to Character::randomize --- src/avatar.cpp | 37 ------------------- src/avatar.h | 5 --- src/character.cpp | 20 +++++++++++ src/character.h | 6 +++- src/newcharacter.cpp | 84 ++++++++++++++++++++++++++++---------------- src/npc.cpp | 49 +++++++++++++++----------- src/npc.h | 1 + 7 files changed, 108 insertions(+), 94 deletions(-) diff --git a/src/avatar.cpp b/src/avatar.cpp index ea81593e549a3..a0849a08ef17b 100644 --- a/src/avatar.cpp +++ b/src/avatar.cpp @@ -1810,43 +1810,6 @@ std::unique_ptr get_talker_for( avatar *me ) return std::make_unique( me ); } -void avatar::randomize_hobbies() -{ - hobbies.clear(); - std::vector choices = get_scenario()->permitted_hobbies(); - choices.erase( std::remove_if( choices.begin(), choices.end(), - [this]( const string_id &hobby ) { - return !prof->allows_hobby( hobby ); - } ), choices.end() ); - if( choices.empty() ) { - debugmsg( "Why would you blacklist all hobbies?" ); - choices = profession::get_all_hobbies(); - }; - - int random = rng( 0, 5 ); - - if( random >= 1 ) { - add_random_hobby( choices ); - } - if( random >= 3 ) { - add_random_hobby( choices ); - } - if( random >= 5 ) { - add_random_hobby( choices ); - } -} - -void avatar::add_random_hobby( std::vector &choices ) -{ - const profession_id hobby = random_entry_removed( choices ); - hobbies.insert( &*hobby ); - - // Add or remove traits from hobby - for( const trait_and_var &cur : hobby->get_locked_traits() ) { - toggle_trait( cur.trait ); - } -} - void avatar::reassign_item( item &it, int invlet ) { bool remove_old = true; diff --git a/src/avatar.h b/src/avatar.h index f1957c04a5db6..398eb89b70d3c 100644 --- a/src/avatar.h +++ b/src/avatar.h @@ -105,9 +105,6 @@ class avatar : public Character bool create( character_type type, const std::string &tempname = "" ); // initialize avatar and avatar mocks void initialize( character_type type ); - void add_profession_items(); - void randomize( bool random_scenario, bool play_now = false ); - void randomize_cosmetics(); bool load_template( const std::string &template_name, pool_type & ); void save_template( const std::string &name, pool_type ); void character_to_template( const std::string &name ); @@ -363,8 +360,6 @@ class avatar : public Character void log_activity_level( float level ) override; std::string total_daily_calories_string() const; //set 0-3 random hobbies, with 1 and 2 being twice as likely as 0 and 3 - void randomize_hobbies(); - void add_random_hobby( std::vector &choices ); int movecounter = 0; diff --git a/src/character.cpp b/src/character.cpp index 14ef52197fdab..0e816011f35f3 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -397,6 +397,12 @@ static const species_id species_HUMAN( "HUMAN" ); static const start_location_id start_location_sloc_shelter_a( "sloc_shelter_a" ); +static const std::string type_hair_color( "hair_color" ); +static const std::string type_hair_style( "hair_style" ); +static const std::string type_skin_tone( "skin_tone" ); +static const std::string type_facial_hair( "facial_hair" ); +static const std::string type_eye_color( "eye_color" ); + static const trait_id trait_ADRENALINE( "ADRENALINE" ); static const trait_id trait_ANTENNAE( "ANTENNAE" ); static const trait_id trait_BADBACK( "BADBACK" ); @@ -421,6 +427,7 @@ static const trait_id trait_DOWN( "DOWN" ); static const trait_id trait_EATHEALTH( "EATHEALTH" ); static const trait_id trait_ELFA_FNV( "ELFA_FNV" ); static const trait_id trait_ELFA_NV( "ELFA_NV" ); +static const trait_id trait_FACIAL_HAIR_NONE( "FACIAL_HAIR_NONE" ); static const trait_id trait_FAERIECREATURE( "FAERIECREATURE" ); static const trait_id trait_FAT( "FAT" ); static const trait_id trait_FEL_NV( "FEL_NV" ); @@ -740,6 +747,19 @@ void Character::randomize_blood() my_blood_type = blood_type::blood_AB; blood_rh_factor = false; } +void Character::randomize_cosmetics() +{ + randomize_cosmetic_trait( type_hair_color ); + randomize_cosmetic_trait( type_hair_style ); + randomize_cosmetic_trait( type_skin_tone ); + randomize_cosmetic_trait( type_eye_color ); + //arbitrary 50% chance to add beard to male characters + if( male && one_in( 2 ) ) { + randomize_cosmetic_trait( type_facial_hair ); + } else { + set_mutation( trait_FACIAL_HAIR_NONE ); + } +} field_type_id Character::bloodType() const { diff --git a/src/character.h b/src/character.h index c24e27c0cb0af..bacef0291bab6 100644 --- a/src/character.h +++ b/src/character.h @@ -586,6 +586,8 @@ class Character : public Creature, public visitable const profession *prof; std::set hobbies; + void randomize_hobbies(); + void add_random_hobby( std::vector &choices ); // Relative direction of a grab, add to posx, posy to get the coordinates of the grabbed thing. tripoint_rel_ms grab_point; @@ -773,6 +775,7 @@ class Character : public Creature, public visitable //returns character's profession const profession *get_profession() const; + void add_profession_items(); //returns the hobbies std::set get_hobbies() const; @@ -2759,7 +2762,8 @@ class Character : public Creature, public visitable int avg_nat_bpm; void randomize_heartrate(); - + void randomize( bool random_scenario, bool play_now = false ); + void randomize_cosmetics(); int get_focus() const { return std::max( 1, focus_pool / 1000 ); } diff --git a/src/newcharacter.cpp b/src/newcharacter.cpp index bb6b0715dcaee..1542c1544b797 100644 --- a/src/newcharacter.cpp +++ b/src/newcharacter.cpp @@ -76,12 +76,6 @@ static const std::string flag_CHALLENGE( "CHALLENGE" ); static const std::string flag_CITY_START( "CITY_START" ); static const std::string flag_SECRET( "SECRET" ); -static const std::string type_hair_color( "hair_color" ); -static const std::string type_hair_style( "hair_style" ); -static const std::string type_skin_tone( "skin_tone" ); -static const std::string type_facial_hair( "facial_hair" ); -static const std::string type_eye_color( "eye_color" ); - static const flag_id json_flag_auto_wield( "auto_wield" ); static const flag_id json_flag_no_auto_equip( "no_auto_equip" ); @@ -92,7 +86,6 @@ static const matype_id style_none( "style_none" ); static const profession_group_id profession_group_adult_basic_background( "adult_basic_background" ); -static const trait_id trait_FACIAL_HAIR_NONE( "FACIAL_HAIR_NONE" ); static const trait_id trait_SMELLY( "SMELLY" ); static const trait_id trait_WEAKSCENT( "WEAKSCENT" ); static const trait_id trait_XS( "XS" ); @@ -203,7 +196,7 @@ static int stat_point_pool() { return 4 * 8 + get_option( "INITIAL_STAT_POINTS" ); } -static int stat_points_used( const avatar &u ) +static int stat_points_used( const Character &u ) { int used = 0; for( int stat : { @@ -218,7 +211,7 @@ static int trait_point_pool() { return get_option( "INITIAL_TRAIT_POINTS" ); } -static int trait_points_used( const avatar &u ) +static int trait_points_used( const Character &u ) { int used = 0; for( trait_id cur_trait : u.get_mutations( true ) ) { @@ -241,7 +234,7 @@ static int skill_point_pool() { return get_option( "INITIAL_SKILL_POINTS" ); } -static int skill_points_used( const avatar &u ) +static int skill_points_used( const Character &u ) { int scenario = get_scenario()->point_cost(); int profession_points = u.prof->point_cost(); @@ -262,12 +255,12 @@ static int point_pool_total() { return stat_point_pool() + trait_point_pool() + skill_point_pool(); } -static int points_used_total( const avatar &u ) +static int points_used_total( const Character &u ) { return stat_points_used( u ) + trait_points_used( u ) + skill_points_used( u ); } -static int has_unspent_points( const avatar &u ) +static int has_unspent_points( const Character &u ) { return points_used_total( u ) < point_pool_total(); } @@ -278,7 +271,7 @@ struct multi_pool { // The amount of points awailable in a pool minus the points that are borrowed // by lower pools plus the points that can be borrowed from higher pools const int stat_points_left, trait_points_left, skill_points_left; - explicit multi_pool( const avatar &u ): + explicit multi_pool( const Character &u ): pure_stat_points( stat_point_pool() - stat_points_used( u ) ), pure_trait_points( trait_point_pool() - trait_points_used( u ) ), pure_skill_points( skill_point_pool() - skill_points_used( u ) ), @@ -425,11 +418,14 @@ static matype_id choose_ma_style( const character_type type, const std::vector( "MAX_TRAIT_POINTS" ); // Reset everything to the defaults to have a clean state. - *this = avatar(); + if( is_avatar() ) { + *this = avatar(); + } + bool gender_selection = one_in( 2 ); male = gender_selection; outfit = gender_selection; @@ -598,23 +594,14 @@ void avatar::randomize( const bool random_scenario, bool play_now ) // Restart cardio accumulator reset_cardio_acc(); -} -void avatar::randomize_cosmetics() -{ - randomize_cosmetic_trait( type_hair_color ); - randomize_cosmetic_trait( type_hair_style ); - randomize_cosmetic_trait( type_skin_tone ); - randomize_cosmetic_trait( type_eye_color ); - //arbitrary 50% chance to add beard to male characters - if( male && one_in( 2 ) ) { - randomize_cosmetic_trait( type_facial_hair ); - } else { - set_mutation( trait_FACIAL_HAIR_NONE ); + if( is_npc() ) { + add_profession_items(); + initialize(); } } -void avatar::add_profession_items() +void Character::add_profession_items() { // Our profession should not be a hobby if( prof->is_hobby() ) { @@ -650,8 +637,8 @@ void avatar::add_profession_items() inv->push_back( it ); } - if( it.is_book() ) { - items_identified.insert( it.typeId() ); + if( it.is_book() && this->is_avatar() ) { + as_avatar()->identify( it ); } } @@ -659,6 +646,43 @@ void avatar::add_profession_items() calc_encumbrance(); } +void Character::randomize_hobbies() +{ + hobbies.clear(); + std::vector choices = get_scenario()->permitted_hobbies(); + choices.erase( std::remove_if( choices.begin(), choices.end(), + [this]( const string_id &hobby ) { + return !prof->allows_hobby( hobby ); + } ), choices.end() ); + if( choices.empty() ) { + debugmsg( "Why would you blacklist all hobbies?" ); + choices = profession::get_all_hobbies(); + }; + + int random = rng( 0, 5 ); + + if( random >= 1 ) { + add_random_hobby( choices ); + } + if( random >= 3 ) { + add_random_hobby( choices ); + } + if( random >= 5 ) { + add_random_hobby( choices ); + } +} + +void Character::add_random_hobby( std::vector &choices ) +{ + const profession_id hobby = random_entry_removed( choices ); + hobbies.insert( &*hobby ); + + // Add or remove traits from hobby + for( const trait_and_var &cur : hobby->get_locked_traits() ) { + toggle_trait( cur.trait ); + } +} + static int calculate_cumulative_experience( int level ) { int sum = 0; diff --git a/src/npc.cpp b/src/npc.cpp index ad1a8200210b2..29a5458cc3632 100644 --- a/src/npc.cpp +++ b/src/npc.cpp @@ -131,6 +131,7 @@ static const npc_class_id NC_ARSONIST( "NC_ARSONIST" ); static const npc_class_id NC_BOUNTY_HUNTER( "NC_BOUNTY_HUNTER" ); static const npc_class_id NC_COWBOY( "NC_COWBOY" ); static const npc_class_id NC_EVAC_SHOPKEEP( "NC_EVAC_SHOPKEEP" ); +static const npc_class_id NC_NONE( "NC_NONE" ); static const npc_class_id NC_TRADER( "NC_TRADER" ); static const overmap_location_str_id overmap_location_source_of_ammo( "source_of_ammo" ); @@ -556,6 +557,11 @@ void npc::randomize( const npc_class_id &type, const npc_template_id &tem_id ) if( !getID().is_valid() ) { setID( g->assign_npc_id() ); } + if( type.is_null() || type == NC_NONE ) { + Character::randomize( false ); + catchup_skills(); + return; + } set_wielded_item( item( "null", calendar::turn_zero ) ); inv->clear(); @@ -608,8 +614,6 @@ void npc::randomize( const npc_class_id &type, const npc_template_id &tem_id ) if( !type.is_valid() ) { debugmsg( "Invalid NPC class %s", type.c_str() ); myclass = npc_class_id::NULL_ID(); - } else if( type.is_null() ) { - myclass = npc_class::random_common(); } else { myclass = type; } @@ -639,25 +643,7 @@ void npc::randomize( const npc_class_id &type, const npc_template_id &tem_id ) set_skill_level( skill.ident(), level ); } - const int cataclysm_days = to_days( calendar::turn - calendar::start_of_cataclysm ); - const int level_cap = get_option( "EXTRA_NPC_SKILL_LEVEL_CAP" ); - const SkillLevelMap &skills_map = get_all_skills(); - // Exp actually multiplied by 100 in Character::practice - const int min_exp = get_option( "MIN_CATCHUP_EXP_PER_POST_CATA_DAY" ); - const int max_exp = get_option( "MAX_CATCHUP_EXP_PER_POST_CATA_DAY" ); - - for( int i = 0; i < cataclysm_days; i++ ) { - const int npc_exp_gained = rng( min_exp, max_exp ); - const std::pair &pair = random_entry( skills_map ); - - // This resets focus to equilibrium before every practice, so NPCs with bonus learning/focus - // will have that reflected by the *actual* gained exp. - mod_focus( calc_focus_equilibrium( true ) - get_focus() ); - - practice( pair.first, npc_exp_gained, level_cap, false, true ); - } - - + catchup_skills(); set_body(); recalc_hp(); int days_since_cata = to_days( calendar::turn - calendar::start_of_cataclysm ); @@ -721,6 +707,27 @@ void npc::randomize( const npc_class_id &type, const npc_template_id &tem_id ) effect_on_conditions::load_new_character( *this ); } +void npc::catchup_skills() +{ + const int cataclysm_days = to_days( calendar::turn - calendar::start_of_cataclysm ); + const int level_cap = get_option( "EXTRA_NPC_SKILL_LEVEL_CAP" ); + const SkillLevelMap &skills_map = get_all_skills(); + // Exp actually multiplied by 100 in Character::practice + const int min_exp = get_option( "MIN_CATCHUP_EXP_PER_POST_CATA_DAY" ); + const int max_exp = get_option( "MAX_CATCHUP_EXP_PER_POST_CATA_DAY" ); + + for( int i = 0; i < cataclysm_days; i++ ) { + const int npc_exp_gained = rng( min_exp, max_exp ); + const std::pair &pair = random_entry( skills_map ); + + // This resets focus to equilibrium before every practice, so NPCs with bonus learning/focus + // will have that reflected by the *actual* gained exp. + mod_focus( calc_focus_equilibrium( true ) - get_focus() ); + + practice( pair.first, npc_exp_gained, level_cap, false, true ); + } +} + void npc::clear_personality_traits() { for( const trait_id &trait : get_mutations() ) { diff --git a/src/npc.h b/src/npc.h index a9d2317d18849..ad8f56b7c2d00 100644 --- a/src/npc.h +++ b/src/npc.h @@ -783,6 +783,7 @@ class npc : public Character void randomize( const npc_class_id &type = npc_class_id::NULL_ID(), const npc_template_id &tem_id = npc_template_id::NULL_ID() ); void randomize_from_faction( faction *fac ); + void catchup_skills(); void apply_ownership_to_inv(); void clear_personality_traits(); void generate_personality_traits(); From e386894688d9bd980ece741e5bfa24cc9e68d65d Mon Sep 17 00:00:00 2001 From: ShnitzelX2 <65314588+ShnitzelX2@users.noreply.github.com> Date: Wed, 9 Oct 2024 17:37:36 -0400 Subject: [PATCH 2/5] map character backgrounds to professions -fix catchup_skills() and personality -adds a bunch of new BG_trait_groups for future character stories --- data/json/npcs/BG_trait_groups.json | 84 ++++++++++++ data/json/professions.json | 198 ++++++++++++++++++++++++++++ src/character.cpp | 7 + src/character.h | 4 + src/newcharacter.cpp | 8 ++ src/npc.cpp | 18 ++- src/npc.h | 1 + src/profession.cpp | 16 +++ src/profession.h | 2 + 9 files changed, 331 insertions(+), 7 deletions(-) diff --git a/data/json/npcs/BG_trait_groups.json b/data/json/npcs/BG_trait_groups.json index a1b441d96e73f..db32e26a4068b 100644 --- a/data/json/npcs/BG_trait_groups.json +++ b/data/json/npcs/BG_trait_groups.json @@ -180,6 +180,90 @@ { "trait": "BGSS_Lab_1" } ] }, + { + "//": "This group is for NPCs that were left unusually emotionally or physically defenseless after the Cataclysm.", + "type": "trait_group", + "id": "BG_survival_story_VULNERABLE", + "subtype": "distribution", + "traits": [ { "trait": "BGSS_Confused_1" }, { "trait": "BGSS_No_Past_2" }, { "trait": "BGSS_No_Past_3" } ] + }, + { + "//": "This group is for NPCs that were exploring a city.", + "type": "trait_group", + "id": "BG_survival_story_TOURIST", + "subtype": "distribution", + "traits": [ { "group": "BG_survival_story_UNIVERSAL" }, { "group": "BG_survival_story_STUCK_IN_TOWN" } ] + }, + { + "//": "This group is for NPCs that retired prior to the Cataclysm.", + "type": "trait_group", + "id": "BG_survival_story_RETIRED", + "subtype": "distribution", + "traits": [ { "group": "BG_survival_story_UNIVERSAL" }, { "trait": "BGSS_Confused_1" }, { "trait": "BGSS_Codger" } ] + }, + { + "//": "This group is for NPCs that are ambiguously unemployed and weirder than usual.", + "type": "trait_group", + "id": "BG_survival_story_ECCENTRIC", + "subtype": "distribution", + "traits": [ { "group": "BG_survival_story_EVACUEE" } ] + }, + { + "//": "This group is for NPCs that prepared in advance and hunkered down after the Cataclysm.", + "type": "trait_group", + "id": "BG_survival_story_PREPPER", + "subtype": "distribution", + "traits": [ { "trait": "BGSS_Prepper_1" }, { "trait": "BGSS_Prepper_2" } ] + }, + { + "//": "This group is for NPCs that are young and roam the streets.", + "type": "trait_group", + "id": "BG_survival_story_TEENAGER_TOUGH", + "subtype": "distribution", + "traits": [ { "group": "BG_survival_story_TEENAGER" } ] + }, + { + "//": "This group is for NPCs that are particularly focused on a spiritual belief.", + "type": "trait_group", + "id": "BG_survival_story_SPIRITUAL", + "subtype": "distribution", + "traits": [ { "trait": "BGSS_Religious_1" }, { "trait": "BGSS_Religious_2" }, { "trait": "BGSS_Dreamer" } ] + }, + { + "//": "This group is for NPCs that are particularly sporty.", + "type": "trait_group", + "id": "BG_survival_story_SPORTS", + "subtype": "distribution", + "traits": [ { "group": "BG_survival_story_EVACUEE" } ] + }, + { + "//": "This group is for NPCs that were commercial workers before the Cataclysm.", + "type": "trait_group", + "id": "BG_survival_story_WORKER_COMMERCIAL", + "subtype": "distribution", + "traits": [ { "group": "BG_survival_story_EVACUEE" } ] + }, + { + "//": "This group is for NPCs that were self-employed before the Cataclysm.", + "type": "trait_group", + "id": "BG_survival_story_WORKER_SELFEMP", + "subtype": "distribution", + "traits": [ { "group": "BG_survival_story_EVACUEE" } ] + }, + { + "//": "This group is for NPCs that were public workers before the Cataclysm.", + "type": "trait_group", + "id": "BG_survival_story_WORKER_PUBLIC", + "subtype": "distribution", + "traits": [ { "group": "BG_survival_story_EVACUEE" } ] + }, + { + "//": "This group is for NPCs that were firefighters before the Cataclysm.", + "type": "trait_group", + "id": "BG_survival_story_WORKER_FIREFIGHTER", + "subtype": "distribution", + "traits": [ { "group": "BG_survival_story_UNIVERSAL" } ] + }, { "//": "This group is for Cyborgs rescued down in the Lab.", "type": "trait_group", diff --git a/data/json/professions.json b/data/json/professions.json index fba541726e3b9..057cd82d6ca1f 100644 --- a/data/json/professions.json +++ b/data/json/professions.json @@ -672,6 +672,7 @@ "id": "vagabond", "name": "Vagabond", "description": "Circumstance left you wandering the world, alone. Now there is nothing to go back to, even if you wanted to. Perhaps your experience in fending for yourself will prove useful in this new world.", + "npc_background": "BG_survival_story_EVACUEE", "points": 1, "skills": [ { "level": 2, "name": "melee" }, @@ -713,6 +714,7 @@ "id": "unemployed", "name": "Survivor", "description": "Some would say that there's nothing particularly notable about you, but you've survived, and that's more than most could say right now.", + "npc_background": "BG_survival_story_EVACUEE", "points": 0, "items": { "both": { @@ -739,6 +741,7 @@ "id": "video_blogger", "name": "Video Blogger", "description": "You made a career out of creating and commentating video content and posting it on various platforms. Now most of your fans are dead, alongside your equipment. Maybe you didn't cultivate the most practical skillset through your career, but you have learned a thing or two about troubleshooting software and getting people to listen to you.", + "npc_background": "BG_survival_story_WORKER_SELFEMP", "points": 2, "skills": [ { "level": 4, "name": "speech" }, { "level": 4, "name": "computer" } ], "items": { @@ -769,6 +772,7 @@ "name": "Sheltered Survivor", "requirement": "achievement_survive_28_days", "description": "At the start of the Cataclysm, you hunkered down in a bomb shelter. You've spent the past months eating canned food, reading books, and tinkering. Now it is winter - time to face the world above.", + "npc_background": "BG_survival_story_EVACUEE", "points": 4, "proficiencies": [ "prof_fibers", "prof_knitting", "prof_carving" ], "skills": [ @@ -810,6 +814,7 @@ "name": "Sheltered Militia", "requirement": "achievement_survive_28_days", "description": "At the start of the Cataclysm, you hunkered down in a bomb shelter with your collection of guns. You've spent the past months eating canned food and practicing your aim. Now it is winter - time to face the world above.", + "npc_background": "BG_survival_story_ECCENTRIC", "points": 4, "proficiencies": [ "prof_gunsmithing_basic", "prof_gunsmithing_improv", "prof_gun_cleaning" ], "skills": [ { "level": 3, "name": "gun" }, { "level": 3, "name": "rifle" }, { "level": 3, "name": "pistol" } ], @@ -846,6 +851,7 @@ "id": "tailor", "name": "Tailor", "description": "Tailoring may not seem like the most useful skill when the world has ended. Most people wouldn't expect a simple tailor to live very long. This is your opportunity to prove them wrong.", + "npc_background": "BG_survival_story_WORKER_COMMERCIAL", "points": 2, "//": "Tailoring book and kit make an already decent class for careful folks much more powerful.", "skills": [ { "level": 6, "name": "tailor" } ], @@ -886,6 +892,7 @@ "id": "chef", "name": "Chef", "description": "Bork bork! Years in the kitchen have left you carrying a prodigious bulk, but you managed to escape the carnage with your trusty butcher knife and only a small collection of stains on your uniform.", + "npc_background": "BG_survival_story_WORKER_COMMERCIAL", "points": 2, "skills": [ { "name": "cooking", "level": 6 } ], "proficiencies": [ @@ -920,6 +927,7 @@ "id": "butcher", "name": "Butcher", "description": "You spent most of your adult life in a butcher shop. Your trusty knife has seen many different creatures and you know how to butcher them.", + "npc_background": "BG_survival_story_WORKER_COMMERCIAL", "points": 2, "skills": [ { "name": "cutting", "level": 2 }, { "name": "cooking", "level": 2 }, { "name": "survival", "level": 2 } ], "proficiencies": [ @@ -958,6 +966,7 @@ "id": "churl", "name": "Churl", "description": "What the deuyl? Ye ne wist noo thing of this straunge plaas nor what wycked enchauntment brought ye hidder. Wyth this accoustrement ye must needs underfongen to find newe lyflode in the most hidous Cataclysm man hath witnessed sithen that deluge Noe rood out in his greet schippe.", + "npc_background": "BG_survival_story_EVACUEE", "points": 0, "items": { "both": { @@ -992,6 +1001,7 @@ "id": "labtech", "name": "Lab Technician", "description": "Thanks to years of study and hard work in the lab, you're familiar with the basics of scientific inquiry. Only one question remains: can you undo the very Cataclysm your colleagues helped create?", + "npc_background": "BG_survival_story_LAB", "points": 3, "skills": [ { "level": 4, "name": "mechanics" }, @@ -1024,6 +1034,7 @@ "id": "engineer_chem", "name": "Chemical Engineer", "description": "You know your way around the periodic table and can name ten different industrial processes that involve any given chemical, but that did not prevent the prospect of employment from looking bleak for you. Fortunately, the Cataclysm might just be the thing to save you from a dead end job.", + "npc_background": "BG_survival_story_LAB", "points": 2, "skills": [ { "level": 5, "name": "chemistry" } ], "proficiencies": [ @@ -1051,6 +1062,7 @@ "id": "mechanic", "name": "Home Mechanic", "description": "You've always loved cars, and there's nothing like getting under the hood and fixing it yourself. You've kept ahold of some handy tools for the job, and at least now you'll never want for parts.", + "npc_background": "BG_survival_story_WORKER_SELFEMP", "proficiencies": [ "prof_metalworking", "prof_welding_basic", "prof_elec_soldering", "prof_driver" ], "points": 2, "skills": [ { "level": 4, "name": "mechanics" }, { "level": 4, "name": "driving" } ], @@ -1081,6 +1093,7 @@ "id": "engineer_mech", "name": "Mechanical Engineer", "description": "You've always loved machines, and have extensively incorporated them into your career. Not long after receiving your degree, you seem to be the one being subjected to a stress test, and it remains unclear if you will retain your structural integrity.", + "npc_background": "BG_survival_story_LAB", "proficiencies": [ "prof_basic_engines", "prof_high_pressure_systems", "prof_pneumatics" ], "points": 2, "skills": [ { "level": 5, "name": "mechanics" } ], @@ -1098,6 +1111,7 @@ "id": "scoundrel", "name": "Scoundrel", "description": "Your flexible outlook on the law, the scuffles you've been in (and avoided) at the bar, and your impressive ability to weasel your way out of the consequences of your actions - all these skills have helped ensure your survival. How much longer will they hold out?", + "npc_background": "BG_survival_story_CRIMINAL", "points": 2, "proficiencies": [ "prof_lockpicking", "prof_knives_familiar", "prof_unarmed_familiar" ], "skills": [ @@ -1136,6 +1150,7 @@ "id": "beekeeper", "name": "Beekeeper", "description": "You used to be a professional apiarist, building and maintaining beehives. You had to abandon your precious bees when the Cataclysm struck, but at least you managed to grab some utensils and honey.", + "npc_background": "BG_survival_story_WORKER_COMMERCIAL", "points": 2, "skills": [ { "name": "fabrication", "level": 4 }, { "name": "survival", "level": 4 } ], "items": { @@ -1164,6 +1179,7 @@ "id": "baseball_player", "name": "Baseball Player", "description": "You played with the local team. You're the only one left, but now you can use your trusty bat for another purpose. Home run!", + "npc_background": "BG_survival_story_SPORTS", "points": 2, "skills": [ { "level": 4, "name": "melee" }, @@ -1199,6 +1215,7 @@ "id": "basketball_player", "name": "Basketball Player", "description": "Your first major game was abruptly canceled when zombies stormed the court. Quick feet and good reflexes meant you were among the lucky few to escape the stadium alive.", + "npc_background": "BG_survival_story_SPORTS", "points": 2, "skills": [ { "level": 5, "name": "dodge" }, { "level": 5, "name": "throw" }, { "level": 4, "name": "swimming" } ], "proficiencies": [ "prof_athlete_basic" ], @@ -1227,6 +1244,7 @@ "id": "football_player", "name": "Football Player", "description": "Your epic touchdown was ruined when your coach's guts were torn out by undead fans. Now you're first pick in the apocalypse draft.", + "npc_background": "BG_survival_story_SPORTS", "points": 3, "skills": [ { "level": 5, "name": "throw" }, @@ -1263,6 +1281,7 @@ "id": "true_foodperson", "name": "True Foodperson", "description": "You are the true Foodperson. Some might think Foodperson is just a mascot, but you know better. The mask has become your face, you are real, and the only thing standing between this world and oblivion is you.", + "npc_background": "BG_survival_story_ECCENTRIC", "points": 0, "traits": [ "PROF_FOODP" ], "skills": [ { "level": 2, "name": "speech" } ], @@ -1299,6 +1318,7 @@ "id": "cyclist", "name": "Professional Cyclist", "description": "You were a promising cyclist with a bright career in front of you before this all happened. Perhaps you'll never get to participate in the grand tours now, but as the saying goes, life is like riding a bicycle: you've got to keep moving.", + "npc_background": "BG_survival_story_SPORTS", "points": 4, "proficiencies": [ "prof_athlete_basic", "prof_athlete_expert", "prof_driver" ], "skills": [ { "level": 5, "name": "driving" }, { "level": 4, "name": "dodge" } ], @@ -1329,6 +1349,7 @@ "name": "Major General", "requirement": "achievement_reach_military_bunker", "description": "You worked your way up through the ranks from a no-name private to a big shot Major General, respected and decorated. On the downside, years of desk duty have left your shooting skills rusty, and all the medals in the world won't protect you now.", + "npc_background": "BG_survival_story_SOLDIER", "points": 4, "proficiencies": [ "prof_gunsmithing_basic", "prof_gun_cleaning" ], "skills": [ @@ -1375,6 +1396,7 @@ "name": { "male": "Marine Infantryman", "female": "Marine Infantrywoman" }, "requirement": "achievement_reach_military_bunker", "description": "You are one of the few and the proud: a member of the US Marine Corps. Now that military command has collapsed in on itself as far as you can tell, you suppose that it falls to you to carry the memory of the Corps forward into the future. Semper fi.", + "npc_background": "BG_survival_story_SOLDIER", "points": 6, "proficiencies": [ "prof_gunsmithing_basic", @@ -1438,6 +1460,7 @@ "name": "Navy Sailor", "requirement": "achievement_reach_aircraft_carrier", "description": "You're a sailor of the US Navy, and spent the last few years working shipside aboard an aircraft carrier. Though you're trained in combat, maintenance of the vessel has been your primary duty. After some event beyond your understanding, the carrier has become a floating graveyard in the middle of nowhere. This is going to take more than a cup of coffee and a monkey wrench to fix.", + "npc_background": "BG_survival_story_SOLDIER", "points": 4, "proficiencies": [ "prof_pneumatics", @@ -1492,6 +1515,7 @@ "name": "Navy Diver", "requirement": "achievement_reach_aircraft_carrier", "description": "You were a member of a Naval Special Warfare diving group, a skilled soldier adept at underwater infiltration and marine combat. You were suiting up for a practice dive when the aircraft carrier you were stationed on was somehow flung from the Yellow Sea to who knows where. You seem to be the only one who survived with your sanity intact, but it's not safe to stay here. At least you're already dressed to abandon ship.", + "npc_background": "BG_survival_story_SOLDIER", "points": 5, "proficiencies": [ "prof_spotting", @@ -1543,6 +1567,7 @@ "name": "Military Veteran", "requirement": "achievement_reach_military_bunker", "description": "After being discharged from the armed forces, you were sent to a veterans' hospital for treatment. Just when you thought you'd overcome your traumas and readjusted to civilian life, the world has come to an end and your worst nightmare has become a reality: life in an endless battlefield.", + "npc_background": "BG_survival_story_SOLDIER", "points": 3, "proficiencies": [ "prof_gunsmithing_basic", "prof_gun_cleaning" ], "skills": [ @@ -1579,6 +1604,7 @@ "name": "Military Recruit", "requirement": "achievement_reach_military_bunker", "description": "Joining the military has been your dream for years. You finally got in, just in time for your training to get interrupted by some sort of national emergency. As far as you can tell, military command abandoned you in this hellhole when you missed the emergency evac.", + "npc_background": "BG_survival_story_SOLDIER", "points": 3, "proficiencies": [ "prof_gunsmithing_basic", @@ -1638,6 +1664,7 @@ "name": "Combat Mechanic", "requirement": "achievement_reach_military_bunker", "description": "Early in your military career, you were hand-picked for extra training in the mechanic's trade, keeping the armor running. It's been years since you last touched a rifle, and the dead men are marching again…", + "npc_background": "BG_survival_story_SOLDIER", "points": 5, "proficiencies": [ "prof_gunsmithing_basic", "prof_metalworking", "prof_welding_basic", "prof_welding", "prof_gun_cleaning" ], "skills": [ @@ -1689,6 +1716,7 @@ "name": "Combat Engineer", "requirement": "achievement_reach_military_bunker", "description": "Your job was simple: Keep the army moving. You built bridges, you built roads, you destroyed fortifications, and you cleared mines. It has been years since you last handled a rifle in basic training; now might be the time to dust off those skills.", + "npc_background": "BG_survival_story_SOLDIER", "points": 7, "proficiencies": [ "prof_gunsmithing_basic", "prof_traps", "prof_trapsetting", "prof_disarming", "prof_spotting", "prof_gun_cleaning" ], "skills": [ @@ -1737,6 +1765,7 @@ "name": "Non-Commissioned Officer", "requirement": "achievement_reach_military_bunker", "description": "You're a veteran of several peacekeeping missions. You led your squad as a sort of parental figure, and they relied on you to give orders and keep them alive. You failed them. And now you're alone.", + "npc_background": "BG_survival_story_SOLDIER", "points": 7, "proficiencies": [ "prof_gunsmithing_basic", @@ -1799,6 +1828,7 @@ "name": "Rifleman", "requirement": "achievement_reach_military_bunker", "description": "When you were young, you dreamed of being a soldier. War is hell and hell is war, but you never thought it would be this bad.", + "npc_background": "BG_survival_story_SOLDIER", "points": 5, "proficiencies": [ "prof_gunsmithing_basic", @@ -1858,6 +1888,7 @@ "id": "seal_sniper", "name": "Navy SEAL Marksmen", "description": "Recruited into the ranks of the US Navy's Special Warfare forces as a designated sniper, your training in precision marksmanship and maritime operations was extensive. As a proficient soldier and combative in all respects, you provided overwatch and long-range elimination services in the line of duty. Now, with naval command imploding and your spotter MIA, your skills with a rifle and covert operations are the only things standing between you and the Cataclysm.", + "npc_background": "BG_survival_story_SOLDIER", "points": 8, "proficiencies": [ "prof_gunsmithing_basic", @@ -1918,6 +1949,7 @@ "name": "Navy SEAL", "requirement": "achievement_reach_aircraft_carrier", "description": "You were a member of the SEALs; a key component of the US Navy's special forces and a proficient combatant in both maritime and ground operations. 'The only easy day was yesterday', and with the chain of command in ruins, you may fulfill your final mission in any way you see fit.", + "npc_background": "BG_survival_story_SOLDIER", "points": 8, "proficiencies": [ "prof_gunsmithing_basic", @@ -1984,6 +2016,7 @@ "name": "Special Operator", "requirement": "achievement_reach_military_base", "description": "You were the best of the best, the military's finest. That's why you're still alive, even after all your comrades fell to the undead. As far as you can tell, military command abandoned you in this hellhole when you missed the emergency evac.", + "npc_background": "BG_survival_story_SOLDIER", "points": 8, "proficiencies": [ "prof_gunsmithing_basic", @@ -2041,6 +2074,7 @@ "id": "maid", "name": { "male": "Butler", "female": "Maid" }, "description": "You were hired to take care of the housekeeping for a wealthy family. Naturally, when things got bad, they all took off on a family vacation to somewhere unknown, leaving you to your fate.", + "npc_background": "BG_survival_story_WORKER_COMMERCIAL", "points": 1, "skills": [ { "level": 3, "name": "tailor" }, { "level": 3, "name": "cooking" }, { "level": 3, "name": "driving" } ], "proficiencies": [ "prof_food_prep", "prof_closures", "prof_knife_skills", "prof_knives_familiar" ], @@ -2083,6 +2117,7 @@ "id": "captive", "name": { "male": "Captive", "female": "Captive" }, "description": "You were following a road at night, trying to get away from the horrors of the city, when you heard a voice calling out in the dark. You followed, hoping they were friendly, but suddenly felt a searing pain in your head and blacked out. You just woke up in this strange place… are you even on Earth anymore?", + "npc_background": "BG_survival_story_PRISONER", "points": -2, "flags": [ "SCEN_ONLY" ] }, @@ -2092,6 +2127,7 @@ "name": { "male": "Rescuer", "female": "Rescuer" }, "requirement": "achievement_reach_mi-Go_encampment", "description": "You were ready. You went in determined to find and rescue your friends. Now the atmosphere in these twisting corridors grows heavy, and you don't feel quite so confident anymore. You might be the one in need of a rescue soon.", + "npc_background": "BG_survival_story_EVACUEE", "points": 3, "proficiencies": [ "prof_auto_rifles_familiar", "prof_knives_familiar", "prof_auto_pistols_familiar" ], "skills": [ @@ -2137,6 +2173,7 @@ "id": "medic", "name": "Medical Resident", "description": "Fresh out of med school, you've got little in the way of practical experience and just a handful of first-aid supplies. You just hope it will be enough if 'physician, heal thyself' turns out to be more literal than you expected.", + "npc_background": "BG_survival_story_WORKER_MEDICAL", "points": 2, "skills": [ { "level": 5, "name": "firstaid" } ], "proficiencies": [ @@ -2181,6 +2218,7 @@ "name": "Doctor", "requirement": "achievement_reach_hospital", "description": "You were a patient-facing doctor practicing general or specialized medicine. While your bedside manner might not get you far in this new world, your medical skills will certainly help.", + "npc_background": "BG_survival_story_WORKER_MEDICAL", "points": 5, "skills": [ { "level": 7, "name": "firstaid" }, { "level": 3, "name": "speech" } ], "proficiencies": [ @@ -2231,6 +2269,7 @@ "name": "Pharmacist", "requirement": "achievement_reach_hospital", "description": "You were a pharmacist working in a community pharmacy. No simple pill-pusher, you have a plethora of knowledge of drug preparation, biochemistry, and biology. With your trusty mortar and pestle, you hope to grind the undead to a pulp.", + "npc_background": "BG_survival_story_WORKER_MEDICAL", "points": 5, "skills": [ { "level": 6, "name": "firstaid" }, { "level": 1, "name": "speech" } ], "proficiencies": [ "prof_intro_biology", "prof_intro_chemistry", "prof_organic_chemistry", "prof_biochemistry", "prof_physiology" ], @@ -2308,6 +2347,7 @@ "name": "Gangster", "requirement": "achievement_kill_100_monsters", "description": "The boss always said he could rely on you to pull through on the tough jobs. Shame he got himself smoked. No problem; the world's always got a place for someone with your kind of talents.", + "npc_background": "BG_survival_story_CRIMINAL", "points": 4, "proficiencies": [ "prof_knives_familiar", "prof_unarmed_familiar", "prof_shivs_familiar", "prof_gross_anatomy" ], "skills": [ @@ -2352,6 +2392,7 @@ "name": "Security Guard", "requirement": "achievement_reach_megastore", "description": "You had a boring, underpaid job watching cameras and patrolling hallways, but things have suddenly gotten a lot more dangerous. You have some useful equipment, but you've never had any call to use it until now.", + "npc_background": "BG_survival_story_WORKER_COMMERCIAL", "points": 2, "skills": [ { "level": 2, "name": "gun" }, @@ -2389,6 +2430,7 @@ "id": "groundskeeper", "name": "Landscaper", "description": "You used to mow lawns and trim hedges for the wealthy. Contract work was getting scarce even before the zombies came, but now you've got nothing left except your tools and expertise.", + "npc_background": "BG_survival_story_WORKER_COMMERCIAL", "points": 1, "proficiencies": [ "prof_short_swords_familiar", "prof_short_swords_pro" ], "skills": [ @@ -2424,6 +2466,7 @@ "name": "Nursing Assistant", "//": "They don't have the doctor's passive bonus to surgery. Nursing assistants aren't required to hold a doctorate.", "description": "You went on providing in-home care for the elderly even as the whole world fell apart around you. You can only pray that you don't see your former clients among the walking dead…", + "npc_background": "BG_survival_story_WORKER_MEDICAL", "points": 1, "skills": [ { "level": 3, "name": "firstaid" }, { "level": 3, "name": "cooking" }, { "level": 3, "name": "speech" } ], "proficiencies": [ "prof_wound_care" ], @@ -2457,6 +2500,7 @@ "name": "Survivalist", "requirement": "achievement_survive_28_days", "description": "Living off the land, far from civilization, is nothing new to you. The only difference is all the monsters that suddenly want you dead. Your equipment is basic, but versatile… except that your canteen's run out!", + "npc_background": "BG_survival_story_RURAL", "points": 5, "proficiencies": [ "prof_gunsmithing_basic", @@ -2513,6 +2557,7 @@ "id": "homeless", "name": "Hobo", "description": "Society drove you to the fringes and left you with no home, no family, no friends. But for all the crap thrown your way, you're still breathing. For now.", + "npc_background": "BG_survival_story_ECCENTRIC", "points": 0, "items": { "both": { @@ -2537,6 +2582,7 @@ "id": "heli_pilot", "name": "Helicopter Pilot", "description": "You got your pilot's license and earned a living ferrying businessmen and tourists around. The Cataclysm has grounded you for now, but the sky still calls to you…", + "npc_background": "BG_survival_story_WORKER_COMMERCIAL", "points": 4, "skills": [ { "level": 6, "name": "driving" }, { "level": 3, "name": "mechanics" }, { "level": 2, "name": "speech" } ], "proficiencies": [ "prof_helicopter_pilot" ], @@ -2564,6 +2610,7 @@ "name": "K9 Officer", "requirement": "achievement_reach_police_station", "description": "You spent your career busting drug smugglers with your faithful canine companion. Now the world has ended, and none of that matters anymore. Your loyal dog is still at your side, though, ready to face the Cataclysm with you.", + "npc_background": "BG_survival_story_POLICE", "points": 5, "skills": [ { "level": 4, "name": "gun" }, @@ -2609,6 +2656,7 @@ "name": "Mounted Police Officer", "requirement": "achievement_reach_police_station", "description": "You have spent many long years forging a bond with your equine companion, from running down common thugs, to entertaining kids when you ride on by. The Cataclysm is upon you, but at least you have each other.", + "npc_background": "BG_survival_story_POLICE", "points": 5, "skills": [ { "level": 5, "name": "survival" }, @@ -2652,6 +2700,7 @@ "id": "dog_lover", "name": "Dog Lover", "description": "You spent your days running around with your faithful dogs by your side. When the world ended, you grabbed your companions along with some of their things to protect them. The zombies could be nearby, but at least your canine friends won't have to worry about the rain.", + "npc_background": "BG_survival_story_EVACUEE", "points": 2, "skills": [ { "level": 3, "name": "survival" } ], "traits": [ "ANIMALEMPATH" ], @@ -2682,6 +2731,7 @@ "id": "crazy_cat_lady", "name": { "male": "Crazy Cat Dude", "female": "Crazy Cat Lady" }, "description": "Everyone is dead? Oh well, it doesn't matter; it's not like you got along with people much anyway. Your beloved cats are all the friends you need!", + "npc_background": "BG_survival_story_ECCENTRIC", "points": 2, "skills": [ { "level": 3, "name": "tailor" }, { "level": 3, "name": "survival" }, { "level": 3, "name": "cooking" } ], "proficiencies": [ "prof_knitting", "prof_knitting_speed" ], @@ -2729,6 +2779,7 @@ "name": "Police Officer", "requirement": "achievement_reach_police_station", "description": "Just a small-town deputy, you got the call and were ready to come to the rescue. Soon it was you who needed rescuing, and you were lucky to escape with your life. Who's going to respect your authority when the government this badge represents might not even exist anymore?", + "npc_background": "BG_survival_story_POLICE", "points": 4, "skills": [ { "level": 4, "name": "gun" }, @@ -2770,6 +2821,7 @@ "name": "Police Detective", "requirement": "achievement_reach_police_station", "description": "You were on the brink of a major breakthrough in your latest homicide case when the Cataclysm struck. Now your prime suspect is dead. Everyone's dead. You could really use a smoke.", + "npc_background": "BG_survival_story_POLICE", "points": 4, "traits": [ "PROF_PD_DET" ], "proficiencies": [ "prof_spotting", "prof_gun_cleaning" ], @@ -2817,6 +2869,7 @@ "name": "SWAT Officer", "requirement": "achievement_reach_police_station", "description": "As a member of the police force's most elite division, you are more than adequately trained and equipped to survive the brutal onslaught of the apocalypse. Unfortunately, the chain of command has broken down; your only mission now is to stay alive.", + "npc_background": "BG_survival_story_POLICE", "points": 6, "proficiencies": [ "prof_gunsmithing_basic", "prof_spotting", "prof_gun_cleaning", "prof_auto_pistols_familiar", "prof_batons_familiar" ], "skills": [ @@ -2868,6 +2921,7 @@ "name": "SWAT CQC Specialist", "requirement": "achievement_reach_police_station", "description": "As a member of the police force's most elite division, you were given special training and became an expert in close-quarters combat. Unfortunately, the chain of command has broken down; your only mission now is to stay alive.", + "npc_background": "BG_survival_story_POLICE", "points": 6, "skills": [ { "level": 5, "name": "gun" }, @@ -2927,6 +2981,7 @@ "name": "Police Sniper", "requirement": "achievement_reach_police_station", "description": "Your skill as a sharpshooter served you well in the line of duty, protecting the innocent with a single, well-placed bullet. Now your own life is on the line, and you can't afford to miss if you don't want to end up as something's dinner.", + "npc_background": "BG_survival_story_POLICE", "points": 6, "proficiencies": [ "prof_gunsmithing_basic", @@ -2981,6 +3036,7 @@ "name": "Riot Control Officer", "requirement": "achievement_reach_police_station", "description": "The riots were brutal, even before the dead rose and started to devour the living. The line you were holding broke. It was only through a bit of luck and a lot of head-bashing that you got away in one piece, and the worst is yet to come.", + "npc_background": "BG_survival_story_POLICE", "points": 5, "skills": [ { "level": 5, "name": "melee" }, @@ -3026,6 +3082,7 @@ "name": "Motorized Police Officer", "requirement": "achievement_reach_police_station", "description": "Just a small-town deputy, you got the call and were ready to ride to the rescue. Soon it was you who needed rescuing, and you had to abandon your motorcycle to escape. Who's going to respect your authority when the government this badge represents doesn't exist anymore?", + "npc_background": "BG_survival_story_POLICE", "points": 4, "skills": [ { "level": 4, "name": "gun" }, @@ -3071,6 +3128,7 @@ "id": "salesman", "name": { "male": "Used Car Salesman", "female": "Used Car Saleswoman" }, "description": "They said you'd sell your own mother for a dollar. How dare they! You've been around the block a few times, and you'd charge way more than a dollar - and get it, too!", + "npc_background": "BG_survival_story_WORKER_COMMERCIAL", "points": 1, "skills": [ { "level": 5, "name": "speech" } ], "items": { @@ -3095,6 +3153,7 @@ "id": "modern_archer", "name": "Modern Archer", "description": "A great fan of the archers of old, but at the same time a follower of the latest trends in archery. You always tried to keep up with the times, acquiring a takedown bow as well as several accessories to complement it. You can only hope all the training you did with them can help you survive in this trying times.", + "npc_background": "BG_survival_story_SPORTS", "points": 4, "proficiencies": [ "prof_bow_basic", "prof_bow_expert" ], "skills": [ { "level": 4, "name": "gun" }, { "level": 4, "name": "archery" }, { "level": 2, "name": "swimming" } ], @@ -3127,6 +3186,7 @@ "id": "bow_hunter", "name": "Bow Hunter", "description": "Ever since you were a child you loved hunting, and quickly developed a talent for archery. Why, if the world ended, there's nothing you'd want at your side more than your trusty bow. So, when it did, you made sure to bring it along.", + "npc_background": "BG_survival_story_RURAL", "points": 3, "proficiencies": [ "prof_bow_basic", @@ -3173,6 +3233,7 @@ "id": "crossbow_hunter", "name": "Crossbow Hunter", "description": "Ever since you were a child you loved hunting, and crossbow hunting was always your favorite. Why, if the world ended, there's nothing you'd want at your side more than your trusty crossbow. So, when it did, you made sure to bring it along, though most of your bolts were lost during the escape.", + "npc_background": "BG_survival_story_RURAL", "points": 3, "proficiencies": [ "prof_bow_basic", @@ -3223,6 +3284,7 @@ "id": "shotgun_hunter", "name": "Shotgun Hunter", "description": "Ever since you were a child you loved hunting, and one year you got a shotgun for your birthday. Why, if the world ended, there's nothing you'd want at your side more than your trusty shotgun. So, when it did, you made sure to bring it along.", + "npc_background": "BG_survival_story_RURAL", "points": 3, "proficiencies": [ "prof_gun_cleaning", @@ -3270,6 +3332,7 @@ "id": "rifle_hunter", "name": "Rifle Hunter", "description": "Ever since you were a child you loved hunting, and you fancy yourself a crack shot. Why, if the world ended, there's nothing you'd want at your side more than your trusty rifle. So, when it did, you made sure to bring it along.", + "npc_background": "BG_survival_story_RURAL", "points": 3, "proficiencies": [ "prof_gun_cleaning", @@ -3316,6 +3379,7 @@ "id": "conversion_hunter", "name": "Big-Bore Hunter", "description": "You always harbored a passion for hunting and a particular fondness for big-bore rifle calibers and affordable conversion kits. Whether it was their cost-effective nature or the simple, testosterone-amplifying notion that you could retool your rifle to belt out .50-caliber bullets, you preferred them for your hunting trips. Now, with your converted rifle in hand, you fancy that there isn't any game too large for you to take down.", + "npc_background": "BG_survival_story_RURAL", "points": 3, "proficiencies": [ "prof_gun_cleaning", @@ -3362,6 +3426,7 @@ "id": "hillbilly", "name": { "male": "Hillbilly", "female": "Hillbilly Girl" }, "description": "You n' yer kin always figured shit would hit the fan some day, but never like this! When they turned on you, you grabbed yer gun and a six pack, and hauled ass in the family truck.", + "npc_background": "BG_survival_story_ECCENTRIC", "points": 4, "proficiencies": [ "prof_driver" ], "skills": [ @@ -3397,6 +3462,7 @@ "id": "construction_worker", "name": { "male": "Handy Man", "female": "Handy Woman" }, "description": "You used to work at a local hardware store, and you did plenty of home renovations yourself. Now you look out at the horizon of a ruined world, and wonder - are your meager skills, and the few supplies you grabbed on the way out, sufficient to help rebuild?", + "npc_background": "BG_survival_story_WORKER_COMMERCIAL", "points": 3, "proficiencies": [ "prof_plumbing", @@ -3432,6 +3498,7 @@ "id": "trucker", "name": "Trucker", "description": "You once ruled the road in your big rig. When the riots hit, you hopped in and drove it to safety. Now it's just you and your truck against the world.", + "npc_background": "BG_survival_story_WORKER_COMMERCIAL", "points": 4, "proficiencies": [ "prof_driver" ], "skills": [ { "level": 6, "name": "driving" }, { "level": 3, "name": "mechanics" } ], @@ -3460,6 +3527,7 @@ "type": "profession", "name": "Rideshare Driver", "description": "You love driving, and decided to start making some money doing it. On your way to pick up a customer, a riot broke out around you. You took a long detour to safety, only to find yourself somewhere unfamiliar.", + "npc_background": "BG_survival_story_WORKER_COMMERCIAL", "points": 3, "proficiencies": [ "prof_driver" ], "skills": [ { "level": 5, "name": "driving" }, { "level": 2, "name": "speech" } ], @@ -3486,6 +3554,7 @@ "type": "profession", "name": "Paramedic Firefighter", "description": "On your way to respond to an emergency call, you nearly drove straight into a riot in the city. Turning off of the burning, debris-covered streets, you took a long detour only to find yourself lost. That call will have to wait - you're in an emergency of your own now.", + "npc_background": "BG_survival_story_WORKER_FIREFIGHTER", "points": 5, "skills": [ { "level": 6, "name": "firstaid" }, @@ -3538,6 +3607,7 @@ "type": "profession", "name": { "male": "Serviceman", "female": "Servicewoman" }, "description": "Employed by a large company, you performed installation and troubleshooting services at the homes of ungrateful luddites. Driving back from your last call, you were suddenly swarmed by what you believed to be angry rioters. You veered off onto an old, neglected side road to escape, only to find yourself lost and low on gas.", + "npc_background": "BG_survival_story_WORKER_COMMERCIAL", "points": 3, "proficiencies": [ "prof_appliance_repair", "prof_driver" ], "skills": [ @@ -3575,6 +3645,7 @@ "type": "profession", "name": "Bus Driver", "description": "You made a living driving kids to and from school, a career choice you regretted almost every day. None of the brats were at their normal stops, and the noise of your bus quickly attracted hordes of zombies. You escaped, but now you've gotten lost. At least you're getting a break from the hellish screams of children, though you're starting to hear new ones…", + "npc_background": "BG_survival_story_WORKER_COMMERCIAL", "points": 3, "proficiencies": [ "prof_driver" ], "skills": [ { "level": 5, "name": "driving" }, { "level": 1, "name": "speech" } ], @@ -3604,6 +3675,7 @@ "name": "Police Interceptor", "requirement": "achievement_reach_police_station", "description": "An on-duty officer, you received the call and were ready to respond to the robbery. It all went to shit, your backup got eaten, and you were lucky to escape with your life and patrol car.", + "npc_background": "BG_survival_story_POLICE", "points": 5, "skills": [ { "level": 4, "name": "gun" }, @@ -3648,6 +3720,7 @@ "name": "Militia", "requirement": "achievement_survive_28_days", "description": "You and a group of like-minded individuals built a hideout in the woods from which to launch looting raids in a jury-rigged pickup. The last run went bad, and now all your comrades are dead. Every breath you take now is an act of rebellion against the cruelty of this doomed world. Do not let that flame of hope perish inside you.", + "npc_background": "BG_survival_story_RURAL", "points": 4, "proficiencies": [ "prof_driver", "prof_auto_rifles_familiar", "prof_auto_pistols_familiar" ], "skills": [ @@ -3696,6 +3769,7 @@ "id": "park_ranger", "name": "Park Ranger", "description": "Your days of patrolling the park and protecting people and wildlife from each other have taught you many useful skills. After finding a gruesome scene at a campsite and getting no response when you radioed for help, you stockpiled as many supplies as possible and set out in your pickup looking for answers.", + "npc_background": "BG_survival_story_WORKER_PUBLIC", "points": 5, "proficiencies": [ "prof_driver", "prof_wound_care" ], "skills": [ @@ -3755,6 +3829,7 @@ "id": "lumberjack", "name": { "male": "Lumberjack", "female": "Lumberjill" }, "description": "You have your trusty wood axe, and you're okay. You felled trees before the world ended, and you suspect the undead aren't nearly as tough.", + "npc_background": "BG_survival_story_WORKER_COMMERCIAL", "points": 2, "proficiencies": [ "prof_great_axes_familiar", "prof_great_axes_pro", "prof_hand_axes_familiar", "prof_hand_axes_pro" ], "skills": [ @@ -3788,6 +3863,7 @@ "id": "fastfoodcook", "name": "Fast Food Cook", "description": "The diners at the fancy burger joint where you worked were even more irritable and unreasonable than usual today. You showed them the meaning of fast food… by running for your life!", + "npc_background": "BG_survival_story_WORKER_COMMERCIAL", "points": 1, "skills": [ { "level": 3, "name": "cooking" } ], "proficiencies": [ "prof_frying", "prof_knives_familiar" ], @@ -3813,6 +3889,7 @@ "id": "electrician", "name": "Electrician", "description": "Small businesses often hired you for electrical work. You were halfway through your latest job when the whole power grid went dead.", + "npc_background": "BG_survival_story_WORKER_COMMERCIAL", "points": 2, "proficiencies": [ "prof_elec_soldering", "prof_appliance_repair" ], "skills": [ { "level": 6, "name": "electronics" } ], @@ -3842,6 +3919,7 @@ "id": "engineer_ee", "name": "Electrical Engineer", "description": "Fresh out of college, you were quite eager to get some practical engineering experience and leave your mark on the world, one solder joint at a time. Now, you are not even sure if the complete failure of the power grid makes your field obsolete or all the more necessary.", + "npc_background": "BG_survival_story_LAB", "points": 2, "proficiencies": [ "prof_elec_soldering", @@ -3869,6 +3947,7 @@ "id": "hacker", "name": "Computer Hacker", "description": "Caffeine pills and all-nighters in front of a computer screen made you an expert at writing and cracking code. The power's gone out, and suddenly your elite skills seem significantly less useful. At least there's no one stopping you from your dream of breaking into a military mainframe now.", + "npc_background": "BG_survival_story_WORKER_COMMERCIAL", "points": 2, "skills": [ { "level": 6, "name": "computer" } ], "items": { @@ -3898,6 +3977,7 @@ "id": "backpacker", "name": "Backpacker", "description": "For the past few years you've been traveling the world, sightseeing and living off your parents' trust fund. You came home to find the world in ruins, and the only thing between you and death is the open road and your backpack.", + "npc_background": "BG_survival_story_RURAL", "points": 1, "skills": [ { "level": 3, "name": "survival" } ], "items": { @@ -3924,6 +4004,7 @@ "id": "student", "name": "Student", "description": "Just an average student, you find yourself facing a test you never studied for, and the stakes are a bit higher than geometry. Maybe there'll be something useful in one of these books you've been lugging around all year.", + "npc_background": "BG_survival_story_TEENAGER", "points": 0, "skills": [ { "level": 2, "name": "chemistry" }, { "level": 2, "name": "computer" } ], "items": { @@ -3954,6 +4035,7 @@ "id": "svictim", "name": "Shower Victim", "description": "You just stepped out of a nice, hot shower to find the world had ended. You've got some soap, along with the most massively useful thing ever… a towel.", + "npc_background": "BG_survival_story_VULNERABLE", "points": -1, "flags": [ "NO_BONUS_ITEMS" ], "items": { "both": { "entries": [ { "item": "towel_wet" }, { "item": "soap", "custom-flags": [ "auto_wield" ] } ] } } @@ -3963,6 +4045,7 @@ "id": "biker", "name": "Biker", "description": "You spent most of your life on a motorcycle, out on the open road with your club. Now they're all dead. Time to ride or die.", + "npc_background": "BG_survival_story_EVACUEE", "points": 3, "proficiencies": [ "prof_driver" ], "skills": [ { "level": 6, "name": "driving" }, { "level": 3, "name": "mechanics" } ], @@ -3993,6 +4076,7 @@ "id": "dancer", "name": "Ballroom Dancer", "description": "Things got a little weird on your way to your weekly dance class. Zombies don't seem to know how to dance, but you're not about to let them step on your toes.", + "npc_background": "BG_survival_story_SPORTS", "points": 0, "skills": [ { "level": 3, "name": "dodge" } ], "items": { @@ -4023,6 +4107,7 @@ "id": "patient", "name": "Patient", "description": "When the diagnosis came back positive, you made a vow: to fight for your life, and to never give in to despair. Now is the time to renew that vow.", + "npc_background": "BG_survival_story_VULNERABLE", "points": -2, "items": { "both": { @@ -4048,6 +4133,7 @@ "id": "mutant_patient", "name": "Unwilling Mutant", "description": "You were a human guinea pig, used by laboratory technicians to understand the immense power of mutation. You are determined to live on, if only to spite them for what they did to you.", + "npc_background": "BG_survival_story_EVACUEE", "points": -1, "items": { "both": [ "subsuit_xl" ], @@ -4062,6 +4148,7 @@ "id": "mutant_volunteer", "name": "Volunteer Mutant", "description": "Your dreams of becoming a mutant superhero through genetic alteration may have fallen a bit short, but the scientists say you're ready. It's time for a field test.", + "npc_background": "BG_survival_story_EVACUEE", "points": 2, "skills": [ { "level": 4, "name": "chemistry" }, { "level": 4, "name": "electronics" } ], "items": { @@ -4089,6 +4176,7 @@ "id": "hitchhiker", "name": "Hitchhiker", "description": "Your house has been demolished and your planet destroyed, but at least you still have your towel.", + "npc_background": "BG_survival_story_VULNERABLE", "points": -1, "items": { "both": [ "house_coat", "slippers", "towel", "guidebook" ], @@ -4101,6 +4189,7 @@ "id": "trapper", "name": "Trapper", "description": "You spent most of your life trapping with your father. Both of you made a decent living selling your catches and running trapping tutorials. Hopefully, your skills will come in useful against less conventional game.", + "npc_background": "BG_survival_story_RURAL", "points": 3, "skills": [ { "level": 6, "name": "traps" }, { "level": 4, "name": "survival" } ], "proficiencies": [ @@ -4141,6 +4230,7 @@ "id": "blacksmith", "name": "Blacksmith", "description": "You ran into trouble coming out of class at your community college's metalsmithing program, but despite the havoc you've managed to keep ahold of some of the equipment you were carrying.", + "npc_background": "BG_survival_story_WORKER_COMMERCIAL", "points": 2, "skills": [ { "level": 6, "name": "fabrication" }, { "level": 2, "name": "swimming" } ], "proficiencies": [ "prof_metalworking", "prof_blacksmithing" ], @@ -4168,6 +4258,7 @@ "id": "jeweler", "name": "Jeweler", "description": "You were an independent artisan, who made gorgeous rings and pendants for the people who afforded your services. You doubt the market for your work has fared well after the end of the world, but perhaps your proficiency with fine tools and metals will come in handy somehow.", + "npc_background": "BG_survival_story_WORKER_COMMERCIAL", "points": 2, "skills": [ { "level": 6, "name": "fabrication" }, { "level": 2, "name": "swimming" } ], "proficiencies": [ "prof_metalworking", "prof_redsmithing", "prof_fine_metalsmithing", "prof_gem_setting" ], @@ -4194,6 +4285,7 @@ "id": "clown", "name": { "male": "Clown", "female": "Clowness" }, "description": "All you ever wanted was to make people laugh. Dropping out of school and performing at kids' parties was a dream come true until the world ended. There are precious few balloon animals in your future now.", + "npc_background": "BG_survival_story_WORKER_SELFEMP", "points": -1, "items": { "both": { @@ -4219,6 +4311,7 @@ "id": "lost_sub", "name": "Lost Submissive", "description": "In the rush to safety, you were separated from your master by cruel fate. Now you are on your own, with nothing to your name but a suit of really kinky black leather. Unfortunately, there are no safewords in the apocalypse.", + "npc_background": "BG_survival_story_VULNERABLE", "points": -1, "traits": [ "MASOCHIST" ], "flags": [ "NO_BONUS_ITEMS" ], @@ -4242,6 +4335,7 @@ "id": "senior", "name": "Senior Citizen", "description": "You haven't seen this much blood since the war. The whole world's gone crazy! They ate your grandkids! But dagnabbit, you'll make them all pay for what they've done.", + "npc_background": "BG_survival_story_RETIRED", "proficiencies": [ "prof_knitting" ], "points": 0, "items": { @@ -4272,6 +4366,7 @@ "id": "otaku", "name": "Otaku", "description": "After many late nights with friends watching anime and eating snacks, you decided to make the trip to the premier anime convention in the Northeast. Now zombies are eating everyone, and even worse, the convention is canceled! At least you were ready in case your costume tore.", + "npc_background": "BG_survival_story_ECCENTRIC", "points": 0, "skills": [ { "level": 2, "name": "tailor" } ], "items": { @@ -4305,6 +4400,7 @@ "id": "spouse", "name": { "male": "Groom", "female": "Bride" }, "description": "The Cataclysm struck on the big day and you escaped with nothing but your wedding attire. Cold feet? You'd just like to keep your feet attached!", + "npc_background": "BG_survival_story_EVACUEE", "points": -1, "items": { "both": { "entries": [ { "item": "ring_wedding" }, { "group": "charged_smart_phone" }, { "group": "starter_wallet_full" } ] }, @@ -4341,6 +4437,7 @@ "id": "punkrockgirl", "name": { "male": "Punk Rock Dude", "female": "Punk Rock Girl" }, "description": "All those wicked songs about the apocalypse have come to life. Brutal! Now that the system is dead, it's time to party among the bones of the world!", + "npc_background": "BG_survival_story_TEENAGER_TOUGH", "points": 0, "skills": [ { "level": 2, "name": "speech" }, { "level": 1, "name": "tailor" } ], "items": { @@ -4377,6 +4474,7 @@ "id": "firefighter", "name": "Firefighter", "description": "As a first responder, you were a direct witness to the gut-wrenching horrors of the apocalypse. Separated from most of your equipment and your unit while on call, you were forced to fight your way to safety with little more than your trusty iron and your bunker gear to protect you.", + "npc_background": "BG_survival_story_WORKER_FIREFIGHTER", "points": 3, "skills": [ { "level": 4, "name": "melee" }, @@ -4411,6 +4509,7 @@ "id": "skaboy", "name": { "male": "Rude Boy", "female": "Rude Girl" }, "description": "Your ska band broke up after the drummer became a zombie. Now you're alone in the Cataclysm with some cigarettes and your mp3 player.", + "npc_background": "BG_survival_story_TEENAGER_TOUGH", "points": 0, "skills": [ { "level": 3, "name": "speech" } ], "items": { @@ -4439,6 +4538,7 @@ "id": "postman", "name": "Mail Carrier", "description": "Neither snow nor rain nor heat nor gloom of night stays you from the swift completion of your appointed rounds, but nobody said anything about zombies.", + "npc_background": "BG_survival_story_WORKER_PUBLIC", "points": 0, "skills": [ { "level": 3, "name": "driving" }, { "level": 2, "name": "dodge" } ], "items": { @@ -4470,6 +4570,7 @@ "id": "convict", "name": "Convict", "description": "Your trial was contentious, but ultimately you found yourself behind bars. The Cataclysm has offered you a chance to escape, but freedom may come with a steep price.", + "npc_background": "BG_survival_story_PRISONER", "points": -1, "items": { "both": [ "striped_shirt", "striped_pants", "sneakers", "socks" ], @@ -4482,6 +4583,7 @@ "id": "hardened_convict", "name": "Hardened Convict", "description": "Most of your adult life has been spent in prison doing hard time. It's been rough but you've learned a few tricks to keep them on their toes. Time to see how tough these zombies are.", + "npc_background": "BG_survival_story_PRISONER", "points": 0, "proficiencies": [ "prof_unarmed_familiar", "prof_shivs_familiar" ], "skills": [ @@ -4502,6 +4604,7 @@ "id": "death_row_convict", "name": "Death Row Convict", "description": "You were a serial killer, ready to walk the green mile, but in a twist of fate you're one of the few still alive. True death comes only from your hands, so you're in for a job.", + "npc_background": "BG_survival_story_PRISONER", "points": 1, "proficiencies": [ "prof_knives_familiar", "prof_unarmed_familiar", "prof_shivs_familiar" ], "skills": [ { "level": 3, "name": "melee" }, { "level": 3, "name": "stabbing" }, { "level": 2, "name": "unarmed" } ], @@ -4517,6 +4620,7 @@ "id": "convict_assassin", "name": "Undercover Assassin Convict", "description": "You were given a target, a mission, but killing your mark seems to have become much more difficult now. Your employer cut contact with you and now you have to make do with what you have.", + "npc_background": "BG_survival_story_PRISONER", "points": 2, "skills": [ { "level": 4, "name": "melee" }, @@ -4554,6 +4658,7 @@ "id": "convict_embezzler", "name": "Embezzler", "description": "You had a genius plan to skim fractions of cents out of your company's accounts. This plan immediately failed and got you arrested. They said you were too soft for prison, but guess what? They're dead, and you're not.", + "npc_background": "BG_survival_story_PRISONER", "points": 0, "skills": [ { "level": 4, "name": "speech" }, { "level": 3, "name": "computer" } ], "items": { @@ -4568,6 +4673,7 @@ "id": "convict_drugs", "name": "Meth Cook", "description": "You clawed your way out of poverty by selling products everyone wanted, and they had the nerve to put you in jail for it. Too bad you can't sell drugs to zombies.", + "npc_background": "BG_survival_story_PRISONER", "points": 2, "skills": [ { "level": 6, "name": "chemistry" }, { "level": 2, "name": "firstaid" } ], "items": { @@ -4592,6 +4698,7 @@ "id": "convict_political", "name": "Political Prisoner", "description": "You did your best to expose what was going on in those labs, but they caught you and threw you in prison on trumped-up charges to silence you. Clearly, they should have listened.", + "npc_background": "BG_survival_story_PRISONER", "points": 1, "skills": [ { "level": 6, "name": "speech" } ], "items": { @@ -4615,6 +4722,7 @@ "id": "convict_ratman", "name": { "male": "Rat Prince", "female": "Rat Princess" }, "description": "You probably needed psychiatric help instead of a prison sentence. At least your loyal subjects have agreed to hold the line as you make your daring escape.", + "npc_background": "BG_survival_story_PRISONER", "points": 3, "skills": [ { "level": 4, "name": "survival" }, { "level": 2, "name": "speech" } ], "traits": [ "ANIMALEMPATH" ], @@ -4631,6 +4739,7 @@ "id": "burglar", "name": "Burglar", "description": "This could be your lucky break. Plenty of loot to be pilfered, and no cops to be seen. Does it count as breaking and entering if everyone in town is undead?", + "npc_background": "BG_survival_story_CRIMINAL", "points": 2, "proficiencies": [ "prof_lockpicking", "prof_safecracking" ], "skills": [ { "level": 6, "name": "traps" }, { "level": 2, "name": "dodge" } ], @@ -4663,6 +4772,7 @@ "id": "lawyer", "name": "Lawyer", "description": "The jury were in the palm of your hand, but after the defendant tried to eat your brain, you were forced to flee the courtroom in disgrace. Now nobody seems to care about your objections.", + "npc_background": "BG_survival_story_WORKER_COMMERCIAL", "points": 1, "skills": [ { "level": 6, "name": "speech" } ], "items": { @@ -4691,6 +4801,7 @@ "id": "priest", "name": "Pastor", "description": "Armageddon has come! You did everything you could to protect your community, but it appears that prayers were not enough. Now that they are all dead, you should probably find something more tangible to protect you.", + "npc_background": "BG_survival_story_SPIRITUAL", "points": 0, "skills": [ { "level": 3, "name": "speech" } ], "items": { @@ -4715,6 +4826,7 @@ "id": "c_priest", "name": { "male": "Catholic Priest", "female": "Nun" }, "description": "For your entire time as a servant of God, you helped, protected and listened to your parish faithful. But the Rapture has come, and your parish turned against you. Now all you can do is pray to the Holy Virgin, and prepare to maintain your wellbeing.", + "npc_background": "BG_survival_story_SPIRITUAL", "points": 0, "skills": [ { "level": 3, "name": "speech" } ], "items": { @@ -4755,6 +4867,7 @@ "id": "shinto_priest", "name": "Kannushi", "description": "You were one of the maintainers of a Shinto shrine, performing rituals and sacred tasks. You preferred it when only the spirits of the dead inhabited your shrine, and not their rotting corpses.", + "npc_background": "BG_survival_story_SPIRITUAL", "points": 0, "skills": [ { "level": 3, "name": "fabrication" }, { "level": 3, "name": "tailor" } ], "items": { @@ -4781,6 +4894,7 @@ "id": "bhikkhu", "name": { "male": "Bhikkhu", "female": "Bhikkhuni" }, "description": "Your life was simple at the Vihara, doing household chores and meditating. Your Sangha wanted to attain liberation from suffering, now their rotting corpses will suffer forever.", + "npc_background": "BG_survival_story_SPIRITUAL", "points": 0, "skills": [ { "level": 3, "name": "speech" } ], "items": { @@ -4805,6 +4919,7 @@ "id": "imam", "name": { "male": "Imam", "female": "Mourchida" }, "description": "You spent much of your time prior to the apocalypse at the local mosque, studying the words of the Prophet and the Quran and guiding your community in prayer. Back then they came from far and wide to listen to you; now they come to eat your brains.", + "npc_background": "BG_survival_story_SPIRITUAL", "points": 0, "//": "No knife, fire, or decent storage/armor. Skill points are countered.", "skills": [ { "level": 3, "name": "speech" } ], @@ -4832,6 +4947,7 @@ "id": "rabbi", "name": "Rabbi", "description": "You were davening Shacharit in shul when the Cataclysm struck. You had always taught that God will restore life to the dead after Moshiach has come, but not like this!", + "npc_background": "BG_survival_story_SPIRITUAL", "points": 0, "skills": [ { "level": 3, "name": "speech" } ], "items": { @@ -4860,6 +4976,7 @@ "id": "guru", "name": "Guru", "description": "You spent many years traveling through the world, becoming wise and learned. Normally you can answer any question, but even you are not quite sure what to do about the ravenous undead.", + "npc_background": "BG_survival_story_SPIRITUAL", "points": 1, "skills": [ { "level": 5, "name": "speech" }, { "level": 3, "name": "survival" } ], "items": { @@ -4889,6 +5006,7 @@ "id": "preacher", "name": "Traveling Preacher", "description": "You devoted your life to spreading the good word, always on the road, traveling from town to town. Now everything has gone to hell, you can't host your daily podcast, and the undead don't seem particularly moved by your sermons.", + "npc_background": "BG_survival_story_SPIRITUAL", "points": 1, "skills": [ { "level": 4, "name": "speech" }, { "level": 4, "name": "driving" } ], "items": { @@ -4919,6 +5037,7 @@ "id": "blackbelt_novice", "name": "Novice Martial Artist", "description": "You've decided today is the day to take your first lesson at the local dojo. You'll be great at it, you're sure of it.", + "npc_background": "BG_survival_story_SPORTS", "points": 1, "flags": [ "NO_BONUS_ITEMS" ], "skills": [ { "level": 1, "name": "melee" }, { "level": 1, "name": "unarmed" } ], @@ -4944,6 +5063,7 @@ "id": "blackbelt_intermediate", "name": "Martial Artist", "description": "'Drop the martial arts!', they said. 'Learn a skill for the REAL world!', they said. Well, you're about to show them! SHOW THEM ALL!", + "npc_background": "BG_survival_story_SPORTS", "points": 3, "starting_styles_choices": [ "style_aikido", @@ -4983,6 +5103,7 @@ "id": "blackbelt", "name": "Black Belt", "description": "As the world ends, you alone stand against the coming darkness with your fists of steel.", + "npc_background": "BG_survival_story_SPORTS", "points": 8, "starting_styles_choices": [ "style_aikido", @@ -5021,6 +5142,7 @@ "id": "pizzaboy", "name": { "male": "Pizza Delivery Boy", "female": "Pizza Delivery Girl" }, "description": "You were delivering the last pizza of the night to one of your common patrons when hungry zombies attempted to make a meal out of you. Fleeing for safety, you find yourself with only your wits and some leftover pizza. And they didn't even leave a tip!", + "npc_background": "BG_survival_story_WORKER_COMMERCIAL", "points": 0, "skills": [ { "level": 3, "name": "driving" }, { "level": 1, "name": "speech" } ], "items": { @@ -5050,6 +5172,7 @@ "id": "archaeologist", "name": "Archaeologist", "description": "Following a clue from your dead grandfather's journal, you made your way to a long-lost temple, but then the ground started to shake uncontrollably. You had a bad feeling about that, so you got out of there quickly.", + "npc_background": "BG_survival_story_WORKER_COMMERCIAL", "points": 2, "skills": [ { "level": 4, "name": "survival" }, @@ -5088,6 +5211,7 @@ "id": "paperboy", "name": { "male": "Paperboy", "female": "Papergirl" }, "description": "You set out this morning to deliver the news of the apocalypse. The undead hordes don't seem to value the latest news, but at least your trusty bicycle is still in working order.", + "npc_background": "BG_survival_story_WORKER_COMMERCIAL", "points": 2, "skills": [ { "level": 4, "name": "driving" }, { "level": 3, "name": "throw" }, { "level": 1, "name": "speech" } ], "proficiencies": [ "prof_athlete_basic", "prof_driver" ], @@ -5120,6 +5244,7 @@ "id": "farmer", "name": "Farmer", "description": "A patch of soil, some water, and sunlight were all you ever needed; why should things be any different now? With a handful of seeds and your trusty hoe, it's time to rebuild the Earth, one plant at a time.", + "npc_background": "BG_survival_story_RURAL", "points": 1, "skills": [ { "level": 3, "name": "survival" }, @@ -5161,6 +5286,7 @@ "name": "National Guardsman", "requirement": "achievement_reach_military_bunker", "description": "The government activated your National Guard unit to deal with the growing epidemics. Despite your best efforts, you were unable to form up before all communications ceased and you found yourself alone among the dead.", + "npc_background": "BG_survival_story_SOLDIER", "points": 4, "skills": [ { "level": 4, "name": "gun" }, @@ -5195,6 +5321,7 @@ "name": "Hardened Scavenger", "requirement": "achievement_survive_91_days", "description": "One of the lucky few who escaped the Cataclysm, you made a life for yourself amidst the ruins of civilization. Whether through force, guile, or luck, you've obtained the best gear you could find.", + "npc_background": "BG_survival_story_EVACUEE", "points": 8, "proficiencies": [ "prof_fibers", @@ -5252,6 +5379,7 @@ "name": "Military Holdout", "requirement": "achievement_reach_military_bunker", "description": "You must have paid attention to your survival training in boot camp; otherwise, you would never have lived long enough to outlast the chain of command and find yourself in this predicament. The only mission now is to survive.", + "npc_background": "BG_survival_story_SOLDIER", "points": 6, "proficiencies": [ "prof_gunsmithing_basic", @@ -5305,6 +5433,7 @@ "id": "mall_cop", "name": "Mall Security", "description": "You spent dull nights guarding the local mall against teen hooligans and petty thieves. Your job training didn't provide any terribly useful skills, but you do have your trusty stun gun, baton, and pocket knife.", + "npc_background": "BG_survival_story_WORKER_COMMERCIAL", "points": 0, "skills": [ { "level": 2, "name": "melee" }, { "level": 2, "name": "bashing" } ], "items": { @@ -5336,6 +5465,7 @@ "name": "Naturalist", "requirement": "achievement_survive_91_days", "description": "Over long years of self-imposed exile in the wilderness, you have come to an understanding with Mother Nature. The world as they knew it might have ended for your forsaken species, but you can hardly tell the difference.", + "npc_background": "BG_survival_story_RURAL", "points": 6, "skills": [ { "level": 7, "name": "survival" }, @@ -5398,6 +5528,7 @@ "id": "fisher", "name": "Fisher", "description": "You spent most of your days fishing in the swamp, getting by quietly on your catch. You found the buzzing of insects enjoyable, but recently they've gotten bigger and meaner. Now their horrible noises have you spooked - you just hope the fish aren't as nasty.", + "npc_background": "BG_survival_story_RURAL", "points": 2, "skills": [ { "level": 5, "name": "survival" }, { "level": 2, "name": "swimming" } ], "proficiencies": [ "prof_fibers", "prof_knives_familiar", "prof_butchering_basic" ], @@ -5432,6 +5563,7 @@ "id": "reenactor", "name": { "male": "Historical Reenactor", "female": "Ahistorical Reenactor" }, "description": { + "npc_background": "BG_survival_story_EVACUEE", "male": "You were on your way to the Annual All New England Revolutionary War Living History exhibition when the end of the world permanently derailed your plans.", "female": "You were on your way to the Annual All New England Revolutionary War Living History exhibition when the end of the world made traditional gender roles obsolete." }, @@ -5483,6 +5615,7 @@ "id": "reenactor2", "name": { "male": "Ahistorical Reenactor", "female": "Historical Reenactor" }, "description": { + "npc_background": "BG_survival_story_EVACUEE", "male": "You were on your way to the Annual All New England Revolutionary War Living History exhibition when the end of the world made traditional gender roles obsolete.", "female": "You were on your way to the Annual All New England Revolutionary War Living History exhibition when the end of the world permanently derailed your plans." }, @@ -5525,6 +5658,7 @@ "id": "skaterkid", "name": { "male": "Skater Boy (Rollerblades)", "female": "Skater Girl (Rollerblades)" }, "description": "You love to skate! You've probably spent more time on a pair of blades than off. Things have gotten pretty bad, but at least the grown-ups aren't telling you where you can't roll.", + "npc_background": "BG_survival_story_TEENAGER_TOUGH", "points": 1, "skills": [ { "level": 4, "name": "dodge" }, { "level": 3, "name": "driving" }, { "level": 2, "name": "swimming" } ], "traits": [ "PROF_SKATER" ], @@ -5560,6 +5694,7 @@ "id": "skaterkid_board", "name": { "male": "Skater Boy (Skateboard)", "female": "Skater Girl (Skateboard)" }, "description": "You love to skate! You've probably spent more time on a skateboard than off. Things have gotten pretty bad, but at least the grown-ups aren't telling you where you can't roll.", + "npc_background": "BG_survival_story_TEENAGER_TOUGH", "points": 1, "proficiencies": [ "prof_driver", "prof_athlete_basic" ], "skills": [ { "level": 4, "name": "dodge" }, { "level": 3, "name": "driving" }, { "level": 2, "name": "swimming" } ], @@ -5596,6 +5731,7 @@ "id": "jdelinquent", "name": "Juvenile Delinquent", "description": "You never cared for grown-ups telling you what to do, so you ended up spending quite a few days in the principal's office. Now, not needing grown-ups to tell you what to do is the only reason you're alive. Man, you really should've played hooky today.", + "npc_background": "BG_survival_story_TEENAGER_TOUGH", "points": 0, "proficiencies": [ "prof_unarmed_familiar" ], "skills": [ @@ -5641,6 +5777,7 @@ "name": "Survivalist Jr.", "requirement": "achievement_survive_7_days", "description": "Your parents were crazy preppers who thought some \"Cataclysm\" was coming, and insisted on preparing you for it. Turns out they were right. You didn't get a chance to thank them. The only thing you can do for them now is what they always hoped you would do in the dark days ahead: survive.", + "npc_background": "BG_survival_story_TEENAGER", "points": 2, "skills": [ { "level": 3, "name": "fabrication" }, @@ -5682,6 +5819,7 @@ "id": "dodgeball_player", "name": "Dodgeball Player", "description": "In dodgeball, failing to dodge meant taking a ball to the head and being out of the game. In the Cataclysm, it means getting eaten by monsters. Don't slip up.", + "npc_background": "BG_survival_story_SPORTS", "points": 2, "skills": [ { "level": 5, "name": "dodge" }, { "level": 4, "name": "throw" }, { "level": 3, "name": "swimming" } ], "proficiencies": [ "prof_athlete_basic" ], @@ -5710,6 +5848,7 @@ "id": "science_club_mem", "name": "Science Club Member", "description": "The school never let your club play with the really fun chemicals, the kind that make things go boom, but there aren't any teachers around to enforce the rules anymore.", + "npc_background": "BG_survival_story_TEENAGER", "points": 1, "skills": [ { "level": 2, "name": "fabrication" }, { "level": 2, "name": "mechanics" }, { "level": 2, "name": "chemistry" } ], "items": { @@ -5739,6 +5878,7 @@ "id": "av_club_mem", "name": "A/V Club Member", "description": "You were a member of the school A/V club. You're sure there's some way you can use your technical skills to help you stay alive. You just haven't figured out how to make an awesome death ray yet.", + "npc_background": "BG_survival_story_TEENAGER", "points": 1, "skills": [ { "level": 3, "name": "electronics" }, { "level": 3, "name": "computer" } ], "items": { @@ -5768,6 +5908,7 @@ "id": "teacher", "name": "Teacher", "description": "You've been teaching kids all your life, experiencing the joy and aggravation of imparting knowledge to young minds. If zombies have any interest in education, they're not showing it.", + "npc_background": "BG_survival_story_WORKER_PUBLIC", "points": 1, "skills": [ { "level": 4, "name": "speech" } ], "items": { @@ -5796,6 +5937,7 @@ "id": "photojournalist", "name": "Photojournalist", "description": "Covering the apocalypse up close could make your career, though finding a publisher seems more difficult a prospect than usual. You managed to hold onto your camera - hopefully you can get some fantastic shots.", + "npc_background": "BG_survival_story_WORKER_SELFEMP", "points": 1, "skills": [ { "level": 4, "name": "speech" } ], "items": { @@ -5822,6 +5964,7 @@ "id": "gym_teacher", "name": "Gym Teacher", "description": "It was hard enough getting kids to run laps without having to worry about them trying to eat your brains. Zombies won't even line up when you blow your whistle.", + "npc_background": "BG_survival_story_WORKER_PUBLIC", "points": 2, "skills": [ { "level": 3, "name": "swimming" }, @@ -5855,6 +5998,7 @@ "id": "miner", "name": "Miner", "description": "You're a miner, not a minor! Your canteen is dry, your jackhammer is out of gas, and you're on your last pair of batteries for your mining helmet…", + "npc_background": "BG_survival_story_WORKER_COMMERCIAL", "points": 1, "skills": [ { "level": 2, "name": "mechanics" }, { "level": 2, "name": "swimming" } ], "items": { @@ -5889,6 +6033,7 @@ "id": "demolition_expert", "name": "Demolition Expert", "description": "Before this all began, you were having the time of your life at your dream job: blowing stuff up. The Cataclysm means you're finally allowed to do it full time.", + "npc_background": "BG_survival_story_WORKER_COMMERCIAL", "skills": [ { "level": 4, "name": "fabrication" }, { "level": 3, "name": "chemistry" }, { "level": 3, "name": "throw" } ], "points": 2, "items": { @@ -5921,6 +6066,7 @@ "id": "parkour_practitioner", "name": { "male": "Traceur", "female": "Traceuse" }, "description": "You've practiced parkour for many years, and made the world your playground. It wouldn't be a lie to say that running is your life. Which is good, because now that the end has come, you're running FOR your life.", + "npc_background": "BG_survival_story_SPORTS", "points": 3, "proficiencies": [ "prof_parkour", "prof_athlete_basic" ], "skills": [ { "level": 6, "name": "dodge" }, { "level": 4, "name": "swimming" } ], @@ -5950,6 +6096,7 @@ "id": "tourist", "name": "Tourist", "description": "This seemed like a great place for a vacation, but you're starting to regret ever leaving home. You came here to get a taste of New England, but New England keeps trying to get a taste of you!", + "npc_background": "BG_survival_story_TOURIST", "points": 0, "items": { "both": { @@ -5981,6 +6128,7 @@ "id": "naked", "name": "Naked and Afraid", "description": "The apocalypse has caught you completely naked! Maybe you were robbed, maybe you were at a nudist beach, or maybe you just enjoy the feeling of liberation brought by the wind touching your skin. Whatever the reason, you lack clothes in a time when everyone wants a piece of you.", + "npc_background": "BG_survival_story_VULNERABLE", "flags": [ "NO_BONUS_ITEMS" ], "points": -1 }, @@ -5989,6 +6137,7 @@ "id": "zoo_keeper", "name": "Zoo Keeper", "description": "You were called in on your day off to feed the animals at the zoo. For some reason, none of your coworkers bothered showing up for work today.", + "npc_background": "BG_survival_story_WORKER_COMMERCIAL", "points": 2, "traits": [ "ANIMALEMPATH" ], "skills": [ { "level": 4, "name": "survival" }, { "level": 3, "name": "firstaid" } ], @@ -6017,6 +6166,7 @@ "id": "urban_samurai", "name": "Urban Samurai", "description": "You were always an inexplicable sight in town, with your funny hair and odd Japanese clothes. Little of this concerned you, but last week the grocery service stopped coming and now the TV no longer turns on. This displeases you.", + "npc_background": "BG_survival_story_ECCENTRIC", "points": 0, "skills": [ { "level": 1, "name": "melee" }, { "level": 1, "name": "cutting" } ], "items": { @@ -6041,6 +6191,7 @@ "id": "fencer", "name": "Competitive Fencer", "description": "Years of training prepared you for the competitive fencing circuit, but your latest tournament was cut short when zombies invaded the piste. The referee was eaten, so you're not sure if the rules are still in play.", + "npc_background": "BG_survival_story_SPORTS", "points": 5, "skills": [ { "level": 6, "name": "melee" }, @@ -6075,6 +6226,7 @@ "id": "politician", "name": "Career Politician", "description": "You've spent your life appealing to the people, persuading many and promising much throughout your time in office. Now that your voting base wants to eat you alive, winning hearts and minds just got that much harder.", + "npc_background": "BG_survival_story_WORKER_PUBLIC", "points": 2, "skills": [ { "level": 8, "name": "speech" } ], "traits": [ "LIAR" ], @@ -6105,6 +6257,7 @@ "id": "rancher", "name": "Rancher", "description": "Taking care of cows, horses, and other animals is your passion, but the ways things are going, this isn't going to be just another day at the ranch.", + "npc_background": "BG_survival_story_RURAL", "points": 2, "skills": [ { "level": 5, "name": "survival" } ], "proficiencies": [ "prof_gross_anatomy", "prof_wp_ungulate" ], @@ -6140,6 +6293,7 @@ "id": "roadie", "name": "Roadie", "description": "You've always worked just outside of the limelight, carrying and fixing the equipment and ensuring that the performers got what they needed. The show must go on.", + "npc_background": "BG_survival_story_WORKER_COMMERCIAL", "points": 2, "skills": [ { "level": 3, "name": "fabrication" }, @@ -6175,6 +6329,7 @@ "id": "musician", "name": "Musician", "description": "You nailed your solo, but the audience erupted into screams instead of applause. You weren't able to grab much during the panic, but at least you have your loaded six string on your back.", + "npc_background": "BG_survival_story_WORKER_SELFEMP", "points": 1, "skills": [ { "level": 5, "name": "speech" } ], "items": { @@ -6209,6 +6364,7 @@ "id": "kit_survivor", "name": "Kitted Survivor", "description": "You saw a sign at the local mall advertising a discount on survival kits. You bought one, more for show than for actual use. Now it's all you have.", + "npc_background": "BG_survival_story_EVACUEE", "points": 1, "items": { "both": { @@ -6233,6 +6389,7 @@ "id": "gunslinger", "name": "Wild West Gunslinger", "description": "You made your living on Wild West exhibitions and shows, impressing tourists with your displays of marksmanship. But that world has ended, so you took your trusty six-shooter and wandered into a world where it's always high noon.", + "npc_background": "BG_survival_story_WORKER_SELFEMP", "points": 4, "proficiencies": [ "prof_gunsmithing_basic", "prof_gun_cleaning" ], "skills": [ @@ -6277,6 +6434,7 @@ "id": "frat", "name": { "male": "Frat Boy", "female": "Sorority Girl" }, "description": "You were living the high life, spending your parents' money without a care in the world. At one of your usual crazy parties, the guests became hungry for more than drugs and booze, but you still have a chance to use the last symbol of your luxurious life - your sports car - and get far away.", + "npc_background": "BG_survival_story_ECCENTRIC", "points": 2, "proficiencies": [ "prof_driver" ], "skills": [ { "level": 3, "name": "driving" }, { "level": 2, "name": "speech" } ], @@ -6329,6 +6487,7 @@ "name": "Military Marksman", "requirement": "achievement_reach_military_bunker", "description": "You like to think of yourself as a sniper, but really you're just infantry with a bigger gun. That said, a big gun is a definite advantage now.", + "npc_background": "BG_survival_story_SOLDIER", "points": 5, "proficiencies": [ "prof_gunsmithing_basic", @@ -6386,6 +6545,7 @@ "name": "Military Automatic Rifleman", "requirement": "achievement_reach_military_bunker", "description": "You were trusted with a big-ass, belt-fed machine gun and plenty of ammo to lay down suppressing fire for your team. Now that it's going to be much harder to resupply, you should probably be more selective with the ol' spray-and-pray.", + "npc_background": "BG_survival_story_SOLDIER", "points": 5, "proficiencies": [ "prof_gunsmithing_basic", @@ -6445,6 +6605,7 @@ "name": "Military Grenadier", "requirement": "achievement_reach_military_bunker", "description": "There's no kill like overkill, and not many people in this world can boast that they have a grenade launcher and know how to use it. Just try not to blow yourself up, that would be really embarrassing.", + "npc_background": "BG_survival_story_SOLDIER", "points": 4, "proficiencies": [ "prof_gunsmithing_basic", @@ -6512,6 +6673,7 @@ "name": "Military Breacher", "requirement": "achievement_reach_military_bunker", "description": "Doors and windows everywhere dare not speak your name. You're going to be breaking into buildings for supplies rather than combat operations now, but the principle is about the same.", + "npc_background": "BG_survival_story_SOLDIER", "points": 5, "proficiencies": [ "prof_gunsmithing_basic", @@ -6573,6 +6735,7 @@ "name": "Military Sniper", "requirement": "achievement_reach_military_bunker", "description": "You're a crack shot with a rifle, and the farther you can stay away from zombies, the better. The only thing stopping you is limited ammo, so you should try to find a place to restock sooner or later.", + "npc_background": "BG_survival_story_SOLDIER", "points": 5, "proficiencies": [ "prof_gunsmithing_basic", @@ -6636,6 +6799,7 @@ "name": "Military Hacker", "requirement": "achievement_reach_military_bunker", "description": "'Hacker' is a silly pop-culture name, popularized by Hollywood and people with little to no knowledge of what your job entails. You prefer 'Electronic Warfare Specialist,' though nobody's really left to make the distinction.", + "npc_background": "BG_survival_story_SOLDIER", "points": 7, "proficiencies": [ "prof_gunsmithing_basic", @@ -6698,6 +6862,7 @@ "id": "mil_undercover", "name": "Undercover Operative", "description": "You've been tailing your target for months, and now he's a zombie. So much for that lead. Command isn't responding to your calls for an evac, so you'll have to make do with what you have on you.", + "npc_background": "BG_survival_story_SOLDIER", "points": 5, "proficiencies": [ "prof_gunsmithing_basic", "prof_gun_cleaning", "prof_knives_familiar", "prof_auto_pistols_familiar" ], "skills": [ @@ -6744,6 +6909,7 @@ "name": "Military Pilot", "requirement": "achievement_reach_military_bunker", "description": "You got to see things fall apart from the sky, transporting soldiers and survivors from one holdout to the next. You knew it was only a matter of time before the horrors patrolling the skies shot you down.", + "npc_background": "BG_survival_story_SOLDIER", "points": 5, "skills": [ { "level": 7, "name": "driving" }, @@ -6792,6 +6958,7 @@ "id": "emt", "name": "EMT", "description": "You were responding to a call with your partner before you got separated. Now all you have is your trusty ambulance, ready to transport patients through the apocalypse.", + "npc_background": "BG_survival_story_WORKER_MEDICAL", "points": 3, "skills": [ { "level": 5, "name": "firstaid" }, { "level": 4, "name": "driving" }, { "level": 2, "name": "mechanics" } ], "proficiencies": [ "prof_wound_care", "prof_intro_biology", "prof_physiology", "prof_burn_care", "prof_driver", "prof_gross_anatomy" ], @@ -6823,6 +6990,7 @@ "id": "paramedic", "name": "Paramedic", "description": "You were separated from your partner while out on a call. You managed to hang onto some medical supplies, but it's looking like the only life that needs saving now is yours.", + "npc_background": "BG_survival_story_WORKER_MEDICAL", "points": 3, "skills": [ { "level": 6, "name": "firstaid" }, { "level": 3, "name": "driving" }, { "level": 1, "name": "mechanics" } ], "proficiencies": [ @@ -6867,6 +7035,7 @@ "name": "Combat Medic", "requirement": "achievement_reach_military_bunker", "description": "You were on the front lines when everything happened, patching up the wounded and providing support. But they wouldn't stop coming. Now you're on your own.", + "npc_background": "BG_survival_story_SOLDIER", "points": 5, "skills": [ { "level": 6, "name": "firstaid" }, @@ -6943,6 +7112,7 @@ "id": "relief_volunteer", "name": "Relief Volunteer", "description": "You were a member of a nonprofit organization dedicated to helping out where help was needed. When the riots happened, you were eager to lend a hand. But you had to cut your plans short when everyone was less interested in handouts, and more interested in eating you.", + "npc_background": "BG_survival_story_EVACUEE", "points": 1, "skills": [ { "level": 3, "name": "firstaid" }, { "level": 1, "name": "speech" } ], "items": { @@ -6974,6 +7144,7 @@ "id": "super_biker", "name": { "male": "Speed King", "female": "Speed Queen" }, "description": "You used to rule the roads before they were filled with wrecks, undead, and unspeakable horrors. At least there's no speed limits in the apocalypse!", + "npc_background": "BG_survival_story_SPORTS", "points": 4, "proficiencies": [ "prof_driver" ], "skills": [ { "level": 8, "name": "driving" } ], @@ -7000,6 +7171,7 @@ "id": "hazmat_unit", "name": "Hazmat Unit", "description": "You were deployed to autopsy one of the rioters showing feral behavior before being put down. When they got back up, you knew this was out of your pay grade.", + "npc_background": "BG_survival_story_WORKER_FIREFIGHTER", "points": 4, "skills": [ { "level": 6, "name": "firstaid" } ], "proficiencies": [ @@ -7036,6 +7208,7 @@ "id": "local_drug_dealer", "name": "Drug Dealer", "description": "You were about to make your biggest sale yet, but when you met the buyer he tried to bite you. To top it off, it seems that this wasn't some sort of bad trip, as the whole town tried going for your throat too.", + "npc_background": "BG_survival_story_CRIMINAL", "points": 2, "skills": [ { "level": 4, "name": "speech" }, @@ -7070,6 +7243,7 @@ "id": "mafia_boss", "name": "Mafia Boss", "description": "Born into poverty, you joined one of the organized crime families to make a living. There, you quickly made it to the top and became the boss. The government was building a RICO case against you, but doomsday arrived first. Your crew is gone, but your past life has prepared you for a world where violence is common currency.", + "npc_background": "BG_survival_story_CRIMINAL", "points": 5, "skills": [ { "level": 6, "name": "speech" }, @@ -7112,6 +7286,7 @@ "id": "paranormal_investigator", "name": "Paranormal Investigator", "description": "You were dismissed from your position as a parapsychology professor at the local university and started your own business as a paranormal investigator. Your former colleagues didn't approve of your research, but it looks like it's paying off now.", + "npc_background": "BG_survival_story_ECCENTRIC", "points": 1, "skills": [ { "level": 3, "name": "electronics" }, { "level": 2, "name": "chemistry" }, { "level": 2, "name": "speech" } ], "traits": [ "SPIRITUAL" ], @@ -7150,6 +7325,7 @@ "id": "birder", "name": "Bird Watcher", "description": "You were at your favorite park looking at the robins when the Cataclysm struck. Now all you have are your binoculars and a lot of trivia about local birds to share with any survivors you may find.", + "npc_background": "BG_survival_story_EVACUEE", "points": 1, "skills": [ { "level": 3, "name": "survival" } ], "items": { @@ -7175,6 +7351,7 @@ "id": "portal_traveler", "name": "Portal Traveler", "description": "You were abducted from your home, taken hostage, and used as a test subject in a lab. For the last test, you were dressed in strange clothes and put in a room where you started to feel… different. You lost consciousness and woke up somewhere unfamiliar.", + "npc_background": "BG_survival_story_EVACUEE", "points": 1, "items": { "both": { @@ -7207,6 +7384,7 @@ "id": "ninja", "name": { "male": "Ninja", "female": "Kunoichi" }, "description": "You are obsessed with the techniques and aesthetics of the ninja, so you practiced your movements, dressed all in black, and spent big bucks to acquire some tools of the trade. Some may question your historical authenticity, but you're perfectly happy living out your fantasy regardless.", + "npc_background": "BG_survival_story_SPORTS", "points": 5, "skills": [ { "level": 4, "name": "melee" }, @@ -7242,6 +7420,7 @@ "id": "cheerleader", "name": "Cheerleader", "description": "Your last cheerleader routine ended abruptly after your partners switched sides to the undead team. Let's hope your quick reflexes and flexibility help you to find new members for the squad.", + "npc_background": "BG_survival_story_SPORTS", "points": 1, "skills": [ { "level": 3, "name": "dodge" }, { "level": 3, "name": "swimming" }, { "level": 3, "name": "speech" } ], "items": { @@ -7265,6 +7444,7 @@ "id": "patriot", "name": "Patriot", "description": "You are a true American patriot, dressed with star-spangled clothing from head to toe. The government has fallen, but the nation lives on with its people.", + "npc_background": "BG_survival_story_ECCENTRIC", "points": -1, "items": { "both": { @@ -7300,6 +7480,7 @@ "id": "prepped_patriot", "name": "Prepped Patriot", "description": "Does the American dream still exist? Well, recent events have put that to the test. Does it still proudly live in your beating heart? Yes. Yes, it does. A patriot to the bitter end, you've readied yourself to go toe to toe with the Cataclysm that would seek to do harm to your darling USA. That is to say, you grabbed your gun… and nothing more. God bless America, soldier.", + "npc_background": "BG_survival_story_ECCENTRIC", "points": 2, "skills": [ { "level": 3, "name": "gun" }, @@ -7330,6 +7511,7 @@ "id": "cowboy", "name": "Cowboy", "description": "You liked to spend your days taking care of the horses and cows, searching the perimeter of the ranch on your steed and looking out for anything suspicious, that's why you managed to escape in time when shit hit the fan.", + "npc_background": "BG_survival_story_RURAL", "points": 3, "proficiencies": [ "prof_gunsmithing_basic", "prof_gun_cleaning" ], "skills": [ @@ -7375,6 +7557,7 @@ "id": "tourist_swimmer", "name": "Tourist Swimmer", "description": "You were looking forward to a nice, relaxing day at the beach. You had to run when some lunatics tried to rip your head off and play beach volleyball with it, but at least you managed to grab your bag on the way out.", + "npc_background": "BG_survival_story_TOURIST", "points": 0, "skills": [ { "level": 2, "name": "swimming" } ], "items": { @@ -7412,6 +7595,7 @@ "id": "professional_swimmer", "name": "Professional Swimmer", "description": "After much practice you were sure the next competition would be your big break, but your rivals started killing each other and you had to escape with only your competition gear on you. Will your athleticism alone be enough to keep you alive?", + "npc_background": "BG_survival_story_SPORTS", "points": 2, "skills": [ { "level": 6, "name": "swimming" }, { "level": 2, "name": "dodge" } ], "traits": [ "OUTDOORSMAN" ], @@ -7427,6 +7611,7 @@ "id": "surfer", "name": "Surfer", "description": "You went to ride the waves, but the waves ended up riding you instead when a putrid hand appeared from underwater and grabbed you by the ankle. You had to ditch your surfboard in favor of a kickboard, and now you'll fight every day to stay ahead of the wave of the undead.", + "npc_background": "BG_survival_story_SPORTS", "points": 1, "flags": [ "NO_BONUS_ITEMS" ], "skills": [ { "level": 4, "name": "dodge" }, { "level": 4, "name": "swimming" } ], @@ -7442,6 +7627,7 @@ "id": "lifeguard", "name": "Lifeguard", "description": "Your job was to safeguard the lives of everyone at the beach, but when the swimmers started drowning each other, you knew the situation was out of your hands.", + "npc_background": "BG_survival_story_WORKER_COMMERCIAL", "points": 2, "skills": [ { "level": 4, "name": "firstaid" }, { "level": 4, "name": "swimming" } ], "traits": [ "OUTDOORSMAN" ], @@ -7459,6 +7645,7 @@ "id": "diver", "name": "Diver", "description": "You were exploring below the waves close to shore when you noticed something weird on the nearby beach, you decided to swim away when you heard the screams.", + "npc_background": "BG_survival_story_SPORTS", "points": 2, "skills": [ { "level": 5, "name": "swimming" } ], "traits": [ "OUTDOORSMAN" ], @@ -7481,6 +7668,7 @@ "type": "profession", "name": "Ship Captain", "description": "You were the captain of your small ship, making a living by ferrying divers and tourists across the waves. The last excursion went bad after your passengers tried to mutiny, but you managed to escape. Will you ever sail the open ocean again?", + "npc_background": "BG_survival_story_WORKER_SELFEMP", "points": 3, "proficiencies": [ "prof_boat_pilot" ], "skills": [ { "level": 4, "name": "driving" }, { "level": 3, "name": "swimming" } ], @@ -7520,6 +7708,7 @@ "name": { "male": "Hitman", "female": "Hitwoman" }, "requirement": "achievement_kill_100_monsters", "description": "You were the best undercover agent they had, with a mission so vital that you had to take it even with the riots going on. Your target seems to have turned feral as well as your contact, you are all alone now.", + "npc_background": "BG_survival_story_CRIMINAL", "points": 6, "skills": [ { "level": 5, "name": "gun" }, @@ -7594,6 +7783,7 @@ "name": "Assassin", "requirement": "achievement_kill_100_monsters", "description": "You were the best undercover agent they had, with a mission so vital that you had to take it even with the riots going on. Your target seems to have turned feral as well as your contact, you are all alone now.", + "npc_background": "BG_survival_story_CRIMINAL", "points": 6, "skills": [ { "level": 6, "name": "throw" }, @@ -7662,6 +7852,7 @@ "id": "old_vet", "name": "Old Veteran", "description": "You've been through hell once before. Hopefully those weekend range trips have kept your skills sharp.", + "npc_background": "BG_survival_story_RETIRED", "points": 4, "skills": [ { "level": 3, "name": "gun" }, @@ -7701,6 +7892,7 @@ "id": "urbex", "name": "Urban Explorer", "description": "You've always admired the beauty of urban desolation, and were ready for your next excursion when the end of the world hit. You suppose that pretty much every building could be considered abandoned now.", + "npc_background": "BG_survival_story_TOURIST", "points": 2, "skills": [ { "level": 4, "name": "traps" }, { "level": 3, "name": "swimming" } ], "proficiencies": [ "prof_lockpicking" ], @@ -7735,6 +7927,7 @@ "id": "officeworker", "name": "Office Worker", "description": "You felt years of your life being sapped away, slaving at your computer as you subsisted on a daily pot of coffee, microwave burritos and an endless supply of crumpled paper to toss. Perhaps the Cataclysm is a refreshing change of pace…", + "npc_background": "BG_survival_story_WORKER_COMMERCIAL", "points": 0, "skills": [ { "level": 2, "name": "computer" }, @@ -7767,6 +7960,7 @@ "id": "rv_hunter", "name": "RV Hunter", "description": "Ever since you were a child you loved hunting and traveling; so when you scraped enough money, you bought yourself an old RV, a gun, and hit the road. You've been all over the country, hunting for good game. Unfortunately the country is all over this time, and even more unfortunately you've lost your ol' reliable in the chaos. Now you gotta find a new reliable.", + "npc_background": "BG_survival_story_RURAL", "points": 4, "proficiencies": [ "prof_driver", @@ -7812,6 +8006,7 @@ "id": "heist_driver", "name": "Heist Driver", "description": "For as long as you can remember, you have lived a double life: a normal driver by the day and a heist driver in the night. Now there are no cops and no law, but even after the Cataclysm, you drive.", + "npc_background": "BG_survival_story_CRIMINAL", "points": 4, "proficiencies": [ "prof_driver", "prof_athlete_basic" ], "skills": [ { "level": 6, "name": "driving" }, { "level": 4, "name": "mechanics" }, { "level": 1, "name": "melee" } ], @@ -7839,6 +8034,7 @@ "id": "explosive_ordnance_disposal", "name": "Explosive Ordnance Disposal Technician", "description": "Ever since you were a child you were fascinated with explosives and all things that go boom. As soon as you turned 18 you joined the army to become an EOD technician. While out on a call about a potential explosive in the neighboring county, your team was overrun by hordes of the undead. You are alone, with nothing but your precious training, gear and love of explosives.", + "npc_background": "BG_survival_story_SOLDIER", "points": 5, "proficiencies": [ "prof_elec_circuits", @@ -7893,6 +8089,7 @@ "id": "mma_fighter", "name": "Mixed Martial Artist", "description": "You've spent plenty of time training to become the next big thing. But now it looks like you will be fighting your life from now on. At least that training won't go to waste!", + "npc_background": "BG_survival_story_SPORTS", "points": 5, "flags": [ "NO_BONUS_ITEMS" ], "skills": [ { "level": 3, "name": "melee" }, { "level": 3, "name": "unarmed" } ], @@ -7920,6 +8117,7 @@ "id": "FBI", "name": "FBI Special Agent", "description": "As a member of the FBI, you dealt with crime that crossed state lines. You had gotten the go-ahead to make the biggest bust of your career; before you kicked down the door, you yelled \"FBI, open up!\" and then the sky broke open.", + "npc_background": "BG_survival_story_SOLDIER", "points": 4, "proficiencies": [ "prof_gunsmithing_basic", "prof_spotting", "prof_gun_cleaning", "prof_auto_pistols_familiar", "prof_batons_familiar" ], "skills": [ diff --git a/src/character.cpp b/src/character.cpp index 0e816011f35f3..ea755549a6984 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -3472,6 +3472,13 @@ std::vector> Character::get_overlay_ids_when return rval; } +void Character::zero_all_skills() +{ + for( Skill &skill : Skill::skills ) { + set_skill_level( skill.ident(), 0 ); + } +} + SkillLevelMap Character::get_all_skills() const { SkillLevelMap skills = *_skills; diff --git a/src/character.h b/src/character.h index bacef0291bab6..c9af7543a3105 100644 --- a/src/character.h +++ b/src/character.h @@ -589,6 +589,7 @@ class Character : public Creature, public visitable void randomize_hobbies(); void add_random_hobby( std::vector &choices ); + // Relative direction of a grab, add to posx, posy to get the coordinates of the grabbed thing. tripoint_rel_ms grab_point; @@ -2424,6 +2425,9 @@ class Character : public Creature, public visitable std::vector> get_overlay_ids_when_override_look() const; // --------------- Skill Stuff --------------- + + //sets all skills to 0 so that they're guaranteed to be in the map + void zero_all_skills(); float get_skill_level( const skill_id &ident ) const; float get_skill_level( const skill_id &ident, const item &context ) const; int get_knowledge_level( const skill_id &ident ) const; diff --git a/src/newcharacter.cpp b/src/newcharacter.cpp index 1542c1544b797..a5832d14d3d26 100644 --- a/src/newcharacter.cpp +++ b/src/newcharacter.cpp @@ -455,6 +455,7 @@ void Character::randomize( const bool random_scenario, bool play_now ) } prof = get_scenario()->weighted_random_profession(); + zero_all_skills(); init_age = rng( this->prof->age_lower, this->prof->age_upper ); starting_city = std::nullopt; world_origin = std::nullopt; @@ -467,6 +468,10 @@ void Character::randomize( const bool random_scenario, bool play_now ) set_body(); randomize_hobbies(); + const trait_id background = prof->pick_background(); + if( !background.is_empty() ) { + set_mutation( background ); + } int num_gtraits = 0; int num_btraits = 0; @@ -597,7 +602,10 @@ void Character::randomize( const bool random_scenario, bool play_now ) if( is_npc() ) { add_profession_items(); + as_npc()->randomize_personality(); + as_npc()->generate_personality_traits(); initialize(); + as_npc()->catchup_skills(); } } diff --git a/src/npc.cpp b/src/npc.cpp index 29a5458cc3632..1299ab04f3d9f 100644 --- a/src/npc.cpp +++ b/src/npc.cpp @@ -559,18 +559,12 @@ void npc::randomize( const npc_class_id &type, const npc_template_id &tem_id ) } if( type.is_null() || type == NC_NONE ) { Character::randomize( false ); - catchup_skills(); return; } set_wielded_item( item( "null", calendar::turn_zero ) ); inv->clear(); - personality.aggression = rng( NPC_PERSONALITY_MIN, NPC_PERSONALITY_MAX ); - personality.bravery = rng( -3, NPC_PERSONALITY_MAX ); - personality.collector = rng( -1, NPC_PERSONALITY_MAX ); - // Normal distribution. Mean = 0, stddev = 3, clamp at NPC_PERSONALITY_MIN and NPC_PERSONALITY_MAX. Rounded to return integer value. - personality.altruism = std::round( std::clamp( normal_roll( 0, 3 ), - static_cast( NPC_PERSONALITY_MIN ), static_cast( NPC_PERSONALITY_MAX ) ) ); + randomize_personality(); moves = 100; mission = NPC_MISSION_NULL; male = one_in( 2 ); @@ -754,6 +748,16 @@ void npc::generate_personality_traits() } } +void npc::randomize_personality() +{ + personality.aggression = rng( NPC_PERSONALITY_MIN, NPC_PERSONALITY_MAX ); + personality.bravery = rng( -3, NPC_PERSONALITY_MAX ); + personality.collector = rng( -1, NPC_PERSONALITY_MAX ); + // Normal distribution. Mean = 0, stddev = 3, clamp at NPC_PERSONALITY_MIN and NPC_PERSONALITY_MAX. Rounded to return integer value. + personality.altruism = std::round( std::clamp( normal_roll( 0, 3 ), + static_cast( NPC_PERSONALITY_MIN ), static_cast( NPC_PERSONALITY_MAX ) ) ); +} + void npc::learn_ma_styles_from_traits() { for( const trait_id &iter : get_mutations() ) { diff --git a/src/npc.h b/src/npc.h index ad8f56b7c2d00..eec7d6a9f4b21 100644 --- a/src/npc.h +++ b/src/npc.h @@ -787,6 +787,7 @@ class npc : public Character void apply_ownership_to_inv(); void clear_personality_traits(); void generate_personality_traits(); + void randomize_personality(); void learn_ma_styles_from_traits(); // Faction version number int get_faction_ver() const; diff --git a/src/profession.cpp b/src/profession.cpp index 887b3b3d02537..e15239355f901 100644 --- a/src/profession.cpp +++ b/src/profession.cpp @@ -29,6 +29,7 @@ #include "translations.h" #include "type_id.h" #include "visitable.h" +#include static const achievement_id achievement_achievement_arcade_mode( "achievement_arcade_mode" ); @@ -247,6 +248,12 @@ void profession::load( const JsonObject &jo, const std::string_view ) _description_male = to_translation( "prof_desc_male", desc_male ); _description_female = to_translation( "prof_desc_female", desc_female ); } + std::string background_group_id; + optional( jo, was_loaded, "npc_background", background_group_id, "" ); + if( !background_group_id.empty() ) { + _starting_npc_background = trait_group::Trait_group_tag( background_group_id ); + } + optional( jo, was_loaded, "age_lower", age_lower, 16 ); optional( jo, was_loaded, "age_upper", age_upper, 55 ); @@ -650,6 +657,15 @@ std::set profession::get_forbidden_traits() const return _forbidden_traits; } +trait_id profession::pick_background() const +{ + const trait_group::Trait_list &background = trait_group::traits_from( _starting_npc_background ); + if( !background.empty() ) { + return background.front().trait; + } + return trait_id(); +} + profession::StartingSkillList profession::skills() const { return _starting_skills; diff --git a/src/profession.h b/src/profession.h index c4f387c80ad06..7f1e70baa84d9 100644 --- a/src/profession.h +++ b/src/profession.h @@ -76,6 +76,7 @@ class profession std::vector _starting_martialarts_choices; std::set _forbidden_traits; std::vector _starting_pets; + trait_group::Trait_group_tag _starting_npc_background; std::set> _hobby_exclusion; bool hobbies_whitelist = true; vproto_id _starting_vehicle = vproto_id::NULL_ID(); @@ -164,6 +165,7 @@ class profession bool is_forbidden_trait( const trait_id &trait ) const; std::vector get_locked_traits() const; std::set get_forbidden_traits() const; + trait_id pick_background() const; bool is_hobby() const; bool is_blacklisted() const; From 566cefc59f416741a9ed9fb14eaebf2acb88b350 Mon Sep 17 00:00:00 2001 From: ShnitzelX2 <65314588+ShnitzelX2@users.noreply.github.com> Date: Sat, 12 Oct 2024 00:08:45 -0400 Subject: [PATCH 3/5] fixed some trait groups, accounted for scenario -improved JSON read of `npc_background`, which should resolve failed tests --- data/json/npcs/BG_trait_groups.json | 7 +++++++ data/json/professions.json | 12 ++++++------ doc/JSON_INFO.md | 1 + src/character.cpp | 12 ++++++------ src/newcharacter.cpp | 5 +++-- src/profession.cpp | 15 ++++++++++----- 6 files changed, 33 insertions(+), 19 deletions(-) diff --git a/data/json/npcs/BG_trait_groups.json b/data/json/npcs/BG_trait_groups.json index db32e26a4068b..0946841141a3a 100644 --- a/data/json/npcs/BG_trait_groups.json +++ b/data/json/npcs/BG_trait_groups.json @@ -264,6 +264,13 @@ "subtype": "distribution", "traits": [ { "group": "BG_survival_story_UNIVERSAL" } ] }, + { + "//": "This group is for NPCs that were prisoners before the Cataclysm.", + "type": "trait_group", + "id": "BG_survival_story_PRISONER", + "subtype": "distribution", + "traits": [ { "trait": "BGSS_Prisoner_1" } ] + }, { "//": "This group is for Cyborgs rescued down in the Lab.", "type": "trait_group", diff --git a/data/json/professions.json b/data/json/professions.json index 057cd82d6ca1f..542500ab43970 100644 --- a/data/json/professions.json +++ b/data/json/professions.json @@ -2173,7 +2173,7 @@ "id": "medic", "name": "Medical Resident", "description": "Fresh out of med school, you've got little in the way of practical experience and just a handful of first-aid supplies. You just hope it will be enough if 'physician, heal thyself' turns out to be more literal than you expected.", - "npc_background": "BG_survival_story_WORKER_MEDICAL", + "npc_background": "BG_survival_story_MEDICAL", "points": 2, "skills": [ { "level": 5, "name": "firstaid" } ], "proficiencies": [ @@ -2218,7 +2218,7 @@ "name": "Doctor", "requirement": "achievement_reach_hospital", "description": "You were a patient-facing doctor practicing general or specialized medicine. While your bedside manner might not get you far in this new world, your medical skills will certainly help.", - "npc_background": "BG_survival_story_WORKER_MEDICAL", + "npc_background": "BG_survival_story_MEDICAL", "points": 5, "skills": [ { "level": 7, "name": "firstaid" }, { "level": 3, "name": "speech" } ], "proficiencies": [ @@ -2269,7 +2269,7 @@ "name": "Pharmacist", "requirement": "achievement_reach_hospital", "description": "You were a pharmacist working in a community pharmacy. No simple pill-pusher, you have a plethora of knowledge of drug preparation, biochemistry, and biology. With your trusty mortar and pestle, you hope to grind the undead to a pulp.", - "npc_background": "BG_survival_story_WORKER_MEDICAL", + "npc_background": "BG_survival_story_MEDICAL", "points": 5, "skills": [ { "level": 6, "name": "firstaid" }, { "level": 1, "name": "speech" } ], "proficiencies": [ "prof_intro_biology", "prof_intro_chemistry", "prof_organic_chemistry", "prof_biochemistry", "prof_physiology" ], @@ -2466,7 +2466,7 @@ "name": "Nursing Assistant", "//": "They don't have the doctor's passive bonus to surgery. Nursing assistants aren't required to hold a doctorate.", "description": "You went on providing in-home care for the elderly even as the whole world fell apart around you. You can only pray that you don't see your former clients among the walking dead…", - "npc_background": "BG_survival_story_WORKER_MEDICAL", + "npc_background": "BG_survival_story_MEDICAL", "points": 1, "skills": [ { "level": 3, "name": "firstaid" }, { "level": 3, "name": "cooking" }, { "level": 3, "name": "speech" } ], "proficiencies": [ "prof_wound_care" ], @@ -6958,7 +6958,7 @@ "id": "emt", "name": "EMT", "description": "You were responding to a call with your partner before you got separated. Now all you have is your trusty ambulance, ready to transport patients through the apocalypse.", - "npc_background": "BG_survival_story_WORKER_MEDICAL", + "npc_background": "BG_survival_story_MEDICAL", "points": 3, "skills": [ { "level": 5, "name": "firstaid" }, { "level": 4, "name": "driving" }, { "level": 2, "name": "mechanics" } ], "proficiencies": [ "prof_wound_care", "prof_intro_biology", "prof_physiology", "prof_burn_care", "prof_driver", "prof_gross_anatomy" ], @@ -6990,7 +6990,7 @@ "id": "paramedic", "name": "Paramedic", "description": "You were separated from your partner while out on a call. You managed to hang onto some medical supplies, but it's looking like the only life that needs saving now is yours.", - "npc_background": "BG_survival_story_WORKER_MEDICAL", + "npc_background": "BG_survival_story_MEDICAL", "points": 3, "skills": [ { "level": 6, "name": "firstaid" }, { "level": 3, "name": "driving" }, { "level": 1, "name": "mechanics" } ], "proficiencies": [ diff --git a/doc/JSON_INFO.md b/doc/JSON_INFO.md index be446850aa798..49964003d279a 100644 --- a/doc/JSON_INFO.md +++ b/doc/JSON_INFO.md @@ -1990,6 +1990,7 @@ The following properties (mandatory, except if noted otherwise) are supported: "name": { "male": "Groom", "female": "Bride" }, // String, either a single gender neutral (i.e. "Survivor") or object with members "male" and "female" "description": "This is an example profession.", // In-game description "points": 0, // Point cost of profession. Positive values cost points and negative values grant points. Has no effect as of 0.G + "npc_background": "BG_survival_story_LAB", // (optional) BG_trait_group ID, provides list of background stories. (see BG_trait_groups.json) "addictions": [ { "intensity": 10, "type": "nicotine" } ], // (optional) Array of addictions. Requires "type" as the string ID of the addiction (see JSON_FLAGS.md) and "intensity" "skills": [ { "name": "archery", "level": 2 } ], // (optional) Array of starting skills. Requires "name" as the string ID of the skill (see skills.json) and "level", which is a value added to the skill level after character creation "missions": [ "MISSION_LAST_DELIVERY" ], // (optional) Array of starting mission IDs diff --git a/src/character.cpp b/src/character.cpp index ea755549a6984..e5ee84f1d774c 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -397,12 +397,6 @@ static const species_id species_HUMAN( "HUMAN" ); static const start_location_id start_location_sloc_shelter_a( "sloc_shelter_a" ); -static const std::string type_hair_color( "hair_color" ); -static const std::string type_hair_style( "hair_style" ); -static const std::string type_skin_tone( "skin_tone" ); -static const std::string type_facial_hair( "facial_hair" ); -static const std::string type_eye_color( "eye_color" ); - static const trait_id trait_ADRENALINE( "ADRENALINE" ); static const trait_id trait_ANTENNAE( "ANTENNAE" ); static const trait_id trait_BADBACK( "BADBACK" ); @@ -491,6 +485,12 @@ static const vitamin_id vitamin_iron( "iron" ); static const std::set ferric = { material_iron, material_steel, material_budget_steel, material_ch_steel, material_hc_steel, material_lc_steel, material_mc_steel, material_qt_steel }; +static const std::string type_hair_color( "hair_color" ); +static const std::string type_hair_style( "hair_style" ); +static const std::string type_skin_tone( "skin_tone" ); +static const std::string type_facial_hair( "facial_hair" ); +static const std::string type_eye_color( "eye_color" ); + namespace io { diff --git a/src/newcharacter.cpp b/src/newcharacter.cpp index a5832d14d3d26..f270b158dd464 100644 --- a/src/newcharacter.cpp +++ b/src/newcharacter.cpp @@ -423,7 +423,7 @@ void Character::randomize( const bool random_scenario, bool play_now ) const int max_trait_points = get_option( "MAX_TRAIT_POINTS" ); // Reset everything to the defaults to have a clean state. if( is_avatar() ) { - *this = avatar(); + *this->as_avatar() = avatar(); } bool gender_selection = one_in( 2 ); @@ -454,7 +454,8 @@ void Character::randomize( const bool random_scenario, bool play_now ) } } - prof = get_scenario()->weighted_random_profession(); + const scenario *scenario_from = is_avatar() ? get_scenario() : scenario::generic(); + prof = scenario_from->weighted_random_profession(); zero_all_skills(); init_age = rng( this->prof->age_lower, this->prof->age_upper ); starting_city = std::nullopt; diff --git a/src/profession.cpp b/src/profession.cpp index e15239355f901..4c7182dade5c8 100644 --- a/src/profession.cpp +++ b/src/profession.cpp @@ -30,8 +30,11 @@ #include "type_id.h" #include "visitable.h" #include +#include static const achievement_id achievement_achievement_arcade_mode( "achievement_arcade_mode" ); +static const trait_group::Trait_group_tag +Trait_group_BG_survival_story_UNIVERSAL( "BG_survival_story_UNIVERSAL" ); namespace { @@ -140,6 +143,7 @@ profession::profession() _name_female( no_translation( "null" ) ), _description_male( no_translation( "null" ) ), _description_female( no_translation( "null" ) ) + { } @@ -249,11 +253,8 @@ void profession::load( const JsonObject &jo, const std::string_view ) _description_female = to_translation( "prof_desc_female", desc_female ); } std::string background_group_id; - optional( jo, was_loaded, "npc_background", background_group_id, "" ); - if( !background_group_id.empty() ) { - _starting_npc_background = trait_group::Trait_group_tag( background_group_id ); - } - + optional( jo, was_loaded, "npc_background", _starting_npc_background, + Trait_group_BG_survival_story_UNIVERSAL ); optional( jo, was_loaded, "age_lower", age_lower, 16 ); optional( jo, was_loaded, "age_upper", age_upper, 55 ); @@ -659,6 +660,10 @@ std::set profession::get_forbidden_traits() const trait_id profession::pick_background() const { + if( mutation_branch::get_group( _starting_npc_background ) == nullptr ) { + debugmsg( "invalid trait group ID for profession: " + id.str() ); + return trait_id(); + } const trait_group::Trait_list &background = trait_group::traits_from( _starting_npc_background ); if( !background.empty() ) { return background.front().trait; From e5d41be948946093ae22ac4d201c458beba55f20 Mon Sep 17 00:00:00 2001 From: ShnitzelX2 <65314588+ShnitzelX2@users.noreply.github.com> Date: Sun, 13 Oct 2024 16:06:06 -0400 Subject: [PATCH 4/5] attempt to fix weird "npc_prefers_guns" test failure the thug spawned in "npc_prefers_guns" started with a gun when it shouldn't have, but thugs spawned in with the debug menu didn't spawn with guns, which makes me think that spawn_npc() was having issues? --- tests/player_helpers.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/player_helpers.cpp b/tests/player_helpers.cpp index 91719e5b36356..695ae72a772bf 100644 --- a/tests/player_helpers.cpp +++ b/tests/player_helpers.cpp @@ -230,8 +230,8 @@ void process_activity( Character &dummy ) npc &spawn_npc( const point_bub_ms &p, const std::string &npc_class ) { - const string_id test_guy( npc_class ); - const character_id model_id = get_map().place_npc( p, test_guy ); + const npc_template_id npc_template = npc_template_id( npc_class ); + const character_id model_id = get_map().place_npc( p, npc_template ); g->load_npcs(); npc *guy = g->find_npc( model_id ); From 21d13dbe19de824dc60b550c3b2715f9edbddca2 Mon Sep 17 00:00:00 2001 From: ShnitzelX2 <65314588+ShnitzelX2@users.noreply.github.com> Date: Wed, 16 Oct 2024 17:04:42 -0400 Subject: [PATCH 5/5] fix "npc-movement" infinite loop -the removed code section was meant to generate an NPC without foot protection, which is better done NOT in a potentially infinite loop that gobbles up CI time -NPCs aren't meant to be randomized more than once --- tests/npc_test.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tests/npc_test.cpp b/tests/npc_test.cpp index 3fcb58a8ae309..8659a7ef94980 100644 --- a/tests/npc_test.cpp +++ b/tests/npc_test.cpp @@ -482,11 +482,12 @@ TEST_CASE( "npc-movement" ) || type == 'B' || type == 'C' ) { shared_ptr_fast guy = make_shared_fast(); - do { - guy->normalize(); - guy->randomize(); - // Repeat until we get an NPC vulnerable to acid - } while( guy->is_immune_field( fd_acid ) ); + guy->normalize(); + guy->randomize(); + guy->remove_worn_items_with( [&]( item & armor ) { + return armor.covers( bodypart_id( "foot_r" ) ) || armor.covers( bodypart_id( "foot_l" ) ); + } ); + REQUIRE( !guy->is_immune_field( fd_acid ) ); guy->spawn_at_precise( get_map().getglobal( p ) ); // Set the shopkeep mission; this means that // the NPC deems themselves to be guarding and stops them